// File: /workspace/github_c_makefile_star2_O1/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 0x13c57
movl %eax, %r14d
movl 0x8(%r12), %edi
callq 0x13c57
cmpl %r14d, %eax
ja 0x12d06
cmpb $0x40, 0x2(%r12)
jne 0x12d06
movl %eax, %ebp
movl $0x99, %r12d
movl $0x1a, %ecx
testq %rbx, %rbx
sete %dl
movb (%rbx,%r12), %al
testb %al, %al
sete %sil
orb %dl, %sil
jne 0x12b90
movl -0x1c4(%rbx,%r12,4), %edx
testl %edx, %edx
je 0x12b90
movl (%r15), %esi
cmpl (%rbx,%rcx,4), %esi
jne 0x12b90
movl 0x4(%r15), %esi
cmpl 0x4(%rbx,%rcx,4), %esi
jne 0x12b90
movb 0x10(%r15), %sil
cmpb 0x10(%rbx,%rcx,4), %sil
je 0x12ca9
incq %r12
addq $0x6, %rcx
cmpq $0x26, %rcx
jne 0x12b4e
cmpb $0x0, 0xef(%rbx)
je 0x12d06
testl %r14d, %r14d
je 0x12d06
movb 0x98(%rbx), %al
andb $-0x41, %al
je 0x12d06
movl (%r15), %eax
movl %eax, %ecx
andl $0xc0ff, %ecx           # imm = 0xC0FF
cmpl $0x80fe, %ecx           # imm = 0x80FE
jne 0x12bde
movb 0xee(%rbx), %cl
incb %cl
jmp 0x12be0
xorl %ecx, %ecx
movl 0x4(%r15), %edi
leaq 0x50(%rbx), %rsi
movl 0x58(%rbx), %r8d
movl 0x5c(%rbx), %r9d
movl $0x99, %r10d
movl $0x78, %r11d
xorl %edx, %edx
cmpb $0x0, (%rbx,%r10)
je 0x12c2c
cmpl -0x10(%rbx,%r11), %eax
jne 0x12c3e
cmpl -0xc(%rbx,%r11), %edi
jne 0x12c3e
cmpl -0x8(%rbx,%r11), %r8d
jne 0x12c3e
cmpl -0x4(%rbx,%r11), %r9d
jne 0x12c3e
cmpb (%rbx,%r11), %cl
jne 0x12c3e
jmp 0x12d06
leal 0x68(%r10), %r15d
testb %dl, %dl
movzbl %dl, %r12d
movzbl %r15b, %edx
cmovnel %r12d, %edx
incq %r10
addq $0x18, %r11
cmpq $0xa8, %r11
jne 0x12bfe
testb %dl, %dl
je 0x12d06
movsbq %dl, %r10
leaq (%r10,%r10,2), %r11
movl %eax, (%rsi,%r11,8)
movl %edi, 0x4(%rsi,%r11,8)
movl %r8d, 0x8(%rsi,%r11,8)
movl %r9d, 0xc(%rsi,%r11,8)
movb %cl, 0x10(%rsi,%r11,8)
movb $0x6, 0x14(%rsi,%r11,8)
testq %rbx, %rbx
je 0x12c91
movl %r14d, 0x9c(%rbx,%r10,4)
movl %ebp, 0xa8(%rbx,%r10,4)
movsbl %dl, %esi
movq %rbx, %rdi
movl $0x8, %edx
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0x4949
cmpl $0x1c20, %r14d          # imm = 0x1C20
ja 0x12cc5
cmpl %edx, %r14d
ja 0x12cc5
movl $0x1c20, %r14d          # imm = 0x1C20
cmpl $0x1c21, %edx           # imm = 0x1C21
jb 0x12ccd
movl %r14d, -0x1c4(%rbx,%r12,4)
cmpl $0x0, -0x1c4(%rbx,%r12,4)
je 0x12d0f
testl %ebp, %ebp
sete %cl
cmpb $0x10, %al
setne %al
orb %cl, %al
jne 0x12cfe
leaq -0x98(%r12), %rax
movsbl %al, %esi
movq %rbx, %rdi
movl $0x30, %edx
callq 0x4949
movl %ebp, -0x1b8(%rbx,%r12,4)
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
leaq 0x25b6(%rip), %rdi      # 0x152cc
leaq 0x4b23(%rip), %rsi      # 0x17840
leaq 0x4b2f(%rip), %rcx      # 0x17853
movl $0xde, %edx
xorl %eax, %eax
callq 0x20d0
xorl %edi, %edi
callq 0x21b0
callq 0x2050