gnrc_ipv6: fix multi-interface packet duplication
This commit is contained in:
parent
f334a9aa1b
commit
a19b0d8262
@ -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");
|
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 = gnrc_netreg_calc_csum(payload, ipv6)) < 0) {
|
||||||
if (res != -ENOENT) { /* if there is no checksum we are okay */
|
if (res != -ENOENT) { /* if there is no checksum we are okay */
|
||||||
DEBUG("ipv6: checksum calculation failed.\n");
|
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
|
#if GNRC_NETIF_NUMOF > 1
|
||||||
/* netif header not present: send over all interfaces */
|
/* netif header not present: send over all interfaces */
|
||||||
if (iface == KERNEL_PID_UNDEF) {
|
if (iface == KERNEL_PID_UNDEF) {
|
||||||
|
assert(pkt == ipv6);
|
||||||
/* send packet to link layer */
|
/* send packet to link layer */
|
||||||
gnrc_pktbuf_hold(pkt, ifnum - 1);
|
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) {
|
if (prep_hdr) {
|
||||||
/* need to get second write access (duplication) to fill IPv6
|
/* need to get second write access (duplication) to fill IPv6
|
||||||
* header interface-local */
|
* 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) {
|
if (ipv6 == NULL) {
|
||||||
DEBUG("ipv6: unable to get write access to IPv6 header, "
|
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;
|
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 */
|
/* error on filling up header */
|
||||||
gnrc_pktbuf_release(pkt);
|
gnrc_pktbuf_release(ipv6);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -469,17 +465,18 @@ static void _send_multicast(kernel_pid_t iface, gnrc_pktsnip_t *pkt,
|
|||||||
if (netif == NULL) {
|
if (netif == NULL) {
|
||||||
DEBUG("ipv6: error on interface header allocation, "
|
DEBUG("ipv6: error on interface header allocation, "
|
||||||
"dropping packet\n");
|
"dropping packet\n");
|
||||||
gnrc_pktbuf_release(pkt);
|
gnrc_pktbuf_release(ipv6);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LL_PREPEND(pkt, netif);
|
LL_PREPEND(ipv6, netif);
|
||||||
|
|
||||||
_send_multicast_over_iface(ifs[i], ipv6);
|
_send_multicast_over_iface(ifs[i], ipv6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* iface != KERNEL_PID_UNDEF implies that netif header is present */
|
/* iface != KERNEL_PID_UNDEF implies that netif header is present */
|
||||||
|
assert(pkt != ipv6);
|
||||||
if (prep_hdr) {
|
if (prep_hdr) {
|
||||||
if (_fill_ipv6_hdr(iface, ipv6, payload) < 0) {
|
if (_fill_ipv6_hdr(iface, ipv6, payload) < 0) {
|
||||||
/* error on filling up header */
|
/* error on filling up header */
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user