1 /*
2 * Copyright 2018, 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 "address_assigner.h"
18
19 #include "log.h"
20
21 #include <errno.h>
22 #include <net/if.h>
23 #include <string.h>
24 #include <sys/socket.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27
AddressAssigner(const char * interfacePrefix,in_addr_t baseAddress,uint32_t maskLength)28 AddressAssigner::AddressAssigner(const char* interfacePrefix,
29 in_addr_t baseAddress,
30 uint32_t maskLength) :
31 mInterfacePrefix(interfacePrefix),
32 mPrefixLength(strlen(interfacePrefix)),
33 mBaseAddress(baseAddress),
34 mMaskLength(maskLength) {
35
36 }
37
onInterfaceState(unsigned int,const char * name,InterfaceState state)38 void AddressAssigner::onInterfaceState(unsigned int /*index*/,
39 const char* name,
40 InterfaceState state) {
41 if (strncmp(name, mInterfacePrefix, mPrefixLength) != 0) {
42 // The interface does not match the prefix, ignore this change
43 return;
44 }
45
46 switch (state) {
47 case InterfaceState::Up:
48 assignAddress(name);
49 break;
50 case InterfaceState::Down:
51 freeAddress(name);
52 break;
53 }
54 }
55
assignAddress(const char * interfaceName)56 void AddressAssigner::assignAddress(const char* interfaceName) {
57 if (mMaskLength > 30) {
58 // The mask length is too long, we can't assign enough IP addresses from
59 // this. A maximum of 30 bits is supported, leaving 4 remaining
60 // addresses, one is network, one is broadcast, one is gateway, one is
61 // client.
62 return;
63 }
64 // Each subnet will have an amount of bits available to it that equals
65 // 32-bits - <mask length>, so if mask length is 29 there will be 3
66 // remaining bits for each subnet. Then the distance between each subnet
67 // is 2 to the power of this number, in our example 2^3 = 8 so to get to the
68 // next subnet we add 8 to the network address.
69 in_addr_t increment = 1 << (32 - mMaskLength);
70
71 // Convert the address to host byte-order first so we can do math on it.
72 for (in_addr_t addr = ntohl(mBaseAddress); true; addr += increment) {
73 // Take the reference of this lookup, that way we can assign a name to
74 // it if needed.
75 auto& usedName = mUsedIpAddresses[addr];
76 if (usedName.empty()) {
77 // This address is not in use, let's use it
78 usedName = interfaceName;
79 // Make sure we convert back to network byte-order when setting it.
80 setIpAddress(interfaceName, htonl(addr));
81 break;
82 }
83 }
84 }
85
setIpAddress(const char * interfaceName,in_addr_t address)86 void AddressAssigner::setIpAddress(const char* interfaceName,
87 in_addr_t address) {
88 int sock = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
89 if (sock == -1) {
90 LOGE("AddressAssigner unable to open IP socket: %s", strerror(errno));
91 return;
92 }
93 if (!setAddress(sock, SIOCSIFADDR, interfaceName, address)) {
94 LOGE("AddressAssigner unable to set interface address: %s",
95 strerror(errno));
96 ::close(sock);
97 return;
98 }
99
100 // The netmask is the inverted maximum value of the lower bits. That is if
101 // the mask length is 29 then the the largest value of the 3 (32-29) lowest
102 // bits is 7 (2^3 - 1) (111 binary). Inverting this value gives the netmask
103 // because it excludes those three bits and sets every other bit.
104 in_addr_t netmask = htonl(~((1 << (32 - mMaskLength)) - 1));
105
106 if (!setAddress(sock, SIOCSIFNETMASK, interfaceName, netmask)) {
107 LOGE("AddressAssigner unable to set interface netmask: %s",
108 strerror(errno));
109 ::close(sock);
110 return;
111 }
112
113 // The broadcast address is just the assigned address with all bits outside
114 // of the netmask set to one.
115 in_addr_t broadcast = address | ~netmask;
116
117 if (!setAddress(sock, SIOCSIFBRDADDR, interfaceName, broadcast)) {
118 LOGE("AddressAssigner unable to set interface broadcast: %s",
119 strerror(errno));
120 ::close(sock);
121 return;
122 }
123 ::close(sock);
124 }
125
setAddress(int sock,int type,const char * interfaceName,in_addr_t address)126 bool AddressAssigner::setAddress(int sock,
127 int type,
128 const char* interfaceName,
129 in_addr_t address) {
130 struct ifreq request;
131 memset(&request, 0, sizeof(request));
132 strlcpy(request.ifr_name, interfaceName, sizeof(request.ifr_name));
133 auto addr = reinterpret_cast<struct sockaddr_in*>(&request.ifr_addr);
134 addr->sin_family = AF_INET;
135 addr->sin_addr.s_addr = address;
136
137 if (::ioctl(sock, type, &request) != 0) {
138 return false;
139 }
140 return true;
141 }
142
freeAddress(const char * interfaceName)143 void AddressAssigner::freeAddress(const char* interfaceName) {
144 for (auto& ipName : mUsedIpAddresses) {
145 if (ipName.second == interfaceName) {
146 // This is the one, free it up for future use
147 mUsedIpAddresses.erase(ipName.first);
148 }
149 }
150 }
151
152