// File: /workspace/github_c_makefile_star2_O3/FH0[P]tun_direct/lwip-2.1.2/src/core/ipv6/nd6.c
// Function: nd6_process_autoconfig_prefix
static void
nd6_process_autoconfig_prefix(struct netif *netif,
  struct prefix_option *prefix_opt, const ip6_addr_t *prefix_addr)
{
  ip6_addr_t ip6addr;
  u32_t valid_life, pref_life;
  u8_t addr_state;
  s8_t i, free_idx;

  /* The caller already checks RFC 4862 Sec. 5.5.3 points (a) and (b). We do
   * the rest, starting with checks for (c) and (d) here. */
  valid_life = lwip_htonl(prefix_opt->valid_lifetime);
  pref_life = lwip_htonl(prefix_opt->preferred_lifetime);
  if (pref_life > valid_life || prefix_opt->prefix_length != 64) {
    return; /* silently ignore this prefix for autoconfiguration purposes */
  }

  /* If an autogenerated address already exists for this prefix, update its
   * lifetimes. An address is considered autogenerated if 1) it is not static
   * (i.e., manually assigned), and 2) there is an advertised autoconfiguration
   * prefix for it (the one we are processing here). This does not necessarily
   * exclude the possibility that the address was actually assigned by, say,
   * DHCPv6. If that distinction becomes important in the future, more state
   * must be kept. As explained elsewhere we also update lifetimes of tentative
   * and duplicate addresses. Skip address slot 0 (the link-local address). */
  for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
    addr_state = netif_ip6_addr_state(netif, i);
    if (!ip6_addr_isinvalid(addr_state) && !netif_ip6_addr_isstatic(netif, i) &&
        ip6_addr_netcmp(prefix_addr, netif_ip6_addr(netif, i))) {
      /* Update the valid lifetime, as per RFC 4862 Sec. 5.5.3 point (e).
       * The valid lifetime will never drop to zero as a result of this. */
      u32_t remaining_life = netif_ip6_addr_valid_life(netif, i);
      if (valid_life > ND6_2HRS || valid_life > remaining_life) {
        netif_ip6_addr_set_valid_life(netif, i, valid_life);
      } else if (remaining_life > ND6_2HRS) {
        netif_ip6_addr_set_valid_life(netif, i, ND6_2HRS);
      }
      LWIP_ASSERT("bad valid lifetime", !netif_ip6_addr_isstatic(netif, i));
      /* Update the preferred lifetime. No bounds checks are needed here. In
       * rare cases the advertisement may un-deprecate the address, though.
       * Deprecation is left to the timer code where it is handled anyway. */
      if (pref_life > 0 && addr_state == IP6_ADDR_DEPRECATED) {
        netif_ip6_addr_set_state(netif, i, IP6_ADDR_PREFERRED);
      }
      netif_ip6_addr_set_pref_life(netif, i, pref_life);
      return; /* there should be at most one matching address */
    }
  }

  /* No autogenerated address exists for this prefix yet. See if we can add a
   * new one. However, if IPv6 autoconfiguration is administratively disabled,
   * do not generate new addresses, but do keep updating lifetimes for existing
   * addresses. Also, when adding new addresses, we must protect explicitly
   * against a valid lifetime of zero, because again, we use that as a special
   * value. The generated address would otherwise expire immediately anyway.
   * Finally, the original link-local address must be usable at all. We start
   * creating addresses even if the link-local address is still in tentative
   * state though, and deal with the fallout of that upon DAD collision. */
  addr_state = netif_ip6_addr_state(netif, 0);
  if (!netif->ip6_autoconfig_enabled || valid_life == IP6_ADDR_LIFE_STATIC ||
      ip6_addr_isinvalid(addr_state) || ip6_addr_isduplicated(addr_state)) {
    return;
  }

  /* Construct the new address that we intend to use, and then see if that
   * address really does not exist. It might have been added manually, after
   * all. As a side effect, find a free slot. Note that we cannot use
   * netif_add_ip6_address() here, as it would return ERR_OK if the address
   * already did exist, resulting in that address being given lifetimes. */
  IP6_ADDR(&ip6addr, prefix_addr->addr[0], prefix_addr->addr[1],
    netif_ip6_addr(netif, 0)->addr[2], netif_ip6_addr(netif, 0)->addr[3]);
  ip6_addr_assign_zone(&ip6addr, IP6_UNICAST, netif);

  free_idx = 0;
  for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
    if (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, i))) {
      if (ip6_addr_cmp(&ip6addr, netif_ip6_addr(netif, i))) {
        return; /* formed address already exists */
      }
    } else if (free_idx == 0) {
      free_idx = i;
    }
  }
  if (free_idx == 0) {
    return; /* no address slots available, try again on next advertisement */
  }

  /* Assign the new address to the interface. */
  ip_addr_copy_from_ip6(netif->ip6_addr[free_idx], ip6addr);
  netif_ip6_addr_set_valid_life(netif, free_idx, valid_life);
  netif_ip6_addr_set_pref_life(netif, free_idx, pref_life);
  netif_ip6_addr_set_state(netif, free_idx, IP6_ADDR_TENTATIVE);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
movq %rdx, %r15
movq %rsi, %r12
movq %rdi, %rbx
movl 0x4(%rsi), %edi
callq 0x135bb
movl %eax, %r14d
movl 0x8(%r12), %edi
callq 0x135bb
cmpl %r14d, %eax
ja 0x1268c
cmpb $0x40, 0x2(%r12)
jne 0x1268c
movl %eax, %ebp
leaq 0x50(%rbx), %rax
movl $0x99, %r12d
movl $0x1a, %edx
movb (%rbx,%r12), %cl
testb %cl, %cl
je 0x12523
movl -0x1c4(%rbx,%r12,4), %esi
testl %esi, %esi
je 0x12523
movl (%r15), %edi
cmpl (%rbx,%rdx,4), %edi
jne 0x12523
movl 0x4(%r15), %edi
cmpl 0x4(%rbx,%rdx,4), %edi
jne 0x12523
movb 0x10(%r15), %dil
cmpb 0x10(%rbx,%rdx,4), %dil
je 0x12639
incq %r12
addq $0x6, %rdx
cmpq $0x26, %rdx
jne 0x124ee
cmpb $0x0, 0xef(%rbx)
je 0x1268c
testl %r14d, %r14d
je 0x1268c
movb 0x98(%rbx), %cl
andb $-0x41, %cl
je 0x1268c
movq (%r15), %rcx
movq %rcx, %xmm0
movq 0x58(%rbx), %xmm1
movl %ecx, %edx
andl $0xc0ff, %edx           # imm = 0xC0FF
cmpl $0x80fe, %edx           # imm = 0x80FE
jne 0x1257c
movb 0xee(%rbx), %dl
incb %dl
jmp 0x1257e
xorl %edx, %edx
movd %xmm1, %edi
pshufd $0x55, %xmm1, %xmm2     # xmm2 = xmm1[1,1,1,1]
movd %xmm2, %r8d
pshufd $0x55, %xmm0, %xmm2     # xmm2 = xmm0[1,1,1,1]
movd %xmm2, %r9d
leaq 0x78(%rbx), %r10
movl $0x99, %r11d
xorl %esi, %esi
cmpb $0x0, (%rbx,%r11)
je 0x125cb
cmpl -0x10(%r10), %ecx
jne 0x125de
cmpl -0xc(%r10), %r9d
jne 0x125de
cmpl -0x8(%r10), %edi
jne 0x125de
cmpl -0x4(%r10), %r8d
jne 0x125de
cmpb (%r10), %dl
jne 0x125de
jmp 0x1268c
leal 0x68(%r11), %r15d
testb %sil, %sil
movzbl %sil, %r12d
movzbl %r15b, %esi
cmovnel %r12d, %esi
incq %r11
addq $0x18, %r10
cmpq $0x9b, %r11
jne 0x125a2
testb %sil, %sil
je 0x1268c
movsbq %sil, %rcx
leaq (%rcx,%rcx,2), %rdi
punpcklqdq %xmm1, %xmm0    # xmm0 = xmm0[0],xmm1[0]
movdqu %xmm0, (%rax,%rdi,8)
movb %dl, 0x10(%rax,%rdi,8)
movb $0x6, 0x14(%rax,%rdi,8)
movl %r14d, 0x9c(%rbx,%rcx,4)
movl %ebp, 0xa8(%rbx,%rcx,4)
movsbl %sil, %esi
movq %rbx, %rdi
movl $0x8, %edx
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0x490e
cmpl $0x1c20, %r14d          # imm = 0x1C20
ja 0x12655
cmpl %esi, %r14d
ja 0x12655
movl $0x1c20, %r14d          # imm = 0x1C20
cmpl $0x1c21, %esi           # imm = 0x1C21
jb 0x1265d
movl %r14d, -0x1c4(%rbx,%r12,4)
testl %ebp, %ebp
sete %al
cmpb $0x10, %cl
setne %cl
orb %al, %cl
jne 0x12684
leaq -0x98(%r12), %rax
movsbl %al, %esi
movq %rbx, %rdi
movl $0x30, %edx
callq 0x490e
movl %ebp, -0x1b8(%rbx,%r12,4)
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq