diff options
| author | Alexander Motin <mav@FreeBSD.org> | 2008-02-24 13:21:13 +0000 |
|---|---|---|
| committer | Alexander Motin <mav@FreeBSD.org> | 2008-02-24 13:21:13 +0000 |
| commit | aba63d90233ea5734afcb01363cd4920ae2f7907 (patch) | |
| tree | c75dc376e583aeabdccd243e26650a21511a541c /sys/netgraph | |
| parent | a79b258cda6ea3164deaf5febe4883f6e9e75055 (diff) | |
Notes
Diffstat (limited to 'sys/netgraph')
| -rw-r--r-- | sys/netgraph/ng_bpf.c | 102 |
1 files changed, 68 insertions, 34 deletions
diff --git a/sys/netgraph/ng_bpf.c b/sys/netgraph/ng_bpf.c index 54ba383afc6e..11e70674da11 100644 --- a/sys/netgraph/ng_bpf.c +++ b/sys/netgraph/ng_bpf.c @@ -80,8 +80,9 @@ MALLOC_DEFINE(M_NETGRAPH_BPF, "netgraph_bpf", "netgraph bpf node "); /* Per hook private info */ struct ng_bpf_hookinfo { - node_p node; hook_p hook; + hook_p match; + hook_p nomatch; struct ng_bpf_hookprog *prog; struct ng_bpf_hookstat stats; }; @@ -226,12 +227,42 @@ ng_bpf_constructor(node_p node) } /* + * Callback functions to be used by NG_NODE_FOREACH_HOOK() macro. + */ +static int +ng_bpf_addrefs(hook_p hook, void* arg) +{ + hinfo_p hip = NG_HOOK_PRIVATE(hook); + hook_p h = (hook_p)arg; + + if (strcmp(hip->prog->ifMatch, NG_HOOK_NAME(h)) == 0) + hip->match = h; + if (strcmp(hip->prog->ifNotMatch, NG_HOOK_NAME(h)) == 0) + hip->nomatch = h; + return (1); +} + +static int +ng_bpf_remrefs(hook_p hook, void* arg) +{ + hinfo_p hip = NG_HOOK_PRIVATE(hook); + hook_p h = (hook_p)arg; + + if (hip->match == h) + hip->match = NULL; + if (hip->nomatch == h) + hip->nomatch = NULL; + return (1); +} + +/* * Add a hook */ static int ng_bpf_newhook(node_p node, hook_p hook, const char *name) { hinfo_p hip; + hook_p tmp; int error; /* Create hook private structure */ @@ -240,7 +271,9 @@ ng_bpf_newhook(node_p node, hook_p hook, const char *name) return (ENOMEM); hip->hook = hook; NG_HOOK_SET_PRIVATE(hook, hip); - hip->node = node; + + /* Add our reference into other hooks data. */ + NG_NODE_FOREACH_HOOK(node, ng_bpf_addrefs, hook, tmp); /* Attach the default BPF program */ if ((error = ng_bpf_setprog(hook, &ng_bpf_default_prog)) != 0) { @@ -250,8 +283,7 @@ ng_bpf_newhook(node_p node, hook_p hook, const char *name) } /* Set hook name */ - strncpy(hip->prog->thisHook, name, sizeof(hip->prog->thisHook) - 1); - hip->prog->thisHook[sizeof(hip->prog->thisHook) - 1] = '\0'; + strlcpy(hip->prog->thisHook, name, sizeof(hip->prog->thisHook)); return (0); } @@ -373,8 +405,8 @@ ng_bpf_rcvdata(hook_p hook, item_p item) { const hinfo_p hip = NG_HOOK_PRIVATE(hook); int totlen; - int needfree = 0, error = 0; - u_char *data; + int error = 0; + u_char *data = NULL; hinfo_p dhip; hook_p dest; u_int len; @@ -388,35 +420,30 @@ ng_bpf_rcvdata(hook_p hook, item_p item) hip->stats.recvFrames++; hip->stats.recvOctets += totlen; - /* Need to put packet in contiguous memory for bpf */ - if (m->m_next != NULL) { - if (totlen > MHLEN) { - MALLOC(data, u_char *, totlen, M_NETGRAPH_BPF, M_NOWAIT); - if (data == NULL) { - NG_FREE_ITEM(item); - return (ENOMEM); - } - needfree = 1; - m_copydata(m, 0, totlen, (caddr_t)data); - } else { + /* Don't call bpf_filter() with totlen == 0! */ + if (totlen == 0) { + len = 0; + goto ready; + } + + /* Try to put packet in contiguous memory for bpf */ + if (m->m_next == NULL || totlen < MHLEN) { + if (m->m_next != NULL) { NGI_M(item) = m = m_pullup(m, totlen); if (m == NULL) { NG_FREE_ITEM(item); return (ENOBUFS); } - data = mtod(m, u_char *); } - } else data = mtod(m, u_char *); + } /* Run packet through filter */ - if (totlen == 0) - len = 0; /* don't call bpf_filter() with totlen == 0! */ - else + if (data) len = bpf_filter(hip->prog->bpf_prog, data, totlen, totlen); - if (needfree) - FREE(data, M_NETGRAPH_BPF); - + else + len = bpf_filter(hip->prog->bpf_prog, (u_char *)m, totlen, 0); +ready: /* See if we got a match and find destination hook */ if (len > 0) { @@ -429,11 +456,11 @@ ng_bpf_rcvdata(hook_p hook, item_p item) /* Assume this never changes m */ if (len < totlen) { m_adj(m, -(totlen - len)); - totlen -= len; + totlen = len; } - dest = ng_findhook(hip->node, hip->prog->ifMatch); + dest = hip->match; } else - dest = ng_findhook(hip->node, hip->prog->ifNotMatch); + dest = hip->nomatch; if (dest == NULL) { NG_FREE_ITEM(item); return (0); @@ -463,16 +490,20 @@ ng_bpf_shutdown(node_p node) static int ng_bpf_disconnect(hook_p hook) { + const node_p node = NG_HOOK_NODE(hook); const hinfo_p hip = NG_HOOK_PRIVATE(hook); + hook_p tmp; KASSERT(hip != NULL, ("%s: null info", __func__)); + + /* Remove our reference from other hooks data. */ + NG_NODE_FOREACH_HOOK(node, ng_bpf_remrefs, hook, tmp); + FREE(hip->prog, M_NETGRAPH_BPF); - bzero(hip, sizeof(*hip)); FREE(hip, M_NETGRAPH_BPF); - NG_HOOK_SET_PRIVATE(hook, NULL); /* for good measure */ - if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0) - && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) { - ng_rmnode_self(NG_HOOK_NODE(hook)); + if ((NG_NODE_NUMHOOKS(node) == 0) && + (NG_NODE_IS_VALID(node))) { + ng_rmnode_self(node); } return (0); } @@ -506,6 +537,9 @@ ng_bpf_setprog(hook_p hook, const struct ng_bpf_hookprog *hp0) if (hip->prog != NULL) FREE(hip->prog, M_NETGRAPH_BPF); hip->prog = hp; + + /* Prepare direct references on target hooks. */ + hip->match = ng_findhook(NG_HOOK_NODE(hook), hip->prog->ifMatch); + hip->nomatch = ng_findhook(NG_HOOK_NODE(hook), hip->prog->ifNotMatch); return (0); } - |
