@@ -128,6 +128,20 @@ static void convert_ns_addr_to_mbed(SocketAddress *s_addr, const ns_address_t *n
128128 s_addr->set_ip_bytes (ns_addr->address , NSAPI_IPv6);
129129}
130130
131+ static int8_t find_interface_by_address (const uint8_t target_addr[16 ])
132+ {
133+ for (int if_id = 1 ; if_id <= 127 ; if_id++) {
134+ int i = 0 ;
135+ uint8_t if_addr[16 ];
136+ while (arm_net_address_list_get_next (if_id, &i, if_addr) == 0 ) {
137+ if (memcmp (target_addr, if_addr, 16 ) == 0 ) {
138+ return if_id;
139+ }
140+ }
141+ }
142+ return -1 ;
143+ }
144+
131145void * NanostackSocket::operator new (std::size_t sz) {
132146 return MALLOC (sz);
133147}
@@ -693,17 +707,50 @@ nsapi_error_t NanostackInterface::setsockopt(void *handle, int level, int optnam
693707 return NSAPI_ERROR_NO_SOCKET;
694708 }
695709
696- nsapi_error_t ret;
697-
698710 NanostackLockGuard lock;
699711
712+ ns_ipv6_mreq_t ns_mreq;
713+
714+ if (level == NSAPI_SOCKET) {
715+ switch (optname) {
716+ case NSAPI_ADD_MEMBERSHIP:
717+ case NSAPI_DROP_MEMBERSHIP: {
718+ if (optlen != sizeof (nsapi_ip_mreq_t )) {
719+ return NSAPI_ERROR_PARAMETER;
720+ }
721+ const nsapi_ip_mreq_t *imr = static_cast <const nsapi_ip_mreq_t *>(optval);
722+
723+ /* Check address types are IPv6, or unspecified for interface */
724+ if (imr->imr_multiaddr .version != NSAPI_IPv6 ||
725+ (imr->imr_interface .version != NSAPI_UNSPEC && imr->imr_interface .version != NSAPI_IPv6)) {
726+ return NSAPI_ERROR_PARAMETER;
727+ }
728+
729+ /* Convert all parameters to Nanostack native, and proceed with setsockopt */
730+ memcpy (ns_mreq.ipv6mr_multiaddr , imr->imr_multiaddr .bytes , 16 );
731+ if (imr->imr_interface .version == NSAPI_UNSPEC || memcmp (imr->imr_interface .bytes , ns_in6addr_any, 16 ) == 0 ) {
732+ ns_mreq.ipv6mr_interface = 0 ;
733+ } else {
734+ // If this fails, Nanostack will itself fault the invalid -1 interface ID
735+ ns_mreq.ipv6mr_interface = find_interface_by_address (imr->imr_interface .bytes );
736+ }
737+
738+ level = SOCKET_IPPROTO_IPV6;
739+ optname = optname == NSAPI_ADD_MEMBERSHIP ? SOCKET_IPV6_JOIN_GROUP : SOCKET_IPV6_LEAVE_GROUP;
740+ optval = &ns_mreq;
741+ optlen = sizeof ns_mreq;
742+ break ;
743+ }
744+ default :
745+ return NSAPI_ERROR_PARAMETER;
746+ }
747+ }
748+
700749 if (::socket_setsockopt (socket->socket_id , level, optname, optval, optlen) == 0 ) {
701- ret = NSAPI_ERROR_OK;
750+ return NSAPI_ERROR_OK;
702751 } else {
703- ret = NSAPI_ERROR_PARAMETER;
752+ return NSAPI_ERROR_PARAMETER;
704753 }
705-
706- return ret;
707754}
708755
709756nsapi_error_t NanostackInterface::getsockopt (void *handle, int level, int optname, void *optval, unsigned *optlen)
0 commit comments