summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/conf/files1
-rw-r--r--sys/modules/netgraph/cisco/ng_cisco.41
-rw-r--r--sys/modules/netgraph/cisco/ng_cisco.81
-rw-r--r--sys/modules/netgraph/netgraph/Makefile2
-rw-r--r--sys/modules/netgraph/netgraph/netgraph.4109
-rw-r--r--sys/modules/netgraph/pppoe/ng_pppoe.41
-rw-r--r--sys/modules/netgraph/pppoe/ng_pppoe.81
-rw-r--r--sys/net/if_ethersubr.c3
-rw-r--r--sys/netgraph/netgraph.h26
-rw-r--r--sys/netgraph/ng_UI.c3
-rw-r--r--sys/netgraph/ng_UI.h2
-rw-r--r--sys/netgraph/ng_async.c55
-rw-r--r--sys/netgraph/ng_async.h28
-rw-r--r--sys/netgraph/ng_base.c319
-rw-r--r--sys/netgraph/ng_cisco.c62
-rw-r--r--sys/netgraph/ng_cisco.h39
-rw-r--r--sys/netgraph/ng_echo.c3
-rw-r--r--sys/netgraph/ng_ether.h10
-rw-r--r--sys/netgraph/ng_frame_relay.c5
-rw-r--r--sys/netgraph/ng_hole.c3
-rw-r--r--sys/netgraph/ng_iface.c14
-rw-r--r--sys/netgraph/ng_ksocket.c557
-rw-r--r--sys/netgraph/ng_ksocket.h22
-rw-r--r--sys/netgraph/ng_lmi.c3
-rw-r--r--sys/netgraph/ng_message.h159
-rw-r--r--sys/netgraph/ng_parse.c1604
-rw-r--r--sys/netgraph/ng_parse.h388
-rw-r--r--sys/netgraph/ng_ppp.c78
-rw-r--r--sys/netgraph/ng_ppp.h48
-rw-r--r--sys/netgraph/ng_pppoe.c3
-rw-r--r--sys/netgraph/ng_rfc1490.c3
-rw-r--r--sys/netgraph/ng_rfc1490.h2
-rw-r--r--sys/netgraph/ng_sample.c3
-rw-r--r--sys/netgraph/ng_socket.c3
-rw-r--r--sys/netgraph/ng_tee.c3
-rw-r--r--sys/netgraph/ng_tty.c21
-rw-r--r--sys/netgraph/ng_vjc.c3
37 files changed, 3433 insertions, 155 deletions
diff --git a/sys/conf/files b/sys/conf/files
index ea7c95d..fbda398 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -572,6 +572,7 @@ netatm/uni/unisig_subr.c optional atm_uni atm_core
netatm/uni/unisig_util.c optional atm_uni atm_core
netatm/uni/unisig_vc_state.c optional atm_uni atm_core
netgraph/ng_base.c optional netgraph
+netgraph/ng_parse.c optional netgraph
netgraph/ng_async.c optional netgraph_async
netgraph/ng_cisco.c optional netgraph_cisco
netgraph/ng_echo.c optional netgraph_echo
diff --git a/sys/modules/netgraph/cisco/ng_cisco.4 b/sys/modules/netgraph/cisco/ng_cisco.4
index 452252f..26370cd 100644
--- a/sys/modules/netgraph/cisco/ng_cisco.4
+++ b/sys/modules/netgraph/cisco/ng_cisco.4
@@ -42,6 +42,7 @@
.Nm ng_cisco
.Nd Cisco HDLC protocol netgraph node type
.Sh SYNOPSIS
+.Fd #include <netinet/in.h>
.Fd #include <netgraph/ng_cisco.h>
.Sh DESCRIPTION
The
diff --git a/sys/modules/netgraph/cisco/ng_cisco.8 b/sys/modules/netgraph/cisco/ng_cisco.8
index 452252f..26370cd 100644
--- a/sys/modules/netgraph/cisco/ng_cisco.8
+++ b/sys/modules/netgraph/cisco/ng_cisco.8
@@ -42,6 +42,7 @@
.Nm ng_cisco
.Nd Cisco HDLC protocol netgraph node type
.Sh SYNOPSIS
+.Fd #include <netinet/in.h>
.Fd #include <netgraph/ng_cisco.h>
.Sh DESCRIPTION
The
diff --git a/sys/modules/netgraph/netgraph/Makefile b/sys/modules/netgraph/netgraph/Makefile
index eb37f19..eaaf4ac 100644
--- a/sys/modules/netgraph/netgraph/Makefile
+++ b/sys/modules/netgraph/netgraph/Makefile
@@ -2,7 +2,7 @@
# $Whistle: Makefile,v 1.2 1999/01/19 19:39:22 archie Exp $
KMOD= netgraph
-SRCS= ng_base.c
+SRCS= ng_base.c ng_parse.c
MAN4= netgraph.4
.include <bsd.kmod.mk>
diff --git a/sys/modules/netgraph/netgraph/netgraph.4 b/sys/modules/netgraph/netgraph/netgraph.4
index e85e22e..f0d0e85 100644
--- a/sys/modules/netgraph/netgraph/netgraph.4
+++ b/sys/modules/netgraph/netgraph/netgraph.4
@@ -57,7 +57,7 @@ Nodes communicate along the edges to process data, implement protocols, etc.
The aim of
.Nm
is to supplement rather than replace the existing kernel networking
-infrastructure. It provides:
+infrastructure. It provides:
.Pp
.Bl -bullet -compact -offset 2n
.It
@@ -132,8 +132,19 @@ in the graph, one edge at a time. The first mbuf in a chain must have the
.Dv M_PKTHDR
flag set. Each node decides how to handle data coming in on its hooks.
.Pp
-Control messages are type-specific structures sent from one node directly
-to an arbitrary other node. There are two ways to address such a message. If
+Control messages are type-specific C structures sent from one node
+directly to some arbitrary other node. Control messages have a common
+header format, followed by type-specific data, and are binary structures
+for efficiency. However, node types also may support conversion of the
+type specific data between binary and
+ASCII for debugging and human interface purposes (see the
+.Dv NGM_ASCII2BINARY
+and
+.Dv NGM_BINARY2ASCII
+generic control messages below). Nodes are not required to support
+these conversions.
+.Pp
+There are two ways to address a control message. If
there is a sequence of edges connecting the two nodes, the message
may be ``source routed'' by specifying the corresponding sequence
of hooks as the destination address for the message (relative
@@ -448,8 +459,17 @@ incrementing
From a hook you can obtain the corresponding node, and from
a node the list of all active hooks.
.Pp
-Node types are described by this structure:
+Node types are described by these structures:
.Bd -literal
+/** How to convert a control message from binary <-> ASCII */
+struct ng_cmdlist {
+ u_int32_t cookie; /* typecookie */
+ int cmd; /* command number */
+ const char *name; /* command name */
+ const struct ng_parse_type *mesgType; /* args if !NGF_RESP */
+ const struct ng_parse_type *respType; /* args if NGF_RESP */
+};
+
struct ng_type {
u_int32_t version; /* Must equal NG_VERSION */
const char *name; /* Unique type name */
@@ -476,6 +496,9 @@ struct ng_type {
struct mbuf *m, /* The data in an mbuf */
meta_p meta); /* Meta-data, if any */
int (*disconnect)(hook_p hook); /* Notify disconnection of hook */
+
+ /** How to convert control messages binary <-> ASCII */
+ const struct ng_cmdlist *cmdlist; /* Optional; may be NULL */
};
.Ed
.Pp
@@ -554,6 +577,58 @@ purposes only).
.Pp
Some modules may choose to implement messages from more than one
of the header files and thus recognize more than one type cookie.
+.Sh Control Message ASCII Form
+Control messages are in binary format for efficiency. However, for
+debugging and human interface purposes, and if the node type supports
+it, control messages may be converted to and from an equivalent ASCII
+form. The ASCII form is similar to the binary form, with two exceptions:
+.Pp
+.Bl -tag -compact -width xxx
+.It o
+The
+.Dv cmdstr
+header field must contain the ASCII name of the command, corresponding to the
+.Dv cmd
+header field.
+.It o
+The
+.Dv args
+field contains a NUL-terminated ASCII string version of the message arguments.
+.El
+.Pp
+In general, the arguments field of a control messgage can be any
+arbitrary C data type. Netgraph includes parsing routines to support
+some pre-defined datatypes in ASCII with this simple syntax:
+.Pp
+.Bl -tag -compact -width xxx
+.It o
+Integer types are represented by base 8, 10, or 16 numbers.
+.It o
+Strings are enclosed in double quotes and respect the normal
+C language backslash escapes.
+.It o
+IP addresses have the obvious form.
+.It o
+Arrays are enclosed in square brackets, with the elements listed
+consecutively starting at index zero. An element may have an optional
+index and equals sign preceeding it. Whenever an element
+does not have an explicit index, the index is implicitly the previous
+element's index plus one.
+.It o
+Structures are enclosed in curly braces, and each field is specified
+in the form ``fieldname=value''.
+.It o
+Any array element or structure field whose value is equal to its
+``default value'' may be omitted. For integer types, the default value
+is usually zero; for string types, the empty string.
+.It o
+Array elements and structure fields may be specified in any order.
+.El
+.Pp
+Each node type may define its own arbitrary types by providing
+the necessary routines to parse and unparse. ASCII forms defined
+for a specific node type are documented in the documentation for
+that node type.
.Sh Generic Control Messages
There are a number of standard predefined messages that will work
for any node, as they are supported directly by the framework itself.
@@ -612,6 +687,32 @@ elect to not support this message. The text response must be less than
.Dv NG_TEXTRESPONSE
bytes in length (presently 1024). This can be used to return general
status information in human readable form.
+.It Dv NGM_BINARY2ASCII
+This generic converts a binary control message to its ASCII form.
+The entire control message to be converted is contained within the
+arguments field of the
+.Dv Dv NGM_BINARY2ASCII
+message itself. If successful, the reply will contain the same control
+message in ASCII form.
+A node will typically only know how to translate messages that it
+itself understands, so
+the target node of the
+.Dv NGM_BINARY2ASCII
+is often the same node that would actually receive that message.
+.It Dv NGM_ASCII2BINARY
+The opposite of
+.Dv NGM_BINARY2ASCII .
+The entire control message to be converted, in ASCII form, is contained
+in the arguments section of the
+.Dv NGM_ASCII2BINARY
+and need only have the
+.Dv flags ,
+.Dv cmdstr ,
+and
+.Dv arglen
+header fields filled in, plus the NUL-terminated string version of
+the arguments in the arguments field. If successful, the reply
+contains the binary version of the control message.
.El
.Sh Metadata
Data moving through the
diff --git a/sys/modules/netgraph/pppoe/ng_pppoe.4 b/sys/modules/netgraph/pppoe/ng_pppoe.4
index c0b0209..69d0016 100644
--- a/sys/modules/netgraph/pppoe/ng_pppoe.4
+++ b/sys/modules/netgraph/pppoe/ng_pppoe.4
@@ -42,6 +42,7 @@
.Nm ng_pppoe
.Nd RFC 2516 PPPOE protocol netgraph node type
.Sh SYNOPSIS
+.Fd #include <net/ethernet.h>
.Fd #include <netgraph/ng_pppoe.h>
.Sh DESCRIPTION
The
diff --git a/sys/modules/netgraph/pppoe/ng_pppoe.8 b/sys/modules/netgraph/pppoe/ng_pppoe.8
index c0b0209..69d0016 100644
--- a/sys/modules/netgraph/pppoe/ng_pppoe.8
+++ b/sys/modules/netgraph/pppoe/ng_pppoe.8
@@ -42,6 +42,7 @@
.Nm ng_pppoe
.Nd RFC 2516 PPPOE protocol netgraph node type
.Sh SYNOPSIS
+.Fd #include <net/ethernet.h>
.Fd #include <netgraph/ng_pppoe.h>
.Sh DESCRIPTION
The
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index dc55d54..ec0f5cf 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -150,7 +150,8 @@ static struct ng_type typestruct = {
ngether_connect,
ngether_rcvdata,
ngether_rcvdata,
- ngether_disconnect
+ ngether_disconnect,
+ NULL
};
#define AC2NG(AC) ((node_p)((AC)->ac_ng))
diff --git a/sys/netgraph/netgraph.h b/sys/netgraph/netgraph.h
index 94649e6..d693aa5 100644
--- a/sys/netgraph/netgraph.h
+++ b/sys/netgraph/netgraph.h
@@ -112,7 +112,7 @@ struct meta_field_header {
};
/* To zero out an option 'in place' set it's cookie to this */
-#define INVALID_COOKIE 865455152
+#define NGM_INVALID_COOKIE 865455152
/* This part of the metadata is always present if the pointer is non NULL */
struct ng_meta {
@@ -132,7 +132,7 @@ typedef struct ng_meta *meta_p;
/* node method definitions */
typedef int ng_constructor_t(node_p *node);
typedef int ng_rcvmsg_t(node_p node, struct ng_mesg *msg,
- const char *retaddr, struct ng_mesg **resp);
+ const char *retaddr, struct ng_mesg **resp);
typedef int ng_shutdown_t(node_p node);
typedef int ng_newhook_t(node_p node, hook_p hook, const char *name);
typedef hook_p ng_findhook_t(node_p node, const char *name);
@@ -141,12 +141,26 @@ typedef int ng_rcvdata_t(hook_p hook, struct mbuf *m, meta_p meta);
typedef int ng_disconnect_t(hook_p hook);
/*
+ * Command list -- each node type specifies the command that it knows
+ * how to convert between ASCII and binary using an array of these.
+ * The last element in the array must be a terminator with cookie=0.
+ */
+
+struct ng_cmdlist {
+ u_int32_t cookie; /* command typecookie */
+ int cmd; /* command number */
+ const char *name; /* command name */
+ const struct ng_parse_type *mesgType; /* args if !NGF_RESP */
+ const struct ng_parse_type *respType; /* args if NGF_RESP */
+};
+
+/*
* Structure of a node type
*/
struct ng_type {
- u_int32_t version; /* must equal NG_VERSION */
- const char *name; /* Unique type name */
+ u_int32_t version; /* must equal NG_VERSION */
+ const char *name; /* Unique type name */
modeventhand_t mod_event; /* Module event handler (optional) */
ng_constructor_t *constructor; /* Node constructor */
ng_rcvmsg_t *rcvmsg; /* control messages come here */
@@ -158,7 +172,9 @@ struct ng_type {
ng_rcvdata_t *rcvdataq; /* or here if been queued */
ng_disconnect_t *disconnect; /* notify on disconnect */
- /* R/W data private to the base netgraph code DON'T TOUCH!*/
+ const struct ng_cmdlist *cmdlist; /* commands we can convert */
+
+ /* R/W data private to the base netgraph code DON'T TOUCH! */
LIST_ENTRY(ng_type) types; /* linked list of all types */
int refs; /* number of instances */
};
diff --git a/sys/netgraph/ng_UI.c b/sys/netgraph/ng_UI.c
index d30005f..21a10f5 100644
--- a/sys/netgraph/ng_UI.c
+++ b/sys/netgraph/ng_UI.c
@@ -94,7 +94,8 @@ static struct ng_type typestruct = {
NULL,
ng_UI_rcvdata,
ng_UI_rcvdata,
- ng_UI_disconnect
+ ng_UI_disconnect,
+ NULL
};
NETGRAPH_INIT(UI, &typestruct);
diff --git a/sys/netgraph/ng_UI.h b/sys/netgraph/ng_UI.h
index f41e5a9..52fc362 100644
--- a/sys/netgraph/ng_UI.h
+++ b/sys/netgraph/ng_UI.h
@@ -45,7 +45,7 @@
/* Node type name and cookie */
#define NG_UI_NODE_TYPE "UI"
-#define NGM_UI_NODE_COOKIE 884639499
+#define NGM_UI_COOKIE 884639499
/* Hook names */
#define NG_UI_HOOK_DOWNSTREAM "downstream"
diff --git a/sys/netgraph/ng_async.c b/sys/netgraph/ng_async.c
index ca96dbe..4c7e3ab 100644
--- a/sys/netgraph/ng_async.c
+++ b/sys/netgraph/ng_async.c
@@ -61,6 +61,7 @@
#include <netgraph/ng_message.h>
#include <netgraph/netgraph.h>
#include <netgraph/ng_async.h>
+#include <netgraph/ng_parse.h>
#include <net/ppp_defs.h>
@@ -91,7 +92,7 @@ typedef struct ng_async_private *sc_p;
#define ERROUT(x) do { error = (x); goto done; } while (0)
/* Netgraph methods */
-static ng_constructor_t nga_constructor;
+static ng_constructor_t nga_constructor;
static ng_rcvdata_t nga_rcvdata;
static ng_rcvmsg_t nga_rcvmsg;
static ng_shutdown_t nga_shutdown;
@@ -102,6 +103,55 @@ static ng_disconnect_t nga_disconnect;
static int nga_rcv_sync(const sc_p sc, struct mbuf *m, meta_p meta);
static int nga_rcv_async(const sc_p sc, struct mbuf *m, meta_p meta);
+/* Parse type for struct ng_async_cfg */
+static const struct ng_parse_struct_info
+ nga_config_type_info = NG_ASYNC_CONFIG_TYPE_INFO;
+static const struct ng_parse_type nga_config_type = {
+ &ng_parse_struct_type,
+ &nga_config_type_info
+};
+
+/* Parse type for struct ng_async_stat */
+static const struct ng_parse_struct_info
+ nga_stats_type_info = NG_ASYNC_STATS_TYPE_INFO;
+static const struct ng_parse_type nga_stats_type = {
+ &ng_parse_struct_type,
+ &nga_stats_type_info,
+};
+
+/* List of commands and how to convert arguments to/from ASCII */
+static const struct ng_cmdlist nga_cmdlist[] = {
+ {
+ NGM_ASYNC_COOKIE,
+ NGM_ASYNC_CMD_SET_CONFIG,
+ "setconfig",
+ &nga_config_type,
+ NULL
+ },
+ {
+ NGM_ASYNC_COOKIE,
+ NGM_ASYNC_CMD_GET_CONFIG,
+ "getconfig",
+ NULL,
+ &nga_config_type
+ },
+ {
+ NGM_ASYNC_COOKIE,
+ NGM_ASYNC_CMD_GET_STATS,
+ "getstats",
+ NULL,
+ &nga_stats_type
+ },
+ {
+ NGM_ASYNC_COOKIE,
+ NGM_ASYNC_CMD_CLR_STATS,
+ "clrstats",
+ &nga_stats_type,
+ NULL
+ },
+ { 0 }
+};
+
/* Define the netgraph node type */
static struct ng_type typestruct = {
NG_VERSION,
@@ -115,7 +165,8 @@ static struct ng_type typestruct = {
NULL,
nga_rcvdata,
nga_rcvdata,
- nga_disconnect
+ nga_disconnect,
+ nga_cmdlist
};
NETGRAPH_INIT(async, &typestruct);
diff --git a/sys/netgraph/ng_async.h b/sys/netgraph/ng_async.h
index a91ef16..63f6e43 100644
--- a/sys/netgraph/ng_async.h
+++ b/sys/netgraph/ng_async.h
@@ -45,7 +45,7 @@
/* Type name and cookie */
#define NG_ASYNC_NODE_TYPE "async"
-#define NGM_ASYNC_COOKIE 886473718
+#define NGM_ASYNC_COOKIE 886473717
/* Hook names */
#define NG_ASYNC_HOOK_SYNC "sync" /* Sync frames */
@@ -68,6 +68,21 @@ struct ng_async_stat {
u_int32_t asyncBadCheckSums;
};
+/* Keep this in sync with the above structure definition */
+#define NG_ASYNC_STATS_TYPE_INFO { \
+ { \
+ { "syncOctets", &ng_parse_int32_type }, \
+ { "syncFrames", &ng_parse_int32_type }, \
+ { "syncOverflows", &ng_parse_int32_type }, \
+ { "asyncOctets", &ng_parse_int32_type }, \
+ { "asyncFrames", &ng_parse_int32_type }, \
+ { "asyncRunts", &ng_parse_int32_type }, \
+ { "asyncOverflows", &ng_parse_int32_type }, \
+ { "asyncBadCheckSums",&ng_parse_int32_type }, \
+ { NULL }, \
+ } \
+}
+
/* Configuration for this node */
struct ng_async_cfg {
u_char enabled; /* Turn encoding on/off */
@@ -76,6 +91,17 @@ struct ng_async_cfg {
u_int32_t accm; /* ACCM encoding */
};
+/* Keep this in sync with the above structure definition */
+#define NG_ASYNC_CONFIG_TYPE_INFO { \
+ { \
+ { "enabled", &ng_parse_int8_type }, \
+ { "amru", &ng_parse_int16_type }, \
+ { "smru", &ng_parse_int16_type }, \
+ { "accm", &ng_parse_int32_type }, \
+ { NULL }, \
+ } \
+}
+
/* Commands */
enum {
NGM_ASYNC_CMD_GET_STATS = 1, /* returns struct ng_async_stat */
diff --git a/sys/netgraph/ng_base.c b/sys/netgraph/ng_base.c
index 84cd696..7d20e80 100644
--- a/sys/netgraph/ng_base.c
+++ b/sys/netgraph/ng_base.c
@@ -62,6 +62,7 @@
#include <netgraph/ng_message.h>
#include <netgraph/netgraph.h>
+#include <netgraph/ng_parse.h>
/* List of all nodes */
static LIST_HEAD(, ng_node) nodelist;
@@ -114,6 +115,179 @@ static ng_ID_t nextID = 1;
/************************************************************************
+ Parse type definitions for generic messages
+************************************************************************/
+
+/* Handy structure parse type defining macro */
+#define DEFINE_PARSE_STRUCT_TYPE(lo, up, args) \
+static const struct ng_parse_struct_info \
+ ng_ ## lo ## _type_info = NG_GENERIC_ ## up ## _INFO args; \
+static const struct ng_parse_type ng_generic_ ## lo ## _type = { \
+ &ng_parse_struct_type, \
+ &ng_ ## lo ## _type_info \
+}
+
+DEFINE_PARSE_STRUCT_TYPE(mkpeer, MKPEER, ());
+DEFINE_PARSE_STRUCT_TYPE(connect, CONNECT, ());
+DEFINE_PARSE_STRUCT_TYPE(name, NAME, ());
+DEFINE_PARSE_STRUCT_TYPE(rmhook, RMHOOK, ());
+DEFINE_PARSE_STRUCT_TYPE(nodeinfo, NODEINFO, ());
+DEFINE_PARSE_STRUCT_TYPE(typeinfo, TYPEINFO, ());
+DEFINE_PARSE_STRUCT_TYPE(linkinfo, LINKINFO, (&ng_generic_nodeinfo_type));
+
+/* Get length of an array when the length is stored as a 32 bit
+ value immediately preceeding the array -- as with struct namelist
+ and struct typelist. */
+static int
+ng_generic_list_getLength(const struct ng_parse_type *type,
+ const u_char *start, const u_char *buf)
+{
+ return *((const u_int32_t *)(buf - 4));
+}
+
+/* Get length of the array of struct linkinfo inside a struct hooklist */
+static int
+ng_generic_linkinfo_getLength(const struct ng_parse_type *type,
+ const u_char *start, const u_char *buf)
+{
+ const struct hooklist *hl = (const struct hooklist *)start;
+
+ return hl->nodeinfo.hooks;
+}
+
+/* Array type for a variable length array of struct namelist */
+static const struct ng_parse_array_info ng_nodeinfoarray_type_info = {
+ &ng_generic_nodeinfo_type,
+ &ng_generic_list_getLength
+};
+static const struct ng_parse_type ng_generic_nodeinfoarray_type = {
+ &ng_parse_array_type,
+ &ng_nodeinfoarray_type_info
+};
+
+/* Array type for a variable length array of struct typelist */
+static const struct ng_parse_array_info ng_typeinfoarray_type_info = {
+ &ng_generic_typeinfo_type,
+ &ng_generic_list_getLength
+};
+static const struct ng_parse_type ng_generic_typeinfoarray_type = {
+ &ng_parse_array_type,
+ &ng_typeinfoarray_type_info
+};
+
+/* Array type for array of struct linkinfo in struct hooklist */
+static const struct ng_parse_array_info ng_generic_linkinfo_array_type_info = {
+ &ng_generic_linkinfo_type,
+ &ng_generic_linkinfo_getLength
+};
+static const struct ng_parse_type ng_generic_linkinfo_array_type = {
+ &ng_parse_array_type,
+ &ng_generic_linkinfo_array_type_info
+};
+
+DEFINE_PARSE_STRUCT_TYPE(typelist, TYPELIST, (&ng_generic_nodeinfoarray_type));
+DEFINE_PARSE_STRUCT_TYPE(hooklist, HOOKLIST,
+ (&ng_generic_nodeinfo_type, &ng_generic_linkinfo_array_type));
+DEFINE_PARSE_STRUCT_TYPE(listnodes, LISTNODES,
+ (&ng_generic_nodeinfoarray_type));
+
+/* List of commands and how to convert arguments to/from ASCII */
+static const struct ng_cmdlist ng_generic_cmds[] = {
+ {
+ NGM_GENERIC_COOKIE,
+ NGM_SHUTDOWN,
+ "shutdown",
+ NULL,
+ NULL
+ },
+ {
+ NGM_GENERIC_COOKIE,
+ NGM_MKPEER,
+ "mkpeer",
+ &ng_generic_mkpeer_type,
+ NULL
+ },
+ {
+ NGM_GENERIC_COOKIE,
+ NGM_CONNECT,
+ "connect",
+ &ng_generic_connect_type,
+ NULL
+ },
+ {
+ NGM_GENERIC_COOKIE,
+ NGM_NAME,
+ "name",
+ &ng_generic_name_type,
+ NULL
+ },
+ {
+ NGM_GENERIC_COOKIE,
+ NGM_RMHOOK,
+ "rmhook",
+ &ng_generic_rmhook_type,
+ NULL
+ },
+ {
+ NGM_GENERIC_COOKIE,
+ NGM_NODEINFO,
+ "nodeinfo",
+ NULL,
+ &ng_generic_nodeinfo_type
+ },
+ {
+ NGM_GENERIC_COOKIE,
+ NGM_LISTHOOKS,
+ "listhooks",
+ NULL,
+ &ng_generic_hooklist_type
+ },
+ {
+ NGM_GENERIC_COOKIE,
+ NGM_LISTNAMES,
+ "listnames",
+ NULL,
+ &ng_generic_listnodes_type /* same as NGM_LISTNODES */
+ },
+ {
+ NGM_GENERIC_COOKIE,
+ NGM_LISTNODES,
+ "listnodes",
+ NULL,
+ &ng_generic_listnodes_type
+ },
+ {
+ NGM_GENERIC_COOKIE,
+ NGM_LISTTYPES,
+ "listtypes",
+ NULL,
+ &ng_generic_typeinfo_type
+ },
+ {
+ NGM_GENERIC_COOKIE,
+ NGM_TEXT_STATUS,
+ "textstatus",
+ NULL,
+ &ng_parse_string_type
+ },
+ {
+ NGM_GENERIC_COOKIE,
+ NGM_ASCII2BINARY,
+ "ascii2binary",
+ &ng_parse_ng_mesg_type,
+ &ng_parse_ng_mesg_type
+ },
+ {
+ NGM_GENERIC_COOKIE,
+ NGM_BINARY2ASCII,
+ "binary2ascii",
+ &ng_parse_ng_mesg_type,
+ &ng_parse_ng_mesg_type
+ },
+ { 0 }
+};
+
+/************************************************************************
Node routines
************************************************************************/
@@ -1256,6 +1430,151 @@ ng_generic_msg(node_p here, struct ng_mesg *msg, const char *retaddr,
break;
}
+ case NGM_BINARY2ASCII:
+ {
+ int bufSize = 2000; /* XXX hard coded constant */
+ const struct ng_parse_type *argstype;
+ const struct ng_cmdlist *c;
+ struct ng_mesg *rp, *binary, *ascii;
+
+ /* Data area must contain a valid netgraph message */
+ binary = (struct ng_mesg *)msg->data;
+ if (msg->header.arglen < sizeof(struct ng_mesg)
+ || msg->header.arglen - sizeof(struct ng_mesg)
+ < binary->header.arglen) {
+ error = EINVAL;
+ break;
+ }
+
+ /* Get a response message with lots of room */
+ NG_MKRESPONSE(rp, msg, sizeof(*ascii) + bufSize, M_NOWAIT);
+ if (rp == NULL) {
+ error = ENOMEM;
+ break;
+ }
+ ascii = (struct ng_mesg *)rp->data;
+
+ /* Copy binary message header to response message payload */
+ bcopy(binary, ascii, sizeof(*binary));
+
+ /* Find command by matching typecookie and command number */
+ for (c = here->type->cmdlist;
+ c != NULL && c->name != NULL; c++) {
+ if (binary->header.typecookie == c->cookie
+ && binary->header.cmd == c->cmd)
+ break;
+ }
+ if (c == NULL || c->name == NULL) {
+ for (c = ng_generic_cmds; c->name != NULL; c++) {
+ if (binary->header.typecookie == c->cookie
+ && binary->header.cmd == c->cmd)
+ break;
+ }
+ if (c->name == NULL) {
+ FREE(rp, M_NETGRAPH);
+ error = ENOSYS;
+ break;
+ }
+ }
+
+ /* Convert command name to ASCII */
+ snprintf(ascii->header.cmdstr, sizeof(ascii->header.cmdstr),
+ "%s", c->name);
+
+ /* Convert command arguments to ASCII */
+ argstype = (binary->header.flags & NGF_RESP) ?
+ c->respType : c->mesgType;
+ if (argstype == NULL)
+ *ascii->data = '\0';
+ else {
+ if ((error = ng_unparse(argstype,
+ (u_char *)binary->data,
+ ascii->data, bufSize)) != 0) {
+ FREE(rp, M_NETGRAPH);
+ break;
+ }
+ }
+
+ /* Return the result as struct ng_mesg plus ASCII string */
+ bufSize = strlen(ascii->data) + 1;
+ ascii->header.arglen = bufSize;
+ rp->header.arglen = sizeof(*ascii) + bufSize;
+ *resp = rp;
+ break;
+ }
+
+ case NGM_ASCII2BINARY:
+ {
+ int bufSize = 2000; /* XXX hard coded constant */
+ const struct ng_cmdlist *c;
+ const struct ng_parse_type *argstype;
+ struct ng_mesg *rp, *ascii, *binary;
+ int off;
+
+ /* Data area must contain at least a struct ng_mesg + '\0' */
+ ascii = (struct ng_mesg *)msg->data;
+ if (msg->header.arglen < sizeof(*ascii) + 1
+ || ascii->header.arglen < 1
+ || msg->header.arglen
+ < sizeof(*ascii) + ascii->header.arglen) {
+ error = EINVAL;
+ break;
+ }
+ ascii->data[ascii->header.arglen - 1] = '\0';
+
+ /* Get a response message with lots of room */
+ NG_MKRESPONSE(rp, msg, sizeof(*binary) + bufSize, M_NOWAIT);
+ if (rp == NULL) {
+ error = ENOMEM;
+ break;
+ }
+ binary = (struct ng_mesg *)rp->data;
+
+ /* Copy ASCII message header to response message payload */
+ bcopy(ascii, binary, sizeof(*ascii));
+
+ /* Find command by matching ASCII command string */
+ for (c = here->type->cmdlist;
+ c != NULL && c->name != NULL; c++) {
+ if (strcmp(ascii->header.cmdstr, c->name) == 0)
+ break;
+ }
+ if (c == NULL || c->name == NULL) {
+ for (c = ng_generic_cmds; c->name != NULL; c++) {
+ if (strcmp(ascii->header.cmdstr, c->name) == 0)
+ break;
+ }
+ if (c->name == NULL) {
+ FREE(rp, M_NETGRAPH);
+ error = ENOSYS;
+ break;
+ }
+ }
+
+ /* Convert command name to binary */
+ binary->header.cmd = c->cmd;
+ binary->header.typecookie = c->cookie;
+
+ /* Convert command arguments to binary */
+ argstype = (binary->header.flags & NGF_RESP) ?
+ c->respType : c->mesgType;
+ if (argstype == NULL)
+ bufSize = 0;
+ else {
+ if ((error = ng_parse(argstype, ascii->data,
+ &off, (u_char *)binary->data, &bufSize)) != 0) {
+ FREE(rp, M_NETGRAPH);
+ break;
+ }
+ }
+
+ /* Return the result */
+ binary->header.arglen = bufSize;
+ rp->header.arglen = sizeof(*binary) + bufSize;
+ *resp = rp;
+ break;
+ }
+
case NGM_TEXT_STATUS:
/*
* This one is tricky as it passes the command down to the
diff --git a/sys/netgraph/ng_cisco.c b/sys/netgraph/ng_cisco.c
index cc30d3d..26898ce 100644
--- a/sys/netgraph/ng_cisco.c
+++ b/sys/netgraph/ng_cisco.c
@@ -67,6 +67,7 @@
#include <netgraph/ng_message.h>
#include <netgraph/netgraph.h>
+#include <netgraph/ng_parse.h>
#include <netgraph/ng_cisco.h>
#define CISCO_MULTICAST 0x8f /* Cisco multicast address */
@@ -105,7 +106,7 @@ struct protoent {
struct cisco_priv {
u_long local_seq;
u_long remote_seq;
- u_long seq_retries; /* how many times we've been here throwing out
+ u_long seqRetries; /* how many times we've been here throwing out
* the same sequence number without ack */
node_p node;
struct callout_handle handle;
@@ -131,6 +132,48 @@ static int cisco_input(sc_p sc, struct mbuf *m, meta_p meta);
static void cisco_keepalive(void *arg);
static int cisco_send(sc_p sc, int type, long par1, long par2);
+/* Parse type for struct ng_cisco_ipaddr */
+static const struct ng_parse_struct_info
+ ng_cisco_ipaddr_type_info = NG_CISCO_IPADDR_TYPE_INFO;
+static const struct ng_parse_type ng_cisco_ipaddr_type = {
+ &ng_parse_struct_type,
+ &ng_cisco_ipaddr_type_info
+};
+
+/* Parse type for struct ng_async_stat */
+static const struct ng_parse_struct_info
+ ng_cisco_stats_type_info = NG_CISCO_STATS_TYPE_INFO;
+static const struct ng_parse_type ng_cisco_stats_type = {
+ &ng_parse_struct_type,
+ &ng_cisco_stats_type_info,
+};
+
+/* List of commands and how to convert arguments to/from ASCII */
+static const struct ng_cmdlist ng_cisco_cmdlist[] = {
+ {
+ NGM_CISCO_COOKIE,
+ NGM_CISCO_SET_IPADDR,
+ "setipaddr",
+ &ng_cisco_ipaddr_type,
+ NULL
+ },
+ {
+ NGM_CISCO_COOKIE,
+ NGM_CISCO_GET_IPADDR,
+ "getipaddr",
+ NULL,
+ &ng_cisco_ipaddr_type
+ },
+ {
+ NGM_CISCO_COOKIE,
+ NGM_CISCO_GET_STATUS,
+ "getstats",
+ NULL,
+ &ng_cisco_stats_type
+ },
+ { 0 }
+};
+
/* Node type */
static struct ng_type typestruct = {
NG_VERSION,
@@ -144,7 +187,8 @@ static struct ng_type typestruct = {
NULL,
cisco_rcvdata,
cisco_rcvdata,
- cisco_disconnect
+ cisco_disconnect,
+ ng_cisco_cmdlist
};
NETGRAPH_INIT(cisco, &typestruct);
@@ -237,7 +281,7 @@ cisco_rcvmsg(node_p node, struct ng_mesg *msg,
pos = sprintf(arg,
"keepalive period: %d sec; ", KEEPALIVE_SECS);
pos += sprintf(arg + pos,
- "unacknowledged keepalives: %ld", sc->seq_retries);
+ "unacknowledged keepalives: %ld", sc->seqRetries);
resp->header.arglen = pos + 1;
break;
}
@@ -278,16 +322,16 @@ cisco_rcvmsg(node_p node, struct ng_mesg *msg,
}
case NGM_CISCO_GET_STATUS:
{
- struct ngciscostat *stat;
+ struct ng_cisco_stats *stat;
NG_MKRESPONSE(resp, msg, sizeof(*stat), M_NOWAIT);
if (!resp) {
error = ENOMEM;
break;
}
- stat = (struct ngciscostat *) resp->data;
- stat->seq_retries = sc->seq_retries;
- stat->keepalive_period = KEEPALIVE_SECS;
+ stat = (struct ng_cisco_stats *)resp->data;
+ stat->seqRetries = sc->seqRetries;
+ stat->keepAlivePeriod = KEEPALIVE_SECS;
break;
}
default:
@@ -445,7 +489,7 @@ cisco_input(sc_p sc, struct mbuf *m, meta_p meta)
sc->remote_seq = ntohl(p->par1);
if (sc->local_seq == ntohl(p->par2)) {
sc->local_seq++;
- sc->seq_retries = 0;
+ sc->seqRetries = 0;
}
break;
case CISCO_ADDR_REQ:
@@ -508,7 +552,7 @@ cisco_keepalive(void *arg)
int s = splimp();
cisco_send(sc, CISCO_KEEPALIVE_REQ, sc->local_seq, sc->remote_seq);
- sc->seq_retries++;
+ sc->seqRetries++;
splx(s);
sc->handle = timeout(cisco_keepalive, sc, hz * KEEPALIVE_SECS);
}
diff --git a/sys/netgraph/ng_cisco.h b/sys/netgraph/ng_cisco.h
index 559cc14..a51dbfa 100644
--- a/sys/netgraph/ng_cisco.h
+++ b/sys/netgraph/ng_cisco.h
@@ -56,21 +56,38 @@
/* Netgraph commands */
enum {
- /* This takes two struct in_addr's: the IP address and netmask */
- NGM_CISCO_SET_IPADDR = 1,
-
- /* This is both received and *sent* by this node (to the "inet"
- peer). The reply contains the same info as NGM_CISCO_SET_IPADDR. */
- NGM_CISCO_GET_IPADDR,
+ NGM_CISCO_SET_IPADDR = 1, /* requires a struct ng_cisco_ipaddr */
+ NGM_CISCO_GET_IPADDR, /* returns a struct ng_cisco_ipaddr */
+ NGM_CISCO_GET_STATUS, /* returns a struct ng_cisco_stat */
+};
- /* This returns a struct ngciscostat (see below) */
- NGM_CISCO_GET_STATUS,
+struct ng_cisco_ipaddr {
+ struct in_addr ipaddr; /* IP address */
+ struct in_addr netmask; /* Netmask */
};
-struct ngciscostat {
- u_int32_t seq_retries; /* # unack'd retries */
- u_int32_t keepalive_period; /* in seconds */
+/* Keep this in sync with the above structure definition */
+#define NG_CISCO_IPADDR_TYPE_INFO { \
+ { \
+ { "ipaddr", &ng_parse_ipaddr_type }, \
+ { "netmask", &ng_parse_ipaddr_type }, \
+ { NULL }, \
+ } \
+}
+
+struct ng_cisco_stats {
+ u_int32_t seqRetries; /* # unack'd retries */
+ u_int32_t keepAlivePeriod; /* in seconds */
};
+/* Keep this in sync with the above structure definition */
+#define NG_CISCO_STATS_TYPE_INFO { \
+ { \
+ { "seqRetries", &ng_parse_int32_type }, \
+ { "keepAlivePeriod", &ng_parse_int32_type }, \
+ { NULL }, \
+ } \
+}
+
#endif /* _NETGRAPH_CISCO_H_ */
diff --git a/sys/netgraph/ng_echo.c b/sys/netgraph/ng_echo.c
index a834659..e5c35b5 100644
--- a/sys/netgraph/ng_echo.c
+++ b/sys/netgraph/ng_echo.c
@@ -75,7 +75,8 @@ static struct ng_type typestruct = {
NULL,
nge_rcvdata,
nge_rcvdata,
- nge_disconnect
+ nge_disconnect,
+ NULL
};
NETGRAPH_INIT(echo, &typestruct);
diff --git a/sys/netgraph/ng_ether.h b/sys/netgraph/ng_ether.h
index 45625e4..f492361 100644
--- a/sys/netgraph/ng_ether.h
+++ b/sys/netgraph/ng_ether.h
@@ -45,11 +45,19 @@
/* Node type name and magic cookie */
#define NG_ETHER_NODE_TYPE "ether"
-#define NGM_ETHER_COOKIE 917786904
+#define NGM_ETHER_COOKIE 917786904
/* Hook names */
#define NG_ETHER_HOOK_ORPHAN "orphans"
#define NG_ETHER_HOOK_DIVERT "divert"
+/* For adding/removing Ethernet multicast addresses */
+enum {
+ NGM_ETHER_ADD_MULTICAST = 1, /* supply struct ether_addr */
+ NGM_ETHER_DEL_MULTICAST, /* supply struct ether_addr */
+ NGM_ETHER_GET_MULTICAST, /* returns array of struct ether_addr */
+ NGM_ETHER_CLR_MULTICAST, /* clears all multicast addresses */
+};
+
#endif /* _NETGRAPH_NG_ETHER_H_ */
diff --git a/sys/netgraph/ng_frame_relay.c b/sys/netgraph/ng_frame_relay.c
index 7923ad2..92437e9 100644
--- a/sys/netgraph/ng_frame_relay.c
+++ b/sys/netgraph/ng_frame_relay.c
@@ -151,7 +151,8 @@ static struct ng_type typestruct = {
NULL,
ngfrm_rcvdata,
ngfrm_rcvdata,
- ngfrm_disconnect
+ ngfrm_disconnect,
+ NULL
};
NETGRAPH_INIT(framerelay, &typestruct);
@@ -246,7 +247,7 @@ ngfrm_constructor(node_p *nodep)
static int
ngfrm_newhook(node_p node, hook_p hook, const char *name)
{
- const sc_p sc = node->private;
+ const sc_p sc = node->private;
const char *cp;
char *eptr;
int dlci = 0;
diff --git a/sys/netgraph/ng_hole.c b/sys/netgraph/ng_hole.c
index 6b3768c..c0b5dcc 100644
--- a/sys/netgraph/ng_hole.c
+++ b/sys/netgraph/ng_hole.c
@@ -71,7 +71,8 @@ static struct ng_type typestruct = {
NULL,
ngh_rcvdata,
ngh_rcvdata,
- ngh_disconnect
+ ngh_disconnect,
+ NULL
};
NETGRAPH_INIT(hole, &typestruct);
diff --git a/sys/netgraph/ng_iface.c b/sys/netgraph/ng_iface.c
index 6a6cbdf3..d450d2e 100644
--- a/sys/netgraph/ng_iface.c
+++ b/sys/netgraph/ng_iface.c
@@ -73,13 +73,14 @@
#include <net/if_types.h>
#include <net/netisr.h>
+#include <netinet/in.h>
+
#include <netgraph/ng_message.h>
#include <netgraph/netgraph.h>
#include <netgraph/ng_iface.h>
#include <netgraph/ng_cisco.h>
#ifdef INET
-#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/in_var.h>
#include <netinet/ip.h>
@@ -206,7 +207,8 @@ static struct ng_type typestruct = {
NULL,
ng_iface_rcvdata,
ng_iface_rcvdata,
- ng_iface_disconnect
+ ng_iface_disconnect,
+ NULL
};
NETGRAPH_INIT(iface, &typestruct);
@@ -683,12 +685,8 @@ ng_iface_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
int s, error = 0;
/* Sanity checks */
-#ifdef DIAGNOSTIC
- if (iffam == NULL)
- panic(__FUNCTION__);
- if ((m->m_flags & M_PKTHDR) == 0)
- panic(__FUNCTION__);
-#endif
+ KASSERT(iffam != NULL, ("%s: iffam", __FUNCTION__));
+ KASSERT(m->m_flags & M_PKTHDR, ("%s: not pkthdr", __FUNCTION__));
if (m == NULL)
return (EINVAL);
if ((ifp->if_flags & IFF_UP) == 0) {
diff --git a/sys/netgraph/ng_ksocket.c b/sys/netgraph/ng_ksocket.c
index 485eeb5..2ce2b4e 100644
--- a/sys/netgraph/ng_ksocket.c
+++ b/sys/netgraph/ng_ksocket.c
@@ -52,20 +52,26 @@
#include <sys/mbuf.h>
#include <sys/proc.h>
#include <sys/malloc.h>
+#include <sys/ctype.h>
#include <sys/protosw.h>
#include <sys/errno.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/syslog.h>
#include <sys/uio.h>
+#include <sys/un.h>
#include <netgraph/ng_message.h>
#include <netgraph/netgraph.h>
+#include <netgraph/ng_parse.h>
#include <netgraph/ng_ksocket.h>
#include <netinet/in.h>
#include <netatalk/at.h>
+#define OFFSETOF(s, e) ((char *)&((s *)0)->e - (char *)((s *)0))
+#define SADATA_OFFSET (OFFSETOF(struct sockaddr, sa_data))
+
/* Node private data */
struct ng_ksocket_private {
hook_p hook;
@@ -88,28 +94,6 @@ struct ng_ksocket_alias {
const int family;
};
-/* Helper functions */
-static void ng_ksocket_incoming(struct socket *so, void *arg, int waitflag);
-static int ng_ksocket_parse(const struct ng_ksocket_alias *aliases,
- const char *s, int family);
-
-/* Node type descriptor */
-static struct ng_type ng_ksocket_typestruct = {
- NG_VERSION,
- NG_KSOCKET_NODE_TYPE,
- NULL,
- ng_ksocket_constructor,
- ng_ksocket_rcvmsg,
- ng_ksocket_rmnode,
- ng_ksocket_newhook,
- NULL,
- NULL,
- ng_ksocket_rcvdata,
- ng_ksocket_rcvdata,
- ng_ksocket_disconnect
-};
-NETGRAPH_INIT(ksocket, &ng_ksocket_typestruct);
-
/* Protocol family aliases */
static const struct ng_ksocket_alias ng_ksocket_families[] = {
{ "local", PF_LOCAL },
@@ -150,6 +134,350 @@ static const struct ng_ksocket_alias ng_ksocket_protos[] = {
{ NULL, -1 },
};
+/* Helper functions */
+static void ng_ksocket_incoming(struct socket *so, void *arg, int waitflag);
+static int ng_ksocket_parse(const struct ng_ksocket_alias *aliases,
+ const char *s, int family);
+
+/************************************************************************
+ STRUCT SOCKADDR PARSE TYPE
+ ************************************************************************/
+
+/* Get the length of the data portion of a generic struct sockaddr */
+static int
+ng_parse_generic_sockdata_getLength(const struct ng_parse_type *type,
+ const u_char *start, const u_char *buf)
+{
+ const struct sockaddr *sa;
+
+ sa = (const struct sockaddr *)(buf - SADATA_OFFSET);
+ return sa->sa_len - SADATA_OFFSET;
+}
+
+/* Type for the variable length data portion of a generic struct sockaddr */
+static const struct ng_parse_type ng_ksocket_generic_sockdata_type = {
+ &ng_parse_bytearray_type,
+ &ng_parse_generic_sockdata_getLength
+};
+
+/* Type for a generic struct sockaddr */
+static const struct ng_parse_struct_info ng_parse_generic_sockaddr_type_info = {
+ {
+ { "len", &ng_parse_int8_type },
+ { "family", &ng_parse_int8_type },
+ { "data", &ng_ksocket_generic_sockdata_type },
+ { NULL }
+ }
+};
+static const struct ng_parse_type ng_ksocket_generic_sockaddr_type = {
+ &ng_parse_struct_type,
+ &ng_parse_generic_sockaddr_type_info
+};
+
+/* Convert a struct sockaddr from ASCII to binary. If its a protocol
+ family that we specially handle, do that, otherwise defer to the
+ generic parse type ng_ksocket_generic_sockaddr_type. */
+static int
+ng_ksocket_sockaddr_parse(const struct ng_parse_type *type,
+ const char *s, int *off, const u_char *const start,
+ u_char *const buf, int *buflen)
+{
+ struct sockaddr *const sa = (struct sockaddr *)buf;
+ enum ng_parse_token tok;
+ char fambuf[32];
+ int family, len;
+ char *t;
+
+ /* If next token is a left curly brace, use generic parse type */
+ if ((tok = ng_parse_get_token(s, off, &len)) == T_LBRACE) {
+ return (*ng_ksocket_generic_sockaddr_type.supertype->parse)
+ (&ng_ksocket_generic_sockaddr_type,
+ s, off, start, buf, buflen);
+ }
+
+ /* Get socket address family followed by a slash */
+ while (isspace(s[*off]))
+ (*off)++;
+ if ((t = index(s + *off, '/')) == NULL)
+ return (EINVAL);
+ if ((len = t - (s + *off)) > sizeof(fambuf) - 1)
+ return (EINVAL);
+ strncpy(fambuf, s + *off, len);
+ fambuf[len] = '\0';
+ *off += len + 1;
+ if ((family = ng_ksocket_parse(ng_ksocket_families, fambuf, 0)) == -1)
+ return (EINVAL);
+
+ /* Set family */
+ if (*buflen < SADATA_OFFSET)
+ return (ERANGE);
+ sa->sa_family = family;
+
+ /* Set family-specific data and length */
+ switch (sa->sa_family) {
+ case PF_LOCAL: /* Get pathname */
+ {
+ const int pathoff = OFFSETOF(struct sockaddr_un, sun_path);
+ struct sockaddr_un *const sun = (struct sockaddr_un *)sa;
+ int toklen, pathlen;
+ char *path;
+
+ if ((path = ng_get_string_token(s, off, &toklen)) == NULL)
+ return (EINVAL);
+ pathlen = strlen(path);
+ if (pathlen > SOCK_MAXADDRLEN) {
+ FREE(path, M_NETGRAPH);
+ return (E2BIG);
+ }
+ if (*buflen < pathoff + pathlen) {
+ FREE(path, M_NETGRAPH);
+ return (ERANGE);
+ }
+ *off += toklen;
+ bcopy(path, sun->sun_path, pathlen);
+ sun->sun_len = pathoff + pathlen;
+ FREE(path, M_NETGRAPH);
+ break;
+ }
+
+ case PF_INET: /* Get an IP address with optional port */
+ {
+ struct sockaddr_in *const sin = (struct sockaddr_in *)sa;
+ int i;
+
+ /* Parse this: <ipaddress>[:port] */
+ for (i = 0; i < 4; i++) {
+ u_long val;
+ char *eptr;
+
+ val = strtoul(s + *off, &eptr, 10);
+ if (val > 0xff || eptr == s + *off)
+ return (EINVAL);
+ *off += (eptr - (s + *off));
+ ((u_char *)&sin->sin_addr)[i] = (u_char)val;
+ if (i < 3) {
+ if (s[*off] != '.')
+ return (EINVAL);
+ (*off)++;
+ } else if (s[*off] == ':') {
+ (*off)++;
+ val = strtoul(s + *off, &eptr, 10);
+ if (val > 0xffff || eptr == s + *off)
+ return (EINVAL);
+ *off += (eptr - (s + *off));
+ sin->sin_port = htons(val);
+ } else
+ sin->sin_port = 0;
+ }
+ bzero(&sin->sin_zero, sizeof(sin->sin_zero));
+ sin->sin_len = sizeof(*sin);
+ break;
+ }
+
+#if 0
+ case PF_APPLETALK: /* XXX implement these someday */
+ case PF_INET6:
+ case PF_IPX:
+#endif
+
+ default:
+ return (EINVAL);
+ }
+
+ /* Done */
+ *buflen = sa->sa_len;
+ return (0);
+}
+
+/* Convert a struct sockaddr from binary to ASCII */
+static int
+ng_ksocket_sockaddr_unparse(const struct ng_parse_type *type,
+ const u_char *data, int *off, char *cbuf, int cbuflen)
+{
+ const struct sockaddr *sa = (const struct sockaddr *)(data + *off);
+ int slen = 0;
+
+ /* Output socket address, either in special or generic format */
+ switch (sa->sa_family) {
+ case PF_LOCAL:
+ {
+ const int pathoff = OFFSETOF(struct sockaddr_un, sun_path);
+ const struct sockaddr_un *sun = (const struct sockaddr_un *)sa;
+ const int pathlen = sun->sun_len - pathoff;
+ char pathbuf[SOCK_MAXADDRLEN + 1];
+ char *pathtoken;
+
+ bcopy(sun->sun_path, pathbuf, pathlen);
+ pathbuf[pathlen] = '\0';
+ if ((pathtoken = ng_encode_string(pathbuf)) == NULL)
+ return (ENOMEM);
+ slen += snprintf(cbuf, cbuflen, "local/%s", pathtoken);
+ FREE(pathtoken, M_NETGRAPH);
+ if (slen >= cbuflen)
+ return (ERANGE);
+ *off += sun->sun_len;
+ return (0);
+ }
+
+ case PF_INET:
+ {
+ const struct sockaddr_in *sin = (const struct sockaddr_in *)sa;
+
+ slen += snprintf(cbuf, cbuflen, "inet/%d.%d.%d.%d",
+ ((const u_char *)&sin->sin_addr)[0],
+ ((const u_char *)&sin->sin_addr)[1],
+ ((const u_char *)&sin->sin_addr)[2],
+ ((const u_char *)&sin->sin_addr)[3]);
+ if (sin->sin_port != 0) {
+ slen += snprintf(cbuf + strlen(cbuf),
+ cbuflen - strlen(cbuf), ":%d",
+ (u_int)ntohs(sin->sin_port));
+ }
+ if (slen >= cbuflen)
+ return (ERANGE);
+ *off += sizeof(*sin);
+ return(0);
+ }
+
+#if 0
+ case PF_APPLETALK: /* XXX implement these someday */
+ case PF_INET6:
+ case PF_IPX:
+#endif
+
+ default:
+ return (*ng_ksocket_generic_sockaddr_type.supertype->unparse)
+ (&ng_ksocket_generic_sockaddr_type,
+ data, off, cbuf, cbuflen);
+ }
+}
+
+/* Parse type for struct sockaddr */
+static const struct ng_parse_type ng_ksocket_sockaddr_type = {
+ NULL,
+ NULL,
+ NULL,
+ &ng_ksocket_sockaddr_parse,
+ &ng_ksocket_sockaddr_unparse,
+ NULL /* no such thing as a default struct sockaddr */
+};
+
+/************************************************************************
+ STRUCT NG_KSOCKET_SOCKOPT PARSE TYPE
+ ************************************************************************/
+
+/* Get length of the struct ng_ksocket_sockopt value field, which is the
+ just the excess of the message argument portion over the length of
+ the struct ng_ksocket_sockopt. */
+static int
+ng_parse_sockoptval_getLength(const struct ng_parse_type *type,
+ const u_char *start, const u_char *buf)
+{
+ static const int offset = OFFSETOF(struct ng_ksocket_sockopt, value);
+ const struct ng_ksocket_sockopt *sopt;
+ const struct ng_mesg *msg;
+
+ sopt = (const struct ng_ksocket_sockopt *)(buf - offset);
+ msg = (const struct ng_mesg *)((const u_char *)sopt - sizeof(*msg));
+ return msg->header.arglen - sizeof(*sopt);
+}
+
+/* Parse type for the option value part of a struct ng_ksocket_sockopt
+ XXX Eventually, we should handle the different socket options specially.
+ XXX This would avoid byte order problems, eg an integer value of 1 is
+ XXX going to be "[1]" for little endian or "[3=1]" for big endian. */
+static const struct ng_parse_type ng_ksocket_sockoptval_type = {
+ &ng_parse_bytearray_type,
+ &ng_parse_sockoptval_getLength
+};
+
+/* Parse type for struct ng_ksocket_sockopt */
+static const struct ng_parse_struct_info ng_ksocket_sockopt_type_info
+ = NG_KSOCKET_SOCKOPT_INFO(&ng_ksocket_sockoptval_type);
+static const struct ng_parse_type ng_ksocket_sockopt_type = {
+ &ng_parse_struct_type,
+ &ng_ksocket_sockopt_type_info,
+};
+
+/* List of commands and how to convert arguments to/from ASCII */
+static const struct ng_cmdlist ng_ksocket_cmds[] = {
+ {
+ NGM_KSOCKET_COOKIE,
+ NGM_KSOCKET_BIND,
+ "bind",
+ &ng_ksocket_sockaddr_type,
+ NULL
+ },
+ {
+ NGM_KSOCKET_COOKIE,
+ NGM_KSOCKET_LISTEN,
+ "listen",
+ &ng_parse_int32_type,
+ NULL
+ },
+ {
+ NGM_KSOCKET_COOKIE,
+ NGM_KSOCKET_ACCEPT,
+ "accept",
+ NULL,
+ &ng_ksocket_sockaddr_type
+ },
+ {
+ NGM_KSOCKET_COOKIE,
+ NGM_KSOCKET_CONNECT,
+ "connect",
+ &ng_ksocket_sockaddr_type,
+ NULL
+ },
+ {
+ NGM_KSOCKET_COOKIE,
+ NGM_KSOCKET_GETNAME,
+ "getname",
+ NULL,
+ &ng_ksocket_sockaddr_type
+ },
+ {
+ NGM_KSOCKET_COOKIE,
+ NGM_KSOCKET_GETPEERNAME,
+ "getpeername",
+ NULL,
+ &ng_ksocket_sockaddr_type
+ },
+ {
+ NGM_KSOCKET_COOKIE,
+ NGM_KSOCKET_SETOPT,
+ "setopt",
+ &ng_ksocket_sockopt_type,
+ NULL
+ },
+ {
+ NGM_KSOCKET_COOKIE,
+ NGM_KSOCKET_GETOPT,
+ "getopt",
+ &ng_ksocket_sockopt_type,
+ &ng_ksocket_sockopt_type
+ },
+ { 0 }
+};
+
+/* Node type descriptor */
+static struct ng_type ng_ksocket_typestruct = {
+ NG_VERSION,
+ NG_KSOCKET_NODE_TYPE,
+ NULL,
+ ng_ksocket_constructor,
+ ng_ksocket_rcvmsg,
+ ng_ksocket_rmnode,
+ ng_ksocket_newhook,
+ NULL,
+ NULL,
+ ng_ksocket_rcvdata,
+ ng_ksocket_rcvdata,
+ ng_ksocket_disconnect,
+ ng_ksocket_cmds
+};
+NETGRAPH_INIT(ksocket, &ng_ksocket_typestruct);
+
#define ERROUT(x) do { error = (x); goto done; } while (0)
/************************************************************************
@@ -193,10 +521,10 @@ ng_ksocket_constructor(node_p *nodep)
static int
ng_ksocket_newhook(node_p node, hook_p hook, const char *name0)
{
+ struct proc *p = curproc ? curproc : &proc0; /* XXX broken */
const priv_p priv = node->private;
char *s1, *s2, name[NG_HOOKLEN+1];
int family, type, protocol, error;
- struct proc *p = &proc0; /* XXX help what to do here */
/* Check if we're already connected */
if (priv->hook != NULL)
@@ -243,9 +571,10 @@ static int
ng_ksocket_rcvmsg(node_p node, struct ng_mesg *msg,
const char *raddr, struct ng_mesg **rptr)
{
+ struct proc *p = curproc ? curproc : &proc0; /* XXX broken */
const priv_p priv = node->private;
+ struct socket *const so = priv->so;
struct ng_mesg *resp = NULL;
- struct proc *p = &proc0;
int error = 0;
switch (msg->header.typecookie) {
@@ -253,62 +582,68 @@ ng_ksocket_rcvmsg(node_p node, struct ng_mesg *msg,
switch (msg->header.cmd) {
case NGM_KSOCKET_BIND:
{
- struct sockaddr *sa = (struct sockaddr *)msg->data;
- struct socket *const so = priv->so;
+ struct sockaddr *const sa
+ = (struct sockaddr *)msg->data;
- /* Must have a connected hook first */
- if (priv->hook == NULL)
- ERROUT(ENETDOWN);
+ /* Sanity check */
+ if (msg->header.arglen < SADATA_OFFSET
+ || msg->header.arglen < sa->sa_len)
+ ERROUT(EINVAL);
+ if (so == NULL)
+ ERROUT(ENXIO);
- /* Set and sanity check sockaddr length */
- if (msg->header.arglen > SOCK_MAXADDRLEN)
- ERROUT(ENAMETOOLONG);
- sa->sa_len = msg->header.arglen;
+ /* Bind */
error = sobind(so, sa, p);
break;
}
case NGM_KSOCKET_LISTEN:
{
- struct socket *const so = priv->so;
- int backlog;
-
- /* Must have a connected hook first */
- if (priv->hook == NULL)
- ERROUT(ENETDOWN);
-
- /* Get backlog argument */
+ /* Sanity check */
if (msg->header.arglen != sizeof(int))
ERROUT(EINVAL);
- backlog = *((int *)msg->data);
+ if (so == NULL)
+ ERROUT(ENXIO);
- /* Do listen */
- if ((error = solisten(so, backlog, p)) != 0)
+ /* Listen */
+ if ((error = solisten(so, *((int *)msg->data), p)) != 0)
break;
/* Notify sender when we get a connection attempt */
/* XXX implement me */
+ error = ENODEV;
break;
}
case NGM_KSOCKET_ACCEPT:
{
- ERROUT(ENODEV); /* XXX implement me */
+ /* Sanity check */
+ if (msg->header.arglen != 0)
+ ERROUT(EINVAL);
+ if (so == NULL)
+ ERROUT(ENXIO);
+
+ /* Accept on the socket in a non-blocking way */
+ /* Create a new ksocket node for the new connection */
+ /* Return a response with the peer's sockaddr and
+ the absolute name of the newly created node */
+
+ /* XXX implement me */
+
+ error = ENODEV;
break;
}
case NGM_KSOCKET_CONNECT:
{
- struct socket *const so = priv->so;
- struct sockaddr *sa = (struct sockaddr *)msg->data;
-
- /* Must have a connected hook first */
- if (priv->hook == NULL)
- ERROUT(ENETDOWN);
+ struct sockaddr *const sa
+ = (struct sockaddr *)msg->data;
- /* Set and sanity check sockaddr length */
- if (msg->header.arglen > SOCK_MAXADDRLEN)
- ERROUT(ENAMETOOLONG);
- sa->sa_len = msg->header.arglen;
+ /* Sanity check */
+ if (msg->header.arglen < SADATA_OFFSET
+ || msg->header.arglen < sa->sa_len)
+ ERROUT(EINVAL);
+ if (so == NULL)
+ ERROUT(ENXIO);
/* Do connect */
if ((so->so_state & SS_ISCONNECTING) != 0)
@@ -325,26 +660,105 @@ ng_ksocket_rcvmsg(node_p node, struct ng_mesg *msg,
}
case NGM_KSOCKET_GETNAME:
- {
- ERROUT(ENODEV); /* XXX implement me */
- break;
- }
-
case NGM_KSOCKET_GETPEERNAME:
{
- ERROUT(ENODEV); /* XXX implement me */
+ int (*func)(struct socket *so, struct sockaddr **nam);
+ struct sockaddr *sa = NULL;
+ int len;
+
+ /* Sanity check */
+ if (msg->header.arglen != 0)
+ ERROUT(EINVAL);
+ if (so == NULL)
+ ERROUT(ENXIO);
+
+ /* Get function */
+ if (msg->header.cmd == NGM_KSOCKET_GETPEERNAME) {
+ if ((so->so_state
+ & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0)
+ ERROUT(ENOTCONN);
+ func = so->so_proto->pr_usrreqs->pru_peeraddr;
+ } else
+ func = so->so_proto->pr_usrreqs->pru_sockaddr;
+
+ /* Get local or peer address */
+ if ((error = (*func)(so, &sa)) != 0)
+ goto bail;
+ len = (sa == NULL) ? 0 : sa->sa_len;
+
+ /* Send it back in a response */
+ NG_MKRESPONSE(resp, msg, len, M_NOWAIT);
+ if (resp == NULL) {
+ error = ENOMEM;
+ goto bail;
+ }
+ bcopy(sa, resp->data, len);
+
+ bail:
+ /* Cleanup */
+ if (sa != NULL)
+ FREE(sa, M_SONAME);
break;
}
case NGM_KSOCKET_GETOPT:
{
- ERROUT(ENODEV); /* XXX implement me */
+ struct ng_ksocket_sockopt *ksopt =
+ (struct ng_ksocket_sockopt *)msg->data;
+ struct sockopt sopt;
+
+ /* Sanity check */
+ if (msg->header.arglen != sizeof(*ksopt))
+ ERROUT(EINVAL);
+ if (so == NULL)
+ ERROUT(ENXIO);
+
+ /* Get response with room for option value */
+ NG_MKRESPONSE(resp, msg, sizeof(*ksopt)
+ + NG_KSOCKET_MAX_OPTLEN, M_NOWAIT);
+ if (resp == NULL)
+ ERROUT(ENOMEM);
+
+ /* Get socket option, and put value in the response */
+ sopt.sopt_dir = SOPT_GET;
+ sopt.sopt_level = ksopt->level;
+ sopt.sopt_name = ksopt->name;
+ sopt.sopt_p = p;
+ sopt.sopt_valsize = NG_KSOCKET_MAX_OPTLEN;
+ ksopt = (struct ng_ksocket_sockopt *)resp->data;
+ sopt.sopt_val = ksopt->value;
+ if ((error = sogetopt(so, &sopt)) != 0) {
+ FREE(resp, M_NETGRAPH);
+ break;
+ }
+
+ /* Set actual value length */
+ resp->header.arglen = sizeof(*ksopt)
+ + sopt.sopt_valsize;
break;
}
case NGM_KSOCKET_SETOPT:
{
- ERROUT(ENODEV); /* XXX implement me */
+ struct ng_ksocket_sockopt *const ksopt =
+ (struct ng_ksocket_sockopt *)msg->data;
+ const int valsize = msg->header.arglen - sizeof(*ksopt);
+ struct sockopt sopt;
+
+ /* Sanity check */
+ if (valsize < 0)
+ ERROUT(EINVAL);
+ if (so == NULL)
+ ERROUT(ENXIO);
+
+ /* Set socket option */
+ sopt.sopt_dir = SOPT_SET;
+ sopt.sopt_level = ksopt->level;
+ sopt.sopt_name = ksopt->name;
+ sopt.sopt_val = ksopt->value;
+ sopt.sopt_valsize = valsize;
+ sopt.sopt_p = p;
+ error = sosetopt(so, &sopt);
break;
}
@@ -373,10 +787,10 @@ done:
static int
ng_ksocket_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
{
+ struct proc *p = curproc ? curproc : &proc0; /* XXX broken */
const node_p node = hook->node;
const priv_p priv = node->private;
struct socket *const so = priv->so;
- struct proc *p = &proc0;
int error;
NG_FREE_META(meta);
@@ -394,6 +808,9 @@ ng_ksocket_rmnode(node_p node)
/* Close our socket (if any) */
if (priv->so != NULL) {
+
+ priv->so->so_upcall = NULL;
+ priv->so->so_rcv.sb_flags &= ~SB_UPCALL;
soclose(priv->so);
priv->so = NULL;
}
@@ -455,8 +872,16 @@ ng_ksocket_incoming(struct socket *so, void *arg, int waitflag)
flags = MSG_DONTWAIT;
do {
if ((error = (*so->so_proto->pr_usrreqs->pru_soreceive)
- (so, &nam, &auio, &m, (struct mbuf **)0, &flags)) == 0)
+ (so, &nam, &auio, &m, (struct mbuf **)0, &flags)) == 0
+ && m != NULL) {
+ struct mbuf *n;
+
+ /* Don't trust the various socket layers to get the
+ packet header and length correct (eg. kern/15175) */
+ for (n = m, m->m_pkthdr.len = 0; n; n = n->m_next)
+ m->m_pkthdr.len += n->m_len;
NG_SEND_DATA(error, priv->hook, m, meta);
+ }
} while (error == 0 && m != NULL);
splx(s);
}
@@ -480,7 +905,7 @@ ng_ksocket_parse(const struct ng_ksocket_alias *aliases,
/* Try parsing as a number */
val = (int)strtoul(s, &eptr, 10);
- if (val <= 0 || *eptr != '\0')
+ if (val < 0 || *eptr != '\0')
return (-1);
return (val);
}
diff --git a/sys/netgraph/ng_ksocket.h b/sys/netgraph/ng_ksocket.h
index 93f3752..48cb41f 100644
--- a/sys/netgraph/ng_ksocket.h
+++ b/sys/netgraph/ng_ksocket.h
@@ -47,6 +47,28 @@
#define NG_KSOCKET_NODE_TYPE "ksocket"
#define NGM_KSOCKET_COOKIE 942710669
+/* For NGM_KSOCKET_SETOPT and NGM_KSOCKET_GETOPT control messages */
+struct ng_ksocket_sockopt {
+ u_int32_t level; /* second arg of [gs]etsockopt() */
+ u_int32_t name; /* third arg of [gs]etsockopt() */
+ u_char value[0]; /* fourth arg of [gs]etsockopt() */
+};
+
+/* Max length socket option we can return via NGM_KSOCKET_GETOPT
+ XXX This should not be necessary, we should dynamically size
+ XXX the response. Until then.. */
+#define NG_KSOCKET_MAX_OPTLEN 1024
+
+/* Keep this in sync with the above structure definition */
+#define NG_KSOCKET_SOCKOPT_INFO(svtype) { \
+ { \
+ { "level", &ng_parse_int32_type }, \
+ { "name", &ng_parse_int32_type }, \
+ { "value", (svtype) }, \
+ { NULL }, \
+ } \
+}
+
/* Netgraph commands */
enum {
NGM_KSOCKET_BIND = 1,
diff --git a/sys/netgraph/ng_lmi.c b/sys/netgraph/ng_lmi.c
index 9dcfa38..3a3afc9 100644
--- a/sys/netgraph/ng_lmi.c
+++ b/sys/netgraph/ng_lmi.c
@@ -109,7 +109,8 @@ static struct ng_type typestruct = {
NULL,
nglmi_rcvdata,
nglmi_rcvdata,
- nglmi_disconnect
+ nglmi_disconnect,
+ NULL
};
NETGRAPH_INIT(lmi, &typestruct);
diff --git a/sys/netgraph/ng_message.h b/sys/netgraph/ng_message.h
index 66c7fba..aab7314 100644
--- a/sys/netgraph/ng_message.h
+++ b/sys/netgraph/ng_message.h
@@ -65,10 +65,33 @@ struct ng_mesg {
} header;
char data[0]; /* placeholder for actual data */
};
-#define NG_VERSION 1
+
+/* Keep this in sync with the above structure definition */
+#define NG_GENERIC_NG_MESG_INFO(dtype) { \
+ { \
+ { "version", &ng_parse_int8_type }, \
+ { "spare", &ng_parse_int8_type }, \
+ { "arglen", &ng_parse_int16_type }, \
+ { "flags", &ng_parse_int32_type }, \
+ { "token", &ng_parse_int32_type }, \
+ { "typecookie", &ng_parse_int32_type }, \
+ { "cmd", &ng_parse_int32_type }, \
+ { "cmdstr", &ng_parse_cmdbuf_type }, \
+ { "data", (dtype) }, \
+ { NULL }, \
+ } \
+}
+
+/* Negraph type binary compatibility field */
+#define NG_VERSION 2
+
+/* Flags field flags */
#define NGF_ORIG 0x0000 /* the msg is the original request */
#define NGF_RESP 0x0001 /* the message is a response */
+/* Type of a unique node ID */
+#define ng_ID_t unsigned int
+
/*
* Here we describe the "generic" messages that all nodes inherently
* understand. With the exception of NGM_TEXT_STATUS, these are handled
@@ -76,46 +99,84 @@ struct ng_mesg {
*/
/* Generic message type cookie */
-#define NGM_GENERIC_COOKIE 851672668
+#define NGM_GENERIC_COOKIE 851672668
/* Generic messages defined for this type cookie */
-#define NGM_SHUTDOWN 0x0001 /* no args */
-#define NGM_MKPEER 0x0002
-#define NGM_CONNECT 0x0003
-#define NGM_NAME 0x0004
-#define NGM_RMHOOK 0x0005
-#define NGM_NODEINFO 0x0006 /* get nodeinfo for the target */
-#define NGM_LISTHOOKS 0x0007 /* get nodeinfo for the target + hook info */
-#define NGM_LISTNAMES 0x0008 /* list all globally named nodes */
-#define NGM_LISTNODES 0x0009 /* list all nodes, named and unnamed */
-#define NGM_LISTTYPES 0x000a /* list all installed node types */
-#define NGM_TEXT_STATUS 0x000b /* (optional) returns human readable status */
+#define NGM_SHUTDOWN 1 /* shut down node */
+#define NGM_MKPEER 2 /* create and attach a peer node */
+#define NGM_CONNECT 3 /* connect two nodes */
+#define NGM_NAME 4 /* give a node a name */
+#define NGM_RMHOOK 5 /* break a connection btw. two nodes */
+#define NGM_NODEINFO 6 /* get nodeinfo for the target */
+#define NGM_LISTHOOKS 7 /* get list of hooks on node */
+#define NGM_LISTNAMES 8 /* list all globally named nodes */
+#define NGM_LISTNODES 9 /* list all nodes, named and unnamed */
+#define NGM_LISTTYPES 10 /* list all installed node types */
+#define NGM_TEXT_STATUS 11 /* (optional) get text status report */
+#define NGM_BINARY2ASCII 12 /* convert struct ng_mesg to ascii */
+#define NGM_ASCII2BINARY 13 /* convert ascii to struct ng_mesg */
-/*
- * Args sections for generic NG commands. All strings are NUL-terminated.
- */
+/* Structure used for NGM_MKPEER */
struct ngm_mkpeer {
char type[NG_TYPELEN + 1]; /* peer type */
char ourhook[NG_HOOKLEN + 1]; /* hook name */
char peerhook[NG_HOOKLEN + 1]; /* peer hook name */
};
+/* Keep this in sync with the above structure definition */
+#define NG_GENERIC_MKPEER_INFO() { \
+ { \
+ { "type", &ng_parse_typebuf_type }, \
+ { "ourhook", &ng_parse_hookbuf_type }, \
+ { "peerhook", &ng_parse_hookbuf_type }, \
+ { NULL }, \
+ } \
+}
+
+/* Structure used for NGM_CONNECT */
struct ngm_connect {
char path[NG_PATHLEN + 1]; /* peer path */
char ourhook[NG_HOOKLEN + 1]; /* hook name */
char peerhook[NG_HOOKLEN + 1]; /* peer hook name */
};
+/* Keep this in sync with the above structure definition */
+#define NG_GENERIC_CONNECT_INFO() { \
+ { \
+ { "path", &ng_parse_pathbuf_type }, \
+ { "ourhook", &ng_parse_hookbuf_type }, \
+ { "peerhook", &ng_parse_hookbuf_type }, \
+ { NULL }, \
+ } \
+}
+
+/* Structure used for NGM_NAME */
struct ngm_name {
char name[NG_NODELEN + 1]; /* node name */
};
+/* Keep this in sync with the above structure definition */
+#define NG_GENERIC_NAME_INFO() { \
+ { \
+ { "name", &ng_parse_nodebuf_type }, \
+ { NULL }, \
+ } \
+}
+
+/* Structure used for NGM_RMHOOK */
struct ngm_rmhook {
char ourhook[NG_HOOKLEN + 1]; /* hook name */
};
-#define ng_ID_t unsigned int
-/* Structures used in response to NGM_NODEINFO and NGM_LISTHOOKS */
+/* Keep this in sync with the above structure definition */
+#define NG_GENERIC_RMHOOK_INFO() { \
+ { \
+ { "hook", &ng_parse_hookbuf_type }, \
+ { NULL }, \
+ } \
+}
+
+/* Structure used for NGM_NODEINFO */
struct nodeinfo {
char name[NG_NODELEN + 1]; /* node name (if any) */
char type[NG_TYPELEN + 1]; /* peer type */
@@ -123,34 +184,92 @@ struct nodeinfo {
u_int32_t hooks; /* number of active hooks */
};
+/* Keep this in sync with the above structure definition */
+#define NG_GENERIC_NODEINFO_INFO() { \
+ { \
+ { "name", &ng_parse_nodebuf_type }, \
+ { "type", &ng_parse_typebuf_type }, \
+ { "id", &ng_parse_int32_type }, \
+ { "hooks", &ng_parse_int32_type }, \
+ { NULL }, \
+ } \
+}
+
+/* Structure used for NGM_LISTHOOKS */
struct linkinfo {
char ourhook[NG_HOOKLEN + 1]; /* hook name */
char peerhook[NG_HOOKLEN + 1]; /* peer hook */
struct nodeinfo nodeinfo;
};
+/* Keep this in sync with the above structure definition */
+#define NG_GENERIC_LINKINFO_INFO(nitype) { \
+ { \
+ { "ourhook", &ng_parse_hookbuf_type }, \
+ { "peerhook", &ng_parse_hookbuf_type }, \
+ { "nodeinfo", (nitype) }, \
+ { NULL }, \
+ } \
+}
+
struct hooklist {
struct nodeinfo nodeinfo; /* node information */
struct linkinfo link[0]; /* info about each hook */
};
-/* Structure used for NGM_LISTNAMES/NGM_LISTNODES (not node specific) */
+/* Keep this in sync with the above structure definition */
+#define NG_GENERIC_HOOKLIST_INFO(nitype,litype) { \
+ { \
+ { "nodeinfo", (nitype) }, \
+ { "linkinfo", (litype) }, \
+ { NULL }, \
+ } \
+}
+
+/* Structure used for NGM_LISTNAMES/NGM_LISTNODES */
struct namelist {
u_int32_t numnames;
struct nodeinfo nodeinfo[0];
};
-/* Structures used for NGM_LISTTYPES (not node specific) */
+/* Keep this in sync with the above structure definition */
+#define NG_GENERIC_LISTNODES_INFO(niarraytype) { \
+ { \
+ { "numnames", &ng_parse_int32_type }, \
+ { "nodeinfo", (niarraytype) }, \
+ { NULL }, \
+ } \
+}
+
+/* Structure used for NGM_LISTTYPES */
struct typeinfo {
char typename[NG_TYPELEN + 1]; /* name of type */
u_int32_t numnodes; /* number alive */
};
+/* Keep this in sync with the above structure definition */
+#define NG_GENERIC_TYPEINFO_INFO() { \
+ { \
+ { "typename", &ng_parse_typebuf_type }, \
+ { "typeinfo", &ng_parse_int32_type }, \
+ { NULL }, \
+ } \
+}
+
struct typelist {
u_int32_t numtypes;
struct typeinfo typeinfo[0];
};
+/* Keep this in sync with the above structure definition */
+#define NG_GENERIC_TYPELIST_INFO(tiarraytype) { \
+ { \
+ { "numtypes", &ng_parse_int32_type }, \
+ { "typeinfo", (tiarraytype) }, \
+ { NULL }, \
+ } \
+}
+
/*
* For netgraph nodes that are somehow associated with file descriptors
* (e.g., a device that has a /dev entry and is also a netgraph node),
diff --git a/sys/netgraph/ng_parse.c b/sys/netgraph/ng_parse.c
new file mode 100644
index 0000000..795d1c1
--- /dev/null
+++ b/sys/netgraph/ng_parse.c
@@ -0,0 +1,1604 @@
+
+/*
+ * ng_parse.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.
+ *
+ * Author: Archie Cobbs <archie@whistle.com>
+ *
+ * $Whistle: ng_parse.c,v 1.3 1999/11/29 01:43:48 archie Exp $
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/ctype.h>
+
+#include <netinet/in.h>
+
+#include <netgraph/ng_message.h>
+#include <netgraph/netgraph.h>
+#include <netgraph/ng_parse.h>
+
+/* Compute alignment for primitive integral types */
+struct int16_temp {
+ char x;
+ int16_t y;
+};
+
+struct int32_temp {
+ char x;
+ int32_t y;
+};
+
+struct int64_temp {
+ char x;
+ int64_t y;
+};
+
+#define INT8_ALIGNMENT 1
+#define INT16_ALIGNMENT ((int)&((struct int16_temp *)0)->y)
+#define INT32_ALIGNMENT ((int)&((struct int32_temp *)0)->y)
+#define INT64_ALIGNMENT ((int)&((struct int64_temp *)0)->y)
+
+/* Type of composite object: struct, array, or fixedarray */
+enum comptype {
+ CT_STRUCT,
+ CT_ARRAY,
+ CT_FIXEDARRAY,
+};
+
+/* Composite types helper functions */
+static int ng_parse_composite(const struct ng_parse_type *type,
+ const char *s, int *off, const u_char *start,
+ u_char *const buf, int *buflen, enum comptype ctype);
+static int ng_unparse_composite(const struct ng_parse_type *type,
+ const u_char *data, int *off, char *cbuf, int cbuflen,
+ enum comptype ctype);
+static int ng_get_composite_elem_default(const struct ng_parse_type *type,
+ int index, const u_char *start, u_char *buf,
+ int *buflen, enum comptype ctype);
+static int ng_get_composite_len(const struct ng_parse_type *type,
+ const u_char *start, const u_char *buf,
+ enum comptype ctype);
+static const struct ng_parse_type *ng_get_composite_etype(const struct
+ ng_parse_type *type, int index, enum comptype ctype);
+static int ng_parse_get_elem_pad(const struct ng_parse_type *type,
+ int index, enum comptype ctype, int posn);
+
+/* Parsing helper functions */
+static int ng_parse_skip_value(const char *s, int off, int *lenp);
+
+/* Poor man's virtual method calls */
+#define METHOD(t,m) (ng_get_ ## m ## _method(t))
+#define INVOKE(t,m) (*METHOD(t,m))
+
+static ng_parse_t *ng_get_parse_method(const struct ng_parse_type *t);
+static ng_unparse_t *ng_get_unparse_method(const struct ng_parse_type *t);
+static ng_getDefault_t *ng_get_getDefault_method(const
+ struct ng_parse_type *t);
+static ng_getAlign_t *ng_get_getAlign_method(const struct ng_parse_type *t);
+
+#define ALIGNMENT(t) (METHOD(t, getAlign) == NULL ? \
+ 0 : INVOKE(t, getAlign)(t))
+
+/* For converting binary to string */
+#define NG_PARSE_APPEND(fmt, args...) \
+ do { \
+ int len; \
+ \
+ len = snprintf((cbuf), (cbuflen), \
+ fmt , ## args); \
+ if (len >= (cbuflen)) \
+ return (ERANGE); \
+ (cbuf) += len; \
+ (cbuflen) -= len; \
+ } while (0)
+
+/************************************************************************
+ PUBLIC FUNCTIONS
+ ************************************************************************/
+
+/*
+ * Convert an ASCII string to binary according to the supplied type descriptor
+ */
+int
+ng_parse(const struct ng_parse_type *type,
+ const char *string, int *off, u_char *buf, int *buflen)
+{
+ return INVOKE(type, parse)(type, string, off, buf, buf, buflen);
+}
+
+/*
+ * Convert binary to an ASCII string according to the supplied type descriptor
+ */
+int
+ng_unparse(const struct ng_parse_type *type,
+ const u_char *data, char *cbuf, int cbuflen)
+{
+ int off = 0;
+
+ return INVOKE(type, unparse)(type, data, &off, cbuf, cbuflen);
+}
+
+/*
+ * Fill in the default value according to the supplied type descriptor
+ */
+int
+ng_parse_getDefault(const struct ng_parse_type *type, u_char *buf, int *buflen)
+{
+ ng_getDefault_t *const func = METHOD(type, getDefault);
+
+ if (func == NULL)
+ return (EOPNOTSUPP);
+ return (*func)(type, buf, buf, buflen);
+}
+
+
+/************************************************************************
+ STRUCTURE TYPE
+ ************************************************************************/
+
+static int
+ng_struct_parse(const struct ng_parse_type *type,
+ const char *s, int *off, const u_char *const start,
+ u_char *const buf, int *buflen)
+{
+ return ng_parse_composite(type, s, off, start, buf, buflen, CT_STRUCT);
+}
+
+static int
+ng_struct_unparse(const struct ng_parse_type *type,
+ const u_char *data, int *off, char *cbuf, int cbuflen)
+{
+ return ng_unparse_composite(type, data, off, cbuf, cbuflen, CT_STRUCT);
+}
+
+static int
+ng_struct_getDefault(const struct ng_parse_type *type,
+ const u_char *const start, u_char *buf, int *buflen)
+{
+ int off = 0;
+
+ return ng_parse_composite(type,
+ "{}", &off, start, buf, buflen, CT_STRUCT);
+}
+
+static int
+ng_struct_getAlign(const struct ng_parse_type *type)
+{
+ const struct ng_parse_struct_info *si = type->info;
+ const struct ng_parse_struct_field *field;
+ int align = 0;
+
+ for (field = si->fields; field->name != NULL; field++) {
+ int falign = ALIGNMENT(field->type);
+
+ if (falign > align)
+ align = falign;
+ }
+ return align;
+}
+
+const struct ng_parse_type ng_parse_struct_type = {
+ NULL,
+ NULL,
+ NULL,
+ ng_struct_parse,
+ ng_struct_unparse,
+ ng_struct_getDefault,
+ ng_struct_getAlign
+};
+
+/************************************************************************
+ FIXED LENGTH ARRAY TYPE
+ ************************************************************************/
+
+static int
+ng_fixedarray_parse(const struct ng_parse_type *type,
+ const char *s, int *off, const u_char *const start,
+ u_char *const buf, int *buflen)
+{
+ return ng_parse_composite(type,
+ s, off, start, buf, buflen, CT_FIXEDARRAY);
+}
+
+static int
+ng_fixedarray_unparse(const struct ng_parse_type *type,
+ const u_char *data, int *off, char *cbuf, int cbuflen)
+{
+ return ng_unparse_composite(type,
+ data, off, cbuf, cbuflen, CT_FIXEDARRAY);
+}
+
+static int
+ng_fixedarray_getDefault(const struct ng_parse_type *type,
+ const u_char *const start, u_char *buf, int *buflen)
+{
+ int off = 0;
+
+ return ng_parse_composite(type,
+ "[]", &off, start, buf, buflen, CT_FIXEDARRAY);
+}
+
+static int
+ng_fixedarray_getAlign(const struct ng_parse_type *type)
+{
+ const struct ng_parse_fixedarray_info *fi = type->info;
+
+ return ALIGNMENT(fi->elementType);
+}
+
+const struct ng_parse_type ng_parse_fixedarray_type = {
+ NULL,
+ NULL,
+ NULL,
+ ng_fixedarray_parse,
+ ng_fixedarray_unparse,
+ ng_fixedarray_getDefault,
+ ng_fixedarray_getAlign
+};
+
+/************************************************************************
+ VARIABLE LENGTH ARRAY TYPE
+ ************************************************************************/
+
+static int
+ng_array_parse(const struct ng_parse_type *type,
+ const char *s, int *off, const u_char *const start,
+ u_char *const buf, int *buflen)
+{
+ return ng_parse_composite(type, s, off, start, buf, buflen, CT_ARRAY);
+}
+
+static int
+ng_array_unparse(const struct ng_parse_type *type,
+ const u_char *data, int *off, char *cbuf, int cbuflen)
+{
+ return ng_unparse_composite(type, data, off, cbuf, cbuflen, CT_ARRAY);
+}
+
+static int
+ng_array_getDefault(const struct ng_parse_type *type,
+ const u_char *const start, u_char *buf, int *buflen)
+{
+ int off = 0;
+
+ return ng_parse_composite(type,
+ "[]", &off, start, buf, buflen, CT_ARRAY);
+}
+
+static int
+ng_array_getAlign(const struct ng_parse_type *type)
+{
+ const struct ng_parse_array_info *ai = type->info;
+
+ return ALIGNMENT(ai->elementType);
+}
+
+const struct ng_parse_type ng_parse_array_type = {
+ NULL,
+ NULL,
+ NULL,
+ ng_array_parse,
+ ng_array_unparse,
+ ng_array_getDefault,
+ ng_array_getAlign
+};
+
+/************************************************************************
+ INT8 TYPE
+ ************************************************************************/
+
+static int
+ng_int8_parse(const struct ng_parse_type *type,
+ const char *s, int *off, const u_char *const start,
+ u_char *const buf, int *buflen)
+{
+ long val;
+ int8_t val8;
+ char *eptr;
+
+ val = strtol(s + *off, &eptr, 0);
+ if (val < -0x80 || val > 0xff || eptr == s + *off)
+ return (EINVAL);
+ *off = eptr - s;
+ val8 = (int8_t)val;
+ bcopy(&val8, buf, sizeof(int8_t));
+ *buflen = sizeof(int8_t);
+ return (0);
+}
+
+static int
+ng_int8_unparse(const struct ng_parse_type *type,
+ const u_char *data, int *off, char *cbuf, int cbuflen)
+{
+ int8_t val;
+
+ bcopy(data + *off, &val, sizeof(int8_t));
+ NG_PARSE_APPEND("%d", (int)val);
+ *off += sizeof(int8_t);
+ return (0);
+}
+
+static int
+ng_int8_getDefault(const struct ng_parse_type *type,
+ const u_char *const start, u_char *buf, int *buflen)
+{
+ int8_t val;
+
+ if (*buflen < sizeof(int8_t))
+ return (ERANGE);
+ val = 0;
+ bcopy(&val, buf, sizeof(int8_t));
+ *buflen = sizeof(int8_t);
+ return (0);
+}
+
+static int
+ng_int8_getAlign(const struct ng_parse_type *type)
+{
+ return INT8_ALIGNMENT;
+}
+
+const struct ng_parse_type ng_parse_int8_type = {
+ NULL,
+ NULL,
+ NULL,
+ ng_int8_parse,
+ ng_int8_unparse,
+ ng_int8_getDefault,
+ ng_int8_getAlign
+};
+
+/************************************************************************
+ INT16 TYPE
+ ************************************************************************/
+
+static int
+ng_int16_parse(const struct ng_parse_type *type,
+ const char *s, int *off, const u_char *const start,
+ u_char *const buf, int *buflen)
+{
+ long val;
+ int16_t val16;
+ char *eptr;
+
+ val = strtol(s + *off, &eptr, 0);
+ if (val < -0x8000 || val > 0xffff || eptr == s + *off)
+ return (EINVAL);
+ *off = eptr - s;
+ val16 = (int16_t)val;
+ bcopy(&val16, buf, sizeof(int16_t));
+ *buflen = sizeof(int16_t);
+ return (0);
+}
+
+static int
+ng_int16_unparse(const struct ng_parse_type *type,
+ const u_char *data, int *off, char *cbuf, int cbuflen)
+{
+ int16_t val;
+
+ bcopy(data + *off, &val, sizeof(int16_t));
+ NG_PARSE_APPEND("%d", (int)val);
+ *off += sizeof(int16_t);
+ return (0);
+}
+
+static int
+ng_int16_getDefault(const struct ng_parse_type *type,
+ const u_char *const start, u_char *buf, int *buflen)
+{
+ int16_t val;
+
+ if (*buflen < sizeof(int16_t))
+ return (ERANGE);
+ val = 0;
+ bcopy(&val, buf, sizeof(int16_t));
+ *buflen = sizeof(int16_t);
+ return (0);
+}
+
+static int
+ng_int16_getAlign(const struct ng_parse_type *type)
+{
+ return INT16_ALIGNMENT;
+}
+
+const struct ng_parse_type ng_parse_int16_type = {
+ NULL,
+ NULL,
+ NULL,
+ ng_int16_parse,
+ ng_int16_unparse,
+ ng_int16_getDefault,
+ ng_int16_getAlign
+};
+
+/************************************************************************
+ INT32 TYPE
+ ************************************************************************/
+
+static int
+ng_int32_parse(const struct ng_parse_type *type,
+ const char *s, int *off, const u_char *const start,
+ u_char *const buf, int *buflen)
+{
+ long val; /* assumes long is at least 32 bits */
+ int32_t val32;
+ char *eptr;
+
+ val = strtol(s + *off, &eptr, 0);
+ if (val < -0x80000000 || val > 0xffffffff || eptr == s + *off)
+ return (EINVAL);
+ *off = eptr - s;
+ val32 = (int32_t)val;
+ bcopy(&val32, buf, sizeof(int32_t));
+ *buflen = sizeof(int32_t);
+ return (0);
+}
+
+static int
+ng_int32_unparse(const struct ng_parse_type *type,
+ const u_char *data, int *off, char *cbuf, int cbuflen)
+{
+ int32_t val;
+
+ bcopy(data + *off, &val, sizeof(int32_t));
+ NG_PARSE_APPEND("%ld", (long)val);
+ *off += sizeof(int32_t);
+ return (0);
+}
+
+static int
+ng_int32_getDefault(const struct ng_parse_type *type,
+ const u_char *const start, u_char *buf, int *buflen)
+{
+ int32_t val;
+
+ if (*buflen < sizeof(int32_t))
+ return (ERANGE);
+ val = 0;
+ bcopy(&val, buf, sizeof(int32_t));
+ *buflen = sizeof(int32_t);
+ return (0);
+}
+
+static int
+ng_int32_getAlign(const struct ng_parse_type *type)
+{
+ return INT32_ALIGNMENT;
+}
+
+const struct ng_parse_type ng_parse_int32_type = {
+ NULL,
+ NULL,
+ NULL,
+ ng_int32_parse,
+ ng_int32_unparse,
+ ng_int32_getDefault,
+ ng_int32_getAlign
+};
+
+/************************************************************************
+ INT64 TYPE
+ ************************************************************************/
+
+static int
+ng_int64_parse(const struct ng_parse_type *type,
+ const char *s, int *off, const u_char *const start,
+ u_char *const buf, int *buflen)
+{
+ quad_t val;
+ int64_t val64;
+ char *eptr;
+
+ val = strtoq(s + *off, &eptr, 0);
+ if (eptr == s + *off)
+ return (EINVAL);
+ *off = eptr - s;
+ val64 = (int64_t)val;
+ bcopy(&val64, buf, sizeof(int64_t));
+ *buflen = sizeof(int64_t);
+ return (0);
+}
+
+static int
+ng_int64_unparse(const struct ng_parse_type *type,
+ const u_char *data, int *off, char *cbuf, int cbuflen)
+{
+ int64_t val;
+
+ bcopy(data + *off, &val, sizeof(int64_t));
+ NG_PARSE_APPEND("%lld", (long long)val);
+ *off += sizeof(int64_t);
+ return (0);
+}
+
+static int
+ng_int64_getDefault(const struct ng_parse_type *type,
+ const u_char *const start, u_char *buf, int *buflen)
+{
+ int64_t val;
+
+ if (*buflen < sizeof(int64_t))
+ return (ERANGE);
+ val = 0;
+ bcopy(&val, buf, sizeof(int64_t));
+ *buflen = sizeof(int64_t);
+ return (0);
+}
+
+static int
+ng_int64_getAlign(const struct ng_parse_type *type)
+{
+ return INT64_ALIGNMENT;
+}
+
+const struct ng_parse_type ng_parse_int64_type = {
+ NULL,
+ NULL,
+ NULL,
+ ng_int64_parse,
+ ng_int64_unparse,
+ ng_int64_getDefault,
+ ng_int64_getAlign
+};
+
+/************************************************************************
+ STRING TYPE
+ ************************************************************************/
+
+static int
+ng_string_parse(const struct ng_parse_type *type,
+ const char *s, int *off, const u_char *const start,
+ u_char *const buf, int *buflen)
+{
+ char *sval;
+ int len;
+
+ if ((sval = ng_get_string_token(s, off, &len)) == NULL)
+ return (EINVAL);
+ *off += len;
+ len = strlen(sval) + 1;
+ bcopy(sval, buf, len);
+ FREE(sval, M_NETGRAPH);
+ *buflen = len;
+ return (0);
+}
+
+static int
+ng_string_unparse(const struct ng_parse_type *type,
+ const u_char *data, int *off, char *cbuf, int cbuflen)
+{
+ const char *const raw = (const char *)data + *off;
+ char *const s = ng_encode_string(raw);
+
+ if (s == NULL)
+ return (ENOMEM);
+ NG_PARSE_APPEND("%s", s);
+ *off += strlen(raw) + 1;
+ FREE(s, M_NETGRAPH);
+ return (0);
+}
+
+static int
+ng_string_getDefault(const struct ng_parse_type *type,
+ const u_char *const start, u_char *buf, int *buflen)
+{
+
+ if (*buflen < 1)
+ return (ERANGE);
+ buf[0] = (u_char)'\0';
+ *buflen = 1;
+ return (0);
+}
+
+const struct ng_parse_type ng_parse_string_type = {
+ NULL,
+ NULL,
+ NULL,
+ ng_string_parse,
+ ng_string_unparse,
+ ng_string_getDefault,
+ NULL
+};
+
+/************************************************************************
+ FIXED BUFFER STRING TYPE
+ ************************************************************************/
+
+static int
+ng_fixedstring_parse(const struct ng_parse_type *type,
+ const char *s, int *off, const u_char *const start,
+ u_char *const buf, int *buflen)
+{
+ const struct ng_parse_fixedsstring_info *const fi = type->info;
+ char *sval;
+ int len;
+
+ if ((sval = ng_get_string_token(s, off, &len)) == NULL)
+ return (EINVAL);
+ if (strlen(sval) + 1 > fi->bufSize)
+ return (E2BIG);
+ *off += len;
+ len = strlen(sval) + 1;
+ bcopy(sval, buf, len);
+ FREE(sval, M_NETGRAPH);
+ bzero(buf + len, fi->bufSize - len);
+ *buflen = fi->bufSize;
+ return (0);
+}
+
+static int
+ng_fixedstring_unparse(const struct ng_parse_type *type,
+ const u_char *data, int *off, char *cbuf, int cbuflen)
+{
+ const struct ng_parse_fixedsstring_info *const fi = type->info;
+ int error, temp = *off;
+
+ if ((error = ng_string_unparse(type, data, &temp, cbuf, cbuflen)) != 0)
+ return (error);
+ *off += fi->bufSize;
+ return (0);
+}
+
+static int
+ng_fixedstring_getDefault(const struct ng_parse_type *type,
+ const u_char *const start, u_char *buf, int *buflen)
+{
+ const struct ng_parse_fixedsstring_info *const fi = type->info;
+
+ if (*buflen < fi->bufSize)
+ return (ERANGE);
+ bzero(buf, fi->bufSize);
+ *buflen = fi->bufSize;
+ return (0);
+}
+
+const struct ng_parse_type ng_parse_fixedstring_type = {
+ NULL,
+ NULL,
+ NULL,
+ ng_fixedstring_parse,
+ ng_fixedstring_unparse,
+ ng_fixedstring_getDefault,
+ NULL
+};
+
+const struct ng_parse_fixedsstring_info ng_parse_nodebuf_info = {
+ NG_NODELEN + 1
+};
+const struct ng_parse_type ng_parse_nodebuf_type = {
+ &ng_parse_fixedstring_type,
+ &ng_parse_nodebuf_info
+};
+
+const struct ng_parse_fixedsstring_info ng_parse_hookbuf_info = {
+ NG_HOOKLEN + 1
+};
+const struct ng_parse_type ng_parse_hookbuf_type = {
+ &ng_parse_fixedstring_type,
+ &ng_parse_hookbuf_info
+};
+
+const struct ng_parse_fixedsstring_info ng_parse_pathbuf_info = {
+ NG_PATHLEN + 1
+};
+const struct ng_parse_type ng_parse_pathbuf_type = {
+ &ng_parse_fixedstring_type,
+ &ng_parse_pathbuf_info
+};
+
+const struct ng_parse_fixedsstring_info ng_parse_typebuf_info = {
+ NG_TYPELEN + 1
+};
+const struct ng_parse_type ng_parse_typebuf_type = {
+ &ng_parse_fixedstring_type,
+ &ng_parse_typebuf_info
+};
+
+const struct ng_parse_fixedsstring_info ng_parse_cmdbuf_info = {
+ NG_CMDSTRLEN + 1
+};
+const struct ng_parse_type ng_parse_cmdbuf_type = {
+ &ng_parse_fixedstring_type,
+ &ng_parse_cmdbuf_info
+};
+
+/************************************************************************
+ IP ADDRESS TYPE
+ ************************************************************************/
+
+static int
+ng_ipaddr_parse(const struct ng_parse_type *type,
+ const char *s, int *off, const u_char *const start,
+ u_char *const buf, int *buflen)
+{
+ int i, error;
+
+ for (i = 0; i < 4; i++) {
+ if ((error = ng_int8_parse(&ng_parse_int8_type,
+ s, off, start, buf + i, buflen)) != 0)
+ return (error);
+ if (i < 3 && s[*off] != '.')
+ return (EINVAL);
+ (*off)++;
+ }
+ *buflen = 4;
+ return (0);
+}
+
+static int
+ng_ipaddr_unparse(const struct ng_parse_type *type,
+ const u_char *data, int *off, char *cbuf, int cbuflen)
+{
+ struct in_addr ip;
+
+ bcopy(data + *off, &ip, sizeof(ip));
+ NG_PARSE_APPEND("%d.%d.%d.%d", ((u_char *)&ip)[0],
+ ((u_char *)&ip)[1], ((u_char *)&ip)[2], ((u_char *)&ip)[3]);
+ *off += sizeof(ip);
+ return (0);
+}
+
+static int
+ng_ipaddr_getDefault(const struct ng_parse_type *type,
+ const u_char *const start, u_char *buf, int *buflen)
+{
+ struct in_addr ip = { 0 };
+
+ if (*buflen < sizeof(ip))
+ return (ERANGE);
+ bcopy(&ip, buf, sizeof(ip));
+ *buflen = sizeof(ip);
+ return (0);
+}
+
+const struct ng_parse_type ng_parse_ipaddr_type = {
+ NULL,
+ NULL,
+ NULL,
+ ng_ipaddr_parse,
+ ng_ipaddr_unparse,
+ ng_ipaddr_getDefault,
+ ng_int32_getAlign
+};
+
+/************************************************************************
+ BYTE ARRAY TYPE
+ ************************************************************************/
+
+/* Get the length of a byte array */
+static int
+ng_parse_bytearray_subtype_getLength(const struct ng_parse_type *type,
+ const u_char *start, const u_char *buf)
+{
+ ng_parse_array_getLength_t *const getLength = type->private;
+
+ return (*getLength)(type, start, buf);
+}
+
+static int
+ng_bytearray_elem_unparse(const struct ng_parse_type *type,
+ const u_char *data, int *off, char *cbuf, int cbuflen)
+{
+ int8_t val;
+
+ bcopy(data + *off, &val, sizeof(int8_t));
+ NG_PARSE_APPEND("0x%02x", (int)val & 0xff); /* always hex format */
+ *off += sizeof(int8_t);
+ return (0);
+}
+
+/* Byte array element type is int8, but always output in hex format */
+const struct ng_parse_type ng_parse_bytearray_elem_type = {
+ &ng_parse_int8_type,
+ NULL,
+ NULL,
+ NULL,
+ ng_bytearray_elem_unparse,
+ NULL,
+ NULL
+};
+
+static const struct ng_parse_array_info ng_parse_bytearray_subtype_info = {
+ &ng_parse_bytearray_elem_type,
+ &ng_parse_bytearray_subtype_getLength,
+ NULL
+};
+static const struct ng_parse_type ng_parse_bytearray_subtype = {
+ &ng_parse_array_type,
+ &ng_parse_bytearray_subtype_info
+};
+
+static int
+ng_bytearray_parse(const struct ng_parse_type *type,
+ const char *s, int *off, const u_char *const start,
+ u_char *const buf, int *buflen)
+{
+ char *str;
+ int toklen;
+
+ /* We accept either an array of bytes or a string constant */
+ if ((str = ng_get_string_token(s, off, &toklen)) != NULL) {
+ ng_parse_array_getLength_t *const getLength = type->info;
+ int arraylen, slen;
+
+ arraylen = (*getLength)(type, start, buf);
+ if (arraylen > *buflen) {
+ FREE(str, M_NETGRAPH);
+ return (ERANGE);
+ }
+ slen = strlen(str) + 1;
+ if (slen > arraylen) {
+ FREE(str, M_NETGRAPH);
+ return (E2BIG);
+ }
+ bcopy(str, buf, slen);
+ bzero(buf + slen, arraylen - slen);
+ FREE(str, M_NETGRAPH);
+ *off += toklen;
+ *buflen = arraylen;
+ return (0);
+ } else {
+ struct ng_parse_type subtype;
+
+ subtype = ng_parse_bytearray_subtype;
+ (const void *)subtype.private = type->info;
+ return ng_array_parse(&subtype, s, off, start, buf, buflen);
+ }
+}
+
+static int
+ng_bytearray_unparse(const struct ng_parse_type *type,
+ const u_char *data, int *off, char *cbuf, int cbuflen)
+{
+ struct ng_parse_type subtype;
+
+ subtype = ng_parse_bytearray_subtype;
+ (const void *)subtype.private = type->info;
+ return ng_array_unparse(&subtype, data, off, cbuf, cbuflen);
+}
+
+static int
+ng_bytearray_getDefault(const struct ng_parse_type *type,
+ const u_char *const start, u_char *buf, int *buflen)
+{
+ struct ng_parse_type subtype;
+
+ subtype = ng_parse_bytearray_subtype;
+ (const void *)subtype.private = type->info;
+ return ng_array_getDefault(&subtype, start, buf, buflen);
+}
+
+const struct ng_parse_type ng_parse_bytearray_type = {
+ NULL,
+ NULL,
+ NULL,
+ ng_bytearray_parse,
+ ng_bytearray_unparse,
+ ng_bytearray_getDefault,
+ NULL
+};
+
+/************************************************************************
+ STRUCT NG_MESG TYPE
+ ************************************************************************/
+
+/* Get msg->header.arglen when "buf" is pointing to msg->data */
+static int
+ng_parse_ng_mesg_getLength(const struct ng_parse_type *type,
+ const u_char *start, const u_char *buf)
+{
+ const struct ng_mesg *msg;
+
+ msg = (const struct ng_mesg *)(buf - sizeof(*msg));
+ return msg->header.arglen;
+}
+
+/* Type for the variable length data portion of a struct ng_mesg */
+static const struct ng_parse_type ng_msg_data_type = {
+ &ng_parse_bytearray_type,
+ &ng_parse_ng_mesg_getLength
+};
+
+/* Type for the entire struct ng_mesg header with data section */
+static const struct ng_parse_struct_info
+ ng_parse_ng_mesg_type_info = NG_GENERIC_NG_MESG_INFO(&ng_msg_data_type);
+const struct ng_parse_type ng_parse_ng_mesg_type = {
+ &ng_parse_struct_type,
+ &ng_parse_ng_mesg_type_info,
+};
+
+/************************************************************************
+ COMPOSITE HELPER ROUTINES
+ ************************************************************************/
+
+/*
+ * Convert a structure or array from ASCII to binary
+ */
+static int
+ng_parse_composite(const struct ng_parse_type *type, const char *s,
+ int *off, const u_char *const start, u_char *const buf, int *buflen,
+ const enum comptype ctype)
+{
+ const int num = ng_get_composite_len(type, start, buf, ctype);
+ int nextIndex = 0; /* next implicit array index */
+ u_int index; /* field or element index */
+ int *foff; /* field value offsets in string */
+ int align, len, blen, error = 0;
+
+ /* Initialize */
+ MALLOC(foff, int *, num * sizeof(*foff), M_NETGRAPH, M_NOWAIT);
+ if (foff == NULL) {
+ error = ENOMEM;
+ goto done;
+ }
+ bzero(foff, num * sizeof(*foff));
+
+ /* Get opening brace/bracket */
+ if (ng_parse_get_token(s, off, &len)
+ != (ctype == CT_STRUCT ? T_LBRACE : T_LBRACKET)) {
+ error = EINVAL;
+ goto done;
+ }
+ *off += len;
+
+ /* Get individual element value positions in the string */
+ for (;;) {
+ enum ng_parse_token tok;
+
+ /* Check for closing brace/bracket */
+ tok = ng_parse_get_token(s, off, &len);
+ if (tok == (ctype == CT_STRUCT ? T_RBRACE : T_RBRACKET)) {
+ *off += len;
+ break;
+ }
+
+ /* For arrays, the 'name' (ie, index) is optional, so
+ distinguish name from values by seeing if the next
+ token is an equals sign */
+ if (ctype != CT_STRUCT) {
+ int len2, off2;
+ char *eptr;
+
+ /* If an opening brace/bracket, index is implied */
+ if (tok == T_LBRACE || tok == T_LBRACKET) {
+ index = nextIndex++;
+ goto gotIndex;
+ }
+
+ /* Might be an index, might be a value, either way... */
+ if (tok != T_WORD) {
+ error = EINVAL;
+ goto done;
+ }
+
+ /* If no equals sign follows, index is implied */
+ off2 = *off + len;
+ if (ng_parse_get_token(s, &off2, &len2) != T_EQUALS) {
+ index = nextIndex++;
+ goto gotIndex;
+ }
+
+ /* Index was specified explicitly; parse it */
+ index = (u_int)strtoul(s + *off, &eptr, 0);
+ if (index < 0 || eptr - (s + *off) != len) {
+ error = EINVAL;
+ goto done;
+ }
+ nextIndex = index + 1;
+ *off += len + len2;
+gotIndex:
+ } else { /* a structure field */
+ const struct ng_parse_struct_field *field = NULL;
+ const struct ng_parse_struct_info *si = type->info;
+
+ /* Find the field by name (required) in field list */
+ if (tok != T_WORD) {
+ error = EINVAL;
+ goto done;
+ }
+ for (index = 0; index < num; index++) {
+ field = &si->fields[index];
+ if (strncmp(&s[*off], field->name, len) == 0
+ && field->name[len] == '\0')
+ break;
+ }
+ if (index == num) {
+ error = ENOENT;
+ goto done;
+ }
+ *off += len;
+
+ /* Get equals sign */
+ if (ng_parse_get_token(s, off, &len) != T_EQUALS) {
+ error = EINVAL;
+ goto done;
+ }
+ *off += len;
+ }
+
+ /* Check array index */
+ if (index >= num) {
+ error = E2BIG;
+ goto done;
+ }
+
+ /* Save value's position and skip over it for now */
+ if (foff[index] != 0) {
+ error = EALREADY; /* duplicate */
+ goto done;
+ }
+ while (isspace(s[*off]))
+ (*off)++;
+ foff[index] = *off;
+ if ((error = ng_parse_skip_value(s, *off, &len)) != 0)
+ goto done;
+ *off += len;
+ }
+
+ /* Now build binary structure from supplied values and defaults */
+ for (blen = index = 0; index < num; index++) {
+ const struct ng_parse_type *const
+ etype = ng_get_composite_etype(type, index, ctype);
+ int k, pad, vlen;
+
+ /* Zero-pad any alignment bytes */
+ pad = ng_parse_get_elem_pad(type, index, ctype, blen);
+ for (k = 0; k < pad; k++) {
+ if (blen >= *buflen) {
+ error = ERANGE;
+ goto done;
+ }
+ buf[blen++] = 0;
+ }
+
+ /* Get value */
+ vlen = *buflen - blen;
+ if (foff[index] == 0) { /* use default value */
+ error = ng_get_composite_elem_default(type, index,
+ start, buf + blen, &vlen, ctype);
+ } else { /* parse given value */
+ *off = foff[index];
+ error = INVOKE(etype, parse)(etype,
+ s, off, start, buf + blen, &vlen);
+ }
+ if (error != 0)
+ goto done;
+ blen += vlen;
+ }
+
+ /* Make total composite structure size a multiple of its alignment */
+ if ((align = ALIGNMENT(type)) != 0) {
+ while (blen % align != 0) {
+ if (blen >= *buflen) {
+ error = ERANGE;
+ goto done;
+ }
+ buf[blen++] = 0;
+ }
+ }
+
+ /* Done */
+ *buflen = blen;
+done:
+ FREE(foff, M_NETGRAPH);
+ return (error);
+}
+
+/*
+ * Convert an array or structure from binary to ASCII
+ */
+static int
+ng_unparse_composite(const struct ng_parse_type *type, const u_char *data,
+ int *off, char *cbuf, int cbuflen, const enum comptype ctype)
+{
+ const int num = ng_get_composite_len(type, data, data + *off, ctype);
+ int nextIndex = 0, didOne = 0;
+ int error, index;
+
+ /* Opening brace/bracket */
+ NG_PARSE_APPEND("%c", (ctype == CT_STRUCT) ? '{' : '[');
+
+ /* Do each item */
+ for (index = 0; index < num; index++) {
+ const struct ng_parse_type *const
+ etype = ng_get_composite_etype(type, index, ctype);
+ u_char temp[1024];
+
+ /* Skip any alignment pad bytes */
+ *off += ng_parse_get_elem_pad(type, index, ctype, *off);
+
+ /* See if element is equal to its default value; skip if so */
+ if (*off < sizeof(temp)) {
+ int tempsize = sizeof(temp) - *off;
+
+ bcopy(data, temp, *off);
+ if (ng_get_composite_elem_default(type, index, temp,
+ temp + *off, &tempsize, ctype) == 0
+ && bcmp(temp + *off, data + *off, tempsize) == 0) {
+ *off += tempsize;
+ continue;
+ }
+ }
+
+ /* Print name= */
+ NG_PARSE_APPEND(" ");
+ if (ctype != CT_STRUCT) {
+ if (index != nextIndex) {
+ nextIndex = index;
+ NG_PARSE_APPEND("%d=", index);
+ }
+ nextIndex++;
+ } else {
+ const struct ng_parse_struct_info *si = type->info;
+
+ NG_PARSE_APPEND("%s=", si->fields[index].name);
+ }
+
+ /* Print value */
+ if ((error = INVOKE(etype, unparse)
+ (etype, data, off, cbuf, cbuflen)) != 0)
+ return (error);
+ cbuflen -= strlen(cbuf);
+ cbuf += strlen(cbuf);
+ didOne = 1;
+ }
+
+ /* Closing brace/bracket */
+ NG_PARSE_APPEND("%s%c",
+ didOne ? " " : "", (ctype == CT_STRUCT) ? '}' : ']');
+ return (0);
+}
+
+/*
+ * Generate the default value for an element of an array or structure
+ * Returns EOPNOTSUPP if default value is unspecified.
+ */
+static int
+ng_get_composite_elem_default(const struct ng_parse_type *type,
+ int index, const u_char *const start, u_char *buf, int *buflen,
+ const enum comptype ctype)
+{
+ const struct ng_parse_type *etype;
+ ng_getDefault_t *func;
+
+ switch (ctype) {
+ case CT_STRUCT:
+ break;
+ case CT_ARRAY:
+ {
+ const struct ng_parse_array_info *const ai = type->info;
+
+ if (ai->getDefault != NULL) {
+ return (*ai->getDefault)(type,
+ index, start, buf, buflen);
+ }
+ break;
+ }
+ case CT_FIXEDARRAY:
+ {
+ const struct ng_parse_fixedarray_info *const fi = type->info;
+
+ if (*fi->getDefault != NULL) {
+ return (*fi->getDefault)(type,
+ index, start, buf, buflen);
+ }
+ break;
+ }
+ default:
+ panic("%s", __FUNCTION__);
+ }
+
+ /* Default to element type default */
+ etype = ng_get_composite_etype(type, index, ctype);
+ func = METHOD(etype, getDefault);
+ if (func == NULL)
+ return (EOPNOTSUPP);
+ return (*func)(etype, start, buf, buflen);
+}
+
+/*
+ * Get the number of elements in a struct, variable or fixed array.
+ */
+static int
+ng_get_composite_len(const struct ng_parse_type *type,
+ const u_char *const start, const u_char *buf,
+ const enum comptype ctype)
+{
+ switch (ctype) {
+ case CT_STRUCT:
+ {
+ const struct ng_parse_struct_info *const si = type->info;
+ int numFields = 0;
+
+ for (numFields = 0; ; numFields++) {
+ const struct ng_parse_struct_field *const
+ fi = &si->fields[numFields];
+
+ if (fi->name == NULL)
+ break;
+ }
+ return (numFields);
+ }
+ case CT_ARRAY:
+ {
+ const struct ng_parse_array_info *const ai = type->info;
+
+ return (*ai->getLength)(type, start, buf);
+ }
+ case CT_FIXEDARRAY:
+ {
+ const struct ng_parse_fixedarray_info *const fi = type->info;
+
+ return fi->length;
+ }
+ default:
+ panic("%s", __FUNCTION__);
+ }
+ return (0);
+}
+
+/*
+ * Return the type of the index'th element of a composite structure
+ */
+static const struct ng_parse_type *
+ng_get_composite_etype(const struct ng_parse_type *type,
+ int index, const enum comptype ctype)
+{
+ const struct ng_parse_type *etype = NULL;
+
+ switch (ctype) {
+ case CT_STRUCT:
+ {
+ const struct ng_parse_struct_info *const si = type->info;
+
+ etype = si->fields[index].type;
+ break;
+ }
+ case CT_ARRAY:
+ {
+ const struct ng_parse_array_info *const ai = type->info;
+
+ etype = ai->elementType;
+ break;
+ }
+ case CT_FIXEDARRAY:
+ {
+ const struct ng_parse_fixedarray_info *const fi = type->info;
+
+ etype = fi->elementType;
+ break;
+ }
+ default:
+ panic("%s", __FUNCTION__);
+ }
+ return (etype);
+}
+
+/*
+ * Get the number of bytes to skip to align for the next
+ * element in a composite structure.
+ */
+static int
+ng_parse_get_elem_pad(const struct ng_parse_type *type,
+ int index, enum comptype ctype, int posn)
+{
+ const struct ng_parse_type *const
+ etype = ng_get_composite_etype(type, index, ctype);
+ int align;
+
+ /* Get element's alignment, and possibly override */
+ align = ALIGNMENT(etype);
+ if (ctype == CT_STRUCT) {
+ const struct ng_parse_struct_info *si = type->info;
+
+ if (si->fields[index].alignment != 0)
+ align = si->fields[index].alignment;
+ }
+
+ /* Return number of bytes to skip to align */
+ return (align ? (align - (posn % align)) % align : 0);
+}
+
+/************************************************************************
+ PARSING HELPER ROUTINES
+ ************************************************************************/
+
+/*
+ * Skip over a value
+ */
+static int
+ng_parse_skip_value(const char *s, int off0, int *lenp)
+{
+ int len, nbracket, nbrace;
+ int off = off0;
+
+ len = nbracket = nbrace = 0;
+ do {
+ switch (ng_parse_get_token(s, &off, &len)) {
+ case T_LBRACKET:
+ nbracket++;
+ break;
+ case T_LBRACE:
+ nbrace++;
+ break;
+ case T_RBRACKET:
+ if (nbracket-- == 0)
+ return (EINVAL);
+ break;
+ case T_RBRACE:
+ if (nbrace-- == 0)
+ return (EINVAL);
+ break;
+ case T_EOF:
+ return (EINVAL);
+ default:
+ break;
+ }
+ off += len;
+ } while (nbracket > 0 || nbrace > 0);
+ *lenp = off - off0;
+ return (0);
+}
+
+/*
+ * Find the next token in the string, starting at offset *startp.
+ * Returns the token type, with *startp pointing to the first char
+ * and *lenp the length.
+ */
+enum ng_parse_token
+ng_parse_get_token(const char *s, int *startp, int *lenp)
+{
+ char *t;
+ int i;
+
+ while (isspace(s[*startp]))
+ (*startp)++;
+ switch (s[*startp]) {
+ case '\0':
+ *lenp = 0;
+ return T_EOF;
+ case '{':
+ *lenp = 1;
+ return T_LBRACE;
+ case '}':
+ *lenp = 1;
+ return T_RBRACE;
+ case '[':
+ *lenp = 1;
+ return T_LBRACKET;
+ case ']':
+ *lenp = 1;
+ return T_RBRACKET;
+ case '=':
+ *lenp = 1;
+ return T_EQUALS;
+ case '"':
+ if ((t = ng_get_string_token(s, startp, lenp)) == NULL)
+ return T_ERROR;
+ FREE(t, M_NETGRAPH);
+ return T_STRING;
+ default:
+ for (i = *startp + 1; s[i] != '\0' && !isspace(s[i])
+ && s[i] != '{' && s[i] != '}' && s[i] != '['
+ && s[i] != ']' && s[i] != '=' && s[i] != '"'; i++)
+ ;
+ *lenp = i - *startp;
+ return T_WORD;
+ }
+}
+
+/*
+ * Get a string token, which must be enclosed in double quotes.
+ * The normal C backslash escapes are recognized.
+ */
+char *
+ng_get_string_token(const char *s, int *startp, int *lenp)
+{
+ char *cbuf, *p;
+ int start, off;
+
+ while (isspace(s[*startp]))
+ (*startp)++;
+ start = *startp;
+ if (s[*startp] != '"')
+ return (NULL);
+ MALLOC(cbuf, char *, strlen(s + start), M_NETGRAPH, M_NOWAIT);
+ if (cbuf == NULL)
+ return (NULL);
+ strcpy(cbuf, s + start + 1);
+ for (off = 1, p = cbuf; *p != '\0'; off++, p++) {
+ if (*p == '"') {
+ *p = '\0';
+ *lenp = off + 1;
+ return (cbuf);
+ } else if (p[0] == '\\' && p[1] != '\0') {
+ int x, k;
+ char *v;
+
+ strcpy(p, p + 1);
+ v = p;
+ switch (*p) {
+ case 't':
+ *v = '\t';
+ off++;
+ continue;
+ case 'n':
+ *v = '\n';
+ off++;
+ continue;
+ case 'r':
+ *v = '\r';
+ off++;
+ continue;
+ case 'v':
+ *v = '\v';
+ off++;
+ continue;
+ case 'f':
+ *v = '\f';
+ off++;
+ continue;
+ case '"':
+ *v = '"';
+ off++;
+ continue;
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ for (x = k = 0;
+ k < 3 && *v >= '0' && *v <= '7'; v++) {
+ x = (x << 3) + (*v - '0');
+ off++;
+ }
+ *--v = (char)x;
+ break;
+ case 'x':
+ for (v++, x = k = 0;
+ k < 2 && isxdigit(*v); v++) {
+ x = (x << 4) + (isdigit(*v) ?
+ (*v - '0') :
+ (tolower(*v) - 'a' + 10));
+ off++;
+ }
+ *--v = (char)x;
+ break;
+ default:
+ continue;
+ }
+ strcpy(p, v);
+ }
+ }
+ return (NULL); /* no closing quote */
+}
+
+/*
+ * Encode a string so it can be safely put in double quotes.
+ * Caller must free the result.
+ */
+char *
+ng_encode_string(const char *raw)
+{
+ char *cbuf;
+ int off = 0;
+
+ MALLOC(cbuf, char *, strlen(raw) * 4 + 3, M_NETGRAPH, M_NOWAIT);
+ if (cbuf == NULL)
+ return (NULL);
+ cbuf[off++] = '"';
+ for ( ; *raw != '\0'; raw++) {
+ switch (*raw) {
+ case '\t':
+ cbuf[off++] = '\\';
+ cbuf[off++] = 't';
+ break;
+ case '\f':
+ cbuf[off++] = '\\';
+ cbuf[off++] = 'f';
+ break;
+ case '\n':
+ cbuf[off++] = '\\';
+ cbuf[off++] = 'n';
+ break;
+ case '\r':
+ cbuf[off++] = '\\';
+ cbuf[off++] = 'r';
+ break;
+ case '\v':
+ cbuf[off++] = '\\';
+ cbuf[off++] = 'v';
+ break;
+ case '"':
+ case '\\':
+ cbuf[off++] = '\\';
+ cbuf[off++] = *raw;
+ break;
+ default:
+ if (*raw < 0x20 || *raw > 0x7e) {
+ off += sprintf(cbuf + off,
+ "\\x%02x", (u_char)*raw);
+ break;
+ }
+ cbuf[off++] = *raw;
+ break;
+ }
+ }
+ cbuf[off++] = '"';
+ cbuf[off] = '\0';
+ return (cbuf);
+}
+
+/************************************************************************
+ VIRTUAL METHOD LOOKUP
+ ************************************************************************/
+
+static ng_parse_t *
+ng_get_parse_method(const struct ng_parse_type *t)
+{
+ while (t != NULL && t->parse == NULL)
+ t = t->supertype;
+ return (t ? t->parse : NULL);
+}
+
+static ng_unparse_t *
+ng_get_unparse_method(const struct ng_parse_type *t)
+{
+ while (t != NULL && t->unparse == NULL)
+ t = t->supertype;
+ return (t ? t->unparse : NULL);
+}
+
+static ng_getDefault_t *
+ng_get_getDefault_method(const struct ng_parse_type *t)
+{
+ while (t != NULL && t->getDefault == NULL)
+ t = t->supertype;
+ return (t ? t->getDefault : NULL);
+}
+
+static ng_getAlign_t *
+ng_get_getAlign_method(const struct ng_parse_type *t)
+{
+ while (t != NULL && t->getAlign == NULL)
+ t = t->supertype;
+ return (t ? t->getAlign : NULL);
+}
+
diff --git a/sys/netgraph/ng_parse.h b/sys/netgraph/ng_parse.h
new file mode 100644
index 0000000..1efbdbe
--- /dev/null
+++ b/sys/netgraph/ng_parse.h
@@ -0,0 +1,388 @@
+
+/*
+ * ng_parse.h
+ *
+ * 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.
+ *
+ * Author: Archie Cobbs <archie@whistle.com>
+ *
+ * $Whistle: ng_parse.h,v 1.2 1999/11/29 01:43:48 archie Exp $
+ * $FreeBSD$
+ */
+
+#ifndef _NETGRAPH_PARSE_H_
+#define _NETGRAPH_PARSE_H_
+
+/*
+
+ This defines a library of routines for converting between various C
+ language types in binary form and ASCII strings. Types are user
+ definable. Several pre-defined types are supplied, for some
+ common C types: structures, variable and fixed length arrays,
+ integer types, variable and fixed length strings, IP addresses,
+ etc.
+
+ Syntax
+ ------
+
+ Structures:
+
+ '{' [ <name>=<value> ... ] '}'
+
+ Omitted fields have their default values by implication.
+ The order in which the fields are specified does not matter.
+
+ Arrays:
+
+ '[' [ [index=]<value> ... ] ']'
+
+ Element value may be specified with or without the "<index>=" prefix;
+ If omitted, the index after the previous element is used.
+ Omitted fields have their default values by implication.
+
+ Strings:
+
+ "foo bar blah\r\n"
+
+ That is, strings are specified just like C strings. The usual
+ backslash escapes are accepted.
+
+ Other simple types have their obvious ASCII forms.
+
+ Example
+ -------
+
+ Structure Binary (big endian)
+ --------- -------------------
+
+ struct foo {
+ struct in_addr ip; 03 03 03 03
+ int bar; 00 00 00 00
+ u_char num; 02 00
+ short ary[0]; 00 05 00 00 00 0a
+ };
+
+ ASCII form: "{ ip=3.3.3.3 num=3 ary=[ 5 2=10 ] }"
+
+ Note that omitted fields or array elements get their default values
+ ("bar" and ary[2]), and that the alignment is handled automatically
+ (the extra 00 byte after "num").
+
+ To define a type, you can define it as a sub-type of a predefined
+ type, overriding some of the predefined type's methods and/or its
+ alignment, or define your own syntax, with the restriction that
+ the ASCII representation must not contain any whitespace or these
+ characters: { } [ ] = "
+
+*/
+
+/************************************************************************
+ METHODS REQUIRED BY A TYPE
+ ************************************************************************/
+
+/*
+ * Three methods are required for a type. These may be given explicitly
+ * or, if NULL, inherited from the super-type.
+ */
+
+struct ng_parse_type;
+
+/*
+ * Convert ASCII to binary according to the supplied type.
+ *
+ * The ASCII characters begin at offset *off in 'string'. The binary
+ * representation is put into 'buf', which has at least *buflen bytes.
+ * 'start' points to the first byte output by ng_parse() (ie, start <= buf).
+ *
+ * Upon return, *buflen contains the length of the new binary data, and
+ * *off is updated to point just past the end of the parsed range of
+ * characters, or, in the case of an error, to the offending character(s).
+ *
+ * Return values:
+ * 0 Success; *buflen holds the length of the data
+ * and *off points just past the last char parsed.
+ * EALREADY Field specified twice
+ * ENOENT Unknown field
+ * E2BIG Array or character string overflow
+ * ERANGE Output was longer than *buflen bytes
+ * EINVAL Parse failure or other invalid content
+ * ENOMEM Out of memory
+ * EOPNOTSUPP Mandatory array/structure element missing
+ */
+typedef int ng_parse_t(const struct ng_parse_type *type, const char *string,
+ int *off, const u_char *start,
+ u_char *buf, int *buflen);
+
+/*
+ * Convert binary to ASCII according to the supplied type.
+ *
+ * The results are put into 'buf', which is at least buflen bytes long.
+ * *off points to the current byte in 'data' and should be updated
+ * before return to point just past the last byte unparsed.
+ *
+ * Returns:
+ * 0 Success
+ * ERANGE Output was longer than buflen bytes
+ */
+typedef int ng_unparse_t(const struct ng_parse_type *type,
+ const u_char *data, int *off, char *buf, int buflen);
+
+/*
+ * Compute the default value according to the supplied type.
+ *
+ * Store the result in 'buf', which is at least *buflen bytes long.
+ * Upon return *buflen contains the length of the output.
+ *
+ * Returns:
+ * 0 Success
+ * ERANGE Output was longer than *buflen bytes
+ * EOPNOTSUPP Default value is not specified for this type
+ */
+typedef int ng_getDefault_t(const struct ng_parse_type *type,
+ const u_char *start, u_char *buf, int *buflen);
+
+/*
+ * Return the alignment requirement of this type. Zero is same as one.
+ */
+typedef int ng_getAlign_t(const struct ng_parse_type *type);
+
+/************************************************************************
+ TYPE DEFINITION
+ ************************************************************************/
+
+/*
+ * This structure describes a type, which may be a sub-type of another
+ * type by pointing to it with 'supertype' and omitting one or more methods.
+ */
+struct ng_parse_type {
+ const struct ng_parse_type *supertype; /* super-type, if any */
+ const void *info; /* type-specific info */
+ void *private; /* client private info */
+ ng_parse_t *parse; /* parse method */
+ ng_unparse_t *unparse; /* unparse method */
+ ng_getDefault_t *getDefault; /* get default value method */
+ ng_getAlign_t *getAlign; /* get alignment */
+};
+
+/************************************************************************
+ PRE-DEFINED TYPES
+ ************************************************************************/
+
+/*
+ * Structures
+ *
+ * Default value: Determined on a per-field basis
+ * Additional info: struct ng_parse_struct_info *
+ */
+extern const struct ng_parse_type ng_parse_struct_type;
+
+/* Each field has a name, type, and optional alignment override. If the
+ override is non-zero, the alignment is determined from the field type.
+ Note: add an extra struct ng_parse_struct_field with name == NULL
+ to indicate the end of the list. */
+struct ng_parse_struct_info {
+ struct ng_parse_struct_field {
+ const char *name; /* field name */
+ const struct ng_parse_type
+ *type; /* field type */
+ int alignment; /* override alignment */
+ } fields[0];
+};
+
+/*
+ * Fixed length arrays
+ *
+ * Default value: See below
+ * Additional info: struct ng_parse_fixedarray_info *
+ */
+extern const struct ng_parse_type ng_parse_fixedarray_type;
+
+typedef int ng_parse_array_getLength_t(const struct ng_parse_type *type,
+ const u_char *start, const u_char *buf);
+typedef int ng_parse_array_getDefault_t(const struct ng_parse_type *type,
+ int index, const u_char *start,
+ u_char *buf, int *buflen);
+
+/* The 'getDefault' method may be NULL, in which case the default value
+ is computed from the element type. If not, it should fill in the
+ default value at *buf (having size *buflen) and update *buflen to the
+ length of the filled-in value before return. */
+struct ng_parse_fixedarray_info {
+ const struct ng_parse_type *elementType;
+ int length;
+ ng_parse_array_getDefault_t *getDefault;
+};
+
+/*
+ * Variable length arrays
+ *
+ * Default value: Same as with fixed length arrays
+ * Additional info: struct ng_parse_array_info *
+ */
+extern const struct ng_parse_type ng_parse_array_type;
+
+struct ng_parse_array_info {
+ const struct ng_parse_type *elementType;
+ ng_parse_array_getLength_t *getLength;
+ ng_parse_array_getDefault_t *getDefault;
+};
+
+/*
+ * Arbitrary length strings
+ *
+ * Default value: Empty string
+ * Additional info: None required
+ */
+extern const struct ng_parse_type ng_parse_string_type;
+
+/*
+ * Bounded length strings. These are strings that have a fixed-size
+ * buffer, and always include a terminating NUL character.
+ *
+ * Default value: Empty string
+ * Additional info: struct ng_parse_fixedsstring_info *
+ */
+extern const struct ng_parse_type ng_parse_fixedstring_type;
+
+struct ng_parse_fixedsstring_info {
+ int bufSize; /* size of buffer (including NUL) */
+};
+
+/*
+ * Some commonly used bounded length string types
+ */
+extern const struct ng_parse_type ng_parse_nodebuf_type; /* NG_NODELEN + 1 */
+extern const struct ng_parse_type ng_parse_hookbuf_type; /* NG_HOOKLEN + 1 */
+extern const struct ng_parse_type ng_parse_pathbuf_type; /* NG_PATHLEN + 1 */
+extern const struct ng_parse_type ng_parse_typebuf_type; /* NG_TYPELEN + 1 */
+extern const struct ng_parse_type ng_parse_cmdbuf_type; /* NG_CMDSTRLEN + 1 */
+
+/*
+ * Integer types
+ *
+ * Default value: 0
+ * Additional info: None required
+ */
+extern const struct ng_parse_type ng_parse_int8_type;
+extern const struct ng_parse_type ng_parse_int16_type;
+extern const struct ng_parse_type ng_parse_int32_type;
+extern const struct ng_parse_type ng_parse_int64_type;
+
+/*
+ * IP address type
+ *
+ * Default value: 0.0.0.0
+ * Additional info: None required
+ */
+extern const struct ng_parse_type ng_parse_ipaddr_type;
+
+/*
+ * Variable length byte array. The bytes are displayed in hex.
+ * ASCII form may be either an array of bytes or a string constant,
+ * in which case the array is zero-filled after the string bytes.
+ *
+ * Default value: All bytes are zero
+ * Additional info: ng_parse_array_getLength_t *
+ */
+extern const struct ng_parse_type ng_parse_bytearray_type;
+
+/*
+ * Netgraph control message type
+ *
+ * Default value: All fields zero
+ * Additional info: None required
+ */
+extern const struct ng_parse_type ng_parse_ng_mesg_type;
+
+/************************************************************************
+ CONVERSTION AND PARSING ROUTINES
+ ************************************************************************/
+
+/* Tokens for parsing structs and arrays */
+enum ng_parse_token {
+ T_LBRACE, /* '{' */
+ T_RBRACE, /* '}' */
+ T_LBRACKET, /* '[' */
+ T_RBRACKET, /* ']' */
+ T_EQUALS, /* '=' */
+ T_STRING, /* string in double quotes */
+ T_ERROR, /* error parsing string in double quotes */
+ T_WORD, /* anything else containing no whitespace */
+ T_EOF, /* end of string reached */
+};
+
+/*
+ * See typedef ng_parse_t for definition
+ */
+extern int ng_parse(const struct ng_parse_type *type, const char *string,
+ int *off, u_char *buf, int *buflen);
+
+/*
+ * See typedef ng_unparse_t for definition (*off assumed to be zero).
+ */
+extern int ng_unparse(const struct ng_parse_type *type,
+ const u_char *data, char *buf, int buflen);
+
+/*
+ * See typedef ng_getDefault_t for definition
+ */
+extern int ng_parse_getDefault(const struct ng_parse_type *type,
+ u_char *buf, int *buflen);
+
+/*
+ * Parse a token: '*startp' is the offset to start looking. Upon
+ * successful return, '*startp' equals the beginning of the token
+ * and '*lenp' the length. If error, '*startp' points at the
+ * offending character(s).
+ */
+extern enum ng_parse_token ng_parse_get_token(const char *s,
+ int *startp, int *lenp);
+
+/*
+ * Like above, but specifically for getting a string token and returning
+ * the string value. The string token must be enclosed in double quotes
+ * and the normal C backslash escapes are recognized. The caller must
+ * eventually free() the returned result. Returns NULL if token is
+ * not a string token, or parse or other error.
+ */
+extern char *ng_get_string_token(const char *s, int *startp, int *lenp);
+
+/*
+ * Convert a raw string into a doubly-quoted string including any
+ * necessary backslash escapes. Caller must free the result.
+ * Returns NULL if ENOMEM.
+ */
+extern char *ng_encode_string(const char *s);
+
+#endif /* _NETGRAPH_PARSE_H_ */
+
diff --git a/sys/netgraph/ng_ppp.c b/sys/netgraph/ng_ppp.c
index 2097de1..7cfb4b6 100644
--- a/sys/netgraph/ng_ppp.c
+++ b/sys/netgraph/ng_ppp.c
@@ -57,6 +57,7 @@
#include <netgraph/ng_message.h>
#include <netgraph/netgraph.h>
+#include <netgraph/ng_parse.h>
#include <netgraph/ng_ppp.h>
#include <netgraph/ng_vjc.h>
@@ -205,6 +206,78 @@ static int ng_ppp_config_valid(node_p node,
static void ng_ppp_update(node_p node, int newConf);
static void ng_ppp_free_frags(node_p node);
+/* Parse type for struct ng_ppp_link_config */
+static const struct ng_parse_struct_info
+ ng_ppp_link_type_info = NG_PPP_LINK_TYPE_INFO;
+static const struct ng_parse_type ng_ppp_link_type = {
+ &ng_parse_struct_type,
+ &ng_ppp_link_type_info,
+};
+
+/* Parse type for struct ng_ppp_node_config */
+struct ng_parse_fixedarray_info ng_ppp_array_info = {
+ &ng_ppp_link_type,
+ NG_PPP_MAX_LINKS
+};
+static const struct ng_parse_type ng_ppp_link_array_type = {
+ &ng_parse_fixedarray_type,
+ &ng_ppp_array_info,
+};
+static const struct ng_parse_struct_info ng_ppp_config_type_info
+ = NG_PPP_CONFIG_TYPE_INFO(&ng_ppp_link_array_type);
+static const struct ng_parse_type ng_ppp_config_type = {
+ &ng_parse_struct_type,
+ &ng_ppp_config_type_info
+};
+
+/* Parse type for struct ng_ppp_link_stat */
+static const struct ng_parse_struct_info
+ ng_ppp_stats_type_info = NG_PPP_STATS_TYPE_INFO;
+static const struct ng_parse_type ng_ppp_stats_type = {
+ &ng_parse_struct_type,
+ &ng_ppp_stats_type_info
+};
+
+/* List of commands and how to convert arguments to/from ASCII */
+static const struct ng_cmdlist ng_ppp_cmds[] = {
+ {
+ NGM_PPP_COOKIE,
+ NGM_PPP_SET_CONFIG,
+ "setconfig",
+ &ng_ppp_config_type,
+ NULL
+ },
+ {
+ NGM_PPP_COOKIE,
+ NGM_PPP_GET_CONFIG,
+ "getconfig",
+ NULL,
+ &ng_ppp_config_type
+ },
+ {
+ NGM_PPP_COOKIE,
+ NGM_PPP_GET_LINK_STATS,
+ "getstats",
+ &ng_parse_int16_type,
+ &ng_ppp_stats_type
+ },
+ {
+ NGM_PPP_COOKIE,
+ NGM_PPP_CLR_LINK_STATS,
+ "clrstats",
+ &ng_parse_int16_type,
+ NULL
+ },
+ {
+ NGM_PPP_COOKIE,
+ NGM_PPP_GETCLR_LINK_STATS,
+ "getclrstats",
+ &ng_parse_int16_type,
+ &ng_ppp_stats_type
+ },
+ { 0 }
+};
+
/* Node type descriptor */
static struct ng_type ng_ppp_typestruct = {
NG_VERSION,
@@ -218,7 +291,8 @@ static struct ng_type ng_ppp_typestruct = {
NULL,
ng_ppp_rcvdata,
ng_ppp_rcvdata,
- ng_ppp_disconnect
+ ng_ppp_disconnect,
+ ng_ppp_cmds
};
NETGRAPH_INIT(ppp, &ng_ppp_typestruct);
@@ -334,7 +408,7 @@ ng_ppp_rcvmsg(node_p node, struct ng_mesg *msg,
case NGM_PPP_SET_CONFIG:
{
struct ng_ppp_node_config *const newConf =
- (struct ng_ppp_node_config *) msg->data;
+ (struct ng_ppp_node_config *) msg->data;
/* Check for invalid or illegal config */
if (msg->header.arglen != sizeof(*newConf))
diff --git a/sys/netgraph/ng_ppp.h b/sys/netgraph/ng_ppp.h
index 7962746..c32b5a31 100644
--- a/sys/netgraph/ng_ppp.h
+++ b/sys/netgraph/ng_ppp.h
@@ -92,6 +92,19 @@ struct ng_ppp_link_config {
u_int32_t bandwidth; /* link bandwidth (in bytes/second) */
};
+/* Keep this in sync with the above structure definition */
+#define NG_PPP_LINK_TYPE_INFO { \
+ { \
+ { "enable", &ng_parse_int8_type }, \
+ { "protocomp", &ng_parse_int8_type }, \
+ { "acfcomp", &ng_parse_int8_type }, \
+ { "mru", &ng_parse_int16_type }, \
+ { "latency", &ng_parse_int32_type }, \
+ { "bandwidth", &ng_parse_int32_type }, \
+ { NULL }, \
+ } \
+}
+
/* Node config structure */
struct ng_ppp_node_config {
u_int16_t mrru; /* multilink peer MRRU */
@@ -112,6 +125,28 @@ struct ng_ppp_node_config {
links[NG_PPP_MAX_LINKS];
};
+/* Keep this in sync with the above structure definition */
+#define NG_PPP_CONFIG_TYPE_INFO(arytype) { \
+ { \
+ { "mrru", &ng_parse_int16_type }, \
+ { "multilink", &ng_parse_int8_type }, \
+ { "recvShortSeq", &ng_parse_int8_type }, \
+ { "xmitShortSeq", &ng_parse_int8_type }, \
+ { "roundRobin", &ng_parse_int8_type }, \
+ { "ip", &ng_parse_int8_type }, \
+ { "appletalk", &ng_parse_int8_type }, \
+ { "ipx", &ng_parse_int8_type }, \
+ { "comp", &ng_parse_int8_type }, \
+ { "decomp", &ng_parse_int8_type }, \
+ { "encryption", &ng_parse_int8_type }, \
+ { "decryption", &ng_parse_int8_type }, \
+ { "vjcomp", &ng_parse_int8_type }, \
+ { "vjdecomp", &ng_parse_int8_type }, \
+ { "links", (arytype) }, \
+ { NULL }, \
+ } \
+}
+
/* Statistics struct for a link (or the bundle if NG_PPP_BUNDLE_LINKNUM) */
struct ng_ppp_link_stat {
u_int32_t xmitFrames; /* xmit frames on link */
@@ -122,4 +157,17 @@ struct ng_ppp_link_stat {
u_int32_t dupFragments; /* MP frames with duplicate seq # */
};
+/* Keep this in sync with the above structure definition */
+#define NG_PPP_STATS_TYPE_INFO { \
+ { \
+ { "xmitFrames", &ng_parse_int32_type }, \
+ { "xmitOctets", &ng_parse_int32_type }, \
+ { "recvFrames", &ng_parse_int32_type }, \
+ { "recvOctets", &ng_parse_int32_type }, \
+ { "badProtos", &ng_parse_int32_type }, \
+ { "dupFragments", &ng_parse_int32_type }, \
+ { NULL }, \
+ } \
+}
+
#endif /* _NETGRAPH_PPP_H_ */
diff --git a/sys/netgraph/ng_pppoe.c b/sys/netgraph/ng_pppoe.c
index 6499e8f..836b295 100644
--- a/sys/netgraph/ng_pppoe.c
+++ b/sys/netgraph/ng_pppoe.c
@@ -88,7 +88,8 @@ static struct ng_type typestruct = {
ng_pppoe_connect,
ng_pppoe_rcvdata,
ng_pppoe_rcvdata,
- ng_pppoe_disconnect
+ ng_pppoe_disconnect,
+ NULL
};
NETGRAPH_INIT(pppoe, &typestruct);
diff --git a/sys/netgraph/ng_rfc1490.c b/sys/netgraph/ng_rfc1490.c
index 6cd20a5..13c3d2d 100644
--- a/sys/netgraph/ng_rfc1490.c
+++ b/sys/netgraph/ng_rfc1490.c
@@ -109,7 +109,8 @@ static struct ng_type typestruct = {
NULL,
ng_rfc1490_rcvdata,
ng_rfc1490_rcvdata,
- ng_rfc1490_disconnect
+ ng_rfc1490_disconnect,
+ NULL
};
NETGRAPH_INIT(rfc1490, &typestruct);
diff --git a/sys/netgraph/ng_rfc1490.h b/sys/netgraph/ng_rfc1490.h
index 98cdf63..494a60f 100644
--- a/sys/netgraph/ng_rfc1490.h
+++ b/sys/netgraph/ng_rfc1490.h
@@ -45,7 +45,7 @@
/* Node type name */
#define NG_RFC1490_NODE_TYPE "rfc1490"
-#define NGM_RFC1490_NODE_COOKIE 861060632
+#define NGM_RFC1490_COOKIE 861060632
/* Hook names */
#define NG_RFC1490_HOOK_DOWNSTREAM "downstream"
diff --git a/sys/netgraph/ng_sample.c b/sys/netgraph/ng_sample.c
index 5c68ad9..688cd81 100644
--- a/sys/netgraph/ng_sample.c
+++ b/sys/netgraph/ng_sample.c
@@ -79,7 +79,8 @@ static struct ng_type typestruct = {
ng_xxx_connect,
ng_xxx_rcvdata,
ng_xxx_rcvdataq,
- ng_xxx_disconnect
+ ng_xxx_disconnect,
+ NULL
};
NETGRAPH_INIT(xxx, &typestruct);
diff --git a/sys/netgraph/ng_socket.c b/sys/netgraph/ng_socket.c
index 321037a..d783687 100644
--- a/sys/netgraph/ng_socket.c
+++ b/sys/netgraph/ng_socket.c
@@ -133,7 +133,8 @@ static struct ng_type typestruct = {
NULL,
ngs_rcvdata,
ngs_rcvdata,
- ngs_disconnect
+ ngs_disconnect,
+ NULL
};
NETGRAPH_INIT(socket, &typestruct);
diff --git a/sys/netgraph/ng_tee.c b/sys/netgraph/ng_tee.c
index 7ae417c..2c5b9f3 100644
--- a/sys/netgraph/ng_tee.c
+++ b/sys/netgraph/ng_tee.c
@@ -96,7 +96,8 @@ static struct ng_type typestruct = {
NULL,
ngt_rcvdata,
ngt_rcvdata,
- ngt_disconnect
+ ngt_disconnect,
+ NULL
};
NETGRAPH_INIT(tee, &typestruct);
diff --git a/sys/netgraph/ng_tty.c b/sys/netgraph/ng_tty.c
index 2d3a1c4..9b5568f 100644
--- a/sys/netgraph/ng_tty.c
+++ b/sys/netgraph/ng_tty.c
@@ -89,15 +89,15 @@
/* Per-node private info */
struct ngt_sc {
- struct tty *tp; /* Terminal device */
- node_p node; /* Netgraph node */
- hook_p hook; /* Netgraph hook */
- struct mbuf *m; /* Incoming data buffer */
- struct mbuf *qhead, **qtail; /* Queue of outgoing mbuf's */
- short qlen; /* Length of queue */
- short hotchar; /* Hotchar, or -1 if none */
- u_int flags; /* Flags */
- struct callout_handle chand; /* See man timeout(9) */
+ struct tty *tp; /* Terminal device */
+ node_p node; /* Netgraph node */
+ hook_p hook; /* Netgraph hook */
+ struct mbuf *m; /* Incoming data buffer */
+ struct mbuf *qhead, **qtail; /* Queue of outgoing mbuf's */
+ short qlen; /* Length of queue */
+ short hotchar; /* Hotchar, or -1 if none */
+ u_int flags; /* Flags */
+ struct callout_handle chand; /* See man timeout(9) */
};
typedef struct ngt_sc *sc_p;
@@ -106,7 +106,7 @@ typedef struct ngt_sc *sc_p;
#define FLG_DEBUG 0x0002
/* Debugging */
-#ifdef DIAGNOSTICS
+#ifdef INVARIANTS
#define QUEUECHECK(sc) \
do { \
struct mbuf **mp; \
@@ -173,6 +173,7 @@ static struct ng_type typestruct = {
ngt_rcvdata,
ngt_rcvdata,
ngt_disconnect,
+ NULL
};
NETGRAPH_INIT(tty, &typestruct);
diff --git a/sys/netgraph/ng_vjc.c b/sys/netgraph/ng_vjc.c
index db96f1c..b572600 100644
--- a/sys/netgraph/ng_vjc.c
+++ b/sys/netgraph/ng_vjc.c
@@ -112,7 +112,8 @@ static struct ng_type typestruct = {
NULL,
ng_vjc_rcvdata,
ng_vjc_rcvdata,
- ng_vjc_disconnect
+ ng_vjc_disconnect,
+ NULL
};
NETGRAPH_INIT(vjc, &typestruct);
OpenPOWER on IntegriCloud