1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-18 12:52:44 +01:00

gnrc_ipv6: fix multi-interface packet duplication

This commit is contained in:
Martine Lenders 2015-09-26 06:09:54 +02:00
parent f334a9aa1b
commit a19b0d8262

View File

@ -376,27 +376,6 @@ static int _fill_ipv6_hdr(kernel_pid_t iface, gnrc_pktsnip_t *ipv6,
DEBUG("ipv6: calculate checksum for upper header.\n");
#if GNRC_NETIF_NUMOF > 1
if (payload->users > 1) {
gnrc_pktsnip_t *ptr = ipv6;
/* We deal with multiple interfaces here (multicast) => possible
* different source addresses => duplication of payload needed */
while (ptr != payload->next) {
gnrc_pktsnip_t *old = ptr->next;
/* duplicate everything including payload */
ptr->next = gnrc_pktbuf_start_write(ptr->next);
if (ptr->next == NULL) {
DEBUG("ipv6: unable to get write access to payload, drop it\n");
return -ENOBUFS;
}
ptr = old;
}
}
#endif /* GNRC_NETIF_NUMOF */
if ((res = gnrc_netreg_calc_csum(payload, ipv6)) < 0) {
if (res != -ENOENT) { /* if there is no checksum we are okay */
DEBUG("ipv6: checksum calculation failed.\n");
@ -439,6 +418,7 @@ static void _send_multicast(kernel_pid_t iface, gnrc_pktsnip_t *pkt,
#if GNRC_NETIF_NUMOF > 1
/* netif header not present: send over all interfaces */
if (iface == KERNEL_PID_UNDEF) {
assert(pkt == ipv6);
/* send packet to link layer */
gnrc_pktbuf_hold(pkt, ifnum - 1);
@ -447,7 +427,9 @@ static void _send_multicast(kernel_pid_t iface, gnrc_pktsnip_t *pkt,
if (prep_hdr) {
/* need to get second write access (duplication) to fill IPv6
* header interface-local */
ipv6 = gnrc_pktbuf_start_write(ipv6);
gnrc_pktsnip_t *tmp = gnrc_pktbuf_start_write(pkt);
gnrc_pktsnip_t *ptr = tmp->next;
ipv6 = tmp;
if (ipv6 == NULL) {
DEBUG("ipv6: unable to get write access to IPv6 header, "
@ -456,9 +438,23 @@ static void _send_multicast(kernel_pid_t iface, gnrc_pktsnip_t *pkt,
return;
}
if (_fill_ipv6_hdr(ifs[i], ipv6, payload) < 0) {
/* multiple interfaces => possibly different source addresses
* => different checksums => duplication of payload needed */
while (ptr != payload->next) {
/* duplicate everything including payload */
tmp->next = gnrc_pktbuf_start_write(ptr);
if (tmp->next == NULL) {
DEBUG("ipv6: unable to get write access to payload, drop it\n");
gnrc_pktbuf_release(ipv6);
return;
}
tmp = tmp->next;
ptr = ptr->next;
}
if (_fill_ipv6_hdr(ifs[i], ipv6, tmp) < 0) {
/* error on filling up header */
gnrc_pktbuf_release(pkt);
gnrc_pktbuf_release(ipv6);
return;
}
}
@ -469,17 +465,18 @@ static void _send_multicast(kernel_pid_t iface, gnrc_pktsnip_t *pkt,
if (netif == NULL) {
DEBUG("ipv6: error on interface header allocation, "
"dropping packet\n");
gnrc_pktbuf_release(pkt);
gnrc_pktbuf_release(ipv6);
return;
}
LL_PREPEND(pkt, netif);
LL_PREPEND(ipv6, netif);
_send_multicast_over_iface(ifs[i], ipv6);
}
}
else {
/* iface != KERNEL_PID_UNDEF implies that netif header is present */
assert(pkt != ipv6);
if (prep_hdr) {
if (_fill_ipv6_hdr(iface, ipv6, payload) < 0) {
/* error on filling up header */