Deleted Added
full compact
in6_mcast.c (191828) in6_mcast.c (192923)
1/*
2 * Copyright (c) 2009 Bruce Simpson.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 19 unchanged lines hidden (view full) ---

28 */
29
30/*
31 * IPv6 multicast socket, group, and socket option processing module.
32 * Normative references: RFC 2292, RFC 3492, RFC 3542, RFC 3678, RFC 3810.
33 */
34
35#include <sys/cdefs.h>
1/*
2 * Copyright (c) 2009 Bruce Simpson.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 19 unchanged lines hidden (view full) ---

28 */
29
30/*
31 * IPv6 multicast socket, group, and socket option processing module.
32 * Normative references: RFC 2292, RFC 3492, RFC 3542, RFC 3678, RFC 3810.
33 */
34
35#include <sys/cdefs.h>
36__FBSDID("$FreeBSD: head/sys/netinet6/in6_mcast.c 191828 2009-05-05 16:27:45Z kan $");
36__FBSDID("$FreeBSD: head/sys/netinet6/in6_mcast.c 192923 2009-05-27 18:57:13Z bms $");
37
38#include "opt_inet6.h"
39#include "opt_route.h"
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/kernel.h>
44#include <sys/malloc.h>

--- 255 unchanged lines hidden (view full) ---

300
301 return (idx);
302}
303
304/*
305 * Find an IPv6 multicast source entry for this imo which matches
306 * the given group index for this socket, and source address.
307 *
37
38#include "opt_inet6.h"
39#include "opt_route.h"
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/kernel.h>
44#include <sys/malloc.h>

--- 255 unchanged lines hidden (view full) ---

300
301 return (idx);
302}
303
304/*
305 * Find an IPv6 multicast source entry for this imo which matches
306 * the given group index for this socket, and source address.
307 *
308 * XXX TODO: The scope ID, if present in src, is stripped before
309 * any comparison. We SHOULD enforce scope/zone checks where the source
310 * filter entry has a link scope.
311 *
308 * NOTE: This does not check if the entry is in-mode, merely if
309 * it exists, which may not be the desired behaviour.
310 */
311static struct in6_msource *
312im6o_match_source(const struct ip6_moptions *imo, const size_t gidx,
313 const struct sockaddr *src)
314{
315 struct ip6_msource find;

--- 7 unchanged lines hidden (view full) ---

323
324 /* The im6o_mfilters array may be lazy allocated. */
325 if (imo->im6o_mfilters == NULL)
326 return (NULL);
327 imf = &imo->im6o_mfilters[gidx];
328
329 psa = (const sockunion_t *)src;
330 find.im6s_addr = psa->sin6.sin6_addr;
312 * NOTE: This does not check if the entry is in-mode, merely if
313 * it exists, which may not be the desired behaviour.
314 */
315static struct in6_msource *
316im6o_match_source(const struct ip6_moptions *imo, const size_t gidx,
317 const struct sockaddr *src)
318{
319 struct ip6_msource find;

--- 7 unchanged lines hidden (view full) ---

327
328 /* The im6o_mfilters array may be lazy allocated. */
329 if (imo->im6o_mfilters == NULL)
330 return (NULL);
331 imf = &imo->im6o_mfilters[gidx];
332
333 psa = (const sockunion_t *)src;
334 find.im6s_addr = psa->sin6.sin6_addr;
335 in6_clearscope(&find.im6s_addr); /* XXX */
331 ims = RB_FIND(ip6_msource_tree, &imf->im6f_sources, &find);
332
333 return ((struct in6_msource *)ims);
334}
335
336/*
337 * Perform filtering for multicast datagrams on a socket by group and source.
338 *

--- 815 unchanged lines hidden (view full) ---

1154{
1155 struct in6_mfilter timf;
1156 struct in6_multi *inm;
1157 int error;
1158#ifdef KTR
1159 char ip6tbuf[INET6_ADDRSTRLEN];
1160#endif
1161
336 ims = RB_FIND(ip6_msource_tree, &imf->im6f_sources, &find);
337
338 return ((struct in6_msource *)ims);
339}
340
341/*
342 * Perform filtering for multicast datagrams on a socket by group and source.
343 *

--- 815 unchanged lines hidden (view full) ---

1159{
1160 struct in6_mfilter timf;
1161 struct in6_multi *inm;
1162 int error;
1163#ifdef KTR
1164 char ip6tbuf[INET6_ADDRSTRLEN];
1165#endif
1166
1167#ifdef INVARIANTS
1168 /*
1169 * Sanity: Check scope zone ID was set for ifp, if and
1170 * only if group is scoped to an interface.
1171 */
1172 KASSERT(IN6_IS_ADDR_MULTICAST(mcaddr),
1173 ("%s: not a multicast address", __func__));
1174 if (IN6_IS_ADDR_MC_LINKLOCAL(mcaddr) ||
1175 IN6_IS_ADDR_MC_INTFACELOCAL(mcaddr)) {
1176 KASSERT(mcaddr->s6_addr16[1] != 0,
1177 ("%s: scope zone ID not set", __func__));
1178 }
1179#endif
1180
1162 IN6_MULTI_LOCK_ASSERT();
1163
1164 CTR4(KTR_MLD, "%s: join %s on %p(%s))", __func__,
1165 ip6_sprintf(ip6tbuf, mcaddr), ifp, ifp->if_xname);
1166
1167 error = 0;
1168 inm = NULL;
1169

--- 185 unchanged lines hidden (view full) ---

1355 __func__, sopt->sopt_name);
1356 return (EOPNOTSUPP);
1357 break;
1358 }
1359
1360 if (!IN6_IS_ADDR_MULTICAST(&gsa->sin6.sin6_addr))
1361 return (EINVAL);
1362
1181 IN6_MULTI_LOCK_ASSERT();
1182
1183 CTR4(KTR_MLD, "%s: join %s on %p(%s))", __func__,
1184 ip6_sprintf(ip6tbuf, mcaddr), ifp, ifp->if_xname);
1185
1186 error = 0;
1187 inm = NULL;
1188

--- 185 unchanged lines hidden (view full) ---

1374 __func__, sopt->sopt_name);
1375 return (EOPNOTSUPP);
1376 break;
1377 }
1378
1379 if (!IN6_IS_ADDR_MULTICAST(&gsa->sin6.sin6_addr))
1380 return (EINVAL);
1381
1382 (void)in6_setscope(&gsa->sin6.sin6_addr, ifp, NULL);
1383
1363 /*
1364 * Check if we are actually a member of this group.
1365 */
1366 imo = in6p_findmoptions(inp);
1367 idx = im6o_match_group(imo, ifp, &gsa->sa);
1368 if (idx == -1 || imo->im6o_mfilters == NULL) {
1369 error = EADDRNOTAVAIL;
1370 goto out_in6p_locked;

--- 190 unchanged lines hidden (view full) ---

1561
1562 INP_WUNLOCK(inp);
1563
1564 error = sooptcopyin(sopt, &msfr, sizeof(struct __msfilterreq),
1565 sizeof(struct __msfilterreq));
1566 if (error)
1567 return (error);
1568
1384 /*
1385 * Check if we are actually a member of this group.
1386 */
1387 imo = in6p_findmoptions(inp);
1388 idx = im6o_match_group(imo, ifp, &gsa->sa);
1389 if (idx == -1 || imo->im6o_mfilters == NULL) {
1390 error = EADDRNOTAVAIL;
1391 goto out_in6p_locked;

--- 190 unchanged lines hidden (view full) ---

1582
1583 INP_WUNLOCK(inp);
1584
1585 error = sooptcopyin(sopt, &msfr, sizeof(struct __msfilterreq),
1586 sizeof(struct __msfilterreq));
1587 if (error)
1588 return (error);
1589
1569 if (msfr.msfr_ifindex == 0 || V_if_index < msfr.msfr_ifindex)
1590 if (msfr.msfr_group.ss_family != AF_INET6 ||
1591 msfr.msfr_group.ss_len != sizeof(struct sockaddr_in6))
1570 return (EINVAL);
1571
1592 return (EINVAL);
1593
1594 gsa = (sockunion_t *)&msfr.msfr_group;
1595 if (!IN6_IS_ADDR_MULTICAST(&gsa->sin6.sin6_addr))
1596 return (EINVAL);
1597
1598 if (msfr.msfr_ifindex == 0 || V_if_index < msfr.msfr_ifindex)
1599 return (EADDRNOTAVAIL);
1572 ifp = ifnet_byindex(msfr.msfr_ifindex);
1573 if (ifp == NULL)
1600 ifp = ifnet_byindex(msfr.msfr_ifindex);
1601 if (ifp == NULL)
1574 return (EINVAL);
1602 return (EADDRNOTAVAIL);
1603 (void)in6_setscope(&gsa->sin6.sin6_addr, ifp, NULL);
1575
1576 INP_WLOCK(inp);
1577
1578 /*
1579 * Lookup group on the socket.
1580 */
1604
1605 INP_WLOCK(inp);
1606
1607 /*
1608 * Lookup group on the socket.
1609 */
1581 gsa = (sockunion_t *)&msfr.msfr_group;
1582 idx = im6o_match_group(imo, ifp, &gsa->sa);
1583 if (idx == -1 || imo->im6o_mfilters == NULL) {
1584 INP_WUNLOCK(inp);
1585 return (EADDRNOTAVAIL);
1586 }
1587 imf = &imo->im6o_mfilters[idx];
1588
1589 /*

--- 208 unchanged lines hidden (view full) ---

1798 is_new = 0;
1799
1800 memset(&gsr, 0, sizeof(struct group_source_req));
1801 gsa = (sockunion_t *)&gsr.gsr_group;
1802 gsa->ss.ss_family = AF_UNSPEC;
1803 ssa = (sockunion_t *)&gsr.gsr_source;
1804 ssa->ss.ss_family = AF_UNSPEC;
1805
1610 idx = im6o_match_group(imo, ifp, &gsa->sa);
1611 if (idx == -1 || imo->im6o_mfilters == NULL) {
1612 INP_WUNLOCK(inp);
1613 return (EADDRNOTAVAIL);
1614 }
1615 imf = &imo->im6o_mfilters[idx];
1616
1617 /*

--- 208 unchanged lines hidden (view full) ---

1826 is_new = 0;
1827
1828 memset(&gsr, 0, sizeof(struct group_source_req));
1829 gsa = (sockunion_t *)&gsr.gsr_group;
1830 gsa->ss.ss_family = AF_UNSPEC;
1831 ssa = (sockunion_t *)&gsr.gsr_source;
1832 ssa->ss.ss_family = AF_UNSPEC;
1833
1834 /*
1835 * Chew everything into struct group_source_req.
1836 * Overwrite the port field if present, as the sockaddr
1837 * being copied in may be matched with a binary comparison.
1838 * Ignore passed-in scope ID.
1839 */
1806 switch (sopt->sopt_name) {
1807 case IPV6_JOIN_GROUP: {
1808 struct ipv6_mreq mreq;
1809
1810 error = sooptcopyin(sopt, &mreq, sizeof(struct ipv6_mreq),
1811 sizeof(struct ipv6_mreq));
1812 if (error)
1813 return (error);

--- 27 unchanged lines hidden (view full) ---

1841 }
1842 if (error)
1843 return (error);
1844
1845 if (gsa->sin6.sin6_family != AF_INET6 ||
1846 gsa->sin6.sin6_len != sizeof(struct sockaddr_in6))
1847 return (EINVAL);
1848
1840 switch (sopt->sopt_name) {
1841 case IPV6_JOIN_GROUP: {
1842 struct ipv6_mreq mreq;
1843
1844 error = sooptcopyin(sopt, &mreq, sizeof(struct ipv6_mreq),
1845 sizeof(struct ipv6_mreq));
1846 if (error)
1847 return (error);

--- 27 unchanged lines hidden (view full) ---

1875 }
1876 if (error)
1877 return (error);
1878
1879 if (gsa->sin6.sin6_family != AF_INET6 ||
1880 gsa->sin6.sin6_len != sizeof(struct sockaddr_in6))
1881 return (EINVAL);
1882
1849 /*
1850 * Overwrite the port field if present, as the sockaddr
1851 * being copied in may be matched with a binary comparison.
1852 */
1853 gsa->sin6.sin6_port = 0;
1854 if (sopt->sopt_name == MCAST_JOIN_SOURCE_GROUP) {
1855 if (ssa->sin6.sin6_family != AF_INET6 ||
1856 ssa->sin6.sin6_len != sizeof(struct sockaddr_in6))
1857 return (EINVAL);
1883 if (sopt->sopt_name == MCAST_JOIN_SOURCE_GROUP) {
1884 if (ssa->sin6.sin6_family != AF_INET6 ||
1885 ssa->sin6.sin6_len != sizeof(struct sockaddr_in6))
1886 return (EINVAL);
1887 if (IN6_IS_ADDR_MULTICAST(&ssa->sin6.sin6_addr))
1888 return (EINVAL);
1889 /*
1890 * TODO: Validate embedded scope ID in source
1891 * list entry against passed-in ifp, if and only
1892 * if source list filter entry is iface or node local.
1893 */
1894 in6_clearscope(&ssa->sin6.sin6_addr);
1858 ssa->sin6.sin6_port = 0;
1895 ssa->sin6.sin6_port = 0;
1896 ssa->sin6.sin6_scope_id = 0;
1859 }
1860
1861 if (gsr.gsr_interface == 0 || V_if_index < gsr.gsr_interface)
1862 return (EADDRNOTAVAIL);
1863 ifp = ifnet_byindex(gsr.gsr_interface);
1864 break;
1865
1866 default:
1867 CTR2(KTR_MLD, "%s: unknown sopt_name %d",
1868 __func__, sopt->sopt_name);
1869 return (EOPNOTSUPP);
1870 break;
1871 }
1872
1897 }
1898
1899 if (gsr.gsr_interface == 0 || V_if_index < gsr.gsr_interface)
1900 return (EADDRNOTAVAIL);
1901 ifp = ifnet_byindex(gsr.gsr_interface);
1902 break;
1903
1904 default:
1905 CTR2(KTR_MLD, "%s: unknown sopt_name %d",
1906 __func__, sopt->sopt_name);
1907 return (EOPNOTSUPP);
1908 break;
1909 }
1910
1873#ifdef notyet
1874 /*
1875 * FIXME: Check for unspecified address (all groups).
1876 * Do we have a normative reference for this 'feature'?
1877 *
1878 * We use the unspecified address to specify to accept
1879 * all multicast addresses. Only super user is allowed
1880 * to do this.
1881 * XXX-BZ might need a better PRIV_NETINET_x for this
1882 */
1883 if (IN6_IS_ADDR_UNSPECIFIED(&gsa->sin6.sin6_addr)) {
1884 error = priv_check(curthread, PRIV_NETINET_MROUTE);
1885 if (error)
1886 break;
1887 } else
1888#endif
1889 if (!IN6_IS_ADDR_MULTICAST(&gsa->sin6.sin6_addr))
1890 return (EINVAL);
1891
1892 if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0)
1893 return (EADDRNOTAVAIL);
1894
1911 if (!IN6_IS_ADDR_MULTICAST(&gsa->sin6.sin6_addr))
1912 return (EINVAL);
1913
1914 if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0)
1915 return (EADDRNOTAVAIL);
1916
1895#ifdef notyet
1917 gsa->sin6.sin6_port = 0;
1918 gsa->sin6.sin6_scope_id = 0;
1919
1896 /*
1920 /*
1897 * FIXME: Set interface scope in group address.
1921 * Always set the scope zone ID on memberships created from userland.
1922 * Use the passed-in ifp to do this.
1923 * XXX The in6_setscope() return value is meaningless.
1924 * XXX SCOPE6_LOCK() is taken by in6_setscope().
1898 */
1925 */
1899 (void)in6_setscope(&gsa->sin6.sin_addr, ifp, NULL);
1900#endif
1926 (void)in6_setscope(&gsa->sin6.sin6_addr, ifp, NULL);
1901
1902 /*
1903 * MCAST_JOIN_SOURCE on an exclusive membership is an error.
1904 * On an existing inclusive membership, it just adds the
1905 * source to the filter list.
1906 */
1907 imo = in6p_findmoptions(inp);
1908 idx = im6o_match_group(imo, ifp, &gsa->sa);

--- 117 unchanged lines hidden (view full) ---

2026
2027/*
2028 * Leave an IPv6 multicast group on an inpcb, possibly with a source.
2029 */
2030static int
2031in6p_leave_group(struct inpcb *inp, struct sockopt *sopt)
2032{
2033 INIT_VNET_NET(curvnet);
1927
1928 /*
1929 * MCAST_JOIN_SOURCE on an exclusive membership is an error.
1930 * On an existing inclusive membership, it just adds the
1931 * source to the filter list.
1932 */
1933 imo = in6p_findmoptions(inp);
1934 idx = im6o_match_group(imo, ifp, &gsa->sa);

--- 117 unchanged lines hidden (view full) ---

2052
2053/*
2054 * Leave an IPv6 multicast group on an inpcb, possibly with a source.
2055 */
2056static int
2057in6p_leave_group(struct inpcb *inp, struct sockopt *sopt)
2058{
2059 INIT_VNET_NET(curvnet);
2060 INIT_VNET_INET6(curvnet);
2061 struct ipv6_mreq mreq;
2034 struct group_source_req gsr;
2035 sockunion_t *gsa, *ssa;
2036 struct ifnet *ifp;
2037 struct in6_mfilter *imf;
2038 struct ip6_moptions *imo;
2039 struct in6_msource *ims;
2040 struct in6_multi *inm;
2062 struct group_source_req gsr;
2063 sockunion_t *gsa, *ssa;
2064 struct ifnet *ifp;
2065 struct in6_mfilter *imf;
2066 struct ip6_moptions *imo;
2067 struct in6_msource *ims;
2068 struct in6_multi *inm;
2069 uint32_t ifindex;
2041 size_t idx;
2042 int error, is_final;
2043#ifdef KTR
2044 char ip6tbuf[INET6_ADDRSTRLEN];
2045#endif
2046
2047 ifp = NULL;
2070 size_t idx;
2071 int error, is_final;
2072#ifdef KTR
2073 char ip6tbuf[INET6_ADDRSTRLEN];
2074#endif
2075
2076 ifp = NULL;
2077 ifindex = 0;
2048 error = 0;
2049 is_final = 1;
2050
2051 memset(&gsr, 0, sizeof(struct group_source_req));
2052 gsa = (sockunion_t *)&gsr.gsr_group;
2053 gsa->ss.ss_family = AF_UNSPEC;
2054 ssa = (sockunion_t *)&gsr.gsr_source;
2055 ssa->ss.ss_family = AF_UNSPEC;
2056
2078 error = 0;
2079 is_final = 1;
2080
2081 memset(&gsr, 0, sizeof(struct group_source_req));
2082 gsa = (sockunion_t *)&gsr.gsr_group;
2083 gsa->ss.ss_family = AF_UNSPEC;
2084 ssa = (sockunion_t *)&gsr.gsr_source;
2085 ssa->ss.ss_family = AF_UNSPEC;
2086
2087 /*
2088 * Chew everything passed in up into a struct group_source_req
2089 * as that is easier to process.
2090 * Note: Any embedded scope ID in the multicast group passed
2091 * in by userland is ignored, the interface index is the recommended
2092 * mechanism to specify an interface; see below.
2093 */
2057 switch (sopt->sopt_name) {
2094 switch (sopt->sopt_name) {
2058 case IPV6_LEAVE_GROUP: {
2059 struct ipv6_mreq mreq;
2060
2095 case IPV6_LEAVE_GROUP:
2061 error = sooptcopyin(sopt, &mreq, sizeof(struct ipv6_mreq),
2062 sizeof(struct ipv6_mreq));
2063 if (error)
2064 return (error);
2096 error = sooptcopyin(sopt, &mreq, sizeof(struct ipv6_mreq),
2097 sizeof(struct ipv6_mreq));
2098 if (error)
2099 return (error);
2065
2066 gsa->sin6.sin6_family = AF_INET6;
2067 gsa->sin6.sin6_len = sizeof(struct sockaddr_in6);
2068 gsa->sin6.sin6_addr = mreq.ipv6mr_multiaddr;
2100 gsa->sin6.sin6_family = AF_INET6;
2101 gsa->sin6.sin6_len = sizeof(struct sockaddr_in6);
2102 gsa->sin6.sin6_addr = mreq.ipv6mr_multiaddr;
2103 gsa->sin6.sin6_port = 0;
2104 gsa->sin6.sin6_scope_id = 0;
2105 ifindex = mreq.ipv6mr_interface;
2106 break;
2069
2107
2070 if (mreq.ipv6mr_interface == 0) {
2071#ifdef notyet
2072 /*
2073 * FIXME: Resolve scope ambiguity when interface
2074 * index is unspecified.
2075 */
2076 ifp = in6p_lookup_mcast_ifp(inp, &gsa->sin6);
2077#else
2078 return (EADDRNOTAVAIL);
2079#endif
2080 } else {
2081 if (mreq.ipv6mr_interface < 0 ||
2082 V_if_index < mreq.ipv6mr_interface)
2083 return (EADDRNOTAVAIL);
2084 ifp = ifnet_byindex(mreq.ipv6mr_interface);
2085 }
2086
2087 CTR3(KTR_MLD, "%s: ipv6mr_interface = %d, ifp = %p",
2088 __func__, mreq.ipv6mr_interface, ifp);
2089 } break;
2090
2091 case MCAST_LEAVE_GROUP:
2092 case MCAST_LEAVE_SOURCE_GROUP:
2093 if (sopt->sopt_name == MCAST_LEAVE_GROUP) {
2094 error = sooptcopyin(sopt, &gsr,
2095 sizeof(struct group_req),
2096 sizeof(struct group_req));
2097 } else if (sopt->sopt_name == MCAST_LEAVE_SOURCE_GROUP) {
2098 error = sooptcopyin(sopt, &gsr,
2099 sizeof(struct group_source_req),
2100 sizeof(struct group_source_req));
2101 }
2102 if (error)
2103 return (error);
2104
2105 if (gsa->sin6.sin6_family != AF_INET6 ||
2106 gsa->sin6.sin6_len != sizeof(struct sockaddr_in6))
2107 return (EINVAL);
2108 case MCAST_LEAVE_GROUP:
2109 case MCAST_LEAVE_SOURCE_GROUP:
2110 if (sopt->sopt_name == MCAST_LEAVE_GROUP) {
2111 error = sooptcopyin(sopt, &gsr,
2112 sizeof(struct group_req),
2113 sizeof(struct group_req));
2114 } else if (sopt->sopt_name == MCAST_LEAVE_SOURCE_GROUP) {
2115 error = sooptcopyin(sopt, &gsr,
2116 sizeof(struct group_source_req),
2117 sizeof(struct group_source_req));
2118 }
2119 if (error)
2120 return (error);
2121
2122 if (gsa->sin6.sin6_family != AF_INET6 ||
2123 gsa->sin6.sin6_len != sizeof(struct sockaddr_in6))
2124 return (EINVAL);
2108
2109 if (sopt->sopt_name == MCAST_LEAVE_SOURCE_GROUP) {
2110 if (ssa->sin6.sin6_family != AF_INET6 ||
2111 ssa->sin6.sin6_len != sizeof(struct sockaddr_in6))
2112 return (EINVAL);
2125 if (sopt->sopt_name == MCAST_LEAVE_SOURCE_GROUP) {
2126 if (ssa->sin6.sin6_family != AF_INET6 ||
2127 ssa->sin6.sin6_len != sizeof(struct sockaddr_in6))
2128 return (EINVAL);
2129 if (IN6_IS_ADDR_MULTICAST(&ssa->sin6.sin6_addr))
2130 return (EINVAL);
2131 /*
2132 * TODO: Validate embedded scope ID in source
2133 * list entry against passed-in ifp, if and only
2134 * if source list filter entry is iface or node local.
2135 */
2136 in6_clearscope(&ssa->sin6.sin6_addr);
2113 }
2137 }
2114
2115 if (gsr.gsr_interface == 0 || V_if_index < gsr.gsr_interface)
2116 return (EADDRNOTAVAIL);
2117
2118 ifp = ifnet_byindex(gsr.gsr_interface);
2138 gsa->sin6.sin6_port = 0;
2139 gsa->sin6.sin6_scope_id = 0;
2140 ifindex = gsr.gsr_interface;
2119 break;
2120
2121 default:
2122 CTR2(KTR_MLD, "%s: unknown sopt_name %d",
2123 __func__, sopt->sopt_name);
2124 return (EOPNOTSUPP);
2125 break;
2126 }
2127
2128 if (!IN6_IS_ADDR_MULTICAST(&gsa->sin6.sin6_addr))
2129 return (EINVAL);
2130
2141 break;
2142
2143 default:
2144 CTR2(KTR_MLD, "%s: unknown sopt_name %d",
2145 __func__, sopt->sopt_name);
2146 return (EOPNOTSUPP);
2147 break;
2148 }
2149
2150 if (!IN6_IS_ADDR_MULTICAST(&gsa->sin6.sin6_addr))
2151 return (EINVAL);
2152
2131#ifdef notyet
2132 /*
2153 /*
2133 * FIXME: Need to embed ifp's scope ID in the address
2134 * handed down to MLD.
2135 * See KAME IPV6_LEAVE_GROUP implementation.
2154 * Validate interface index if provided. If no interface index
2155 * was provided separately, attempt to look the membership up
2156 * from the default scope as a last resort to disambiguate
2157 * the membership we are being asked to leave.
2158 * XXX SCOPE6 lock potentially taken here.
2136 */
2159 */
2137 (void)in6_setscope(&mreq->ipv6mr_multiaddr, ifp, NULL);
2138#endif
2160 if (ifindex != 0) {
2161 if (ifindex < 0 || V_if_index < ifindex)
2162 return (EADDRNOTAVAIL);
2163 ifp = ifnet_byindex(ifindex);
2164 if (ifp == NULL)
2165 return (EADDRNOTAVAIL);
2166 (void)in6_setscope(&gsa->sin6.sin6_addr, ifp, NULL);
2167 } else {
2168 error = sa6_embedscope(&gsa->sin6, V_ip6_use_defzone);
2169 if (error)
2170 return (EADDRNOTAVAIL);
2171 /*
2172 * XXX For now, stomp on zone ID for the corner case.
2173 * This is not the 'KAME way', but we need to see the ifp
2174 * directly until such time as this implementation is
2175 * refactored, assuming the scope IDs are the way to go.
2176 */
2177 ifindex = ntohs(gsa->sin6.sin6_addr.s6_addr16[1]);
2178 KASSERT(ifindex != 0, ("%s: bad zone ID", __func__));
2179 ifp = ifnet_byindex(ifindex);
2180 if (ifp == NULL)
2181 return (EADDRNOTAVAIL);
2182 }
2139
2183
2184 CTR2(KTR_MLD, "%s: ifp = %p", __func__, ifp);
2185 KASSERT(ifp != NULL, ("%s: ifp did not resolve", __func__));
2186
2140 /*
2141 * Find the membership in the membership array.
2142 */
2143 imo = in6p_findmoptions(inp);
2144 idx = im6o_match_group(imo, ifp, &gsa->sa);
2145 if (idx == -1) {
2146 error = EADDRNOTAVAIL;
2147 goto out_in6p_locked;

--- 159 unchanged lines hidden (view full) ---

2307 gsa = (sockunion_t *)&msfr.msfr_group;
2308 if (!IN6_IS_ADDR_MULTICAST(&gsa->sin6.sin6_addr))
2309 return (EINVAL);
2310
2311 gsa->sin6.sin6_port = 0; /* ignore port */
2312
2313 if (msfr.msfr_ifindex == 0 || V_if_index < msfr.msfr_ifindex)
2314 return (EADDRNOTAVAIL);
2187 /*
2188 * Find the membership in the membership array.
2189 */
2190 imo = in6p_findmoptions(inp);
2191 idx = im6o_match_group(imo, ifp, &gsa->sa);
2192 if (idx == -1) {
2193 error = EADDRNOTAVAIL;
2194 goto out_in6p_locked;

--- 159 unchanged lines hidden (view full) ---

2354 gsa = (sockunion_t *)&msfr.msfr_group;
2355 if (!IN6_IS_ADDR_MULTICAST(&gsa->sin6.sin6_addr))
2356 return (EINVAL);
2357
2358 gsa->sin6.sin6_port = 0; /* ignore port */
2359
2360 if (msfr.msfr_ifindex == 0 || V_if_index < msfr.msfr_ifindex)
2361 return (EADDRNOTAVAIL);
2315
2316 ifp = ifnet_byindex(msfr.msfr_ifindex);
2317 if (ifp == NULL)
2318 return (EADDRNOTAVAIL);
2362 ifp = ifnet_byindex(msfr.msfr_ifindex);
2363 if (ifp == NULL)
2364 return (EADDRNOTAVAIL);
2365 (void)in6_setscope(&gsa->sin6.sin6_addr, ifp, NULL);
2319
2320 /*
2321 * Take the INP write lock.
2322 * Check if this socket is a member of this group.
2323 */
2324 imo = in6p_findmoptions(inp);
2325 idx = im6o_match_group(imo, ifp, &gsa->sa);
2326 if (idx == -1 || imo->im6o_mfilters == NULL) {

--- 61 unchanged lines hidden (view full) ---

2388 if (psin->sin6_family != AF_INET6) {
2389 error = EAFNOSUPPORT;
2390 break;
2391 }
2392 if (psin->sin6_len != sizeof(struct sockaddr_in6)) {
2393 error = EINVAL;
2394 break;
2395 }
2366
2367 /*
2368 * Take the INP write lock.
2369 * Check if this socket is a member of this group.
2370 */
2371 imo = in6p_findmoptions(inp);
2372 idx = im6o_match_group(imo, ifp, &gsa->sa);
2373 if (idx == -1 || imo->im6o_mfilters == NULL) {

--- 61 unchanged lines hidden (view full) ---

2435 if (psin->sin6_family != AF_INET6) {
2436 error = EAFNOSUPPORT;
2437 break;
2438 }
2439 if (psin->sin6_len != sizeof(struct sockaddr_in6)) {
2440 error = EINVAL;
2441 break;
2442 }
2443 if (IN6_IS_ADDR_MULTICAST(&psin->sin6_addr)) {
2444 error = EINVAL;
2445 break;
2446 }
2447 /*
2448 * TODO: Validate embedded scope ID in source
2449 * list entry against passed-in ifp, if and only
2450 * if source list filter entry is iface or node local.
2451 */
2452 in6_clearscope(&psin->sin6_addr);
2396 error = im6f_get_source(imf, psin, &lims);
2397 if (error)
2398 break;
2399 lims->im6sl_st[1] = imf->im6f_st[1];
2400 }
2401 free(kss, M_TEMP);
2402 }
2403

--- 151 unchanged lines hidden (view full) ---

2555 * 0..n of struct in6_addr.
2556 * For use by ifmcstat(8).
2557 * SMPng: NOTE: unlocked read of ifindex space.
2558 */
2559static int
2560sysctl_ip6_mcast_filters(SYSCTL_HANDLER_ARGS)
2561{
2562 INIT_VNET_NET(curvnet);
2453 error = im6f_get_source(imf, psin, &lims);
2454 if (error)
2455 break;
2456 lims->im6sl_st[1] = imf->im6f_st[1];
2457 }
2458 free(kss, M_TEMP);
2459 }
2460

--- 151 unchanged lines hidden (view full) ---

2612 * 0..n of struct in6_addr.
2613 * For use by ifmcstat(8).
2614 * SMPng: NOTE: unlocked read of ifindex space.
2615 */
2616static int
2617sysctl_ip6_mcast_filters(SYSCTL_HANDLER_ARGS)
2618{
2619 INIT_VNET_NET(curvnet);
2563 struct in6_addr *pgina;
2620 struct in6_addr mcaddr;
2564 struct in6_addr src;
2565 struct ifnet *ifp;
2566 struct ifmultiaddr *ifma;
2567 struct in6_multi *inm;
2568 struct ip6_msource *ims;
2569 int *name;
2570 int retval;
2571 u_int namelen;

--- 14 unchanged lines hidden (view full) ---

2586
2587 ifindex = name[0];
2588 if (ifindex <= 0 || ifindex > V_if_index) {
2589 CTR2(KTR_MLD, "%s: ifindex %u out of range",
2590 __func__, ifindex);
2591 return (ENOENT);
2592 }
2593
2621 struct in6_addr src;
2622 struct ifnet *ifp;
2623 struct ifmultiaddr *ifma;
2624 struct in6_multi *inm;
2625 struct ip6_msource *ims;
2626 int *name;
2627 int retval;
2628 u_int namelen;

--- 14 unchanged lines hidden (view full) ---

2643
2644 ifindex = name[0];
2645 if (ifindex <= 0 || ifindex > V_if_index) {
2646 CTR2(KTR_MLD, "%s: ifindex %u out of range",
2647 __func__, ifindex);
2648 return (ENOENT);
2649 }
2650
2594 pgina = (struct in6_addr *)&name[1];
2595 if (!IN6_IS_ADDR_MULTICAST(pgina)) {
2651 memcpy(&mcaddr, &name[1], sizeof(struct in6_addr));
2652 if (!IN6_IS_ADDR_MULTICAST(&mcaddr)) {
2596 CTR2(KTR_MLD, "%s: group %s is not multicast",
2653 CTR2(KTR_MLD, "%s: group %s is not multicast",
2597 __func__, ip6_sprintf(ip6tbuf, pgina));
2654 __func__, ip6_sprintf(ip6tbuf, &mcaddr));
2598 return (EINVAL);
2599 }
2600
2601 ifp = ifnet_byindex(ifindex);
2602 if (ifp == NULL) {
2603 CTR2(KTR_MLD, "%s: no ifp for ifindex %u",
2604 __func__, ifindex);
2605 return (ENOENT);
2606 }
2655 return (EINVAL);
2656 }
2657
2658 ifp = ifnet_byindex(ifindex);
2659 if (ifp == NULL) {
2660 CTR2(KTR_MLD, "%s: no ifp for ifindex %u",
2661 __func__, ifindex);
2662 return (ENOENT);
2663 }
2664 /*
2665 * Internal MLD lookups require that scope/zone ID is set.
2666 */
2667 (void)in6_setscope(&mcaddr, ifp, NULL);
2607
2608 retval = sysctl_wire_old_buffer(req,
2609 sizeof(uint32_t) + (in6_mcast_maxgrpsrc * sizeof(struct in6_addr)));
2610 if (retval)
2611 return (retval);
2612
2613 IN6_MULTI_LOCK();
2614
2615 IF_ADDR_LOCK(ifp);
2616 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
2617 if (ifma->ifma_addr->sa_family != AF_INET6 ||
2618 ifma->ifma_protospec == NULL)
2619 continue;
2620 inm = (struct in6_multi *)ifma->ifma_protospec;
2668
2669 retval = sysctl_wire_old_buffer(req,
2670 sizeof(uint32_t) + (in6_mcast_maxgrpsrc * sizeof(struct in6_addr)));
2671 if (retval)
2672 return (retval);
2673
2674 IN6_MULTI_LOCK();
2675
2676 IF_ADDR_LOCK(ifp);
2677 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
2678 if (ifma->ifma_addr->sa_family != AF_INET6 ||
2679 ifma->ifma_protospec == NULL)
2680 continue;
2681 inm = (struct in6_multi *)ifma->ifma_protospec;
2621 if (!IN6_ARE_ADDR_EQUAL(&inm->in6m_addr, pgina))
2682 if (!IN6_ARE_ADDR_EQUAL(&inm->in6m_addr, &mcaddr))
2622 continue;
2623 fmode = inm->in6m_st[1].iss_fmode;
2624 retval = SYSCTL_OUT(req, &fmode, sizeof(uint32_t));
2625 if (retval != 0)
2626 break;
2627 RB_FOREACH(ims, ip6_msource_tree, &inm->in6m_srcs) {
2628 CTR2(KTR_MLD, "%s: visit node %p", __func__, ims);
2629 /*

--- 103 unchanged lines hidden ---
2683 continue;
2684 fmode = inm->in6m_st[1].iss_fmode;
2685 retval = SYSCTL_OUT(req, &fmode, sizeof(uint32_t));
2686 if (retval != 0)
2687 break;
2688 RB_FOREACH(ims, ip6_msource_tree, &inm->in6m_srcs) {
2689 CTR2(KTR_MLD, "%s: visit node %p", __func__, ims);
2690 /*

--- 103 unchanged lines hidden ---