forked from DavidAnson/DHCPLite
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDHCPLite.h
198 lines (159 loc) · 5.56 KB
/
DHCPLite.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
#pragma once
#include <map>
#include <array>
#include <vector>
#include <string>
#include <functional>
#include <windows.h>
#include <winsock.h>
namespace DHCPLite {
// Maximum size of a UDP datagram (see RFC 768)
constexpr auto MAX_UDP_MESSAGE_SIZE = 65536 - 8;
// DHCP constants (see RFC 2131 section 4.1)
constexpr auto DHCP_SERVER_PORT = 67;
// DHCP constants (see RFC 2131 section 4.1)
constexpr auto DHCP_CLIENT_PORT = 68;
// Broadcast bit for flags field (RFC 2131 section 2)
constexpr auto BROADCAST_FLAG = 0x80;
// For display of host name information
constexpr auto MAX_HOSTNAME_LENGTH = 256;
class DHCPMessage {
public:
enum MessageTypes {
MsgType_DISCOVER = 1,
MsgType_OFFER = 2,
MsgType_REQUEST = 3,
MsgType_DECLINE = 4,
MsgType_ACK = 5,
MsgType_NAK = 6,
MsgType_RELEASE = 7,
MsgType_INFORM = 8,
};
enum MessageOpValues { // RFC 2131 section 2
MsgOp_BOOT_REQUEST = 1,
MsgOp_BOOT_REPLY = 2,
};
enum MessageOptionValues { // RFC 2132 section 9.6
MsgOption_PAD = 0,
MsgOption_SUBNET_MASK = 1,
MsgOption_HOSTNAME = 12,
MsgOption_REQUESTED_ADDRESS = 50,
MsgOption_ADDRESS_LEASETIME = 51,
MsgOption_MESSAGE_TYPE = 53,
MsgOption_SERVER_IDENTIFIER = 54,
MsgOption_CLIENT_IDENTIFIER = 61,
MsgOption_END = 255,
};
private:
std::map<BYTE, std::vector<BYTE>> optionList;
// Get the options and save it into optionList
size_t SetOptionList(std::vector<BYTE> options);
public:
struct MessageBody { // RFC 2131 section 2
BYTE op; // 0: Message opcode/type
BYTE htype; // 1: Hardware addr type (net/if_types.h)
BYTE hlen; // 2: Hardware addr length
BYTE hops; // 3: Number of relay agent hops from client
DWORD xid; // 4: Transaction ID
WORD secs; // 8: Seconds since client started looking
WORD flags; // 10: Flag bits
DWORD ciaddr; // 12: Client IP address (if already in use)
DWORD yiaddr; // 16: Client IP address
DWORD siaddr; // 20: IP address of next server to talk to
DWORD giaddr; // 24: DHCP relay agent IP address
BYTE chaddr[16]; // 28: Client hardware address
BYTE sname[64]; // 44: Server name
BYTE file[128]; // 108: Boot filename
DWORD magicCookie; // 236: Optional parameters (First is MagicCookie)
} body;
DHCPMessage();
DHCPMessage(std::vector<BYTE> data);
std::vector<BYTE> GetData();
void SetData(std::vector<BYTE> data);
std::vector<BYTE> GetOptionRaw(MessageOptionValues option);
template <class T> T GetOption(MessageOptionValues option);
void SetOptionRaw(MessageOptionValues option, std::vector<BYTE> data);
template <class T> void SetOption(MessageOptionValues option, T data);
void SetOption(MessageOptionValues option);
static std::vector<BYTE> PByteToVByte(const BYTE *data, int size);
};
class DHCPServer {
private:
struct AddressInUseInformation {
DWORD dwAddrValue;
BYTE *pbClientIdentifier;
DWORD dwClientIdentifierSize;
// SYSTEMTIME stExpireTime; // If lease timeouts are needed
};
typedef std::vector<AddressInUseInformation> VectorAddressInUseInformation;
typedef std::function<bool(const AddressInUseInformation &raiui)> FindIndexOfFilter;
private:
SOCKET sServerSocket = INVALID_SOCKET; // Global to allow ConsoleCtrlHandlerRoutine access to it
VectorAddressInUseInformation vAddressesInUse;
char pcsServerHostName[MAX_HOSTNAME_LENGTH]{};
std::string serverName = "DHCPLite DHCP Server";
int FindIndexOf(const VectorAddressInUseInformation *const pvAddressesInUse, FindIndexOfFilter pFilter);
bool InitializeDHCPServer();
void ProcessDHCPClientRequest(const BYTE *const pbData, const int iDataSize);
bool ReadDHCPClientRequests();
public:
struct IPAddrInfo {
DWORD address;
DWORD mask;
};
struct DHCPConfig {
IPAddrInfo addrInfo;
DWORD minAddr;
DWORD maxAddr;
};
typedef std::function<void(char *clientHostName, DWORD offerAddr)> MessageCallback;
static DWORD IPtoValue(DWORD ip);
static DWORD ValuetoIP(DWORD value);
static std::string IPAddrToString(DWORD address);
static std::vector<IPAddrInfo> GetIPAddrInfoList();
static DHCPConfig GetDHCPConfig();
private:
DHCPConfig config{};
MessageCallback MessageCallback_Discover;
MessageCallback MessageCallback_ACK;
MessageCallback MessageCallback_NAK;
public:
// Set Discover Message Callback
// Callback Parameter: pcsClientHostName, dwOfferAddr
void SetDiscoverCallback(MessageCallback callback);
// Set Acknowledge Message Callback
// Callback Parameter: pcsClientHostName, dwClientPreviousOfferAddr
void SetACKCallback(MessageCallback callback);
// Set Negative Acknowledgment Message Callback
// Callback Parameter: pcsClientHostName, dwClientPreviousOfferAddr
void SetNAKCallback(MessageCallback callback);
DHCPServer() {}
DHCPServer(DHCPConfig config);
bool Init();
bool Init(DHCPConfig config);
void Start();
void Close();
bool Cleanup();
bool SetServerName(std::string name);
};
class DHCPException : public std::exception {
public:
DHCPException(const char *Message) : exception(Message, 1) {}
};
class MessageException : public DHCPException {
public:
MessageException(const char *Message) : DHCPException(Message) {}
};
class IPAddrException : public DHCPException {
public:
IPAddrException(const char *Message) : DHCPException(Message) {}
};
class SocketException : public DHCPException {
public:
SocketException(const char *Message) : DHCPException(Message) {}
};
class RequestException : public DHCPException {
public:
RequestException(const char *Message) : DHCPException(Message) {}
};
}