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