void gnrc_icmpv6_demux(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt) { gnrc_pktsnip_t *icmpv6, *ipv6; icmpv6_hdr_t *hdr; icmpv6 = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_ICMPV6); assert(icmpv6 != NULL); /* there can be extension headers between IPv6 and ICMPv6 header so we have * to search it */ ipv6 = gnrc_pktsnip_search_type(icmpv6, GNRC_NETTYPE_IPV6); assert(ipv6 != NULL); if (icmpv6->size < sizeof(icmpv6_hdr_t)) { DEBUG("icmpv6: packet too short.\n"); return; } /* Note: size will be checked again in packet handlers */ hdr = (icmpv6_hdr_t *)icmpv6->data; if (_calc_csum(icmpv6, ipv6, pkt)) { DEBUG("icmpv6: wrong checksum.\n"); /* don't release: IPv6 does this */ return; } switch (hdr->type) { /* TODO: handle ICMPv6 errors */ #ifdef MODULE_GNRC_ICMPV6_ECHO case ICMPV6_ECHO_REQ: DEBUG("icmpv6: handle echo request.\n"); gnrc_icmpv6_echo_req_handle(netif, (ipv6_hdr_t *)ipv6->data, (icmpv6_echo_t *)hdr, icmpv6->size); break; #endif case ICMPV6_RTR_SOL: case ICMPV6_RTR_ADV: case ICMPV6_NBR_SOL: case ICMPV6_NBR_ADV: case ICMPV6_REDIRECT: case ICMPV6_DAR: case ICMPV6_DAC: DEBUG("icmpv6: NDP message received. Handle with gnrc_ipv6_nib\n"); gnrc_ipv6_nib_handle_pkt(netif, ipv6->data, hdr, icmpv6->size); break; default: DEBUG("icmpv6: unknown type field %u\n", hdr->type); (void)netif; break; } /* ICMPv6-all will be send in gnrc_ipv6.c so only dispatch of subtypes is * needed */ if (!gnrc_netapi_dispatch_receive(GNRC_NETTYPE_ICMPV6, hdr->type, pkt)) { DEBUG("icmpv6: no one interested in type %d\n", hdr->type); gnrc_pktbuf_release(pkt); } }
void gnrc_icmpv6_demux(kernel_pid_t iface, gnrc_pktsnip_t *pkt) { gnrc_pktsnip_t *icmpv6, *ipv6; icmpv6_hdr_t *hdr; gnrc_netreg_entry_t *sendto; LL_SEARCH_SCALAR(pkt, icmpv6, type, GNRC_NETTYPE_ICMPV6); assert(icmpv6 != NULL); /* there can be extension headers between IPv6 and ICMPv6 header so we have * to search it */ LL_SEARCH_SCALAR(icmpv6, ipv6, type, GNRC_NETTYPE_IPV6); assert(ipv6 != NULL); hdr = (icmpv6_hdr_t *)icmpv6->data; if (_calc_csum(icmpv6, ipv6, pkt)) { DEBUG("icmpv6: wrong checksum.\n"); /* don't release: IPv6 does this */ return; } switch (hdr->type) { /* TODO: handle ICMPv6 errors */ #ifdef MODULE_GNRC_ICMPV6_ECHO case ICMPV6_ECHO_REQ: DEBUG("icmpv6: handle echo request.\n"); gnrc_icmpv6_echo_req_handle(iface, (ipv6_hdr_t *)ipv6->data, (icmpv6_echo_t *)hdr, icmpv6->size); break; #endif case ICMPV6_RTR_SOL: DEBUG("icmpv6: router solicitation received\n"); /* TODO */ break; case ICMPV6_RTR_ADV: DEBUG("icmpv6: router advertisement received\n"); /* TODO */ break; case ICMPV6_NBR_SOL: DEBUG("icmpv6: neighbor solicitation received\n"); gnrc_ndp_nbr_sol_handle(iface, pkt, ipv6->data, (ndp_nbr_sol_t *)hdr, icmpv6->size); break; case ICMPV6_NBR_ADV: DEBUG("icmpv6: neighbor advertisement received\n"); gnrc_ndp_nbr_adv_handle(iface, pkt, ipv6->data, (ndp_nbr_adv_t *)hdr, icmpv6->size); break; case ICMPV6_REDIRECT: DEBUG("icmpv6: redirect message received\n"); /* TODO */ break; default: DEBUG("icmpv6: unknown type field %" PRIu8 "\n", hdr->type); break; } /* ICMPv6-all will be send in gnrc_ipv6.c so only dispatch of subtypes is * needed */ sendto = gnrc_netreg_lookup(GNRC_NETTYPE_ICMPV6, hdr->type); if (sendto == NULL) { DEBUG("icmpv6: no receivers for ICMPv6 type %" PRIu8 "\n", hdr->type); /* don't release: IPv6 does this */ return; } /* ICMPv6 is not interested anymore so `- 1` */ gnrc_pktbuf_hold(pkt, gnrc_netreg_num(GNRC_NETTYPE_ICMPV6, hdr->type)); while (sendto != NULL) { gnrc_netapi_receive(sendto->pid, pkt); sendto = gnrc_netreg_getnext(sendto); } }