Home | History | Annotate | Download | only in netmgr
      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 
     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 
     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 
     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 
     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 
    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 
    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