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 --- |