static void _send_multicast(kernel_pid_t iface, gnrc_pktsnip_t *pkt, gnrc_pktsnip_t *ipv6, gnrc_pktsnip_t *payload, bool prep_hdr) { kernel_pid_t ifs[GNRC_NETIF_NUMOF]; size_t ifnum = 0; if (iface == KERNEL_PID_UNDEF) { /* get list of interfaces */ ifnum = gnrc_netif_get(ifs); /* throw away packet if no one is interested */ if (ifnum == 0) { DEBUG("ipv6: no interfaces registered, dropping packet\n"); gnrc_pktbuf_release(pkt); return; } } #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); for (size_t i = 0; i < ifnum; i++) { gnrc_pktsnip_t *netif; if (prep_hdr) { /* need to get second write access (duplication) to fill IPv6 * header interface-local */ 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, " "for interface %" PRIkernel_pid "\n", ifs[i]); gnrc_pktbuf_release(pkt); return; } /* 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(ipv6); return; } } /* allocate interface header */ netif = gnrc_netif_hdr_build(NULL, 0, NULL, 0); if (netif == NULL) { DEBUG("ipv6: error on interface header allocation, " "dropping packet\n"); gnrc_pktbuf_release(ipv6); return; } 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 */ gnrc_pktbuf_release(pkt); return; } } _send_multicast_over_iface(iface, pkt); } #else /* GNRC_NETIF_NUMOF */ (void)ifnum; /* not used in this build branch */ if (iface == KERNEL_PID_UNDEF) { gnrc_pktsnip_t *netif; iface = ifs[0]; /* allocate interface header */ netif = gnrc_netif_hdr_build(NULL, 0, NULL, 0); if (netif == NULL) { DEBUG("ipv6: error on interface header allocation, " "dropping packet\n"); gnrc_pktbuf_release(pkt); return; } LL_PREPEND(pkt, netif); } if (prep_hdr) { if (_fill_ipv6_hdr(iface, ipv6, payload) < 0) { /* error on filling up header */ gnrc_pktbuf_release(pkt); return; } } _send_multicast_over_iface(iface, pkt); #endif /* GNRC_NETIF_NUMOF */ }
static void _send_multicast(kernel_pid_t iface, ng_pktsnip_t *pkt, ng_pktsnip_t *ipv6, ng_pktsnip_t *payload, bool prep_hdr) { ng_pktsnip_t *netif; kernel_pid_t ifs[NG_NETIF_NUMOF]; size_t ifnum = 0; if (iface == KERNEL_PID_UNDEF) { /* get list of interfaces */ ifnum = ng_netif_get(ifs); /* throw away packet if no one is interested */ if (ifnum == 0) { DEBUG("ipv6: no interfaces registered, dropping packet\n"); ng_pktbuf_release(pkt); return; } } #if NG_NETIF_NUMOF > 1 /* netif header not present: send over all interfaces */ if (iface == KERNEL_PID_UNDEF) { /* send packet to link layer */ ng_pktbuf_hold(pkt, ifnum - 1); for (size_t i = 0; i < ifnum; i++) { if (prep_hdr) { /* need to get second write access (duplication) to fill IPv6 * header interface-local */ ipv6 = ng_pktbuf_start_write(ipv6); if (ipv6 == NULL) { DEBUG("ipv6: unable to get write access to IPv6 header, " "for interface %" PRIkernel_pid "\n", ifs[i]); ng_pktbuf_release(pkt); return; } if (_fill_ipv6_hdr(ifs[i], ipv6, payload) < 0) { /* error on filling up header */ ng_pktbuf_release(pkt); return; } } /* allocate interface header */ netif = ng_netif_hdr_build(NULL, 0, NULL, 0); if (netif == NULL) { DEBUG("ipv6: error on interface header allocation, " "dropping packet\n"); ng_pktbuf_release(pkt); return; } LL_PREPEND(pkt, netif); _send_multicast_over_iface(ifs[i], pkt, netif); } } else { /* iface != KERNEL_PID_UNDEF implies that netif header is present */ if (prep_hdr) { if (_fill_ipv6_hdr(iface, ipv6, payload) < 0) { /* error on filling up header */ ng_pktbuf_release(pkt); return; } } netif = pkt; _send_multicast_over_iface(iface, pkt, netif); } #else /* NG_NETIF_NUMOF */ (void)ifnum; /* not used in this build branch */ if (iface == KERNEL_PID_UNDEF) { iface = ifs[0]; /* allocate interface header */ netif = ng_netif_hdr_build(NULL, 0, NULL, 0); if (netif == NULL) { DEBUG("ipv6: error on interface header allocation, " "dropping packet\n"); ng_pktbuf_release(pkt); return; } LL_PREPEND(pkt, netif); } else { netif = pkt; } if (prep_hdr) { if (_fill_ipv6_hdr(iface, ipv6, payload) < 0) { /* error on filling up header */ ng_pktbuf_release(pkt); return; } } _send_multicast_over_iface(iface, pkt, netif); #endif /* NG_NETIF_NUMOF */ }