diff options
Diffstat (limited to 'sys/netgraph')
-rw-r--r-- | sys/netgraph/netgraph.h | 3 | ||||
-rw-r--r-- | sys/netgraph/ng_base.c | 33 | ||||
-rw-r--r-- | sys/netgraph/ng_socket.c | 2 |
3 files changed, 28 insertions, 10 deletions
diff --git a/sys/netgraph/netgraph.h b/sys/netgraph/netgraph.h index 69559ce..e0b53d1 100644 --- a/sys/netgraph/netgraph.h +++ b/sys/netgraph/netgraph.h @@ -608,6 +608,7 @@ struct ng_apply_info { ng_apply_t *apply; void *context; int refs; + int error; }; struct ng_item { u_long el_flags; @@ -634,7 +635,7 @@ struct ng_item { * and its context. */ struct ng_apply_info *apply; - void *PAD1; + uintptr_t depth; #ifdef NETGRAPH_DEBUG /*----------------------------------------------*/ char *lastfile; int lastline; diff --git a/sys/netgraph/ng_base.c b/sys/netgraph/ng_base.c index 10eca62..cde7fdb 100644 --- a/sys/netgraph/ng_base.c +++ b/sys/netgraph/ng_base.c @@ -2250,9 +2250,13 @@ ng_flush_input_queue(struct ng_queue * ngq) NG_QUEUE_UNLOCK(ngq); /* If the item is supplying a callback, call it with an error */ - if (item->apply != NULL && - refcount_release(&item->apply->refs)) { - (*item->apply->apply)(item->apply->context, ENOENT); + if (item->apply != NULL) { + if (item->depth == 1) + item->apply->error = ENOENT; + if (refcount_release(&item->apply->refs)) { + (*item->apply->apply)(item->apply->context, + item->apply->error); + } } NG_FREE_ITEM(item); NG_QUEUE_LOCK(ngq); @@ -2367,6 +2371,7 @@ ng_snd_item(item_p item, int flags) #ifdef NETGRAPH_DEBUG _ngi_check(item, __FILE__, __LINE__); #endif + item->depth = 1; NG_QUEUE_LOCK(ngq); ng_queue_rw(ngq, item, rw); NG_QUEUE_UNLOCK(ngq); @@ -2394,6 +2399,7 @@ ng_snd_item(item_p item, int flags) NGI_GET_NODE(item, node); /* zaps stored node */ + item->depth++; error = ng_apply_item(node, item, rw); /* drops r/w lock when done */ /* @@ -2413,8 +2419,14 @@ ng_snd_item(item_p item, int flags) done: /* If was not sent, apply callback here. */ - if (item->apply != NULL && refcount_release(&item->apply->refs)) - (*item->apply->apply)(item->apply->context, error); + if (item->apply != NULL) { + if (item->depth == 0 && error != 0) + item->apply->error = error; + if (refcount_release(&item->apply->refs)) { + (*item->apply->apply)(item->apply->context, + item->apply->error); + } + } NG_FREE_ITEM(item); return (error); @@ -2430,10 +2442,10 @@ static int ng_apply_item(node_p node, item_p item, int rw) { hook_p hook; - int error = 0; ng_rcvdata_t *rcvdata; ng_rcvmsg_t *rcvmsg; struct ng_apply_info *apply; + int error = 0, depth; /* Node and item are never optional. */ KASSERT(node != NULL, ("ng_apply_item: node is NULL")); @@ -2445,6 +2457,7 @@ ng_apply_item(node_p node, item_p item, int rw) #endif apply = item->apply; + depth = item->depth; switch (item->el_flags & NGQF_TYPE) { case NGQF_DATA: @@ -2552,8 +2565,12 @@ ng_apply_item(node_p node, item_p item, int rw) ng_leave_write(&node->nd_input_queue); /* Apply callback. */ - if (apply != NULL && refcount_release(&apply->refs)) - (*apply->apply)(apply->context, error); + if (apply != NULL) { + if (depth == 1 && error != 0) + apply->error = error; + if (refcount_release(&apply->refs)) + (*apply->apply)(apply->context, apply->error); + } return (error); } diff --git a/sys/netgraph/ng_socket.c b/sys/netgraph/ng_socket.c index b444794..410c2d9 100644 --- a/sys/netgraph/ng_socket.c +++ b/sys/netgraph/ng_socket.c @@ -919,7 +919,7 @@ ngs_rcvmsg(node_p node, item_p item, hook_p lasthook) if (sbappendaddr(&so->so_rcv, (struct sockaddr *)&addr, m, NULL) == 0) { TRAP_ERROR; m_freem(m); - error = so->so_error = ENOBUFS; + return (ENOBUFS); } sorwakeup(so); |