-.\" $OpenBSD: if_get.9,v 1.2 2015/12/08 18:35:51 jmc Exp $
+.\" $OpenBSD: if_get.9,v 1.3 2021/01/18 09:55:43 mvs Exp $
.\"
.\" Copyright (c) 2015 Martin Pieuchot
.\"
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: December 8 2015 $
+.Dd $Mdocdate: January 18 2021 $
.Dt IF_GET 9
.Os
.Sh NAME
.Nm if_get ,
+.Nm if_unit ,
.Nm if_put
.Nd get an interface pointer from an interface index
.Sh SYNOPSIS
.In net/if.h
.Ft struct ifnet *
.Fn if_get "unsigned int ifidx"
+.Ft struct ifnet *
+.Fn if_unit "const char *name"
.Ft void
.Fn if_put "struct ifnet *ifp"
.Sh DESCRIPTION
an interface index is valid or not.
.Pp
The
+.Fn if_unit
+function returns a pointer to the interface descriptor corresponding to the
+unique name
+.Fa name .
+This descriptor is guaranteed to be valid until
+.Fn if_put
+is called on the returned pointer.
+.Pp
+The
.Fn if_put
function releases a reference on the interface descriptor pointed by
.Fa ifp .
pointer, no action occurs.
.Sh CONTEXT
.Fn if_get ,
+.Fn if_unit
and
.Fn if_put
can be called during autoconf, from process context, or from interrupt context.
.Fn if_get
returns a pointer to an interface descriptor if the index is valid, otherwise
.Dv NULL .
+.Pp
+.Fn if_unit
+returns a pointer to an interface descriptor if the interface with present
+name exists, otherwise
+.Dv NULL .
-/* $OpenBSD: if.c,v 1.624 2021/01/09 14:55:21 bluhm Exp $ */
+/* $OpenBSD: if.c,v 1.625 2021/01/18 09:55:43 mvs Exp $ */
/* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */
/*
void if_attachsetup(struct ifnet *);
void if_attachdomain(struct ifnet *);
void if_attach_common(struct ifnet *);
+void if_remove(struct ifnet *);
int if_createrdomain(int, struct ifnet *);
int if_setrdomain(struct ifnet *, int);
void if_slowtimo(void *);
srp_update_locked(&if_ifp_gc, &map[index], NULL);
if_idxmap.count--;
/* end of if_idxmap modifications */
-
- /* sleep until the last reference is released */
- refcnt_finalize(&ifp->if_refcnt, "ifidxrm");
}
void
mtx_leave(&if_hooks_mtx);
}
+void
+if_remove(struct ifnet *ifp)
+{
+ /* Remove the interface from the list of all interfaces. */
+ NET_LOCK();
+ TAILQ_REMOVE(&ifnet, ifp, if_list);
+ NET_UNLOCK();
+
+ /* Remove the interface from the interface index map. */
+ if_idxmap_remove(ifp);
+
+ /* Sleep until the last reference is released. */
+ refcnt_finalize(&ifp->if_refcnt, "ifrm");
+}
+
void
if_deactivate(struct ifnet *ifp)
{
/* Undo pseudo-driver changes. */
if_deactivate(ifp);
- ifq_clr_oactive(&ifp->if_snd);
-
/* Other CPUs must not have a reference before we start destroying. */
- if_idxmap_remove(ifp);
+ if_remove(ifp);
+
+ ifq_clr_oactive(&ifp->if_snd);
#if NBPFILTER > 0
bpfdetach(ifp);
pfi_detach_ifnet(ifp);
#endif
- /* Remove the interface from the list of all interfaces. */
- TAILQ_REMOVE(&ifnet, ifp, if_list);
-
while ((ifg = TAILQ_FIRST(&ifp->if_groups)) != NULL)
if_delgroup(ifp, ifg->ifgl_group->ifg_group);
rw_enter_write(&if_cloners_lock);
- if (ifunit(name) != NULL) {
+ if ((ifp = if_unit(name)) != NULL) {
ret = EEXIST;
goto unlock;
}
ret = (*ifc->ifc_create)(ifc, unit);
- if (ret != 0 || (ifp = ifunit(name)) == NULL)
+ if (ret != 0 || (ifp = if_unit(name)) == NULL)
goto unlock;
NET_LOCK();
NET_UNLOCK();
unlock:
rw_exit_write(&if_cloners_lock);
+ if_put(ifp);
return (ret);
}
rw_enter_write(&if_cloners_lock);
- ifp = ifunit(name);
+ TAILQ_FOREACH(ifp, &ifnet, if_list) {
+ if (strcmp(ifp->if_xname, name) == 0)
+ break;
+ }
if (ifp == NULL) {
rw_exit_write(&if_cloners_lock);
return (ENXIO);
}
/*
- * Map interface name to interface structure pointer.
+ * Map interface name to interface structure pointer (legacy).
*/
struct ifnet *
ifunit(const char *name)
return (NULL);
}
+/*
+ * Map interface name to interface structure pointer.
+ */
+struct ifnet *
+if_unit(const char *name)
+{
+ struct ifnet *ifp;
+
+ if ((ifp = ifunit(name)) != NULL)
+ if_ref(ifp);
+
+ return (ifp);
+}
+
/*
* Map interface index to interface structure pointer.
*/
/* Create rdomain including its loopback if with unit == rdomain */
snprintf(loifname, sizeof(loifname), "lo%u", unit);
error = if_clone_create(loifname, 0);
- if ((loifp = ifunit(loifname)) == NULL)
+ if ((loifp = if_unit(loifname)) == NULL)
return (ENXIO);
- if (error && (ifp != loifp || error != EEXIST))
+ if (error && (ifp != loifp || error != EEXIST)) {
+ if_put(loifp);
return (error);
+ }
rtable_l2set(rdomain, rdomain, loifp->if_index);
loifp->if_rdomain = rdomain;
+ if_put(loifp);
return (0);
}
return (ifioctl_get(cmd, data));
}
- ifp = ifunit(ifr->ifr_name);
+ ifp = if_unit(ifr->ifr_name);
if (ifp == NULL)
return (ENXIO);
oif_flags = ifp->if_flags;
if (((oif_flags ^ ifp->if_flags) & IFF_UP) != 0)
getmicrotime(&ifp->if_lastchange);
+ if_put(ifp);
+
return (error);
}
return (error);
}
- ifp = ifunit(ifr->ifr_name);
+ ifp = if_unit(ifr->ifr_name);
if (ifp == NULL)
return (ENXIO);
NET_RUNLOCK_IN_IOCTL();
+ if_put(ifp);
+
return (error);
}