// File: /workspace/github_c_makefile_star2_O0/FH0[P]tun_direct/lwip-2.1.2/src/core/ipv4/ip4_frag.c
// Function: ip_reass_chain_frag_into_datagram_and_validate
static int
ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct pbuf *new_p, int is_last)
{
  struct ip_reass_helper *iprh, *iprh_tmp, *iprh_prev = NULL;
  struct pbuf *q;
  u16_t offset, len;
  u8_t hlen;
  struct ip_hdr *fraghdr;
  int valid = 1;

  /* Extract length and fragment offset from current fragment */
  fraghdr = (struct ip_hdr *)new_p->payload;
  len = lwip_ntohs(IPH_LEN(fraghdr));
  hlen = IPH_HL_BYTES(fraghdr);
  if (hlen > len) {
    /* invalid datagram */
    return IP_REASS_VALIDATE_PBUF_DROPPED;
  }
  len = (u16_t)(len - hlen);
  offset = IPH_OFFSET_BYTES(fraghdr);

  /* overwrite the fragment's ip header from the pbuf with our helper struct,
   * and setup the embedded helper structure. */
  /* make sure the struct ip_reass_helper fits into the IP header */
  LWIP_ASSERT("sizeof(struct ip_reass_helper) <= IP_HLEN",
              sizeof(struct ip_reass_helper) <= IP_HLEN);
  iprh = (struct ip_reass_helper *)new_p->payload;
  iprh->next_pbuf = NULL;
  iprh->start = offset;
  iprh->end = (u16_t)(offset + len);
  if (iprh->end < offset) {
    /* u16_t overflow, cannot handle this */
    return IP_REASS_VALIDATE_PBUF_DROPPED;
  }

  /* Iterate through until we either get to the end of the list (append),
   * or we find one with a larger offset (insert). */
  for (q = ipr->p; q != NULL;) {
    iprh_tmp = (struct ip_reass_helper *)q->payload;
    if (iprh->start < iprh_tmp->start) {
      /* the new pbuf should be inserted before this */
      iprh->next_pbuf = q;
      if (iprh_prev != NULL) {
        /* not the fragment with the lowest offset */
#if IP_REASS_CHECK_OVERLAP
        if ((iprh->start < iprh_prev->end) || (iprh->end > iprh_tmp->start)) {
          /* fragment overlaps with previous or following, throw away */
          return IP_REASS_VALIDATE_PBUF_DROPPED;
        }
#endif /* IP_REASS_CHECK_OVERLAP */
        iprh_prev->next_pbuf = new_p;
        if (iprh_prev->end != iprh->start) {
          /* There is a fragment missing between the current
           * and the previous fragment */
          valid = 0;
        }
      } else {
#if IP_REASS_CHECK_OVERLAP
        if (iprh->end > iprh_tmp->start) {
          /* fragment overlaps with following, throw away */
          return IP_REASS_VALIDATE_PBUF_DROPPED;
        }
#endif /* IP_REASS_CHECK_OVERLAP */
        /* fragment with the lowest offset */
        ipr->p = new_p;
      }
      break;
    } else if (iprh->start == iprh_tmp->start) {
      /* received the same datagram twice: no need to keep the datagram */
      return IP_REASS_VALIDATE_PBUF_DROPPED;
#if IP_REASS_CHECK_OVERLAP
    } else if (iprh->start < iprh_tmp->end) {
      /* overlap: no need to keep the new datagram */
      return IP_REASS_VALIDATE_PBUF_DROPPED;
#endif /* IP_REASS_CHECK_OVERLAP */
    } else {
      /* Check if the fragments received so far have no holes. */
      if (iprh_prev != NULL) {
        if (iprh_prev->end != iprh_tmp->start) {
          /* There is a fragment missing between the current
           * and the previous fragment */
          valid = 0;
        }
      }
    }
    q = iprh_tmp->next_pbuf;
    iprh_prev = iprh_tmp;
  }

  /* If q is NULL, then we made it to the end of the list. Determine what to do now */
  if (q == NULL) {
    if (iprh_prev != NULL) {
      /* this is (for now), the fragment with the highest offset:
       * chain it to the last fragment */
#if IP_REASS_CHECK_OVERLAP
      LWIP_ASSERT("check fragments don't overlap", iprh_prev->end <= iprh->start);
#endif /* IP_REASS_CHECK_OVERLAP */
      iprh_prev->next_pbuf = new_p;
      if (iprh_prev->end != iprh->start) {
        valid = 0;
      }
    } else {
#if IP_REASS_CHECK_OVERLAP
      LWIP_ASSERT("no previous fragment, this must be the first fragment!",
                  ipr->p == NULL);
#endif /* IP_REASS_CHECK_OVERLAP */
      /* this is the first fragment we ever received for this ip datagram */
      ipr->p = new_p;
    }
  }

  /* At this point, the validation part begins: */
  /* If we already received the last fragment */
  if (is_last || ((ipr->flags & IP_REASS_FLAG_LASTFRAG) != 0)) {
    /* and had no holes so far */
    if (valid) {
      /* then check if the rest of the fragments is here */
      /* Check if the queue starts with the first datagram */
      if ((ipr->p == NULL) || (((struct ip_reass_helper *)ipr->p->payload)->start != 0)) {
        valid = 0;
      } else {
        /* and check that there are no holes after this datagram */
        iprh_prev = iprh;
        q = iprh->next_pbuf;
        while (q != NULL) {
          iprh = (struct ip_reass_helper *)q->payload;
          if (iprh_prev->end != iprh->start) {
            valid = 0;
            break;
          }
          iprh_prev = iprh;
          q = iprh->next_pbuf;
        }
        /* if still valid, all fragments are received
         * (because to the MF==0 already arrived */
        if (valid) {
          LWIP_ASSERT("sanity check", ipr->p != NULL);
          LWIP_ASSERT("sanity check",
                      ((struct ip_reass_helper *)ipr->p->payload) != iprh);
          LWIP_ASSERT("validate_datagram:next_pbuf!=NULL",
                      iprh->next_pbuf == NULL);
        }
      }
    }
    /* If valid is 0 here, there are some fragments missing in the middle
     * (since MF == 0 has already arrived). Such datagrams simply time out if
     * no more fragments are received... */
    return valid ? IP_REASS_VALIDATE_TELEGRAM_FINISHED : IP_REASS_VALIDATE_PBUF_QUEUED;
  }
  /* If we come here, not all fragments were received, yet! */
  return IP_REASS_VALIDATE_PBUF_QUEUED; /* not yet valid! */
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movl %edx, -0x1c(%rbp)
movq $0x0, -0x38(%rbp)
movl $0x1, -0x54(%rbp)
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rax
movzwl 0x2(%rax), %edi
callq 0x251c0
movw %ax, -0x44(%rbp)
movq -0x50(%rbp), %rax
movzbl (%rax), %eax
andl $0xf, %eax
shll $0x2, %eax
movb %al, -0x45(%rbp)
movzbl -0x45(%rbp), %eax
movzwl -0x44(%rbp), %ecx
cmpl %ecx, %eax
jle 0x1b237
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x1b67e
movzwl -0x44(%rbp), %eax
movzbl -0x45(%rbp), %ecx
subl %ecx, %eax
movw %ax, -0x44(%rbp)
movq -0x50(%rbp), %rax
movzwl 0x6(%rax), %edi
callq 0x251c0
movzwl %ax, %eax
andl $0x1fff, %eax           # imm = 0x1FFF
shll $0x3, %eax
movw %ax, -0x42(%rbp)
jmp 0x1b263
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rax
movq $0x0, (%rax)
movw -0x42(%rbp), %cx
movq -0x28(%rbp), %rax
movw %cx, 0x8(%rax)
movzwl -0x42(%rbp), %eax
movzwl -0x44(%rbp), %ecx
addl %ecx, %eax
movw %ax, %cx
movq -0x28(%rbp), %rax
movw %cx, 0xa(%rax)
movq -0x28(%rbp), %rax
movzwl 0xa(%rax), %eax
movzwl -0x42(%rbp), %ecx
cmpl %ecx, %eax
jge 0x1b2b7
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x1b67e
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x40(%rbp)
cmpq $0x0, -0x40(%rbp)
je 0x1b413
movq -0x40(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x28(%rbp), %rax
movzwl 0x8(%rax), %eax
movq -0x30(%rbp), %rcx
movzwl 0x8(%rcx), %ecx
cmpl %ecx, %eax
jge 0x1b391
movq -0x40(%rbp), %rcx
movq -0x28(%rbp), %rax
movq %rcx, (%rax)
cmpq $0x0, -0x38(%rbp)
je 0x1b360
movq -0x28(%rbp), %rax
movzwl 0x8(%rax), %eax
movq -0x38(%rbp), %rcx
movzwl 0xa(%rcx), %ecx
cmpl %ecx, %eax
jl 0x1b32c
movq -0x28(%rbp), %rax
movzwl 0xa(%rax), %eax
movq -0x30(%rbp), %rcx
movzwl 0x8(%rcx), %ecx
cmpl %ecx, %eax
jle 0x1b338
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x1b67e
movq -0x18(%rbp), %rcx
movq -0x38(%rbp), %rax
movq %rcx, (%rax)
movq -0x38(%rbp), %rax
movzwl 0xa(%rax), %eax
movq -0x28(%rbp), %rcx
movzwl 0x8(%rcx), %ecx
cmpl %ecx, %eax
je 0x1b35e
movl $0x0, -0x54(%rbp)
jmp 0x1b38c
movq -0x28(%rbp), %rax
movzwl 0xa(%rax), %eax
movq -0x30(%rbp), %rcx
movzwl 0x8(%rcx), %ecx
cmpl %ecx, %eax
jle 0x1b380
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x1b67e
movq -0x18(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x8(%rax)
jmp 0x1b413
movq -0x28(%rbp), %rax
movzwl 0x8(%rax), %eax
movq -0x30(%rbp), %rcx
movzwl 0x8(%rcx), %ecx
cmpl %ecx, %eax
jne 0x1b3b1
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x1b67e
movq -0x28(%rbp), %rax
movzwl 0x8(%rax), %eax
movq -0x30(%rbp), %rcx
movzwl 0xa(%rcx), %ecx
cmpl %ecx, %eax
jge 0x1b3d1
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x1b67e
cmpq $0x0, -0x38(%rbp)
je 0x1b3f5
movq -0x38(%rbp), %rax
movzwl 0xa(%rax), %eax
movq -0x30(%rbp), %rcx
movzwl 0x8(%rcx), %ecx
cmpl %ecx, %eax
je 0x1b3f3
movl $0x0, -0x54(%rbp)
jmp 0x1b3f5
jmp 0x1b3f7
jmp 0x1b3f9
jmp 0x1b3fb
movq -0x30(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x40(%rbp)
movq -0x30(%rbp), %rax
movq %rax, -0x38(%rbp)
jmp 0x1b2c3
cmpq $0x0, -0x40(%rbp)
jne 0x1b4e4
cmpq $0x0, -0x38(%rbp)
je 0x1b496
jmp 0x1b427
movq -0x38(%rbp), %rax
movzwl 0xa(%rax), %eax
movq -0x28(%rbp), %rcx
movzwl 0x8(%rcx), %ecx
cmpl %ecx, %eax
jle 0x1b46c
jmp 0x1b43d
leaq 0xbe88(%rip), %rdi      # 0x272cc
leaq 0xe471(%rip), %rsi      # 0x298bc
movl $0x1b6, %edx            # imm = 0x1B6
leaq 0xe36e(%rip), %rcx      # 0x297c5
movb $0x0, %al
callq 0x20d0
xorl %eax, %eax
movl %eax, %edi
callq 0x21b0
callq 0x2040
jmp 0x1b46e
movq -0x18(%rbp), %rcx
movq -0x38(%rbp), %rax
movq %rcx, (%rax)
movq -0x38(%rbp), %rax
movzwl 0xa(%rax), %eax
movq -0x28(%rbp), %rcx
movzwl 0x8(%rcx), %ecx
cmpl %ecx, %eax
je 0x1b494
movl $0x0, -0x54(%rbp)
jmp 0x1b4e2
jmp 0x1b498
movq -0x10(%rbp), %rax
cmpq $0x0, 0x8(%rax)
je 0x1b4d4
jmp 0x1b4a5
leaq 0xbe20(%rip), %rdi      # 0x272cc
leaq 0xe427(%rip), %rsi      # 0x298da
movl $0x1bf, %edx            # imm = 0x1BF
leaq 0xe306(%rip), %rcx      # 0x297c5
movb $0x0, %al
callq 0x20d0
xorl %eax, %eax
movl %eax, %edi
callq 0x21b0
callq 0x2040
jmp 0x1b4d6
movq -0x18(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x8(%rax)
jmp 0x1b4e4
cmpl $0x0, -0x1c(%rbp)
jne 0x1b4fe
movq -0x10(%rbp), %rax
movzbl 0x26(%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x1b677
cmpl $0x0, -0x54(%rbp)
je 0x1b662
movq -0x10(%rbp), %rax
cmpq $0x0, 0x8(%rax)
je 0x1b528
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq 0x8(%rax), %rax
movzwl 0x8(%rax), %eax
cmpl $0x0, %eax
je 0x1b534
movl $0x0, -0x54(%rbp)
jmp 0x1b660
movq -0x28(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x28(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x40(%rbp)
cmpq $0x0, -0x40(%rbp)
je 0x1b58c
movq -0x40(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x38(%rbp), %rax
movzwl 0xa(%rax), %eax
movq -0x28(%rbp), %rcx
movzwl 0x8(%rcx), %ecx
cmpl %ecx, %eax
je 0x1b577
movl $0x0, -0x54(%rbp)
jmp 0x1b58c
movq -0x28(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x28(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x40(%rbp)
jmp 0x1b547
cmpl $0x0, -0x54(%rbp)
je 0x1b65e
jmp 0x1b598
movq -0x10(%rbp), %rax
cmpq $0x0, 0x8(%rax)
jne 0x1b5d4
jmp 0x1b5a5
leaq 0xbd20(%rip), %rdi      # 0x272cc
leaq 0xe35e(%rip), %rsi      # 0x29911
movl $0x1df, %edx            # imm = 0x1DF
leaq 0xe206(%rip), %rcx      # 0x297c5
movb $0x0, %al
callq 0x20d0
xorl %eax, %eax
movl %eax, %edi
callq 0x21b0
callq 0x2040
jmp 0x1b5d6
jmp 0x1b5d8
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq 0x8(%rax), %rax
cmpq -0x28(%rbp), %rax
jne 0x1b61b
jmp 0x1b5ec
leaq 0xbcd9(%rip), %rdi      # 0x272cc
leaq 0xe317(%rip), %rsi      # 0x29911
movl $0x1e1, %edx            # imm = 0x1E1
leaq 0xe1bf(%rip), %rcx      # 0x297c5
movb $0x0, %al
callq 0x20d0
xorl %eax, %eax
movl %eax, %edi
callq 0x21b0
callq 0x2040
jmp 0x1b61d
jmp 0x1b61f
movq -0x28(%rbp), %rax
cmpq $0x0, (%rax)
je 0x1b65a
jmp 0x1b62b
leaq 0xbc9a(%rip), %rdi      # 0x272cc
leaq 0xe2e5(%rip), %rsi      # 0x2991e
movl $0x1e3, %edx            # imm = 0x1E3
leaq 0xe180(%rip), %rcx      # 0x297c5
movb $0x0, %al
callq 0x20d0
xorl %eax, %eax
movl %eax, %edi
callq 0x21b0
callq 0x2040
jmp 0x1b65c
jmp 0x1b65e
jmp 0x1b660
jmp 0x1b662
movl -0x54(%rbp), %edx
xorl %eax, %eax
movl $0x1, %ecx
cmpl $0x0, %edx
cmovnel %ecx, %eax
movl %eax, -0x4(%rbp)
jmp 0x1b67e
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x60, %rsp
popq %rbp
retq
nopw (%rax,%rax)