vcpe/srcs/opendhcp183/opendhcpd.cpp

5621 lines
188 KiB
C++

/**************************************************************************
* Copyright (C) 2005 by Achal Dhir *
* achaldhir@gmail.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
// opendhcp.cpp ///
#include <cmath>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <climits>
#include <sys/socket.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cerrno>
#include <memory.h>
#include <sys/stat.h>
#include <cstdlib>
#include <syslog.h>
#include <pthread.h>
#include <map>
using namespace std;
#include "dhcpd.h"
#include "opendhcpd.h"
#include "user_errno.h"
#include "task_manager.h"
void on_system_exit(void *p);
//Global Variables
data1 network;
data1 newNetwork;
data2 cfig;
bool verbatim = false;
data9 dhcpr;
data9 token;
//MYBYTE currentInd = 0;
//MYBYTE newInd = 0;
//data18 magin;
bool kRunning = true;
dhcpMap dhcpCache;
char serviceName[] = "OpenDHCP";
//expiryMap dhcpAge;
//char tempbuff[512] = "";
//char extbuff[512];
//char logBuff[256] = "";
char exeFile[PATH_MAX] = "";
char iniFile[PATH_MAX] = "";
char leaFile[PATH_MAX] = "";
//char logFile[PATH_MAX] = "";
//char tempFile[PATH_MAX] = "/tmp/opendhcp.tmp";
char filePATH[PATH_MAX] = "";
char htmlTitle[PATH_MAX] = "";
char icoFile[PATH_MAX] = "";
char nicif[256] = "";
char *icoString = nullptr;
unsigned long icoSize = 0;
data71 lump;
//char arpa[] = ".in-addr.arpa";
//char ip6arpa[] = ".ip6.arpa";
time_t t = time(nullptr);
timeval tv;
fd_set readfds;
//fd_set writefds;
pthread_mutex_t mutStateFile = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutLogFile = PTHREAD_MUTEX_INITIALIZER;
struct ifconf Ifc;
struct ifreq IfcBuf[MAX_SERVERS];
//constants
const char NBSP = 32;
const char RANGESET[] = "RANGE_SET";
const char GLOBALOPTIONS[] = "GLOBAL_OPTIONS";
//const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
//const char send200[] = "HTTP/1.1 200 OK\r\nDate: %s\r\nLast-Modified: %s\r\nContent-Type: text/html\r\nConnection: Close\r\nTransfer-Encoding: chunked\r\n";
//const char send200[] = "HTTP/1.1 200 OK\r\nDate: %s\r\nLast-Modified: %s\r\nContent-Type: text/html\r\nConnection: Close\r\nContent-Length: \r\n\r\n";
//const char send200[] = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: Close\r\n\r\n";
const char send200[] = "HTTP/1.1 200 OK\r\nContent-Type: %s\r\nConnection: close\r\nContent-Length: %i\r\n\r\n";
const char send403[] = "HTTP/1.1 403 Forbidden\r\n\r\n<h1>403 Forbidden</h1>";
const char send404[] = "HTTP/1.1 404 Not Found\r\n\r\n<h1>404 Not Found</h1>";
const char td200[] = "<td>%s</td>";
const char tdnowrap200[] = "<td nowrap>%s</td>";
const char sVersion[] = "Open DHCP Server Version 1.83 Linux Build 1057";
const char htmlStart
[] = "<html>\n<head>\n<title>%s</title><meta http-equiv=\"refresh\" content=\"60\">\n<meta "
"http-equiv=\"cache-control\" content=\"no-cache\">\n</head>\n";
const char bodyStart
[] = "<body bgcolor=\"#cccccc\"><table border=\"0\"><tr><td>\n<table width=\"100%%\" border=\"0\"><tr><td nowrap "
"colspan=\"2\" align=\"center\"><font size=\"6\"><b>%s</b></font></td></tr><tr><td "
"align=\"left\"><b>Server:</b> %s %s %s</td></tr></table>";
//const char htmlStart[] = "<html>\n<head>\n<title>%s</title><meta http-equiv=\"refresh\" content=\"60\">\n<meta http-equiv=\"cache-control\" content=\"no-cache\">\n</head>\n";
//const char bodyStart[] = "<body bgcolor=\"#cccccc\"><table width=\"800\"><tr><td align=\"center\"><font size=\"5\"><b>%s</b></font></b></b></td></tr><tr><td align=\"right\"><a target=\"_new\" href=\"http://dhcp-dns-server.sourceforge.net/\">http://dhcp-dns-server.sourceforge.net/</b></b></td></tr></table>";
//const char bodyStart[] = "<body bgcolor=\"#cccccc\"><table width=640><tr><td align=\"center\"><font size=\"5\"><b>%s</b></font></td></tr><tr><td align=\"right\"><a target=\"_new\" href=\"http://dhcpserver.sourceforge.net\">http://dhcpserver.sourceforge.net</td></tr></table>";
//const char bodyStart[] = "<body bgcolor=\"#cccccc\"><table width=640><tr><td align=\"center\"><font size=\"5\"><b>%s</b></font></td></tr><tr><td align=\"center\"><font size=\"5\">%s</font></td></tr></table>";
const data4 opData[] = {
{"SubnetMask", 1, 3, true },
{"TimeOffset", 2, 4, true },
{"Router", 3, 3, true },
{"TimeServer", 4, 3, true },
{"NameServer", 5, 3, true },
{"DomainServer", 6, 3, true },
{"LogServer", 7, 3, true },
{"QuotesServer", 8, 3, true },
{"LPRServer", 9, 3, true },
{"ImpressServer", 10, 3, true },
{"RLPServer", 11, 3, true },
{"Hostname", 12, 1, true },
{"BootFileSize", 13, 5, true },
{"MeritDumpFile", 14, 1, true },
{"DomainName", 15, 1, true },
{"SwapServer", 16, 3, true },
{"RootPath", 17, 1, true },
{"ExtensionFile", 18, 1, true },
{"ForwardOn/Off", 19, 7, true },
{"SrcRteOn/Off", 20, 7, true },
{"PolicyFilter", 21, 8, true },
{"MaxDGAssembly", 22, 5, true },
{"DefaultIPTTL", 23, 6, true },
{"MTUTimeout", 24, 4, true },
{"MTUPlateau", 25, 2, true },
{"MTUInterface", 26, 5, true },
{"MTUSubnet", 27, 7, true },
{"BroadcastAddress", 28, 3, true },
{"MaskDiscovery", 29, 7, true },
{"MaskSupplier", 30, 7, true },
{"RouterDiscovery", 31, 7, true },
{"RouterRequest", 32, 3, true },
{"StaticRoute", 33, 8, true },
{"Trailers", 34, 7, true },
{"ARPTimeout", 35, 4, true },
{"Ethernet", 36, 7, true },
{"DefaultTCPTTL", 37, 6, true },
{"KeepaliveTime", 38, 4, true },
{"KeepaliveData", 39, 7, true },
{"NISDomain", 40, 1, true },
{"NISServers", 41, 3, true },
{"NTPServers", 42, 3, true },
{"VendorSpecificInf", 43, 2, false},
{"NETBIOSNameSrv", 44, 3, true },
{"NETBIOSDistSrv", 45, 3, true },
{"NETBIOSNodeType", 46, 6, true },
{"NETBIOSScope", 47, 1, true },
{"XWindowFont", 48, 1, true },
{"XWindowManager", 49, 3, true },
{"AddressRequest", 50, 3, false},
{"AddressTime", 51, 4, true },
{"OverLoad", 52, 7, false},
{"DHCPMsgType", 53, 6, false},
{"DHCPServerId", 54, 3, false},
{"ParameterList", 55, 2, false},
{"DHCPMessage", 56, 1, false},
{"DHCPMaxMsgSize", 57, 5, false},
{"RenewalTime", 58, 4, true },
{"RebindingTime", 59, 4, true },
{"ClassId", 60, 1, true },
{"ClientId", 61, 2, false},
{"NetWareIPDomain", 62, 1, true },
{"NetWareIPOption", 63, 2, true },
{"NISDomainName", 64, 1, true },
{"NISServerAddr", 65, 3, true },
{"TFTPServerName", 66, 1, true },
{"BootFileOption", 67, 1, true },
{"HomeAgentAddrs", 68, 3, true },
{"SMTPServer", 69, 3, true },
{"POP3Server", 70, 3, true },
{"NNTPServer", 71, 3, true },
{"WWWServer", 72, 3, true },
{"FingerServer", 73, 3, true },
{"IRCServer", 74, 3, true },
{"StreetTalkServer", 75, 3, true },
{"STDAServer", 76, 3, true },
{"UserClass", 77, 1, false},
{"DirectoryAgent", 78, 1, true },
{"ServiceScope", 79, 1, true },
{"RapidCommit", 80, 2, false},
{"ClientFQDN", 81, 2, false},
{"RelayAgentInformation", 82, 2, false},
{"iSNS", 83, 1, true },
{"NDSServers", 85, 3, true },
{"NDSTreeName", 86, 1, true },
{"NDSContext", 87, 1, true },
{"LDAP", 95, 1, true },
{"PCode", 100, 1, true },
{"TCode", 101, 1, true },
{"NetInfoAddress", 112, 3, true },
{"NetInfoTag", 113, 1, true },
{"URL", 114, 1, true },
{"AutoConfig", 116, 7, true },
{"NameServiceSearch", 117, 2, true },
{"SubnetSelectionOption", 118, 3, true },
{"DomainSearch", 119, 1, true },
{"SIPServersDHCPOption", 120, 1, true },
// { "121", 121, 1 , true},
{"CCC", 122, 1, true },
{"TFTPServerIPaddress", 128, 3, true },
{"CallServerIPaddress", 129, 3, true },
{"DiscriminationString", 130, 1, true },
{"RemoteStatisticsServerIPAddress", 131, 3, true },
{"HTTPProxyPhone", 135, 3, true },
{"OPTION_CAPWAP_AC_V4", 138, 1, true },
{"OPTIONIPv4_AddressMoS", 139, 1, true },
{"OPTIONIPv4_FQDNMoS", 140, 1, true },
{"SIPUAServiceDomains", 141, 1, true },
{"OPTIONIPv4_AddressANDSF", 142, 1, true },
{"IPTelephone", 176, 1, true },
{"ConfigurationFile", 209, 1, true },
{"PathPrefix", 210, 1, true },
{"RebootTime", 211, 4, true },
{"OPTION_6RD", 212, 1, true },
{"OPTION_V4_ACCESS_DOMAIN", 213, 1, true },
{"BootFileName", 253, 1, true },
{"NextServer", 254, 3, true },
};
int dhcpd_main(int daemon, const char *pInifile, const char *pStatusFile, const char *pIfName) {
char logBuff[256] = "";
logBuff[0] = 0;
task_add_exit_event_handler(on_system_exit, nullptr);
#if 0
/*
char *ds = strrchr(argv[0], '/');
if (ds)
ds++;
else
ds = argv[0];
sprintf(tempbuff, "ps -e | grep \" %s$\" | awk '{ print $1 }'", ds, ds);
FILE *p = popen(tempbuff,"r");
if (p)
{
while (fgets(tempbuff, sizeof(tempbuff), p))
{
if (STR2INT(tempbuff) != getpid())
{
sprintf(logBuff, "Error: %s is already running, Pid = %s", ds, tempbuff);
break;
}
}
pclose(p);
}
*/
for (int i = 1; i < argc; i++) {
if (!strcasecmp(argv[i], "-v")) {
verbatim = true;
} else if (!strcmp(argv[i], "-i") && argc > i + 1 && argv[i + 1][0] != '-') {
myTrim(iniFile, argv[i + 1]);
i++;
} else if (!strcmp(argv[i], "-s") && argc > i + 1 && argv[i + 1][0] != '-') {
myTrim(leaFile, argv[i + 1]);
i++;
} else if (!strcmp(argv[i], "-l") && argc > i + 1 && argv[i + 1][0] != '-') {
myTrim(logFile, argv[i + 1]);
i++;
} else if (!strcmp(argv[i], "-n") && argc > i + 1 && argv[i + 1][0] != '-') {
myTrim(icoFile, argv[i + 1]);
i++;
} else if (!strncasecmp(argv[i], "-i", 2)) {
myTrim(iniFile, argv[i] + 2);
} else if (!strncasecmp(argv[i], "-s", 2)) {
myTrim(leaFile, argv[i] + 2);
} else if (!strncasecmp(argv[i], "-l", 2)) {
myTrim(logFile, argv[i] + 2);
} else if (!strncasecmp(argv[i], "-n", 2)) {
myTrim(icoFile, argv[i] + 2);
} else {
sprintf(logBuff, "Error: Invalid Argument %s", argv[i]);
}
}
if (!leaFile[0]) {
strcpy(leaFile, "/tmp/opendhcp.state");
}
if (!iniFile[0]) {
strcpy(iniFile, "/etc/opendhcp.ini");
}
#endif
verbatim = (daemon > 0);
if (pInifile && strlen(pInifile) > 0) {
strcpy(iniFile, pInifile);
} else {
strcpy(iniFile, "/etc/opendhcp.ini");
}
if (pStatusFile && strlen(pStatusFile) > 0) {
strcpy(leaFile, pStatusFile);
} else {
strcpy(leaFile, "/tmp/opendhcp.state");
}
if (pIfName && strlen(pIfName) > 0) {
strcpy(nicif, pIfName);
} else {
strcpy(nicif, "vxlan0");
}
strcpy(filePATH, iniFile);
if (strrchr(filePATH, '/')) {
char *fileExt = strrchr(filePATH, '/');
fileExt++;
*fileExt = 0;
}
if (verbatim) {
if (logBuff[0]) {
printf("%s\n", logBuff);
sleep(1);
exit(EXIT_FAILURE);
}
if (getuid()) {
printf("Error: Only root should run this program\n");
sleep(1);
exit(EXIT_FAILURE);
}
//printf("%i\n",sizeof(data7));
memset(&cfig, 0, sizeof(cfig));
cfig.ppid = getpid();
pthread_t threadId;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
int errcode = pthread_create(&threadId, &attr, init, nullptr);
pthread_attr_destroy(&attr);
if (errcode) {
printf("init thread Creation Failed");
sleep(1);
exit(EXIT_FAILURE);
}
while (true) {
FD_ZERO(&readfds);
tv.tv_sec = 20;
tv.tv_usec = 0;
if (!network.ready) {
sleep(1);
network.busy = false;
continue;
}
if (!network.dhcpConn[0].ready) {
sleep(1);
network.busy = false;
continue;
}
//Sleep(200000);
//debug("good");
network.busy = true;
if (network.httpConn.ready) {
FD_SET(network.httpConn.sock, &readfds);
}
if (network.dhcpListener.ready) {
FD_SET(network.dhcpListener.sock, &readfds);
}
for (int i = 0; i < MAX_SERVERS && network.dhcpConn[i].ready; i++) {
FD_SET(network.dhcpConn[i].sock, &readfds);
}
if (cfig.dhcpReplConn.ready) {
FD_SET(cfig.dhcpReplConn.sock, &readfds);
}
if (select(network.maxFD, &readfds, nullptr, nullptr, &tv)) {
t = time(nullptr);
if (network.httpConn.ready && FD_ISSET(network.httpConn.sock, &readfds)) {
auto *req = (data19 *)calloc(1, sizeof(data19));
if (req) {
req->sockLen = sizeof(req->remote);
req->sock = accept(network.httpConn.sock, (sockaddr *)&req->remote, &req->sockLen);
////errno = WSAGetLastError();
if (errno || req->sock == INVALID_SOCKET) {
sprintf(logBuff, "Accept Failed, Error %s", strerror(errno));
logDHCPMess(logBuff, 1);
free(req);
} else {
procHTTP(req);
}
} else {
sprintf(logBuff, "Memory Error");
logDHCPMess(logBuff, 1);
}
}
if (network.dhcpListener.ready && FD_ISSET(network.dhcpListener.sock, &readfds) &&
gdmess(&dhcpr, 255) && sdmess(&dhcpr)) {
alad(&dhcpr);
}
if (cfig.dhcpReplConn.ready && FD_ISSET(cfig.dhcpReplConn.sock, &readfds)) {
errno = 0;
dhcpr.sockLen = sizeof(dhcpr.remote);
dhcpr.bytes = (int)recvfrom(cfig.dhcpReplConn.sock,
dhcpr.raw,
sizeof(dhcpr.raw),
0,
(sockaddr *)&dhcpr.remote,
&dhcpr.sockLen);
////errno = WSAGetLastError();
if (errno || dhcpr.bytes <= 0) {
cfig.dhcpRepl = 0;
}
}
for (int i = 0; i < MAX_SERVERS && network.dhcpConn[i].ready; i++) {
if (FD_ISSET(network.dhcpConn[i].sock, &readfds) && gdmess(&dhcpr, i) && sdmess(&dhcpr)) {
alad(&dhcpr);
}
}
} else {
t = time(nullptr);
}
}
//printf("Here\n");
} else {
if (logBuff[0]) {
syslog(LOG_MAKEPRI(LOG_LOCAL1, LOG_CRIT), "%s", logBuff);
sleep(1);
exit(EXIT_FAILURE);
}
if (getuid()) {
syslog(LOG_MAKEPRI(LOG_LOCAL1, LOG_CRIT), "%s", "Only root should run this program");
sleep(1);
exit(EXIT_FAILURE);
}
/* Our process ID and Session ID */
pid_t pid, sid;
/* Fork off the parent process */
pid = fork();
if (pid < 0) {
exit(EXIT_FAILURE);
}
/* If we got a good PID, then
we can exit the parent process. */
if (pid > 0) {
exit(EXIT_SUCCESS);
}
/* Change the file mode mask */
umask(0);
/* Open any logs here */
/* Create a new SID for the child process */
sid = setsid();
if (sid < 0) {
/* Log the failure */
exit(EXIT_FAILURE);
}
/* Change the current working directory */
if ((chdir("/")) < 0) {
/* Log the failure */
exit(EXIT_FAILURE);
}
/* Close out the standard file descriptors */
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
/* Daemon-specific initialization goes here */
//printf("%i\n",sizeof(data7));
memset(&cfig, 0, sizeof(cfig));
cfig.ppid = getpid();
pthread_t threadId;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
int errcode = pthread_create(&threadId, &attr, init, nullptr);
pthread_attr_destroy(&attr);
if (errcode) {
syslog(LOG_MAKEPRI(LOG_LOCAL1, LOG_CRIT), "%s", "init thread Creation Failed");
sleep(1);
exit(EXIT_FAILURE);
}
//listDSNCache(0);
/* The Big Loop */
while (true) {
FD_ZERO(&readfds);
tv.tv_sec = 20;
tv.tv_usec = 0;
if (!network.ready) {
sleep(1);
network.busy = false;
continue;
}
if (!network.dhcpConn[0].ready) {
sleep(1);
network.busy = false;
continue;
}
//Sleep(200000);
//debug("good");
network.busy = true;
if (network.httpConn.ready) {
FD_SET(network.httpConn.sock, &readfds);
}
if (network.dhcpListener.ready) {
FD_SET(network.dhcpListener.sock, &readfds);
}
for (int i = 0; i < MAX_SERVERS && network.dhcpConn[i].ready; i++) {
FD_SET(network.dhcpConn[i].sock, &readfds);
}
if (cfig.dhcpReplConn.ready) {
FD_SET(cfig.dhcpReplConn.sock, &readfds);
}
if (select(network.maxFD, &readfds, nullptr, nullptr, &tv)) {
t = time(nullptr);
if (network.httpConn.ready && FD_ISSET(network.httpConn.sock, &readfds)) {
auto *req = (data19 *)calloc(1, sizeof(data19));
if (req) {
req->sockLen = sizeof(req->remote);
req->sock = accept(network.httpConn.sock, (sockaddr *)&req->remote, &req->sockLen);
////errno = WSAGetLastError();
if (errno || req->sock == INVALID_SOCKET) {
sprintf(logBuff, "Accept Failed, Error %s", strerror(errno));
logDHCPMess(logBuff, 1);
free(req);
} else {
procHTTP(req);
}
} else {
sprintf(logBuff, "Memory Error");
logDHCPMess(logBuff, 1);
}
}
if (network.dhcpListener.ready && FD_ISSET(network.dhcpListener.sock, &readfds) &&
gdmess(&dhcpr, 255) && sdmess(&dhcpr)) {
alad(&dhcpr);
}
if (cfig.dhcpReplConn.ready && FD_ISSET(cfig.dhcpReplConn.sock, &readfds)) {
errno = 0;
dhcpr.sockLen = sizeof(dhcpr.remote);
dhcpr.bytes = (int)recvfrom(cfig.dhcpReplConn.sock,
dhcpr.raw,
sizeof(dhcpr.raw),
0,
(sockaddr *)&dhcpr.remote,
&dhcpr.sockLen);
////errno = WSAGetLastError();
if (errno || dhcpr.bytes <= 0) {
cfig.dhcpRepl = 0;
}
}
for (int i = 0; i < MAX_SERVERS && network.dhcpConn[i].ready; i++) {
if (FD_ISSET(network.dhcpConn[i].sock, &readfds) && gdmess(&dhcpr, i) && sdmess(&dhcpr)) {
alad(&dhcpr);
}
}
} else {
t = time(nullptr);
}
}
}
closeConn();
if (cfig.dhcpReplConn.ready) {
close(cfig.dhcpReplConn.sock);
}
return 0;
}
void closeConn() {
for (int i = 0; i < MAX_SERVERS && network.dhcpConn[i].loaded; i++) {
if (network.dhcpConn[i].ready) {
close(network.dhcpConn[i].sock);
network.dhcpConn[i].ready = false;
}
}
if (network.dhcpListener.ready) {
close(network.dhcpListener.sock);
network.dhcpListener.ready = false;
}
if (network.httpConn.ready) {
close(network.httpConn.sock);
network.httpConn.ready = false;
}
}
void on_system_exit(void *p) {
char logBuff[256];
if (cfig.ppid == getpid()) {
kRunning = false;
network.ready = false;
//while (kRunning && network.busy)
// sleep(1);
sprintf(logBuff, "Closing Network Connections...");
logDHCPMess(logBuff, 1);
sleep(1);
closeConn();
if (cfig.dhcpReplConn.ready) {
close(cfig.dhcpReplConn.sock);
}
sprintf(logBuff, "OpenDHCP Server Stopped !\n");
logDHCPMess(logBuff, 1);
close(cfig.fixedSocket);
sleep(1);
}
}
//bool chkQu(char *query) {
// if (strlen(query) >= UCHAR_MAX) {
// return false;
// }
//
// while (true) {
// char *dp = strchr(query, '.');
// if (dp) {
// MYWORD size = dp - query;
// if (size >= 64) {
// return false;
// }
// query += (size + 1);
// } else if (strlen(query) >= 64) {
// return false;
// } else {
// return true;
// }
// }
//}
MYWORD fUShort(void *raw) {
return ntohs(*((MYWORD *)raw));
}
MYDWORD fULong(void *raw) {
return ntohl(*((MYDWORD *)raw));
}
MYDWORD fIP(void *raw) {
return (*((MYDWORD *)raw));
}
MYDWORD fUInt(void *raw) {
return ntohl(*((MYDWORD *)raw));
}
MYBYTE pUShort(void *raw, MYWORD data) {
*((MYWORD *)raw) = htons(data);
return sizeof(MYWORD);
}
MYBYTE pULong(void *raw, MYDWORD data) {
*((MYDWORD *)raw) = htonl(data);
return sizeof(MYDWORD);
}
MYBYTE pIP(void *raw, MYDWORD data) {
*((MYDWORD *)raw) = data;
return sizeof(MYDWORD);
}
MYBYTE pUInt(void *raw, MYDWORD data) {
*((MYDWORD *)raw) = htonl(data);
return sizeof(MYDWORD);
}
void prepareUserHtmlRespStatus(data19 *req) {
//debug("sendStatus");
char ipbuff[16];
char extbuff[16];
char logBuff[512];
char tempbuff[512];
dhcpMap::iterator p;
MYDWORD iip = 0;
data7 *dhcpEntry = nullptr;
//data7 *cache = nullptr;
//printf("%d=%d\n", dhcpCache.size(), cfig.dhcpSize);
req->memSize = (int)(2048 + (135 * dhcpCache.size()) + (cfig.dhcpSize * 26));
req->dp = (char *)calloc(1, req->memSize);
if (!req->dp) {
sprintf(logBuff, "Memory Error");
logDHCPMess(logBuff, 1);
closesocket(req->sock);
free(req);
return;
}
char *fp = req->dp;
char *maxData = req->dp + (req->memSize - 512);
//tm *ttm = gmtime(&t);
//strftime(tempbuff, sizeof(tempbuff), "%a, %d %b %Y %H:%M:%S GMT", ttm);
//fp += sprintf(fp, send200, tempbuff, tempbuff);
//fp += sprintf(fp, send200);
//char *contentStart = fp;
fp += sprintf(fp, htmlStart, htmlTitle);
if (cfig.replication == 1) {
fp += sprintf(fp, bodyStart, sVersion, cfig.servername, "(Primary)", MY_EXE_SIZE);
} else if (cfig.replication == 2) {
fp += sprintf(fp, bodyStart, sVersion, cfig.servername, "(Secondary)", MY_EXE_SIZE);
} else {
fp += sprintf(fp, bodyStart, sVersion, cfig.servername, "", MY_EXE_SIZE);
}
fp += sprintf(fp, "\n<table border=\"1\" cellpadding=\"1\" width=\"100%%\" bgcolor=\"#b8b8b8\">\n");
if (cfig.dhcpRepl > t) {
fp += sprintf(fp, "<tr><th colspan=\"5\"><font size=\"5\"><i>Active Leases</i></font></th></tr>\n");
fp += sprintf(fp,
"<tr><th>Mac Address</th><th>IP</th><th>Lease Expiry</th><th>Hostname (first 20 "
"chars)</th><th>Server</th></tr>\n");
} else {
fp += sprintf(fp, "<tr><th colspan=\"4\"><font size=\"5\"><i>Active Leases</i></font></th></tr>\n");
fp += sprintf(
fp,
"<tr><th>Mac Address</th><th>IP</th><th>Lease Expiry</th><th>Hostname (first 20 chars)</th></tr>\n");
}
for (p = dhcpCache.begin(); kRunning && p != dhcpCache.end() && fp < maxData; p++) {
//if ((dhcpEntry = p->second) && dhcpEntry->display)
if ((dhcpEntry = p->second) && dhcpEntry->display && dhcpEntry->expiry >= t) {
fp += sprintf(fp, "<tr>");
fp += sprintf(fp, td200, dhcpEntry->mapname); // mapname is MAC address
fp += sprintf(fp, td200, IP2String(tempbuff, dhcpEntry->ip));
if (dhcpEntry->expiry >= MY_MAX_TIME) {
fp += sprintf(fp, td200, "Infinity");
} else {
tm *ttm = localtime(&dhcpEntry->expiry);
strftime(tempbuff, sizeof(tempbuff), "%d-%b-%y %X", ttm);
fp += sprintf(fp, tdnowrap200, tempbuff);
}
if (dhcpEntry->hostname[0]) {
strcpy(tempbuff, dhcpEntry->hostname);
tempbuff[20] = 0;
fp += sprintf(fp, td200, tempbuff);
} else {
fp += sprintf(fp, td200, "&nbsp;");
}
if (cfig.dhcpRepl > t) {
if (dhcpEntry->local && cfig.replication == 1) {
fp += sprintf(fp, td200, "Primary");
} else if (dhcpEntry->local && cfig.replication == 2) {
fp += sprintf(fp, td200, "Secondary");
} else if (cfig.replication == 1) {
fp += sprintf(fp, td200, "Secondary");
} else {
fp += sprintf(fp, td200, "Primary");
}
}
fp += sprintf(fp, "</tr>\n");
}
}
fp += sprintf(fp, "</table>\n<br>\n<table border=\"1\" cellpadding=\"1\" width=\"100%%\" bgcolor=\"#b8b8b8\">\n");
fp += sprintf(fp, "<tr><th colspan=\"4\"><font size=\"5\"><i>Free Dynamic Leases</i></font></th></tr>\n");
fp += sprintf(fp,
"<tr><td><b>DHCP Range</b></td><td><b>Mask</b></td><td align=\"right\"><b>Available "
"Leases</b></td><td align=\"right\"><b>Free Leases</b></td></tr>\n");
for (char rangeInd = 0; kRunning && rangeInd < cfig.rangeCount && fp < maxData; rangeInd++) {
MYWORD ipused = 0;
MYWORD ipfree = 0;
MYWORD ind = 0;
for (MYDWORD ip = cfig.dhcpRanges[rangeInd].rangeStart; ip <= cfig.dhcpRanges[rangeInd].rangeEnd; ip++, ind++) {
if (cfig.dhcpRanges[rangeInd].expiry[ind] != MY_MAX_TIME) {
if (cfig.dhcpRanges[rangeInd].expiry[ind] < t) {
ipfree++;
} else {
ipused++;
}
}
}
IP2String(tempbuff, ntohl(cfig.dhcpRanges[rangeInd].rangeStart));
IP2String(ipbuff, ntohl(cfig.dhcpRanges[rangeInd].rangeEnd));
IP2String(extbuff, cfig.dhcpRanges[rangeInd].mask);
fp += sprintf(fp,
"<tr><td nowrap>%s - %s</td><td nowrap>%s</td><td align=\"right\">%i</td><td "
"align=\"right\">%i</td></tr>\n",
tempbuff,
ipbuff,
extbuff,
(ipused + ipfree),
ipfree);
}
fp += sprintf(fp, "</table>\n<br>\n<table border=\"1\" width=\"100%%\" cellpadding=\"1\" bgcolor=\"#b8b8b8\">\n");
fp += sprintf(fp, "<tr><th colspan=\"4\"><font size=\"5\"><i>Free Static Leases</i></font></th></tr>\n");
fp += sprintf(fp, "<tr><th>Mac Address</th><th>IP</th><th>Mac Address</th><th>IP</th></tr>\n");
MYBYTE colNum = 0;
for (p = dhcpCache.begin(); kRunning && p != dhcpCache.end() && fp < maxData; p++) {
if ((dhcpEntry = p->second) && dhcpEntry->fixed && dhcpEntry->expiry < t) {
if (!colNum) {
fp += sprintf(fp, "<tr>");
colNum = 1;
} else if (colNum == 1) {
colNum = 2;
} else if (colNum == 2) {
fp += sprintf(fp, "</tr>\n<tr>");
colNum = 1;
}
fp += sprintf(fp, td200, dhcpEntry->mapname);
fp += sprintf(fp, td200, IP2String(tempbuff, dhcpEntry->ip));
}
}
if (colNum) {
fp += sprintf(fp, "</tr>\n");
}
fp += sprintf(fp, "</table></td></tr></table>\n</body>\n</html>");
//MYBYTE x = sprintf(tempbuff, "%u", (fp - contentStart));
//memcpy((contentStart - 12), tempbuff, x);
req->bytes = (int)(fp - req->dp);
// pthread_t threadId;
// pthread_attr_t attr;
// pthread_attr_init(&attr);
// pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
// int errcode = pthread_create(&threadId, &attr, sendHTTP, (void *)req);
// pthread_attr_destroy(&attr);
}
void procHTTP(data19 *req) {
#if 0
char logBuff[256];
char tempbuff[512];
req->ling.l_onoff = 1; //0 = off (l_linger ignored), nonzero = on
req->ling.l_linger = 30; //0 = discard data, nonzero = wait for data sent
setsockopt(req->sock, SOL_SOCKET, SO_LINGER, (const char *)&req->ling, sizeof(req->ling));
timeval tv1 {};
fd_set readfds1;
FD_ZERO(&readfds1);
tv1.tv_sec = 1;
tv1.tv_usec = 0;
FD_SET(req->sock, &readfds1);
if (!select((req->sock + 1), &readfds1, nullptr, nullptr, &tv1)) {
sprintf(logBuff, "HTTP Client %s, Message Receive failed", IP2String(tempbuff, req->remote.sin_addr.s_addr));
logDHCPMess(logBuff, 1);
closesocket(req->sock);
free(req);
return;
}
char buffer[2048];
req->bytes = (int)recv(req->sock, buffer, sizeof(buffer), 0);
//errno = WSAGetLastError();
if ((verbatim || cfig.dhcpLogLevel >= 1) && (errno || req->bytes <= 0)) {
sprintf(logBuff,
"HTTP Client %s, Message Receive failed, WSAError %d",
IP2String(tempbuff, req->remote.sin_addr.s_addr),
errno);
logDHCPMess(logBuff, 1);
closesocket(req->sock);
free(req);
return;
}
if (cfig.httpClients[0] && !findServer(cfig.httpClients, 8, req->remote.sin_addr.s_addr)) {
if (verbatim || cfig.dhcpLogLevel >= 2) {
sprintf(logBuff, "HTTP Client %s, Access Denied", IP2String(tempbuff, req->remote.sin_addr.s_addr));
logDHCPMess(logBuff, 2);
}
req->dp = (char *)calloc(1, sizeof(send403));
req->bytes = sprintf(req->dp, send403);
return;
}
if (verbatim || cfig.dhcpLogLevel >= 2) {
sprintf(logBuff, "HTTP Client %s, Request Processed", IP2String(tempbuff, req->remote.sin_addr.s_addr));
logDHCPMess(logBuff, 2);
//printf("%s\n", buffer);
}
buffer[sizeof(buffer) - 1] = 0;
char *fp = nullptr;
char *end = strchr(buffer, '\n');
if (end && end > buffer && (*(end - 1) == '\r')) {
*(end - 1) = 0;
if (myTokenize(buffer, buffer, " ", true) > 1) {
fp = myGetToken(buffer, 1);
}
}
if (fp && !strcasecmp(fp, "/")) {
sendStatus(req);
} else if (fp && icoSize > 0 && !strcasecmp(fp, "/favicon.ico")) {
strcpy(req->contentType, "img");
req->bytes = icoSize;
req->dp = (char *)calloc(1, icoSize);
memcpy(req->dp, icoString, icoSize);
pthread_t threadId;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
int errcode = pthread_create(&threadId, &attr, sendHTTP, (void *)req);
pthread_attr_destroy(&attr);
return;
}
// else if (fp && !strcasecmp(fp, "/scopestatus"))
// sendScopeStatus(req);
else {
if (fp && (verbatim || cfig.dhcpLogLevel >= 2)) {
sprintf(logBuff, "HTTP Client %s, %s not found", IP2String(tempbuff, req->remote.sin_addr.s_addr), fp);
logDHCPMess(logBuff, 2);
} else if (verbatim || cfig.dhcpLogLevel >= 2) {
sprintf(logBuff, "HTTP Client %s, Invalid request", IP2String(tempbuff, req->remote.sin_addr.s_addr));
logDHCPMess(logBuff, 2);
}
req->dp = (char *)calloc(1, sizeof(send404));
req->bytes = sprintf(req->dp, send404);
pthread_t threadId;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
int errcode = pthread_create(&threadId, &attr, sendHTTP, (void *)req);
pthread_attr_destroy(&attr);
return;
}
#endif
}
#if 0
void sendStatus(data19 *req) {
char ipbuff[16];
char extbuff[16];
char logBuff[512];
char tempbuff[512];
dhcpMap::iterator p;
MYDWORD iip = 0;
data7 *dhcpEntry = nullptr;
//data7 *cache = nullptr;
//sprintf(tempbuff, "%d=%d", dhcpCache.size(), cfig.dhcpSize);
req->memSize = 2048 + (135 * dhcpCache.size()) + (cfig.dhcpSize * 26);
req->dp = (char *)calloc(1, req->memSize);
if (!req->dp) {
sprintf(logBuff, "Memory Error");
logDHCPMess(logBuff, 1);
closesocket(req->sock);
free(req);
return;
}
char *fp = req->dp;
char *maxData = req->dp + (req->memSize - 512);
//tm *ttm = gmtime(&t);
//strftime(tempbuff, sizeof(tempbuff), "%a, %d %b %Y %H:%M:%S GMT", ttm);
//fp += sprintf(fp, send200, tempbuff, tempbuff);
//fp += sprintf(fp, send200);
//char *contentStart = fp;
fp += sprintf(fp, htmlStart, htmlTitle);
//const char bodyStart[] = "<body bgcolor=\"#cccccc\"><table border=\"0\"><tr><td>\n<table width=\"100%%\" border=\"0\"><tr><td colspan=\"2\" align=\"center\"><font size=\"5\"><b>%s</b></font></td></tr><tr><td align=\"left\">Server Name: %s%s</td><td align=\"right\"><a target=\"_new\" href=\"http://dhcp-dns-server.sourceforge.net\">http://dhcp-dns-server.sourceforge.net</td></tr></table>";
if (cfig.replication == 1) {
fp += sprintf(fp, bodyStart, sVersion, cfig.servername, "(Primary)", MY_EXE_SIZE);
} else if (cfig.replication == 2) {
fp += sprintf(fp, bodyStart, sVersion, cfig.servername, "(Secondary)", MY_EXE_SIZE);
} else {
fp += sprintf(fp, bodyStart, sVersion, cfig.servername, "", MY_EXE_SIZE);
}
//fp += sprintf(fp, bodyStart, sVersion, cfig.servername);
fp += sprintf(fp, "\n<table border=\"1\" cellpadding=\"1\" width=\"100%%\" bgcolor=\"#b8b8b8\">\n");
if (cfig.dhcpRepl > t) {
fp += sprintf(fp, "<tr><th colspan=\"5\"><font size=\"5\"><i>Active Leases</i></font></th></tr>\n");
fp += sprintf(fp,
"<tr><th>Mac Address</th><th>IP</th><th>Lease Expiry</th><th>Hostname (first 20 "
"chars)</th><th>Server</th></tr>\n");
} else {
fp += sprintf(fp, "<tr><th colspan=\"4\"><font size=\"5\"><i>Active Leases</i></font></th></tr>\n");
fp += sprintf(
fp,
"<tr><th>Mac Address</th><th>IP</th><th>Lease Expiry</th><th>Hostname (first 20 chars)</th></tr>\n");
}
for (p = dhcpCache.begin(); kRunning && p != dhcpCache.end() && fp < maxData; p++) {
//if ((dhcpEntry = p->second) && dhcpEntry->display)
if ((dhcpEntry = p->second) && dhcpEntry->display && dhcpEntry->expiry >= t) {
fp += sprintf(fp, "<tr>");
fp += sprintf(fp, td200, dhcpEntry->mapname);
fp += sprintf(fp, td200, IP2String(tempbuff, dhcpEntry->ip));
if (dhcpEntry->expiry >= MY_MAX_TIME) {
fp += sprintf(fp, td200, "Infinity");
} else {
tm *ttm = localtime(&dhcpEntry->expiry);
strftime(tempbuff, sizeof(tempbuff), "%d-%b-%y %X", ttm);
fp += sprintf(fp, tdnowrap200, tempbuff);
}
if (dhcpEntry->hostname[0]) {
strcpy(tempbuff, dhcpEntry->hostname);
tempbuff[20] = 0;
fp += sprintf(fp, td200, tempbuff);
} else {
fp += sprintf(fp, td200, "&nbsp;");
}
if (cfig.dhcpRepl > t) {
if (dhcpEntry->local && cfig.replication == 1) {
fp += sprintf(fp, td200, "Primary");
} else if (dhcpEntry->local && cfig.replication == 2) {
fp += sprintf(fp, td200, "Secondary");
} else if (cfig.replication == 1) {
fp += sprintf(fp, td200, "Secondary");
} else {
fp += sprintf(fp, td200, "Primary");
}
}
fp += sprintf(fp, "</tr>\n");
}
}
fp += sprintf(fp, "</table>\n<br>\n<table border=\"1\" cellpadding=\"1\" width=\"100%%\" bgcolor=\"#b8b8b8\">\n");
fp += sprintf(fp, "<tr><th colspan=\"4\"><font size=\"5\"><i>Free Dynamic Leases</i></font></th></tr>\n");
fp += sprintf(fp,
"<tr><td><b>DHCP Range</b></td><td><b>Mask</b></td><td align=\"right\"><b>Available "
"Leases</b></td><td align=\"right\"><b>Free Leases</b></td></tr>\n");
for (char rangeInd = 0; kRunning && rangeInd < cfig.rangeCount && fp < maxData; rangeInd++) {
MYWORD ipused = 0;
MYWORD ipfree = 0;
MYWORD ind = 0;
for (MYDWORD i = cfig.dhcpRanges[rangeInd].rangeStart; i <= cfig.dhcpRanges[rangeInd].rangeEnd; i++, ind++) {
if (cfig.dhcpRanges[rangeInd].expiry[ind] != MY_MAX_TIME) {
if (cfig.dhcpRanges[rangeInd].expiry[ind] < t) {
ipfree++;
} else {
ipused++;
}
}
}
IP2String(tempbuff, ntohl(cfig.dhcpRanges[rangeInd].rangeStart));
IP2String(ipbuff, ntohl(cfig.dhcpRanges[rangeInd].rangeEnd));
IP2String(extbuff, cfig.dhcpRanges[rangeInd].mask);
fp += sprintf(fp,
"<tr><td nowrap>%s - %s</td><td nowrap>%s</td><td align=\"right\">%i</td><td "
"align=\"right\">%i</td></tr>\n",
tempbuff,
ipbuff,
extbuff,
(ipused + ipfree),
ipfree);
}
fp += sprintf(fp, "</table>\n<br>\n<table border=\"1\" width=\"100%%\" cellpadding=\"1\" bgcolor=\"#b8b8b8\">\n");
fp += sprintf(fp, "<tr><th colspan=\"4\"><font size=\"5\"><i>Free Static Leases</i></font></th></tr>\n");
fp += sprintf(fp, "<tr><th>Mac Address</th><th>IP</th><th>Mac Address</th><th>IP</th></tr>\n");
MYBYTE colNum = 0;
for (p = dhcpCache.begin(); kRunning && p != dhcpCache.end() && fp < maxData; p++) {
if ((dhcpEntry = p->second) && dhcpEntry->fixed && dhcpEntry->expiry < t) {
if (!colNum) {
fp += sprintf(fp, "<tr>");
colNum = 1;
} else if (colNum == 1) {
colNum = 2;
} else if (colNum == 2) {
fp += sprintf(fp, "</tr>\n<tr>");
colNum = 1;
}
fp += sprintf(fp, td200, dhcpEntry->mapname);
fp += sprintf(fp, td200, IP2String(tempbuff, dhcpEntry->ip));
}
}
if (colNum) {
fp += sprintf(fp, "</tr>\n");
}
fp += sprintf(fp, "</table></td></tr></table>\n</body>\n</html>");
//MYBYTE x = sprintf(tempbuff, "%u", (fp - contentStart));
//memcpy((contentStart - 12), tempbuff, x);
strcpy(req->contentType, "text/html");
req->bytes = fp - req->dp;
pthread_t threadId;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
int errcode = pthread_create(&threadId, &attr, sendHTTP, (void *)req);
pthread_attr_destroy(&attr);
return;
}
#endif
/*
void sendScopeStatus(data19 *req)
{
MYBYTE rangeCount = 0;
req->memSize = 1536 + (150 * cfig.rangeCount);
req->dp = (char*)calloc(1, req->memSize);
if (!req->dp)
{
sprintf(logBuff, "Memory Error");
logDHCPMess(logBuff, 1);
closesocket(req->sock);
free(req);
return;
}
char *fp = req->dp;
char *maxData = req->dp + (req->memSize - 512);
tm *ttm = gmtime(&t);
strftime(tempbuff, sizeof(tempbuff), "%a, %d %b %Y %H:%M:%S GMT", ttm);
fp += sprintf(fp, send200, tempbuff, tempbuff);
char *contentStart = fp;
fp += sprintf(fp, htmlStart, htmlTitle);
fp += sprintf(fp, bodyStart, sVersion);
fp += sprintf(fp, "<table border=\"1\" cellpadding=\"1\" width=\"640\" bgcolor=\"#b8b8b8\">\n");
fp += sprintf(fp, "<tr><th colspan=\"4\"><font size=\"5\"><i>Scope Status</i></font></th></tr>\n");
fp += sprintf(fp, "<tr><td><b>DHCP Range</b></td><td align=\"right\"><b>IPs Used</b></td><td align=\"right\"><b>IPs Free</b></td><td align=\"right\"><b>%% Free</b></td></tr>\n");
MYBYTE colNum = 0;
for (char rangeInd = 0; kRunning && rangeInd < cfig.rangeCount && fp < maxData; rangeInd++)
{
float ipused = 0;
float ipfree = 0;
int ind = 0;
for (MYDWORD iip = cfig.dhcpRanges[rangeInd].rangeStart; iip <= cfig.dhcpRanges[rangeInd].rangeEnd; iip++, ind++)
{
if (cfig.dhcpRanges[rangeInd].expiry[ind] > t)
ipused++;
else
ipfree++;
}
IP2String(tempbuff, ntohl(cfig.dhcpRanges[rangeInd].rangeStart));
IP2String(extbuff, ntohl(cfig.dhcpRanges[rangeInd].rangeEnd));
fp += sprintf(fp, "<tr><td>%s - %s</td><td align=\"right\">%5.0f</td><td align=\"right\">%5.0f</td><td align=\"right\">%2.2f</td></tr>\n", tempbuff, extbuff, ipused, ipfree, ((ipfree * 100)/(ipused + ipfree)));
}
fp += sprintf(fp, "</table>\n</body>\n</html>");
memcpy((contentStart - 12), tempbuff, sprintf(tempbuff, "%u", (fp - contentStart)));
req->bytes = fp - req->dp;
pthread_t threadId;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
int errcode = pthread_create(&threadId, &attr, sendHTTP, (void*)req);
pthread_attr_destroy(&attr);
return;
}
*/
void *sendHTTP(void *lpParam) {
auto *req = (data19 *)lpParam;
//char logBuff[512];
//sprintf(logBuff, "sendHTTP memsize=%d bytes=%d", req->memSize, req->bytes);
char *dp = req->dp;
timeval tv1 {};
fd_set writefds1;
int sent = 0;
bool sendheader = true;
while (kRunning && req->bytes > 0) {
tv1.tv_sec = 5;
tv1.tv_usec = 0;
FD_ZERO(&writefds1);
FD_SET(req->sock, &writefds1);
if (select((req->sock + 1), nullptr, &writefds1, nullptr, &tv1)) {
if (sendheader) {
char header[256];
sprintf(header, send200, req->contentType, req->bytes);
send(req->sock, header, strlen(header), 0);
sendheader = false;
} else if (req->bytes > 1024) {
sent = (int)send(req->sock, dp, 1024, 0);
} else if (req->bytes > 0) {
sent = (int)send(req->sock, dp, req->bytes, 0);
} else {
break;
}
//errno = WSAGetLastError();
if (errno || sent < 0) {
break;
}
dp += sent;
req->bytes -= sent;
} else {
break;
}
}
//Sleep(10*1000);
//shutdown(req->sock, 2);
closesocket(req->sock);
free(req->dp);
free(req);
pthread_exit(nullptr);
}
bool checkRange(data17 *rangeData, char rangeInd) {
//debug("checkRange");
if (!cfig.hasFilter) {
return true;
}
MYBYTE rangeSetInd = cfig.dhcpRanges[rangeInd].rangeSetInd;
data14 *rangeSet = &cfig.rangeSet[rangeSetInd];
//printf("checkRange entering, rangeInd=%i rangeSetInd=%i\n", rangeInd, rangeSetInd);
//printf("checkRange entered, macFound=%i vendFound=%i userFound=%i\n", macFound, vendFound, userFound);
if ((!rangeData->macFound && !rangeSet->macSize[0]) || (rangeData->macFound && rangeData->macArray[rangeSetInd])) {
if ((!rangeData->vendFound && !rangeSet->vendClassSize[0]) ||
(rangeData->vendFound && rangeData->vendArray[rangeSetInd])) {
if ((!rangeData->userFound && !rangeSet->userClassSize[0]) ||
(rangeData->userFound && rangeData->userArray[rangeSetInd])) {
if ((!rangeData->subnetFound && !rangeSet->subnetIP[0]) ||
(rangeData->subnetFound && rangeData->subnetArray[rangeSetInd])) {
return true;
}
}
}
}
//printf("checkRange, returning false rangeInd=%i rangeSetInd=%i\n", rangeInd, rangeSetInd);
return false;
}
bool checkIP(data9 *req, data17 *rangeData, MYDWORD ip) {
MYDWORD rangeStart;
MYDWORD rangeEnd;
char rangeInd = (char)(getRangeInd(ip) & 0xFF);
if (rangeInd < 0) {
return false;
}
if (!checkRange(rangeData, rangeInd)) {
return false;
}
MYWORD ind = getIndex(rangeInd, ip);
data13 *range = &cfig.dhcpRanges[rangeInd];
data7 *dhcpEntry = range->dhcpEntry[ind];
if ((req->dhcpEntry != dhcpEntry && range->expiry[ind] > t) or range->expiry[ind] == INT_MAX) {
return false;
}
if (req->subnetIP) {
if (cfig.rangeSet[range->rangeSetInd].subnetIP[0]) {
rangeStart = range->rangeStart;
rangeEnd = range->rangeEnd;
} else {
calcRangeLimits(req->subnetIP, range->mask, &rangeStart, &rangeEnd);
if (rangeStart < range->rangeStart) {
rangeStart = range->rangeStart;
}
if (rangeEnd > range->rangeEnd) {
rangeEnd = range->rangeEnd;
}
}
if (htonl(ip) >= rangeStart && htonl(ip) <= rangeEnd) {
return true;
}
} else {
calcRangeLimits(network.dhcpConn[req->sockInd].server, range->mask, &rangeStart, &rangeEnd);
if (rangeStart < range->rangeStart) {
rangeStart = range->rangeStart;
}
if (rangeEnd > range->rangeEnd) {
rangeEnd = range->rangeEnd;
}
if (htonl(ip) >= rangeStart && htonl(ip) <= rangeEnd) {
return true;
}
}
return false;
}
MYDWORD resad(data9 *req) {
//debug("resad");
char logBuff[512];
char tempbuff[512];
if (req->dhcpp.header.bp_giaddr) {
lockIP(req->dhcpp.header.bp_giaddr);
lockIP(req->remote.sin_addr.s_addr);
}
req->dhcpEntry = findDHCPEntry(req->chaddr);
if (req->dhcpEntry && req->dhcpEntry->fixed) {
if (req->dhcpEntry->ip) {
setTempLease(req->dhcpEntry);
return req->dhcpEntry->ip;
} else {
if (verbatim || cfig.dhcpLogLevel) {
sprintf(logBuff,
"Static DHCP Host %s (%s) has No IP, DHCPDISCOVER ignored",
req->chaddr,
req->hostname);
logDHCPMess(logBuff, 1);
}
return 0;
}
}
MYDWORD rangeStart = 0;
MYDWORD rangeEnd = 0;
MYDWORD iipNew = 0;
MYDWORD iipExp = 0;
bool rangeFound = false;
data17 rangeData {};
memset(&rangeData, 0, sizeof(data17));
if (cfig.hasFilter) {
for (MYBYTE rangeSetInd = 0; rangeSetInd < MAX_RANGE_SETS && cfig.rangeSet[rangeSetInd].active; rangeSetInd++) {
data14 *rangeSet = &cfig.rangeSet[rangeSetInd];
for (MYBYTE i = 0; i < MAX_RANGE_FILTERS && rangeSet->macSize[i]; i++) {
//printf("%s\n", hex2String(tempbuff, rangeSet->macStart[i], rangeSet->macSize[i]));
//printf("%s\n", hex2String(tempbuff, rangeSet->macEnd[i], rangeSet->macSize[i]));
if (memcmp(req->dhcpp.header.bp_chaddr, rangeSet->macStart[i], rangeSet->macSize[i]) >= 0 &&
memcmp(req->dhcpp.header.bp_chaddr, rangeSet->macEnd[i], rangeSet->macSize[i]) <= 0) {
rangeData.macArray[rangeSetInd] = 1;
rangeData.macFound = true;
//printf("mac Found, rangeSetInd=%i\n", rangeSetInd);
break;
}
}
for (MYBYTE i = 0; i < MAX_RANGE_FILTERS && req->vendClass.size && rangeSet->vendClassSize[i]; i++) {
if (rangeSet->vendClassSize[i] == req->vendClass.size &&
!memcmp(req->vendClass.value, rangeSet->vendClass[i], rangeSet->vendClassSize[i])) {
rangeData.vendArray[rangeSetInd] = 1;
rangeData.vendFound = true;
//printf("vend Found, rangeSetInd=%i\n", rangeSetInd);
break;
}
}
for (MYBYTE i = 0; i < MAX_RANGE_FILTERS && req->userClass.size && rangeSet->userClassSize[i]; i++) {
if (rangeSet->userClassSize[i] == req->userClass.size &&
!memcmp(req->userClass.value, rangeSet->userClass[i], rangeSet->userClassSize[i])) {
rangeData.userArray[rangeSetInd] = 1;
rangeData.userFound = true;
//printf("user Found, rangeSetInd=%i\n", rangeSetInd);
break;
}
}
for (MYBYTE i = 0; i < MAX_RANGE_FILTERS && req->subnetIP && rangeSet->subnetIP[i]; i++) {
if (req->subnetIP == rangeSet->subnetIP[i]) {
rangeData.subnetArray[rangeSetInd] = 1;
rangeData.subnetFound = true;
//printf("subnet Found, rangeSetInd=%i\n", rangeSetInd);
break;
}
}
}
}
// printArray("macArray", (char*)cfig.macArray);
// printArray("vendArray", (char*)cfig.vendArray);
// printArray("userArray", (char*)cfig.userArray);
if (!iipNew && req->reqIP && checkIP(req, &rangeData, req->reqIP)) {
iipNew = ntohl(req->reqIP);
}
if (!iipNew && req->dhcpEntry && req->dhcpEntry->ip && checkIP(req, &rangeData, req->dhcpEntry->ip)) {
iipNew = ntohl(req->dhcpEntry->ip);
}
for (char k = 0; !iipNew && k < cfig.rangeCount; k++) {
data13 *range = &cfig.dhcpRanges[k];
if (checkRange(&rangeData, k)) {
if (!cfig.rangeSet[range->rangeSetInd].subnetIP[0]) {
if (req->subnetIP) {
calcRangeLimits(req->subnetIP, range->mask, &rangeStart, &rangeEnd);
} else {
calcRangeLimits(network.dhcpConn[req->sockInd].server,
network.dhcpConn[req->sockInd].mask,
&rangeStart,
&rangeEnd);
}
if (rangeStart < range->rangeStart) {
rangeStart = range->rangeStart;
}
if (rangeEnd > range->rangeEnd) {
rangeEnd = range->rangeEnd;
}
} else {
rangeStart = range->rangeStart;
rangeEnd = range->rangeEnd;
}
if (rangeStart <= rangeEnd) {
//sprintf(logBuff, "Start=%u End=%u", rangeStart, rangeEnd);
//logDHCPMess(logBuff, 1);
rangeFound = true;
if (cfig.replication == 2) {
for (MYDWORD m = rangeEnd; m >= rangeStart; m--) {
unsigned int ind = m - range->rangeStart;
if (!range->expiry[ind]) {
iipNew = m;
break;
} else if (!iipExp && range->expiry[ind] < t) {
iipExp = m;
}
}
} else {
for (MYDWORD m = rangeStart; m <= rangeEnd; m++) {
unsigned int ind = m - range->rangeStart;
//sprintf(logBuff, "Ind=%u Exp=%u", m, range->expiry[ind]);
//logDHCPMess(logBuff, 1);
if (!range->expiry[ind]) {
iipNew = m;
break;
} else if (!iipExp && range->expiry[ind] < t) {
iipExp = m;
}
}
}
}
}
}
//sprintf(logBuff, "New=%u Old=%u", iipNew, iipExp);
//logDHCPMess(logBuff, 1);
if (!iipNew && iipExp) {
iipNew = iipExp;
}
if (iipNew) {
if (!req->dhcpEntry) {
memset(&lump, 0, sizeof(data71));
lump.cacheType = CTYPE_DHCP_ENTRY;
lump.mapname = req->chaddr;
lump.hostname = req->hostname;
req->dhcpEntry = createCache(&lump);
if (!req->dhcpEntry) {
return 0;
}
dhcpCache[req->dhcpEntry->mapname] = req->dhcpEntry;
}
req->dhcpEntry->ip = htonl(iipNew);
req->dhcpEntry->rangeInd = getRangeInd(req->dhcpEntry->ip);
req->dhcpEntry->subnetFlg = !!req->subnetIP;
setTempLease(req->dhcpEntry);
return req->dhcpEntry->ip;
}
if (verbatim || cfig.dhcpLogLevel) {
if (rangeFound) {
if (req->dhcpp.header.bp_giaddr) {
sprintf(logBuff,
"No free leases for DHCPDISCOVER for %s (%s) from RelayAgent %s",
req->chaddr,
req->hostname,
IP2String(tempbuff, req->dhcpp.header.bp_giaddr));
} else {
sprintf(logBuff,
"No free leases for DHCPDISCOVER for %s (%s) from interface %s",
req->chaddr,
req->hostname,
IP2String(tempbuff, network.dhcpConn[req->sockInd].server));
}
} else {
if (req->dhcpp.header.bp_giaddr) {
sprintf(logBuff,
"No Matching DHCP Range for DHCPDISCOVER for %s (%s) from RelayAgent %s",
req->chaddr,
req->hostname,
IP2String(tempbuff, req->dhcpp.header.bp_giaddr));
} else {
sprintf(logBuff,
"No Matching DHCP Range for DHCPDISCOVER for %s (%s) from interface %s",
req->chaddr,
req->hostname,
IP2String(tempbuff, network.dhcpConn[req->sockInd].server));
}
}
logDHCPMess(logBuff, 1);
}
return 0;
}
MYDWORD chkaddr(data9 *req) {
//debug("chaddr");
//debug(req->remote.sin_addr.s_addr);
//debug(req->dhcpp.header.bp_ciaddr);
req->dhcpEntry = findDHCPEntry(req->chaddr);
if (!req->dhcpEntry || !req->dhcpEntry->ip) {
return 0;
}
//debug(req->dhcpEntry->subnetFlg);
req->dhcpEntry->rangeInd = getRangeInd(req->dhcpEntry->ip);
if (req->dhcpEntry->fixed) {
return req->dhcpEntry->ip;
}
MYDWORD rangeStart = 0;
MYDWORD rangeEnd = 0;
if (req->dhcpEntry->rangeInd >= 0) {
data17 rangeData {};
memset(&rangeData, 0, sizeof(data17));
data13 *range = &cfig.dhcpRanges[req->dhcpEntry->rangeInd];
int ind = getIndex((char)req->dhcpEntry->rangeInd, req->dhcpEntry->ip);
bool rangeOK = true;
if (cfig.hasFilter) {
for (MYBYTE rangeSetInd = 0; rangeSetInd < MAX_RANGE_SETS && cfig.rangeSet[rangeSetInd].active;
rangeSetInd++) {
data14 *rangeSet = &cfig.rangeSet[rangeSetInd];
for (MYBYTE i = 0; i < MAX_RANGE_FILTERS && rangeSet->macSize[i]; i++) {
//printf("%s\n", hex2String(tempbuff, rangeSet->macStart[i], rangeSet->macSize[i]));
//printf("%s\n", hex2String(tempbuff, rangeSet->macEnd[i], rangeSet->macSize[i]));
if (memcmp(req->dhcpp.header.bp_chaddr, rangeSet->macStart[i], rangeSet->macSize[i]) >= 0 &&
memcmp(req->dhcpp.header.bp_chaddr, rangeSet->macEnd[i], rangeSet->macSize[i]) <= 0) {
rangeData.macArray[rangeSetInd] = 1;
rangeData.macFound = true;
//printf("mac Found, rangeSetInd=%i\n", rangeSetInd);
break;
}
}
for (MYBYTE i = 0; i < MAX_RANGE_FILTERS && req->vendClass.size && rangeSet->vendClassSize[i]; i++) {
if (rangeSet->vendClassSize[i] == req->vendClass.size &&
!memcmp(req->vendClass.value, rangeSet->vendClass[i], rangeSet->vendClassSize[i])) {
rangeData.vendArray[rangeSetInd] = 1;
rangeData.vendFound = true;
//printf("vend Found, rangeSetInd=%i\n", rangeSetInd);
break;
}
}
for (MYBYTE i = 0; i < MAX_RANGE_FILTERS && req->userClass.size && rangeSet->userClassSize[i]; i++) {
if (rangeSet->userClassSize[i] == req->userClass.size &&
!memcmp(req->userClass.value, rangeSet->userClass[i], rangeSet->userClassSize[i])) {
rangeData.userArray[rangeSetInd] = 1;
rangeData.userFound = true;
//printf("user Found, rangeSetInd=%i\n", rangeSetInd);
break;
}
}
for (MYBYTE i = 0; i < MAX_RANGE_FILTERS && req->subnetIP && rangeSet->subnetIP[i]; i++) {
if (req->subnetIP == rangeSet->subnetIP[i]) {
rangeData.subnetArray[rangeSetInd] = 1;
rangeData.subnetFound = true;
//printf("subnet Found, rangeSetInd=%i\n", rangeSetInd);
break;
}
}
}
MYBYTE rangeSetInd = range->rangeSetInd;
data14 *rangeSet = &cfig.rangeSet[rangeSetInd];
rangeOK = false;
if ((!rangeData.macFound && !rangeSet->macSize[0]) ||
(rangeData.macFound && rangeData.macArray[rangeSetInd])) {
if ((!rangeData.vendFound && !rangeSet->vendClassSize[0]) ||
(rangeData.vendFound && rangeData.vendArray[rangeSetInd])) {
if ((!rangeData.userFound && !rangeSet->userClassSize[0]) ||
(rangeData.userFound && rangeData.userArray[rangeSetInd])) {
rangeOK = true;
}
}
}
}
if (range->dhcpEntry[ind] == req->dhcpEntry && rangeOK) {
if (rangeData.subnetFound) {
if (rangeData.subnetArray[range->rangeSetInd]) {
return req->dhcpEntry->ip;
} else {
return 0;
}
} else if (req->subnetIP) {
calcRangeLimits(req->subnetIP, range->mask, &rangeStart, &rangeEnd);
if (rangeStart < range->rangeStart) {
rangeStart = range->rangeStart;
}
if (rangeEnd > range->rangeEnd) {
rangeEnd = range->rangeEnd;
}
if (htonl(req->dhcpEntry->ip) >= rangeStart && htonl(req->dhcpEntry->ip) <= rangeEnd) {
return req->dhcpEntry->ip;
}
} else if (!req->dhcpEntry->subnetFlg && !cfig.rangeSet[range->rangeSetInd].subnetIP[0]) {
calcRangeLimits(network.dhcpConn[req->sockInd].server, range->mask, &rangeStart, &rangeEnd);
if (rangeStart < range->rangeStart) {
rangeStart = range->rangeStart;
}
if (rangeEnd > range->rangeEnd) {
rangeEnd = range->rangeEnd;
}
if (htonl(req->dhcpEntry->ip) >= rangeStart && htonl(req->dhcpEntry->ip) <= rangeEnd) {
return req->dhcpEntry->ip;
}
} else if (req->dhcpEntry->subnetFlg) {
return req->dhcpEntry->ip;
}
}
}
return 0;
}
MYDWORD sdmess(data9 *req) {
//sprintf(logBuff, "sdmess, Request Type = %u",req->req_type);
//debug(logBuff);
char tempbuff[512];
char logBuff[256];
if (req->req_type == DHCP_MESS_NONE) {
req->dhcpp.header.bp_yiaddr = chkaddr(req);
if (req->dhcpp.header.bp_yiaddr && req->dhcpEntry && req->dhcpEntry->fixed) {
req->lease = UINT_MAX;
} else {
if (verbatim || cfig.dhcpLogLevel) {
sprintf(logBuff, "No Static Entry found for BOOTPREQUEST from Host %s", req->chaddr);
logDHCPMess(logBuff, 1);
}
return 0;
}
} else if (req->req_type == DHCP_MESS_DECLINE) {
/* Thanks to Timo for fixing issue here */
if (req->reqIP && chkaddr(req) == req->reqIP) {
lockIP(req->reqIP);
req->dhcpEntry->ip = 0;
req->dhcpEntry->expiry = INT_MAX;
req->dhcpEntry->display = false;
req->dhcpEntry->local = false;
if (verbatim || cfig.dhcpLogLevel) {
sprintf(logBuff,
"IP Address %s declined by Host %s (%s), locked",
IP2String(tempbuff, req->reqIP),
req->chaddr,
req->dhcpEntry->hostname);
logDHCPMess(logBuff, 1);
}
}
return 0;
} else if (req->req_type == DHCP_MESS_RELEASE) {
if (req->dhcpp.header.bp_ciaddr && chkaddr(req) == req->dhcpp.header.bp_ciaddr) {
req->dhcpEntry->display = false;
req->dhcpEntry->local = false;
setLeaseExpiry(req->dhcpEntry, 0);
//_beginthread(updateStateFile, 0, (void*)req->dhcpEntry);
pthread_t threadId;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
int errcode = pthread_create(&threadId, &attr, updateStateFile, req->dhcpEntry);
pthread_attr_destroy(&attr);
if (verbatim || cfig.dhcpLogLevel) {
sprintf(logBuff,
"IP Address %s released by Host %s (%s)",
IP2String(tempbuff, req->dhcpp.header.bp_ciaddr),
req->chaddr,
req->hostname);
logDHCPMess(logBuff, 1);
}
}
return 0;
} else if (req->req_type == DHCP_MESS_INFORM) {
//printf("repl0=%s\n", IP2String(tempbuff, cfig.zoneServers[0]));
//printf("repl1=%s\n", IP2String(tempbuff, cfig.zoneServers[1]));
//printf("IP=%s bytes=%u replication=%i\n", IP2String(tempbuff, req->remote.sin_addr.s_addr), req->bytes, cfig.replication);
if ((cfig.replication == 1 && req->remote.sin_addr.s_addr == cfig.zoneServers[1]) ||
(cfig.replication == 2 && req->remote.sin_addr.s_addr == cfig.zoneServers[0])) {
recvRepl(req);
}
return 0;
}
//else if (req->req_type == DHCP_MESS_DISCOVER && strcasecmp(req->hostname, cfig.servername))
else if (req->req_type == DHCP_MESS_DISCOVER) {
req->dhcpp.header.bp_yiaddr = resad(req);
if (!req->dhcpp.header.bp_yiaddr) {
return 0;
}
req->resp_type = DHCP_MESS_OFFER;
} else if (req->req_type == DHCP_MESS_REQUEST) {
//printf("%s\n", IP2String(tempbuff, req->dhcpp.header.bp_ciaddr));
if (req->server) {
if (req->server == network.dhcpConn[req->sockInd].server) {
if (req->reqIP && req->reqIP == chkaddr(req) && req->dhcpEntry->expiry > t) {
req->resp_type = DHCP_MESS_ACK;
req->dhcpp.header.bp_yiaddr = req->reqIP;
} else if (req->dhcpp.header.bp_ciaddr && req->dhcpp.header.bp_ciaddr == chkaddr(req) &&
req->dhcpEntry->expiry > t) {
req->resp_type = DHCP_MESS_ACK;
req->dhcpp.header.bp_yiaddr = req->dhcpp.header.bp_ciaddr;
req->dhcpp.header.bp_ciaddr = 0;
} else {
req->resp_type = DHCP_MESS_NAK;
req->dhcpp.header.bp_yiaddr = 0;
if (verbatim || cfig.dhcpLogLevel) {
sprintf(logBuff,
"DHCPREQUEST from Host %s (%s) without Discover, NAKed",
req->chaddr,
req->hostname);
logDHCPMess(logBuff, 1);
}
}
} else {
return 0;
}
} else if (req->dhcpp.header.bp_ciaddr && req->dhcpp.header.bp_ciaddr == chkaddr(req) &&
req->dhcpEntry->expiry > t) {
req->resp_type = DHCP_MESS_ACK;
req->dhcpp.header.bp_yiaddr = req->dhcpp.header.bp_ciaddr;
req->dhcpp.header.bp_ciaddr = 0;
} else if (req->reqIP && req->reqIP == chkaddr(req) && req->dhcpEntry->expiry > t) {
req->resp_type = DHCP_MESS_ACK;
req->dhcpp.header.bp_yiaddr = req->reqIP;
} else {
req->resp_type = DHCP_MESS_NAK;
req->dhcpp.header.bp_yiaddr = 0;
if (verbatim || cfig.dhcpLogLevel) {
sprintf(logBuff, "DHCPREQUEST from Host %s (%s) without Discover, NAKed", req->chaddr, req->hostname);
logDHCPMess(logBuff, 1);
}
}
} else {
return 0;
}
addOptions(req);
int packSize = (int)(req->vp - (MYBYTE *)&req->dhcpp);
packSize++;
if (req->req_type == DHCP_MESS_NONE) {
packSize = req->messsize;
}
//debug(req->dhcpEntry->rangeInd);
//debug(cfig.dhcpRanges[req->dhcpEntry->rangeInd].rangeSetInd);
if (req->subnetIP && req->dhcpEntry && req->dhcpEntry->rangeInd >= 0) {
MYBYTE rangeSetInd = cfig.dhcpRanges[req->dhcpEntry->rangeInd].rangeSetInd;
req->targetIP = cfig.rangeSet[rangeSetInd].targetIP;
}
if (req->targetIP) {
req->remote.sin_port = htons(IPPORT_DHCPS);
req->remote.sin_addr.s_addr = req->targetIP;
} else if (req->dhcpp.header.bp_giaddr) {
req->remote.sin_port = htons(IPPORT_DHCPS);
req->remote.sin_addr.s_addr = req->dhcpp.header.bp_giaddr;
} else if (req->dhcpp.header.bp_broadcast || !req->remote.sin_addr.s_addr) {
req->remote.sin_port = htons(IPPORT_DHCPC);
req->remote.sin_addr.s_addr = INADDR_BROADCAST;
} else {
req->remote.sin_port = htons(IPPORT_DHCPC);
}
req->dhcpp.header.bp_op = BOOTP_REPLY;
errno = 0;
sockaddr_in cliAddr = get_cliAddr(nicif, tempbuff, req);
if (req->req_type == DHCP_MESS_DISCOVER && !req->remote.sin_addr.s_addr) {
req->bytes = (int)sendto(network.dhcpConn[req->sockInd].sock,
req->raw,
packSize,
MSG_DONTROUTE,
(sockaddr *)&cliAddr,
sizeof(cliAddr));
} else {
req->bytes = (int)
sendto(network.dhcpConn[req->sockInd].sock, req->raw, packSize, 0, (sockaddr *)&cliAddr, sizeof(cliAddr));
}
if (errno || req->bytes <= 0) {
return 0;
}
//printf("goes=%s %i\n",IP2String(tempbuff, req->dhcpp.header.bp_yiaddr),req->sockInd);
return req->dhcpp.header.bp_yiaddr;
}
MYDWORD alad(data9 *req) {
//debug("alad");
//printf("in alad hostname=%s\n", req->hostname);
char tempbuff[512];
char logBuff[256];
if (req->dhcpEntry && (req->req_type == DHCP_MESS_NONE || req->resp_type == DHCP_MESS_ACK)) {
MYDWORD hangTime = req->lease;
if (req->rebind > req->lease) {
hangTime = req->rebind;
}
req->dhcpEntry->display = true;
req->dhcpEntry->local = true;
setLeaseExpiry(req->dhcpEntry, hangTime);
//_beginthread(updateStateFile, 0, (void*)req->dhcpEntry);
pthread_t threadId;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
int errcode = pthread_create(&threadId, &attr, updateStateFile, req->dhcpEntry);
pthread_attr_destroy(&attr);
if (verbatim || cfig.dhcpLogLevel >= 1) {
if (req->lease && req->reqIP) {
sprintf(logBuff,
"Host %s (%s) allotted %s for %u seconds",
req->chaddr,
req->hostname,
IP2String(tempbuff, req->dhcpp.header.bp_yiaddr),
req->lease);
} else if (req->req_type) {
sprintf(logBuff,
"Host %s (%s) renewed %s for %u seconds",
req->chaddr,
req->hostname,
IP2String(tempbuff, req->dhcpp.header.bp_yiaddr),
req->lease);
} else {
sprintf(logBuff,
"BOOTP Host %s (%s) allotted %s",
req->chaddr,
req->hostname,
IP2String(tempbuff, req->dhcpp.header.bp_yiaddr));
}
logDHCPMess(logBuff, 1);
}
if (cfig.replication && cfig.dhcpRepl > t) {
sendRepl(req);
}
return req->dhcpEntry->ip;
} else if ((verbatim || cfig.dhcpLogLevel >= 2) && req->resp_type == DHCP_MESS_OFFER) {
sprintf(logBuff,
"Host %s (%s) offered %s",
req->chaddr,
req->hostname,
IP2String(tempbuff, req->dhcpp.header.bp_yiaddr));
logDHCPMess(logBuff, 2);
}
//printf("%u=out\n", req->resp_type);
return 0;
}
void addOptions(data9 *req) {
//debug("addOptions");
data3 op {};
int i;
if (req->req_type && req->resp_type) {
op.opt_code = DHCP_OPTION_MESSAGETYPE;
op.size = 1;
op.value[0] = req->resp_type;
pvdata(req, &op);
}
if (req->dhcpEntry && req->resp_type != DHCP_MESS_DECLINE && req->resp_type != DHCP_MESS_NAK) {
strcpy(req->dhcpp.header.bp_sname, cfig.servername);
if (req->dhcpEntry->fixed) {
//printf("%u,%u\n", req->dhcpEntry->options, *req->dhcpEntry->options);
MYBYTE *opPointer = req->dhcpEntry->options;
if (opPointer) {
MYBYTE requestedOnly = *opPointer;
opPointer++;
while (*opPointer && *opPointer != DHCP_OPTION_END) {
op.opt_code = *opPointer;
opPointer++;
op.size = *opPointer;
opPointer++;
if (!requestedOnly || req->paramreqlist[*opPointer]) {
memcpy(op.value, opPointer, op.size);
pvdata(req, &op);
}
opPointer += op.size;
}
}
}
if (req->req_type && req->resp_type) {
if (req->dhcpEntry->rangeInd >= 0) {
MYBYTE *opPointer = cfig.dhcpRanges[req->dhcpEntry->rangeInd].options;
//printf("Range=%i Pointer=%u\n", req->dhcpEntry->rangeInd,opPointer);
if (opPointer) {
MYBYTE requestedOnly = *opPointer;
opPointer++;
while (*opPointer && *opPointer != DHCP_OPTION_END) {
op.opt_code = *opPointer;
opPointer++;
op.size = *opPointer;
opPointer++;
if (!requestedOnly || req->paramreqlist[*opPointer]) {
memcpy(op.value, opPointer, op.size);
pvdata(req, &op);
}
opPointer += op.size;
}
}
}
MYBYTE *opPointer = cfig.options;
if (opPointer) {
MYBYTE requestedOnly = *opPointer;
opPointer++;
while (*opPointer && *opPointer != DHCP_OPTION_END) {
op.opt_code = *opPointer;
opPointer++;
op.size = *opPointer;
opPointer++;
if (!requestedOnly || req->paramreqlist[*opPointer]) {
memcpy(op.value, opPointer, op.size);
pvdata(req, &op);
}
opPointer += op.size;
}
}
op.opt_code = DHCP_OPTION_SERVERID;
op.size = 4;
pIP(op.value, network.dhcpConn[req->sockInd].server);
pvdata(req, &op);
op.opt_code = DHCP_OPTION_DOMAINNAME;
op.size = strlen(cfig.zone) + 1;
memcpy(op.value, cfig.zone, op.size);
pvdata(req, &op);
if (!req->opAdded[DHCP_OPTION_IPADDRLEASE]) {
op.opt_code = DHCP_OPTION_IPADDRLEASE;
op.size = 4;
pULong(op.value, cfig.lease);
pvdata(req, &op);
}
if (!req->opAdded[DHCP_OPTION_NETMASK]) {
op.opt_code = DHCP_OPTION_NETMASK;
op.size = 4;
if (req->dhcpEntry->rangeInd >= 0) {
pIP(op.value, cfig.dhcpRanges[req->dhcpEntry->rangeInd].mask);
} else {
pIP(op.value, cfig.mask);
}
pvdata(req, &op);
}
if (req->subnet.opt_code == DHCP_OPTION_SUBNETSELECTION) {
pvdata(req, &req->subnet);
}
if (req->agentOption.opt_code == DHCP_OPTION_RELAYAGENTINFO) {
pvdata(req, &req->agentOption);
}
}
if (req->hostname[0]) {
strcpy(req->dhcpEntry->hostname, req->hostname);
} else if (req->dhcpEntry->hostname[0]) {
strcpy(req->hostname, req->dhcpEntry->hostname);
} else {
genHostName(req->hostname, req->dhcpp.header.bp_chaddr, req->dhcpp.header.bp_hlen);
strcpy(req->dhcpEntry->hostname, req->hostname);
}
}
*(req->vp) = DHCP_OPTION_END;
}
void pvdata(data9 *req, data3 *op) {
//debug("pvdata");
MYBYTE opsize = op->size;
if (!req->opAdded[op->opt_code] && ((req->vp - (MYBYTE *)&req->dhcpp) + opsize < req->messsize)) {
if (op->opt_code == DHCP_OPTION_NEXTSERVER) {
req->dhcpp.header.bp_siaddr = fIP(op->value);
} else if (op->opt_code == DHCP_OPTION_BP_FILE) {
if (opsize <= 128) {
memcpy(req->dhcpp.header.bp_file, op->value, opsize);
}
} else if (opsize) {
if (op->opt_code == DHCP_OPTION_IPADDRLEASE) {
if (!req->lease || req->lease > fULong(op->value)) {
req->lease = fULong(op->value);
}
if (req->lease >= INT_MAX) {
req->lease = UINT_MAX;
}
pULong(op->value, req->lease);
} else if (op->opt_code == DHCP_OPTION_REBINDINGTIME) {
req->rebind = fULong(op->value);
} else if (op->opt_code == DHCP_OPTION_HOSTNAME) {
memcpy(req->hostname, op->value, opsize);
req->hostname[opsize] = 0;
req->hostname[64] = 0;
if (char *ptr = strchr(req->hostname, '.')) {
*ptr = 0;
}
opsize = strlen(req->hostname) + 1;
memcpy(op->value, req->hostname, opsize);
}
opsize += 2;
memcpy(req->vp, op, opsize);
(req->vp) += opsize;
}
req->opAdded[op->opt_code] = true;
}
}
void setTempLease(data7 *dhcpEntry) {
if (dhcpEntry && dhcpEntry->ip) {
dhcpEntry->display = false;
dhcpEntry->local = false;
dhcpEntry->expiry = t + 20;
int ind = getIndex((char)dhcpEntry->rangeInd, dhcpEntry->ip);
if (ind >= 0) {
if (cfig.dhcpRanges[dhcpEntry->rangeInd].expiry[ind] != INT_MAX) {
cfig.dhcpRanges[dhcpEntry->rangeInd].expiry[ind] = dhcpEntry->expiry;
}
cfig.dhcpRanges[dhcpEntry->rangeInd].dhcpEntry[ind] = dhcpEntry;
}
}
}
void setLeaseExpiry(data7 *dhcpEntry, MYDWORD lease) {
//printf("%d=%d\n", t, lease);
if (dhcpEntry && dhcpEntry->ip) {
if (lease > (MYDWORD)(INT_MAX - t)) {
dhcpEntry->expiry = INT_MAX;
} else {
dhcpEntry->expiry = t + lease;
}
int ind = getIndex((char)dhcpEntry->rangeInd, dhcpEntry->ip);
if (ind >= 0) {
if (cfig.dhcpRanges[dhcpEntry->rangeInd].expiry[ind] != INT_MAX) {
cfig.dhcpRanges[dhcpEntry->rangeInd].expiry[ind] = dhcpEntry->expiry;
}
cfig.dhcpRanges[dhcpEntry->rangeInd].dhcpEntry[ind] = dhcpEntry;
}
}
}
void setLeaseExpiry(data7 *dhcpEntry) {
if (dhcpEntry && dhcpEntry->ip) {
int ind = getIndex((char)dhcpEntry->rangeInd, dhcpEntry->ip);
if (ind >= 0) {
if (cfig.dhcpRanges[dhcpEntry->rangeInd].expiry[ind] != INT_MAX) {
cfig.dhcpRanges[dhcpEntry->rangeInd].expiry[ind] = dhcpEntry->expiry;
}
cfig.dhcpRanges[dhcpEntry->rangeInd].dhcpEntry[ind] = dhcpEntry;
}
}
}
void lockIP(MYDWORD ip) {
if (ip) {
MYDWORD iip = htonl(ip);
for (char rangeInd = 0; rangeInd < cfig.rangeCount; rangeInd++) {
if (iip >= cfig.dhcpRanges[rangeInd].rangeStart && iip <= cfig.dhcpRanges[rangeInd].rangeEnd) {
unsigned int ind = iip - cfig.dhcpRanges[rangeInd].rangeStart;
if (cfig.dhcpRanges[rangeInd].expiry[ind] != INT_MAX) {
cfig.dhcpRanges[rangeInd].expiry[ind] = INT_MAX;
}
break;
}
}
}
}
//void holdIP(MYDWORD ip) {
// if (ip) {
// MYDWORD iip = htonl(ip);
//
// for (char rangeInd = 0; rangeInd < cfig.rangeCount; rangeInd++) {
// if (iip >= cfig.dhcpRanges[rangeInd].rangeStart && iip <= cfig.dhcpRanges[rangeInd].rangeEnd) {
// unsigned int ind = iip - cfig.dhcpRanges[rangeInd].rangeStart;
//
// if (cfig.dhcpRanges[rangeInd].expiry[ind] == 0) {
// cfig.dhcpRanges[rangeInd].expiry[ind] = 1;
// }
//
// break;
// }
// }
// }
//}
void *sendToken(void *lpParam) {
sleep(10);
while (kRunning) {
errno = 0;
sendto(cfig.dhcpReplConn.sock, token.raw, token.bytes, 0, (sockaddr *)&token.remote, sizeof(token.remote));
// errno = WSAGetLastError();
// if (errno)
// debug(strerror(errno));
// else if (verbatim || cfig.dhcpLogLevel >= 2)
// debug("Token Sent");
sleep(300);
}
pthread_exit(nullptr);
}
MYDWORD sendRepl(data9 *req) {
char logBuff[256];
char ipbuff[32];
data3 op {};
MYBYTE *opPointer = req->dhcpp.vend_data;
while ((*opPointer) != DHCP_OPTION_END && opPointer < req->vp) {
if ((*opPointer) == DHCP_OPTION_MESSAGETYPE) {
*(opPointer + 2) = DHCP_MESS_INFORM;
break;
}
opPointer = opPointer + *(opPointer + 1) + 2;
}
if (!req->opAdded[DHCP_OPTION_MESSAGETYPE]) {
op.opt_code = DHCP_OPTION_MESSAGETYPE;
op.size = 1;
op.value[0] = DHCP_MESS_INFORM;
pvdata(req, &op);
}
if (req->hostname[0] && !req->opAdded[DHCP_OPTION_HOSTNAME]) {
op.opt_code = DHCP_OPTION_HOSTNAME;
op.size = strlen(req->hostname) + 1;
memcpy(op.value, req->hostname, op.size);
pvdata(req, &op);
}
// op.opt_code = DHCP_OPTION_SERIAL;
// op.size = 4;
// pULong(op.value, cfig.serial1);
// pvdata(req, &op);
*(req->vp) = DHCP_OPTION_END;
req->vp++;
req->bytes = (int)(req->vp - (MYBYTE *)req->raw);
req->dhcpp.header.bp_op = BOOTP_REQUEST;
errno = 0;
req->bytes = (int)
sendto(cfig.dhcpReplConn.sock, req->raw, req->bytes, 0, (sockaddr *)&token.remote, sizeof(token.remote));
//errno = WSAGetLastError();
if (errno || req->bytes <= 0) {
cfig.dhcpRepl = 0;
if (verbatim || cfig.dhcpLogLevel >= 1) {
if (cfig.replication == 1) {
sprintf(logBuff, "Error %s Sending DHCP Update to Secondary Server", strerror(errno));
} else {
sprintf(logBuff, "Error %s Sending DHCP Update to Primary Server", strerror(errno));
}
logDHCPMess(logBuff, 1);
}
return 0;
} else if (verbatim || cfig.dhcpLogLevel >= 2) {
if (cfig.replication == 1) {
sprintf(logBuff,
"DHCP Update for host %s (%s) sent to Secondary Server",
req->dhcpEntry->mapname,
IP2String(ipbuff, req->dhcpEntry->ip));
} else {
sprintf(logBuff,
"DHCP Update for host %s (%s) sent to Primary Server",
req->dhcpEntry->mapname,
IP2String(ipbuff, req->dhcpEntry->ip));
}
logDHCPMess(logBuff, 2);
}
return req->dhcpp.header.bp_yiaddr;
}
/*
MYDWORD sendRepl(data7 *dhcpEntry)
{
data9 req;
memset(&req, 0, sizeof(data9));
req.vp = req.dhcpp.vend_data;
req.messsize = sizeof(dhcp_packet);
req.dhcpEntry = dhcpEntry;
req.dhcpp.header.bp_op = BOOTP_REQUEST;
req.dhcpp.header.bp_xid = t;
req.dhcpp.header.bp_ciaddr = dhcpEntry->ip;
req.dhcpp.header.bp_yiaddr = dhcpEntry->ip;
req.dhcpp.header.bp_hlen = 16;
getHexValue(req.dhcpp.header.bp_chaddr, req.dhcpEntry->mapname, &(req.dhcpp.header.bp_hlen));
req.dhcpp.header.bp_magic_num[0] = 99;
req.dhcpp.header.bp_magic_num[1] = 130;
req.dhcpp.header.bp_magic_num[2] = 83;
req.dhcpp.header.bp_magic_num[3] = 99;
strcpy(req.hostname, dhcpEntry->hostname);
return sendRepl(&req);
}
*/
void recvRepl(data9 *req) {
char ipbuff[32];
char logBuff[512];
cfig.dhcpRepl = t + 650;
MYDWORD ip = req->dhcpp.header.bp_yiaddr ? req->dhcpp.header.bp_yiaddr : req->dhcpp.header.bp_ciaddr;
if (!ip && !req->dhcpp.header.bp_hlen) {
if (cfig.replication == 1) {
errno = 0;
sendto(cfig.dhcpReplConn.sock, token.raw, token.bytes, 0, (sockaddr *)&token.remote, sizeof(token.remote));
}
return;
}
int rInd = getRangeInd(ip);
if (rInd >= 0) {
int ind = getIndex((char)rInd, ip);
req->dhcpEntry = cfig.dhcpRanges[rInd].dhcpEntry[ind];
if (req->dhcpEntry && !req->dhcpEntry->fixed && strcasecmp(req->dhcpEntry->mapname, req->chaddr)) {
req->dhcpEntry->expiry = 0;
}
}
req->dhcpEntry = findDHCPEntry(req->chaddr);
if (req->dhcpEntry && req->dhcpEntry->ip != ip) {
if (req->dhcpEntry->fixed) {
if (cfig.replication == 1) {
sprintf(logBuff,
"DHCP Update ignored for %s (%s) from Secondary Server",
req->chaddr,
IP2String(ipbuff, ip));
} else {
sprintf(logBuff,
"DHCP Update ignored for %s (%s) from Primary Server",
req->chaddr,
IP2String(ipbuff, ip));
}
logDHCPMess(logBuff, 1);
return;
} else if (req->dhcpEntry->rangeInd >= 0) {
int ind = getIndex((char)req->dhcpEntry->rangeInd, req->dhcpEntry->ip);
if (ind >= 0) {
cfig.dhcpRanges[req->dhcpEntry->rangeInd].dhcpEntry[ind] = nullptr;
}
}
}
if (!req->dhcpEntry && rInd >= 0) {
memset(&lump, 0, sizeof(data71));
lump.cacheType = CTYPE_DHCP_ENTRY;
lump.mapname = req->chaddr;
lump.hostname = req->hostname;
req->dhcpEntry = createCache(&lump);
if (req->dhcpEntry) {
dhcpCache[req->dhcpEntry->mapname] = req->dhcpEntry;
}
/*
req->dhcpEntry = (data7*)calloc(1, sizeof(data7));
if (!req->dhcpEntry)
{
sprintf(logBuff, "Memory Allocation Error");
logDHCPMess(logBuff, 1);
return;
}
req->dhcpEntry->mapname = cloneString(req->chaddr);
if (!req->dhcpEntry->mapname)
{
sprintf(logBuff, "Memory Allocation Error");
free(req->dhcpEntry);
logDHCPMess(logBuff, 1);
return;
}
*/
}
if (req->dhcpEntry) {
req->dhcpEntry->ip = ip;
req->dhcpEntry->rangeInd = rInd;
req->dhcpEntry->display = true;
req->dhcpEntry->local = false;
if (req->rebind > req->lease) {
req->lease = req->rebind;
}
setLeaseExpiry(req->dhcpEntry, req->lease);
strcpy(req->dhcpEntry->hostname, req->hostname);
//_beginthread(updateStateFile, 0, (void*)req->dhcpEntry);
pthread_t threadId;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
int errcode = pthread_create(&threadId, &attr, updateStateFile, req->dhcpEntry);
pthread_attr_destroy(&attr);
if (verbatim || cfig.dhcpLogLevel >= 2) {
if (cfig.replication == 1) {
sprintf(logBuff,
"DHCP Update received for %s (%s) from Secondary Server",
req->chaddr,
IP2String(ipbuff, ip));
} else {
sprintf(logBuff,
"DHCP Update received for %s (%s) from Primary Server",
req->chaddr,
IP2String(ipbuff, ip));
}
logDHCPMess(logBuff, 2);
}
} else {
if (cfig.replication == 1) {
sprintf(logBuff,
"DHCP Update ignored for %s (%s) from Secondary Server",
req->chaddr,
IP2String(ipbuff, ip));
} else {
sprintf(logBuff, "DHCP Update ignored for %s (%s) from Primary Server", req->chaddr, IP2String(ipbuff, ip));
}
logDHCPMess(logBuff, 1);
return;
}
}
int getRangeInd(MYDWORD ip) {
if (ip) {
MYDWORD iip = htonl(ip);
for (char k = 0; k < cfig.rangeCount; k++) {
if (iip >= cfig.dhcpRanges[k].rangeStart && iip <= cfig.dhcpRanges[k].rangeEnd) {
return k;
}
}
}
return -1;
}
int getIndex(char rangeInd, MYDWORD ip) {
if (ip && rangeInd >= 0 && rangeInd < cfig.rangeCount) {
MYDWORD iip = htonl(ip);
if (iip >= cfig.dhcpRanges[rangeInd].rangeStart && iip <= cfig.dhcpRanges[rangeInd].rangeEnd) {
return (int)(iip - cfig.dhcpRanges[rangeInd].rangeStart);
}
}
return -1;
}
void loadOptions(FILE *f, const char *sectionName, data20 *optionData) {
optionData->ip = 0;
optionData->mask = 0;
MYBYTE maxInd = sizeof(opData) / sizeof(data4);
MYWORD buffsize = sizeof(dhcp_packet) - sizeof(dhcp_header);
MYBYTE *dp = optionData->options;
MYBYTE op_specified[256];
memset(op_specified, 0, 256);
*dp = 0;
dp++;
char raw[512];
char name[512];
char value[512];
char logBuff[512];
while (readSection(raw, f)) {
MYBYTE *ddp = dp;
MYBYTE hoption[256];
MYBYTE valSize = sizeof(hoption) - 1;
MYBYTE opTag = 0;
MYBYTE opType = 0;
MYBYTE valType = 0;
bool tagFound = false;
mySplit(name, value, raw, '=');
//printf("%s=%s\n", name, value);
if (!name[0]) {
sprintf(logBuff, "Warning: section [%s] invalid option %s ignored", sectionName, raw);
logDHCPMess(logBuff, 1);
continue;
}
if (!strcasecmp(name, "DHCPRange")) {
if (!strcasecmp(sectionName, RANGESET)) {
addDHCPRange(value);
} else {
sprintf(logBuff,
"Warning: section [%s] option %s not allowed in this section, option ignored",
sectionName,
raw);
logDHCPMess(logBuff, 1);
}
continue;
} else if (!strcasecmp(name, "IP")) {
if (!strcasecmp(sectionName, GLOBALOPTIONS) || !strcasecmp(sectionName, RANGESET)) {
sprintf(logBuff,
"Warning: section [%s] option %s not allowed in this section, option ignored",
sectionName,
raw);
logDHCPMess(logBuff, 1);
} else if (!isIP(value) && strcasecmp(value, "0.0.0.0")) {
sprintf(logBuff, "Warning: section [%s] option Invalid IP Addr %s option ignored", sectionName, value);
logDHCPMess(logBuff, 1);
} else {
optionData->ip = inet_addr(value);
}
continue;
} else if (!strcasecmp(name, "FilterMacRange")) {
if (!strcasecmp(sectionName, RANGESET)) {
addMacRange(optionData->rangeSetInd, value);
} else {
sprintf(logBuff,
"Warning: section [%s] option %s not allowed in this section, option ignored",
sectionName,
raw);
logDHCPMess(logBuff, 1);
}
continue;
}
if (!value[0]) {
valType = 9;
} else if (value[0] == '"' && value[strlen(value) - 1] == '"') {
valType = 2;
value[0] = NBSP;
value[strlen(value) - 1] = NBSP;
myTrim(value, value);
if (strlen(value) <= UCHAR_MAX) {
valSize = strlen(value);
} else {
sprintf(logBuff, "Warning: section [%s] option %s value too big, option ignored", sectionName, raw);
logDHCPMess(logBuff, 1);
continue;
}
} else if (strchr(value, ':')) {
valType = 2;
valSize = sizeof(hoption) - 1;
char *errorPos = getHexValue(hoption, value, &valSize);
if (errorPos) {
valType = 1;
valSize = strlen(value);
} else {
memcpy(value, hoption, valSize);
}
} else if (isInt(value) && strtol(value, nullptr, 10) > USHRT_MAX) {
valType = 4;
} else if (isInt(value) && STR2INT(value) > UCHAR_MAX) {
valType = 5;
} else if (isInt(value)) {
valType = 6;
} else if (strchr(value, '.') || strchr(value, ',')) {
valType = 2;
char buff[1024];
int numbytes = myTokenize(buff, value, "/,.", true);
if (numbytes > 255) {
sprintf(logBuff, "Warning: section [%s] option %s, too many bytes, entry ignored", sectionName, raw);
logDHCPMess(logBuff, 1);
continue;
} else {
char *ptr = buff;
valSize = 0;
for (; *ptr; ptr = myGetToken(ptr, 1)) {
//printf("%s:", ptr);
if (isInt(ptr) && STR2INT(ptr) <= UCHAR_MAX) {
hoption[valSize] = STR2INT(ptr);
valSize++;
} else {
break;
}
}
if (!(*ptr)) {
memcpy(value, hoption, valSize);
} else {
valType = 1;
valSize = strlen(value);
}
}
} else {
if (strlen(value) <= UCHAR_MAX) {
valSize = strlen(value);
valType = 1;
} else {
sprintf(logBuff, "Warning: section [%s] option %s value too long, option ignored", sectionName, raw);
logDHCPMess(logBuff, 1);
continue;
}
}
if (!strcasecmp(name, "FilterVendorClass")) {
if (!strcasecmp(sectionName, RANGESET)) {
addVendClass(optionData->rangeSetInd, value, valSize);
} else {
sprintf(logBuff,
"Warning: section [%s] option %s not allowed in this section, option ignored",
sectionName,
raw);
logDHCPMess(logBuff, 1);
}
continue;
} else if (!strcasecmp(name, "FilterUserClass")) {
if (!strcasecmp(sectionName, RANGESET)) {
addUserClass(optionData->rangeSetInd, value, valSize);
} else {
sprintf(logBuff,
"Warning: section [%s] option %s not allowed in this section, option ignored",
sectionName,
raw);
logDHCPMess(logBuff, 1);
}
continue;
} else if (!strcasecmp(name, "FilterSubnetSelection")) {
if (valSize != 4) {
sprintf(logBuff, "Warning: section [%s] invalid value %s, option ignored", sectionName, raw);
logDHCPMess(logBuff, 1);
} else if (!strcasecmp(sectionName, RANGESET)) {
addServer(cfig.rangeSet[optionData->rangeSetInd].subnetIP, MAX_RANGE_FILTERS, fIP(value));
cfig.hasFilter = true;
} else {
sprintf(logBuff,
"Warning: section [%s] option %s not allowed in this section, option ignored",
sectionName,
raw);
logDHCPMess(logBuff, 1);
}
continue;
} else if (!strcasecmp(name, "TargetRelayAgent")) {
if (valSize != 4) {
sprintf(logBuff, "Warning: section [%s] invalid value %s, option ignored", sectionName, raw);
logDHCPMess(logBuff, 1);
} else if (!strcasecmp(sectionName, RANGESET)) {
cfig.rangeSet[optionData->rangeSetInd].targetIP = fIP(value);
//printf("TARGET IP %s set RangeSetInd %d\n", IP2String(ipbuff, cfig.rangeSet[optionData->rangeSetInd].targetIP), optionData->rangeSetInd);
} else {
sprintf(logBuff,
"Warning: section [%s] option %s not allowed in this section, option ignored",
sectionName,
raw);
logDHCPMess(logBuff, 1);
}
continue;
}
opTag = 0;
if (isInt(name)) {
if (STR2INT(name) < 1 || STR2INT(name) >= 254) {
sprintf(logBuff, "Warning: section [%s] invalid option %s, ignored", sectionName, raw);
logDHCPMess(logBuff, 1);
continue;
}
opTag = STR2INT(name);
opType = 0;
}
for (MYBYTE i = 0; i < maxInd; i++) {
if (!strcasecmp(name, opData[i].opName) || (opTag && opTag == opData[i].opTag)) {
opTag = opData[i].opTag;
opType = opData[i].opType;
tagFound = true;
break;
}
}
if (!opTag) {
sprintf(logBuff, "Warning: section [%s] invalid option %s, ignored", sectionName, raw);
logDHCPMess(logBuff, 1);
continue;
}
if (!opType) {
opType = valType;
}
//sprintf(logBuff, "Tag %i ValType %i opType %i value=%s size=%u", opTag, valType, opType, value, valSize);
//logDHCPMess(logBuff, 1);
if (op_specified[opTag]) {
sprintf(logBuff, "Warning: section [%s] duplicate option %s, ignored", sectionName, raw);
logDHCPMess(logBuff, 1);
continue;
}
//printf("Option=%u opType=%u valueType=%u valSize=%u\n", opTag, opType, valType, valSize);
op_specified[opTag] = true;
if (valType == 9) {
if (buffsize > 2) {
*dp = opTag;
dp++;
*dp = 0;
dp++;
buffsize -= 2;
} else {
sprintf(logBuff, "Warning: section [%s] option %s, no more space for options", sectionName, raw);
logDHCPMess(logBuff, 1);
}
continue;
}
switch (opType) {
case 1: {
value[valSize] = 0;
valSize++;
if (valType != 1 && valType != 2) {
sprintf(logBuff,
"Warning: section [%s] option %s, need string value, option ignored",
sectionName,
raw);
logDHCPMess(logBuff, 1);
} else if (!strcasecmp(serviceName, "DUALServer") && opTag == DHCP_OPTION_DOMAINNAME) {
sprintf(logBuff,
"Warning: section [%s] Domain Name %s should be in section [DOMAIN_NAME], ignored",
sectionName,
value);
logDHCPMess(logBuff, 1);
continue;
} else if (buffsize > valSize + 2) {
*dp = opTag;
dp++;
*dp = valSize;
dp++;
memcpy(dp, value, valSize);
dp += valSize;
buffsize -= (valSize + 2);
} else {
sprintf(logBuff, "Warning: section [%s] option %s, no more space for options", sectionName, raw);
logDHCPMess(logBuff, 1);
}
} break;
case 3:
case 8: {
if (valType == 2) {
if (opType == 3 && valSize % 4) {
sprintf(logBuff,
"Warning: section [%s] option %s, missing/extra bytes/octates in IP, option ignored",
sectionName,
raw);
logDHCPMess(logBuff, 1);
continue;
} else if (opType == 8 && valSize % 8) {
sprintf(logBuff,
"Warning: section [%s] option %s, some values not in IP/Mask form, option ignored",
sectionName,
raw);
logDHCPMess(logBuff, 1);
continue;
}
if (opTag == DHCP_OPTION_NETMASK) {
if (valSize != 4 || !checkMask(fIP(value))) {
sprintf(logBuff,
"Warning: section [%s] Invalid subnetmask %s, option ignored",
sectionName,
raw);
logDHCPMess(logBuff, 1);
continue;
} else {
optionData->mask = fIP(value);
}
}
if (buffsize > valSize + 2) {
*dp = opTag;
dp++;
*dp = valSize;
dp++;
memcpy(dp, value, valSize);
dp += valSize;
buffsize -= (valSize + 2);
} else {
sprintf(logBuff,
"Warning: section [%s] option %s, no more space for options",
sectionName,
raw);
logDHCPMess(logBuff, 1);
}
} else {
sprintf(logBuff,
"Warning: section [%s] option %s, Invalid value, should be one or more IP/4 Bytes",
sectionName,
raw);
logDHCPMess(logBuff, 1);
}
} break;
case 4: {
MYDWORD j;
if (valType == 2 && valSize == 4) {
j = fULong(value);
} else if (valType >= 4 && valType <= 6) {
j = strtol(value, nullptr, 10);
} else {
sprintf(logBuff,
"Warning: section [%s] option %s, value should be integer between 0 & %u or 4 bytes, "
"option ignored",
sectionName,
name,
UINT_MAX);
logDHCPMess(logBuff, 1);
continue;
}
if (opTag == DHCP_OPTION_IPADDRLEASE) {
if (j == 0) {
j = UINT_MAX;
}
if (!strcasecmp(serviceName, "DUALServer")) {
if (!strcasecmp(sectionName, GLOBALOPTIONS)) {
sprintf(logBuff,
"Warning: section [%s] option %s not allowed in this section, please set it in "
"[TIMINGS] section",
sectionName,
raw);
logDHCPMess(logBuff, 1);
continue;
} else if (j < cfig.lease) {
sprintf(
logBuff,
"Warning: section [%s] option %s value should be more then %u (Default Lease), ignored",
sectionName,
name,
cfig.lease);
logDHCPMess(logBuff, 1);
continue;
}
} else if (!strcasecmp(serviceName, "OpenDHCP") && !strcasecmp(sectionName, GLOBALOPTIONS)) {
cfig.lease = j;
}
}
if (buffsize > 6) {
*dp = opTag;
dp++;
*dp = 4;
dp++;
dp += pULong(dp, j);
buffsize -= 6;
//printf("%s=%u=%u\n",opData[op_index].opName,opData[op_index].opType,htonl(j));
} else {
sprintf(logBuff, "Warning: section [%s] option %s, no more space for options", sectionName, raw);
logDHCPMess(logBuff, 1);
}
} break;
case 5: {
MYWORD j;
if (valType == 2 && valSize == 2) {
j = fUShort(value);
} else if (valType == 5 || valType == 6) {
j = strtol(value, nullptr, 10);
} else {
sprintf(
logBuff,
"Warning: section [%s] option %s, value should be between 0 & %u or 2 bytes, option ignored",
sectionName,
name,
USHRT_MAX);
logDHCPMess(logBuff, 1);
continue;
}
if (buffsize > 4) {
*dp = opTag;
dp++;
*dp = 2;
dp++;
dp += pUShort(dp, j);
buffsize -= 4;
} else {
sprintf(logBuff, "Warning: section [%s] option %s, no more space for options", sectionName, raw);
logDHCPMess(logBuff, 1);
}
} break;
case 6: {
MYBYTE j;
if (valType == 2 && valSize == 1) {
j = *value;
} else if (valType == 6) {
j = strtol(value, nullptr, 10);
} else {
sprintf(logBuff,
"Warning: section [%s] option %s, value should be between 0 & %u or single byte, option "
"ignored",
sectionName,
name,
UCHAR_MAX);
logDHCPMess(logBuff, 1);
continue;
}
if (buffsize > 3) {
*dp = opTag;
dp++;
*dp = 1;
dp++;
*dp = j;
dp++;
buffsize -= 3;
} else {
sprintf(logBuff, "Warning: section [%s] option %s, no more space for options", sectionName, raw);
logDHCPMess(logBuff, 1);
}
} break;
case 7: {
MYBYTE j;
if (valType == 2 && valSize == 1 && *value < 2) {
j = *value;
} else if (valType == 1 &&
(!strcasecmp(value, "yes") || !strcasecmp(value, "on") || !strcasecmp(value, "true"))) {
j = 1;
} else if (valType == 1 &&
(!strcasecmp(value, "no") || !strcasecmp(value, "off") || !strcasecmp(value, "false"))) {
j = 0;
} else if (valType == 6 && STR2INT(value) < 2) {
j = STR2INT(value);
} else {
sprintf(logBuff,
"Warning: section [%s] option %s, value should be yes/on/true/1 or no/off/false/0, option "
"ignored",
sectionName,
raw);
logDHCPMess(logBuff, 1);
continue;
}
if (buffsize > 3) {
*dp = opTag;
dp++;
*dp = 1;
dp++;
*dp = j;
dp++;
buffsize -= 3;
} else {
sprintf(logBuff, "Warning: section [%s] option %s, no more space for options", sectionName, raw);
logDHCPMess(logBuff, 1);
}
} break;
default: {
if (valType == 6) {
valType = 2;
valSize = 1;
*value = STR2INT(value);
}
if (opType == 2 && valType != 2) {
sprintf(logBuff,
"Warning: section [%s] option %s, value should be comma separated bytes or hex string, "
"option ignored",
sectionName,
raw);
logDHCPMess(logBuff, 1);
continue;
} else if (buffsize > valSize + 2) {
*dp = opTag;
dp++;
*dp = valSize;
dp++;
memcpy(dp, value, valSize);
dp += valSize;
buffsize -= (valSize + 2);
} else {
sprintf(logBuff, "Warning: section [%s] option %s, no more space for options", sectionName, raw);
logDHCPMess(logBuff, 1);
}
} break;
}
//printf("%s Option=%u opType=%u valType=%u valSize=%u\n", raw, opTag, opType, valType, valSize);
//printf("%s %s\n", name, hex2String(tempbuff, ddp, valSize+2, ':'));
}
//printf("%s=%s\n", sectionName, optionData->vendClass);
*dp = DHCP_OPTION_END;
dp++;
optionData->optionSize = (dp - optionData->options);
//printf("section=%s buffersize = %u option size=%u\n", sectionName, buffsize, optionData->optionSize);
}
void lockOptions(FILE *f) {
char raw[512];
char name[512];
char value[512];
while (readSection(raw, f)) {
mySplit(name, value, raw, '=');
if (!name[0] || !value[0]) {
continue;
}
int op_index;
MYBYTE n = sizeof(opData) / sizeof(data4);
for (op_index = 0; op_index < n; op_index++) {
if (!strcasecmp(name, opData[op_index].opName) ||
(opData[op_index].opTag && STR2INT(name) == opData[op_index].opTag)) {
break;
}
}
if (op_index >= n) {
continue;
}
if (opData[op_index].opType == 3) {
if (myTokenize(value, value, "/,.", true)) {
char *ptr = value;
char hoption[256];
MYBYTE valueSize = 0;
for (; *ptr; ptr = myGetToken(ptr, 1)) {
if (valueSize >= UCHAR_MAX) {
break;
} else if (isInt(ptr) && STR2INT(ptr) <= UCHAR_MAX) {
hoption[valueSize] = STR2INT(ptr);
valueSize++;
} else {
break;
}
}
if (*ptr) {
continue;
}
if (valueSize % 4) {
continue;
}
for (MYBYTE i = 0; i < valueSize; i += 4) {
MYDWORD ip = *((MYDWORD *)&(hoption[i]));
if (ip != INADDR_ANY && ip != INADDR_NONE) {
lockIP(ip);
}
}
}
}
}
}
int addDHCPRange(char *dp) {
char logBuff[256];
MYDWORD rs = 0;
MYDWORD re = 0;
char name[512];
char value[512];
mySplit(name, value, dp, '-');
if (isIP(name) && isIP(value)) {
rs = htonl(inet_addr(name));
re = htonl(inet_addr(value));
if (rs && re && rs <= re) {
data13 *range;
MYBYTE m = 0;
for (; m < MAX_DHCP_RANGES && cfig.dhcpRanges[m].rangeStart; m++) {
range = &cfig.dhcpRanges[m];
if ((rs >= range->rangeStart && rs <= range->rangeEnd) ||
(re >= range->rangeStart && re <= range->rangeEnd) ||
(range->rangeStart >= rs && range->rangeStart <= re) ||
(range->rangeEnd >= rs && range->rangeEnd <= re)) {
sprintf(logBuff, "Warning: DHCP Range %s overlaps with another range, ignored", dp);
logDHCPMess(logBuff, 1);
return ERR_ITEM_EXISTS;
}
}
if (m < MAX_DHCP_RANGES) {
cfig.dhcpSize += (re - rs + 1);
range = &cfig.dhcpRanges[m];
range->rangeStart = rs;
range->rangeEnd = re;
range->expiry = (time_t *)calloc((re - rs + 1), sizeof(time_t));
range->dhcpEntry = (data7 **)calloc((re - rs + 1), sizeof(data7 *));
if (!range->expiry || !range->dhcpEntry) {
if (range->expiry) {
free(range->expiry);
}
if (range->dhcpEntry) {
free(range->dhcpEntry);
}
sprintf(logBuff, "DHCP Ranges Load, Memory Allocation Error");
logDHCPMess(logBuff, 1);
return ERR_MALLOC_MEMORY;
}
}
} else {
sprintf(logBuff, "Section [%s] Invalid DHCP range %s in ini file, ignored", RANGESET, dp);
logDHCPMess(logBuff, 1);
return ERR_INPUT_PARAMS;
}
} else {
sprintf(logBuff, "Section [%s] Invalid DHCP range %s in ini file, ignored", RANGESET, dp);
logDHCPMess(logBuff, 1);
return ERR_INPUT_PARAMS;
}
return ERR_SUCCESS;
}
void addVendClass(MYBYTE rangeSetInd, char *vendClass, MYBYTE vendClassSize) {
char logBuff[256];
data14 *rangeSet = &cfig.rangeSet[rangeSetInd];
MYBYTE i = 0;
for (; i <= MAX_RANGE_FILTERS && rangeSet->vendClassSize[i]; i++)
;
if (i >= MAX_RANGE_FILTERS || !vendClassSize) {
return;
}
rangeSet->vendClass[i] = (MYBYTE *)calloc(vendClassSize, 1);
if (!rangeSet->vendClass[i]) {
sprintf(logBuff, "Vendor Class Load, Memory Allocation Error");
logDHCPMess(logBuff, 1);
} else {
cfig.hasFilter = true;
rangeSet->vendClassSize[i] = vendClassSize;
memcpy(rangeSet->vendClass[i], vendClass, vendClassSize);
//printf("Loaded Vendor Class %s Size=%i rangeSetInd=%i Ind=%i\n", rangeSet->vendClass[i], rangeSet->vendClassSize[i], rangeSetInd, i);
//printf("Loaded Vendor Class %s Size=%i rangeSetInd=%i Ind=%i\n", hex2String(tempbuff, rangeSet->vendClass[i], rangeSet->vendClassSize[i], ':'), rangeSet->vendClassSize[i], rangeSetInd, i);
}
}
void addUserClass(MYBYTE rangeSetInd, char *userClass, MYBYTE userClassSize) {
char logBuff[256];
data14 *rangeSet = &cfig.rangeSet[rangeSetInd];
MYBYTE i = 0;
for (; i <= MAX_RANGE_FILTERS && rangeSet->userClassSize[i]; i++)
;
if (i >= MAX_RANGE_FILTERS || !userClassSize) {
return;
}
rangeSet->userClass[i] = (MYBYTE *)calloc(userClassSize, 1);
if (!rangeSet->userClass[i]) {
sprintf(logBuff, "Vendor Class Load, Memory Allocation Error");
logDHCPMess(logBuff, 1);
} else {
cfig.hasFilter = true;
rangeSet->userClassSize[i] = userClassSize;
memcpy(rangeSet->userClass[i], userClass, userClassSize);
//printf("Loaded User Class %s Size=%i rangeSetInd=%i Ind=%i\n", hex2String(tempbuff, rangeSet->userClass[i], rangeSet->userClassSize[i], ':'), rangeSet->vendClassSize[i], rangeSetInd, i);
}
}
void addMacRange(MYBYTE rangeSetInd, char *macRange) {
char logBuff[256];
if (macRange[0]) {
data14 *rangeSet = &cfig.rangeSet[rangeSetInd];
MYBYTE i = 0;
for (; i <= MAX_RANGE_FILTERS && rangeSet->macSize[i]; i++)
;
if (i >= MAX_RANGE_FILTERS) {
return;
}
char name[256];
char value[256];
mySplit(name, value, macRange, '-');
//printf("%s=%s\n", name, value);
if (!name[0] || !value[0]) {
sprintf(logBuff, "Section [%s], invalid Filter_Mac_Range %s, ignored", RANGESET, macRange);
logDHCPMess(logBuff, 1);
} else {
MYBYTE macSize1 = 16;
MYBYTE macSize2 = 16;
auto *macStart = (MYBYTE *)calloc(1, macSize1);
auto *macEnd = (MYBYTE *)calloc(1, macSize2);
if (!macStart || !macEnd) {
sprintf(logBuff, "DHCP Range Load, Memory Allocation Error");
logDHCPMess(logBuff, 1);
} else if (getHexValue(macStart, name, &macSize1) || getHexValue(macEnd, value, &macSize2)) {
sprintf(logBuff, "Section [%s], Invalid character in Filter_Mac_Range %s", RANGESET, macRange);
logDHCPMess(logBuff, 1);
free(macStart);
free(macEnd);
} else if (memcmp(macStart, macEnd, 16) > 0) {
sprintf(logBuff,
"Section [%s], Invalid Filter_Mac_Range %s, (higher bound specified on left), ignored",
RANGESET,
macRange);
logDHCPMess(logBuff, 1);
free(macStart);
free(macEnd);
} else if (macSize1 != macSize2) {
sprintf(logBuff,
"Section [%s], Invalid Filter_Mac_Range %s, (start/end size mismatched), ignored",
RANGESET,
macRange);
logDHCPMess(logBuff, 1);
free(macStart);
free(macEnd);
} else {
cfig.hasFilter = true;
rangeSet->macSize[i] = macSize1;
rangeSet->macStart[i] = macStart;
rangeSet->macEnd[i] = macEnd;
//printf("Mac Loaded, Size=%i Start=%s rangeSetInd=%i Ind=%i\n", rangeSet->macSize[i], hex2String(tempbuff, rangeSet->macStart[i], rangeSet->macSize[i]), rangeSetInd, i);
}
}
}
}
void loadDHCP() {
char ipbuff[32];
char logBuff[512];
data7 *dhcpEntry = nullptr;
data8 dhcpData {};
char mapname[64];
FILE *f = nullptr;
FILE *ff = nullptr;
if ((f = openSection(GLOBALOPTIONS, 1))) {
data20 optionData {};
loadOptions(f, GLOBALOPTIONS, &optionData);
cfig.options = (MYBYTE *)calloc(1, optionData.optionSize);
memcpy(cfig.options, optionData.options, optionData.optionSize);
cfig.mask = optionData.mask;
}
if (!cfig.mask) {
cfig.mask = inet_addr("255.255.255.0");
}
#if 1
opendhcp_add_ip_pool_set();
#else
for (MYBYTE i = 1; i <= MAX_RANGE_SETS; i++) {
if ((f = openSection(RANGESET, i))) {
MYBYTE m = cfig.rangeCount;
data20 optionData {};
optionData.rangeSetInd = i - 1;
loadOptions(f, RANGESET, &optionData);
MYBYTE *options = nullptr;
cfig.rangeSet[optionData.rangeSetInd].active = true;
if (optionData.optionSize > 3) {
options = (MYBYTE *)calloc(1, optionData.optionSize);
memcpy(options, optionData.options, optionData.optionSize);
}
for (; m < MAX_DHCP_RANGES && cfig.dhcpRanges[m].rangeStart; m++) {
cfig.dhcpRanges[m].rangeSetInd = optionData.rangeSetInd;
cfig.dhcpRanges[m].options = options;
cfig.dhcpRanges[m].mask = optionData.mask;
}
cfig.rangeCount = (char)m;
} else {
break;
}
}
#endif
//printf("%s\n", IP2String(ipbuff, cfig.mask));
for (char rangeInd = 0; rangeInd < cfig.rangeCount; rangeInd++) {
if (!cfig.dhcpRanges[rangeInd].mask) {
cfig.dhcpRanges[rangeInd].mask = cfig.mask;
}
for (MYDWORD iip = cfig.dhcpRanges[rangeInd].rangeStart; iip <= cfig.dhcpRanges[rangeInd].rangeEnd; iip++) {
MYDWORD ip = htonl(iip);
if ((cfig.dhcpRanges[rangeInd].mask | (~ip)) == UINT_MAX ||
(cfig.dhcpRanges[rangeInd].mask | ip) == UINT_MAX) {
cfig.dhcpRanges[rangeInd].expiry[iip - cfig.dhcpRanges[rangeInd].rangeStart] = INT_MAX;
}
}
}
if ((f = openSection(GLOBALOPTIONS, 1))) {
lockOptions(f);
}
for (MYBYTE i = 1; i <= MAX_RANGE_SETS; i++) {
if ((f = openSection(RANGESET, i))) {
lockOptions(f);
} else {
break;
}
}
ff = fopen(iniFile, "rt");
#if 1
opendhcp_add_mac_filter();
#else
if (ff) {
char sectionName[512];
while (fgets(sectionName, 510, ff)) {
if (*sectionName == '[') {
char *secend = strchr(sectionName, ']');
if (secend) {
*secend = 0;
sectionName[0] = NBSP;
myTrim(sectionName, sectionName);
} else {
continue;
}
} else {
continue;
}
if (!strchr(sectionName, ':')) {
continue;
}
//printf("%s\n", sectionName);
MYBYTE hexValue[UCHAR_MAX];
MYBYTE hexValueSize = sizeof(hexValue);
data20 optionData {};
if (strlen(sectionName) <= 48 && !getHexValue(hexValue, sectionName, &hexValueSize)) {
if (hexValueSize <= 16) {
dhcpEntry = findDHCPEntry(hex2String(mapname, hexValue, hexValueSize));
if (!dhcpEntry) {
if ((f = openSection(sectionName, 1))) {
loadOptions(f, sectionName, &optionData);
}
if ((f = openSection(sectionName, 1))) {
lockOptions(f);
}
auto p = dhcpCache.begin();
for (; p != dhcpCache.end(); p++) {
if (p->second && p->second->ip && p->second->ip == optionData.ip) {
break;
}
}
if (p == dhcpCache.end()) {
memset(&lump, 0, sizeof(data71));
lump.cacheType = CTYPE_DHCP_ENTRY;
lump.mapname = mapname;
lump.optionSize = optionData.optionSize;
lump.options = optionData.options;
dhcpEntry = createCache(&lump);
if (!dhcpEntry) {
return;
}
dhcpEntry->ip = optionData.ip;
dhcpEntry->rangeInd = getRangeInd(optionData.ip);
dhcpEntry->fixed = 1;
dhcpEntry->expiry = 0;
dhcpCache[dhcpEntry->mapname] = dhcpEntry;
setLeaseExpiry(dhcpEntry);
lockIP(optionData.ip);
//printf("%s=%s=%s size=%u %u\n", mapname, dhcpEntry->mapname, IP2String(ipbuff, optionData.ip), optionData.optionSize, dhcpEntry->options);
} else {
sprintf(logBuff,
"Static DHCP Host [%s] Duplicate IP Address %s, Entry ignored",
sectionName,
IP2String(ipbuff, optionData.ip));
logDHCPMess(logBuff, 1);
}
} else {
sprintf(logBuff, "Duplicate Static DHCP Host [%s] ignored", sectionName);
logDHCPMess(logBuff, 1);
}
} else {
sprintf(logBuff, "Invalid Static DHCP Host MAC Addr size, ignored");
logDHCPMess(logBuff, 1);
}
} else {
sprintf(logBuff, "Invalid Static DHCP Host MAC Addr [%s] ignored", sectionName);
logDHCPMess(logBuff, 1);
}
if (!optionData.ip) {
sprintf(logBuff, "Warning: No IP Address for DHCP Static Host %s specified", sectionName);
logDHCPMess(logBuff, 1);
}
}
fclose(ff);
}
#endif
f = fopen(leaFile, "rb");
if (f) {
while (fread(&dhcpData, sizeof(data8), 1, f)) {
int rangeInd = -1;
int ind = -1;
//sprintf(logBuff, "Loading %s=%s", dhcpData.hostname, IP2String(ipbuff, dhcpData.ip));
//logDHCPMess(logBuff, 1);
if (dhcpData.expiry > (t - 31 * 24 * 3600) && dhcpData.bp_hlen <= 16 &&
!findServer(network.allServers, MAX_SERVERS, dhcpData.ip)) {
hex2String(mapname, dhcpData.bp_chaddr, dhcpData.bp_hlen);
auto p = dhcpCache.begin();
for (; p != dhcpCache.end(); p++) {
dhcpEntry = p->second;
if (!dhcpEntry || (!strcasecmp(mapname, dhcpEntry->mapname) || dhcpEntry->ip == dhcpData.ip)) {
break;
}
}
if ((p != dhcpCache.end()) &&
(strcasecmp(mapname, dhcpEntry->mapname) || dhcpEntry->ip != dhcpData.ip)) {
continue;
}
dhcpEntry = findDHCPEntry(mapname);
rangeInd = getRangeInd(dhcpData.ip);
if (!dhcpEntry && rangeInd >= 0) {
memset(&lump, 0, sizeof(data71));
lump.cacheType = CTYPE_DHCP_ENTRY;
lump.mapname = mapname;
dhcpEntry = createCache(&lump);
}
if (dhcpEntry) {
dhcpCache[dhcpEntry->mapname] = dhcpEntry;
dhcpEntry->subnetFlg = dhcpData.subnetFlg;
dhcpEntry->ip = dhcpData.ip;
dhcpEntry->rangeInd = rangeInd;
dhcpEntry->expiry = dhcpData.expiry;
dhcpEntry->local = dhcpData.local;
dhcpEntry->display = true;
strcpy(dhcpEntry->hostname, dhcpData.hostname);
setLeaseExpiry(dhcpEntry);
}
}
}
fclose(f);
}
f = fopen(leaFile, "wb");
fclose(f);
f = fopen(leaFile, "rb+");
if (f) {
auto p = dhcpCache.begin();
for (; p != dhcpCache.end(); p++) {
if ((dhcpEntry = p->second) && dhcpEntry->expiry > (t - 31 * 24 * 3600)) {
memset(&dhcpData, 0, sizeof(data8));
MYBYTE bp_hlen = 16;
getHexValue(dhcpData.bp_chaddr, dhcpEntry->mapname, &bp_hlen);
dhcpData.bp_hlen = bp_hlen;
dhcpData.ip = dhcpEntry->ip;
dhcpData.subnetFlg = dhcpEntry->subnetFlg;
dhcpData.expiry = dhcpEntry->expiry;
dhcpData.local = dhcpEntry->local;
strcpy(dhcpData.hostname, dhcpEntry->hostname);
cfig.dhcpInd += 1;
dhcpEntry->dhcpInd = cfig.dhcpInd;
dhcpData.dhcpInd = dhcpEntry->dhcpInd;
if (fseek(f, (long)((dhcpData.dhcpInd - 1) * sizeof(data8)), SEEK_SET) >= 0) {
fwrite(&dhcpData, sizeof(data8), 1, f);
}
}
}
fclose(f);
}
}
#if 0
bool getSection(const char *sectionName, char *buffer, MYBYTE serial, char *fileName) {
//printf("%s=%s\n",fileName,sectionName);
char section[128];
sprintf(section, "[%s]", sectionName);
myUpper(section);
FILE *f = fopen(fileName, "rt");
char buff[512];
MYBYTE found = 0;
if (f) {
while (fgets(buff, 511, f)) {
myUpper(buff);
myTrim(buff, buff);
if (strstr(buff, section) == buff) {
found++;
if (found == serial) {
//printf("%s=%s\n",fileName,sectionName);
while (fgets(buff, 511, f)) {
myTrim(buff, buff);
if (strstr(buff, "[") == buff) {
break;
}
if ((*buff) >= '0' && (*buff) <= '9' || (*buff) >= 'A' && (*buff) <= 'Z' ||
(*buff) >= 'a' && (*buff) <= 'z' || ((*buff) && strchr("/\\?*", (*buff)))) {
buffer += sprintf(buffer, "%s", buff);
buffer++;
}
}
break;
}
}
}
fclose(f);
}
*buffer = 0;
*(buffer + 1) = 0;
return (found == serial);
}
#endif
FILE *openSection(const char *sectionName, MYBYTE serial) {
char logBuff[256];
char tempbuff[512];
char section[128];
sprintf(section, "[%s]", sectionName);
myUpper(section);
FILE *f = nullptr;
f = fopen(iniFile, "rt");
if (f) {
//printf("opened %s=%d\n", tempbuff, f);
char buff[512];
MYBYTE found = 0;
while (fgets(buff, 511, f)) {
myUpper(buff);
myTrim(buff, buff);
if (strstr(buff, section) == buff) {
found++;
if (found == serial) {
MYDWORD fpos = ftell(f);
if (fgets(buff, 511, f)) {
myTrim(buff, buff);
if (buff[0] == '@') {
fclose(f);
f = nullptr;
buff[0] = NBSP;
myTrim(buff, buff);
if (strchr(buff, '\\') || strchr(buff, '/')) {
strcpy(tempbuff, buff);
} else {
sprintf(tempbuff, "%s%s", filePATH, buff);
}
f = fopen(tempbuff, "rt");
if (f) {
return f;
} else {
sprintf(logBuff, "Error: Section [%s], file %s not found", sectionName, tempbuff);
logDHCPMess(logBuff, 1);
return nullptr;
}
} else {
fseek(f, fpos, SEEK_SET);
return f;
}
}
}
}
}
fclose(f);
}
return nullptr;
}
char *readSection(char *buff, FILE *f) {
while (fgets(buff, 511, f)) {
myTrim(buff, buff);
if (*buff == '[') {
break;
}
if ((*buff) >= '0' && (*buff) <= '9' || (*buff) >= 'A' && (*buff) <= 'Z' || (*buff) >= 'a' && (*buff) <= 'z' ||
((*buff) && strchr("/\\?*", (*buff)))) {
return buff;
}
}
fclose(f);
return nullptr;
}
char *myGetToken(char *buff, MYBYTE index) {
while (*buff) {
if (index) {
index--;
} else {
break;
}
buff += strlen(buff) + 1;
}
return buff;
}
MYWORD myTokenize(char *target, char *source, const char *sep, bool whiteSep) {
bool found = true;
char *dp = target;
MYWORD kount = 0;
while (*source) {
if (sep && sep[0] && strchr(sep, (*source))) {
found = true;
source++;
continue;
} else if (whiteSep && (*source) <= NBSP) {
found = true;
source++;
continue;
}
if (found) {
if (target != dp) {
*dp = 0;
dp++;
}
kount++;
}
found = false;
*dp = *source;
dp++;
source++;
}
*dp = 0;
dp++;
*dp = 0;
//printf("%s\n", target);
return kount;
}
char *myTrim(char *target, char *source) {
while ((*source) && (*source) <= NBSP) {
source++;
}
int i = 0;
for (; i < 511 && source[i]; i++) {
target[i] = source[i];
}
target[i] = source[i];
i--;
for (; i >= 0 && target[i] <= NBSP; i--) {
target[i] = 0;
}
return target;
}
void mySplit(char *name, char *value, const char *source, char splitChar) {
int i = 0;
int j = 0;
int k = 0;
for (; source[i] && j <= 510 && source[i] != splitChar; i++, j++) {
name[j] = source[i];
}
if (source[i]) {
i++;
for (; k <= 510 && source[i]; i++, k++) {
value[k] = source[i];
}
}
name[j] = 0;
value[k] = 0;
myTrim(name, name);
myTrim(value, value);
//printf("%s %s\n", name, value);
}
//
//MYDWORD getClassNetwork(MYDWORD ip) {
// data15 data {};
// data.ip = ip;
// data.octate[3] = 0;
//
// if (data.octate[0] < 192) {
// data.octate[2] = 0;
// }
//
// if (data.octate[0] < 128) {
// data.octate[1] = 0;
// }
//
// return data.ip;
//}
/*
char *IP2Auth(MYDWORD ip)
{
data15 data;
data.ip = ip;
if (data.octate[0] >= 192)
sprintf(tempbuff, "%u.%u.%u", data.octate[2], data.octate[1], data.octate[0]);
else if (data.octate[0] >= 128)
sprintf(tempbuff, "%u.%u", data.octate[1], data.octate[0]);
else
sprintf(tempbuff, "%u", data.octate[0]);
strcat(tempbuff, arpa);
return tempbuff;
}
*/
char *IP2String(char *target, MYDWORD ip, MYBYTE dnsType) {
char *dp = target;
(*dp) = (char)dnsType;
dp++;
data15 inaddr {};
inaddr.ip = ip;
sprintf(dp, "%u.%u.%u.%u", inaddr.octate[0], inaddr.octate[1], inaddr.octate[2], inaddr.octate[3]);
//MYBYTE *octate = (MYBYTE*)&ip;
//sprintf(target, "%u.%u.%u.%u", octate[0], octate[1], octate[2], octate[3]);
return target;
}
char *IP2String(char *target, MYDWORD ip) {
data15 inaddr {};
inaddr.ip = ip;
sprintf(target, "%u.%u.%u.%u", inaddr.octate[0], inaddr.octate[1], inaddr.octate[2], inaddr.octate[3]);
//MYBYTE *octate = (MYBYTE*)&ip;
//sprintf(target, "%u.%u.%u.%u", octate[0], octate[1], octate[2], octate[3]);
return target;
}
MYBYTE addServer(MYDWORD *array, MYBYTE maxServers, MYDWORD ip) {
if (ip) {
for (MYBYTE i = 0; i < maxServers; i++) {
if (array[i] == ip) {
return i;
} else if (!array[i]) {
array[i] = ip;
return i;
}
}
}
return maxServers;
}
MYDWORD *findServer(MYDWORD *array, MYBYTE maxServers, MYDWORD ip) {
if (ip) {
for (MYBYTE i = 0; i < maxServers && array[i]; i++) {
if (array[i] == ip) {
return &(array[i]);
}
}
}
return nullptr;
}
bool isInt(char *str) {
if (!str || !(*str)) {
return false;
}
for (; *str; str++) {
if (*str < '0' || *str > '9') {
return false;
}
}
return true;
}
bool isIP(char *str) {
if (!str || !(*str)) {
return false;
}
MYDWORD ip = inet_addr(str);
if (ip == INADDR_NONE || ip == INADDR_ANY) {
return false;
}
int j = 0;
for (; *str; str++) {
if (*str == '.' && *(str + 1) != '.') {
j++;
} else if (*str < '0' || *str > '9') {
return false;
}
}
if (j == 3) {
return true;
} else {
return false;
}
}
/*
char *toBase64(MYBYTE *source, MYBYTE length)
{
MYBYTE a = 0, b = 0, i = 0;
char *dp = tempbuff;
for (; length; length--, source++)
{
i += 2;
a = (*source) >> i;
*dp = base64[a + b];
dp++;
b = (*source) << (8 - i);
b >>= 2;
if (i == 6)
{
*dp = base64[b];
dp++;
i = b = 0;
}
}
if (i)
{
*dp = base64[b];
dp++;
}
*dp = 0;
//printf("%s\n",tempbuff);
return tempbuff;
}
MYBYTE getBaseValue(MYBYTE a)
{
if (a >= 'A' && a <= 'Z')
a -= 'A';
else if (a >= 'a' && a <= 'z')
a = a - 'a' + 26;
else if (a >= '0' && a <= '9')
a = a - '0' + 52;
else if (a == '+')
a = 62;
else if (a == '/')
a = 63;
else
a = UCHAR_MAX;
return a;
}
MYBYTE fromBase64(MYBYTE *target, char *source)
{
//printf("SOURCE=%s\n", source);
MYBYTE b = 0;
MYBYTE shift = 4;
MYBYTE bp_hlen = (3 * strlen(source))/4;
*target = 0;
if (*source)
{
b = getBaseValue(*source);
*target = b << 2;
source++;
while (*source)
{
b = getBaseValue(*source);
(*target) += (b >> (8 - shift));
target++;
(*target) = (b << shift);
shift += 2;
if (shift > 8)
{
source++;
if (*source)
{
b = getBaseValue(*source);
*target = b << 2;
shift = 4;
}
else
break;
}
source++;
}
}
//printf("SIZE=%u\n", bp_hlen);
return bp_hlen;
}
char *toUUE(char *tempbuff, MYBYTE *source, MYBYTE length)
{
MYBYTE a = 0, b = 0, i = 0;
char *dp = tempbuff;
for (; length; length--, source++)
{
i += 2;
a = (*source) >> i;
*dp = a + b + NBSP;
dp++;
b = (*source) << (8 - i);
b >>= 2;
if (i == 6)
{
*dp = b + NBSP;
dp++;
i = b = 0;
}
}
if (i)
{
*dp = b + NBSP;
dp++;
}
*dp = 0;
//printf("%s\n",tempbuff);
return tempbuff;
}
MYBYTE fromUUE(MYBYTE *target, char *source)
{
//printf("SOURCE=%s\n", source);
MYBYTE b = 0;
MYBYTE shift = 4;
MYBYTE bp_hlen = (3 * strlen(source))/4;
*target = 0;
if (*source)
{
b = *source - NBSP;
*target = b << 2;
source++;
while (*source)
{
b = *source - NBSP;
(*target) += (b >> (8 - shift));
target++;
(*target) = (b << shift);
shift += 2;
if (shift > 8)
{
source++;
if (*source)
{
b = *source - NBSP;
*target = b << 2;
shift = 4;
}
else
break;
}
source++;
}
}
//printf("SIZE=%u\n", bp_hlen);
return bp_hlen;
}
*/
char *hex2String(char *target, const MYBYTE *hex, MYBYTE bytes) {
char *dp = target;
if (bytes) {
dp += sprintf(target, "%02x", *hex);
} else {
*target = 0;
}
for (MYBYTE i = 1; i < bytes; i++) {
dp += sprintf(dp, ":%02x", *(hex + i));
}
return target;
}
char *genHostName(char *target, const MYBYTE *hex, MYBYTE bytes) {
char *dp = target;
if (bytes) {
dp += sprintf(target, "Host%02x", *hex);
} else {
*target = 0;
}
for (MYBYTE i = 1; i < bytes; i++) {
dp += sprintf(dp, "%02x", *(hex + i));
}
return target;
}
/*
char *IP62String(char *target, MYBYTE *source)
{
MYWORD *dw = (MYWORD*)source;
char *dp = target;
MYBYTE markbyte;
for (markbyte = 4; markbyte > 0 && !dw[markbyte - 1]; markbyte--);
for (MYBYTE i = 0; i < markbyte; i++)
dp += sprintf(dp, "%x:", ntohs(dw[i]));
for (markbyte = 4; markbyte < 8 && !dw[markbyte]; markbyte++);
for (MYBYTE i = markbyte; i < 8; i++)
dp += sprintf(dp, ":%x", htons(dw[i]));
return target;
}
*/
//
//char *IP62String(char *target, MYBYTE *source) {
// char *dp = target;
// bool zerostarted = false;
// bool zeroended = false;
//
// for (MYBYTE i = 0; i < 16; i += 2, source += 2) {
// if (source[0]) {
// if (zerostarted) {
// zeroended = true;
// }
//
// if (zerostarted && zeroended) {
// dp += sprintf(dp, "::");
// zerostarted = false;
// } else if (dp != target) {
// dp += sprintf(dp, ":");
// }
//
// dp += sprintf(dp, "%x", source[0]);
// dp += sprintf(dp, "%02x", source[1]);
// } else if (source[1]) {
// if (zerostarted) {
// zeroended = true;
// }
//
// if (zerostarted && zeroended) {
// dp += sprintf(dp, "::");
// zerostarted = false;
// } else if (dp != target) {
// dp += sprintf(dp, ":");
// }
//
// dp += sprintf(dp, "%0x", source[1]);
// } else if (!zeroended) {
// zerostarted = true;
// }
// }
//
// return target;
//}
char *getHexValue(MYBYTE *target, char *source, MYBYTE *size) {
if (*size) {
memset(target, 0, (*size));
}
for ((*size) = 0; (*source) && (*size) < UCHAR_MAX; (*size)++, target++) {
if ((*source) >= '0' && (*source) <= '9') {
(*target) = (*source) - '0';
} else if ((*source) >= 'a' && (*source) <= 'f') {
(*target) = (*source) - 'a' + 10;
} else if ((*source) >= 'A' && (*source) <= 'F') {
(*target) = (*source) - 'A' + 10;
} else {
return source;
}
source++;
if ((*source) >= '0' && (*source) <= '9') {
(*target) *= 16;
(*target) += (*source) - '0';
} else if ((*source) >= 'a' && (*source) <= 'f') {
(*target) *= 16;
(*target) += (*source) - 'a' + 10;
} else if ((*source) >= 'A' && (*source) <= 'F') {
(*target) *= 16;
(*target) += (*source) - 'A' + 10;
} else if ((*source) == ':' || (*source) == '-') {
source++;
continue;
} else if (*source) {
return source;
} else {
continue;
}
source++;
if ((*source) == ':' || (*source) == '-') {
source++;
} else if (*source) {
return source;
}
}
if (*source) {
return source;
}
//printf("macfucked in=%s\n", tSource);
//printf("macfucked out=%s\n", hex2String(tempbuff, tTarget, *size));
return nullptr;
}
char *myUpper(char *string) {
char diff = 'a' - 'A';
MYWORD len = strlen(string);
for (int i = 0; i < len; i++) {
if (string[i] >= 'a' && string[i] <= 'z') {
string[i] = (char)(string[i] - diff);
}
}
return string;
}
char *myLower(char *string) {
char diff = 'a' - 'A';
MYWORD len = strlen(string);
for (int i = 0; i < len; i++) {
if (string[i] >= 'A' && string[i] <= 'Z') {
string[i] = (char)(string[i] + diff);
}
}
return string;
}
#if 0
bool wildcmp(char *string, char *wild) {
// Written by Jack Handy - jakkhandy@hotmail.com
// slightly modified
char *cp = nullptr;
char *mp = nullptr;
while ((*string) && (*wild != '*')) {
if ((*wild != *string) && (*wild != '?')) {
return false;
}
wild++;
string++;
}
while (*string) {
if (*wild == '*') {
if (!*++wild) {
return true;
}
mp = wild;
cp = string + 1;
} else if ((*wild == *string) || (*wild == '?')) {
wild++;
string++;
} else {
wild = mp;
string = cp++;
}
}
while (*wild == '*') {
wild++;
}
return !(*wild);
}
bool isLocal(MYDWORD ip) {
if (cfig.rangeStart && htonl(ip) >= cfig.rangeStart && htonl(ip) <= cfig.rangeEnd) {
return true;
}
// else if (getRangeInd(ip) >= 0)
// return true;
else {
return false;
}
}
char *setMapName(char *tempbuff, char *mapname, MYBYTE dnsType) {
char *dp = tempbuff;
(*dp) = (char)dnsType;
dp++;
strcpy(dp, mapname);
myLower(dp);
return tempbuff;
}
void listDhcpCache() {
char logBuff[256];
auto p = dhcpCache.begin();
data7 *cache = nullptr;
while (p != dhcpCache.end()) {
cache = p->second;
snprintf(logBuff, 256, "%s", cache->mapname);
logDHCPMess(logBuff, 1);
p++;
}
}
#endif
void calcRangeLimits(MYDWORD ip, MYDWORD mask, MYDWORD *rangeStart, MYDWORD *rangeEnd) {
*rangeStart = htonl(ip & mask) + 1;
*rangeEnd = htonl(ip | (~mask)) - 1;
}
bool checkMask(MYDWORD mask) {
mask = htonl(mask);
while (mask) {
if (mask < (mask << 1)) {
return false;
}
mask <<= 1;
}
return true;
}
data7 *findDHCPEntry(char *key) {
//printf("finding %u=%s\n",ind,key);
myLower(key);
auto it = dhcpCache.find(key);
if (it != dhcpCache.end() && it->second) {
return it->second;
}
return nullptr;
}
char *cloneString(char *string) {
char *s = (char *)calloc(1, strlen(string) + 1);
if (s) {
strcpy(s, string);
}
return s;
}
void *init(void *lparam) {
char tempbuff[512];
char logBuff[256];
char ipbuff[32];
char raw[512];
char name[512];
char value[512];
FILE *f = nullptr;
memset(exeFile, 0, sizeof(exeFile));
char id[256];
sprintf(id, "/proc/%d/exe", getpid());
readlink(id, exeFile, PATH_MAX - 1);
exeFile[PATH_MAX - 1] = 0;
strcpy(filePATH, exeFile);
char *ptr = strrchr(filePATH, '/');
ptr++;
*ptr = 0;
if (!iniFile[0]) {
sprintf(iniFile, "%s%s", filePATH, "opendhcp.ini");
}
if (!leaFile[0]) {
sprintf(leaFile, "%s%s", filePATH, "opendhcp.state");
}
if (!icoFile[0]) {
sprintf(icoFile, "%s%s", filePATH, "opendhcp.png");
}
// if (!logFile[0]) {
// sprintf(logFile, "%s%s", filePATH, "log/opendhcp%Y%m%d.log");
// }
#if 1
cfig.dhcpLogLevel = 2;
sprintf(logBuff, "%s Starting...", sVersion);
logDHCPMess(logBuff, 1);
#else
if ((f = openSection("LOGGING", 1))) {
cfig.dhcpLogLevel = 2;
tempbuff[0] = 0;
while (readSection(raw, f)) {
mySplit(name, value, raw, '=');
if (name[0] && value[0]) {
if (!strcasecmp(name, "LogLevel")) {
if (!strcasecmp(value, "None")) {
cfig.dhcpLogLevel = 0;
} else if (!strcasecmp(value, "Normal")) {
cfig.dhcpLogLevel = 1;
} else if (!strcasecmp(value, "All")) {
cfig.dhcpLogLevel = 2;
} else {
sprintf(tempbuff, "Section [LOGGING], Invalid LogLevel: %s", value);
}
} else {
sprintf(tempbuff, "Section [LOGGING], Invalid Entry %s ignored", raw);
}
} else {
sprintf(tempbuff, "Section [LOGGING], Invalid Entry %s ignored", raw);
}
}
if (tempbuff[0]) {
logDHCPMess(logBuff, 1);
}
sprintf(logBuff, "%s Starting...", sVersion);
logDHCPMess(logBuff, 1);
} else {
printf("%s Starting...\n", sVersion);
}
#endif
sleep(1);
if ((f = fopen(iniFile, "rt"))) {
fclose(f);
}
// else {
// sprintf(logBuff, "Warning: file %s not found, defaults will be used", iniFile);
// logDHCPMess(logBuff, 1);
// }
sleep(1);
if ((f = fopen(iniFile, "rt"))) {
fclose(f);
}
// else {
// sprintf(logBuff, "Warning: file %s not found, defaults will be used", iniFile);
// logDHCPMess(logBuff, 1);
// }
sprintf(logBuff, "Starting DHCP Service");
logDHCPMess(logBuff, 1);
sleep(1);
if (cfig.dhcpLogLevel >= 2) {
sprintf(logBuff, "Logging: All");
} else if (cfig.dhcpLogLevel == 1) {
sprintf(logBuff, "Logging: Normal");
} else {
sprintf(logBuff, "Logging: None");
}
logDHCPMess(logBuff, 1);
f = fopen(icoFile, "rb+");
if (f) {
if (cfig.dhcpLogLevel >= 2 || verbatim) {
logDHCPMess(icoFile, 2);
}
fseek(f, 0, SEEK_END);
icoSize = ftell(f);
icoString = (char *)calloc(1, icoSize);
fseek(f, 0, SEEK_SET);
icoSize = fread(icoString, 1, icoSize, f);
fclose(f);
}
// if (verbatim || cfig.dhcpLogLevel >= 1) {
// logDHCPMess(exeFile, 2);
// logDHCPMess(iniFile, 2);
// logDHCPMess(logFile, 2);
// logDHCPMess(leaFile, 2);
// }
if ((f = openSection("LISTEN_ON", 1))) {
while (readSection(raw, f)) {
if (isIP(raw)) {
MYDWORD addr = inet_addr(raw);
addServer(cfig.specifiedServers, MAX_SERVERS, addr);
} else {
sprintf(logBuff, "Warning: Section [LISTEN_ON], Invalid Interface Address %s, ignored", raw);
logDHCPMess(logBuff, 1);
}
}
}
// 合并 vcpe.cfg 配置文件配置内容
opendhcp_add_listener();
cfig.lease = opendhcp_set_lease_time();
cfig.fixedSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (cfig.fixedSocket < 0) {
sprintf(logBuff, "Failed to create Socket");
logDHCPMess(logBuff, 1);
sleep(1);
exit(EXIT_FAILURE);
}
getInterfaces(&network);
sprintf(cfig.servername_fqn, "%s.%s", cfig.servername, cfig.zone);
#if 1
opendhcp_set_replication_svr();
#else
if ((f = openSection("REPLICATION_SERVERS", 1))) {
while (readSection(raw, f)) {
mySplit(name, value, raw, '=');
if (name[0] && value[0]) {
if (!isIP(name) && isIP(value)) {
if (!strcasecmp(name, "Primary")) {
cfig.zoneServers[0] = inet_addr(value);
} else if (!strcasecmp(name, "Secondary")) {
cfig.zoneServers[1] = inet_addr(value);
} else {
sprintf(logBuff, "Section [REPLICATION_SERVERS] Invalid Entry: %s ignored", raw);
logDHCPMess(logBuff, 1);
}
} else {
sprintf(logBuff, "Section [REPLICATION_SERVERS] Invalid Entry: %s ignored", raw);
logDHCPMess(logBuff, 1);
}
} else {
sprintf(logBuff, "Section [REPLICATION_SERVERS], Missing value, entry %s ignored", raw);
logDHCPMess(logBuff, 1);
}
}
}
#endif
if (!cfig.zoneServers[0] && cfig.zoneServers[1]) {
sprintf(logBuff, "Section [REPLICATION_SERVERS] Missing Primary Server");
logDHCPMess(logBuff, 1);
} else if (cfig.zoneServers[0] && !cfig.zoneServers[1]) {
sprintf(logBuff, "Section [REPLICATION_SERVERS] Missing Secondary Server");
logDHCPMess(logBuff, 1);
} else if (cfig.zoneServers[0] && cfig.zoneServers[1]) {
if (findServer(newNetwork.allServers, MAX_SERVERS, cfig.zoneServers[0]) &&
findServer(newNetwork.allServers, MAX_SERVERS, cfig.zoneServers[1])) {
sprintf(logBuff, "Section [REPLICATION_SERVERS] Primary & Secondary should be Different Boxes");
logDHCPMess(logBuff, 1);
} else if (findServer(network.allServers, MAX_SERVERS, cfig.zoneServers[0])) {
cfig.replication = 1;
} else if (findServer(network.allServers, MAX_SERVERS, cfig.zoneServers[1])) {
cfig.replication = 2;
} else {
sprintf(logBuff, "Section [REPLICATION_SERVERS] No Server IP not found on this Machine");
logDHCPMess(logBuff, 1);
}
}
if (cfig.replication) {
lockIP(cfig.zoneServers[0]);
lockIP(cfig.zoneServers[1]);
}
loadDHCP();
/*
for (int i = 0; i < cfig.rangeCount; i++)
{
char *logPtr = logBuff;
logPtr += sprintf(logPtr, "DHCP Range: ");
logPtr += sprintf(logPtr, "%s", IP2String(ipbuff, htonl(cfig.dhcpRanges[i].rangeStart)));
logPtr += sprintf(logPtr, "-%s", IP2String(ipbuff, htonl(cfig.dhcpRanges[i].rangeEnd)));
logPtr += sprintf(logPtr, "/%s", IP2String(ipbuff, cfig.dhcpRanges[i].mask));
logDHCPMess(logBuff, 1);
}
*/
if (cfig.replication) {
lockIP(cfig.zoneServers[0]);
lockIP(cfig.zoneServers[1]);
cfig.dhcpReplConn.sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (cfig.dhcpReplConn.sock == INVALID_SOCKET) {
sprintf(logBuff, "Failed to Create DHCP Replication Socket");
logDHCPMess(logBuff, 1);
} else {
//printf("Socket %u\n", cfig.dhcpReplConn.sock);
if (cfig.replication == 1) {
cfig.dhcpReplConn.server = cfig.zoneServers[0];
} else {
cfig.dhcpReplConn.server = cfig.zoneServers[1];
}
cfig.dhcpReplConn.addr.sin_family = AF_INET;
cfig.dhcpReplConn.addr.sin_addr.s_addr = cfig.dhcpReplConn.server;
cfig.dhcpReplConn.addr.sin_port = 0;
int nRet = bind(cfig.dhcpReplConn.sock, (sockaddr *)&cfig.dhcpReplConn.addr, sizeof(struct sockaddr_in));
if (nRet == SOCKET_ERROR) {
cfig.dhcpReplConn.ready = false;
sprintf(logBuff, "DHCP Replication Server, Bind Failed");
logDHCPMess(logBuff, 1);
} else {
cfig.dhcpReplConn.port = IPPORT_DHCPS;
cfig.dhcpReplConn.loaded = true;
cfig.dhcpReplConn.ready = true;
data3 op {};
memset(&token, 0, sizeof(data9));
token.vp = token.dhcpp.vend_data;
token.messsize = sizeof(dhcp_packet);
token.remote.sin_port = htons(IPPORT_DHCPS);
token.remote.sin_family = AF_INET;
if (cfig.replication == 1) {
token.remote.sin_addr.s_addr = cfig.zoneServers[1];
} else if (cfig.replication == 2) {
token.remote.sin_addr.s_addr = cfig.zoneServers[0];
}
token.dhcpp.header.bp_op = BOOTP_REQUEST;
token.dhcpp.header.bp_xid = t;
strcpy(token.dhcpp.header.bp_sname, cfig.servername);
token.dhcpp.header.bp_magic_num[0] = 99;
token.dhcpp.header.bp_magic_num[1] = 130;
token.dhcpp.header.bp_magic_num[2] = 83;
token.dhcpp.header.bp_magic_num[3] = 99;
op.opt_code = DHCP_OPTION_MESSAGETYPE;
op.size = 1;
op.value[0] = DHCP_MESS_INFORM;
pvdata(&token, &op);
//op.opt_code = DHCP_OPTION_HOSTNAME;
//op.size = strlen(cfig.servername);
//memcpy(op.value, cfig.servername, op.size);
//pvdata(&token, &op);
token.vp[0] = DHCP_OPTION_END;
token.vp++;
token.bytes = (int)(token.vp - (MYBYTE *)token.raw);
//if (cfig.replication == 2)
// _beginthread(sendToken, 0, 0);
if (cfig.replication == 2) {
pthread_t threadId;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
int errcode = pthread_create(&threadId, &attr, sendToken, nullptr);
pthread_attr_destroy(&attr);
}
}
}
}
if (cfig.lease >= INT_MAX) {
sprintf(logBuff, "Default Lease: Infinity");
} else {
sprintf(logBuff, "Default Lease: %u (sec)", cfig.lease);
}
logDHCPMess(logBuff, 1);
getInterfaces(&newNetwork);
memcpy(cfig.oldservers, newNetwork.allServers, (MAX_SERVERS * sizeof(MYDWORD)));
do {
bool bindfailed = false;
newNetwork.maxFD = 0;
//printf("Setting DHCP Sockets\n");
int i = 0;
for (int j = 0; j < MAX_SERVERS && newNetwork.listenServers[j]; j++) {
int k = 0;
for (; k < MAX_SERVERS && network.dhcpConn[k].loaded; k++) {
if (network.dhcpConn[k].ready && network.dhcpConn[k].server == newNetwork.listenServers[j]) {
break;
}
}
if (network.dhcpConn[k].ready && network.dhcpConn[k].server == newNetwork.listenServers[j]) {
memcpy(&(newNetwork.dhcpConn[i]), &(network.dhcpConn[k]), sizeof(DhcpConnType));
if (newNetwork.maxFD < newNetwork.dhcpConn[i].sock) {
newNetwork.maxFD = newNetwork.dhcpConn[i].sock;
}
network.dhcpConn[k].ready = false;
i++;
continue;
} else {
newNetwork.dhcpConn[i].sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (newNetwork.dhcpConn[i].sock == INVALID_SOCKET) {
bindfailed = true;
sprintf(logBuff, "Failed to Create Socket");
logDHCPMess(logBuff, 1);
continue;
}
//printf("Socket %u\n", newNetwork.dhcpConn[i].sock);
newNetwork.dhcpConn[i].addr.sin_family = AF_INET;
newNetwork.dhcpConn[i].addr.sin_addr.s_addr = newNetwork.listenServers[j];
newNetwork.dhcpConn[i].addr.sin_port = htons(IPPORT_DHCPS);
newNetwork.dhcpConn[i].reUseVal = true;
newNetwork.dhcpConn[i].reUseSize = sizeof(newNetwork.dhcpConn[i].reUseVal);
setsockopt(newNetwork.dhcpConn[i].sock,
SOL_SOCKET,
SO_REUSEADDR,
(char *)&newNetwork.dhcpConn[i].reUseVal,
newNetwork.dhcpConn[i].reUseSize);
newNetwork.dhcpConn[i].broadCastVal = true;
newNetwork.dhcpConn[i].broadCastSize = sizeof(newNetwork.dhcpConn[i].broadCastVal);
setsockopt(newNetwork.dhcpConn[i].sock,
SOL_SOCKET,
SO_BROADCAST,
(char *)&newNetwork.dhcpConn[i].broadCastVal,
newNetwork.dhcpConn[i].broadCastSize);
int nRet = bind(newNetwork.dhcpConn[i].sock,
(sockaddr *)&newNetwork.dhcpConn[i].addr,
sizeof(struct sockaddr_in));
if (nRet == SOCKET_ERROR) {
bindfailed = true;
close(newNetwork.dhcpConn[i].sock);
sprintf(logBuff, "%s Port 67 already in use", IP2String(ipbuff, newNetwork.listenServers[j]));
logDHCPMess(logBuff, 1);
continue;
}
newNetwork.dhcpConn[i].loaded = true;
newNetwork.dhcpConn[i].ready = true;
if (newNetwork.maxFD < newNetwork.dhcpConn[i].sock) {
newNetwork.maxFD = newNetwork.dhcpConn[i].sock;
}
newNetwork.dhcpConn[i].server = newNetwork.listenServers[j];
newNetwork.dhcpConn[i].mask = newNetwork.listenMasks[j];
newNetwork.dhcpConn[i].port = IPPORT_DHCPS;
i++;
}
}
if (network.dhcpListener.ready) {
memcpy(&(newNetwork.dhcpListener), &(network.dhcpListener), sizeof(DhcpConnType));
if (newNetwork.maxFD < newNetwork.dhcpListener.sock) {
newNetwork.maxFD = newNetwork.dhcpListener.sock;
}
network.dhcpListener.ready = false;
} else {
newNetwork.dhcpListener.sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (newNetwork.dhcpListener.sock == INVALID_SOCKET) {
bindfailed = true;
sprintf(logBuff, "Failed to Creat DHCP Socket");
logDHCPMess(logBuff, 1);
} else {
newNetwork.dhcpListener.reUseVal = true;
newNetwork.dhcpListener.reUseSize = sizeof(newNetwork.dhcpListener.reUseVal);
setsockopt(newNetwork.dhcpListener.sock,
SOL_SOCKET,
SO_REUSEADDR,
(char *)&newNetwork.dhcpListener.reUseVal,
newNetwork.dhcpListener.reUseSize);
newNetwork.dhcpListener.pktinfoVal = true;
newNetwork.dhcpListener.pktinfoSize = sizeof(newNetwork.dhcpListener.pktinfoVal);
setsockopt(newNetwork.dhcpListener.sock,
IPPROTO_IP,
IP_PKTINFO,
&newNetwork.dhcpListener.pktinfoVal,
newNetwork.dhcpListener.pktinfoSize);
newNetwork.dhcpListener.addr.sin_family = AF_INET;
newNetwork.dhcpListener.addr.sin_addr.s_addr = INADDR_ANY;
newNetwork.dhcpListener.addr.sin_port = htons(IPPORT_DHCPS);
int nRet = bind(newNetwork.dhcpListener.sock,
(sockaddr *)&newNetwork.dhcpListener.addr,
sizeof(struct sockaddr_in));
if (nRet == SOCKET_ERROR) {
bindfailed = true;
close(newNetwork.dhcpListener.sock);
sprintf(logBuff, "DHCP Port 67 already in use");
logDHCPMess(logBuff, 1);
} else {
newNetwork.dhcpListener.loaded = true;
newNetwork.dhcpListener.ready = true;
if (newNetwork.maxFD < newNetwork.dhcpListener.sock) {
newNetwork.maxFD = newNetwork.dhcpListener.sock;
}
}
}
}
#if 1
network.httpConn.ready = false;
#ifdef HTTPSERVER_ON
opendhcp_init_http_server();
#endif
#else
newNetwork.httpConn.port = 6789;
newNetwork.httpConn.server = newNetwork.dhcpConn[0].server;
newNetwork.httpConn.loaded = true;
if ((f = openSection("HTTP_INTERFACE", 1))) {
while (readSection(raw, f)) {
mySplit(name, value, raw, '=');
if (!strcasecmp(name, "HTTPServer")) {
mySplit(name, value, value, ':');
if (isIP(name)) {
newNetwork.httpConn.loaded = true;
newNetwork.httpConn.server = inet_addr(name);
} else {
newNetwork.httpConn.loaded = false;
sprintf(logBuff, "Warning: Section [HTTP_INTERFACE], Invalid IP Address %s, ignored", name);
logDHCPMess(logBuff, 1);
}
if (value[0]) {
if (STR2INT(value)) {
newNetwork.httpConn.port = STR2INT(value);
} else {
newNetwork.httpConn.loaded = false;
sprintf(logBuff, "Warning: Section [HTTP_INTERFACE], Invalid port %s, ignored", value);
logDHCPMess(logBuff, 1);
}
}
if (newNetwork.httpConn.server != inet_addr("127.0.0.1") &&
!findServer(newNetwork.allServers, MAX_SERVERS, newNetwork.httpConn.server)) {
newNetwork.httpConn.loaded = false;
sprintf(logBuff, "Warning: Section [HTTP_INTERFACE], %s not available, ignored", raw);
logDHCPMess(logBuff, 1);
}
} else if (!strcasecmp(name, "HTTPClient")) {
if (isIP(value)) {
addServer(cfig.httpClients, 8, inet_addr(value));
} else {
sprintf(logBuff, "Warning: Section [HTTP_INTERFACE], invalid client IP %s, ignored", raw);
logDHCPMess(logBuff, 1);
}
} else if (!strcasecmp(name, "HTTPTitle")) {
strncpy(htmlTitle, value, 255);
htmlTitle[255] = 0;
} else {
sprintf(logBuff, "Warning: Section [HTTP_INTERFACE], invalid entry %s, ignored", raw);
logDHCPMess(logBuff, 1);
}
}
}
if (!htmlTitle[0]) {
sprintf(htmlTitle, "%s on %s", serviceName, cfig.servername);
}
if (newNetwork.httpConn.loaded) {
if (network.httpConn.ready && network.httpConn.server == newNetwork.httpConn.server &&
network.httpConn.port == newNetwork.httpConn.port) {
memcpy(&(newNetwork.httpConn), &(network.httpConn), sizeof(ConnType));
if (newNetwork.httpConn.sock > newNetwork.maxFD) {
newNetwork.maxFD = newNetwork.httpConn.sock;
}
network.httpConn.ready = false;
} else if (newNetwork.httpConn.server) {
newNetwork.httpConn.sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (newNetwork.httpConn.sock == INVALID_SOCKET) {
bindfailed = true;
sprintf(logBuff, "Failed to Create Socket");
logDHCPMess(logBuff, 1);
} else {
//printf("Socket %u\n", newNetwork.httpConn.sock);
newNetwork.httpConn.addr.sin_family = AF_INET;
newNetwork.httpConn.addr.sin_addr.s_addr = newNetwork.httpConn.server;
newNetwork.httpConn.addr.sin_port = htons(newNetwork.httpConn.port);
int nRet = bind(newNetwork.httpConn.sock,
(sockaddr *)&newNetwork.httpConn.addr,
sizeof(struct sockaddr_in));
if (nRet == SOCKET_ERROR) {
bindfailed = true;
sprintf(logBuff,
"Http Interface %s TCP Port %u not available",
IP2String(ipbuff, newNetwork.httpConn.server),
newNetwork.httpConn.port);
logDHCPMess(logBuff, 1);
closesocket(newNetwork.httpConn.sock);
} else {
nRet = listen(newNetwork.httpConn.sock, SOMAXCONN);
if (nRet == SOCKET_ERROR) {
bindfailed = true;
sprintf(logBuff,
"%s TCP Port %u Error on Listen",
IP2String(ipbuff, newNetwork.httpConn.server),
newNetwork.httpConn.port);
logDHCPMess(logBuff, 1);
closesocket(newNetwork.httpConn.sock);
} else {
newNetwork.httpConn.loaded = true;
newNetwork.httpConn.ready = true;
if (newNetwork.httpConn.sock > newNetwork.maxFD) {
newNetwork.maxFD = newNetwork.httpConn.sock;
}
}
}
}
}
}
#endif
for (MYBYTE m = 0; m < MAX_SERVERS && newNetwork.allServers[m]; m++) {
lockIP(newNetwork.allServers[m]);
}
for (MYBYTE m = 0; m < MAX_SERVERS && newNetwork.dns[m]; m++) {
lockIP(newNetwork.dns[m]);
}
if (bindfailed) {
cfig.failureCount++;
} else {
cfig.failureCount = 0;
}
closeConn();
newNetwork.maxFD++;
memcpy(&network, &newNetwork, sizeof(data1));
//printf("%i %i %i\n", network.dhcpConn[0].ready, network.dnsUdpConn[0].ready, network.dnsTcpConn[0].ready);
if (!network.dhcpConn[0].ready) {
sprintf(logBuff, "No Static Interface ready, Waiting...");
logDHCPMess(logBuff, 1);
continue;
}
if (cfig.replication == 1) {
sprintf(logBuff, "Server Name: %s (Primary)", cfig.servername);
} else if (cfig.replication == 2) {
sprintf(logBuff, "Server Name: %s (Secondary)", cfig.servername);
} else {
sprintf(logBuff, "Server Name: %s", cfig.servername);
}
logDHCPMess(logBuff, 1);
if (network.httpConn.ready) {
sprintf(logBuff,
"Lease Status URL: http://%s:%u",
IP2String(ipbuff, network.httpConn.server),
network.httpConn.port);
logDHCPMess(logBuff, 1);
}
for (int k = 0; k < MAX_SERVERS && network.listenServers[k]; k++) {
for (MYBYTE j = 0; j < MAX_SERVERS; j++) {
if (!network.dhcpConn[j].server && !network.dnsUdpConn[j].server) {
break;
} else if (network.dhcpConn[j].server == network.listenServers[k] ||
network.dnsUdpConn[j].server == network.listenServers[k]) {
sprintf(logBuff, "Listening On: %s", IP2String(ipbuff, network.listenServers[k]));
logDHCPMess(logBuff, 1);
break;
}
}
}
} while (detectChange());
pthread_exit(nullptr);
}
bool detectChange() {
char logBuff[256];
network.ready = true;
while (kRunning) {
sleep(20);
//printf("Checking Networks (failue count=%u, failue cycle=%u)..\n", cfig.failureCount, cfig.failureCycle);
if (cfig.failureCount) {
cfig.failureCycle++;
if (kRunning && cfig.failureCycle == (MYDWORD)pow(2, cfig.failureCount)) {
sprintf(logBuff, "Retrying failed Listening Interfaces..");
logDHCPMess(logBuff, 1);
break;
}
} else if (getInterfaces(&newNetwork)) {
memcpy(cfig.oldservers, newNetwork.allServers, (MAX_SERVERS * sizeof(MYDWORD)));
sprintf(logBuff, "Network changed, re-detecting Listening Interfaces..");
logDHCPMess(logBuff, 1);
break;
} else {
cfig.failureCycle = 0;
}
}
network.ready = false;
while (kRunning && network.busy) {
sleep(1);
}
return (kRunning);
}
bool getInterfaces(data1 *pNetwork) {
char logBuff[256];
char ipbuff[32];
memset(pNetwork, 0, sizeof(data1));
Ifc.ifc_len = sizeof(IfcBuf);
Ifc.ifc_buf = (char *)IfcBuf;
if (ioctl(cfig.fixedSocket, SIOCGIFCONF, &Ifc) >= 0) {
MYDWORD addr, mask;
short flags;
struct ifreq pIfr {};
MYBYTE numInterfaces = Ifc.ifc_len / sizeof(ifreq);
for (MYBYTE i = 0; i < numInterfaces; i++) {
memcpy(&pIfr, &(IfcBuf[i]), sizeof(ifreq));
if (!ioctl(cfig.fixedSocket, SIOCGIFADDR, &pIfr)) {
addr = ((struct sockaddr_in *)&pIfr.ifr_addr)->sin_addr.s_addr;
} else {
addr = 0;
}
if (!ioctl(cfig.fixedSocket, SIOCGIFNETMASK, &pIfr)) {
mask = ((struct sockaddr_in *)&pIfr.ifr_addr)->sin_addr.s_addr;
} else {
mask = 0;
}
if (!ioctl(cfig.fixedSocket, SIOCGIFFLAGS, &pIfr)) {
flags = pIfr.ifr_flags;
} else {
flags = 0;
}
if (addr && mask && (flags & IFF_RUNNING) && (flags & IFF_UP) && !(flags & IFF_LOOPBACK) &&
!(flags & IFF_POINTOPOINT)) {
addServer(pNetwork->allServers, MAX_SERVERS, addr);
if (!(flags & IFF_DYNAMIC)) {
MYBYTE k = addServer(pNetwork->staticServers, MAX_SERVERS, addr);
if (k < MAX_SERVERS) {
pNetwork->staticMasks[k] = mask;
}
}
}
}
}
if (!memcmp(cfig.oldservers, pNetwork->allServers, (MAX_SERVERS * sizeof(MYDWORD)))) {
return false;
}
if (cfig.specifiedServers[0]) {
for (MYBYTE i = 0; i < MAX_SERVERS && cfig.specifiedServers[i]; i++) {
MYBYTE j = 0;
for (; j < MAX_SERVERS && pNetwork->staticServers[j]; j++) {
if (pNetwork->staticServers[j] == cfig.specifiedServers[i]) {
MYBYTE k = addServer(pNetwork->listenServers, MAX_SERVERS, pNetwork->staticServers[j]);
if (k < MAX_SERVERS) {
pNetwork->listenMasks[k] = pNetwork->staticMasks[j];
}
break;
}
}
if (j == MAX_SERVERS || !pNetwork->staticServers[j]) {
if (findServer(pNetwork->allServers, MAX_SERVERS, cfig.specifiedServers[i])) {
sprintf(logBuff,
"Warning: Section [LISTEN_ON] Interface %s is not static, ignored",
IP2String(ipbuff, cfig.specifiedServers[i]));
} else {
sprintf(logBuff,
"Warning: Section [LISTEN_ON] Interface %s is not found, ignored",
IP2String(ipbuff, cfig.specifiedServers[i]));
}
logDHCPMess(logBuff, 2);
}
}
} else {
for (MYBYTE i = 0; i < MAX_SERVERS && pNetwork->allServers[i]; i++) {
MYBYTE j = 0;
for (; j < MAX_SERVERS && pNetwork->staticServers[j]; j++) {
if (pNetwork->staticServers[j] == pNetwork->allServers[i]) {
MYBYTE k = addServer(pNetwork->listenServers, MAX_SERVERS, pNetwork->staticServers[j]);
if (k < MAX_SERVERS) {
pNetwork->listenMasks[k] = pNetwork->staticMasks[j];
}
break;
}
}
if (j == MAX_SERVERS || !pNetwork->staticServers[j]) {
sprintf(logBuff,
"Warning: Interface %s is not Static, ignored",
IP2String(ipbuff, pNetwork->allServers[i]));
logDHCPMess(logBuff, 2);
}
}
}
if (!cfig.zone[0]) {
getdomainname(cfig.zone, sizeof(cfig.zone));
cfig.zLen = strlen(cfig.zone);
}
gethostname(cfig.servername, sizeof(cfig.servername));
char *ptr = strchr(cfig.servername, '.');
if (ptr) {
*ptr = 0;
if (!strncmp(cfig.zone, "(none)", 6) || !cfig.zone[0]) {
ptr++;
strcpy(cfig.zone, ptr);
cfig.zLen = strlen(cfig.zone);
}
}
if (!strncmp(cfig.zone, "(none)", 6) || !cfig.zone[0]) {
strcpy(cfig.zone, "workgroup");
cfig.zLen = strlen(cfig.zone);
}
return true;
}
void *updateStateFile(void *lparam) {
pthread_mutex_lock(&mutStateFile);
auto *dhcpEntry = (data7 *)lparam;
data8 dhcpData {};
memset(&dhcpData, 0, sizeof(data8));
MYBYTE bp_hlen = 16;
getHexValue(dhcpData.bp_chaddr, dhcpEntry->mapname, &bp_hlen);
dhcpData.bp_hlen = bp_hlen;
dhcpData.ip = dhcpEntry->ip;
dhcpData.subnetFlg = dhcpEntry->subnetFlg;
dhcpData.expiry = dhcpEntry->expiry;
dhcpData.local = dhcpEntry->local;
strcpy(dhcpData.hostname, dhcpEntry->hostname);
if (!dhcpEntry->dhcpInd) {
cfig.dhcpInd += 1;
dhcpEntry->dhcpInd = cfig.dhcpInd;
}
dhcpData.dhcpInd = dhcpEntry->dhcpInd;
FILE *f = fopen(leaFile, "rb+");
if (f) {
if (fseek(f, (long)((dhcpData.dhcpInd - 1) * sizeof(data8)), SEEK_SET) >= 0) {
fwrite(&dhcpData, sizeof(data8), 1, f);
}
fclose(f);
}
pthread_mutex_unlock(&mutStateFile);
pthread_exit(nullptr);
}
#if 0
void debug(const char *mess) {
char ts[254];
strcpy(ts, mess);
logDHCPMess(ts, 1);
}
void debug(int i) {
char ts[254];
sprintf(ts, "%i", i);
logDHCPMess(ts, 1);
}
void *logThread(void *lpParam) {
pthread_mutex_lock(&mutLogFile);
char *mess = (char *)lpParam;
time_t ts = time(nullptr);
tm *ttm = localtime(&ts);
char buffer[256];
strftime(buffer, sizeof(buffer), logFile, ttm);
if (strcmp(cfig.logFileName, buffer)) {
if (cfig.logFileName[0]) {
FILE *f = fopen(cfig.logFileName, "at");
if (f) {
fprintf(f, "Logging Continued on file %s\n", buffer);
fclose(f);
}
strcpy(cfig.logFileName, buffer);
f = fopen(cfig.logFileName, "at");
if (f) {
fprintf(f, "%s\n\n", sVersion);
fclose(f);
}
}
strcpy(cfig.logFileName, buffer);
}
FILE *f = fopen(cfig.logFileName, "at");
if (f) {
strftime(buffer, sizeof(buffer), "%d-%b-%y %X", ttm);
fprintf(f, "[%s] %s\n", buffer, mess);
fclose(f);
} else if (verbatim) {
printf("Failed top open log file %s", cfig.logFileName);
cfig.dhcpLogLevel = 0;
} else {
syslog(LOG_MAKEPRI(LOG_LOCAL1, LOG_CRIT), "Failed top open log file %s", cfig.logFileName);
cfig.dhcpLogLevel = 0;
}
free(mess);
pthread_mutex_unlock(&mutLogFile);
pthread_exit(nullptr);
}
void logDHCPMess(char *logBuff, MYBYTE logLevel) {
if (verbatim) {
printf("%s\n", logBuff);
}
if (logFile[0] && logLevel <= cfig.dhcpLogLevel) {
char *mess = cloneString(logBuff);
pthread_t threadId;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
int errcode = pthread_create(&threadId, &attr, logThread, mess);
pthread_attr_destroy(&attr);
}
}
void logDHCPMess(const char *title, const char *mess) {
char ts[512];
sprintf(ts, "%s %s", title, mess);
logDHCPMess(ts, 1);
}
#endif
MYWORD gdmess(data9 *req, MYBYTE sockInd) {
char ipbuff[32];
char logBuff[512];
memset(req, 0, sizeof(data9));
errno = 0;
if (sockInd == 255) {
int msgflags = 0;
req->iov[0].iov_base = req->raw;
req->iov[0].iov_len = sizeof(dhcp_packet);
req->msg.msg_iov = req->iov;
req->msg.msg_iovlen = 1;
req->msg.msg_name = &req->remote;
req->msg.msg_namelen = sizeof(sockaddr_in);
req->msg.msg_control = &req->msgcontrol;
req->msg.msg_controllen = sizeof(msg_control);
req->msg.msg_flags = msgflags;
int flags = 0;
req->bytes = (int)recvmsg(network.dhcpListener.sock, &req->msg, flags);
if (errno || req->bytes <= 0) {
return 0;
}
//printf("%u\n", req->msg.msg_controllen);
//msgcontrol = (msg_control*)msg.msg_control;
//struct in_addr local_addr;
//struct in_addr rem_addr;
//local_addr = msgcontrol->pktinfo.ipi_addr;
//rem_addr = msgcontrol->pktinfo.ipi_spec_dst;
//printf("IF = %u\n", req->msgcontrol.pktinfo.ipi_ifindex);
//printf("LADDR = %s\n", inet_ntoa(req->msgcontrol.pktinfo.ipi_addr));
//printf("RADDR = %s\n", inet_ntoa(req->msgcontrol. pktinfo.ipi_spec_dst));
MYDWORD addr = req->msgcontrol.pktinfo.ipi_spec_dst.s_addr;
//printf("%s\n",IP2String(tempbuff, addr));
if (!addr) {
return 0;
}
for (int i = 0;; i++) {
if (i == MAX_SERVERS || !network.dhcpConn[i].server) {
return 0;
} else if (addr == network.dhcpConn[i].server) {
req->sockInd = i;
break;
}
}
} else {
req->sockInd = sockInd;
req->sockLen = sizeof(req->remote);
errno = 0;
req->bytes = (int)recvfrom(network.dhcpConn[sockInd].sock,
req->raw,
sizeof(dhcp_packet),
0,
(sockaddr *)&req->remote,
&req->sockLen);
if (errno || req->bytes <= 0) {
return 0;
}
}
if (req->dhcpp.header.bp_op != BOOTP_REQUEST) {
return 0;
}
hex2String(req->chaddr, req->dhcpp.header.bp_chaddr, req->dhcpp.header.bp_hlen);
data3 *op;
MYBYTE *raw = req->dhcpp.vend_data;
MYBYTE *rawEnd = raw + (req->bytes - sizeof(dhcp_header));
for (; raw < rawEnd && *raw != DHCP_OPTION_END;) {
op = (data3 *)raw;
//printf("OpCode=%u,MessType=%u\n", op->opt_code, op->value[0]);
switch (op->opt_code) {
case DHCP_OPTION_PAD:
raw++;
continue;
case DHCP_OPTION_PARAMREQLIST:
for (int ix = 0; ix < op->size; ix++) {
req->paramreqlist[op->value[ix]] = 1;
}
break;
case DHCP_OPTION_MESSAGETYPE:
req->req_type = op->value[0];
break;
case DHCP_OPTION_SERVERID:
req->server = fIP(op->value);
break;
case DHCP_OPTION_IPADDRLEASE:
req->lease = fULong(op->value);
break;
case DHCP_OPTION_MAXDHCPMSGSIZE:
req->messsize = fUShort(op->value);
break;
case DHCP_OPTION_REQUESTEDIPADDR:
req->reqIP = fIP(op->value);
break;
case DHCP_OPTION_HOSTNAME:
memcpy(req->hostname, op->value, op->size);
req->hostname[op->size] = 0;
req->hostname[64] = 0;
if (char *ptr = strchr(req->hostname, '.')) {
*ptr = 0;
}
break;
case DHCP_OPTION_VENDORCLASSID:
memcpy(&req->vendClass, op, op->size + 2);
if (op->size > 16) {
if (process_iptv_multicast(op->value, op->size, req->chaddr) == 0) {
return 0;
}
}
break;
case DHCP_OPTION_USERCLASS:
memcpy(&req->userClass, op, op->size + 2);
break;
case DHCP_OPTION_RELAYAGENTINFO:
memcpy(&req->agentOption, op, op->size + 2);
break;
case DHCP_OPTION_CLIENTID:
memcpy(&req->clientId, op, op->size + 2);
break;
case DHCP_OPTION_SUBNETSELECTION:
memcpy(&req->subnet, op, op->size + 2);
req->subnetIP = fIP(op->value);
break;
case DHCP_OPTION_REBINDINGTIME:
req->rebind = fULong(op->value);
break;
}
raw += 2;
raw += op->size;
}
if (!req->subnetIP) {
req->subnetIP = req->dhcpp.header.bp_giaddr;
}
if (!req->messsize) {
if (req->req_type == DHCP_MESS_NONE) {
req->messsize = req->bytes;
} else {
req->messsize = sizeof(dhcp_packet);
}
}
// if (!req->hostname[0] && req->dhcpp.header.bp_ciaddr)
// {
// data7* cache = findEntry(IP2String(ipbuff, htonl(req->dhcpp.header.bp_ciaddr)), DNS_TYPE_PTR);
//
// if (cache)
// strcpy(req->hostname, cache->hostname);
// }
//
// if ((req->req_type == 1 || req->req_type == 3) && cfig.dhcpLogLevel == 3)
// {
// data9 *req1 = (data9*)calloc(1, sizeof(data9));
// memcpy(req1, req, sizeof(data9));
// _beginthread(logDebug, 0, req1);
// }
if (verbatim || cfig.dhcpLogLevel >= 2) {
if (req->req_type == DHCP_MESS_NONE) {
if (req->dhcpp.header.bp_giaddr) {
sprintf(logBuff,
"BOOTPREQUEST for %s (%s) from RelayAgent %s received",
req->chaddr,
req->hostname,
IP2String(ipbuff, req->dhcpp.header.bp_giaddr));
} else {
sprintf(logBuff,
"BOOTPREQUEST for %s (%s) from interface %s received",
req->chaddr,
req->hostname,
IP2String(ipbuff, network.dhcpConn[req->sockInd].server));
}
logDHCPMess(logBuff, 2);
} else if (req->req_type == DHCP_MESS_DISCOVER) {
if (req->dhcpp.header.bp_giaddr) {
sprintf(logBuff,
"DHCPDISCOVER for %s (%s) from RelayAgent %s received",
req->chaddr,
req->hostname,
IP2String(ipbuff, req->dhcpp.header.bp_giaddr));
} else {
sprintf(logBuff,
"DHCPDISCOVER for %s (%s) from interface %s received",
req->chaddr,
req->hostname,
IP2String(ipbuff, network.dhcpConn[req->sockInd].server));
}
logDHCPMess(logBuff, 2);
} else if (req->req_type == DHCP_MESS_REQUEST) {
if ((!req->server) || req->server == network.dhcpConn[req->sockInd].server) {
if (req->dhcpp.header.bp_giaddr) {
sprintf(logBuff,
"DHCPREQUEST for %s (%s) from RelayAgent %s received",
req->chaddr,
req->hostname,
IP2String(ipbuff, req->dhcpp.header.bp_giaddr));
} else {
sprintf(logBuff,
"DHCPREQUEST for %s (%s) from interface %s received",
req->chaddr,
req->hostname,
IP2String(ipbuff, network.dhcpConn[req->sockInd].server));
}
logDHCPMess(logBuff, 2);
}
}
}
req->vp = req->dhcpp.vend_data;
memset(req->vp, 0, sizeof(dhcp_packet) - sizeof(dhcp_header));
//printf("end bytes=%u\n", req->bytes);
return 1;
}
data7 *createCache(data71 *pLump) {
MYWORD dataSize = 70 + sizeof(data7) + strlen(pLump->mapname) + pLump->optionSize;
auto *cache = (data7 *)calloc(1, dataSize);
if (!cache) {
return nullptr;
}
MYBYTE *dp = &cache->data;
cache->mapname = (char *)dp;
strcpy(cache->mapname, pLump->mapname);
dp += strlen(cache->mapname);
dp++;
cache->hostname = (char *)dp;
if (pLump->hostname) {
strcpy(cache->hostname, pLump->hostname);
}
dp += 65;
if (pLump->optionSize >= 3) {
cache->options = dp;
memcpy(cache->options, pLump->options, pLump->optionSize);
} else {
cache->options = nullptr;
}
return cache;
}