@@ -767,6 +767,17 @@ int net_context_bind(struct net_context *context, const struct sockaddr *addr,
767767 if (net_ipv6_is_addr_mcast (& addr6 -> sin6_addr )) {
768768 struct net_if_mcast_addr * maddr ;
769769
770+ if (IS_ENABLED (CONFIG_NET_UDP ) &&
771+ net_context_get_type (context ) == SOCK_DGRAM ) {
772+ if (COND_CODE_1 (CONFIG_NET_IPV6 ,
773+ (context -> options .ipv6_mcast_ifindex > 0 ),
774+ (false))) {
775+ IF_ENABLED (CONFIG_NET_IPV6 ,
776+ (iface = net_if_get_by_index (
777+ context -> options .ipv6_mcast_ifindex )));
778+ }
779+ }
780+
770781 maddr = net_if_ipv6_maddr_lookup (& addr6 -> sin6_addr ,
771782 & iface );
772783 if (!maddr ) {
@@ -1830,6 +1841,55 @@ static int get_context_mtu(struct net_context *context,
18301841 return 0 ;
18311842}
18321843
1844+ static int get_context_mcast_ifindex (struct net_context * context ,
1845+ void * value , size_t * len )
1846+ {
1847+ #if defined(CONFIG_NET_IPV6 )
1848+ if (net_context_get_family (context ) != AF_INET6 ) {
1849+ return - EAFNOSUPPORT ;
1850+ }
1851+
1852+ /* If user has not set the ifindex, then get the interface
1853+ * that this socket is bound to.
1854+ */
1855+ if (context -> options .ipv6_mcast_ifindex == 0 ) {
1856+ struct net_if * iface ;
1857+ int ifindex ;
1858+
1859+ if (net_context_is_bound_to_iface (context )) {
1860+ iface = net_context_get_iface (context );
1861+ } else {
1862+ iface = net_if_get_default ();
1863+ }
1864+
1865+ if (!net_if_flag_is_set (iface , NET_IF_IPV6 )) {
1866+ return - EPROTOTYPE ;
1867+ }
1868+
1869+ ifindex = net_if_get_by_iface (iface );
1870+ if (ifindex < 1 ) {
1871+ return - ENOENT ;
1872+ }
1873+
1874+ * ((int * )value ) = ifindex ;
1875+ } else {
1876+ * ((int * )value ) = context -> options .ipv6_mcast_ifindex ;
1877+ }
1878+
1879+ if (len ) {
1880+ * len = sizeof (int );
1881+ }
1882+
1883+ return 0 ;
1884+ #else
1885+ ARG_UNUSED (context );
1886+ ARG_UNUSED (value );
1887+ ARG_UNUSED (len );
1888+
1889+ return - ENOTSUP ;
1890+ #endif
1891+ }
1892+
18331893/* If buf is not NULL, then use it. Otherwise read the data to be written
18341894 * to net_pkt from msghdr.
18351895 */
@@ -2007,7 +2067,7 @@ static int context_sendto(struct net_context *context,
20072067 bool sendto )
20082068{
20092069 const struct msghdr * msghdr = NULL ;
2010- struct net_if * iface ;
2070+ struct net_if * iface = NULL ;
20112071 struct net_pkt * pkt = NULL ;
20122072 sa_family_t family ;
20132073 size_t tmp_len ;
@@ -2067,18 +2127,31 @@ static int context_sendto(struct net_context *context,
20672127 return - EDESTADDRREQ ;
20682128 }
20692129
2130+ if (IS_ENABLED (CONFIG_NET_UDP ) &&
2131+ net_context_get_type (context ) == SOCK_DGRAM ) {
2132+ if (net_ipv6_is_addr_mcast (& addr6 -> sin6_addr ) &&
2133+ COND_CODE_1 (CONFIG_NET_IPV6 ,
2134+ (context -> options .ipv6_mcast_ifindex > 0 ), (false))) {
2135+ IF_ENABLED (CONFIG_NET_IPV6 ,
2136+ (iface = net_if_get_by_index (
2137+ context -> options .ipv6_mcast_ifindex )));
2138+ }
2139+ }
2140+
20702141 /* If application has not yet set the destination address
20712142 * i.e., by not calling connect(), then set the interface
20722143 * here so that the packet gets sent to the correct network
20732144 * interface. This issue can be seen if there are multiple
20742145 * network interfaces and we are trying to send data to
20752146 * second or later network interface.
20762147 */
2077- if (net_ipv6_is_addr_unspecified (
2078- & net_sin6 (& context -> remote )-> sin6_addr ) &&
2079- !net_context_is_bound_to_iface (context )) {
2080- iface = net_if_ipv6_select_src_iface (& addr6 -> sin6_addr );
2081- net_context_set_iface (context , iface );
2148+ if (iface == NULL ) {
2149+ if (net_ipv6_is_addr_unspecified (
2150+ & net_sin6 (& context -> remote )-> sin6_addr ) &&
2151+ !net_context_is_bound_to_iface (context )) {
2152+ iface = net_if_ipv6_select_src_iface (& addr6 -> sin6_addr );
2153+ net_context_set_iface (context , iface );
2154+ }
20822155 }
20832156
20842157 } else if (IS_ENABLED (CONFIG_NET_IPV4 ) && family == AF_INET ) {
@@ -3211,6 +3284,58 @@ static int set_context_timestamping(struct net_context *context,
32113284#endif
32123285}
32133286
3287+ static int set_context_mcast_ifindex (struct net_context * context ,
3288+ const void * value , size_t len )
3289+ {
3290+ #if defined(CONFIG_NET_IPV6 )
3291+ int mcast_ifindex = * ((int * )value );
3292+ enum net_sock_type type ;
3293+ struct net_if * iface ;
3294+
3295+ if (net_context_get_family (context ) != AF_INET6 ) {
3296+ return - EAFNOSUPPORT ;
3297+ }
3298+
3299+ if (len != sizeof (int )) {
3300+ return - EINVAL ;
3301+ }
3302+
3303+ type = net_context_get_type (context );
3304+ if (type != SOCK_DGRAM && type != SOCK_RAW ) {
3305+ return - EINVAL ;
3306+ }
3307+
3308+ /* optlen equal to 0 then remove the binding */
3309+ if (mcast_ifindex == 0 ) {
3310+ context -> options .ipv6_mcast_ifindex = 0 ;
3311+ return 0 ;
3312+ }
3313+
3314+ if (mcast_ifindex < 1 || mcast_ifindex > 255 ) {
3315+ return - EINVAL ;
3316+ }
3317+
3318+ iface = net_if_get_by_index (mcast_ifindex );
3319+ if (iface == NULL ) {
3320+ return - ENOENT ;
3321+ }
3322+
3323+ if (!net_if_flag_is_set (iface , NET_IF_IPV6 )) {
3324+ return - EPROTOTYPE ;
3325+ }
3326+
3327+ context -> options .ipv6_mcast_ifindex = mcast_ifindex ;
3328+
3329+ return 0 ;
3330+ #else
3331+ ARG_UNUSED (context );
3332+ ARG_UNUSED (value );
3333+ ARG_UNUSED (len );
3334+
3335+ return - ENOTSUP ;
3336+ #endif
3337+ }
3338+
32143339int net_context_set_option (struct net_context * context ,
32153340 enum net_context_option option ,
32163341 const void * value , size_t len )
@@ -3290,6 +3415,9 @@ int net_context_set_option(struct net_context *context,
32903415 ret = set_context_ipv6_mtu (context , value , len );
32913416 }
32923417
3418+ break ;
3419+ case NET_OPT_MCAST_IFINDEX :
3420+ ret = set_context_mcast_ifindex (context , value , len );
32933421 break ;
32943422 }
32953423
@@ -3370,6 +3498,9 @@ int net_context_get_option(struct net_context *context,
33703498 case NET_OPT_MTU :
33713499 ret = get_context_mtu (context , value , len );
33723500 break ;
3501+ case NET_OPT_MCAST_IFINDEX :
3502+ ret = get_context_mcast_ifindex (context , value , len );
3503+ break ;
33733504 }
33743505
33753506 k_mutex_unlock (& context -> lock );
0 commit comments