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

Return to bug 242637