// File: /workspace/github_c_makefile_star2_O1/FH0[P]tun_direct/lwip-2.1.2/src/core/udp.c
// Function: udp_bind
err_t
udp_bind(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port)
{
  struct udp_pcb *ipcb;
  u8_t rebind;
#if LWIP_IPV6 && LWIP_IPV6_SCOPES
  ip_addr_t zoned_ipaddr;
#endif /* LWIP_IPV6 && LWIP_IPV6_SCOPES */

  LWIP_ASSERT_CORE_LOCKED();

#if LWIP_IPV4
  /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */
  if (ipaddr == NULL) {
    ipaddr = IP4_ADDR_ANY;
  }
#else /* LWIP_IPV4 */
  LWIP_ERROR("udp_bind: invalid ipaddr", ipaddr != NULL, return ERR_ARG);
#endif /* LWIP_IPV4 */

  LWIP_ERROR("udp_bind: invalid pcb", pcb != NULL, return ERR_ARG);

  LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_bind(ipaddr = "));
  ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE, ipaddr);
  LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, (", port = %"U16_F")\n", port));

  rebind = 0;
  /* Check for double bind and rebind of the same pcb */
  for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
    /* is this UDP PCB already on active list? */
    if (pcb == ipcb) {
      rebind = 1;
      break;
    }
  }

#if LWIP_IPV6 && LWIP_IPV6_SCOPES
  /* If the given IP address should have a zone but doesn't, assign one now.
   * This is legacy support: scope-aware callers should always provide properly
   * zoned source addresses. Do the zone selection before the address-in-use
   * check below; as such we have to make a temporary copy of the address. */
  if (IP_IS_V6(ipaddr) && ip6_addr_lacks_zone(ip_2_ip6(ipaddr), IP6_UNKNOWN)) {
    ip_addr_copy(zoned_ipaddr, *ipaddr);
    ip6_addr_select_zone(ip_2_ip6(&zoned_ipaddr), ip_2_ip6(&zoned_ipaddr));
    ipaddr = &zoned_ipaddr;
  }
#endif /* LWIP_IPV6 && LWIP_IPV6_SCOPES */

  /* no port specified? */
  if (port == 0) {
    port = udp_new_port();
    if (port == 0) {
      /* no more ports available in local range */
      LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: out of free UDP ports\n"));
      return ERR_USE;
    }
  } else {
    for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
      if (pcb != ipcb) {
        /* By default, we don't allow to bind to a port that any other udp
           PCB is already bound to, unless *all* PCBs with that port have tha
           REUSEADDR flag set. */
#if SO_REUSE
        if (!ip_get_option(pcb, SOF_REUSEADDR) ||
            !ip_get_option(ipcb, SOF_REUSEADDR))
#endif /* SO_REUSE */
        {
          /* port matches that of PCB in list and REUSEADDR not set -> reject */
          if ((ipcb->local_port == port) &&
              /* IP address matches or any IP used? */
              (ip_addr_cmp(&ipcb->local_ip, ipaddr) || ip_addr_isany(ipaddr) ||
              ip_addr_isany(&ipcb->local_ip))) {
            /* other PCB already binds to this local IP and port */
            LWIP_DEBUGF(UDP_DEBUG,
                        ("udp_bind: local port %"U16_F" already bound by another pcb\n", port));
            return ERR_USE;
          }
        }
      }
    }
  }

  ip_addr_set_ipaddr(&pcb->local_ip, ipaddr);

  pcb->local_port = port;
  mib2_udp_bind(pcb);
  /* pcb not active yet? */
  if (rebind == 0) {
    /* place the PCB on the active list if not already there */
    pcb->next = udp_pcbs;
    udp_pcbs = pcb;
  }
  LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("udp_bind: bound to "));
  ip_addr_debug_print_val(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, pcb->local_ip);
  LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, (", port %"U16_F")\n", pcb->local_port));
  return ERR_OK;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
subq $0x18, %rsp
movl %edx, %ebp
movq %rdi, %rbx
testq %rsi, %rsi
jne 0xd978
leaq 0x9a20(%rip), %rsi      # 0x17398
testq %rbx, %rbx
je 0xdbdd
leaq 0x10018(%rip), %rax     # 0x1d9a0
movq (%rax), %r15
testq %r15, %r15
je 0xd999
leaq 0x38(%r15), %rax
cmpq %rbx, %r15
jne 0xd988
movb 0x14(%rsi), %cl
cmpb $0x6, %cl
jne 0xd9ac
movb 0x10(%rsi), %al
testb %al, %al
je 0xdb3a
movq %rsi, %r14
movq 0xffea(%rip), %rax      # 0x1d9a0
testw %bp, %bp
je 0xda87
testq %rax, %rax
je 0xdad3
cmpq %rbx, %rax
je 0xda7e
cmpw %bp, 0x42(%rax)
jne 0xda7e
movb 0x14(%rax), %cl
movb 0x14(%r14), %dl
cmpb %dl, %cl
jne 0xda26
movl (%rax), %esi
movl (%r14), %edi
cmpb $0x6, %cl
jne 0xda1e
cmpl %edi, %esi
jne 0xda26
movl 0x4(%rax), %esi
cmpl 0x4(%r14), %esi
jne 0xda26
movl 0x8(%rax), %esi
cmpl 0x8(%r14), %esi
jne 0xda26
movl 0xc(%rax), %esi
cmpl 0xc(%r14), %esi
jne 0xda26
movb 0x10(%rax), %sil
cmpb 0x10(%r14), %sil
jne 0xda26
jmp 0xdb2d
cmpl %edi, %esi
je 0xdb2d
movl (%r14), %esi
cmpb $0x6, %dl
jne 0xda4c
testl %esi, %esi
jne 0xda54
cmpl $0x0, 0x4(%r14)
jne 0xda54
cmpl $0x0, 0x8(%r14)
jne 0xda54
cmpl $0x0, 0xc(%r14)
jne 0xda54
jmp 0xdb2d
testl %esi, %esi
je 0xdb2d
movl (%rax), %edx
cmpb $0x6, %cl
jne 0xda76
testl %edx, %edx
jne 0xda7e
cmpl $0x0, 0x4(%rax)
jne 0xda7e
cmpl $0x0, 0x8(%rax)
jne 0xda7e
cmpl $0x0, 0xc(%rax)
jne 0xda7e
jmp 0xdb2d
testl %edx, %edx
je 0xdb2d
movq 0x38(%rax), %rax
jmp 0xd9bf
movzwl 0xf6c2(%rip), %ecx      # 0x1d150
xorl %edx, %edx
movl $0xc000, %esi           # imm = 0xC000
incw %cx
cmovel %esi, %ecx
movq %rax, %rdi
testq %rax, %rax
je 0xdac5
cmpw %cx, 0x42(%rdi)
je 0xdab4
movq 0x38(%rdi), %rdi
testq %rdi, %rdi
jne 0xdaa3
jmp 0xdac5
incl %edx
movzwl %dx, %edi
cmpl $0x4000, %edi           # imm = 0x4000
jne 0xda95
xorl %ebp, %ebp
jmp 0xdac7
movl %ecx, %ebp
movw %cx, 0xf682(%rip)       # 0x1d150
testw %bp, %bp
je 0xdb2d
movb 0x14(%r14), %al
movb %al, 0x14(%rbx)
cmpb $0x6, 0x14(%r14)
movl (%r14), %eax
movl %eax, (%rbx)
jne 0xdb04
movl 0x4(%r14), %eax
movl %eax, 0x4(%rbx)
movl 0x8(%r14), %eax
movl %eax, 0x8(%rbx)
movl 0xc(%r14), %eax
movl %eax, 0xc(%rbx)
movb 0x10(%r14), %al
movb %al, 0x10(%rbx)
jmp 0xdb0e
xorl %eax, %eax
movq %rax, 0x9(%rbx)
movq %rax, 0x4(%rbx)
movw %bp, 0x42(%rbx)
testq %r15, %r15
jne 0xdb29
movq 0xfe82(%rip), %rax      # 0x1d9a0
movq %rax, 0x38(%rbx)
movq %rbx, 0xfe77(%rip)      # 0x1d9a0
xorl %eax, %eax
jmp 0xdb2f
movb $-0x8, %al
addq $0x18, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
movl (%rsi), %edx
movl %edx, %edi
andl $0xc0ff, %edi           # imm = 0xC0FF
cmpl $0x80fe, %edi           # imm = 0x80FE
je 0xdb68
movl %edx, %edi
andl $0x8fff, %edi           # imm = 0x8FFF
cmpl $0x2ff, %edi            # imm = 0x2FF
je 0xdb68
cmpl $0x1ff, %edi            # imm = 0x1FF
jne 0xd9ac
movq %rsp, %r14
movb %cl, 0x14(%r14)
movl %edx, (%r14)
movl 0x4(%rsi), %ecx
movl %ecx, 0x4(%r14)
movl 0x8(%rsi), %ecx
movl %ecx, 0x8(%r14)
movl 0xc(%rsi), %ecx
movl %ecx, 0xc(%r14)
movb %al, 0x10(%r14)
movq %r14, %rdi
movq %r14, %rsi
callq 0xfae4
testq %rax, %rax
je 0xd9af
movl (%rsp), %ecx
movl %ecx, %edx
andl $0xc0ff, %edx           # imm = 0xC0FF
cmpl $0x80fe, %edx           # imm = 0x80FE
je 0xdbc8
andl $0x8fff, %ecx           # imm = 0x8FFF
cmpl $0x2ff, %ecx            # imm = 0x2FF
je 0xdbc8
cmpl $0x1ff, %ecx            # imm = 0x1FF
jne 0xdbd9
movb 0xee(%rax), %al
incb %al
movb %al, 0x10(%rsp)
jmp 0xd9af
xorl %eax, %eax
jmp 0xdbd0
leaq 0x76e8(%rip), %rdi      # 0x152cc
leaq 0x95fb(%rip), %rsi      # 0x171e6
leaq 0x93ae(%rip), %rcx      # 0x16fa0
movl $0x425, %edx            # imm = 0x425
xorl %eax, %eax
callq 0x20d0
xorl %edi, %edi
callq 0x21b0
callq 0x2050