9765 lines
338 KiB
C++
9765 lines
338 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. *
|
||
|
***************************************************************************/
|
||
|
// dualserver.cpp ///
|
||
|
#include <string>
|
||
|
#include <cmath>
|
||
|
#include <sys/types.h>
|
||
|
#include <sys/ioctl.h>
|
||
|
#include <climits>
|
||
|
#include <sys/socket.h>
|
||
|
#include <netinet/in.h>
|
||
|
#include <net/if.h>
|
||
|
#include <arpa/inet.h>
|
||
|
#include <unistd.h>
|
||
|
#include <csignal>
|
||
|
#include <cstdio>
|
||
|
#include <fcntl.h>
|
||
|
#include <cerrno>
|
||
|
#include <memory.h>
|
||
|
#include <sys/stat.h>
|
||
|
#include <cstdlib>
|
||
|
#include <syslog.h>
|
||
|
#include <pthread.h>
|
||
|
#include <map>
|
||
|
#pragma clang diagnostic push
|
||
|
#pragma ide diagnostic ignored "OCDFAInspection"
|
||
|
using namespace std;
|
||
|
#include "dualserverd.h"
|
||
|
#include "dualsvr.h"
|
||
|
|
||
|
//Global Variables
|
||
|
data1 network;
|
||
|
data1 newNetwork;
|
||
|
data2 cfig;
|
||
|
bool verbatim = false;
|
||
|
data9 dhcpr;
|
||
|
data9 token;
|
||
|
data5 dnsr;
|
||
|
//data5 dnstcp;
|
||
|
MYBYTE currentInd = 0;
|
||
|
//MYBYTE newInd = 0;
|
||
|
data18 g_magin;
|
||
|
bool kRunning = true;
|
||
|
hostMap dnsCache[2];
|
||
|
expiryMap dnsAge[2];
|
||
|
dhcpMap dhcpCache;
|
||
|
char serviceName[] = "DUALServer";
|
||
|
//expiryMap dhcpAge;
|
||
|
//char tempbuff[512] = "";
|
||
|
//char extbuff[512];
|
||
|
//char logBuff[256] = "";
|
||
|
char exeFile[PATH_MAX] = "";
|
||
|
char iniFile[PATH_MAX] = "";
|
||
|
char leaFile[PATH_MAX] = "";
|
||
|
char logFile[PATH_MAX] = "";
|
||
|
char tempFile[PATH_MAX] = "/tmp/dualserver.tmp";
|
||
|
char filePATH[PATH_MAX] = "";
|
||
|
char htmlTitle[PATH_MAX] = "";
|
||
|
char icoFile[PATH_MAX] = "";
|
||
|
char *icoString = nullptr;
|
||
|
int icoSize = 0;
|
||
|
data71 g_lump;
|
||
|
char arpa[] = ".in-addr.arpa";
|
||
|
char ip6arpa[] = ".ip6.arpa";
|
||
|
bool dhcpService = true;
|
||
|
bool dnsService = true;
|
||
|
time_t t = time(nullptr);
|
||
|
timeval tv;
|
||
|
fd_set readfds;
|
||
|
//fd_set writefds;
|
||
|
pthread_mutex_t mutStateFile = PTHREAD_MUTEX_INITIALIZER;
|
||
|
pthread_mutex_t mutLogFile = PTHREAD_MUTEX_INITIALIZER;
|
||
|
struct ifconf Ifc;
|
||
|
struct ifreq IfcBuf[MAX_SERVERS];
|
||
|
|
||
|
//constants
|
||
|
const char NBSP = 32;
|
||
|
const char RANGESET[] = "RANGE_SET";
|
||
|
const char GLOBALOPTIONS[] = "GLOBAL_OPTIONS";
|
||
|
//const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||
|
//const char send200[] = "HTTP/1.1 200 OK\r\nDate: %s\r\nLast-Modified: %s\r\nContent-Type: text/html\r\nConnection: Close\r\nContent-Length: \r\n\r\n";
|
||
|
//const char send200[] = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: Close\r\n\r\n";
|
||
|
//const char send200[] = "HTTP/1.1 200 OK\r\nDate: %s\r\nLast-Modified: %s\r\nContent-Type: text/html\r\nConnection: Close\r\nTransfer-Encoding: chunked\r\n";
|
||
|
//const char send403[] = "HTTP/1.1 403 Forbidden\r\nDate: %s\r\nLast-Modified: %s\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 send200[] = "HTTP/1.1 200 OK\r\nContent-Type: %s\r\nConnection: close\r\nContent-Length: %i\r\n\r\n";
|
||
|
const char td200[] = "<td>%s</td>";
|
||
|
const char tdnowrap200[] = "<td nowrap>%s</td>";
|
||
|
const char sVersion[] = "Dual DHCP DNS Server Version 7.60 Linux Build 7057";
|
||
|
const char htmlStart
|
||
|
[] = "<html>\n<head>\n<title>%s</title><meta http-equiv=\"refresh\" content=\"60\">\n<meta "
|
||
|
"http-equiv=\"cache-control\" content=\"no-cache\">\n</head>\n";
|
||
|
const char bodyStart
|
||
|
[] = "<body bgcolor=\"#cccccc\"><table border=\"0\"><tr><td>\n<table width=\"100%%\" border=\"0\"><tr><td nowrap "
|
||
|
"colspan=\"2\" align=\"center\"><font size=\"6\"><b>%s</b></font></td></tr><tr><td "
|
||
|
"align=\"left\"><b>Server:</b> %s %s %s</td><td align=\"right\"><a target=\"_new\" "
|
||
|
"href=\"http://dhcp-dns-server.sourceforge.net\">http://dhcp-dns-server.sourceforge.net</td></tr></table>";
|
||
|
//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://dhcp-dns-server.sourceforge.net\">http://dhcp-dns-server.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, 1 , true},
|
||
|
{"CCC", 122, 1, true},
|
||
|
{"TFTPServerIPaddress", 128, 3, true},
|
||
|
{"CallServerIPaddress", 129, 3, true},
|
||
|
{"DiscriminationString", 130, 1, true},
|
||
|
{"RemoteStatisticsServerIPAddress", 131, 3, true},
|
||
|
{"HTTPProxyPhone", 135, 3, true},
|
||
|
{"OPTION_CAPWAP_AC_V4", 138, 1, true},
|
||
|
{"OPTIONIPv4_AddressMoS", 139, 1, true},
|
||
|
{"OPTIONIPv4_FQDNMoS", 140, 1, true},
|
||
|
{"SIPUAServiceDomains", 141, 1, true},
|
||
|
{"OPTIONIPv4_AddressANDSF", 142, 1, true},
|
||
|
{"IPTelephone", 176, 1, true},
|
||
|
{"ConfigurationFile", 209, 1, true},
|
||
|
{"PathPrefix", 210, 1, true},
|
||
|
{"RebootTime", 211, 4, true},
|
||
|
{"OPTION_6RD", 212, 1, true},
|
||
|
{"OPTION_V4_ACCESS_DOMAIN", 213, 1, true},
|
||
|
{"BootFileName", 253, 1, true},
|
||
|
{"NextServer", 254, 3, true},
|
||
|
};
|
||
|
|
||
|
int dual_server_main(int argc, char **argv) {
|
||
|
char logBuff[256] = "";
|
||
|
|
||
|
signal(SIGINT, catch_int);
|
||
|
signal(SIGABRT, catch_int);
|
||
|
signal(SIGTERM, catch_int);
|
||
|
signal(SIGQUIT, catch_int);
|
||
|
signal(SIGTSTP, catch_int);
|
||
|
signal(SIGHUP, catch_int);
|
||
|
signal(SIGPIPE, SIG_IGN);
|
||
|
//printf("%i\n", argc);
|
||
|
|
||
|
for (int i = 1; i < argc; i++) {
|
||
|
if (!strcasecmp(argv[i], "-v"))
|
||
|
verbatim = true;
|
||
|
else if (!strcmp(argv[i], "-i") && argc > i + 1 && argv[i + 1][0] != '-') {
|
||
|
myTrim(iniFile, argv[i + 1]);
|
||
|
i++;
|
||
|
} else if (!strcmp(argv[i], "-s") && argc > i + 1 && argv[i + 1][0] != '-') {
|
||
|
myTrim(leaFile, argv[i + 1]);
|
||
|
i++;
|
||
|
} else if (!strcmp(argv[i], "-l") && argc > i + 1 && argv[i + 1][0] != '-') {
|
||
|
myTrim(logFile, argv[i + 1]);
|
||
|
i++;
|
||
|
} else if (!strcmp(argv[i], "-n") && argc > i + 1 && argv[i + 1][0] != '-') {
|
||
|
myTrim(icoFile, argv[i + 1]);
|
||
|
i++;
|
||
|
} else if (!strncasecmp(argv[i], "-i", 2))
|
||
|
myTrim(iniFile, argv[i] + 2);
|
||
|
else if (!strncasecmp(argv[i], "-s", 2))
|
||
|
myTrim(leaFile, argv[i] + 2);
|
||
|
else if (!strncasecmp(argv[i], "-l", 2))
|
||
|
myTrim(logFile, argv[i] + 2);
|
||
|
else if (!strncasecmp(argv[i], "-n", 2))
|
||
|
myTrim(icoFile, argv[i] + 2);
|
||
|
else
|
||
|
sprintf(logBuff, "Error: Invalid Argument %s", argv[i]);
|
||
|
}
|
||
|
|
||
|
if (verbatim) {
|
||
|
if (logBuff[0]) {
|
||
|
printf("%s\n", logBuff);
|
||
|
sleep(1);
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
if (getuid()) {
|
||
|
printf("Error: Only root should run this program\n");
|
||
|
sleep(1);
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
//printf("%i\n",sizeof(data7));
|
||
|
memset(&cfig, 0, sizeof(cfig));
|
||
|
cfig.ppid = getpid();
|
||
|
pthread_t threadId;
|
||
|
pthread_attr_t attr;
|
||
|
pthread_attr_init(&attr);
|
||
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||
|
int errcode = pthread_create(&threadId, &attr, init, nullptr);
|
||
|
pthread_attr_destroy(&attr);
|
||
|
|
||
|
if (errcode) {
|
||
|
printf("init thread Creation Failed");
|
||
|
sleep(1);
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
while (true) {
|
||
|
if (!network.ready) {
|
||
|
network.readyForChange = true;
|
||
|
sleep(1);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ((dhcpService && !network.dhcpConn[0].ready) || (dnsService && !network.dnsUdpConn[0].ready)) {
|
||
|
sleep(1);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
//Sleep(200000);
|
||
|
|
||
|
//network.busy = true;
|
||
|
FD_ZERO(&readfds);
|
||
|
tv.tv_sec = 20;
|
||
|
tv.tv_usec = 0;
|
||
|
|
||
|
if (dhcpService) {
|
||
|
if (network.httpConn.ready)
|
||
|
FD_SET(network.httpConn.sock, &readfds);
|
||
|
|
||
|
if (network.dhcpListener.ready)
|
||
|
FD_SET(network.dhcpListener.sock, &readfds);
|
||
|
|
||
|
for (int i = 0; i < MAX_SERVERS && network.dhcpConn[i].ready; i++)
|
||
|
FD_SET(network.dhcpConn[i].sock, &readfds);
|
||
|
|
||
|
if (cfig.dhcpReplConn.ready)
|
||
|
FD_SET(cfig.dhcpReplConn.sock, &readfds);
|
||
|
}
|
||
|
|
||
|
if (dnsService) {
|
||
|
for (int i = 0; i < MAX_SERVERS && network.dnsUdpConn[i].ready; i++)
|
||
|
FD_SET(network.dnsUdpConn[i].sock, &readfds);
|
||
|
|
||
|
for (int i = 0; i < MAX_SERVERS && network.dnsTcpConn[i].ready; i++)
|
||
|
FD_SET(network.dnsTcpConn[i].sock, &readfds);
|
||
|
|
||
|
if (network.forwConn.ready)
|
||
|
FD_SET(network.forwConn.sock, &readfds);
|
||
|
}
|
||
|
|
||
|
if (select(network.maxFD, &readfds, nullptr, nullptr, &tv)) {
|
||
|
t = time(nullptr);
|
||
|
|
||
|
if (dhcpService) {
|
||
|
if (network.httpConn.ready && FD_ISSET(network.httpConn.sock, &readfds)) {
|
||
|
auto *req = (data19 *)calloc(1, sizeof(data19));
|
||
|
|
||
|
if (req) {
|
||
|
req->sockLen = sizeof(req->remote);
|
||
|
req->sock = accept(network.httpConn.sock, (sockaddr *)&req->remote, &req->sockLen);
|
||
|
////errno = WSAGetLastError();
|
||
|
|
||
|
if (errno || req->sock == INVALID_SOCKET) {
|
||
|
sprintf(logBuff, "Accept Failed, Error %s", strerror(errno));
|
||
|
logDHCPMess(logBuff, 1);
|
||
|
free(req);
|
||
|
} else
|
||
|
procHTTP(req);
|
||
|
} else {
|
||
|
sprintf(logBuff, "Memory Error");
|
||
|
logDHCPMess(logBuff, 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (network.dhcpListener.ready && FD_ISSET(network.dhcpListener.sock, &readfds)
|
||
|
&& gdmess(&dhcpr, 255) && sdmess(&dhcpr))
|
||
|
alad(&dhcpr);
|
||
|
|
||
|
if (cfig.dhcpReplConn.ready && FD_ISSET(cfig.dhcpReplConn.sock, &readfds)) {
|
||
|
errno = 0;
|
||
|
dhcpr.sockLen = sizeof(dhcpr.remote);
|
||
|
|
||
|
dhcpr.bytes = (int)recvfrom(cfig.dhcpReplConn.sock,
|
||
|
dhcpr.raw,
|
||
|
sizeof(dhcpr.raw),
|
||
|
0,
|
||
|
(sockaddr *)&dhcpr.remote,
|
||
|
&dhcpr.sockLen);
|
||
|
|
||
|
////errno = WSAGetLastError();
|
||
|
|
||
|
if (errno || dhcpr.bytes <= 0)
|
||
|
cfig.dhcpRepl = 0;
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < MAX_SERVERS && network.dhcpConn[i].ready; i++) {
|
||
|
if (FD_ISSET(network.dhcpConn[i].sock, &readfds) && gdmess(&dhcpr, i) && sdmess(&dhcpr))
|
||
|
alad(&dhcpr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (dnsService) {
|
||
|
for (int i = 0; i < MAX_SERVERS && network.dnsUdpConn[i].ready; i++) {
|
||
|
if (FD_ISSET(network.dnsUdpConn[i].sock, &readfds)) {
|
||
|
if (gdnmess(&dnsr, i)) {
|
||
|
if (scanloc(&dnsr)) {
|
||
|
if (dnsr.dnsp->header.ancount) {
|
||
|
if (verbatim || cfig.dnsLogLevel >= 2) {
|
||
|
if (dnsr.dnsType == DNS_TYPE_SOA)
|
||
|
sprintf(logBuff, "SOA Sent for zone %s", dnsr.query);
|
||
|
else if (dnsr.dnsType == DNS_TYPE_NS)
|
||
|
sprintf(logBuff, "NS Sent for zone %s", dnsr.query);
|
||
|
else if (dnsr.cacheType == CTYPE_CACHED)
|
||
|
sprintf(logBuff,
|
||
|
"%s resolved from Cache to %s",
|
||
|
strquery(&dnsr),
|
||
|
getResult(&dnsr));
|
||
|
else
|
||
|
sprintf(logBuff,
|
||
|
"%s resolved Locally to %s",
|
||
|
strquery(&dnsr),
|
||
|
getResult(&dnsr));
|
||
|
|
||
|
logDNSMess(&dnsr, logBuff, 2);
|
||
|
}
|
||
|
} else if (dnsr.dnsp->header.rcode == RCODE_NOERROR) {
|
||
|
dnsr.dnsp->header.rcode = RCODE_NAMEERROR;
|
||
|
|
||
|
if (verbatim || cfig.dnsLogLevel >= 2) {
|
||
|
sprintf(logBuff, "%s not found", strquery(&dnsr));
|
||
|
logDNSMess(&dnsr, logBuff, 2);
|
||
|
}
|
||
|
}
|
||
|
sdnmess(&dnsr);
|
||
|
} else if (!fdnmess(&dnsr)) {
|
||
|
if (!dnsr.dnsp->header.ancount
|
||
|
&& (dnsr.dnsp->header.rcode == RCODE_NOERROR
|
||
|
|| dnsr.dnsp->header.rcode == RCODE_NAMEERROR)) {
|
||
|
dnsr.dnsp->header.rcode = RCODE_NAMEERROR;
|
||
|
|
||
|
if (verbatim || cfig.dnsLogLevel >= 2) {
|
||
|
sprintf(logBuff, "%s not found", strquery(&dnsr));
|
||
|
logDNSMess(&dnsr, logBuff, 2);
|
||
|
}
|
||
|
}
|
||
|
sdnmess(&dnsr);
|
||
|
}
|
||
|
} else if (dnsr.dnsp)
|
||
|
sdnmess(&dnsr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < MAX_SERVERS && network.dnsTcpConn[i].ready; i++) {
|
||
|
if (FD_ISSET(network.dnsTcpConn[i].sock, &readfds)) {
|
||
|
dnsr.sockInd = i;
|
||
|
dnsr.sockLen = sizeof(dnsr.remote);
|
||
|
errno = 0;
|
||
|
dnsr.sock = accept(network.dnsTcpConn[i].sock, (sockaddr *)&dnsr.remote, &dnsr.sockLen);
|
||
|
////errno = WSAGetLastError();
|
||
|
|
||
|
if (dnsr.sock == INVALID_SOCKET || errno) {
|
||
|
if (verbatim || cfig.dnsLogLevel) {
|
||
|
sprintf(logBuff, "Accept Failed, Error=%s", strerror(errno));
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
} else
|
||
|
procTCP(&dnsr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (network.forwConn.ready && FD_ISSET(network.forwConn.sock, &readfds)) {
|
||
|
if (frdnmess(&dnsr)) {
|
||
|
sdnmess(&dnsr);
|
||
|
|
||
|
if (verbatim || cfig.dnsLogLevel >= 2) {
|
||
|
if (dnsr.dnsIndex < MAX_SERVERS) {
|
||
|
if (dnsr.dnsp->header.ancount) {
|
||
|
if (getResult(&dnsr))
|
||
|
sprintf(logBuff,
|
||
|
"%s resolved from Forwarding Server as %s",
|
||
|
strquery(&dnsr),
|
||
|
dnsr.tempname);
|
||
|
else
|
||
|
sprintf(logBuff, "%s resolved from Forwarding Server", strquery(&dnsr));
|
||
|
} else
|
||
|
sprintf(logBuff, "%s not found by Forwarding Server", strquery(&dnsr));
|
||
|
} else {
|
||
|
if (dnsr.dnsp->header.ancount) {
|
||
|
if (getResult(&dnsr))
|
||
|
sprintf(logBuff,
|
||
|
"%s resolved from Conditional Forwarder as %s",
|
||
|
strquery(&dnsr),
|
||
|
dnsr.tempname);
|
||
|
else
|
||
|
sprintf(logBuff, "%s resolved from Conditional Forwarder", strquery(&dnsr));
|
||
|
} else
|
||
|
sprintf(logBuff, "%s not found by Conditional Forwarder", strquery(&dnsr));
|
||
|
}
|
||
|
|
||
|
logDNSMess(&dnsr, logBuff, 2);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
} else
|
||
|
t = time(nullptr);
|
||
|
|
||
|
if (g_magin.done) {
|
||
|
currentInd = g_magin.currentInd;
|
||
|
g_magin.done = false;
|
||
|
//sprintf(logBuff, "New Index=%u", currentInd);
|
||
|
//logMess(logBuff, 2);
|
||
|
} else
|
||
|
checkSize();
|
||
|
}
|
||
|
//printf("Here\n");
|
||
|
} else {
|
||
|
if (logBuff[0]) {
|
||
|
syslog(LOG_MAKEPRI(LOG_LOCAL1, LOG_CRIT), "%s", logBuff);
|
||
|
sleep(1);
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
if (getuid()) {
|
||
|
syslog(LOG_MAKEPRI(LOG_LOCAL1, LOG_CRIT), "%s", "Only root should run this program");
|
||
|
sleep(1);
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
/* Our process ID and Session ID */
|
||
|
pid_t pid, sid;
|
||
|
|
||
|
/* Fork off the parent process */
|
||
|
pid = fork();
|
||
|
|
||
|
if (pid < 0) {
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
/* If we got a good PID, then
|
||
|
we can exit the parent process. */
|
||
|
if (pid > 0) {
|
||
|
exit(EXIT_SUCCESS);
|
||
|
}
|
||
|
|
||
|
/* Change the file mode mask */
|
||
|
umask(0);
|
||
|
|
||
|
/* Open any logs here */
|
||
|
|
||
|
/* Create a new SID for the child process */
|
||
|
sid = setsid();
|
||
|
if (sid < 0) {
|
||
|
/* Log the failure */
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
/* Change the current working directory */
|
||
|
if ((chdir("/")) < 0) {
|
||
|
/* Log the failure */
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
/* Close out the standard file descriptors */
|
||
|
close(STDIN_FILENO);
|
||
|
close(STDOUT_FILENO);
|
||
|
close(STDERR_FILENO);
|
||
|
|
||
|
/* Daemon-specific initialization goes here */
|
||
|
//printf("%i\n",sizeof(data7));
|
||
|
memset(&cfig, 0, sizeof(cfig));
|
||
|
cfig.ppid = getpid();
|
||
|
pthread_t threadId;
|
||
|
pthread_attr_t attr;
|
||
|
pthread_attr_init(&attr);
|
||
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||
|
int errcode = pthread_create(&threadId, &attr, init, nullptr);
|
||
|
pthread_attr_destroy(&attr);
|
||
|
|
||
|
if (errcode) {
|
||
|
syslog(LOG_MAKEPRI(LOG_LOCAL1, LOG_CRIT), "%s", "init thread Creation Failed");
|
||
|
sleep(1);
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
//listDSNCache(0);
|
||
|
/* The Big Loop */
|
||
|
while (true) {
|
||
|
if (!network.ready) {
|
||
|
network.readyForChange = true;
|
||
|
sleep(1);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ((dhcpService && !network.dhcpConn[0].ready) || (dnsService && !network.dnsUdpConn[0].ready)) {
|
||
|
sleep(1);
|
||
|
continue;
|
||
|
}
|
||
|
//Sleep(200000);
|
||
|
|
||
|
//network.busy = true;
|
||
|
FD_ZERO(&readfds);
|
||
|
tv.tv_sec = 20;
|
||
|
tv.tv_usec = 0;
|
||
|
|
||
|
if (dhcpService) {
|
||
|
if (network.httpConn.ready)
|
||
|
FD_SET(network.httpConn.sock, &readfds);
|
||
|
|
||
|
if (network.dhcpListener.ready)
|
||
|
FD_SET(network.dhcpListener.sock, &readfds);
|
||
|
|
||
|
for (int i = 0; i < MAX_SERVERS && network.dhcpConn[i].ready; i++)
|
||
|
FD_SET(network.dhcpConn[i].sock, &readfds);
|
||
|
|
||
|
if (cfig.dhcpReplConn.ready)
|
||
|
FD_SET(cfig.dhcpReplConn.sock, &readfds);
|
||
|
}
|
||
|
|
||
|
if (dnsService) {
|
||
|
for (int i = 0; i < MAX_SERVERS && network.dnsUdpConn[i].ready; i++)
|
||
|
FD_SET(network.dnsUdpConn[i].sock, &readfds);
|
||
|
|
||
|
for (int i = 0; i < MAX_SERVERS && network.dnsTcpConn[i].ready; i++)
|
||
|
FD_SET(network.dnsTcpConn[i].sock, &readfds);
|
||
|
|
||
|
if (network.forwConn.ready)
|
||
|
FD_SET(network.forwConn.sock, &readfds);
|
||
|
}
|
||
|
|
||
|
if (select(network.maxFD, &readfds, nullptr, nullptr, &tv)) {
|
||
|
t = time(nullptr);
|
||
|
|
||
|
if (dhcpService) {
|
||
|
if (network.httpConn.ready && FD_ISSET(network.httpConn.sock, &readfds)) {
|
||
|
auto *req = (data19 *)calloc(1, sizeof(data19));
|
||
|
|
||
|
if (req) {
|
||
|
req->sockLen = sizeof(req->remote);
|
||
|
req->sock = accept(network.httpConn.sock, (sockaddr *)&req->remote, &req->sockLen);
|
||
|
////errno = WSAGetLastError();
|
||
|
|
||
|
if (errno || req->sock == INVALID_SOCKET) {
|
||
|
sprintf(logBuff, "Accept Failed, Error %s", strerror(errno));
|
||
|
logDHCPMess(logBuff, 1);
|
||
|
free(req);
|
||
|
} else
|
||
|
procHTTP(req);
|
||
|
} else {
|
||
|
sprintf(logBuff, "Memory Error");
|
||
|
logDHCPMess(logBuff, 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (network.dhcpListener.ready && FD_ISSET(network.dhcpListener.sock, &readfds)
|
||
|
&& gdmess(&dhcpr, 255) && sdmess(&dhcpr))
|
||
|
alad(&dhcpr);
|
||
|
|
||
|
if (cfig.dhcpReplConn.ready && FD_ISSET(cfig.dhcpReplConn.sock, &readfds)) {
|
||
|
errno = 0;
|
||
|
dhcpr.sockLen = sizeof(dhcpr.remote);
|
||
|
|
||
|
dhcpr.bytes = (int)recvfrom(cfig.dhcpReplConn.sock,
|
||
|
dhcpr.raw,
|
||
|
sizeof(dhcpr.raw),
|
||
|
0,
|
||
|
(sockaddr *)&dhcpr.remote,
|
||
|
&dhcpr.sockLen);
|
||
|
|
||
|
////errno = WSAGetLastError();
|
||
|
|
||
|
if (errno || dhcpr.bytes <= 0)
|
||
|
cfig.dhcpRepl = 0;
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < MAX_SERVERS && network.dhcpConn[i].ready; i++) {
|
||
|
if (FD_ISSET(network.dhcpConn[i].sock, &readfds) && gdmess(&dhcpr, i) && sdmess(&dhcpr))
|
||
|
alad(&dhcpr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (dnsService) {
|
||
|
for (int i = 0; i < MAX_SERVERS && network.dnsUdpConn[i].ready; i++) {
|
||
|
if (FD_ISSET(network.dnsUdpConn[i].sock, &readfds)) {
|
||
|
if (gdnmess(&dnsr, i)) {
|
||
|
if (scanloc(&dnsr)) {
|
||
|
if (dnsr.dnsp->header.ancount) {
|
||
|
if (verbatim || cfig.dnsLogLevel >= 2) {
|
||
|
if (dnsr.dnsType == DNS_TYPE_SOA)
|
||
|
sprintf(logBuff, "SOA Sent for zone %s", dnsr.query);
|
||
|
else if (dnsr.dnsType == DNS_TYPE_NS)
|
||
|
sprintf(logBuff, "NS Sent for zone %s", dnsr.query);
|
||
|
else if (dnsr.cacheType == CTYPE_CACHED)
|
||
|
sprintf(logBuff,
|
||
|
"%s resolved from Cache to %s",
|
||
|
strquery(&dnsr),
|
||
|
getResult(&dnsr));
|
||
|
else
|
||
|
sprintf(logBuff,
|
||
|
"%s resolved Locally to %s",
|
||
|
strquery(&dnsr),
|
||
|
getResult(&dnsr));
|
||
|
|
||
|
logDNSMess(&dnsr, logBuff, 2);
|
||
|
}
|
||
|
} else if (dnsr.dnsp->header.rcode == RCODE_NOERROR) {
|
||
|
dnsr.dnsp->header.rcode = RCODE_NAMEERROR;
|
||
|
|
||
|
if (verbatim || cfig.dnsLogLevel >= 2) {
|
||
|
sprintf(logBuff, "%s not found", strquery(&dnsr));
|
||
|
logDNSMess(&dnsr, logBuff, 2);
|
||
|
}
|
||
|
}
|
||
|
sdnmess(&dnsr);
|
||
|
} else if (!fdnmess(&dnsr)) {
|
||
|
if (!dnsr.dnsp->header.ancount
|
||
|
&& (dnsr.dnsp->header.rcode == RCODE_NOERROR
|
||
|
|| dnsr.dnsp->header.rcode == RCODE_NAMEERROR)) {
|
||
|
dnsr.dnsp->header.rcode = RCODE_NAMEERROR;
|
||
|
|
||
|
if (verbatim || cfig.dnsLogLevel >= 2) {
|
||
|
sprintf(logBuff, "%s not found", strquery(&dnsr));
|
||
|
logDNSMess(&dnsr, logBuff, 2);
|
||
|
}
|
||
|
}
|
||
|
sdnmess(&dnsr);
|
||
|
}
|
||
|
} else if (dnsr.dnsp)
|
||
|
sdnmess(&dnsr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < MAX_SERVERS && network.dnsTcpConn[i].ready; i++) {
|
||
|
if (FD_ISSET(network.dnsTcpConn[i].sock, &readfds)) {
|
||
|
dnsr.sockInd = i;
|
||
|
dnsr.sockLen = sizeof(dnsr.remote);
|
||
|
errno = 0;
|
||
|
dnsr.sock = accept(network.dnsTcpConn[i].sock, (sockaddr *)&dnsr.remote, &dnsr.sockLen);
|
||
|
////errno = WSAGetLastError();
|
||
|
|
||
|
if (dnsr.sock == INVALID_SOCKET || errno) {
|
||
|
if (verbatim || cfig.dnsLogLevel) {
|
||
|
sprintf(logBuff, "Accept Failed, Error=%s", strerror(errno));
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
} else
|
||
|
procTCP(&dnsr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (network.forwConn.ready && FD_ISSET(network.forwConn.sock, &readfds)) {
|
||
|
if (frdnmess(&dnsr)) {
|
||
|
sdnmess(&dnsr);
|
||
|
|
||
|
if (verbatim || cfig.dnsLogLevel >= 2) {
|
||
|
if (dnsr.dnsIndex < MAX_SERVERS) {
|
||
|
if (dnsr.dnsp->header.ancount) {
|
||
|
if (getResult(&dnsr))
|
||
|
sprintf(logBuff,
|
||
|
"%s resolved from Forwarding Server as %s",
|
||
|
strquery(&dnsr),
|
||
|
dnsr.tempname);
|
||
|
else
|
||
|
sprintf(logBuff, "%s resolved from Forwarding Server", strquery(&dnsr));
|
||
|
} else
|
||
|
sprintf(logBuff, "%s not found by Forwarding Server", strquery(&dnsr));
|
||
|
} else {
|
||
|
if (dnsr.dnsp->header.ancount) {
|
||
|
if (getResult(&dnsr))
|
||
|
sprintf(logBuff,
|
||
|
"%s resolved from Conditional Forwarder as %s",
|
||
|
strquery(&dnsr),
|
||
|
dnsr.tempname);
|
||
|
else
|
||
|
sprintf(logBuff, "%s resolved from Conditional Forwarder", strquery(&dnsr));
|
||
|
} else
|
||
|
sprintf(logBuff, "%s not found by Conditional Forwarder", strquery(&dnsr));
|
||
|
}
|
||
|
|
||
|
logDNSMess(&dnsr, logBuff, 2);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
} else
|
||
|
t = time(nullptr);
|
||
|
|
||
|
if (g_magin.done) {
|
||
|
currentInd = g_magin.currentInd;
|
||
|
g_magin.done = false;
|
||
|
//sprintf(logBuff, "New Index=%u", currentInd);
|
||
|
//logMess(logBuff, 2);
|
||
|
} else
|
||
|
checkSize();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
closeConn();
|
||
|
|
||
|
if (cfig.dhcpReplConn.ready)
|
||
|
close(cfig.dhcpReplConn.sock);
|
||
|
}
|
||
|
|
||
|
void closeConn() {
|
||
|
if (dhcpService) {
|
||
|
for (int i = 0; i < MAX_SERVERS && network.dhcpConn[i].loaded; i++) {
|
||
|
if (network.dhcpConn[i].ready) {
|
||
|
close(network.dhcpConn[i].sock);
|
||
|
network.dhcpConn[i].ready = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (network.dhcpListener.ready) {
|
||
|
close(network.dhcpListener.sock);
|
||
|
network.dhcpListener.ready = false;
|
||
|
}
|
||
|
|
||
|
if (network.httpConn.ready) {
|
||
|
close(network.httpConn.sock);
|
||
|
network.httpConn.ready = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (dnsService) {
|
||
|
for (int i = 0; i < MAX_SERVERS && network.dnsUdpConn[i].loaded; i++)
|
||
|
if (network.dnsUdpConn[i].ready) {
|
||
|
close(network.dnsUdpConn[i].sock);
|
||
|
network.dnsUdpConn[i].ready = false;
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < MAX_SERVERS && network.dnsTcpConn[i].loaded; i++)
|
||
|
if (network.dnsTcpConn[i].ready) {
|
||
|
close(network.dnsTcpConn[i].sock);
|
||
|
network.dnsTcpConn[i].ready = false;
|
||
|
}
|
||
|
|
||
|
if (network.forwConn.ready) {
|
||
|
close(network.forwConn.sock);
|
||
|
network.forwConn.ready = false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void catch_int(int sig_num) {
|
||
|
char logBuff[256];
|
||
|
|
||
|
if (cfig.ppid == getpid()) {
|
||
|
kRunning = false;
|
||
|
network.ready = false;
|
||
|
|
||
|
//while (kRunning && network.busy)
|
||
|
// sleep(1);
|
||
|
|
||
|
sprintf(logBuff, "Closing Network Connections...");
|
||
|
logMess(logBuff, 1);
|
||
|
|
||
|
sleep(1);
|
||
|
closeConn();
|
||
|
|
||
|
if (cfig.dhcpReplConn.ready)
|
||
|
close(cfig.dhcpReplConn.sock);
|
||
|
|
||
|
sprintf(logBuff, "Dual Server Stopped !\n");
|
||
|
logMess(logBuff, 1);
|
||
|
|
||
|
close(cfig.fixedSocket);
|
||
|
|
||
|
sleep(1);
|
||
|
exit(EXIT_SUCCESS);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool chkQu(char *query) {
|
||
|
if (strlen(query) >= UCHAR_MAX)
|
||
|
return false;
|
||
|
|
||
|
while (true) {
|
||
|
char *dp = strchr(query, '.');
|
||
|
if (dp) {
|
||
|
MYWORD size = dp - query;
|
||
|
if (size >= 64)
|
||
|
return false;
|
||
|
query += (size + 1);
|
||
|
} else if (strlen(query) >= 64)
|
||
|
return false;
|
||
|
else
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
MYWORD fQu(char *query, dnsPacket *mess, char *raw) {
|
||
|
auto *xname = (MYBYTE *)query;
|
||
|
auto *xraw = (MYBYTE *)raw;
|
||
|
MYWORD retvalue = 0;
|
||
|
bool goneout = false;
|
||
|
|
||
|
while (true) {
|
||
|
MYWORD size = *xraw;
|
||
|
xraw++;
|
||
|
|
||
|
if (!size)
|
||
|
break;
|
||
|
else if (size <= 63) {
|
||
|
if (!goneout)
|
||
|
retvalue += (size + 1);
|
||
|
|
||
|
memcpy(xname, xraw, size);
|
||
|
xname += size;
|
||
|
xraw += size;
|
||
|
|
||
|
if (!*xraw)
|
||
|
break;
|
||
|
|
||
|
*xname = '.';
|
||
|
xname++;
|
||
|
} else {
|
||
|
if (!goneout)
|
||
|
retvalue += 2;
|
||
|
|
||
|
goneout = true;
|
||
|
size %= 128;
|
||
|
size %= 64;
|
||
|
size *= 256;
|
||
|
size += *xraw;
|
||
|
xraw = (MYBYTE *)mess + size;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
*xname = 0;
|
||
|
|
||
|
if (!goneout)
|
||
|
retvalue++;
|
||
|
|
||
|
return retvalue;
|
||
|
}
|
||
|
|
||
|
MYWORD qLen(char *query) {
|
||
|
MYWORD fullsize = 1;
|
||
|
|
||
|
while (true) {
|
||
|
char *dp = strchr(query, '.');
|
||
|
|
||
|
if (dp != nullptr) {
|
||
|
int size = (int)(dp - query);
|
||
|
query += (size + 1);
|
||
|
fullsize += (size + 1);
|
||
|
} else {
|
||
|
int size = (int)strlen(query);
|
||
|
|
||
|
if (size)
|
||
|
fullsize += (size + 1);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
//printf("%i\n",fullsize);
|
||
|
return fullsize;
|
||
|
}
|
||
|
|
||
|
#pragma clang diagnostic push
|
||
|
#pragma ide diagnostic ignored "cppcoreguidelines-narrowing-conversions"
|
||
|
MYWORD pQu(char *raw, char *query) {
|
||
|
MYWORD fullsize = 1;
|
||
|
|
||
|
while (true) {
|
||
|
char *i = strchr(query, '.');
|
||
|
|
||
|
if (i != nullptr) {
|
||
|
int size = i - query;
|
||
|
*raw = size;
|
||
|
raw++;
|
||
|
memcpy(raw, query, size);
|
||
|
raw += size;
|
||
|
query += (size + 1);
|
||
|
fullsize += (size + 1);
|
||
|
} else {
|
||
|
int size = (int)strlen(query);
|
||
|
if (size) {
|
||
|
*raw = size;
|
||
|
raw++;
|
||
|
strcpy(raw, query);
|
||
|
fullsize += (size + 1);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
//printf("%i\n",fullsize);
|
||
|
return fullsize;
|
||
|
}
|
||
|
#pragma clang diagnostic pop
|
||
|
|
||
|
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 addRREmpty(data5 *req) {
|
||
|
req->dnsp->header.ra = 0;
|
||
|
req->dnsp->header.at = 0;
|
||
|
req->dnsp->header.aa = 0;
|
||
|
req->dnsp->header.qr = 1;
|
||
|
req->dnsp->header.qdcount = 0;
|
||
|
req->dnsp->header.ancount = 0;
|
||
|
req->dnsp->header.nscount = 0;
|
||
|
req->dnsp->header.adcount = 0;
|
||
|
req->dp = &req->dnsp->data;
|
||
|
}
|
||
|
|
||
|
void addRRError(data5 *req, MYBYTE rcode) {
|
||
|
req->dnsp->header.qr = 1;
|
||
|
req->dp = req->raw + req->bytes;
|
||
|
req->dnsp->header.rcode = rcode;
|
||
|
}
|
||
|
|
||
|
void addRRNone(data5 *req) {
|
||
|
if (network.dns[0])
|
||
|
req->dnsp->header.ra = 1;
|
||
|
else
|
||
|
req->dnsp->header.ra = 0;
|
||
|
|
||
|
req->dnsp->header.at = 0;
|
||
|
req->dnsp->header.aa = 0;
|
||
|
|
||
|
req->dnsp->header.qr = 1;
|
||
|
req->dnsp->header.ancount = 0;
|
||
|
req->dnsp->header.nscount = 0;
|
||
|
req->dnsp->header.adcount = 0;
|
||
|
}
|
||
|
|
||
|
#pragma clang diagnostic push
|
||
|
#pragma ide diagnostic ignored "hicpp-multiway-paths-covered"
|
||
|
void addRRExt(data5 *req) {
|
||
|
char tempbuff[512];
|
||
|
//char logBuff[512];
|
||
|
//sprintf(logBuff, "%s=%s=%i\n", req->cname, req->query, req->bytes);
|
||
|
//logMess(logBuff, 2);
|
||
|
|
||
|
if (strcasecmp(req->cname, req->query) != 0) {
|
||
|
MYBYTE temp[2048];
|
||
|
memcpy(temp, req->raw, req->bytes);
|
||
|
auto *input = (dnsPacket *)temp;
|
||
|
req->dnsp = (dnsPacket *)req->raw;
|
||
|
|
||
|
req->dnsp->header.aa = 0;
|
||
|
req->dnsp->header.at = 0;
|
||
|
req->dnsp->header.qdcount = htons(1);
|
||
|
req->dnsp->header.ancount = htons(1);
|
||
|
|
||
|
//manuplate the response
|
||
|
req->dp = &req->dnsp->data;
|
||
|
req->dp += pQu(req->dp, req->query);
|
||
|
req->dp += pUShort(req->dp, DNS_TYPE_A);
|
||
|
req->dp += pUShort(req->dp, DNS_CLASS_IN);
|
||
|
req->dp += pQu(req->dp, req->query);
|
||
|
req->dp += pUShort(req->dp, DNS_TYPE_CNAME);
|
||
|
req->dp += pUShort(req->dp, DNS_CLASS_IN);
|
||
|
req->dp += pUInt(req->dp, cfig.lease);
|
||
|
req->dp += pUShort(req->dp, qLen(req->cname));
|
||
|
req->dp += pQu(req->dp, req->cname);
|
||
|
|
||
|
char *indp = &input->data;
|
||
|
|
||
|
for (int i = 1; i <= ntohs(input->header.qdcount); i++) {
|
||
|
indp += fQu(tempbuff, input, indp);
|
||
|
indp += 4;
|
||
|
}
|
||
|
|
||
|
for (int i = 1; i <= ntohs(input->header.ancount); i++) {
|
||
|
indp += fQu(tempbuff, input, indp);
|
||
|
MYWORD type = fUShort(indp);
|
||
|
req->dp += pQu(req->dp, tempbuff);
|
||
|
memcpy(req->dp, indp, 8);
|
||
|
req->dp += 8;
|
||
|
indp += 8;
|
||
|
//indp += 2; //type
|
||
|
//indp += 2; //class
|
||
|
//indp += 4; //ttl
|
||
|
MYWORD zLen = fUShort(indp);
|
||
|
indp += 2;//datalength
|
||
|
|
||
|
switch (type) {
|
||
|
case DNS_TYPE_A:
|
||
|
req->dp += pUShort(req->dp, zLen);
|
||
|
req->dp += pIP(req->dp, fIP(indp));
|
||
|
break;
|
||
|
case DNS_TYPE_CNAME:
|
||
|
fQu(tempbuff, input, indp);
|
||
|
MYWORD dl = pQu(req->dp + 2, tempbuff);
|
||
|
req->dp += pUShort(req->dp, dl);
|
||
|
req->dp += dl;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
indp += zLen;
|
||
|
req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1);
|
||
|
}
|
||
|
} else {
|
||
|
req->dnsp = (dnsPacket *)req->raw;
|
||
|
req->dp = req->raw + req->bytes;
|
||
|
}
|
||
|
}
|
||
|
#pragma clang diagnostic pop
|
||
|
|
||
|
#pragma clang diagnostic push
|
||
|
#pragma ide diagnostic ignored "hicpp-multiway-paths-covered"
|
||
|
void addRRCache(data5 *req, data7 *cache) {
|
||
|
char tempbuff[512];
|
||
|
|
||
|
if (req->dnsType == DNS_TYPE_A) {
|
||
|
//manuplate the response
|
||
|
//printf("%s=%s\n", req->cname, req->query);
|
||
|
auto *input = (dnsPacket *)cache->response;
|
||
|
char *indp = &input->data;
|
||
|
req->dnsp = (dnsPacket *)req->raw;
|
||
|
req->dp = &req->dnsp->data;
|
||
|
|
||
|
req->dnsp->header.aa = 0;
|
||
|
req->dnsp->header.at = 0;
|
||
|
req->dnsp->header.ancount = 0;
|
||
|
req->dnsp->header.qdcount = htons(1);
|
||
|
|
||
|
req->dp = &req->dnsp->data;
|
||
|
req->dp += pQu(req->dp, req->query);
|
||
|
req->dp += pUShort(req->dp, req->dnsType);
|
||
|
req->dp += pUShort(req->dp, req->qclass);
|
||
|
|
||
|
if (strcasecmp(req->cname, req->query) != 0) {
|
||
|
req->dp += pQu(req->dp, req->query);
|
||
|
req->dp += pUShort(req->dp, DNS_TYPE_CNAME);
|
||
|
req->dp += pUShort(req->dp, DNS_CLASS_IN);
|
||
|
req->dp += pUInt(req->dp, cfig.lease);
|
||
|
req->dp += pUShort(req->dp, qLen(req->cname));
|
||
|
req->dp += pQu(req->dp, req->cname);
|
||
|
req->dnsp->header.ancount = htons(1);
|
||
|
}
|
||
|
|
||
|
for (int i = 1; i <= ntohs(input->header.qdcount); i++) {
|
||
|
indp += fQu(tempbuff, input, indp);
|
||
|
indp += 4;
|
||
|
}
|
||
|
|
||
|
for (int i = 1; i <= ntohs(input->header.ancount); i++) {
|
||
|
indp += fQu(tempbuff, input, indp);
|
||
|
MYWORD type = fUShort(indp);
|
||
|
|
||
|
if (!strcasecmp(tempbuff, req->query))
|
||
|
strcpy(tempbuff, req->query);
|
||
|
|
||
|
req->dp += pQu(req->dp, tempbuff);
|
||
|
memcpy(req->dp, indp, 8);
|
||
|
req->dp += 8;
|
||
|
indp += 8;
|
||
|
//indp += 2; //type
|
||
|
//indp += 2; //class
|
||
|
//indp += 4; //ttl
|
||
|
MYWORD zLen = fUShort(indp);
|
||
|
indp += 2;//datalength
|
||
|
|
||
|
switch (type) {
|
||
|
case DNS_TYPE_A:
|
||
|
req->dp += pUShort(req->dp, zLen);
|
||
|
req->dp += pIP(req->dp, fIP(indp));
|
||
|
break;
|
||
|
case DNS_TYPE_CNAME:
|
||
|
fQu(tempbuff, input, indp);
|
||
|
MYWORD dl = pQu(req->dp + 2, tempbuff);
|
||
|
req->dp += pUShort(req->dp, dl);
|
||
|
req->dp += dl;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
indp += zLen;
|
||
|
req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1);
|
||
|
}
|
||
|
} else if (req->dnsType == DNS_TYPE_PTR || req->dnsType == DNS_TYPE_ANY || req->dnsType == DNS_TYPE_AAAA) {
|
||
|
req->dnsp = (dnsPacket *)req->raw;
|
||
|
MYWORD xid = req->dnsp->header.xid;
|
||
|
memcpy(req->raw, cache->response, cache->bytes);
|
||
|
req->dp = req->raw + cache->bytes;
|
||
|
req->dnsp->header.xid = xid;
|
||
|
}
|
||
|
}
|
||
|
#pragma clang diagnostic pop
|
||
|
|
||
|
void addRRA(data5 *req) {
|
||
|
//if (req->qType == QTYPE_A_BARE && req->cacheType != CTYPE_NONE)
|
||
|
// sprintf(req->cname, "%s.%s", req->query, cfig.zone);
|
||
|
|
||
|
if (strcasecmp(req->query, req->cname) != 0) {
|
||
|
req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1);
|
||
|
req->dp += pQu(req->dp, req->query);
|
||
|
req->dp += pUShort(req->dp, DNS_TYPE_CNAME);
|
||
|
req->dp += pUShort(req->dp, DNS_CLASS_IN);
|
||
|
req->dp += pUInt(req->dp, cfig.lease);
|
||
|
req->dp += pUShort(req->dp, qLen(req->cname));
|
||
|
req->dp += pQu(req->dp, req->cname);
|
||
|
}
|
||
|
|
||
|
for (; req->iterBegin != dnsCache[currentInd].end(); req->iterBegin++) {
|
||
|
data7 *cache = req->iterBegin->second;
|
||
|
|
||
|
if (strcasecmp(cache->name, req->mapname) != 0)
|
||
|
break;
|
||
|
|
||
|
if (cache->ip) {
|
||
|
req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1);
|
||
|
req->dp += pQu(req->dp, req->cname);
|
||
|
req->dp += pUShort(req->dp, DNS_TYPE_A);
|
||
|
req->dp += pUShort(req->dp, DNS_CLASS_IN);
|
||
|
req->dp += pUInt(req->dp, cfig.lease);
|
||
|
req->dp += pUShort(req->dp, 4);
|
||
|
req->dp += pIP(req->dp, cache->ip);
|
||
|
}
|
||
|
}
|
||
|
//req->bytes = req->dp - req->raw;
|
||
|
}
|
||
|
|
||
|
void addRRPtr(data5 *req) {
|
||
|
for (; req->iterBegin != dnsCache[currentInd].end(); req->iterBegin++) {
|
||
|
if (data7 *cache = req->iterBegin->second) {
|
||
|
if (strcasecmp(cache->name, req->mapname) != 0)
|
||
|
break;
|
||
|
|
||
|
req->dp += pQu(req->dp, req->query);
|
||
|
req->dp += pUShort(req->dp, DNS_TYPE_PTR);
|
||
|
req->dp += pUShort(req->dp, DNS_CLASS_IN);
|
||
|
req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1);
|
||
|
req->dp += pUInt(req->dp, cfig.lease);
|
||
|
|
||
|
if (!cache->hostname[0])
|
||
|
strcpy(req->cname, cfig.zone);
|
||
|
else if (!strchr(cache->hostname, '.'))
|
||
|
sprintf(req->cname, "%s.%s", cache->hostname, cfig.zone);
|
||
|
else
|
||
|
strcpy(req->cname, cache->hostname);
|
||
|
|
||
|
req->dp += pUShort(req->dp, qLen(req->cname));
|
||
|
req->dp += pQu(req->dp, req->cname);
|
||
|
}
|
||
|
}
|
||
|
//req->bytes = req->dp - req->raw;
|
||
|
}
|
||
|
|
||
|
void addRRServerA(data5 *req) {
|
||
|
//if (req->qType == QTYPE_A_BARE)
|
||
|
// sprintf(req->cname, "%s.%s", req->query, cfig.zone);
|
||
|
|
||
|
if (strcasecmp(req->query, req->cname) != 0) {
|
||
|
req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1);
|
||
|
req->dp += pQu(req->dp, req->query);
|
||
|
req->dp += pUShort(req->dp, DNS_TYPE_CNAME);
|
||
|
req->dp += pUShort(req->dp, DNS_CLASS_IN);
|
||
|
req->dp += pUInt(req->dp, cfig.lease);
|
||
|
req->dp += pUShort(req->dp, qLen(req->cname));
|
||
|
req->dp += pQu(req->dp, req->cname);
|
||
|
}
|
||
|
|
||
|
auto it = req->iterBegin;
|
||
|
|
||
|
for (; it != dnsCache[currentInd].end(); it++) {
|
||
|
if (data7 *cache = it->second) {
|
||
|
if (strcasecmp(cache->name, req->mapname) != 0)
|
||
|
break;
|
||
|
|
||
|
if (cache->ip && cache->ip == network.dnsUdpConn[req->sockInd].server) {
|
||
|
req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1);
|
||
|
req->dp += pQu(req->dp, req->cname);
|
||
|
req->dp += pUShort(req->dp, DNS_TYPE_A);
|
||
|
req->dp += pUShort(req->dp, DNS_CLASS_IN);
|
||
|
req->dp += pUInt(req->dp, cfig.lease);
|
||
|
req->dp += pUShort(req->dp, 4);
|
||
|
req->dp += pIP(req->dp, cache->ip);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (; req->iterBegin != dnsCache[currentInd].end(); req->iterBegin++) {
|
||
|
if (data7 *cache = req->iterBegin->second) {
|
||
|
if (strcasecmp(cache->name, req->mapname) != 0)
|
||
|
break;
|
||
|
|
||
|
if (cache->ip && cache->ip != network.dnsUdpConn[req->sockInd].server) {
|
||
|
req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1);
|
||
|
req->dp += pQu(req->dp, req->cname);
|
||
|
req->dp += pUShort(req->dp, DNS_TYPE_A);
|
||
|
req->dp += pUShort(req->dp, DNS_CLASS_IN);
|
||
|
req->dp += pUInt(req->dp, cfig.lease);
|
||
|
req->dp += pUShort(req->dp, 4);
|
||
|
req->dp += pIP(req->dp, cache->ip);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
//req->bytes = req->dp - req->raw;
|
||
|
}
|
||
|
|
||
|
void addRRAny(data5 *req) {
|
||
|
if (req->qType == QTYPE_A_BARE || req->qType == QTYPE_A_LOCAL || req->qType == QTYPE_A_ZONE)
|
||
|
req->iterBegin = dnsCache[currentInd].find(setMapName(req->tempname, req->mapname, DNS_TYPE_A));
|
||
|
else if (req->qType == QTYPE_P_LOCAL || req->qType == QTYPE_P_ZONE)
|
||
|
req->iterBegin = dnsCache[currentInd].find(setMapName(req->tempname, req->mapname, DNS_TYPE_PTR));
|
||
|
else
|
||
|
return;
|
||
|
|
||
|
addRRNone(req);
|
||
|
|
||
|
for (; req->iterBegin != dnsCache[currentInd].end(); req->iterBegin++) {
|
||
|
if (data7 *cache = req->iterBegin->second) {
|
||
|
if (strcasecmp(cache->name, req->mapname) != 0)
|
||
|
break;
|
||
|
|
||
|
if (cache->expiry < t)
|
||
|
continue;
|
||
|
|
||
|
switch (cache->cacheType) {
|
||
|
case CTYPE_LOCAL_A:
|
||
|
case CTYPE_SERVER_A_AUTH:
|
||
|
case CTYPE_STATIC_A_AUTH:
|
||
|
req->dp += pQu(req->dp, req->cname);
|
||
|
req->dp += pUShort(req->dp, DNS_TYPE_A);
|
||
|
req->dp += pUShort(req->dp, DNS_CLASS_IN);
|
||
|
req->dp += pUInt(req->dp, cfig.lease);
|
||
|
req->dp += pUShort(req->dp, 4);
|
||
|
req->dp += pIP(req->dp, cache->ip);
|
||
|
req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1);
|
||
|
break;
|
||
|
|
||
|
case CTYPE_EXT_CNAME:
|
||
|
req->dp += pQu(req->dp, req->cname);
|
||
|
req->dp += pUShort(req->dp, DNS_TYPE_CNAME);
|
||
|
req->dp += pUShort(req->dp, DNS_CLASS_IN);
|
||
|
req->dp += pUInt(req->dp, cfig.lease);
|
||
|
req->dp += pUShort(req->dp, qLen(cache->hostname));
|
||
|
req->dp += pQu(req->dp, cache->hostname);
|
||
|
req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1);
|
||
|
break;
|
||
|
|
||
|
case CTYPE_LOCAL_CNAME:
|
||
|
req->dp += pQu(req->dp, req->cname);
|
||
|
req->dp += pUShort(req->dp, DNS_TYPE_CNAME);
|
||
|
req->dp += pUShort(req->dp, DNS_CLASS_IN);
|
||
|
req->dp += pUInt(req->dp, cfig.lease);
|
||
|
sprintf(req->cname, "%s.%s", cache->hostname, cfig.zone);
|
||
|
req->dp += pUShort(req->dp, qLen(req->cname));
|
||
|
req->dp += pQu(req->dp, req->cname);
|
||
|
req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1);
|
||
|
break;
|
||
|
|
||
|
case CTYPE_LOCAL_PTR_AUTH:
|
||
|
case CTYPE_LOCAL_PTR_NAUTH:
|
||
|
case CTYPE_STATIC_PTR_AUTH:
|
||
|
case CTYPE_STATIC_PTR_NAUTH:
|
||
|
case CTYPE_SERVER_PTR_AUTH:
|
||
|
case CTYPE_SERVER_PTR_NAUTH:
|
||
|
req->dp += pQu(req->dp, req->cname);
|
||
|
req->dp += pUShort(req->dp, DNS_TYPE_PTR);
|
||
|
req->dp += pUShort(req->dp, DNS_CLASS_IN);
|
||
|
req->dp += pUInt(req->dp, cfig.lease);
|
||
|
|
||
|
if (!cache->hostname[0])
|
||
|
strcpy(req->extbuff, cfig.zone);
|
||
|
else if (strchr(cache->hostname, '.'))
|
||
|
strcpy(req->extbuff, cache->hostname);
|
||
|
else
|
||
|
sprintf(req->extbuff, "%s.%s", cache->hostname, cfig.zone);
|
||
|
|
||
|
req->dp += pUShort(req->dp, qLen(req->extbuff));
|
||
|
req->dp += pQu(req->dp, req->extbuff);
|
||
|
req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (req->qType == QTYPE_A_ZONE) {
|
||
|
addRRMX(req);
|
||
|
addRRNS(req);
|
||
|
addRRSOA(req);
|
||
|
} else if (req->qType == QTYPE_P_ZONE) {
|
||
|
addRRNS(req);
|
||
|
addRRSOA(req);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void addRRWildA(data5 *req, MYDWORD ip) {
|
||
|
req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1);
|
||
|
req->dp += pQu(req->dp, req->query);
|
||
|
req->dp += pUShort(req->dp, DNS_TYPE_A);
|
||
|
req->dp += pUShort(req->dp, DNS_CLASS_IN);
|
||
|
req->dp += pUInt(req->dp, cfig.lease);
|
||
|
req->dp += pUShort(req->dp, 4);
|
||
|
req->dp += pIP(req->dp, ip);
|
||
|
//req->bytes = req->dp - req->raw;
|
||
|
}
|
||
|
|
||
|
void addRRLocalhostA(data5 *req, data7 *cache) {
|
||
|
if (strcasecmp(req->query, req->mapname) != 0) {
|
||
|
req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1);
|
||
|
req->dp += pQu(req->dp, req->query);
|
||
|
req->dp += pUShort(req->dp, DNS_TYPE_CNAME);
|
||
|
req->dp += pUShort(req->dp, DNS_CLASS_IN);
|
||
|
req->dp += pUInt(req->dp, cfig.lease);
|
||
|
req->dp += pUShort(req->dp, qLen(req->mapname));
|
||
|
req->dp += pQu(req->dp, req->mapname);
|
||
|
}
|
||
|
|
||
|
req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1);
|
||
|
req->dp += pQu(req->dp, req->mapname);
|
||
|
req->dp += pUShort(req->dp, DNS_TYPE_A);
|
||
|
req->dp += pUShort(req->dp, DNS_CLASS_IN);
|
||
|
req->dp += pUInt(req->dp, cfig.lease);
|
||
|
req->dp += pUShort(req->dp, 4);
|
||
|
req->dp += pIP(req->dp, cache->ip);
|
||
|
//req->bytes = req->dp - req->raw;
|
||
|
}
|
||
|
|
||
|
void addRRLocalhostPtr(data5 *req, data7 *cache) {
|
||
|
req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1);
|
||
|
req->dp += pQu(req->dp, req->query);
|
||
|
req->dp += pUShort(req->dp, DNS_TYPE_PTR);
|
||
|
req->dp += pUShort(req->dp, DNS_CLASS_IN);
|
||
|
req->dp += pUInt(req->dp, cfig.lease);
|
||
|
req->dp += pUShort(req->dp, qLen(cache->hostname));
|
||
|
req->dp += pQu(req->dp, cache->hostname);
|
||
|
//req->bytes = req->dp - req->raw;
|
||
|
}
|
||
|
|
||
|
void addRRMX(data5 *req) {
|
||
|
if (cfig.mxCount[currentInd]) {
|
||
|
for (int m = 0; m < cfig.mxCount[currentInd]; m++)
|
||
|
addRRMXOne(req, m);
|
||
|
}
|
||
|
|
||
|
//req->bytes = req->dp - req->raw;
|
||
|
}
|
||
|
|
||
|
void addRRSOA(data5 *req) {
|
||
|
if (cfig.authorized && cfig.expireTime > t) {
|
||
|
req->dnsp->header.at = 1;
|
||
|
req->dnsp->header.aa = 1;
|
||
|
|
||
|
if (req->qType == QTYPE_A_BARE || req->qType == QTYPE_A_LOCAL || req->qType == QTYPE_A_ZONE)
|
||
|
req->dp += pQu(req->dp, cfig.zone);
|
||
|
else if (req->qType == QTYPE_P_LOCAL || req->qType == QTYPE_P_ZONE)
|
||
|
req->dp += pQu(req->dp, cfig.authority);
|
||
|
else
|
||
|
return;
|
||
|
|
||
|
if ((req->dnsType == DNS_TYPE_ANY || req->dnsType == DNS_TYPE_NS || req->dnsType == DNS_TYPE_SOA
|
||
|
|| req->dnsType == DNS_TYPE_AXFR)
|
||
|
&& (req->qType == QTYPE_A_ZONE || req->qType == QTYPE_P_ZONE))
|
||
|
req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1);
|
||
|
else
|
||
|
req->dnsp->header.nscount = htons(htons(req->dnsp->header.nscount) + 1);
|
||
|
|
||
|
req->dp += pUShort(req->dp, DNS_TYPE_SOA);
|
||
|
req->dp += pUShort(req->dp, DNS_CLASS_IN);
|
||
|
req->dp += pUInt(req->dp, cfig.lease);
|
||
|
char *data = req->dp;
|
||
|
req->dp += 2;
|
||
|
req->dp += pQu(req->dp, cfig.nsP);
|
||
|
sprintf(req->extbuff, "hostmaster.%s", cfig.zone);
|
||
|
req->dp += pQu(req->dp, req->extbuff);
|
||
|
|
||
|
if (req->qType == QTYPE_P_LOCAL || req->qType == QTYPE_P_EXT || req->qType == QTYPE_P_ZONE)
|
||
|
req->dp += pUInt(req->dp, cfig.serial2);
|
||
|
else
|
||
|
req->dp += pUInt(req->dp, cfig.serial1);
|
||
|
|
||
|
req->dp += pUInt(req->dp, cfig.refresh);
|
||
|
req->dp += pUInt(req->dp, cfig.retry);
|
||
|
req->dp += pUInt(req->dp, cfig.expire);
|
||
|
req->dp += pUInt(req->dp, cfig.minimum);
|
||
|
pUShort(data, (req->dp - data) - 2);
|
||
|
}
|
||
|
//req->bytes = req->dp - req->raw;
|
||
|
}
|
||
|
|
||
|
void addRRNS(data5 *req) {
|
||
|
//printf("%s=%u\n", cfig.ns, cfig.expireTime);
|
||
|
if (cfig.authorized && cfig.expireTime > t) {
|
||
|
req->dnsp->header.at = 1;
|
||
|
req->dnsp->header.aa = 1;
|
||
|
|
||
|
//if (cfig.nsP[0])
|
||
|
if (cfig.nsP[0] && (cfig.replication != 2 || cfig.dnsRepl > t)) {
|
||
|
if (req->qType == QTYPE_A_BARE || req->qType == QTYPE_A_LOCAL || req->qType == QTYPE_A_ZONE)
|
||
|
req->dp += pQu(req->dp, cfig.zone);
|
||
|
else if (req->qType == QTYPE_P_LOCAL || req->qType == QTYPE_P_ZONE)
|
||
|
req->dp += pQu(req->dp, cfig.authority);
|
||
|
else
|
||
|
return;
|
||
|
|
||
|
if ((req->dnsType == DNS_TYPE_ANY || req->dnsType == DNS_TYPE_NS || req->dnsType == DNS_TYPE_SOA
|
||
|
|| req->dnsType == DNS_TYPE_AXFR)
|
||
|
&& (req->qType == QTYPE_A_ZONE || req->qType == QTYPE_P_ZONE))
|
||
|
req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1);
|
||
|
else
|
||
|
req->dnsp->header.nscount = htons(htons(req->dnsp->header.nscount) + 1);
|
||
|
|
||
|
req->dp += pUShort(req->dp, DNS_TYPE_NS);
|
||
|
req->dp += pUShort(req->dp, DNS_CLASS_IN);
|
||
|
req->dp += pUInt(req->dp, cfig.expire);
|
||
|
req->dp += pUShort(req->dp, qLen(cfig.nsP));
|
||
|
req->dp += pQu(req->dp, cfig.nsP);
|
||
|
}
|
||
|
|
||
|
if (cfig.nsS[0] && (cfig.replication == 2 || cfig.dnsRepl > t))
|
||
|
//if (cfig.nsS[0] && cfig.dnsRepl > t)
|
||
|
{
|
||
|
if (req->qType == QTYPE_A_BARE || req->qType == QTYPE_A_LOCAL || req->qType == QTYPE_A_ZONE)
|
||
|
req->dp += pQu(req->dp, cfig.zone);
|
||
|
else if (req->qType == QTYPE_P_LOCAL || req->qType == QTYPE_P_ZONE)
|
||
|
req->dp += pQu(req->dp, cfig.authority);
|
||
|
else
|
||
|
return;
|
||
|
|
||
|
if ((req->dnsType == DNS_TYPE_ANY || req->dnsType == DNS_TYPE_NS || req->dnsType == DNS_TYPE_SOA
|
||
|
|| req->dnsType == DNS_TYPE_AXFR)
|
||
|
&& (req->qType == QTYPE_A_ZONE || req->qType == QTYPE_P_ZONE))
|
||
|
req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1);
|
||
|
else
|
||
|
req->dnsp->header.nscount = htons(htons(req->dnsp->header.nscount) + 1);
|
||
|
|
||
|
req->dp += pUShort(req->dp, DNS_TYPE_NS);
|
||
|
req->dp += pUShort(req->dp, DNS_CLASS_IN);
|
||
|
req->dp += pUInt(req->dp, cfig.expire);
|
||
|
req->dp += pUShort(req->dp, qLen(cfig.nsS));
|
||
|
req->dp += pQu(req->dp, cfig.nsS);
|
||
|
}
|
||
|
}
|
||
|
//req->bytes = req->dp - req->raw;
|
||
|
}
|
||
|
|
||
|
void addRRAd(data5 *req) {
|
||
|
//printf("%s=%u\n", cfig.ns, cfig.expireTime);
|
||
|
if (cfig.authorized && cfig.expireTime > t) {
|
||
|
//if (cfig.nsP[0])
|
||
|
if (cfig.nsP[0] && (cfig.replication != 2 || cfig.dnsRepl > t)) {
|
||
|
req->dnsp->header.adcount = htons(htons(req->dnsp->header.adcount) + 1);
|
||
|
req->dp += pQu(req->dp, cfig.nsP);
|
||
|
|
||
|
req->dp += pUShort(req->dp, DNS_TYPE_A);
|
||
|
req->dp += pUShort(req->dp, DNS_CLASS_IN);
|
||
|
req->dp += pUInt(req->dp, cfig.lease);
|
||
|
req->dp += pUShort(req->dp, 4);
|
||
|
|
||
|
if (cfig.replication)
|
||
|
req->dp += pIP(req->dp, cfig.zoneServers[0]);
|
||
|
else
|
||
|
req->dp += pIP(req->dp, network.listenServers[req->sockInd]);
|
||
|
}
|
||
|
|
||
|
if (cfig.nsS[0] && (cfig.replication == 2 || cfig.dnsRepl > t))
|
||
|
//if (cfig.nsS[0] && cfig.dnsRepl > t)
|
||
|
{
|
||
|
req->dnsp->header.adcount = htons(htons(req->dnsp->header.adcount) + 1);
|
||
|
req->dp += pQu(req->dp, cfig.nsS);
|
||
|
req->dp += pUShort(req->dp, DNS_TYPE_A);
|
||
|
req->dp += pUShort(req->dp, DNS_CLASS_IN);
|
||
|
req->dp += pUInt(req->dp, cfig.lease);
|
||
|
req->dp += pUShort(req->dp, 4);
|
||
|
req->dp += pIP(req->dp, cfig.zoneServers[1]);
|
||
|
}
|
||
|
}
|
||
|
//req->bytes = req->dp - req->raw;
|
||
|
}
|
||
|
|
||
|
void addRRAOne(data5 *req) {
|
||
|
if (data7 *cache = req->iterBegin->second) {
|
||
|
req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1);
|
||
|
|
||
|
if (!cache->name[0])
|
||
|
strcpy(req->cname, cfig.zone);
|
||
|
else if (!strchr(cache->name, '.'))
|
||
|
sprintf(req->cname, "%s.%s", cache->name, cfig.zone);
|
||
|
else
|
||
|
strcpy(req->cname, cache->name);
|
||
|
|
||
|
req->dp += pQu(req->dp, req->cname);
|
||
|
req->dp += pUShort(req->dp, DNS_TYPE_A);
|
||
|
req->dp += pUShort(req->dp, DNS_CLASS_IN);
|
||
|
req->dp += pUInt(req->dp, cfig.lease);
|
||
|
req->dp += pUShort(req->dp, 4);
|
||
|
req->dp += pIP(req->dp, cache->ip);
|
||
|
//req->bytes = req->dp - req->raw;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void addRRPtrOne(data5 *req) {
|
||
|
if (data7 *cache = req->iterBegin->second) {
|
||
|
req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1);
|
||
|
sprintf(req->cname, "%s%s", cache->name, arpa);
|
||
|
req->dp += pQu(req->dp, req->cname);
|
||
|
req->dp += pUShort(req->dp, DNS_TYPE_PTR);
|
||
|
req->dp += pUShort(req->dp, DNS_CLASS_IN);
|
||
|
req->dp += pUInt(req->dp, cfig.lease);
|
||
|
|
||
|
if (!cache->hostname[0])
|
||
|
strcpy(req->cname, cfig.zone);
|
||
|
else if (!strchr(cache->hostname, '.'))
|
||
|
sprintf(req->cname, "%s.%s", cache->hostname, cfig.zone);
|
||
|
else
|
||
|
strcpy(req->cname, cache->hostname);
|
||
|
|
||
|
req->dp += pUShort(req->dp, qLen(req->cname));
|
||
|
req->dp += pQu(req->dp, req->cname);
|
||
|
}
|
||
|
|
||
|
//req->bytes = req->dp - req->raw;
|
||
|
}
|
||
|
|
||
|
void addRRSTAOne(data5 *req) {
|
||
|
if (data7 *cache = req->iterBegin->second) {
|
||
|
req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1);
|
||
|
|
||
|
if (!cache->name[0])
|
||
|
strcpy(req->cname, cfig.zone);
|
||
|
else if (!strchr(cache->name, '.'))
|
||
|
sprintf(req->cname, "%s.%s", cache->name, cfig.zone);
|
||
|
else
|
||
|
strcpy(req->cname, cache->name);
|
||
|
|
||
|
req->dp += pQu(req->dp, req->cname);
|
||
|
req->dp += pUShort(req->dp, DNS_TYPE_A);
|
||
|
req->dp += pUShort(req->dp, DNS_CLASS_IN);
|
||
|
req->dp += pUInt(req->dp, cfig.lease);
|
||
|
req->dp += pUShort(req->dp, 4);
|
||
|
req->dp += pIP(req->dp, cache->ip);
|
||
|
}
|
||
|
//req->bytes = req->dp - req->raw;
|
||
|
}
|
||
|
|
||
|
void addRRCNOne(data5 *req) {
|
||
|
if (data7 *cache = req->iterBegin->second) {
|
||
|
req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1);
|
||
|
|
||
|
if (!cache->name[0])
|
||
|
strcpy(req->cname, cfig.zone);
|
||
|
else if (strchr(cache->name, '.'))
|
||
|
strcpy(req->cname, cache->name);
|
||
|
else
|
||
|
sprintf(req->cname, "%s.%s", cache->name, cfig.zone);
|
||
|
|
||
|
req->dp += pQu(req->dp, req->cname);
|
||
|
req->dp += pUShort(req->dp, DNS_TYPE_CNAME);
|
||
|
req->dp += pUShort(req->dp, DNS_CLASS_IN);
|
||
|
req->dp += pUInt(req->dp, cfig.lease);
|
||
|
|
||
|
if (!cache->hostname[0])
|
||
|
strcpy(req->cname, cfig.zone);
|
||
|
else if (strchr(cache->hostname, '.'))
|
||
|
strcpy(req->cname, cache->hostname);
|
||
|
else
|
||
|
sprintf(req->cname, "%s.%s", cache->hostname, cfig.zone);
|
||
|
|
||
|
req->dp += pUShort(req->dp, qLen(req->cname));
|
||
|
req->dp += pQu(req->dp, req->cname);
|
||
|
}
|
||
|
//req->bytes = req->dp - req->raw;
|
||
|
}
|
||
|
|
||
|
void addRRMXOne(data5 *req, MYBYTE m) {
|
||
|
//req->dp += pQu(req->dp, req->query);
|
||
|
req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1);
|
||
|
req->dp += pQu(req->dp, cfig.zone);
|
||
|
req->dp += pUShort(req->dp, DNS_TYPE_MX);
|
||
|
req->dp += pUShort(req->dp, DNS_CLASS_IN);
|
||
|
req->dp += pUInt(req->dp, cfig.lease);
|
||
|
req->dp += pUShort(req->dp, strlen(cfig.mxServers[currentInd][m].hostname) + 4);
|
||
|
req->dp += pUShort(req->dp, cfig.mxServers[currentInd][m].pref);
|
||
|
req->dp += pQu(req->dp, cfig.mxServers[currentInd][m].hostname);
|
||
|
//req->bytes = req->dp - req->raw;
|
||
|
}
|
||
|
|
||
|
void procHTTP(data19 *req) {
|
||
|
char logBuff[256];
|
||
|
char tempbuff[512];
|
||
|
req->ling.l_onoff = 1; //0 = off (l_linger ignored), nonzero = on
|
||
|
req->ling.l_linger = 30;//0 = discard data, nonzero = wait for data sent
|
||
|
setsockopt(req->sock, SOL_SOCKET, SO_LINGER, (const char *)&req->ling, sizeof(req->ling));
|
||
|
|
||
|
timeval tv1 {};
|
||
|
fd_set readfds1;
|
||
|
FD_ZERO(&readfds1);
|
||
|
tv1.tv_sec = 1;
|
||
|
tv1.tv_usec = 0;
|
||
|
FD_SET(req->sock, &readfds1);
|
||
|
|
||
|
if (!select((req->sock + 1), &readfds1, nullptr, nullptr, &tv1)) {
|
||
|
sprintf(logBuff, "HTTP Client %s, Message Receive failed", IP2String(tempbuff, req->remote.sin_addr.s_addr));
|
||
|
logDHCPMess(logBuff, 1);
|
||
|
closesocket(req->sock);
|
||
|
free(req);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
char buffer[2048];
|
||
|
req->bytes = (int)recv(req->sock, buffer, sizeof(buffer), 0);
|
||
|
//errno = WSAGetLastError();
|
||
|
|
||
|
if ((verbatim || cfig.dhcpLogLevel >= 1) && (errno || req->bytes <= 0)) {
|
||
|
sprintf(logBuff,
|
||
|
"HTTP Client %s, Message Receive failed, WSAError %d",
|
||
|
IP2String(tempbuff, req->remote.sin_addr.s_addr),
|
||
|
errno);
|
||
|
logDHCPMess(logBuff, 1);
|
||
|
closesocket(req->sock);
|
||
|
free(req);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (cfig.httpClients[0] && !findServer(cfig.httpClients, 8, req->remote.sin_addr.s_addr)) {
|
||
|
if (verbatim || cfig.dhcpLogLevel >= 2) {
|
||
|
sprintf(logBuff, "HTTP Client %s, Access Denied", IP2String(tempbuff, req->remote.sin_addr.s_addr));
|
||
|
logDHCPMess(logBuff, 2);
|
||
|
}
|
||
|
|
||
|
req->dp = (char *)calloc(1, sizeof(send403));
|
||
|
req->bytes = sprintf(req->dp, send403);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (verbatim || cfig.dhcpLogLevel >= 2) {
|
||
|
sprintf(logBuff, "HTTP Client %s, Request Processed", IP2String(tempbuff, req->remote.sin_addr.s_addr));
|
||
|
logDHCPMess(logBuff, 2);
|
||
|
//printf("%s\n", buffer);
|
||
|
}
|
||
|
|
||
|
buffer[sizeof(buffer) - 1] = 0;
|
||
|
char *fp = nullptr;
|
||
|
char *end = strchr(buffer, '\n');
|
||
|
|
||
|
if (end && end > buffer && (*(end - 1) == '\r')) {
|
||
|
*(end - 1) = 0;
|
||
|
|
||
|
if (myTokenize(buffer, buffer, " ", true) > 1)
|
||
|
fp = myGetToken(buffer, 1);
|
||
|
}
|
||
|
|
||
|
if (fp && !strcasecmp(fp, "/"))
|
||
|
sendStatus(req);
|
||
|
else if (fp && icoSize > 0 && !strcasecmp(fp, "/favicon.ico")) {
|
||
|
strcpy(req->contentType, "img");
|
||
|
req->bytes = icoSize;
|
||
|
req->dp = (char *)calloc(1, icoSize);
|
||
|
memcpy(req->dp, icoString, icoSize);
|
||
|
pthread_t threadId;
|
||
|
pthread_attr_t attr;
|
||
|
pthread_attr_init(&attr);
|
||
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||
|
int errcode = pthread_create(&threadId, &attr, sendHTTP, (void *)req);
|
||
|
pthread_attr_destroy(&attr);
|
||
|
return;
|
||
|
}
|
||
|
// else if (fp && !strcasecmp(fp, "/scopestatus"))
|
||
|
// sendScopeStatus(req);
|
||
|
else {
|
||
|
if (fp && (verbatim || cfig.dhcpLogLevel >= 2)) {
|
||
|
sprintf(logBuff, "HTTP Client %s, %s not found", IP2String(tempbuff, req->remote.sin_addr.s_addr), fp);
|
||
|
logDHCPMess(logBuff, 2);
|
||
|
} else if (verbatim || cfig.dhcpLogLevel >= 2) {
|
||
|
sprintf(logBuff, "HTTP Client %s, Invalid request", IP2String(tempbuff, req->remote.sin_addr.s_addr));
|
||
|
logDHCPMess(logBuff, 2);
|
||
|
}
|
||
|
|
||
|
req->dp = (char *)calloc(1, sizeof(send404));
|
||
|
req->bytes = sprintf(req->dp, send404);
|
||
|
pthread_t threadId;
|
||
|
pthread_attr_t attr;
|
||
|
pthread_attr_init(&attr);
|
||
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||
|
int errcode = pthread_create(&threadId, &attr, sendHTTP, (void *)req);
|
||
|
pthread_attr_destroy(&attr);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#pragma clang diagnostic push
|
||
|
#pragma ide diagnostic ignored "bugprone-branch-clone"
|
||
|
void sendStatus(data19 *req) {
|
||
|
char ipbuff[16];
|
||
|
char extbuff[16];
|
||
|
char logBuff[512];
|
||
|
char tempbuff[512];
|
||
|
|
||
|
dhcpMap::iterator p;
|
||
|
MYDWORD iip = 0;
|
||
|
data7 *dhcpEntry = nullptr;
|
||
|
//data7 *cache = nullptr;
|
||
|
//sprintf(tempbuff, "%d=%d", dhcpCache.size(), cfig.dhcpSize);
|
||
|
req->memSize = (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);
|
||
|
|
||
|
//const char bodyStart[] = "<body bgcolor=\"#cccccc\"><table border=\"0\"><tr><td>\n<table width=\"100%%\" border=\"0\"><tr><td colspan=\"2\" align=\"center\"><font size=\"5\"><b>%s</b></font></td></tr><tr><td align=\"left\">Server Name: %s%s</td><td align=\"right\"><a target=\"_new\" href=\"http://dhcp-dns-server.sourceforge.net\">http://dhcp-dns-server.sourceforge.net</td></tr></table>";
|
||
|
|
||
|
if (cfig.replication == 1)
|
||
|
fp += sprintf(fp, bodyStart, sVersion, cfig.servername, "(Primary)", MY_EXE_SIZE);
|
||
|
else if (cfig.replication == 2)
|
||
|
fp += sprintf(fp, bodyStart, sVersion, cfig.servername, "(Secondary)", MY_EXE_SIZE);
|
||
|
else
|
||
|
fp += sprintf(fp, bodyStart, sVersion, cfig.servername, "", MY_EXE_SIZE);
|
||
|
|
||
|
//fp += sprintf(fp, bodyStart, sVersion, cfig.servername);
|
||
|
fp += sprintf(fp, "\n<table border=\"1\" cellpadding=\"1\" width=\"100%%\" bgcolor=\"#b8b8b8\">\n");
|
||
|
|
||
|
if (cfig.dhcpRepl > t) {
|
||
|
fp += sprintf(fp, "<tr><th colspan=\"5\"><font size=\"5\"><i>Active Leases</i></font></th></tr>\n");
|
||
|
fp += sprintf(fp,
|
||
|
"<tr><th>Mac Address</th><th>IP</th><th>Lease Expiry</th><th>Hostname (first 20 "
|
||
|
"chars)</th><th>Server</th></tr>\n");
|
||
|
} else {
|
||
|
fp += sprintf(fp, "<tr><th colspan=\"4\"><font size=\"5\"><i>Active Leases</i></font></th></tr>\n");
|
||
|
fp += sprintf(
|
||
|
fp, "<tr><th>Mac Address</th><th>IP</th><th>Lease Expiry</th><th>Hostname (first 20 chars)</th></tr>\n");
|
||
|
}
|
||
|
|
||
|
for (p = dhcpCache.begin(); kRunning && p != dhcpCache.end() && fp < maxData; p++) {
|
||
|
//if ((dhcpEntry = p->second) && dhcpEntry->display)
|
||
|
if ((dhcpEntry = p->second) && dhcpEntry->display && dhcpEntry->expiry >= t) {
|
||
|
fp += sprintf(fp, "<tr>");
|
||
|
fp += sprintf(fp, td200, dhcpEntry->mapname);
|
||
|
fp += sprintf(fp, td200, IP2String(tempbuff, dhcpEntry->ip));
|
||
|
|
||
|
if (dhcpEntry->expiry >= MY_MAX_TIME)
|
||
|
fp += sprintf(fp, td200, "Infinity");
|
||
|
else {
|
||
|
tm *ttm = localtime(&dhcpEntry->expiry);
|
||
|
strftime(tempbuff, sizeof(tempbuff), "%d-%b-%y %X", ttm);
|
||
|
fp += sprintf(fp, tdnowrap200, tempbuff);
|
||
|
}
|
||
|
|
||
|
if (dhcpEntry->hostname[0]) {
|
||
|
strcpy(tempbuff, dhcpEntry->hostname);
|
||
|
tempbuff[20] = 0;
|
||
|
fp += sprintf(fp, td200, tempbuff);
|
||
|
} else
|
||
|
fp += sprintf(fp, td200, " ");
|
||
|
|
||
|
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 k = cfig.dhcpRanges[rangeInd].rangeStart; k <= cfig.dhcpRanges[rangeInd].rangeEnd; k++, ind++) {
|
||
|
if (cfig.dhcpRanges[rangeInd].expiry[ind] != MY_MAX_TIME) {
|
||
|
if (cfig.dhcpRanges[rangeInd].expiry[ind] < t)
|
||
|
ipfree++;
|
||
|
else
|
||
|
ipused++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
IP2String(tempbuff, ntohl(cfig.dhcpRanges[rangeInd].rangeStart));
|
||
|
IP2String(ipbuff, ntohl(cfig.dhcpRanges[rangeInd].rangeEnd));
|
||
|
IP2String(extbuff, cfig.dhcpRanges[rangeInd].mask);
|
||
|
fp += sprintf(fp,
|
||
|
"<tr><td nowrap>%s - %s</td><td nowrap>%s</td><td align=\"right\">%i</td><td "
|
||
|
"align=\"right\">%i</td></tr>\n",
|
||
|
tempbuff,
|
||
|
ipbuff,
|
||
|
extbuff,
|
||
|
(ipused + ipfree),
|
||
|
ipfree);
|
||
|
}
|
||
|
|
||
|
fp += sprintf(fp, "</table>\n<br>\n<table border=\"1\" width=\"100%%\" cellpadding=\"1\" bgcolor=\"#b8b8b8\">\n");
|
||
|
fp += sprintf(fp, "<tr><th colspan=\"4\"><font size=\"5\"><i>Free Static Leases</i></font></th></tr>\n");
|
||
|
fp += sprintf(fp, "<tr><th>Mac Address</th><th>IP</th><th>Mac Address</th><th>IP</th></tr>\n");
|
||
|
|
||
|
MYBYTE colNum = 0;
|
||
|
|
||
|
for (p = dhcpCache.begin(); kRunning && p != dhcpCache.end() && fp < maxData; p++) {
|
||
|
if ((dhcpEntry = p->second) && dhcpEntry->fixed && dhcpEntry->expiry < t) {
|
||
|
if (!colNum) {
|
||
|
fp += sprintf(fp, "<tr>");
|
||
|
colNum = 1;
|
||
|
} else if (colNum == 1) {
|
||
|
colNum = 2;
|
||
|
} else if (colNum == 2) {
|
||
|
fp += sprintf(fp, "</tr>\n<tr>");
|
||
|
colNum = 1;
|
||
|
}
|
||
|
|
||
|
fp += sprintf(fp, td200, dhcpEntry->mapname);
|
||
|
fp += sprintf(fp, td200, IP2String(tempbuff, dhcpEntry->ip));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (colNum)
|
||
|
fp += sprintf(fp, "</tr>\n");
|
||
|
|
||
|
fp += sprintf(fp, "</table></td></tr></table>\n</body>\n</html>");
|
||
|
//MYBYTE x = sprintf(tempbuff, "%u", (fp - contentStart));
|
||
|
//memcpy((contentStart - 12), tempbuff, x);
|
||
|
strcpy(req->contentType, "text/html");
|
||
|
req->bytes = (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);
|
||
|
}
|
||
|
#pragma clang diagnostic pop
|
||
|
|
||
|
/*
|
||
|
void sendScopeStatus(data19 *req)
|
||
|
{
|
||
|
|
||
|
MYBYTE rangeCount = 0;
|
||
|
req->memSize = 1536 + (150 * cfig.rangeCount);
|
||
|
req->dp = (char*)calloc(1, req->memSize);
|
||
|
|
||
|
if (!req->dp)
|
||
|
{
|
||
|
sprintf(logBuff, "Memory Error");
|
||
|
logDHCPMess(logBuff, 1);
|
||
|
closesocket(req->sock);
|
||
|
free(req);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
char *fp = req->dp;
|
||
|
char *maxData = req->dp + (req->memSize - 512);
|
||
|
tm *ttm = gmtime(&t);
|
||
|
strftime(tempbuff, sizeof(tempbuff), "%a, %d %b %Y %H:%M:%S GMT", ttm);
|
||
|
fp += sprintf(fp, send200, tempbuff, tempbuff);
|
||
|
char *contentStart = fp;
|
||
|
fp += sprintf(fp, htmlStart, htmlTitle);
|
||
|
fp += sprintf(fp, bodyStart, sVersion);
|
||
|
fp += sprintf(fp, "<table border=\"1\" cellpadding=\"1\" width=\"640\" bgcolor=\"#b8b8b8\">\n");
|
||
|
fp += sprintf(fp, "<tr><th colspan=\"4\"><font size=\"5\"><i>Scope Status</i></font></th></tr>\n");
|
||
|
fp += sprintf(fp, "<tr><td><b>DHCP Range</b></td><td align=\"right\"><b>IPs Used</b></td><td align=\"right\"><b>IPs Free</b></td><td align=\"right\"><b>%% Free</b></td></tr>\n");
|
||
|
MYBYTE colNum = 0;
|
||
|
|
||
|
for (char rangeInd = 0; kRunning && rangeInd < cfig.rangeCount && fp < maxData; rangeInd++)
|
||
|
{
|
||
|
float ipused = 0;
|
||
|
float ipfree = 0;
|
||
|
int ind = 0;
|
||
|
|
||
|
for (MYDWORD iip = cfig.dhcpRanges[rangeInd].rangeStart; iip <= cfig.dhcpRanges[rangeInd].rangeEnd; iip++, ind++)
|
||
|
{
|
||
|
if (cfig.dhcpRanges[rangeInd].expiry[ind] > t)
|
||
|
ipused++;
|
||
|
else
|
||
|
ipfree++;
|
||
|
}
|
||
|
|
||
|
IP2String(tempbuff, ntohl(cfig.dhcpRanges[rangeInd].rangeStart));
|
||
|
IP2String(extbuff, ntohl(cfig.dhcpRanges[rangeInd].rangeEnd));
|
||
|
fp += sprintf(fp, "<tr><td>%s - %s</td><td align=\"right\">%5.0f</td><td align=\"right\">%5.0f</td><td align=\"right\">%2.2f</td></tr>\n", tempbuff, extbuff, ipused, ipfree, ((ipfree * 100)/(ipused + ipfree)));
|
||
|
}
|
||
|
|
||
|
fp += sprintf(fp, "</table>\n</body>\n</html>");
|
||
|
memcpy((contentStart - 12), tempbuff, sprintf(tempbuff, "%u", (fp - contentStart)));
|
||
|
req->bytes = fp - req->dp;
|
||
|
|
||
|
pthread_t threadId;
|
||
|
pthread_attr_t attr;
|
||
|
pthread_attr_init(&attr);
|
||
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||
|
int errcode = pthread_create(&threadId, &attr, sendHTTP, (void*)req);
|
||
|
pthread_attr_destroy(&attr);
|
||
|
return;
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
void *sendHTTP(void *lpParam) {
|
||
|
auto *req = (data19 *)lpParam;
|
||
|
|
||
|
//char logBuff[512];
|
||
|
//sprintf(logBuff, "sendHTTP memsize=%d bytes=%d", req->memSize, req->bytes);
|
||
|
|
||
|
char *dp = req->dp;
|
||
|
timeval tv1{};
|
||
|
fd_set writefds1;
|
||
|
int sent = 0;
|
||
|
bool sendheader = true;
|
||
|
|
||
|
while (kRunning && req->bytes > 0) {
|
||
|
tv1.tv_sec = 5;
|
||
|
tv1.tv_usec = 0;
|
||
|
FD_ZERO(&writefds1);
|
||
|
FD_SET(req->sock, &writefds1);
|
||
|
|
||
|
if (select((req->sock + 1), nullptr, &writefds1, nullptr, &tv1)) {
|
||
|
if (sendheader) {
|
||
|
char header[256];
|
||
|
sprintf(header, send200, req->contentType, req->bytes);
|
||
|
send(req->sock, header, strlen(header), 0);
|
||
|
sendheader = false;
|
||
|
} else if (req->bytes > 1024)
|
||
|
sent = (int)send(req->sock, dp, 1024, 0);
|
||
|
else if (req->bytes > 0)
|
||
|
sent = (int)send(req->sock, dp, req->bytes, 0);
|
||
|
else
|
||
|
break;
|
||
|
|
||
|
//errno = WSAGetLastError();
|
||
|
|
||
|
if (errno || sent < 0)
|
||
|
break;
|
||
|
|
||
|
dp += sent;
|
||
|
req->bytes -= sent;
|
||
|
} else
|
||
|
break;
|
||
|
}
|
||
|
//Sleep(10*1000);
|
||
|
//shutdown(req->sock, 2);
|
||
|
closesocket(req->sock);
|
||
|
free(req->dp);
|
||
|
free(req);
|
||
|
pthread_exit(nullptr);
|
||
|
}
|
||
|
|
||
|
void procTCP(data5 *req) {
|
||
|
//debug("procTCP");
|
||
|
|
||
|
char logBuff[512];
|
||
|
req->ling.l_onoff = 1; //0 = off (l_linger ignored), nonzero = on
|
||
|
req->ling.l_linger = 10;//0 = discard data, nonzero = wait for data sent
|
||
|
setsockopt(req->sock, SOL_SOCKET, SO_LINGER, (const char *)&req->ling, sizeof(req->ling));
|
||
|
|
||
|
errno = 0;
|
||
|
req->bytes = recvTcpDnsMess(req->raw, req->sock, sizeof(req->raw));
|
||
|
//printf("%u\n",req->bytes);
|
||
|
|
||
|
if (req->bytes < 2) {
|
||
|
sprintf(logBuff, "Error Getting TCP DNS Message");
|
||
|
logDNSMess(logBuff, 1);
|
||
|
closesocket(req->sock);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
MYWORD pktSize = fUShort(req->raw);
|
||
|
req->dp = req->raw + 2;
|
||
|
req->dnsp = (dnsPacket *)(req->dp);
|
||
|
|
||
|
if (req->dnsp->header.qr)
|
||
|
return;
|
||
|
|
||
|
req->dp = &req->dnsp->data;
|
||
|
MYDWORD clientIP = req->remote.sin_addr.s_addr;
|
||
|
|
||
|
if (!findServer(network.allServers, MAX_SERVERS, clientIP)
|
||
|
&& !findServer(cfig.zoneServers, MAX_TCP_CLIENTS, clientIP)
|
||
|
&& !findServer(&cfig.zoneServers[2], MAX_TCP_CLIENTS - 2, clientIP)) {
|
||
|
sprintf(logBuff, "DNS TCP Query, Access Denied");
|
||
|
logTCPMess(req, logBuff, 1);
|
||
|
addRRError(req, RCODE_REFUSED);
|
||
|
sendTCPmess(req);
|
||
|
closesocket(req->sock);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (ntohs(req->dnsp->header.qdcount) != 1 || ntohs(req->dnsp->header.ancount)) {
|
||
|
sprintf(logBuff, "DNS Query Format Error");
|
||
|
logTCPMess(req, logBuff, 1);
|
||
|
addRRError(req, RCODE_FORMATERROR);
|
||
|
sendTCPmess(req);
|
||
|
closesocket(req->sock);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (req->dnsp->header.opcode != OPCODE_STANDARD_QUERY) {
|
||
|
switch (req->dnsp->header.opcode) {
|
||
|
case OPCODE_INVERSE_QUERY:
|
||
|
sprintf(logBuff, "Inverse query not supported");
|
||
|
break;
|
||
|
|
||
|
case OPCODE_SRVR_STAT_REQ:
|
||
|
sprintf(logBuff, "Server Status Request not supported");
|
||
|
break;
|
||
|
|
||
|
case OPCODE_NOTIFY:
|
||
|
sprintf(logBuff, "Notify not supported");
|
||
|
break;
|
||
|
|
||
|
case OPCODE_DYNAMIC_UPDATE:
|
||
|
sprintf(logBuff, "Dynamic Update not needed/supported by Dual Server");
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
sprintf(logBuff, "OpCode %u not supported", req->dnsp->header.opcode);
|
||
|
}
|
||
|
|
||
|
logTCPMess(req, logBuff, 1);
|
||
|
addRRError(req, RCODE_NOTIMPL);
|
||
|
sendTCPmess(req);
|
||
|
closesocket(req->sock);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
for (int i = 1; i <= ntohs(req->dnsp->header.qdcount); i++) {
|
||
|
req->dp += fQu(req->query, req->dnsp, req->dp);
|
||
|
req->dnsType = fUShort(req->dp);
|
||
|
req->dp += 2;
|
||
|
req->qclass = fUShort(req->dp);
|
||
|
req->dp += 2;
|
||
|
}
|
||
|
|
||
|
if (req->qclass != DNS_CLASS_IN) {
|
||
|
sprintf(logBuff, "DNS Class %u not supported", req->qclass);
|
||
|
logTCPMess(req, logBuff, 1);
|
||
|
addRRError(req, RCODE_NOTIMPL);
|
||
|
sendTCPmess(req);
|
||
|
closesocket(req->sock);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (!req->dnsType) {
|
||
|
sprintf(logBuff, "missing query type");
|
||
|
logTCPMess(req, logBuff, 1);
|
||
|
addRRError(req, RCODE_FORMATERROR);
|
||
|
sendTCPmess(req);
|
||
|
closesocket(req->sock);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
strcpy(req->cname, req->query);
|
||
|
strcpy(req->mapname, req->query);
|
||
|
myLower(req->mapname);
|
||
|
req->qLen = strlen(req->cname);
|
||
|
req->qType = makeLocal(req->mapname);
|
||
|
|
||
|
if (req->qType == QTYPE_A_EXT && req->qLen > cfig.zLen) {
|
||
|
char *dp = req->cname + (req->qLen - cfig.zLen);
|
||
|
|
||
|
if (!strcasecmp(dp, cfig.zone))
|
||
|
req->qType = QTYPE_CHILDZONE;
|
||
|
}
|
||
|
|
||
|
if (req->dnsType != DNS_TYPE_NS && req->dnsType != DNS_TYPE_SOA && req->dnsType != DNS_TYPE_AXFR
|
||
|
&& req->dnsType != DNS_TYPE_IXFR) {
|
||
|
addRRError(req, RCODE_NOTIMPL);
|
||
|
sendTCPmess(req);
|
||
|
sprintf(logBuff, "%s, Query Type not supported", strquery(req));
|
||
|
logTCPMess(req, logBuff, 1);
|
||
|
closesocket(req->sock);
|
||
|
return;
|
||
|
} else if (!cfig.authorized
|
||
|
|| (req->qType != QTYPE_A_ZONE && req->qType != QTYPE_A_LOCAL && req->qType != QTYPE_P_ZONE
|
||
|
&& req->qType != QTYPE_P_LOCAL)) {
|
||
|
addRRError(req, RCODE_NOTAUTH);
|
||
|
sendTCPmess(req);
|
||
|
sprintf(logBuff, "Server is not authority for zone %s", req->query);
|
||
|
logTCPMess(req, logBuff, 1);
|
||
|
} else if (cfig.expireTime < t) {
|
||
|
addRRError(req, RCODE_NOTZONE);
|
||
|
sendTCPmess(req);
|
||
|
sprintf(logBuff, "Zone %s expired", req->query);
|
||
|
logTCPMess(req, logBuff, 1);
|
||
|
} else {
|
||
|
switch (req->dnsType) {
|
||
|
case DNS_TYPE_SOA:
|
||
|
addRRNone(req);
|
||
|
addRRSOA(req);
|
||
|
sendTCPmess(req);
|
||
|
|
||
|
if (req->dnsp->header.ancount)
|
||
|
sprintf(logBuff, "SOA Sent for zone %s", req->query);
|
||
|
else
|
||
|
sprintf(logBuff, "%s not found", strquery(req));
|
||
|
|
||
|
logTCPMess(req, logBuff, 2);
|
||
|
break;
|
||
|
|
||
|
case DNS_TYPE_NS:
|
||
|
addRRNone(req);
|
||
|
addRRNS(req);
|
||
|
addRRAd(req);
|
||
|
sendTCPmess(req);
|
||
|
|
||
|
if (req->dnsp->header.ancount)
|
||
|
sprintf(logBuff, "NS Sent for zone %s", req->query);
|
||
|
else
|
||
|
sprintf(logBuff, "%s not found", strquery(req));
|
||
|
|
||
|
logTCPMess(req, logBuff, 2);
|
||
|
break;
|
||
|
|
||
|
case DNS_TYPE_AXFR:
|
||
|
case DNS_TYPE_IXFR:
|
||
|
|
||
|
if (req->qType == QTYPE_A_ZONE) {
|
||
|
MYWORD records = 0;
|
||
|
|
||
|
addRREmpty(req);
|
||
|
addRRSOA(req);
|
||
|
|
||
|
if (!sendTCPmess(req)) {
|
||
|
closesocket(req->sock);
|
||
|
return;
|
||
|
} else
|
||
|
records++;
|
||
|
|
||
|
addRREmpty(req);
|
||
|
addRRNS(req);
|
||
|
|
||
|
if (!sendTCPmess(req)) {
|
||
|
closesocket(req->sock);
|
||
|
return;
|
||
|
} else
|
||
|
records++;
|
||
|
|
||
|
req->iterBegin = dnsCache[currentInd].begin();
|
||
|
|
||
|
for (; req->iterBegin != dnsCache[currentInd].end(); req->iterBegin++) {
|
||
|
//char tempbuff[256];
|
||
|
//sprintf(tempbuff, "%s=%d=%u",req->iterBegin->second->mapname, req->iterBegin->second->cacheType, req->iterBegin->second->expiry);
|
||
|
//debug(tempbuff);
|
||
|
|
||
|
if (req->iterBegin->second->expiry > t) {
|
||
|
switch (req->iterBegin->second->cacheType) {
|
||
|
case CTYPE_LOCAL_A:
|
||
|
addRREmpty(req);
|
||
|
addRRAOne(req);
|
||
|
break;
|
||
|
|
||
|
case CTYPE_SERVER_A_AUTH:
|
||
|
case CTYPE_STATIC_A_AUTH:
|
||
|
addRREmpty(req);
|
||
|
addRRSTAOne(req);
|
||
|
break;
|
||
|
|
||
|
case CTYPE_LOCAL_CNAME:
|
||
|
case CTYPE_EXT_CNAME:
|
||
|
addRREmpty(req);
|
||
|
addRRCNOne(req);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (!sendTCPmess(req)) {
|
||
|
closesocket(req->sock);
|
||
|
return;
|
||
|
} else
|
||
|
records++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (int m = 0; m < cfig.mxCount[currentInd]; m++) {
|
||
|
addRREmpty(req);
|
||
|
addRRMXOne(req, m);
|
||
|
|
||
|
if (!sendTCPmess(req)) {
|
||
|
closesocket(req->sock);
|
||
|
return;
|
||
|
} else
|
||
|
records++;
|
||
|
}
|
||
|
|
||
|
addRREmpty(req);
|
||
|
addRRSOA(req);
|
||
|
|
||
|
if (sendTCPmess(req)) {
|
||
|
records++;
|
||
|
sprintf(logBuff, "Zone %s with %d RRs Sent", req->query, records);
|
||
|
logTCPMess(req, logBuff, 2);
|
||
|
}
|
||
|
} else if (req->qType == QTYPE_P_ZONE) {
|
||
|
MYWORD records = 0;
|
||
|
|
||
|
addRREmpty(req);
|
||
|
addRRSOA(req);
|
||
|
|
||
|
if (!sendTCPmess(req)) {
|
||
|
closesocket(req->sock);
|
||
|
return;
|
||
|
} else
|
||
|
records++;
|
||
|
|
||
|
addRREmpty(req);
|
||
|
addRRNS(req);
|
||
|
|
||
|
if (!sendTCPmess(req)) {
|
||
|
closesocket(req->sock);
|
||
|
return;
|
||
|
} else
|
||
|
records++;
|
||
|
|
||
|
req->iterBegin = dnsCache[currentInd].begin();
|
||
|
|
||
|
for (; req->iterBegin != dnsCache[currentInd].end(); req->iterBegin++) {
|
||
|
addRREmpty(req);
|
||
|
|
||
|
if (req->iterBegin->second->expiry > t) {
|
||
|
switch (req->iterBegin->second->cacheType) {
|
||
|
case CTYPE_LOCAL_PTR_AUTH:
|
||
|
case CTYPE_STATIC_PTR_AUTH:
|
||
|
case CTYPE_SERVER_PTR_AUTH:
|
||
|
addRRPtrOne(req);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (!sendTCPmess(req)) {
|
||
|
closesocket(req->sock);
|
||
|
return;
|
||
|
} else
|
||
|
records++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
addRREmpty(req);
|
||
|
addRRSOA(req);
|
||
|
|
||
|
if (sendTCPmess(req)) {
|
||
|
records++;
|
||
|
sprintf(logBuff, "Zone %s with %d RRs Sent", req->query, records);
|
||
|
logTCPMess(req, logBuff, 2);
|
||
|
}
|
||
|
} else {
|
||
|
addRRNone(req);
|
||
|
req->dnsp->header.rcode = RCODE_NOTAUTH;
|
||
|
sendTCPmess(req);
|
||
|
sprintf(logBuff, "Server is not authority for zone %s", req->query);
|
||
|
logTCPMess(req, logBuff, 1);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
sprintf(logBuff, "%s Query type not supported", strquery(req));
|
||
|
logTCPMess(req, logBuff, 1);
|
||
|
addRRError(req, RCODE_NOTIMPL);
|
||
|
sendTCPmess(req);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
closesocket(req->sock);
|
||
|
}
|
||
|
|
||
|
bool sendTCPmess(data5 *req) {
|
||
|
char logBuff[256];
|
||
|
|
||
|
if (req->dp == &req->dnsp->data)
|
||
|
return true;
|
||
|
|
||
|
timeval tv1 {};
|
||
|
fd_set writefds;
|
||
|
|
||
|
FD_ZERO(&writefds);
|
||
|
FD_SET(req->sock, &writefds);
|
||
|
tv1.tv_sec = 5;
|
||
|
tv1.tv_usec = 0;
|
||
|
|
||
|
if (select((req->sock + 1), nullptr, &writefds, nullptr, &tv1) > 0) {
|
||
|
errno = 0;
|
||
|
req->dnsp->header.ra = 0;
|
||
|
req->bytes = (int)(req->dp - req->raw);
|
||
|
pUShort(req->raw, req->bytes - 2);
|
||
|
|
||
|
if (req->bytes == send(req->sock, req->raw, req->bytes, 0) && !errno)
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if (verbatim || cfig.dnsLogLevel >= 1) {
|
||
|
sprintf(logBuff, "Failed to send %s", strquery(req));
|
||
|
logTCPMess(req, logBuff, 1);
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
MYWORD gdnmess(data5 *req, MYBYTE sockInd) {
|
||
|
char logBuff[256];
|
||
|
memset(req, 0, sizeof(data5));
|
||
|
req->sockLen = sizeof(req->remote);
|
||
|
errno = 0;
|
||
|
|
||
|
req->bytes = (int)recvfrom(
|
||
|
network.dnsUdpConn[sockInd].sock, req->raw, sizeof(req->raw), 0, (sockaddr *)&req->remote, &req->sockLen);
|
||
|
|
||
|
//errno = WSAGetLastError();
|
||
|
|
||
|
if (errno || req->bytes <= 0)
|
||
|
return 0;
|
||
|
|
||
|
req->sockInd = sockInd;
|
||
|
req->dnsp = (dnsPacket *)req->raw;
|
||
|
|
||
|
if (req->dnsp->header.qr)
|
||
|
return 0;
|
||
|
|
||
|
if (req->dnsp->header.opcode != OPCODE_STANDARD_QUERY) {
|
||
|
if (verbatim || cfig.dnsLogLevel >= 1) {
|
||
|
switch (req->dnsp->header.opcode) {
|
||
|
case OPCODE_INVERSE_QUERY:
|
||
|
sprintf(logBuff, "Inverse query not supported");
|
||
|
break;
|
||
|
|
||
|
case OPCODE_SRVR_STAT_REQ:
|
||
|
sprintf(logBuff, "Server Status Request not supported");
|
||
|
break;
|
||
|
|
||
|
case OPCODE_NOTIFY:
|
||
|
sprintf(logBuff, "Notify not supported");
|
||
|
break;
|
||
|
|
||
|
case OPCODE_DYNAMIC_UPDATE:
|
||
|
sprintf(logBuff, "Dynamic Update not needed/supported by Dual Server");
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
sprintf(logBuff, "OpCode %d not supported", req->dnsp->header.opcode);
|
||
|
}
|
||
|
|
||
|
logDNSMess(req, logBuff, 1);
|
||
|
}
|
||
|
|
||
|
addRRError(req, RCODE_NOTIMPL);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (ntohs(req->dnsp->header.qdcount) != 1 || ntohs(req->dnsp->header.ancount)) {
|
||
|
if (verbatim || cfig.dnsLogLevel >= 1) {
|
||
|
sprintf(logBuff, "DNS Query Format Error");
|
||
|
logDNSMess(req, logBuff, 1);
|
||
|
}
|
||
|
|
||
|
addRRError(req, RCODE_FORMATERROR);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
req->dp = &req->dnsp->data;
|
||
|
|
||
|
for (int i = 1; i <= ntohs(req->dnsp->header.qdcount); i++) {
|
||
|
req->dp += fQu(req->query, req->dnsp, req->dp);
|
||
|
req->dnsType = fUShort(req->dp);
|
||
|
req->dp += 2;
|
||
|
req->qclass = fUShort(req->dp);
|
||
|
req->dp += 2;
|
||
|
}
|
||
|
|
||
|
if (req->qclass != DNS_CLASS_IN) {
|
||
|
if (verbatim || cfig.dnsLogLevel >= 1) {
|
||
|
sprintf(logBuff, "DNS Class %d not supported", req->qclass);
|
||
|
logDNSMess(req, logBuff, 1);
|
||
|
}
|
||
|
addRRError(req, RCODE_NOTIMPL);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (!req->dnsType) {
|
||
|
if (verbatim || cfig.dnsLogLevel >= 1) {
|
||
|
sprintf(logBuff, "missing query type");
|
||
|
logDNSMess(req, logBuff, 1);
|
||
|
}
|
||
|
|
||
|
addRRError(req, RCODE_FORMATERROR);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
MYDWORD ip = req->remote.sin_addr.s_addr;
|
||
|
MYDWORD iip = ntohl(ip);
|
||
|
|
||
|
for (int i = 0; i < MAX_DNS_RANGES && cfig.dnsRanges[i].rangeStart; i++) {
|
||
|
if (iip >= cfig.dnsRanges[i].rangeStart && iip <= cfig.dnsRanges[i].rangeEnd)
|
||
|
return req->bytes;
|
||
|
}
|
||
|
|
||
|
if (isLocal(ip))
|
||
|
return req->bytes;
|
||
|
|
||
|
if (getRangeInd(ip) >= 0)
|
||
|
return req->bytes;
|
||
|
|
||
|
if (findDNSEntry(IP2String(req->cname, iip), DNS_TYPE_PTR, CTYPE_LOCAL_PTR_NAUTH))
|
||
|
return req->bytes;
|
||
|
|
||
|
if (findServer(network.allServers, MAX_SERVERS, ip))
|
||
|
return req->bytes;
|
||
|
|
||
|
if (verbatim || cfig.dnsLogLevel >= 1) {
|
||
|
sprintf(logBuff, "DNS UDP Query, Access Denied");
|
||
|
logDNSMess(req, logBuff, 1);
|
||
|
}
|
||
|
|
||
|
addRRError(req, RCODE_REFUSED);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
MYWORD scanloc(data5 *req) {
|
||
|
char logBuff[512];
|
||
|
|
||
|
if (!req->query[0])
|
||
|
return 0;
|
||
|
|
||
|
strcpy(req->mapname, req->query);
|
||
|
myLower(req->mapname);
|
||
|
req->qType = makeLocal(req->mapname);
|
||
|
//MYDWORD ip = req->remote.sin_addr.s_addr;
|
||
|
//sprintf(logBuff, "qType=%u dnsType=%u query=%s mapname=%s", req->qType, req->dnsType, req->query, req->mapname);
|
||
|
//logMess(logBuff, 2);
|
||
|
|
||
|
//strcpy(req->cname, req->query);
|
||
|
if (req->qType == QTYPE_A_BARE)
|
||
|
sprintf(req->cname, "%s.%s", req->query, cfig.zone);
|
||
|
else
|
||
|
strcpy(req->cname, req->query);
|
||
|
|
||
|
switch (req->qType) {
|
||
|
case QTYPE_P_EXT:
|
||
|
case QTYPE_A_EXT:
|
||
|
|
||
|
break;
|
||
|
|
||
|
case QTYPE_A_BARE:
|
||
|
case QTYPE_P_LOCAL:
|
||
|
case QTYPE_A_LOCAL:
|
||
|
case QTYPE_A_ZONE:
|
||
|
case QTYPE_P_ZONE:
|
||
|
|
||
|
switch (req->dnsType) {
|
||
|
case DNS_TYPE_A:
|
||
|
case DNS_TYPE_PTR:
|
||
|
break;
|
||
|
|
||
|
case DNS_TYPE_MX: {
|
||
|
if (!strcasecmp(req->query, cfig.zone)
|
||
|
&& (cfig.authorized || cfig.mxServers[currentInd][0].hostname[0])) {
|
||
|
addRRNone(req);
|
||
|
addRRMX(req);
|
||
|
addRRNS(req);
|
||
|
addRRAd(req);
|
||
|
return 1;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case DNS_TYPE_NS: {
|
||
|
if (cfig.authorized
|
||
|
&& (req->qType == QTYPE_A_ZONE || req->qType == QTYPE_P_ZONE || req->qType == QTYPE_A_BARE)) {
|
||
|
addRRNone(req);
|
||
|
addRRNS(req);
|
||
|
addRRAd(req);
|
||
|
return 1;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case DNS_TYPE_SOA: {
|
||
|
if (cfig.authorized) {
|
||
|
if (req->qType == QTYPE_P_ZONE) {
|
||
|
if (cfig.replication == 1 && req->remote.sin_addr.s_addr == cfig.zoneServers[1]
|
||
|
&& (t - cfig.dnsCheck) < 2) {
|
||
|
if (cfig.refresh > (MYDWORD)(MY_MAX_TIME - t))
|
||
|
cfig.dnsRepl = MY_MAX_TIME;
|
||
|
else
|
||
|
cfig.dnsRepl = t + cfig.refresh + cfig.retry + cfig.retry;
|
||
|
}
|
||
|
|
||
|
cfig.dnsCheck = 0;
|
||
|
addRRNone(req);
|
||
|
addRRSOA(req);
|
||
|
return 1;
|
||
|
} else if (req->qType == QTYPE_A_ZONE) {
|
||
|
if (cfig.replication == 1 && req->remote.sin_addr.s_addr == cfig.zoneServers[1])
|
||
|
cfig.dnsCheck = t;
|
||
|
|
||
|
addRRNone(req);
|
||
|
addRRSOA(req);
|
||
|
return 1;
|
||
|
} else if (req->qType == QTYPE_A_BARE) {
|
||
|
addRRNone(req);
|
||
|
addRRSOA(req);
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case DNS_TYPE_ANY: {
|
||
|
addRRAny(req);
|
||
|
return 1;
|
||
|
}
|
||
|
default: {
|
||
|
if (cfig.authorized) {
|
||
|
if (verbatim || cfig.dnsLogLevel) {
|
||
|
sprintf(logBuff, "%s, DNS Query Type not supported", strquery(req));
|
||
|
logDNSMess(req, logBuff, 1);
|
||
|
}
|
||
|
addRRNone(req);
|
||
|
addRRNS(req);
|
||
|
addRRAd(req);
|
||
|
req->dnsp->header.rcode = RCODE_NOTIMPL;
|
||
|
return 1;
|
||
|
} else
|
||
|
return 0;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (int m = 0; m < 3; m++) {
|
||
|
req->iterBegin = dnsCache[currentInd].find(setMapName(req->tempname, req->mapname, req->dnsType));
|
||
|
|
||
|
if (req->iterBegin == dnsCache[currentInd].end())
|
||
|
break;
|
||
|
|
||
|
data7 *cache = req->iterBegin->second;
|
||
|
|
||
|
if (cache->expiry < t && cache->cacheType != CTYPE_CACHED)
|
||
|
break;
|
||
|
|
||
|
req->cacheType = cache->cacheType;
|
||
|
|
||
|
switch (req->cacheType) {
|
||
|
case CTYPE_LOCAL_A:
|
||
|
case CTYPE_STATIC_A_AUTH:
|
||
|
addRRNone(req);
|
||
|
addRRA(req);
|
||
|
addRRNS(req);
|
||
|
addRRAd(req);
|
||
|
return 1;
|
||
|
|
||
|
case CTYPE_LOCAL_PTR_AUTH:
|
||
|
case CTYPE_STATIC_PTR_AUTH:
|
||
|
case CTYPE_SERVER_PTR_AUTH:
|
||
|
addRRNone(req);
|
||
|
addRRPtr(req);
|
||
|
addRRNS(req);
|
||
|
addRRAd(req);
|
||
|
return 1;
|
||
|
|
||
|
case CTYPE_LOCALHOST_A:
|
||
|
addRRNone(req);
|
||
|
addRRLocalhostA(req, cache);
|
||
|
return 1;
|
||
|
|
||
|
case CTYPE_LOCALHOST_PTR:
|
||
|
addRRNone(req);
|
||
|
addRRLocalhostPtr(req, cache);
|
||
|
return 1;
|
||
|
|
||
|
case CTYPE_STATIC_A_NAUTH:
|
||
|
addRRNone(req);
|
||
|
addRRA(req);
|
||
|
return 1;
|
||
|
|
||
|
case CTYPE_LOCAL_PTR_NAUTH:
|
||
|
case CTYPE_SERVER_PTR_NAUTH:
|
||
|
case CTYPE_STATIC_PTR_NAUTH:
|
||
|
addRRNone(req);
|
||
|
addRRPtr(req);
|
||
|
return 1;
|
||
|
|
||
|
case CTYPE_SERVER_A_AUTH:
|
||
|
addRRNone(req);
|
||
|
addRRServerA(req);
|
||
|
addRRNS(req);
|
||
|
addRRAd(req);
|
||
|
return 1;
|
||
|
|
||
|
case CTYPE_CACHED:
|
||
|
addRRNone(req);
|
||
|
addRRCache(req, cache);
|
||
|
return 1;
|
||
|
|
||
|
case CTYPE_LOCAL_CNAME:
|
||
|
case CTYPE_EXT_CNAME:
|
||
|
|
||
|
if (!cache->hostname[0])
|
||
|
strcpy(req->cname, cfig.zone);
|
||
|
else if (strchr(cache->hostname, '.'))
|
||
|
strcpy(req->cname, cache->hostname);
|
||
|
else
|
||
|
sprintf(req->cname, "%s.%s", cache->hostname, cfig.zone);
|
||
|
|
||
|
//sprintf(logBuff, "cacheType=%u, cache->name=%s, cname=%s, hostname=%s", cache->cacheType, cache->name, req->cname, cache->hostname);
|
||
|
//logMess(logBuff, 2);
|
||
|
|
||
|
strcpy(req->mapname, cache->hostname);
|
||
|
myLower(req->mapname);
|
||
|
continue;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//sprintf(logBuff, "cacheType=%u,dnsType=%u,query=%s,cname=%s", req->cacheType, req->dnsType, req->query, req->cname);
|
||
|
//logMess(logBuff, 2);
|
||
|
|
||
|
if (req->dnsType == DNS_TYPE_A && cfig.wildHosts[0].wildcard[0]) {
|
||
|
for (MYWORD i = 0; i < MAX_WILD_HOSTS && cfig.wildHosts[i].wildcard[0]; i++) {
|
||
|
if (wildcmp(req->mapname, cfig.wildHosts[i].wildcard)) {
|
||
|
addRRNone(req);
|
||
|
|
||
|
if (cfig.wildHosts[i].ip)
|
||
|
addRRWildA(req, cfig.wildHosts[i].ip);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (req->cacheType == CTYPE_EXT_CNAME) {
|
||
|
req->qType = makeLocal(req->cname);
|
||
|
req->dp = &req->dnsp->data;
|
||
|
req->dp += pQu(req->dp, req->cname);
|
||
|
req->dp += pUShort(req->dp, DNS_TYPE_A);
|
||
|
req->dp += pUShort(req->dp, DNS_CLASS_IN);
|
||
|
req->bytes = (int)(req->dp - req->raw);
|
||
|
return 0;
|
||
|
} else if (req->qType == QTYPE_A_BARE || req->qType == QTYPE_A_ZONE || req->qType == QTYPE_P_ZONE) {
|
||
|
addRRNone(req);
|
||
|
addRRA(req);
|
||
|
addRRNS(req);
|
||
|
addRRAd(req);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
MYWORD fdnmess(data5 *req) {
|
||
|
//printf("before qType=%d %d\n", req->qType, QTYPE_A_SUBZONE);
|
||
|
char ipbuff[32];
|
||
|
char logBuff[256];
|
||
|
req->qLen = strlen(req->cname);
|
||
|
MYBYTE zoneDNS;
|
||
|
int nRet = -1;
|
||
|
|
||
|
char mapname[8];
|
||
|
sprintf(mapname, "%u", req->dnsp->header.xid);
|
||
|
data7 *queue = findQueue(mapname);
|
||
|
|
||
|
for (zoneDNS = 0; zoneDNS < MAX_COND_FORW && cfig.dnsRoutes[zoneDNS].zLen; zoneDNS++) {
|
||
|
if (req->qLen == cfig.dnsRoutes[zoneDNS].zLen && !strcasecmp(req->cname, cfig.dnsRoutes[zoneDNS].zone))
|
||
|
req->qType = QTYPE_CHILDZONE;
|
||
|
else if (req->qLen > cfig.dnsRoutes[zoneDNS].zLen) {
|
||
|
char *dp = req->cname + (req->qLen - cfig.dnsRoutes[zoneDNS].zLen - 1);
|
||
|
|
||
|
if (*dp == '.' && !strcasecmp(dp + 1, cfig.dnsRoutes[zoneDNS].zone))
|
||
|
req->qType = QTYPE_CHILDZONE;
|
||
|
}
|
||
|
|
||
|
if (req->qType == QTYPE_CHILDZONE) {
|
||
|
if (queue && cfig.dnsRoutes[zoneDNS].dns[1])
|
||
|
cfig.dnsRoutes[zoneDNS].currentDNS = 1 - cfig.dnsRoutes[zoneDNS].currentDNS;
|
||
|
|
||
|
if (req->remote.sin_addr.s_addr != cfig.dnsRoutes[zoneDNS].dns[cfig.dnsRoutes[zoneDNS].currentDNS]) {
|
||
|
req->addr.sin_family = AF_INET;
|
||
|
req->addr.sin_addr.s_addr = cfig.dnsRoutes[zoneDNS].dns[cfig.dnsRoutes[zoneDNS].currentDNS];
|
||
|
req->addr.sin_port = htons(IPPORT_DNS);
|
||
|
errno = 0;
|
||
|
|
||
|
nRet = (int)sendto(
|
||
|
network.forwConn.sock, req->raw, req->bytes, 0, (sockaddr *)&req->addr, sizeof(req->addr));
|
||
|
|
||
|
//errno = WSAGetLastError();
|
||
|
|
||
|
if (errno || nRet <= 0) {
|
||
|
if (verbatim || cfig.dnsLogLevel) {
|
||
|
sprintf(logBuff,
|
||
|
"Error Forwarding UDP DNS Message to Conditional Forwarder %s",
|
||
|
IP2String(ipbuff, req->addr.sin_addr.s_addr));
|
||
|
logDNSMess(req, logBuff, 1);
|
||
|
addRRNone(req);
|
||
|
req->dnsp->header.rcode = RCODE_SERVERFAIL;
|
||
|
}
|
||
|
|
||
|
if (cfig.dnsRoutes[zoneDNS].dns[1])
|
||
|
cfig.dnsRoutes[zoneDNS].currentDNS = 1 - cfig.dnsRoutes[zoneDNS].currentDNS;
|
||
|
|
||
|
return 0;
|
||
|
} else {
|
||
|
if (verbatim || cfig.dnsLogLevel >= 2) {
|
||
|
sprintf(logBuff,
|
||
|
"%s forwarded to Conditional Forwarder %s",
|
||
|
strquery(req),
|
||
|
IP2String(ipbuff, cfig.dnsRoutes[zoneDNS].dns[cfig.dnsRoutes[zoneDNS].currentDNS]));
|
||
|
logDNSMess(req, logBuff, 2);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (req->qType != QTYPE_CHILDZONE) {
|
||
|
//sprintf(logBuff, "after qType=%d %d", req->qType, QTYPE_CHILDZONE);
|
||
|
//logMess(logBuff, 2);
|
||
|
|
||
|
if (cfig.authorized && (req->qType == QTYPE_A_LOCAL || req->qType == QTYPE_P_LOCAL)) {
|
||
|
switch (req->dnsType) {
|
||
|
case DNS_TYPE_A:
|
||
|
addRRNone(req);
|
||
|
addRRA(req);
|
||
|
addRRNS(req);
|
||
|
addRRAd(req);
|
||
|
return 0;
|
||
|
|
||
|
case DNS_TYPE_SOA:
|
||
|
addRRNone(req);
|
||
|
addRRSOA(req);
|
||
|
return 0;
|
||
|
|
||
|
default:
|
||
|
addRRNone(req);
|
||
|
addRRNS(req);
|
||
|
addRRAd(req);
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!req->dnsp->header.rd) {
|
||
|
addRRNone(req);
|
||
|
if (verbatim || cfig.dnsLogLevel) {
|
||
|
sprintf(logBuff, "%s is not found (recursion not desired)", strquery(req));
|
||
|
logDNSMess(req, logBuff, 2);
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (!network.dns[0]) {
|
||
|
addRRNone(req);
|
||
|
req->dnsp->header.ra = 0;
|
||
|
if (verbatim || cfig.dnsLogLevel) {
|
||
|
sprintf(logBuff, "%s not found (recursion not available)", strquery(req));
|
||
|
logDNSMess(req, logBuff, 2);
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (queue && network.dns[1] && queue->dnsIndex < MAX_SERVERS && network.currentDNS == queue->dnsIndex) {
|
||
|
network.currentDNS++;
|
||
|
|
||
|
if (network.currentDNS >= MAX_SERVERS || !network.dns[network.currentDNS])
|
||
|
network.currentDNS = 0;
|
||
|
}
|
||
|
|
||
|
if (req->remote.sin_addr.s_addr != network.dns[network.currentDNS]) {
|
||
|
req->addr.sin_family = AF_INET;
|
||
|
req->addr.sin_addr.s_addr = network.dns[network.currentDNS];
|
||
|
req->addr.sin_port = htons(IPPORT_DNS);
|
||
|
errno = 0;
|
||
|
|
||
|
nRet = (int)sendto(
|
||
|
network.forwConn.sock, req->raw, req->bytes, 0, (sockaddr *)&req->addr, sizeof(req->addr));
|
||
|
|
||
|
//errno = WSAGetLastError();
|
||
|
|
||
|
if (errno || nRet <= 0) {
|
||
|
if (verbatim || cfig.dnsLogLevel) {
|
||
|
sprintf(logBuff,
|
||
|
"Error forwarding UDP DNS Message to Forwarding Server %s",
|
||
|
IP2String(ipbuff, network.dns[network.currentDNS]));
|
||
|
logDNSMess(req, logBuff, 1);
|
||
|
addRRNone(req);
|
||
|
req->dnsp->header.rcode = RCODE_SERVERFAIL;
|
||
|
}
|
||
|
|
||
|
if (network.dns[1]) {
|
||
|
network.currentDNS++;
|
||
|
|
||
|
if (network.currentDNS >= MAX_SERVERS || !network.dns[network.currentDNS])
|
||
|
network.currentDNS = 0;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
} else {
|
||
|
if (verbatim || cfig.dnsLogLevel >= 2) {
|
||
|
sprintf(logBuff,
|
||
|
"%s forwarded to Forwarding Server %s",
|
||
|
strquery(req),
|
||
|
IP2String(ipbuff, network.dns[network.currentDNS]));
|
||
|
logDNSMess(req, logBuff, 2);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!queue) {
|
||
|
memset(&g_lump, 0, sizeof(data71));
|
||
|
g_lump.dnsType = req->dnsType;
|
||
|
g_lump.cacheType = CTYPE_QUEUE;
|
||
|
g_lump.mapname = mapname;
|
||
|
g_lump.addr = &req->remote;
|
||
|
g_lump.query = req->query;
|
||
|
queue = createCache(&g_lump);
|
||
|
|
||
|
if (queue) {
|
||
|
queue->expiry = 2 + t;
|
||
|
addDNSEntry(queue);
|
||
|
} else
|
||
|
return 0;
|
||
|
} else {
|
||
|
queue->expiry = 2 + t;
|
||
|
memcpy(queue->addr, &req->remote, sizeof(req->remote));
|
||
|
}
|
||
|
|
||
|
queue->sockInd = req->sockInd;
|
||
|
|
||
|
if (req->qType == QTYPE_CHILDZONE)
|
||
|
queue->dnsIndex = 128 + (2 * zoneDNS) + cfig.dnsRoutes[zoneDNS].currentDNS;
|
||
|
else
|
||
|
queue->dnsIndex = network.currentDNS;
|
||
|
|
||
|
//sprintf(logBuff, "queue created for %s", req->query);
|
||
|
|
||
|
return (nRet);
|
||
|
}
|
||
|
|
||
|
MYWORD frdnmess(data5 *req) {
|
||
|
char tempbuff[512];
|
||
|
memset(req, 0, sizeof(data5));
|
||
|
req->sockLen = sizeof(req->remote);
|
||
|
errno = 0;
|
||
|
MYBYTE dnsType = 0;
|
||
|
|
||
|
req->bytes = (int)recvfrom(
|
||
|
network.forwConn.sock, req->raw, sizeof(req->raw), 0, (sockaddr *)&req->remote, &req->sockLen);
|
||
|
|
||
|
//errno = WSAGetLastError();
|
||
|
|
||
|
if (errno || req->bytes <= 0)
|
||
|
return 0;
|
||
|
|
||
|
req->dnsp = (dnsPacket *)req->raw;
|
||
|
req->dp = &req->dnsp->data;
|
||
|
|
||
|
for (int i = 1; i <= ntohs(req->dnsp->header.qdcount); i++) {
|
||
|
req->dp += fQu(req->cname, req->dnsp, req->dp);
|
||
|
strcpy(req->mapname, req->cname);
|
||
|
dnsType = fUShort(req->dp);
|
||
|
req->dp += 4;//type and class
|
||
|
|
||
|
if (dnsType == DNS_TYPE_PTR) {
|
||
|
myLower(req->mapname);
|
||
|
char *dp = strstr(req->mapname, arpa);
|
||
|
|
||
|
if (dp && !strcasecmp(dp, arpa))
|
||
|
*dp = 0;
|
||
|
} else {
|
||
|
strcpy(req->mapname, req->cname);
|
||
|
myLower(req->mapname);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ((dnsType == DNS_TYPE_A || dnsType == DNS_TYPE_ANY || dnsType == DNS_TYPE_AAAA || dnsType == DNS_TYPE_PTR)
|
||
|
&& !req->dnsp->header.rcode && !req->dnsp->header.tc && req->dnsp->header.ancount) {
|
||
|
time_t expiry = 0;
|
||
|
bool resultFound = false;
|
||
|
|
||
|
for (int i = 1; i <= ntohs(req->dnsp->header.ancount); i++) {
|
||
|
resultFound = true;
|
||
|
req->dp += fQu(tempbuff, req->dnsp, req->dp);
|
||
|
//dnsType = fUShort(req->dp);
|
||
|
|
||
|
//logDNSMess(tempbuff, 2);
|
||
|
req->dp += 4;//type and class
|
||
|
|
||
|
if (!expiry || fUInt(req->dp) < (MYDWORD)expiry)
|
||
|
expiry = fUInt(req->dp);
|
||
|
|
||
|
req->dp += 4;//ttl
|
||
|
int zLen = fUShort(req->dp);
|
||
|
req->dp += 2;//datalength
|
||
|
req->dp += zLen;
|
||
|
}
|
||
|
|
||
|
if (resultFound) {
|
||
|
MYWORD cacheSize = req->dp - req->raw;
|
||
|
|
||
|
if (cfig.minCache && expiry < cfig.minCache)
|
||
|
expiry = cfig.minCache;
|
||
|
|
||
|
if (cfig.maxCache && expiry > cfig.maxCache)
|
||
|
expiry = cfig.maxCache;
|
||
|
|
||
|
if (expiry < MY_MAX_TIME - t)
|
||
|
expiry += t;
|
||
|
else
|
||
|
expiry = MY_MAX_TIME;
|
||
|
|
||
|
memset(&g_lump, 0, sizeof(data71));
|
||
|
g_lump.cacheType = CTYPE_CACHED;
|
||
|
g_lump.dnsType = dnsType;
|
||
|
g_lump.mapname = req->mapname;
|
||
|
g_lump.bytes = req->bytes;
|
||
|
g_lump.response = (MYBYTE *)req->dnsp;
|
||
|
data7 *cache = createCache(&g_lump);
|
||
|
|
||
|
if (cache) {
|
||
|
cache->expiry = expiry;
|
||
|
addDNSEntry(cache);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
char mapname[8];
|
||
|
sprintf(mapname, "%u", req->dnsp->header.xid);
|
||
|
data7 *queue = findQueue(mapname);
|
||
|
|
||
|
if (queue && queue->expiry) {
|
||
|
queue->expiry = 0;
|
||
|
|
||
|
if (queue->dnsIndex < MAX_SERVERS) {
|
||
|
if (req->remote.sin_addr.s_addr != network.dns[network.currentDNS]) {
|
||
|
for (MYBYTE i = 0; i < MAX_SERVERS && network.dns[i]; i++) {
|
||
|
if (network.dns[i] == req->remote.sin_addr.s_addr) {
|
||
|
network.currentDNS = i;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
} else if (queue->dnsIndex >= 128 && queue->dnsIndex < 192) {
|
||
|
MYBYTE rid = (queue->dnsIndex - 128) / 2;
|
||
|
data10 *dnsRoute = &cfig.dnsRoutes[rid];
|
||
|
|
||
|
if (dnsRoute->dns[0] == req->remote.sin_addr.s_addr)
|
||
|
dnsRoute->currentDNS = 0;
|
||
|
else if (dnsRoute->dns[1] == req->remote.sin_addr.s_addr)
|
||
|
dnsRoute->currentDNS = 1;
|
||
|
}
|
||
|
|
||
|
memcpy(&req->remote, queue->addr, sizeof(req->remote));
|
||
|
strcpy(req->query, queue->query);
|
||
|
req->sockInd = queue->sockInd;
|
||
|
req->dnsIndex = queue->dnsIndex;
|
||
|
req->dnsType = queue->dnsType;
|
||
|
addRRExt(req);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
MYWORD sdnmess(data5 *req) {
|
||
|
|
||
|
errno = 0;
|
||
|
req->bytes = (int)(req->dp - req->raw);
|
||
|
req->bytes = (int)sendto(
|
||
|
network.dnsUdpConn[req->sockInd].sock, req->raw, req->bytes, 0, (sockaddr *)&req->remote, sizeof(req->remote));
|
||
|
|
||
|
//errno = WSAGetLastError();
|
||
|
|
||
|
if (errno || req->bytes <= 0)
|
||
|
return 0;
|
||
|
else
|
||
|
return req->bytes;
|
||
|
}
|
||
|
|
||
|
void add2Cache(char *hostname, MYDWORD ip, time_t expiry, MYBYTE aType, MYBYTE pType) {
|
||
|
//char logBuff[256];
|
||
|
//char ipbuff[256];
|
||
|
//sprintf(logBuff, "Adding %s=%s %u", hostname, IP2String(ipbuff, ip), expiry - t);
|
||
|
//debug(logBuff);
|
||
|
|
||
|
//memset(&g_lump, 0, sizeof(data71));
|
||
|
|
||
|
char tempbuff[512];
|
||
|
|
||
|
if (!hostname || !ip)
|
||
|
return;
|
||
|
|
||
|
data7 *cache = nullptr;
|
||
|
hostMap::iterator p;
|
||
|
|
||
|
if (pType) {
|
||
|
IP2String(tempbuff, htonl(ip), DNS_TYPE_PTR);
|
||
|
p = dnsCache[currentInd].find(tempbuff);
|
||
|
|
||
|
for (; p != dnsCache[currentInd].end(); p++) {
|
||
|
if (strcasecmp(p->second->mapname, tempbuff) != 0)
|
||
|
break;
|
||
|
|
||
|
if (!strcasecmp(p->second->hostname, hostname)) {
|
||
|
cache = p->second;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!cache) {
|
||
|
memset(&g_lump, 0, sizeof(data71));
|
||
|
g_lump.cacheType = pType;
|
||
|
g_lump.dnsType = DNS_TYPE_PTR;
|
||
|
g_lump.mapname = IP2String(tempbuff, htonl(ip));
|
||
|
g_lump.hostname = hostname;
|
||
|
cache = createCache(&g_lump);
|
||
|
|
||
|
if (cache) {
|
||
|
cache->expiry = expiry;
|
||
|
addDNSEntry(cache);
|
||
|
|
||
|
if (cfig.replication != 2 && (pType == CTYPE_LOCAL_PTR_AUTH || pType == CTYPE_SERVER_PTR_AUTH))
|
||
|
cfig.serial2 = t;
|
||
|
}
|
||
|
} else if (cache->expiry < expiry) {
|
||
|
cache->cacheType = pType;
|
||
|
cache->expiry = expiry;
|
||
|
}
|
||
|
//printf("Added %s=%s\n", IP2String(ipbuff, ip), hostname);
|
||
|
}
|
||
|
|
||
|
if (aType) {
|
||
|
cache = nullptr;
|
||
|
setMapName(tempbuff, hostname, DNS_TYPE_A);
|
||
|
|
||
|
p = dnsCache[currentInd].find(tempbuff);
|
||
|
|
||
|
for (; p != dnsCache[currentInd].end(); p++) {
|
||
|
if (strcasecmp(p->second->mapname, tempbuff) != 0)
|
||
|
break;
|
||
|
|
||
|
if (p->second->ip == ip) {
|
||
|
cache = p->second;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!cache) {
|
||
|
memset(&g_lump, 0, sizeof(data71));
|
||
|
g_lump.cacheType = aType;
|
||
|
g_lump.dnsType = DNS_TYPE_A;
|
||
|
g_lump.mapname = hostname;
|
||
|
cache = createCache(&g_lump);
|
||
|
|
||
|
if (cache) {
|
||
|
cache->ip = ip;
|
||
|
cache->expiry = expiry;
|
||
|
addDNSEntry(cache);
|
||
|
|
||
|
if (cfig.replication != 2 && (aType == CTYPE_LOCAL_A || aType == CTYPE_SERVER_A_AUTH))
|
||
|
cfig.serial1 = t;
|
||
|
}
|
||
|
} else if (cache->expiry < expiry) {
|
||
|
cache->cacheType = aType;
|
||
|
cache->expiry = expiry;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void expireEntry(MYDWORD ip) {
|
||
|
char ipbuff[32];
|
||
|
|
||
|
if (!ip)
|
||
|
return;
|
||
|
|
||
|
IP2String(ipbuff, htonl(ip));
|
||
|
data7 *cache = findDNSEntry(ipbuff, DNS_TYPE_PTR, CTYPE_LOCAL_PTR_AUTH);
|
||
|
|
||
|
if (!cache)
|
||
|
cache = findDNSEntry(ipbuff, DNS_TYPE_PTR, CTYPE_LOCAL_PTR_NAUTH);
|
||
|
|
||
|
if (cache && cache->hostname[0] && cache->expiry < MY_MAX_TIME) {
|
||
|
data7 *cache1 = findDNSEntry(cache->hostname, DNS_TYPE_A, CTYPE_LOCAL_A);
|
||
|
|
||
|
if (cache1 && cache1->ip == ip && cache1->expiry < MY_MAX_TIME) {
|
||
|
cache->expiry = 0;
|
||
|
cache1->expiry = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void addHostNotFound(char *hostname) {
|
||
|
memset(&g_lump, 0, sizeof(data71));
|
||
|
g_lump.cacheType = CTYPE_STATIC_A_NAUTH;
|
||
|
g_lump.dnsType = DNS_TYPE_A;
|
||
|
g_lump.mapname = hostname;
|
||
|
data7 *cache = createCache(&g_lump);
|
||
|
/*
|
||
|
data7 *cache = (data7*)calloc(1, sizeof(data7));
|
||
|
|
||
|
if (cache)
|
||
|
{
|
||
|
cache->mapname = myLower(cloneString(hostname));
|
||
|
|
||
|
if (!cache->mapname)
|
||
|
{
|
||
|
sprintf(logBuff, "Memory Allocation Error");
|
||
|
free(cache);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
cache->ip = 0;
|
||
|
cache->cacheType = CTYPE_STATIC_A_NAUTH;
|
||
|
cache->expiry = MY_MAX_TIME;
|
||
|
addDNSEntry(cache);
|
||
|
}
|
||
|
*/
|
||
|
if (cache) {
|
||
|
cache->ip = 0;
|
||
|
cache->cacheType = CTYPE_STATIC_A_NAUTH;
|
||
|
cache->expiry = MY_MAX_TIME;
|
||
|
addDNSEntry(cache);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
char *getResult(data5 *req) {
|
||
|
char buff[256];
|
||
|
|
||
|
req->tempname[0] = 0;
|
||
|
char *raw = &req->dnsp->data;
|
||
|
MYWORD queueIndex;
|
||
|
|
||
|
for (int i = 1; i <= ntohs(req->dnsp->header.qdcount); i++) {
|
||
|
raw += fQu(buff, req->dnsp, raw);
|
||
|
raw += 4;
|
||
|
}
|
||
|
|
||
|
for (int i = 1; i <= ntohs(req->dnsp->header.ancount); i++) {
|
||
|
raw += fQu(buff, req->dnsp, raw);
|
||
|
int type = fUShort(raw);
|
||
|
raw += 2;//type
|
||
|
raw += 2;//class
|
||
|
raw += 4;//ttl
|
||
|
int zLen = fUShort(raw);
|
||
|
raw += 2;//datalength
|
||
|
|
||
|
if (type == DNS_TYPE_A)
|
||
|
return IP2String(req->tempname, fIP(raw));
|
||
|
else if (type == DNS_TYPE_AAAA)
|
||
|
return IP62String(req->tempname, (MYBYTE *)raw);
|
||
|
else if (type == DNS_TYPE_PTR) {
|
||
|
fQu(req->tempname, req->dnsp, raw);
|
||
|
return req->tempname;
|
||
|
} else if (type == DNS_TYPE_MX)
|
||
|
fQu(req->tempname, req->dnsp, (raw + 2));
|
||
|
else if (type == DNS_TYPE_CNAME)
|
||
|
fQu(req->tempname, req->dnsp, raw);
|
||
|
else if (type == DNS_TYPE_NS)
|
||
|
fQu(req->tempname, req->dnsp, raw);
|
||
|
|
||
|
raw += zLen;
|
||
|
}
|
||
|
|
||
|
if (req->tempname[0])
|
||
|
return req->tempname;
|
||
|
else
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
bool checkRange(data17 *rangeData, char rangeInd) {
|
||
|
|
||
|
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 = getRangeInd(ip);
|
||
|
|
||
|
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) {
|
||
|
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);
|
||
|
|
||
|
if (!iipNew && dnsService && req->hostname[0]) {
|
||
|
char hostname[128];
|
||
|
strcpy(hostname, req->hostname);
|
||
|
myLower(hostname);
|
||
|
auto it = dnsCache[currentInd].find(hostname);
|
||
|
|
||
|
for (; it != dnsCache[currentInd].end(); it++) {
|
||
|
data7 *cache = it->second;
|
||
|
|
||
|
//printf("%u\n", cache->mapname);
|
||
|
|
||
|
if (!cache || strcasecmp(cache->mapname, hostname) != 0)
|
||
|
break;
|
||
|
|
||
|
if (cache->ip && checkIP(req, &rangeData, cache->ip))
|
||
|
iipNew = ntohl(cache->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--) {
|
||
|
int ind = (int)(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++) {
|
||
|
int ind = (int)(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(&g_lump, 0, sizeof(data71));
|
||
|
g_lump.cacheType = CTYPE_DHCP_ENTRY;
|
||
|
g_lump.mapname = req->chaddr;
|
||
|
g_lump.hostname = req->hostname;
|
||
|
req->dhcpEntry = createCache(&g_lump);
|
||
|
|
||
|
if (!req->dhcpEntry)
|
||
|
return 0;
|
||
|
|
||
|
dhcpCache[req->dhcpEntry->mapname] = req->dhcpEntry;
|
||
|
}
|
||
|
|
||
|
char idx = getRangeInd(req->dhcpEntry->ip);
|
||
|
|
||
|
req->dhcpEntry->ip = htonl(iipNew);
|
||
|
req->dhcpEntry->rangeInd = idx < 0 ? -1 : (int)idx;
|
||
|
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) {
|
||
|
|
||
|
req->dhcpEntry = findDHCPEntry(req->chaddr);
|
||
|
|
||
|
if (!req->dhcpEntry || !req->dhcpEntry->ip)
|
||
|
return 0;
|
||
|
|
||
|
char idx = getRangeInd(req->dhcpEntry->ip);
|
||
|
req->dhcpEntry->rangeInd = idx < 0 ? -1 : (int)idx;
|
||
|
|
||
|
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);
|
||
|
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);
|
||
|
|
||
|
//_beginthread(updateStateFile, 0, (void*)req->dhcpEntry);
|
||
|
pthread_t threadId;
|
||
|
pthread_attr_t attr;
|
||
|
pthread_attr_init(&attr);
|
||
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||
|
int errcode = pthread_create(&threadId, &attr, updateStateFile, req->dhcpEntry);
|
||
|
pthread_attr_destroy(&attr);
|
||
|
|
||
|
if (verbatim || cfig.dhcpLogLevel) {
|
||
|
sprintf(logBuff,
|
||
|
"IP Address %s released by Host %s (%s)",
|
||
|
IP2String(tempbuff, req->dhcpp.header.bp_ciaddr),
|
||
|
req->chaddr,
|
||
|
req->hostname);
|
||
|
logDHCPMess(logBuff, 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
} else if (req->req_type == DHCP_MESS_INFORM) {
|
||
|
//printf("repl0=%s\n", IP2String(tempbuff, cfig.zoneServers[0]));
|
||
|
//printf("repl1=%s\n", IP2String(tempbuff, cfig.zoneServers[1]));
|
||
|
//printf("IP=%s bytes=%u replication=%i\n", IP2String(tempbuff, req->remote.sin_addr.s_addr), req->bytes, cfig.replication);
|
||
|
|
||
|
if ((cfig.replication == 1 && req->remote.sin_addr.s_addr == cfig.zoneServers[1])
|
||
|
|| (cfig.replication == 2 && req->remote.sin_addr.s_addr == cfig.zoneServers[0]))
|
||
|
recvRepl(req);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
//else if (req->req_type == DHCP_MESS_DISCOVER && strcasecmp(req->hostname, cfig.servername))
|
||
|
else if (req->req_type == DHCP_MESS_DISCOVER) {
|
||
|
req->dhcpp.header.bp_yiaddr = resad(req);
|
||
|
|
||
|
if (!req->dhcpp.header.bp_yiaddr)
|
||
|
return 0;
|
||
|
|
||
|
req->resp_type = DHCP_MESS_OFFER;
|
||
|
} else if (req->req_type == DHCP_MESS_REQUEST) {
|
||
|
//printf("%s\n", IP2String(tempbuff, req->dhcpp.header.bp_ciaddr));
|
||
|
|
||
|
if (req->server) {
|
||
|
if (req->server == network.dhcpConn[req->sockInd].server) {
|
||
|
if (req->reqIP && req->reqIP == chkaddr(req) && req->dhcpEntry->expiry > t) {
|
||
|
req->resp_type = DHCP_MESS_ACK;
|
||
|
req->dhcpp.header.bp_yiaddr = req->reqIP;
|
||
|
} else if (req->dhcpp.header.bp_ciaddr && req->dhcpp.header.bp_ciaddr == chkaddr(req)
|
||
|
&& req->dhcpEntry->expiry > t) {
|
||
|
req->resp_type = DHCP_MESS_ACK;
|
||
|
req->dhcpp.header.bp_yiaddr = req->dhcpp.header.bp_ciaddr;
|
||
|
req->dhcpp.header.bp_ciaddr = 0;
|
||
|
} else {
|
||
|
req->resp_type = DHCP_MESS_NAK;
|
||
|
req->dhcpp.header.bp_yiaddr = 0;
|
||
|
|
||
|
if (verbatim || cfig.dhcpLogLevel) {
|
||
|
sprintf(logBuff,
|
||
|
"DHCPREQUEST from Host %s (%s) without Discover, NAKed",
|
||
|
req->chaddr,
|
||
|
req->hostname);
|
||
|
logDHCPMess(logBuff, 1);
|
||
|
}
|
||
|
}
|
||
|
} else
|
||
|
return 0;
|
||
|
} else if (req->dhcpp.header.bp_ciaddr && req->dhcpp.header.bp_ciaddr == chkaddr(req)
|
||
|
&& req->dhcpEntry->expiry > t) {
|
||
|
req->resp_type = DHCP_MESS_ACK;
|
||
|
req->dhcpp.header.bp_yiaddr = req->dhcpp.header.bp_ciaddr;
|
||
|
req->dhcpp.header.bp_ciaddr = 0;
|
||
|
} else if (req->reqIP && req->reqIP == chkaddr(req) && req->dhcpEntry->expiry > t) {
|
||
|
req->resp_type = DHCP_MESS_ACK;
|
||
|
req->dhcpp.header.bp_yiaddr = req->reqIP;
|
||
|
} else {
|
||
|
req->resp_type = DHCP_MESS_NAK;
|
||
|
req->dhcpp.header.bp_yiaddr = 0;
|
||
|
|
||
|
if (verbatim || cfig.dhcpLogLevel) {
|
||
|
sprintf(logBuff, "DHCPREQUEST from Host %s (%s) without Discover, NAKed", req->chaddr, req->hostname);
|
||
|
logDHCPMess(logBuff, 1);
|
||
|
}
|
||
|
}
|
||
|
} else
|
||
|
return 0;
|
||
|
|
||
|
addOptions(req);
|
||
|
int packSize = (int)(req->vp - (MYBYTE *)&req->dhcpp);
|
||
|
packSize++;
|
||
|
|
||
|
if (req->req_type == DHCP_MESS_NONE)
|
||
|
packSize = req->messsize;
|
||
|
|
||
|
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;
|
||
|
|
||
|
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 *)&req->remote,
|
||
|
sizeof(req->remote));
|
||
|
} else {
|
||
|
req->bytes = (int)sendto(
|
||
|
network.dhcpConn[req->sockInd].sock, req->raw, packSize, 0, (sockaddr *)&req->remote, 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) {
|
||
|
//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);
|
||
|
|
||
|
if (dnsService && cfig.replication != 2)
|
||
|
updateDNS(req);
|
||
|
|
||
|
//_beginthread(updateStateFile, 0, (void*)req->dhcpEntry);
|
||
|
pthread_t threadId;
|
||
|
pthread_attr_t attr;
|
||
|
pthread_attr_init(&attr);
|
||
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||
|
int errcode = pthread_create(&threadId, &attr, updateStateFile, req->dhcpEntry);
|
||
|
pthread_attr_destroy(&attr);
|
||
|
|
||
|
if (verbatim || cfig.dhcpLogLevel >= 1) {
|
||
|
if (req->lease && req->reqIP) {
|
||
|
sprintf(logBuff,
|
||
|
"Host %s (%s) allotted %s for %u seconds",
|
||
|
req->chaddr,
|
||
|
req->hostname,
|
||
|
IP2String(tempbuff, req->dhcpp.header.bp_yiaddr),
|
||
|
req->lease);
|
||
|
} else if (req->req_type) {
|
||
|
sprintf(logBuff,
|
||
|
"Host %s (%s) renewed %s for %u seconds",
|
||
|
req->chaddr,
|
||
|
req->hostname,
|
||
|
IP2String(tempbuff, req->dhcpp.header.bp_yiaddr),
|
||
|
req->lease);
|
||
|
} else {
|
||
|
sprintf(logBuff,
|
||
|
"BOOTP Host %s (%s) allotted %s",
|
||
|
req->chaddr,
|
||
|
req->hostname,
|
||
|
IP2String(tempbuff, req->dhcpp.header.bp_yiaddr));
|
||
|
}
|
||
|
logDHCPMess(logBuff, 1);
|
||
|
}
|
||
|
|
||
|
if (cfig.replication && cfig.dhcpRepl > t)
|
||
|
sendRepl(req);
|
||
|
|
||
|
return req->dhcpEntry->ip;
|
||
|
} else if ((verbatim || cfig.dhcpLogLevel >= 2) && req->resp_type == DHCP_MESS_OFFER) {
|
||
|
sprintf(logBuff,
|
||
|
"Host %s (%s) offered %s",
|
||
|
req->chaddr,
|
||
|
req->hostname,
|
||
|
IP2String(tempbuff, req->dhcpp.header.bp_yiaddr));
|
||
|
logDHCPMess(logBuff, 2);
|
||
|
}
|
||
|
//printf("%u=out\n", req->resp_type);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void addOptions(data9 *req) {
|
||
|
|
||
|
data3 op {};
|
||
|
int i;
|
||
|
|
||
|
if (req->req_type && req->resp_type) {
|
||
|
op.opt_code = DHCP_OPTION_MESSAGETYPE;
|
||
|
op.size = 1;
|
||
|
op.value[0] = req->resp_type;
|
||
|
pvdata(req, &op);
|
||
|
}
|
||
|
|
||
|
if (req->dhcpEntry && req->resp_type != DHCP_MESS_DECLINE && req->resp_type != DHCP_MESS_NAK) {
|
||
|
strcpy(req->dhcpp.header.bp_sname, cfig.servername);
|
||
|
|
||
|
if (req->dhcpEntry->fixed) {
|
||
|
//printf("%u,%u\n", req->dhcpEntry->options, *req->dhcpEntry->options);
|
||
|
MYBYTE *opPointer = req->dhcpEntry->options;
|
||
|
|
||
|
if (opPointer) {
|
||
|
MYBYTE requestedOnly = *opPointer;
|
||
|
opPointer++;
|
||
|
|
||
|
while (*opPointer && *opPointer != DHCP_OPTION_END) {
|
||
|
op.opt_code = *opPointer;
|
||
|
opPointer++;
|
||
|
op.size = *opPointer;
|
||
|
opPointer++;
|
||
|
|
||
|
if (!requestedOnly || req->paramreqlist[*opPointer]) {
|
||
|
memcpy(op.value, opPointer, op.size);
|
||
|
pvdata(req, &op);
|
||
|
}
|
||
|
opPointer += op.size;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (req->req_type && req->resp_type) {
|
||
|
if (req->dhcpEntry->rangeInd >= 0) {
|
||
|
MYBYTE *opPointer = cfig.dhcpRanges[req->dhcpEntry->rangeInd].options;
|
||
|
//printf("Range=%i Pointer=%u\n", req->dhcpEntry->rangeInd,opPointer);
|
||
|
|
||
|
if (opPointer) {
|
||
|
MYBYTE requestedOnly = *opPointer;
|
||
|
opPointer++;
|
||
|
|
||
|
while (*opPointer && *opPointer != DHCP_OPTION_END) {
|
||
|
op.opt_code = *opPointer;
|
||
|
opPointer++;
|
||
|
op.size = *opPointer;
|
||
|
opPointer++;
|
||
|
|
||
|
if (!requestedOnly || req->paramreqlist[*opPointer]) {
|
||
|
memcpy(op.value, opPointer, op.size);
|
||
|
pvdata(req, &op);
|
||
|
}
|
||
|
opPointer += op.size;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
MYBYTE *opPointer = cfig.options;
|
||
|
|
||
|
if (opPointer) {
|
||
|
MYBYTE requestedOnly = *opPointer;
|
||
|
|
||
|
opPointer++;
|
||
|
while (*opPointer && *opPointer != DHCP_OPTION_END) {
|
||
|
op.opt_code = *opPointer;
|
||
|
opPointer++;
|
||
|
op.size = *opPointer;
|
||
|
opPointer++;
|
||
|
|
||
|
if (!requestedOnly || req->paramreqlist[*opPointer]) {
|
||
|
memcpy(op.value, opPointer, op.size);
|
||
|
pvdata(req, &op);
|
||
|
}
|
||
|
opPointer += op.size;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
op.opt_code = DHCP_OPTION_SERVERID;
|
||
|
op.size = 4;
|
||
|
pIP(op.value, network.dhcpConn[req->sockInd].server);
|
||
|
pvdata(req, &op);
|
||
|
|
||
|
op.opt_code = DHCP_OPTION_DOMAINNAME;
|
||
|
op.size = strlen(cfig.zone) + 1;
|
||
|
memcpy(op.value, cfig.zone, op.size);
|
||
|
pvdata(req, &op);
|
||
|
|
||
|
if (!req->opAdded[DHCP_OPTION_IPADDRLEASE]) {
|
||
|
op.opt_code = DHCP_OPTION_IPADDRLEASE;
|
||
|
op.size = 4;
|
||
|
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->opAdded[DHCP_OPTION_DNS])
|
||
|
{
|
||
|
if (dnsService)
|
||
|
{
|
||
|
op.opt_code = DHCP_OPTION_DNS;
|
||
|
|
||
|
if (cfig.dhcpRepl > t && cfig.dnsRepl > t)
|
||
|
{
|
||
|
if (cfig.replication == 1)
|
||
|
{
|
||
|
op.size = 8;
|
||
|
pIP(op.value, cfig.zoneServers[0]);
|
||
|
pIP(op.value + 4, cfig.zoneServers[1]);
|
||
|
pvdata(req, &op);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
op.size = 8;
|
||
|
pIP(op.value, cfig.zoneServers[1]);
|
||
|
pIP(op.value + 4, cfig.zoneServers[0]);
|
||
|
pvdata(req, &op);
|
||
|
}
|
||
|
}
|
||
|
else if (cfig.dnsRepl > t)
|
||
|
{
|
||
|
op.size = 8;
|
||
|
pIP(op.value, cfig.zoneServers[1]);
|
||
|
pIP(op.value + 4, cfig.zoneServers[0]);
|
||
|
pvdata(req, &op);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
op.size = 4;
|
||
|
pIP(op.value, network.dhcpConn[req->sockInd].server);
|
||
|
pvdata(req, &op);
|
||
|
}
|
||
|
}
|
||
|
else if (cfig.dnsRepl > t && cfig.replication == 2)
|
||
|
{
|
||
|
op.opt_code = DHCP_OPTION_DNS;
|
||
|
op.size = 4;
|
||
|
pIP(op.value, cfig.zoneServers[0]);
|
||
|
pvdata(req, &op);
|
||
|
}
|
||
|
}
|
||
|
*/
|
||
|
if (!req->opAdded[DHCP_OPTION_DNS] && dnsService) {
|
||
|
op.opt_code = DHCP_OPTION_DNS;
|
||
|
|
||
|
if (cfig.dnsRepl > t) {
|
||
|
op.size = 8;
|
||
|
pIP(op.value, cfig.zoneServers[0]);
|
||
|
pIP(op.value + 4, cfig.zoneServers[1]);
|
||
|
pvdata(req, &op);
|
||
|
} else {
|
||
|
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) {
|
||
|
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 updateDNS(data9 *req) {
|
||
|
if (req->dhcpEntry && cfig.replication != 2) {
|
||
|
MYDWORD expiry = MY_MAX_TIME;
|
||
|
|
||
|
if (req->lease < (MYDWORD)(MY_MAX_TIME - t))
|
||
|
expiry = t + req->lease;
|
||
|
|
||
|
//printf("Update DNS t=%d exp=%d\n", t, req->dhcpEntry->expiry);
|
||
|
if (isLocal(req->dhcpEntry->ip))
|
||
|
add2Cache(req->hostname, req->dhcpEntry->ip, expiry, CTYPE_LOCAL_A, CTYPE_LOCAL_PTR_AUTH);
|
||
|
else
|
||
|
add2Cache(req->hostname, req->dhcpEntry->ip, expiry, CTYPE_LOCAL_A, CTYPE_LOCAL_PTR_NAUTH);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void setTempLease(data7 *dhcpEntry) {
|
||
|
if (dhcpEntry && dhcpEntry->ip) {
|
||
|
dhcpEntry->display = false;
|
||
|
dhcpEntry->local = false;
|
||
|
dhcpEntry->expiry = t + 20;
|
||
|
|
||
|
int ind = getIndex((char)(dhcpEntry->rangeInd), dhcpEntry->ip);
|
||
|
|
||
|
if (ind >= 0) {
|
||
|
if (cfig.dhcpRanges[dhcpEntry->rangeInd].expiry[ind] != MY_MAX_TIME)
|
||
|
cfig.dhcpRanges[dhcpEntry->rangeInd].expiry[ind] = dhcpEntry->expiry;
|
||
|
|
||
|
cfig.dhcpRanges[dhcpEntry->rangeInd].dhcpEntry[ind] = dhcpEntry;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void setLeaseExpiry(data7 *dhcpEntry, MYDWORD lease) {
|
||
|
//printf("%d=%d\n", t, lease);
|
||
|
if (dhcpEntry && dhcpEntry->ip) {
|
||
|
if (lease > (MYDWORD)(MY_MAX_TIME - t))
|
||
|
dhcpEntry->expiry = MY_MAX_TIME;
|
||
|
else
|
||
|
dhcpEntry->expiry = t + lease;
|
||
|
|
||
|
int ind = getIndex((char)(dhcpEntry->rangeInd), dhcpEntry->ip);
|
||
|
|
||
|
if (ind >= 0) {
|
||
|
if (cfig.dhcpRanges[dhcpEntry->rangeInd].expiry[ind] != MY_MAX_TIME)
|
||
|
cfig.dhcpRanges[dhcpEntry->rangeInd].expiry[ind] = dhcpEntry->expiry;
|
||
|
|
||
|
cfig.dhcpRanges[dhcpEntry->rangeInd].dhcpEntry[ind] = dhcpEntry;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void setLeaseExpiry(data7 *dhcpEntry) {
|
||
|
if (dhcpEntry && dhcpEntry->ip) {
|
||
|
int ind = getIndex((char)(dhcpEntry->rangeInd), dhcpEntry->ip);
|
||
|
|
||
|
if (ind >= 0) {
|
||
|
if (cfig.dhcpRanges[dhcpEntry->rangeInd].expiry[ind] != MY_MAX_TIME)
|
||
|
cfig.dhcpRanges[dhcpEntry->rangeInd].expiry[ind] = dhcpEntry->expiry;
|
||
|
|
||
|
cfig.dhcpRanges[dhcpEntry->rangeInd].dhcpEntry[ind] = dhcpEntry;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void lockIP(MYDWORD ip) {
|
||
|
if (dhcpService && ip) {
|
||
|
MYDWORD iip = htonl(ip);
|
||
|
|
||
|
for (unsigned char rangeInd = 0; rangeInd < cfig.rangeCount; rangeInd++) {
|
||
|
if (iip >= cfig.dhcpRanges[rangeInd].rangeStart && iip <= cfig.dhcpRanges[rangeInd].rangeEnd) {
|
||
|
int ind = (int)(iip - cfig.dhcpRanges[rangeInd].rangeStart);
|
||
|
|
||
|
if (cfig.dhcpRanges[rangeInd].expiry[ind] != MY_MAX_TIME)
|
||
|
cfig.dhcpRanges[rangeInd].expiry[ind] = MY_MAX_TIME;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void holdIP(MYDWORD ip) {
|
||
|
if (dhcpService && ip) {
|
||
|
MYDWORD iip = htonl(ip);
|
||
|
|
||
|
for (unsigned char rangeInd = 0; rangeInd < cfig.rangeCount; rangeInd++) {
|
||
|
if (iip >= cfig.dhcpRanges[rangeInd].rangeStart && iip <= cfig.dhcpRanges[rangeInd].rangeEnd) {
|
||
|
int ind = (int)(iip - cfig.dhcpRanges[rangeInd].rangeStart);
|
||
|
|
||
|
if (cfig.dhcpRanges[rangeInd].expiry[ind] == 0)
|
||
|
cfig.dhcpRanges[rangeInd].expiry[ind] = 1;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void *sendToken(void *lpParam) {
|
||
|
sleep(10);
|
||
|
|
||
|
while (kRunning) {
|
||
|
strcpy(token.dhcpp.header.bp_sname, cfig.servername);
|
||
|
errno = 0;
|
||
|
|
||
|
sendto(cfig.dhcpReplConn.sock, token.raw, token.bytes, 0, (sockaddr *)&token.remote, sizeof(token.remote));
|
||
|
|
||
|
// errno = WSAGetLastError();
|
||
|
|
||
|
// if (errno)
|
||
|
// else if (verbatim || cfig.dhcpLogLevel >= 2)
|
||
|
|
||
|
sleep(300);
|
||
|
}
|
||
|
|
||
|
pthread_exit(nullptr);
|
||
|
}
|
||
|
|
||
|
MYDWORD sendRepl(data9 *req) {
|
||
|
char logBuff[256];
|
||
|
char ipbuff[32];
|
||
|
data3 op {};
|
||
|
|
||
|
MYBYTE *opPointer = req->dhcpp.vend_data;
|
||
|
|
||
|
while ((*opPointer) != DHCP_OPTION_END && opPointer < req->vp) {
|
||
|
if ((*opPointer) == DHCP_OPTION_MESSAGETYPE) {
|
||
|
*(opPointer + 2) = DHCP_MESS_INFORM;
|
||
|
break;
|
||
|
}
|
||
|
opPointer = opPointer + *(opPointer + 1) + 2;
|
||
|
}
|
||
|
|
||
|
if (!req->opAdded[DHCP_OPTION_MESSAGETYPE]) {
|
||
|
op.opt_code = DHCP_OPTION_MESSAGETYPE;
|
||
|
op.size = 1;
|
||
|
op.value[0] = DHCP_MESS_INFORM;
|
||
|
pvdata(req, &op);
|
||
|
}
|
||
|
|
||
|
if (req->hostname[0] && !req->opAdded[DHCP_OPTION_HOSTNAME]) {
|
||
|
op.opt_code = DHCP_OPTION_HOSTNAME;
|
||
|
op.size = strlen(req->hostname) + 1;
|
||
|
memcpy(op.value, req->hostname, op.size);
|
||
|
pvdata(req, &op);
|
||
|
}
|
||
|
|
||
|
// op.opt_code = DHCP_OPTION_SERIAL;
|
||
|
// op.size = 4;
|
||
|
// 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 (req->dns)
|
||
|
cfig.dnsRepl = t + 650;
|
||
|
|
||
|
if (cfig.replication == 1) {
|
||
|
if (dnsService) {
|
||
|
sprintf(cfig.nsS, "%s.%s", req->dhcpp.header.bp_sname, cfig.zone);
|
||
|
add2Cache(req->dhcpp.header.bp_sname,
|
||
|
cfig.zoneServers[1],
|
||
|
(t + 650),
|
||
|
CTYPE_SERVER_A_AUTH,
|
||
|
CTYPE_SERVER_PTR_AUTH);
|
||
|
}
|
||
|
|
||
|
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);
|
||
|
// }
|
||
|
} else if (cfig.replication == 2) {
|
||
|
if (!cfig.nsP[0] && req->dhcpp.header.bp_sname[0])
|
||
|
sprintf(cfig.nsP, "%s.%s", req->dhcpp.header.bp_sname, cfig.zone);
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
char rInd = getRangeInd(ip);
|
||
|
|
||
|
if (rInd >= 0) {
|
||
|
int ind = getIndex(rInd, ip);
|
||
|
req->dhcpEntry = cfig.dhcpRanges[rInd].dhcpEntry[ind];
|
||
|
|
||
|
if (req->dhcpEntry && !req->dhcpEntry->fixed && strcasecmp(req->dhcpEntry->mapname, req->chaddr) != 0)
|
||
|
req->dhcpEntry->expiry = 0;
|
||
|
}
|
||
|
|
||
|
req->dhcpEntry = findDHCPEntry(req->chaddr);
|
||
|
|
||
|
if (req->dhcpEntry && req->dhcpEntry->ip != ip) {
|
||
|
if (req->dhcpEntry->fixed) {
|
||
|
if (cfig.replication == 1)
|
||
|
sprintf(logBuff,
|
||
|
"DHCP Update ignored for %s (%s) from Secondary Server",
|
||
|
req->chaddr,
|
||
|
IP2String(ipbuff, ip));
|
||
|
else
|
||
|
sprintf(
|
||
|
logBuff, "DHCP Update ignored for %s (%s) from Primary Server", req->chaddr, IP2String(ipbuff, ip));
|
||
|
|
||
|
logDHCPMess(logBuff, 1);
|
||
|
return;
|
||
|
} else if (req->dhcpEntry->rangeInd >= 0) {
|
||
|
int ind = getIndex((char)(req->dhcpEntry->rangeInd), req->dhcpEntry->ip);
|
||
|
|
||
|
if (ind >= 0)
|
||
|
cfig.dhcpRanges[req->dhcpEntry->rangeInd].dhcpEntry[ind] = nullptr;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!req->dhcpEntry && rInd >= 0) {
|
||
|
memset(&g_lump, 0, sizeof(data71));
|
||
|
g_lump.cacheType = CTYPE_DHCP_ENTRY;
|
||
|
g_lump.mapname = req->chaddr;
|
||
|
g_lump.hostname = req->hostname;
|
||
|
req->dhcpEntry = createCache(&g_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 < 0 ? -1 : (int)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);
|
||
|
|
||
|
//_beginthread(updateStateFile, 0, (void*)req->dhcpEntry);
|
||
|
pthread_t threadId;
|
||
|
pthread_attr_t attr;
|
||
|
pthread_attr_init(&attr);
|
||
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||
|
int errcode = pthread_create(&threadId, &attr, updateStateFile, req->dhcpEntry);
|
||
|
pthread_attr_destroy(&attr);
|
||
|
|
||
|
if (dnsService && cfig.replication != 2) {
|
||
|
if (req->lease)
|
||
|
updateDNS(req);
|
||
|
else
|
||
|
expireEntry(req->dhcpEntry->ip);
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
char getRangeInd(MYDWORD ip) {
|
||
|
if (ip) {
|
||
|
MYDWORD iip = htonl(ip);
|
||
|
|
||
|
for (unsigned char k = 0; k < cfig.rangeCount; k++)
|
||
|
if (iip >= cfig.dhcpRanges[k].rangeStart && iip <= cfig.dhcpRanges[k].rangeEnd)
|
||
|
return (char)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) && strtol(value, nullptr, 10) > 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) && strtol(ptr, nullptr, 10) <= UCHAR_MAX) {
|
||
|
hoption[valSize] = strtol(ptr, nullptr, 10);
|
||
|
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 = 1;
|
||
|
} 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 (strtol(name, nullptr, 10) < 1 || strtol(name, nullptr, 10) >= 254) {
|
||
|
sprintf(logBuff, "Warning: section [%s] invalid option %s, ignored", sectionName, raw);
|
||
|
logDHCPMess(logBuff, 1);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
opTag = strtol(name, nullptr, 10);
|
||
|
opType = 0;
|
||
|
}
|
||
|
|
||
|
for (MYBYTE i = 0; i < maxInd; i++)
|
||
|
if (!strcasecmp(name, opData[i].opName) || (opTag && opTag == opData[i].opTag)) {
|
||
|
opTag = opData[i].opTag;
|
||
|
opType = opData[i].opType;
|
||
|
tagFound = true;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (!opTag) {
|
||
|
sprintf(logBuff, "Warning: section [%s] invalid option %s, ignored", sectionName, raw);
|
||
|
logDHCPMess(logBuff, 1);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (!opType)
|
||
|
opType = valType;
|
||
|
|
||
|
//sprintf(logBuff, "Tag %i ValType %i opType %i value=%s size=%u", opTag, valType, opType, value, valSize);
|
||
|
//logDHCPMess(logBuff, 1);
|
||
|
|
||
|
if (op_specified[opTag]) {
|
||
|
sprintf(logBuff, "Warning: section [%s] duplicate option %s, ignored", sectionName, raw);
|
||
|
logDHCPMess(logBuff, 1);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
//printf("Option=%u opType=%u valueType=%u valSize=%u\n", opTag, opType, valType, valSize);
|
||
|
|
||
|
op_specified[opTag] = true;
|
||
|
|
||
|
if (valType == 9) {
|
||
|
if (buffsize > 2) {
|
||
|
*dp = opTag;
|
||
|
dp++;
|
||
|
*dp = 0;
|
||
|
dp++;
|
||
|
buffsize -= 2;
|
||
|
} else {
|
||
|
sprintf(logBuff, "Warning: section [%s] option %s, no more space for options", sectionName, raw);
|
||
|
logDHCPMess(logBuff, 1);
|
||
|
}
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
switch (opType) {
|
||
|
case 1: {
|
||
|
value[valSize] = 0;
|
||
|
valSize++;
|
||
|
|
||
|
if (valType != 1 && valType != 2) {
|
||
|
sprintf(logBuff,
|
||
|
"Warning: section [%s] option %s, need string value, option ignored",
|
||
|
sectionName,
|
||
|
raw);
|
||
|
logDHCPMess(logBuff, 1);
|
||
|
} else if (!strcasecmp(serviceName, "DUALServer") && opTag == DHCP_OPTION_DOMAINNAME) {
|
||
|
sprintf(logBuff,
|
||
|
"Warning: section [%s] Domain Name %s should be in section [DOMAIN_NAME], ignored",
|
||
|
sectionName,
|
||
|
value);
|
||
|
logDHCPMess(logBuff, 1);
|
||
|
continue;
|
||
|
} else if (buffsize > valSize + 2) {
|
||
|
*dp = opTag;
|
||
|
dp++;
|
||
|
*dp = valSize;
|
||
|
dp++;
|
||
|
memcpy(dp, value, valSize);
|
||
|
dp += valSize;
|
||
|
buffsize -= (valSize + 2);
|
||
|
} else {
|
||
|
sprintf(logBuff, "Warning: section [%s] option %s, no more space for options", sectionName, raw);
|
||
|
logDHCPMess(logBuff, 1);
|
||
|
}
|
||
|
} break;
|
||
|
|
||
|
case 3:
|
||
|
case 8: {
|
||
|
if (valType == 2) {
|
||
|
if (opType == 3 && valSize % 4) {
|
||
|
sprintf(logBuff,
|
||
|
"Warning: section [%s] option %s, missing/extra bytes/octates in IP, option ignored",
|
||
|
sectionName,
|
||
|
raw);
|
||
|
logDHCPMess(logBuff, 1);
|
||
|
continue;
|
||
|
} else if (opType == 8 && valSize % 8) {
|
||
|
sprintf(logBuff,
|
||
|
"Warning: section [%s] option %s, some values not in IP/Mask form, option ignored",
|
||
|
sectionName,
|
||
|
raw);
|
||
|
logDHCPMess(logBuff, 1);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (opTag == DHCP_OPTION_NETMASK) {
|
||
|
if (valSize != 4 || !checkMask(fIP(value))) {
|
||
|
sprintf(logBuff,
|
||
|
"Warning: section [%s] Invalid subnetmask %s, option ignored",
|
||
|
sectionName,
|
||
|
raw);
|
||
|
logDHCPMess(logBuff, 1);
|
||
|
continue;
|
||
|
} else
|
||
|
optionData->mask = fIP(value);
|
||
|
}
|
||
|
|
||
|
if (buffsize > valSize + 2) {
|
||
|
*dp = opTag;
|
||
|
dp++;
|
||
|
*dp = valSize;
|
||
|
dp++;
|
||
|
memcpy(dp, value, valSize);
|
||
|
dp += valSize;
|
||
|
buffsize -= (valSize + 2);
|
||
|
} else {
|
||
|
sprintf(
|
||
|
logBuff, "Warning: section [%s] option %s, no more space for options", sectionName, raw);
|
||
|
logDHCPMess(logBuff, 1);
|
||
|
}
|
||
|
} else {
|
||
|
sprintf(logBuff,
|
||
|
"Warning: section [%s] option %s, Invalid value, should be one or more IP/4 Bytes",
|
||
|
sectionName,
|
||
|
raw);
|
||
|
logDHCPMess(logBuff, 1);
|
||
|
}
|
||
|
} break;
|
||
|
|
||
|
case 4: {
|
||
|
MYDWORD j;
|
||
|
|
||
|
if (valType == 2 && valSize == 4)
|
||
|
j = 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 && strtol(value, nullptr, 10) < 2)
|
||
|
j = strtol(value, nullptr, 10);
|
||
|
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)strtol(value, nullptr, 10);
|
||
|
}
|
||
|
|
||
|
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 && strtol(name, nullptr, 10) == 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) && strtol(ptr, nullptr, 10) <= UCHAR_MAX) {
|
||
|
hoption[valueSize] = (char)strtol(ptr, nullptr, 10);
|
||
|
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);
|
||
|
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));
|
||
|
memset(range->expiry, 0, (re - rs + 1) * sizeof(time_t));
|
||
|
range->dhcpEntry = (data7 **)calloc((re - rs + 1), sizeof(struct data7 *));
|
||
|
memset(range->dhcpEntry, 0, (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);
|
||
|
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 = m;
|
||
|
} else
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//printf("%s\n", IP2String(ipbuff, cfig.mask));
|
||
|
|
||
|
for (unsigned 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(&g_lump, 0, sizeof(data71));
|
||
|
g_lump.cacheType = CTYPE_DHCP_ENTRY;
|
||
|
g_lump.mapname = mapname;
|
||
|
g_lump.optionSize = optionData.optionSize;
|
||
|
g_lump.options = optionData.options;
|
||
|
dhcpEntry = createCache(&g_lump);
|
||
|
|
||
|
if (!dhcpEntry)
|
||
|
return;
|
||
|
|
||
|
char idx = getRangeInd(optionData.ip);
|
||
|
|
||
|
dhcpEntry->ip = optionData.ip;
|
||
|
dhcpEntry->rangeInd = idx < 0 ? -1 : (int)idx;
|
||
|
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)) {
|
||
|
char 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(&g_lump, 0, sizeof(data71));
|
||
|
g_lump.cacheType = CTYPE_DHCP_ENTRY;
|
||
|
g_lump.mapname = mapname;
|
||
|
dhcpEntry = createCache(&g_lump);
|
||
|
}
|
||
|
|
||
|
if (dhcpEntry) {
|
||
|
dhcpCache[dhcpEntry->mapname] = dhcpEntry;
|
||
|
dhcpEntry->subnetFlg = dhcpData.subnetFlg;
|
||
|
dhcpEntry->ip = dhcpData.ip;
|
||
|
dhcpEntry->rangeInd = rangeInd < 0 ? -1 : (int)rangeInd;
|
||
|
dhcpEntry->expiry = dhcpData.expiry;
|
||
|
dhcpEntry->local = dhcpData.local;
|
||
|
dhcpEntry->display = true;
|
||
|
strcpy(dhcpEntry->hostname, dhcpData.hostname);
|
||
|
setLeaseExpiry(dhcpEntry);
|
||
|
|
||
|
if (dnsService && dhcpData.hostname[0] && cfig.replication != 2 && dhcpData.expiry > t) {
|
||
|
if (isLocal(dhcpEntry->ip))
|
||
|
add2Cache(
|
||
|
dhcpData.hostname, dhcpEntry->ip, dhcpData.expiry, CTYPE_LOCAL_A, CTYPE_LOCAL_PTR_AUTH);
|
||
|
else
|
||
|
add2Cache(dhcpData.hostname,
|
||
|
dhcpEntry->ip,
|
||
|
dhcpData.expiry,
|
||
|
CTYPE_LOCAL_A,
|
||
|
CTYPE_LOCAL_PTR_NAUTH);
|
||
|
}
|
||
|
//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 logBuff[256];
|
||
|
char tempbuff[512];
|
||
|
char section[128];
|
||
|
sprintf(section, "[%s]", sectionName);
|
||
|
myUpper(section);
|
||
|
FILE *f = nullptr;
|
||
|
f = fopen(iniFile, "rt");
|
||
|
|
||
|
if (f) {
|
||
|
//printf("opened %s=%d\n", tempbuff, f);
|
||
|
char buff[512];
|
||
|
MYBYTE found = 0;
|
||
|
|
||
|
while (fgets(buff, 511, f)) {
|
||
|
myUpper(buff);
|
||
|
myTrim(buff, buff);
|
||
|
|
||
|
if (strstr(buff, section) == buff) {
|
||
|
found++;
|
||
|
|
||
|
if (found == serial) {
|
||
|
MYDWORD fpos = ftell(f);
|
||
|
|
||
|
if (fgets(buff, 511, f)) {
|
||
|
myTrim(buff, buff);
|
||
|
|
||
|
if (buff[0] == '@') {
|
||
|
fclose(f);
|
||
|
f = nullptr;
|
||
|
|
||
|
buff[0] = NBSP;
|
||
|
myTrim(buff, buff);
|
||
|
|
||
|
if (strchr(buff, '\\') || strchr(buff, '/'))
|
||
|
strcpy(tempbuff, buff);
|
||
|
else
|
||
|
sprintf(tempbuff, "%s%s", filePATH, buff);
|
||
|
|
||
|
f = fopen(tempbuff, "rt");
|
||
|
|
||
|
if (f)
|
||
|
return f;
|
||
|
else {
|
||
|
sprintf(logBuff, "Error: Section [%s], file %s not found", sectionName, tempbuff);
|
||
|
logMess(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);
|
||
|
}
|
||
|
|
||
|
char *strquery(data5 *req) {
|
||
|
strcpy(req->extbuff, req->query);
|
||
|
|
||
|
switch (req->dnsType) {
|
||
|
case 1:
|
||
|
strcat(req->extbuff, " A");
|
||
|
break;
|
||
|
case 2:
|
||
|
strcat(req->extbuff, " NS");
|
||
|
break;
|
||
|
case 3:
|
||
|
strcat(req->extbuff, " MD");
|
||
|
break;
|
||
|
case 4:
|
||
|
strcat(req->extbuff, " MF");
|
||
|
break;
|
||
|
case 5:
|
||
|
strcat(req->extbuff, " CNAME");
|
||
|
break;
|
||
|
case 6:
|
||
|
strcat(req->extbuff, " SOA");
|
||
|
break;
|
||
|
case 7:
|
||
|
strcat(req->extbuff, " MB");
|
||
|
break;
|
||
|
case 8:
|
||
|
strcat(req->extbuff, " MG");
|
||
|
break;
|
||
|
case 9:
|
||
|
strcat(req->extbuff, " MR");
|
||
|
break;
|
||
|
case 10:
|
||
|
strcat(req->extbuff, " nullptr");
|
||
|
break;
|
||
|
case 11:
|
||
|
strcat(req->extbuff, " WKS");
|
||
|
break;
|
||
|
case 12:
|
||
|
strcat(req->extbuff, " PTR");
|
||
|
break;
|
||
|
case 13:
|
||
|
strcat(req->extbuff, " HINFO");
|
||
|
break;
|
||
|
case 14:
|
||
|
strcat(req->extbuff, " MINFO");
|
||
|
break;
|
||
|
case 15:
|
||
|
strcat(req->extbuff, " MX");
|
||
|
break;
|
||
|
case 16:
|
||
|
strcat(req->extbuff, " TXT");
|
||
|
break;
|
||
|
case 28:
|
||
|
strcat(req->extbuff, " AAAA");
|
||
|
break;
|
||
|
case 251:
|
||
|
strcat(req->extbuff, " IXFR");
|
||
|
break;
|
||
|
case 252:
|
||
|
strcat(req->extbuff, " AXFR");
|
||
|
break;
|
||
|
case 253:
|
||
|
strcat(req->extbuff, " MAILB");
|
||
|
break;
|
||
|
case 254:
|
||
|
strcat(req->extbuff, " MAILA");
|
||
|
break;
|
||
|
case 255:
|
||
|
strcat(req->extbuff, " ANY");
|
||
|
break;
|
||
|
}
|
||
|
return req->extbuff;
|
||
|
}
|
||
|
|
||
|
#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, MYBYTE dnsType) {
|
||
|
char *dp = target;
|
||
|
(*dp) = (char)dnsType;
|
||
|
dp++;
|
||
|
data15 inaddr{};
|
||
|
inaddr.ip = ip;
|
||
|
sprintf(dp, "%u.%u.%u.%u", inaddr.octate[0], inaddr.octate[1], inaddr.octate[2], inaddr.octate[3]);
|
||
|
//MYBYTE *octate = (MYBYTE*)&ip;
|
||
|
//sprintf(target, "%u.%u.%u.%u", octate[0], octate[1], octate[2], octate[3]);
|
||
|
return target;
|
||
|
}
|
||
|
|
||
|
char *IP2String(char *target, MYDWORD ip) {
|
||
|
data15 inaddr{};
|
||
|
inaddr.ip = ip;
|
||
|
sprintf(target, "%u.%u.%u.%u", inaddr.octate[0], inaddr.octate[1], inaddr.octate[2], inaddr.octate[3]);
|
||
|
//MYBYTE *octate = (MYBYTE*)&ip;
|
||
|
//sprintf(target, "%u.%u.%u.%u", octate[0], octate[1], octate[2], octate[3]);
|
||
|
return target;
|
||
|
}
|
||
|
|
||
|
MYBYTE addServer(MYDWORD *array, MYBYTE maxServers, MYDWORD ip) {
|
||
|
if (ip) {
|
||
|
for (MYBYTE i = 0; i < maxServers; i++) {
|
||
|
if (array[i] == ip)
|
||
|
return i;
|
||
|
else if (!array[i]) {
|
||
|
array[i] = ip;
|
||
|
return i;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return maxServers;
|
||
|
}
|
||
|
|
||
|
MYDWORD *findServer(MYDWORD *array, MYBYTE maxServers, MYDWORD ip) {
|
||
|
if (ip) {
|
||
|
for (MYBYTE i = 0; i < maxServers && array[i]; i++) {
|
||
|
if (array[i] == ip)
|
||
|
return &(array[i]);
|
||
|
}
|
||
|
}
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
bool isInt(char *str) {
|
||
|
if (!str || !(*str))
|
||
|
return false;
|
||
|
|
||
|
for (; *str; str++)
|
||
|
if (*str < '0' || *str > '9')
|
||
|
return false;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool isIP(char *str) {
|
||
|
if (!str || !(*str))
|
||
|
return false;
|
||
|
|
||
|
MYDWORD ip = inet_addr(str);
|
||
|
|
||
|
if (ip == INADDR_NONE || ip == INADDR_ANY)
|
||
|
return false;
|
||
|
|
||
|
int j = 0;
|
||
|
|
||
|
for (; *str; str++) {
|
||
|
if (*str == '.' && *(str + 1) != '.')
|
||
|
j++;
|
||
|
else if (*str < '0' || *str > '9')
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (j == 3)
|
||
|
return true;
|
||
|
else
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
char *toBase64(MYBYTE *source, MYBYTE length)
|
||
|
{
|
||
|
MYBYTE a = 0, b = 0, i = 0;
|
||
|
char *dp = tempbuff;
|
||
|
|
||
|
for (; length; length--, source++)
|
||
|
{
|
||
|
i += 2;
|
||
|
a = (*source) >> i;
|
||
|
*dp = base64[a + b];
|
||
|
dp++;
|
||
|
b = (*source) << (8 - i);
|
||
|
b >>= 2;
|
||
|
if (i == 6)
|
||
|
{
|
||
|
*dp = base64[b];
|
||
|
dp++;
|
||
|
i = b = 0;
|
||
|
}
|
||
|
}
|
||
|
if (i)
|
||
|
{
|
||
|
*dp = base64[b];
|
||
|
dp++;
|
||
|
}
|
||
|
*dp = 0;
|
||
|
//printf("%s\n",tempbuff);
|
||
|
return tempbuff;
|
||
|
}
|
||
|
|
||
|
MYBYTE getBaseValue(MYBYTE a)
|
||
|
{
|
||
|
if (a >= 'A' && a <= 'Z')
|
||
|
a -= 'A';
|
||
|
else if (a >= 'a' && a <= 'z')
|
||
|
a = a - 'a' + 26;
|
||
|
else if (a >= '0' && a <= '9')
|
||
|
a = a - '0' + 52;
|
||
|
else if (a == '+')
|
||
|
a = 62;
|
||
|
else if (a == '/')
|
||
|
a = 63;
|
||
|
else
|
||
|
a = UCHAR_MAX;
|
||
|
|
||
|
return a;
|
||
|
}
|
||
|
|
||
|
MYBYTE fromBase64(MYBYTE *target, char *source)
|
||
|
{
|
||
|
//printf("SOURCE=%s\n", source);
|
||
|
MYBYTE b = 0;
|
||
|
MYBYTE shift = 4;
|
||
|
MYBYTE bp_hlen = (3 * strlen(source))/4;
|
||
|
*target = 0;
|
||
|
|
||
|
if (*source)
|
||
|
{
|
||
|
b = getBaseValue(*source);
|
||
|
*target = b << 2;
|
||
|
source++;
|
||
|
|
||
|
while (*source)
|
||
|
{
|
||
|
b = getBaseValue(*source);
|
||
|
(*target) += (b >> (8 - shift));
|
||
|
target++;
|
||
|
(*target) = (b << shift);
|
||
|
shift += 2;
|
||
|
|
||
|
if (shift > 8)
|
||
|
{
|
||
|
source++;
|
||
|
|
||
|
if (*source)
|
||
|
{
|
||
|
b = getBaseValue(*source);
|
||
|
*target = b << 2;
|
||
|
shift = 4;
|
||
|
}
|
||
|
else
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
source++;
|
||
|
}
|
||
|
}
|
||
|
//printf("SIZE=%u\n", bp_hlen);
|
||
|
return bp_hlen;
|
||
|
}
|
||
|
|
||
|
char *toUUE(char *tempbuff, MYBYTE *source, MYBYTE length)
|
||
|
{
|
||
|
MYBYTE a = 0, b = 0, i = 0;
|
||
|
char *dp = tempbuff;
|
||
|
|
||
|
for (; length; length--, source++)
|
||
|
{
|
||
|
i += 2;
|
||
|
a = (*source) >> i;
|
||
|
*dp = a + b + NBSP;
|
||
|
dp++;
|
||
|
b = (*source) << (8 - i);
|
||
|
b >>= 2;
|
||
|
if (i == 6)
|
||
|
{
|
||
|
*dp = b + NBSP;
|
||
|
dp++;
|
||
|
i = b = 0;
|
||
|
}
|
||
|
}
|
||
|
if (i)
|
||
|
{
|
||
|
*dp = b + NBSP;
|
||
|
dp++;
|
||
|
}
|
||
|
*dp = 0;
|
||
|
//printf("%s\n",tempbuff);
|
||
|
return tempbuff;
|
||
|
}
|
||
|
|
||
|
MYBYTE fromUUE(MYBYTE *target, char *source)
|
||
|
{
|
||
|
//printf("SOURCE=%s\n", source);
|
||
|
MYBYTE b = 0;
|
||
|
MYBYTE shift = 4;
|
||
|
MYBYTE bp_hlen = (3 * strlen(source))/4;
|
||
|
*target = 0;
|
||
|
|
||
|
if (*source)
|
||
|
{
|
||
|
b = *source - NBSP;
|
||
|
*target = b << 2;
|
||
|
source++;
|
||
|
|
||
|
while (*source)
|
||
|
{
|
||
|
b = *source - NBSP;
|
||
|
(*target) += (b >> (8 - shift));
|
||
|
target++;
|
||
|
(*target) = (b << shift);
|
||
|
shift += 2;
|
||
|
|
||
|
if (shift > 8)
|
||
|
{
|
||
|
source++;
|
||
|
|
||
|
if (*source)
|
||
|
{
|
||
|
b = *source - NBSP;
|
||
|
*target = b << 2;
|
||
|
shift = 4;
|
||
|
}
|
||
|
else
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
source++;
|
||
|
}
|
||
|
}
|
||
|
//printf("SIZE=%u\n", bp_hlen);
|
||
|
return bp_hlen;
|
||
|
}
|
||
|
*/
|
||
|
char *hex2String(char *target, const MYBYTE *hex, MYBYTE bytes) {
|
||
|
char *dp = target;
|
||
|
|
||
|
if (bytes)
|
||
|
dp += sprintf(target, "%02x", *hex);
|
||
|
else
|
||
|
*target = 0;
|
||
|
|
||
|
for (MYBYTE i = 1; i < bytes; i++)
|
||
|
dp += sprintf(dp, ":%02x", *(hex + i));
|
||
|
|
||
|
return target;
|
||
|
}
|
||
|
|
||
|
char *genHostName(char *target, const MYBYTE *hex, MYBYTE bytes) {
|
||
|
char *dp = target;
|
||
|
|
||
|
if (bytes)
|
||
|
dp += sprintf(target, "Host%02x", *hex);
|
||
|
else
|
||
|
*target = 0;
|
||
|
|
||
|
for (MYBYTE i = 1; i < bytes; i++)
|
||
|
dp += sprintf(dp, "%02x", *(hex + i));
|
||
|
|
||
|
return target;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
char *IP62String(char *target, MYBYTE *source)
|
||
|
{
|
||
|
MYWORD *dw = (MYWORD*)source;
|
||
|
char *dp = target;
|
||
|
MYBYTE markbyte;
|
||
|
|
||
|
for (markbyte = 4; markbyte > 0 && !dw[markbyte - 1]; markbyte--);
|
||
|
|
||
|
for (MYBYTE i = 0; i < markbyte; i++)
|
||
|
dp += sprintf(dp, "%x:", ntohs(dw[i]));
|
||
|
|
||
|
for (markbyte = 4; markbyte < 8 && !dw[markbyte]; markbyte++);
|
||
|
|
||
|
for (MYBYTE i = markbyte; i < 8; i++)
|
||
|
dp += sprintf(dp, ":%x", htons(dw[i]));
|
||
|
|
||
|
return target;
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
char *IP62String(char *target, MYBYTE *source) {
|
||
|
char *dp = target;
|
||
|
bool zerostarted = false;
|
||
|
bool zeroended = false;
|
||
|
|
||
|
for (MYBYTE i = 0; i < 16; i += 2, source += 2) {
|
||
|
if (source[0]) {
|
||
|
if (zerostarted)
|
||
|
zeroended = true;
|
||
|
|
||
|
if (zerostarted && zeroended) {
|
||
|
dp += sprintf(dp, "::");
|
||
|
zerostarted = false;
|
||
|
} else if (dp != target)
|
||
|
dp += sprintf(dp, ":");
|
||
|
|
||
|
dp += sprintf(dp, "%x", source[0]);
|
||
|
dp += sprintf(dp, "%02x", source[1]);
|
||
|
} else if (source[1]) {
|
||
|
if (zerostarted)
|
||
|
zeroended = true;
|
||
|
|
||
|
if (zerostarted && zeroended) {
|
||
|
dp += sprintf(dp, "::");
|
||
|
zerostarted = false;
|
||
|
} else if (dp != target)
|
||
|
dp += sprintf(dp, ":");
|
||
|
|
||
|
dp += sprintf(dp, "%0x", source[1]);
|
||
|
} else if (!zeroended)
|
||
|
zerostarted = true;
|
||
|
}
|
||
|
|
||
|
return target;
|
||
|
}
|
||
|
|
||
|
char *getHexValue(MYBYTE *target, char *source, MYBYTE *size) {
|
||
|
if (*size)
|
||
|
memset(target, 0, (*size));
|
||
|
|
||
|
for ((*size) = 0; (*source) && (*size) < UCHAR_MAX; (*size)++, target++) {
|
||
|
if ((*source) >= '0' && (*source) <= '9') {
|
||
|
(*target) = (*source) - '0';
|
||
|
} else if ((*source) >= 'a' && (*source) <= 'f') {
|
||
|
(*target) = (*source) - 'a' + 10;
|
||
|
} else if ((*source) >= 'A' && (*source) <= 'F') {
|
||
|
(*target) = (*source) - 'A' + 10;
|
||
|
} else {
|
||
|
return source;
|
||
|
}
|
||
|
|
||
|
source++;
|
||
|
|
||
|
if ((*source) >= '0' && (*source) <= '9') {
|
||
|
(*target) *= 16;
|
||
|
(*target) += (*source) - '0';
|
||
|
} else if ((*source) >= 'a' && (*source) <= 'f') {
|
||
|
(*target) *= 16;
|
||
|
(*target) += (*source) - 'a' + 10;
|
||
|
} else if ((*source) >= 'A' && (*source) <= 'F') {
|
||
|
(*target) *= 16;
|
||
|
(*target) += (*source) - 'A' + 10;
|
||
|
} else if ((*source) == ':' || (*source) == '-') {
|
||
|
source++;
|
||
|
continue;
|
||
|
} else if (*source) {
|
||
|
return source;
|
||
|
} else {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
source++;
|
||
|
|
||
|
if ((*source) == ':' || (*source) == '-') {
|
||
|
source++;
|
||
|
} else if (*source)
|
||
|
return source;
|
||
|
}
|
||
|
|
||
|
if (*source)
|
||
|
return source;
|
||
|
|
||
|
//printf("macfucked in=%s\n", tSource);
|
||
|
//printf("macfucked out=%s\n", hex2String(tempbuff, tTarget, *size));
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
char *myUpper(char *string) {
|
||
|
char diff = 'a' - 'A';
|
||
|
MYWORD len = strlen(string);
|
||
|
for (int i = 0; i < len; i++)
|
||
|
if (string[i] >= 'a' && string[i] <= 'z')
|
||
|
string[i] = (char)(string[i] - diff);
|
||
|
return string;
|
||
|
}
|
||
|
|
||
|
char *myLower(char *string) {
|
||
|
char diff = 'a' - 'A';
|
||
|
MYWORD len = strlen(string);
|
||
|
for (int i = 0; i < len; i++)
|
||
|
if (string[i] >= 'A' && string[i] <= 'Z')
|
||
|
string[i] = (char)(string[i] + diff);
|
||
|
return string;
|
||
|
}
|
||
|
|
||
|
bool wildcmp(char *string, char *wild) {
|
||
|
// Written by Jack Handy - jakkhandy@hotmail.com
|
||
|
// slightly modified
|
||
|
char *cp = nullptr;
|
||
|
char *mp = nullptr;
|
||
|
|
||
|
while ((*string) && (*wild != '*')) {
|
||
|
if ((*wild != *string) && (*wild != '?')) {
|
||
|
return false;
|
||
|
}
|
||
|
wild++;
|
||
|
string++;
|
||
|
}
|
||
|
|
||
|
while (*string) {
|
||
|
if (*wild == '*') {
|
||
|
if (!*++wild)
|
||
|
return true;
|
||
|
|
||
|
mp = wild;
|
||
|
cp = string + 1;
|
||
|
} else if ((*wild == *string) || (*wild == '?')) {
|
||
|
wild++;
|
||
|
string++;
|
||
|
} else {
|
||
|
wild = mp;
|
||
|
string = cp++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
while (*wild == '*')
|
||
|
wild++;
|
||
|
|
||
|
return !(*wild);
|
||
|
}
|
||
|
|
||
|
bool isLocal(MYDWORD ip) {
|
||
|
if (cfig.rangeStart && htonl(ip) >= cfig.rangeStart && htonl(ip) <= cfig.rangeEnd)
|
||
|
return true;
|
||
|
// else if (getRangeInd(ip) >= 0)
|
||
|
// return true;
|
||
|
else
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
char *setMapName(char *tempbuff, char *mapname, MYBYTE dnsType) {
|
||
|
char *dp = tempbuff;
|
||
|
(*dp) = (char)dnsType;
|
||
|
dp++;
|
||
|
strcpy(dp, mapname);
|
||
|
myLower(dp);
|
||
|
return tempbuff;
|
||
|
}
|
||
|
|
||
|
MYBYTE makeLocal(char *mapname) {
|
||
|
if (!strcasecmp(mapname, cfig.zone)) {
|
||
|
mapname[0] = 0;
|
||
|
return QTYPE_A_ZONE;
|
||
|
} else if (!strcasecmp(mapname, cfig.authority)) {
|
||
|
//char *dp = strstr(mapname, arpa);
|
||
|
//(*dp) = 0;
|
||
|
return QTYPE_P_ZONE;
|
||
|
} else if (char *dp = strchr(mapname, '.')) {
|
||
|
if (!strcasecmp(dp + 1, cfig.zone)) {
|
||
|
*dp = 0;
|
||
|
return QTYPE_A_LOCAL;
|
||
|
} else if ((dp = strstr(mapname, arpa))) {
|
||
|
if (strstr(mapname, cfig.authority)) {
|
||
|
*dp = 0;
|
||
|
return QTYPE_P_LOCAL;
|
||
|
} else {
|
||
|
*dp = 0;
|
||
|
return QTYPE_P_EXT;
|
||
|
}
|
||
|
} else if (strstr(mapname, ip6arpa))
|
||
|
return QTYPE_P_EXT;
|
||
|
else
|
||
|
return QTYPE_A_EXT;
|
||
|
} else
|
||
|
return QTYPE_A_BARE;
|
||
|
}
|
||
|
|
||
|
|
||
|
#if 0
|
||
|
void listCache() {
|
||
|
char ipbuff[32];
|
||
|
char logBuff[256];
|
||
|
auto p = dnsCache[currentInd].begin();
|
||
|
data7 *cache = nullptr;
|
||
|
|
||
|
while (p != dnsCache[currentInd].end()) {
|
||
|
cache = p->second;
|
||
|
|
||
|
if (cache->hostname)
|
||
|
sprintf(logBuff, "%s=%s", cache->mapname, cache->hostname);
|
||
|
else
|
||
|
sprintf(logBuff, "%s=%s", cache->mapname, IP2String(ipbuff, cache->ip));
|
||
|
|
||
|
logDNSMess(logBuff, 1);
|
||
|
p++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void listDhcpCache() {
|
||
|
char logBuff[256];
|
||
|
auto p = dhcpCache.begin();
|
||
|
data7 *cache = nullptr;
|
||
|
|
||
|
while (p != dhcpCache.end()) {
|
||
|
cache = p->second;
|
||
|
sprintf(logBuff, "%s", cache->mapname);
|
||
|
logDHCPMess(logBuff, 1);
|
||
|
p++;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
void checkSize() {
|
||
|
data7 *cache = nullptr;
|
||
|
expiryMap::iterator p;
|
||
|
|
||
|
//while (p != dnsAge[currentInd].end() && p->first < t && maxDelete > 0)
|
||
|
while (true) {
|
||
|
p = dnsAge[currentInd].begin();
|
||
|
|
||
|
if (p == dnsAge[currentInd].end())
|
||
|
break;
|
||
|
|
||
|
if (p->first > t)
|
||
|
break;
|
||
|
|
||
|
cache = p->second;
|
||
|
//debug(cache->mapname);
|
||
|
|
||
|
dnsAge[currentInd].erase(p);
|
||
|
|
||
|
if (!cache)
|
||
|
continue;
|
||
|
|
||
|
if (cache->expiry > t) {
|
||
|
dnsAge[currentInd].insert(pair<time_t, data7 *>(cache->expiry, cache));
|
||
|
//sprintf(logBuff, "Entry %s being advanced", cache->name);
|
||
|
//logMess(logBuff, 1);
|
||
|
} else {
|
||
|
if (cache->cacheType == CTYPE_QUEUE && cache->expiry) {
|
||
|
if (cache->dnsIndex < MAX_SERVERS) {
|
||
|
if (network.currentDNS == cache->dnsIndex) {
|
||
|
if (network.dns[1]) {
|
||
|
network.currentDNS++;
|
||
|
|
||
|
if (network.currentDNS >= MAX_SERVERS || !network.dns[network.currentDNS])
|
||
|
network.currentDNS = 0;
|
||
|
}
|
||
|
}
|
||
|
} else if (cache->dnsIndex >= 128 && cache->dnsIndex < 192) {
|
||
|
data10 *dnsRoute = &cfig.dnsRoutes[(cache->dnsIndex - 128) / 2];
|
||
|
MYBYTE currentDNS = cache->dnsIndex % 2;
|
||
|
|
||
|
if (dnsRoute->currentDNS == currentDNS && dnsRoute->dns[1])
|
||
|
dnsRoute->currentDNS = 1 - dnsRoute->currentDNS;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (cfig.replication != 2) {
|
||
|
if (cache->cacheType == CTYPE_LOCAL_A || cache->cacheType == CTYPE_SERVER_A_AUTH)
|
||
|
cfig.serial1 = t;
|
||
|
else if (cache->cacheType == CTYPE_LOCAL_PTR_AUTH || cache->cacheType == CTYPE_SERVER_PTR_AUTH)
|
||
|
cfig.serial2 = t;
|
||
|
}
|
||
|
|
||
|
//char logBuff[256];
|
||
|
//sprintf(logBuff, "cache %p Data Type=%u Cache Size=%u, Age Size=%u, Entry %s being deleted", cache, cache->cacheType, dnsCache[currentInd].size(), dnsAge[currentInd].size(), cache->name);
|
||
|
//logMess(logBuff, 1);
|
||
|
delDnsEntry(cache);
|
||
|
//maxDelete--;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//sprintf(logBuff, "End Cache size %u=%u",dnsCache[currentInd].size(),dnsAge[currentInd].size());
|
||
|
//debug(logBuff);
|
||
|
}
|
||
|
|
||
|
void delDnsEntry(data7 *cache) {
|
||
|
auto r = dnsCache[currentInd].find(cache->mapname);
|
||
|
|
||
|
for (; r != dnsCache[currentInd].end(); r++) {
|
||
|
if (strcasecmp(r->second->mapname, cache->mapname) != 0)
|
||
|
break;
|
||
|
else if (r->second == cache) {
|
||
|
//char logBuff[256];
|
||
|
//sprintf(logBuff, "cache %p Data Type=%u CacheSize=%u, AgeSize=%u, Entry %s being deleted", cache, cache->cacheType, dnsCache[currentInd].size(), dnsAge[currentInd].size(), cache->name);
|
||
|
//debug(logBuff);
|
||
|
dnsCache[currentInd].erase(r);
|
||
|
free(cache);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void calcRangeLimits(MYDWORD ip, MYDWORD mask, MYDWORD *rangeStart, MYDWORD *rangeEnd) {
|
||
|
*rangeStart = htonl(ip & mask) + 1;
|
||
|
*rangeEnd = htonl(ip | (~mask)) - 1;
|
||
|
}
|
||
|
|
||
|
bool checkMask(MYDWORD mask) {
|
||
|
mask = htonl(mask);
|
||
|
|
||
|
while (mask) {
|
||
|
if (mask < (mask << 1))
|
||
|
return false;
|
||
|
|
||
|
mask <<= 1;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
#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 *findHost(char *tempbuff, MYDWORD ip) {
|
||
|
IP2String(tempbuff, htonl(ip));
|
||
|
data7 *cache = findDNSEntry(tempbuff, DNS_TYPE_PTR);
|
||
|
|
||
|
if (cache)
|
||
|
strcpy(tempbuff, cache->hostname);
|
||
|
else
|
||
|
tempbuff[0] = 0;
|
||
|
|
||
|
return tempbuff;
|
||
|
}
|
||
|
|
||
|
data7 *findDNSEntry(char *key, MYBYTE dnsType, MYBYTE cacheType) {
|
||
|
char tempbuff[512];
|
||
|
auto it = dnsCache[currentInd].find(setMapName(tempbuff, key, dnsType));
|
||
|
|
||
|
while (it != dnsCache[currentInd].end() && it->second && !strcasecmp(it->second->mapname, tempbuff)) {
|
||
|
if (it->second->cacheType == cacheType)
|
||
|
return it->second;
|
||
|
else
|
||
|
it++;
|
||
|
}
|
||
|
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
data7 *findDNSEntry(char *key, MYBYTE dnsType) {
|
||
|
char tempbuff[512];
|
||
|
//printf("finding %u=%s\n",ind,key);
|
||
|
auto it = dnsCache[currentInd].find(setMapName(tempbuff, key, dnsType));
|
||
|
|
||
|
if (it != dnsCache[currentInd].end() && it->second)
|
||
|
return it->second;
|
||
|
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
data7 *findQueue(const char *key) {
|
||
|
//printf("finding %u=%s\n",ind,key);
|
||
|
auto it = dnsCache[currentInd].find(key);
|
||
|
|
||
|
if (it != dnsCache[currentInd].end() && it->second->cacheType == CTYPE_QUEUE)
|
||
|
return it->second;
|
||
|
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
data7 *findDHCPEntry(char *key) {
|
||
|
//printf("finding %u=%s\n",ind,key);
|
||
|
myLower(key);
|
||
|
auto it = dhcpCache.find(key);
|
||
|
|
||
|
if (it != dhcpCache.end() && it->second)
|
||
|
return it->second;
|
||
|
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
void addDNSEntry(data7 *entry) {
|
||
|
myLower(entry->mapname);
|
||
|
dnsCache[currentInd].insert(pair<string, data7 *>(entry->mapname, entry));
|
||
|
|
||
|
if (entry->expiry && entry->expiry < MY_MAX_TIME)
|
||
|
dnsAge[currentInd].insert(pair<time_t, data7 *>(entry->expiry, entry));
|
||
|
}
|
||
|
|
||
|
char *cloneString(char *string) {
|
||
|
char *s = (char *)calloc(1, strlen(string) + 1);
|
||
|
|
||
|
if (s)
|
||
|
strcpy(s, string);
|
||
|
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
MYDWORD getSerial(char *zone) {
|
||
|
char tempbuff[512];
|
||
|
char logBuff[256];
|
||
|
char ipbuff[32];
|
||
|
MYDWORD serial1 = 0;
|
||
|
data5 req;
|
||
|
memset(&req, 0, sizeof(data5));
|
||
|
req.remote.sin_family = AF_INET;
|
||
|
req.remote.sin_port = htons(IPPORT_DNS);
|
||
|
timeval tv1 {};
|
||
|
fd_set readfds1;
|
||
|
|
||
|
if (cfig.replication == 2)
|
||
|
req.remote.sin_addr.s_addr = cfig.zoneServers[0];
|
||
|
else
|
||
|
req.remote.sin_addr.s_addr = cfig.zoneServers[1];
|
||
|
|
||
|
req.sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||
|
req.dnsp = (dnsPacket *)req.raw;
|
||
|
req.dnsp->header.qdcount = htons(1);
|
||
|
req.dnsp->header.rd = false;
|
||
|
req.dnsp->header.xid = (t % USHRT_MAX);
|
||
|
req.dp = &req.dnsp->data;
|
||
|
req.dp += pQu(req.dp, zone);
|
||
|
req.dp += pUShort(req.dp, DNS_TYPE_SOA);
|
||
|
req.dp += pUShort(req.dp, DNS_CLASS_IN);
|
||
|
req.bytes = (int)(req.dp - req.raw);
|
||
|
//pUShort(req.raw, req.bytes - 2);
|
||
|
|
||
|
if ((req.bytes = (int)sendto(req.sock, req.raw, req.bytes, 0, (sockaddr *)&req.remote, sizeof(req.remote))) <= 0) {
|
||
|
closesocket(req.sock);
|
||
|
sprintf(logBuff, "Failed to send request to Primary Server %s", IP2String(ipbuff, req.remote.sin_addr.s_addr));
|
||
|
logDNSMess(logBuff, 1);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
FD_ZERO(&readfds1);
|
||
|
tv1.tv_sec = 3;
|
||
|
tv1.tv_usec = 0;
|
||
|
FD_SET(req.sock, &readfds1);
|
||
|
select(USHRT_MAX, &readfds1, nullptr, nullptr, &tv1);
|
||
|
|
||
|
if (FD_ISSET(req.sock, &readfds1)) {
|
||
|
req.sockLen = sizeof(req.remote);
|
||
|
req.bytes = (int)recvfrom(req.sock, req.raw, sizeof(req.raw), 0, (sockaddr *)&req.remote, &req.sockLen);
|
||
|
|
||
|
if (req.bytes > 0 && !req.dnsp->header.rcode && req.dnsp->header.qr && ntohs(req.dnsp->header.ancount)) {
|
||
|
req.dp = &req.dnsp->data;
|
||
|
|
||
|
for (int j = 1; j <= ntohs(req.dnsp->header.qdcount); j++) {
|
||
|
req.dp += fQu(tempbuff, req.dnsp, req.dp);
|
||
|
req.dp += 4;
|
||
|
}
|
||
|
|
||
|
for (int i = 1; i <= ntohs(req.dnsp->header.ancount); i++) {
|
||
|
req.dp += fQu(tempbuff, req.dnsp, req.dp);
|
||
|
req.dnsType = fUShort(req.dp);
|
||
|
req.dp += 2;//type
|
||
|
req.qclass = fUShort(req.dp);
|
||
|
req.dp += 2;//class
|
||
|
fUInt(req.dp);
|
||
|
req.dp += 4;//ttl
|
||
|
req.dp += 2;//datalength
|
||
|
|
||
|
if (req.dnsType == DNS_TYPE_SOA) {
|
||
|
req.dp += fQu(tempbuff, req.dnsp, req.dp);
|
||
|
req.dp += fQu(tempbuff, req.dnsp, req.dp);
|
||
|
serial1 = fUInt(req.dp);
|
||
|
}
|
||
|
}
|
||
|
closesocket(req.sock);
|
||
|
return serial1;
|
||
|
} else {
|
||
|
closesocket(req.sock);
|
||
|
//sprintf(logBuff, "Zone %s not found on Primary Server %s", zone, IP2String(ipbuff, req.remote.sin_addr.s_addr));
|
||
|
//logDNSMess(logBuff, 1);
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
closesocket(req.sock);
|
||
|
sprintf(logBuff, "Failed to contact the Primary Server %s", IP2String(ipbuff, req.remote.sin_addr.s_addr));
|
||
|
logDNSMess(logBuff, 1);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
void sendServerName() {
|
||
|
errno = 0;
|
||
|
data5 req;
|
||
|
memset(&req, 0, sizeof(data5));
|
||
|
req.remote.sin_family = AF_INET;
|
||
|
req.remote.sin_port = htons(IPPORT_DNS);
|
||
|
req.remote.sin_addr.s_addr = cfig.zoneServers[0];
|
||
|
|
||
|
timeval tv1{};
|
||
|
fd_set readfds1;
|
||
|
|
||
|
req.sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||
|
req.dnsp = (dnsPacket *)req.raw;
|
||
|
req.dnsp->header.opcode = OPCODE_DYNAMIC_UPDATE;
|
||
|
req.dnsp->header.qr = true;
|
||
|
req.dnsp->header.zcount = htons(1);
|
||
|
req.dnsp->header.prcount = htons(1);
|
||
|
req.dnsp->header.xid = (t % USHRT_MAX);
|
||
|
req.dp = &req.dnsp->data;
|
||
|
req.dp += pQu(req.dp, cfig.zone);
|
||
|
req.dp += pUShort(req.dp, DNS_TYPE_SOA);
|
||
|
req.dp += pUShort(req.dp, DNS_CLASS_IN);
|
||
|
req.dp += pQu(req.dp, cfig.servername_fqn);
|
||
|
req.dp += pUShort(req.dp, DNS_TYPE_A);
|
||
|
req.dp += pUShort(req.dp, DNS_CLASS_IN);
|
||
|
req.dp += pUInt(req.dp, 0);
|
||
|
req.dp += pUShort(req.dp, 4);
|
||
|
req.dp += pIP(req.dp, cfig.zoneServers[1]);
|
||
|
req.bytes = req.dp - req.raw;
|
||
|
//pUShort(req.raw, req.bytes - 2);
|
||
|
|
||
|
if ((req.bytes = (int)sendto(req.sock, req.raw, req.bytes, 0, (sockaddr *)&req.remote, sizeof(req.remote))) <= 0) {
|
||
|
closesocket(req.sock);
|
||
|
}
|
||
|
|
||
|
FD_ZERO(&readfds1);
|
||
|
tv1.tv_sec = 5;
|
||
|
tv1.tv_usec = 0;
|
||
|
FD_SET(req.sock, &readfds1);
|
||
|
select(USHRT_MAX, &readfds1, nullptr, nullptr, &tv1);
|
||
|
|
||
|
if (FD_ISSET(req.sock, &readfds1)) {
|
||
|
req.sockLen = sizeof(req.remote);
|
||
|
req.bytes = recvfrom(req.sock, req.raw, sizeof(req.raw), 0, (sockaddr *)&req.remote, &req.sockLen);
|
||
|
}
|
||
|
|
||
|
closesocket(req.sock);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
MYWORD recvTcpDnsMess(char *target, SOCKET sock, MYWORD targetSize) {
|
||
|
timeval tv1 {};
|
||
|
fd_set readfds1;
|
||
|
|
||
|
FD_ZERO(&readfds1);
|
||
|
FD_SET(sock, &readfds1);
|
||
|
tv1.tv_sec = 5;
|
||
|
tv1.tv_usec = 0;
|
||
|
|
||
|
if (select(sock + 1, &readfds1, nullptr, nullptr, &tv1)) {
|
||
|
errno = 0;
|
||
|
auto chunk = (int)recv(sock, target, 2, 0);
|
||
|
//errno = WSAGetLastError();
|
||
|
|
||
|
if (!errno && chunk == 2) {
|
||
|
char *ptr;
|
||
|
MYWORD rcd = chunk;
|
||
|
MYWORD bytes = fUShort(target) + rcd;
|
||
|
|
||
|
if (bytes > targetSize - 2)
|
||
|
return 0;
|
||
|
|
||
|
while (rcd < bytes) {
|
||
|
FD_ZERO(&readfds1);
|
||
|
FD_SET(sock, &readfds1);
|
||
|
tv1.tv_sec = 5;
|
||
|
tv1.tv_usec = 0;
|
||
|
|
||
|
if (select(sock + 1, &readfds1, nullptr, nullptr, &tv1)) {
|
||
|
errno = 0;
|
||
|
ptr = target + rcd;
|
||
|
chunk = (int)recv(sock, ptr, bytes - rcd, 0);
|
||
|
//errno = WSAGetLastError();
|
||
|
|
||
|
if (chunk <= 0 || errno)
|
||
|
return 0;
|
||
|
else
|
||
|
rcd += chunk;
|
||
|
} else
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
return rcd;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void emptyCache(MYBYTE ind) {
|
||
|
char logBuff[256];
|
||
|
data7 *cache = nullptr;
|
||
|
|
||
|
//sprintf(logBuff, "Emptying cache[%d] Start %d=%d",ind, dnsCache[ind].size(), dnsAge[ind].size());
|
||
|
//logMess(logBuff, 2);
|
||
|
|
||
|
cfig.mxCount[ind] = 0;
|
||
|
dnsAge[ind].clear();
|
||
|
auto p = dnsCache[ind].begin();
|
||
|
|
||
|
while (p != dnsCache[ind].end()) {
|
||
|
cache = p->second;
|
||
|
dnsCache[ind].erase(p);
|
||
|
free(cache);
|
||
|
p = dnsCache[ind].begin();
|
||
|
}
|
||
|
|
||
|
dnsCache[ind].clear();
|
||
|
}
|
||
|
|
||
|
void *checkZone(void *lpParam) {
|
||
|
char ipbuff[16];
|
||
|
char logBuff[256];
|
||
|
|
||
|
auto *magin = (data18 *)lpParam;
|
||
|
sleep(cfig.refresh);
|
||
|
|
||
|
while (kRunning) {
|
||
|
// //if (!dhcpService && !findDNSEntry(IP2String(ipbuff, htonl(cfig.zoneServers[1])), DNS_TYPE_PTR))
|
||
|
// if (!dhcpService)
|
||
|
// sendServerName();
|
||
|
|
||
|
MYBYTE updateInd = !magin->currentInd;
|
||
|
emptyCache(updateInd);
|
||
|
sprintf(logBuff, "Checking Serial from Primary Server %s", IP2String(ipbuff, cfig.zoneServers[0]));
|
||
|
logDNSMess(logBuff, 2);
|
||
|
|
||
|
MYDWORD serial1 = getSerial(cfig.zone);
|
||
|
MYDWORD serial2 = 0;
|
||
|
|
||
|
if (serial1)
|
||
|
serial2 = getSerial(cfig.authority);
|
||
|
|
||
|
if (!serial1 || !serial2) {
|
||
|
//cfig.dnsRepl = 0;
|
||
|
//cfig.dhcpRepl = 0;
|
||
|
sprintf(logBuff, "Failed to get SOA from Primary Server, waiting %i seconds to retry", cfig.retry);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
sleep(cfig.retry);
|
||
|
continue;
|
||
|
} else if (cfig.serial1 && cfig.serial1 == serial1 && cfig.serial2 && cfig.serial2 == serial2) {
|
||
|
if (cfig.refresh > (MYDWORD)(MY_MAX_TIME - t))
|
||
|
cfig.dnsRepl = MY_MAX_TIME;
|
||
|
else
|
||
|
cfig.dnsRepl = t + cfig.refresh + cfig.retry + cfig.retry;
|
||
|
|
||
|
if (cfig.expire > (MYDWORD)(MY_MAX_TIME - t))
|
||
|
cfig.expireTime = MY_MAX_TIME;
|
||
|
else
|
||
|
cfig.expireTime = t + cfig.expire;
|
||
|
|
||
|
sprintf(logBuff, "Zone Refresh not required");
|
||
|
logDNSMess(logBuff, 2);
|
||
|
sleep(cfig.refresh);
|
||
|
} else {
|
||
|
//WaitForSingleObject(rEvent, INFINITE);
|
||
|
serial1 = getZone(updateInd, cfig.zone);
|
||
|
sleep(5);
|
||
|
|
||
|
if (serial1)
|
||
|
serial2 = getZone(updateInd, cfig.authority);
|
||
|
//SetEvent(rEvent);
|
||
|
|
||
|
if (!serial1 || !serial2) {
|
||
|
sprintf(logBuff, "Waiting %u seconds to retry", cfig.retry);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
sleep(cfig.retry);
|
||
|
} else {
|
||
|
if (cfig.refresh > (MYDWORD)(MY_MAX_TIME - t))
|
||
|
cfig.dnsRepl = MY_MAX_TIME;
|
||
|
else
|
||
|
cfig.dnsRepl = t + cfig.refresh + cfig.retry + cfig.retry;
|
||
|
|
||
|
magin->currentInd = updateInd;
|
||
|
magin->done = true;
|
||
|
cfig.serial1 = serial1;
|
||
|
cfig.serial2 = serial2;
|
||
|
|
||
|
if (cfig.expire > (MYDWORD)(MY_MAX_TIME - t))
|
||
|
cfig.expireTime = MY_MAX_TIME;
|
||
|
else
|
||
|
cfig.expireTime = t + cfig.expire;
|
||
|
|
||
|
sleep(cfig.refresh);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pthread_exit(nullptr);
|
||
|
}
|
||
|
|
||
|
FILE *pullZone(SOCKET sock) {
|
||
|
char target[4096];
|
||
|
timeval tv1 {};
|
||
|
fd_set readfds1;
|
||
|
FILE *f = fopen(tempFile, "wb");
|
||
|
|
||
|
if (f) {
|
||
|
fclose(f);
|
||
|
f = fopen(tempFile, "ab");
|
||
|
} else {
|
||
|
closesocket(sock);
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
while (true) {
|
||
|
FD_ZERO(&readfds1);
|
||
|
FD_SET(sock, &readfds1);
|
||
|
tv1.tv_sec = 10;
|
||
|
tv1.tv_usec = 0;
|
||
|
|
||
|
if (select((sock + 1), &readfds1, nullptr, nullptr, &tv1) > 0) {
|
||
|
errno = 0;
|
||
|
auto bytes = recv(sock, target, sizeof(target), 0);
|
||
|
//errno = WSAGetLastError();
|
||
|
|
||
|
if (errno) {
|
||
|
closesocket(sock);
|
||
|
fclose(f);
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
if (bytes <= 0)
|
||
|
break;
|
||
|
|
||
|
if (bytes != fwrite(target, 1, bytes, f)) {
|
||
|
closesocket(sock);
|
||
|
fclose(f);
|
||
|
return nullptr;
|
||
|
}
|
||
|
} else {
|
||
|
break;
|
||
|
//closesocket(sock);
|
||
|
//fclose(f);
|
||
|
//return nullptr;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
closesocket(sock);
|
||
|
fclose(f);
|
||
|
f = fopen(tempFile, "rb");
|
||
|
return f;
|
||
|
}
|
||
|
|
||
|
MYDWORD getZone(MYBYTE ind, char *zone) {
|
||
|
data71 lump {};
|
||
|
char tempbuff[512];
|
||
|
char ipbuff[16];
|
||
|
char logBuff[512];
|
||
|
char localhost[] = "localhost";
|
||
|
char localhost_ip[] = "1.0.0.127";
|
||
|
MYDWORD serial1 = 0;
|
||
|
MYDWORD serial2 = 0;
|
||
|
MYDWORD hostExpiry = 0;
|
||
|
MYDWORD refresh = 0;
|
||
|
MYDWORD retry = 0;
|
||
|
MYDWORD expire = 0;
|
||
|
MYDWORD expiry;
|
||
|
MYDWORD minimum = 0;
|
||
|
int added = 0;
|
||
|
char *data;
|
||
|
char *dp;
|
||
|
MYDWORD ip;
|
||
|
data5 req;
|
||
|
data7 *cache = nullptr;
|
||
|
|
||
|
memset(&lump, 0, sizeof(data71));
|
||
|
lump.cacheType = CTYPE_LOCALHOST_A;
|
||
|
lump.dnsType = DNS_TYPE_A;
|
||
|
lump.mapname = localhost;
|
||
|
cache = createCache(&lump);
|
||
|
|
||
|
if (cache) {
|
||
|
cache->ip = ntohl(inet_addr(localhost_ip));
|
||
|
cache->expiry = MY_MAX_TIME;
|
||
|
dnsCache[ind].insert(pair<string, data7 *>(cache->mapname, cache));
|
||
|
}
|
||
|
|
||
|
memset(&lump, 0, sizeof(data71));
|
||
|
lump.cacheType = CTYPE_LOCALHOST_PTR;
|
||
|
lump.dnsType = DNS_TYPE_PTR;
|
||
|
lump.mapname = localhost_ip;
|
||
|
lump.hostname = localhost;
|
||
|
cache = createCache(&lump);
|
||
|
|
||
|
if (cache) {
|
||
|
cache->expiry = MY_MAX_TIME;
|
||
|
dnsCache[ind].insert(pair<string, data7 *>(cache->mapname, cache));
|
||
|
}
|
||
|
|
||
|
memset(&req, 0, sizeof(data5));
|
||
|
req.sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||
|
|
||
|
if (req.sock == INVALID_SOCKET) {
|
||
|
sprintf(logBuff, "Failed to Create Socket, Zone Transfer Failed");
|
||
|
logDNSMess(logBuff, 1);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
req.addr.sin_family = AF_INET;
|
||
|
req.addr.sin_addr.s_addr = cfig.zoneServers[1];
|
||
|
req.addr.sin_port = 0;
|
||
|
|
||
|
int nRet = bind(req.sock, (sockaddr *)&req.addr, sizeof(req.addr));
|
||
|
|
||
|
if (nRet == SOCKET_ERROR) {
|
||
|
closesocket(req.sock);
|
||
|
sprintf(logBuff,
|
||
|
"Error: Interface %s not ready, Zone Transfer Failed",
|
||
|
IP2String(ipbuff, req.addr.sin_addr.s_addr));
|
||
|
logDNSMess(logBuff, 1);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
req.remote.sin_family = AF_INET;
|
||
|
req.remote.sin_port = htons(IPPORT_DNS);
|
||
|
req.remote.sin_addr.s_addr = cfig.zoneServers[0];
|
||
|
|
||
|
req.sockLen = sizeof(req.remote);
|
||
|
|
||
|
if (connect(req.sock, (sockaddr *)&req.remote, req.sockLen) >= 0) {
|
||
|
req.dp = req.raw;
|
||
|
req.dp += 2;
|
||
|
req.dnsp = (dnsPacket *)req.dp;
|
||
|
req.dnsp->header.qdcount = htons(1);
|
||
|
req.dnsp->header.xid = (t % USHRT_MAX);
|
||
|
req.dp = &req.dnsp->data;
|
||
|
req.dp += pQu(req.dp, zone);
|
||
|
req.dp += pUShort(req.dp, DNS_TYPE_AXFR);
|
||
|
req.dp += pUShort(req.dp, DNS_CLASS_IN);
|
||
|
req.bytes = (int)(req.dp - req.raw);
|
||
|
pUShort(req.raw, req.bytes - 2);
|
||
|
|
||
|
if (send(req.sock, req.raw, req.bytes, 0) < req.bytes) {
|
||
|
closesocket(req.sock);
|
||
|
sprintf(logBuff,
|
||
|
"Failed to contact Primary Server %s, Zone Transfer Failed",
|
||
|
IP2String(ipbuff, req.remote.sin_addr.s_addr));
|
||
|
logDNSMess(logBuff, 1);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
FILE *f = pullZone(req.sock);
|
||
|
|
||
|
if (!f)
|
||
|
return 0;
|
||
|
|
||
|
while (kRunning && !serial2) {
|
||
|
req.bytes = (int)fread(req.raw, 1, 2, f);
|
||
|
|
||
|
if (req.bytes != 2)
|
||
|
break;
|
||
|
|
||
|
MYWORD pktSize = fUShort(req.raw);
|
||
|
|
||
|
req.bytes = (int)fread(req.raw, 1, pktSize, f);
|
||
|
|
||
|
if ((MYWORD)req.bytes != pktSize) {
|
||
|
fclose(f);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
req.dnsp = (dnsPacket *)(req.raw);
|
||
|
req.dp = &req.dnsp->data;
|
||
|
char *dataend = req.raw + pktSize;
|
||
|
|
||
|
if (req.dnsp->header.rcode) {
|
||
|
sprintf(
|
||
|
logBuff, "Primary Server %s, zone %s refused", IP2String(ipbuff, req.remote.sin_addr.s_addr), zone);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
fclose(f);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (!req.dnsp->header.qr || !ntohs(req.dnsp->header.ancount)) {
|
||
|
fclose(f);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
for (int j = 1; j <= ntohs(req.dnsp->header.qdcount); j++) {
|
||
|
req.dp += fQu(req.query, req.dnsp, req.dp);
|
||
|
req.dp += 4;
|
||
|
}
|
||
|
|
||
|
for (int i = 1; i <= ntohs(req.dnsp->header.ancount); i++) {
|
||
|
//char *dp = req.dp;
|
||
|
req.dp += fQu(req.mapname, req.dnsp, req.dp);
|
||
|
|
||
|
if (!req.mapname[0]) {
|
||
|
fclose(f);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
//sprintf(logBuff, "%u=%s\n", pktSize, req.mapname);
|
||
|
//logMess(logBuff, 2);
|
||
|
|
||
|
req.dnsType = fUShort(req.dp);
|
||
|
req.dp += 2;//type
|
||
|
req.qclass = fUShort(req.dp);
|
||
|
req.dp += 2;//class
|
||
|
expiry = fUInt(req.dp);
|
||
|
req.dp += 4;//ttl
|
||
|
int dataSize = fUShort(req.dp);
|
||
|
req.dp += 2;//datalength
|
||
|
data = req.dp;
|
||
|
req.dp += dataSize;
|
||
|
|
||
|
switch (req.dnsType) {
|
||
|
case DNS_TYPE_SOA:
|
||
|
|
||
|
data += fQu(req.cname, req.dnsp, data);
|
||
|
data += fQu(tempbuff, req.dnsp, data);
|
||
|
|
||
|
if (!cfig.nsP[0])
|
||
|
strcpy(cfig.nsP, req.cname);
|
||
|
|
||
|
if (!serial1) {
|
||
|
hostExpiry = expiry;
|
||
|
serial1 = fUInt(data);
|
||
|
data += 4;
|
||
|
refresh = fUInt(data);
|
||
|
data += 4;
|
||
|
retry = fUInt(data);
|
||
|
data += 4;
|
||
|
expire = fUInt(data);
|
||
|
data += 4;
|
||
|
minimum = fUInt(data);
|
||
|
data += 4;
|
||
|
added++;
|
||
|
} else if (!serial2)
|
||
|
serial2 = fUInt(data);
|
||
|
|
||
|
break;
|
||
|
|
||
|
case DNS_TYPE_A:
|
||
|
|
||
|
ip = fIP(data);
|
||
|
makeLocal(req.mapname);
|
||
|
memset(&lump, 0, sizeof(data71));
|
||
|
lump.cacheType = CTYPE_LOCAL_A;
|
||
|
lump.dnsType = DNS_TYPE_A;
|
||
|
lump.mapname = req.mapname;
|
||
|
cache = createCache(&lump);
|
||
|
|
||
|
if (cache) {
|
||
|
cache->ip = ip;
|
||
|
cache->expiry = MY_MAX_TIME;
|
||
|
dnsCache[ind].insert(pair<string, data7 *>(cache->mapname, cache));
|
||
|
added++;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case DNS_TYPE_PTR:
|
||
|
|
||
|
myLower(req.mapname);
|
||
|
dp = strstr(req.mapname, arpa);
|
||
|
|
||
|
if (dp) {
|
||
|
*dp = 0;
|
||
|
fQu(req.cname, req.dnsp, data);
|
||
|
makeLocal(req.cname);
|
||
|
memset(&lump, 0, sizeof(data71));
|
||
|
lump.cacheType = CTYPE_LOCAL_PTR_AUTH;
|
||
|
lump.dnsType = DNS_TYPE_PTR;
|
||
|
lump.mapname = req.mapname;
|
||
|
lump.hostname = req.cname;
|
||
|
cache = createCache(&lump);
|
||
|
|
||
|
if (cache) {
|
||
|
cache->expiry = MY_MAX_TIME;
|
||
|
dnsCache[ind].insert(pair<string, data7 *>(cache->mapname, cache));
|
||
|
added++;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case DNS_TYPE_MX:
|
||
|
|
||
|
if (makeLocal(req.mapname) == QTYPE_A_ZONE) {
|
||
|
cfig.mxServers[ind][cfig.mxCount[ind]].pref = fUShort(data);
|
||
|
data += sizeof(MYWORD);
|
||
|
fQu(req.cname, req.dnsp, data);
|
||
|
strcpy(cfig.mxServers[ind][cfig.mxCount[ind]].hostname, req.cname);
|
||
|
cfig.mxCount[ind]++;
|
||
|
added++;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case DNS_TYPE_NS:
|
||
|
|
||
|
fQu(req.cname, req.dnsp, data);
|
||
|
|
||
|
if (!cfig.nsS[0] && !strcasecmp(cfig.servername_fqn, req.cname))
|
||
|
strcpy(cfig.nsS, req.cname);
|
||
|
|
||
|
break;
|
||
|
|
||
|
case DNS_TYPE_CNAME:
|
||
|
|
||
|
makeLocal(req.mapname);
|
||
|
fQu(req.cname, req.dnsp, data);
|
||
|
memset(&lump, 0, sizeof(data71));
|
||
|
|
||
|
if (makeLocal(req.cname) == QTYPE_A_EXT)
|
||
|
lump.cacheType = CTYPE_EXT_CNAME;
|
||
|
else
|
||
|
lump.cacheType = CTYPE_LOCAL_CNAME;
|
||
|
|
||
|
lump.dnsType = DNS_TYPE_A;
|
||
|
lump.mapname = req.mapname;
|
||
|
lump.hostname = req.cname;
|
||
|
cache = createCache(&lump);
|
||
|
|
||
|
//sprintf(logBuff, "%s=%s=%u=%s=%s", req.mapname, req.cname, cache->mapname[0], &cache->mapname[1], cache->hostname);
|
||
|
//logDNSMess(logBuff, 2);
|
||
|
|
||
|
if (cache) {
|
||
|
dnsCache[ind].insert(pair<string, data7 *>(cache->mapname, cache));
|
||
|
cache->expiry = MY_MAX_TIME;
|
||
|
added++;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (req.dp != dataend) {
|
||
|
fclose(f);
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fclose(f);
|
||
|
|
||
|
if (serial1 && serial1 == serial2 && hostExpiry) {
|
||
|
if (cfig.replication == 2) {
|
||
|
cfig.lease = hostExpiry;
|
||
|
cfig.refresh = refresh;
|
||
|
cfig.retry = retry;
|
||
|
cfig.expire = expire;
|
||
|
cfig.minimum = minimum;
|
||
|
}
|
||
|
|
||
|
//printf("Refresh ind %i serial %u size %i\n", ind, serial1, dnsCache[ind].size());
|
||
|
sprintf(logBuff, "Zone %s Transferred from Primary Server, %u RRs imported", zone, added);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
return serial1;
|
||
|
} else {
|
||
|
sprintf(logBuff,
|
||
|
"Primary Server %s, zone %s Invalid AXFR data",
|
||
|
IP2String(ipbuff, req.remote.sin_addr.s_addr),
|
||
|
zone);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
} else {
|
||
|
sprintf(logBuff,
|
||
|
"Failed to contact Primary Server %s, Zone Transfer Failed",
|
||
|
IP2String(ipbuff, req.remote.sin_addr.s_addr));
|
||
|
logDNSMess(logBuff, 1);
|
||
|
closesocket(req.sock);
|
||
|
return 0;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
bool getSecondary() {
|
||
|
char logBuff[256];
|
||
|
MYDWORD ip;
|
||
|
MYDWORD hostExpiry = 0;
|
||
|
MYDWORD expiry = 0;
|
||
|
char *data = nullptr;
|
||
|
char *dp = nullptr;
|
||
|
MYWORD rr = 0;
|
||
|
data5 req;
|
||
|
MYDWORD serial = 0;
|
||
|
|
||
|
memset(&req, 0, sizeof(data5));
|
||
|
req.sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||
|
|
||
|
if (req.sock == INVALID_SOCKET)
|
||
|
return false;
|
||
|
|
||
|
req.addr.sin_family = AF_INET;
|
||
|
req.addr.sin_addr.s_addr = cfig.zoneServers[0];
|
||
|
req.addr.sin_port = 0;
|
||
|
|
||
|
int nRet = bind(req.sock, (sockaddr *)&req.addr, sizeof(req.addr));
|
||
|
|
||
|
if (nRet == SOCKET_ERROR) {
|
||
|
closesocket(req.sock);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
req.remote.sin_family = AF_INET;
|
||
|
req.remote.sin_port = htons(IPPORT_DNS);
|
||
|
|
||
|
if (dhcpService && cfig.replication == 1)
|
||
|
req.remote.sin_addr.s_addr = cfig.zoneServers[1];
|
||
|
else
|
||
|
return false;
|
||
|
|
||
|
req.sockLen = sizeof(req.remote);
|
||
|
time_t local_t = time(nullptr);
|
||
|
|
||
|
if (connect(req.sock, (sockaddr *)&req.remote, req.sockLen) == 0) {
|
||
|
req.dp = req.raw;
|
||
|
req.dp += 2;
|
||
|
req.dnsp = (dnsPacket *)req.dp;
|
||
|
req.dnsp->header.qdcount = htons(1);
|
||
|
req.dnsp->header.xid = (local_t % USHRT_MAX);
|
||
|
req.dp = &req.dnsp->data;
|
||
|
req.dp += pQu(req.dp, cfig.authority);
|
||
|
req.dp += pUShort(req.dp, DNS_TYPE_AXFR);
|
||
|
req.dp += pUShort(req.dp, DNS_CLASS_IN);
|
||
|
req.bytes = (int)(req.dp - req.raw);
|
||
|
pUShort(req.raw, (req.bytes - 2));
|
||
|
|
||
|
if (send(req.sock, req.raw, req.bytes, 0) < req.bytes) {
|
||
|
closesocket(req.sock);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
FILE *f = pullZone(req.sock);
|
||
|
|
||
|
if (!f)
|
||
|
return false;
|
||
|
|
||
|
while (kRunning) {
|
||
|
req.bytes = (int)fread(req.raw, 1, 2, f);
|
||
|
|
||
|
if (req.bytes < 2)
|
||
|
break;
|
||
|
|
||
|
MYWORD pktSize = fUShort(req.raw);
|
||
|
req.bytes = (int)fread(req.raw, 1, pktSize, f);
|
||
|
|
||
|
if ((MYWORD)req.bytes != pktSize) {
|
||
|
fclose(f);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
req.dnsp = (dnsPacket *)(req.raw);
|
||
|
req.dp = &req.dnsp->data;
|
||
|
char *dataend = req.raw + pktSize;
|
||
|
|
||
|
if (req.dnsp->header.rcode) {
|
||
|
fclose(f);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (!req.dnsp->header.qr || !ntohs(req.dnsp->header.ancount)) {
|
||
|
fclose(f);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
for (int j = 1; j <= ntohs(req.dnsp->header.qdcount); j++) {
|
||
|
req.dp += fQu(req.query, req.dnsp, req.dp);
|
||
|
req.dp += 4;
|
||
|
}
|
||
|
|
||
|
for (int i = 1; i <= ntohs(req.dnsp->header.ancount); i++) {
|
||
|
//char *dp = req.dp;
|
||
|
req.dp += fQu(req.mapname, req.dnsp, req.dp);
|
||
|
|
||
|
if (!req.mapname[0]) {
|
||
|
fclose(f);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
req.dnsType = fUShort(req.dp);
|
||
|
req.dp += 2;//type
|
||
|
req.qclass = fUShort(req.dp);
|
||
|
req.dp += 2;//class
|
||
|
expiry = fUInt(req.dp);
|
||
|
req.dp += 4;//ttl
|
||
|
int dataSize = fUShort(req.dp);
|
||
|
req.dp += 2;//datalength
|
||
|
data = req.dp;
|
||
|
req.dp += dataSize;
|
||
|
|
||
|
if (req.dnsType == DNS_TYPE_PTR) {
|
||
|
myLower(req.mapname);
|
||
|
dp = strstr(req.mapname, arpa);
|
||
|
|
||
|
if (dp) {
|
||
|
*dp = 0;
|
||
|
ip = ntohl(inet_addr(req.mapname));
|
||
|
fQu(req.cname, req.dnsp, data);
|
||
|
makeLocal(req.cname);
|
||
|
|
||
|
auto p = dhcpCache.begin();
|
||
|
data7 *dhcpEntry = nullptr;
|
||
|
|
||
|
for (; p != dhcpCache.end(); p++) {
|
||
|
if ((dhcpEntry = p->second) && dhcpEntry->ip && dhcpEntry->hostname) {
|
||
|
if (ip == dhcpEntry->ip && !strcasecmp(req.cname, dhcpEntry->hostname)) {
|
||
|
if (expiry < (MYDWORD)(MY_MAX_TIME - local_t))
|
||
|
expiry += local_t;
|
||
|
else
|
||
|
expiry = MY_MAX_TIME;
|
||
|
|
||
|
add2Cache(req.cname, ip, expiry, CTYPE_LOCAL_A, CTYPE_LOCAL_PTR_AUTH);
|
||
|
rr++;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (req.dp != dataend) {
|
||
|
fclose(f);
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sprintf(logBuff, "%u RRs rebuild from Secondary Server", rr);
|
||
|
logDNSMess(logBuff, 2);
|
||
|
fclose(f);
|
||
|
return true;
|
||
|
} else {
|
||
|
closesocket(req.sock);
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void *init(void *lparam) {
|
||
|
char tempbuff[512];
|
||
|
char logBuff[256];
|
||
|
char ipbuff[32];
|
||
|
char raw[512];
|
||
|
char name[512];
|
||
|
char value[512];
|
||
|
FILE *f = nullptr;
|
||
|
|
||
|
memset(exeFile, 0, sizeof(exeFile));
|
||
|
char id[256];
|
||
|
sprintf(id, "/proc/%d/exe", getpid());
|
||
|
readlink(id, exeFile, PATH_MAX - 1);
|
||
|
exeFile[PATH_MAX - 1] = 0;
|
||
|
strcpy(filePATH, exeFile);
|
||
|
char *ptr = strrchr(filePATH, '/');
|
||
|
ptr++;
|
||
|
*ptr = 0;
|
||
|
|
||
|
if (!iniFile[0])
|
||
|
sprintf(iniFile, "%s%s", filePATH, "dualserver.ini");
|
||
|
|
||
|
if (dhcpService && !leaFile[0])
|
||
|
sprintf(leaFile, "%s%s", filePATH, "dualserver.state");
|
||
|
|
||
|
if (dhcpService && !icoFile[0])
|
||
|
sprintf(icoFile, "%s%s", filePATH, "dualserver.png");
|
||
|
|
||
|
if (!logFile[0])
|
||
|
sprintf(logFile, "%s%s", filePATH, "log/dualserver%Y%m%d.log");
|
||
|
|
||
|
if ((f = openSection("LOGGING", 1))) {
|
||
|
cfig.dnsLogLevel = 1;
|
||
|
cfig.dhcpLogLevel = 1;
|
||
|
tempbuff[0] = 0;
|
||
|
|
||
|
while (readSection(raw, f)) {
|
||
|
mySplit(name, value, raw, '=');
|
||
|
|
||
|
if (name[0] && value[0]) {
|
||
|
if (!strcasecmp(name, "DNSLogLevel")) {
|
||
|
if (!strcasecmp(value, "None"))
|
||
|
cfig.dnsLogLevel = 0;
|
||
|
else if (!strcasecmp(value, "Normal"))
|
||
|
cfig.dnsLogLevel = 1;
|
||
|
else if (!strcasecmp(value, "All"))
|
||
|
cfig.dnsLogLevel = 2;
|
||
|
else
|
||
|
sprintf(tempbuff, "Section [LOGGING], Invalid DNSLogLevel: %s", value);
|
||
|
} else if (!strcasecmp(name, "DHCPLogLevel")) {
|
||
|
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 DHCPLogLevel: %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])
|
||
|
logMess(logBuff, 1);
|
||
|
|
||
|
sprintf(logBuff, "%s Starting...", sVersion);
|
||
|
logMess(logBuff, 1);
|
||
|
} else
|
||
|
printf("%s Starting...", sVersion);
|
||
|
|
||
|
sleep(1);
|
||
|
|
||
|
if ((f = fopen(iniFile, "rt"))) {
|
||
|
fclose(f);
|
||
|
} else {
|
||
|
sprintf(logBuff, "Warning: file %s not found, defaults will be used", iniFile);
|
||
|
logMess(logBuff, 1);
|
||
|
}
|
||
|
|
||
|
if ((f = openSection("SERVICES", 1))) {
|
||
|
dhcpService = false;
|
||
|
dnsService = false;
|
||
|
|
||
|
while (readSection(raw, f)) {
|
||
|
if (!strcasecmp(raw, "DNS"))
|
||
|
dnsService = true;
|
||
|
else if (!strcasecmp(raw, "DHCP"))
|
||
|
dhcpService = true;
|
||
|
else {
|
||
|
sprintf(logBuff, "Section [SERVICES] invalid entry %s ignored", raw);
|
||
|
logMess(logBuff, 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!dhcpService && !dnsService) {
|
||
|
dhcpService = true;
|
||
|
dnsService = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (dnsService) {
|
||
|
sprintf(logBuff, "Starting DNS Service");
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
|
||
|
if (dhcpService) {
|
||
|
sprintf(logBuff, "Starting DHCP Service");
|
||
|
logMess(logBuff, 1);
|
||
|
}
|
||
|
|
||
|
sleep(1);
|
||
|
|
||
|
if (dnsService) {
|
||
|
if (cfig.dnsLogLevel == 2)
|
||
|
sprintf(logBuff, "DNS Logging: All");
|
||
|
else if (cfig.dnsLogLevel == 1)
|
||
|
sprintf(logBuff, "DNS Logging: Normal");
|
||
|
else
|
||
|
sprintf(logBuff, "DNS Logging: None");
|
||
|
|
||
|
logMess(logBuff, 1);
|
||
|
}
|
||
|
|
||
|
if (dhcpService) {
|
||
|
if (cfig.dhcpLogLevel >= 2)
|
||
|
sprintf(logBuff, "DHCP Logging: All");
|
||
|
else if (cfig.dhcpLogLevel == 1)
|
||
|
sprintf(logBuff, "DHCP Logging: Normal");
|
||
|
else
|
||
|
sprintf(logBuff, "DHCP Logging: None");
|
||
|
|
||
|
logDHCPMess(logBuff, 1);
|
||
|
|
||
|
f = fopen(icoFile, "rb+");
|
||
|
|
||
|
if (f) {
|
||
|
if (cfig.dhcpLogLevel >= 2 || verbatim)
|
||
|
logDHCPMess("icon file:", icoFile);
|
||
|
|
||
|
fseek(f, 0, SEEK_END);
|
||
|
icoSize = (int)ftell(f);
|
||
|
icoString = (char *)calloc(1, icoSize);
|
||
|
fseek(f, 0, SEEK_SET);
|
||
|
icoSize = (int)fread(icoString, 1, icoSize, f);
|
||
|
fclose(f);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (verbatim || cfig.dhcpLogLevel >= 2 || cfig.dnsLogLevel >= 2) {
|
||
|
logMess("exe file:", exeFile);
|
||
|
logMess("ini file:", iniFile);
|
||
|
logMess("log file:", logFile);
|
||
|
|
||
|
if (dhcpService)
|
||
|
logDHCPMess("state file:", leaFile);
|
||
|
}
|
||
|
|
||
|
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);
|
||
|
logMess(logBuff, 1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
cfig.lease = 36000;
|
||
|
|
||
|
if ((f = openSection("TIMINGS", 1))) {
|
||
|
while (readSection(raw, f)) {
|
||
|
mySplit(name, value, raw, '=');
|
||
|
|
||
|
if (name[0] && value[0]) {
|
||
|
if (strtol(value, nullptr, 10) || !strcasecmp(value, "0")) {
|
||
|
if (!strcasecmp(name, "AddressTime")) {
|
||
|
cfig.lease = strtol(value, nullptr, 10);
|
||
|
|
||
|
if (!cfig.lease)
|
||
|
cfig.lease = UINT_MAX;
|
||
|
} else if (!strcasecmp(name, "Refresh"))
|
||
|
cfig.refresh = strtol(value, nullptr, 10);
|
||
|
else if (!strcasecmp(name, "Retry"))
|
||
|
cfig.retry = strtol(value, nullptr, 10);
|
||
|
else if (!strcasecmp(name, "Expire"))
|
||
|
cfig.expire = strtol(value, nullptr, 10);
|
||
|
else if (!strcasecmp(name, "Minimum"))
|
||
|
cfig.minimum = strtol(value, nullptr, 10);
|
||
|
else if (!strcasecmp(name, "MinCacheTime"))
|
||
|
cfig.minCache = strtol(value, nullptr, 10);
|
||
|
else if (!strcasecmp(name, "MaxCacheTime"))
|
||
|
cfig.maxCache = strtol(value, nullptr, 10);
|
||
|
else {
|
||
|
sprintf(logBuff, "Section [TIMINGS], Invalid Entry: %s ignored", raw);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
} else {
|
||
|
sprintf(logBuff, "Section [TIMINGS], Invalid value: %s ignored", value);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
} else {
|
||
|
sprintf(logBuff, "Section [TIMINGS], Missing value, entry %s ignored", raw);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!cfig.refresh) {
|
||
|
cfig.refresh = cfig.lease / 10;
|
||
|
|
||
|
if (cfig.refresh > 3600)
|
||
|
cfig.refresh = 3600;
|
||
|
|
||
|
if (cfig.refresh < 300)
|
||
|
cfig.refresh = 300;
|
||
|
}
|
||
|
|
||
|
if (!cfig.retry || cfig.retry > cfig.refresh) {
|
||
|
cfig.retry = cfig.refresh / 10;
|
||
|
|
||
|
if (cfig.retry > 600)
|
||
|
cfig.retry = 600;
|
||
|
|
||
|
if (cfig.retry < 60)
|
||
|
cfig.retry = 60;
|
||
|
}
|
||
|
|
||
|
if (!cfig.expire) {
|
||
|
if (UINT_MAX / 24 > cfig.lease)
|
||
|
cfig.expire = 24 * cfig.lease;
|
||
|
else
|
||
|
cfig.expire = UINT_MAX;
|
||
|
}
|
||
|
|
||
|
if (!cfig.minimum)
|
||
|
cfig.minimum = cfig.retry;
|
||
|
|
||
|
if ((f = openSection("DOMAIN_NAME", 1))) {
|
||
|
while (readSection(raw, f)) {
|
||
|
mySplit(name, value, raw, '=');
|
||
|
|
||
|
if (name[0] && value[0]) {
|
||
|
data15 mask{};
|
||
|
data15 network_l{};
|
||
|
char left[64];
|
||
|
|
||
|
cfig.authority[0] = 0;
|
||
|
myLower(value);
|
||
|
mask.ip = 0;
|
||
|
network_l.ip = 0;
|
||
|
|
||
|
for (MYBYTE octateNum = 0; octateNum < 3; octateNum++) {
|
||
|
mySplit(left, value, value, '.');
|
||
|
if (left[0] == '0' || (strtol(left, nullptr, 10) && strtol(left, nullptr, 10) < 256)) {
|
||
|
for (int j = 2; j >= 0; j--) {
|
||
|
network_l.octate[j + 1] = network_l.octate[j];
|
||
|
mask.octate[j + 1] = mask.octate[j];
|
||
|
}
|
||
|
|
||
|
mask.octate[0] = UCHAR_MAX;
|
||
|
network_l.octate[0] = strtol(left, nullptr, 10);
|
||
|
strcat(cfig.authority, left);
|
||
|
strcat(cfig.authority, ".");
|
||
|
} else
|
||
|
break;
|
||
|
|
||
|
if (!strcasecmp(value, arpa + 1))
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (!strcasecmp(value, arpa + 1)) {
|
||
|
strcat(cfig.authority, arpa + 1);
|
||
|
cfig.aLen = strlen(cfig.authority);
|
||
|
calcRangeLimits(network_l.ip, mask.ip, &cfig.rangeStart, &cfig.rangeEnd);
|
||
|
cfig.authorized = 1;
|
||
|
} else {
|
||
|
sprintf(logBuff, "Warning: Invalid Domain Name (Part %s), ignored", cfig.authority);
|
||
|
cfig.aLen = 0;
|
||
|
cfig.authority[0] = 0;
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (chkQu(name)) {
|
||
|
strcpy(cfig.zone, name);
|
||
|
cfig.zLen = strlen(cfig.zone);
|
||
|
} else {
|
||
|
cfig.aLen = 0;
|
||
|
cfig.authority[0] = 0;
|
||
|
sprintf(logBuff, "Warning: Invalid Domain Name %s, ignored", raw);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (dnsService) {
|
||
|
if ((f = openSection("FORWARDING_SERVERS", 1))) {
|
||
|
char raw_l[512];
|
||
|
|
||
|
while (readSection(raw_l, f)) {
|
||
|
if (isIP(raw_l)) {
|
||
|
MYDWORD addr = inet_addr(raw_l);
|
||
|
addServer(cfig.specifiedDnsServers, MAX_SERVERS, addr);
|
||
|
} else {
|
||
|
sprintf(logBuff, "Section [FORWARDING_SERVERS] Invalid Entry: %s ignored", raw_l);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
cfig.fixedSocket = socket(AF_INET, SOCK_DGRAM, 0);
|
||
|
|
||
|
if (cfig.fixedSocket < 0) {
|
||
|
sprintf(logBuff, "Failed to create Socket");
|
||
|
logMess(logBuff, 1);
|
||
|
sleep(1);
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
getInterfaces(&network);
|
||
|
sprintf(cfig.servername_fqn, "%s.%s", cfig.servername, cfig.zone);
|
||
|
|
||
|
while (true) {
|
||
|
if ((f = openSection("ZONE_REPLICATION", 1))) {
|
||
|
int i = 2;
|
||
|
while (readSection(raw, f)) {
|
||
|
if (i < MAX_TCP_CLIENTS) {
|
||
|
if (!cfig.authorized) {
|
||
|
sprintf(
|
||
|
logBuff, "Section [ZONE_REPLICATION], Server is not an authority, entry %s ignored", raw);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
mySplit(name, value, raw, '=');
|
||
|
|
||
|
if (name[0] && value[0]) {
|
||
|
if (chkQu(name) && !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 if (!strcasecmp(name, "AXFRClient")) {
|
||
|
cfig.zoneServers[i] = inet_addr(value);
|
||
|
i++;
|
||
|
} else {
|
||
|
sprintf(logBuff, "Section [ZONE_REPLICATION] Invalid Entry: %s ignored", raw);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
} else {
|
||
|
sprintf(logBuff, "Section [ZONE_REPLICATION] Invalid Entry: %s ignored", raw);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
} else {
|
||
|
sprintf(logBuff, "Section [ZONE_REPLICATION], Missing value, entry %s ignored", raw);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!cfig.zoneServers[0] && !cfig.zoneServers[1])
|
||
|
break;
|
||
|
else if (!cfig.zoneServers[0] && cfig.zoneServers[1]) {
|
||
|
sprintf(logBuff, "Section [ZONE_REPLICATION] Missing Primary Server, stopping");
|
||
|
logDNSMess(logBuff, 1);
|
||
|
sleep(1);
|
||
|
exit(-1);
|
||
|
} else if (cfig.zoneServers[0] && !cfig.zoneServers[1]) {
|
||
|
sprintf(logBuff, "Section [ZONE_REPLICATION] Missing Secondary Server, stopping");
|
||
|
logDNSMess(logBuff, 1);
|
||
|
sleep(1);
|
||
|
exit(-1);
|
||
|
} else {
|
||
|
if (findServer(network.allServers, MAX_SERVERS, cfig.zoneServers[0])
|
||
|
&& findServer(network.allServers, MAX_SERVERS, cfig.zoneServers[1])) {
|
||
|
sprintf(logBuff,
|
||
|
"Section [ZONE_REPLICATION] Primary & Secondary should be Different Boxes, stopping");
|
||
|
logDNSMess(logBuff, 1);
|
||
|
sleep(1);
|
||
|
exit(-1);
|
||
|
} else if (findServer(network.allServers, MAX_SERVERS, cfig.zoneServers[0])) {
|
||
|
cfig.replication = 1;
|
||
|
break;
|
||
|
} else if (findServer(network.allServers, MAX_SERVERS, cfig.zoneServers[1])) {
|
||
|
cfig.replication = 2;
|
||
|
break;
|
||
|
} else {
|
||
|
sprintf(logBuff,
|
||
|
"Section [ZONE_REPLICATION] No Server IP not found on this Machine, waiting %u seconds",
|
||
|
cfig.retry);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sleep(cfig.retry);
|
||
|
getInterfaces(&network);
|
||
|
}
|
||
|
|
||
|
if (dhcpService) {
|
||
|
loadDHCP();
|
||
|
/*
|
||
|
for (int i = 0; i < cfig.rangeCount; i++)
|
||
|
{
|
||
|
char *logPtr = logBuff;
|
||
|
logPtr += sprintf(logPtr, "DHCP Range: ");
|
||
|
logPtr += sprintf(logPtr, "%s", IP2String(ipbuff, htonl(cfig.dhcpRanges[i].rangeStart)));
|
||
|
logPtr += sprintf(logPtr, "-%s", IP2String(ipbuff, htonl(cfig.dhcpRanges[i].rangeEnd)));
|
||
|
logPtr += sprintf(logPtr, "/%s", IP2String(ipbuff, cfig.dhcpRanges[i].mask));
|
||
|
logMess(logBuff, 1);
|
||
|
}
|
||
|
*/
|
||
|
if (cfig.replication) {
|
||
|
lockIP(cfig.zoneServers[0]);
|
||
|
lockIP(cfig.zoneServers[1]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (dnsService) {
|
||
|
if (FILE *fp = openSection("FORWARDING_SERVERS", 1)) {
|
||
|
char raw_l[512];
|
||
|
int i = 0;
|
||
|
|
||
|
while (readSection(raw_l, fp)) {
|
||
|
if (i < MAX_SERVERS) {
|
||
|
if (isIP(raw_l)) {
|
||
|
MYDWORD addr = inet_addr(raw_l);
|
||
|
if (addServer(cfig.specifiedDnsServers, MAX_SERVERS, addr))
|
||
|
i++;
|
||
|
} else {
|
||
|
sprintf(logBuff, "Section [FORWARDING_SERVERS] Invalid Entry: %s ignored", raw_l);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ((f = openSection("DNS_ALLOWED_HOSTS", 1))) {
|
||
|
int i = 0;
|
||
|
|
||
|
while (readSection(raw, f)) {
|
||
|
if (i < MAX_DNS_RANGES) {
|
||
|
MYDWORD rs = 0;
|
||
|
MYDWORD re = 0;
|
||
|
mySplit(name, value, raw, '-');
|
||
|
|
||
|
if (isIP(name) && isIP(value)) {
|
||
|
rs = htonl(inet_addr(name));
|
||
|
re = htonl(inet_addr(value));
|
||
|
} else if (isIP(name) && !value[0]) {
|
||
|
rs = htonl(inet_addr(name));
|
||
|
re = rs;
|
||
|
}
|
||
|
|
||
|
//printf("%u=%u\n", rs, re);
|
||
|
|
||
|
if (rs && re && rs <= re) {
|
||
|
cfig.dnsRanges[i].rangeStart = rs;
|
||
|
cfig.dnsRanges[i].rangeEnd = re;
|
||
|
i++;
|
||
|
} else {
|
||
|
sprintf(logBuff, "Section [DNS_ALLOWED_HOSTS] Invalid entry %s in ini file, ignored", raw);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (cfig.replication != 2 && (f = openSection("DNS_HOSTS", 1))) {
|
||
|
while (readSection(raw, f)) {
|
||
|
mySplit(name, value, raw, '=');
|
||
|
|
||
|
if (name[0] && value[0]) {
|
||
|
if (chkQu(name) && !isIP(name)) {
|
||
|
MYDWORD ip = inet_addr(value);
|
||
|
MYBYTE nameType = makeLocal(name);
|
||
|
bool ipLocal = isLocal(ip);
|
||
|
|
||
|
if (!strcasecmp(value, "0.0.0.0")) {
|
||
|
addHostNotFound(name);
|
||
|
continue;
|
||
|
} else if (!ip) {
|
||
|
sprintf(logBuff, "Section [DNS_HOSTS] Invalid Entry %s ignored", raw);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
switch (nameType) {
|
||
|
case QTYPE_A_ZONE:
|
||
|
case QTYPE_A_BARE:
|
||
|
case QTYPE_A_LOCAL:
|
||
|
add2Cache(name, ip, MY_MAX_TIME, CTYPE_STATIC_A_AUTH, 0);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
if (cfig.replication) {
|
||
|
sprintf(logBuff,
|
||
|
"Section [DNS_HOSTS] forward entry for %s not in Forward Zone, ignored",
|
||
|
raw);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
} else
|
||
|
add2Cache(name, ip, MY_MAX_TIME, CTYPE_STATIC_A_NAUTH, 0);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (ipLocal) {
|
||
|
add2Cache(name, ip, MY_MAX_TIME, 0, CTYPE_STATIC_PTR_AUTH);
|
||
|
holdIP(ip);
|
||
|
} else if (cfig.replication) {
|
||
|
sprintf(
|
||
|
logBuff, "Section [DNS_HOSTS] reverse entry for %s not in Reverse Zone, ignored", raw);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
} else
|
||
|
add2Cache(name, ip, MY_MAX_TIME, 0, CTYPE_STATIC_PTR_NAUTH);
|
||
|
} else {
|
||
|
sprintf(logBuff, "Section [DNS_HOSTS] Invalid Entry: %s ignored", raw);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
} else {
|
||
|
sprintf(logBuff, "Section [DNS_HOSTS], Missing value, entry %s ignored", raw);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (cfig.replication != 2 && (f = openSection("ALIASES", 1))) {
|
||
|
int i = 0;
|
||
|
|
||
|
while (readSection(raw, f)) {
|
||
|
mySplit(name, value, raw, '=');
|
||
|
|
||
|
if (name[0] && value[0]) {
|
||
|
MYBYTE nameType = makeLocal(name);
|
||
|
MYBYTE aliasType = makeLocal(value);
|
||
|
|
||
|
if (chkQu(name) && chkQu(value) && strcasecmp(value, cfig.zone) != 0) {
|
||
|
if ((nameType == QTYPE_A_BARE || nameType == QTYPE_A_LOCAL || nameType == QTYPE_A_ZONE)) {
|
||
|
data7 *cache = findDNSEntry(name, DNS_TYPE_A);
|
||
|
|
||
|
if (!cache) {
|
||
|
memset(&g_lump, 0, sizeof(data71));
|
||
|
|
||
|
if ((aliasType == QTYPE_A_BARE || aliasType == QTYPE_A_LOCAL
|
||
|
|| aliasType == QTYPE_A_ZONE))
|
||
|
g_lump.cacheType = CTYPE_LOCAL_CNAME;
|
||
|
else
|
||
|
g_lump.cacheType = CTYPE_EXT_CNAME;
|
||
|
|
||
|
g_lump.dnsType = DNS_TYPE_A;
|
||
|
g_lump.mapname = name;
|
||
|
g_lump.hostname = value;
|
||
|
cache = createCache(&g_lump);
|
||
|
|
||
|
if (cache) {
|
||
|
cache->expiry = MY_MAX_TIME;
|
||
|
addDNSEntry(cache);
|
||
|
}
|
||
|
} else {
|
||
|
sprintf(logBuff, "Section [ALIASES] duplicate entry %s ignored", raw);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
} else {
|
||
|
sprintf(
|
||
|
logBuff, "Section [ALIASES] alias %s should be bare/local name, entry ignored", name);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
} else {
|
||
|
sprintf(logBuff, "Section [ALIASES] Invalid Entry: %s ignored", raw);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
} else {
|
||
|
sprintf(logBuff, "Section [ALIASES], Missing value, entry %s ignored", raw);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (cfig.replication != 2 && (f = openSection("MAIL_SERVERS", 1))) {
|
||
|
cfig.mxCount[0] = 0;
|
||
|
|
||
|
while (readSection(raw, f)) {
|
||
|
if (cfig.mxCount[0] < MAX_SERVERS) {
|
||
|
mySplit(name, value, raw, '=');
|
||
|
if (name[0] && value[0]) {
|
||
|
if (chkQu(name) && strtol(value, nullptr, 10)) {
|
||
|
cfig.mxServers[0][cfig.mxCount[0]].pref = strtol(value, nullptr, 10);
|
||
|
cfig.mxServers[1][cfig.mxCount[0]].pref = strtol(value, nullptr, 10);
|
||
|
|
||
|
if (!strchr(name, '.')) {
|
||
|
strcat(name, ".");
|
||
|
strcat(name, cfig.zone);
|
||
|
}
|
||
|
|
||
|
strcpy(cfig.mxServers[0][cfig.mxCount[0]].hostname, name);
|
||
|
strcpy(cfig.mxServers[1][cfig.mxCount[0]].hostname, name);
|
||
|
cfig.mxCount[0]++;
|
||
|
} else {
|
||
|
sprintf(logBuff, "Section [MAIL_SERVERS] Invalid Entry: %s ignored", raw);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
} else {
|
||
|
sprintf(logBuff, "Section [MAIL_SERVERS], Missing value, entry %s ignored", raw);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
}
|
||
|
//cfig.mxCount[1] = cfig.mxCount[0];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ((f = openSection("CONDITIONAL_FORWARDERS", 1))) {
|
||
|
int i = 0;
|
||
|
|
||
|
while (readSection(raw, f)) {
|
||
|
if (i < MAX_COND_FORW) {
|
||
|
mySplit(name, value, raw, '=');
|
||
|
|
||
|
if (name[0] && value[0]) {
|
||
|
int j = 0;
|
||
|
|
||
|
for (; j < MAX_COND_FORW && cfig.dnsRoutes[j].zone[0]; j++) {
|
||
|
if (!strcasecmp(cfig.dnsRoutes[j].zone, name)) {
|
||
|
sprintf(logBuff,
|
||
|
"Section [CONDITIONAL_FORWARDERS], Duplicate Entry for Child Zone %s ignored",
|
||
|
raw);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (j < MAX_COND_FORW && !cfig.dnsRoutes[j].zone[0]) {
|
||
|
if (name[0] && chkQu(name) && value[0]) {
|
||
|
char *value1 = strchr(value, ',');
|
||
|
|
||
|
if (value1) {
|
||
|
*value1 = 0;
|
||
|
value1++;
|
||
|
|
||
|
MYDWORD ip = inet_addr(myTrim(value, value));
|
||
|
MYDWORD ip1 = inet_addr(myTrim(value1, value1));
|
||
|
|
||
|
if (isIP(value) && isIP(value1)) {
|
||
|
strcpy(cfig.dnsRoutes[i].zone, name);
|
||
|
cfig.dnsRoutes[i].zLen = strlen(cfig.dnsRoutes[i].zone);
|
||
|
cfig.dnsRoutes[i].dns[0] = ip;
|
||
|
cfig.dnsRoutes[i].dns[1] = ip1;
|
||
|
i++;
|
||
|
} else {
|
||
|
sprintf(
|
||
|
logBuff, "Section [CONDITIONAL_FORWARDERS] Invalid Entry: %s ignored", raw);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
} else {
|
||
|
MYDWORD ip = inet_addr(value);
|
||
|
|
||
|
if (isIP(value)) {
|
||
|
strcpy(cfig.dnsRoutes[i].zone, name);
|
||
|
cfig.dnsRoutes[i].zLen = strlen(cfig.dnsRoutes[i].zone);
|
||
|
cfig.dnsRoutes[i].dns[0] = ip;
|
||
|
i++;
|
||
|
} else {
|
||
|
sprintf(
|
||
|
logBuff, "Section [CONDITIONAL_FORWARDERS] Invalid Entry: %s ignored", raw);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
sprintf(logBuff, "Section [CONDITIONAL_FORWARDERS] Invalid Entry: %s ignored", raw);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
sprintf(logBuff, "Section [CONDITIONAL_FORWARDERS], Missing value, entry %s ignored", raw);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ((f = openSection("WILD_HOSTS", 1))) {
|
||
|
int i = 0;
|
||
|
|
||
|
while (readSection(raw, f)) {
|
||
|
if (i < MAX_WILD_HOSTS) {
|
||
|
mySplit(name, value, raw, '=');
|
||
|
|
||
|
if (name[0] && value[0]) {
|
||
|
if (chkQu(name) && (isIP(value) || !strcasecmp(value, "0.0.0.0"))) {
|
||
|
MYDWORD ip = inet_addr(value);
|
||
|
strcpy(cfig.wildHosts[i].wildcard, name);
|
||
|
myLower(cfig.wildHosts[i].wildcard);
|
||
|
cfig.wildHosts[i].ip = ip;
|
||
|
i++;
|
||
|
} else {
|
||
|
sprintf(logBuff, "Section [WILD_HOSTS] Invalid Entry: %s ignored", raw);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
} else {
|
||
|
sprintf(logBuff, "Section [WILD_HOSTS], Missing value, entry %s ignored", raw);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (cfig.replication == 2) {
|
||
|
// if (dhcpService)
|
||
|
// strcpy(cfig.nsS, cfig.servername_fqn);
|
||
|
|
||
|
while (kRunning) {
|
||
|
// //if (!dhcpService && !findDNSEntry(IP2String(ipbuff, htonl(cfig.zoneServers[1])), DNS_TYPE_PTR))
|
||
|
// if (!dhcpService)
|
||
|
// {
|
||
|
// sendServerName();
|
||
|
// sleep(1);
|
||
|
// }
|
||
|
|
||
|
MYDWORD serial1 = getSerial(cfig.zone);
|
||
|
MYDWORD serial2 = 0;
|
||
|
|
||
|
if (serial1)
|
||
|
serial2 = getSerial(cfig.authority);
|
||
|
|
||
|
if (serial1 && serial2) {
|
||
|
cfig.serial1 = getZone(0, cfig.zone);
|
||
|
sleep(5);
|
||
|
|
||
|
if (cfig.serial1)
|
||
|
cfig.serial2 = getZone(0, cfig.authority);
|
||
|
}
|
||
|
|
||
|
if (cfig.serial1 && cfig.serial2) {
|
||
|
if (cfig.refresh > (MYDWORD)(MY_MAX_TIME - t))
|
||
|
cfig.dnsRepl = MY_MAX_TIME;
|
||
|
else
|
||
|
cfig.dnsRepl = t + cfig.refresh + cfig.retry + cfig.retry;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
sprintf(logBuff, "Failed to get Zone(s) from Primary Server, waiting %d seconds to retry", cfig.retry);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
|
||
|
sleep(cfig.retry);
|
||
|
}
|
||
|
|
||
|
if (dhcpService) {
|
||
|
data7 *cache = nullptr;
|
||
|
auto p = dnsCache[currentInd].begin();
|
||
|
|
||
|
while (p != dnsCache[currentInd].end()) {
|
||
|
cache = p->second;
|
||
|
|
||
|
switch (cache->cacheType) {
|
||
|
case CTYPE_STATIC_A_AUTH:
|
||
|
holdIP(cache->ip);
|
||
|
break;
|
||
|
|
||
|
case CTYPE_STATIC_PTR_AUTH:
|
||
|
holdIP(htonl(inet_addr(cache->mapname)));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
p++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (cfig.expire > (MYDWORD)(MY_MAX_TIME - t))
|
||
|
cfig.expireTime = MY_MAX_TIME;
|
||
|
else
|
||
|
cfig.expireTime = t + cfig.expire;
|
||
|
|
||
|
g_magin.currentInd = 0;
|
||
|
g_magin.done = false;
|
||
|
|
||
|
pthread_t threadId;
|
||
|
pthread_attr_t attr;
|
||
|
pthread_attr_init(&attr);
|
||
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||
|
int errcode = pthread_create(&threadId, &attr, checkZone, &g_magin);
|
||
|
pthread_attr_destroy(&attr);
|
||
|
} else if (cfig.replication == 1) {
|
||
|
strcpy(cfig.nsP, cfig.servername_fqn);
|
||
|
findHost(cfig.nsS, cfig.zoneServers[1]);
|
||
|
|
||
|
if (cfig.nsS[0]) {
|
||
|
strcat(cfig.nsS, ".");
|
||
|
strcat(cfig.nsS, cfig.zone);
|
||
|
}
|
||
|
|
||
|
cfig.serial1 = t;
|
||
|
cfig.serial2 = t;
|
||
|
cfig.expireTime = MY_MAX_TIME;
|
||
|
|
||
|
if (dhcpService)
|
||
|
getSecondary();
|
||
|
} else {
|
||
|
strcpy(cfig.nsP, cfig.servername_fqn);
|
||
|
|
||
|
cfig.serial1 = t;
|
||
|
cfig.serial2 = t;
|
||
|
cfig.expireTime = MY_MAX_TIME;
|
||
|
char localhost[] = "localhost";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (dhcpService) {
|
||
|
if (cfig.replication) {
|
||
|
cfig.dhcpReplConn.sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||
|
|
||
|
if (cfig.dhcpReplConn.sock == INVALID_SOCKET) {
|
||
|
sprintf(logBuff, "Failed to Create DHCP Replication Socket");
|
||
|
logDHCPMess(logBuff, 1);
|
||
|
} else {
|
||
|
//printf("Socket %u\n", cfig.dhcpReplConn.sock);
|
||
|
|
||
|
if (cfig.replication == 1)
|
||
|
cfig.dhcpReplConn.server = cfig.zoneServers[0];
|
||
|
else
|
||
|
cfig.dhcpReplConn.server = cfig.zoneServers[1];
|
||
|
|
||
|
cfig.dhcpReplConn.addr.sin_family = AF_INET;
|
||
|
cfig.dhcpReplConn.addr.sin_addr.s_addr = cfig.dhcpReplConn.server;
|
||
|
cfig.dhcpReplConn.addr.sin_port = 0;
|
||
|
|
||
|
int nRet = bind(
|
||
|
cfig.dhcpReplConn.sock, (sockaddr *)&cfig.dhcpReplConn.addr, sizeof(struct sockaddr_in));
|
||
|
|
||
|
if (nRet == SOCKET_ERROR) {
|
||
|
cfig.dhcpReplConn.ready = false;
|
||
|
sprintf(logBuff, "DHCP Replication Server, Bind Failed");
|
||
|
logDHCPMess(logBuff, 1);
|
||
|
} else {
|
||
|
cfig.dhcpReplConn.port = IPPORT_DHCPS;
|
||
|
cfig.dhcpReplConn.loaded = true;
|
||
|
cfig.dhcpReplConn.ready = true;
|
||
|
|
||
|
data3 op{};
|
||
|
memset(&token, 0, sizeof(data9));
|
||
|
token.vp = token.dhcpp.vend_data;
|
||
|
token.messsize = sizeof(dhcp_packet);
|
||
|
|
||
|
token.remote.sin_port = htons(IPPORT_DHCPS);
|
||
|
token.remote.sin_family = AF_INET;
|
||
|
|
||
|
if (cfig.replication == 1)
|
||
|
token.remote.sin_addr.s_addr = cfig.zoneServers[1];
|
||
|
else if (cfig.replication == 2)
|
||
|
token.remote.sin_addr.s_addr = cfig.zoneServers[0];
|
||
|
|
||
|
token.dhcpp.header.bp_op = BOOTP_REQUEST;
|
||
|
token.dhcpp.header.bp_xid = t;
|
||
|
strcpy(token.dhcpp.header.bp_sname, cfig.servername);
|
||
|
token.dhcpp.header.bp_magic_num[0] = 99;
|
||
|
token.dhcpp.header.bp_magic_num[1] = 130;
|
||
|
token.dhcpp.header.bp_magic_num[2] = 83;
|
||
|
token.dhcpp.header.bp_magic_num[3] = 99;
|
||
|
|
||
|
op.opt_code = DHCP_OPTION_MESSAGETYPE;
|
||
|
op.size = 1;
|
||
|
op.value[0] = DHCP_MESS_INFORM;
|
||
|
pvdata(&token, &op);
|
||
|
|
||
|
if (dnsService) {
|
||
|
op.opt_code = DHCP_OPTION_DNS;
|
||
|
op.size = 4;
|
||
|
|
||
|
if (cfig.replication == 1)
|
||
|
pIP(op.value, cfig.zoneServers[0]);
|
||
|
else
|
||
|
pIP(op.value, cfig.zoneServers[1]);
|
||
|
|
||
|
pvdata(&token, &op);
|
||
|
}
|
||
|
|
||
|
//op.opt_code = DHCP_OPTION_HOSTNAME;
|
||
|
//op.size = strlen(cfig.servername);
|
||
|
//memcpy(op.value, cfig.servername, op.size);
|
||
|
//pvdata(&token, &op);
|
||
|
|
||
|
token.vp[0] = DHCP_OPTION_END;
|
||
|
token.vp++;
|
||
|
token.bytes = (int)(token.vp - (MYBYTE *)token.raw);
|
||
|
|
||
|
if (cfig.replication == 2) {
|
||
|
pthread_t threadId;
|
||
|
pthread_attr_t attr;
|
||
|
pthread_attr_init(&attr);
|
||
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||
|
int errcode = pthread_create(&threadId, &attr, sendToken, nullptr);
|
||
|
pthread_attr_destroy(&attr);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (cfig.lease >= MY_MAX_TIME)
|
||
|
sprintf(logBuff, "Default Lease: Infinity");
|
||
|
else
|
||
|
sprintf(logBuff, "Default Lease: %u (sec)", cfig.lease);
|
||
|
|
||
|
logMess(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);
|
||
|
|
||
|
logDNSMess(logBuff, 1);
|
||
|
|
||
|
if (dnsService) {
|
||
|
if (cfig.authorized)
|
||
|
sprintf(logBuff, "Authority for Zone: %s (%s)", cfig.zone, cfig.authority);
|
||
|
else
|
||
|
sprintf(logBuff, "Domain Name: %s", cfig.zone);
|
||
|
|
||
|
logDNSMess(logBuff, 1);
|
||
|
|
||
|
if (cfig.lease >= MY_MAX_TIME)
|
||
|
sprintf(logBuff, "Default Host Expiry: Infinity");
|
||
|
else
|
||
|
sprintf(logBuff, "Default Host Expiry: %u (sec)", cfig.lease);
|
||
|
|
||
|
logDNSMess(logBuff, 1);
|
||
|
|
||
|
if (cfig.replication) {
|
||
|
sprintf(logBuff, "Refresh: %u (sec)", cfig.refresh);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
sprintf(logBuff, "Retry: %u (sec)", cfig.retry);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
|
||
|
if (cfig.expire == UINT_MAX)
|
||
|
sprintf(logBuff, "Expire: Infinity");
|
||
|
else
|
||
|
sprintf(logBuff, "Expire: %u (sec)", cfig.expire);
|
||
|
|
||
|
logDNSMess(logBuff, 1);
|
||
|
sprintf(logBuff, "Min: %u (sec)", cfig.minimum);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < MAX_COND_FORW && cfig.dnsRoutes[i].dns[0]; i++) {
|
||
|
char temp[256];
|
||
|
|
||
|
if (!cfig.dnsRoutes[i].dns[1])
|
||
|
sprintf(logBuff,
|
||
|
"Conditional Forwarder: %s for %s",
|
||
|
IP2String(ipbuff, cfig.dnsRoutes[i].dns[0]),
|
||
|
cfig.dnsRoutes[i].zone);
|
||
|
else
|
||
|
sprintf(logBuff,
|
||
|
"Conditional Forwarder: %s, %s for %s",
|
||
|
IP2String(temp, cfig.dnsRoutes[i].dns[0]),
|
||
|
IP2String(ipbuff, cfig.dnsRoutes[i].dns[1]),
|
||
|
cfig.dnsRoutes[i].zone);
|
||
|
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < MAX_SERVERS && network.dns[i]; i++) {
|
||
|
sprintf(logBuff, "Default Forwarding Server: %s", IP2String(ipbuff, network.dns[i]));
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
|
||
|
//char temp[128];
|
||
|
|
||
|
for (int i = 0; i <= MAX_DNS_RANGES && cfig.dnsRanges[i].rangeStart; i++) {
|
||
|
char *logPtr = logBuff;
|
||
|
logPtr += sprintf(logPtr, "%s", "DNS Service Permitted Hosts: ");
|
||
|
logPtr += sprintf(logPtr, "%s-", IP2String(ipbuff, htonl(cfig.dnsRanges[i].rangeStart)));
|
||
|
logPtr += sprintf(logPtr, "%s", IP2String(ipbuff, htonl(cfig.dnsRanges[i].rangeEnd)));
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
} else {
|
||
|
sprintf(logBuff, "Domain Name: %s", cfig.zone);
|
||
|
logDNSMess(logBuff, 1);
|
||
|
}
|
||
|
|
||
|
getInterfaces(&newNetwork);
|
||
|
memcpy(cfig.oldservers, newNetwork.allServers, (MAX_SERVERS * sizeof(MYDWORD)));
|
||
|
|
||
|
do {
|
||
|
bool bindfailed = false;
|
||
|
newNetwork.maxFD = 0;
|
||
|
|
||
|
//printf("Setting DHCP Sockets\n");
|
||
|
|
||
|
if (dhcpService) {
|
||
|
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");
|
||
|
logMess(logBuff, 1);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
//printf("Socket %u\n", newNetwork.dhcpConn[i].sock);
|
||
|
|
||
|
newNetwork.dhcpConn[i].addr.sin_family = AF_INET;
|
||
|
newNetwork.dhcpConn[i].addr.sin_addr.s_addr = newNetwork.listenServers[j];
|
||
|
newNetwork.dhcpConn[i].addr.sin_port = htons(IPPORT_DHCPS);
|
||
|
newNetwork.dhcpConn[i].reUseVal = true;
|
||
|
newNetwork.dhcpConn[i].reUseSize = sizeof(newNetwork.dhcpConn[i].reUseVal);
|
||
|
|
||
|
setsockopt(newNetwork.dhcpConn[i].sock,
|
||
|
SOL_SOCKET,
|
||
|
SO_REUSEADDR,
|
||
|
(char *)&newNetwork.dhcpConn[i].reUseVal,
|
||
|
newNetwork.dhcpConn[i].reUseSize);
|
||
|
|
||
|
newNetwork.dhcpConn[i].broadCastVal = true;
|
||
|
newNetwork.dhcpConn[i].broadCastSize = sizeof(newNetwork.dhcpConn[i].broadCastVal);
|
||
|
|
||
|
setsockopt(newNetwork.dhcpConn[i].sock,
|
||
|
SOL_SOCKET,
|
||
|
SO_BROADCAST,
|
||
|
(char *)&newNetwork.dhcpConn[i].broadCastVal,
|
||
|
newNetwork.dhcpConn[i].broadCastSize);
|
||
|
int nRet = bind(newNetwork.dhcpConn[i].sock,
|
||
|
(sockaddr *)&newNetwork.dhcpConn[i].addr,
|
||
|
sizeof(struct sockaddr_in));
|
||
|
|
||
|
if (nRet == SOCKET_ERROR) {
|
||
|
bindfailed = true;
|
||
|
close(newNetwork.dhcpConn[i].sock);
|
||
|
sprintf(logBuff, "%s Port 67 already in use", IP2String(ipbuff, newNetwork.listenServers[j]));
|
||
|
logMess(logBuff, 1);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
newNetwork.dhcpConn[i].loaded = true;
|
||
|
newNetwork.dhcpConn[i].ready = true;
|
||
|
|
||
|
if (newNetwork.maxFD < newNetwork.dhcpConn[i].sock)
|
||
|
newNetwork.maxFD = newNetwork.dhcpConn[i].sock;
|
||
|
|
||
|
newNetwork.dhcpConn[i].server = newNetwork.listenServers[j];
|
||
|
newNetwork.dhcpConn[i].mask = newNetwork.listenMasks[j];
|
||
|
newNetwork.dhcpConn[i].port = IPPORT_DHCPS;
|
||
|
|
||
|
i++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (network.dhcpListener.ready) {
|
||
|
memcpy(&(newNetwork.dhcpListener), &(network.dhcpListener), sizeof(DhcpConnType));
|
||
|
|
||
|
if (newNetwork.maxFD < newNetwork.dhcpListener.sock)
|
||
|
newNetwork.maxFD = newNetwork.dhcpListener.sock;
|
||
|
|
||
|
network.dhcpListener.ready = false;
|
||
|
} else {
|
||
|
newNetwork.dhcpListener.sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||
|
|
||
|
if (newNetwork.dhcpListener.sock == INVALID_SOCKET) {
|
||
|
bindfailed = true;
|
||
|
sprintf(logBuff, "Failed to Creat DHCP Socket");
|
||
|
logMess(logBuff, 1);
|
||
|
} else {
|
||
|
newNetwork.dhcpListener.reUseVal = true;
|
||
|
newNetwork.dhcpListener.reUseSize = sizeof(newNetwork.dhcpListener.reUseVal);
|
||
|
setsockopt(newNetwork.dhcpListener.sock,
|
||
|
SOL_SOCKET,
|
||
|
SO_REUSEADDR,
|
||
|
(char *)&newNetwork.dhcpListener.reUseVal,
|
||
|
newNetwork.dhcpListener.reUseSize);
|
||
|
newNetwork.dhcpListener.pktinfoVal = true;
|
||
|
newNetwork.dhcpListener.pktinfoSize = sizeof(newNetwork.dhcpListener.pktinfoVal);
|
||
|
setsockopt(newNetwork.dhcpListener.sock,
|
||
|
IPPROTO_IP,
|
||
|
IP_PKTINFO,
|
||
|
&newNetwork.dhcpListener.pktinfoVal,
|
||
|
newNetwork.dhcpListener.pktinfoSize);
|
||
|
|
||
|
newNetwork.dhcpListener.addr.sin_family = AF_INET;
|
||
|
newNetwork.dhcpListener.addr.sin_addr.s_addr = INADDR_ANY;
|
||
|
newNetwork.dhcpListener.addr.sin_port = htons(IPPORT_DHCPS);
|
||
|
|
||
|
int nRet = bind(newNetwork.dhcpListener.sock,
|
||
|
(sockaddr *)&newNetwork.dhcpListener.addr,
|
||
|
sizeof(struct sockaddr_in));
|
||
|
|
||
|
if (nRet == SOCKET_ERROR) {
|
||
|
bindfailed = true;
|
||
|
close(newNetwork.dhcpListener.sock);
|
||
|
sprintf(logBuff, "DHCP Port 67 already in use");
|
||
|
logMess(logBuff, 1);
|
||
|
} else {
|
||
|
newNetwork.dhcpListener.loaded = true;
|
||
|
newNetwork.dhcpListener.ready = true;
|
||
|
|
||
|
if (newNetwork.maxFD < newNetwork.dhcpListener.sock)
|
||
|
newNetwork.maxFD = newNetwork.dhcpListener.sock;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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);
|
||
|
logMess(logBuff, 1);
|
||
|
}
|
||
|
|
||
|
if (value[0]) {
|
||
|
if (strtol(value, nullptr, 10))
|
||
|
newNetwork.httpConn.port = strtol(value, nullptr, 10);
|
||
|
else {
|
||
|
newNetwork.httpConn.loaded = false;
|
||
|
sprintf(logBuff, "Warning: Section [HTTP_INTERFACE], Invalid port %s, ignored", value);
|
||
|
logMess(logBuff, 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (newNetwork.httpConn.server != inet_addr("127.0.0.1")
|
||
|
&& !findServer(newNetwork.allServers, MAX_SERVERS, newNetwork.httpConn.server)) {
|
||
|
newNetwork.httpConn.loaded = false;
|
||
|
sprintf(logBuff, "Warning: Section [HTTP_INTERFACE], %s not available, ignored", raw);
|
||
|
logMess(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);
|
||
|
logMess(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);
|
||
|
logMess(logBuff, 1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (htmlTitle[0] == 0)
|
||
|
sprintf(htmlTitle, "Dual Server on %s", cfig.servername);
|
||
|
|
||
|
if (newNetwork.httpConn.loaded) {
|
||
|
if (network.httpConn.ready && network.httpConn.server == newNetwork.httpConn.server
|
||
|
&& network.httpConn.port == newNetwork.httpConn.port) {
|
||
|
memcpy(&(newNetwork.httpConn), &(network.httpConn), sizeof(ConnType));
|
||
|
|
||
|
if (newNetwork.httpConn.sock > newNetwork.maxFD)
|
||
|
newNetwork.maxFD = newNetwork.httpConn.sock;
|
||
|
|
||
|
network.httpConn.ready = false;
|
||
|
} else if (newNetwork.httpConn.server) {
|
||
|
newNetwork.httpConn.sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||
|
|
||
|
if (newNetwork.httpConn.sock == INVALID_SOCKET) {
|
||
|
bindfailed = true;
|
||
|
sprintf(logBuff, "Failed to Create Socket");
|
||
|
logMess(logBuff, 1);
|
||
|
} else {
|
||
|
//printf("Socket %u\n", newNetwork.httpConn.sock);
|
||
|
|
||
|
newNetwork.httpConn.addr.sin_family = AF_INET;
|
||
|
newNetwork.httpConn.addr.sin_addr.s_addr = newNetwork.httpConn.server;
|
||
|
newNetwork.httpConn.addr.sin_port = htons(newNetwork.httpConn.port);
|
||
|
|
||
|
int nRet = bind(newNetwork.httpConn.sock,
|
||
|
(sockaddr *)&newNetwork.httpConn.addr,
|
||
|
sizeof(struct sockaddr_in));
|
||
|
|
||
|
if (nRet == SOCKET_ERROR) {
|
||
|
bindfailed = true;
|
||
|
sprintf(logBuff,
|
||
|
"Http Interface %s TCP Port %u not available",
|
||
|
IP2String(ipbuff, newNetwork.httpConn.server),
|
||
|
newNetwork.httpConn.port);
|
||
|
logMess(logBuff, 1);
|
||
|
closesocket(newNetwork.httpConn.sock);
|
||
|
} else {
|
||
|
nRet = listen(newNetwork.httpConn.sock, SOMAXCONN);
|
||
|
|
||
|
if (nRet == SOCKET_ERROR) {
|
||
|
bindfailed = true;
|
||
|
sprintf(logBuff,
|
||
|
"%s TCP Port %u Error on Listen",
|
||
|
IP2String(ipbuff, newNetwork.httpConn.server),
|
||
|
newNetwork.httpConn.port);
|
||
|
logMess(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;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//printf("Setting DNS Sockets\n");
|
||
|
|
||
|
if (dnsService) {
|
||
|
if (cfig.replication != 2) {
|
||
|
char localhost[] = "localhost";
|
||
|
add2Cache(localhost, inet_addr("127.0.0.1"), MY_MAX_TIME, CTYPE_LOCALHOST_A, CTYPE_LOCALHOST_PTR);
|
||
|
|
||
|
for (int i = 0; i < MAX_SERVERS && newNetwork.listenServers[i]; i++) {
|
||
|
if (isLocal(newNetwork.listenServers[i]))
|
||
|
add2Cache(cfig.servername,
|
||
|
newNetwork.listenServers[i],
|
||
|
MY_MAX_TIME,
|
||
|
CTYPE_SERVER_A_AUTH,
|
||
|
CTYPE_SERVER_PTR_AUTH);
|
||
|
else
|
||
|
add2Cache(cfig.servername,
|
||
|
newNetwork.listenServers[i],
|
||
|
MY_MAX_TIME,
|
||
|
CTYPE_SERVER_A_AUTH,
|
||
|
CTYPE_SERVER_PTR_NAUTH);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int i = 0;
|
||
|
|
||
|
for (int j = 0; j < MAX_SERVERS && newNetwork.listenServers[j]; j++) {
|
||
|
int k = 0;
|
||
|
|
||
|
for (; k < MAX_SERVERS && network.dnsUdpConn[k].loaded; k++) {
|
||
|
if (network.dnsUdpConn[k].ready && network.dnsUdpConn[k].server == newNetwork.listenServers[j])
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (network.dnsUdpConn[k].ready && network.dnsUdpConn[k].server == newNetwork.listenServers[j]) {
|
||
|
memcpy(&(newNetwork.dnsUdpConn[i]), &(network.dnsUdpConn[k]), sizeof(ConnType));
|
||
|
|
||
|
if (newNetwork.maxFD < newNetwork.dnsUdpConn[i].sock)
|
||
|
newNetwork.maxFD = newNetwork.dnsUdpConn[i].sock;
|
||
|
|
||
|
network.dnsUdpConn[k].ready = false;
|
||
|
i++;
|
||
|
continue;
|
||
|
} else {
|
||
|
newNetwork.dnsUdpConn[i].sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||
|
|
||
|
if (newNetwork.dnsUdpConn[i].sock == INVALID_SOCKET) {
|
||
|
bindfailed = true;
|
||
|
sprintf(logBuff, "Failed to Create Socket");
|
||
|
logDNSMess(logBuff, 1);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
//printf("Socket %u\n", newNetwork.dnsUdpConn[i].sock);
|
||
|
|
||
|
newNetwork.dnsUdpConn[i].addr.sin_family = AF_INET;
|
||
|
newNetwork.dnsUdpConn[i].addr.sin_addr.s_addr = newNetwork.listenServers[j];
|
||
|
newNetwork.dnsUdpConn[i].addr.sin_port = htons(IPPORT_DNS);
|
||
|
|
||
|
int nRet = bind(newNetwork.dnsUdpConn[i].sock,
|
||
|
(sockaddr *)&newNetwork.dnsUdpConn[i].addr,
|
||
|
sizeof(struct sockaddr_in));
|
||
|
|
||
|
if (nRet == SOCKET_ERROR) {
|
||
|
bindfailed = true;
|
||
|
closesocket(newNetwork.dnsUdpConn[i].sock);
|
||
|
sprintf(logBuff,
|
||
|
"Warning: %s UDP Port 53 already in use",
|
||
|
IP2String(ipbuff, newNetwork.listenServers[j]));
|
||
|
logDNSMess(logBuff, 1);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
newNetwork.dnsUdpConn[i].loaded = true;
|
||
|
newNetwork.dnsUdpConn[i].ready = true;
|
||
|
|
||
|
if (newNetwork.maxFD < newNetwork.dnsUdpConn[i].sock)
|
||
|
newNetwork.maxFD = newNetwork.dnsUdpConn[i].sock;
|
||
|
|
||
|
newNetwork.dnsUdpConn[i].server = newNetwork.listenServers[j];
|
||
|
newNetwork.dnsUdpConn[i].port = IPPORT_DNS;
|
||
|
|
||
|
i++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (network.forwConn.ready) {
|
||
|
memcpy(&(newNetwork.forwConn), &(network.forwConn), sizeof(ConnType));
|
||
|
|
||
|
if (newNetwork.maxFD < newNetwork.forwConn.sock)
|
||
|
newNetwork.maxFD = newNetwork.forwConn.sock;
|
||
|
|
||
|
network.forwConn.ready = false;
|
||
|
} else {
|
||
|
newNetwork.forwConn.sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||
|
|
||
|
if (newNetwork.forwConn.sock == INVALID_SOCKET) {
|
||
|
bindfailed = true;
|
||
|
sprintf(logBuff, "Failed to Create Socket");
|
||
|
logDNSMess(logBuff, 1);
|
||
|
} else {
|
||
|
newNetwork.forwConn.addr.sin_family = AF_INET;
|
||
|
newNetwork.forwConn.server = network.dns[0];
|
||
|
newNetwork.forwConn.port = IPPORT_DNS;
|
||
|
//bind(newNetwork.forwConn.sock, (sockaddr*)&newNetwork.forwConn.addr, sizeof(struct sockaddr_in));
|
||
|
|
||
|
//int val = 0;
|
||
|
//setsockopt(network.forwConn.sock, IPPROTO_IP, IP_DONTFRAG, &val, sizeof(val));
|
||
|
int val = IP_PMTUDISC_DONT;
|
||
|
setsockopt(network.forwConn.sock, IPPROTO_IP, IP_PMTUDISC_DONT, &val, sizeof(val));
|
||
|
|
||
|
newNetwork.forwConn.loaded = true;
|
||
|
newNetwork.forwConn.ready = true;
|
||
|
|
||
|
if (newNetwork.maxFD < newNetwork.forwConn.sock)
|
||
|
newNetwork.maxFD = newNetwork.forwConn.sock;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
i = 0;
|
||
|
|
||
|
for (int j = 0; j < MAX_SERVERS && newNetwork.listenServers[j]; j++) {
|
||
|
int k = 0;
|
||
|
|
||
|
for (; k < MAX_SERVERS && network.dnsTcpConn[k].loaded; k++) {
|
||
|
if (network.dnsTcpConn[k].ready && network.dnsTcpConn[k].server == newNetwork.listenServers[j])
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (network.dnsTcpConn[k].ready && network.dnsTcpConn[k].server == newNetwork.listenServers[j]) {
|
||
|
memcpy(&(newNetwork.dnsTcpConn[i]), &(network.dnsTcpConn[k]), sizeof(ConnType));
|
||
|
|
||
|
if (newNetwork.maxFD < newNetwork.dnsTcpConn[i].sock)
|
||
|
newNetwork.maxFD = newNetwork.dnsTcpConn[i].sock;
|
||
|
|
||
|
network.dnsTcpConn[k].ready = false;
|
||
|
i++;
|
||
|
continue;
|
||
|
} else {
|
||
|
newNetwork.dnsTcpConn[i].sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||
|
|
||
|
if (newNetwork.dnsTcpConn[i].sock == INVALID_SOCKET) {
|
||
|
bindfailed = true;
|
||
|
sprintf(logBuff, "Failed to Create Socket");
|
||
|
logDNSMess(logBuff, 1);
|
||
|
} else {
|
||
|
//printf("Socket %u\n", newNetwork.dnsTcpConn[i].sock);
|
||
|
newNetwork.dnsTcpConn[i].addr.sin_family = AF_INET;
|
||
|
newNetwork.dnsTcpConn[i].addr.sin_addr.s_addr = newNetwork.listenServers[j];
|
||
|
newNetwork.dnsTcpConn[i].addr.sin_port = htons(IPPORT_DNS);
|
||
|
|
||
|
int nRet = bind(newNetwork.dnsTcpConn[i].sock,
|
||
|
(sockaddr *)&newNetwork.dnsTcpConn[i].addr,
|
||
|
sizeof(struct sockaddr_in));
|
||
|
|
||
|
if (nRet == SOCKET_ERROR) {
|
||
|
bindfailed = true;
|
||
|
closesocket(newNetwork.dnsTcpConn[i].sock);
|
||
|
sprintf(logBuff,
|
||
|
"Warning: %s TCP Port 53 already in use",
|
||
|
IP2String(ipbuff, newNetwork.listenServers[j]));
|
||
|
logDNSMess(logBuff, 1);
|
||
|
} else {
|
||
|
nRet = listen(newNetwork.dnsTcpConn[i].sock, SOMAXCONN);
|
||
|
|
||
|
if (nRet == SOCKET_ERROR) {
|
||
|
closesocket(newNetwork.dnsTcpConn[i].sock);
|
||
|
sprintf(logBuff, "TCP Port 53 Error on Listen");
|
||
|
logDNSMess(logBuff, 1);
|
||
|
} else {
|
||
|
newNetwork.dnsTcpConn[i].server = newNetwork.listenServers[j];
|
||
|
newNetwork.dnsTcpConn[i].port = IPPORT_DNS;
|
||
|
|
||
|
newNetwork.dnsTcpConn[i].loaded = true;
|
||
|
newNetwork.dnsTcpConn[i].ready = true;
|
||
|
|
||
|
if (newNetwork.maxFD < newNetwork.dnsTcpConn[i].sock)
|
||
|
newNetwork.maxFD = newNetwork.dnsTcpConn[i].sock;
|
||
|
|
||
|
i++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (dhcpService) {
|
||
|
for (MYBYTE m = 0; m < MAX_SERVERS && newNetwork.allServers[m]; m++)
|
||
|
lockIP(newNetwork.allServers[m]);
|
||
|
|
||
|
for (MYBYTE m = 0; m < MAX_SERVERS && newNetwork.dns[m]; m++)
|
||
|
lockIP(newNetwork.dns[m]);
|
||
|
}
|
||
|
|
||
|
if (bindfailed)
|
||
|
cfig.failureCount++;
|
||
|
else
|
||
|
cfig.failureCount = 0;
|
||
|
|
||
|
closeConn();
|
||
|
newNetwork.maxFD++;
|
||
|
memcpy(&network, &newNetwork, sizeof(data1));
|
||
|
|
||
|
//printf("%i %i %i\n", network.dhcpConn[0].ready, network.dnsUdpConn[0].ready, network.dnsTcpConn[0].ready);
|
||
|
|
||
|
if ((dhcpService && !network.dhcpConn[0].ready)
|
||
|
|| (dnsService && !(network.dnsUdpConn[0].ready && network.dnsTcpConn[0].ready))) {
|
||
|
sprintf(logBuff, "No Static Interface ready, Waiting...");
|
||
|
logMess(logBuff, 1);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (dhcpService && network.httpConn.ready) {
|
||
|
sprintf(logBuff,
|
||
|
"Lease Status URL: http://%s:%u",
|
||
|
IP2String(ipbuff, network.httpConn.server),
|
||
|
network.httpConn.port);
|
||
|
logMess(logBuff, 1);
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < MAX_SERVERS && network.listenServers[i]; i++) {
|
||
|
for (MYBYTE j = 0; j < MAX_SERVERS; j++) {
|
||
|
if (!network.dhcpConn[j].server && !network.dnsUdpConn[j].server)
|
||
|
break;
|
||
|
else if (network.dhcpConn[j].server == network.listenServers[i]
|
||
|
|| network.dnsUdpConn[j].server == network.listenServers[i]) {
|
||
|
sprintf(logBuff, "Listening On: %s", IP2String(ipbuff, network.listenServers[i]));
|
||
|
logMess(logBuff, 1);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} while (kRunning && detectChange());
|
||
|
|
||
|
pthread_exit(nullptr);
|
||
|
}
|
||
|
|
||
|
bool detectChange() {
|
||
|
char logBuff[256];
|
||
|
network.ready = true;
|
||
|
network.readyForChange = false;
|
||
|
|
||
|
while (kRunning) {
|
||
|
sleep(20);
|
||
|
//printf("Checking Networks (failue count=%u, failue cycle=%u)..\n", cfig.failureCount, cfig.failureCycle);
|
||
|
|
||
|
if (cfig.failureCount) {
|
||
|
cfig.failureCycle++;
|
||
|
|
||
|
if (kRunning && cfig.failureCycle == (MYDWORD)pow(2, cfig.failureCount)) {
|
||
|
sprintf(logBuff, "Retrying failed Listening Interfaces..");
|
||
|
logMess(logBuff, 1);
|
||
|
break;
|
||
|
}
|
||
|
} else if (getInterfaces(&newNetwork)) {
|
||
|
memcpy(cfig.oldservers, newNetwork.allServers, (MAX_SERVERS * sizeof(MYDWORD)));
|
||
|
sprintf(logBuff, "Network changed, re-detecting Listening Interfaces..");
|
||
|
logMess(logBuff, 1);
|
||
|
break;
|
||
|
} else
|
||
|
cfig.failureCycle = 0;
|
||
|
}
|
||
|
|
||
|
network.ready = false;
|
||
|
|
||
|
while (kRunning && !network.readyForChange)
|
||
|
sleep(1);
|
||
|
|
||
|
return (kRunning);
|
||
|
}
|
||
|
|
||
|
bool getInterfaces(data1 *netinfo) {
|
||
|
char logBuff[256];
|
||
|
char ipbuff[32];
|
||
|
memset(netinfo, 0, sizeof(data1));
|
||
|
|
||
|
Ifc.ifc_len = sizeof(IfcBuf);
|
||
|
Ifc.ifc_buf = (char *)IfcBuf;
|
||
|
|
||
|
if (ioctl(cfig.fixedSocket, SIOCGIFCONF, &Ifc) >= 0) {
|
||
|
MYDWORD addr, mask;
|
||
|
short flags;
|
||
|
struct ifreq pIfr {};
|
||
|
MYBYTE numInterfaces = Ifc.ifc_len / sizeof(ifreq);
|
||
|
|
||
|
for (MYBYTE i = 0; i < numInterfaces; i++) {
|
||
|
memcpy(&pIfr, &(IfcBuf[i]), sizeof(ifreq));
|
||
|
|
||
|
if (!ioctl(cfig.fixedSocket, SIOCGIFADDR, &pIfr))
|
||
|
addr = ((struct sockaddr_in *)&pIfr.ifr_addr)->sin_addr.s_addr;
|
||
|
else
|
||
|
addr = 0;
|
||
|
|
||
|
if (!ioctl(cfig.fixedSocket, SIOCGIFNETMASK, &pIfr))
|
||
|
mask = ((struct sockaddr_in *)&pIfr.ifr_addr)->sin_addr.s_addr;
|
||
|
else
|
||
|
mask = 0;
|
||
|
|
||
|
if (!ioctl(cfig.fixedSocket, SIOCGIFFLAGS, &pIfr))
|
||
|
flags = pIfr.ifr_flags;
|
||
|
else
|
||
|
flags = 0;
|
||
|
|
||
|
if (addr && mask && (flags & IFF_RUNNING) && (flags & IFF_UP) && !(flags & IFF_LOOPBACK)
|
||
|
&& !(flags & IFF_POINTOPOINT)) {
|
||
|
addServer(netinfo->allServers, MAX_SERVERS, addr);
|
||
|
|
||
|
if (!(flags & IFF_DYNAMIC)) {
|
||
|
MYBYTE k = addServer(netinfo->staticServers, MAX_SERVERS, addr);
|
||
|
|
||
|
if (k < MAX_SERVERS)
|
||
|
netinfo->staticMasks[k] = mask;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!memcmp(cfig.oldservers, netinfo->allServers, (MAX_SERVERS * sizeof(MYDWORD))))
|
||
|
return false;
|
||
|
|
||
|
if (cfig.specifiedServers[0]) {
|
||
|
for (MYBYTE i = 0; i < MAX_SERVERS && cfig.specifiedServers[i]; i++) {
|
||
|
MYBYTE j = 0;
|
||
|
|
||
|
for (; j < MAX_SERVERS && netinfo->staticServers[j]; j++) {
|
||
|
if (netinfo->staticServers[j] == cfig.specifiedServers[i]) {
|
||
|
MYBYTE k = addServer(netinfo->listenServers, MAX_SERVERS, netinfo->staticServers[j]);
|
||
|
|
||
|
if (k < MAX_SERVERS)
|
||
|
netinfo->listenMasks[k] = netinfo->staticMasks[j];
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (j == MAX_SERVERS || !netinfo->staticServers[j]) {
|
||
|
if (findServer(netinfo->allServers, MAX_SERVERS, cfig.specifiedServers[i]))
|
||
|
sprintf(logBuff,
|
||
|
"Warning: Section [LISTEN_ON] Interface %s is not static, ignored",
|
||
|
IP2String(ipbuff, cfig.specifiedServers[i]));
|
||
|
else
|
||
|
sprintf(logBuff,
|
||
|
"Warning: Section [LISTEN_ON] Interface %s is not found, ignored",
|
||
|
IP2String(ipbuff, cfig.specifiedServers[i]));
|
||
|
|
||
|
logMess(logBuff, 2);
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
for (MYBYTE i = 0; i < MAX_SERVERS && netinfo->allServers[i]; i++) {
|
||
|
MYBYTE j = 0;
|
||
|
|
||
|
for (; j < MAX_SERVERS && netinfo->staticServers[j]; j++) {
|
||
|
if (netinfo->staticServers[j] == netinfo->allServers[i]) {
|
||
|
MYBYTE k = addServer(netinfo->listenServers, MAX_SERVERS, netinfo->staticServers[j]);
|
||
|
|
||
|
if (k < MAX_SERVERS)
|
||
|
netinfo->listenMasks[k] = netinfo->staticMasks[j];
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (j == MAX_SERVERS || !netinfo->staticServers[j]) {
|
||
|
sprintf(
|
||
|
logBuff, "Warning: Interface %s is not Static, ignored", IP2String(ipbuff, netinfo->allServers[i]));
|
||
|
logMess(logBuff, 2);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!cfig.zone[0]) {
|
||
|
getdomainname(cfig.zone, sizeof(cfig.zone));
|
||
|
cfig.zLen = strlen(cfig.zone);
|
||
|
}
|
||
|
|
||
|
if (dnsService) {
|
||
|
if (cfig.specifiedDnsServers[0]) {
|
||
|
for (int i = 0; i < MAX_SERVERS && cfig.specifiedDnsServers[i]; i++) {
|
||
|
if (!findServer(netinfo->allServers, MAX_SERVERS, cfig.specifiedDnsServers[i]))
|
||
|
addServer(netinfo->dns, MAX_SERVERS, cfig.specifiedDnsServers[i]);
|
||
|
}
|
||
|
} else {
|
||
|
FILE *f = fopen("/etc/resolv.conf", "rt");
|
||
|
char buff[256];
|
||
|
|
||
|
while (f && fgets(buff, 255, f)) {
|
||
|
myTokenize(buff, buff, nullptr, true);
|
||
|
|
||
|
if (!strcasecmp(myGetToken(buff, 0), "nameserver")) {
|
||
|
MYDWORD addr = inet_addr(myGetToken(buff, 1));
|
||
|
|
||
|
if (!findServer(netinfo->allServers, MAX_SERVERS, addr))
|
||
|
addServer(netinfo->dns, MAX_SERVERS, addr);
|
||
|
} else if (!strcasecmp(myGetToken(buff, 0), "search")) {
|
||
|
if (!strncmp(cfig.zone, "(none)", 6) || !cfig.zone[0]) {
|
||
|
strcpy(cfig.zone, myGetToken(buff, 1));
|
||
|
cfig.zLen = strlen(cfig.zone);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (f)
|
||
|
fclose(f);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
gethostname(cfig.servername, sizeof(cfig.servername));
|
||
|
char *ptr = strchr(cfig.servername, '.');
|
||
|
|
||
|
if (ptr) {
|
||
|
*ptr = 0;
|
||
|
|
||
|
if (!strncmp(cfig.zone, "(none)", 6) || !cfig.zone[0]) {
|
||
|
ptr++;
|
||
|
strcpy(cfig.zone, ptr);
|
||
|
cfig.zLen = strlen(cfig.zone);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!strncmp(cfig.zone, "(none)", 6) || !cfig.zone[0]) {
|
||
|
strcpy(cfig.zone, "workgroup");
|
||
|
cfig.zLen = strlen(cfig.zone);
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void *updateStateFile(void *lparam) {
|
||
|
pthread_mutex_lock(&mutStateFile);
|
||
|
|
||
|
auto *dhcpEntry = (data7 *)lparam;
|
||
|
data8 dhcpData{};
|
||
|
memset(&dhcpData, 0, sizeof(data8));
|
||
|
MYBYTE bp_hlen = 16;
|
||
|
getHexValue(dhcpData.bp_chaddr, dhcpEntry->mapname, &bp_hlen);
|
||
|
dhcpData.bp_hlen = bp_hlen;
|
||
|
dhcpData.ip = dhcpEntry->ip;
|
||
|
dhcpData.subnetFlg = dhcpEntry->subnetFlg;
|
||
|
dhcpData.expiry = dhcpEntry->expiry;
|
||
|
dhcpData.local = dhcpEntry->local;
|
||
|
strcpy(dhcpData.hostname, dhcpEntry->hostname);
|
||
|
|
||
|
if (!dhcpEntry->dhcpInd) {
|
||
|
cfig.dhcpInd += 1;
|
||
|
dhcpEntry->dhcpInd = cfig.dhcpInd;
|
||
|
}
|
||
|
|
||
|
dhcpData.dhcpInd = dhcpEntry->dhcpInd;
|
||
|
FILE *f = fopen(leaFile, "rb+");
|
||
|
|
||
|
if (f) {
|
||
|
if (fseek(f, (long)((dhcpData.dhcpInd - 1) * sizeof(data8)), SEEK_SET) >= 0)
|
||
|
fwrite(&dhcpData, sizeof(data8), 1, f);
|
||
|
|
||
|
fclose(f);
|
||
|
}
|
||
|
|
||
|
pthread_mutex_unlock(&mutStateFile);
|
||
|
pthread_exit(nullptr);
|
||
|
}
|
||
|
|
||
|
MYWORD gdmess(data9 *req, MYBYTE sockInd) {
|
||
|
char ipbuff[16];
|
||
|
char logBuff[256];
|
||
|
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_DNS:
|
||
|
req->dns = 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 = findDNSEntry(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));
|
||
|
// }
|
||
|
|
||
|
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 logDHCPMess(const char *title, const char *mess) {
|
||
|
char t1[512];
|
||
|
sprintf(t1, "%s %s", title, mess);
|
||
|
logDHCPMess(t1, 1);
|
||
|
}
|
||
|
|
||
|
void logMess(const char *title, const char *mess) {
|
||
|
char t1[512];
|
||
|
sprintf(t1, "%s %s", title, mess);
|
||
|
logMess(t1, 1);
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
void debug(const char *mess) {
|
||
|
char t1[254];
|
||
|
sprintf(t1, "%s", mess);
|
||
|
logMess(t1, 1);
|
||
|
}
|
||
|
|
||
|
void debug(const char *title, int i) {
|
||
|
char t1[254];
|
||
|
sprintf(t1, "%s: %i", title, i);
|
||
|
logMess(t1, 1);
|
||
|
}
|
||
|
|
||
|
void debug(const char *title, const char *mess) {
|
||
|
char t1[254];
|
||
|
sprintf(t1, "%s: %s", title, mess);
|
||
|
logMess(t1, 1);
|
||
|
}
|
||
|
#endif
|
||
|
void *logThread(void *lpParam) {
|
||
|
pthread_mutex_lock(&mutLogFile);
|
||
|
char *mess = (char *)lpParam;
|
||
|
time_t local_t = time(nullptr);
|
||
|
tm *ttm = localtime(&local_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);
|
||
|
}
|
||
|
|
||
|
void logMess(char *logBuff, MYBYTE logLevel) {
|
||
|
if (verbatim)
|
||
|
printf("%s\n", logBuff);
|
||
|
|
||
|
if (logFile[0] && (logLevel <= cfig.dnsLogLevel || logLevel <= cfig.dhcpLogLevel)) {
|
||
|
char *mess = cloneString(logBuff);
|
||
|
pthread_t threadId;
|
||
|
pthread_attr_t attr;
|
||
|
pthread_attr_init(&attr);
|
||
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||
|
int errcode = pthread_create(&threadId, &attr, logThread, mess);
|
||
|
pthread_attr_destroy(&attr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void logDHCPMess(char *logBuff, MYBYTE logLevel) {
|
||
|
if (verbatim)
|
||
|
printf("%s\n", logBuff);
|
||
|
|
||
|
if (logFile[0] && logLevel <= cfig.dhcpLogLevel) {
|
||
|
char *mess = cloneString(logBuff);
|
||
|
pthread_t threadId;
|
||
|
pthread_attr_t attr;
|
||
|
pthread_attr_init(&attr);
|
||
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||
|
int errcode = pthread_create(&threadId, &attr, logThread, mess);
|
||
|
pthread_attr_destroy(&attr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void logDNSMess(char *logBuff, MYBYTE logLevel) {
|
||
|
if (verbatim)
|
||
|
printf("%s\n", logBuff);
|
||
|
|
||
|
if (logFile[0] && logLevel <= cfig.dnsLogLevel) {
|
||
|
char *mess = cloneString(logBuff);
|
||
|
pthread_t threadId;
|
||
|
pthread_attr_t attr;
|
||
|
pthread_attr_init(&attr);
|
||
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||
|
int errcode = pthread_create(&threadId, &attr, logThread, mess);
|
||
|
pthread_attr_destroy(&attr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void logDNSMess(data5 *req, char *logBuff, MYBYTE logLevel) {
|
||
|
if (verbatim)
|
||
|
printf("%s\n", logBuff);
|
||
|
|
||
|
if (logFile[0] && logLevel <= cfig.dnsLogLevel) {
|
||
|
char *mess = (char *)calloc(1, 512);
|
||
|
sprintf(mess, "Client %s, %s", inet_ntoa(req->remote.sin_addr), logBuff);
|
||
|
pthread_t threadId;
|
||
|
pthread_attr_t attr;
|
||
|
pthread_attr_init(&attr);
|
||
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||
|
int errcode = pthread_create(&threadId, &attr, logThread, mess);
|
||
|
pthread_attr_destroy(&attr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void logTCPMess(data5 *req, char *logBuff, MYBYTE logLevel) {
|
||
|
if (verbatim)
|
||
|
printf("%s\n", logBuff);
|
||
|
|
||
|
if (logFile[0] && logLevel <= cfig.dnsLogLevel) {
|
||
|
char *mess = (char *)calloc(1, 512);
|
||
|
sprintf(mess, "TCP Client %s, %s", inet_ntoa(req->remote.sin_addr), 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) {
|
||
|
if (!pLump->mapname || !pLump->cacheType)
|
||
|
return nullptr;
|
||
|
|
||
|
MYWORD dataSize = 5 + sizeof(data7) + strlen(pLump->mapname);
|
||
|
data7 *cache = nullptr;
|
||
|
|
||
|
switch (pLump->cacheType) {
|
||
|
case CTYPE_DHCP_ENTRY: {
|
||
|
dataSize += 64;
|
||
|
dataSize += pLump->optionSize;
|
||
|
cache = (data7 *)calloc(1, dataSize);
|
||
|
|
||
|
if (!cache)
|
||
|
return nullptr;
|
||
|
|
||
|
MYBYTE *dp = &cache->data;
|
||
|
cache->mapname = (char *)dp;
|
||
|
strcpy(cache->mapname, pLump->mapname);
|
||
|
myLower(cache->mapname);
|
||
|
dp += strlen(cache->mapname);
|
||
|
dp++;
|
||
|
cache->hostname = (char *)dp;
|
||
|
|
||
|
if (pLump->hostname)
|
||
|
strcpy(cache->hostname, pLump->hostname);
|
||
|
|
||
|
dp += 65;
|
||
|
|
||
|
if (pLump->options && pLump->optionSize >= 3) {
|
||
|
cache->options = dp;
|
||
|
memcpy(cache->options, pLump->options, pLump->optionSize);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case CTYPE_QUEUE: {
|
||
|
//debug("about to create queue");
|
||
|
dataSize += strlen(pLump->query);
|
||
|
dataSize += sizeof(SOCKADDR_IN);
|
||
|
cache = (data7 *)calloc(1, dataSize);
|
||
|
|
||
|
if (!cache)
|
||
|
return nullptr;
|
||
|
|
||
|
cache->cacheType = pLump->cacheType;
|
||
|
cache->dnsType = pLump->dnsType;
|
||
|
MYBYTE *dp = &cache->data;
|
||
|
cache->mapname = (char *)dp;
|
||
|
cache->name = (char *)dp;
|
||
|
strcpy(cache->mapname, pLump->mapname);
|
||
|
//myLower(cache->mapname);
|
||
|
dp += strlen(cache->mapname);
|
||
|
dp++;
|
||
|
cache->query = (char *)dp;
|
||
|
strcpy(cache->query, pLump->query);
|
||
|
//debug(cache->query);
|
||
|
//debug(strlen(cache->query));
|
||
|
dp += strlen(cache->query);
|
||
|
dp++;
|
||
|
//debug((int)pLump->addr);
|
||
|
cache->addr = (SOCKADDR_IN *)dp;
|
||
|
memcpy(cache->addr, pLump->addr, sizeof(SOCKADDR_IN));
|
||
|
//debug("done create queue");
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case CTYPE_CACHED: {
|
||
|
dataSize += pLump->bytes;
|
||
|
cache = (data7 *)calloc(1, dataSize);
|
||
|
|
||
|
if (!cache)
|
||
|
return nullptr;
|
||
|
|
||
|
cache->cacheType = pLump->cacheType;
|
||
|
cache->dnsType = pLump->dnsType;
|
||
|
MYBYTE *dp = &cache->data;
|
||
|
cache->mapname = (char *)dp;
|
||
|
setMapName(cache->mapname, pLump->mapname, pLump->dnsType);
|
||
|
dp++;
|
||
|
cache->name = (char *)dp;
|
||
|
dp += strlen(pLump->mapname);
|
||
|
dp++;
|
||
|
cache->response = dp;
|
||
|
cache->bytes = pLump->bytes;
|
||
|
memcpy(cache->response, pLump->response, cache->bytes);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case CTYPE_LOCAL_PTR_AUTH:
|
||
|
case CTYPE_LOCAL_PTR_NAUTH:
|
||
|
case CTYPE_LOCALHOST_PTR:
|
||
|
case CTYPE_SERVER_PTR_AUTH:
|
||
|
case CTYPE_SERVER_PTR_NAUTH:
|
||
|
case CTYPE_STATIC_PTR_AUTH:
|
||
|
case CTYPE_STATIC_PTR_NAUTH:
|
||
|
case CTYPE_LOCAL_CNAME:
|
||
|
case CTYPE_EXT_CNAME: {
|
||
|
dataSize += strlen(pLump->mapname);
|
||
|
dataSize += strlen(pLump->hostname);
|
||
|
cache = (data7 *)calloc(1, dataSize);
|
||
|
|
||
|
if (!cache)
|
||
|
return nullptr;
|
||
|
|
||
|
cache->cacheType = pLump->cacheType;
|
||
|
cache->dnsType = pLump->dnsType;
|
||
|
MYBYTE *dp = &cache->data;
|
||
|
cache->mapname = (char *)dp;
|
||
|
setMapName(cache->mapname, pLump->mapname, pLump->dnsType);
|
||
|
dp += strlen(pLump->mapname);
|
||
|
dp += 2;
|
||
|
cache->name = (char *)dp;
|
||
|
strcpy(cache->name, pLump->mapname);
|
||
|
dp += strlen(pLump->mapname);
|
||
|
dp++;
|
||
|
cache->hostname = (char *)dp;
|
||
|
strcpy(cache->hostname, pLump->hostname);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
default: {
|
||
|
dataSize += strlen(pLump->mapname);
|
||
|
cache = (data7 *)calloc(1, dataSize);
|
||
|
|
||
|
if (!cache)
|
||
|
return nullptr;
|
||
|
|
||
|
cache->cacheType = pLump->cacheType;
|
||
|
cache->dnsType = pLump->dnsType;
|
||
|
MYBYTE *dp = &cache->data;
|
||
|
cache->mapname = (char *)dp;
|
||
|
setMapName(cache->mapname, pLump->mapname, pLump->dnsType);
|
||
|
dp += strlen(pLump->mapname);
|
||
|
dp += 2;
|
||
|
cache->name = (char *)dp;
|
||
|
strcpy(cache->name, pLump->mapname);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
/*
|
||
|
if (pLump->cacheType != CTYPE_DHCP_ENTRY)
|
||
|
{
|
||
|
char logBuff[256];
|
||
|
sprintf(logBuff, "New Cache %p datasize=%d cacheType=%d dnsType=%u name=%s hostname=%s", cache, dataSize, cache->cacheType, cache->dnsType, cache->name, cache->hostname);
|
||
|
logMess(logBuff, 1);
|
||
|
}
|
||
|
*/
|
||
|
return cache;
|
||
|
}
|
||
|
|
||
|
#pragma clang diagnostic pop
|