/************************************************************************** * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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

403 Forbidden

"; const char send404[] = "HTTP/1.1 404 Not Found\r\n\r\n

404 Not Found

"; 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[] = "%s"; const char tdnowrap200[] = "%s"; const char sVersion[] = "Dual DHCP DNS Server Version 7.60 Linux Build 7057"; const char htmlStart [] = "\n\n%s\n\n\n"; const char bodyStart [] = "
\n
%s
Server: %s %s %shttp://dhcp-dns-server.sourceforge.net
"; //const char bodyStart[] = "
%s
http://dhcp-dns-server.sourceforge.net/
"; //const char bodyStart[] = "
%s
http://dhcp-dns-server.sourceforge.net
"; //const char bodyStart[] = "
%s
%s
"; 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[] = "
\n
%s
Server Name: %s%shttp://dhcp-dns-server.sourceforge.net
"; 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\n"); if (cfig.dhcpRepl > t) { fp += sprintf(fp, "\n"); fp += sprintf(fp, "\n"); } else { fp += sprintf(fp, "\n"); fp += sprintf( fp, "\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, ""); 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, "\n"); } } fp += sprintf(fp, "
Active Leases
Mac AddressIPLease ExpiryHostname (first 20 " "chars)Server
Active Leases
Mac AddressIPLease ExpiryHostname (first 20 chars)
\n
\n\n"); fp += sprintf(fp, "\n"); fp += sprintf(fp, "\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, "\n", tempbuff, ipbuff, extbuff, (ipused + ipfree), ipfree); } fp += sprintf(fp, "
Free Dynamic Leases
DHCP RangeMaskAvailable " "LeasesFree Leases
%s - %s%s%i%i
\n
\n\n"); fp += sprintf(fp, "\n"); fp += sprintf(fp, "\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, ""); colNum = 1; } else if (colNum == 1) { colNum = 2; } else if (colNum == 2) { fp += sprintf(fp, "\n"); colNum = 1; } fp += sprintf(fp, td200, dhcpEntry->mapname); fp += sprintf(fp, td200, IP2String(tempbuff, dhcpEntry->ip)); } } if (colNum) fp += sprintf(fp, "\n"); fp += sprintf(fp, "
Free Static Leases
Mac AddressIPMac AddressIP
\n\n"); //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, "\n"); fp += sprintf(fp, "\n"); fp += sprintf(fp, "\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, "\n", tempbuff, extbuff, ipused, ipfree, ((ipfree * 100)/(ipused + ipfree))); } fp += sprintf(fp, "
Scope Status
DHCP RangeIPs UsedIPs Free%% Free
%s - %s%5.0f%5.0f%2.2f
\n\n"); 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(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(entry->mapname, entry)); if (entry->expiry && entry->expiry < MY_MAX_TIME) dnsAge[currentInd].insert(pair(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(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(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(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(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(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