summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/net/if.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/net/if.c')
-rw-r--r--freebsd/sys/net/if.c128
1 files changed, 61 insertions, 67 deletions
diff --git a/freebsd/sys/net/if.c b/freebsd/sys/net/if.c
index d57e6983..37e1581b 100644
--- a/freebsd/sys/net/if.c
+++ b/freebsd/sys/net/if.c
@@ -34,6 +34,7 @@
* $FreeBSD$
*/
+#include <rtems/bsd/local/opt_bpf.h>
#include <rtems/bsd/local/opt_inet6.h>
#include <rtems/bsd/local/opt_inet.h>
@@ -1253,16 +1254,20 @@ static void
if_vmove(struct ifnet *ifp, struct vnet *new_vnet)
{
struct if_clone *ifc;
+#ifdef DEV_BPF
u_int bif_dlt, bif_hdrlen;
+#endif
void *old;
int rc;
+#ifdef DEV_BPF
/*
* if_detach_internal() will call the eventhandler to notify
* interface departure. That will detach if_bpf. We need to
* safe the dlt and hdrlen so we can re-attach it later.
*/
bpf_get_bp_params(ifp->if_bpf, &bif_dlt, &bif_hdrlen);
+#endif
/*
* Detach from current vnet, but preserve LLADDR info, do not
@@ -1309,8 +1314,10 @@ if_vmove(struct ifnet *ifp, struct vnet *new_vnet)
if_attach_internal(ifp, 1, ifc);
+#ifdef DEV_BPF
if (ifp->if_bpf == NULL)
bpfattach(ifp, bif_dlt, bif_hdrlen);
+#endif
CURVNET_RESTORE();
}
@@ -1447,14 +1454,12 @@ if_addgroup(struct ifnet *ifp, const char *groupname)
return (EEXIST);
}
- if ((ifgl = (struct ifg_list *)malloc(sizeof(struct ifg_list), M_TEMP,
- M_NOWAIT)) == NULL) {
+ if ((ifgl = malloc(sizeof(*ifgl), M_TEMP, M_NOWAIT)) == NULL) {
IFNET_WUNLOCK();
return (ENOMEM);
}
- if ((ifgm = (struct ifg_member *)malloc(sizeof(struct ifg_member),
- M_TEMP, M_NOWAIT)) == NULL) {
+ if ((ifgm = malloc(sizeof(*ifgm), M_TEMP, M_NOWAIT)) == NULL) {
free(ifgl, M_TEMP);
IFNET_WUNLOCK();
return (ENOMEM);
@@ -1465,8 +1470,7 @@ if_addgroup(struct ifnet *ifp, const char *groupname)
break;
if (ifg == NULL) {
- if ((ifg = (struct ifg_group *)malloc(sizeof(struct ifg_group),
- M_TEMP, M_NOWAIT)) == NULL) {
+ if ((ifg = malloc(sizeof(*ifg), M_TEMP, M_NOWAIT)) == NULL) {
free(ifgl, M_TEMP);
free(ifgm, M_TEMP);
IFNET_WUNLOCK();
@@ -1498,39 +1502,36 @@ if_addgroup(struct ifnet *ifp, const char *groupname)
}
/*
- * Remove a group from an interface
+ * Helper function to remove a group out of an interface. Expects the global
+ * ifnet lock to be write-locked, and drops it before returning.
*/
-int
-if_delgroup(struct ifnet *ifp, const char *groupname)
+static void
+_if_delgroup_locked(struct ifnet *ifp, struct ifg_list *ifgl,
+ const char *groupname)
{
- struct ifg_list *ifgl;
- struct ifg_member *ifgm;
- int freeifgl;
+ struct ifg_member *ifgm;
+ bool freeifgl;
- IFNET_WLOCK();
- CK_STAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next)
- if (!strcmp(ifgl->ifgl_group->ifg_group, groupname))
- break;
- if (ifgl == NULL) {
- IFNET_WUNLOCK();
- return (ENOENT);
- }
+ IFNET_WLOCK_ASSERT();
- freeifgl = 0;
IF_ADDR_WLOCK(ifp);
CK_STAILQ_REMOVE(&ifp->if_groups, ifgl, ifg_list, ifgl_next);
IF_ADDR_WUNLOCK(ifp);
- CK_STAILQ_FOREACH(ifgm, &ifgl->ifgl_group->ifg_members, ifgm_next)
- if (ifgm->ifgm_ifp == ifp)
+ CK_STAILQ_FOREACH(ifgm, &ifgl->ifgl_group->ifg_members, ifgm_next) {
+ if (ifgm->ifgm_ifp == ifp) {
+ CK_STAILQ_REMOVE(&ifgl->ifgl_group->ifg_members, ifgm,
+ ifg_member, ifgm_next);
break;
-
- if (ifgm != NULL)
- CK_STAILQ_REMOVE(&ifgl->ifgl_group->ifg_members, ifgm, ifg_member, ifgm_next);
+ }
+ }
if (--ifgl->ifgl_group->ifg_refcnt == 0) {
- CK_STAILQ_REMOVE(&V_ifg_head, ifgl->ifgl_group, ifg_group, ifg_next);
- freeifgl = 1;
+ CK_STAILQ_REMOVE(&V_ifg_head, ifgl->ifgl_group, ifg_group,
+ ifg_next);
+ freeifgl = true;
+ } else {
+ freeifgl = false;
}
IFNET_WUNLOCK();
@@ -1543,6 +1544,26 @@ if_delgroup(struct ifnet *ifp, const char *groupname)
free(ifgl, M_TEMP);
EVENTHANDLER_INVOKE(group_change_event, groupname);
+}
+
+/*
+ * Remove a group from an interface
+ */
+int
+if_delgroup(struct ifnet *ifp, const char *groupname)
+{
+ struct ifg_list *ifgl;
+
+ IFNET_WLOCK();
+ CK_STAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next)
+ if (strcmp(ifgl->ifgl_group->ifg_group, groupname) == 0)
+ break;
+ if (ifgl == NULL) {
+ IFNET_WUNLOCK();
+ return (ENOENT);
+ }
+
+ _if_delgroup_locked(ifp, ifgl, groupname);
return (0);
}
@@ -1553,44 +1574,13 @@ if_delgroup(struct ifnet *ifp, const char *groupname)
static void
if_delgroups(struct ifnet *ifp)
{
- struct ifg_list *ifgl;
- struct ifg_member *ifgm;
+ struct ifg_list *ifgl;
char groupname[IFNAMSIZ];
- int ifglfree;
IFNET_WLOCK();
- while (!CK_STAILQ_EMPTY(&ifp->if_groups)) {
- ifgl = CK_STAILQ_FIRST(&ifp->if_groups);
-
+ while ((ifgl = CK_STAILQ_FIRST(&ifp->if_groups)) != NULL) {
strlcpy(groupname, ifgl->ifgl_group->ifg_group, IFNAMSIZ);
-
- IF_ADDR_WLOCK(ifp);
- CK_STAILQ_REMOVE(&ifp->if_groups, ifgl, ifg_list, ifgl_next);
- IF_ADDR_WUNLOCK(ifp);
-
- CK_STAILQ_FOREACH(ifgm, &ifgl->ifgl_group->ifg_members, ifgm_next)
- if (ifgm->ifgm_ifp == ifp)
- break;
-
- if (ifgm != NULL)
- CK_STAILQ_REMOVE(&ifgl->ifgl_group->ifg_members, ifgm, ifg_member,
- ifgm_next);
- ifglfree = 0;
- if (--ifgl->ifgl_group->ifg_refcnt == 0) {
- CK_STAILQ_REMOVE(&V_ifg_head, ifgl->ifgl_group, ifg_group, ifg_next);
- ifglfree = 1;
- }
-
- IFNET_WUNLOCK();
- epoch_wait_preempt(net_epoch_preempt);
- free(ifgm, M_TEMP);
- if (ifglfree) {
- EVENTHANDLER_INVOKE(group_detach_event,
- ifgl->ifgl_group);
- free(ifgl->ifgl_group, M_TEMP);
- }
- EVENTHANDLER_INVOKE(group_change_event, groupname);
-
+ _if_delgroup_locked(ifp, ifgl, groupname);
IFNET_WLOCK();
}
IFNET_WUNLOCK();
@@ -1678,7 +1668,7 @@ if_getgroupmembers(struct ifgroupreq *ifgr)
IFNET_RLOCK();
CK_STAILQ_FOREACH(ifg, &V_ifg_head, ifg_next)
- if (!strcmp(ifg->ifg_group, ifgr->ifgr_name))
+ if (strcmp(ifg->ifg_group, ifgr->ifgr_name) == 0)
break;
if (ifg == NULL) {
IFNET_RUNLOCK();
@@ -1957,10 +1947,13 @@ ifa_maintain_loopback_route(int cmd, const char *otype, struct ifaddr *ifa,
error = rtrequest1_fib(cmd, &info, NULL, ifp->if_fib);
- if (error != 0 &&
- !(cmd == RTM_ADD && error == EEXIST) &&
- !(cmd == RTM_DELETE && error == ENOENT))
- if_printf(ifp, "%s failed: %d\n", otype, error);
+ if (error == 0 ||
+ (cmd == RTM_ADD && error == EEXIST) ||
+ (cmd == RTM_DELETE && (error == ENOENT || error == ESRCH)))
+ return (error);
+
+ log(LOG_DEBUG, "%s: %s failed for interface %s: %u\n",
+ __func__, otype, if_name(ifp), error);
return (error);
}
@@ -2951,6 +2944,7 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
case SIOCGIFGENERIC:
case SIOCGIFRSSKEY:
case SIOCGIFRSSHASH:
+ case SIOCGIFDOWNREASON:
if (ifp->if_ioctl == NULL)
return (EOPNOTSUPP);
error = (*ifp->if_ioctl)(ifp, cmd, data);