From c8683d7eb9bb95de2090431e8daaa45d92b45e38 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Tue, 1 Sep 2015 16:53:35 +0900 Subject: Don't break IPv6 connectivity when in doze mode. Working IPv6 connectivity relies on the kernel being able to receive certain ICMPv6 packets (router advertisements, neighbour solicitations, neighbour advertisements) at all times. Allow these packets when in doze mode. This is not necessary for IPv4 because in IPv4 these functions use ARP, which is invisible to iptables. Bug: 23158230 Change-Id: I29ed77561db9688486cf58cd14ac3bce7fce4b40 --- server/FirewallController.cpp | 19 +++++++++++++++++++ server/FirewallController.h | 3 +++ 2 files changed, 22 insertions(+) diff --git a/server/FirewallController.cpp b/server/FirewallController.cpp index bcf7524c..cf5a7de2 100644 --- a/server/FirewallController.cpp +++ b/server/FirewallController.cpp @@ -37,6 +37,18 @@ const char* FirewallController::LOCAL_FORWARD = "fw_FORWARD"; const char* FirewallController::LOCAL_DOZABLE = "fw_dozable"; const char* FirewallController::LOCAL_STANDBY = "fw_standby"; +// ICMPv6 types that are required for any form of IPv6 connectivity to work. Note that because the +// fw_dozable chain is called from both INPUT and OUTPUT, this includes both packets that we need +// to be able to send (e.g., RS, NS), and packets that we need to receive (e.g., RA, NA). +const char* FirewallController::ICMPV6_TYPES[] = { + "packet-too-big", + "router-solicitation", + "router-advertisement", + "neighbour-solicitation", + "neighbour-advertisement", + "redirect", +}; + FirewallController::FirewallController(void) { // If no rules are set, it's in BLACKLIST mode mFirewallType = BLACKLIST; @@ -264,11 +276,18 @@ int FirewallController::createChain(const char* childChain, int res = 0; res |= execIptables(V4V6, "-t", TABLE, "-N", childChain, NULL); if (type == WHITELIST) { + // Allow ICMPv6 packets necessary to make IPv6 connectivity work. http://b/23158230 . + for (size_t i = 0; i < ARRAY_SIZE(ICMPV6_TYPES); i++) { + res |= execIptables(V6, "-A", childChain, "-p", "icmpv6", "--icmpv6-type", + ICMPV6_TYPES[i], "-j", "RETURN", NULL); + } + // create default white list for system uid range char uidStr[16]; sprintf(uidStr, "0-%d", AID_APP - 1); res |= execIptables(V4V6, "-A", childChain, "-m", "owner", "--uid-owner", uidStr, "-j", "RETURN", NULL); + // create default rule to drop all traffic res |= execIptables(V4V6, "-A", childChain, "-j", "DROP", NULL); } diff --git a/server/FirewallController.h b/server/FirewallController.h index b32072e7..34a8b9ce 100644 --- a/server/FirewallController.h +++ b/server/FirewallController.h @@ -64,6 +64,9 @@ public: static const char* LOCAL_DOZABLE; static const char* LOCAL_STANDBY; + + static const char* ICMPV6_TYPES[]; + private: FirewallType mFirewallType; int attachChain(const char*, const char*); -- cgit v1.2.3