Skip to content

Commit 0cc7a9d

Browse files
kjbraceycmonr
authored andcommitted
NSAPI: Add Nanostack multicast membership support
Add support for recently introduced NSAPI generic socket options to control group membership. Previously applications using Nanostack would have had to use Nanostack's native socket options.
1 parent 9e81356 commit 0cc7a9d

File tree

1 file changed

+53
-6
lines changed

1 file changed

+53
-6
lines changed

features/nanostack/FEATURE_NANOSTACK/nanostack-interface/NanostackInterface.cpp

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
131145
void* 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

709756
nsapi_error_t NanostackInterface::getsockopt(void *handle, int level, int optname, void *optval, unsigned *optlen)

0 commit comments

Comments
 (0)