int run_tests() {
  int i;
  int success = 0, total = 0;
  for (i = 0; i < (sizeof(cases) / sizeof(cases[0])); i++) {
    uint8_t buf[512], *rp, unpack[512];
    struct ip6_packet packet;
    struct ieee154_frame_addr fr, result_fr;
    memset(buf, 0, 512);
    total++;
    printf("\n\n----- Test case %i ----\n", i+1);

    setup_test(&cases[i], &packet.ip6_hdr, &fr);
    printf("IEEE 802.15.4 frame: ");
    print_buffer(&fr, sizeof(struct ieee154_frame_addr));
    printf("\n");
    printf("IPv6 Header:\n");
    print_buffer(&packet.ip6_hdr, sizeof(struct ip6_hdr));
    printf("\n");

    rp = lowpan_pack_headers(&packet, &fr, buf, 512);
    printf("Packed result:\n");
    print_buffer(buf, rp - buf);


    rp = lowpan_unpack_headers(unpack, sizeof(unpack), &result_fr, buf, rp - buf);

    printf("Unpacked result:\n");
    print_buffer(unpack, 40);

    if (memcmp(unpack, &packet.ip6_hdr, 40) == 0)
      success++;
  }
  printf("%s: %i/%i tests succeeded\n", __FILE__, success, total);
  if (success == total) return 0;
  return 1;
}
int lowpan_frag_get(uint8_t *frag, size_t len,
                    struct ip6_packet *packet,
                    struct ieee154_frame_addr *frame,
                    struct lowpan_ctx *ctx) {
  uint8_t *buf, *lowpan_buf, *ieee_buf = frag;
  uint16_t extra_payload;

  /* pack 802.15.4 */
  buf = lowpan_buf = pack_ieee154_header(frag, len, frame);
  if (ctx->offset == 0) {
    int offset = 0;

#if LIB6LOWPAN_HC_VERSION == -1
    /* just copy the ipv6 header around... */
    *buf++ = LOWPAN_IPV6_PATTERN;
    memcpy(buf, &packet->ip6_hdr, sizeof(struct ip6_hdr));
    buf += sizeof(struct ip6_hdr);
#elif !defined(LIB6LOWPAN_HC_VERSION) || LIB6LOWPAN_HC_VERSION == 6
    /* pack the IPv6 header */
    buf = lowpan_pack_headers(packet, frame, buf, len - (buf - frag));
    if (!buf) return -1;

    /* pack the next headers */
    offset = pack_nhc_chain(&buf, len - (buf - ieee_buf), packet);
    if (offset < 0) return -2;
#endif

    /* copy the rest of the payload into this fragment */
    extra_payload = ntohs(packet->ip6_hdr.ip6_plen) - offset;

    /* may need to fragment -- insert a FRAG1 header if so */
    if (extra_payload > len - (buf - ieee_buf)) {
      struct packed_lowmsg lowmsg;
      memmove(lowpan_buf + LOWMSG_FRAG1_LEN, 
                lowpan_buf,
                buf - lowpan_buf);

      lowmsg.data = lowpan_buf;
      lowmsg.len  = LOWMSG_FRAG1_LEN;
      lowmsg.headers = 0;
      setupHeaders(&lowmsg, LOWMSG_FRAG1_HDR);
      setFragDgramSize(&lowmsg, ntohs(packet->ip6_hdr.ip6_plen) + sizeof(struct ip6_hdr));
      setFragDgramTag(&lowmsg, ctx->tag);

      lowpan_buf += LOWMSG_FRAG1_LEN;
      buf += LOWMSG_FRAG1_LEN;

      extra_payload = len - (buf - ieee_buf);
      extra_payload -= (extra_payload % 8);

    }
    
    if (iov_read(packet->ip6_data, offset, extra_payload, buf) != extra_payload) {
      return -3;
    }

    ctx->offset = offset + extra_payload + sizeof(struct ip6_hdr);
    return (buf - frag) + extra_payload;
  } else {
    struct packed_lowmsg lowmsg;
    buf = lowpan_buf = pack_ieee154_header(frag, len, frame);

    /* setup the FRAGN header */
    lowmsg.data = lowpan_buf;
    lowmsg.len = LOWMSG_FRAGN_LEN;
    lowmsg.headers = 0;
    setupHeaders(&lowmsg, LOWMSG_FRAGN_HDR);
    if (setFragDgramSize(&lowmsg, ntohs(packet->ip6_hdr.ip6_plen) + sizeof(struct ip6_hdr)))
      return -5;
    if (setFragDgramTag(&lowmsg, ctx->tag))
      return -6;
    if (setFragDgramOffset(&lowmsg, ctx->offset / 8))
      return -7;
    buf += LOWMSG_FRAGN_LEN;

    extra_payload = ntohs(packet->ip6_hdr.ip6_plen) + sizeof(struct ip6_hdr) - ctx->offset;
    if (extra_payload > len - (buf - ieee_buf)) {
      extra_payload = len - (buf - ieee_buf);
      extra_payload -= (extra_payload % 8);
    }

    if (iov_read(packet->ip6_data, ctx->offset - sizeof(struct ip6_hdr), extra_payload, buf) != extra_payload) {
      return -4;
    }

    ctx->offset += extra_payload;

    if (extra_payload == 0) return 0;
    else return (lowpan_buf - ieee_buf) + LOWMSG_FRAGN_LEN + extra_payload;
  }
}