/*
 * Copyright 2011 Daniel Drown
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * ipv4.c - takes ipv4 packets, finds their headers, and then calls translation functions on them
 */
#include <string.h>

#include "netutils/checksum.h"

#include "debug.h"
#include "dump.h"
#include "logging.h"
#include "translate.h"

/* function: icmp_packet
 * translates an icmp packet
 * out      - output packet
 * icmp     - pointer to icmp header in packet
 * checksum - pseudo-header checksum
 * len      - size of ip payload
 * returns: the highest position in the output clat_packet that's filled in
 */
int icmp_packet(clat_packet out, clat_packet_index pos, const struct icmphdr *icmp,
                uint32_t checksum, size_t len) {
  const uint8_t *payload;
  size_t payload_size;

  if (len < sizeof(struct icmphdr)) {
    logmsg_dbg(ANDROID_LOG_ERROR, "icmp_packet/(too small)");
    return 0;
  }

  payload      = (const uint8_t *)(icmp + 1);
  payload_size = len - sizeof(struct icmphdr);

  return icmp_to_icmp6(out, pos, icmp, checksum, payload, payload_size);
}

/* function: ipv4_packet
 * translates an ipv4 packet
 * out    - output packet
 * packet - packet data
 * len    - size of packet
 * returns: the highest position in the output clat_packet that's filled in
 */
int ipv4_packet(clat_packet out, clat_packet_index pos, const uint8_t *packet, size_t len) {
  const struct iphdr *header = (struct iphdr *)packet;
  struct ip6_hdr *ip6_targ   = (struct ip6_hdr *)out[pos].iov_base;
  struct ip6_frag *frag_hdr;
  size_t frag_hdr_len;
  uint8_t nxthdr;
  const uint8_t *next_header;
  size_t len_left;
  uint32_t old_sum, new_sum;
  int iov_len;

  if (len < sizeof(struct iphdr)) {
    logmsg_dbg(ANDROID_LOG_ERROR, "ip_packet/too short for an ip header");
    return 0;
  }

  if (header->ihl < 5) {
    logmsg_dbg(ANDROID_LOG_ERROR, "ip_packet/ip header length set to less than 5: %x", header->ihl);
    return 0;
  }

  if ((size_t)header->ihl * 4 > len) {  // ip header length larger than entire packet
    logmsg_dbg(ANDROID_LOG_ERROR, "ip_packet/ip header length set too large: %x", header->ihl);
    return 0;
  }

  if (header->version != 4) {
    logmsg_dbg(ANDROID_LOG_ERROR, "ip_packet/ip header version not 4: %x", header->version);
    return 0;
  }

  /* rfc6145 - If any IPv4 options are present in the IPv4 packet, they MUST be
   * ignored and the packet translated normally; there is no attempt to
   * translate the options.
   */

  next_header = packet + header->ihl * 4;
  len_left    = len - header->ihl * 4;

  nxthdr = header->protocol;
  if (nxthdr == IPPROTO_ICMP) {
    // ICMP and ICMPv6 have different protocol numbers.
    nxthdr = IPPROTO_ICMPV6;
  }

  /* Fill in the IPv6 header. We need to do this before we translate the packet because TCP and
   * UDP include parts of the IP header in the checksum. Set the length to zero because we don't
   * know it yet.
   */
  fill_ip6_header(ip6_targ, 0, nxthdr, header);
  out[pos].iov_len = sizeof(struct ip6_hdr);

  /* Calculate the pseudo-header checksum.
   * Technically, the length that is used in the pseudo-header checksum is the transport layer
   * length, which is not the same as len_left in the case of fragmented packets. But since
   * translation does not change the transport layer length, the checksum is unaffected.
   */
  old_sum = ipv4_pseudo_header_checksum(header, len_left);
  new_sum = ipv6_pseudo_header_checksum(ip6_targ, len_left, nxthdr);

  // If the IPv4 packet is fragmented, add a Fragment header.
  frag_hdr             = (struct ip6_frag *)out[pos + 1].iov_base;
  frag_hdr_len         = maybe_fill_frag_header(frag_hdr, ip6_targ, header);
  out[pos + 1].iov_len = frag_hdr_len;

  if (frag_hdr_len && frag_hdr->ip6f_offlg & IP6F_OFF_MASK) {
    // Non-first fragment. Copy the rest of the packet as is.
    iov_len = generic_packet(out, pos + 2, next_header, len_left);
  } else if (nxthdr == IPPROTO_ICMPV6) {
    iov_len = icmp_packet(out, pos + 2, (const struct icmphdr *)next_header, new_sum, len_left);
  } else if (nxthdr == IPPROTO_TCP) {
    iov_len =
      tcp_packet(out, pos + 2, (const struct tcphdr *)next_header, old_sum, new_sum, len_left);
  } else if (nxthdr == IPPROTO_UDP) {
    iov_len =
      udp_packet(out, pos + 2, (const struct udphdr *)next_header, old_sum, new_sum, len_left);
  } else if (nxthdr == IPPROTO_GRE || nxthdr == IPPROTO_ESP) {
    iov_len = generic_packet(out, pos + 2, next_header, len_left);
  } else {
#if CLAT_DEBUG
    logmsg_dbg(ANDROID_LOG_ERROR, "ip_packet/unknown protocol: %x", header->protocol);
    logcat_hexdump("ipv4/protocol", packet, len);
#endif
    return 0;
  }

  // Set the length.
  ip6_targ->ip6_plen = htons(packet_length(out, pos));
  return iov_len;
}
