in_mcast.c (9b7501e7977c1f4a0a4a798cdf0af64846009df8) in_mcast.c (c8ee75f2315e8267ad814dc5b4645ef205f0e0e1)
1/*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 2007-2009 Bruce Simpson.
5 * Copyright (c) 2005 Robert N. M. Watson.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without

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

39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/kernel.h>
43#include <sys/lock.h>
44#include <sys/malloc.h>
45#include <sys/mbuf.h>
46#include <sys/protosw.h>
1/*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 2007-2009 Bruce Simpson.
5 * Copyright (c) 2005 Robert N. M. Watson.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without

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

39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/kernel.h>
43#include <sys/lock.h>
44#include <sys/malloc.h>
45#include <sys/mbuf.h>
46#include <sys/protosw.h>
47#include <sys/rmlock.h>
48#include <sys/socket.h>
49#include <sys/socketvar.h>
50#include <sys/protosw.h>
51#include <sys/sysctl.h>
52#include <sys/ktr.h>
53#include <sys/taskqueue.h>
54#include <sys/tree.h>
55

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

1373 * SMPng: NOTE: Must take Giant as a join may create a new ifma.
1374 *
1375 * Return 0 if successful, otherwise return an appropriate error code.
1376 */
1377static int
1378inp_block_unblock_source(struct inpcb *inp, struct sockopt *sopt)
1379{
1380 struct group_source_req gsr;
47#include <sys/socket.h>
48#include <sys/socketvar.h>
49#include <sys/protosw.h>
50#include <sys/sysctl.h>
51#include <sys/ktr.h>
52#include <sys/taskqueue.h>
53#include <sys/tree.h>
54

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

1372 * SMPng: NOTE: Must take Giant as a join may create a new ifma.
1373 *
1374 * Return 0 if successful, otherwise return an appropriate error code.
1375 */
1376static int
1377inp_block_unblock_source(struct inpcb *inp, struct sockopt *sopt)
1378{
1379 struct group_source_req gsr;
1381 struct rm_priotracker in_ifa_tracker;
1382 sockunion_t *gsa, *ssa;
1383 struct ifnet *ifp;
1384 struct in_mfilter *imf;
1385 struct ip_moptions *imo;
1386 struct in_msource *ims;
1387 struct in_multi *inm;
1388 uint16_t fmode;
1389 int error, doblock;

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

1411 gsa->sin.sin_len = sizeof(struct sockaddr_in);
1412 gsa->sin.sin_addr = mreqs.imr_multiaddr;
1413
1414 ssa->sin.sin_family = AF_INET;
1415 ssa->sin.sin_len = sizeof(struct sockaddr_in);
1416 ssa->sin.sin_addr = mreqs.imr_sourceaddr;
1417
1418 if (!in_nullhost(mreqs.imr_interface)) {
1380 sockunion_t *gsa, *ssa;
1381 struct ifnet *ifp;
1382 struct in_mfilter *imf;
1383 struct ip_moptions *imo;
1384 struct in_msource *ims;
1385 struct in_multi *inm;
1386 uint16_t fmode;
1387 int error, doblock;

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

1409 gsa->sin.sin_len = sizeof(struct sockaddr_in);
1410 gsa->sin.sin_addr = mreqs.imr_multiaddr;
1411
1412 ssa->sin.sin_family = AF_INET;
1413 ssa->sin.sin_len = sizeof(struct sockaddr_in);
1414 ssa->sin.sin_addr = mreqs.imr_sourceaddr;
1415
1416 if (!in_nullhost(mreqs.imr_interface)) {
1419 IN_IFADDR_RLOCK(&in_ifa_tracker);
1417 struct epoch_tracker et;
1418
1419 NET_EPOCH_ENTER(et);
1420 INADDR_TO_IFP(mreqs.imr_interface, ifp);
1420 INADDR_TO_IFP(mreqs.imr_interface, ifp);
1421 IN_IFADDR_RUNLOCK(&in_ifa_tracker);
1421 /* XXXGL: ifref? */
1422 NET_EPOCH_EXIT(et);
1422 }
1423 if (sopt->sopt_name == IP_BLOCK_SOURCE)
1424 doblock = 1;
1425
1426 CTR3(KTR_IGMPV3, "%s: imr_interface = 0x%08x, ifp = %p",
1427 __func__, ntohl(mreqs.imr_interface.s_addr), ifp);
1428 break;
1429 }

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

1866 * Returns NULL if no ifp could be found, otherwise return referenced ifp.
1867 *
1868 * FUTURE: Implement IPv4 source-address selection.
1869 */
1870static struct ifnet *
1871inp_lookup_mcast_ifp(const struct inpcb *inp,
1872 const struct sockaddr_in *gsin, const struct in_addr ina)
1873{
1423 }
1424 if (sopt->sopt_name == IP_BLOCK_SOURCE)
1425 doblock = 1;
1426
1427 CTR3(KTR_IGMPV3, "%s: imr_interface = 0x%08x, ifp = %p",
1428 __func__, ntohl(mreqs.imr_interface.s_addr), ifp);
1429 break;
1430 }

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

1867 * Returns NULL if no ifp could be found, otherwise return referenced ifp.
1868 *
1869 * FUTURE: Implement IPv4 source-address selection.
1870 */
1871static struct ifnet *
1872inp_lookup_mcast_ifp(const struct inpcb *inp,
1873 const struct sockaddr_in *gsin, const struct in_addr ina)
1874{
1874 struct rm_priotracker in_ifa_tracker;
1875 struct ifnet *ifp;
1876 struct nhop_object *nh;
1877
1878 NET_EPOCH_ASSERT();
1879 KASSERT(inp != NULL, ("%s: inp must not be NULL", __func__));
1880 KASSERT(gsin->sin_family == AF_INET, ("%s: not AF_INET", __func__));
1881 KASSERT(IN_MULTICAST(ntohl(gsin->sin_addr.s_addr)),
1882 ("%s: not multicast", __func__));
1883
1884 ifp = NULL;
1885 if (!in_nullhost(ina)) {
1875 struct ifnet *ifp;
1876 struct nhop_object *nh;
1877
1878 NET_EPOCH_ASSERT();
1879 KASSERT(inp != NULL, ("%s: inp must not be NULL", __func__));
1880 KASSERT(gsin->sin_family == AF_INET, ("%s: not AF_INET", __func__));
1881 KASSERT(IN_MULTICAST(ntohl(gsin->sin_addr.s_addr)),
1882 ("%s: not multicast", __func__));
1883
1884 ifp = NULL;
1885 if (!in_nullhost(ina)) {
1886 IN_IFADDR_RLOCK(&in_ifa_tracker);
1887 INADDR_TO_IFP(ina, ifp);
1888 if (ifp != NULL)
1889 if_ref(ifp);
1886 INADDR_TO_IFP(ina, ifp);
1887 if (ifp != NULL)
1888 if_ref(ifp);
1890 IN_IFADDR_RUNLOCK(&in_ifa_tracker);
1891 } else {
1892 nh = fib4_lookup(inp->inp_inc.inc_fibnum, gsin->sin_addr, 0, NHR_NONE, 0);
1893 if (nh != NULL) {
1894 ifp = nh->nh_ifp;
1895 if_ref(ifp);
1896 } else {
1897 struct in_ifaddr *ia;
1898 struct ifnet *mifp;

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

2242/*
2243 * Leave an IPv4 multicast group on an inpcb, possibly with a source.
2244 */
2245static int
2246inp_leave_group(struct inpcb *inp, struct sockopt *sopt)
2247{
2248 struct group_source_req gsr;
2249 struct ip_mreq_source mreqs;
1889 } else {
1890 nh = fib4_lookup(inp->inp_inc.inc_fibnum, gsin->sin_addr, 0, NHR_NONE, 0);
1891 if (nh != NULL) {
1892 ifp = nh->nh_ifp;
1893 if_ref(ifp);
1894 } else {
1895 struct in_ifaddr *ia;
1896 struct ifnet *mifp;

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

2240/*
2241 * Leave an IPv4 multicast group on an inpcb, possibly with a source.
2242 */
2243static int
2244inp_leave_group(struct inpcb *inp, struct sockopt *sopt)
2245{
2246 struct group_source_req gsr;
2247 struct ip_mreq_source mreqs;
2250 struct rm_priotracker in_ifa_tracker;
2251 sockunion_t *gsa, *ssa;
2252 struct ifnet *ifp;
2253 struct in_mfilter *imf;
2254 struct ip_moptions *imo;
2255 struct in_msource *ims;
2256 struct in_multi *inm;
2257 int error;
2258 bool is_final;

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

2302 /*
2303 * Attempt to look up hinted ifp from interface address.
2304 * Fallthrough with null ifp iff lookup fails, to
2305 * preserve 4.4BSD mcast API idempotence.
2306 * XXX NOTE WELL: The RFC 3678 API is preferred because
2307 * using an IPv4 address as a key is racy.
2308 */
2309 if (!in_nullhost(mreqs.imr_interface)) {
2248 sockunion_t *gsa, *ssa;
2249 struct ifnet *ifp;
2250 struct in_mfilter *imf;
2251 struct ip_moptions *imo;
2252 struct in_msource *ims;
2253 struct in_multi *inm;
2254 int error;
2255 bool is_final;

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

2299 /*
2300 * Attempt to look up hinted ifp from interface address.
2301 * Fallthrough with null ifp iff lookup fails, to
2302 * preserve 4.4BSD mcast API idempotence.
2303 * XXX NOTE WELL: The RFC 3678 API is preferred because
2304 * using an IPv4 address as a key is racy.
2305 */
2306 if (!in_nullhost(mreqs.imr_interface)) {
2310 IN_IFADDR_RLOCK(&in_ifa_tracker);
2307 struct epoch_tracker et;
2308
2309 NET_EPOCH_ENTER(et);
2311 INADDR_TO_IFP(mreqs.imr_interface, ifp);
2310 INADDR_TO_IFP(mreqs.imr_interface, ifp);
2312 IN_IFADDR_RUNLOCK(&in_ifa_tracker);
2311 /* XXXGL ifref? */
2312 NET_EPOCH_EXIT(et);
2313 }
2314 CTR3(KTR_IGMPV3, "%s: imr_interface = 0x%08x, ifp = %p",
2315 __func__, ntohl(mreqs.imr_interface.s_addr), ifp);
2316
2317 break;
2318
2319 case MCAST_LEAVE_GROUP:
2320 case MCAST_LEAVE_SOURCE_GROUP:

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

2460 * Either an instance of struct in_addr or an instance of struct ip_mreqn
2461 * may be passed to this socket option. An address of INADDR_ANY or an
2462 * interface index of 0 is used to remove a previous selection.
2463 * When no interface is selected, one is chosen for every send.
2464 */
2465static int
2466inp_set_multicast_if(struct inpcb *inp, struct sockopt *sopt)
2467{
2313 }
2314 CTR3(KTR_IGMPV3, "%s: imr_interface = 0x%08x, ifp = %p",
2315 __func__, ntohl(mreqs.imr_interface.s_addr), ifp);
2316
2317 break;
2318
2319 case MCAST_LEAVE_GROUP:
2320 case MCAST_LEAVE_SOURCE_GROUP:

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

2460 * Either an instance of struct in_addr or an instance of struct ip_mreqn
2461 * may be passed to this socket option. An address of INADDR_ANY or an
2462 * interface index of 0 is used to remove a previous selection.
2463 * When no interface is selected, one is chosen for every send.
2464 */
2465static int
2466inp_set_multicast_if(struct inpcb *inp, struct sockopt *sopt)
2467{
2468 struct rm_priotracker in_ifa_tracker;
2469 struct in_addr addr;
2470 struct ip_mreqn mreqn;
2471 struct ifnet *ifp;
2472 struct ip_moptions *imo;
2473 int error;
2474
2475 if (sopt->sopt_valsize == sizeof(struct ip_mreqn)) {
2476 /*

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

2499 */
2500 error = sooptcopyin(sopt, &addr, sizeof(struct in_addr),
2501 sizeof(struct in_addr));
2502 if (error)
2503 return (error);
2504 if (in_nullhost(addr)) {
2505 ifp = NULL;
2506 } else {
2468 struct in_addr addr;
2469 struct ip_mreqn mreqn;
2470 struct ifnet *ifp;
2471 struct ip_moptions *imo;
2472 int error;
2473
2474 if (sopt->sopt_valsize == sizeof(struct ip_mreqn)) {
2475 /*

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

2498 */
2499 error = sooptcopyin(sopt, &addr, sizeof(struct in_addr),
2500 sizeof(struct in_addr));
2501 if (error)
2502 return (error);
2503 if (in_nullhost(addr)) {
2504 ifp = NULL;
2505 } else {
2507 IN_IFADDR_RLOCK(&in_ifa_tracker);
2506 struct epoch_tracker et;
2507
2508 NET_EPOCH_ENTER(et);
2508 INADDR_TO_IFP(addr, ifp);
2509 INADDR_TO_IFP(addr, ifp);
2509 IN_IFADDR_RUNLOCK(&in_ifa_tracker);
2510 /* XXXGL ifref? */
2511 NET_EPOCH_EXIT(et);
2510 if (ifp == NULL)
2511 return (EADDRNOTAVAIL);
2512 }
2513 CTR3(KTR_IGMPV3, "%s: ifp = %p, addr = 0x%08x", __func__, ifp,
2514 ntohl(addr.s_addr));
2515 }
2516
2517 /* Reject interfaces which do not support multicast. */

--- 526 unchanged lines hidden ---
2512 if (ifp == NULL)
2513 return (EADDRNOTAVAIL);
2514 }
2515 CTR3(KTR_IGMPV3, "%s: ifp = %p, addr = 0x%08x", __func__, ifp,
2516 ntohl(addr.s_addr));
2517 }
2518
2519 /* Reject interfaces which do not support multicast. */

--- 526 unchanged lines hidden ---