1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "proxy.h" 18 19 #include <errno.h> 20 #include <linux/if_packet.h> 21 #include <poll.h> 22 #include <signal.h> 23 24 #include "log.h" 25 #include "message.h" 26 #include "packet.h" 27 #include "result.h" 28 29 // The prefix length for an address of a single unique node 30 static const uint8_t kNodePrefixLength = 128; 31 static const size_t kLinkAddressSize = 6; 32 33 // Rewrite the link address of a neighbor discovery option to the link address 34 // of |interface|. This can be either a source or target link address as 35 // specified by |optionType|. The valid values are ND_OPT_TARGET_LINKADDR and 36 // ND_OPT_SOURCE_LINKADDR. This will modify the message data inside |packet|. 37 static void rewriteLinkAddressOption(Packet& packet, 38 const Interface& interface, 39 int optionType) { 40 for (nd_opt_hdr* opt = packet.firstOpt(); opt; opt = packet.nextOpt(opt)) { 41 if (opt->nd_opt_type == optionType) { 42 auto src = interface.linkAddr().get<sockaddr_ll>(); 43 auto dest = reinterpret_cast<char*>(opt) + sizeof(nd_opt_hdr); 44 memcpy(dest, src->sll_addr, kLinkAddressSize); 45 } 46 } 47 } 48 49 int Proxy::run() { 50 sigset_t blockMask, originalMask; 51 int status = ::sigfillset(&blockMask); 52 if (status != 0) { 53 loge("Unable to fill signal set: %s\n", strerror(errno)); 54 return 1; 55 } 56 status = ::sigprocmask(SIG_SETMASK, &blockMask, &originalMask); 57 if (status != 0) { 58 loge("Unable to set signal mask: %s\n", strerror(errno)); 59 return 1; 60 } 61 // Init outer interface and router 62 if (!mOuterIf.init() || !mRouter.init()) { 63 return 1; 64 } 65 // Init all inner interfaces 66 for (size_t i = 0; i < mInnerIfs.size(); ++i) { 67 if (!mInnerIfs[i].init()) { 68 return 1; 69 } 70 } 71 72 // Create list of FDs to poll, we're only looking for input (POLLIN) 73 std::vector<pollfd> fds(mInnerIfs.size() + 1); 74 fds[0].fd = mOuterIf.ipSocket().get(); 75 fds[0].events = POLLIN; 76 for (size_t i = 0; i < mInnerIfs.size(); ++i) { 77 fds[i + 1].fd = mInnerIfs[i].ipSocket().get(); 78 fds[i + 1].events = POLLIN; 79 } 80 81 Message message; 82 while (status >= 0) { 83 status = ::ppoll(fds.data(), fds.size(), nullptr, &originalMask); 84 if (status > 0) { 85 // Something available to read 86 for (const struct pollfd& fd : fds) { 87 if (receiveIfPossible(fd, mOuterIf.ipSocket(), &message)) { 88 // Received a message on the outer interface 89 handleOuterMessage(message); 90 } else { 91 for (auto& inner : mInnerIfs) { 92 if (receiveIfPossible(fd, inner.ipSocket(), &message)) { 93 // Received a message on the inner interface 94 handleInnerMessage(inner, message); 95 } 96 } 97 } 98 } 99 } 100 } 101 loge("Polling failed: %s\n", strerror(errno)); 102 return 1; 103 } 104 105 bool Proxy::receiveIfPossible(const pollfd& fd, 106 Socket& socket, 107 Message* message) { 108 // Check if it's actually the socket we're interested in 109 if (fd.fd != socket.get()) { 110 return false; 111 } 112 // Check if there is something to read on this socket 113 if ((fd.revents & POLLIN) == 0) { 114 return false; 115 } 116 117 // Receive the message and place the data in the message parameter 118 Result res = socket.receive(message); 119 if (!res) { 120 loge("Error receiving on socket: %s\n", res.c_str()); 121 return false; 122 } 123 return true; 124 } 125 126 void Proxy::handleOuterMessage(Message& message) { 127 Packet packet(message); 128 uint32_t options = kForwardOnly; 129 switch (packet.type()) { 130 case Packet::Type::RouterAdvertisement: 131 options = kRewriteSourceLink | kSetDefaultGateway; 132 break; 133 case Packet::Type::NeighborSolicitation: 134 options = kSpoofSource; 135 break; 136 case Packet::Type::NeighborAdvertisement: 137 options = kRewriteTargetLink; 138 break; 139 default: 140 return; 141 } 142 for (auto& inner : mInnerIfs) { 143 forward(mOuterIf, inner, packet, options); 144 } 145 } 146 147 void Proxy::handleInnerMessage(const Interface& inner, Message& message) { 148 Packet packet(message); 149 uint32_t options = kForwardOnly; 150 switch (packet.type()) { 151 case Packet::Type::RouterSolicitation: 152 options = kSpoofSource; 153 break; 154 case Packet::Type::NeighborSolicitation: 155 options = kSpoofSource | kAddRoute; 156 break; 157 case Packet::Type::NeighborAdvertisement: 158 options = kRewriteTargetLink | kSpoofSource | kAddRoute; 159 break; 160 default: 161 return; 162 } 163 forward(inner, mOuterIf, packet, options); 164 } 165 166 void Proxy::forward(const Interface& from, 167 Interface& to, 168 Packet& packet, 169 uint32_t options) { 170 if (mLogDebug) { 171 logd("Forwarding %s from %s/%s to %s/%s\n", 172 packet.description().c_str(), 173 from.name().c_str(), addrToStr(packet.ip()->ip6_src).c_str(), 174 to.name().c_str(), addrToStr(packet.ip()->ip6_dst).c_str()); 175 } 176 177 if (options & kRewriteTargetLink) { 178 rewriteLinkAddressOption(packet, to, ND_OPT_TARGET_LINKADDR); 179 } 180 if (options & kRewriteSourceLink) { 181 rewriteLinkAddressOption(packet, to, ND_OPT_SOURCE_LINKADDR); 182 } 183 184 Result res = Result::success(); 185 if (options & kSpoofSource) { 186 // Spoof the source of the packet so that it appears to originate from 187 // the same source that we see. 188 res = to.icmpSocket().sendFrom(packet.ip()->ip6_src, 189 packet.ip()->ip6_dst, 190 packet.icmp(), 191 packet.icmpSize()); 192 } else { 193 res = to.icmpSocket().sendTo(packet.ip()->ip6_dst, 194 packet.icmp(), 195 packet.icmpSize()); 196 } 197 if (!res) { 198 loge("Failed to forward %s from %s to %s: %s\n", 199 packet.description().c_str(), 200 from.name().c_str(), to.name().c_str(), 201 res.c_str()); 202 } 203 204 if (options & kAddRoute) { 205 mRouter.addRoute(packet.ip()->ip6_src, kNodePrefixLength, from.index()); 206 } 207 if (packet.type() == Packet::Type::RouterAdvertisement && 208 options & kSetDefaultGateway) { 209 // Set the default gateway from this router advertisement. This is 210 // needed so that packets that are forwarded as a result of proxying 211 // actually have somewhere to go. 212 if (!mRouter.setDefaultGateway(packet.ip()->ip6_src, from.index())) { 213 loge("Failed to set default gateway %s\n", 214 addrToStr(packet.ip()->ip6_src).c_str()); 215 } 216 } 217 } 218 219