/** * @brief Function called by the device driver on device events * * @param[in] event type of event * @param[in] data optional parameter */ static void _event_cb(ng_netdev_event_t event, void *data) { DEBUG("nomac: event triggered -> %i\n", event); /* NOMAC only understands the RX_COMPLETE event... */ if (event == NETDEV_EVENT_RX_COMPLETE) { ng_pktsnip_t *pkt; ng_netreg_entry_t *sendto; /* get pointer to the received packet */ pkt = (ng_pktsnip_t *)data; /* find out, who to send the packet to */ sendto = ng_netreg_lookup(pkt->type, NG_NETREG_DEMUX_CTX_ALL); /* throw away packet if no one is interested */ if (sendto == NULL) { DEBUG("nomac: unable to forward packet of type %i\n", pkt->type); ng_pktbuf_release(pkt); return; } /* send the packet to everyone interested in it's type */ ng_pktbuf_hold(pkt, ng_netreg_num(pkt->type, NG_NETREG_DEMUX_CTX_ALL) - 1); while (sendto != NULL) { DEBUG("nomac: sending pkt %p to PID %u\n", (void*)pkt, sendto->pid); ng_netapi_receive(sendto->pid, pkt); sendto = ng_netreg_getnext(sendto); } } }
static void _dispatch_rcv_pkt(ng_nettype_t type, uint32_t demux_ctx, ng_pktsnip_t *pkt) { ng_netreg_entry_t *entry = ng_netreg_lookup(type, demux_ctx); while (entry) { DEBUG("ipv6: Send receive command for %p to %" PRIu16 "\n", (void *)pkt, entry->pid); ng_netapi_receive(entry->pid, pkt); entry = ng_netreg_getnext(entry); } }
/* SLIP receive handler */ static void _slip_receive(ng_slip_dev_t *dev, size_t bytes) { ng_netif_hdr_t *hdr; ng_netreg_entry_t *sendto; ng_pktsnip_t *pkt, *netif_hdr; pkt = ng_pktbuf_add(NULL, NULL, bytes, NG_NETTYPE_UNDEF); if (pkt == NULL) { DEBUG("slip: no space left in packet buffer\n"); return; } netif_hdr = ng_pktbuf_add(pkt, NULL, sizeof(ng_netif_hdr_t), NG_NETTYPE_NETIF); if (netif_hdr == NULL) { DEBUG("slip: no space left in packet buffer\n"); ng_pktbuf_release(pkt); return; } hdr = netif_hdr->data; ng_netif_hdr_init(hdr, 0, 0); hdr->if_pid = thread_getpid(); if (ringbuffer_get(dev->in_buf, pkt->data, bytes) != bytes) { DEBUG("slip: could not read %zu bytes from ringbuffer\n", bytes); ng_pktbuf_release(pkt); return; } #ifdef MODULE_NG_IPV6 if ((pkt->size >= sizeof(ipv6_hdr_t)) && ipv6_hdr_is(pkt->data)) { pkt->type = NG_NETTYPE_IPV6; } #endif sendto = ng_netreg_lookup(pkt->type, NG_NETREG_DEMUX_CTX_ALL); if (sendto == NULL) { DEBUG("slip: unable to forward packet of type %i\n", pkt->type); ng_pktbuf_release(pkt); } ng_pktbuf_hold(pkt, ng_netreg_num(pkt->type, NG_NETREG_DEMUX_CTX_ALL) - 1); while (sendto != NULL) { DEBUG("slip: sending pkt %p to PID %u\n", pkt, sendto->pid); ng_netapi_receive(sendto->pid, pkt); sendto = ng_netreg_getnext(sendto); } }
static void _receive(ng_pktsnip_t *pkt) { ng_pktsnip_t *udp, *ipv6; ng_udp_hdr_t *hdr; uint32_t port; ng_netreg_entry_t *sendto; /* mark UDP header */ udp = ng_pktbuf_start_write(pkt); if (udp == NULL) { DEBUG("udp: unable to get write access to packet\n"); ng_pktbuf_release(pkt); return; } pkt = udp; udp = ng_pktbuf_add(pkt, pkt->data, sizeof(ng_udp_hdr_t), NG_NETTYPE_UDP); if (udp == NULL) { DEBUG("udp: error marking UDP header, dropping packet\n"); ng_pktbuf_release(pkt); return; } /* mark payload as Type: UNDEF */ pkt->type = NG_NETTYPE_UNDEF; /* get explicit pointer to UDP header */ hdr = (ng_udp_hdr_t *)udp->data; LL_SEARCH_SCALAR(pkt, ipv6, type, NG_NETTYPE_IPV6); /* validate checksum */ if (_calc_csum(udp, ipv6, pkt)) { DEBUG("udp: received packet with invalid checksum, dropping it\n"); ng_pktbuf_release(pkt); return; } /* get port (netreg demux context) */ port = (uint32_t)byteorder_ntohs(hdr->dst_port); /* send payload to receivers */ sendto = ng_netreg_lookup(NG_NETTYPE_UDP, port); if (sendto == NULL) { DEBUG("udp: unable to forward packet as no one is interested in it\n"); ng_pktbuf_release(pkt); return; } ng_pktbuf_hold(pkt, ng_netreg_num(NG_NETTYPE_UDP, port) - 1); while (sendto != NULL) { ng_netapi_receive(sendto->pid, pkt); sendto = ng_netreg_getnext(sendto); } }
void ng_icmpv6_demux(kernel_pid_t iface, ng_pktsnip_t *pkt) { ng_pktsnip_t *icmpv6, *ipv6; ng_icmpv6_hdr_t *hdr; ng_netreg_entry_t *sendto; LL_SEARCH_SCALAR(pkt, icmpv6, type, NG_NETTYPE_ICMPV6); /* there can be extension headers between IPv6 and ICMPv6 header so we have * to search it */ LL_SEARCH_SCALAR(icmpv6, ipv6, type, NG_NETTYPE_IPV6); hdr = (ng_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_NG_ICMPV6_ECHO case NG_ICMPV6_ECHO_REQ: DEBUG("icmpv6: handle echo request.\n"); ng_icmpv6_echo_req_handle(iface, (ng_ipv6_hdr_t *)ipv6->data, (ng_icmpv6_echo_t *)hdr, icmpv6->size); break; #endif case NG_ICMPV6_RTR_SOL: DEBUG("icmpv6: router solicitation received\n"); /* TODO */ break; case NG_ICMPV6_RTR_ADV: DEBUG("icmpv6: router advertisement received\n"); /* TODO */ break; case NG_ICMPV6_NBR_SOL: DEBUG("icmpv6: neighbor solicitation received\n"); ng_ndp_nbr_sol_handle(iface, pkt, ipv6->data, (ng_ndp_nbr_sol_t *)hdr, icmpv6->size); break; case NG_ICMPV6_NBR_ADV: DEBUG("icmpv6: neighbor advertisement received\n"); ng_ndp_nbr_adv_handle(iface, pkt, ipv6->data, (ng_ndp_nbr_adv_t *)hdr, icmpv6->size); break; case NG_ICMPV6_REDIRECT: DEBUG("icmpv6: redirect message received\n"); /* TODO */ break; #ifdef MODULE_NG_RPL case NG_ICMPV6_RPL_CTRL: DEBUG("icmpv6: RPL control message received\n"); /* TODO */ break; #endif default: DEBUG("icmpv6: unknown type field %" PRIu8 "\n", hdr->type); break; } /* ICMPv6-all will be send in ng_ipv6.c so only dispatch of subtypes is * needed */ sendto = ng_netreg_lookup(NG_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` */ ng_pktbuf_hold(pkt, ng_netreg_num(NG_NETTYPE_ICMPV6, hdr->type)); while (sendto != NULL) { ng_netapi_receive(sendto->pid, pkt); sendto = ng_netreg_getnext(sendto); } }
static void _send(ng_pktsnip_t *pkt, bool prep_hdr) { kernel_pid_t iface = KERNEL_PID_UNDEF; ng_pktsnip_t *ipv6, *payload; ng_ipv6_addr_t *tmp; ng_ipv6_hdr_t *hdr; /* get IPv6 snip and (if present) generic interface header */ if (pkt->type == NG_NETTYPE_NETIF) { /* If there is already a netif header (routing protocols and * neighbor discovery might add them to preset sending interface) */ iface = ((ng_netif_hdr_t *)pkt->data)->if_pid; /* seize payload as temporary variable */ ipv6 = ng_pktbuf_start_write(pkt); /* write protect for later removal * in _send_unicast() */ if (ipv6 == NULL) { DEBUG("ipv6: unable to get write access to netif header, dropping packet\n"); ng_pktbuf_release(pkt); return; } pkt = ipv6; /* Reset pkt from temporary variable */ ipv6 = pkt->next; } else { ipv6 = pkt; } /* seize payload as temporary variable */ payload = ng_pktbuf_start_write(ipv6); if (payload == NULL) { DEBUG("ipv6: unable to get write access to IPv6 header, dropping packet\n"); ng_pktbuf_release(pkt); return; } if (ipv6 != pkt) { /* in case packet has netif header */ pkt->next = payload;/* pkt is already write-protected so we can do that */ } ipv6 = payload; /* Reset ipv6 from temporary variable */ hdr = ipv6->data; payload = ipv6->next; if (ng_ipv6_addr_is_multicast(&hdr->dst)) { _send_multicast(iface, pkt, ipv6, payload, prep_hdr); } else if ((ng_ipv6_addr_is_loopback(&hdr->dst)) || /* dst is loopback address */ ((iface == KERNEL_PID_UNDEF) && /* or dst registered to any local interface */ ((iface = ng_ipv6_netif_find_by_addr(&tmp, &hdr->dst)) != KERNEL_PID_UNDEF)) || ((iface != KERNEL_PID_UNDEF) && /* or dst registered to given interface */ (ng_ipv6_netif_find_addr(iface, &hdr->dst) != NULL))) { uint8_t *rcv_data; ng_pktsnip_t *ptr = ipv6, *rcv_pkt; if (prep_hdr) { if (_fill_ipv6_hdr(iface, ipv6, payload) < 0) { /* error on filling up header */ ng_pktbuf_release(pkt); return; } } rcv_pkt = ng_pktbuf_add(NULL, NULL, ng_pkt_len(ipv6), NG_NETTYPE_IPV6); if (rcv_pkt == NULL) { DEBUG("ipv6: error on generating loopback packet\n"); ng_pktbuf_release(pkt); return; } rcv_data = rcv_pkt->data; /* "reverse" packet (by making it one snip as if received from NIC) */ while (ptr != NULL) { memcpy(rcv_data, ptr->data, ptr->size); rcv_data += ptr->size; ptr = ptr->next; } ng_pktbuf_release(pkt); DEBUG("ipv6: packet is addressed to myself => loopback\n"); ng_netapi_receive(ng_ipv6_pid, rcv_pkt); } else { uint8_t l2addr_len = NG_IPV6_NC_L2_ADDR_MAX; uint8_t l2addr[l2addr_len]; iface = _next_hop_l2addr(l2addr, &l2addr_len, iface, &hdr->dst, pkt); if (iface == KERNEL_PID_UNDEF) { DEBUG("ipv6: error determining next hop's link layer address\n"); ng_pktbuf_release(pkt); return; } if (prep_hdr) { if (_fill_ipv6_hdr(iface, ipv6, payload) < 0) { /* error on filling up header */ ng_pktbuf_release(pkt); return; } } _send_unicast(iface, l2addr, l2addr_len, pkt); } }
void _receive(ng_pktsnip_t *pkt) { ng_pktsnip_t *payload; uint8_t *dispatch; ng_netreg_entry_t *entry; LL_SEARCH_SCALAR(pkt, payload, type, NG_NETTYPE_SIXLOWPAN); if ((payload == NULL) || (payload->size < 1)) { DEBUG("6lo: Received packet has no 6LoWPAN payload\n"); ng_pktbuf_release(pkt); } dispatch = payload->data; if (dispatch[0] == NG_SIXLOWPAN_UNCOMPRESSED) { ng_pktsnip_t *sixlowpan; DEBUG("6lo: received uncompressed IPv6 packet\n"); payload = ng_pktbuf_start_write(payload); if (payload == NULL) { DEBUG("6lo: can not get write access on received packet\n"); #if defined(DEVELHELP) && defined(ENABLE_DEBUG) ng_pktbuf_stats(); #endif ng_pktbuf_release(pkt); return; } /* packet is uncompressed: just mark and remove the dispatch */ sixlowpan = ng_pktbuf_add(payload, payload->data, sizeof(uint8_t), NG_NETTYPE_SIXLOWPAN); LL_DELETE(pkt, sixlowpan); ng_pktbuf_release(sixlowpan); } #ifdef MODULE_NG_SIXLOWPAN_FRAG else if (ng_sixlowpan_frag_is((ng_sixlowpan_frag_t *)dispatch)) { DEBUG("6lo: received 6LoWPAN fragment\n"); ng_sixlowpan_frag_handle_pkt(pkt); } #endif else { DEBUG("6lo: dispatch %02x ... is not supported\n", dispatch[0]); ng_pktbuf_release(pkt); return; } payload->type = NG_NETTYPE_IPV6; entry = ng_netreg_lookup(NG_NETTYPE_IPV6, NG_NETREG_DEMUX_CTX_ALL); if (entry == NULL) { DEBUG("ipv6: No receivers for this packet found\n"); ng_pktbuf_release(pkt); return; } ng_pktbuf_hold(pkt, ng_netreg_num(NG_NETTYPE_IPV6, NG_NETREG_DEMUX_CTX_ALL) - 1); while (entry) { DEBUG("6lo: Send receive command for %p to %" PRIu16 "\n", (void *)pkt, entry->pid); ng_netapi_receive(entry->pid, pkt); entry = ng_netreg_getnext(entry); } }
void rbuf_add(ng_netif_hdr_t *netif_hdr, ng_sixlowpan_frag_t *frag, size_t frag_size, size_t offset) { rbuf_t *entry; rbuf_int_t *ptr; uint8_t *data = ((uint8_t *)frag) + sizeof(ng_sixlowpan_frag_t); uint16_t dg_frag_size = frag_size; /* may differ on first fragment */ _rbuf_gc(); entry = _rbuf_get(ng_netif_hdr_get_src_addr(netif_hdr), netif_hdr->src_l2addr_len, ng_netif_hdr_get_dst_addr(netif_hdr), netif_hdr->dst_l2addr_len, byteorder_ntohs(frag->disp_size) & NG_SIXLOWPAN_FRAG_SIZE_MASK, byteorder_ntohs(frag->tag)); if (entry == NULL) { DEBUG("6lo rbuf: reassembly buffer full.\n"); return; } ptr = entry->ints; /* dispatches in the first fragment are ignored */ if (offset != 0) { switch (((uint8_t *)(entry->pkt->data))[0]) { case NG_SIXLOWPAN_UNCOMPRESSED: offset++; break; default: break; } data++; /* also don't take offset field */ } else { switch (data[0]) { case NG_SIXLOWPAN_UNCOMPRESSED: dg_frag_size--; break; default: break; } } if ((offset + frag_size) > entry->pkt->size) { DEBUG("6lo rfrag: fragment too big for resulting datagram, discarding datagram\n"); ng_pktbuf_release(entry->pkt); _rbuf_rem(entry); return; } while (ptr != NULL) { if (_rbuf_int_in(ptr, offset, offset + dg_frag_size - 1)) { DEBUG("6lo rfrag: overlapping or same intervals, discarding datagram\n"); ng_pktbuf_release(entry->pkt); _rbuf_rem(entry); return; } ptr = ptr->next; } if (_rbuf_update_ints(entry, offset, dg_frag_size)) { if (dg_frag_size < frag_size) { /* some dispatches do not count to datagram size and we need * more space because of that */ if (ng_pktbuf_realloc_data(entry->pkt, entry->pkt->size + (frag_size - dg_frag_size)) < 0) { DEBUG("6lo rbuf: could not reallocate packet data.\n"); return; } /* move already inserted fragments (frag_size - dg_frag_size) to the right */ if (entry->cur_size > 0) { for (int i = entry->pkt->size - (frag_size - dg_frag_size); i > 0; i--) { uint8_t *d = ((uint8_t *)(entry->pkt->data)) + i; *d = *(d - 1); } } } DEBUG("6lo rbuf: add fragment data\n"); entry->cur_size += (uint16_t)dg_frag_size; memcpy(((uint8_t *)entry->pkt->data) + offset, data, frag_size); } if (entry->cur_size == entry->datagram_size) { kernel_pid_t iface = netif_hdr->if_pid; ng_pktsnip_t *netif = ng_netif_hdr_build(entry->src, entry->src_len, entry->dst, entry->dst_len); if (netif == NULL) { DEBUG("6lo rbuf: error allocating netif header\n"); ng_pktbuf_release(entry->pkt); return; } netif_hdr = netif->data; netif_hdr->if_pid = iface; LL_APPEND(entry->pkt, netif); DEBUG("6lo rbuf: datagram complete, send to self\n"); ng_netapi_receive(thread_getpid(), entry->pkt); _rbuf_rem(entry); } }