Skip to content

Commit 7f55e70

Browse files
M1chacfriedt
authored andcommitted
net: mqtt_sn: udp: fix joining v6 multicast group
GCC gave the following warning: mqtt_sn_transport_udp.c: In function ‘tp_udp_init’: mqtt_sn_transport_udp.c:117:9: warning: ‘memcpy’ forming offset [12, 105] is out of the bounds [0, 12] of object ‘mreqn’ with type ‘struct ip_mreqn’ [-Warray-bounds=] 117 | memcpy(&mreqn.imr_multiaddr, &udp->bcaddr.data[2], si... | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ mqtt_sn_transport_udp.c:48:25: note: ‘mreqn’ declared here 48 | struct ip_mreqn mreqn; | ^~~~~ And it turns out that it's right. The original code looks like it tries to copy the IP address to imr_multiaddr in a way that works for both v4 and v6. It ignores, that bcaddr.data may be way larger than even a v6 addr, because it's a buffer that's big enough to hold many other structs as well. Not only that, IP_ADD_MEMBERSHIP is for IPv4 only and imr_multiaddr can only hold an IPv4 address anyway. This modifies the code to have separate code paths for v4 and v6 and call the correct APIs. This also gets rid of the memcpy, since it can be a simple struct assignment now. Signed-off-by: Michael Zimmermann <[email protected]>
1 parent 557d2aa commit 7f55e70

File tree

1 file changed

+28
-8
lines changed

1 file changed

+28
-8
lines changed

subsys/net/lib/mqtt_sn/mqtt_sn_transport_udp.c

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ static int tp_udp_init(struct mqtt_sn_transport *transport)
4545
struct mqtt_sn_transport_udp *udp = UDP_TRANSPORT(transport);
4646
int err;
4747
struct sockaddr addrm;
48-
struct ip_mreqn mreqn;
4948
int optval;
5049
struct net_if *iface;
5150

@@ -112,22 +111,43 @@ static int tp_udp_init(struct mqtt_sn_transport *transport)
112111
return errno;
113112
}
114113

115-
memcpy(&mreqn.imr_multiaddr, &udp->bcaddr.data[2], sizeof(udp->bcaddr.data) - 2);
116114
if (udp->bcaddr.sa_family == AF_INET && IS_ENABLED(CONFIG_NET_IPV4)) {
115+
struct sockaddr_in *bcaddr_in = (struct sockaddr_in *)&udp->bcaddr;
116+
struct ip_mreqn mreqn;
117+
117118
iface = net_if_ipv4_select_src_iface(
118119
&((struct sockaddr_in *)&udp->bcaddr)->sin_addr);
120+
121+
mreqn = (struct ip_mreqn) {
122+
.imr_multiaddr = bcaddr_in->sin_addr,
123+
.imr_ifindex = net_if_get_by_iface(iface),
124+
};
125+
126+
err = zsock_setsockopt(udp->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreqn,
127+
sizeof(mreqn));
128+
if (err < 0) {
129+
return errno;
130+
}
119131
} else if (udp->bcaddr.sa_family == AF_INET6 && IS_ENABLED(CONFIG_NET_IPV6)) {
132+
struct sockaddr_in6 *bcaddr_in6 = (struct sockaddr_in6 *)&udp->bcaddr;
133+
struct ipv6_mreq mreq;
134+
120135
iface = net_if_ipv6_select_src_iface(&((struct sockaddr_in6 *)&addrm)->sin6_addr);
136+
137+
mreq = (struct ipv6_mreq) {
138+
.ipv6mr_multiaddr = bcaddr_in6->sin6_addr,
139+
.ipv6mr_ifindex = net_if_get_by_iface(iface),
140+
};
141+
142+
err = zsock_setsockopt(udp->sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq,
143+
sizeof(mreq));
144+
if (err < 0) {
145+
return errno;
146+
}
121147
} else {
122148
LOG_ERR("Unknown AF");
123149
return -EINVAL;
124150
}
125-
mreqn.imr_ifindex = net_if_get_by_iface(iface);
126-
127-
err = zsock_setsockopt(udp->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreqn, sizeof(mreqn));
128-
if (err < 0) {
129-
return errno;
130-
}
131151

132152
optval = CONFIG_MQTT_SN_LIB_BROADCAST_RADIUS;
133153
err = zsock_setsockopt(udp->sock, IPPROTO_IP, IP_MULTICAST_TTL, &optval, sizeof(optval));

0 commit comments

Comments
 (0)