Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Make usages of ifp MP-safe in some functions of IP multi...
details: https://anonhg.NetBSD.org/src/rev/b5fb11dd0c8b
branches: trunk
changeset: 351865:b5fb11dd0c8b
user: ozaki-r <ozaki-r%NetBSD.org@localhost>
date: Thu Mar 02 05:24:23 2017 +0000
description:
Make usages of ifp MP-safe in some functions of IP multicast
diffstat:
sys/netinet/ip_output.c | 106 +++++++++++++++++++++++++++++++++------------
sys/netinet6/ip6_output.c | 50 ++++++++++++++------
sys/netinet6/ip6_var.h | 6 +-
3 files changed, 115 insertions(+), 47 deletions(-)
diffs (truncated from 426 to 300 lines):
diff -r e8c726b9acff -r b5fb11dd0c8b sys/netinet/ip_output.c
--- a/sys/netinet/ip_output.c Thu Mar 02 04:33:56 2017 +0000
+++ b/sys/netinet/ip_output.c Thu Mar 02 05:24:23 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ip_output.c,v 1.272 2017/02/22 07:05:04 ozaki-r Exp $ */
+/* $NetBSD: ip_output.c,v 1.273 2017/03/02 05:24:23 ozaki-r Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -91,7 +91,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.272 2017/02/22 07:05:04 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.273 2017/03/02 05:24:23 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -1444,6 +1444,7 @@
/*
* following RFC1724 section 3.3, 0.0.0.0/8 is interpreted as interface index.
+ * Must be called in a pserialize critical section.
*/
static struct ifnet *
ip_multicast_if(struct in_addr *a, int *ifindexp)
@@ -1462,10 +1463,12 @@
if (ifindexp)
*ifindexp = ifindex;
} else {
- LIST_FOREACH(ia, &IN_IFADDR_HASH(a->s_addr), ia_hash) {
+ IN_ADDRHASH_READER_FOREACH(ia, a->s_addr) {
if (in_hosteq(ia->ia_addr.sin_addr, *a) &&
(ia->ia_ifp->if_flags & IFF_MULTICAST) != 0) {
ifp = ia->ia_ifp;
+ if (if_is_deactivated(ifp))
+ ifp = NULL;
break;
}
}
@@ -1509,7 +1512,7 @@
static int
ip_get_membership(const struct sockopt *sopt, struct ifnet **ifp,
- struct in_addr *ia, bool add)
+ struct psref *psref, struct in_addr *ia, bool add)
{
int error;
struct ip_mreq mreq;
@@ -1546,12 +1549,28 @@
if (error != 0)
return error;
*ifp = (rt = rtcache_init(&ro)) != NULL ? rt->rt_ifp : NULL;
+ if (*ifp != NULL) {
+ if (if_is_deactivated(*ifp))
+ *ifp = NULL;
+ else
+ if_acquire(*ifp, psref);
+ }
rtcache_unref(rt, &ro);
rtcache_free(&ro);
} else {
+ int s = pserialize_read_enter();
*ifp = ip_multicast_if(&mreq.imr_interface, NULL);
- if (!add && *ifp == NULL)
+ if (!add && *ifp == NULL) {
+ pserialize_read_exit(s);
return EADDRNOTAVAIL;
+ }
+ if (*ifp != NULL) {
+ if (if_is_deactivated(*ifp))
+ *ifp = NULL;
+ else
+ if_acquire(*ifp, psref);
+ }
+ pserialize_read_exit(s);
}
return 0;
}
@@ -1565,26 +1584,31 @@
{
struct ifnet *ifp = NULL; // XXX: gcc [ppc]
struct in_addr ia;
- int i, error;
+ int i, error, bound;
+ struct psref psref;
+ bound = curlwp_bind();
if (sopt->sopt_size == sizeof(struct ip_mreq))
- error = ip_get_membership(sopt, &ifp, &ia, true);
+ error = ip_get_membership(sopt, &ifp, &psref, &ia, true);
else
#ifdef INET6
- error = ip6_get_membership(sopt, &ifp, &ia, sizeof(ia));
+ error = ip6_get_membership(sopt, &ifp, &psref, &ia, sizeof(ia));
#else
- return EINVAL;
+ error = EINVAL;
+ goto out;
#endif
if (error)
- return error;
+ goto out;
/*
* See if we found an interface, and confirm that it
* supports multicast.
*/
- if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0)
- return EADDRNOTAVAIL;
+ if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
+ error = EADDRNOTAVAIL;
+ goto out;
+ }
/*
* See if the membership already exists or if all the
@@ -1595,21 +1619,31 @@
in_hosteq(imo->imo_membership[i]->inm_addr, ia))
break;
}
- if (i < imo->imo_num_memberships)
- return EADDRINUSE;
+ if (i < imo->imo_num_memberships) {
+ error = EADDRINUSE;
+ goto out;
+ }
- if (i == IP_MAX_MEMBERSHIPS)
- return ETOOMANYREFS;
+ if (i == IP_MAX_MEMBERSHIPS) {
+ error = ETOOMANYREFS;
+ goto out;
+ }
/*
* Everything looks good; add a new record to the multicast
* address list for the given interface.
*/
- if ((imo->imo_membership[i] = in_addmulti(&ia, ifp)) == NULL)
- return ENOBUFS;
+ if ((imo->imo_membership[i] = in_addmulti(&ia, ifp)) == NULL) {
+ error = ENOBUFS;
+ goto out;
+ }
++imo->imo_num_memberships;
- return 0;
+ error = 0;
+out:
+ if_put(ifp, &psref);
+ curlwp_bindx(bound);
+ return error;
}
/*
@@ -1621,19 +1655,24 @@
{
struct in_addr ia = { .s_addr = 0 }; // XXX: gcc [ppc]
struct ifnet *ifp = NULL; // XXX: gcc [ppc]
- int i, error;
+ int i, error, bound;
+ struct psref psref;
+ /* imo is protected by solock or referenced only by the caller */
+
+ bound = curlwp_bind();
if (sopt->sopt_size == sizeof(struct ip_mreq))
- error = ip_get_membership(sopt, &ifp, &ia, false);
+ error = ip_get_membership(sopt, &ifp, &psref, &ia, false);
else
#ifdef INET6
- error = ip6_get_membership(sopt, &ifp, &ia, sizeof(ia));
+ error = ip6_get_membership(sopt, &ifp, &psref, &ia, sizeof(ia));
#else
- return EINVAL;
+ error = EINVAL;
+ goto out;
#endif
if (error)
- return error;
+ goto out;
/*
* Find the membership in the membership array.
@@ -1644,8 +1683,10 @@
in_hosteq(imo->imo_membership[i]->inm_addr, ia))
break;
}
- if (i == imo->imo_num_memberships)
- return EADDRNOTAVAIL;
+ if (i == imo->imo_num_memberships) {
+ error = EADDRNOTAVAIL;
+ goto out;
+ }
/*
* Give up the multicast address record to which the
@@ -1659,7 +1700,11 @@
for (++i; i < imo->imo_num_memberships; ++i)
imo->imo_membership[i-1] = imo->imo_membership[i];
--imo->imo_num_memberships;
- return 0;
+ error = 0;
+out:
+ curlwp_bindx(bound);
+ if_put(ifp, &psref);
+ return error;
}
/*
@@ -1691,7 +1736,8 @@
}
switch (sopt->sopt_name) {
- case IP_MULTICAST_IF:
+ case IP_MULTICAST_IF: {
+ int s;
/*
* Select the interface for outgoing multicast packets.
*/
@@ -1713,17 +1759,21 @@
* IP address. Find the interface and confirm that
* it supports multicasting.
*/
+ s = pserialize_read_enter();
ifp = ip_multicast_if(&addr, &ifindex);
if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
+ pserialize_read_exit(s);
error = EADDRNOTAVAIL;
break;
}
imo->imo_multicast_if_index = ifp->if_index;
+ pserialize_read_exit(s);
if (ifindex)
imo->imo_multicast_addr = addr;
else
imo->imo_multicast_addr.s_addr = INADDR_ANY;
break;
+ }
case IP_MULTICAST_TTL:
/*
diff -r e8c726b9acff -r b5fb11dd0c8b sys/netinet6/ip6_output.c
--- a/sys/netinet6/ip6_output.c Thu Mar 02 04:33:56 2017 +0000
+++ b/sys/netinet6/ip6_output.c Thu Mar 02 05:24:23 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ip6_output.c,v 1.188 2017/03/02 01:05:02 ozaki-r Exp $ */
+/* $NetBSD: ip6_output.c,v 1.189 2017/03/02 05:24:23 ozaki-r Exp $ */
/* $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $ */
/*
@@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.188 2017/03/02 01:05:02 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.189 2017/03/02 05:24:23 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -2380,13 +2380,14 @@
}
int
-ip6_get_membership(const struct sockopt *sopt, struct ifnet **ifp, void *v,
- size_t l)
+ip6_get_membership(const struct sockopt *sopt, struct ifnet **ifp,
+ struct psref *psref, void *v, size_t l)
{
struct ipv6_mreq mreq;
int error;
struct in6_addr *ia = &mreq.ipv6mr_multiaddr;
struct in_addr *ia4 = (void *)&ia->s6_addr32[3];
+
error = sockopt_get(sopt, &mreq, sizeof(mreq));
if (error != 0)
return error;
@@ -2437,15 +2438,16 @@
if (error != 0)
return error;
rt = rtcache_init(&ro);
- *ifp = rt != NULL ? rt->rt_ifp : NULL;
- /* FIXME *ifp is NOMPSAFE */
+ *ifp = rt != NULL ?
+ if_get_byindex(rt->rt_ifp->if_index, psref) : NULL;
rtcache_unref(rt, &ro);
rtcache_free(&ro);
} else {
/*
* If the interface is specified, validate it.
*/
- if ((*ifp = if_byindex(mreq.ipv6mr_interface)) == NULL)
+ *ifp = if_get_byindex(mreq.ipv6mr_interface, psref);
+ if (*ifp == NULL)
return ENXIO; /* XXX EINVAL? */
}
if (sizeof(*ia) == l)
Home |
Main Index |
Thread Index |
Old Index