View | Details | Raw Unified | Return to bug 242637 | Differences between
and this patch

Collapse All | Expand All

(-)b/emulators/virtualbox-ose/files/patch-src_VBox_HostDrivers_VBoxNetFlt_VBoxNetFltInternal.h (+13 lines)
Added Link Here
1
--- src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFltInternal.h	2019-12-10 10:52:37.000000000 -0700
2
+++ src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFltInternal.h	2019-12-13 17:34:41.330051000 -0700
3
@@ -243,6 +243,10 @@
4
             hook_p input;
5
             /** Output hook */
6
             hook_p output;
7
+            /** Pending synchronous netgraph requests */
8
+            STAILQ_HEAD(,vboxnetflt_sreq) sreq_list;
9
+            /** Synchronous request lock */
10
+            struct mtx sreq_lck;
11
             /** Original interface flags */
12
             unsigned int flags;
13
             /** Input queue */
(-)b/emulators/virtualbox-ose/files/patch-src_VBox_HostDrivers_VBoxNetFlt_freebsd_VBoxNetFlt-freebsd.c (-67 / +760 lines)
Lines 1-51 Link Here
1
--- src/VBox/HostDrivers/VBoxNetFlt/freebsd/VBoxNetFlt-freebsd.c.orig	2019-11-21 17:02:02 UTC
1
--- src/VBox/HostDrivers/VBoxNetFlt/freebsd/VBoxNetFlt-freebsd.c	2019-12-14 11:59:42.519507000 -0700
2
+++ src/VBox/HostDrivers/VBoxNetFlt/freebsd/VBoxNetFlt-freebsd.c
2
+++ src/VBox/HostDrivers/VBoxNetFlt/freebsd/VBoxNetFlt-freebsd.c	2019-12-14 11:59:42.519507000 -0700
3
@@ -52,6 +52,7 @@
3
@@ -52,10 +52,12 @@
4
 #include <net/if_dl.h>
4
 #include <net/if_dl.h>
5
 #include <net/if_types.h>
5
 #include <net/if_types.h>
6
 #include <net/ethernet.h>
6
 #include <net/ethernet.h>
7
+#include <net/if_vlan_var.h>
7
+#include <net/if_vlan_var.h>
8
 
8
 
9
 #include <netgraph/ng_message.h>
9
 #include <netgraph/ng_message.h>
10
 #include <netgraph/netgraph.h>
10
 #include <netgraph/netgraph.h>
11
@@ -73,6 +74,7 @@
11
 #include <netgraph/ng_parse.h>
12
+#include <netgraph/ng_ether.h>
13
 
14
 #define LOG_GROUP LOG_GROUP_NET_FLT_DRV
15
 #include <VBox/version.h>
16
@@ -73,6 +75,9 @@
12
 
17
 
13
 #define VBOXNETFLT_OS_SPECFIC 1
18
 #define VBOXNETFLT_OS_SPECFIC 1
14
 #include "../VBoxNetFltInternal.h"
19
 #include "../VBoxNetFltInternal.h"
15
+#include "freebsd/the-freebsd-kernel.h"
20
+#include "freebsd/the-freebsd-kernel.h"
21
+                                                                                                                        
22
+MALLOC_DEFINE(M_VBOXNETFLT, "vboxnetflt", "VBoxNetFlt netgraph node");
16
 
23
 
17
 static int vboxnetflt_modevent(struct module *, int, void *);
24
 static int vboxnetflt_modevent(struct module *, int, void *);
18
 static ng_constructor_t    ng_vboxnetflt_constructor;
25
 static ng_constructor_t    ng_vboxnetflt_constructor;
19
@@ -436,6 +438,8 @@ static void vboxNetFltFreeBSDinput(void *arg, int pend
26
@@ -93,6 +98,9 @@
27
 /** Output netgraph hook name */
28
 #define NG_VBOXNETFLT_HOOK_OUT      "output"
29
 
30
+/** Maximum time to wait for ng_ether replies */
31
+#define NG_VBOXNETFLT_RPLY_TIMEOUT  (10*hz)
32
+
33
 /** mbuf tag identifier */
34
 #define MTAG_VBOX                   0x56424f58
35
 /** mbuf packet tag */
36
@@ -115,6 +123,18 @@
37
 #endif /* !defined(__FreeBSD_version) || __FreeBSD_version < 800500 */
38
 
39
 /*
40
+ * Context used to track synchronous netgraph request state.
41
+ */
42
+struct vboxnetflt_sreq {
43
+    uint32_t         typecookie;    /**< Matched type cookie. */
44
+    uint32_t         cmd;           /**< Matched command. */
45
+    uint32_t         token;         /**< Matched token. */
46
+    struct ng_mesg  *resp;          /**< On completion, a copy of the reply */
47
+
48
+    STAILQ_ENTRY(vboxnetflt_sreq) sr_link;
49
+};
50
+
51
+/*
52
  * Netgraph command list, we don't support any
53
  * additional commands.
54
  */
55
@@ -303,24 +323,225 @@
56
 }
57
 
58
 /**
59
- * Netgraph message processing for node specific messages.
60
- * We don't accept any special messages so this is not used.
61
+ * Enqueue and return a reference to a new synchronous response handler, or
62
+ * NULL if allocation fails.
63
  */
64
+static struct vboxnetflt_sreq *
65
+vboxnetflt_sreq_enqueue(PVBOXNETFLTINS pThis, uint32_t cookie, uint32_t cmd,
66
+    uint32_t token)
67
+{
68
+    struct vboxnetflt_sreq *sreq;
69
+
70
+    mtx_assert(&pThis->u.s.sreq_lck, MA_OWNED);
71
+
72
+    sreq = malloc(sizeof(*sreq), M_VBOXNETFLT, M_NOWAIT|M_ZERO);
73
+    if (sreq == NULL)
74
+        return (NULL);
75
+
76
+    sreq->typecookie = cookie;
77
+    sreq->cmd = cmd;
78
+    sreq->token = token;
79
+
80
+    STAILQ_INSERT_TAIL(&pThis->u.s.sreq_list, sreq, sr_link);
81
+
82
+    return (sreq);
83
+}
84
+
85
+/**
86
+ * Dequeue and return the first synchronous responder handler capable of
87
+ * handling the given message, or NULL if no handler is found.
88
+ *
89
+ * The caller assumes ownership of any returned handler.
90
+ */
91
+static struct vboxnetflt_sreq *
92
+vboxnetflt_sreq_dequeue(PVBOXNETFLTINS pThis, struct ng_mesg *msg)
93
+{
94
+    struct vboxnetflt_sreq *sreq, *sr_next;
95
+    int error;
96
+
97
+    mtx_assert(&pThis->u.s.sreq_lck, MA_OWNED);
98
+
99
+    if (!(msg->header.flags & NGF_RESP))
100
+        return (EINVAL);
101
+
102
+    STAILQ_FOREACH_SAFE(sreq, &pThis->u.s.sreq_list, sr_link, sr_next)
103
+    {
104
+        if (sreq->typecookie != msg->header.typecookie)
105
+            continue;
106
+
107
+        if (sreq->cmd != msg->header.cmd)
108
+            continue;
109
+
110
+        if (sreq->token != msg->header.token)
111
+            continue;
112
+
113
+        STAILQ_REMOVE(&pThis->u.s.sreq_list, sreq, vboxnetflt_sreq,
114
+            sr_link);
115
+
116
+        return (sreq);
117
+    }
118
+
119
+    return (NULL);
120
+}
121
+
122
+/**
123
+ * Wait for completion of a previously enqueued response handler. On
124
+ * return, the handler will no longer be enqueued, and the caller is
125
+ * responsible for deallocating it via vboxnetflt_sreq_free().
126
+ */
127
+static int
128
+vboxnetflt_sreq_wait_enqueued(PVBOXNETFLTINS pThis,
129
+    struct vboxnetflt_sreq *sreq, int timo)
130
+{
131
+    int error;
132
+
133
+    mtx_assert(&pThis->u.s.sreq_lck, MA_OWNED);
134
+
135
+    while (sreq->resp == NULL) {
136
+        error = mtx_sleep(sreq, &pThis->u.s.sreq_lck, 0, "vboxnetflt_sreq",
137
+            timo);
138
+
139
+        if (error)
140
+            break;
141
+    }
142
+
143
+    /* If our request was completed, we don't care if mtx_sleep()
144
+     * timed out or otherwise failed */
145
+    if (sreq->resp != NULL)
146
+        return (0);
147
+
148
+    /*
149
+     * Otherwise, we stopped waiting before a response has been
150
+     * received, and we're responsible for removing this handler from
151
+     * the queue.
152
+     *
153
+     * If the expected message is delivered later, it will be dropped as
154
+     * spurious if it fails to match against another registered handler.
155
+     */
156
+    STAILQ_REMOVE(&pThis->u.s.sreq_list, sreq, vboxnetflt_sreq,
157
+        sr_link);
158
+
159
+    return (ETIMEDOUT);
160
+}
161
+
162
+/**
163
+ * Free the given synchronous request handler and all associated
164
+ * state.
165
+ *
166
+ * The handler must be dequeued and owned by the caller.
167
+ */
168
+static void
169
+vboxnetflt_sreq_free(struct vboxnetflt_sreq *sreq)
170
+{
171
+    if (sreq->resp != NULL)
172
+        NG_FREE_MSG(sreq->resp);
173
+
174
+    free(sreq, M_VBOXNETFLT);
175
+}
176
+
177
+
178
+
179
+/**
180
+ * Send a simple control message with no additional bytes, blocking until
181
+ * a response is received or a timeout is reached.
182
+ *
183
+ * On success, the caller assumes ownership of the response message, and
184
+ * is responsible for deallocating it via NG_FREE_MSG().
185
+ */
186
+int
187
+vboxnetflt_sreq_simple_rpc(PVBOXNETFLTINS pThis, node_p node, ng_ID_t peer,
188
+    uint32_t cookie, uint32_t cmd, struct ng_mesg **resp)
189
+{
190
+    struct ng_mesg *msg;
191
+    struct vboxnetflt_sreq *sr;
192
+    int error;
193
+
194
+    NG_MKMESSAGE(msg, cookie, cmd, 0, M_NOWAIT);
195
+    if (msg == NULL)
196
+        return (ENOMEM);
197
+
198
+    NG_SEND_MSG_ID(error, node, msg, peer, 0);
199
+    if (error) {
200
+        LogRel(("VBoxNetFlt: error sending netgraph message (cookie=%u, "
201
+            "cmd=%u) to [%x]\n", cookie, cmd, peer));
202
+        return (error);
203
+    }
204
+
205
+    mtx_lock(&pThis->u.s.sreq_lck);
206
+
207
+    /* Enqueue our response handler and wait for completion */
208
+    if ((sr = vboxnetflt_sreq_enqueue(pThis, cookie, cmd, 0)) == NULL) {
209
+        mtx_unlock(&pThis->u.s.sreq_lck);
210
+        return (ENOMEM);
211
+    }
212
+
213
+    error = vboxnetflt_sreq_wait_enqueued(pThis, sr,
214
+        NG_VBOXNETFLT_RPLY_TIMEOUT);
215
+
216
+    mtx_unlock(&pThis->u.s.sreq_lck);
217
+
218
+    if (error)
219
+        goto cleanup;
220
+
221
+    /* Transfer ownership of the message to the caller */
222
+    *resp = sr->resp;
223
+    sr->resp = NULL;
224
+
225
+    /* fallthrough to common cleanup */
226
+
227
+cleanup:
228
+    vboxnetflt_sreq_free(sr);
229
+    return (error);
230
+}
231
+
232
+/**
233
+ * Netgraph control message processing
234
+ */
235
 static int ng_vboxnetflt_rcvmsg(node_p node, item_p item, hook_p lasthook)
236
 {
237
     PVBOXNETFLTINS pThis = NG_NODE_PRIVATE(node);
238
     struct ng_mesg *msg;
239
-    int error = 0;
240
+    struct vboxnetflt_sreq *sreq;
241
+    int error;
242
 
243
     NGI_GET_MSG(item, msg);
244
-    if (msg->header.typecookie != NGM_VBOXNETFLT_COOKIE)
245
-        return (EINVAL);
246
 
247
-    switch (msg->header.cmd)
248
+    /* We don't accept any control messages of our own; drop anything that is
249
+     * not a message response. */
250
+    if (!(msg->header.flags & NGF_RESP))
251
     {
252
-        default:
253
-            error = EINVAL;
254
+        error = EINVAL;
255
+        goto failed;
256
     }
257
+
258
+    /* Deqeueue the first matching response handler, if any */
259
+    mtx_lock(&pThis->u.s.sreq_lck);
260
+    if ((sreq = vboxnetflt_sreq_dequeue(pThis, msg)) == NULL)
261
+    {
262
+        mtx_unlock(&pThis->u.s.sreq_lck);
263
+
264
+        LogRel(("VBoxNetFlt: dropping spurious netgraph reply (typecookie=%u, "
265
+            "cmd=%u, token=%u)\n", msg->header.typecookie, msg->header.cmd,
266
+            msg->header.token));
267
+
268
+        error = EINVAL;
269
+        goto failed;
270
+    }
271
+
272
+    /* Populate response data, transfering ownership of the message
273
+     * to the response handler. */
274
+    KASSERT(sreq->resp == NULL, ("request already completed"));
275
+    sreq->resp = msg;
276
+    msg = NULL;
277
+
278
+    /* Wake up any waiting threads */
279
+    mtx_unlock(&pThis->u.s.sreq_lck);
280
+    wakeup(sreq);
281
+
282
+    return (0);
283
+
284
+failed:
285
+    NG_FREE_MSG(msg);
286
     return (error);
287
 }
288
 
289
@@ -436,6 +657,8 @@
20
     struct ifnet *ifp = pThis->u.s.ifp;
290
     struct ifnet *ifp = pThis->u.s.ifp;
21
     unsigned int cSegs = 0;
291
     unsigned int cSegs = 0;
22
     bool fDropIt = false, fActive;
292
     bool fDropIt = false, fActive;
23
+    bool is_vl_tagged = false;
293
+    bool is_vl_tagged = false;
24
+    uint16_t vl_tag;
294
+    uint16_t vl_tag;
25
     PINTNETSG pSG;
295
     PINTNETSG pSG;
26
 
296
 
27
     VBOXCURVNET_SET(ifp->if_vnet);
297
     VBOXCURVNET_SET(ifp->if_vnet);
28
@@ -448,6 +452,19 @@ static void vboxNetFltFreeBSDinput(void *arg, int pend
298
@@ -448,6 +671,19 @@
29
         if (m == NULL)
299
         if (m == NULL)
30
             break;
300
             break;
31
 
301
 
32
+        /* Prepend a VLAN header for consumption by the virtual switch */
302
+        /* Prepend a VLAN header for consumption by the virtual switch */
33
+        if (m->m_flags & M_VLANTAG) {
303
+        if (m->m_flags & M_VLANTAG) {
34
+            vl_tag = m->m_pkthdr.ether_vtag;
304
+            vl_tag = m->m_pkthdr.ether_vtag;
35
+            is_vl_tagged = true;
305
+            is_vl_tagged = true;
36
+
306
+
37
+            m = ether_vlanencap(m, m->m_pkthdr.ether_vtag);
307
+            m = ether_vlanencap(m, m->m_pkthdr.ether_vtag);
38
+            if (m == NULL) {
308
+            if (m == NULL) {
39
+                printf("vboxflt: unable to prepend VLAN header\n");
309
+                printf("vboxflt: unable to prepend VLAN header\n");
40
+                break;
310
+                break;
41
+            }
311
+            }
42
+            m->m_flags &= ~M_VLANTAG;
312
+            m->m_flags &= ~M_VLANTAG;
43
+        }
313
+        }
44
+
314
+
45
         for (m0 = m; m0 != NULL; m0 = m0->m_next)
315
         for (m0 = m; m0 != NULL; m0 = m0->m_next)
46
             if (m0->m_len > 0)
316
             if (m0->m_len > 0)
47
                 cSegs++;
317
                 cSegs++;
48
@@ -462,6 +479,27 @@ static void vboxNetFltFreeBSDinput(void *arg, int pend
318
@@ -462,6 +698,27 @@
49
         vboxNetFltFreeBSDMBufToSG(pThis, m, pSG, cSegs, 0);
319
         vboxNetFltFreeBSDMBufToSG(pThis, m, pSG, cSegs, 0);
50
         fDropIt = pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, NULL /* pvIf */, pSG, INTNETTRUNKDIR_WIRE);
320
         fDropIt = pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, NULL /* pvIf */, pSG, INTNETTRUNKDIR_WIRE);
51
         RTMemTmpFree(pSG);
321
         RTMemTmpFree(pSG);
Lines 73-247 Link Here
73
         if (fDropIt)
343
         if (fDropIt)
74
             m_freem(m);
344
             m_freem(m);
75
         else
345
         else
76
@@ -521,6 +559,7 @@ static void vboxNetFltFreeBSDoutput(void *arg, int pen
346
@@ -521,6 +778,7 @@
77
  */
347
  */
78
 int vboxNetFltPortOsXmit(PVBOXNETFLTINS pThis, void *pvIfData, PINTNETSG pSG, uint32_t fDst)
348
 int vboxNetFltPortOsXmit(PVBOXNETFLTINS pThis, void *pvIfData, PINTNETSG pSG, uint32_t fDst)
79
 {
349
 {
80
+    IPRT_FREEBSD_SAVE_EFL_AC();
350
+    IPRT_FREEBSD_SAVE_EFL_AC();
81
     NOREF(pvIfData);
351
     NOREF(pvIfData);
82
 
352
 
83
     void (*input_f)(struct ifnet *, struct mbuf *);
353
     void (*input_f)(struct ifnet *, struct mbuf *);
84
@@ -537,10 +576,16 @@ int vboxNetFltPortOsXmit(PVBOXNETFLTINS pThis, void *p
354
@@ -537,10 +795,16 @@
85
     {
355
     {
86
         m = vboxNetFltFreeBSDSGMBufFromSG(pThis, pSG);
356
         m = vboxNetFltFreeBSDSGMBufFromSG(pThis, pSG);
87
         if (m == NULL)
357
         if (m == NULL)
88
+        {
358
+        {
89
+            IPRT_FREEBSD_RESTORE_EFL_AC();
359
+            IPRT_FREEBSD_RESTORE_EFL_AC();
90
             return VERR_NO_MEMORY;
360
             return VERR_NO_MEMORY;
91
+        }
361
+        }
92
         m = m_pullup(m, ETHER_HDR_LEN);
362
         m = m_pullup(m, ETHER_HDR_LEN);
93
         if (m == NULL)
363
         if (m == NULL)
94
+        {
364
+        {
95
+            IPRT_FREEBSD_RESTORE_EFL_AC();
365
+            IPRT_FREEBSD_RESTORE_EFL_AC();
96
             return VERR_NO_MEMORY;
366
             return VERR_NO_MEMORY;
97
+        }
367
+        }
98
 
368
 
99
         m->m_flags |= M_PKTHDR;
369
         m->m_flags |= M_PKTHDR;
100
         ether_output_frame(ifp, m);
370
         ether_output_frame(ifp, m);
101
@@ -550,10 +595,16 @@ int vboxNetFltPortOsXmit(PVBOXNETFLTINS pThis, void *p
371
@@ -550,10 +814,16 @@
102
     {
372
     {
103
         m = vboxNetFltFreeBSDSGMBufFromSG(pThis, pSG);
373
         m = vboxNetFltFreeBSDSGMBufFromSG(pThis, pSG);
104
         if (m == NULL)
374
         if (m == NULL)
105
+        {
375
+        {
106
+            IPRT_FREEBSD_RESTORE_EFL_AC();
376
+            IPRT_FREEBSD_RESTORE_EFL_AC();
107
             return VERR_NO_MEMORY;
377
             return VERR_NO_MEMORY;
108
+        }
378
+        }
109
         m = m_pullup(m, ETHER_HDR_LEN);
379
         m = m_pullup(m, ETHER_HDR_LEN);
110
         if (m == NULL)
380
         if (m == NULL)
111
+        {
381
+        {
112
+            IPRT_FREEBSD_RESTORE_EFL_AC();
382
+            IPRT_FREEBSD_RESTORE_EFL_AC();
113
             return VERR_NO_MEMORY;
383
             return VERR_NO_MEMORY;
114
+        }
384
+        }
115
         /*
385
         /*
116
          * Delivering packets to the host will be captured by the
386
          * Delivering packets to the host will be captured by the
117
          * input hook. Tag the packet with a mbuf tag so that we
387
          * input hook. Tag the packet with a mbuf tag so that we
118
@@ -564,6 +615,7 @@ int vboxNetFltPortOsXmit(PVBOXNETFLTINS pThis, void *p
388
@@ -564,6 +834,7 @@
119
         if (mtag == NULL)
389
         if (mtag == NULL)
120
         {
390
         {
121
             m_freem(m);
391
             m_freem(m);
122
+            IPRT_FREEBSD_RESTORE_EFL_AC();
392
+            IPRT_FREEBSD_RESTORE_EFL_AC();
123
             return VERR_NO_MEMORY;
393
             return VERR_NO_MEMORY;
124
         }
394
         }
125
 
395
 
126
@@ -574,6 +626,7 @@ int vboxNetFltPortOsXmit(PVBOXNETFLTINS pThis, void *p
396
@@ -574,6 +845,7 @@
127
         ifp->if_input(ifp, m);
397
         ifp->if_input(ifp, m);
128
     }
398
     }
129
     VBOXCURVNET_RESTORE();
399
     VBOXCURVNET_RESTORE();
130
+    IPRT_FREEBSD_RESTORE_EFL_AC();
400
+    IPRT_FREEBSD_RESTORE_EFL_AC();
131
     return VINF_SUCCESS;
401
     return VINF_SUCCESS;
132
 }
402
 }
133
 
403
 
134
@@ -586,6 +639,7 @@ static bool vboxNetFltFreeBsdIsPromiscuous(PVBOXNETFLT
404
@@ -584,9 +856,43 @@
405
     return (pThis->u.s.flags & IFF_PROMISC) ? true : false;
406
 }
135
 
407
 
408
+static bool vboxNetFltFreeBSDNodeName(const char *ifname, char *output, size_t len)
409
+{
410
+    size_t i;
411
+
412
+    /* rewrite all characters in netgraph's reserved set '[]:.' to '_' */
413
+    for (i = 0; i < len; i++)
414
+    {
415
+        char c = ifname[i];
416
+
417
+        switch (c)
418
+        {
419
+            case '[':
420
+            case ']':
421
+            case ':':
422
+            case '.':
423
+                output[i] = '_';
424
+                break;
425
+            default:
426
+                output[i] = c;
427
+                break;
428
+        }
429
+
430
+        if (c == '\0')
431
+            break;
432
+    }
433
+
434
+    if (ifname[i] != '\0')
435
+        return false;
436
+
437
+    return true;
438
+}
439
+
136
 int vboxNetFltOsInitInstance(PVBOXNETFLTINS pThis, void *pvContext)
440
 int vboxNetFltOsInitInstance(PVBOXNETFLTINS pThis, void *pvContext)
137
 {
441
 {
138
+    IPRT_FREEBSD_SAVE_EFL_AC();
442
+    IPRT_FREEBSD_SAVE_EFL_AC();
139
     char nam[NG_NODESIZ];
443
     char nam[NG_NODESIZ];
444
+    char nam_if[IFNAMSIZ];
140
     struct ifnet *ifp;
445
     struct ifnet *ifp;
141
     node_p node;
446
     node_p node;
142
@@ -594,7 +648,10 @@ int vboxNetFltOsInitInstance(PVBOXNETFLTINS pThis, voi
447
 
448
@@ -594,11 +900,27 @@
143
     NOREF(pvContext);
449
     NOREF(pvContext);
144
     ifp = ifunit(pThis->szName);
450
     ifp = ifunit(pThis->szName);
145
     if (ifp == NULL)
451
     if (ifp == NULL)
146
+    {
452
+    {
453
+        VBOXCURVNET_RESTORE();
147
+        IPRT_FREEBSD_RESTORE_EFL_AC();
454
+        IPRT_FREEBSD_RESTORE_EFL_AC();
148
         return VERR_INTNET_FLT_IF_NOT_FOUND;
455
         return VERR_INTNET_FLT_IF_NOT_FOUND;
149
+    }
456
+    }
150
 
457
 
458
+    /* Rewrite netgraph-reserved characters in the interface name to produce
459
+     * our node's name suffix */
460
+    if (!vboxNetFltFreeBSDNodeName(pThis->szName, nam_if, sizeof(nam_if)))
461
+    {
462
+        VBOXCURVNET_RESTORE();
463
+        IPRT_FREEBSD_RESTORE_EFL_AC();
464
+        return VERR_INTNET_FLT_IF_NOT_FOUND;
465
+    }
466
+
151
     /* Create a new netgraph node for this instance */
467
     /* Create a new netgraph node for this instance */
152
     if (ng_make_node_common(&ng_vboxnetflt_typestruct, &node) != 0)
468
-    if (ng_make_node_common(&ng_vboxnetflt_typestruct, &node) != 0)
153
@@ -638,12 +695,14 @@ int vboxNetFltOsInitInstance(PVBOXNETFLTINS pThis, voi
469
+    if (ng_make_node_common(&ng_vboxnetflt_typestruct, &node) != 0) {
470
+        VBOXCURVNET_RESTORE();
471
+        IPRT_FREEBSD_RESTORE_EFL_AC();
472
         return VERR_INTERNAL_ERROR;
473
+    }
474
 
475
     RTSpinlockAcquire(pThis->hSpinlock);
476
 
477
@@ -607,6 +929,10 @@
478
     bcopy(IF_LLADDR(ifp), &pThis->u.s.MacAddr, ETHER_ADDR_LEN);
479
     ASMAtomicUoWriteBool(&pThis->fDisconnectedFromHost, false);
480
 
481
+    /* Initialize synchronous request state */
482
+    mtx_init(&pThis->u.s.sreq_lck, "vboxnetflt ng_recv", NULL, MTX_DEF|MTX_NEW);
483
+    STAILQ_INIT(&pThis->u.s.sreq_list);
484
+
485
     /* Initialize deferred input queue */
486
     bzero(&pThis->u.s.inq, sizeof(struct ifqueue));
487
     mtx_init(&pThis->u.s.inq.ifq_mtx, "vboxnetflt inq", NULL, MTX_SPIN);
488
@@ -622,7 +948,7 @@
489
     NG_NODE_SET_PRIVATE(node, pThis);
490
 
491
     /* Attempt to name it vboxnetflt_<ifname> */
492
-    snprintf(nam, NG_NODESIZ, "vboxnetflt_%s", pThis->szName);
493
+    snprintf(nam, NG_NODESIZ, "vboxnetflt_%s", nam_if);
494
     ng_name_node(node, nam);
495
 
496
     /* Report MAC address, promiscuous mode and GSO capabilities. */
497
@@ -638,12 +964,14 @@
154
         vboxNetFltRelease(pThis, true /*fBusy*/);
498
         vboxNetFltRelease(pThis, true /*fBusy*/);
155
     }
499
     }
156
     VBOXCURVNET_RESTORE();
500
     VBOXCURVNET_RESTORE();
157
+    IPRT_FREEBSD_RESTORE_EFL_AC();
501
+    IPRT_FREEBSD_RESTORE_EFL_AC();
158
 
502
 
159
     return VINF_SUCCESS;
503
     return VINF_SUCCESS;
160
 }
504
 }
161
 
505
 
162
 bool vboxNetFltOsMaybeRediscovered(PVBOXNETFLTINS pThis)
506
 bool vboxNetFltOsMaybeRediscovered(PVBOXNETFLTINS pThis)
163
 {
507
 {
164
+    IPRT_FREEBSD_SAVE_EFL_AC();
508
+    IPRT_FREEBSD_SAVE_EFL_AC();
165
     struct ifnet *ifp, *ifp0;
509
     struct ifnet *ifp, *ifp0;
166
 
510
 
167
     ifp = ASMAtomicUoReadPtrT(&pThis->u.s.ifp, struct ifnet *);
511
     ifp = ASMAtomicUoReadPtrT(&pThis->u.s.ifp, struct ifnet *);
168
@@ -660,6 +719,7 @@ bool vboxNetFltOsMaybeRediscovered(PVBOXNETFLTINS pThi
512
@@ -660,6 +988,7 @@
169
         pThis->u.s.node = NULL;
513
         pThis->u.s.node = NULL;
170
     }
514
     }
171
     VBOXCURVNET_RESTORE();
515
     VBOXCURVNET_RESTORE();
172
+    IPRT_FREEBSD_RESTORE_EFL_AC();
516
+    IPRT_FREEBSD_RESTORE_EFL_AC();
173
 
517
 
174
     if (ifp0 != NULL)
518
     if (ifp0 != NULL)
175
     {
519
     {
176
@@ -672,6 +732,7 @@ bool vboxNetFltOsMaybeRediscovered(PVBOXNETFLTINS pThi
520
@@ -672,6 +1001,7 @@
177
 
521
 
178
 void vboxNetFltOsDeleteInstance(PVBOXNETFLTINS pThis)
522
 void vboxNetFltOsDeleteInstance(PVBOXNETFLTINS pThis)
179
 {
523
 {
180
+    IPRT_FREEBSD_SAVE_EFL_AC();
524
+    IPRT_FREEBSD_SAVE_EFL_AC();
181
 
525
 
182
     taskqueue_drain(taskqueue_fast, &pThis->u.s.tskin);
526
     taskqueue_drain(taskqueue_fast, &pThis->u.s.tskin);
183
     taskqueue_drain(taskqueue_fast, &pThis->u.s.tskout);
527
     taskqueue_drain(taskqueue_fast, &pThis->u.s.tskout);
184
@@ -684,6 +745,7 @@ void vboxNetFltOsDeleteInstance(PVBOXNETFLTINS pThis)
528
@@ -684,6 +1014,18 @@
185
         ng_rmnode_self(pThis->u.s.node);
529
         ng_rmnode_self(pThis->u.s.node);
186
     VBOXCURVNET_RESTORE();
530
     VBOXCURVNET_RESTORE();
187
     pThis->u.s.node = NULL;
531
     pThis->u.s.node = NULL;
532
+
533
+    /* Must be done *after* the node has been destroyed, as any incoming
534
+     * netgraph replies will need to acquire this lock. */
535
+    mtx_destroy(&pThis->u.s.sreq_lck);
536
+
537
+    /* Not possible unless a state management bug in VBoxNetFlt triggers
538
+     * instance deletion while also blocked in another thread on an active
539
+     * call into our instance */
540
+    KASSERT(STAILQ_EMPTY(&pThis->u.s.sreq_list),
541
+        ("incomplete synchronous netgraph requests"));
542
+
188
+    IPRT_FREEBSD_RESTORE_EFL_AC();
543
+    IPRT_FREEBSD_RESTORE_EFL_AC();
189
 }
544
 }
190
 
545
 
191
 int vboxNetFltOsPreInitInstance(PVBOXNETFLTINS pThis)
546
 int vboxNetFltOsPreInitInstance(PVBOXNETFLTINS pThis)
192
@@ -697,6 +759,7 @@ int vboxNetFltOsPreInitInstance(PVBOXNETFLTINS pThis)
547
@@ -695,95 +1037,323 @@
548
     return VINF_SUCCESS;
549
 }
193
 
550
 
194
 void vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, bool fActive)
551
-void vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, bool fActive)
552
+/**
553
+ * Fetch the list of netgraph nodes.
554
+ *
555
+ * On success, the caller assumes ownership of the list of node names, and
556
+ * is responsible for deallocating it via vboxNetFltFreeBSDFreeNodeList().
557
+ */
558
+int vboxNetFltFreeBSDListNodes(PVBOXNETFLTINS pThis, node_p node,
559
+    struct namelist **names)
195
 {
560
 {
196
+    IPRT_FREEBSD_SAVE_EFL_AC();
561
-    struct ifnet *ifp;
197
     struct ifnet *ifp;
562
-    struct ifreq ifreq;
198
     struct ifreq ifreq;
563
+    struct ng_mesg *msg;
564
+    struct namelist *nl;
565
+    size_t len, ni_len, ni_count;
199
     int error;
566
     int error;
200
@@ -730,7 +793,10 @@ void vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, b
567
-    node_p node;
201
         NG_MKMESSAGE(msg, NGM_GENERIC_COOKIE, NGM_CONNECT,
568
+
202
             sizeof(struct ngm_connect), M_NOWAIT);
569
+    /* Fetch the node list */
203
         if (msg == NULL)
570
+    error = vboxnetflt_sreq_simple_rpc(pThis, node, NG_NODE_ID(node),
204
+        {
571
+        NGM_GENERIC_COOKIE, NGM_LISTNODES, &msg);
205
+            IPRT_FREEBSD_RESTORE_EFL_AC();
572
+    if (error)
206
             return;
573
+    {
574
+        LogRel(("VBoxNetFlt: NGM_LISTNODES failed (%d)\n", error));
575
+        return error;
576
+    }
577
+
578
+    /* Must be at least large enough for the fixed entry count. */
579
+    nl = (struct namelist *)msg->data;
580
+    if (msg->header.arglen < sizeof(*nl)) {
581
+        error = ENXIO;
582
+        goto cleanup;
583
+    }
584
+
585
+    /* Must be large enough for the header + (numnames * sizeof(nodeinfo)) */
586
+    ni_count = nl->numnames;
587
+    ni_len = msg->header.arglen - sizeof(*nl);
588
+
589
+    if (SIZE_MAX / sizeof(nl->nodeinfo[0]) < ni_count) {
590
+        /* Would overflow */
591
+        error = ENXIO;
592
+        goto cleanup;
593
+    }
594
+
595
+    if (ni_len < (sizeof(nl->nodeinfo[0]) * ni_count)) {
596
+        error = ENXIO;
597
+        goto cleanup;
598
+    }
599
+
600
+    /* Copy out the result */
601
+    nl = malloc(msg->header.arglen, M_VBOXNETFLT, M_NOWAIT);
602
+    if (nl == NULL) {
603
+
604
+        error = ENOMEM;
605
+        goto cleanup;
606
+    }
607
+    memcpy(nl, msg->data, msg->header.arglen);
608
+
609
+    *names = nl;
610
+    error = 0;
611
+
612
+    /* fallthrough */
613
+
614
+cleanup:
615
+    NG_FREE_MSG(msg);
616
+    return (error);
617
+}
618
+
619
+int vboxNetFltFreeBSDFreeNodeList(struct namelist *names)
620
+{
621
+    free(names, M_VBOXNETFLT);
622
+}
623
+
624
+/**
625
+ * Fetch the interface name from an ng_ether node.
626
+ */
627
+int vboxNetFltFreeBSDEtherGetIfName(PVBOXNETFLTINS pThis, node_p node,
628
+    ng_ID_t ether_node, char *buf, size_t buflen)
629
+{
630
     struct ng_mesg *msg;
631
+    char *ifname;
632
+    size_t namelen;
633
+    int error;
634
+
635
+    /* Fetch the interface name */
636
+    error = vboxnetflt_sreq_simple_rpc(pThis, node, ether_node,
637
+        NGM_ETHER_COOKIE, NGM_ETHER_GET_IFNAME, &msg);
638
+    if (error)
639
+    {
640
+        /* May fail for innocuous reasons; e.g. if the node disappeared while
641
+         * iterating the node list, etc. */
642
+        Log(("VBoxNetFlt: NGM_ETHER_GET_IFNAME failed (%d)\n", error));
643
+        return (error);
644
+    }
645
+
646
+    ifname = (const char *)msg->data;
647
+    namelen = strnlen(ifname, msg->header.arglen);
648
+
649
+    /* Must be NUL-terminated */
650
+    if (namelen == msg->header.arglen) {
651
+        NG_FREE_MSG(msg);
652
+        return (ENXIO);
653
+    }
654
+
655
+    /* Copy out the result */
656
+    if (buflen < namelen+1) {
657
+        NG_FREE_MSG(msg);
658
+        return (ENOMEM);
659
+    }
660
+
661
+    strlcpy(buf, ifname, buflen);
662
+    NG_FREE_MSG(msg);
663
+
664
+    return (0);
665
+}
666
+
667
+/**
668
+ * Find the ng_ether node correspnding to our target interface.
669
+ */
670
+static int vboxNetFltFreeBSDFindEtherNode(PVBOXNETFLTINS pThis, node_p node,
671
+    ng_ID_t *id)
672
+{
673
+    struct namelist *nl;
674
+    int error;
675
+
676
+    /* Fetch the full node list */
677
+    if ((error = vboxNetFltFreeBSDListNodes(pThis, node, &nl))) {
678
+        LogRel(("VBoxNetFlt: failed to fetch node list (%d)\n", error));
679
+        return (error);
680
+    }
681
+
682
+    /* Look for a matching NG_ETHER node */
683
+    for (uint32_t i = 0; i < nl->numnames; i++) {
684
+        struct nodeinfo *ni;
685
+        char ifname[IF_NAMESIZE];
686
+
687
+        ni = &nl->nodeinfo[i];
688
+
689
+        /* We only care about ng_ether nodes */
690
+        if (strcmp(ni->type, NG_ETHER_NODE_TYPE) != 0)
691
+            continue;
692
+
693
+        /* Fetch the interface name */
694
+        error = vboxNetFltFreeBSDEtherGetIfName(pThis, node, ni->id, ifname,
695
+            sizeof(ifname));
696
+        if (error) {
697
+            Log(("VBoxNetFlt: failed to fetch interface name (%d)\n",
698
+                error));
699
+            continue;
207
+        }
700
+        }
208
         con = (struct ngm_connect *)msg->data;
701
+
209
         snprintf(con->path, NG_PATHSIZ, "vboxnetflt_%s:", ifp->if_xname);
702
+        /* Skip non-matching interfaces */
210
         strlcpy(con->ourhook, "lower", NG_HOOKSIZ);
703
+        if (strcmp(ifname, pThis->szName) != 0)
211
@@ -744,7 +810,10 @@ void vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, b
704
+            continue;
212
         NG_MKMESSAGE(msg, NGM_GENERIC_COOKIE, NGM_CONNECT,
705
+
213
             sizeof(struct ngm_connect), M_NOWAIT);
706
+        *id = ni->id;
214
         if (msg == NULL)
707
+        vboxNetFltFreeBSDFreeNodeList(nl);
215
+        {
708
+        return (0);
216
+            IPRT_FREEBSD_RESTORE_EFL_AC();
709
+    }
217
             return;
710
+
218
+        }
711
+    vboxNetFltFreeBSDFreeNodeList(nl);
219
         con = (struct ngm_connect *)msg->data;
712
+    return (ENOENT);
220
         snprintf(con->path, NG_PATHSIZ, "vboxnetflt_%s:",
713
+}
221
             ifp->if_xname);
714
+
222
@@ -767,7 +836,10 @@ void vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, b
715
+/**
223
         NG_MKMESSAGE(msg, NGM_GENERIC_COOKIE, NGM_RMHOOK,
716
+ * Send an NGM_CONNECT message.
224
             sizeof(struct ngm_rmhook), M_NOWAIT);
717
+ */
225
         if (msg == NULL)
718
+static int vboxNetFltFreeBSDConnectHook(PVBOXNETFLTINS pThis, node_p node,
226
+        {
719
+    ng_ID_t peer, const char *ourhook, const char *peerhook)
227
+            IPRT_FREEBSD_RESTORE_EFL_AC();
720
+{
228
             return;
721
+    struct ng_mesg *msg;
229
+        }
722
     struct ngm_connect *con;
230
         rm = (struct ngm_rmhook *)msg->data;
723
+    int error;
231
         strlcpy(rm->ourhook, "input", NG_HOOKSIZ);
724
+
232
         NG_SEND_MSG_PATH(error, node, msg, path, 0);
725
+    if (strlen(ourhook) > NG_HOOKSIZ || strlen(peerhook) > NG_HOOKSIZ)
233
@@ -778,12 +850,16 @@ void vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, b
726
+        return (EINVAL);
234
         NG_MKMESSAGE(msg, NGM_GENERIC_COOKIE, NGM_RMHOOK,
727
+
235
             sizeof(struct ngm_rmhook), M_NOWAIT);
728
+    NG_MKMESSAGE(msg, NGM_GENERIC_COOKIE, NGM_CONNECT,
236
         if (msg == NULL)
729
+        sizeof(struct ngm_connect), M_NOWAIT);
237
+        {
730
+    if (msg == NULL)
238
+            IPRT_FREEBSD_RESTORE_EFL_AC();
731
+        return (ENOMEM);
239
             return;
732
+
240
+        }
733
+    con = (struct ngm_connect *)msg->data;
241
         rm = (struct ngm_rmhook *)msg->data;
734
+    snprintf(con->path, NG_PATHSIZ, "[%x]:", NG_NODE_ID(node));
242
         strlcpy(rm->ourhook, "output", NG_HOOKSIZ);
735
+    strlcpy(con->ourhook, ourhook, NG_HOOKSIZ);
243
         NG_SEND_MSG_PATH(error, node, msg, path, 0);
736
+    strlcpy(con->peerhook, peerhook, NG_HOOKSIZ);
737
+
738
+    NG_SEND_MSG_ID(error, node, msg, peer, 0);
739
+    return (error);
740
+}
741
+
742
+/**
743
+ * Send an NGM_RMHOOK message.
744
+ */
745
+static int vboxNetFltFreeBSDRmHook(PVBOXNETFLTINS pThis, node_p node,
746
+    const char *ourhook)
747
+{
748
+    struct ng_mesg *msg;
749
     struct ngm_rmhook *rm;
750
-    char path[NG_PATHSIZ];
751
+    int error;
752
 
753
-    Log(("%s: fActive:%d\n", __func__, fActive));
754
+    if (strlen(ourhook) > NG_HOOKSIZ)
755
+        return (EINVAL);
756
 
757
-    ifp = ASMAtomicUoReadPtrT(&pThis->u.s.ifp, struct ifnet *);
758
-    VBOXCURVNET_SET(ifp->if_vnet);
759
-    node = ASMAtomicUoReadPtrT(&pThis->u.s.node, node_p);
760
+    NG_MKMESSAGE(msg, NGM_GENERIC_COOKIE, NGM_RMHOOK,
761
+        sizeof(struct ngm_rmhook), M_NOWAIT);
762
+    if (msg == NULL)
763
+        return (ENOMEM);
764
 
765
-    memset(&ifreq, 0, sizeof(struct ifreq));
766
-    /* Activate interface */
767
-    if (fActive)
768
-    {
769
-        pThis->u.s.flags = ifp->if_flags;
770
-        ifpromisc(ifp, 1);
771
+    rm = (struct ngm_rmhook *)msg->data;
772
+    strlcpy(rm->ourhook, ourhook, NG_HOOKSIZ);
773
 
774
-        /* ng_ether nodes are named after the interface name */
775
-        snprintf(path, sizeof(path), "%s:", ifp->if_xname);
776
+    NG_SEND_MSG_PATH(error, node, msg, ".:", 0);
777
+    return (error);
778
+}
779
 
780
-        /*
781
-         * Send a netgraph connect message to the ng_ether node
782
-         * assigned to the bridged interface. Connecting
783
-         * the hooks 'lower' (ng_ether) to out 'input'.
784
-         */
785
-        NG_MKMESSAGE(msg, NGM_GENERIC_COOKIE, NGM_CONNECT,
786
-            sizeof(struct ngm_connect), M_NOWAIT);
787
-        if (msg == NULL)
788
-            return;
789
-        con = (struct ngm_connect *)msg->data;
790
-        snprintf(con->path, NG_PATHSIZ, "vboxnetflt_%s:", ifp->if_xname);
791
-        strlcpy(con->ourhook, "lower", NG_HOOKSIZ);
792
-        strlcpy(con->peerhook, "input", NG_HOOKSIZ);
793
-        NG_SEND_MSG_PATH(error, node, msg, path, 0);
794
+/**
795
+ * Called by vboxNetFltPortOsSetActive() to activate the filter driver instance.
796
+ */
797
+static int vboxNetFltFreeBSDActivate(PVBOXNETFLTINS pThis, struct ifnet *ifp,
798
+    node_p node)
799
+{
800
+    ng_ID_t ether_node;
801
+    int error;
802
 
803
-        /*
804
-         * Do the same for the hooks 'upper' (ng_ether) and our
805
-         * 'output' hook.
806
-         */
807
-        NG_MKMESSAGE(msg, NGM_GENERIC_COOKIE, NGM_CONNECT,
808
-            sizeof(struct ngm_connect), M_NOWAIT);
809
-        if (msg == NULL)
810
-            return;
811
-        con = (struct ngm_connect *)msg->data;
812
-        snprintf(con->path, NG_PATHSIZ, "vboxnetflt_%s:",
813
-            ifp->if_xname);
814
-        strlcpy(con->ourhook, "upper", sizeof(con->ourhook));
815
-        strlcpy(con->peerhook, "output", sizeof(con->peerhook));
816
-        NG_SEND_MSG_PATH(error, node, msg, path, 0);
817
+    pThis->u.s.flags = ifp->if_flags;
818
+    ifpromisc(ifp, 1);
819
+
820
+    /* Locate the interface's corresponding NG_ETHER netgraph node */
821
+    if ((error = vboxNetFltFreeBSDFindEtherNode(pThis, node, &ether_node))) {
822
+        LogRel(("VBoxNetFlt: Failed to locate netgraph node for %s: %d\n",
823
+            ifp->if_xname, error));
824
+        return (error);
825
     }
826
-    else
827
-    {
828
-        /* De-activate interface */
829
-        pThis->u.s.flags = 0;
830
-        ifpromisc(ifp, 0);
831
 
832
-        /* Disconnect msgs are addressed to ourself */
833
-        snprintf(path, sizeof(path), "vboxnetflt_%s:", ifp->if_xname);
834
+    /*
835
+     * Send a netgraph connect message to the ng_ether node
836
+     * assigned to the bridged interface. Connecting
837
+     * the hooks 'lower' (ng_ether) to out 'input'.
838
+     */
839
+    error = vboxNetFltFreeBSDConnectHook(pThis, node, ether_node,
840
+        NG_ETHER_HOOK_LOWER, NG_VBOXNETFLT_HOOK_IN);
841
+    if (error) {
842
+        LogRel(("VBoxNetFlt: Failed to connect netgraph input hook for %s:"
843
+            " %d\n", ifp->if_xname, error));
844
+        return (error);
845
+    }
846
 
847
-        /*
848
-         * Send a netgraph message to disconnect our 'input' hook
849
-         */
850
-        NG_MKMESSAGE(msg, NGM_GENERIC_COOKIE, NGM_RMHOOK,
851
-            sizeof(struct ngm_rmhook), M_NOWAIT);
852
-        if (msg == NULL)
853
-            return;
854
-        rm = (struct ngm_rmhook *)msg->data;
855
-        strlcpy(rm->ourhook, "input", NG_HOOKSIZ);
856
-        NG_SEND_MSG_PATH(error, node, msg, path, 0);
857
+    /*
858
+     * Do the same for the hooks 'upper' (ng_ether) and our
859
+     * 'output' hook.
860
+     */
861
+    error = vboxNetFltFreeBSDConnectHook(pThis, node, ether_node,
862
+        NG_ETHER_HOOK_UPPER, NG_VBOXNETFLT_HOOK_OUT);
863
+    if (error) {
864
+        LogRel(("VBoxNetFlt: Failed to connect netgraph output hook for %s:"
865
+            " %d\n", ifp->if_xname, error));
866
+        return (error);
867
+    }
868
 
869
-        /*
870
-         * Send a netgraph message to disconnect our 'output' hook
871
-         */
872
-        NG_MKMESSAGE(msg, NGM_GENERIC_COOKIE, NGM_RMHOOK,
873
-            sizeof(struct ngm_rmhook), M_NOWAIT);
874
-        if (msg == NULL)
875
-            return;
876
-        rm = (struct ngm_rmhook *)msg->data;
877
-        strlcpy(rm->ourhook, "output", NG_HOOKSIZ);
878
-        NG_SEND_MSG_PATH(error, node, msg, path, 0);
879
+    return (0);
880
+}
881
+
882
+/**
883
+ * Called by vboxNetFltPortOsSetActive() to deactivate the filter driver
884
+ * instance.
885
+ */
886
+static int vboxNetFltFreeBSDDeactivate(PVBOXNETFLTINS pThis, struct ifnet *ifp,
887
+    node_p node)
888
+{
889
+    int ng_error;
890
+    int error = 0;
891
+
892
+    pThis->u.s.flags = 0;
893
+    ifpromisc(ifp, 0);
894
+
895
+    /*
896
+     * Send a netgraph message to disconnect our input and output hooks; on
897
+     * failure, we still attempt to disconnect any remaining hooks.
898
+     */
899
+    ng_error = vboxNetFltFreeBSDRmHook(pThis, node, NG_VBOXNETFLT_HOOK_IN);
900
+    if (ng_error) {
901
+        LogRel(("VBoxNetFlt: Failed to disconnect netgraph input hook for %s:"
902
+            " %d\n", ifp->if_xname, error));
903
+        error = ng_error;
244
     }
904
     }
905
+
906
+    ng_error = vboxNetFltFreeBSDRmHook(pThis, node, NG_VBOXNETFLT_HOOK_OUT);
907
+    if (ng_error) {
908
+        LogRel(("VBoxNetFlt: Failed to disconnect netgraph output hook for %s:"
909
+            " %d\n", ifp->if_xname, error));
910
+        error = ng_error;
911
+    }
912
+
913
+    return (error);
914
+}
915
+
916
+void vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, bool fActive)
917
+{
918
+    IPRT_FREEBSD_SAVE_EFL_AC();
919
+    struct ifnet *ifp;
920
+    int error;
921
+    node_p node;
922
+
923
+    Log(("%s: fActive:%d\n", __func__, fActive));
924
+
925
+    ifp = ASMAtomicUoReadPtrT(&pThis->u.s.ifp, struct ifnet *);
926
+    VBOXCURVNET_SET(ifp->if_vnet);
927
+    node = ASMAtomicUoReadPtrT(&pThis->u.s.node, node_p);
928
+
929
+    if (fActive)
930
+        error = vboxNetFltFreeBSDActivate(pThis, ifp, node);
931
+    else
932
+        error = vboxNetFltFreeBSDDeactivate(pThis, ifp, node);
933
+
934
+    if (error) 
935
+        LogRel(("VBoxNetFlt: Failed to %s %s filter driver: %d\n",
936
+            (fActive ? "activate" : "deactivate"), ifp->if_xname, error));
937
+
245
     VBOXCURVNET_RESTORE();
938
     VBOXCURVNET_RESTORE();
246
+    IPRT_FREEBSD_RESTORE_EFL_AC();
939
+    IPRT_FREEBSD_RESTORE_EFL_AC();
247
 }
940
 }

Return to bug 242637