summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--share/man/man9/if_get.922
-rw-r--r--sys/net/if.c71
-rw-r--r--sys/net/if.h3
3 files changed, 75 insertions, 21 deletions
diff --git a/share/man/man9/if_get.9 b/share/man/man9/if_get.9
index 5174d7c2676..4138c747f39 100644
--- a/share/man/man9/if_get.9
+++ b/share/man/man9/if_get.9
@@ -1,4 +1,4 @@
-.\" $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
.\"
@@ -14,17 +14,20 @@
.\" 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
@@ -43,6 +46,15 @@ is never associated with an interface descriptor and can be used to determine if
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 .
@@ -53,6 +65,7 @@ is a
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.
@@ -60,3 +73,8 @@ 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 .
diff --git a/sys/net/if.c b/sys/net/if.c
index 0206594d787..50d1e1d2a6b 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -1,4 +1,4 @@
-/* $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 $ */
/*
@@ -134,6 +134,7 @@
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 *);
@@ -386,9 +387,6 @@ if_idxmap_remove(struct ifnet *ifp)
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
@@ -951,6 +949,21 @@ if_hooks_run(struct task_list *hooks)
}
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)
{
/*
@@ -995,10 +1008,10 @@ if_detach(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);
@@ -1033,9 +1046,6 @@ if_detach(struct ifnet *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);
@@ -1141,14 +1151,14 @@ if_clone_create(const char *name, int rdomain)
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();
@@ -1158,6 +1168,7 @@ if_clone_create(const char *name, int rdomain)
NET_UNLOCK();
unlock:
rw_exit_write(&if_cloners_lock);
+ if_put(ifp);
return (ret);
}
@@ -1181,7 +1192,10 @@ if_clone_destroy(const char *name)
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);
@@ -1640,7 +1654,7 @@ if_watchdog_task(void *xifidx)
}
/*
- * Map interface name to interface structure pointer.
+ * Map interface name to interface structure pointer (legacy).
*/
struct ifnet *
ifunit(const char *name)
@@ -1657,6 +1671,20 @@ ifunit(const char *name)
}
/*
+ * 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.
*/
struct ifnet *
@@ -1727,13 +1755,16 @@ if_createrdomain(int rdomain, struct ifnet *ifp)
/* 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);
}
@@ -1856,7 +1887,7 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p)
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;
@@ -2214,6 +2245,8 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p)
if (((oif_flags ^ ifp->if_flags) & IFF_UP) != 0)
getmicrotime(&ifp->if_lastchange);
+ if_put(ifp);
+
return (error);
}
@@ -2254,7 +2287,7 @@ ifioctl_get(u_long cmd, caddr_t data)
return (error);
}
- ifp = ifunit(ifr->ifr_name);
+ ifp = if_unit(ifr->ifr_name);
if (ifp == NULL)
return (ENXIO);
@@ -2328,6 +2361,8 @@ ifioctl_get(u_long cmd, caddr_t data)
NET_RUNLOCK_IN_IOCTL();
+ if_put(ifp);
+
return (error);
}
diff --git a/sys/net/if.h b/sys/net/if.h
index 8f8892d6a03..48a7417955f 100644
--- a/sys/net/if.h
+++ b/sys/net/if.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if.h,v 1.204 2020/09/30 19:22:51 mvs Exp $ */
+/* $OpenBSD: if.h,v 1.205 2021/01/18 09:55:43 mvs Exp $ */
/* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */
/*
@@ -546,6 +546,7 @@ int if_addgroup(struct ifnet *, const char *);
int if_delgroup(struct ifnet *, const char *);
void if_group_routechange(struct sockaddr *, struct sockaddr *);
struct ifnet *ifunit(const char *);
+struct ifnet *if_unit(const char *);
struct ifnet *if_get(unsigned int);
void if_put(struct ifnet *);
void ifnewlladdr(struct ifnet *);