Skip to content

Commit 6b034fb

Browse files
authored
Merge pull request #5870 from kjbracey-arm/multicast_ns
NSAPI: Add Nanostack multicast membership support
2 parents 1a3dae7 + 268a07d commit 6b034fb

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)