// File: /workspace/github_c_makefile_star2_O3/FH0[P]tun_direct/lwip-2.1.2/src/core/ipv4/icmp.c
// Function: icmp_send_response
static void
icmp_send_response(struct pbuf *p, u8_t type, u8_t code)
{
  struct pbuf *q;
  struct ip_hdr *iphdr;
  /* we can use the echo header here */
  struct icmp_echo_hdr *icmphdr;
  ip4_addr_t iphdr_src;
  struct netif *netif;

  /* increase number of messages attempted to send */
  MIB2_STATS_INC(mib2.icmpoutmsgs);

  /* ICMP header + IP header + 8 bytes of data */
  q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE,
                 PBUF_RAM);
  if (q == NULL) {
    LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n"));
    MIB2_STATS_INC(mib2.icmpouterrors);
    return;
  }
  LWIP_ASSERT("check that first pbuf can hold icmp message",
              (q->len >= (sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE)));

  iphdr = (struct ip_hdr *)p->payload;
  LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));
  ip4_addr_debug_print_val(ICMP_DEBUG, iphdr->src);
  LWIP_DEBUGF(ICMP_DEBUG, (" to "));
  ip4_addr_debug_print_val(ICMP_DEBUG, iphdr->dest);
  LWIP_DEBUGF(ICMP_DEBUG, ("\n"));

  icmphdr = (struct icmp_echo_hdr *)q->payload;
  icmphdr->type = type;
  icmphdr->code = code;
  icmphdr->id = 0;
  icmphdr->seqno = 0;

  /* copy fields from original packet */
  SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_echo_hdr), (u8_t *)p->payload,
          IP_HLEN + ICMP_DEST_UNREACH_DATASIZE);

  ip4_addr_copy(iphdr_src, iphdr->src);
#ifdef LWIP_HOOK_IP4_ROUTE_SRC
  {
    ip4_addr_t iphdr_dst;
    ip4_addr_copy(iphdr_dst, iphdr->dest);
    netif = ip4_route_src(&iphdr_dst, &iphdr_src);
  }
#else
  netif = ip4_route(&iphdr_src);
#endif
  if (netif != NULL) {
    /* calculate checksum */
    icmphdr->chksum = 0;
#if CHECKSUM_GEN_ICMP
    IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP) {
      icmphdr->chksum = inet_chksum(icmphdr, q->len);
    }
#endif
    ICMP_STATS_INC(icmp.xmit);
    ip4_output_if(q, NULL, &iphdr_src, ICMP_TTL, 0, IP_PROTO_ICMP, netif);
  }
  pbuf_free(q);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
subq $0x18, %rsp
movl %edx, %ebp
movl %esi, %r15d
movq %rdi, %r14
movl $0x36, %edi
movl $0x24, %esi
movl $0x280, %edx            # imm = 0x280
callq 0x4df7
testq %rax, %rax
je 0xe0d8
movq %rax, %rbx
cmpw $0x23, 0x12(%rax)
jbe 0xe0e3
movq 0x8(%r14), %rax
movq 0x8(%rbx), %r14
movb %r15b, (%r14)
movb %bpl, 0x1(%r14)
movl $0x0, 0x4(%r14)
movups (%rax), %xmm0
movups 0xc(%rax), %xmm1
movups %xmm0, 0x8(%r14)
movups %xmm1, 0x14(%r14)
movl 0xc(%rax), %eax
leaq 0x14(%rsp), %rdi
movl %eax, (%rdi)
callq 0xe120
testq %rax, %rax
je 0xe0d0
movq %rax, %r15
movw $0x0, 0x2(%r14)
movzwl 0x12(%rbx), %esi
movq %r14, %rdi
callq 0x13be5
movw %ax, 0x2(%r14)
movq %r15, (%rsp)
leaq 0x14(%rsp), %rdx
movq %rbx, %rdi
xorl %esi, %esi
movl $0x40, %ecx
xorl %r8d, %r8d
movl $0x1, %r9d
callq 0xe33b
movq %rbx, %rdi
callq 0x4fdf
addq $0x18, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
leaq 0x61e2(%rip), %rdi      # 0x142cc
leaq 0x81d9(%rip), %rsi      # 0x162ca
leaq 0x8180(%rip), %rcx      # 0x16278
movl $0x169, %edx            # imm = 0x169
xorl %eax, %eax
callq 0x20d0
xorl %edi, %edi
callq 0x21b0
callq 0x2050