• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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