Home | History | Annotate | Download | only in client
      1 /*
      2  * Copyright 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 #pragma once
     17 
     18 #include "interface.h"
     19 #include "message.h"
     20 #include "result.h"
     21 #include "router.h"
     22 #include "socket.h"
     23 #include "timer.h"
     24 
     25 #include <netinet/in.h>
     26 #include <stdint.h>
     27 
     28 #include <random>
     29 
     30 
     31 class DhcpClient {
     32 public:
     33     DhcpClient();
     34 
     35     // Initialize the DHCP client to listen on |interfaceName|.
     36     Result init(const char* interfaceName);
     37     Result run();
     38 private:
     39     enum class State {
     40         Init,
     41         Selecting,
     42         Requesting,
     43         Bound,
     44         Renewing,
     45         Rebinding
     46     };
     47     const char* stateToStr(State state);
     48 
     49     // Wait for any pending timeouts
     50     void waitAndReceive(const sigset_t& pollSignalMask);
     51     // Create a varying timeout (+- 1 second) based on the next timeout.
     52     uint32_t calculateTimeoutMillis();
     53     // Increase the next timeout in a manner that's compliant with the DHCP RFC.
     54     void increaseTimeout();
     55     // Move to |state|, the next poll timeout will be zero and the new
     56     // state will be immediately evaluated.
     57     void setNextState(State state);
     58     // Configure network interface based on the DHCP configuration in |msg|.
     59     bool configureDhcp(const Message& msg);
     60     // Halt network operations on the network interface for when configuration
     61     // is not possible and the protocol demands it.
     62     void haltNetwork();
     63     // Receive a message on the socket and populate |msg| with the received
     64     // data. If the message is a valid DHCP message the method returns true. If
     65     // it's not valid false is returned.
     66     bool receiveDhcpMessage(Message* msg);
     67 
     68     void sendDhcpDiscover();
     69     void sendDhcpRequest(in_addr_t destination);
     70     void sendMessage(const Message& message);
     71     Result send(in_addr_t source, in_addr_t destination,
     72                 uint16_t sourcePort, uint16_t destinationPort,
     73                 const uint8_t* data, size_t size);
     74 
     75     std::mt19937 mRandomEngine; // Mersenne Twister RNG
     76     std::uniform_int_distribution<int> mRandomDistribution;
     77 
     78     struct DhcpInfo {
     79         uint32_t t1;
     80         uint32_t t2;
     81         uint32_t leaseTime;
     82         uint16_t mtu;
     83         in_addr_t dns[4];
     84         in_addr_t gateway;
     85         in_addr_t subnetMask;
     86         in_addr_t serverId;
     87         in_addr_t offeredAddress;
     88     } mDhcpInfo;
     89 
     90     Router mRouter;
     91     Interface mInterface;
     92     Message mLastMsg;
     93     Timer mT1, mT2;
     94     Socket mSocket;
     95     State mState;
     96     uint32_t mNextTimeout;
     97     bool mFuzzNextTimeout;
     98 
     99     in_addr_t mRequestAddress; // Address we'd like to use in requests
    100     in_addr_t mServerAddress;  // Server to send request to
    101 };
    102 
    103