summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjoern Johansson <bjoernj@google.com>2018-09-06 15:29:22 -0700
committerBjoern Johansson <bjoernj@google.com>2018-09-06 15:29:22 -0700
commitf52fc12be67cfb72a44bf79a77112d80e01f3cf3 (patch)
tree8e4ab9a188a65781a5c566a2f0331f4a1959edcb
parent355b598179da0bb0908bee3568f8ad66c984c385 (diff)
downloadandroid_device_generic_goldfish-f52fc12be67cfb72a44bf79a77112d80e01f3cf3.tar.gz
android_device_generic_goldfish-f52fc12be67cfb72a44bf79a77112d80e01f3cf3.tar.bz2
android_device_generic_goldfish-f52fc12be67cfb72a44bf79a77112d80e01f3cf3.zip
Make DHCP server assign interface-based addresses
Currently the DHCP server used in the router namespace assigns addresses as configured on the command line. This is redundant information as all the necessary information can be deduced from the current interface address anyway. Remove most of the command line options in favor of assigning addresses from the same subnet that the interface is in and a gateway that is the same address as the interface. BUG: 111997081 Test: Run emulator and verify that radio and wifi networking works Change-Id: I8b6adb76f7445b7650da8f2a59b020b4fef991ee
-rw-r--r--dhcp/server/dhcpserver.cpp161
-rw-r--r--dhcp/server/dhcpserver.h26
-rw-r--r--dhcp/server/log.h2
-rw-r--r--dhcp/server/main.cpp87
-rw-r--r--init.ranchu.rc2
5 files changed, 138 insertions, 140 deletions
diff --git a/dhcp/server/dhcpserver.cpp b/dhcp/server/dhcpserver.cpp
index 33fb61a..d6d4a7b 100644
--- a/dhcp/server/dhcpserver.cpp
+++ b/dhcp/server/dhcpserver.cpp
@@ -35,16 +35,7 @@
static const int kMaxDnsServers = 4;
-DhcpServer::DhcpServer(in_addr_t dhcpRangeStart,
- in_addr_t dhcpRangeEnd,
- in_addr_t netmask,
- in_addr_t gateway,
- unsigned int excludeInterface) :
- mNextAddressOffset(0),
- mDhcpRangeStart(dhcpRangeStart),
- mDhcpRangeEnd(dhcpRangeEnd),
- mNetmask(netmask),
- mGateway(gateway),
+DhcpServer::DhcpServer(unsigned int excludeInterface) :
mExcludeInterface(excludeInterface)
{
}
@@ -147,9 +138,13 @@ void DhcpServer::sendDhcpOffer(const Message& message,
unsigned int interfaceIndex ) {
updateDnsServers();
in_addr_t offerAddress;
+ in_addr_t netmask;
+ in_addr_t gateway;
Result res = getOfferAddress(interfaceIndex,
message.dhcpData.chaddr,
- &offerAddress);
+ &offerAddress,
+ &netmask,
+ &gateway);
if (!res) {
ALOGE("Failed to get address for offer: %s", res.c_str());
return;
@@ -165,8 +160,8 @@ void DhcpServer::sendDhcpOffer(const Message& message,
Message offer = Message::offer(message,
serverAddress,
offerAddress,
- mNetmask,
- mGateway,
+ netmask,
+ gateway,
mDnsServers.data(),
mDnsServers.size());
res = sendMessage(interfaceIndex, serverAddress, offer);
@@ -177,10 +172,15 @@ void DhcpServer::sendDhcpOffer(const Message& message,
void DhcpServer::sendAck(const Message& message, unsigned int interfaceIndex) {
updateDnsServers();
- in_addr_t offerAddress, serverAddress;
+ in_addr_t offerAddress;
+ in_addr_t netmask;
+ in_addr_t gateway;
+ in_addr_t serverAddress;
Result res = getOfferAddress(interfaceIndex,
message.dhcpData.chaddr,
- &offerAddress);
+ &offerAddress,
+ &netmask,
+ &gateway);
if (!res) {
ALOGE("Failed to get address for offer: %s", res.c_str());
return;
@@ -194,8 +194,8 @@ void DhcpServer::sendAck(const Message& message, unsigned int interfaceIndex) {
Message ack = Message::ack(message,
serverAddress,
offerAddress,
- mNetmask,
- mGateway,
+ netmask,
+ gateway,
mDnsServers.data(),
mDnsServers.size());
res = sendMessage(interfaceIndex, serverAddress, ack);
@@ -222,9 +222,13 @@ void DhcpServer::sendNack(const Message& message, unsigned int interfaceIndex) {
bool DhcpServer::isValidDhcpRequest(const Message& message,
unsigned int interfaceIndex) {
in_addr_t offerAddress;
+ in_addr_t netmask;
+ in_addr_t gateway;
Result res = getOfferAddress(interfaceIndex,
message.dhcpData.chaddr,
- &offerAddress);
+ &offerAddress,
+ &netmask,
+ &gateway);
if (!res) {
ALOGE("Failed to get address for offer: %s", res.c_str());
return false;
@@ -251,32 +255,99 @@ void DhcpServer::updateDnsServers() {
}
}
-Result DhcpServer::getInterfaceAddress(unsigned int interfaceIndex,
- in_addr_t* address) {
+Result DhcpServer::getInterfaceData(unsigned int interfaceIndex,
+ unsigned long type,
+ struct ifreq* response) {
char interfaceName[IF_NAMESIZE + 1];
if (if_indextoname(interfaceIndex, interfaceName) == nullptr) {
return Result::error("Failed to get interface name for index %u: %s",
interfaceIndex, strerror(errno));
}
- struct ifreq request;
- memset(&request, 0, sizeof(request));
- request.ifr_addr.sa_family = AF_INET;
- strncpy(request.ifr_name, interfaceName, IFNAMSIZ - 1);
+ memset(response, 0, sizeof(*response));
+ response->ifr_addr.sa_family = AF_INET;
+ strncpy(response->ifr_name, interfaceName, IFNAMSIZ - 1);
- if (::ioctl(mSocket.get(), SIOCGIFADDR, &request) == -1) {
- return Result::error("Failed to get address for interface %s: %s",
+ if (::ioctl(mSocket.get(), type, response) == -1) {
+ return Result::error("Failed to get data for interface %s: %s",
interfaceName, strerror(errno));
}
- auto inAddr = reinterpret_cast<struct sockaddr_in*>(&request.ifr_addr);
- *address = inAddr->sin_addr.s_addr;
-
return Result::success();
}
+Result DhcpServer::getInterfaceAddress(unsigned int interfaceIndex,
+ in_addr_t* address) {
+ struct ifreq data;
+ Result res = getInterfaceData(interfaceIndex, SIOCGIFADDR, &data);
+ if (res.isSuccess()) {
+ auto inAddr = reinterpret_cast<struct sockaddr_in*>(&data.ifr_addr);
+ *address = inAddr->sin_addr.s_addr;
+ }
+ return res;
+}
+
+Result DhcpServer::getInterfaceNetmask(unsigned int interfaceIndex,
+ in_addr_t* address) {
+ struct ifreq data;
+ Result res = getInterfaceData(interfaceIndex, SIOCGIFNETMASK, &data);
+ if (res.isSuccess()) {
+ auto inAddr = reinterpret_cast<struct sockaddr_in*>(&data.ifr_addr);
+ *address = inAddr->sin_addr.s_addr;
+ }
+ return res;
+}
+
+static bool isValidHost(const in_addr_t address,
+ const in_addr_t interfaceAddress,
+ const in_addr_t netmask) {
+ // If the bits outside of the netmask are all zero it's a network address,
+ // don't use this.
+ bool isNetworkAddress = (address & ~netmask) == 0;
+ // If all bits outside of the netmask are set then it's a broadcast address,
+ // don't use this either.
+ bool isBroadcastAddress = (address & ~netmask) == ~netmask;
+ // Don't assign the interface address to a host
+ bool isInterfaceAddress = address == interfaceAddress;
+
+ return !isNetworkAddress && !isBroadcastAddress && !isInterfaceAddress;
+}
+
+static bool addressInRange(const in_addr_t address,
+ const in_addr_t interfaceAddress,
+ const in_addr_t netmask) {
+ if (address <= (interfaceAddress & netmask)) {
+ return false;
+ }
+ if (address >= (interfaceAddress | ~netmask)) {
+ return false;
+ }
+ return true;
+}
+
Result DhcpServer::getOfferAddress(unsigned int interfaceIndex,
const uint8_t* macAddress,
- in_addr_t* address) {
+ in_addr_t* address,
+ in_addr_t* netmask,
+ in_addr_t* gateway) {
+ // The interface address will be the gateway and will be used to determine
+ // the range of valid addresses (along with the netmask) for the client.
+ in_addr_t interfaceAddress = 0;
+ Result res = getInterfaceAddress(interfaceIndex, &interfaceAddress);
+ if (!res) {
+ return res;
+ }
+ // The netmask of the interface will be the netmask for the client as well
+ // as used to determine network range.
+ in_addr_t mask = 0;
+ res = getInterfaceNetmask(interfaceIndex, &mask);
+ if (!res) {
+ return res;
+ }
+
+ // Assign these values now before they are modified below
+ *gateway = interfaceAddress;
+ *netmask = mask;
+
Lease key(interfaceIndex, macAddress);
// Find or create entry, if it's created it will be zero and we update it
@@ -284,18 +355,30 @@ Result DhcpServer::getOfferAddress(unsigned int interfaceIndex,
if (value == 0) {
// Addresses are stored in network byte order so when doing math on them
// they have to be converted to host byte order
- in_addr_t nextAddress = ntohl(mDhcpRangeStart) + mNextAddressOffset;
- uint8_t lastAddressByte = nextAddress & 0xFF;
- while (lastAddressByte == 0xFF || lastAddressByte == 0) {
- // The address ends in .255 or .0 which means it's a broadcast or
- // network address respectively. Increase it further to avoid this.
+ interfaceAddress = ntohl(interfaceAddress);
+ mask = ntohl(mask);
+ // Get a reference to the offset so we can use it and increase it at the
+ // same time. If the entry does not exist it will be created with a
+ // value of zero.
+ in_addr_t& offset = mNextAddressOffsets[interfaceIndex];
+ if (offset == 0) {
+ // Increase if zero to avoid assigning network address
+ ++offset;
+ }
+ // Start out at the first address in the range as determined by netmask
+ in_addr_t nextAddress = (interfaceAddress & mask) + offset;
+
+ // Ensure the address is valid
+ while (!isValidHost(nextAddress, interfaceAddress, mask) &&
+ addressInRange(nextAddress, interfaceAddress, mask)) {
++nextAddress;
- ++mNextAddressOffset;
+ ++offset;
}
- if (nextAddress <= ntohl(mDhcpRangeEnd)) {
- // And then converted back again
+
+ if (addressInRange(nextAddress, interfaceAddress, mask)) {
+ // Convert back to network byte order
value = htonl(nextAddress);
- ++mNextAddressOffset;
+ ++offset;
} else {
// Ran out of addresses
return Result::error("DHCP server is out of addresses");
diff --git a/dhcp/server/dhcpserver.h b/dhcp/server/dhcpserver.h
index c5e1007..276cd5b 100644
--- a/dhcp/server/dhcpserver.h
+++ b/dhcp/server/dhcpserver.h
@@ -30,14 +30,9 @@ class Message;
class DhcpServer {
public:
- // Construct a DHCP server with the given parameters. Ignore any requests
- // and discoveries coming on the network interface identified by
- // |excludeInterface|.
- DhcpServer(in_addr_t dhcpRangeStart,
- in_addr_t dhcpRangeEnd,
- in_addr_t netmask,
- in_addr_t gateway,
- unsigned int excludeInterface);
+ // Construct a DHCP server. Ignore any requests and discoveries coming on
+ // the network interface identified by |excludeInterface|.
+ explicit DhcpServer(unsigned int excludeInterface);
Result init();
Result run();
@@ -54,24 +49,27 @@ private:
bool isValidDhcpRequest(const Message& message,
unsigned int interfaceIndex);
void updateDnsServers();
+ Result getInterfaceData(unsigned int interfaceIndex,
+ unsigned long type,
+ struct ifreq* response);
Result getInterfaceAddress(unsigned int interfaceIndex,
in_addr_t* address);
+ Result getInterfaceNetmask(unsigned int interfaceIndex,
+ in_addr_t* netmask);
Result getOfferAddress(unsigned int interfaceIndex,
const uint8_t* macAddress,
- in_addr_t* address);
+ in_addr_t* address,
+ in_addr_t* netmask,
+ in_addr_t* gateway);
Socket mSocket;
// This is the next address offset. This will be added to whatever the base
// address of the DHCP address range is. For each new MAC address seen this
// value will increase by one.
- in_addr_t mNextAddressOffset;
- in_addr_t mDhcpRangeStart;
- in_addr_t mDhcpRangeEnd;
- in_addr_t mNetmask;
- in_addr_t mGateway;
std::vector<in_addr_t> mDnsServers;
// Map a lease to an IP address for that lease
std::unordered_map<Lease, in_addr_t> mLeases;
+ std::unordered_map<unsigned int, in_addr_t> mNextAddressOffsets;
unsigned int mExcludeInterface;
};
diff --git a/dhcp/server/log.h b/dhcp/server/log.h
index bb1094f..a0f21e0 100644
--- a/dhcp/server/log.h
+++ b/dhcp/server/log.h
@@ -16,5 +16,5 @@
#pragma once
#define LOG_TAG "dhcpserver"
-#include <cutils/log.h>
+#include <log/log.h>
diff --git a/dhcp/server/main.cpp b/dhcp/server/main.cpp
index eecafc1..482ffd6 100644
--- a/dhcp/server/main.cpp
+++ b/dhcp/server/main.cpp
@@ -26,73 +26,10 @@ static void usage(const char* program) {
}
int main(int argc, char* argv[]) {
- in_addr_t rangeStart = 0;
- in_addr_t rangeEnd = 0;
- in_addr_t gateway = 0;
- in_addr_t netmask = 0;
char* excludeInterfaceName = nullptr;
unsigned int excludeInterfaceIndex = 0;
for (int i = 1; i < argc; ++i) {
- if (strcmp("--range", argv[i]) == 0) {
- if (i + 1 >= argc) {
- ALOGE("ERROR: Missing argument to --range parameter");
- usage(argv[0]);
- return 1;
- }
- char* divider = strchr(argv[i + 1], ',');
- if (divider != nullptr) {
- *divider = '\0';
- struct in_addr address;
- if (inet_pton(AF_INET, argv[i + 1], &address) > 0) {
- rangeStart = address.s_addr;
- } else {
- ALOGE("ERROR: Invalid start address '%s'", argv[i + 1]);
- usage(argv[0]);
- return 1;
- }
- char* next = divider + 1;
- if (inet_pton(AF_INET, next, &address) > 0) {
- rangeEnd = address.s_addr;
- } else {
- ALOGE("ERROR: Invalid end address '%s'", next);
- usage(argv[0]);
- return 1;
- }
- } else {
- ALOGE("ERROR: Invalid --range parameter '%s'", argv[i + 1]);
- usage(argv[0]);
- return 1;
- }
- ++i;
- } else if (strcmp("--gateway", argv[i]) == 0) {
- if (i + 1 >= argc) {
- ALOGE("ERROR: Missing argument to --gateway parameter");
- usage(argv[0]);
- return 1;
- }
- struct in_addr address;
- if (inet_pton(AF_INET, argv[i + 1], &address) > 0) {
- gateway = address.s_addr;
- } else {
- ALOGE("ERROR: Invalid gateway '%s'", argv[i + 1]);
- usage(argv[0]);
- return 1;
- }
- } else if (strcmp("--netmask", argv[i]) == 0) {
- if (i + 1 >= argc) {
- ALOGE("ERROR: Missing argument to --netmask parameter");
- usage(argv[0]);
- return 1;
- }
- struct in_addr address;
- if (inet_pton(AF_INET, argv[i + 1], &address) > 0) {
- netmask = address.s_addr;
- } else {
- ALOGE("ERROR: Invalid netmask '%s'", argv[i + 1]);
- usage(argv[0]);
- return 1;
- }
- } else if (strcmp("--exclude-interface", argv[i]) == 0) {
+ if (strcmp("--exclude-interface", argv[i]) == 0) {
if (i + 1 >= argc) {
ALOGE("ERROR: Missing argument to "
"--exclude-interfaces parameter");
@@ -110,27 +47,7 @@ int main(int argc, char* argv[]) {
}
}
- if (rangeStart == 0 || rangeEnd == 0) {
- ALOGE("ERROR: Missing or invalid --range argument");
- usage(argv[0]);
- return 1;
- }
- if (gateway == 0) {
- ALOGE("ERROR: Missing or invalid --gateway argument");
- usage(argv[0]);
- return 1;
- }
- if (netmask == 0) {
- ALOGE("ERROR: Missing or invalid --netmask argument");
- usage(argv[0]);
- return 1;
- }
-
- DhcpServer server(rangeStart,
- rangeEnd,
- netmask,
- gateway,
- excludeInterfaceIndex);
+ DhcpServer server(excludeInterfaceIndex);
Result res = server.init();
if (!res) {
ALOGE("Failed to initialize DHCP server: %s\n", res.c_str());
diff --git a/init.ranchu.rc b/init.ranchu.rc
index bf77184..5871766 100644
--- a/init.ranchu.rc
+++ b/init.ranchu.rc
@@ -70,7 +70,7 @@ service emu_hostapd /vendor/bin/execns -u wifi -g wifi router /vendor/bin/hostap
group root wifi net_raw net_admin
disabled
-service dhcpserver /vendor/bin/execns router /vendor/bin/dhcpserver --range 192.168.232.2,192.168.239.254 --gateway 192.168.232.1 --netmask 255.255.248.0 --exclude-interface eth0
+service dhcpserver /vendor/bin/execns router /vendor/bin/dhcpserver --exclude-interface eth0
user root
group root
disabled