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