+
+static
+int dlil_recycle_ioctl(struct ifnet *ifnet_ptr, u_long ioctl_code, void *ioctl_arg)
+{
+
+ return EOPNOTSUPP;
+}
+
+static
+int dlil_recycle_output(struct ifnet *ifnet_ptr, struct mbuf *m)
+{
+
+ m_freem(m);
+ return 0;
+}
+
+static
+int dlil_recycle_free(struct ifnet *ifnet_ptr)
+{
+ return 0;
+}
+
+static
+int dlil_recycle_set_bpf_tap(struct ifnet *ifp, int mode,
+ int (*bpf_callback)(struct ifnet *, struct mbuf *))
+{
+ /* XXX not sure what to do here */
+ return 0;
+}
+
+int dlil_if_acquire(u_long family, void *uniqueid, size_t uniqueid_len,
+ struct ifnet **ifp)
+{
+ struct ifnet *ifp1 = NULL;
+ struct dlil_ifnet *dlifp1 = NULL;
+ int s, ret = 0;
+ boolean_t funnel_state;
+
+ funnel_state = thread_funnel_set(network_flock, TRUE);
+ s = splnet();
+
+ TAILQ_FOREACH(dlifp1, &dlil_ifnet_head, dl_if_link) {
+
+ ifp1 = (struct ifnet *)dlifp1;
+
+ if (ifp1->if_family == family) {
+
+ /* same uniqueid and same len or no unique id specified */
+ if ((uniqueid_len == dlifp1->if_uniqueid_len)
+ && !bcmp(uniqueid, dlifp1->if_uniqueid, uniqueid_len)) {
+
+ /* check for matching interface in use */
+ if (ifp1->if_eflags & IFEF_INUSE) {
+ if (uniqueid_len) {
+ ret = EBUSY;
+ goto end;
+ }
+ }
+ else {
+
+ ifp1->if_eflags |= (IFEF_INUSE + IFEF_REUSE);
+ *ifp = ifp1;
+ goto end;
+ }
+ }
+ }
+ }
+
+ /* no interface found, allocate a new one */
+ MALLOC(dlifp1, struct dlil_ifnet *, sizeof(*dlifp1), M_NKE, M_WAITOK);
+ if (dlifp1 == 0) {
+ ret = ENOMEM;
+ goto end;
+ }
+
+ bzero(dlifp1, sizeof(*dlifp1));
+
+ if (uniqueid_len) {
+ MALLOC(dlifp1->if_uniqueid, void *, uniqueid_len, M_NKE, M_WAITOK);
+ if (dlifp1->if_uniqueid == 0) {
+ FREE(dlifp1, M_NKE);
+ ret = ENOMEM;
+ goto end;
+ }
+ bcopy(uniqueid, dlifp1->if_uniqueid, uniqueid_len);
+ dlifp1->if_uniqueid_len = uniqueid_len;
+ }
+
+ ifp1 = (struct ifnet *)dlifp1;
+ ifp1->if_eflags |= IFEF_INUSE;
+
+ TAILQ_INSERT_TAIL(&dlil_ifnet_head, dlifp1, dl_if_link);
+
+ *ifp = ifp1;
+
+end:
+
+ splx(s);
+ thread_funnel_set(network_flock, funnel_state);
+ return ret;
+}
+
+void dlil_if_release(struct ifnet *ifp)
+{
+ struct dlil_ifnet *dlifp = (struct dlil_ifnet *)ifp;
+ int s;
+ boolean_t funnel_state;
+
+ funnel_state = thread_funnel_set(network_flock, TRUE);
+ s = splnet();
+
+ ifp->if_eflags &= ~IFEF_INUSE;
+ ifp->if_ioctl = dlil_recycle_ioctl;
+ ifp->if_output = dlil_recycle_output;
+ ifp->if_free = dlil_recycle_free;
+ ifp->if_set_bpf_tap = dlil_recycle_set_bpf_tap;
+
+ strncpy(dlifp->if_namestorage, ifp->if_name, IFNAMSIZ);
+ ifp->if_name = dlifp->if_namestorage;
+
+ splx(s);
+ thread_funnel_set(network_flock, funnel_state);
+}
+