Rewrite of netgraph to start getting ready for SMP.

This version is functional and is aproaching solid..
notice I said APROACHING. There are many node types I cannot test
I have tested: echo hole ppp socket vjc iface tee bpf async tty
The rest compile and "Look" right.  More changes to follow.
DEBUGGING is enabled in this code to help if people have problems.
This commit is contained in:
Julian Elischer 2001-01-06 00:46:47 +00:00
parent 3269187d41
commit 069154d55f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=70700
39 changed files with 3618 additions and 2046 deletions

View File

@ -198,13 +198,6 @@ in the reverse direction. To facilitate this, the recipient of a
control message is supplied with a
.Dq return address
that is suitable for addressing a reply.
In addition, depending on the topology of
the graph and whether the source has requested it, a pointer to a
pointer that can be read by the source node may also be supplied.
This allows the destination node to directly respond in a
synchronous manner when control returns to the source node, by
simply pointing the supplied pointer to the response message.
Such synchronous message responses are more efficient but are not always possible.
.Pp
Each control message contains a 32 bit value called a
.Em typecookie
@ -223,11 +216,7 @@ messages for flow control and link management purposes are
defined by the base system that are usually
passed around in this manner. Flow control message would usually travel
in the opposite direction to the data to which they pertain.
.Pp
Since flow control packets can also result from data being sent, it is also
possible to return a synchronous message response to a data packet being
sent between nodes. (See later).
.Sh Netgraph is Functional
.Sh Netgraph is (usually) Functional
In order to minimize latency, most
.Nm
operations are functional.
@ -241,20 +230,25 @@ node B and calls B's
.Dq receive data
method. There are exceptions to this.
.Pp
It is allowable for nodes to reject a data packet, or to pass it back to the
caller in a modified or completely replaced form. The caller can notify the
node being called that it does not wish to receive any such packets
by using the
.Fn NG_SEND_DATA
and
.Fn NG_SEND_DATA_ONLY
macros, in which case, the second node should just discard rejected packets.
If the sender knows how to handle returned packets, it must use the
.Fn NG_SEND_DATA_RET
macro, which will adjust the parameters to point to the returned data
or NULL if no data was returned to the caller. No packet return is possible
across a queuing link (though an explicitly sent return is of course possible,
it doesn't mean quite the same thing).
Each node has an input queue, and some operations can be considered to
be 'writers' in that they alter the state of the node. Obviously in an SMP
world it would be bad if the state of a node were changed while another
data packet were transiting the node. For this purpose, the input queue
implements a
.Em reader/writer
semantic so that when there is a writer in the node, all other requests
are queued, and while there are readers, a writer, and any following
packets are queued. In the case where there is no reason to queue the
data, the input method is called directly, as mentionned above.
.Pp
A node may declare that all requests should be considered as writers,
or that requests coming in over a particular hook should be considered to
be a writer, or even that packets leaving or entering across a particular
hook should always be queued, rather than delivered directly (often useful
for interrupt routines who want to get back to the hardware quickly).
By default, all controll message packets are considered to be writers
unless specifically declared to be a reader in their definition. (see
NGM_READONLY in ng_message.h)
.Pp
While this mode of operation
results in good performance, it has a few implications for node
@ -358,20 +352,42 @@ but doesn't remove it, in which case the generic destructor is not called.
Two other methods are also supported by all nodes:
.Bl -tag -width xxx
.It Receive data message
An mbuf chain is passed to the node.
The node is notified on which hook the data arrived,
A
.Em Netgraph queueable reqest item
(usually refered to as an
.Em item
is recieved by the function.
The item contains a pointer to an mbuf and metadata about the packet.
.Pp
The node is notified on which hook the item arrived,
and can use this information in its processing decision.
The receiving node must always
.Fn m_freem
the mbuf chain on completion or error, pass it back (reject it), or pass
it on to another node
.Fn NG_FREE_M
the mbuf chain on completion or error, or pass it on to another node
(or kernel module) which will then be responsible for freeing it.
If a node passes a packet back to the caller, it does not have to be the
same mbuf, in which case the original must be freed. Passing a packet
back allows a module to modify the original data (e.g. encrypt it),
or in some other way filter it (e.g. packet filtering).
Similarly the
.Em item
must be freed if it is not to be passed on to another node, by using the
.Fn NG_FREE_ITEM
macro. If the item still holds references to mbufs or metadata at the time of
freeing then they will also be appropriatly freed.
Therefore, if there is any chance that the mbuf or metadata will be
changed or freed separatly from the item, it is very important
that these fields be retrieved using the
.Fn NGI_GET_M
and
.Fn NGI_GET_META
macros that also remove the reference within the item. (or multiple frees
of the same object will occur).
.Pp
In addition to the mbuf chain itself there is also a pointer to a
If it is only required to examine the contents of the mbufs or the
metadata, then it is possible to use the
.Fn NGI_M
and
.Fn NGI_META
macros to both read and rewrite these fields.
.Pp
In addition to the mbuf chain itself there may also be a pointer to a
structure describing meta-data about the message
(e.g. priority information). This pointer may be
.Dv NULL
@ -381,18 +397,15 @@ described in
The memory for meta-data must allocated via
.Fn malloc
with type
.Dv M_NETGRAPH .
.Dv M_NETGRAPH_META .
As with the data itself, it is the receiver's responsibility to
.Fn free
the meta-data. If the mbuf chain is freed the meta-data must
be freed at the same time. If the meta-data is freed but the
real data on is passed on, then a
.Dv NULL
pointer must be substituted.
Meta-data may be passed back in the same way that mbuf data may be passed back.
As with mbuf data, the rejected or returned meta-data pointer may point to
the same or different meta-data as that passed in,
and if it is different, the original must be freed.
pointer must be substituted. It is also the duty of the receiver to free
the request item itself, or to use it to pass the message on further.
.Pp
The receiving node may decide to defer the data by queueing it in the
.Nm
@ -414,34 +427,44 @@ presently used in frame-relay to indicate that management packets
should be queued for transmission
at a higher priority than data packets. This is required for
conformance with Frame Relay standards.
.Pp
The node may also receive information allowing it to send a synchronous
message response to one of the originators of the data. it is envisionned
that such a message would contain error or flow-control information.
Standard messages for these purposes have been defined in
.Pa sys/netgraph/netgraph.h .
.It Receive control message
This method is called when a control message is addressed to the node.
As with the received data, an
.Em item
is reveived, with a pointer to the control message.
The message can be examined using the
.Fn NGI_MSG
macro, or completely extracted from the item using the
.Fn NGI_GET_MSG
which also removes the reference within the item.
If the Item still holds a reference to the message when it is freed
(using the
.Fn NG_FREE_ITEM
macro), then the message will also be freed appropriatly. If the
reference has been removed the node must free the message itself using the
.Fn NG_FREE_MSG
macro.
A return address is always supplied, giving the address of the node
that originated the message so a reply message can be sent anytime later.
.Pp
It is possible for a synchronous reply to be made, and in fact this
is more common in practice.
This is done by setting a pointer (supplied as an extra function parameter)
to point to the reply.
Then when the control message delivery function returns,
the caller can check if this pointer has been made non-NULL,
and if so then it points to the reply message allocated via
.Fn malloc
and containing the synchronous response. In both directions,
(request and response) it is up to the
receiver of that message to
.Fn free
the control message buffer. All control messages and replies are
The return address is retrieved from the
.Em item
using the
.Fn NGI_RETADDR
macro and is of type
.Em ng_ID_t.
All control messages and replies are
allocated with
.Fn malloc
type
.Dv M_NETGRAPH .
.Dv M_NETGRAPH_MSG ,
however it is more usual to use the
.Fn NG_MKMESSAGE
and
.Fn NG_MKRESPONSE
macros to allocate and fill out a message.
Messages must be freed using the
.Fn NG_FREE_MSG
macro.
.Pp
If the message was delivered via a specific hook, that hook will
also be made known, which allows the use of such things as flow-control
@ -484,6 +507,7 @@ Here are some examples of valid netgraph addresses:
.Bd -literal -offset 4n -compact
.:
[3f]:
foo:
.:hook1
foo:hook1.hook2
@ -571,92 +595,71 @@ over an ISDN line:
[ (no name) ] [ (no name) ]
.Ed
.Sh Netgraph Structures
Interesting members of the node and hook structures are shown below
however you should
check
Structures are defined in
.Pa sys/netgraph/netgraph.h
on your system for more up-to-date versions.
.Bd -literal
struct ng_node {
char *name; /* Optional globally unique name */
void *private; /* Node implementation private info */
struct ng_type *type; /* The type of this node */
int refs; /* Number of references to this struct */
int numhooks; /* Number of connected hooks */
hook_p hooks; /* Linked list of (connected) hooks */
};
typedef struct ng_node *node_p;
(for kernel sructures only of interest to nodes)
and
.Pa sys/netgraph/ng_message.h
(for message definitions also of interest to user programs).
struct ng_hook {
char *name; /* This node's name for this hook */
void *private; /* Node implementation private info */
int refs; /* Number of references to this struct */
struct ng_node *node; /* The node this hook is attached to */
struct ng_hook *peer; /* The other hook in this connected pair */
struct ng_hook *next; /* Next in list of hooks for this node */
};
typedef struct ng_hook *hook_p;
.Ed
The following structures exist and have the following access
fields of interest to the node writers. If applicable I show the
access method for that information.
for their fields:
.Bl -tag -width xxx
./.Bl -bullet -compact -offset 2n
.It struct ng_node
typedef struct ng_node *node_p;
.Bl -tag -width xxx
.It char name[NG_NODELEN+1]
Optional globally unique name, null terminated string. If there
is a value in here, it is the name of the node.
.Pp
The maintenance of the name pointers, reference counts, and linked list
if (node->name[0]) ....
.Pp
.It void *private
Node implementation private info.
You may place anything you wish here.
.It int numhooks
Number of connected hooks.
.It hook_p hooks
Linked list of (connected) hooks.
.El
.It struct ng_hook
typedef struct ng_hook *hook_p;
.Bl -tag -width xxx
.It void *private;
Node implementation private info.
You may place anything you wish in this field.
.It struct ng_node *node;
The node this hook is attached to.
.It struct ng_hook *peer;
The other hook in this connected pair.
.It struct ng_hook *next;
Next in list of hooks for this node.
A hook list traversal method will be supplied so use of this field
directly will go away.
.El
.Pp
The maintenance of the names, reference counts, and linked list
of hooks for each node is handled automatically by the
.Nm
subsystem.
Typically a node's private info contains a back-pointer to the node or hook
structure, which counts as a new reference that must be registered by
incrementing
.Dv "node->refs" .
structure, which counts as a new reference that must be included
in the reference count for the node. When the node constructor is called
there is already a reference for this calculated in, so that
when the node is destroyed, it should remember to do a
.Fn ng_unref
on the node.
.Pp
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 the structures below:
.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_ABI_VERSION */
const char *name; /* Unique type name */
/* Module event handler */
modeventhand_t mod_event; /* Handle load/unload (optional) */
/* Constructor */
int (*constructor)(node_p *node); /* Create a new node */
/** Methods using the node **/
int (*rcvmsg)(node_p node, /* Receive control message */
struct ng_mesg *msg, /* The message */
const char *retaddr, /* Return address */
struct ng_mesg **resp /* Synchronous response */
hook_p lasthook); /* last hook traversed */
int (*shutdown)(node_p node); /* Shutdown this node */
int (*newhook)(node_p node, /* create a new hook */
hook_p hook, /* Pre-allocated struct */
const char *name); /* Name for new hook */
/** Methods using the hook **/
int (*connect)(hook_p hook); /* Confirm new hook attachment */
int (*rcvdata)(hook_p hook, /* Receive data on a hook */
struct mbuf *m, /* The data in an mbuf */
meta_p meta, /* Meta-data, if any */
struct mbuf **ret_m, /* return data here */
meta_p *ret_meta, /* return Meta-data here */
struct ng_message **resp); /* Synchronous reply info */
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
a node, the list of all active hooks.
.Pp
A current example of how to define a node can always be seen in
.Em sys/netgraph/ng_sample.c
and should be used as a starting point for new node writers.
.Sh Netgraph Message Structure
Control messages have the following structure:
.Bd -literal
#define NG_CMDSTRLEN 15 /* Max command string (16 with null) */
@ -1116,8 +1119,8 @@ Nodes are responsible for freeing what they allocate.
There are three exceptions:
.Bl -tag -width xxxx
.It 1
Mbufs sent across a data link are never to be freed by the sender,
unless it is returned from the recipient.
Mbufs sent across a data link are never to be freed by the sender. In the
case of error, they should be considered freed.
.It 2
Any meta-data information traveling with the data has the same restriction.
It might be freed by any node the data passes through, and a
@ -1126,7 +1129,7 @@ passed onwards, but the caller will never free it.
Two macros
.Fn NG_FREE_META "meta"
and
.Fn NG_FREE_DATA "m" "meta"
.Fn NG_FREE_M "m"
should be used if possible to free data and meta data (see
.Pa netgraph.h ) .
.It 3
@ -1135,6 +1138,13 @@ Messages sent using
are freed by the recipient. As in the case above, the addresses
associated with the message are freed by whatever allocated them so the
recipient should copy them if it wants to keep that information.
.It 4
Both control mesages and data are delivered and queued with
a netgraph
.Em item .
The item must be freed using
.Fn NG_FREE_ITEM "item"
or passed on to another node.
.El
.Sh FILES
.Bl -tag -width xxxxx -compact
@ -1159,6 +1169,8 @@ nodes, including the type cookie definition.
Netgraph subsystem loadable KLD module.
.It Pa /modules/ng_{type}.ko
Loadable KLD module for node type {type}.
.It Pa /sys/netgraph/ng_sample.c
Skeleton netgraph node. Use this as a starting point for new node types.
.El
.Sh USER MODE SUPPORT
There is a library for supporting user-mode programs that wish

View File

@ -267,7 +267,7 @@ static void ngar_init(void* ignored);
static ng_constructor_t ngar_constructor;
static ng_rcvmsg_t ngar_rcvmsg;
static ng_shutdown_t ngar_rmnode;
static ng_shutdown_t ngar_shutdown;
static ng_newhook_t ngar_newhook;
/*static ng_findhook_t ngar_findhook; */
static ng_connect_t ngar_connect;
@ -280,7 +280,7 @@ static struct ng_type typestruct = {
NULL,
ngar_constructor,
ngar_rcvmsg,
ngar_rmnode,
ngar_shutdown,
ngar_newhook,
NULL,
ngar_connect,
@ -509,18 +509,17 @@ arattach(struct ar_hardc *hc)
if (ngar_done_init == 0) ngar_init(NULL);
if (ng_make_node_common(&typestruct, &sc->node) != 0)
return (0);
sprintf(sc->nodename, "%s%d", NG_AR_NODE_TYPE, sc->unit);
if (ng_name_node(sc->node, sc->nodename)) {
ng_unref(sc->node); /* drop it again */
return (0);
}
sc->node->private = sc;
callout_handle_init(&sc->handle);
sc->xmitq.ifq_maxlen = IFQ_MAXLEN;
sc->xmitq_hipri.ifq_maxlen = IFQ_MAXLEN;
mtx_init(&sc->xmitq.ifq_mtx, "ar_xmitq", MTX_DEF);
mtx_init(&sc->xmitq_hipri.ifq_mtx, "ar_xmitq_hipri", MTX_DEF);
sprintf(sc->nodename, "%s%d", NG_AR_NODE_TYPE, sc->unit);
if (ng_name_node(sc->node, sc->nodename)) {
ng_rmnode(sc->node);
ng_unref(sc->node);
return (0);
}
sc->running = 0;
#endif /* NETGRAPH */
}
@ -2173,7 +2172,7 @@ ngar_watchdog_frame(void * arg)
* If the hardware exists, it will already have created it.
*/
static int
ngar_constructor(node_p *nodep)
ngar_constructor(node_p node)
{
return (EINVAL);
}
@ -2216,13 +2215,14 @@ ngar_newhook(node_p node, hook_p hook, const char *name)
* Just respond to the generic TEXT_STATUS message
*/
static int
ngar_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
struct ng_mesg **rptr, hook_p lasthook)
ngar_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
struct ar_softc * sc;
struct ng_mesg *resp = NULL;
int error = 0;
struct ng_mesg *msg;
NGI_GET_MSG(item, msg);
sc = node->private;
switch (msg->header.typecookie) {
case NG_AR_COOKIE:
@ -2268,13 +2268,8 @@ ngar_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
break;
}
/* Take care of synchronous response, if any */
if (rptr)
*rptr = resp;
else if (resp)
/* Should send the hard way */
FREE(resp, M_NETGRAPH);
free(msg, M_NETGRAPH);
NG_RESPOND_MSG(error, node, item, resp);
NG_FREE_MSG(msg);
return (error);
}
@ -2282,14 +2277,18 @@ ngar_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
* get data from another node and transmit it to the correct channel
*/
static int
ngar_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
ngar_rcvdata(hook_p hook, item_p item)
{
int s;
int error = 0;
struct ar_softc * sc = hook->node->private;
struct ifqueue *xmitq_p;
struct mbuf *m;
meta_p meta;
NGI_GET_M(item, m);
NGI_GET_META(item, meta);
NG_FREE_ITEM(item);
/*
* data doesn't come in from just anywhere (e.g control hook)
*/
@ -2326,7 +2325,8 @@ ngar_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* It was an error case.
* check if we need to free the mbuf, and then return the error
*/
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_META(meta);
return (error);
}
@ -2336,13 +2336,27 @@ ngar_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* don't unref the node, or remove our name. just clear our links up.
*/
static int
ngar_rmnode(node_p node)
ngar_shutdown(node_p node)
{
struct ar_softc * sc = node->private;
ar_down(sc);
ng_cutlinks(node);
node->flags &= ~NG_INVALID; /* bounce back to life */
ng_unref(node);
/* XXX need to drain the output queues! */
/* The node is dead, long live the node! */
/* stolen from the attach routine */
if (ng_make_node_common(&typestruct, &sc->node) != 0)
return (0);
sprintf(sc->nodename, "%s%d", NG_AR_NODE_TYPE, sc->unit);
if (ng_name_node(sc->node, sc->nodename)) {
sc->node = NULL;
printf("node naming failed\n");
ng_unref(sc->node); /* node dissappears */
return (0);
}
sc->node->private = sc;
sc->running = 0;
return (0);
}

View File

@ -267,7 +267,7 @@ static void ngar_init(void* ignored);
static ng_constructor_t ngar_constructor;
static ng_rcvmsg_t ngar_rcvmsg;
static ng_shutdown_t ngar_rmnode;
static ng_shutdown_t ngar_shutdown;
static ng_newhook_t ngar_newhook;
/*static ng_findhook_t ngar_findhook; */
static ng_connect_t ngar_connect;
@ -280,7 +280,7 @@ static struct ng_type typestruct = {
NULL,
ngar_constructor,
ngar_rcvmsg,
ngar_rmnode,
ngar_shutdown,
ngar_newhook,
NULL,
ngar_connect,
@ -509,18 +509,17 @@ arattach(struct ar_hardc *hc)
if (ngar_done_init == 0) ngar_init(NULL);
if (ng_make_node_common(&typestruct, &sc->node) != 0)
return (0);
sprintf(sc->nodename, "%s%d", NG_AR_NODE_TYPE, sc->unit);
if (ng_name_node(sc->node, sc->nodename)) {
ng_unref(sc->node); /* drop it again */
return (0);
}
sc->node->private = sc;
callout_handle_init(&sc->handle);
sc->xmitq.ifq_maxlen = IFQ_MAXLEN;
sc->xmitq_hipri.ifq_maxlen = IFQ_MAXLEN;
mtx_init(&sc->xmitq.ifq_mtx, "ar_xmitq", MTX_DEF);
mtx_init(&sc->xmitq_hipri.ifq_mtx, "ar_xmitq_hipri", MTX_DEF);
sprintf(sc->nodename, "%s%d", NG_AR_NODE_TYPE, sc->unit);
if (ng_name_node(sc->node, sc->nodename)) {
ng_rmnode(sc->node);
ng_unref(sc->node);
return (0);
}
sc->running = 0;
#endif /* NETGRAPH */
}
@ -2173,7 +2172,7 @@ ngar_watchdog_frame(void * arg)
* If the hardware exists, it will already have created it.
*/
static int
ngar_constructor(node_p *nodep)
ngar_constructor(node_p node)
{
return (EINVAL);
}
@ -2216,13 +2215,14 @@ ngar_newhook(node_p node, hook_p hook, const char *name)
* Just respond to the generic TEXT_STATUS message
*/
static int
ngar_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
struct ng_mesg **rptr, hook_p lasthook)
ngar_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
struct ar_softc * sc;
struct ng_mesg *resp = NULL;
int error = 0;
struct ng_mesg *msg;
NGI_GET_MSG(item, msg);
sc = node->private;
switch (msg->header.typecookie) {
case NG_AR_COOKIE:
@ -2268,13 +2268,8 @@ ngar_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
break;
}
/* Take care of synchronous response, if any */
if (rptr)
*rptr = resp;
else if (resp)
/* Should send the hard way */
FREE(resp, M_NETGRAPH);
free(msg, M_NETGRAPH);
NG_RESPOND_MSG(error, node, item, resp);
NG_FREE_MSG(msg);
return (error);
}
@ -2282,14 +2277,18 @@ ngar_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
* get data from another node and transmit it to the correct channel
*/
static int
ngar_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
ngar_rcvdata(hook_p hook, item_p item)
{
int s;
int error = 0;
struct ar_softc * sc = hook->node->private;
struct ifqueue *xmitq_p;
struct mbuf *m;
meta_p meta;
NGI_GET_M(item, m);
NGI_GET_META(item, meta);
NG_FREE_ITEM(item);
/*
* data doesn't come in from just anywhere (e.g control hook)
*/
@ -2326,7 +2325,8 @@ ngar_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* It was an error case.
* check if we need to free the mbuf, and then return the error
*/
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_META(meta);
return (error);
}
@ -2336,13 +2336,27 @@ ngar_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* don't unref the node, or remove our name. just clear our links up.
*/
static int
ngar_rmnode(node_p node)
ngar_shutdown(node_p node)
{
struct ar_softc * sc = node->private;
ar_down(sc);
ng_cutlinks(node);
node->flags &= ~NG_INVALID; /* bounce back to life */
ng_unref(node);
/* XXX need to drain the output queues! */
/* The node is dead, long live the node! */
/* stolen from the attach routine */
if (ng_make_node_common(&typestruct, &sc->node) != 0)
return (0);
sprintf(sc->nodename, "%s%d", NG_AR_NODE_TYPE, sc->unit);
if (ng_name_node(sc->node, sc->nodename)) {
sc->node = NULL;
printf("node naming failed\n");
ng_unref(sc->node); /* node dissappears */
return (0);
}
sc->node->private = sc;
sc->running = 0;
return (0);
}

View File

@ -1130,18 +1130,17 @@ lmc_attach(lmc_softc_t * const sc)
if (ng_lmc_done_init == 0) ng_lmc_init(NULL);
if (ng_make_node_common(&typestruct, &sc->lmc_node) != 0)
return (0);
sprintf(sc->lmc_nodename, "%s%d", NG_LMC_NODE_TYPE, sc->lmc_unit);
if (ng_name_node(sc->lmc_node, sc->lmc_nodename)) {
ng_unref(sc->lmc_node); /* make it go away again */
return (0);
}
sc->lmc_node->private = sc;
callout_handle_init(&sc->lmc_handle);
sc->lmc_xmitq.ifq_maxlen = IFQ_MAXLEN;
sc->lmc_xmitq_hipri.ifq_maxlen = IFQ_MAXLEN;
mtx_init(&sc->lmc_xmitq.ifq_mtx, "lmc_xmitq", MTX_DEF);
mtx_init(&sc->lmc_xmitq_hipri.ifq_mtx, "lmc_xmitq_hipri", MTX_DEF);
sprintf(sc->lmc_nodename, "%s%d", NG_LMC_NODE_TYPE, sc->lmc_unit);
if (ng_name_node(sc->lmc_node, sc->lmc_nodename)) {
ng_rmnode(sc->lmc_node);
ng_unref(sc->lmc_node);
return (0);
}
sc->lmc_running = 0;
/*
@ -1251,7 +1250,7 @@ ng_lmc_watchdog_frame(void *arg)
* If the hardware exists, it will already have created it.
*/
static int
ng_lmc_constructor(node_p *nodep)
ng_lmc_constructor(node_p node)
{
return (EINVAL);
}
@ -1295,13 +1294,14 @@ ng_lmc_newhook(node_p node, hook_p hook, const char *name)
* Just respond to the generic TEXT_STATUS message
*/
static int
ng_lmc_rcvmsg(node_p node, struct ng_mesg *msg,
const char *retaddr, struct ng_mesg **rptr, hook_p lasthook)
ng_lmc_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
lmc_softc_t *sc = (lmc_softc_t *) node->private;
struct ng_mesg *resp = NULL;
int error = 0;
struct ng_mesg *msg;
NGI_GET_MSG(item, msg);
switch (msg->header.typecookie) {
case NG_LMC_COOKIE:
switch (msg->header.cmd) {
@ -1377,12 +1377,8 @@ ng_lmc_rcvmsg(node_p node, struct ng_mesg *msg,
}
/* Take care of synchronous response, if any */
if (rptr)
*rptr = resp;
else if (resp)
FREE(resp, M_NETGRAPH);
free(msg, M_NETGRAPH);
NG_RESPOND_MSG(error, node, item, resp);
NG_FREE_MSG(msg);
return (error);
}
@ -1390,13 +1386,19 @@ ng_lmc_rcvmsg(node_p node, struct ng_mesg *msg,
* get data from another node and transmit it to the line
*/
static int
ng_lmc_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
ng_lmc_rcvdata(hook_p hook, item_p item)
{
int s;
int error = 0;
lmc_softc_t * sc = (lmc_softc_t *) hook->node->private;
struct ifqueue *xmitq_p;
struct mbuf *m;
meta_p meta;
/* Unpack all the data components */
NGI_GET_M(item, m);
NGI_GET_META(item, meta);
NG_FREE_ITEM(item);
/*
* data doesn't come in from just anywhere (e.g control hook)
@ -1434,7 +1436,8 @@ ng_lmc_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* It was an error case.
* check if we need to free the mbuf, and then return the error
*/
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_META(meta);
return (error);
}
@ -1449,8 +1452,35 @@ ng_lmc_rmnode(node_p node)
lmc_softc_t * sc = (lmc_softc_t *) node->private;
lmc_ifdown(sc);
ng_cutlinks(node);
node->flags &= ~NG_INVALID; /* bounce back to life */
/*
* Get rid of the old node.
*/
node->flags |= NG_INVALID;
node->private = NULL;
ng_unref(node);
/*
* Create a new node. This is basically what a device
* driver would do in the attach routine. So let's just do that..
* The node is dead, long live the node!
*/
if (ng_make_node_common(&typestruct, &sc->lmc_node) != 0)
return (0);
sprintf(sc->lmc_nodename, "%s%d", NG_LMC_NODE_TYPE, sc->lmc_unit);
if (ng_name_node(sc->lmc_node, sc->lmc_nodename)) {
sc->lmc_node = NULL; /* to be sure */
ng_unref(sc->lmc_node); /* make it go away */
return (0);
}
sc->lmc_node->private = sc;
callout_handle_init(&sc->lmc_handle);
sc->lmc_running = 0;
/*
* turn off those LEDs...
*/
sc->lmc_miireg16 |= LMC_MII16_LED_ALL;
lmc_led_on(sc, LMC_MII16_LED0);
return (0);
}
/* already linked */

View File

@ -834,7 +834,7 @@ musycc_intr1(void *arg)
*/
static int
musycc_constructor(node_p *nodep)
musycc_constructor(node_p node)
{
return (EINVAL);
@ -929,21 +929,19 @@ musycc_config(node_p node, char *set, char *ret)
/*
* Handle status and config enquiries.
* Respond with a synchronous response.
* [JRE] -this would be easier to read with the usual 'switch' structure-
*/
static int
musycc_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
struct ng_mesg **rptr, hook_p lasthook)
musycc_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
struct softc *sc;
struct ng_mesg *resp = NULL;
char *s, *r;
int error = 0;
struct ng_mesg *msg;
NGI_GET_MSG(item, msg);
sc = node->private;
if (rptr)
*rptr = NULL; /* default answer in case of errors */
if (msg->header.typecookie != NGM_GENERIC_COOKIE)
goto out;
@ -957,7 +955,7 @@ musycc_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
s = (char *)resp->data;
status_8370(sc, s);
resp->header.arglen = strlen(s) + 1;
FREE(msg, M_NETGRAPH);
NG_FREE_MSG(msg);
} else if (msg->header.cmd == NGM_TEXT_CONFIG) {
if (msg->header.arglen) {
@ -976,19 +974,15 @@ musycc_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
*r = '\0';
musycc_config(node, s, r);
resp->header.arglen = strlen(r) + 1;
FREE(msg, M_NETGRAPH);
NG_FREE_MSG(msg);
} else {
error = EINVAL;
}
out:
/* Take care of synchronous response, if any */
if (rptr)
*rptr = resp;
else if (resp)
FREE(resp, M_NETGRAPH); /* eventually 'send' the response */
FREE(msg, M_NETGRAPH);
NG_RESPOND_MSG(error, node, item, resp);
NG_FREE_MSG(msg);
return (error);
}
@ -1044,8 +1038,7 @@ musycc_newhook(node_p node, hook_p hook, const char *name)
}
static int
musycc_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
musycc_rcvdata(hook_p hook, item_p item)
{
struct softc *sc;
@ -1054,6 +1047,7 @@ musycc_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mdesc *md;
u_int32_t ch, u, len;
struct mbuf *m2;
struct mbuf *m;
sch = hook->private;
sc = sch->sc;
@ -1062,24 +1056,26 @@ musycc_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
if (csc->state != C_RUNNING) {
printf("csc->state = %d\n", csc->state);
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
return (0);
}
NG_FREE_META(meta);
meta = NULL;
if (sch->state != UP) {
printf("sch->state = %d\n", sch->state);
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
return (0);
}
NGI_GET_M(item, m);
NG_FREE_ITEM(item);
if (sch->tx_pending + m->m_pkthdr.len > sch->tx_limit * maxlatency) {
printf("pend %ld len %d lim %ld\n", sch->tx_pending, m->m_pkthdr.len, sch->tx_limit * maxlatency);
NG_FREE_DATA(m, meta);
printf("pend %ld len %d lim %ld\n", sch->tx_pending,
m->m_pkthdr.len, sch->tx_limit * maxlatency);
NG_FREE_M(m);
return (0);
}
m2 = m;
len = m->m_pkthdr.len;
while (len) {

View File

@ -367,7 +367,7 @@ static void ngsr_init(void* ignored);
static ng_constructor_t ngsr_constructor;
static ng_rcvmsg_t ngsr_rcvmsg;
static ng_shutdown_t ngsr_rmnode;
static ng_shutdown_t ngsr_shutdown;
static ng_newhook_t ngsr_newhook;
/*static ng_findhook_t ngsr_findhook; */
static ng_connect_t ngsr_connect;
@ -380,7 +380,7 @@ static struct ng_type typestruct = {
NULL,
ngsr_constructor,
ngsr_rcvmsg,
ngsr_rmnode,
ngsr_shutdown,
ngsr_newhook,
NULL,
ngsr_connect,
@ -934,18 +934,17 @@ srattach(struct sr_hardc *hc)
if (ngsr_done_init == 0) ngsr_init(NULL);
if (ng_make_node_common(&typestruct, &sc->node) != 0)
return (0);
sprintf(sc->nodename, "%s%d", NG_SR_NODE_TYPE, sc->unit);
if (ng_name_node(sc->node, sc->nodename)) {
ng_unref(sc->node); /* make it go away again */
return (0);
}
sc->node->private = sc;
callout_handle_init(&sc->handle);
sc->xmitq.ifq_maxlen = IFQ_MAXLEN;
sc->xmitq_hipri.ifq_maxlen = IFQ_MAXLEN;
mtx_init(&sc->xmitq.ifq_mtx, "sr_xmitq", MTX_DEF);
mtx_init(&sc->xmitq_hipri.ifq_mtx, "sr_xmitq_hipri", MTX_DEF);
sprintf(sc->nodename, "%s%d", NG_SR_NODE_TYPE, sc->unit);
if (ng_name_node(sc->node, sc->nodename)) {
ng_rmnode(sc->node);
ng_unref(sc->node);
return (0);
}
sc->running = 0;
#endif /* NETGRAPH */
}
@ -3126,7 +3125,7 @@ ngsr_watchdog_frame(void * arg)
* If the hardware exists, it will already have created it.
*/
static int
ngsr_constructor(node_p *nodep)
ngsr_constructor(node_p node)
{
return (EINVAL);
}
@ -3169,13 +3168,14 @@ ngsr_newhook(node_p node, hook_p hook, const char *name)
* Just respond to the generic TEXT_STATUS message
*/
static int
ngsr_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
struct ng_mesg **rptr, hook_p lasthook)
ngsr_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
struct sr_softc * sc;
struct ng_mesg *resp = NULL;
int error = 0;
struct ng_mesg *msg;
NGI_GET_MSG(item,msg);
sc = node->private;
switch (msg->header.typecookie) {
case NG_SR_COOKIE:
@ -3223,12 +3223,8 @@ ngsr_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
break;
}
/* Take care of synchronous response, if any */
if (rptr)
*rptr = resp;
else if (resp)
FREE(resp, M_NETGRAPH);
free(msg, M_NETGRAPH);
NG_RESPOND_MSG(error, node, item, resp);
NG_FREE_MSG(msg);
return (error);
}
@ -3236,14 +3232,18 @@ ngsr_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
* get data from another node and transmit it to the correct channel
*/
static int
ngsr_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
ngsr_rcvdata(hook_p hook, item_p item)
{
int s;
int error = 0;
struct sr_softc * sc = hook->node->private;
struct ifqueue *xmitq_p;
struct mbuf *m;
meta_p meta;
NGI_GET_M(item, m);
NGI_GET_META(item, meta);
NG_FREE_ITEM(item);
/*
* data doesn't come in from just anywhere (e.g control hook)
*/
@ -3280,7 +3280,8 @@ ngsr_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* It was an error case.
* check if we need to free the mbuf, and then return the error
*/
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_META(meta);
return (error);
}
@ -3290,13 +3291,25 @@ ngsr_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* don't unref the node, or remove our name. just clear our links up.
*/
static int
ngsr_rmnode(node_p node)
ngsr_shutdown(node_p node)
{
struct sr_softc * sc = node->private;
sr_down(sc);
ng_cutlinks(node);
node->flags &= ~NG_INVALID; /* bounce back to life */
ng_unref(node);
/* XXX should drain queues! */
if (ng_make_node_common(&typestruct, &sc->node) != 0)
return (0);
sprintf(sc->nodename, "%s%d", NG_SR_NODE_TYPE, sc->unit);
if (ng_name_node(sc->node, sc->nodename)) {
printf("node naming failed\n");
sc->node = NULL;
ng_unref(sc->node); /* drop it again */
return (0);
}
sc->node->private = sc;
callout_handle_init(&sc->handle); /* should kill timeout */
sc->running = 0;
return (0);
}

View File

@ -367,7 +367,7 @@ static void ngsr_init(void* ignored);
static ng_constructor_t ngsr_constructor;
static ng_rcvmsg_t ngsr_rcvmsg;
static ng_shutdown_t ngsr_rmnode;
static ng_shutdown_t ngsr_shutdown;
static ng_newhook_t ngsr_newhook;
/*static ng_findhook_t ngsr_findhook; */
static ng_connect_t ngsr_connect;
@ -380,7 +380,7 @@ static struct ng_type typestruct = {
NULL,
ngsr_constructor,
ngsr_rcvmsg,
ngsr_rmnode,
ngsr_shutdown,
ngsr_newhook,
NULL,
ngsr_connect,
@ -934,18 +934,17 @@ srattach(struct sr_hardc *hc)
if (ngsr_done_init == 0) ngsr_init(NULL);
if (ng_make_node_common(&typestruct, &sc->node) != 0)
return (0);
sprintf(sc->nodename, "%s%d", NG_SR_NODE_TYPE, sc->unit);
if (ng_name_node(sc->node, sc->nodename)) {
ng_unref(sc->node); /* make it go away again */
return (0);
}
sc->node->private = sc;
callout_handle_init(&sc->handle);
sc->xmitq.ifq_maxlen = IFQ_MAXLEN;
sc->xmitq_hipri.ifq_maxlen = IFQ_MAXLEN;
mtx_init(&sc->xmitq.ifq_mtx, "sr_xmitq", MTX_DEF);
mtx_init(&sc->xmitq_hipri.ifq_mtx, "sr_xmitq_hipri", MTX_DEF);
sprintf(sc->nodename, "%s%d", NG_SR_NODE_TYPE, sc->unit);
if (ng_name_node(sc->node, sc->nodename)) {
ng_rmnode(sc->node);
ng_unref(sc->node);
return (0);
}
sc->running = 0;
#endif /* NETGRAPH */
}
@ -3126,7 +3125,7 @@ ngsr_watchdog_frame(void * arg)
* If the hardware exists, it will already have created it.
*/
static int
ngsr_constructor(node_p *nodep)
ngsr_constructor(node_p node)
{
return (EINVAL);
}
@ -3169,13 +3168,14 @@ ngsr_newhook(node_p node, hook_p hook, const char *name)
* Just respond to the generic TEXT_STATUS message
*/
static int
ngsr_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
struct ng_mesg **rptr, hook_p lasthook)
ngsr_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
struct sr_softc * sc;
struct ng_mesg *resp = NULL;
int error = 0;
struct ng_mesg *msg;
NGI_GET_MSG(item,msg);
sc = node->private;
switch (msg->header.typecookie) {
case NG_SR_COOKIE:
@ -3223,12 +3223,8 @@ ngsr_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
break;
}
/* Take care of synchronous response, if any */
if (rptr)
*rptr = resp;
else if (resp)
FREE(resp, M_NETGRAPH);
free(msg, M_NETGRAPH);
NG_RESPOND_MSG(error, node, item, resp);
NG_FREE_MSG(msg);
return (error);
}
@ -3236,14 +3232,18 @@ ngsr_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
* get data from another node and transmit it to the correct channel
*/
static int
ngsr_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
ngsr_rcvdata(hook_p hook, item_p item)
{
int s;
int error = 0;
struct sr_softc * sc = hook->node->private;
struct ifqueue *xmitq_p;
struct mbuf *m;
meta_p meta;
NGI_GET_M(item, m);
NGI_GET_META(item, meta);
NG_FREE_ITEM(item);
/*
* data doesn't come in from just anywhere (e.g control hook)
*/
@ -3280,7 +3280,8 @@ ngsr_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* It was an error case.
* check if we need to free the mbuf, and then return the error
*/
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_META(meta);
return (error);
}
@ -3290,13 +3291,25 @@ ngsr_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* don't unref the node, or remove our name. just clear our links up.
*/
static int
ngsr_rmnode(node_p node)
ngsr_shutdown(node_p node)
{
struct sr_softc * sc = node->private;
sr_down(sc);
ng_cutlinks(node);
node->flags &= ~NG_INVALID; /* bounce back to life */
ng_unref(node);
/* XXX should drain queues! */
if (ng_make_node_common(&typestruct, &sc->node) != 0)
return (0);
sprintf(sc->nodename, "%s%d", NG_SR_NODE_TYPE, sc->unit);
if (ng_name_node(sc->node, sc->nodename)) {
printf("node naming failed\n");
sc->node = NULL;
ng_unref(sc->node); /* drop it again */
return (0);
}
sc->node->private = sc;
callout_handle_init(&sc->handle); /* should kill timeout */
sc->running = 0;
return (0);
}

View File

@ -355,22 +355,20 @@ USB_ATTACH(udbp)
if ((err = ng_make_node_common(&ng_udbp_typestruct, &sc->node)) == 0) {
char nodename[128];
sc->node->private = sc;
sc->xmitq.ifq_maxlen = IFQ_MAXLEN;
sc->xmitq_hipri.ifq_maxlen = IFQ_MAXLEN;
mtx_init(&sc->xmitq.ifq_mtx, "usb_xmitq", MTX_DEF);
mtx_init(&sc->xmitq_hipri.ifq_mtx, "usb_xmitq_hipri", MTX_DEF);
sprintf(nodename, "%s", USBDEVNAME(sc->sc_dev));
if ((err = ng_name_node(sc->node, nodename))) {
ng_rmnode(sc->node);
ng_unref(sc->node);
sc->node = NULL;
goto bad;
} else {
/* something to note it's done */
sc->node->private = sc;
sc->xmitq.ifq_maxlen = IFQ_MAXLEN;
sc->xmitq_hipri.ifq_maxlen = IFQ_MAXLEN;
mtx_init(&sc->xmitq.ifq_mtx, "usb_xmitq", MTX_DEF);
mtx_init(&sc->xmitq_hipri.ifq_mtx,
"usb_xmitq_hipri", MTX_DEF);
}
}
if (err) {
goto bad;
}
sc->flags = NETGRAPH_INITIALISED;
/* sc->flags &= ~DISCONNECTED; */ /* XXX */
@ -612,7 +610,7 @@ DRIVER_MODULE(udbp, uhub, udbp_driver, udbp_devclass, usbd_driver_load, 0);
* to create nodes that depend on hardware (unless you can add the hardware :)
*/
Static int
ng_udbp_constructor(node_p *nodep)
ng_udbp_constructor(node_p node)
{
return (EINVAL);
}
@ -641,7 +639,6 @@ ng_udbp_newhook(node_p node, hook_p hook, const char *name)
#endif
if (strcmp(name, NG_UDBP_HOOK_NAME) == 0) {
/* do something specific to a debug connection */
sc->hook = hook;
hook->private = NULL;
} else {
@ -662,14 +659,14 @@ ng_udbp_newhook(node_p node, hook_p hook, const char *name)
* (so that old userland programs could continue to work).
*/
Static int
ng_udbp_rcvmsg(node_p node,
struct ng_mesg *msg, const char *retaddr, struct ng_mesg **rptr,
hook_p lasthook)
ng_udbp_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
const udbp_p sc = node->private;
struct ng_mesg *resp = NULL;
int error = 0;
struct ng_mesg *msg;
NGI_GET_MSG(item, msg);
/* Deal with message according to cookie and command */
switch (msg->header.typecookie) {
case NGM_UDBP_COOKIE:
@ -706,13 +703,8 @@ ng_udbp_rcvmsg(node_p node,
}
/* Take care of synchronous response, if any */
if (rptr)
*rptr = resp;
else if (resp)
FREE(resp, M_NETGRAPH);
/* Free the message and return */
FREE(msg, M_NETGRAPH);
NG_RESPOND_MSG(error, node, item, resp);
NG_FREE_MSG(msg);
return(error);
}
@ -720,14 +712,18 @@ ng_udbp_rcvmsg(node_p node,
* Accept data from the hook and queue it for output.
*/
Static int
ng_udbp_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
ng_udbp_rcvdata(hook_p hook, item_p item)
{
const udbp_p sc = hook->node->private;
int error;
struct ifqueue *xmitq_p;
int s;
struct mbuf *m;
meta_p meta;
NGI_GET_M(item, m);
NGI_GET_META(item, meta);
NG_FREE_ITEM(item);
/*
* Now queue the data for when it can be sent
*/
@ -756,7 +752,8 @@ ng_udbp_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* It was an error case.
* check if we need to free the mbuf, and then return the error
*/
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_META(meta);
return (error);
}
@ -769,9 +766,9 @@ Static int
ng_udbp_rmnode(node_p node)
{
const udbp_p sc = node->private;
int err;
node->flags |= NG_INVALID;
ng_cutlinks(node);
/* Drain the queues */
IF_DRAIN(&sc->xmitq_hipri);
@ -779,8 +776,21 @@ ng_udbp_rmnode(node_p node)
sc->packets_in = 0; /* reset stats */
sc->packets_out = 0;
node->flags &= ~NG_INVALID; /* reset invalid flag */
return (0);
ng_unref(node); /* forget it ever existed */
/* stolen from attach routine */
if ((err = ng_make_node_common(&ng_udbp_typestruct, &sc->node)) == 0) {
char nodename[128];
sprintf(nodename, "%s", USBDEVNAME(sc->sc_dev));
if ((err = ng_name_node(sc->node, nodename))) {
ng_unref(sc->node); /* out damned spot! */
sc->flags &= ~NETGRAPH_INITIALISED;
sc->node = NULL;
} else {
sc->node->private = sc;
}
}
return (err);
}
/*
@ -807,8 +817,9 @@ ng_udbp_disconnect(hook_p hook)
const udbp_p sc = hook->node->private;
sc->hook = NULL;
if (hook->node->numhooks == 0)
ng_rmnode(hook->node);
if ((hook->node->numhooks == 0)
&& ((hook->node->flags & NG_INVALID) == 0))
ng_rmnode_self(hook->node);
return (0);
}

View File

@ -267,7 +267,7 @@ static void ngar_init(void* ignored);
static ng_constructor_t ngar_constructor;
static ng_rcvmsg_t ngar_rcvmsg;
static ng_shutdown_t ngar_rmnode;
static ng_shutdown_t ngar_shutdown;
static ng_newhook_t ngar_newhook;
/*static ng_findhook_t ngar_findhook; */
static ng_connect_t ngar_connect;
@ -280,7 +280,7 @@ static struct ng_type typestruct = {
NULL,
ngar_constructor,
ngar_rcvmsg,
ngar_rmnode,
ngar_shutdown,
ngar_newhook,
NULL,
ngar_connect,
@ -509,18 +509,17 @@ arattach(struct ar_hardc *hc)
if (ngar_done_init == 0) ngar_init(NULL);
if (ng_make_node_common(&typestruct, &sc->node) != 0)
return (0);
sprintf(sc->nodename, "%s%d", NG_AR_NODE_TYPE, sc->unit);
if (ng_name_node(sc->node, sc->nodename)) {
ng_unref(sc->node); /* drop it again */
return (0);
}
sc->node->private = sc;
callout_handle_init(&sc->handle);
sc->xmitq.ifq_maxlen = IFQ_MAXLEN;
sc->xmitq_hipri.ifq_maxlen = IFQ_MAXLEN;
mtx_init(&sc->xmitq.ifq_mtx, "ar_xmitq", MTX_DEF);
mtx_init(&sc->xmitq_hipri.ifq_mtx, "ar_xmitq_hipri", MTX_DEF);
sprintf(sc->nodename, "%s%d", NG_AR_NODE_TYPE, sc->unit);
if (ng_name_node(sc->node, sc->nodename)) {
ng_rmnode(sc->node);
ng_unref(sc->node);
return (0);
}
sc->running = 0;
#endif /* NETGRAPH */
}
@ -2173,7 +2172,7 @@ ngar_watchdog_frame(void * arg)
* If the hardware exists, it will already have created it.
*/
static int
ngar_constructor(node_p *nodep)
ngar_constructor(node_p node)
{
return (EINVAL);
}
@ -2216,13 +2215,14 @@ ngar_newhook(node_p node, hook_p hook, const char *name)
* Just respond to the generic TEXT_STATUS message
*/
static int
ngar_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
struct ng_mesg **rptr, hook_p lasthook)
ngar_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
struct ar_softc * sc;
struct ng_mesg *resp = NULL;
int error = 0;
struct ng_mesg *msg;
NGI_GET_MSG(item, msg);
sc = node->private;
switch (msg->header.typecookie) {
case NG_AR_COOKIE:
@ -2268,13 +2268,8 @@ ngar_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
break;
}
/* Take care of synchronous response, if any */
if (rptr)
*rptr = resp;
else if (resp)
/* Should send the hard way */
FREE(resp, M_NETGRAPH);
free(msg, M_NETGRAPH);
NG_RESPOND_MSG(error, node, item, resp);
NG_FREE_MSG(msg);
return (error);
}
@ -2282,14 +2277,18 @@ ngar_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
* get data from another node and transmit it to the correct channel
*/
static int
ngar_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
ngar_rcvdata(hook_p hook, item_p item)
{
int s;
int error = 0;
struct ar_softc * sc = hook->node->private;
struct ifqueue *xmitq_p;
struct mbuf *m;
meta_p meta;
NGI_GET_M(item, m);
NGI_GET_META(item, meta);
NG_FREE_ITEM(item);
/*
* data doesn't come in from just anywhere (e.g control hook)
*/
@ -2326,7 +2325,8 @@ ngar_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* It was an error case.
* check if we need to free the mbuf, and then return the error
*/
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_META(meta);
return (error);
}
@ -2336,13 +2336,27 @@ ngar_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* don't unref the node, or remove our name. just clear our links up.
*/
static int
ngar_rmnode(node_p node)
ngar_shutdown(node_p node)
{
struct ar_softc * sc = node->private;
ar_down(sc);
ng_cutlinks(node);
node->flags &= ~NG_INVALID; /* bounce back to life */
ng_unref(node);
/* XXX need to drain the output queues! */
/* The node is dead, long live the node! */
/* stolen from the attach routine */
if (ng_make_node_common(&typestruct, &sc->node) != 0)
return (0);
sprintf(sc->nodename, "%s%d", NG_AR_NODE_TYPE, sc->unit);
if (ng_name_node(sc->node, sc->nodename)) {
sc->node = NULL;
printf("node naming failed\n");
ng_unref(sc->node); /* node dissappears */
return (0);
}
sc->node->private = sc;
sc->running = 0;
return (0);
}

View File

@ -367,7 +367,7 @@ static void ngsr_init(void* ignored);
static ng_constructor_t ngsr_constructor;
static ng_rcvmsg_t ngsr_rcvmsg;
static ng_shutdown_t ngsr_rmnode;
static ng_shutdown_t ngsr_shutdown;
static ng_newhook_t ngsr_newhook;
/*static ng_findhook_t ngsr_findhook; */
static ng_connect_t ngsr_connect;
@ -380,7 +380,7 @@ static struct ng_type typestruct = {
NULL,
ngsr_constructor,
ngsr_rcvmsg,
ngsr_rmnode,
ngsr_shutdown,
ngsr_newhook,
NULL,
ngsr_connect,
@ -934,18 +934,17 @@ srattach(struct sr_hardc *hc)
if (ngsr_done_init == 0) ngsr_init(NULL);
if (ng_make_node_common(&typestruct, &sc->node) != 0)
return (0);
sprintf(sc->nodename, "%s%d", NG_SR_NODE_TYPE, sc->unit);
if (ng_name_node(sc->node, sc->nodename)) {
ng_unref(sc->node); /* make it go away again */
return (0);
}
sc->node->private = sc;
callout_handle_init(&sc->handle);
sc->xmitq.ifq_maxlen = IFQ_MAXLEN;
sc->xmitq_hipri.ifq_maxlen = IFQ_MAXLEN;
mtx_init(&sc->xmitq.ifq_mtx, "sr_xmitq", MTX_DEF);
mtx_init(&sc->xmitq_hipri.ifq_mtx, "sr_xmitq_hipri", MTX_DEF);
sprintf(sc->nodename, "%s%d", NG_SR_NODE_TYPE, sc->unit);
if (ng_name_node(sc->node, sc->nodename)) {
ng_rmnode(sc->node);
ng_unref(sc->node);
return (0);
}
sc->running = 0;
#endif /* NETGRAPH */
}
@ -3126,7 +3125,7 @@ ngsr_watchdog_frame(void * arg)
* If the hardware exists, it will already have created it.
*/
static int
ngsr_constructor(node_p *nodep)
ngsr_constructor(node_p node)
{
return (EINVAL);
}
@ -3169,13 +3168,14 @@ ngsr_newhook(node_p node, hook_p hook, const char *name)
* Just respond to the generic TEXT_STATUS message
*/
static int
ngsr_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
struct ng_mesg **rptr, hook_p lasthook)
ngsr_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
struct sr_softc * sc;
struct ng_mesg *resp = NULL;
int error = 0;
struct ng_mesg *msg;
NGI_GET_MSG(item,msg);
sc = node->private;
switch (msg->header.typecookie) {
case NG_SR_COOKIE:
@ -3223,12 +3223,8 @@ ngsr_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
break;
}
/* Take care of synchronous response, if any */
if (rptr)
*rptr = resp;
else if (resp)
FREE(resp, M_NETGRAPH);
free(msg, M_NETGRAPH);
NG_RESPOND_MSG(error, node, item, resp);
NG_FREE_MSG(msg);
return (error);
}
@ -3236,14 +3232,18 @@ ngsr_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
* get data from another node and transmit it to the correct channel
*/
static int
ngsr_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
ngsr_rcvdata(hook_p hook, item_p item)
{
int s;
int error = 0;
struct sr_softc * sc = hook->node->private;
struct ifqueue *xmitq_p;
struct mbuf *m;
meta_p meta;
NGI_GET_M(item, m);
NGI_GET_META(item, meta);
NG_FREE_ITEM(item);
/*
* data doesn't come in from just anywhere (e.g control hook)
*/
@ -3280,7 +3280,8 @@ ngsr_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* It was an error case.
* check if we need to free the mbuf, and then return the error
*/
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_META(meta);
return (error);
}
@ -3290,13 +3291,25 @@ ngsr_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* don't unref the node, or remove our name. just clear our links up.
*/
static int
ngsr_rmnode(node_p node)
ngsr_shutdown(node_p node)
{
struct sr_softc * sc = node->private;
sr_down(sc);
ng_cutlinks(node);
node->flags &= ~NG_INVALID; /* bounce back to life */
ng_unref(node);
/* XXX should drain queues! */
if (ng_make_node_common(&typestruct, &sc->node) != 0)
return (0);
sprintf(sc->nodename, "%s%d", NG_SR_NODE_TYPE, sc->unit);
if (ng_name_node(sc->node, sc->nodename)) {
printf("node naming failed\n");
sc->node = NULL;
ng_unref(sc->node); /* drop it again */
return (0);
}
sc->node->private = sc;
callout_handle_init(&sc->handle); /* should kill timeout */
sc->running = 0;
return (0);
}

View File

@ -166,7 +166,7 @@ struct ngingstat {
static ng_constructor_t ng_ing_constructor;
static ng_rcvmsg_t ng_ing_rcvmsg;
static ng_shutdown_t ng_ing_rmnode;
static ng_shutdown_t ng_ing_shutdown;
static ng_newhook_t ng_ing_newhook;
static ng_connect_t ng_ing_connect;
static ng_rcvdata_t ng_ing_rcvdata;
@ -208,7 +208,7 @@ static struct ng_type typestruct = {
NULL,
ng_ing_constructor,
ng_ing_rcvmsg,
ng_ing_rmnode,
ng_ing_shutdown,
ng_ing_newhook,
NULL,
ng_ing_connect,
@ -274,22 +274,22 @@ i4bingattach(void *dummy)
printf("ing: ng_make_node_common, ret = %d\n!", ret);
}
/* name the netgraph node */
sprintf(sc->nodename, "%s%d", NG_ING_NODE_TYPE, sc->sc_unit);
if((ret = ng_name_node(sc->node, sc->nodename)))
{
printf("ing: ng_name node, ret = %d\n!", ret);
ng_unref(sc->node);
break;
}
sc->node->private = sc;
sc->xmitq.ifq_maxlen = IFQ_MAXLEN;
sc->xmitq_hipri.ifq_maxlen = IFQ_MAXLEN;
mtx_init(&sc->xmitq.ifq_mtx, "i4b_ing_xmitq", MTX_DEF);
mtx_init(&sc->xmitq_hipri.ifq_mtx, "i4b_ing_hipri", MTX_DEF);
/* name the netgraph node */
sprintf(sc->nodename, "%s%d", NG_ING_NODE_TYPE, sc->sc_unit);
if(ng_name_node(sc->node, sc->nodename))
{
ng_rmnode(sc->node);
ng_unref(sc->node);
}
}
}
@ -575,7 +575,7 @@ ing_init_linktab(int unit)
* If the hardware exists, it will already have created it.
*---------------------------------------------------------------------------*/
static int
ng_ing_constructor(node_p *nodep)
ng_ing_constructor(node_p node)
{
return(EINVAL);
}
@ -621,8 +621,7 @@ ng_ing_newhook(node_p node, hook_p hook, const char *name)
*---------------------------------------------------------------------------*/
#if defined(__FreeBSD_version) && __FreeBSD_version >= 500000
static int
ng_ing_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
struct ng_mesg **rptr, hook_p lasthook)
ng_ing_rcvmsg(node_p node, item_p item, hook_p lasthook)
#else
static int
ng_ing_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
@ -633,7 +632,11 @@ ng_ing_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
struct ng_mesg *resp = NULL;
int error = 0;
#if defined(__FreeBSD_version) && __FreeBSD_version >= 500000
struct ng_mesg *msg;
NGI_GET_MSG(item, msg);
#endif
if(msg->header.typecookie == NGM_GENERIC_COOKIE)
{
switch(msg->header.cmd)
@ -726,15 +729,9 @@ ng_ing_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
}
/* Take care of synchronous response, if any */
if (rptr)
*rptr = resp;
else if (resp)
FREE(resp, M_NETGRAPH);
NG_RESPOND_MSG(error, node, item, resp);
/* Free the message and return */
FREE(msg, M_NETGRAPH);
NG_FREE_MSG(msg);
return(error);
}
@ -743,8 +740,7 @@ ng_ing_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
*---------------------------------------------------------------------------*/
#if defined(__FreeBSD_version) && __FreeBSD_version >= 500000
static int
ng_ing_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
ng_ing_rcvdata(hook_p hook, item_p item)
#else
static int
ng_ing_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
@ -753,10 +749,18 @@ ng_ing_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
struct ing_softc *sc = hook->node->private;
struct ifqueue *xmitq_p;
int s;
#if defined(__FreeBSD_version) && __FreeBSD_version >= 500000
struct mbuf *m;
meta_p meta;
NGI_GET_M(item, m);
NGI_GET_META(item, meta);
NG_FREE_ITEM(item);
#endif
if(hook->private == NULL)
{
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_META(meta);
return(ENETDOWN);
}
@ -789,7 +793,8 @@ ng_ing_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
_IF_DROP(xmitq_p);
IF_UNLOCK(xmitq_p);
splx(s);
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_META(meta);
return(ENOBUFS);
}
@ -808,17 +813,32 @@ ng_ing_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
* we'd only remove our links and reset ourself.
*---------------------------------------------------------------------------*/
static int
ng_ing_rmnode(node_p node)
ng_ing_shutdown(node_p node)
{
struct ing_softc *sc = node->private;
int ret;
node->flags |= NG_INVALID;
ng_cutlinks(node);
ng_unref(node);
sc->packets_in = 0; /* reset stats */
sc->packets_out = 0;
node->flags &= ~NG_INVALID; /* reset invalid flag */
if ((ret = ng_make_node_common(&typestruct, &sc->node)))
{
printf("ing: ng_make_node_common, ret = %d\n!", ret);
}
/* name the netgraph node */
sprintf(sc->nodename, "%s%d", NG_ING_NODE_TYPE, sc->sc_unit);
if((ret = ng_name_node(sc->node, sc->nodename)))
{
printf("ing: ng_name node, ret = %d\n!", ret);
ng_unref(sc->node);
return (0);
}
sc->node->private = sc;
return (0);
}

View File

@ -13,6 +13,8 @@ Archie's suggestions... :-)
- They allow conditional compilation which keeps
statistics & counters on various memory allocation
(or so it seems)
- Now tend to have NG_FREE_XX() macros. they
allow better debugging
- In struct ng_mesg: at least make "header" into "hdr", if not
getting rid of it altogether. It doesn't seem necessary and
@ -34,9 +36,12 @@ Archie's suggestions... :-)
#define NG_MSG_HDR_SIZE (sizeof(struct ng_message) - 1)
#endif
- inertia rules :-b
- Have a user level program to print out and manipulate nodes, etc.
- [DONE]
see ngctl
see ngctl, nghook
- "Netgraph global" flags to turn on tracing, etc.
@ -57,6 +62,8 @@ Archie's suggestions... :-)
colon character at the end of the name. Note ngctl allows you
to do it either way!
[DONE] (I think)
- bind on a control socket has been disabled
it was a bad idea.
- Need to implement passing meta information through socket nodes
using sendmsg() and recvmsg().
@ -64,14 +71,16 @@ Archie's suggestions... :-)
- Stuff needing to be added to manual:
- Awareness of SPL level, use ng_queue*() functions when necessary.
- Malloc all memory with type M_NETGRAPH.
- Malloc all memory with type M_NETGRAPH. -DONE
- Write code so it can be an LKM or built into the kernel.. this means
be careful with things like #ifdef INET.
- All nodes assume that all data mbufs have the M_PKTHDR flag set!
The ng_send_data() and related functions should have an
#ifdef DIAGNOSTICS check to check this assumption for every mbuf.
-DONE with INVARIANTS. Framework should test this more.
- More generally, netgraph code should make liberal use of the
#ifdef DIAGNOSTICS definition.
-INVARIANTS.
- Since data and messages are sent functionally, programmers need
to watch out for infinite feedback loops. Should ng_base.c detect
this automatically?
@ -79,3 +88,16 @@ Archie's suggestions... :-)
which is set to the colour of the packet as you pass through.
hitting a node already of your colour would abort. Each packet
has another (incremented) colour.
-new 'item' type can hold a hopcount...
NEW in 2001
All piggyback responses have gone away.
use the node ID in the return address field for quick response delivery.
Every node has a queue, plus there is a list of nodes that have queued work.
Extensive use of Mutexes. Getting in shape for SMP.
Messages and data are deliverd in a new form. An Item now has
all information needed to queue such a request and deliver it later, so
it is now the basis of all data transfer since any transfer may need to
be queued.

View File

@ -51,11 +51,24 @@
#error "This file should not be included in user level programs"
#endif
#include <sys/mutex.h>
/* The structure for queueing across ISR switches */
struct ng_item ; /* forward reference */
typedef struct ng_item *item_p;
struct ng_queue {
u_long q_flags;
struct mtx q_mtx;
item_p queue;
item_p *last;
struct ng_node *q_node; /* find the front of the node.. */
};
/*
* Structure of a hook
*/
struct ng_hook {
char *name; /* what this node knows this link as */
char name[NG_HOOKLEN+1];/* what this node knows this link as */
void *private; /* node dependant ID for this hook */
int flags; /* info about this hook/link */
int refs; /* dont actually free this till 0 */
@ -68,30 +81,32 @@ typedef struct ng_hook *hook_p;
/* Flags for a hook */
#define HK_INVALID 0x0001 /* don't trust it! */
#define HK_QUEUE 0x0002 /* queue for later delivery */
#define HK_FORCE_WRITER 0x0004 /* Incoming data queued as a writer */
/*
* Structure of a node
*/
struct ng_node {
char *name; /* optional globally unique name */
char name[NG_NODELEN+1]; /* optional globally unique name */
struct ng_type *type; /* the installed 'type' */
int flags; /* see below for bit definitions */
int sleepers; /* #procs sleeping on this node */
int refs; /* number of references to this node */
int numhooks; /* number of hooks */
int colour; /* for graph colouring algorithms */
void *private; /* node type dependant node ID */
ng_ID_t ID; /* Unique per node */
LIST_HEAD(hooks, ng_hook) hooks; /* linked list of node hooks */
LIST_ENTRY(ng_node) nodes; /* linked list of all nodes */
LIST_ENTRY(ng_node) idnodes; /* ID hash collision list */
TAILQ_ENTRY(ng_node) work; /* nodes with work to do */
struct ng_queue input_queue; /* input queue for locking */
};
typedef struct ng_node *node_p;
/* Flags for a node */
#define NG_INVALID 0x001 /* free when all sleepers and refs go to 0 */
#define NG_BUSY 0x002 /* callers should sleep or wait */
#define NG_TOUCHED 0x004 /* to avoid cycles when 'flooding' */
#define NG_INVALID 0x00000001 /* free when refs go to 0 */
#define NG_WORKQ 0x00000002 /* node is on the work queue */
#define NG_FORCE_WRITER 0x00000004 /* Never multithread this node */
#define NG_CLOSING 0x00000008 /* ng_rmnode() at work */
#define NGF_TYPE1 0x10000000 /* reserved for type specific storage */
#define NGF_TYPE2 0x20000000 /* reserved for type specific storage */
#define NGF_TYPE3 0x40000000 /* reserved for type specific storage */
@ -131,18 +146,15 @@ typedef struct ng_meta *meta_p;
#define NGMF_TRACE 0x02 /* trace when handing this data to a node */
/* 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,
hook_p lasthook);
typedef int ng_constructor_t(node_p node);
typedef int ng_rcvmsg_t(node_p node, item_p item, hook_p lasthook);
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);
typedef int ng_connect_t(hook_p hook);
typedef int ng_rcvdata_t(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp);
typedef int ng_rcvdata_t(hook_p hook, item_p item);
typedef int ng_disconnect_t(hook_p hook);
typedef int ng_rcvitem (node_p node, hook_p hook, item_p item);
/*
* Command list -- each node type specifies the command that it knows
* how to convert between ASCII and binary using an array of these.
@ -191,73 +203,371 @@ struct ng_type {
int refs; /* number of instances */
};
struct ng_item {
u_long el_flags;
item_p el_next;
node_p el_dest; /* The node it will be applied against (or NULL) */
hook_p el_hook; /* Entering hook. Optional in Control messages */
union {
struct {
struct mbuf *da_m;
meta_p da_meta;
} data;
struct {
struct ng_mesg *msg_msg;
ng_ID_t msg_retaddr;
} msg;
} body;
#define ITEM_DEBUG
#ifdef ITEM_DEBUG
char *lastfile;
int lastline;
TAILQ_ENTRY(ng_item) all; /* all existing items */
#endif /* ITEM_DEBUG */
};
#define NGQF_D_M 0x01 /* MASK of data/message */
#define NGQF_DATA 0x01 /* the queue element is data */
#define NGQF_MESG 0x00 /* the queue element is a message */
#define NGQF_TYPE 0x02 /* MASK for queue entry type */
#define NGQF_READER 0x02 /* queued as a reader */
#define NGQF_WRITER 0x00 /* queued as a writer */
#define NGQF_FREE 0x04
/*
* This defines the in-kernel binary interface version.
* It is possible to change this but leave the external message
* API the same. Each type also has it's own cookies for versioning as well.
* Change it for ITEM_DEBUG version so we cannot mix debug and non debug
* modules.
*/
#define NG_ABI_VERSION 5
#define _NG_ABI_VERSION 5
#ifdef ITEM_DEBUG
#define NG_ABI_VERSION (_NG_ABI_VERSION + 0x10000)
#else /* ITEM_DEBUG */
#define NG_ABI_VERSION _NG_ABI_VERSION
#endif /* ITEM_DEBUG */
/* Send data packet with meta-data */
#define NG_SEND_DATA(err, hook, m, meta) \
/**********************************************************************
* Queue item macros. Peek and extract values.
**********************************************************************/
/*
* Get the mbuf (etc) out of an item.
* Sets the value in the item to NULL in case we need to call NG_FREE_ITEM()
* with it, (to avoid freeing the things twice).
* If you don't want to zero out the item then realise that the
* item still owns it.
* Retaddr is different. There are no references on that. It's just a number.
* The debug versions must be either all used everywhere or not at all.
*/
#define _NGI_M(i) ((i)->body.data.da_m)
#define _NGI_META(i) ((i)->body.data.da_meta)
#define _NGI_MSG(i) ((i)->body.msg.msg_msg)
#define _NGI_RETADDR(i) ((i)->body.msg.msg_retaddr)
#ifdef ITEM_DEBUG
void dumpitem(item_p item, char *file, int line);
static __inline void _ngi_check(item_p item, char *file, int line) ;
static __inline struct mbuf ** _ngi_m(item_p item, char *file, int line) ;
static __inline meta_p * _ngi_meta(item_p item, char *file, int line) ;
static __inline struct ng_mesg ** _ngi_msg(item_p item, char *file, int line) ;
static __inline ng_ID_t * _ngi_retaddr(item_p item, char *file, int line) ;
static __inline void
_ngi_check(item_p item, char *file, int line)
{
if (item->el_flags & NGQF_FREE) {
dumpitem(item, file, line);
panic ("free item!");
}
(item)->lastline = line;
(item)->lastfile = file;
}
static __inline struct mbuf **
_ngi_m(item_p item, char *file, int line)
{
_ngi_check(item, file, line);
return (&_NGI_M(item));
}
static __inline meta_p *
_ngi_meta(item_p item, char *file, int line)
{
_ngi_check(item, file, line);
return (&_NGI_META(item));
}
static __inline struct ng_mesg **
_ngi_msg(item_p item, char *file, int line)
{
_ngi_check(item, file, line);
return (&_NGI_MSG(item));
}
static __inline ng_ID_t *
_ngi_retaddr(item_p item, char *file, int line)
{
_ngi_check(item, file, line);
return (&_NGI_RETADDR(item));
}
#define NGI_M(i) (*_ngi_m(i, __FILE__, __LINE__))
#define NGI_META(i) (*_ngi_meta(i, __FILE__, __LINE__))
#define NGI_MSG(i) (*_ngi_msg(i, __FILE__, __LINE__))
#define NGI_RETADDR(i) (*_ngi_retaddr(i, __FILE__, __LINE__))
#define NGI_GET_M(i,m) \
do { \
(err) = ng_send_data((hook), (m), (meta), \
NULL, NULL, NULL); \
(m) = NULL; \
(meta) = NULL; \
m = NGI_M(i); \
_NGI_M(i) = NULL; \
} while (0)
/* Send data packet with no meta-data */
#define NG_SEND_DATA_ONLY(err, hook, m) \
#define NGI_GET_META(i,m) \
do { \
(err) = ng_send_data((hook), (m), NULL, \
NULL, NULL, NULL); \
(m) = NULL; \
m = NGI_META(i); \
_NGI_META(i) = NULL; \
} while (0)
#define NGI_GET_MSG(i,m) \
do { \
m = NGI_MSG(i); \
_NGI_MSG(i) = NULL; \
} while (0)
#define NG_FREE_ITEM(item) \
do { \
_ngi_check(item, __FILE__, __LINE__); \
ng_free_item((item)); \
} while (0)
#define SAVE_LINE(item) \
do { \
(item)->lastline = __LINE__; \
(item)->lastfile = __FILE__; \
} while (0)
#else /* ITEM_DEBUG */
#define NGI_M(i) _NGI_M(i)
#define NGI_META(i) _NGI_META(i)
#define NGI_MSG(i) _NGI_MSG(i)
#define NGI_RETADDR(i) _NGI_RETADDR(i)
#define NGI_GET_M(i,m) do {m = NGI_M(i); NGI_M(i) = NULL; } while (0)
#define NGI_GET_META(i,m) do {m = NGI_META(i); NGI_META(i) = NULL;} while (0)
#define NGI_GET_MSG(i,m) do {m = NGI_MSG(i); NGI_MSG(i) = NULL; } while (0)
#define NG_FREE_ITEM(item) ng_free_item((item))
#define SAVE_LINE(item)
#endif /* ITEM_DEBUG */
/**********************************************************************
* Data macros. Send, manipulate and free.
**********************************************************************/
/* Send data packet including a possible sync response pointer */
#define NG_SEND_DATA_RESP(err, hook, m, meta, rmsg) \
#define NG_SEND_DATA(error, hook, m, meta) \
do { \
(err) = ng_send_data((hook), (m), (meta), \
NULL, NULL, rmsg); \
item_p item; \
if ((item = ng_package_data((m), (meta)))) { \
if (!((error) = ng_address_hook(NULL, item, \
hook, NULL))) { \
SAVE_LINE(item); \
(error) = ng_snd_item((item), 0); \
} \
} else { \
(error) = ENOMEM; \
} \
(m) = NULL; \
(meta) = NULL; \
} while (0)
#define NG_SEND_DATA_ONLY(error, hook, m) \
do { \
item_p item; \
if ((item = ng_package_data((m), NULL))) { \
if (!((error) = ng_address_hook(NULL, item, \
hook, NULL))) { \
SAVE_LINE(item); \
(error) = ng_snd_item((item), 0); \
} \
} else { \
(error) = ENOMEM; \
} \
(m) = NULL; \
} while (0)
/*
* Send data packet including a possible sync response pointer
* Allow the callee to replace the data and pass it back
* or to simply 'reject it' or 'keep it'
* Forward a data packet with no new meta-data.
* old metadata is passed along without change.
* Mbuf pointer is updated to new value.
*/
#define NG_SEND_DATA_RET(err, hook, m, meta, rmsg) \
#define NG_FWD_NEW_DATA(error, item, hook, m) \
do { \
struct mbuf *rm = NULL; \
meta_p rmeta = NULL; \
(err) = ng_send_data((hook), (m), (meta), \
&rm, &rmeta, (rmsg)); \
(m) = rm; \
(meta) = rmeta; \
NGI_M(item) = m; \
if (!((error) = ng_address_hook(NULL, (item), \
(hook), NULL))) { \
SAVE_LINE(item); \
(error) = ng_snd_item((item), 0); \
} \
(item) = NULL; \
(m) = NULL; \
} while (0)
/*
* Assuming the data is already ok, just set the new address and send
*/
#define NG_FWD_DATA(error, item, hook) \
do { \
if (!((error) = ng_address_hook(NULL, (item), \
(hook), NULL))) { \
SAVE_LINE(item); \
(error) = ng_snd_item((item), 0); \
} else { \
(error) = ENXIO; \
} \
(item) = NULL; \
} while (0)
/* Free metadata */
/* Note that messages can be static (e.g. in ng_rmnode_self()) */
/* XXX flag should not be user visible */
#define NG_FREE_MSG(msg) \
do { \
if ((msg)) { \
if ((msg->header.flags & NGF_STATIC) == 0) { \
FREE((msg), M_NETGRAPH_MSG); \
} \
(msg) = NULL; \
} \
} while (0)
#define NG_FREE_META(meta) \
do { \
if ((meta)) { \
FREE((meta), M_NETGRAPH); \
meta = NULL; \
} \
FREE((meta), M_NETGRAPH_META); \
(meta) = NULL; \
} \
} while (0)
/* Free any data packet and/or meta-data */
#define NG_FREE_DATA(m, meta) \
#define NG_FREE_M(m) \
do { \
if ((m)) { \
m_freem((m)); \
m = NULL; \
(m) = NULL; \
} \
} while (0)
/* Free any data packet and/or meta-data */
#define NG_FREE_DATAX(m, meta) \
do { \
NG_FREE_M((m)); \
NG_FREE_META((meta)); \
} while (0)
/*****************************************
* Message macros
*****************************************/
#define NG_SEND_MSG_HOOK(error, here, msg, hook, retaddr) \
do { \
item_p item; \
if ((item = ng_package_msg(msg)) \
&& (ng_address_hook((here), (item), \
(hook), (retaddr)) == 0)) { \
SAVE_LINE(item); \
(error) = ng_snd_item((item), 0); \
} else { \
(error) = EINVAL; \
} \
(msg) = NULL; \
} while (0)
#define NG_SEND_MSG_PATH(error, here, msg, path, retaddr) \
do { \
item_p item; \
if ((item = ng_package_msg(msg)) \
&& (ng_address_path((here), (item), \
(path), (retaddr)) == 0)) { \
SAVE_LINE(item); \
(error) = ng_snd_item((item), 0); \
} else { \
(error) = EINVAL; \
} \
(msg) = NULL; \
} while (0)
#define NG_SEND_MSG_ID(error, here, msg, ID, retaddr) \
do { \
item_p item; \
if ((item = ng_package_msg(msg)) \
&& (ng_address_ID((here), (item), \
(ID), (retaddr)) == 0)) { \
SAVE_LINE(item); \
(error) = ng_snd_item((item), 0); \
} else { \
(error) = EINVAL; \
} \
(msg) = NULL; \
} while (0)
#define NG_QUEUE_MSG(error, here, msg, path, retaddr) \
do { \
item_p item; \
if ((item = ng_package_msg(msg)) \
&& (ng_address_path((here), (item), \
(path), (retaddr)) == 0)) { \
SAVE_LINE(item); \
(error) = ng_snd_item((item), 0); \
} else { \
(error) = EINVAL; \
} \
(msg) = NULL; \
} while (0)
/*
* Redirect the message to the next hop using the given hook.
* ng_retarget_msg() frees the item if there is an error
* and returns an error code. It returns 0 on success.
*/
#define NG_FWD_MSG_HOOK(error, here, item, hook, retaddr) \
do { \
if ((ng_address_hook((here), (item), \
(hook), (retaddr))) == 0) { \
SAVE_LINE(item); \
(error) = ng_snd_item((item), 0); \
} else { \
(error) = EINVAL; \
} \
(item) = NULL; \
} while (0)
/*
* Send a queue item back to it's originator with a response message.
* Assume original message was removed and freed separatly.
*/
#define NG_RESPOND_MSG(error, here, item, resp) \
do { \
if (resp) { \
ng_ID_t dest = NGI_RETADDR(item); \
NGI_RETADDR(item) = NULL; \
NGI_MSG(item) = resp; \
if ((ng_address_ID((here), (item), \
dest, NULL )) == 0) { \
SAVE_LINE(item); \
(error) = ng_snd_item((item), 1); \
} else { \
(error) = EINVAL; \
} \
} else { \
NG_FREE_ITEM(item); \
} \
(item) = NULL; \
} while (0)
/*
* Use the NETGRAPH_INIT() macro to link a node type into the
@ -284,39 +594,35 @@ MODULE_DEPEND(ng_##typename, netgraph, 1, 1, 1)
NETGRAPH_INIT_ORDERED(tn, tp, SI_SUB_PSEUDO, SI_ORDER_ANY)
/* Special malloc() type for netgraph structs and ctrl messages */
/* Only these two types should be visible to nodes */
MALLOC_DECLARE(M_NETGRAPH);
MALLOC_DECLARE(M_NETGRAPH_MSG);
MALLOC_DECLARE(M_NETGRAPH_META);
int ng_bypass(hook_p hook1, hook_p hook2);
void ng_cutlinks(node_p node);
int ng_con_nodes(node_p node,
const char *name, node_p node2, const char *name2);
/* Methods that should go away (or become private)*/
/* Methods that should exist */
int ng_address_ID(node_p here, item_p item, ng_ID_t ID, ng_ID_t retaddr);
int ng_address_hook(node_p here, item_p item, hook_p hook, ng_ID_t retaddr);
int ng_address_path(node_p here, item_p item,
char *address, ng_ID_t retaddr);
meta_p ng_copy_meta(meta_p meta);
void ng_destroy_hook(hook_p hook);
hook_p ng_findhook(node_p node, const char *name);
node_p ng_findname(node_p node, const char *name);
struct ng_type *ng_findtype(const char *type);
int ng_make_node(const char *type, node_p *nodepp);
void ng_free_item(item_p item);
int ng_make_node_common(struct ng_type *typep, node_p *nodep);
int ng_mkpeer(node_p node, const char *name, const char *name2, char *type);
int ng_mod_event(module_t mod, int what, void *arg);
int ng_name_node(node_p node, const char *name);
int ng_newtype(struct ng_type *tp);
ng_ID_t ng_node2ID(node_p node);
int ng_path2node(node_p here, const char *path,
node_p *dest, hook_p *lasthook);
int ng_path_parse(char *addr, char **node, char **path, char **hook);
int ng_queue_data(hook_p hook, struct mbuf *m, meta_p meta);
int ng_queue_msg(node_p here, struct ng_mesg *msg, const char *address,
hook_p hook, char *retaddr);
void ng_release_node(node_p node);
void ng_rmnode(node_p node);
int ng_send_data(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp);
int ng_send_msg(node_p here, struct ng_mesg *msg, const char *address,
hook_p hook, char *retaddr, struct ng_mesg **resp);
item_p ng_package_data(struct mbuf *m, meta_p meta);
item_p ng_package_msg(struct ng_mesg *msg);
item_p ng_package_msg_self(node_p here, hook_p hook, struct ng_mesg *msg);
void ng_replace_retaddr(node_p here, item_p item, ng_ID_t retaddr);
int ng_rmnode_self(node_p here);
int ng_snd_item(item_p item, int queue);
void ng_unname(node_p node);
void ng_unref(node_p node);
int ng_wait_node(node_p node, char *msg);
#endif /* _NETGRAPH_NETGRAPH_H_ */

View File

@ -70,7 +70,7 @@ typedef struct ng_UI_private *priv_p;
/* Netgraph node methods */
static ng_constructor_t ng_UI_constructor;
static ng_rcvmsg_t ng_UI_rcvmsg;
static ng_shutdown_t ng_UI_rmnode;
static ng_shutdown_t ng_UI_shutdown;
static ng_newhook_t ng_UI_newhook;
static ng_rcvdata_t ng_UI_rcvdata;
static ng_disconnect_t ng_UI_disconnect;
@ -82,7 +82,7 @@ static struct ng_type typestruct = {
NULL,
ng_UI_constructor,
ng_UI_rcvmsg,
ng_UI_rmnode,
ng_UI_shutdown,
ng_UI_newhook,
NULL,
NULL,
@ -101,24 +101,16 @@ NETGRAPH_INIT(UI, &typestruct);
*/
static int
ng_UI_constructor(node_p *nodep)
ng_UI_constructor(node_p nodep)
{
priv_p priv;
int error;
/* Allocate private structure */
MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_NOWAIT | M_ZERO);
if (priv == NULL)
if (priv == NULL) {
return (ENOMEM);
/* Call generic node constructor */
if ((error = ng_make_node_common(&typestruct, nodep))) {
FREE(priv, M_NETGRAPH);
return (error);
}
(*nodep)->private = priv;
/* Done */
nodep->private = priv;
return (0);
}
@ -147,26 +139,30 @@ ng_UI_newhook(node_p node, hook_p hook, const char *name)
* Receive a control message
*/
static int
ng_UI_rcvmsg(node_p node, struct ng_mesg *msg,
const char *raddr, struct ng_mesg **rp, hook_p lasthook)
ng_UI_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
int error;
const priv_p priv = node->private;
struct ng_mesg *msg;
msg = NGI_MSG(item); /* only peeking */
if ((msg->header.typecookie == NGM_FLOW_COOKIE) && lasthook) {
if (lasthook == priv->downlink) {
if (priv->uplink) {
return (ng_send_msg(node, msg, NULL,
priv->uplink, raddr, rp));
NG_FWD_MSG_HOOK(error, node, item,
priv->uplink, 0);
return (error);
}
} else {
if (priv->downlink) {
return (ng_send_msg(node, msg, NULL,
priv->downlink, raddr, rp));
NG_FWD_MSG_HOOK(error, node, item,
priv->downlink, 0);
return (error);
}
}
}
FREE(msg, M_NETGRAPH);
NG_FREE_MSG(msg);
return (EINVAL);
}
@ -177,13 +173,14 @@ ng_UI_rcvmsg(node_p node, struct ng_mesg *msg,
* Receive a data frame
*/
static int
ng_UI_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
ng_UI_rcvdata(hook_p hook, item_p item)
{
const node_p node = hook->node;
const priv_p priv = node->private;
struct mbuf *m;
int error = 0;
NGI_GET_M(item, m);
if (hook == priv->downlink) {
u_char *start, *ptr;
@ -197,18 +194,20 @@ ng_UI_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
ERROUT(0);
m_adj(m, ptr - start);
NG_SEND_DATA(error, priv->uplink, m, meta); /* m -> NULL */
NG_FWD_NEW_DATA(error, item, priv->uplink, m); /* m -> NULL */
} else if (hook == priv->uplink) {
M_PREPEND(m, 1, M_DONTWAIT); /* Prepend IP NLPID */
if (!m)
ERROUT(ENOBUFS);
mtod(m, u_char *)[0] = HDLC_UI;
NG_SEND_DATA(error, priv->downlink, m, meta); /* m -> NULL */
NG_FWD_NEW_DATA(error, item, priv->downlink, m); /* m -> NULL */
} else
panic(__FUNCTION__);
done:
NG_FREE_DATA(m, meta); /* does nothing if m == NULL */
NG_FREE_M(m); /* does nothing if m == NULL */
if (item)
NG_FREE_ITEM(item);
return (error);
}
@ -216,15 +215,11 @@ ng_UI_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* Shutdown node
*/
static int
ng_UI_rmnode(node_p node)
ng_UI_shutdown(node_p node)
{
const priv_p priv = node->private;
/* Take down netgraph node */
node->flags |= NG_INVALID;
ng_cutlinks(node);
ng_unname(node);
bzero(priv, sizeof(*priv));
FREE(priv, M_NETGRAPH);
node->private = NULL;
ng_unref(node);
@ -239,14 +234,20 @@ ng_UI_disconnect(hook_p hook)
{
const priv_p priv = hook->node->private;
if (hook->node->numhooks == 0)
ng_rmnode(hook->node);
else if (hook == priv->downlink)
if (hook == priv->downlink)
priv->downlink = NULL;
else if (hook == priv->uplink)
priv->uplink = NULL;
else
panic(__FUNCTION__);
/*
* If we are not already shutting down,
* and we have no more hooks, then DO shut down.
*/
if ((hook->node->numhooks == 0)
&& ((hook->node->flags & NG_INVALID) == 0)) {
ng_rmnode_self(hook->node);
}
return (0);
}

View File

@ -94,8 +94,8 @@ static ng_newhook_t nga_newhook;
static ng_disconnect_t nga_disconnect;
/* Helper stuff */
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);
static int nga_rcv_sync(const sc_p sc, item_p item);
static int nga_rcv_async(const sc_p sc, item_p item);
/* Parse type for struct ng_async_cfg */
static const struct ng_parse_struct_info
@ -174,13 +174,10 @@ static const u_int16_t fcstab[];
* Initialize a new node
*/
static int
nga_constructor(node_p *nodep)
nga_constructor(node_p node)
{
sc_p sc;
int error;
if ((error = ng_make_node_common(&typestruct, nodep)))
return (error);
MALLOC(sc, sc_p, sizeof(*sc), M_NETGRAPH, M_NOWAIT | M_ZERO);
if (sc == NULL)
return (ENOMEM);
@ -200,8 +197,8 @@ nga_constructor(node_p *nodep)
FREE(sc, M_NETGRAPH);
return (ENOMEM);
}
(*nodep)->private = sc;
sc->node = *nodep;
node->private = sc;
sc->node = node;
return (0);
}
@ -214,13 +211,30 @@ nga_newhook(node_p node, hook_p hook, const char *name)
const sc_p sc = node->private;
hook_p *hookp;
if (!strcmp(name, NG_ASYNC_HOOK_ASYNC))
if (!strcmp(name, NG_ASYNC_HOOK_ASYNC)) {
/*
* We use a static buffer here so only one packet
* at a time can be allowed to travel in this direction.
* Force Writer semantics.
*/
hook->flags |= HK_FORCE_WRITER;
hookp = &sc->async;
} else if (!strcmp(name, NG_ASYNC_HOOK_SYNC)) {
/*
* We use a static state here so only one packet
* at a time can be allowed to travel in this direction.
* Force Writer semantics.
* Since we set this for both directions
* we might as well set it for the whole node
* bit I haven;t done that (yet).
*/
hook->flags |= HK_FORCE_WRITER;
hookp = &sc->async;
else if (!strcmp(name, NG_ASYNC_HOOK_SYNC))
hookp = &sc->sync;
else
} else {
return (EINVAL);
if (*hookp)
}
if (*hookp) /* actually can't happen I think [JRE] */
return (EISCONN);
*hookp = hook;
return (0);
@ -230,15 +244,17 @@ nga_newhook(node_p node, hook_p hook, const char *name)
* Receive incoming data
*/
static int
nga_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
nga_rcvdata(hook_p hook, item_p item)
{
const sc_p sc = hook->node->private;
#ifdef ITEM_DEBUG
meta_p meta = NGI_META(item);
#endif
if (hook == sc->sync)
return (nga_rcv_sync(sc, m, meta));
return (nga_rcv_sync(sc, item));
if (hook == sc->async)
return (nga_rcv_async(sc, m, meta));
return (nga_rcv_async(sc, item));
panic(__FUNCTION__);
}
@ -246,13 +262,15 @@ nga_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* Receive incoming control message
*/
static int
nga_rcvmsg(node_p node, struct ng_mesg *msg,
const char *rtn, struct ng_mesg **rptr, hook_p lasthook)
nga_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
const sc_p sc = (sc_p) node->private;
struct ng_mesg *resp = NULL;
int error = 0;
struct ng_mesg *msg;
NGI_GET_MSG(item, msg);
switch (msg->header.typecookie) {
case NGM_ASYNC_COOKIE:
switch (msg->header.cmd) {
@ -317,13 +335,9 @@ nga_rcvmsg(node_p node, struct ng_mesg *msg,
default:
ERROUT(EINVAL);
}
if (rptr)
*rptr = resp;
else if (resp)
FREE(resp, M_NETGRAPH);
done:
FREE(msg, M_NETGRAPH);
NG_RESPOND_MSG(error, node, item, resp);
NG_FREE_MSG(msg);
return (error);
}
@ -335,8 +349,6 @@ nga_shutdown(node_p node)
{
const sc_p sc = node->private;
ng_cutlinks(node);
ng_unname(node);
FREE(sc->abuf, M_NETGRAPH);
FREE(sc->sbuf, M_NETGRAPH);
bzero(sc, sizeof(*sc));
@ -366,8 +378,9 @@ nga_disconnect(hook_p hook)
*hookp = NULL;
bzero(&sc->stats, sizeof(sc->stats));
sc->lasttime = 0;
if (hook->node->numhooks == 0)
ng_rmnode(hook->node);
if ((hook->node->numhooks == 0)
&& ((hook->node->flags & NG_INVALID) == 0))
ng_rmnode_self(hook->node);
return (0);
}
@ -395,21 +408,26 @@ nga_async_add(const sc_p sc, u_int16_t *fcs, u_int32_t accm, int *len, u_char x)
* Receive incoming synchronous data.
*/
static int
nga_rcv_sync(const sc_p sc, struct mbuf *m, meta_p meta)
nga_rcv_sync(const sc_p sc, item_p item)
{
struct ifnet *const rcvif = m->m_pkthdr.rcvif;
struct ifnet *rcvif;
int alen, error = 0;
struct timeval time;
u_int16_t fcs, fcs0;
u_int32_t accm;
struct mbuf *m;
#define ADD_BYTE(x) nga_async_add(sc, &fcs, accm, &alen, (x))
/* Check for bypass mode */
if (!sc->cfg.enabled) {
NG_SEND_DATA(error, sc->async, m, meta);
NG_FWD_DATA(error, item, sc->async );
return (error);
}
NGI_GET_M(item, m);
rcvif = m->m_pkthdr.rcvif;
/* Get ACCM; special case LCP frames, which use full ACCM */
accm = sc->cfg.accm;
@ -430,7 +448,8 @@ nga_rcv_sync(const sc_p sc, struct mbuf *m, meta_p meta)
/* Check for overflow */
if (m->m_pkthdr.len > sc->cfg.smru) {
sc->stats.syncOverflows++;
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_ITEM(item);
return (EMSGSIZE);
}
@ -470,10 +489,11 @@ nga_rcv_sync(const sc_p sc, struct mbuf *m, meta_p meta)
/* Put frame in an mbuf and ship it off */
if (!(m = m_devget(sc->abuf, alen, 0, rcvif, NULL))) {
NG_FREE_META(meta);
NG_FREE_ITEM(item);
error = ENOBUFS;
} else
NG_SEND_DATA(error, sc->async, m, meta);
} else {
NG_FWD_NEW_DATA(error, item, sc->async, m);
}
return (error);
}
@ -483,16 +503,18 @@ nga_rcv_sync(const sc_p sc, struct mbuf *m, meta_p meta)
* that are in our ACCM. Not sure if this is good or not.
*/
static int
nga_rcv_async(const sc_p sc, struct mbuf * m, meta_p meta)
nga_rcv_async(const sc_p sc, item_p item)
{
struct ifnet *const rcvif = m->m_pkthdr.rcvif;
struct ifnet *rcvif;
int error;
struct mbuf *m;
if (!sc->cfg.enabled) {
NG_SEND_DATA(error, sc->sync, m, meta);
NG_FWD_DATA(error, item, sc->sync);
return (error);
}
NG_FREE_META(meta);
NGI_GET_M(item, m);
rcvif = m->m_pkthdr.rcvif;
while (m) {
struct mbuf *n;
@ -531,8 +553,15 @@ nga_rcv_async(const sc_p sc, struct mbuf * m, meta_p meta)
/* OK, ship it out */
if ((n = m_devget(sc->sbuf + skip,
sc->slen - skip, 0, rcvif, NULL)))
NG_SEND_DATA(error, sc->sync, n, meta);
sc->slen - skip, 0, rcvif, NULL))) {
if (item) { /* sets NULL -> item */
NG_FWD_NEW_DATA(error, item,
sc->sync, n);
} else {
NG_SEND_DATA_ONLY(error,
sc->sync ,n);
}
}
sc->stats.asyncFrames++;
reset:
sc->amode = MODE_NORMAL;
@ -569,6 +598,8 @@ nga_rcv_async(const sc_p sc, struct mbuf * m, meta_p meta)
MFREE(m, n);
m = n;
}
if (item)
NG_FREE_ITEM(item);
return (0);
}

File diff suppressed because it is too large Load Diff

View File

@ -83,7 +83,7 @@ typedef struct ng_bpf_hookinfo *hinfo_p;
/* Netgraph methods */
static ng_constructor_t ng_bpf_constructor;
static ng_rcvmsg_t ng_bpf_rcvmsg;
static ng_shutdown_t ng_bpf_rmnode;
static ng_shutdown_t ng_bpf_shutdown;
static ng_newhook_t ng_bpf_newhook;
static ng_rcvdata_t ng_bpf_rcvdata;
static ng_disconnect_t ng_bpf_disconnect;
@ -191,7 +191,7 @@ static struct ng_type typestruct = {
NULL,
ng_bpf_constructor,
ng_bpf_rcvmsg,
ng_bpf_rmnode,
ng_bpf_shutdown,
ng_bpf_newhook,
NULL,
NULL,
@ -214,15 +214,12 @@ static const struct ng_bpf_hookprog ng_bpf_default_prog = {
* Node constructor
*
* We don't keep any per-node private data
* We go via the hooks.
*/
static int
ng_bpf_constructor(node_p *nodep)
ng_bpf_constructor(node_p node)
{
int error = 0;
if ((error = ng_make_node_common(&typestruct, nodep)))
return (error);
(*nodep)->private = NULL;
node->private = NULL;
return (0);
}
@ -260,12 +257,13 @@ ng_bpf_newhook(node_p node, hook_p hook, const char *name)
* Receive a control message
*/
static int
ng_bpf_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
struct ng_mesg **rptr, hook_p lasthook)
ng_bpf_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
struct ng_mesg *msg;
struct ng_mesg *resp = NULL;
int error = 0;
NGI_GET_MSG(item, msg);
switch (msg->header.typecookie) {
case NGM_BPF_COOKIE:
switch (msg->header.cmd) {
@ -357,13 +355,11 @@ ng_bpf_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
error = EINVAL;
break;
}
if (rptr)
*rptr = resp;
else if (resp)
FREE(resp, M_NETGRAPH);
NG_RESPOND_MSG(error, node, item, resp);
done:
FREE(msg, M_NETGRAPH);
if (item)
NG_FREE_ITEM(item);
NG_FREE_MSG(msg);
return (error);
}
@ -373,19 +369,23 @@ ng_bpf_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
* Apply the filter, and then drop or forward packet as appropriate.
*/
static int
ng_bpf_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
ng_bpf_rcvdata(hook_p hook, item_p item)
{
const hinfo_p hip = hook->private;
int totlen = m->m_pkthdr.len;
int totlen;
int needfree = 0, error = 0;
u_char *data, buf[256];
hinfo_p dhip;
hook_p dest;
u_int len;
struct mbuf *m;
/* Update stats on incoming hook */
hip->stats.recvFrames++;
m = NGI_M(item); /* 'item' still owns it.. we are peeking */
totlen = m->m_pkthdr.len;
/* Update stats on incoming hook. XXX Can we do 64 bits atomically? */
/* atomic_add_int64(&hip->stats.recvFrames, 1); */
/* atomic_add_int64(&hip->stats.recvOctets, totlen); */
hip->stats.recvFrames++;
hip->stats.recvOctets += totlen;
/* Need to put packet in contiguous memory for bpf */
@ -393,7 +393,7 @@ ng_bpf_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
if (totlen > sizeof(buf)) {
MALLOC(data, u_char *, totlen, M_NETGRAPH, M_NOWAIT);
if (data == NULL) {
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
return (ENOMEM);
}
needfree = 1;
@ -412,10 +412,12 @@ ng_bpf_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
if (len > 0) {
/* Update stats */
/* XXX atomically? */
hip->stats.recvMatchFrames++;
hip->stats.recvMatchOctets += totlen;
/* Truncate packet length if required by the filter */
/* Assume this never changes m */
if (len < totlen) {
m_adj(m, -(totlen - len));
totlen -= len;
@ -424,7 +426,7 @@ ng_bpf_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
} else
dest = ng_findhook(hip->node, hip->prog->ifNotMatch);
if (dest == NULL) {
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
return (0);
}
@ -432,7 +434,7 @@ ng_bpf_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
dhip = (hinfo_p)dest->private;
dhip->stats.xmitOctets += totlen;
dhip->stats.xmitFrames++;
NG_SEND_DATA(error, dest, m, meta);
NG_FWD_DATA(error, item, dest);
return (error);
}
@ -440,11 +442,9 @@ ng_bpf_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* Shutdown processing
*/
static int
ng_bpf_rmnode(node_p node)
ng_bpf_shutdown(node_p node)
{
node->flags |= NG_INVALID;
ng_cutlinks(node);
ng_unname(node);
ng_unref(node);
return (0);
}
@ -462,8 +462,10 @@ ng_bpf_disconnect(hook_p hook)
bzero(hip, sizeof(*hip));
FREE(hip, M_NETGRAPH);
hook->private = NULL; /* for good measure */
if (hook->node->numhooks == 0)
ng_rmnode(hook->node);
if ((hook->node->numhooks == 0)
&& ((hook->node->flags && NG_INVALID) == 0)) {
ng_rmnode_self(hook->node);
}
return (0);
}

View File

@ -112,7 +112,7 @@ SLIST_HEAD(ng_bridge_bucket, ng_bridge_hent);
/* Netgraph node methods */
static ng_constructor_t ng_bridge_constructor;
static ng_rcvmsg_t ng_bridge_rcvmsg;
static ng_shutdown_t ng_bridge_rmnode;
static ng_shutdown_t ng_bridge_shutdown;
static ng_newhook_t ng_bridge_newhook;
static ng_rcvdata_t ng_bridge_rcvdata;
static ng_disconnect_t ng_bridge_disconnect;
@ -271,7 +271,7 @@ static struct ng_type ng_bridge_typestruct = {
NULL,
ng_bridge_constructor,
ng_bridge_rcvmsg,
ng_bridge_rmnode,
ng_bridge_shutdown,
ng_bridge_newhook,
NULL,
NULL,
@ -292,10 +292,9 @@ MODULE_DEPEND(ng_bridge, ng_ether, 1, 1, 1);
* Node constructor
*/
static int
ng_bridge_constructor(node_p *nodep)
ng_bridge_constructor(node_p node)
{
priv_p priv;
int error;
/* Allocate and initialize private info */
MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_NOWAIT | M_ZERO);
@ -317,17 +316,21 @@ ng_bridge_constructor(node_p *nodep)
priv->conf.maxStaleness = DEFAULT_MAX_STALENESS;
priv->conf.minStableAge = DEFAULT_MIN_STABLE_AGE;
/* Call superclass constructor */
if ((error = ng_make_node_common(&ng_bridge_typestruct, nodep))) {
FREE(priv, M_NETGRAPH);
return (error);
}
(*nodep)->private = priv;
priv->node = *nodep;
/*
* This node has all kinds of stuff that could be screwed by SMP.
* Until it gets it's own internal protection, we go through in
* single file. This could hurt a machine bridging beteen two
* GB ethernets so it should be fixed.
* When it's fixed the process SHOULD NOT SLEEP, spinlocks please!
* (and atomic ops )
*/
node->flags |= NG_FORCE_WRITER;
node->private = priv;
priv->node = node;
/* Start timer by faking a timeout event */
(*nodep)->refs++;
ng_bridge_timeout(*nodep);
node->refs++; /* XXX ???? because of the timeout?*/
ng_bridge_timeout(node);
return (0);
}
@ -372,13 +375,14 @@ ng_bridge_newhook(node_p node, hook_p hook, const char *name)
* Receive a control message
*/
static int
ng_bridge_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
struct ng_mesg **rptr, hook_p lasthook)
ng_bridge_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
const priv_p priv = node->private;
struct ng_mesg *resp = NULL;
int error = 0;
struct ng_mesg *msg;
NGI_GET_MSG(item, msg);
switch (msg->header.typecookie) {
case NGM_BRIDGE_COOKIE:
switch (msg->header.cmd) {
@ -497,11 +501,8 @@ ng_bridge_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
}
/* Done */
if (rptr)
*rptr = resp;
else if (resp != NULL)
FREE(resp, M_NETGRAPH);
FREE(msg, M_NETGRAPH);
NG_RESPOND_MSG(error, node, item, resp);
NG_FREE_MSG(msg);
return (error);
}
@ -509,8 +510,7 @@ ng_bridge_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
* Receive data on a hook
*/
static int
ng_bridge_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
ng_bridge_rcvdata(hook_p hook, item_p item)
{
const node_p node = hook->node;
const priv_p priv = node->private;
@ -518,8 +518,12 @@ ng_bridge_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct ng_bridge_link *link;
struct ether_header *eh;
int error = 0, linkNum;
int i, manycast;
int manycast;
struct mbuf *m;
meta_p meta;
struct ng_bridge_link *firstLink;
NGI_GET_M(item, m);
/* Get link number */
linkNum = LINK_NUM(hook);
KASSERT(linkNum >= 0 && linkNum < NG_BRIDGE_MAX_LINKS,
@ -530,25 +534,28 @@ ng_bridge_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
/* Sanity check packet and pull up header */
if (m->m_pkthdr.len < ETHER_HDR_LEN) {
link->stats.recvRunts++;
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
NG_FREE_M(m);
return (EINVAL);
}
if (m->m_len < ETHER_HDR_LEN && !(m = m_pullup(m, ETHER_HDR_LEN))) {
link->stats.memoryFailures++;
NG_FREE_META(meta);
NG_FREE_ITEM(item);
return (ENOBUFS);
}
eh = mtod(m, struct ether_header *);
if ((eh->ether_shost[0] & 1) != 0) {
link->stats.recvInvalid++;
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
NG_FREE_M(m);
return (EINVAL);
}
/* Is link disabled due to a loopback condition? */
if (link->loopCount != 0) {
link->stats.loopDrops++;
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
NG_FREE_M(m);
return (ELOOP); /* XXX is this an appropriate error? */
}
@ -605,7 +612,8 @@ ng_bridge_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
/* Drop packet */
link->stats.loopDrops++;
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
NG_FREE_M(m);
return (ELOOP); /* XXX appropriate? */
}
@ -616,7 +624,8 @@ ng_bridge_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
} else {
if (!ng_bridge_put(priv, eh->ether_shost, linkNum)) {
link->stats.memoryFailures++;
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
NG_FREE_M(m);
return (ENOMEM);
}
}
@ -641,14 +650,15 @@ ng_bridge_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
KASSERT(destLink != NULL,
("%s: link%d null", __FUNCTION__, host->linkNum));
if (destLink == link) {
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
NG_FREE_M(m);
return (0);
}
/* Deliver packet out the destination link */
destLink->stats.xmitPackets++;
destLink->stats.xmitOctets += m->m_pkthdr.len;
NG_SEND_DATA(error, destLink->hook, m, meta);
NG_FWD_NEW_DATA(error, item, destLink->hook, m);
return (error);
}
@ -657,31 +667,58 @@ ng_bridge_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
}
/* Distribute unknown, multicast, broadcast pkts to all other links */
for (linkNum = i = 0; i < priv->numLinks - 1; linkNum++) {
struct ng_bridge_link *const destLink = priv->links[linkNum];
meta = NGI_META(item); /* peek.. */
firstLink = NULL;
for (linkNum = 0; linkNum <= priv->numLinks; linkNum++) {
struct ng_bridge_link *destLink;
meta_p meta2 = NULL;
struct mbuf *m2;
struct mbuf *m2 = NULL;
/* Skip incoming link and disconnected links */
if (destLink == NULL || destLink == link)
continue;
/*
* If we have checked all the links then now
* send the original on its reserved link
*/
if (linkNum == priv->numLinks) {
/* If we never saw a good link, leave. */
if (firstLink == NULL) {
NG_FREE_ITEM(item);
NG_FREE_M(m);
return (0);
}
destLink = firstLink;
} else {
destLink = priv->links[linkNum];
/* Skip incoming link and disconnected links */
if (destLink == NULL || destLink == link) {
continue;
}
if (firstLink == NULL) {
/*
* This is the first usable link we have found.
* Reserve it for the originals.
* If we never find another we save a copy.
*/
firstLink = destLink;
continue;
}
/* Copy mbuf and meta info */
if (++i == priv->numLinks - 1) { /* last link */
m2 = m;
meta2 = meta;
} else {
/*
* It's usable link but not the reserved (first) one.
* Copy mbuf and meta info for sending.
*/
m2 = m_dup(m, M_NOWAIT); /* XXX m_copypacket() */
if (m2 == NULL) {
link->stats.memoryFailures++;
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
NG_FREE_M(m);
return (ENOBUFS);
}
if (meta != NULL
&& (meta2 = ng_copy_meta(meta)) == NULL) {
link->stats.memoryFailures++;
m_freem(m2);
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
NG_FREE_M(m);
return (ENOMEM);
}
}
@ -701,7 +738,16 @@ ng_bridge_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
}
/* Send packet */
NG_SEND_DATA(error, destLink->hook, m2, meta2);
if (destLink == firstLink) {
/*
* If we've sent all the others, send the original
* on the first link we found.
*/
NG_FWD_NEW_DATA(error, item, destLink->hook, m);
break; /* always done last - not really needed. */
} else {
NG_SEND_DATA(error, destLink->hook, m2, meta2);
}
}
return (error);
}
@ -710,12 +756,10 @@ ng_bridge_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* Shutdown node
*/
static int
ng_bridge_rmnode(node_p node)
ng_bridge_shutdown(node_p node)
{
const priv_p priv = node->private;
ng_unname(node);
ng_cutlinks(node); /* frees all link and host info */
KASSERT(priv->numLinks == 0 && priv->numHosts == 0,
("%s: numLinks=%d numHosts=%d",
__FUNCTION__, priv->numLinks, priv->numHosts));
@ -750,8 +794,9 @@ ng_bridge_disconnect(hook_p hook)
priv->numLinks--;
/* If no more hooks, go away */
if (hook->node->numhooks == 0)
ng_rmnode(hook->node);
if ((hook->node->numhooks == 0)
&& (( hook->node->flags & NG_INVALID) == 0))
ng_rmnode_self(hook->node);
return (0);
}

View File

@ -117,13 +117,13 @@ typedef struct cisco_priv *sc_p;
/* Netgraph methods */
static ng_constructor_t cisco_constructor;
static ng_rcvmsg_t cisco_rcvmsg;
static ng_shutdown_t cisco_rmnode;
static ng_shutdown_t cisco_shutdown;
static ng_newhook_t cisco_newhook;
static ng_rcvdata_t cisco_rcvdata;
static ng_disconnect_t cisco_disconnect;
/* Other functions */
static int cisco_input(sc_p sc, struct mbuf *m, meta_p meta);
static int cisco_input(sc_p sc, item_p item);
static void cisco_keepalive(void *arg);
static int cisco_send(sc_p sc, int type, long par1, long par2);
@ -176,7 +176,7 @@ static struct ng_type typestruct = {
NULL,
cisco_constructor,
cisco_rcvmsg,
cisco_rmnode,
cisco_shutdown,
cisco_newhook,
NULL,
NULL,
@ -190,22 +190,17 @@ NETGRAPH_INIT(cisco, &typestruct);
* Node constructor
*/
static int
cisco_constructor(node_p *nodep)
cisco_constructor(node_p node)
{
sc_p sc;
int error = 0;
MALLOC(sc, sc_p, sizeof(*sc), M_NETGRAPH, M_NOWAIT | M_ZERO);
if (sc == NULL)
return (ENOMEM);
callout_handle_init(&sc->handle);
if ((error = ng_make_node_common(&typestruct, nodep))) {
FREE(sc, M_NETGRAPH);
return (error);
}
(*nodep)->private = sc;
sc->node = *nodep;
node->private = sc;
sc->node = node;
/* Initialise the varous protocol hook holders */
sc->downstream.af = 0xffff;
@ -250,13 +245,14 @@ cisco_newhook(node_p node, hook_p hook, const char *name)
* Receive control message.
*/
static int
cisco_rcvmsg(node_p node, struct ng_mesg *msg,
const char *retaddr, struct ng_mesg **rptr, hook_p lasthook)
cisco_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
struct ng_mesg *msg;
const sc_p sc = node->private;
struct ng_mesg *resp = NULL;
int error = 0;
NGI_GET_MSG(item, msg);
switch (msg->header.typecookie) {
case NGM_GENERIC_COOKIE:
switch (msg->header.cmd) {
@ -337,11 +333,8 @@ cisco_rcvmsg(node_p node, struct ng_mesg *msg,
error = EINVAL;
break;
}
if (rptr)
*rptr = resp;
else if (resp)
FREE(resp, M_NETGRAPH);
FREE(msg, M_NETGRAPH);
NG_RESPOND_MSG(error, node, item, resp);
NG_FREE_MSG(msg);
return (error);
}
@ -349,23 +342,24 @@ cisco_rcvmsg(node_p node, struct ng_mesg *msg,
* Receive data
*/
static int
cisco_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
cisco_rcvdata(hook_p hook, item_p item)
{
const sc_p sc = hook->node->private;
struct protoent *pep;
struct cisco_header *h;
int error = 0;
struct mbuf *m;
if ((pep = hook->private) == NULL)
goto out;
/* If it came from our downlink, deal with it separately */
if (pep->af == 0xffff)
return (cisco_input(sc, m, meta));
return (cisco_input(sc, item));
/* OK so it came from a protocol, heading out. Prepend general data
packet header. For now, IP,IPX only */
m = NGI_M(item); /* still associated with item */
M_PREPEND(m, CISCO_HEADER_LEN, M_DONTWAIT);
if (!m) {
error = ENOBUFS;
@ -394,11 +388,11 @@ cisco_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
}
/* Send it */
NG_SEND_DATA(error, sc->downstream.hook, m, meta);
NG_FWD_NEW_DATA(error, item, sc->downstream.hook, m);
return (error);
out:
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
return (error);
}
@ -406,13 +400,11 @@ cisco_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* Shutdown node
*/
static int
cisco_rmnode(node_p node)
cisco_shutdown(node_p node)
{
const sc_p sc = node->private;
node->flags |= NG_INVALID;
ng_cutlinks(node);
ng_unname(node);
node->private = NULL;
ng_unref(sc->node);
FREE(sc, M_NETGRAPH);
@ -440,8 +432,9 @@ cisco_disconnect(hook_p hook)
}
/* If no more hooks, remove the node */
if (hook->node->numhooks == 0)
ng_rmnode(hook->node);
if ((hook->node->numhooks == 0)
&& ((hook->node->flags & NG_INVALID) == 0))
ng_rmnode_self(hook->node);
return (0);
}
@ -449,13 +442,15 @@ cisco_disconnect(hook_p hook)
* Receive data
*/
static int
cisco_input(sc_p sc, struct mbuf *m, meta_p meta)
cisco_input(sc_p sc, item_p item)
{
struct cisco_header *h;
struct cisco_packet *p;
struct protoent *pep;
int error = 0;
struct mbuf *m;
m = NGI_M(item);
if (m->m_pkthdr.len <= CISCO_HEADER_LEN)
goto drop;
@ -477,7 +472,7 @@ cisco_input(sc_p sc, struct mbuf *m, meta_p meta)
switch (ntohl(p->type)) {
default:
log(LOG_WARNING,
"cisco: unknown cisco packet type: 0x%lx\n",
"cisco: unknown cisco packet type: 0x%x\n",
ntohl(p->type));
break;
case CISCO_ADDR_REPLY:
@ -492,7 +487,8 @@ cisco_input(sc_p sc, struct mbuf *m, meta_p meta)
break;
case CISCO_ADDR_REQ:
{
struct ng_mesg *msg, *resp;
struct ng_mesg *msg;
int dummy_error = 0;
/* Ask inet peer for IP address information */
if (sc->inet.hook == NULL)
@ -501,12 +497,13 @@ cisco_input(sc_p sc, struct mbuf *m, meta_p meta)
NGM_CISCO_GET_IPADDR, 0, M_NOWAIT);
if (msg == NULL)
goto nomsg;
ng_send_msg(sc->node, msg, NULL,
sc->inet.hook, NULL, &resp);
if (resp != NULL)
cisco_rcvmsg(sc->node, resp, ".",
NULL, NULL);
NG_SEND_MSG_HOOK(dummy_error, sc->node, msg,
sc->inet.hook, NULL);
/*
* XXX Now maybe we should set a flag telling
* our receiver to send this message when the response comes in
* instead of now when the data may be bad.
*/
nomsg:
/* Send reply to peer device */
error = cisco_send(sc, CISCO_ADDR_REPLY,
@ -535,11 +532,11 @@ cisco_input(sc_p sc, struct mbuf *m, meta_p meta)
/* Send it on */
if (pep->hook == NULL)
goto drop;
NG_SEND_DATA(error, pep->hook, m, meta);
NG_FWD_NEW_DATA(error, item, pep->hook, m);
return (error);
drop:
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
return (error);
}
@ -570,7 +567,6 @@ cisco_send(sc_p sc, int type, long par1, long par2)
struct mbuf *m;
u_long t;
int error = 0;
meta_p meta = NULL;
struct timeval time;
getmicrotime(&time);
@ -596,6 +592,6 @@ cisco_send(sc_p sc, int type, long par1, long par2)
ch->time0 = htons((u_short) (t >> 16));
ch->time1 = htons((u_short) t);
NG_SEND_DATA(error, sc->downstream.hook, m, meta);
NG_SEND_DATA_ONLY(error, sc->downstream.hook, m);
return (error);
}

View File

@ -55,6 +55,7 @@
#include <netgraph/ng_echo.h>
/* Netgraph methods */
static ng_constructor_t nge_cons;
static ng_rcvmsg_t nge_rcvmsg;
static ng_rcvdata_t nge_rcvdata;
static ng_disconnect_t nge_disconnect;
@ -64,7 +65,7 @@ static struct ng_type typestruct = {
NG_ABI_VERSION,
NG_ECHO_NODE_TYPE,
NULL,
NULL,
nge_cons,
nge_rcvmsg,
NULL,
NULL,
@ -76,33 +77,37 @@ static struct ng_type typestruct = {
};
NETGRAPH_INIT(echo, &typestruct);
static int
nge_cons(node_p node)
{
return (0);
}
/*
* Receive control message. We just bounce it back as a reply.
*/
static int
nge_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
struct ng_mesg **rptr, hook_p lasthook)
nge_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
if (rptr) {
msg->header.flags |= NGF_RESP;
*rptr = msg;
} else {
FREE(msg, M_NETGRAPH);
}
return (0);
struct ng_mesg *msg;
int error = 0;
NGI_GET_MSG(item, msg);
msg->header.flags |= NGF_RESP;
NG_RESPOND_MSG(error, node, item, msg);
return (error);
}
/*
* Receive data
*/
static int
nge_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
nge_rcvdata(hook_p hook, item_p item)
{
int error = 0;
NG_SEND_DATA(error, hook, m, meta);
return (error);
NG_FWD_DATA(error, item, hook);
return (0);
}
/*
@ -111,8 +116,10 @@ nge_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
static int
nge_disconnect(hook_p hook)
{
if (hook->node->numhooks == 0)
ng_rmnode(hook->node);
if ((hook->node->numhooks == 0)
&& ((hook->node->flags & NG_INVALID) == 0)) {
ng_rmnode_self(hook->node);
}
return (0);
}

View File

@ -98,7 +98,7 @@ static int ng_ether_rcv_upper(node_p node, struct mbuf *m, meta_p meta);
/* Netgraph node methods */
static ng_constructor_t ng_ether_constructor;
static ng_rcvmsg_t ng_ether_rcvmsg;
static ng_shutdown_t ng_ether_rmnode;
static ng_shutdown_t ng_ether_shutdown;
static ng_newhook_t ng_ether_newhook;
static ng_connect_t ng_ether_connect;
static ng_rcvdata_t ng_ether_rcvdata;
@ -185,7 +185,7 @@ static struct ng_type ng_ether_typestruct = {
ng_ether_mod_event,
ng_ether_constructor,
ng_ether_rcvmsg,
ng_ether_rmnode,
ng_ether_shutdown,
ng_ether_newhook,
NULL,
ng_ether_connect,
@ -272,7 +272,6 @@ ng_ether_output(struct ifnet *ifp, struct mbuf **mp)
{
const node_p node = IFP2NG(ifp);
const priv_p priv = node->private;
meta_p meta = NULL;
int error = 0;
/* If "upper" hook not connected, let packet continue */
@ -280,13 +279,7 @@ ng_ether_output(struct ifnet *ifp, struct mbuf **mp)
return (0);
/* Send it out "upper" hook */
NG_SEND_DATA_RET(error, priv->upper, *mp, meta, NULL);
/* If we got a reflected packet back, handle it */
if (error == 0 && *mp != NULL) {
error = ng_ether_rcv_upper(node, *mp, meta);
*mp = NULL;
}
NG_SEND_DATA_ONLY(error, priv->upper, *mp);
return (error);
}
@ -342,9 +335,8 @@ ng_ether_detach(struct ifnet *ifp)
if (node == NULL) /* no node (why not?), ignore */
return;
ng_rmnode(node); /* break all links to other nodes */
ng_rmnode_self(node); /* break all links to other nodes */
node->flags |= NG_INVALID;
ng_unname(node); /* free name (and its reference) */
IFP2NG(ifp) = NULL; /* detach node from interface */
priv = node->private; /* free node private info */
bzero(priv, sizeof(*priv));
@ -438,7 +430,7 @@ ng_ether_glueback_header(struct mbuf **mp, struct ether_header *eh)
* this node type's KLD is loaded).
*/
static int
ng_ether_constructor(node_p *nodep)
ng_ether_constructor(node_p node)
{
return (EINVAL);
}
@ -495,13 +487,14 @@ ng_ether_connect(hook_p hook)
* Receive an incoming control message.
*/
static int
ng_ether_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
struct ng_mesg **rptr, hook_p lasthook)
ng_ether_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
const priv_p priv = node->private;
struct ng_mesg *resp = NULL;
int error = 0;
struct ng_mesg *msg;
NGI_GET_MSG(item, msg);
switch (msg->header.typecookie) {
case NGM_ETHER_COOKIE:
switch (msg->header.cmd) {
@ -589,11 +582,8 @@ ng_ether_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
error = EINVAL;
break;
}
if (rptr)
*rptr = resp;
else if (resp != NULL)
FREE(resp, M_NETGRAPH);
FREE(msg, M_NETGRAPH);
NG_RESPOND_MSG(error, node, item, resp);
NG_FREE_MSG(msg);
return (error);
}
@ -601,12 +591,16 @@ ng_ether_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
* Receive data on a hook.
*/
static int
ng_ether_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
ng_ether_rcvdata(hook_p hook, item_p item)
{
const node_p node = hook->node;
const priv_p priv = node->private;
struct mbuf *m;
meta_p meta;
NGI_GET_M(item, m);
NGI_GET_META(item, meta);
NG_FREE_ITEM(item);
if (hook == priv->lower)
return ng_ether_rcv_lower(node, m, meta);
if (hook == priv->upper)
@ -624,7 +618,8 @@ ng_ether_rcv_lower(node_p node, struct mbuf *m, meta_p meta)
/* Make sure header is fully pulled up */
if (m->m_pkthdr.len < sizeof(struct ether_header)) {
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_META(meta);
return (EINVAL);
}
if (m->m_len < sizeof(struct ether_header)
@ -656,7 +651,8 @@ ng_ether_rcv_upper(node_p node, struct mbuf *m, meta_p meta)
/* Check length and pull off header */
if (m->m_pkthdr.len < sizeof(*eh)) {
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_META(meta);
return (EINVAL);
}
if (m->m_len < sizeof(*eh) && (m = m_pullup(m, sizeof(*eh))) == NULL) {
@ -677,19 +673,38 @@ ng_ether_rcv_upper(node_p node, struct mbuf *m, meta_p meta)
/*
* Shutdown node. This resets the node but does not remove it.
* Actually it produces a new node. XXX The problem is what to do when
* the node really DOES need to go away,
* or if our re-make of the node fails.
*/
static int
ng_ether_rmnode(node_p node)
ng_ether_shutdown(node_p node)
{
char name[IFNAMSIZ + 1];
const priv_p priv = node->private;
ng_cutlinks(node);
node->flags &= ~NG_INVALID; /* bounce back to life */
if (priv->promisc) { /* disable promiscuous mode */
(void)ifpromisc(priv->ifp, 0);
priv->promisc = 0;
}
ng_unref(node);
snprintf(name, sizeof(name), "%s%d", priv->ifp->if_name, priv->ifp->if_unit);
if (ng_make_node_common(&ng_ether_typestruct, &node) != 0) {
log(LOG_ERR, "%s: can't %s for %s\n",
__FUNCTION__, "create node", name);
return (ENOMEM);
}
/* Allocate private data */
node->private = priv;
IFP2NG(priv->ifp) = node;
priv->autoSrcAddr = 1; /* reset auto-src-addr flag */
/* Try to give the node the same name as the interface */
if (ng_name_node(node, name) != 0) {
log(LOG_WARNING, "%s: can't name node %s\n",
__FUNCTION__, name);
}
return (0);
}
@ -708,8 +723,9 @@ ng_ether_disconnect(hook_p hook)
priv->lowerOrphan = 0;
} else
panic("%s: weird hook", __FUNCTION__);
if (hook->node->numhooks == 0)
ng_rmnode(hook->node); /* reset node */
if ((hook->node->numhooks == 0)
&& ((hook->node->flags & NG_INVALID) == 0))
ng_rmnode_self(hook->node); /* reset node */
return (0);
}

View File

@ -34,7 +34,7 @@
* THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* Author: Julian Elisher <julian@freebsd.org>
* Author: Julian Elischer <julian@freebsd.org>
*
* $FreeBSD$
* $Whistle: ng_frame_relay.c,v 1.20 1999/11/01 09:24:51 julian Exp $
@ -125,13 +125,13 @@ static struct segment {
/* Netgraph methods */
static ng_constructor_t ngfrm_constructor;
static ng_shutdown_t ngfrm_rmnode;
static ng_shutdown_t ngfrm_shutdown;
static ng_newhook_t ngfrm_newhook;
static ng_rcvdata_t ngfrm_rcvdata;
static ng_disconnect_t ngfrm_disconnect;
/* Other internal functions */
static int ngfrm_decode(node_p node, struct mbuf * m, meta_p meta);
static int ngfrm_decode(node_p node, item_p item);
static int ngfrm_addrlen(char *hdr);
static int ngfrm_allocate_CTX(sc_p sc, int dlci);
@ -142,7 +142,7 @@ static struct ng_type typestruct = {
NULL,
ngfrm_constructor,
NULL,
ngfrm_rmnode,
ngfrm_shutdown,
ngfrm_newhook,
NULL,
NULL,
@ -212,23 +212,18 @@ ngfrm_allocate_CTX(sc_p sc, int dlci)
* Node constructor
*/
static int
ngfrm_constructor(node_p *nodep)
ngfrm_constructor(node_p node)
{
sc_p sc;
int error = 0;
MALLOC(sc, sc_p, sizeof(*sc), M_NETGRAPH, M_NOWAIT | M_ZERO);
if (!sc)
return (ENOMEM);
if ((error = ng_make_node_common(&typestruct, nodep))) {
FREE(sc, M_NETGRAPH);
return (error);
}
sc->addrlen = 2; /* default */
/* Link the node and our private info */
(*nodep)->private = sc;
sc->node = *nodep;
node->private = sc;
sc->node = node;
return (0);
}
@ -335,8 +330,7 @@ ngfrm_addrlen(char *hdr)
* Receive data packet
*/
static int
ngfrm_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
ngfrm_rcvdata(hook_p hook, item_p item)
{
struct ctxinfo *const ctxp = hook->private;
int error = 0;
@ -344,6 +338,7 @@ ngfrm_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
sc_p sc;
int alen;
char *data;
struct mbuf *m;
/* Data doesn't come in from just anywhere (e.g debug hook) */
if (ctxp == NULL) {
@ -354,8 +349,9 @@ ngfrm_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
/* If coming from downstream, decode it to a channel */
dlci = ctxp->dlci;
if (dlci == -1)
return (ngfrm_decode(hook->node, m, meta));
return (ngfrm_decode(hook->node, item));
NGI_GET_M(item, m);
/* Derive the softc we will need */
sc = hook->node->private;
@ -408,11 +404,12 @@ ngfrm_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
}
/* Send it */
NG_SEND_DATA(error, sc->downstream.hook, m, meta);
NG_FWD_NEW_DATA(error, item, sc->downstream.hook, m);
return (error);
bad:
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
NG_FREE_M(m);
return (error);
}
@ -420,7 +417,7 @@ ngfrm_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* Decode an incoming frame coming from the switch
*/
static int
ngfrm_decode(node_p node, struct mbuf *m, meta_p meta)
ngfrm_decode(node_p node, item_p item)
{
const sc_p sc = node->private;
char *data;
@ -428,7 +425,9 @@ ngfrm_decode(node_p node, struct mbuf *m, meta_p meta)
u_int dlci = 0;
int error = 0;
int ctxnum;
struct mbuf *m;
NGI_GET_M(item, m);
if (m->m_len < 4 && (m = m_pullup(m, 4)) == NULL) {
error = ENOBUFS;
goto out;
@ -466,13 +465,14 @@ ngfrm_decode(node_p node, struct mbuf *m, meta_p meta)
if ((ctxnum & CTX_VALID) && sc->channel[ctxnum &= CTX_VALUE].hook) {
/* Send it */
m_adj(m, alen);
NG_SEND_DATA(error, sc->channel[ctxnum].hook, m, meta);
NG_FWD_NEW_DATA(error, item, sc->channel[ctxnum].hook, m);
return (error);
} else {
error = ENETDOWN;
}
out:
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
NG_FREE_M(m);
return (error);
}
@ -480,13 +480,11 @@ ngfrm_decode(node_p node, struct mbuf *m, meta_p meta)
* Shutdown node
*/
static int
ngfrm_rmnode(node_p node)
ngfrm_shutdown(node_p node)
{
const sc_p sc = node->private;
node->flags |= NG_INVALID;
ng_cutlinks(node);
ng_unname(node);
node->private = NULL;
FREE(sc, M_NETGRAPH);
ng_unref(node);
@ -515,7 +513,8 @@ ngfrm_disconnect(hook_p hook)
cp->flags = 0;
sc->datahooks--;
}
if (hook->node->numhooks == 0)
ng_rmnode(hook->node);
if ((hook->node->numhooks == 0)
&& ((hook->node->flags & NG_INVALID) == 0))
ng_rmnode_self(hook->node);
return (0);
}

View File

@ -53,33 +53,42 @@
#include <netgraph/ng_hole.h>
/* Netgraph methods */
static ng_constructor_t ngh_cons;
static ng_rcvdata_t ngh_rcvdata;
static ng_disconnect_t ngh_disconnect;
static struct ng_type typestruct = {
NG_ABI_VERSION,
NG_HOLE_NODE_TYPE,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
ngh_rcvdata,
ngh_disconnect,
NULL
NULL, /* modeventhand_t */
ngh_cons, /* ng_constructor_t */
NULL, /* ng_rcvmsg_t */
NULL, /* ng_shutdown_t */
NULL, /* ng_newhook_t */
NULL, /* ng_findhook_t */
NULL, /* ng_connect_t */
ngh_rcvdata, /* ng_rcvdata_t */
ngh_disconnect, /* ng_disconnect_t */
NULL /* ng_cmdlist */
};
NETGRAPH_INIT(hole, &typestruct);
/*
* Be obliging. but no work to do.
*/
static int
ngh_cons(node_p node)
{
return(0);
}
/*
* Receive data
*/
static int
ngh_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
ngh_rcvdata(hook_p hook, item_p item)
{
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
return 0;
}
@ -90,6 +99,6 @@ static int
ngh_disconnect(hook_p hook)
{
if (hook->node->numhooks == 0)
ng_rmnode(hook->node);
ng_rmnode_self(hook->node);
return (0);
}

View File

@ -118,7 +118,7 @@ static void ng_iface_print_ioctl(struct ifnet *ifp, int cmd, caddr_t data);
/* Netgraph methods */
static ng_constructor_t ng_iface_constructor;
static ng_rcvmsg_t ng_iface_rcvmsg;
static ng_shutdown_t ng_iface_rmnode;
static ng_shutdown_t ng_iface_shutdown;
static ng_newhook_t ng_iface_newhook;
static ng_rcvdata_t ng_iface_rcvdata;
static ng_disconnect_t ng_iface_disconnect;
@ -186,7 +186,7 @@ static struct ng_type typestruct = {
NULL,
ng_iface_constructor,
ng_iface_rcvmsg,
ng_iface_rmnode,
ng_iface_shutdown,
ng_iface_newhook,
NULL,
NULL,
@ -521,11 +521,10 @@ ng_iface_print_ioctl(struct ifnet *ifp, int command, caddr_t data)
* Constructor for a node
*/
static int
ng_iface_constructor(node_p *nodep)
ng_iface_constructor(node_p node)
{
char ifname[NG_IFACE_IFACE_NAME_MAX + 1];
struct ifnet *ifp;
node_p node;
priv_p priv;
int error = 0;
@ -550,15 +549,6 @@ ng_iface_constructor(node_p *nodep)
return (error);
}
/* Call generic node constructor */
if ((error = ng_make_node_common(&typestruct, nodep)) != 0) {
ng_iface_free_unit(priv->unit);
FREE(ifp, M_NETGRAPH);
FREE(priv, M_NETGRAPH);
return (error);
}
node = *nodep;
/* Link together node and private info */
node->private = priv;
priv->node = node;
@ -615,14 +605,15 @@ ng_iface_newhook(node_p node, hook_p hook, const char *name)
* Receive a control message
*/
static int
ng_iface_rcvmsg(node_p node, struct ng_mesg *msg,
const char *retaddr, struct ng_mesg **rptr, hook_p lasthook)
ng_iface_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
const priv_p priv = node->private;
struct ifnet *const ifp = priv->ifp;
struct ng_mesg *resp = NULL;
int error = 0;
struct ng_mesg *msg;
NGI_GET_MSG(item, msg);
switch (msg->header.typecookie) {
case NGM_IFACE_COOKIE:
switch (msg->header.cmd) {
@ -707,11 +698,8 @@ ng_iface_rcvmsg(node_p node, struct ng_mesg *msg,
error = EINVAL;
break;
}
if (rptr)
*rptr = resp;
else if (resp)
FREE(resp, M_NETGRAPH);
FREE(msg, M_NETGRAPH);
NG_RESPOND_MSG(error, node, item, resp);
NG_FREE_MSG(msg);
return (error);
}
@ -719,20 +707,22 @@ ng_iface_rcvmsg(node_p node, struct ng_mesg *msg,
* Recive data from a hook. Pass the packet to the correct input routine.
*/
static int
ng_iface_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
ng_iface_rcvdata(hook_p hook, item_p item)
{
const priv_p priv = hook->node->private;
const iffam_p iffam = get_iffam_from_hook(priv, hook);
struct ifnet *const ifp = priv->ifp;
struct mbuf *m;
NGI_GET_M(item, m);
NG_FREE_ITEM(item);
/* Sanity checks */
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) {
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
return (ENETDOWN);
}
@ -746,9 +736,6 @@ ng_iface_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
/* Berkeley packet filter */
ng_iface_bpftap(ifp, m, iffam->family);
/* Ignore any meta-data */
NG_FREE_META(meta);
/* Send packet */
return family_enqueue(iffam->family, m);
}
@ -757,12 +744,10 @@ ng_iface_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* Shutdown and remove the node and its associated interface.
*/
static int
ng_iface_rmnode(node_p node)
ng_iface_shutdown(node_p node)
{
const priv_p priv = node->private;
ng_cutlinks(node);
ng_unname(node);
bpfdetach(priv->ifp);
if_detach(priv->ifp);
priv->ifp = NULL;

View File

@ -80,7 +80,7 @@ typedef struct ng_ksocket_private *priv_p;
/* Netgraph node methods */
static ng_constructor_t ng_ksocket_constructor;
static ng_rcvmsg_t ng_ksocket_rcvmsg;
static ng_shutdown_t ng_ksocket_rmnode;
static ng_shutdown_t ng_ksocket_shutdown;
static ng_newhook_t ng_ksocket_newhook;
static ng_rcvdata_t ng_ksocket_rcvdata;
static ng_disconnect_t ng_ksocket_disconnect;
@ -464,7 +464,7 @@ static struct ng_type ng_ksocket_typestruct = {
NULL,
ng_ksocket_constructor,
ng_ksocket_rcvmsg,
ng_ksocket_rmnode,
ng_ksocket_shutdown,
ng_ksocket_newhook,
NULL,
NULL,
@ -484,22 +484,16 @@ NETGRAPH_INIT(ksocket, &ng_ksocket_typestruct);
* Node type constructor
*/
static int
ng_ksocket_constructor(node_p *nodep)
ng_ksocket_constructor(node_p node)
{
priv_p priv;
int error;
/* Allocate private structure */
MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_NOWAIT | M_ZERO);
if (priv == NULL)
return (ENOMEM);
/* Call generic node constructor */
if ((error = ng_make_node_common(&ng_ksocket_typestruct, nodep))) {
FREE(priv, M_NETGRAPH);
return (error);
}
(*nodep)->private = priv;
node->private = priv;
/* Done */
return (0);
@ -563,15 +557,16 @@ ng_ksocket_newhook(node_p node, hook_p hook, const char *name0)
* Receive a control message
*/
static int
ng_ksocket_rcvmsg(node_p node, struct ng_mesg *msg,
const char *raddr, struct ng_mesg **rptr, hook_p lasthook)
ng_ksocket_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
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;
int error = 0;
struct ng_mesg *msg;
NGI_GET_MSG(item, msg);
switch (msg->header.typecookie) {
case NGM_KSOCKET_COOKIE:
switch (msg->header.cmd) {
@ -723,7 +718,7 @@ ng_ksocket_rcvmsg(node_p node, struct ng_mesg *msg,
ksopt = (struct ng_ksocket_sockopt *)resp->data;
sopt.sopt_val = ksopt->value;
if ((error = sogetopt(so, &sopt)) != 0) {
FREE(resp, M_NETGRAPH);
NG_FREE_MSG(resp);
break;
}
@ -766,13 +761,9 @@ ng_ksocket_rcvmsg(node_p node, struct ng_mesg *msg,
error = EINVAL;
break;
}
if (rptr)
*rptr = resp;
else if (resp)
FREE(resp, M_NETGRAPH);
done:
FREE(msg, M_NETGRAPH);
NG_RESPOND_MSG(error, node, item, resp);
NG_FREE_MSG(msg);
return (error);
}
@ -780,16 +771,17 @@ ng_ksocket_rcvmsg(node_p node, struct ng_mesg *msg,
* Receive incoming data on our hook. Send it out the socket.
*/
static int
ng_ksocket_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
ng_ksocket_rcvdata(hook_p hook, item_p item)
{
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;
int error;
struct mbuf *m;
NG_FREE_META(meta);
NGI_GET_M(item, m);
NG_FREE_ITEM(item);
error = (*so->so_proto->pr_usrreqs->pru_sosend)(so, 0, 0, m, 0, 0, p);
return (error);
}
@ -798,7 +790,7 @@ ng_ksocket_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* Destroy node
*/
static int
ng_ksocket_rmnode(node_p node)
ng_ksocket_shutdown(node_p node)
{
const priv_p priv = node->private;
@ -813,8 +805,6 @@ ng_ksocket_rmnode(node_p node)
/* Take down netgraph node */
node->flags |= NG_INVALID;
ng_cutlinks(node);
ng_unname(node);
bzero(priv, sizeof(*priv));
FREE(priv, M_NETGRAPH);
node->private = NULL;
@ -830,7 +820,8 @@ ng_ksocket_disconnect(hook_p hook)
{
KASSERT(hook->node->numhooks == 0,
("%s: numhooks=%d?", __FUNCTION__, hook->node->numhooks));
ng_rmnode(hook->node);
if ((hook->node->flags & NG_INVALID) == 0)
ng_rmnode_self(hook->node);
return (0);
}
@ -846,7 +837,6 @@ ng_ksocket_incoming(struct socket *so, void *arg, int waitflag)
{
const node_p node = arg;
const priv_p priv = node->private;
meta_p meta = NULL;
struct mbuf *m;
struct uio auio;
int s, flags, error;
@ -876,7 +866,7 @@ ng_ksocket_incoming(struct socket *so, void *arg, int waitflag)
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);
NG_SEND_DATA_ONLY(error, priv->hook, m);
}
} while (error == 0 && m != NULL);
splx(s);

View File

@ -91,11 +91,11 @@
*/
static ng_constructor_t nglmi_constructor;
static ng_rcvmsg_t nglmi_rcvmsg;
static ng_shutdown_t nglmi_rmnode;
static ng_shutdown_t nglmi_shutdown;
static ng_newhook_t nglmi_newhook;
static ng_rcvdata_t nglmi_rcvdata;
static ng_disconnect_t nglmi_disconnect;
static int nglmi_checkdata(hook_p hook, struct mbuf *m, meta_p meta);
static int nglmi_checkdata(hook_p hook, struct mbuf *m);
static struct ng_type typestruct = {
NG_ABI_VERSION,
@ -103,7 +103,7 @@ static struct ng_type typestruct = {
NULL,
nglmi_constructor,
nglmi_rcvmsg,
nglmi_rmnode,
nglmi_shutdown,
nglmi_newhook,
NULL,
NULL,
@ -184,23 +184,17 @@ do { \
* Node constructor
*/
static int
nglmi_constructor(node_p *nodep)
nglmi_constructor(node_p node)
{
sc_p sc;
int error = 0;
MALLOC(sc, sc_p, sizeof(*sc), M_NETGRAPH, M_NOWAIT | M_ZERO);
if (sc == NULL)
return (ENOMEM);
callout_handle_init(&sc->handle);
if ((error = ng_make_node_common(&typestruct, nodep))) {
FREE(sc, M_NETGRAPH);
return (error);
}
(*nodep)->private = sc;
node->private = sc;
sc->protoname = NAME_NONE;
sc->node = *nodep;
sc->node = node;
sc->liv_per_full = NG_LMI_SEQ_PER_FULL; /* make this dynamic */
sc->liv_rate = NG_LMI_KEEPALIVE_RATE;
return (0);
@ -449,13 +443,14 @@ ngauto_state_machine(sc_p sc)
* Receive a netgraph control message.
*/
static int
nglmi_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
struct ng_mesg **rptr, hook_p lasthook)
nglmi_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
sc_p sc = node->private;
struct ng_mesg *resp = NULL;
int error = 0;
struct ng_mesg *msg;
NGI_GET_MSG(item, msg);
switch (msg->header.typecookie) {
case NGM_GENERIC_COOKIE:
switch (msg->header.cmd) {
@ -544,12 +539,8 @@ nglmi_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
break;
}
if (rptr)
*rptr = resp;
else if (resp != NULL)
FREE(resp, M_NETGRAPH);
FREE(msg, M_NETGRAPH);
NG_RESPOND_MSG(error, node, item, resp);
NG_FREE_MSG(msg);
return (error);
}
@ -564,8 +555,7 @@ nglmi_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
* Anything coming in on the debug port is discarded.
*/
static int
nglmi_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
nglmi_rcvdata(hook_p hook, item_p item)
{
sc_p sc = hook->node->private;
u_char *data;
@ -573,7 +563,10 @@ nglmi_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
u_short packetlen;
int resptype_seen = 0;
int seq_seen = 0;
struct mbuf *m;
NGI_GET_M(item, m);
NG_FREE_ITEM(item);
if (hook->private == NULL) {
goto drop;
}
@ -587,10 +580,9 @@ nglmi_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
if (m->m_len < packetlen && (m = m_pullup(m, packetlen)) == NULL) {
log(LOG_WARNING,
"nglmi: m_pullup failed for %d bytes\n", packetlen);
NG_FREE_META(meta);
return (0);
}
if (nglmi_checkdata(hook, m, meta) == 0)
if (nglmi_checkdata(hook, m) == 0)
return (0);
/* pass the first 4 bytes (already checked in the nglmi_checkdata()) */
@ -734,11 +726,11 @@ nglmi_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
nextIE:
STEPBY(segsize + 2);
}
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
return (0);
drop:
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
return (EINVAL);
}
@ -748,7 +740,7 @@ nglmi_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* All data is discarded if a 0 is returned.
*/
static int
nglmi_checkdata(hook_p hook, struct mbuf *m, meta_p meta)
nglmi_checkdata(hook_p hook, struct mbuf *m)
{
sc_p sc = hook->node->private;
u_char *data;
@ -1052,7 +1044,7 @@ nglmi_checkdata(hook_p hook, struct mbuf *m, meta_p meta)
i++;
}
}
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
return (0);
}
@ -1061,13 +1053,11 @@ nglmi_checkdata(hook_p hook, struct mbuf *m, meta_p meta)
* Cut any remaining links and free our local resources.
*/
static int
nglmi_rmnode(node_p node)
nglmi_shutdown(node_p node)
{
const sc_p sc = node->private;
node->flags |= NG_INVALID;
ng_cutlinks(node);
ng_unname(node);
node->private = NULL;
ng_unref(sc->node);
FREE(sc, M_NETGRAPH);
@ -1092,7 +1082,8 @@ nglmi_disconnect(hook_p hook)
untimeout(LMI_ticker, sc, sc->handle);
/* Self-destruct */
ng_rmnode(hook->node);
if ((hook->node->flags & NG_INVALID) == 0)
ng_rmnode_self(hook->node);
return (0);
}

View File

@ -66,6 +66,8 @@ struct ng_mesg {
char data[0]; /* placeholder for actual data */
};
/* this command is guaranteed to not alter data or'd into the command */
#define NGM_READONLY 0x10000000
/* Keep this in sync with the above structure definition */
#define NG_GENERIC_NG_MESG_INFO(dtype) { \
@ -88,12 +90,13 @@ struct ng_mesg {
* Interfaces within the kernel are defined by a different
* value (see NG_ABI_VERSION in netgraph.g)
*/
#define NG_VERSION 4
#define NG_VERSION 5
/* Flags field flags */
#define NGF_ORIG 0x0000 /* the msg is the original request */
#define NGF_RESP 0x0001 /* the message is a response */
#define NGF_ORIG 0x00000000 /* the msg is the original request */
#define NGF_RESP 0x00000001 /* the message is a response */
#define NGF_STATIC 0x00000002 /* Not malloc'd. Don't FREE */
/* Only checked in generic message */
/* Type of a unique node ID */
#define ng_ID_t unsigned int
@ -104,7 +107,7 @@ struct ng_mesg {
*/
/* Generic message type cookie */
#define NGM_GENERIC_COOKIE 851672668
#define NGM_GENERIC_COOKIE 977674408
/* Generic messages defined for this type cookie */
#define NGM_SHUTDOWN 1 /* shut down node */
@ -112,14 +115,14 @@ struct ng_mesg {
#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 */
#define NGM_NODEINFO (6|NGM_READONLY)/* get nodeinfo for target */
#define NGM_LISTHOOKS (7|NGM_READONLY)/* get list of hooks on node */
#define NGM_LISTNAMES (8|NGM_READONLY)/* list globally named nodes */
#define NGM_LISTNODES (9|NGM_READONLY)/* list nodes, named & not */
#define NGM_LISTTYPES (10|NGM_READONLY)/* list installed node types */
#define NGM_TEXT_STATUS (11|NGM_READONLY)/* (optional) get txt status */
#define NGM_BINARY2ASCII (12|NGM_READONLY)/* convert ng_mesg to ascii */
#define NGM_ASCII2BINARY (13|NGM_READONLY)/* convert ascii to ng_mesg */
#define NGM_TEXT_CONFIG 14 /* (optional) get/set text config */
/*
@ -143,13 +146,13 @@ struct ng_mesg {
/* Downstream messages */
#define NGM_DROP_LINK 41 /* drop DTR, etc. - stay in the graph */
#define NGM_RAISE LINK 42 /* if you previously dropped it */
#define NGM_FLUSH_QUEUE 43 /* no data */
#define NGM_GET_BANDWIDTH 44 /* either real or measured */
#define NGM_SET_XMIT_Q_LIMITS 45 /* includes queue state */
#define NGM_GET_XMIT_Q_LIMITS 46 /* returns queue state */
#define NGM_MICROMANAGE 47 /* We want sync. queue state reply
for each packet sent down */
#define NGM_SET_FLOW_MANAGER 48 /* send flow control here */
#define NGM_FLUSH_QUEUE 43 /* no data */
#define NGM_GET_BANDWIDTH (44|NGM_READONLY) /* either real or measured */
#define NGM_SET_XMIT_Q_LIMITS 45 /* includes queue state */
#define NGM_GET_XMIT_Q_LIMITS (46|NGM_READONLY) /* returns queue state */
#define NGM_MICROMANAGE 47 /* We want sync. queue state
reply for each packet sent */
#define NGM_SET_FLOW_MANAGER 48 /* send flow control here */
/* Structure used for NGM_MKPEER */
struct ngm_mkpeer {
char type[NG_TYPELEN + 1]; /* peer type */
@ -388,7 +391,7 @@ struct flow_manager {
#define NG_MKMESSAGE(msg, cookie, cmdid, len, how) \
do { \
MALLOC((msg), struct ng_mesg *, sizeof(struct ng_mesg) \
+ (len), M_NETGRAPH, (how) | M_ZERO); \
+ (len), M_NETGRAPH_MSG, (how) | M_ZERO); \
if ((msg) == NULL) \
break; \
(msg)->header.version = NG_VERSION; \
@ -406,7 +409,7 @@ struct flow_manager {
#define NG_MKRESPONSE(rsp, msg, len, how) \
do { \
MALLOC((rsp), struct ng_mesg *, sizeof(struct ng_mesg) \
+ (len), M_NETGRAPH, (how) | M_ZERO); \
+ (len), M_NETGRAPH_MSG, (how) | M_ZERO); \
if ((rsp) == NULL) \
break; \
(rsp)->header.version = NG_VERSION; \

View File

@ -119,14 +119,14 @@ struct ng_mppc_dir {
struct ng_mppc_private {
struct ng_mppc_dir xmit; /* compress/encrypt config */
struct ng_mppc_dir recv; /* decompress/decrypt config */
char *ctrlpath; /* path to controlling node */
ng_ID_t ctrlnode; /* path to controlling node */
};
typedef struct ng_mppc_private *priv_p;
/* Netgraph node methods */
static ng_constructor_t ng_mppc_constructor;
static ng_rcvmsg_t ng_mppc_rcvmsg;
static ng_shutdown_t ng_mppc_rmnode;
static ng_shutdown_t ng_mppc_shutdown;
static ng_newhook_t ng_mppc_newhook;
static ng_rcvdata_t ng_mppc_rcvdata;
static ng_disconnect_t ng_mppc_disconnect;
@ -148,7 +148,7 @@ static struct ng_type ng_mppc_typestruct = {
NULL,
ng_mppc_constructor,
ng_mppc_rcvmsg,
ng_mppc_rmnode,
ng_mppc_shutdown,
ng_mppc_newhook,
NULL,
NULL,
@ -171,22 +171,16 @@ static const u_char ng_mppe_weakenkey[3] = { 0xd1, 0x26, 0x9e };
* Node type constructor
*/
static int
ng_mppc_constructor(node_p *nodep)
ng_mppc_constructor(node_p node)
{
priv_p priv;
int error;
/* Allocate private structure */
MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_NOWAIT | M_ZERO);
if (priv == NULL)
return (ENOMEM);
/* Call generic node constructor */
if ((error = ng_make_node_common(&ng_mppc_typestruct, nodep))) {
FREE(priv, M_NETGRAPH);
return (error);
}
(*nodep)->private = priv;
node->private = priv;
/* Done */
return (0);
@ -222,13 +216,14 @@ ng_mppc_newhook(node_p node, hook_p hook, const char *name)
* Receive a control message
*/
static int
ng_mppc_rcvmsg(node_p node, struct ng_mesg *msg,
const char *raddr, struct ng_mesg **rptr, hook_p lasthook)
ng_mppc_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
const priv_p priv = node->private;
struct ng_mesg *resp = NULL;
int error = 0;
struct ng_mesg *msg;
NGI_GET_MSG(item, msg);
switch (msg->header.typecookie) {
case NGM_MPPC_COOKIE:
switch (msg->header.cmd) {
@ -260,17 +255,7 @@ ng_mppc_rcvmsg(node_p node, struct ng_mesg *msg,
cfg->bits = 0;
/* Save return address so we can send reset-req's */
if (priv->ctrlpath != NULL) {
FREE(priv->ctrlpath, M_NETGRAPH);
priv->ctrlpath = NULL;
}
if (!isComp && raddr != NULL) {
MALLOC(priv->ctrlpath, char *,
strlen(raddr) + 1, M_NETGRAPH, M_NOWAIT);
if (priv->ctrlpath == NULL)
ERROUT(ENOMEM);
strcpy(priv->ctrlpath, raddr);
}
priv->ctrlnode = NGI_RETADDR(item);
/* Configuration is OK, reset to it */
d->cfg = *cfg;
@ -331,13 +316,9 @@ ng_mppc_rcvmsg(node_p node, struct ng_mesg *msg,
error = EINVAL;
break;
}
if (rptr)
*rptr = resp;
else if (resp)
FREE(resp, M_NETGRAPH);
done:
FREE(msg, M_NETGRAPH);
NG_RESPOND_MSG(error, node, item, resp);
NG_FREE_MSG(msg);
return (error);
}
@ -345,38 +326,43 @@ ng_mppc_rcvmsg(node_p node, struct ng_mesg *msg,
* Receive incoming data on our hook.
*/
static int
ng_mppc_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
ng_mppc_rcvdata(hook_p hook, item_p item)
{
const node_p node = hook->node;
const priv_p priv = node->private;
struct mbuf *out;
int error;
struct mbuf *m;
NGI_GET_M(item, m);
/* Compress and/or encrypt */
if (hook == priv->xmit.hook) {
if (!priv->xmit.cfg.enable) {
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_ITEM(item);
return (ENXIO);
}
if ((error = ng_mppc_compress(node, m, &out)) != 0) {
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_ITEM(item);
return(error);
}
m_freem(m);
NG_SEND_DATA(error, priv->xmit.hook, out, meta);
NG_FREE_M(m);
NG_FWD_NEW_DATA(error, item, priv->xmit.hook, out);
return (error);
}
/* Decompress and/or decrypt */
if (hook == priv->recv.hook) {
if (!priv->recv.cfg.enable) {
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_ITEM(item);
return (ENXIO);
}
if ((error = ng_mppc_decompress(node, m, &out)) != 0) {
NG_FREE_DATA(m, meta);
if (error == EINVAL && priv->ctrlpath != NULL) {
NG_FREE_M(m);
NG_FREE_ITEM(item);
if (error == EINVAL && priv->ctrlnode != NULL) {
struct ng_mesg *msg;
/* Need to send a reset-request */
@ -384,14 +370,13 @@ ng_mppc_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
NGM_MPPC_RESETREQ, 0, M_NOWAIT);
if (msg == NULL)
return (error);
/* XXX can we use a hook instead of ctrlpath? */
ng_send_msg(node, msg, priv->ctrlpath,
NULL, NULL, NULL);
NG_SEND_MSG_ID(error, node, msg,
priv->ctrlnode, NULL);
}
return (error);
}
m_freem(m);
NG_SEND_DATA(error, priv->recv.hook, out, meta);
NG_FREE_M(m);
NG_FWD_NEW_DATA(error, item, priv->recv.hook, out);
return (error);
}
@ -403,16 +388,12 @@ ng_mppc_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* Destroy node
*/
static int
ng_mppc_rmnode(node_p node)
ng_mppc_shutdown(node_p node)
{
const priv_p priv = node->private;
/* Take down netgraph node */
node->flags |= NG_INVALID;
ng_cutlinks(node);
ng_unname(node);
if (priv->ctrlpath != NULL)
FREE(priv->ctrlpath, M_NETGRAPH);
#ifdef NETGRAPH_MPPC_COMPRESSION
if (priv->xmit.history != NULL)
FREE(priv->xmit.history, M_NETGRAPH);
@ -442,8 +423,9 @@ ng_mppc_disconnect(hook_p hook)
priv->recv.hook = NULL;
/* Go away if no longer connected */
if (node->numhooks == 0)
ng_rmnode(node);
if ((node->numhooks == 0)
&& ((node->flags & NG_INVALID) == 0))
ng_rmnode_self(node);
return (0);
}

View File

@ -80,7 +80,7 @@ typedef struct ng_one2many_private *priv_p;
/* Netgraph node methods */
static ng_constructor_t ng_one2many_constructor;
static ng_rcvmsg_t ng_one2many_rcvmsg;
static ng_shutdown_t ng_one2many_rmnode;
static ng_shutdown_t ng_one2many_shutdown;
static ng_newhook_t ng_one2many_newhook;
static ng_rcvdata_t ng_one2many_rcvdata;
static ng_disconnect_t ng_one2many_disconnect;
@ -167,7 +167,7 @@ static struct ng_type ng_one2many_typestruct = {
NULL,
ng_one2many_constructor,
ng_one2many_rcvmsg,
ng_one2many_rmnode,
ng_one2many_shutdown,
ng_one2many_newhook,
NULL,
NULL,
@ -185,10 +185,9 @@ NETGRAPH_INIT(one2many, &ng_one2many_typestruct);
* Node constructor
*/
static int
ng_one2many_constructor(node_p *nodep)
ng_one2many_constructor(node_p node)
{
priv_p priv;
int error;
/* Allocate and initialize private info */
MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_NOWAIT | M_ZERO);
@ -197,12 +196,7 @@ ng_one2many_constructor(node_p *nodep)
priv->conf.xmitAlg = NG_ONE2MANY_XMIT_ROUNDROBIN;
priv->conf.failAlg = NG_ONE2MANY_FAIL_MANUAL;
/* Call superclass constructor */
if ((error = ng_make_node_common(&ng_one2many_typestruct, nodep))) {
FREE(priv, M_NETGRAPH);
return (error);
}
(*nodep)->private = priv;
node->private = priv;
/* Done */
return (0);
@ -260,13 +254,14 @@ ng_one2many_newhook(node_p node, hook_p hook, const char *name)
* Receive a control message
*/
static int
ng_one2many_rcvmsg(node_p node, struct ng_mesg *msg,
const char *retaddr, struct ng_mesg **rptr, hook_p lasthook)
ng_one2many_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
const priv_p priv = node->private;
struct ng_mesg *resp = NULL;
int error = 0;
struct ng_mesg *msg;
NGI_GET_MSG(item, msg);
switch (msg->header.typecookie) {
case NGM_ONE2MANY_COOKIE:
switch (msg->header.cmd) {
@ -369,11 +364,8 @@ ng_one2many_rcvmsg(node_p node, struct ng_mesg *msg,
}
/* Done */
if (rptr)
*rptr = resp;
else if (resp != NULL)
FREE(resp, M_NETGRAPH);
FREE(msg, M_NETGRAPH);
NG_RESPOND_MSG(error, node, item, resp);
NG_FREE_MSG(msg);
return (error);
}
@ -381,8 +373,7 @@ ng_one2many_rcvmsg(node_p node, struct ng_mesg *msg,
* Receive data on a hook
*/
static int
ng_one2many_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
ng_one2many_rcvdata(hook_p hook, item_p item)
{
const node_p node = hook->node;
const priv_p priv = node->private;
@ -390,7 +381,9 @@ ng_one2many_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct ng_one2many_link *dst;
int error = 0;
int linkNum;
struct mbuf *m;
m = NGI_M(item); /* just peaking, mbuf still owned by item */
/* Get link number */
linkNum = LINK_NUM(hook);
KASSERT(linkNum == NG_ONE2MANY_ONE_LINKNUM
@ -409,7 +402,7 @@ ng_one2many_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
/* Figure out destination link */
if (linkNum == NG_ONE2MANY_ONE_LINKNUM) {
if (priv->numActiveMany == 0) {
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
return (ENOTCONN);
}
dst = &priv->many[priv->activeMany[priv->nextMany]];
@ -422,7 +415,7 @@ ng_one2many_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
dst->stats.xmitOctets += m->m_pkthdr.len;
/* Deliver packet */
NG_SEND_DATA(error, dst->hook, m, meta);
NG_FWD_DATA(error, item, dst->hook);
return (error);
}
@ -430,12 +423,10 @@ ng_one2many_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* Shutdown node
*/
static int
ng_one2many_rmnode(node_p node)
ng_one2many_shutdown(node_p node)
{
const priv_p priv = node->private;
ng_unname(node);
ng_cutlinks(node);
KASSERT(priv->numActiveMany == 0,
("%s: numActiveMany=%d", __FUNCTION__, priv->numActiveMany));
FREE(priv, M_NETGRAPH);
@ -469,8 +460,9 @@ ng_one2many_disconnect(hook_p hook)
}
/* If no hooks left, go away */
if (hook->node->numhooks == 0)
ng_rmnode(hook->node);
if ((hook->node->numhooks == 0)
&& ((hook->node->flags & NG_INVALID) == 0))
ng_rmnode_self(hook->node);
return (0);
}

View File

@ -207,18 +207,17 @@ typedef struct ng_ppp_private *priv_p;
/* Netgraph node methods */
static ng_constructor_t ng_ppp_constructor;
static ng_rcvmsg_t ng_ppp_rcvmsg;
static ng_shutdown_t ng_ppp_rmnode;
static ng_shutdown_t ng_ppp_shutdown;
static ng_newhook_t ng_ppp_newhook;
static ng_rcvdata_t ng_ppp_rcvdata;
static ng_disconnect_t ng_ppp_disconnect;
/* Helper functions */
static int ng_ppp_input(node_p node, int bypass,
int linkNum, struct mbuf *m, meta_p meta);
int linkNum, item_p item);
static int ng_ppp_output(node_p node, int bypass, int proto,
int linkNum, struct mbuf *m, meta_p meta);
static int ng_ppp_mp_input(node_p node, int linkNum,
struct mbuf *m, meta_p meta);
int linkNum, item_p item);
static int ng_ppp_mp_input(node_p node, int linkNum, item_p item);
static int ng_ppp_check_packet(node_p node);
static void ng_ppp_get_packet(node_p node, struct mbuf **mp, meta_p *metap);
static int ng_ppp_frag_process(node_p node);
@ -347,7 +346,7 @@ static struct ng_type ng_ppp_typestruct = {
NULL,
ng_ppp_constructor,
ng_ppp_rcvmsg,
ng_ppp_rmnode,
ng_ppp_shutdown,
ng_ppp_newhook,
NULL,
NULL,
@ -375,22 +374,17 @@ static const struct timeval ng_ppp_max_staleness = { 2, 0 }; /* 2 seconds */
* Node type constructor
*/
static int
ng_ppp_constructor(node_p *nodep)
ng_ppp_constructor(node_p node)
{
priv_p priv;
int i, error;
int i;
/* Allocate private structure */
MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_NOWAIT | M_ZERO);
if (priv == NULL)
return (ENOMEM);
/* Call generic node constructor */
if ((error = ng_make_node_common(&ng_ppp_typestruct, nodep))) {
FREE(priv, M_NETGRAPH);
return (error);
}
(*nodep)->private = priv;
node->private = priv;
/* Initialize state */
TAILQ_INIT(&priv->frags);
@ -461,13 +455,14 @@ ng_ppp_newhook(node_p node, hook_p hook, const char *name)
* Receive a control message
*/
static int
ng_ppp_rcvmsg(node_p node, struct ng_mesg *msg,
const char *raddr, struct ng_mesg **rptr, hook_p lasthook)
ng_ppp_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
const priv_p priv = node->private;
struct ng_mesg *resp = NULL;
int error = 0;
struct ng_mesg *msg;
NGI_GET_MSG(item, msg);
switch (msg->header.typecookie) {
case NGM_PPP_COOKIE:
switch (msg->header.cmd) {
@ -555,26 +550,24 @@ ng_ppp_rcvmsg(node_p node, struct ng_mesg *msg,
break;
case NGM_VJC_COOKIE:
{
char path[NG_PATHLEN + 1];
node_p origNode;
if ((error = ng_path2node(node, raddr, &origNode, NULL)) != 0)
ERROUT(error);
snprintf(path, sizeof(path), "[%lx]:%s",
(long)node->ID, NG_PPP_HOOK_VJC_IP);
return ng_send_msg(origNode, msg, path, NULL, NULL, rptr);
/*
* Forward it to the vjc node. leave the
* old return address alone.
*/
NGI_MSG(item) = msg; /* put it back in the item */
if (priv->links[HOOK_INDEX_VJC_IP].hook) {
NG_FWD_MSG_HOOK(error, NULL, item,
priv->links[HOOK_INDEX_VJC_IP].hook, NULL);
}
return (error);
}
default:
error = EINVAL;
break;
}
if (rptr)
*rptr = resp;
else if (resp)
FREE(resp, M_NETGRAPH);
done:
FREE(msg, M_NETGRAPH);
NG_RESPOND_MSG(error, node, item, resp);
NG_FREE_MSG(msg);
return (error);
}
@ -582,8 +575,7 @@ ng_ppp_rcvmsg(node_p node, struct ng_mesg *msg,
* Receive data on a hook
*/
static int
ng_ppp_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
ng_ppp_rcvdata(hook_p hook, item_p item)
{
const node_p node = hook->node;
const priv_p priv = node->private;
@ -591,7 +583,9 @@ ng_ppp_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
u_int16_t linkNum = NG_PPP_BUNDLE_LINKNUM;
hook_p outHook = NULL;
int proto = 0, error;
struct mbuf *m;
NGI_GET_M(item, m);
/* Did it come from a link hook? */
if (index < 0) {
struct ng_ppp_link *link;
@ -609,7 +603,7 @@ ng_ppp_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
/* Strip address and control fields, if present */
if (m->m_pkthdr.len >= 2) {
if (m->m_len < 2 && (m = m_pullup(m, 2)) == NULL) {
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
return (ENOBUFS);
}
if (bcmp(mtod(m, u_char *), &ng_ppp_acf, 2) == 0)
@ -617,31 +611,33 @@ ng_ppp_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
}
/* Dispatch incoming frame (if not enabled, to bypass) */
NGI_M(item) = m; /* put changed m back in item */
return ng_ppp_input(node,
!link->conf.enableLink, linkNum, m, meta);
!link->conf.enableLink, linkNum, item);
}
/* Get protocol & check if data allowed from this hook */
NGI_M(item) = m; /* put possibly changed m back in item */
switch (index) {
/* Outgoing data */
case HOOK_INDEX_ATALK:
if (!priv->conf.enableAtalk) {
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
return (ENXIO);
}
proto = PROT_APPLETALK;
break;
case HOOK_INDEX_IPX:
if (!priv->conf.enableIPX) {
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
return (ENXIO);
}
proto = PROT_IPX;
break;
case HOOK_INDEX_IPV6:
if (!priv->conf.enableIPv6) {
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
return (ENXIO);
}
proto = PROT_IPV6;
@ -649,54 +645,56 @@ ng_ppp_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
case HOOK_INDEX_INET:
case HOOK_INDEX_VJC_VJIP:
if (!priv->conf.enableIP) {
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
return (ENXIO);
}
proto = PROT_IP;
break;
case HOOK_INDEX_VJC_COMP:
if (!priv->conf.enableVJCompression) {
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
return (ENXIO);
}
proto = PROT_VJCOMP;
break;
case HOOK_INDEX_VJC_UNCOMP:
if (!priv->conf.enableVJCompression) {
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
return (ENXIO);
}
proto = PROT_VJUNCOMP;
break;
case HOOK_INDEX_COMPRESS:
if (!priv->conf.enableCompression) {
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
return (ENXIO);
}
proto = PROT_COMPD;
break;
case HOOK_INDEX_ENCRYPT:
if (!priv->conf.enableEncryption) {
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
return (ENXIO);
}
proto = PROT_CRYPTD;
break;
case HOOK_INDEX_BYPASS:
if (m->m_pkthdr.len < 4) {
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
return (EINVAL);
}
if (m->m_len < 4 && (m = m_pullup(m, 4)) == NULL) {
NG_FREE_META(meta);
NGI_M(item) = NULL; /* don't free twice */
NG_FREE_ITEM(item);
return (ENOBUFS);
}
NGI_M(item) = m; /* m may have changed */
linkNum = ntohs(mtod(m, u_int16_t *)[0]);
proto = ntohs(mtod(m, u_int16_t *)[1]);
m_adj(m, 4);
if (linkNum >= NG_PPP_MAX_LINKS
&& linkNum != NG_PPP_BUNDLE_LINKNUM) {
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
return (EINVAL);
}
break;
@ -704,19 +702,19 @@ ng_ppp_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
/* Incoming data */
case HOOK_INDEX_VJC_IP:
if (!priv->conf.enableIP || !priv->conf.enableVJDecompression) {
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
return (ENXIO);
}
break;
case HOOK_INDEX_DECOMPRESS:
if (!priv->conf.enableDecompression) {
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
return (ENXIO);
}
break;
case HOOK_INDEX_DECRYPT:
if (!priv->conf.enableDecryption) {
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
return (ENXIO);
}
break;
@ -743,9 +741,11 @@ ng_ppp_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
if (priv->conf.enableCompression
&& priv->hooks[HOOK_INDEX_COMPRESS] != NULL) {
if ((m = ng_ppp_addproto(m, proto, 1)) == NULL) {
NG_FREE_META(meta);
NGI_M(item) = NULL;
NG_FREE_ITEM(item);
return (ENOBUFS);
}
NGI_M(item) = m; /* m may have changed */
outHook = priv->hooks[HOOK_INDEX_COMPRESS];
break;
}
@ -754,24 +754,25 @@ ng_ppp_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
if (priv->conf.enableEncryption
&& priv->hooks[HOOK_INDEX_ENCRYPT] != NULL) {
if ((m = ng_ppp_addproto(m, proto, 1)) == NULL) {
NG_FREE_META(meta);
NGI_M(item) = NULL;
NG_FREE_ITEM(item);
return (ENOBUFS);
}
NGI_M(item) = m; /* m may have changed */
outHook = priv->hooks[HOOK_INDEX_ENCRYPT];
break;
}
/* FALLTHROUGH */
case HOOK_INDEX_ENCRYPT:
return ng_ppp_output(node, 0,
proto, NG_PPP_BUNDLE_LINKNUM, m, meta);
return ng_ppp_output(node, 0, proto, NG_PPP_BUNDLE_LINKNUM, item);
case HOOK_INDEX_BYPASS:
return ng_ppp_output(node, 1, proto, linkNum, m, meta);
return ng_ppp_output(node, 1, proto, linkNum, item);
/* Incoming data */
case HOOK_INDEX_DECRYPT:
case HOOK_INDEX_DECOMPRESS:
return ng_ppp_input(node, 0, NG_PPP_BUNDLE_LINKNUM, m, meta);
return ng_ppp_input(node, 0, NG_PPP_BUNDLE_LINKNUM, item);
case HOOK_INDEX_VJC_IP:
outHook = priv->hooks[HOOK_INDEX_INET];
@ -779,9 +780,13 @@ ng_ppp_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
}
/* Send packet out hook */
NG_SEND_DATA_RET(error, outHook, m, meta, resp);
if (m != NULL || meta != NULL)
return ng_ppp_rcvdata(outHook, m, meta, NULL, NULL, resp);
NG_FWD_DATA(error, item, outHook);
#if 0
/* help archie... what's going on? */
/* Looks like you were acrually USING the stub functions
(now gone again) */
return ng_ppp_rcvdata(outHook, item);
#endif
return (error);
}
@ -789,7 +794,7 @@ ng_ppp_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* Destroy node
*/
static int
ng_ppp_rmnode(node_p node)
ng_ppp_shutdown(node_p node)
{
const priv_p priv = node->private;
@ -798,8 +803,6 @@ ng_ppp_rmnode(node_p node)
/* Take down netgraph node */
node->flags |= NG_INVALID;
ng_cutlinks(node);
ng_unname(node);
ng_ppp_frag_reset(node);
bzero(priv, sizeof(*priv));
FREE(priv, M_NETGRAPH);
@ -825,10 +828,13 @@ ng_ppp_disconnect(hook_p hook)
priv->hooks[index] = NULL;
/* Update derived info (or go away if no hooks left) */
if (node->numhooks > 0)
if (node->numhooks > 0) {
ng_ppp_update(node, 0);
else
ng_rmnode(node);
} else {
if ((node->flags & NG_INVALID) == 0) {
ng_rmnode_self(node);
}
}
return (0);
}
@ -841,16 +847,19 @@ ng_ppp_disconnect(hook_p hook)
* and dispatch accordingly.
*/
static int
ng_ppp_input(node_p node, int bypass, int linkNum, struct mbuf *m, meta_p meta)
ng_ppp_input(node_p node, int bypass, int linkNum, item_p item)
{
const priv_p priv = node->private;
hook_p outHook = NULL;
int proto, error;
struct mbuf *m;
NGI_GET_M(item, m);
/* Extract protocol number */
for (proto = 0; !PROT_VALID(proto) && m->m_pkthdr.len > 0; ) {
if (m->m_len < 1 && (m = m_pullup(m, 1)) == NULL) {
NG_FREE_META(meta);
NG_FREE_ITEM(item);
return (ENOBUFS);
}
proto = (proto << 8) + *mtod(m, u_char *);
@ -861,7 +870,8 @@ ng_ppp_input(node_p node, int bypass, int linkNum, struct mbuf *m, meta_p meta)
priv->bundleStats.badProtos++;
else
priv->links[linkNum].stats.badProtos++;
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
NG_FREE_M(m);
return (EINVAL);
}
@ -890,7 +900,7 @@ ng_ppp_input(node_p node, int bypass, int linkNum, struct mbuf *m, meta_p meta)
case PROT_MP:
if (priv->conf.enableMultilink
&& linkNum != NG_PPP_BUNDLE_LINKNUM)
return ng_ppp_mp_input(node, linkNum, m, meta);
return ng_ppp_mp_input(node, linkNum, item);
break;
case PROT_APPLETALK:
if (priv->conf.enableAtalk)
@ -918,14 +928,14 @@ ng_ppp_input(node_p node, int bypass, int linkNum, struct mbuf *m, meta_p meta)
hdr[0] = htons(linkNum);
hdr[1] = htons((u_int16_t)proto);
if ((m = ng_ppp_prepend(m, &hdr, 4)) == NULL) {
NG_FREE_META(meta);
NG_FREE_ITEM(item);
return (ENOBUFS);
}
outHook = priv->hooks[HOOK_INDEX_BYPASS];
}
/* Forward frame */
NG_SEND_DATA(error, outHook, m, meta);
NG_FWD_NEW_DATA(error, item, outHook, m);
return (error);
}
@ -935,12 +945,14 @@ ng_ppp_input(node_p node, int bypass, int linkNum, struct mbuf *m, meta_p meta)
*/
static int
ng_ppp_output(node_p node, int bypass,
int proto, int linkNum, struct mbuf *m, meta_p meta)
int proto, int linkNum, item_p item)
{
const priv_p priv = node->private;
struct ng_ppp_link *link;
int len, error;
struct mbuf *m;
NGI_GET_M(item, m); /* separate them for a while */
/* If not doing MP, map bundle virtual link to (the only) link */
if (linkNum == NG_PPP_BUNDLE_LINKNUM && !priv->conf.enableMultilink)
linkNum = priv->activeLinks[0];
@ -952,11 +964,13 @@ ng_ppp_output(node_p node, int bypass,
/* Check link status (if real) */
if (linkNum != NG_PPP_BUNDLE_LINKNUM) {
if (!bypass && !link->conf.enableLink) {
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_ITEM(item);
return (ENXIO);
}
if (link->hook == NULL) {
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_ITEM(item);
return (ENETDOWN);
}
}
@ -965,25 +979,31 @@ ng_ppp_output(node_p node, int bypass,
if ((m = ng_ppp_addproto(m, proto,
linkNum == NG_PPP_BUNDLE_LINKNUM
|| link->conf.enableProtoComp)) == NULL) {
NG_FREE_META(meta);
NG_FREE_ITEM(item);
return (ENOBUFS);
}
/* Special handling for the MP virtual link */
if (linkNum == NG_PPP_BUNDLE_LINKNUM)
if (linkNum == NG_PPP_BUNDLE_LINKNUM) {
meta_p meta;
/* strip off and discard the queue item */
NGI_GET_META(item, meta);
NG_FREE_ITEM(item);
return ng_ppp_mp_output(node, m, meta);
}
/* Prepend address and control field (unless compressed) */
if (proto == PROT_LCP || !link->conf.enableACFComp) {
if ((m = ng_ppp_prepend(m, &ng_ppp_acf, 2)) == NULL) {
NG_FREE_META(meta);
NG_FREE_ITEM(item);
return (ENOBUFS);
}
}
/* Deliver frame */
len = m->m_pkthdr.len;
NG_SEND_DATA(error, link->hook, m, meta);
NG_FWD_NEW_DATA(error, item, link->hook, m);
/* Update stats and 'bytes in queue' counter */
if (error == 0) {
@ -1048,14 +1068,19 @@ ng_ppp_output(node_p node, int bypass,
* This assumes linkNum != NG_PPP_BUNDLE_LINKNUM.
*/
static int
ng_ppp_mp_input(node_p node, int linkNum, struct mbuf *m, meta_p meta)
ng_ppp_mp_input(node_p node, int linkNum, item_p item)
{
const priv_p priv = node->private;
struct ng_ppp_link *const link = &priv->links[linkNum];
struct ng_ppp_frag frag0, *frag = &frag0;
struct ng_ppp_frag *qent;
int i, diff, inserted;
struct mbuf *m;
meta_p meta;
NGI_GET_M(item, m);
NGI_GET_META(item, meta);
NG_FREE_ITEM(item);
/* Stats */
priv->bundleStats.recvFrames++;
priv->bundleStats.recvOctets += m->m_pkthdr.len;
@ -1066,7 +1091,8 @@ ng_ppp_mp_input(node_p node, int linkNum, struct mbuf *m, meta_p meta)
if (m->m_pkthdr.len < 2) {
link->stats.runts++;
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_META(meta);
return (EINVAL);
}
if (m->m_len < 2 && (m = m_pullup(m, 2)) == NULL) {
@ -1084,7 +1110,8 @@ ng_ppp_mp_input(node_p node, int linkNum, struct mbuf *m, meta_p meta)
if (m->m_pkthdr.len < 4) {
link->stats.runts++;
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_META(meta);
return (EINVAL);
}
if (m->m_len < 4 && (m = m_pullup(m, 4)) == NULL) {
@ -1106,7 +1133,8 @@ ng_ppp_mp_input(node_p node, int linkNum, struct mbuf *m, meta_p meta)
fragment as lost, so we have no choice now but to drop it */
if (diff < 0) {
link->stats.dropFragments++;
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_META(meta);
return (0);
}
@ -1123,7 +1151,8 @@ ng_ppp_mp_input(node_p node, int linkNum, struct mbuf *m, meta_p meta)
/* Allocate a new frag struct for the queue */
MALLOC(frag, struct ng_ppp_frag *, sizeof(*frag), M_NETGRAPH, M_NOWAIT);
if (frag == NULL) {
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_META(meta);
ng_ppp_frag_process(node);
return (ENOMEM);
}
@ -1139,7 +1168,8 @@ ng_ppp_mp_input(node_p node, int linkNum, struct mbuf *m, meta_p meta)
break;
} else if (diff == 0) { /* should never happen! */
link->stats.dupFragments++;
NG_FREE_DATA(frag->data, frag->meta);
NG_FREE_M(frag->data);
NG_FREE_META(frag->meta);
FREE(frag, M_NETGRAPH);
return (EINVAL);
}
@ -1265,7 +1295,8 @@ ng_ppp_frag_trim(node_p node)
("%s: empty q", __FUNCTION__));
priv->bundleStats.dropFragments++;
TAILQ_REMOVE(&priv->frags, qent, f_qent);
NG_FREE_DATA(qent->data, qent->meta);
NG_FREE_M(qent->data);
NG_FREE_META(qent->meta);
FREE(qent, M_NETGRAPH);
priv->qlen--;
removed = 1;
@ -1283,18 +1314,21 @@ ng_ppp_frag_process(node_p node)
const priv_p priv = node->private;
struct mbuf *m;
meta_p meta;
item_p item;
/* Deliver any deliverable packets */
while (ng_ppp_check_packet(node)) {
ng_ppp_get_packet(node, &m, &meta);
ng_ppp_input(node, 0, NG_PPP_BUNDLE_LINKNUM, m, meta);
item = ng_package_data(m, meta);
ng_ppp_input(node, 0, NG_PPP_BUNDLE_LINKNUM, item);
}
/* Delete dead fragments and try again */
if (ng_ppp_frag_trim(node)) {
while (ng_ppp_check_packet(node)) {
ng_ppp_get_packet(node, &m, &meta);
ng_ppp_input(node, 0, NG_PPP_BUNDLE_LINKNUM, m, meta);
item = ng_package_data(m, meta);
ng_ppp_input(node, 0, NG_PPP_BUNDLE_LINKNUM, item);
}
}
@ -1327,7 +1361,8 @@ ng_ppp_frag_process(node_p node)
/* Drop it */
priv->bundleStats.dropFragments++;
TAILQ_REMOVE(&priv->frags, qent, f_qent);
NG_FREE_DATA(qent->data, qent->meta);
NG_FREE_M(qent->data);
NG_FREE_META(qent->meta);
FREE(qent, M_NETGRAPH);
priv->qlen--;
@ -1360,6 +1395,7 @@ ng_ppp_frag_checkstale(node_p node)
struct mbuf *m;
meta_p meta;
int i, seq;
item_p item;
now.tv_sec = 0; /* uninitialized state */
while (1) {
@ -1403,7 +1439,8 @@ ng_ppp_frag_checkstale(node_p node)
("%s: empty q", __FUNCTION__));
priv->bundleStats.dropFragments++;
TAILQ_REMOVE(&priv->frags, qent, f_qent);
NG_FREE_DATA(qent->data, qent->meta);
NG_FREE_M(qent->data);
NG_FREE_META(qent->meta);
FREE(qent, M_NETGRAPH);
priv->qlen--;
}
@ -1425,7 +1462,8 @@ ng_ppp_frag_checkstale(node_p node)
}
/* Deliver packet */
ng_ppp_input(node, 0, NG_PPP_BUNDLE_LINKNUM, m, meta);
item = ng_package_data(m, meta);
ng_ppp_input(node, 0, NG_PPP_BUNDLE_LINKNUM, item);
}
}
@ -1471,10 +1509,12 @@ ng_ppp_mp_output(node_p node, struct mbuf *m, meta_p meta)
int distrib[NG_PPP_MAX_LINKS];
int firstFragment;
int activeLinkNum;
item_p item;
/* At least one link must be active */
if (priv->numActiveLinks == 0) {
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_META(meta);
return (ENETDOWN);
}
@ -1535,7 +1575,8 @@ ng_ppp_mp_output(node_p node, struct mbuf *m, meta_p meta)
struct mbuf *n = m_split(m, len, M_NOWAIT);
if (n == NULL) {
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_META(meta);
return (ENOMEM);
}
m = n;
@ -1578,11 +1619,13 @@ ng_ppp_mp_output(node_p node, struct mbuf *m, meta_p meta)
meta2 = lastFragment ? meta : ng_copy_meta(meta);
/* Send fragment */
error = ng_ppp_output(node, 0,
PROT_MP, linkNum, m2, meta2);
item = ng_package_data(m2, meta2);
error = ng_ppp_output(node, 0, PROT_MP, linkNum, item);
if (error != 0) {
if (!lastFragment)
NG_FREE_DATA(m, meta);
if (!lastFragment) {
NG_FREE_M(m);
NG_FREE_META(meta);
}
return (error);
}
}
@ -1991,7 +2034,8 @@ ng_ppp_frag_reset(node_p node)
for (qent = TAILQ_FIRST(&priv->frags); qent; qent = qnext) {
qnext = TAILQ_NEXT(qent, f_qent);
NG_FREE_DATA(qent->data, qent->meta);
NG_FREE_M(qent->data);
NG_FREE_META(qent->meta);
FREE(qent, M_NETGRAPH);
}
TAILQ_INIT(&priv->frags);

View File

@ -70,7 +70,7 @@
static ng_constructor_t ng_pppoe_constructor;
static ng_rcvmsg_t ng_pppoe_rcvmsg;
static ng_shutdown_t ng_pppoe_rmnode;
static ng_shutdown_t ng_pppoe_shutdown;
static ng_newhook_t ng_pppoe_newhook;
static ng_connect_t ng_pppoe_connect;
static ng_rcvdata_t ng_pppoe_rcvdata;
@ -153,7 +153,7 @@ static struct ng_type typestruct = {
NULL,
ng_pppoe_constructor,
ng_pppoe_rcvmsg,
ng_pppoe_rmnode,
ng_pppoe_shutdown,
ng_pppoe_newhook,
NULL,
ng_pppoe_connect,
@ -209,7 +209,7 @@ struct sess_con {
hook_p hook;
u_int16_t Session_ID;
enum state state;
char creator[NG_NODELEN + 1]; /* who to notify */
ng_ID_t creator; /* who to notify */
struct pppoe_full_hdr pkt_hdr; /* used when connected */
negp neg; /* used when negotiating */
/*struct sess_con *hash_next;*/ /* not yet used */
@ -532,10 +532,9 @@ AAA
* unref the node so it gets freed too.
*/
static int
ng_pppoe_constructor(node_p *nodep)
ng_pppoe_constructor(node_p node)
{
priv_p privdata;
int error;
AAA
/* Initialize private descriptor */
@ -544,15 +543,9 @@ AAA
if (privdata == NULL)
return (ENOMEM);
/* Call the 'generic' (ie, superclass) node constructor */
if ((error = ng_make_node_common(&typestruct, nodep))) {
FREE(privdata, M_NETGRAPH);
return (error);
}
/* Link structs together; this counts as our one reference to *nodep */
(*nodep)->private = privdata;
privdata->node = *nodep;
node->private = privdata;
privdata->node = node;
return (0);
}
@ -602,8 +595,7 @@ AAA
* Always free the message.
*/
static int
ng_pppoe_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
struct ng_mesg **rptr, hook_p lasthook)
ng_pppoe_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
priv_p privp = node->private;
struct ngpppoe_init_data *ourmsg = NULL;
@ -612,8 +604,10 @@ ng_pppoe_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
hook_p hook = NULL;
sessp sp = NULL;
negp neg = NULL;
struct ng_mesg *msg;
AAA
NGI_GET_MSG(item, msg);
/* Deal with message according to cookie and command */
switch (msg->header.typecookie) {
case NGM_PPPOE_COOKIE:
@ -704,8 +698,7 @@ AAA
neg->pkt->pkt_header.ph.sid = 0x0000;
neg->timeout = 0;
strncpy(sp->creator, retaddr, NG_NODELEN);
sp->creator[NG_NODELEN] = '\0';
sp->creator = NGI_RETADDR(item);
}
switch (msg->header.cmd) {
case NGM_PPPOE_GET_STATUS:
@ -810,14 +803,10 @@ AAA
}
/* Take care of synchronous response, if any */
if (rptr)
*rptr = resp;
else if (resp)
FREE(resp, M_NETGRAPH);
/* Free the message and return */
quit:
FREE(msg, M_NETGRAPH);
NG_RESPOND_MSG(error, node, item, resp);
/* Free the message and return */
NG_FREE_MSG(msg);
return(error);
}
@ -857,8 +846,7 @@ AAA
* if we use up this data or abort we must free BOTH of these.
*/
static int
ng_pppoe_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
ng_pppoe_rcvdata(hook_p hook, item_p item)
{
node_p node = hook->node;
const priv_p privp = node->private;
@ -876,14 +864,16 @@ ng_pppoe_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
union uniq data;
} uniqtag;
negp neg = NULL;
struct mbuf *m;
AAA
NGI_GET_M(item, m);
if (hook->private == &privp->debug_hook) {
/*
* Data from the debug hook gets sent without modification
* straight to the ethernet.
*/
NG_SEND_DATA( error, privp->ethernet_hook, m, meta);
NG_FWD_DATA( error, item, privp->ethernet_hook);
privp->packets_out++;
} else if (hook->private == &privp->ethernet_hook) {
/*
@ -901,10 +891,7 @@ AAA
}
}
wh = mtod(m, struct pppoe_full_hdr *);
ph = &wh->ph;
session = ntohs(wh->ph.sid);
length = ntohs(wh->ph.length);
code = wh->ph.code;
switch(wh->eh.ether_type) {
case ETHERTYPE_PPPOE_DISC:
/*
@ -913,8 +900,6 @@ AAA
* of a buffer and make a mess.
* (Linux wouldn't have this problem).
*/
/*XXX fix this mess */
if (m->m_pkthdr.len <= MHLEN) {
if( m->m_len < m->m_pkthdr.len) {
m = m_pullup(m, m->m_pkthdr.len);
@ -928,10 +913,29 @@ AAA
/*
* It's not all in one piece.
* We need to do extra work.
* Put it into a cluster.
*/
printf("packet fragmented\n");
LEAVE(EMSGSIZE);
struct mbuf *n;
n = m_dup(m, M_DONTWAIT);
m_freem(m);
m = n;
if (m) {
/* just check we got a cluster */
if (m->m_len != m->m_pkthdr.len) {
m_freem(m);
m = NULL;
}
}
if (m == NULL) {
printf("packet fragmented\n");
LEAVE(EMSGSIZE);
}
}
wh = mtod(m, struct pppoe_full_hdr *);
length = ntohs(wh->ph.length);
ph = &wh->ph;
session = ntohs(wh->ph.sid);
code = wh->ph.code;
switch(code) {
case PADI_CODE:
@ -951,7 +955,8 @@ AAA
sendhook = pppoe_match_svc(hook->node,
tag->tag_data, ntohs(tag->tag_len));
if (sendhook) {
NG_SEND_DATA(error, sendhook, m, meta);
NG_FWD_NEW_DATA(error, item,
sendhook, m);
} else {
printf("no such service\n");
LEAVE(ENETUNREACH);
@ -1149,7 +1154,6 @@ AAA
* Find matching peer/session combination.
*/
sendhook = pppoe_findsession(node, wh);
NG_FREE_DATA(m, meta); /* no longer needed */
if (sendhook == NULL) {
LEAVE(ENETUNREACH);
}
@ -1202,7 +1206,7 @@ AAA
break;
}
}
NG_SEND_DATA( error, sendhook, m, meta);
NG_FWD_NEW_DATA( error, item, sendhook, m);
break;
default:
LEAVE(EPFNOSUPPORT);
@ -1247,7 +1251,7 @@ AAA
}
wh = mtod(m, struct pppoe_full_hdr *);
bcopy(&sp->pkt_hdr, wh, sizeof(*wh));
NG_SEND_DATA( error, privp->ethernet_hook, m, meta);
NG_FWD_NEW_DATA( error, item, privp->ethernet_hook, m);
privp->packets_out++;
break;
}
@ -1332,7 +1336,8 @@ AAA
}
}
quit:
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
NG_FREE_M(m);
return error;
}
@ -1342,14 +1347,12 @@ AAA
* we'd only remove our links and reset ourself.
*/
static int
ng_pppoe_rmnode(node_p node)
ng_pppoe_shutdown(node_p node)
{
const priv_p privdata = node->private;
AAA
node->flags |= NG_INVALID;
ng_cutlinks(node);
ng_unname(node);
node->private = NULL;
ng_unref(privdata->node);
FREE(privdata, M_NETGRAPH);
@ -1387,7 +1390,8 @@ AAA
privp->debug_hook = NULL;
} else if (hook->private == &privp->ethernet_hook) {
privp->ethernet_hook = NULL;
ng_rmnode(node);
if ((node->flags & NG_INVALID) == 0)
ng_rmnode_self(node);
} else {
sp = hook->private;
if (sp->state != PPPOE_SNONE ) {
@ -1405,7 +1409,6 @@ AAA
struct pppoe_full_hdr *wh;
struct pppoe_tag *tag;
int msglen = strlen(SIGNOFF);
void *dummy = NULL;
int error = 0;
/* revert the stored header to DISC/PADT mode */
@ -1434,8 +1437,8 @@ AAA
m->m_pkthdr.len = (m->m_len += sizeof(*tag) +
msglen);
wh->ph.length = htons(sizeof(*tag) + msglen);
NG_SEND_DATA(error, privp->ethernet_hook, m,
dummy);
NG_SEND_DATA_ONLY(error,
privp->ethernet_hook, m);
}
}
/*
@ -1455,8 +1458,9 @@ AAA
if (privp->ethernet_hook) hooks -= 1;
if (privp->debug_hook) hooks -= 1;
}
if (node->numhooks == 0)
ng_rmnode(node);
if ((node->numhooks == 0)
&& ((node->flags & NG_INVALID) == 0))
ng_rmnode_self(node);
return (0);
}
@ -1473,7 +1477,6 @@ pppoe_ticker(void *arg)
int error = 0;
struct mbuf *m0 = NULL;
priv_p privp = hook->node->private;
meta_p dummy = NULL;
AAA
switch(sp->state) {
@ -1486,7 +1489,7 @@ AAA
case PPPOE_SREQ:
/* timeouts on these produce resends */
m0 = m_copypacket(sp->neg->m, M_DONTWAIT);
NG_SEND_DATA( error, privp->ethernet_hook, m0, dummy);
NG_SEND_DATA_ONLY( error, privp->ethernet_hook, m0);
neg->timeout_handle = timeout(pppoe_ticker,
hook, neg->timeout * hz);
if ((neg->timeout <<= 1) > PPPOE_TIMEOUT_LIMIT) {
@ -1519,7 +1522,6 @@ sendpacket(sessp sp)
hook_p hook = sp->hook;
negp neg = sp->neg;
priv_p privp = hook->node->private;
meta_p dummy = NULL;
AAA
switch(sp->state) {
@ -1533,7 +1535,7 @@ AAA
case PPPOE_NEWCONNECTED:
/* send the PADS without a timeout - we're now connected */
m0 = m_copypacket(sp->neg->m, M_DONTWAIT);
NG_SEND_DATA( error, privp->ethernet_hook, m0, dummy);
NG_SEND_DATA_ONLY( error, privp->ethernet_hook, m0);
break;
case PPPOE_PRIMED:
@ -1548,7 +1550,7 @@ AAA
* in PPPOE_OFFER_TIMEOUT seconds, forget about it.
*/
m0 = m_copypacket(sp->neg->m, M_DONTWAIT);
NG_SEND_DATA( error, privp->ethernet_hook, m0, dummy);
NG_SEND_DATA_ONLY( error, privp->ethernet_hook, m0);
neg->timeout_handle = timeout(pppoe_ticker,
hook, PPPOE_OFFER_TIMEOUT * hz);
break;
@ -1556,7 +1558,7 @@ AAA
case PPPOE_SINIT:
case PPPOE_SREQ:
m0 = m_copypacket(sp->neg->m, M_DONTWAIT);
NG_SEND_DATA( error, privp->ethernet_hook, m0, dummy);
NG_SEND_DATA_ONLY( error, privp->ethernet_hook, m0);
neg->timeout_handle = timeout(pppoe_ticker, hook,
(hz * PPPOE_INITIAL_TIMEOUT));
neg->timeout = PPPOE_INITIAL_TIMEOUT * 2;
@ -1627,6 +1629,6 @@ AAA
return (ENOMEM);
sts = (struct ngpppoe_sts *)msg->data;
strncpy(sts->hook, sp->hook->name, NG_HOOKLEN + 1);
error = ng_send_msg(sp->hook->node, msg, sp->creator, NULL, NULL, NULL);
NG_SEND_MSG_ID(error, sp->hook->node, msg, sp->creator, NULL);
return (error);
}

View File

@ -172,14 +172,14 @@ typedef struct ng_pptpgre_private *priv_p;
/* Netgraph node methods */
static ng_constructor_t ng_pptpgre_constructor;
static ng_rcvmsg_t ng_pptpgre_rcvmsg;
static ng_shutdown_t ng_pptpgre_rmnode;
static ng_shutdown_t ng_pptpgre_shutdown;
static ng_newhook_t ng_pptpgre_newhook;
static ng_rcvdata_t ng_pptpgre_rcvdata;
static ng_disconnect_t ng_pptpgre_disconnect;
/* Helper functions */
static int ng_pptpgre_xmit(node_p node, struct mbuf *m, meta_p meta);
static int ng_pptpgre_recv(node_p node, struct mbuf *m, meta_p meta);
static int ng_pptpgre_xmit(node_p node, item_p item);
static int ng_pptpgre_recv(node_p node, item_p item);
static void ng_pptpgre_start_send_ack_timer(node_p node, int ackTimeout);
static void ng_pptpgre_start_recv_ack_timer(node_p node);
static void ng_pptpgre_recv_ack_timeout(void *arg);
@ -250,7 +250,7 @@ static struct ng_type ng_pptpgre_typestruct = {
NULL,
ng_pptpgre_constructor,
ng_pptpgre_rcvmsg,
ng_pptpgre_rmnode,
ng_pptpgre_shutdown,
ng_pptpgre_newhook,
NULL,
NULL,
@ -270,22 +270,16 @@ NETGRAPH_INIT(pptpgre, &ng_pptpgre_typestruct);
* Node type constructor
*/
static int
ng_pptpgre_constructor(node_p *nodep)
ng_pptpgre_constructor(node_p node)
{
priv_p priv;
int error;
/* Allocate private structure */
MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_NOWAIT | M_ZERO);
if (priv == NULL)
return (ENOMEM);
/* Call generic node constructor */
if ((error = ng_make_node_common(&ng_pptpgre_typestruct, nodep))) {
FREE(priv, M_NETGRAPH);
return (error);
}
(*nodep)->private = priv;
node->private = priv;
/* Initialize state */
callout_handle_init(&priv->ackp.sackTimer);
@ -325,13 +319,14 @@ ng_pptpgre_newhook(node_p node, hook_p hook, const char *name)
* Receive a control message.
*/
static int
ng_pptpgre_rcvmsg(node_p node, struct ng_mesg *msg,
const char *raddr, struct ng_mesg **rptr, hook_p lasthook)
ng_pptpgre_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
const priv_p priv = node->private;
struct ng_mesg *resp = NULL;
int error = 0;
struct ng_mesg *msg;
NGI_GET_MSG(item, msg);
switch (msg->header.typecookie) {
case NGM_PPTPGRE_COOKIE:
switch (msg->header.cmd) {
@ -379,12 +374,8 @@ ng_pptpgre_rcvmsg(node_p node, struct ng_mesg *msg,
break;
}
done:
if (rptr)
*rptr = resp;
else if (resp)
FREE(resp, M_NETGRAPH);
FREE(msg, M_NETGRAPH);
NG_RESPOND_MSG(error, node, item, resp);
NG_FREE_MSG(msg);
return (error);
}
@ -392,23 +383,22 @@ ng_pptpgre_rcvmsg(node_p node, struct ng_mesg *msg,
* Receive incoming data on a hook.
*/
static int
ng_pptpgre_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
ng_pptpgre_rcvdata(hook_p hook, item_p item)
{
const node_p node = hook->node;
const priv_p priv = node->private;
/* If not configured, reject */
if (!priv->conf.enabled) {
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
return (ENXIO);
}
/* Treat as xmit or recv data */
if (hook == priv->upper)
return ng_pptpgre_xmit(node, m, meta);
return ng_pptpgre_xmit(node, item);
if (hook == priv->lower)
return ng_pptpgre_recv(node, m, meta);
return ng_pptpgre_recv(node, item);
panic("%s: weird hook", __FUNCTION__);
}
@ -416,7 +406,7 @@ ng_pptpgre_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* Destroy node
*/
static int
ng_pptpgre_rmnode(node_p node)
ng_pptpgre_shutdown(node_p node)
{
const priv_p priv = node->private;
@ -425,8 +415,6 @@ ng_pptpgre_rmnode(node_p node)
/* Take down netgraph node */
node->flags |= NG_INVALID;
ng_cutlinks(node);
ng_unname(node);
bzero(priv, sizeof(*priv));
FREE(priv, M_NETGRAPH);
node->private = NULL;
@ -452,8 +440,9 @@ ng_pptpgre_disconnect(hook_p hook)
panic("%s: unknown hook", __FUNCTION__);
/* Go away if no longer connected to anything */
if (node->numhooks == 0)
ng_rmnode(node);
if ((node->numhooks == 0)
&& ((node->flags & NG_INVALID) == 0))
ng_rmnode_self(node);
return (0);
}
@ -465,14 +454,20 @@ ng_pptpgre_disconnect(hook_p hook)
* Transmit an outgoing frame, or just an ack if m is NULL.
*/
static int
ng_pptpgre_xmit(node_p node, struct mbuf *m, meta_p meta)
ng_pptpgre_xmit(node_p node, item_p item)
{
const priv_p priv = node->private;
struct ng_pptpgre_ackp *const a = &priv->ackp;
u_char buf[sizeof(struct greheader) + 2 * sizeof(u_int32_t)];
struct greheader *const gre = (struct greheader *)buf;
int grelen, error;
struct mbuf *m;
if (item) {
NGI_GET_M(item, m);
} else {
m = NULL;
}
/* Check if there's data */
if (m != NULL) {
@ -480,18 +475,21 @@ ng_pptpgre_xmit(node_p node, struct mbuf *m, meta_p meta)
if ((u_int32_t)PPTP_SEQ_DIFF(priv->xmitSeq, priv->recvAck)
>= a->xmitWin) {
priv->stats.xmitDrops++;
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_ITEM(item);
return (ENOBUFS);
}
/* Sanity check frame length */
if (m != NULL && m->m_pkthdr.len > PPTP_MAX_PAYLOAD) {
priv->stats.xmitTooBig++;
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_ITEM(item);
return (EMSGSIZE);
}
} else
} else {
priv->stats.xmitLoneAcks++;
}
/* Build GRE header */
((u_int32_t *)gre)[0] = htonl(PPTP_INIT_VALUE);
@ -521,7 +519,8 @@ ng_pptpgre_xmit(node_p node, struct mbuf *m, meta_p meta)
MGETHDR(m, M_DONTWAIT, MT_DATA);
if (m == NULL) {
priv->stats.memoryFailures++;
NG_FREE_META(meta);
if (item)
NG_FREE_ITEM(item);
return (ENOBUFS);
}
m->m_len = m->m_pkthdr.len = grelen;
@ -531,7 +530,8 @@ ng_pptpgre_xmit(node_p node, struct mbuf *m, meta_p meta)
if (m == NULL || (m->m_len < grelen
&& (m = m_pullup(m, grelen)) == NULL)) {
priv->stats.memoryFailures++;
NG_FREE_META(meta);
if (item)
NG_FREE_ITEM(item);
return (ENOBUFS);
}
}
@ -542,7 +542,12 @@ ng_pptpgre_xmit(node_p node, struct mbuf *m, meta_p meta)
priv->stats.xmitOctets += m->m_pkthdr.len;
/* Deliver packet */
NG_SEND_DATA(error, priv->lower, m, meta);
if (item) {
NG_FWD_NEW_DATA(error, item, priv->lower, m);
} else {
NG_SEND_DATA_ONLY(error, priv->lower, m);
}
/* Start receive ACK timer if data was sent and not already running */
if (error == 0 && gre->hasSeq && priv->xmitSeq == priv->recvAck + 1)
@ -554,14 +559,16 @@ ng_pptpgre_xmit(node_p node, struct mbuf *m, meta_p meta)
* Handle an incoming packet. The packet includes the IP header.
*/
static int
ng_pptpgre_recv(node_p node, struct mbuf *m, meta_p meta)
ng_pptpgre_recv(node_p node, item_p item)
{
const priv_p priv = node->private;
int iphlen, grelen, extralen;
struct greheader *gre;
struct ip *ip;
int error = 0;
struct mbuf *m;
NGI_GET_M(item, m);
/* Update stats */
priv->stats.recvPackets++;
priv->stats.recvOctets += m->m_pkthdr.len;
@ -570,7 +577,8 @@ ng_pptpgre_recv(node_p node, struct mbuf *m, meta_p meta)
if (m->m_pkthdr.len < sizeof(*ip) + sizeof(*gre)) {
priv->stats.recvRunts++;
bad:
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_ITEM(item);
return (EINVAL);
}
@ -578,7 +586,7 @@ ng_pptpgre_recv(node_p node, struct mbuf *m, meta_p meta)
if (m->m_len < sizeof(*ip) + sizeof(*gre)
&& (m = m_pullup(m, sizeof(*ip) + sizeof(*gre))) == NULL) {
priv->stats.memoryFailures++;
NG_FREE_META(meta);
NG_FREE_ITEM(item);
return (ENOBUFS);
}
ip = mtod(m, struct ip *);
@ -586,7 +594,7 @@ ng_pptpgre_recv(node_p node, struct mbuf *m, meta_p meta)
if (m->m_len < iphlen + sizeof(*gre)) {
if ((m = m_pullup(m, iphlen + sizeof(*gre))) == NULL) {
priv->stats.memoryFailures++;
NG_FREE_META(meta);
NG_FREE_ITEM(item);
return (ENOBUFS);
}
ip = mtod(m, struct ip *);
@ -600,7 +608,7 @@ ng_pptpgre_recv(node_p node, struct mbuf *m, meta_p meta)
if (m->m_len < iphlen + grelen) {
if ((m = m_pullup(m, iphlen + grelen)) == NULL) {
priv->stats.memoryFailures++;
NG_FREE_META(meta);
NG_FREE_ITEM(item);
return (ENOBUFS);
}
ip = mtod(m, struct ip *);
@ -695,7 +703,7 @@ ng_pptpgre_recv(node_p node, struct mbuf *m, meta_p meta)
/* If delayed ACK is disabled, send it now */
if (!priv->conf.enableDelayedAck
|| maxWait < PPTP_MIN_ACK_DELAY)
ng_pptpgre_xmit(node, NULL, NULL);
ng_pptpgre_xmit(node, NULL);
else { /* send the ack later */
if (maxWait > PPTP_MAX_ACK_DELAY)
maxWait = PPTP_MAX_ACK_DELAY;
@ -709,10 +717,11 @@ ng_pptpgre_recv(node_p node, struct mbuf *m, meta_p meta)
m_adj(m, -extralen);
/* Deliver frame to upper layers */
NG_SEND_DATA(error, priv->upper, m, meta);
NG_FWD_NEW_DATA(error, item, priv->upper, m);
} else {
priv->stats.recvLoneAcks++;
NG_FREE_DATA(m, meta); /* no data to deliver */
NG_FREE_ITEM(item);
NG_FREE_M(m); /* no data to deliver */
}
return (error);
}
@ -868,7 +877,7 @@ ng_pptpgre_send_ack_timeout(void *arg)
a->sackTimerPtr = NULL;
/* Send a frame with an ack but no payload */
ng_pptpgre_xmit(node, NULL, NULL);
ng_pptpgre_xmit(node, NULL);
splx(s);
}

View File

@ -89,7 +89,7 @@ typedef struct ng_rfc1490_private *priv_p;
/* Netgraph node methods */
static ng_constructor_t ng_rfc1490_constructor;
static ng_rcvmsg_t ng_rfc1490_rcvmsg;
static ng_shutdown_t ng_rfc1490_rmnode;
static ng_shutdown_t ng_rfc1490_shutdown;
static ng_newhook_t ng_rfc1490_newhook;
static ng_rcvdata_t ng_rfc1490_rcvdata;
static ng_disconnect_t ng_rfc1490_disconnect;
@ -101,7 +101,7 @@ static struct ng_type typestruct = {
NULL,
ng_rfc1490_constructor,
ng_rfc1490_rcvmsg,
ng_rfc1490_rmnode,
ng_rfc1490_shutdown,
ng_rfc1490_newhook,
NULL,
NULL,
@ -119,22 +119,16 @@ NETGRAPH_INIT(rfc1490, &typestruct);
* Node constructor
*/
static int
ng_rfc1490_constructor(node_p *nodep)
ng_rfc1490_constructor(node_p node)
{
priv_p priv;
int error;
/* Allocate private structure */
MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_NOWAIT | M_ZERO);
if (priv == NULL)
return (ENOMEM);
/* Call generic node constructor */
if ((error = ng_make_node_common(&typestruct, nodep))) {
FREE(priv, M_NETGRAPH);
return (error);
}
(*nodep)->private = priv;
node->private = priv;
/* Done */
return (0);
@ -169,10 +163,9 @@ ng_rfc1490_newhook(node_p node, hook_p hook, const char *name)
* Receive a control message. We don't support any special ones.
*/
static int
ng_rfc1490_rcvmsg(node_p node, struct ng_mesg *msg,
const char *raddr, struct ng_mesg **rp, hook_p lasthook)
ng_rfc1490_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
FREE(msg, M_NETGRAPH);
NG_FREE_ITEM(item);
return (EINVAL);
}
@ -213,13 +206,14 @@ ng_rfc1490_rcvmsg(node_p node, struct ng_mesg *msg,
#define OUICMP(P,A,B,C) ((P)[0]==(A) && (P)[1]==(B) && (P)[2]==(C))
static int
ng_rfc1490_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
ng_rfc1490_rcvdata(hook_p hook, item_p item)
{
const node_p node = hook->node;
const priv_p priv = node->private;
int error = 0;
struct mbuf *m;
NGI_GET_M(item, m);
if (hook == priv->downlink) {
u_char *start, *ptr;
@ -248,8 +242,8 @@ ng_rfc1490_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
m_adj(m, ptr - start);
switch (etype) {
case ETHERTYPE_IP:
NG_SEND_DATA(error,
priv->inet, m, meta);
NG_FWD_NEW_DATA(error, item,
priv->inet, m);
break;
case ETHERTYPE_ARP:
case ETHERTYPE_REVARP:
@ -263,11 +257,11 @@ ng_rfc1490_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
break;
case NLPID_IP:
m_adj(m, ptr - start);
NG_SEND_DATA(error, priv->inet, m, meta);
NG_FWD_NEW_DATA(error, item, priv->inet, m);
break;
case NLPID_PPP:
m_adj(m, ptr - start);
NG_SEND_DATA(error, priv->ppp, m, meta);
NG_FWD_NEW_DATA(error, item, priv->ppp, m);
break;
case NLPID_Q933:
case NLPID_CLNP:
@ -279,7 +273,7 @@ ng_rfc1490_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
if ((*ptr & 0x01) == 0x01)
ERROUT(0);
m_adj(m, ptr - start);
NG_SEND_DATA(error, priv->ppp, m, meta);
NG_FWD_NEW_DATA(error, item, priv->ppp, m);
break;
}
} else if (hook == priv->ppp) {
@ -288,19 +282,21 @@ ng_rfc1490_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
ERROUT(ENOBUFS);
mtod(m, u_char *)[0] = HDLC_UI;
mtod(m, u_char *)[1] = NLPID_PPP;
NG_SEND_DATA(error, priv->downlink, m, meta);
NG_FWD_NEW_DATA(error, item, priv->downlink, m);
} else if (hook == priv->inet) {
M_PREPEND(m, 2, M_DONTWAIT); /* Prepend IP NLPID */
if (!m)
ERROUT(ENOBUFS);
mtod(m, u_char *)[0] = HDLC_UI;
mtod(m, u_char *)[1] = NLPID_IP;
NG_SEND_DATA(error, priv->downlink, m, meta);
NG_FWD_NEW_DATA(error, item, priv->downlink, m);
} else
panic(__FUNCTION__);
done:
NG_FREE_DATA(m, meta);
if (item)
NG_FREE_ITEM(item);
NG_FREE_M(m);
return (error);
}
@ -308,14 +304,12 @@ ng_rfc1490_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* Nuke node
*/
static int
ng_rfc1490_rmnode(node_p node)
ng_rfc1490_shutdown(node_p node)
{
const priv_p priv = node->private;
/* Take down netgraph node */
node->flags |= NG_INVALID;
ng_cutlinks(node);
ng_unname(node);
bzero(priv, sizeof(*priv));
node->private = NULL;
ng_unref(node); /* let the node escape */
@ -330,8 +324,9 @@ ng_rfc1490_disconnect(hook_p hook)
{
const priv_p priv = hook->node->private;
if (hook->node->numhooks == 0)
ng_rmnode(hook->node);
if ((hook->node->numhooks == 0)
&& ((hook->node->flags & NG_INVALID) == 0))
ng_rmnode_self(hook->node);
else if (hook == priv->downlink)
priv->downlink = NULL;
else if (hook == priv->inet)

View File

@ -61,7 +61,7 @@
static ng_constructor_t ng_xxx_constructor;
static ng_rcvmsg_t ng_xxx_rcvmsg;
static ng_shutdown_t ng_xxx_rmnode;
static ng_shutdown_t ng_xxx_shutdown;
static ng_newhook_t ng_xxx_newhook;
static ng_connect_t ng_xxx_connect;
static ng_rcvdata_t ng_xxx_rcvdata; /* note these are both ng_rcvdata_t */
@ -101,7 +101,7 @@ static struct ng_type typestruct = {
NULL,
ng_xxx_constructor,
ng_xxx_rcvmsg,
ng_xxx_rmnode,
ng_xxx_shutdown,
ng_xxx_newhook,
NULL,
ng_xxx_connect,
@ -131,20 +131,16 @@ struct XXX {
typedef struct XXX *xxx_p;
/*
* Allocate the private data structure and the generic node
* and link them together.
*
* ng_make_node_common() returns with a generic node struct
* with a single reference for us.. we transfer it to the
* private structure.. when we free the private struct we must
* unref the node so it gets freed too.
* Allocate the private data structure. The generic node has already
* been created. Link them together. We arrive with a reference to the node
* i.e. the reference count is incremented for us already.
*
* If this were a device node than this work would be done in the attach()
* routine and the constructor would return EINVAL as you should not be able
* to creatednodes that depend on hardware (unless you can add the hardware :)
*/
static int
ng_xxx_constructor(node_p *nodep)
ng_xxx_constructor(node_p nodep)
{
xxx_p privdata;
int i, error;
@ -159,12 +155,6 @@ ng_xxx_constructor(node_p *nodep)
privdata->channel[i].channel = i;
}
/* Call the 'generic' (ie, superclass) node constructor */
if ((error = ng_make_node_common(&typestruct, nodep))) {
FREE(privdata, M_NETGRAPH);
return (error);
}
/* Link structs together; this counts as our one reference to *nodep */
(*nodep)->private = privdata;
privdata->node = *nodep;
@ -245,6 +235,11 @@ ng_xxx_newhook(node_p node, hook_p hook, const char *name)
/*
* Get a netgraph control message.
* We actually recieve a queue item that has a pointer to the message.
* If we free the item, the message will be freed too, unless we remove
* it from the item using NGI_GET_MSG();
* The return address is also stored in the item, as an ng_ID_t,
* accessible as NGI_RETADDR(item);
* Check it is one we understand. If needed, send a response.
* We could save the address for an async action later, but don't here.
* Always free the message.
@ -255,13 +250,14 @@ ng_xxx_newhook(node_p node, hook_p hook, const char *name)
* (so that old userland programs could continue to work).
*/
static int
ng_xxx_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
struct ng_mesg **rptr, hook_p lasthook)
ng_xxx_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
const xxx_p xxxp = node->private;
struct ng_mesg *resp = NULL;
int error = 0;
struct ng_mesg *msg;
NGI_GET_MSG(item, msg);
/* Deal with message according to cookie and command */
switch (msg->header.typecookie) {
case NGM_XXX_COOKIE:
@ -298,18 +294,17 @@ ng_xxx_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
}
/* Take care of synchronous response, if any */
if (rptr)
*rptr = resp;
else if (resp)
FREE(resp, M_NETGRAPH);
NG_RESPOND_MSG(error, node, item, resp);
/* Free the message and return */
FREE(msg, M_NETGRAPH);
NG_FREE_MSG(msg);
return(error);
}
/*
* Receive data, and do something with it.
* Actually we receive a queue item which holds the data.
* If we free the item it wil also froo the data and metadata unless
* we have previously disassociated them using the NGI_GET_xxx() macros.
* Possibly send it out on another link after processing.
* Possibly do something different if it comes from different
* hooks. the caller will never free m or meta, so
@ -321,14 +316,17 @@ ng_xxx_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
* in the connect() method.
*/
static int
ng_xxx_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
ng_xxx_rcvdata(hook_p hook, item_p item )
{
const xxx_p xxxp = hook->node->private;
int chan = -2;
int dlci = -2;
int error;
struct mbuf *m;
meta_p meta;
NGI_GET_M(item, m);
if (hook->private) {
dlci = ((struct XXX_hookinfo *) hook->private)->dlci;
chan = ((struct XXX_hookinfo *) hook->private)->channel;
@ -339,8 +337,8 @@ ng_xxx_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* the front here */
/* M_PREPEND(....) ; */
/* mtod(m, xxxxxx)->dlci = dlci; */
NG_SEND_DATA(error, xxxp->downstream_hook.hook,
m, meta);
NG_FWD_NEW_DATA(error, item,
xxxp->downstream_hook.hook, m);
xxxp->packets_out++;
} else {
/* data came from the multiplexed link */
@ -350,7 +348,8 @@ ng_xxx_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
if (xxxp->channel[chan].dlci == dlci)
break;
if (chan == XXX_NUM_DLCIS) {
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
NG_FREE_M(m);
return (ENETUNREACH);
}
/* If we were called at splnet, use the following:
@ -364,13 +363,15 @@ ng_xxx_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* the processing of the data can continue. after
* these are run 'm' and 'meta' should be considered
* as invalid and NG_SEND_DATA actually zaps them. */
NG_SEND_DATA(error, xxxp->channel[chan].hook, m, meta);
NG_FWD_NEW_DATA(error, item,
xxxp->channel[chan].hook, m);
xxxp->packets_in++;
}
} else {
/* It's the debug hook, throw it away.. */
if (hook == xxxp->downstream_hook.hook)
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
NG_FREE_M(m);
}
return 0;
}
@ -398,24 +399,46 @@ devintr()
/*
* Do local shutdown processing..
* All our links and the name have already been removed.
* If we are a persistant device, we might refuse to go away, and
* we'd only remove our links and reset ourself.
* we'd create a new node immediatly.
*/
static int
ng_xxx_rmnode(node_p node)
ng_xxx_shutdown(node_p node)
{
const xxx_p privdata = node->private;
int error;
node->flags |= NG_INVALID;
ng_cutlinks(node);
#ifndef PERSISTANT_NODE
ng_unname(node);
node->private = NULL;
ng_unref(privdata->node);
#ifndef PERSISTANT_NODE
FREE(privdata, M_NETGRAPH);
#else
/*
* Create a new node. This is basically what a device
* driver would do in the attach routine.
*/
error = ng_make_node_common(&typestruct, &node);
if (node == NULL) {
printf ("node recreation failed:");
return (error);
}
if ( ng_name_node(node, "name")) { /* whatever name is needed */
printf("something informative");
ng_unref(node); /* drop it again */
return (0);
}
privdata->packets_in = 0; /* reset stats */
privdata->packets_out = 0;
for (i = 0; i < XXX_NUM_DLCIS; i++) {
privdata->channel[i].dlci = -2;
privdata->channel[i].channel = i;
}
/* Link structs together; this counts as our one reference to node */
privdata->node = node;
node->private = privdata;
node->flags &= ~NG_INVALID; /* reset invalid flag */
#endif /* PERSISTANT_NODE */
return (0);
@ -470,8 +493,9 @@ ng_xxx_disconnect(hook_p hook)
{
if (hook->private)
((struct XXX_hookinfo *) (hook->private))->hook = NULL;
if (hook->node->numhooks == 0)
ng_rmnode(hook->node);
if ((hook->node->numhooks == 0)
&& ((hook->node->flags & NG_INVALID) == 0)) /* already shutting down? */
ng_rmnode_self(hook->node);
return (0);
}

View File

@ -98,7 +98,7 @@
/* Netgraph node methods */
static ng_constructor_t ngs_constructor;
static ng_rcvmsg_t ngs_rcvmsg;
static ng_shutdown_t ngs_rmnode;
static ng_shutdown_t ngs_shutdown;
static ng_newhook_t ngs_newhook;
static ng_rcvdata_t ngs_rcvdata;
static ng_disconnect_t ngs_disconnect;
@ -111,7 +111,6 @@ static void ng_detach_common(struct ngpcb *pcbp, int type);
/*static int ng_internalize(struct mbuf *m, struct proc *p); */
static int ng_connect_data(struct sockaddr *nam, struct ngpcb *pcbp);
static int ng_connect_cntl(struct sockaddr *nam, struct ngpcb *pcbp);
static int ng_bind(struct sockaddr *nam, struct ngpcb *pcbp);
static int ngs_mod_event(module_t mod, int event, void *data);
@ -125,7 +124,7 @@ static struct ng_type typestruct = {
ngs_mod_event,
ngs_constructor,
ngs_rcvmsg,
ngs_rmnode,
ngs_shutdown,
ngs_newhook,
NULL,
NULL,
@ -182,9 +181,9 @@ ngc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
{
struct ngpcb *const pcbp = sotongpcb(so);
struct sockaddr_ng *const sap = (struct sockaddr_ng *) addr;
struct ng_mesg *resp;
struct ng_mesg *msg;
struct mbuf *m0;
char *msg, *path = NULL;
char *path = NULL;
int len, error = 0;
if (pcbp == NULL) {
@ -229,21 +228,15 @@ ngc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
/* Move the data into a linear buffer as well. Messages are not
* delivered in mbufs. */
MALLOC(msg, char *, len + 1, M_NETGRAPH, M_WAITOK);
MALLOC(msg, struct ng_mesg *, len + 1, M_NETGRAPH_MSG, M_WAITOK);
if (msg == NULL) {
error = ENOMEM;
goto release;
}
m_copydata(m, 0, len, msg);
m_copydata(m, 0, len, (char *)msg);
/* The callee will free the msg when done. The addr is our business. */
error = ng_send_msg(pcbp->sockdata->node,
(struct ng_mesg *) msg, path, NULL, NULL, &resp);
/* If the callee responded with a synchronous response, then put it
* back on the receive side of the socket; sap is source address. */
if (error == 0 && resp != NULL)
error = ship_msg(pcbp, resp, sap);
/* The callee will free the msg when done. The path is our business. */
NG_SEND_MSG_PATH(error, pcbp->sockdata->node, msg, path, NULL);
release:
if (path != NULL)
@ -268,11 +261,11 @@ ngc_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
static int
ngc_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
{
struct ngpcb *const pcbp = sotongpcb(so);
if (pcbp == 0)
return (EINVAL);
return (ng_connect_cntl(nam, pcbp));
/*
* At this time refuse to do this.. it used to
* do something but it was undocumented and not used.
*/
return (EINVAL);
}
/***************************************************************
@ -517,7 +510,7 @@ ng_detach_common(struct ngpcb *pcbp, int which)
panic(__FUNCTION__);
}
if ((--sockdata->refs == 0) && (sockdata->node != NULL))
ng_rmnode(sockdata->node);
ng_rmnode_self(sockdata->node);
}
pcbp->ng_socket->so_pcb = NULL;
pcbp->ng_socket = NULL;
@ -598,61 +591,53 @@ ng_connect_data(struct sockaddr *nam, struct ngpcb *pcbp)
node_p farnode;
struct ngsock *sockdata;
int error;
item_p item;
/* If we are already connected, don't do it again */
if (pcbp->sockdata != NULL)
return (EISCONN);
/* Find the target (victim) and check it doesn't already have a data
* socket. Also check it is a 'socket' type node. */
* socket. Also check it is a 'socket' type node.
* Use ng_package_data() and address_path() to do this.
*/
sap = (struct sockaddr_ng *) nam;
if ((error = ng_path2node(NULL, sap->sg_data, &farnode, NULL)))
return (error);
/* The item will hold the node reference */
item = ng_package_data(NULL, NULL);
if (item == NULL) {
return (ENOMEM);
}
if ((error = ng_address_path(NULL, item, sap->sg_data, NULL)))
return (error); /* item is freed on failure */
if (strcmp(farnode->type->name, NG_SOCKET_NODE_TYPE) != 0)
/*
* Extract node from item and free item. Remember we now have
* a reference on the node. The item holds it for us.
* when we free the item we release the reference.
*/
farnode = item->el_dest; /* shortcut */
if (strcmp(farnode->type->name, NG_SOCKET_NODE_TYPE) != 0) {
NG_FREE_ITEM(item); /* drop the reference to the node */
return (EINVAL);
}
sockdata = farnode->private;
if (sockdata->datasock != NULL)
if (sockdata->datasock != NULL) {
NG_FREE_ITEM(item); /* drop the reference to the node */
return (EADDRINUSE);
}
/* Link the PCB and the private data struct. and note the extra
* reference */
/*
* Link the PCB and the private data struct. and note the extra
* reference. Drop the extra reference on the node.
*/
sockdata->datasock = pcbp;
pcbp->sockdata = sockdata;
sockdata->refs++;
sockdata->refs++; /* XXX possible race if it's being freed */
NG_FREE_ITEM(item); /* drop the reference to the node */
return (0);
}
/*
* Connect the existing control socket node to a named node:hook.
* The hook we use on this end is the same name as the remote node name.
*/
static int
ng_connect_cntl(struct sockaddr *nam, struct ngpcb *pcbp)
{
struct ngsock *const sockdata = pcbp->sockdata;
struct sockaddr_ng *sap;
char *node, *hook;
node_p farnode;
int rtn, error;
sap = (struct sockaddr_ng *) nam;
rtn = ng_path_parse(sap->sg_data, &node, NULL, &hook);
if (rtn < 0 || node == NULL || hook == NULL) {
TRAP_ERROR;
return (EINVAL);
}
farnode = ng_findname(sockdata->node, node);
if (farnode == NULL) {
TRAP_ERROR;
return (EADDRNOTAVAIL);
}
/* Connect, using a hook name the same as the far node name. */
error = ng_con_nodes(sockdata->node, node, farnode, hook);
return error;
}
/*
* Binding a socket means giving the corresponding node a name
*/
@ -693,7 +678,7 @@ ship_msg(struct ngpcb *pcbp, struct ng_mesg *msg, struct sockaddr_ng *addr)
/* Here we free the message, as we are the end of the line.
* We need to do that regardless of whether we got mbufs. */
FREE(msg, M_NETGRAPH);
NG_FREE_MSG(msg);
if (mdata == NULL) {
TRAP_ERROR;
@ -715,7 +700,7 @@ ship_msg(struct ngpcb *pcbp, struct ng_mesg *msg, struct sockaddr_ng *addr)
* You can only create new nodes from the socket end of things.
*/
static int
ngs_constructor(node_p *nodep)
ngs_constructor(node_p nodep)
{
return (EINVAL);
}
@ -736,14 +721,19 @@ ngs_newhook(node_p node, hook_p hook, const char *name)
* Unless they are for us specifically (socket_type)
*/
static int
ngs_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
struct ng_mesg **resp, hook_p lasthook)
ngs_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
struct ngsock *const sockdata = node->private;
struct ngpcb *const pcbp = sockdata->ctlsock;
struct sockaddr_ng *addr;
int addrlen;
int error = 0;
struct ng_mesg *msg;
ng_ID_t retaddr = NGI_RETADDR(item);
char retabuf[32];
NGI_GET_MSG(item, msg);
NG_FREE_ITEM(item); /* we have all we need */
/* Only allow mesgs to be passed if we have the control socket.
* Data sockets can only support the generic messages. */
@ -764,14 +754,13 @@ ngs_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
error = EINVAL; /* unknown command */
}
/* Free the message and return */
FREE(msg, M_NETGRAPH);
NG_FREE_MSG(msg);
return(error);
}
/* Get the return address into a sockaddr */
if ((retaddr == NULL) || (*retaddr == '\0'))
retaddr = "";
addrlen = strlen(retaddr);
sprintf(retabuf,"[%x]:", retaddr);
addrlen = strlen(retabuf);
MALLOC(addr, struct sockaddr_ng *, addrlen + 4, M_NETGRAPH, M_NOWAIT);
if (addr == NULL) {
TRAP_ERROR;
@ -779,7 +768,7 @@ ngs_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
}
addr->sg_len = addrlen + 3;
addr->sg_family = AF_NETGRAPH;
bcopy(retaddr, addr->sg_data, addrlen);
bcopy(retabuf, addr->sg_data, addrlen);
addr->sg_data[addrlen] = '\0';
/* Send it up */
@ -792,8 +781,7 @@ ngs_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
* Receive data on a hook
*/
static int
ngs_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
ngs_rcvdata(hook_p hook, item_p item)
{
struct ngsock *const sockdata = hook->node->private;
struct ngpcb *const pcbp = sockdata->datasock;
@ -801,10 +789,13 @@ ngs_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct sockaddr_ng *addr;
char *addrbuf[NG_HOOKLEN + 1 + 4];
int addrlen;
struct mbuf *m;
NGI_GET_M(item, m);
NG_FREE_ITEM(item);
/* If there is no data socket, black-hole it */
if (pcbp == NULL) {
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
return (0);
}
so = pcbp->ng_socket;
@ -817,9 +808,6 @@ ngs_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
bcopy(hook->name, addr->sg_data, addrlen);
addr->sg_data[addrlen] = '\0';
/* We have no use for the meta data, free/clear it now. */
NG_FREE_META(meta);
/* Try to tell the socket which hook it came in on */
if (sbappendaddr(&so->so_rcv, (struct sockaddr *) addr, m, NULL) == 0) {
m_freem(m);
@ -842,8 +830,9 @@ ngs_disconnect(hook_p hook)
struct ngsock *const sockdata = hook->node->private;
if ((sockdata->flags & NGS_FLAG_NOLINGER )
&& (hook->node->numhooks == 0)) {
ng_rmnode(hook->node);
&& (hook->node->numhooks == 0)
&& ((hook->node->flags & NG_INVALID) == 0)) {
ng_rmnode_self(hook->node);
}
return (0);
}
@ -854,15 +843,12 @@ ngs_disconnect(hook_p hook)
* knows we should be shutting down.
*/
static int
ngs_rmnode(node_p node)
ngs_shutdown(node_p node)
{
struct ngsock *const sockdata = node->private;
struct ngpcb *const dpcbp = sockdata->datasock;
struct ngpcb *const pcbp = sockdata->ctlsock;
ng_cutlinks(node);
ng_unname(node);
if (dpcbp != NULL) {
soisdisconnected(dpcbp->ng_socket);
dpcbp->sockdata = NULL;
@ -939,39 +925,41 @@ extern struct domain ngdomain; /* stop compiler warnings */
static struct protosw ngsw[] = {
{
SOCK_DGRAM,
&ngdomain,
SOCK_DGRAM, /* protocol type */
&ngdomain, /* backpointer to domain */
NG_CONTROL,
PR_ATOMIC | PR_ADDR /* | PR_RIGHTS */,
0, 0, 0, 0,
NULL,
0, 0, 0, 0,
&ngc_usrreqs
PR_ATOMIC | PR_ADDR /* | PR_RIGHTS */, /* flags */
0, 0, 0, 0, /* input, output, ctlinput, ctloutput */
NULL, /* ousrreq */
0, 0, 0, 0, /* init, fasttimeo, slowtimo, drain */
&ngc_usrreqs, /* usrreq table (above) */
/*{NULL}*/ /* pffh (protocol filter head?) */
},
{
SOCK_DGRAM,
&ngdomain,
SOCK_DGRAM, /* protocol type */
&ngdomain, /* backpointer to domain */
NG_DATA,
PR_ATOMIC | PR_ADDR,
0, 0, 0, 0,
NULL,
0, 0, 0, 0,
&ngd_usrreqs
PR_ATOMIC | PR_ADDR, /* flags */
0, 0, 0, 0, /* input, output, ctlinput, ctloutput */
NULL, /* ousrreq() */
0, 0, 0, 0, /* init, fasttimeo, slowtimo, drain */
&ngd_usrreqs, /* usrreq table (above) */
/*{NULL}*/ /* pffh (protocol filter head?) */
}
};
struct domain ngdomain = {
AF_NETGRAPH,
"netgraph",
0,
NULL,
NULL,
ngsw,
&ngsw[sizeof(ngsw) / sizeof(ngsw[0])],
0,
NULL,
0,
0
NULL, /* init() */
NULL, /* externalise() */
NULL, /* dispose() */
ngsw, /* protosw entry */
&ngsw[sizeof(ngsw) / sizeof(ngsw[0])], /* Number of protosw entries */
NULL, /* next domain in list */
NULL, /* rtattach() */
0, /* arg to rtattach in bits */
0 /* maxrtkey */
};
/*
@ -996,12 +984,13 @@ ngs_mod_event(module_t mod, int event, void *data)
}
#ifdef NOTYET
if ((LIST_EMPTY(&ngsocklist)) && (typestruct.refs == 0)) {
/* Unregister protocol domain XXX can't do this yet.. */
if ((error = net_rm_domain(&ngdomain)) != 0)
break;
#else
error = EBUSY;
if ((error = net_rm_domain(&ngdomain)) != 0)
break;
} else
#endif
error = EBUSY;
break;
default:
error = EOPNOTSUPP;

View File

@ -79,7 +79,7 @@ typedef struct privdata *sc_p;
/* Netgraph methods */
static ng_constructor_t ngt_constructor;
static ng_rcvmsg_t ngt_rcvmsg;
static ng_shutdown_t ngt_rmnode;
static ng_shutdown_t ngt_shutdown;
static ng_newhook_t ngt_newhook;
static ng_rcvdata_t ngt_rcvdata;
static ng_disconnect_t ngt_disconnect;
@ -133,7 +133,7 @@ static struct ng_type ng_tee_typestruct = {
NULL,
ngt_constructor,
ngt_rcvmsg,
ngt_rmnode,
ngt_shutdown,
ngt_newhook,
NULL,
NULL,
@ -147,21 +147,16 @@ NETGRAPH_INIT(tee, &ng_tee_typestruct);
* Node constructor
*/
static int
ngt_constructor(node_p *nodep)
ngt_constructor(node_p node)
{
sc_p privdata;
int error = 0;
MALLOC(privdata, sc_p, sizeof(*privdata), M_NETGRAPH, M_NOWAIT|M_ZERO);
if (privdata == NULL)
return (ENOMEM);
if ((error = ng_make_node_common(&ng_tee_typestruct, nodep))) {
FREE(privdata, M_NETGRAPH);
return (error);
}
(*nodep)->private = privdata;
privdata->node = *nodep;
node->private = privdata;
privdata->node = node;
return (0);
}
@ -198,13 +193,14 @@ ngt_newhook(node_p node, hook_p hook, const char *name)
* Receive a control message
*/
static int
ngt_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
struct ng_mesg **rptr, hook_p lasthook)
ngt_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
const sc_p sc = node->private;
struct ng_mesg *resp = NULL;
int error = 0;
struct ng_mesg *msg;
NGI_GET_MSG(item, msg);
switch (msg->header.typecookie) {
case NGM_TEE_COOKIE:
switch (msg->header.cmd) {
@ -248,17 +244,32 @@ ngt_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
break;
}
break;
case NGM_FLOW_COOKIE:
if (lasthook) {
if (lasthook == sc->left.hook) {
if (sc->right.hook) {
NGI_MSG(item) = msg;
NG_FWD_MSG_HOOK(error, node, item,
sc->right.hook, 0);
return (error);
}
} else {
if (sc->left.hook) {
NGI_MSG(item) = msg;
NG_FWD_MSG_HOOK(error, node, item,
sc->left.hook, 0);
return (error);
}
}
}
break;
default:
error = EINVAL;
break;
}
if (rptr)
*rptr = resp;
else if (resp)
FREE(resp, M_NETGRAPH);
done:
FREE(msg, M_NETGRAPH);
NG_RESPOND_MSG(error, node, item, resp);
NG_FREE_MSG(msg);
return (error);
}
@ -273,15 +284,18 @@ ngt_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
* from the other side.
*/
static int
ngt_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
ngt_rcvdata(hook_p hook, item_p item)
{
const sc_p sc = hook->node->private;
struct hookinfo *const hinfo = (struct hookinfo *) hook->private;
struct hookinfo *dest;
struct hookinfo *dup;
int error = 0;
struct mbuf *m;
meta_p meta;
m = NGI_M(item);
meta = NGI_META(item); /* leave these owned by the item */
/* Which hook? */
if (hinfo == &sc->left) {
dup = &sc->left2right;
@ -302,42 +316,43 @@ ngt_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
hinfo->stats.inOctets += m->m_pkthdr.len;
hinfo->stats.inFrames++;
/*
* Don't make a copy if only the dup hook exists.
*/
if ((dup && dup->hook) && (dest->hook == NULL)) {
dest = dup;
dup = NULL;
}
/* Duplicate packet and meta info if requried */
if (dup != NULL) {
struct mbuf *m2;
meta_p meta2;
/* Copy packet */
/* Copy packet (failure will not stop the original)*/
m2 = m_dup(m, M_NOWAIT);
if (m2 == NULL) {
NG_FREE_DATA(m, meta);
return (ENOBUFS);
if (m2) {
/* Copy meta info */
/* If we can't get a copy, tough.. */
if (meta != NULL) {
meta2 = ng_copy_meta(meta);
} else
meta2 = NULL;
/* Deliver duplicate */
dup->stats.outOctets += m->m_pkthdr.len;
dup->stats.outFrames++;
NG_SEND_DATA(error, dup->hook, m2, meta2);
}
/* Copy meta info */
if (meta != NULL) {
MALLOC(meta2, meta_p,
meta->used_len, M_NETGRAPH, M_NOWAIT);
if (meta2 == NULL) {
m_freem(m2);
NG_FREE_DATA(m, meta);
return (ENOMEM);
}
bcopy(meta, meta2, meta->used_len);
meta2->allocated_len = meta->used_len;
} else
meta2 = NULL;
/* Deliver duplicate */
dup->stats.outOctets += m->m_pkthdr.len;
dup->stats.outFrames++;
NG_SEND_DATA(error, dup->hook, m2, meta2);
}
/* Deliver frame out destination hook */
dest->stats.outOctets += m->m_pkthdr.len;
dest->stats.outFrames++;
NG_SEND_DATA(error, dest->hook, m, meta);
if (dest->hook)
NG_FWD_DATA(error, item, dest->hook);
else
NG_FREE_ITEM(item);
return (0);
}
@ -353,15 +368,15 @@ ngt_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* from two links is in ng_base.c.
*/
static int
ngt_rmnode(node_p node)
ngt_shutdown(node_p node)
{
const sc_p privdata = node->private;
node->flags |= NG_INVALID;
#if 0 /* can never happen as cutlinks is already called */
if (privdata->left.hook && privdata->right.hook)
ng_bypass(privdata->left.hook, privdata->right.hook);
ng_cutlinks(node);
ng_unname(node);
#endif
node->private = NULL;
ng_unref(privdata->node);
FREE(privdata, M_NETGRAPH);
@ -378,8 +393,9 @@ ngt_disconnect(hook_p hook)
KASSERT(hinfo != NULL, ("%s: null info", __FUNCTION__));
hinfo->hook = NULL;
if (hook->node->numhooks == 0)
ng_rmnode(hook->node);
if ((hook->node->numhooks == 0)
&& ((hook->node->flags & NG_INVALID) == 0))
ng_rmnode_self(hook->node);
return (0);
}

View File

@ -229,19 +229,19 @@ ngt_open(dev_t dev, struct tty *tp)
}
snprintf(name, sizeof(name), "%s%d", typestruct.name, ngt_unit++);
/* Set back pointers */
sc->node->private = sc;
tp->t_sc = (caddr_t) sc;
/* Assign node its name */
if ((error = ng_name_node(sc->node, name))) {
log(LOG_ERR, "%s: node name exists?\n", name);
ngt_nodeop_ok = 1;
ng_rmnode(sc->node);
ng_unref(sc->node);
ngt_nodeop_ok = 0;
goto done;
}
/* Set back pointers */
sc->node->private = sc;
tp->t_sc = (caddr_t) sc;
/*
* Pre-allocate cblocks to the an appropriate amount.
* I'm not sure what is appropriate.
@ -279,7 +279,7 @@ ngt_close(struct tty *tp, int flag)
sc->flags &= ~FLG_TIMEOUT;
}
ngt_nodeop_ok = 1;
ng_rmnode(sc->node);
ng_rmnode_self(sc->node);
ngt_nodeop_ok = 0;
tp->t_sc = NULL;
}
@ -493,11 +493,9 @@ ngt_timeout(void *arg)
* the line discipline on a tty, so always return an error if not.
*/
static int
ngt_constructor(node_p *nodep)
ngt_constructor(node_p node)
{
if (!ngt_nodeop_ok)
return (EOPNOTSUPP);
return (ng_make_node_common(&typestruct, nodep));
return (EOPNOTSUPP);
}
/*
@ -521,12 +519,13 @@ ngt_newhook(node_p node, hook_p hook, const char *name)
}
/*
* set the hooks into queueing mode (for outgoing packets)
* Set the hooks into queueing mode (for outgoing packets)
* Force single client at a time.
*/
static int
ngt_connect(hook_p hook)
{
hook->peer->flags |= HK_QUEUE;
hook->peer->flags |= HK_QUEUE|HK_FORCE_WRITER;
return (0);
}
@ -560,8 +559,6 @@ ngt_shutdown(node_p node)
if (!ngt_nodeop_ok)
return (EOPNOTSUPP);
ng_unname(node);
ng_cutlinks(node);
node->private = NULL;
ng_unref(sc->node);
m_freem(sc->qhead);
@ -576,15 +573,17 @@ ngt_shutdown(node_p node)
* output queue and start output if necessary.
*/
static int
ngt_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
ngt_rcvdata(hook_p hook, item_p item)
{
const sc_p sc = hook->node->private;
int s, error = 0;
struct mbuf *m;
if (hook != sc->hook)
panic(__FUNCTION__);
NG_FREE_META(meta);
NGI_GET_M(item, m);
NG_FREE_ITEM(item);
s = spltty();
if (sc->qlen >= MAX_MBUFQ)
ERROUT(ENOBUFS);
@ -607,13 +606,14 @@ ngt_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* Receive control message
*/
static int
ngt_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
struct ng_mesg **rptr, hook_p lasthook)
ngt_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
const sc_p sc = (sc_p) node->private;
struct ng_mesg *resp = NULL;
int error = 0;
struct ng_mesg *msg;
NGI_GET_MSG(item, msg);
switch (msg->header.typecookie) {
case NGM_TTY_COOKIE:
switch (msg->header.cmd) {
@ -643,13 +643,9 @@ ngt_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
default:
ERROUT(EINVAL);
}
if (rptr)
*rptr = resp;
else if (resp)
FREE(resp, M_NETGRAPH);
done:
FREE(msg, M_NETGRAPH);
NG_RESPOND_MSG(error, node, item, resp);
NG_FREE_MSG(msg);
return (error);
}

View File

@ -89,7 +89,7 @@ typedef struct ng_vjc_private *priv_p;
/* Netgraph node methods */
static ng_constructor_t ng_vjc_constructor;
static ng_rcvmsg_t ng_vjc_rcvmsg;
static ng_shutdown_t ng_vjc_rmnode;
static ng_shutdown_t ng_vjc_shutdown;
static ng_newhook_t ng_vjc_newhook;
static ng_rcvdata_t ng_vjc_rcvdata;
static ng_disconnect_t ng_vjc_disconnect;
@ -227,7 +227,7 @@ static struct ng_type ng_vjc_typestruct = {
NULL,
ng_vjc_constructor,
ng_vjc_rcvmsg,
ng_vjc_rmnode,
ng_vjc_shutdown,
ng_vjc_newhook,
NULL,
NULL,
@ -245,22 +245,16 @@ NETGRAPH_INIT(vjc, &ng_vjc_typestruct);
* Create a new node
*/
static int
ng_vjc_constructor(node_p *nodep)
ng_vjc_constructor(node_p node)
{
priv_p priv;
int error;
/* Allocate private structure */
MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_NOWAIT | M_ZERO);
if (priv == NULL)
return (ENOMEM);
/* Call generic node constructor */
if ((error = ng_make_node_common(&ng_vjc_typestruct, nodep))) {
FREE(priv, M_NETGRAPH);
return (error);
}
(*nodep)->private = priv;
node->private = priv;
/* Done */
return (0);
@ -300,13 +294,14 @@ ng_vjc_newhook(node_p node, hook_p hook, const char *name)
* Receive a control message
*/
static int
ng_vjc_rcvmsg(node_p node, struct ng_mesg *msg,
const char *raddr, struct ng_mesg **rptr, hook_p lasthook)
ng_vjc_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
const priv_p priv = (priv_p) node->private;
struct ng_mesg *resp = NULL;
int error = 0;
struct ng_mesg *msg;
NGI_GET_MSG(item, msg);
/* Check type cookie */
switch (msg->header.typecookie) {
case NGM_VJC_COOKIE:
@ -396,13 +391,9 @@ ng_vjc_rcvmsg(node_p node, struct ng_mesg *msg,
error = EINVAL;
break;
}
if (rptr)
*rptr = resp;
else if (resp)
FREE(resp, M_NETGRAPH);
done:
FREE(msg, M_NETGRAPH);
NG_RESPOND_MSG(error, node, item, resp);
NG_FREE_MSG(msg);
return (error);
}
@ -410,13 +401,14 @@ ng_vjc_rcvmsg(node_p node, struct ng_mesg *msg,
* Receive data
*/
static int
ng_vjc_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
ng_vjc_rcvdata(hook_p hook, item_p item)
{
const node_p node = hook->node;
const priv_p priv = (priv_p) node->private;
int error = 0;
struct mbuf *m;
NGI_GET_M(item, m);
if (hook == priv->ip) { /* outgoing packet */
u_int type = TYPE_IP;
@ -425,7 +417,7 @@ ng_vjc_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct ip *ip;
if ((m = ng_vjc_pulluphdrs(m, 0)) == NULL) {
NG_FREE_META(meta);
NG_FREE_ITEM(item);
return (ENOBUFS);
}
ip = mtod(m, struct ip *);
@ -460,7 +452,8 @@ ng_vjc_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
/* Are we decompressing? */
if (!priv->conf.enableDecomp) {
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_ITEM(item);
return (ENXIO);
}
@ -471,7 +464,7 @@ ng_vjc_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
if (m->m_len < need2pullup
&& (m = m_pullup(m, need2pullup)) == NULL) {
priv->slc.sls_errorin++;
NG_FREE_META(meta);
NG_FREE_ITEM(item);
return (ENOBUFS);
}
@ -480,7 +473,8 @@ ng_vjc_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
m->m_len, m->m_pkthdr.len, TYPE_COMPRESSED_TCP,
&priv->slc, &hdr, &hlen);
if (vjlen <= 0) {
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_ITEM(item);
return (EINVAL);
}
m_adj(m, vjlen);
@ -489,7 +483,8 @@ ng_vjc_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
MGETHDR(hm, M_DONTWAIT, MT_DATA);
if (hm == NULL) {
priv->slc.sls_errorin++;
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_ITEM(item);
return (ENOBUFS);
}
hm->m_len = 0;
@ -499,7 +494,8 @@ ng_vjc_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
if ((hm->m_flags & M_EXT) == 0) {
m_freem(hm);
priv->slc.sls_errorin++;
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_ITEM(item);
return (ENOBUFS);
}
}
@ -517,13 +513,14 @@ ng_vjc_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
/* Are we decompressing? */
if (!priv->conf.enableDecomp) {
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_ITEM(item);
return (ENXIO);
}
/* Pull up IP+TCP headers */
if ((m = ng_vjc_pulluphdrs(m, 1)) == NULL) {
NG_FREE_META(meta);
NG_FREE_ITEM(item);
return (ENOBUFS);
}
@ -531,7 +528,8 @@ ng_vjc_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
if (sl_uncompress_tcp_core(mtod(m, u_char *),
m->m_len, m->m_pkthdr.len, TYPE_UNCOMPRESSED_TCP,
&priv->slc, &hdr, &hlen) < 0) {
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_ITEM(item);
return (EINVAL);
}
hook = priv->ip;
@ -541,7 +539,7 @@ ng_vjc_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
panic("%s: unknown hook", __FUNCTION__);
/* Send result back out */
NG_SEND_DATA(error, hook, m, meta);
NG_FWD_NEW_DATA(error, item, hook, m);
return (error);
}
@ -549,13 +547,11 @@ ng_vjc_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* Shutdown node
*/
static int
ng_vjc_rmnode(node_p node)
ng_vjc_shutdown(node_p node)
{
const priv_p priv = (priv_p) node->private;
node->flags |= NG_INVALID;
ng_cutlinks(node);
ng_unname(node);
bzero(priv, sizeof(*priv));
FREE(priv, M_NETGRAPH);
node->private = NULL;
@ -585,8 +581,9 @@ ng_vjc_disconnect(hook_p hook)
panic("%s: unknown hook", __FUNCTION__);
/* Go away if no hooks left */
if (node->numhooks == 0)
ng_rmnode(node);
if ((node->numhooks == 0)
&& ((node->flags & NG_INVALID) == 0))
ng_rmnode_self(node);
return (0);
}

View File

@ -267,7 +267,7 @@ struct softc {
};
static int
ngmn_constructor(node_p *nodep)
ngmn_constructor(node_p node)
{
return (EINVAL);
@ -281,29 +281,29 @@ ngmn_shutdown(node_p nodep)
}
static int
ngmn_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
struct ng_mesg **rptr, hook_p lasthook)
ngmn_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
struct softc *sc;
struct ng_mesg *resp = NULL;
struct schan *sch;
char *arg;
int pos, i;
struct ng_mesg *msg;
NGI_GET_MSG(item, msg);
sc = node->private;
if (msg->header.typecookie != NGM_GENERIC_COOKIE ||
rptr == NULL || /* temporary */
msg->header.cmd != NGM_TEXT_STATUS) {
if (rptr)
*rptr = NULL;
FREE(msg, M_NETGRAPH);
NG_FREE_ITEM(item);
NG_FREE_MSG(msg);
return (EINVAL);
}
NG_MKRESPONSE(resp, msg, sizeof(struct ng_mesg) + NG_TEXTRESPONSE,
M_NOWAIT);
if (resp == NULL) {
FREE(msg, M_NETGRAPH);
NG_FREE_ITEM(item);
NG_FREE_MSG(msg);
return (ENOMEM);
}
arg = (char *)resp->data;
@ -377,12 +377,8 @@ ngmn_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
resp->header.arglen = pos + 1;
/* Take care of synchronous response, if any */
if (rptr)
*rptr = resp;
else if (resp)
FREE(resp, M_NETGRAPH); /* Will eventually send the hard way */
FREE(msg, M_NETGRAPH);
NG_RESPOND_MSG(i, node, item, resp);
NG_FREE_MSG(msg);
return (0);
}
@ -505,28 +501,30 @@ mn_fmt_ts(char *p, u_int32_t ts)
*/
static int
ngmn_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
ngmn_rcvdata(hook_p hook, item_p item)
{
struct mbuf *m2;
struct trxd *dp, *dp2;
struct schan *sch;
struct softc *sc;
int chan, pitch, len;
struct mbuf *m;
sch = hook->private;
sc = sch->sc;
chan = sch->chan;
if (sch->state != UP) {
NG_FREE_DATA(m, meta);
NG_FREE_ITEM(item);
return (0);
}
NGI_GET_M(item, m);
if (sch->tx_pending + m->m_pkthdr.len > sch->tx_limit * mn_maxlatency) {
NG_FREE_DATA(m, meta);
NG_FREE_M(m);
NG_FREE_ITEM(item);
return (0);
}
NG_FREE_META(meta);
NG_FREE_ITEM(item);
pitch = 0;
m2 = m;
dp2 = sc->ch[chan]->xl;
@ -1350,7 +1348,6 @@ mn_attach (device_t self)
sc->node->private = sc;
sprintf(sc->nodename, "%s%d", NG_MN_NODE_TYPE, sc->unit);
if (ng_name_node(sc->node, sc->nodename)) {
ng_rmnode(sc->node);
ng_unref(sc->node);
return (0);
}