int lowpan_recon_start(struct ieee154_frame_addr *frame_addr,
                       struct lowpan_reconstruct *recon,
                       uint8_t *pkt, size_t len) {
  uint8_t *unpack_point, *unpack_end;
  struct packed_lowmsg msg;

  msg.data = pkt;
  msg.len  = len;
  msg.headers = getHeaderBitmap(&msg);
  if (msg.headers == LOWMSG_NALP) return -1;

  /* remove the 6lowpan headers from the payload */
  unpack_point = getLowpanPayload(&msg);
  len -= (unpack_point - pkt);

  /* set up the reconstruction, or just fill in the packet length */
  if (hasFrag1Header(&msg)) {
    getFragDgramTag(&msg, &recon->r_tag);
    getFragDgramSize(&msg, &recon->r_size);
  } else {
    recon->r_size = LIB6LOWPAN_MAX_LEN + LOWPAN_LINK_MTU;
  }
  recon->r_buf = malloc(recon->r_size);
  if (!recon->r_buf) return -2;
  memset(recon->r_buf, 0, recon->r_size);
  recon->r_app_len = NULL;

  if (*unpack_point == LOWPAN_IPV6_PATTERN) {
    /* uncompressed header... no need to un-hc */
    unpack_point++; len --;
    memcpy(recon->r_buf, unpack_point, len);
    unpack_end = recon->r_buf + len;
  } else {
    /* unpack the first fragment */
    unpack_end = lowpan_unpack_headers(recon, 
                                       frame_addr,
                                       unpack_point, len);
  }

  if (!unpack_end) {
    free(recon->r_buf);
    return -3;
  }

  if (!hasFrag1Header(&msg)) {
    recon->r_size = (unpack_end - recon->r_buf);
  }
  recon->r_bytes_rcvd = unpack_end - recon->r_buf;
  ((struct ip6_hdr *)(recon->r_buf))->ip6_plen = 
    htons(recon->r_size - sizeof(struct ip6_hdr));
  /* fill in any elided app data length fields */
  if (recon->r_app_len) {
    *recon->r_app_len = 
      htons(recon->r_size - (recon->r_transport_header - recon->r_buf));
  }
  
  /* done, updated all the fields */
  /* reconstruction is complete if r_bytes_rcvd == r_size */
  return 0;
}
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;
}