5413 lines
179 KiB
C++
5413 lines
179 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. *
|
|
***************************************************************************/
|
|
// opendhcpd.cpp //
|
|
#include <string>
|
|
#include <cmath>
|
|
#include <map>
|
|
using namespace std;
|
|
#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 <fcntl.h>
|
|
#include <cerrno>
|
|
#include <memory.h>
|
|
#include <sys/stat.h>
|
|
#include <cstdlib>
|
|
#include <syslog.h>
|
|
#include <zlog.h>
|
|
#include "opendhcpd.h"
|
|
#include "dhcpd.h"
|
|
#include "task_manager.h"
|
|
#include "user_errno.h"
|
|
|
|
void on_system_exit(void *p);
|
|
//Global Variables
|
|
timeval tv;
|
|
fd_set readfds;
|
|
//fd_set writefds;
|
|
data9 dhcpr;
|
|
data9 token;
|
|
data1 network;
|
|
data1 newNetwork;
|
|
data2 cfig;
|
|
data71 lump;
|
|
bool kRunning = true;
|
|
dhcpMap dhcpCache;
|
|
char serviceName[] = "OpenDHCPServer";
|
|
int ERR_PARAM;
|
|
//char tempbuff[512] = "";
|
|
//char logBuff[256];
|
|
//char extbuff[256] = "";
|
|
bool verbatim = false;
|
|
char iniFile[256] = "";
|
|
char leaFile[256] = "";
|
|
//char logFile[256] = "";
|
|
char filePATH[256] = "";
|
|
char htmlTitle[256] = "";
|
|
char nicif[256] = "";
|
|
//char arpa[] = ".in-addr.arpa";
|
|
time_t t = time(nullptr);
|
|
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 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.80 Linux Build 1054";
|
|
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</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, false},
|
|
{"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, 2 , 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] = "";
|
|
|
|
task_add_exit_event_handler(on_system_exit, nullptr);
|
|
#if 0
|
|
//printf("%i\n", argc);
|
|
/*
|
|
logBuff[0] = 0;
|
|
char *ds = strrchr(argv[0], '/');
|
|
|
|
if (ds)
|
|
ds++;
|
|
else
|
|
ds = argv[0];
|
|
|
|
sprintf(tempbuff, "ps -e | grep -v grep | grep -v \"rc.%s\" | grep \"%s$\" | head -1 | 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], "-l") && argc > i + 1 && argv[i + 1][0] != '-') {
|
|
myTrim(logFile, 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], "-k") && argc > i + 1 && argv[i + 1][0] != '-') {
|
|
myTrim(nicif, argv[i + 1]);
|
|
i++;
|
|
} else if (!strncasecmp(argv[i], "-i", 2))
|
|
myTrim(iniFile, argv[i] + 2);
|
|
else if (!strncasecmp(argv[i], "-l", 2))
|
|
myTrim(logFile, argv[i] + 2);
|
|
else if (!strncasecmp(argv[i], "-s", 2))
|
|
myTrim(leaFile, argv[i] + 2);
|
|
else if (!strncasecmp(argv[i], "-k", 2))
|
|
myTrim(nicif, argv[i] + 2);
|
|
else
|
|
sprintf(logBuff, "Error: Invalid Argument %s", argv[i]);
|
|
}
|
|
#endif
|
|
|
|
verbatim = (daemon > 0) ? true : false;
|
|
|
|
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);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
if (getuid()) {
|
|
printf("Error: Only root should run this program\n");
|
|
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");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
while (kRunning) {
|
|
if (!network.dhcpConn[0].ready || !network.ready) {
|
|
sleep(1);
|
|
network.busy = false;
|
|
continue;
|
|
}
|
|
|
|
network.busy = true;
|
|
FD_ZERO(&readfds);
|
|
tv.tv_sec = 20;
|
|
tv.tv_usec = 0;
|
|
|
|
if (network.httpConn.ready) {
|
|
FD_SET(network.httpConn.sock, &readfds);
|
|
}
|
|
|
|
for (int i = 0; i < MAX_SERVERS && network.dhcpConn[i].ready; i++) {
|
|
FD_SET(network.dhcpConn[i].sock, &readfds);
|
|
}
|
|
|
|
FD_SET(network.dhcpListener.sock, &readfds);
|
|
|
|
if (cfig.replication) {
|
|
FD_SET(cfig.dhcpReplConn.sock, &readfds);
|
|
}
|
|
|
|
//printf("%i\n",select(network.maxFD, &readfds, nullptr, nullptr, &tv));
|
|
if (select(network.maxFD, &readfds, nullptr, nullptr, &tv)) {
|
|
t = time(nullptr);
|
|
network.busy = true;
|
|
|
|
if (network.httpConn.ready && FD_ISSET(network.httpConn.sock, &readfds)) {
|
|
auto *req = (data19 *)calloc(1, sizeof(data19));
|
|
|
|
if (req) {
|
|
req->sockLen = sizeof(req->remote);
|
|
errno = 0;
|
|
req->sock = accept(network.httpConn.sock, (sockaddr *)&req->remote, &req->sockLen);
|
|
|
|
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, 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);
|
|
}
|
|
}
|
|
|
|
if (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;
|
|
}
|
|
}
|
|
} else {
|
|
t = time(nullptr);
|
|
}
|
|
}
|
|
} else {
|
|
if (logBuff[0]) {
|
|
syslog(LOG_MAKEPRI(LOG_LOCAL1, LOG_CRIT), "%s", logBuff);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
if (getuid()) {
|
|
syslog(LOG_MAKEPRI(LOG_LOCAL1, LOG_CRIT), "%s", "Only root should run this program");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
/* Our process ID and Session ID */
|
|
pid_t sid, pid;
|
|
|
|
/* 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 */
|
|
memset(&cfig, 0, sizeof(cfig));
|
|
cfig.ppid = getpid();
|
|
data9 dhcpr_local {};
|
|
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");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
/* The Big Loop */
|
|
while (kRunning) {
|
|
if (!network.dhcpConn[0].ready || !network.ready) {
|
|
sleep(1);
|
|
network.busy = false;
|
|
continue;
|
|
}
|
|
|
|
network.busy = true;
|
|
|
|
FD_ZERO(&readfds);
|
|
tv.tv_sec = 20;
|
|
tv.tv_usec = 0;
|
|
|
|
if (network.httpConn.ready) {
|
|
FD_SET(network.httpConn.sock, &readfds);
|
|
}
|
|
|
|
for (int i = 0; i < MAX_SERVERS && network.dhcpConn[i].ready; i++) {
|
|
FD_SET(network.dhcpConn[i].sock, &readfds);
|
|
}
|
|
|
|
FD_SET(network.dhcpListener.sock, &readfds);
|
|
|
|
if (cfig.replication) {
|
|
FD_SET(cfig.dhcpReplConn.sock, &readfds);
|
|
}
|
|
|
|
//printf("%i\n",select(network.maxFD, &readfds, nullptr, nullptr, &tv));
|
|
if (select(network.maxFD, &readfds, nullptr, nullptr, &tv)) {
|
|
t = time(nullptr);
|
|
network.busy = true;
|
|
|
|
if (network.httpConn.ready && FD_ISSET(network.httpConn.sock, &readfds)) {
|
|
auto *req = (data19 *)calloc(1, sizeof(data19));
|
|
|
|
if (req) {
|
|
req->sockLen = sizeof(req->remote);
|
|
errno = 0;
|
|
req->sock = accept(network.httpConn.sock, (sockaddr *)&req->remote, &req->sockLen);
|
|
|
|
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, 0);
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < MAX_SERVERS && network.dhcpConn[i].ready; i++) {
|
|
if (FD_ISSET(network.dhcpConn[i].sock, &readfds) && gdmess(&dhcpr_local, i) &&
|
|
sdmess(&dhcpr_local)) {
|
|
alad(&dhcpr_local);
|
|
}
|
|
}
|
|
|
|
if (FD_ISSET(network.dhcpListener.sock, &readfds) && gdmess(&dhcpr_local, 255) &&
|
|
sdmess(&dhcpr_local)) {
|
|
alad(&dhcpr_local);
|
|
}
|
|
|
|
if (cfig.dhcpReplConn.ready && FD_ISSET(cfig.dhcpReplConn.sock, &readfds)) {
|
|
errno = 0;
|
|
dhcpr_local.sockLen = sizeof(dhcpr_local.remote);
|
|
dhcpr_local.bytes = (int)recvfrom(cfig.dhcpReplConn.sock,
|
|
dhcpr_local.raw,
|
|
sizeof(dhcpr_local.raw),
|
|
0,
|
|
(sockaddr *)&dhcpr_local.remote,
|
|
&dhcpr_local.sockLen);
|
|
|
|
//errno = WSAGetLastError();
|
|
|
|
if (errno || dhcpr_local.bytes <= 0) {
|
|
cfig.dhcpRepl = 0;
|
|
}
|
|
}
|
|
} else {
|
|
t = time(nullptr);
|
|
}
|
|
}
|
|
}
|
|
|
|
closeConn();
|
|
|
|
if (cfig.dhcpReplConn.ready) {
|
|
close(cfig.dhcpReplConn.sock);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void closeConn() {
|
|
if (network.dhcpListener.ready) {
|
|
close(network.dhcpListener.sock);
|
|
}
|
|
|
|
if (network.httpConn.ready) {
|
|
close(network.httpConn.sock);
|
|
}
|
|
|
|
for (int i = 0; i < MAX_SERVERS && network.dhcpConn[i].loaded; i++) {
|
|
if (network.dhcpConn[i].ready) {
|
|
close(network.dhcpConn[i].sock);
|
|
}
|
|
}
|
|
}
|
|
|
|
void on_system_exit(void *p) {
|
|
char logBuff[256];
|
|
|
|
//printf("%u=%u\n", cfig.ppid, getpid());
|
|
if (cfig.ppid == getpid()) {
|
|
network.ready = false;
|
|
kRunning = false;
|
|
sprintf(logBuff, "Closing Network Connections...");
|
|
logDHCPMess(logBuff, 1);
|
|
sleep(1);
|
|
|
|
closeConn();
|
|
|
|
if (cfig.dhcpReplConn.ready) {
|
|
close(cfig.dhcpReplConn.sock);
|
|
}
|
|
|
|
close(cfig.fixedSocket);
|
|
|
|
sprintf(logBuff, "Open DHCP Server Stopped !");
|
|
logDHCPMess(logBuff, 1);
|
|
sleep(1);
|
|
}
|
|
}
|
|
|
|
MYWORD fUShort(void *raw) {
|
|
return ntohs(*((MYWORD *)raw));
|
|
}
|
|
|
|
MYDWORD fUInt(void *raw) {
|
|
return ntohl(*((MYDWORD *)raw));
|
|
}
|
|
|
|
MYDWORD fIP(void *raw) {
|
|
return (*((MYDWORD *)raw));
|
|
}
|
|
|
|
MYBYTE pUShort(void *raw, MYWORD data) {
|
|
*((MYWORD *)raw) = htons(data);
|
|
return sizeof(MYWORD);
|
|
}
|
|
|
|
MYBYTE pUInt(void *raw, MYDWORD data) {
|
|
*((MYDWORD *)raw) = htonl(data);
|
|
return sizeof(MYDWORD);
|
|
}
|
|
|
|
MYBYTE pIP(void *raw, MYDWORD data) {
|
|
*((MYDWORD *)raw) = data;
|
|
return sizeof(MYDWORD);
|
|
}
|
|
|
|
void procHTTP(data19 *req) {
|
|
#if 0
|
|
static int recCnt = 0;
|
|
//debug("procHTTP");
|
|
char tempbuff[512];
|
|
char logBuff[256];
|
|
|
|
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;
|
|
}
|
|
|
|
errno = 0;
|
|
char buffer[1024] = {0};
|
|
req->bytes = (int)recv(req->sock, buffer, sizeof(buffer), 0);
|
|
//errno = WSAGetLastError();
|
|
|
|
recCnt++;
|
|
// printf("+++++++receive(%04d)\n", recCnt);
|
|
// printf("%s\n", buffer);
|
|
// printf("-------receive(%04d)\n", recCnt);
|
|
|
|
if (errno || req->bytes <= 0) {
|
|
sprintf(logBuff,
|
|
"HTTP Client %s, Message Receive failed, Error %s",
|
|
IP2String(tempbuff, req->remote.sin_addr.s_addr),
|
|
strerror(errno));
|
|
logDHCPMess(logBuff, 1);
|
|
closesocket(req->sock);
|
|
free(req);
|
|
return;
|
|
} else 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);
|
|
}
|
|
|
|
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->memSize = sizeof(send403);
|
|
req->bytes = sprintf(req->dp, "%s", send403);
|
|
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;
|
|
}
|
|
|
|
buffer[sizeof(buffer) - 1] = 0;
|
|
|
|
char *buffer1 = strdup(buffer);
|
|
|
|
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);
|
|
}
|
|
|
|
int judge_flag = method_Judge(req, buffer1);
|
|
if (judge_flag == 1 || judge_flag == 2)
|
|
return;
|
|
|
|
if (fp && !strcasecmp(fp, "/")) {
|
|
//sendStatus(req);
|
|
// 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, "%s", send404);
|
|
req->memSize = sizeof(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);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
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)");
|
|
} else if (cfig.replication == 2) {
|
|
fp += sprintf(fp, bodyStart, sVersion, cfig.servername, "(Secondary)");
|
|
} else {
|
|
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); // 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, " ");
|
|
}
|
|
|
|
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 sendScopeStatus(data19 *req)
|
|
{
|
|
//debug("sendScopeStatus");
|
|
|
|
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;
|
|
|
|
_beginthread(sendHTTP, 0, (void*)req);
|
|
return;
|
|
}
|
|
*/
|
|
|
|
/*
|
|
void *sendHTTP(void *lpParam)
|
|
{
|
|
data19 *req = (data19*)lpParam;
|
|
|
|
//sprintf(logBuff, "sendHTTP memsize=%d bytes=%d", req->memSize, req->bytes);
|
|
//(logBuff);
|
|
|
|
char *dp = req->dp;
|
|
timeval tv1;
|
|
fd_set writefds1;
|
|
char header[16];
|
|
int sent = 0;
|
|
byte 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 send200[] = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: close\r\nTransfer-Encoding: chunked\r\n";
|
|
send(req->sock, send200, strlen(send200), 0);
|
|
sendheader = false;
|
|
}
|
|
else if (req->bytes > 1024)
|
|
{
|
|
sprintf(header, "\r\n%04x\r\n", 1024);
|
|
send(req->sock, header, 8, 0);
|
|
sent = send(req->sock, dp, 1024, 0);
|
|
}
|
|
else if (req->bytes > 0)
|
|
{
|
|
sprintf(header, "\r\n%04x\r\n", req->bytes);
|
|
send(req->sock, header, 8, 0);
|
|
sent = send(req->sock, dp, req->bytes, 0);
|
|
}
|
|
else
|
|
{
|
|
sprintf(header, "\r\n%04x\r\n", 0);
|
|
send(req->sock, header, 8, 0);
|
|
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);
|
|
}
|
|
*/
|
|
|
|
/*
|
|
void *sendHTTP(void *lpParam)
|
|
{
|
|
data19 *req = (data19*)lpParam;
|
|
|
|
//sprintf(logBuff, "sendHTTP memsize=%d bytes=%d", req->memSize, req->bytes);
|
|
//(logBuff);
|
|
|
|
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 send200[] = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n";
|
|
send(req->sock, send200, strlen(send200), 0);
|
|
sendheader = false;
|
|
}
|
|
else if (req->bytes > 1024)
|
|
sent = send(req->sock, dp, 1024, 0);
|
|
else if (req->bytes > 0)
|
|
sent = 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);
|
|
}
|
|
*/
|
|
|
|
void *sendHTTP(void *lpParam) {
|
|
auto *req = (data19 *)lpParam;
|
|
|
|
//sprintf(logBuff, "sendHTTP memsize=%d bytes=%d", req->memSize, req->bytes);
|
|
//(logBuff);
|
|
|
|
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 send200
|
|
[] = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
|
|
"close\r\nContent-Length: %i\r\n\r\n";
|
|
char header[256];
|
|
sprintf(header, send200, 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] >= MY_MAX_TIME) {
|
|
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);
|
|
//logMess(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]);
|
|
//logMess(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);
|
|
//logMess(logBuff, 1);
|
|
|
|
if (!iipNew && iipExp) {
|
|
iipNew = iipExp;
|
|
}
|
|
|
|
if (iipNew) {
|
|
if (!req->dhcpEntry) {
|
|
memset(&lump, 0, sizeof(data71));
|
|
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 = MY_MAX_TIME;
|
|
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);
|
|
|
|
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, (void *)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;
|
|
}
|
|
|
|
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(req->remote));
|
|
} else {
|
|
req->bytes = (int)sendto(network.dhcpConn[req->sockInd].sock,
|
|
req->raw,
|
|
packSize,
|
|
0,
|
|
(sockaddr *)&cliAddr,
|
|
sizeof(req->remote));
|
|
}
|
|
|
|
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);
|
|
|
|
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, (void *)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);
|
|
|
|
if (!req->opAdded[DHCP_OPTION_IPADDRLEASE]) {
|
|
op.opt_code = DHCP_OPTION_IPADDRLEASE;
|
|
op.size = 4;
|
|
pUInt(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->opAdded[DHCP_OPTION_ROUTER])
|
|
{
|
|
op.opt_code = DHCP_OPTION_ROUTER;
|
|
op.size = 4;
|
|
pIP(op.value, network.dhcpConn[req->sockInd].server);
|
|
pvdata(req, &op);
|
|
}
|
|
|
|
if (req->clientId.opt_code == DHCP_OPTION_CLIENTID)
|
|
pvdata(req, &req->clientId);
|
|
*/
|
|
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 > fUInt(op->value)) {
|
|
req->lease = fUInt(op->value);
|
|
}
|
|
|
|
if (req->lease >= MY_MAX_TIME) {
|
|
req->lease = UINT_MAX;
|
|
}
|
|
|
|
pUInt(op->value, req->lease);
|
|
} else if (op->opt_code == DHCP_OPTION_REBINDINGTIME) {
|
|
req->rebind = fUInt(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;
|
|
setLeaseExpiry(dhcpEntry);
|
|
}
|
|
}
|
|
|
|
void setLeaseExpiry(data7 *dhcpEntry, MYDWORD lease) {
|
|
//printf("%d=%d\n", t, lease);
|
|
if (dhcpEntry && dhcpEntry->ip) {
|
|
if (lease > (MYDWORD)(MY_MAX_TIME - t)) {
|
|
dhcpEntry->expiry = MY_MAX_TIME;
|
|
} else {
|
|
dhcpEntry->expiry = t + lease;
|
|
}
|
|
|
|
setLeaseExpiry(dhcpEntry);
|
|
}
|
|
}
|
|
|
|
void setLeaseExpiry(data7 *dhcpEntry) {
|
|
if (dhcpEntry && dhcpEntry->ip) {
|
|
int ind = getIndex((char)dhcpEntry->rangeInd, dhcpEntry->ip);
|
|
|
|
if (ind >= 0) {
|
|
cfig.dhcpRanges[dhcpEntry->rangeInd].dhcpEntry[ind] = dhcpEntry;
|
|
|
|
if (cfig.dhcpRanges[dhcpEntry->rangeInd].expiry[ind] < MY_MAX_TIME) {
|
|
cfig.dhcpRanges[dhcpEntry->rangeInd].expiry[ind] = dhcpEntry->expiry;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void lockIP(MYDWORD 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] < MY_MAX_TIME) {
|
|
cfig.dhcpRanges[rangeInd].expiry[ind] = MY_MAX_TIME;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void *sendToken(void *lpParam) {
|
|
//debug("Send Token");
|
|
sleep(10);
|
|
|
|
while (true) {
|
|
errno = 0;
|
|
|
|
sendto(cfig.dhcpReplConn.sock, token.raw, token.bytes, 0, (sockaddr *)&token.remote, sizeof(token.remote));
|
|
|
|
// errno = WSAGetLastError();
|
|
//
|
|
// if (!errno && verbatim || cfig.dhcpLogLevel >= 2)
|
|
// {
|
|
// sprintf(logBuff, "Token Sent");
|
|
// logDHCPMess(logBuff, 2);
|
|
// }
|
|
|
|
sleep(300);
|
|
}
|
|
|
|
pthread_exit(nullptr);
|
|
}
|
|
|
|
MYDWORD sendRepl(data9 *req) {
|
|
char ipBuff[16];
|
|
char logBuff[256];
|
|
|
|
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;
|
|
// pUInt(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 (verbatim || cfig.dhcpLogLevel >= 2)
|
|
// {
|
|
// sprintf(logBuff, "Token Received");
|
|
// logDHCPMess(logBuff, 2);
|
|
// }
|
|
|
|
if (cfig.replication == 1) {
|
|
errno = 0;
|
|
|
|
sendto(cfig.dhcpReplConn.sock, token.raw, token.bytes, 0, (sockaddr *)&token.remote, sizeof(token.remote));
|
|
|
|
// errno = WSAGetLastError();
|
|
//
|
|
// if (!errno && (verbatim || cfig.dhcpLogLevel >= 2))
|
|
// {
|
|
// sprintf(logBuff, "Token Responded");
|
|
// logDHCPMess(logBuff, 2);
|
|
// }
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
int rInd = getRangeInd(ip);
|
|
req->dhcpEntry = findDHCPEntry(req->chaddr);
|
|
|
|
if (req->dhcpEntry && req->dhcpEntry->ip != ip) {
|
|
if (req->dhcpEntry->fixed || rInd < 0) {
|
|
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.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;
|
|
|
|
MYDWORD hangTime = req->lease;
|
|
|
|
if (hangTime) {
|
|
if (req->rebind > hangTime) {
|
|
hangTime = req->rebind;
|
|
}
|
|
} else {
|
|
hangTime = UINT_MAX;
|
|
}
|
|
|
|
setLeaseExpiry(req->dhcpEntry, hangTime);
|
|
strcpy(req->dhcpEntry->hostname, req->hostname);
|
|
|
|
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, (void *)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") != 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] option %u should be under [DOMAIN_NAME], ignored",
|
|
sectionName,
|
|
opTag);
|
|
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 = fUInt(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, "OpenDHCPServer") && !strcasecmp(sectionName, GLOBALOPTIONS)) {
|
|
cfig.lease = j;
|
|
}
|
|
}
|
|
|
|
if (buffsize > 6) {
|
|
*dp = opTag;
|
|
dp++;
|
|
*dp = 4;
|
|
dp++;
|
|
dp += pUInt(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 = (char)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 (isInt(ptr) && STR2INT(ptr) <= UCHAR_MAX) {
|
|
hoption[valueSize] = (char)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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void 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);
|
|
ERR_PARAM = ERR_ITEM_EXISTS;
|
|
return;
|
|
}
|
|
}
|
|
|
|
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(struct 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);
|
|
ERR_PARAM = ERR_MALLOC_MEMORY;
|
|
return;
|
|
}
|
|
}
|
|
} else {
|
|
sprintf(logBuff, "Section [%s] Invalid DHCP range %s in ini file, ignored", RANGESET, dp);
|
|
logDHCPMess(logBuff, 1);
|
|
}
|
|
} else {
|
|
sprintf(logBuff, "Section [%s] Invalid DHCP range %s in ini file, ignored", RANGESET, dp);
|
|
logDHCPMess(logBuff, 1);
|
|
}
|
|
}
|
|
|
|
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");
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
//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] = MY_MAX_TIME;
|
|
}
|
|
}
|
|
}
|
|
|
|
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 (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.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);
|
|
}
|
|
|
|
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) != 0 || dhcpEntry->ip != dhcpData.ip)) {
|
|
continue;
|
|
}
|
|
|
|
dhcpEntry = findDHCPEntry(mapname);
|
|
rangeInd = getRangeInd(dhcpData.ip);
|
|
|
|
if (!dhcpEntry && rangeInd >= 0) {
|
|
memset(&lump, 0, sizeof(data71));
|
|
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);
|
|
|
|
//printf("Loaded %s=%s\n", dhcpData.hostname, IP2String(ipbuff, dhcpData.ip));
|
|
}
|
|
}
|
|
}
|
|
|
|
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 tempbuff[512];
|
|
char logBuff[256];
|
|
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);
|
|
}
|
|
|
|
#if 0
|
|
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;
|
|
}
|
|
#endif
|
|
/*
|
|
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) {
|
|
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 kount, MYDWORD ip) {
|
|
if (ip) {
|
|
for (MYBYTE i = 0; i < kount && 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);
|
|
int j = 0;
|
|
|
|
for (; *str; str++) {
|
|
if (*str == '.' && *(str + 1) != '.') {
|
|
j++;
|
|
} else if (*str < '0' || *str > '9') {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (j == 3) {
|
|
if (ip == INADDR_NONE || ip == INADDR_ANY) {
|
|
return false;
|
|
} else {
|
|
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;
|
|
}
|
|
*/
|
|
|
|
#if 0
|
|
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;
|
|
}
|
|
#endif
|
|
|
|
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;
|
|
}
|
|
|
|
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 0;
|
|
}
|
|
wild++;
|
|
string++;
|
|
}
|
|
|
|
while (*string) {
|
|
if (*wild == '*') {
|
|
if (!*++wild)
|
|
return 1;
|
|
|
|
mp = wild;
|
|
cp = string + 1;
|
|
} else if ((*wild == *string) || (*wild == '?')) {
|
|
wild++;
|
|
string++;
|
|
} else {
|
|
wild = mp;
|
|
string = cp++;
|
|
}
|
|
}
|
|
|
|
while (*wild == '*')
|
|
wild++;
|
|
|
|
return !(*wild);
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
void checkSize()
|
|
{
|
|
data7 *dhcpEntry = nullptr;
|
|
|
|
//printf("checksize dhcpdhcpEntry[%d]=%d dhcpAge[%d]=%d\n", currentInd, dhcpdhcpEntry.size(), currentInd, dhcpAge.size());
|
|
expiryMap::iterator p = dhcpAge.begin();
|
|
expiryMap::iterator q;
|
|
|
|
while (p != dhcpAge.end() && p->first < t)
|
|
{
|
|
dhcpEntry = p->second;
|
|
//printf("processing %s=%d\n", dhcpEntry->mapname, p->first - t);
|
|
|
|
if (dhcpEntry->expiry < t)
|
|
{
|
|
sprintf(logBuff, "Lease %s Being Released", IP2String(tempbuff, dhcpEntry->ip));
|
|
logDHCPMess(logBuff, 2);
|
|
q = p;
|
|
p++;
|
|
|
|
dhcpAge.erase(q);
|
|
dhcpEntry->hanged = false;
|
|
updateDHCP(dhcpEntry, 0);
|
|
}
|
|
else if (dhcpEntry->expiry > p->first)
|
|
{
|
|
q = p;
|
|
p++;
|
|
dhcpAge.erase(q);
|
|
dhcpAge.insert(pair<time_t, data7*>(dhcpEntry->expiry, dhcpEntry));
|
|
}
|
|
else
|
|
p++;
|
|
}
|
|
//printf("Done %u=%u\n",dnsdhcpEntry[ind].size(),dnsAge[currentInd].size());
|
|
}
|
|
*/
|
|
|
|
void *updateStateFile(void *lpParam) {
|
|
pthread_mutex_lock(&mutStateFile);
|
|
|
|
auto *dhcpEntry = (data7 *)lpParam;
|
|
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);
|
|
}
|
|
|
|
void calcRangeLimits(MYDWORD ip, MYDWORD mask, MYDWORD *rangeStart, MYDWORD *rangeEnd) {
|
|
*rangeStart = htonl(ip & mask) + 1;
|
|
*rangeEnd = htonl(ip | (~mask)) - 1;
|
|
}
|
|
|
|
data7 *findDHCPEntry(char *key) {
|
|
//printf("finding %u=%s\n",ind,key);
|
|
myLower(key);
|
|
auto it = dhcpCache.find(key);
|
|
|
|
if (it == dhcpCache.end()) {
|
|
return nullptr;
|
|
} else {
|
|
return it->second;
|
|
}
|
|
}
|
|
|
|
bool checkMask(MYDWORD mask) {
|
|
mask = htonl(mask);
|
|
|
|
while (mask) {
|
|
if (mask < (mask << 1)) {
|
|
return false;
|
|
}
|
|
|
|
mask <<= 1;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
#if 0
|
|
MYDWORD calcMask(MYDWORD rangeStart, MYDWORD rangeEnd) {
|
|
data15 ip1, ip2, mask;
|
|
|
|
ip1.ip = htonl(rangeStart);
|
|
ip2.ip = htonl(rangeEnd);
|
|
|
|
for (MYBYTE i = 0; i < 4; i++) {
|
|
mask.octate[i] = ip1.octate[i] ^ ip2.octate[i];
|
|
|
|
if (i && mask.octate[i - 1] < 255)
|
|
mask.octate[i] = 0;
|
|
else if (mask.octate[i] == 0)
|
|
mask.octate[i] = 255;
|
|
else if (mask.octate[i] < 2)
|
|
mask.octate[i] = 254;
|
|
else if (mask.octate[i] < 4)
|
|
mask.octate[i] = 252;
|
|
else if (mask.octate[i] < 8)
|
|
mask.octate[i] = 248;
|
|
else if (mask.octate[i] < 16)
|
|
mask.octate[i] = 240;
|
|
else if (mask.octate[i] < 32)
|
|
mask.octate[i] = 224;
|
|
else if (mask.octate[i] < 64)
|
|
mask.octate[i] = 192;
|
|
else if (mask.octate[i] < 128)
|
|
mask.octate[i] = 128;
|
|
else
|
|
mask.octate[i] = 0;
|
|
}
|
|
return mask.ip;
|
|
}
|
|
#endif
|
|
|
|
char *cloneString(char *string) {
|
|
if (!string) {
|
|
return nullptr;
|
|
}
|
|
|
|
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 raw[512];
|
|
char name[512];
|
|
char value[512];
|
|
FILE *f = nullptr;
|
|
|
|
if ((f = openSection("LOGGING", 1))) {
|
|
cfig.dhcpLogLevel = 1;
|
|
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);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
cfig.lease = 36000;
|
|
loadDHCP();
|
|
|
|
if (cfig.dhcpLogLevel > 1) {
|
|
sprintf(logBuff, "Logging: All");
|
|
} else if (cfig.dhcpLogLevel >= 1) {
|
|
sprintf(logBuff, "Logging: Normal");
|
|
} else {
|
|
sprintf(logBuff, "Logging: None");
|
|
}
|
|
|
|
logDHCPMess(logBuff, 1);
|
|
|
|
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();
|
|
|
|
/*
|
|
for (int i = 0; i < cfig.rangeCount; i++)
|
|
{
|
|
char *logPtr = logBuff;
|
|
logPtr += sprintf(logPtr, "DHCP Range: ");
|
|
logPtr += sprintf(logPtr, "%s", IP2String(tempbuff, htonl(cfig.dhcpRanges[i].rangeStart)));
|
|
logPtr += sprintf(logPtr, "-%s", IP2String(tempbuff, htonl(cfig.dhcpRanges[i].rangeEnd)));
|
|
logPtr += sprintf(logPtr, "/%s", IP2String(tempbuff, cfig.dhcpRanges[i].mask));
|
|
logDHCPMess(logBuff, 1);
|
|
}
|
|
*/
|
|
gethostname(cfig.servername, sizeof(cfig.servername));
|
|
|
|
char *ptr = strchr(cfig.servername, '.');
|
|
|
|
if (ptr) {
|
|
*ptr = 0;
|
|
ptr++;
|
|
strcpy(cfig.zone, ptr);
|
|
cfig.zLen = strlen(cfig.zone);
|
|
}
|
|
#ifdef getdomainname
|
|
else {
|
|
getdomainname(cfig.zone, sizeof(cfig.zone));
|
|
cfig.zLen = strlen(cfig.zone);
|
|
}
|
|
#endif
|
|
|
|
cfig.fixedSocket = socket(AF_INET, SOCK_DGRAM, 0);
|
|
|
|
if (cfig.fixedSocket < 0) {
|
|
sprintf(logBuff, "Failed to Create Socket");
|
|
logDHCPMess(logBuff, 1);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
getInterfaces(&newNetwork);
|
|
memcpy(cfig.oldservers, newNetwork.staticServers, (MAX_SERVERS * sizeof(MYDWORD)));
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
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(newNetwork.allServers, MAX_SERVERS, cfig.zoneServers[0])) {
|
|
cfig.replication = 1;
|
|
} else if (findServer(newNetwork.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]);
|
|
|
|
//sprintf(logBuff, "Contacting Primary DHCP Server %s", IP2String(tempbuff, cfig.zoneServers[0]));
|
|
//logDHCPMess(logBuff, 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.dhcpp.header.bp_op = BOOTP_REQUEST;
|
|
token.dhcpp.header.bp_xid = 0;
|
|
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);
|
|
|
|
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 {
|
|
token.remote.sin_addr.s_addr = cfig.zoneServers[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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
sprintf(cfig.servername_fqn, "%s.%s", cfig.servername, cfig.zone);
|
|
|
|
if (cfig.lease >= MY_MAX_TIME) {
|
|
sprintf(logBuff, "Default Lease: Infinity");
|
|
} else {
|
|
sprintf(logBuff, "Default Lease: %u (sec)", cfig.lease);
|
|
}
|
|
|
|
logDHCPMess(logBuff, 1);
|
|
|
|
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);
|
|
|
|
do {
|
|
if (newNetwork.maxFD < cfig.dhcpReplConn.sock) {
|
|
newNetwork.maxFD = cfig.dhcpReplConn.sock;
|
|
}
|
|
|
|
bool bindfailed = false;
|
|
|
|
if (cfig.specifiedServers[0]) {
|
|
for (MYBYTE i = 0; i < MAX_SERVERS && cfig.specifiedServers[i]; i++) {
|
|
MYBYTE j = 0;
|
|
|
|
for (; j < MAX_SERVERS && newNetwork.allServers[j]; j++) {
|
|
if (newNetwork.allServers[j] == cfig.specifiedServers[i]) {
|
|
MYBYTE k = addServer(newNetwork.listenServers, MAX_SERVERS, newNetwork.allServers[j]);
|
|
|
|
if (k != MAX_SERVERS) {
|
|
newNetwork.listenMasks[k] = newNetwork.allMasks[j];
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (j == MAX_SERVERS || !newNetwork.allServers[j]) {
|
|
bindfailed = true;
|
|
sprintf(logBuff,
|
|
"Warning: Section [LISTEN_ON], Interface %s not available, ignored",
|
|
IP2String(tempbuff, cfig.specifiedServers[i]));
|
|
logDHCPMess(logBuff, 1);
|
|
}
|
|
}
|
|
} else {
|
|
//sprintf(logBuff, "Detecting Static Interfaces..");
|
|
//logDHCPMess(logBuff, 1);
|
|
|
|
for (MYBYTE i = 0; i < MAX_SERVERS && newNetwork.allServers[i]; i++) {
|
|
if (findServer(newNetwork.staticServers, MAX_SERVERS, newNetwork.allServers[i])) {
|
|
MYBYTE k = addServer(newNetwork.listenServers, MAX_SERVERS, newNetwork.allServers[i]);
|
|
|
|
if (k != MAX_SERVERS) {
|
|
newNetwork.listenMasks[k] = newNetwork.allMasks[i];
|
|
}
|
|
} else {
|
|
sprintf(logBuff,
|
|
"Warning: Interface %s is not Static, not used",
|
|
IP2String(tempbuff, newNetwork.allServers[i]));
|
|
logDHCPMess(logBuff, 2);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
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) {
|
|
close(newNetwork.dhcpConn[i].sock);
|
|
sprintf(logBuff, "%s Port 67 already in use", IP2String(tempbuff, 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) {
|
|
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,
|
|
SOL_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) {
|
|
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;
|
|
opendhcp_init_http_server();
|
|
#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)) {
|
|
bindfailed = true;
|
|
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] == 0) {
|
|
sprintf(htmlTitle, "Open DHCP on %s", cfig.servername);
|
|
}
|
|
|
|
if (network.httpConn.ready && network.httpConn.server == newNetwork.httpConn.server) {
|
|
memcpy(&(newNetwork.httpConn), &(network.httpConn), sizeof(ConnType));
|
|
|
|
if (newNetwork.httpConn.sock > newNetwork.maxFD) {
|
|
newNetwork.maxFD = newNetwork.httpConn.sock;
|
|
}
|
|
|
|
network.httpConn.ready = false;
|
|
} else {
|
|
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(tempbuff, 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(tempbuff, 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
|
|
newNetwork.maxFD++;
|
|
|
|
for (MYBYTE m = 0; m < MAX_SERVERS && newNetwork.allServers[m]; m++) {
|
|
lockIP(newNetwork.allServers[m]);
|
|
}
|
|
|
|
if (bindfailed) {
|
|
cfig.failureCount++;
|
|
} else {
|
|
cfig.failureCount = 0;
|
|
}
|
|
|
|
closeConn();
|
|
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 (network.httpConn.ready) {
|
|
sprintf(logBuff,
|
|
"Lease Status URL: http://%s:%u",
|
|
IP2String(tempbuff, network.httpConn.server),
|
|
network.httpConn.port);
|
|
logDHCPMess(logBuff, 1);
|
|
}
|
|
|
|
for (int k = 0; k < MAX_SERVERS && network.allServers[k]; k++) {
|
|
for (auto &j : network.dhcpConn) {
|
|
if (j.server == network.allServers[k]) {
|
|
sprintf(logBuff, "Listening On: %s", IP2String(tempbuff, network.allServers[k]));
|
|
logDHCPMess(logBuff, 1);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
network.ready = true;
|
|
|
|
} while (detectChange());
|
|
|
|
pthread_exit(nullptr);
|
|
}
|
|
|
|
bool detectChange() {
|
|
//printf("Entering detectchange\n");
|
|
char logBuff[256];
|
|
|
|
while (kRunning) {
|
|
sleep(20);
|
|
//printf("Checking Networks (failue count=%u, failue cycle=%u)..\n", cfig.failureCount, cfig.failureCycle);
|
|
|
|
getInterfaces(&newNetwork);
|
|
|
|
if (memcmp(cfig.oldservers, newNetwork.staticServers, (MAX_SERVERS * sizeof(MYDWORD))) != 0) {
|
|
memcpy(cfig.oldservers, newNetwork.staticServers, (MAX_SERVERS * sizeof(MYDWORD)));
|
|
sprintf(logBuff, "Network changed, re-detecting Listening Interfaces..");
|
|
logDHCPMess(logBuff, 1);
|
|
break;
|
|
} else 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 {
|
|
cfig.failureCycle = 0;
|
|
}
|
|
}
|
|
|
|
network.ready = false;
|
|
|
|
while (kRunning && network.busy) {
|
|
sleep(1);
|
|
}
|
|
|
|
//printf("Returning from detectchange\n");
|
|
|
|
return (kRunning);
|
|
}
|
|
|
|
void getInterfaces(data1 *pNetwork) {
|
|
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)) {
|
|
MYBYTE k = addServer(pNetwork->allServers, MAX_SERVERS, addr);
|
|
|
|
if (k != MAX_SERVERS) {
|
|
pNetwork->allMasks[k] = mask;
|
|
}
|
|
|
|
if (!(flags & IFF_DYNAMIC)) {
|
|
addServer(pNetwork->staticServers, MAX_SERVERS, addr);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
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 = fUInt(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);
|
|
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 = fUInt(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;
|
|
}
|
|
|
|
void debug(const char *mess) {
|
|
char tmp[254];
|
|
strcpy(tmp, mess);
|
|
logDHCPMess(tmp, 1);
|
|
}
|
|
|
|
#if 0
|
|
void *logThread(void *lpParam) {
|
|
char *mess = (char *)lpParam;
|
|
pthread_mutex_lock(&mutLogFile);
|
|
tm *ttm = localtime(&t);
|
|
char buffer[256];
|
|
strftime(buffer, sizeof(buffer), logFile, ttm);
|
|
|
|
if (strcmp(cfig.logFileName, buffer) != 0) {
|
|
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);
|
|
}
|
|
#endif
|
|
|
|
void logDHCPMess(char *logBuff, MYBYTE logLevel) {
|
|
// if (verbatim)
|
|
// printf("%s\n", logBuff);
|
|
|
|
if (logLevel == 2) {
|
|
dzlog_debug("%s\n", logBuff);
|
|
} else if (logLevel == 1) {
|
|
dzlog_info("%s\n", logBuff);
|
|
} else if (logLevel == 0) {
|
|
dzlog_error("%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);
|
|
// }
|
|
}
|
|
|
|
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;
|
|
}
|