Add generic IP packet code and use it for GRE.

Bug: 11542311
Change-Id: I174e0b268869bc77927feeee57003580c47c30f2
diff --git a/ipv4.c b/ipv4.c
index 47f2422..b5cbf80 100644
--- a/ipv4.c
+++ b/ipv4.c
@@ -123,12 +123,14 @@
   // Calculate the pseudo-header checksum.
   checksum = ipv6_pseudo_header_checksum(0, ip6_targ, len_left);
 
-  if(nxthdr == IPPROTO_ICMPV6) {
+  if (nxthdr == IPPROTO_ICMPV6) {
     iov_len = icmp_packet(out, pos + 1, (const struct icmphdr *) next_header, checksum, len_left);
-  } else if(nxthdr == IPPROTO_TCP) {
+  } else if (nxthdr == IPPROTO_TCP) {
     iov_len = tcp_packet(out, pos + 1, (const struct tcphdr *) next_header, checksum, len_left);
-  } else if(nxthdr == IPPROTO_UDP) {
+  } else if (nxthdr == IPPROTO_UDP) {
     iov_len = udp_packet(out, pos + 1, (const struct udphdr *) next_header, checksum, len_left);
+  } else if (nxthdr == IPPROTO_GRE) {
+    iov_len = generic_packet(out, pos + 1, next_header, len_left);
   } else {
 #if CLAT_DEBUG
     logmsg_dbg(ANDROID_LOG_ERROR, "ip_packet/unknown protocol: %x",header->protocol);
diff --git a/ipv6.c b/ipv6.c
index 9eaa6ab..04d9f9c 100644
--- a/ipv6.c
+++ b/ipv6.c
@@ -137,14 +137,16 @@
   checksum = ipv4_pseudo_header_checksum(0, ip_targ, len_left);
 
   // does not support IPv6 extension headers, this will drop any packet with them
-  if(protocol == IPPROTO_ICMP) {
+  if (protocol == IPPROTO_ICMP) {
     iov_len = icmp6_packet(out, pos + 1, (const struct icmp6_hdr *) next_header, len_left);
-  } else if(ip6->ip6_nxt == IPPROTO_TCP) {
+  } else if (ip6->ip6_nxt == IPPROTO_TCP) {
     iov_len = tcp_packet(out, pos + 1, (const struct tcphdr *) next_header, checksum,
                          len_left);
-  } else if(ip6->ip6_nxt == IPPROTO_UDP) {
+  } else if (ip6->ip6_nxt == IPPROTO_UDP) {
     iov_len = udp_packet(out, pos + 1, (const struct udphdr *) next_header, checksum,
                          len_left);
+  } else if (ip6->ip6_nxt == IPPROTO_GRE) {
+    iov_len = generic_packet(out, pos + 1, next_header, len_left);
   } else {
 #if CLAT_DEBUG
     logmsg(ANDROID_LOG_ERROR, "ipv6_packet/unknown next header type: %x", ip6->ip6_nxt);
diff --git a/translate.c b/translate.c
index 75ad08a..927b49c 100644
--- a/translate.c
+++ b/translate.c
@@ -279,6 +279,22 @@
   return clat_packet_len;
 }
 
+/* function: generic_packet
+ * takes a generic IP packet and sets it up for translation
+ * out      - output packet
+ * pos      - position in the output packet of the transport header
+ * payload  - pointer to IP payload
+ * len      - size of ip payload
+ * returns: the highest position in the output clat_packet that's filled in
+ */
+int generic_packet(clat_packet out, int pos, const char *payload, size_t len) {
+  out[pos].iov_len = 0;
+  out[CLAT_POS_PAYLOAD].iov_base = (char *) payload;
+  out[CLAT_POS_PAYLOAD].iov_len = len;
+
+  return CLAT_POS_PAYLOAD + 1;
+}
+
 /* function: udp_packet
  * takes a udp packet and sets it up for translation
  * out      - output packet
diff --git a/translate.h b/translate.h
index c4d8ede..9f1ac15 100644
--- a/translate.h
+++ b/translate.h
@@ -57,6 +57,9 @@
 int icmp6_to_icmp(clat_packet out, int pos, const struct icmp6_hdr *icmp6,
                   const char *payload, size_t payload_size);
 
+// Translate generic IP packets.
+int generic_packet(clat_packet out, int pos, const char *payload, size_t len);
+
 // Translate TCP and UDP packets.
 int tcp_packet(clat_packet out, int pos, const struct tcphdr *tcp, uint32_t checksum, size_t len);
 int udp_packet(clat_packet out, int pos, const struct udphdr *udp, uint32_t checksum, size_t len);