Kill sockets when a VPN comes up.

1. Change the SockDiag callback function to be a filter that
   returns a bool instead of a function that optionally kills a
   socket. All existing callbacks basically only existed to kill
   sockets under certain conditions, and making them return a
   boolean allows reusing the same callback function signature
   to filter sockets as well.
2. Add a new SockDiag method to kill sockets based on a UidRanges
   object (which contains a number of UID ranges) and a list of
   users to skip.
3. Add a new UIDRANGE mode to SockDiagTest to test the above.
4. When UID ranges are added or removed from the VPN, kill
   sockets in those UID ranges unless the socket UIDs are in
   mProtectableUsers and thus their creator might have set the
   protect bit on their mark.  Short of actually being
   able to see the socket mark on each socket and basing our
   decision on that, this is the best we can do.

Bug: 26976388
Change-Id: I53a30df3feb63254a6451a29fa6041c9b679f9bb
diff --git a/server/VirtualNetwork.cpp b/server/VirtualNetwork.cpp
index 5db3645..3d83703 100644
--- a/server/VirtualNetwork.cpp
+++ b/server/VirtualNetwork.cpp
@@ -14,8 +14,10 @@
  * limitations under the License.
  */
 
+#include <set>
 #include "VirtualNetwork.h"
 
+#include "SockDiag.h"
 #include "RouteController.h"
 
 #define LOG_TAG "Netd"
@@ -40,7 +42,30 @@
     return mUidRanges.hasUid(uid);
 }
 
-int VirtualNetwork::addUsers(const UidRanges& uidRanges) {
+
+int VirtualNetwork::maybeCloseSockets(bool add, const UidRanges& uidRanges,
+                                      const std::set<uid_t>& protectableUsers) {
+    if (!mSecure) {
+        return 0;
+    }
+
+    SockDiag sd;
+    if (!sd.open()) {
+        return -EBADFD;
+    }
+
+    if (int ret = sd.destroySockets(uidRanges, protectableUsers)) {
+        ALOGE("Failed to close sockets while %s %s to network %d: %s",
+              add ? "adding" : "removing", uidRanges.toString().c_str(), mNetId, strerror(-ret));
+        return ret;
+    }
+
+    return 0;
+}
+
+int VirtualNetwork::addUsers(const UidRanges& uidRanges, const std::set<uid_t>& protectableUsers) {
+    maybeCloseSockets(true, uidRanges, protectableUsers);
+
     for (const std::string& interface : mInterfaces) {
         if (int ret = RouteController::addUsersToVirtualNetwork(mNetId, interface.c_str(), mSecure,
                                                                 uidRanges)) {
@@ -52,7 +77,10 @@
     return 0;
 }
 
-int VirtualNetwork::removeUsers(const UidRanges& uidRanges) {
+int VirtualNetwork::removeUsers(const UidRanges& uidRanges,
+                                const std::set<uid_t>& protectableUsers) {
+    maybeCloseSockets(false, uidRanges, protectableUsers);
+
     for (const std::string& interface : mInterfaces) {
         if (int ret = RouteController::removeUsersFromVirtualNetwork(mNetId, interface.c_str(),
                                                                      mSecure, uidRanges)) {