Use a packet socket to receive packets.

Combined with the previous change to send on a raw socket
instead of a tunnel interface, this allows us to get rid of the
clat interface and remove all the routing configuration code.

(cherry picked from commit d44fac888a441cf21111358f43384f3942399d5d)

Bug: 15340961
Change-Id: I2147dbfc07321bbd64d3fb9762b1120487712133
diff --git a/Android.mk b/Android.mk
index f94acdf..a640e06 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,7 +1,7 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES:=clatd.c dump.c checksum.c translate.c icmp.c ipv4.c ipv6.c config.c dns64.c logging.c getaddr.c getroute.c netlink_callbacks.c netlink_msg.c setif.c setroute.c mtu.c
+LOCAL_SRC_FILES:=clatd.c dump.c checksum.c translate.c icmp.c ipv4.c ipv6.c config.c dns64.c logging.c getaddr.c netlink_callbacks.c netlink_msg.c setif.c mtu.c
 
 LOCAL_CFLAGS := -Wall -Werror -Wunused-parameter
 LOCAL_C_INCLUDES := external/libnl/include bionic/libc/dns/include
diff --git a/clatd.c b/clatd.c
index be7d0c6..001c4cb 100644
--- a/clatd.c
+++ b/clatd.c
@@ -32,9 +32,12 @@
 #include <sys/capability.h>
 #include <sys/uio.h>
 #include <linux/prctl.h>
+#include <linux/filter.h>
 #include <linux/if.h>
 #include <linux/if_tun.h>
 #include <linux/if_ether.h>
+#include <linux/if_packet.h>
+#include <net/if.h>
 
 #include <private/android_filesystem_config.h>
 
@@ -44,31 +47,17 @@
 #include "logging.h"
 #include "resolv_netid.h"
 #include "setif.h"
-#include "setroute.h"
 #include "mtu.h"
 #include "getaddr.h"
 #include "dump.h"
 
-#define DEVICENAME6 "clat"
 #define DEVICENAME4 "clat4"
 
 /* 40 bytes IPv6 header - 20 bytes IPv4 header + 8 bytes fragment header */
 #define MTU_DELTA 28
 
-int forwarding_fd = -1;
 volatile sig_atomic_t running = 1;
 
-/* function: set_forwarding
- * enables/disables ipv6 forwarding
- */
-void set_forwarding(int fd, const char *setting) {
-  /* we have to forward packets from the WAN to the tun interface */
-  if(write(fd, setting, strlen(setting)) < 0) {
-    logmsg(ANDROID_LOG_FATAL,"set_forwarding(%s) failed: %s", setting, strerror(errno));
-    exit(1);
-  }
-}
-
 /* function: stop_loop
  * signal handler: stop the event loop
  */
@@ -114,34 +103,51 @@
   return 0;
 }
 
-/* function: deconfigure_tun_ipv6
- * removes the ipv6 route
- * tunnel - tun device data
+/* function: configure_packet_socket
+ * Binds the packet socket and attaches the receive filter to it.
+ * sock - the socket to configure
  */
-void deconfigure_tun_ipv6(const struct tun_data *tunnel) {
-  int status;
-
-  status = if_route(tunnel->device6, AF_INET6, &Global_Clatd_Config.ipv6_local_subnet,
-      128, NULL, 1, 0, ROUTE_DELETE);
-  if(status < 0) {
-    logmsg(ANDROID_LOG_WARN,"deconfigure_tun_ipv6/if_route(6) failed: %s",strerror(-status));
+int configure_packet_socket(int sock) {
+  struct sockaddr_ll sll = {
+    .sll_family   = AF_PACKET,
+    .sll_protocol = htons(ETH_P_IPV6),
+    .sll_ifindex  = if_nametoindex((char *) &Global_Clatd_Config.default_pdp_interface),
+    .sll_pkttype  = PACKET_OTHERHOST,  // The 464xlat IPv6 address is not assigned to the kernel.
+  };
+  if (bind(sock, (struct sockaddr *) &sll, sizeof(sll))) {
+    logmsg(ANDROID_LOG_FATAL, "binding packet socket: %s", strerror(errno));
+    return 0;
   }
-}
 
-/* function: configure_tun_ipv6
- * configures the ipv6 route
- * note: routes a /128 out of the (assumed routed to us) /64 to the CLAT interface
- * tunnel - tun device data
- */
-void configure_tun_ipv6(const struct tun_data *tunnel) {
-  int status;
+  uint32_t *ipv6 = Global_Clatd_Config.ipv6_local_subnet.s6_addr32;
+  struct sock_filter filter_code[] = {
+    // Load the first four bytes of the IPv6 destination address (starts 24 bytes in).
+    // Compare it against the first four bytes of our IPv6 address, in host byte order (BPF loads
+    // are always in host byte order). If it matches, continue with next instruction (JMP 0). If it
+    // doesn't match, jump ahead to statement that returns 0 (ignore packet). Repeat for the other
+    // three words of the IPv6 address, and if they all match, return PACKETLEN (accept packet).
+    BPF_STMT(BPF_LD  | BPF_W   | BPF_ABS,  24),
+    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K,    htonl(ipv6[0]), 0, 7),
+    BPF_STMT(BPF_LD  | BPF_W   | BPF_ABS,  28),
+    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K,    htonl(ipv6[1]), 0, 5),
+    BPF_STMT(BPF_LD  | BPF_W   | BPF_ABS,  32),
+    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K,    htonl(ipv6[2]), 0, 3),
+    BPF_STMT(BPF_LD  | BPF_W   | BPF_ABS,  36),
+    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K,    htonl(ipv6[3]), 0, 1),
+    BPF_STMT(BPF_RET | BPF_K,              PACKETLEN),
+    BPF_STMT(BPF_RET | BPF_K, 0)
+  };
+  struct sock_fprog filter = {
+    sizeof(filter_code) / sizeof(filter_code[0]),
+    filter_code
+  };
 
-  status = if_route(tunnel->device6, AF_INET6, &Global_Clatd_Config.ipv6_local_subnet,
-      128, NULL, 1, 0, ROUTE_CREATE);
-  if(status < 0) {
-    logmsg(ANDROID_LOG_FATAL,"configure_tun_ipv6/if_route(6) failed: %s",strerror(-status));
-    exit(1);
+  if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter))) {
+    logmsg(ANDROID_LOG_FATAL, "attach packet filter failed: %s", strerror(errno));
+    return 0;
   }
+
+  return 1;
 }
 
 /* function: interface_poll
@@ -153,7 +159,8 @@
 
   interface_ip = getinterface_ip(Global_Clatd_Config.default_pdp_interface, AF_INET6);
   if(!interface_ip) {
-    logmsg(ANDROID_LOG_WARN,"unable to find an ipv6 ip on interface %s",Global_Clatd_Config.default_pdp_interface);
+    logmsg(ANDROID_LOG_WARN,"unable to find an ipv6 ip on interface %s",
+           Global_Clatd_Config.default_pdp_interface);
     return;
   }
 
@@ -165,12 +172,15 @@
     inet_ntop(AF_INET6, &interface_ip->ip6, to_addr, sizeof(to_addr));
     logmsg(ANDROID_LOG_WARN, "clat subnet changed from %s to %s", from_addr, to_addr);
 
-    // remove old route
-    deconfigure_tun_ipv6(tunnel);
-
-    // add new route, start translating packets to the new prefix
+    // Start translating packets to the new prefix.
     memcpy(&Global_Clatd_Config.ipv6_local_subnet, &interface_ip->ip6, sizeof(struct in6_addr));
-    configure_tun_ipv6(tunnel);
+
+    // Update our packet socket filter to reflect the new 464xlat IP address.
+    if (!configure_packet_socket(tunnel->read_fd6)) {
+        // Things aren't going to work. Bail out and hope we have better luck next time.
+        // We don't log an error here because attach_filter has already done so.
+        exit(1);
+    }
   }
 
   free(interface_ip);
@@ -192,24 +202,10 @@
     exit(1);
   }
 
-  status = add_address(tunnel->device6, AF_INET6, &Global_Clatd_Config.ipv6_local_address,
-      64, NULL);
-  if(status < 0) {
-    logmsg(ANDROID_LOG_FATAL,"configure_tun_ip/if_address(6) failed: %s",strerror(-status));
-    exit(1);
-  }
-
-  if((status = if_up(tunnel->device6, Global_Clatd_Config.mtu)) < 0) {
-    logmsg(ANDROID_LOG_FATAL,"configure_tun_ip/if_up(6) failed: %s",strerror(-status));
-    exit(1);
-  }
-
   if((status = if_up(tunnel->device4, Global_Clatd_Config.ipv4mtu)) < 0) {
     logmsg(ANDROID_LOG_FATAL,"configure_tun_ip/if_up(4) failed: %s",strerror(-status));
     exit(1);
   }
-
-  configure_tun_ipv6(tunnel);
 }
 
 /* function: drop_root
@@ -248,10 +244,10 @@
   }
 }
 
-/* function: open_raw_socket
- * opens the raw socket for sending IPv6 packets
+/* function: open_socket
+ * opens raw and packet sockets
  */
-void open_raw_socket(struct tun_data *tunnel) {
+void open_sockets(struct tun_data *tunnel) {
   int rawsock = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
   if (rawsock < 0) {
     logmsg(ANDROID_LOG_FATAL, "raw socket failed: %s", strerror(errno));
@@ -264,6 +260,14 @@
   }
 
   tunnel->write_fd6 = rawsock;
+
+  int packetsock = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6));
+  if (packetsock < 0) {
+    logmsg(ANDROID_LOG_FATAL, "packet socket failed: %s", strerror(errno));
+    exit(1);
+  }
+
+  tunnel->read_fd6 = packetsock;
 }
 
 /* function: configure_interface
@@ -300,12 +304,6 @@
     logmsg(ANDROID_LOG_WARN,"ipv4mtu now set to = %d",Global_Clatd_Config.ipv4mtu);
   }
 
-  error = tun_alloc(tunnel->device6, tunnel->read_fd6);
-  if(error < 0) {
-    logmsg(ANDROID_LOG_FATAL,"tun_alloc failed: %s",strerror(errno));
-    exit(1);
-  }
-
   error = tun_alloc(tunnel->device4, tunnel->fd4);
   if(error < 0) {
     logmsg(ANDROID_LOG_FATAL,"tun_alloc/4 failed: %s",strerror(errno));
@@ -322,13 +320,10 @@
  */
 void read_packet(int active_fd, const struct tun_data *tunnel) {
   ssize_t readlen;
-  uint8_t packet[PACKETLEN];
+  uint8_t buf[PACKETLEN], *packet;
+  int fd;
 
-  // In case something ignores the packet length.
-  // TODO: remove it.
-  memset(packet, 0, PACKETLEN);
-
-  readlen = read(active_fd,packet,PACKETLEN);
+  readlen = read(active_fd, buf, PACKETLEN);
 
   if(readlen < 0) {
     logmsg(ANDROID_LOG_WARN,"read_packet/read error: %s", strerror(errno));
@@ -336,32 +331,37 @@
   } else if(readlen == 0) {
     logmsg(ANDROID_LOG_WARN,"read_packet/tun interface removed");
     running = 0;
-  } else {
+    return;
+  }
+
+  if (active_fd == tunnel->fd4) {
     ssize_t header_size = sizeof(struct tun_pi);
 
-    if(readlen < header_size) {
+    if (readlen < header_size) {
       logmsg(ANDROID_LOG_WARN,"read_packet/short read: got %ld bytes", readlen);
       return;
     }
 
-    struct tun_pi *tun_header = (struct tun_pi *) packet;
-    if(tun_header->flags != 0) {
-      logmsg(ANDROID_LOG_WARN, "%s: unexpected flags = %d", __func__, tun_header->flags);
-    }
-
-    int fd;
+    struct tun_pi *tun_header = (struct tun_pi *) buf;
     uint16_t proto = ntohs(tun_header->proto);
-    if (proto == ETH_P_IP) {
-      fd = tunnel->write_fd6;
-    } else if (proto == ETH_P_IPV6) {
-      fd = tunnel->fd4;
-    } else {
+    if (proto != ETH_P_IP) {
       logmsg(ANDROID_LOG_WARN, "%s: unknown packet type = 0x%x", __func__, proto);
       return;
     }
 
-    translate_packet(fd, (proto == ETH_P_IP), packet + header_size, readlen - header_size);
+    if(tun_header->flags != 0) {
+      logmsg(ANDROID_LOG_WARN, "%s: unexpected flags = %d", __func__, tun_header->flags);
+    }
+
+    fd = tunnel->write_fd6;
+    packet = buf + header_size;
+    readlen -= header_size;
+  } else {
+    fd = tunnel->fd4;
+    packet = buf;
   }
+
+  translate_packet(fd, (fd == tunnel->write_fd6), packet, readlen);
 }
 
 /* function: event_loop
@@ -423,7 +423,6 @@
   char *uplink_interface = NULL, *plat_prefix = NULL, *net_id_str = NULL;
   unsigned net_id = NETID_UNSET;
 
-  strcpy(tunnel.device6, DEVICENAME6);
   strcpy(tunnel.device4, DEVICENAME4);
 
   while((opt = getopt(argc, argv, "i:p:n:h")) != -1) {
@@ -460,28 +459,14 @@
   }
   logmsg(ANDROID_LOG_INFO, "Starting clat version %s on %s", CLATD_VERSION, uplink_interface);
 
-  // open the tunnel device before dropping privs
-  tunnel.read_fd6 = tun_open();
-  if(tunnel.read_fd6 < 0) {
-    logmsg(ANDROID_LOG_FATAL, "tun_open6 failed: %s", strerror(errno));
-    exit(1);
-  }
-
+  // open the tunnel device and our raw sockets before dropping privs
   tunnel.fd4 = tun_open();
   if(tunnel.fd4 < 0) {
     logmsg(ANDROID_LOG_FATAL, "tun_open4 failed: %s", strerror(errno));
     exit(1);
   }
 
-  // open the forwarding configuration before dropping privs
-  forwarding_fd = open("/proc/sys/net/ipv6/conf/all/forwarding", O_RDWR);
-  if(forwarding_fd < 0) {
-    logmsg(ANDROID_LOG_FATAL,"open /proc/sys/net/ipv6/conf/all/forwarding failed: %s",
-           strerror(errno));
-    exit(1);
-  }
-
-  open_raw_socket(&tunnel);
+  open_sockets(&tunnel);
 
   // run under a regular user
   drop_root();
@@ -492,7 +477,10 @@
 
   configure_interface(uplink_interface, plat_prefix, &tunnel, net_id);
 
-  set_forwarding(forwarding_fd,"1\n");
+  if (!configure_packet_socket(tunnel.read_fd6)) {
+    // We've already logged an error.
+    exit(1);
+  }
 
   // Loop until someone sends us a signal or brings down the tun interface.
   if(signal(SIGTERM, stop_loop) == SIG_ERR) {
@@ -501,7 +489,6 @@
   }
   event_loop(&tunnel);
 
-  set_forwarding(forwarding_fd,"0\n");
   logmsg(ANDROID_LOG_INFO,"Shutting down clat on %s", uplink_interface);
 
   return 0;
diff --git a/clatd.h b/clatd.h
index 0a48013..0f4809d 100644
--- a/clatd.h
+++ b/clatd.h
@@ -23,7 +23,7 @@
 
 #define MAXMTU 1500
 #define PACKETLEN (MAXMTU+sizeof(struct tun_pi))
-#define CLATD_VERSION "1.2"
+#define CLATD_VERSION "1.3"
 
 // how frequently (in seconds) to poll for an address change while traffic is passing
 #define INTERFACE_POLL_FREQUENCY 30
@@ -32,7 +32,7 @@
 #define NO_TRAFFIC_INTERFACE_POLL_FREQUENCY 90
 
 struct tun_data {
-  char device6[IFNAMSIZ], device4[IFNAMSIZ];
+  char device4[IFNAMSIZ];
   int read_fd6, write_fd6, fd4;
 };
 
diff --git a/config.c b/config.c
index 3d39ff0..d8bec80 100644
--- a/config.c
+++ b/config.c
@@ -31,7 +31,6 @@
 #include "logging.h"
 #include "getaddr.h"
 #include "clatd.h"
-#include "setroute.h"
 
 struct clat_config Global_Clatd_Config;
 
diff --git a/dump.c b/dump.c
index 0fda4e7..27b75d1 100644
--- a/dump.c
+++ b/dump.c
@@ -162,7 +162,7 @@
 }
 
 /* print tcp header */
-void dump_tcp_generic(const struct tcphdr *tcp, const char *options, size_t options_size, uint32_t temp_checksum, const char *payload, size_t payload_size) {
+void dump_tcp_generic(const struct tcphdr *tcp, const uint8_t *options, size_t options_size, uint32_t temp_checksum, const uint8_t *payload, size_t payload_size) {
   uint16_t my_checksum;
 
   temp_checksum = ip_checksum_add(temp_checksum, tcp, sizeof(struct tcphdr));
@@ -205,7 +205,7 @@
 /* print ipv4/tcp header */
 void dump_tcp(const struct tcphdr *tcp, const struct iphdr *ip,
               const uint8_t *payload, size_t payload_size,
-              const char *options, size_t options_size) {
+              const uint8_t *options, size_t options_size) {
   uint32_t temp_checksum;
 
   temp_checksum = ipv4_pseudo_header_checksum(ip, sizeof(*tcp) + options_size + payload_size);
@@ -215,7 +215,7 @@
 /* print ipv6/tcp header */
 void dump_tcp6(const struct tcphdr *tcp, const struct ip6_hdr *ip6,
                const uint8_t *payload, size_t payload_size,
-               const char *options, size_t options_size) {
+               const uint8_t *options, size_t options_size) {
   uint32_t temp_checksum;
 
   temp_checksum = ipv6_pseudo_header_checksum(ip6, sizeof(*tcp) + options_size + payload_size, IPPROTO_TCP);
diff --git a/getroute.c b/getroute.c
deleted file mode 100644
index a615a4f..0000000
--- a/getroute.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright 2012 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.
- *
- * getroute.c - get an ip route
- */
-#include <string.h>
-#include <errno.h>
-
-#include <sys/socket.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-#include <arpa/inet.h>
-
-#include <netlink/handlers.h>
-#include <netlink/msg.h>
-
-#include "getroute.h"
-#include "netlink_callbacks.h"
-#include "netlink_msg.h"
-
-/* function: get_default_route_cb
- * finds the default route with the request family and out interface and saves the gateway
- * msg  - netlink message
- * data - (struct default_route_data) requested filters and response storage
- */
-static int get_default_route_cb(struct nl_msg *msg, void *data) {
-  struct rtmsg *rt_p;
-  struct rtattr *rta_p;
-  int rta_len;
-  struct default_route_data *default_route = data;
-  union anyip *this_gateway = NULL;
-  ssize_t this_gateway_size;
-  int this_interface_id = -1;
-
-  if(default_route->reply_found_route) { // we already found our route
-    return NL_OK;
-  }
-
-  rt_p = (struct rtmsg *)nlmsg_data(nlmsg_hdr(msg));
-  if(rt_p->rtm_dst_len != 0) { // not a default route
-    return NL_OK;
-  }
-  if((rt_p->rtm_family != default_route->request_family) || (rt_p->rtm_table != RT_TABLE_MAIN)) { // not a route we care about
-    return NL_OK;
-  }
-
-  rta_p = (struct rtattr *)RTM_RTA(rt_p);
-  rta_len = RTM_PAYLOAD(nlmsg_hdr(msg));
-  for(; RTA_OK(rta_p, rta_len); rta_p = RTA_NEXT(rta_p, rta_len)) {
-    switch(rta_p->rta_type) {
-      case RTA_GATEWAY:
-        this_gateway = RTA_DATA(rta_p);
-        this_gateway_size = RTA_PAYLOAD(rta_p);
-        break;
-      case RTA_OIF:
-        this_interface_id = *(int *)RTA_DATA(rta_p);
-        break;
-      default:
-        break;
-    }
-  }
-
-  if(this_interface_id == default_route->request_interface_id) {
-    default_route->reply_found_route = 1;
-    if(this_gateway != NULL) {
-      memcpy(&default_route->reply_gateway, this_gateway, this_gateway_size);
-      default_route->reply_has_gateway = 1;
-    } else {
-      default_route->reply_has_gateway = 0;
-    }
-  }
-  return NL_OK;
-}
-
-/* function: error_handler
- * error callback for get_default_route
- * nla  - where the message came from
- * err  - netlink message
- * arg  - (int *) storage for the error number
- */
-static int error_handler(__attribute__((unused)) struct sockaddr_nl *nla,
-                         struct nlmsgerr *err, void *arg) {
-  int *retval = arg;
-  if(err->error < 0) { // error_handler called even on no error (NLMSG_ERROR reply type used)
-    *retval = err->error;
-  }
-  return NL_OK;
-}
-
-/* function: get_default_route
- * finds the first default route with the given family and interface, returns the gateway (if it exists) in the struct
- * default_route - requested family and interface, and response storage
- */
-int get_default_route(struct default_route_data *default_route) {
-  struct rtmsg msg;
-  struct nl_cb *callbacks = NULL;
-  struct nl_msg *nlmsg = NULL;
-  int retval = 0;
-
-  default_route->reply_has_gateway = 0;
-  default_route->reply_found_route = 0;
-
-  memset(&msg,'\0',sizeof(msg));
-  msg.rtm_family = default_route->request_family;
-  msg.rtm_table = RT_TABLE_MAIN;
-  msg.rtm_protocol = RTPROT_KERNEL;
-  msg.rtm_scope = RT_SCOPE_UNIVERSE;
-
-  callbacks = nl_cb_alloc(NL_CB_DEFAULT);
-  if(!callbacks) {
-    retval = -ENOMEM;
-    goto cleanup;
-  }
-  // get_default_route_cb sets the response fields in default_route
-  nl_cb_set(callbacks, NL_CB_VALID, NL_CB_CUSTOM, get_default_route_cb, default_route);
-  nl_cb_err(callbacks, NL_CB_CUSTOM, error_handler, &retval);
-
-  nlmsg = nlmsg_alloc_rtmsg(RTM_GETROUTE, NLM_F_REQUEST | NLM_F_ROOT, &msg);
-  if(!nlmsg) {
-    retval = -ENOMEM;
-    goto cleanup;
-  }
-  send_netlink_msg(nlmsg, callbacks);
-
-cleanup:
-  if(callbacks)
-    nl_cb_put(callbacks);
-  if(nlmsg)
-    nlmsg_free(nlmsg);
-
-  return retval;
-}
diff --git a/getroute.h b/getroute.h
deleted file mode 100644
index e7b8670..0000000
--- a/getroute.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2012 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.
- *
- * getroute.h - get an ip route
- */
-#ifndef __GETROUTE_H__
-#define __GETROUTE_H__
-
-// for union anyip
-#include "getaddr.h"
-
-struct default_route_data {
-  int request_interface_id;
-  int request_family;
-
-  union anyip reply_gateway;
-  int reply_has_gateway;
-  int reply_found_route;
-};
-
-int get_default_route(struct default_route_data *default_route);
-
-#endif
diff --git a/setroute.c b/setroute.c
deleted file mode 100644
index cffee9f..0000000
--- a/setroute.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright 2012 Daniel Drown <dan-android@drown.org>
- *
- * 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.
- *
- * setroute.c - network route configuration
- */
-#include <errno.h>
-#include <netinet/in.h>
-#include <net/if.h>
-
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-#include <netlink/handlers.h>
-#include <netlink/msg.h>
-
-#include "netlink_msg.h"
-#include "setroute.h"
-#include "logging.h"
-#include "getroute.h"
-
-/* function: if_route
- * create/replace/delete a route
- * ifname      - name of the outbound interface
- * family      - AF_INET or AF_INET6
- * destination - pointer to a struct in_addr or in6_addr for the destination network
- * prefixlen   - bitlength of the network address (example: 24 for AF_INET's 255.255.255.0)
- * gateway     - pointer to a struct in_addr or in6_addr for the gateway to use or NULL for an interface route
- * metric      - route metric (lower is better)
- * mtu         - route-specific mtu or 0 for the interface mtu
- * change_type - ROUTE_DELETE, ROUTE_REPLACE, or ROUTE_CREATE
- */
-int if_route(const char *ifname, int family, const void *destination, int prefixlen, const void *gateway, int metric, int mtu, int change_type) {
-  int retval;
-  struct nl_msg *msg = NULL;
-  struct rtmsg rt;
-  uint16_t type, flags = 0;
-  size_t addr_size;
-  uint32_t ifindex;
-
-  addr_size = inet_family_size(family);
-  if(addr_size == 0) {
-    retval = -EAFNOSUPPORT;
-    goto cleanup;
-  }
-
-  if (!(ifindex = if_nametoindex(ifname))) {
-    retval = -ENODEV;
-    goto cleanup;
-  }
-
-  memset(&rt, 0, sizeof(rt));
-  rt.rtm_family = family;
-  rt.rtm_table = RT_TABLE_MAIN;
-  rt.rtm_dst_len = prefixlen;
-  switch(change_type) {
-    case ROUTE_DELETE:
-      rt.rtm_scope = RT_SCOPE_NOWHERE;
-      type = RTM_DELROUTE;
-      break;
-
-    case ROUTE_REPLACE:
-      flags = NLM_F_REPLACE;
-    case ROUTE_CREATE:
-      type = RTM_NEWROUTE;
-      flags |= NLM_F_CREATE;
-      if(gateway == NULL) {
-        rt.rtm_scope = RT_SCOPE_LINK;
-      } else {
-        rt.rtm_scope = RT_SCOPE_UNIVERSE;
-      }
-      rt.rtm_type = RTN_UNICAST;
-      //RTPROT_STATIC = from administrator's configuration
-      //RTPROT_BOOT = from an automatic process
-      rt.rtm_protocol = RTPROT_BOOT;
-      break;
-
-    default:
-      retval = -EINVAL;
-      goto cleanup;
-  }
-
-  flags |= NLM_F_REQUEST | NLM_F_ACK;
-
-  msg = nlmsg_alloc_rtmsg(type, flags, &rt);
-  if(!msg) {
-    retval = -ENOMEM;
-    goto cleanup;
-  }
-
-  if(nla_put(msg, RTA_DST, addr_size, destination) < 0) {
-    retval = -ENOMEM;
-    goto cleanup;
-  }
-  if(gateway != NULL)
-    if(nla_put(msg, RTA_GATEWAY, addr_size, gateway) < 0) {
-      retval = -ENOMEM;
-      goto cleanup;
-    }
-  if(nla_put(msg, RTA_OIF, 4, &ifindex) < 0) {
-    retval = -ENOMEM;
-    goto cleanup;
-  }
-  if(nla_put(msg, RTA_PRIORITY, 4, &metric) < 0) {
-    retval = -ENOMEM;
-    goto cleanup;
-  }
-  if(mtu > 0 && change_type != ROUTE_DELETE) {
-    // MTU is inside an RTA_METRICS nested message
-    struct nlattr *metrics = nla_nest_start(msg, RTA_METRICS);
-    if(metrics == NULL) {
-      retval = -ENOMEM;
-      goto cleanup;
-    }
-
-    if(nla_put(msg, RTAX_MTU, 4, &mtu) < 0) {
-      retval = -ENOMEM;
-      goto cleanup;
-    }
-
-    nla_nest_end(msg, metrics);
-  }
-
-  retval = netlink_sendrecv(msg);
-
-cleanup:
-  if(msg)
-    nlmsg_free(msg);
-
-  return retval;
-}
diff --git a/setroute.h b/setroute.h
deleted file mode 100644
index 58f61cf..0000000
--- a/setroute.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2012 Daniel Drown <dan-android@drown.org>
- *
- * 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.
- *
- * setroute.h - network route configuration
- */
-
-#ifndef __SETROUTE_H__
-#define __SETROUTE_H__
-
-#define ROUTE_DELETE 0
-#define ROUTE_REPLACE 1
-#define ROUTE_CREATE 2
-int if_route(const char *ifname, int family, const void *destination, int cidr, const void *gateway, int metric, int mtu, int change_type);
-
-#endif