使用win7的承载网络开启共享wifi,ICS分配IP地址比较慢,自己重新写了一个简单的DHCP协议,IP地址可以从2分配到254.可以用winshark来抓包,分析DHCP协议。
mydhcp.cpp
#include "pch.h"
#include "mydhcp.h"
#include <winsock2.h>
#include <iphlpapi.h>
#include <string.h>
#include "windows.h"
#include "Wbemcli.h"
#include <map>
#include <string>
#include <vector>
using namespace std;
struct mac_address {
int iIndex;
UINT8 data[6];
};
typedef struct mac_address MAC_ADDRESS;
DWORD WINAPI message_dispatcher(void);
void init_reply(DHCP_MESSAGE* request, DHCP_MESSAGE* reply);
UINT8 fill_dhcp_reply_offer(DHCP_MESSAGE* request, DHCP_MESSAGE* reply);
INT send_dhcp_reply(sockaddr_in* client_sock, DHCP_MESSAGE* reply, DWORD len);
UINT8 fill_dhcp_reply_ack(DHCP_MESSAGE* request, DHCP_MESSAGE* reply);
int SearchBinding(UINT8* strMac);
vector<MAC_ADDRESS> g_mapIPMAC;
sockaddr_in g_ServerAddr;
sockaddr_in g_ClientAddr;
int g_RecvPort = 67;
int g_SndPort = 68;
char g_RecvBuf[1024];
int g_BufLen;
SOCKET g_ServerSocket;
HANDLE g_hDispatcher;
mydhcp::mydhcp()
{
g_hDispatcher = NULL;
//g_ServerSocket = NULL;
}
mydhcp::~mydhcp()
{
if (g_hDispatcher != NULL) {
CloseHandle(g_hDispatcher);
}
//if (g_ServerSocket != NULL) {
// closesocket(g_ServerSocket);
//}
//WSACleanup();
g_hDispatcher = NULL;
//g_ServerSocket = NULL;
}
int mydhcp::StartMyDHCPServer(void)
{
WSADATA wsaData;
int iRetVal = 0;
BOOL bOpt = 1;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
int iError = WSAGetLastError();
CString csError;
csError.Format(_T("WSAStartup() Failed!:WSAGetLastError = %d"), iError);
AfxMessageBox(csError);
return -1;
}
memset((void*)&g_ClientAddr, 0, sizeof(g_ClientAddr));
g_ClientAddr.sin_family = AF_INET;
g_ClientAddr.sin_port = htons(g_SndPort);
g_ClientAddr.sin_addr.S_un.S_addr = inet_addr("255.255.255.255"); //reply->YourClientIPAdress;
g_ServerAddr.sin_family = AF_INET;
g_ServerAddr.sin_port = htons(g_RecvPort);
g_ServerAddr.sin_addr.S_un.S_addr = inet_addr("192.168.237.1");
g_ServerSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (g_ServerSocket != NULL) {
iRetVal = setsockopt(g_ServerSocket, SOL_SOCKET, SO_BROADCAST, (char FAR*) & bOpt, sizeof(bOpt));
if (iRetVal == SOCKET_ERROR) {
int iError = WSAGetLastError();
CString csError;
csError.Format(_T("setsockopt() Failed!:WSAGetLastError = %d"), iError);
//AfxMessageBox(csError);
closesocket(g_ServerSocket);
WSACleanup();
}
else {
iRetVal = bind(g_ServerSocket, (SOCKADDR*)&g_ServerAddr, sizeof(g_ServerAddr));
if (iRetVal == SOCKET_ERROR) {
int iError = WSAGetLastError();
CString csError;
csError.Format(_T("bind() Failed!:WSAGetLastError = %d"), iError);
/*AfxMessageBox(csError);*/
closesocket(g_ServerSocket);
WSACleanup();
}
else {
g_hDispatcher = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)message_dispatcher, NULL, 0, NULL);
}
}
}
else {
int iError = WSAGetLastError();
CString csError;
csError.Format(_T("socket() Failed!:WSAGetLastError = %d"), iError);
//AfxMessageBox(csError);
}
return iRetVal;
}
DWORD WINAPI message_dispatcher(void)
{
while (1) {
sockaddr_in client_sock;
int slen = sizeof(client_sock);
DWORD len;
DWORD send_len = 0;
DHCP_MESSAGE request;
DHCP_MESSAGE reply;
UINT8 type;
const UINT8 option_magic[4] = {0x63, 0x82, 0x53, 0x63};
DHCP_OPTIONS *opt_start, * opt_end;
if ((len = recvfrom(g_ServerSocket, (char*)& request, sizeof(request), 0, (SOCKADDR*)& client_sock, &slen)) < DHCP_HEADER_SIZE + 5) {
continue;
}
if (request.MessageType != BOOTREQUEST) {
continue;
}
if (request.HardwareAddressLength < 1 || request.HardwareAddressLength >16) {
continue;
}
if((len - DHCP_HEADER_SIZE < 4) || memcmp(request.MagicCookie, option_magic, sizeof(option_magic)) != 0) {
continue;
}
opt_start = (DHCP_OPTIONS*)(request.Options);
opt_end = (DHCP_OPTIONS*)(((UINT8*)(request.Options))+ len - DHCP_HEADER_SIZE);
while (opt_start < opt_end && opt_start->id != 0xff) {
opt_start = (DHCP_OPTIONS*)(((UINT8*)opt_start) + 2 + opt_start->len);
if (opt_start > opt_end) {
break;
}
}
if (!(opt_start < opt_end && opt_start->id == 0xff)) {
continue;
}
opt_start = (DHCP_OPTIONS*)(request.Options);
if (opt_start->id == 0x35) {
type = opt_start->data[0];
}
else {
continue;
}
init_reply(&request, &reply);
switch (type) {
case DHCP_DISCOVER:
type = fill_dhcp_reply_offer(&request, &reply);
send_len = DHCP_HEADER_SIZE + 62;
break;
case DHCP_REQUEST:
type = fill_dhcp_reply_ack(&request, &reply);
send_len = DHCP_HEADER_SIZE + 62;
break;
case DHCP_DECLINE:
break;
case DHCP_RELEASE:
break;
case DHCP_INFORM:
break;
default:
break;
}
if (type > 0) {
send_dhcp_reply(&client_sock, &reply, send_len);
}
send_len = 0;
Sleep(10);
}
WSACleanup();
return 0;
}
void init_reply(DHCP_MESSAGE* request, DHCP_MESSAGE* reply)
{
memset(reply, 0, sizeof(DHCP_MESSAGE));
reply->MessageType = BOOTREPLY;
reply->HardwareType = request->HardwareType;
reply->HardwareAddressLength = request->HardwareAddressLength;
reply->TransactionID = request->TransactionID;
reply->BootpFlags = request->BootpFlags;
reply->RelayAgentIPAddress = request->RelayAgentIPAddress;
memcpy(reply->ClienthardwareAddress, request->ClienthardwareAddress, request->HardwareAddressLength);
memcpy(reply->MagicCookie, request->MagicCookie, 4);
}
INT send_dhcp_reply(sockaddr_in* client_sock, DHCP_MESSAGE* reply, DWORD len)
{
INT iRet;
if ((iRet = sendto(g_ServerSocket, (char*)reply, len, 0, (SOCKADDR*)&g_ClientAddr, sizeof(g_ClientAddr))) < 0) {
int iError = WSAGetLastError();
return -1;
}
return iRet;
}
UINT8 fill_dhcp_reply_offer(DHCP_MESSAGE* request, DHCP_MESSAGE* reply)
{
int iIPTemp = SearchBinding(request->ClienthardwareAddress);
if (iIPTemp < 2 || iIPTemp>254) {
return 0;
}
UINT8 ucTemp = (UINT8)iIPTemp;
reply->YourClientIPAdress[3] = ucTemp;
reply->YourClientIPAdress[2] = 0xED;
reply->YourClientIPAdress[1] = 0xa8;
reply->YourClientIPAdress[0] = 0xc0;
reply->Options[0] = DHCP_MESSAGE_TYPE;
reply->Options[1] = 1;
reply->Options[2] = DHCP_OFFER;
reply->Options[3] = SERVER_IDENTIFIER;
reply->Options[4] = 4;
reply->Options[5] = 192;
reply->Options[6] = 168;
reply->Options[7] = 237;
reply->Options[8] = 1;
reply->Options[9] = SUBNET_MASK;
reply->Options[10] = 4;
reply->Options[11] = 255;
reply->Options[12] = 255;
reply->Options[13] = 255;
reply->Options[14] = 0;
reply->Options[15] = ROUTER;
reply->Options[16] = 4;
reply->Options[17] = 192;
reply->Options[18] = 168;
reply->Options[19] = 237;
reply->Options[20] = 1;
reply->Options[21] = DOMAIN_NAME_SERVER;
reply->Options[22] = 4;
reply->Options[23] = 192;
reply->Options[24] = 168;
reply->Options[25] = 237;
reply->Options[26] = 1;
reply->Options[27] = RENEWAL_T1_TIME_VALUE;
reply->Options[28] = 4;
reply->Options[29] = 0;
reply->Options[30] = 0;
reply->Options[31] = 0x01;
reply->Options[32] = 0x2c;
reply->Options[33] = REBINDING_T2_TIME_VALUE;
reply->Options[34] = 4;
reply->Options[35] = 0x00;
reply->Options[36] = 0x06;
reply->Options[37] = 0xeb;
reply->Options[38] = 0xe0;
reply->Options[39] = IP_ADDRESS_LEASE_TIME;
reply->Options[40] = 4;
reply->Options[41] = 0x00;
reply->Options[42] = 0x09;
reply->Options[43] = 0x3a;
reply->Options[44] = 0x80;
reply->Options[45] = NETBIOS_OVER_TCP_IP_NODE_TYPE;
reply->Options[46] = 1;
reply->Options[47] = 0x04;
reply->Options[48] = DOMAIN_NAME;
reply->Options[49] = 11;
reply->Options[50] = 0x6d;
reply->Options[51] = 0x73;
reply->Options[52] = 0x68;
reply->Options[53] = 0x6f;
reply->Options[54] = 0x6d;
reply->Options[55] = 0x65;
reply->Options[56] = 0x2e;
reply->Options[57] = 0x6e;
reply->Options[58] = 0x65;
reply->Options[59] = 0x74;
reply->Options[60] = 0x00;
reply->Options[61] = END;
return DHCP_OFFER;
}
UINT8 fill_dhcp_reply_ack(DHCP_MESSAGE* request, DHCP_MESSAGE* reply)
{
int iIPTemp = SearchBinding(request->ClienthardwareAddress);
if (iIPTemp < 2 || iIPTemp>254) {
return 0;
}
UINT8 ucTemp = (UINT8)iIPTemp;
reply->YourClientIPAdress[3] = ucTemp;
reply->YourClientIPAdress[2] = 0xED;
reply->YourClientIPAdress[1] = 0xa8;
reply->YourClientIPAdress[0] = 0xc0;
reply->Options[0] = DHCP_MESSAGE_TYPE;
reply->Options[1] = 1;
reply->Options[2] = DHCP_ACK;
reply->Options[3] = SERVER_IDENTIFIER;
reply->Options[4] = 4;
reply->Options[5] = 192;
reply->Options[6] = 168;
reply->Options[7] = 237;
reply->Options[8] = 1;
reply->Options[9] = SUBNET_MASK;
reply->Options[10] = 4;
reply->Options[11] = 255;
reply->Options[12] = 255;
reply->Options[13] = 255;
reply->Options[14] = 0;
reply->Options[15] = ROUTER;
reply->Options[16] = 4;
reply->Options[17] = 192;
reply->Options[18] = 168;
reply->Options[19] = 237;
reply->Options[20] = 1;
reply->Options[21] = DOMAIN_NAME_SERVER;
reply->Options[22] = 4;
reply->Options[23] = 192;
reply->Options[24] = 168;
reply->Options[25] = 237;
reply->Options[26] = 1;
reply->Options[27] = RENEWAL_T1_TIME_VALUE;
reply->Options[28] = 4;
reply->Options[29] = 0;
reply->Options[30] = 0;
reply->Options[31] = 0x01;
reply->Options[32] = 0x2c;
reply->Options[33] = REBINDING_T2_TIME_VALUE;
reply->Options[34] = 4;
reply->Options[35] = 0x00;
reply->Options[36] = 0x06;
reply->Options[37] = 0xeb;
reply->Options[38] = 0xe0;
reply->Options[39] = IP_ADDRESS_LEASE_TIME;
reply->Options[40] = 4;
reply->Options[41] = 0x00;
reply->Options[42] = 0x09;
reply->Options[43] = 0x3a;
reply->Options[44] = 0x80;
reply->Options[45] = NETBIOS_OVER_TCP_IP_NODE_TYPE;
reply->Options[46] = 1;
reply->Options[47] = 0x04;
reply->Options[48] = DOMAIN_NAME;
reply->Options[49] = 11;
reply->Options[50] = 0x6d;
reply->Options[51] = 0x73;
reply->Options[52] = 0x68;
reply->Options[53] = 0x6f;
reply->Options[54] = 0x6d;
reply->Options[55] = 0x65;
reply->Options[56] = 0x2e;
reply->Options[57] = 0x6e;
reply->Options[58] = 0x65;
reply->Options[59] = 0x74;
reply->Options[60] = 0x00;
reply->Options[61] = END;
return DHCP_ACK;
}
int SearchBinding(UINT8* strMac)
{
vector<MAC_ADDRESS> ::iterator iter;
int iRet = 0;
BOOL bRet;
string strTemp = "";
MAC_ADDRESS stuTemp;
for (int j = 0; j < 6; j++) {
stuTemp.data[j] = strMac[j];
}
if (g_mapIPMAC.empty()) {
stuTemp.iIndex = 2;
g_mapIPMAC.push_back(stuTemp);
return stuTemp.iIndex;
}
else {
for (iter = g_mapIPMAC.begin(); iter != g_mapIPMAC.end(); iter++) {
bRet = TRUE;
for (int i = 0; i < 6; i++) {
if (iter->data[i] != stuTemp.data[i]) {
bRet = FALSE;
break;
}
}
if (bRet) {
return iter->iIndex;
}
}
int iSize = (int)g_mapIPMAC.size();
if (iSize < 252) {
stuTemp.iIndex = iSize + 2;
g_mapIPMAC.push_back(stuTemp);
return stuTemp.iIndex;
}
else {
return -1;
}
}
}
mydhcp.h:
#pragma once
enum PORTS {
BOOTPS = 67,
BOOTPC = 68
};
enum OP_TYPES {
BOOTREQUEST = 1,
BOOTREPLY = 2
};
enum HARDWARE_ADDRESS_TYPES {
ETHERNET = 0x01,
ETHERNET_LEN = 0x06
};
enum DHCP_MESSAGE_TYPE {
DHCP_DISCOVER = 1,
DHCP_OFFER = 2,
DHCP_REQUEST = 3,
DHCP_DECLINE = 4,
DHCP_ACK = 5,
DHCP_NAK = 6,
DHCP_RELEASE = 7,
DHCP_INFORM = 8
};
enum {
/* RFC 1497 Vendor Extensions */
PAD = 0,
END = 255,
SUBNET_MASK = 1,
TIME_OFFSET = 2,
ROUTER = 3,
TIME_SERVER = 4,
NAME_SERVER = 5,
DOMAIN_NAME_SERVER = 6,
LOG_SERVER = 7,
COOKIE_SERVER = 8,
LPR_SERVER = 9,
IMPRESS_SERVER = 10,
RESOURCE_LOCATION_SERVER = 11,
HOST_NAME = 12,
BOOT_FILE_SIZE = 13,
MERIT_DUMP_FILE = 14,
DOMAIN_NAME = 15,
SWAP_SERVER = 16,
ROOT_PATH = 17,
EXTENSIONS_PATH = 18,
/* IP Layer Parameters per Host */
IP_FORWARDING = 19,
NON_LOCAL_SOURCE_ROUTING = 20,
POLICY_FILTER = 21,
MAXIMUM_DATAGRAM_REASSEMBLY_SIZE = 22,
DEFAULT_IP_TIME_TO_LIVE = 23,
PATH_MTU_AGING_TIMEOUT = 24,
PATH_MTU_PLATEAU_TABLE = 25,
/* IP Layer Parameters per Interface */
INTERFACE_MTU = 26,
ALL_SUBNETS_ARE_LOCAL = 27,
BROADCAST_ADDRESS = 28,
PERFORM_MASK_DISCOVERY = 29,
MASK_SUPPLIER = 30,
PERFORM_ROUTER_DISCOVERY = 31,
ROUTER_SOLICITATION_ADDRESS = 32,
STATIC_ROUTE = 33,
/* Link Layer Parameters per Interface */
TRAILER_ENCAPSULATION = 34,
ARP_CACHE_TIMEOUT = 35,
ETHERNET_ENCAPSULATION = 36,
/* TCP Parameters */
TCP_DEFAULT_TTL = 37,
TCP_KEEPALIVE_INTERVAL = 38,
TCP_KEEPALIVE_GARBAGE = 39,
/* Application and Service Parameters */
NETWORK_INFORMATION_SERVICE_DOMAIN = 40,
NETWORK_INFORMATION_SERVERS = 41,
NETWORK_TIME_PROTOCOL_SERVERS = 42,
VENDOR_SPECIFIC_INFORMATION = 43,
NETBIOS_OVER_TCP_IP_NAME_SERVER = 44,
NETBIOS_OVER_TCP_IP_DATAGRAM_DISTRIBUTION_SERVER = 4,
NETBIOS_OVER_TCP_IP_NODE_TYPE = 46,
NETBIOS_OVER_TCP_IP_SCOPE = 47,
X_WINDOW_SYSTEM_FONT_SERVER = 48,
X_WINDOW_SYSTEM_DISPLAY_MANAGER = 49,
NETWORK_INFORMATION_SERVICE_PLUS_DOMAIN = 64,
NETWORK_INFORMATION_SERVICE_PLUS_SERVERS = 65,
MOBILE_IP_HOME_AGENT = 68,
SMTP_SERVER = 69,
POP3_SERVER = 70,
NNTP_SERVER = 71,
DEFAULT_WWW_SERVER = 72,
DEFAULT_FINGER_SERVER = 73,
DEFAULT_IRC_SERVER = 74,
STREETTALK_SERVER = 75,
STREETTALK_DIRECTORY_ASSISTANCE_SERVER = 76,
/* DHCP Extensions */
REQUESTED_IP_ADDRESS = 50,
IP_ADDRESS_LEASE_TIME = 51,
OPTION_OVERLOAD = 52,
TFTP_SERVER_NAME = 66,
BOOTFILE_NAME = 67,
DHCP_MESSAGE_TYPE = 53,
SERVER_IDENTIFIER = 54,
PARAMETER_REQUEST_LIST = 55,
MESSAGE = 56,
MAXIMUM_DHCP_MESSAGE_SIZE = 57,
RENEWAL_T1_TIME_VALUE = 58,
REBINDING_T2_TIME_VALUE = 59,
VENDOR_CLASS_IDENTIFIER = 60,
CLIENT_IDENTIFIER = 61
};
enum {
DHCP_HEADER_SIZE = 240
};
struct dhcp_message {
UINT8 MessageType;
UINT8 HardwareType;
UINT8 HardwareAddressLength;
UINT8 Hops;
UINT32 TransactionID;
UINT16 SecondsElapsed;
UINT16 BootpFlags;
UINT32 ClientIPAdress;
UINT8 YourClientIPAdress[4];
UINT32 NextServerIPAddress;
UINT32 RelayAgentIPAddress;
UINT8 ClienthardwareAddress[16];
UINT8 ServerHostName[64];
UINT8 BootFileName[128];
UINT8 MagicCookie[4];
UINT8 Options[312];
};
typedef struct dhcp_message DHCP_MESSAGE;
struct dhcp_options {
UINT8 id;
UINT8 len;
UINT8 data[256];
};
typedef struct dhcp_options DHCP_OPTIONS;
extern HANDLE g_hDispatcher;
extern SOCKET g_ServerSocket;
class mydhcp
{
public:
mydhcp::mydhcp();
mydhcp::~mydhcp();
int mydhcp::StartmyDHCPServer(void);
};