static void _send_to_iface(kernel_pid_t iface, ng_pktsnip_t *pkt) { ng_ipv6_netif_t *if_entry = ng_ipv6_netif_get(iface); ((ng_netif_hdr_t *)pkt->data)->if_pid = iface; if ((if_entry != NULL) && (if_entry->flags & NG_IPV6_NETIF_FLAGS_SIXLOWPAN)) { DEBUG("ipv6: send to 6LoWPAN instead\n"); ng_netreg_entry_t *reg = ng_netreg_lookup(NG_NETTYPE_SIXLOWPAN, NG_NETREG_DEMUX_CTX_ALL); if (reg != NULL) { ng_pktbuf_hold(pkt, ng_netreg_num(NG_NETTYPE_SIXLOWPAN, NG_NETREG_DEMUX_CTX_ALL) - 1); } else { DEBUG("ipv6: no 6LoWPAN thread found"); } while (reg) { ng_netapi_send(reg->pid, pkt); reg = ng_netreg_getnext(reg); } } else { ng_netapi_send(iface, pkt); } }
static void _send(ng_pktsnip_t *pkt) { ng_udp_hdr_t *hdr; ng_pktsnip_t *udp_snip; ng_netreg_entry_t *sendto; /* get udp snip and hdr */ LL_SEARCH_SCALAR(pkt, udp_snip, type, NG_NETTYPE_UDP); udp_snip = ng_pktbuf_start_write(udp_snip); if (udp_snip == NULL) { DEBUG("udp: cannot send packet: unable to allocate packet\n"); ng_pktbuf_release(pkt); return; } hdr = (ng_udp_hdr_t *)udp_snip->data; /* fill in size field */ hdr->length = byteorder_htons(ng_pkt_len(udp_snip)); /* and forward packet to the network layer */ sendto = ng_netreg_lookup(pkt->type, NG_NETREG_DEMUX_CTX_ALL); /* throw away packet if no one is interested */ if (sendto == NULL) { DEBUG("udp: cannot send packet: network layer not found\n"); ng_pktbuf_release(pkt); return; } /* send packet to network layer */ ng_pktbuf_hold(pkt, ng_netreg_num(pkt->type, NG_NETREG_DEMUX_CTX_ALL) - 1); while (sendto != NULL) { ng_netapi_send(sendto->pid, pkt); sendto = ng_netreg_getnext(sendto); } }
static void send(char *addr_str, char *port_str, char *data) { uint8_t port[2]; uint16_t tmp; ng_pktsnip_t *payload, *udp, *ip; ng_ipv6_addr_t addr; ng_netreg_entry_t *sendto; /* parse destination address */ if (ng_ipv6_addr_from_str(&addr, addr_str) == NULL) { puts("Error: unable to parse destination address"); return; } /* parse port */ tmp = (uint16_t)atoi(port_str); if (tmp == 0) { puts("Error: unable to parse destination port"); return; } port[0] = (uint8_t)tmp; port[1] = tmp >> 8; /* allocate payload */ payload = ng_pktbuf_add(NULL, data, strlen(data), NG_NETTYPE_UNDEF); if (payload == NULL) { puts("Error: unable to copy data to packet buffer"); return; } /* allocate UDP header, set source port := destination port */ udp = ng_udp_hdr_build(payload, port, 2, port, 2); if (udp == NULL) { puts("Error: unable to allocate UDP header"); ng_pktbuf_release(payload); return; } /* allocate IPv6 header */ ip = ng_ipv6_hdr_build(udp, NULL, 0, (uint8_t *)&addr, sizeof(addr)); if (ip == NULL) { puts("Error: unable to allocate IPv6 header"); ng_pktbuf_release(udp); return; } /* send packet */ sendto = ng_netreg_lookup(NG_NETTYPE_UDP, NG_NETREG_DEMUX_CTX_ALL); if (sendto == NULL) { puts("Error: unable to locate UDP thread"); ng_pktbuf_release(ip); return; } ng_pktbuf_hold(ip, ng_netreg_num(NG_NETTYPE_UDP, NG_NETREG_DEMUX_CTX_ALL) - 1); while (sendto != NULL) { ng_netapi_send(sendto->pid, ip); sendto = ng_netreg_getnext(sendto); } printf("Success: send %i byte to %s:%u\n", payload->size, addr_str, tmp); }
static uint16_t _send_1st_fragment(ng_sixlowpan_netif_t *iface, ng_pktsnip_t *pkt, size_t payload_len, size_t datagram_size) { ng_pktsnip_t *frag; uint16_t max_frag_size = _floor8(iface->max_frag_size - (payload_len - datagram_size) - sizeof(ng_sixlowpan_frag_t)); uint16_t local_offset = 0; ng_sixlowpan_frag_t *hdr; uint8_t *data; DEBUG("6lo frag: determined max_frag_size = %" PRIu16 "\n", max_frag_size); /* 6LoWPAN dispatches don't count into that */ max_frag_size += (payload_len - datagram_size); frag = _build_frag_pkt(pkt, payload_len, max_frag_size + sizeof(ng_sixlowpan_frag_t)); if (frag == NULL) { return 0; } hdr = frag->next->data; data = (uint8_t *)(hdr + 1); hdr->disp_size = byteorder_htons((uint16_t)datagram_size); hdr->disp_size.u8[0] |= NG_SIXLOWPAN_FRAG_1_DISP; hdr->tag = byteorder_htons(_tag); pkt = pkt->next; /* don't copy netif header */ while (pkt != NULL) { size_t clen = _min(max_frag_size - local_offset, pkt->size); memcpy(data + local_offset, pkt->data, clen); local_offset += clen; if (local_offset >= max_frag_size) { break; } pkt = pkt->next; } DEBUG("6lo frag: send first fragment (datagram size: %u, " "datagram tag: %" PRIu16 ", fragment size: %" PRIu16 ")\n", (unsigned int)datagram_size, _tag, local_offset); ng_netapi_send(iface->pid, frag); return local_offset; }
/* shell commands */ int _netif_send(int argc, char **argv) { kernel_pid_t dev; uint8_t addr[MAX_ADDR_LEN]; size_t addr_len; ng_pktsnip_t *pkt; ng_netif_hdr_t *nethdr; uint8_t flags = 0x00; if (argc < 4) { printf("usage: %s <if> [<addr>|bcast] <data>\n", argv[0]); return 1; } /* parse interface */ dev = (kernel_pid_t)atoi(argv[1]); if (!_is_iface(dev)) { puts("error: invalid interface given"); return 1; } /* parse address */ addr_len = ng_netif_addr_from_str(addr, sizeof(addr), argv[2]); if (addr_len == 0) { if (strcmp(argv[2], "bcast") == 0) { flags |= NG_NETIF_HDR_FLAGS_BROADCAST; } else { puts("error: invalid address given"); return 1; } } /* put packet together */ pkt = ng_pktbuf_add(NULL, argv[3], strlen(argv[3]), NG_NETTYPE_UNDEF); pkt = ng_pktbuf_add(pkt, NULL, sizeof(ng_netif_hdr_t) + addr_len, NG_NETTYPE_NETIF); nethdr = (ng_netif_hdr_t *)pkt->data; ng_netif_hdr_init(nethdr, 0, addr_len); ng_netif_hdr_set_dst_addr(nethdr, addr, addr_len); nethdr->flags = flags; /* and send it */ ng_netapi_send(dev, pkt); return 0; }
static void _send_to_iface(kernel_pid_t iface, ng_pktsnip_t *pkt) { ng_ipv6_netif_t *if_entry = ng_ipv6_netif_get(iface); ((ng_netif_hdr_t *)pkt->data)->if_pid = iface; if ((if_entry != NULL) && (if_entry->flags & NG_IPV6_NETIF_FLAGS_SIXLOWPAN)) { DEBUG("ipv6: send to 6LoWPAN instead\n"); if (!ng_netapi_dispatch_send(NG_NETTYPE_SIXLOWPAN, NG_NETREG_DEMUX_CTX_ALL, pkt)) { DEBUG("ipv6: no 6LoWPAN thread found"); ng_pktbuf_release(pkt); } } else { ng_netapi_send(iface, pkt); } }
static void udp_send(const char *str) { uint8_t data[20]; ng_pktsnip_t *payload, *udp, *ip; ng_netreg_entry_t *sendto; memcpy(data, str, strlen(str)); /* allocate payload */ payload = ng_pktbuf_add(NULL, data, strlen(str), NG_NETTYPE_UNDEF); if (payload == NULL) { puts("Error: unable to copy data to packet buffer"); return; } /* allocate UDP header, set source port := destination port */ udp = ng_udp_hdr_build(payload, port, 2, port, 2); if (udp == NULL) { puts("Error: unable to allocate UDP header"); ng_pktbuf_release(payload); return; } /* allocate IPv6 header */ ip = ng_ipv6_hdr_build(udp, NULL, 0, (uint8_t *)&addr, sizeof(addr)); if (ip == NULL) { puts("Error: unable to allocate IPv6 header"); ng_pktbuf_release(udp); return; } /* send packet */ sendto = ng_netreg_lookup(NG_NETTYPE_UDP, NG_NETREG_DEMUX_CTX_ALL); if (sendto == NULL) { puts("Error: unable to locate UDP thread"); ng_pktbuf_release(ip); return; } ng_pktbuf_hold(ip, ng_netreg_num(NG_NETTYPE_UDP, NG_NETREG_DEMUX_CTX_ALL) - 1); while (sendto != NULL) { ng_netapi_send(sendto->pid, ip); sendto = ng_netreg_getnext(sendto); } printf("Send %s\n", str); }
void icn_send(eui64_t *dst, ng_pktsnip_t *pkt) { ng_netif_hdr_t *nethdr; uint8_t flags = 0x00; if (!_linkIsScheduled(dst)) { LOG_DEBUG("No direct neighbor, look for a route\n"); eui64_t *tmp; tmp = _routeLookup(dst); if (tmp == NULL) { LOG_ERROR("Not route for %s found\n", ng_netif_addr_to_str(l2addr_str, sizeof(l2addr_str), dst->uint8, ADDR_LEN_64B)); ng_pktbuf_release(pkt); return; } dst = tmp; } LOG_DEBUG("Sending to %s\n", ng_netif_addr_to_str(l2addr_str, sizeof(l2addr_str), dst->uint8, ADDR_LEN_64B)); /* put packet together */ if (pkt->type == NG_NETTYPE_NETIF) { LOG_DEBUG("packet has already a netif header\n"); } else { LOG_DEBUG("creating netif header\n"); pkt = ng_pktbuf_add(pkt, NULL, sizeof(ng_netif_hdr_t) + ADDR_LEN_64B, NG_NETTYPE_NETIF); } nethdr = (ng_netif_hdr_t *)pkt->data; ng_netif_hdr_init(nethdr, 0, ADDR_LEN_64B); ng_netif_hdr_set_dst_addr(nethdr, dst->uint8, ADDR_LEN_64B); nethdr->flags = flags; /* and send it */ send_counter++; ng_netapi_send(*if_id, pkt); }
void ng_icmpv6_echo_req_handle(kernel_pid_t iface, ng_ipv6_hdr_t *ipv6_hdr, ng_icmpv6_echo_t *echo, uint16_t len) { uint8_t *payload = ((uint8_t *)echo) + sizeof(ng_icmpv6_echo_t); ng_pktsnip_t *hdr, *pkt; ng_netreg_entry_t *sendto = NULL; if ((echo == NULL) || (len < sizeof(ng_icmpv6_echo_t))) { DEBUG("icmpv6_echo: echo was NULL or len (%" PRIu16 ") was < sizeof(ng_icmpv6_echo_t)\n", len); return; } pkt = ng_icmpv6_echo_build(NG_ICMPV6_ECHO_REP, byteorder_ntohs(echo->id), byteorder_ntohs(echo->seq), payload, len - sizeof(ng_icmpv6_echo_t)); if (pkt == NULL) { DEBUG("icmpv6_echo: no space left in packet buffer\n"); return; } if (ipv6_addr_is_multicast(&ipv6_hdr->dst)) { hdr = ng_ipv6_hdr_build(pkt, NULL, 0, (uint8_t *)&ipv6_hdr->src, sizeof(ipv6_addr_t)); } else { hdr = ng_ipv6_hdr_build(pkt, (uint8_t *)&ipv6_hdr->dst, sizeof(ipv6_addr_t), (uint8_t *)&ipv6_hdr->src, sizeof(ipv6_addr_t)); } if (hdr == NULL) { DEBUG("icmpv6_echo: no space left in packet buffer\n"); ng_pktbuf_release(pkt); return; } pkt = hdr; hdr = ng_netif_hdr_build(NULL, 0, NULL, 0); ((ng_netif_hdr_t *)hdr->data)->if_pid = iface; LL_PREPEND(pkt, hdr); sendto = ng_netreg_lookup(NG_NETTYPE_IPV6, NG_NETREG_DEMUX_CTX_ALL); if (sendto == NULL) { DEBUG("icmpv6_echo: no receivers for IPv6 packets\n"); ng_pktbuf_release(pkt); return; } /* ICMPv6 is not interested anymore so `- 1` */ ng_pktbuf_hold(pkt, ng_netreg_num(NG_NETTYPE_IPV6, NG_NETREG_DEMUX_CTX_ALL) - 1); while (sendto != NULL) { ng_netapi_send(sendto->pid, pkt); sendto = ng_netreg_getnext(sendto); } }
static void _send_nbr_adv(kernel_pid_t iface, ng_ipv6_addr_t *tgt, ng_ipv6_addr_t *dst, bool supply_tl2a) { ng_pktsnip_t *hdr, *pkt = NULL; uint8_t adv_flags = 0; DEBUG("ndp: send neighbor advertisement (iface: %" PRIkernel_pid ", tgt: %s, ", iface, ng_ipv6_addr_to_str(addr_str, tgt, sizeof(addr_str))); DEBUG("dst: %s, supply_tl2a: %d)\n", ng_ipv6_addr_to_str(addr_str, dst, sizeof(addr_str)), supply_tl2a); if (ng_ipv6_netif_get(iface)->flags & NG_IPV6_NETIF_FLAGS_ROUTER) { adv_flags |= NG_NDP_NBR_ADV_FLAGS_R; } if (ng_ipv6_addr_is_unspecified(dst)) { ng_ipv6_addr_set_all_nodes_multicast(dst, NG_IPV6_ADDR_MCAST_SCP_LINK_LOCAL); } else { adv_flags |= NG_NDP_NBR_ADV_FLAGS_S; } if (supply_tl2a) { uint8_t l2src[8]; uint16_t l2src_len; /* we previously checked if we are the target, so we can take our L2src */ l2src_len = _get_l2src(l2src, sizeof(l2src), iface); if (l2src_len > 0) { /* add target address link-layer address option */ pkt = ng_ndp_opt_tl2a_build(l2src, l2src_len, NULL); if (pkt == NULL) { DEBUG("ndp: error allocating Target Link-layer address option.\n"); ng_pktbuf_release(pkt); return; } } } /* TODO: also check if the node provides proxy servies for tgt */ if ((pkt != NULL) && !ng_ipv6_netif_addr_is_non_unicast(tgt)) { /* TL2A is not supplied and tgt is not anycast */ adv_flags |= NG_NDP_NBR_ADV_FLAGS_O; } hdr = ng_ndp_nbr_adv_build(adv_flags, tgt, pkt); if (hdr == NULL) { DEBUG("ndp: error allocating Neighbor advertisement.\n"); ng_pktbuf_release(pkt); return; } pkt = hdr; hdr = ng_ipv6_hdr_build(pkt, NULL, 0, (uint8_t *)dst, sizeof(ng_ipv6_addr_t)); if (hdr == NULL) { DEBUG("ndp: error allocating IPv6 header.\n"); ng_pktbuf_release(pkt); return; } ((ng_ipv6_hdr_t *)hdr->data)->hl = 255; pkt = hdr; /* add netif header for send interface specification */ hdr = ng_netif_hdr_build(NULL, 0, NULL, 0); if (hdr == NULL) { DEBUG("ndp: error allocating netif header.\n"); return; } ((ng_netif_hdr_t *)hdr->data)->if_pid = iface; LL_PREPEND(pkt, hdr); if (ng_ipv6_netif_addr_is_non_unicast(tgt)) { /* avoid collision for anycast addresses * (see https://tools.ietf.org/html/rfc4861#section-7.2.7) */ timex_t delay = { _rand(0, NG_NDP_MAX_AC_TGT_DELAY), 0 }; ng_ipv6_nc_t *nc_entry = ng_ipv6_nc_get(iface, tgt); DEBUG("ndp: delay neighbor advertisement for %" PRIu32 " sec.", delay.seconds); /* nc_entry must be set so no need to check it */ _send_delayed(&nc_entry->nbr_adv_timer, delay, pkt); } else { ng_netapi_send(ng_ipv6_pid, pkt); } }
static void _send_nbr_sol(kernel_pid_t iface, ng_ipv6_addr_t *tgt, ng_ipv6_addr_t *dst) { ng_pktsnip_t *hdr, *pkt = NULL; ng_ipv6_addr_t *src = NULL; size_t src_len = 0; DEBUG("ndp: send neighbor solicitation (iface: %" PRIkernel_pid ", tgt: %s, ", iface, ng_ipv6_addr_to_str(addr_str, tgt, sizeof(addr_str))); DEBUG("dst: %s)\n", ng_ipv6_addr_to_str(addr_str, dst, sizeof(addr_str))); /* check if there is a fitting source address to target */ if ((src = ng_ipv6_netif_find_best_src_addr(iface, tgt)) != NULL) { uint8_t l2src[8]; uint16_t l2src_len; src_len = sizeof(ng_ipv6_addr_t); l2src_len = _get_l2src(l2src, sizeof(l2src), iface); if (l2src_len > 0) { /* add source address link-layer address option */ pkt = ng_ndp_opt_sl2a_build(l2src, l2src_len, NULL); if (pkt == NULL) { DEBUG("ndp: error allocating Source Link-layer address option.\n"); ng_pktbuf_release(pkt); return; } } } hdr = ng_ndp_nbr_sol_build(tgt, pkt); if (hdr == NULL) { DEBUG("ndp: error allocating Neighbor solicitation.\n"); ng_pktbuf_release(pkt); return; } pkt = hdr; hdr = ng_ipv6_hdr_build(pkt, (uint8_t *)src, src_len, (uint8_t *)dst, sizeof(ng_ipv6_addr_t)); if (hdr == NULL) { DEBUG("ndp: error allocating IPv6 header.\n"); ng_pktbuf_release(pkt); return; } ((ng_ipv6_hdr_t *)hdr->data)->hl = 255; pkt = hdr; /* add netif header for send interface specification */ hdr = ng_netif_hdr_build(NULL, 0, NULL, 0); if (hdr == NULL) { DEBUG("ndp: error allocating netif header.\n"); return; } ((ng_netif_hdr_t *)hdr->data)->if_pid = iface; LL_PREPEND(pkt, hdr); ng_netapi_send(ng_ipv6_pid, pkt); }
void ng_ndp_nbr_adv_handle(kernel_pid_t iface, ng_pktsnip_t *pkt, ng_ipv6_hdr_t *ipv6, ng_ndp_nbr_adv_t *nbr_adv, size_t icmpv6_size) { uint16_t opt_offset = 0; uint8_t *buf = ((uint8_t *)nbr_adv) + sizeof(ng_ndp_nbr_adv_t); int l2tgt_len = 0; uint8_t l2tgt[NG_IPV6_NC_L2_ADDR_MAX]; int sicmpv6_size = (int)icmpv6_size; ng_ipv6_nc_t *nc_entry = ng_ipv6_nc_get(iface, &nbr_adv->tgt); ng_pktsnip_t *netif; ng_netif_hdr_t *netif_hdr = NULL; DEBUG("ndp: received neighbor advertisement (src: %s, ", ng_ipv6_addr_to_str(addr_str, &ipv6->src, sizeof(addr_str))); DEBUG("dst: %s, ", ng_ipv6_addr_to_str(addr_str, &ipv6->dst, sizeof(addr_str))); DEBUG("tgt: %s)\n", ng_ipv6_addr_to_str(addr_str, &nbr_adv->tgt, sizeof(addr_str))); /* check validity */ if ((ipv6->hl != 255) || (nbr_adv->code != 0) || (icmpv6_size < sizeof(ng_ndp_nbr_adv_t)) || ng_ipv6_addr_is_multicast(&nbr_adv->tgt)) { DEBUG("ndp: neighbor advertisement was invalid.\n"); /* ipv6 releases */ return; } if (nc_entry == NULL) { /* see https://tools.ietf.org/html/rfc4861#section-7.2.5 */ DEBUG("ndp: no neighbor cache entry found for advertisement's target\n"); /* ipv6 releases */ return; } sicmpv6_size -= sizeof(ng_ndp_nbr_adv_t); while (sicmpv6_size > 0) { ng_ndp_opt_t *opt = (ng_ndp_opt_t *)(buf + opt_offset); switch (opt->type) { case NG_NDP_OPT_TL2A: if ((l2tgt_len = _handle_tl2a_opt(pkt, ipv6, nbr_adv->type, opt, l2tgt)) < 0) { /* invalid target link-layer address option */ return; } break; default: /* silently discard all other options */ break; } opt_offset += (opt->len * 8); sicmpv6_size -= (opt->len * 8); } LL_SEARCH_SCALAR(pkt, netif, type, NG_NETTYPE_NETIF); if (netif != NULL) { netif_hdr = netif->data; } if (ng_ipv6_nc_get_state(nc_entry) == NG_IPV6_NC_STATE_INCOMPLETE) { ng_pktqueue_t *queued_pkt; if (_pkt_has_l2addr(netif_hdr) && (l2tgt_len == 0)) { /* link-layer has addresses, but no TLLAO supplied: discard silently * (see https://tools.ietf.org/html/rfc4861#section-7.2.5) */ return; } nc_entry->iface = iface; nc_entry->l2_addr_len = l2tgt_len; memcpy(nc_entry->l2_addr, l2tgt, l2tgt_len); if (nbr_adv->flags & NG_NDP_NBR_ADV_FLAGS_S) { _set_state(nc_entry, NG_IPV6_NC_STATE_REACHABLE); } else { _set_state(nc_entry, NG_IPV6_NC_STATE_STALE); } if (nbr_adv->flags & NG_NDP_NBR_ADV_FLAGS_R) { nc_entry->flags |= NG_IPV6_NC_IS_ROUTER; } else { nc_entry->flags &= ~NG_IPV6_NC_IS_ROUTER; /* TODO: update FIB */ } while ((queued_pkt = ng_pktqueue_remove_head(&nc_entry->pkts)) != NULL) { ng_netapi_send(ng_ipv6_pid, queued_pkt->pkt); queued_pkt->pkt = NULL; } } else { /* first or-term: no link-layer, but nc_entry has l2addr, * second or-term: different l2addr cached */ bool l2tgt_changed = false; if ((!_pkt_has_l2addr(netif_hdr)) && (l2tgt_len == 0)) { /* there was previously a L2 address registered */ l2tgt_changed = (nc_entry->l2_addr_len != 0); } /* link-layer has addresses and TLLAO with different address */ else if (_pkt_has_l2addr(netif_hdr) && (l2tgt_len != 0)) { l2tgt_changed = (!(l2tgt_len == nc_entry->l2_addr_len)) && (memcmp(nc_entry->l2_addr, l2tgt, l2tgt_len) == 0); } if ((nbr_adv->flags & NG_NDP_NBR_ADV_FLAGS_O) || !l2tgt_changed || (l2tgt_len == 0)) { if (l2tgt_len != 0) { nc_entry->iface = iface; nc_entry->l2_addr_len = l2tgt_len; memcpy(nc_entry->l2_addr, l2tgt, l2tgt_len); } if (nbr_adv->flags & NG_NDP_NBR_ADV_FLAGS_S) { _set_state(nc_entry, NG_IPV6_NC_STATE_REACHABLE); } else if (l2tgt_changed && (l2tgt_len != 0)) { _set_state(nc_entry, NG_IPV6_NC_STATE_STALE); } if (nbr_adv->flags & NG_NDP_NBR_ADV_FLAGS_R) { nc_entry->flags |= NG_IPV6_NC_IS_ROUTER; } else { nc_entry->flags &= ~NG_IPV6_NC_IS_ROUTER; /* TODO: update FIB */ } } else if (l2tgt_changed) { if (ng_ipv6_nc_get_state(nc_entry) == NG_IPV6_NC_STATE_REACHABLE) { _set_state(nc_entry, NG_IPV6_NC_STATE_STALE); } } } return; }
static inline void _send_to_iface(kernel_pid_t iface, ng_pktsnip_t *pkt) { ((ng_netif_hdr_t *)pkt->data)->if_pid = iface; ng_netapi_send(iface, pkt); }
static void _send(ng_pktsnip_t *pkt) { ng_netif_hdr_t *hdr; ng_pktsnip_t *ipv6, *sixlowpan; ng_sixlowpan_netif_t *iface; /* cppcheck: datagram_size will be read by frag */ /* cppcheck-suppress unreadVariable */ size_t payload_len, datagram_size; uint16_t max_frag_size; /* cppcheck: disp is needed in other build paths on this level already */ /* cppcheck-suppress variableScope */ uint8_t *disp; if ((pkt == NULL) || (pkt->size < sizeof(ng_netif_hdr_t))) { DEBUG("6lo: Sending packet has no netif header\n"); ng_pktbuf_release(pkt); return; } hdr = pkt->data; ipv6 = pkt->next; if ((ipv6 == NULL) || (ipv6->type != NG_NETTYPE_IPV6)) { DEBUG("6lo: Sending packet has no IPv6 header\n"); ng_pktbuf_release(pkt); return; } /* payload length and datagram size are different in that the payload * length is the length of the IPv6 datagram + 6LoWPAN dispatches, * while the datagram size is the size of only the IPv6 datagram */ payload_len = ng_pkt_len(ipv6); /* cppcheck: datagram_size will be read by ng_sixlowpan_frag implementation */ /* cppcheck-suppress unreadVariable */ datagram_size = (uint16_t)payload_len; /* use sixlowpan packet snip as temporary one */ sixlowpan = ng_pktbuf_start_write(pkt); if (sixlowpan == NULL) { DEBUG("6lo: no space left in packet buffer\n"); ng_pktbuf_release(pkt); return; } pkt = sixlowpan; iface = ng_sixlowpan_netif_get(hdr->if_pid); if (iface == NULL) { if (ng_netapi_get(hdr->if_pid, NETCONF_OPT_MAX_PACKET_SIZE, 0, &max_frag_size, sizeof(max_frag_size)) < 0) { /* if error we assume it works */ DEBUG("6lo: can not get max packet size from interface %" PRIkernel_pid "\n", hdr->if_pid); max_frag_size = UINT16_MAX; } ng_sixlowpan_netif_add(hdr->if_pid, max_frag_size); iface = ng_sixlowpan_netif_get(hdr->if_pid); } else { max_frag_size = iface->max_frag_size; } #ifdef MODULE_NG_SIXLOWPAN_IPHC if (iface->iphc_enabled) { if (!ng_sixlowpan_iphc_encode(pkt)) { DEBUG("6lo: error on IPHC encoding\n"); ng_pktbuf_release(pkt); return; } } else { DEBUG("6lo: Send uncompressed\n"); sixlowpan = ng_pktbuf_add(NULL, NULL, sizeof(uint8_t), NG_NETTYPE_SIXLOWPAN); if (sixlowpan == NULL) { DEBUG("6lo: no space left in packet buffer\n"); ng_pktbuf_release(pkt); return; } sixlowpan->next = ipv6; pkt->next = sixlowpan; disp = sixlowpan->data; disp[0] = NG_SIXLOWPAN_UNCOMPRESSED; payload_len++; } #else DEBUG("6lo: Send uncompressed\n"); sixlowpan = ng_pktbuf_add(NULL, NULL, sizeof(uint8_t), NG_NETTYPE_SIXLOWPAN); if (sixlowpan == NULL) { DEBUG("6lo: no space left in packet buffer\n"); ng_pktbuf_release(pkt); return; } sixlowpan->next = ipv6; pkt->next = sixlowpan; disp = sixlowpan->data; disp[0] = NG_SIXLOWPAN_UNCOMPRESSED; payload_len++; #endif DEBUG("6lo: max_frag_size = %" PRIu16 " for interface %" PRIkernel_pid "\n", max_frag_size, hdr->if_pid); /* IP should not send anything here if it is not a 6LoWPAN interface, * so we don't need to check for NULL pointers */ if (payload_len <= max_frag_size) { DEBUG("6lo: Send SND command for %p to %" PRIu16 "\n", (void *)pkt, hdr->if_pid); ng_netapi_send(hdr->if_pid, pkt); return; } #ifdef MODULE_NG_SIXLOWPAN_FRAG else { DEBUG("6lo: Send fragmented (%u > %" PRIu16 ")\n", (unsigned int)payload_len, max_frag_size); ng_sixlowpan_frag_send(hdr->if_pid, pkt, payload_len, datagram_size); } #else (void)datagram_size; DEBUG("6lo: packet too big (%u> %" PRIu16 ")\n", (unsigned int)payload_len, max_frag_size); #endif }
static void _send(ng_pktsnip_t *pkt) { ng_netif_hdr_t *hdr; ng_pktsnip_t *pkt2; ng_sixlowpan_netif_t *iface; /* datagram_size: pure IPv6 packet without 6LoWPAN dispatches or compression */ size_t datagram_size; if ((pkt == NULL) || (pkt->size < sizeof(ng_netif_hdr_t))) { DEBUG("6lo: Sending packet has no netif header\n"); ng_pktbuf_release(pkt); return; } if ((pkt->next == NULL) || (pkt->next->type != NG_NETTYPE_IPV6)) { DEBUG("6lo: Sending packet has no IPv6 header\n"); ng_pktbuf_release(pkt); return; } pkt2 = ng_pktbuf_start_write(pkt); if (pkt2 == NULL) { DEBUG("6lo: no space left in packet buffer\n"); ng_pktbuf_release(pkt); return; } hdr = pkt2->data; iface = ng_sixlowpan_netif_get(hdr->if_pid); datagram_size = ng_pkt_len(pkt2->next); if (iface == NULL) { DEBUG("6lo: Can not get 6LoWPAN specific interface information.\n"); ng_pktbuf_release(pkt); return; } #ifdef MODULE_NG_SIXLOWPAN_IPHC if (iface->iphc_enabled) { if (!ng_sixlowpan_iphc_encode(pkt2)) { DEBUG("6lo: error on IPHC encoding\n"); ng_pktbuf_release(pkt2); return; } /* IPHC dispatch does not count on dispatch length since it _shortens_ * the datagram */ } else { if (!_add_uncompr_disp(pkt2)) { /* adding uncompressed dispatch failed */ DEBUG("6lo: no space left in packet buffer\n"); ng_pktbuf_release(pkt2); return; } } #else /* suppress clang-analyzer report about iface being not read */ (void) iface; if (!_add_uncompr_disp(pkt2)) { /* adding uncompressed dispatch failed */ DEBUG("6lo: no space left in packet buffer\n"); ng_pktbuf_release(pkt2); return; } #endif DEBUG("6lo: iface->max_frag_size = %" PRIu16 " for interface %" PRIkernel_pid "\n", iface->max_frag_size, hdr->if_pid); /* IP should not send anything here if it is not a 6LoWPAN interface, * so we don't need to check for NULL pointers */ if (datagram_size <= iface->max_frag_size) { DEBUG("6lo: Send SND command for %p to %" PRIu16 "\n", (void *)pkt2, hdr->if_pid); ng_netapi_send(hdr->if_pid, pkt2); return; } #ifdef MODULE_NG_SIXLOWPAN_FRAG else { DEBUG("6lo: Send fragmented (%u > %" PRIu16 ")\n", (unsigned int)datagram_size, iface->max_frag_size); ng_sixlowpan_frag_send(hdr->if_pid, pkt2, datagram_size); } #else (void)datagram_size; DEBUG("6lo: packet too big (%u> %" PRIu16 ")\n", (unsigned int)datagram_size, iface->max_frag_size); #endif }
static uint16_t _send_nth_fragment(ng_sixlowpan_netif_t *iface, ng_pktsnip_t *pkt, size_t payload_len, size_t datagram_size, uint16_t offset) { ng_pktsnip_t *frag; uint16_t max_frag_size = _floor8(iface->max_frag_size - sizeof(ng_sixlowpan_frag_n_t)); uint16_t local_offset = 0, offset_count = 0; ng_sixlowpan_frag_n_t *hdr; uint8_t *data; DEBUG("6lo frag: determined max_frag_size = %" PRIu16 "\n", max_frag_size); frag = _build_frag_pkt(pkt, payload_len - offset + sizeof(ng_sixlowpan_frag_n_t), max_frag_size + sizeof(ng_sixlowpan_frag_n_t)); if (frag == NULL) { return 0; } hdr = frag->next->data; data = (uint8_t *)(hdr + 1); /* XXX: truncation of datagram_size > 4095 may happen here */ hdr->disp_size = byteorder_htons((uint16_t)datagram_size); hdr->disp_size.u8[0] |= NG_SIXLOWPAN_FRAG_N_DISP; hdr->tag = byteorder_htons(_tag); hdr->offset = (uint8_t)(offset >> 3); pkt = pkt->next; /* don't copy netif header */ while ((pkt != NULL) && (offset_count != offset)) { /* go to offset */ offset_count += (uint16_t)pkt->size; if (offset_count > offset) { /* we overshot */ /* => copy rest of partly send packet snip */ uint16_t pkt_offset = offset - (offset_count - ((uint16_t)pkt->size)); size_t clen = _min(max_frag_size, pkt->size - pkt_offset); memcpy(data, ((uint8_t *)pkt->data) + pkt_offset, clen); local_offset = clen; pkt = pkt->next; break; } pkt = pkt->next; } if (local_offset < max_frag_size) { /* copy other packet snips */ while (pkt != NULL) { size_t clen = _min(max_frag_size - local_offset, pkt->size); memcpy(data + local_offset, pkt->data, clen); local_offset += clen; if (local_offset == max_frag_size) { break; } pkt = pkt->next; } } DEBUG("6lo frag: send subsequent fragment (datagram size: %u, " "datagram tag: %" PRIu16 ", offset: %" PRIu8 " (%u bytes), " "fragment size: %" PRIu16 ")\n", (unsigned int)datagram_size, _tag, hdr->offset, hdr->offset << 3, local_offset); ng_netapi_send(iface->pid, frag); return local_offset; }