home *** CD-ROM | disk | FTP | other *** search
Wrap
/************************************************************************** * Copyright (C) 2005 by Achal Dhir * * achaldhir@gmail.com * Portions modified and Copyright (C) 2010 by Connectify * * * 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. * ***************************************************************************/ // Dual Service.cpp #include <stdio.h> #include <winsock2.h> #include <time.h> #include <tchar.h> #include <ws2tcpip.h> #include <limits.h> #include <iphlpapi.h> #include <process.h> #include "DualServer.h" //Global Variables SERVICE_STATUS serviceStatus; SERVICE_STATUS_HANDLE serviceStatusHandle = 0; HANDLE stopServiceEvent = 0; data1 network; data2 cfig; BYTE cacheInd = 0; BYTE newInd = 0; hostMap dnsCache[2]; dhcpMap dhcpCache; expiryMap dnsAge[2]; expiryMap dhcpAge; char serviceName[] = "DUALServer"; char displayName[] = "Dual DHCP DNS Service"; char tempbuff[256]; char extbuff[256]; char logBuff[256]; bool verbatim = false; char iniFile[_MAX_PATH]; // "DualServer.ini" char leaFile[_MAX_PATH]; // "DualServer.state" char logFile[_MAX_PATH]; // "DualServer.state" WORD loggingDay; char arpa[] = ".in-addr.arpa"; bool dhcpService = true; bool dnsService = true; timeval tv; fd_set readfds; fd_set writefds; HANDLE fEvent; //HANDLE lEvent; DWORD portOffset; vciMap vci; //constants 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\nDate: %s\r\nLast-Modified: %s\r\nContent-Type: text/html\r\nConnection: Close\r\nTransfer-Encoding: chunked\r\n"; const char line200[] = "<td>%s</td>"; const char sVersion[] = "Dual DHCP DNS Server Version 6.50 Windows Build 6501"; const data4 opData[] = { {"IP_Addr", 0, 0}, {"DHCP_Range", 0, 1}, //{"Authorized", 0, 6}, {"SubNet_Mask", DHCP_OPTION_NETMASK, 3}, {"Time_Offset", DHCP_OPTION_TIMEOFFSET, 4}, {"Router", DHCP_OPTION_ROUTER, 3}, {"Time_Server", DHCP_OPTION_TIMESERVER, 3}, {"Name_Server", DHCP_OPTION_NAMESERVER, 3}, {"DNS_Server", DHCP_OPTION_DNS, 3}, {"Log_Server", DHCP_OPTION_LOGSERVER, 3}, {"Cookie_Server", DHCP_OPTION_COOKIESERVER, 3}, {"LPR_Server", DHCP_OPTION_LPRSERVER, 3}, {"Impress_Server", DHCP_OPTION_IMPRESSSERVER, 3}, {"RLP_Server", DHCP_OPTION_RESLOCSERVER, 3}, {"Hostname", DHCP_OPTION_HOSTNAME, 1}, {"Boot_File_Size", DHCP_OPTION_BOOTFILESIZE, 5}, // {"Domain_Name", DHCP_OPTION_DOMAINNAME, 1}, {"Swap_Server", DHCP_OPTION_SWAPSERVER, 3}, {"Root_Path", DHCP_OPTION_ROOTPATH, 1}, {"Extension_Path", DHCP_OPTION_EXTSPATH, 1}, {"IP_Forward_On/Off", DHCP_OPTION_IPFORWARD, 7}, {"SrcRte_On/Off", DHCP_OPTION_NONLOCALSR, 7}, {"Policy_Filter", DHCP_OPTION_POLICYFILTER, 3}, {"Default_IP_TTL", DHCP_OPTION_IPTTL, 6}, {"MTU_Timeout", DHCP_OPTION_PATHMTUAGING, 4}, {"MTU_Plateau", DHCP_OPTION_PATHMTUPLATEAU, 2}, {"MTU_Interface", DHCP_OPTION_INTERFACEMTU, 5}, {"All_Subnet_Local", DHCP_OPTION_SUBNETSLOCAL, 7}, {"Broadcast_Address", DHCP_OPTION_BCASTADDRESS, 3}, {"Mask_Discovery", DHCP_OPTION_MASKDISCOVERY, 7}, {"Mask_Supplier", DHCP_OPTION_MASKSUPPLIER, 7}, {"Router_Discovery", DHCP_OPTION_ROUTERDISCOVERY, 7}, {"Router_Soli_Address", DHCP_OPTION_ROUTERSOLIC, 3}, {"Static_Routes", DHCP_OPTION_STATICROUTE, 3}, {"Trailers", DHCP_OPTION_TRAILERENCAPS, 7}, {"ARP_Timeout", DHCP_OPTION_ARPTIMEOUT, 4}, {"Ethernet_Encp", DHCP_OPTION_ETHERNETENCAPS, 7}, {"Default_TCP_TTL", DHCP_OPTION_TCPTTL, 6}, {"Keepalive_Time", DHCP_OPTION_TCPKEEPALIVEINT, 4}, {"Keepalive_Garbage", DHCP_OPTION_TCPKEEPALIVEGRBG, 7}, {"NIS_Domain", DHCP_OPTION_NISDOMAIN, 1}, {"NIS_Servers", DHCP_OPTION_NISSERVERS, 3}, {"NTP_Servers", DHCP_OPTION_NTPSERVERS, 3}, {"NETBIOS_Name_Srv", DHCP_OPTION_NETBIOSNAMESERV, 3}, {"NETBIOS_Dist_Srv", DHCP_OPTION_NETBIOSDGDIST, 3}, {"NETBIOS_Node_Type", DHCP_OPTION_NETBIOSNODETYPE, 6}, {"NETBIOS_Scope", DHCP_OPTION_NETBIOSSCOPE, 1}, {"X_Window_Font", DHCP_OPTION_X11FONTS, 3}, {"X_Window_Manager", DHCP_OPTION_X11DISPLAYMNGR, 3}, {"Lease_Time", DHCP_OPTION_IPADDRLEASE, 4}, {"Renewal_Time", DHCP_OPTION_RENEWALTIME, 4}, {"Rebinding_Time", DHCP_OPTION_REBINDINGTIME, 4}, {"Netware/IP_Domain", 62, 1}, {"Netware/IP_Options", 63, 2}, {"NIS+_Domain_Name", DHCP_OPTION_NISPLUSDOMAIN, 1}, {"NIS+_Server_Addr", DHCP_OPTION_NISPLUSSERVERS, 3}, {"TFTP_Server_Name", DHCP_OPTION_TFTPSERVER, 1}, {"Boot_File", DHCP_OPTION_BOOTFILE, 1}, {"Home_Agent_Addrs", DHCP_OPTION_MOBILEIPHOME, 3}, {"SMTP_Server", DHCP_OPTION_SMTPSERVER, 3}, {"POP3_Server", DHCP_OPTION_POP3SERVER, 3}, {"NNTP_Server", DHCP_OPTION_NNTPSERVER, 3}, {"WWW_Server", DHCP_OPTION_WWWSERVER, 3}, {"Finger_Server", DHCP_OPTION_FINGERSERVER, 3}, {"IRC_Server", DHCP_OPTION_IRCSERVER, 3}, {"StreetTalk_Server", DHCP_OPTION_STSERVER, 3}, {"STDA_Server", DHCP_OPTION_STDASERVER, 3}, {"NDS_Servers", DHCP_OPTION_NDSSERVERS, 3}, {"NDS_Tree_Name", DHCP_OPTION_NDSTREENAME, 1}, {"NDS_Context", 87, 1}, {"LDAP_URL", DHCP_OPTION_LDAP, 1}, {"Auto_Configure", DHCP_OPTION_AUTO_CONFIG, 7}, {"Name_Service_Search", DHCP_OPTION_NAMESERVICESEARCH, 2}, {"Subnet_Selection", DHCP_OPTION_SUBNETSELECTION, 3}, //{"DNS_Domain_Search", DHCP_OPTION_DOMAINSEARCH, 1}, {"TFTP_Phone_Server", DHCP_OPTION_TFPTSERVERIPADDRESS, 3}, //{"TFTP_Server", DHCP_OPTION_TFPTSERVERIPADDRESS, 3}, {"Call_Server", DHCP_OPTION_CALLSERVERIPADDRESS, 3}, {"Discrimination_String", DHCP_OPTION_DISCRIMINATIONSTRING, 1}, {"RemoteStatisticsServer", DHCP_OPTION_REMOTESTATISTICSSERVER, 3}, {"Phone_Http_Proxy", DHCP_OPTION_HTTPPROXYFORPHONE_SPEC, 3}, {"IP_Phone", 176, 1}, {"Next_Server", DHCP_OPTION_NEXTSERVER, 3} }; void WINAPI ServiceControlHandler(DWORD controlCode) { switch (controlCode) { case SERVICE_CONTROL_INTERROGATE: break; case SERVICE_CONTROL_SHUTDOWN: case SERVICE_CONTROL_STOP: serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; serviceStatus.dwWaitHint = 20000; serviceStatus.dwCheckPoint = 1; SetServiceStatus(serviceStatusHandle, &serviceStatus); SetEvent(stopServiceEvent); return; case SERVICE_CONTROL_PAUSE: break; case SERVICE_CONTROL_CONTINUE: break; default: if (controlCode >= 128 && controlCode <= UCHAR_MAX) break; else break; } SetServiceStatus(serviceStatusHandle, &serviceStatus); } void WINAPI ServiceMain(DWORD /*argc*/, TCHAR* /*argv*/[]) { serviceStatus.dwServiceType = SERVICE_WIN32; serviceStatus.dwCurrentState = SERVICE_STOPPED; serviceStatus.dwControlsAccepted = 0; serviceStatus.dwWin32ExitCode = NO_ERROR; serviceStatus.dwServiceSpecificExitCode = NO_ERROR; serviceStatus.dwCheckPoint = 0; serviceStatus.dwWaitHint = 0; serviceStatusHandle = RegisterServiceCtrlHandler(serviceName, ServiceControlHandler); if (serviceStatusHandle) { serviceStatus.dwCurrentState = SERVICE_START_PENDING; SetServiceStatus(serviceStatusHandle, &serviceStatus); if (!(_beginthread(init, 0, 0) > 0)) { if (cfig.dnsLogLevel || cfig.dhcpLogLevel) { sprintf(logBuff, "Thread Creation Failed"); logMess(logBuff, 1); } } data9 dhcpr; data5 dnsr; tv.tv_sec = 20; tv.tv_usec = 0; stopServiceEvent = CreateEvent(0, FALSE, FALSE, 0); serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); serviceStatus.dwCurrentState = SERVICE_RUNNING; SetServiceStatus(serviceStatusHandle, &serviceStatus); do { network.busy = false; if ((!network.dhcpConn[0].server && !network.dnsUdpConn[0].server) || !network.ready) { Sleep(1000); continue; } FD_ZERO(&readfds); if (dhcpService) { if (network.httpConn.server) FD_SET(network.httpConn.sock, &readfds); for (int i = 0; i < MAX_SERVERS && network.dhcpConn[i].server; i++) FD_SET(network.dhcpConn[i].sock, &readfds); if (cfig.replication) FD_SET(network.dhcpReplConn.sock, &readfds); } if (dnsService) { for (int i = 0; i < MAX_SERVERS && network.dnsUdpConn[i].server; i++) FD_SET(network.dnsUdpConn[i].sock, &readfds); for (int i = 0; i < MAX_SERVERS && network.dnsTcpConn[i].server; i++) FD_SET(network.dnsTcpConn[i].sock, &readfds); FD_SET(network.forwConn.sock, &readfds); } if (select(network.maxFD, &readfds, NULL, NULL, &tv)) { if (network.ready) { network.busy = true; if (dhcpService) { if (network.httpConn.server && FD_ISSET(network.httpConn.sock, &readfds)) { data19 *req = (data19*)calloc(1, sizeof(data19)); if (req) { req->sockLen = sizeof(req->addr); req->sock = accept(network.httpConn.sock, (sockaddr*)&req->addr, &req->sockLen); if (req->sock == INVALID_SOCKET) { sprintf(logBuff, "Accept Failed, Error=%u\n", WSAGetLastError()); logDHCPMess(logBuff, 2); free(req); } else procHTTP(req); } else { sprintf(logBuff, "Memory Error"); logDHCPMess(logBuff, 0); } } if (cfig.replication && FD_ISSET(network.dhcpReplConn.sock, &readfds)) { dhcpr.sockLen = sizeof(dhcpr.addr); dhcpr.bytes = recvfrom(network.dhcpReplConn.sock, dhcpr.raw, sizeof(dhcpr.raw), 0, (sockaddr*)&dhcpr.addr, &dhcpr.sockLen); } } for (int i = 0; i < MAX_SERVERS && network.dhcpConn[i].server; 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].server; i++) { if (FD_ISSET(network.dnsUdpConn[i].sock, &readfds)) { if (gdnmess(&dnsr, i)) { if (dnsr.dnsp->header.rcode == RCODE_NOTIMPL || dnsr.dnsp->header.rcode == RCODE_REFUSED) sdnmess(&dnsr); else if (scanloc(&dnsr)) { if (htons(dnsr.dnsp->header.ancount)) { if (cfig.dnsLogLevel == 2) { if (dnsr.qtype == DNS_TYPE_SOA) sprintf(logBuff, "SOA Sent for zone %s", dnsr.query); else if (dnsr.qtype == DNS_TYPE_NS) sprintf(logBuff, "NS Sent for zone %s", dnsr.query); else if (dnsr.cache.dataType == CACHED) sprintf(logBuff, "%s resolved from Cache to %s", dnsr.query, getResult(&dnsr)); else sprintf(logBuff, "%s resolved Locally to %s", dnsr.query, getResult(&dnsr)); logDNSMess(&dnsr, logBuff, 2); } } else if (dnsr.dnsp->header.rcode == RCODE_NAMEERROR || dnsr.dnsp->header.rcode == RCODE_NOERROR) { dnsr.dnsp->header.rcode = RCODE_NAMEERROR; if (cfig.dnsLogLevel == 2) { sprintf(logBuff, "%s not found", dnsr.query); logDNSMess(&dnsr, logBuff, 2); } } sdnmess(&dnsr); } else if (!fdnmess(&dnsr)) sdnmess(&dnsr); } } } for (int i = 0; i < MAX_SERVERS && network.dnsTcpConn[i].server; i++) { if (FD_ISSET(network.dnsTcpConn[i].sock, &readfds)) { dnsr.sockInd = i; dnsr.sockLen = sizeof(dnsr.addr); errno = 0; dnsr.sock = accept(network.dnsTcpConn[i].sock, (sockaddr*)&dnsr.addr, &dnsr.sockLen); if (dnsr.sock == INVALID_SOCKET) { if (cfig.dnsLogLevel) { sprintf(logBuff, "Accept Failed, Error=%u", WSAGetLastError()); logDHCPMess(logBuff, 1); } } else procTCP(&dnsr); } } if (FD_ISSET(network.forwConn.sock, &readfds)) { if (frdnmess(&dnsr)) { sdnmess(&dnsr); if (cfig.dnsLogLevel == 2) { if (dnsr.cache.dnsIndex < MAX_SERVERS) { if (dnsr.dnsp->header.ancount) { if (getResult(&dnsr)) sprintf(logBuff, "%s resolved from Forwarding server as %s", dnsr.query, tempbuff); else sprintf(logBuff, "%s resolved from Forwarding server", dnsr.query); } else sprintf(logBuff, "%s not found by Forwarding Server", dnsr.query); } else { if (dnsr.dnsp->header.ancount) { if (getResult(&dnsr)) sprintf(logBuff, "%s resolved from Child Server as %s", dnsr.query, tempbuff); else sprintf(logBuff, "%s resolved from Child Server", dnsr.query); } else sprintf(logBuff, "%s not found by Child Server", dnsr.query); } logDNSMess(&dnsr, logBuff, 2); } } } } } } cacheInd = newInd; checkSize(cacheInd); } while (WaitForSingleObject(stopServiceEvent, 0) == WAIT_TIMEOUT); serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; //serviceStatus.dwCheckPoint = 2; //serviceStatus.dwWaitHint = 1000; SetServiceStatus(serviceStatusHandle, &serviceStatus); sprintf(logBuff, "Closing Network Connections..."); logMess(logBuff, 1); closeConn(); sprintf(logBuff, "Dual Server Stopped !\n"); logMess(logBuff, 1); if (cfig.logfile) { fclose(cfig.logfile); cfig.logfile = 0; } WSACleanup(); serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); serviceStatus.dwCurrentState = SERVICE_STOPPED; SetServiceStatus(serviceStatusHandle, &serviceStatus); CloseHandle(stopServiceEvent); stopServiceEvent = 0; } } void closeConn() { if (network.httpConn.server) { closesocket(network.httpConn.sock); } if (dhcpService) { for (int i = 0; i < MAX_SERVERS && network.dhcpConn[i].server; i++) closesocket(network.dhcpConn[i].sock); if (cfig.replication) closesocket(network.dhcpReplConn.sock); } if (dnsService) { for (int i = 0; i < MAX_SERVERS && network.dnsUdpConn[i].server; i++) closesocket(network.dnsUdpConn[i].sock); for (int i = 0; i < MAX_SERVERS && network.dnsTcpConn[i].server; i++) closesocket(network.dnsTcpConn[i].sock); closesocket(network.forwConn.sock); } } void runService() { SERVICE_TABLE_ENTRY serviceTable[] = { {serviceName, ServiceMain}, {0, 0} }; StartServiceCtrlDispatcher(serviceTable); } void showError(DWORD enumber) { LPTSTR lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, enumber, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR)&lpMsgBuf, 0, NULL ); printf("%s\n", lpMsgBuf); } bool stopService(SC_HANDLE service) { if (service) { SERVICE_STATUS serviceStatus; QueryServiceStatus(service, &serviceStatus); if (serviceStatus.dwCurrentState != SERVICE_STOPPED) { ControlService(service, SERVICE_CONTROL_STOP, &serviceStatus); printf("Stopping Service."); for (int i = 0; i < 100; i++) { QueryServiceStatus(service, &serviceStatus); if (serviceStatus.dwCurrentState == SERVICE_STOPPED) { printf("Stopped\n"); return true; } else { Sleep(500); printf("."); } } printf("Failed\n"); return false; } } return true; } void installService() { SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE | SERVICE_START); if (serviceControlManager) { TCHAR path[ _MAX_PATH + 1 ]; if (GetModuleFileName(0, path, sizeof(path) / sizeof(path[0])) > 0) { SC_HANDLE service = CreateService(serviceControlManager, serviceName, displayName, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, path, 0, 0, 0, 0, 0); if (service) { printf("Successfully installed.. !\n"); StartService(service, 0, NULL); CloseServiceHandle(service); } else { showError(GetLastError()); } } CloseServiceHandle(serviceControlManager); } } void uninstallService() { SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CONNECT); if (serviceControlManager) { SC_HANDLE service = OpenService(serviceControlManager, serviceName, SERVICE_QUERY_STATUS | SERVICE_STOP | DELETE); if (service) { if (stopService(service)) { if (DeleteService(service)) printf("Successfully Removed !\n"); else showError(GetLastError()); } else printf("Failed to Stop Service..\n"); CloseServiceHandle(service); } else printf("Service Not Found..\n"); CloseServiceHandle(serviceControlManager); } } int main(int argc, TCHAR* argv[]) { OSVERSIONINFO osvi; osvi.dwOSVersionInfoSize = sizeof(osvi); bool result = GetVersionEx(&osvi); if (result && osvi.dwPlatformId >= VER_PLATFORM_WIN32_NT) { if (argc > 1 && lstrcmpi(argv[1], TEXT("-i")) == 0) { installService(); } else if (argc > 1 && lstrcmpi(argv[1], TEXT("-u")) == 0) { uninstallService(); } else if (argc > 1 && lstrcmpi(argv[1], TEXT("-v")) == 0) { SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CONNECT); bool serviceStopped = true; if (serviceControlManager) { SC_HANDLE service = OpenService(serviceControlManager, serviceName, SERVICE_QUERY_STATUS | SERVICE_STOP); if (service) { serviceStopped = stopService(service); CloseServiceHandle(service); } CloseServiceHandle(serviceControlManager); } if (serviceStopped) runProg(); else printf("Failed to Stop Service\n"); } else runService(); } else if (argc == 1 || lstrcmpi(argv[1], TEXT("-v")) == 0) runProg(); else printf("This option is not available on Windows95/98/ME\n"); return 0; } void runProg() { //printf("%i\n",t); //printf("%i\n",sizeof(data7)); //printf("%d\n",dnsCache[cacheInd].max_size()); verbatim = true; if (!(_beginthread(init, 0, 0) > 0)) { if (cfig.dnsLogLevel || cfig.dhcpLogLevel) { sprintf(logBuff, "Thread Creation Failed"); logMess(logBuff, 1); } } data9 dhcpr; data5 dnsr; //dns request tv.tv_sec = 20; tv.tv_usec = 0; while (true) { //printf("Cache1=%u Cache2=%u Expiry=%u dhcp=%u\n", dnsCache[0].size(),dnsCache[1].size(),dnsAge[ind].size(),dhcpCache.size()); network.busy = false; if ((!network.dhcpConn[0].server && !network.dnsUdpConn[0].server) || !network.ready) { Sleep(1000); continue; } FD_ZERO(&readfds); if (dhcpService) { if (network.httpConn.server) FD_SET(network.httpConn.sock, &readfds); if (cfig.replication) FD_SET(network.dhcpReplConn.sock, &readfds); for (int i = 0; i < MAX_SERVERS && network.dhcpConn[i].server; i++) FD_SET(network.dhcpConn[i].sock, &readfds); } if (dnsService) { FD_SET(network.forwConn.sock, &readfds); for (int i = 0; i < MAX_SERVERS && network.dnsUdpConn[i].server; i++) FD_SET(network.dnsUdpConn[i].sock, &readfds); for (int i = 0; i < MAX_SERVERS && network.dnsTcpConn[i].server; i++) FD_SET(network.dnsTcpConn[i].sock, &readfds); } //printf("dhcpCache=%u,dns0=%u,dns1=%u\n",dhcpCache.size(),dnsCache[0].size(),dnsCache[1].size()); //printf("%i\n",select(USHRT_MAX, &readfds, NULL, NULL, &tv)); //printf("%i\n",select(USHRT_MAX, &readfds, NULL, NULL, &tv)); if (select(network.maxFD, &readfds, NULL, NULL, &tv)) { if (network.ready) { network.busy = true; if (dhcpService) { if (network.httpConn.server && FD_ISSET(network.httpConn.sock, &readfds)) { data19 *req = (data19*)calloc(1, sizeof(data19)); if (req) { req->sockLen = sizeof(req->addr); req->sock = accept(network.httpConn.sock, (sockaddr*)&req->addr, &req->sockLen); if (req->sock == INVALID_SOCKET) { sprintf(logBuff, "Accept Failed, Error=%u\n", WSAGetLastError()); logDHCPMess(logBuff, 2); free(req); } else procHTTP(req); } else { sprintf(logBuff, "Memory Error"); logDHCPMess(logBuff, 0); } } if (cfig.replication && FD_ISSET(network.dhcpReplConn.sock, &readfds)) { //printf("Repl\n"); dhcpr.sockLen = sizeof(dhcpr.addr); dhcpr.bytes = recvfrom(network.dhcpReplConn.sock, dhcpr.raw, sizeof(dhcpr.raw), 0, (sockaddr*)&dhcpr.addr, &dhcpr.sockLen); } for (int i = 0; i < MAX_SERVERS && network.dhcpConn[i].server; 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].server; i++) { if (FD_ISSET(network.dnsUdpConn[i].sock, &readfds)) { if (gdnmess(&dnsr, i)) //-- get dns query { if (dnsr.dnsp->header.rcode == RCODE_NOTIMPL || dnsr.dnsp->header.rcode == RCODE_REFUSED) { sdnmess(&dnsr); } else if (scanloc(&dnsr)) //-- solve domain name locally { if (htons(dnsr.dnsp->header.ancount)) //-- if there are answers, print a message. { if (dnsr.qtype == DNS_TYPE_SOA) printf("SOA Sent for zone %s\n", dnsr.query); else if (dnsr.qtype == DNS_TYPE_NS) printf("NS Sent for zone %s\n", dnsr.query); else if (dnsr.cache.dataType == CACHED) printf("%s resolved from Cache to %s\n", dnsr.query, getResult(&dnsr)); else printf("%s resolved Locally to %s\n", dnsr.query, getResult(&dnsr)); } //-- else: cannot find the IP of the domain name, set response code as RCODE_NAMEERROR and print a message else if (dnsr.dnsp->header.rcode == RCODE_NAMEERROR || dnsr.dnsp->header.rcode == RCODE_NOERROR) { dnsr.dnsp->header.rcode = RCODE_NAMEERROR; printf("%s not found\n", dnsr.query); } sdnmess(&dnsr); //-- send dns messages back to clients } else if (!fdnmess(&dnsr)) //-- forward to child server sdnmess(&dnsr); } } } for (int i = 0; i < MAX_SERVERS && network.dnsTcpConn[i].server; i++) { if (FD_ISSET(network.dnsTcpConn[i].sock, &readfds)) { dnsr.sockInd = i; dnsr.sockLen = sizeof(dnsr.addr); errno = 0; dnsr.sock = accept(network.dnsTcpConn[i].sock, (sockaddr*)&dnsr.addr, &dnsr.sockLen); if (dnsr.sock == INVALID_SOCKET) printf("Accept Failed, Error=%u", WSAGetLastError()); else procTCP(&dnsr); } } if (FD_ISSET(network.forwConn.sock, &readfds)) { if (frdnmess(&dnsr)) //-- get the forward response DNS message { sdnmess(&dnsr); //-- send the DNS result back to clients //-- print results if (dnsr.cache.dnsIndex < MAX_SERVERS) { if (dnsr.dnsp->header.ancount) { if (getResult(&dnsr)) printf("%s resolved from Forwarding server as %s\n", dnsr.query, tempbuff); else printf("%s resolved from Forwarding server\n", dnsr.query); } else printf("%s not found by Forwarding Server\n", dnsr.query); } else { if (dnsr.dnsp->header.ancount) { if (getResult(&dnsr)) printf("%s resolved from Child Server as %s\n", dnsr.query, tempbuff); else printf("%s resolved from Child Server\n", dnsr.query); } else printf("%s not found by Child Server\n", dnsr.query); } } } } } cacheInd = newInd; checkSize(cacheInd); } } sprintf(logBuff, "Closing Network Connections..."); logMess(logBuff, 1); closeConn(); sprintf(logBuff, "Dual Server Stopped !\n"); logMess(logBuff, 1); if (cfig.logfile) { fclose(cfig.logfile); cfig.logfile = 0; } WSACleanup(); } bool chkQu(char *query) { if (strlen(query) >= 255) return 0; while (true) { char *dp = strchr(query, '.'); if (dp) { WORD size = (DWORD)dp - (DWORD)query; if (size >= 64) return 0; query += (size + 1); } else if (strlen(query) >= 64) return 0; else return 1; } } WORD fQu(char *query, dnsPacket *mess, char *raw) { BYTE *xname = (BYTE*)query; BYTE *xraw = (BYTE*)raw; WORD retvalue = 0; bool goneout = false; while (true) { BYTE 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 = (BYTE*)mess + size; } } *xname = 0; if (!goneout) retvalue++; return retvalue; } WORD qLen(char *query) { WORD fullsize = 1; while (true) { char *i = strchr(query, '.'); if (i != NULL) { int size = (DWORD)i - (DWORD)query; query += (size + 1); fullsize += (size + 1); } else { int size = strlen(query); if (size) fullsize += (size + 1); break; } } //printf("%i\n",fullsize); return fullsize; } WORD pQu(char *raw, char *query) { WORD fullsize = 1; while (true) { char *i = strchr(query, '.'); if (i != NULL) { int size = (DWORD)i - (DWORD)query; *raw = size; raw++; memcpy(raw, query, size); raw += size; query += (size + 1); fullsize += (size + 1); } else { int size = strlen(query); if (size) { *raw = size; raw++; strcpy(raw, query); fullsize += (size + 1); } break; } } //printf("%i\n",fullsize); return fullsize; } WORD fUShort(void *raw) { return ntohs(*(WORD*)raw); } DWORD fULong(void *raw) { return ntohl(*(DWORD*)raw); } DWORD fIP(void *raw) { return (*(DWORD*)raw); } BYTE pUShort(void *raw, WORD data) { *((WORD*)raw) = htons(data); return 2; } BYTE pULong(void *raw, DWORD data) { *((DWORD*)raw) = htonl(data); return 4; } BYTE pIP(void *raw, DWORD data) { *((DWORD*)raw) = data; return 4; } 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; } void addRRExt(data5 *req) { //printf("%u=%u\n", req->cache.dataType, CACHED); WORD xid = req->dnsp->header.xid; if (strcasecmp(req->cname, req->query)) { dnsPacket *packet; if (req->cache.dataType == CACHED && req->cache.response) packet = (dnsPacket*)req->cache.response; else { memcpy(req->temp, req->dnsp, req->bytes); packet = (dnsPacket*)req->temp; } 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->data = &req->dnsp->data; req->data += pQu(req->data, req->query); req->data += pUShort(req->data, DNS_TYPE_A); req->data += pUShort(req->data, DNS_CLASS_IN); req->data += pQu(req->data, req->query); req->data += pUShort(req->data, DNS_TYPE_CNAME); req->data += pUShort(req->data, DNS_CLASS_IN); req->data += pULong(req->data, cfig.ttl); req->data += pUShort(req->data, qLen(req->cname)); req->data += pQu(req->data, req->cname); char *dp = &packet->data; for (int i = 1; i <= ntohs(packet->header.qdcount); i++) { dp += fQu(req->cname, packet, dp); dp += 4; } WORD dl = 0; for (int i = 1; i <= ntohs(packet->header.ancount); i++) { dp += fQu(req->cname, packet, dp); req->data += pQu(req->data, req->cname); memcpy(req->data, dp, 8); req->data += 8; int type = fUShort(dp); dp += 2; //type dp += 2; //class dp += 4; //ttl WORD zLen = fUShort(dp); dp += 2; //datalength switch (type) { case DNS_TYPE_A: req->data += pUShort(req->data, zLen); req->data += pULong(req->data, fULong(dp)); break; case DNS_TYPE_CNAME: fQu(req->cname, packet, dp); dl = pQu(req->data + 2, req->cname); req->data += pUShort(req->data, dl); req->data += dl; break; } dp += zLen; req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1); } req->bytes = (DWORD)req->data - (DWORD)req->raw; } else if (req->cache.dataType == CACHED && req->cache.response) { memcpy(req->dnsp, req->cache.response, req->cache.bytes); req->dnsp->header.xid = xid; req->bytes = req->cache.bytes; } } void addRRA(data5 *req) { if (strcasecmp(req->query, req->cname)) { req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1); req->data += pQu(req->data, req->query); req->data += pUShort(req->data, DNS_TYPE_CNAME); req->data += pUShort(req->data, DNS_CLASS_IN); req->data += pULong(req->data, cfig.ttl); req->data += pUShort(req->data, qLen(req->cname)); req->data += pQu(req->data, req->cname); } for (;req->iterBegin != dnsCache[cacheInd].end(); req->iterBegin++) { data7 *cache = req->iterBegin->second; if (strcasecmp(cache->mapname, req->mapname)) break; if (cache->ip) { req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1); req->data += pQu(req->data, req->cname); req->data += pUShort(req->data, DNS_TYPE_A); req->data += pUShort(req->data, DNS_CLASS_IN); if (cache->dataType == LOCAL_A) { if (cache->expiry == LONG_MAX) req->data += pULong(req->data, ULONG_MAX); else if ((DWORD)(cache->expiry - time(NULL)) >= cfig.ttl) req->data += pULong(req->data, cfig.ttl - 1); else req->data += pULong(req->data, (cache->expiry - time(NULL))); } else req->data += pULong(req->data, cfig.ttl); req->data += pUShort(req->data, 4); req->data += pIP(req->data, cache->ip); } } req->bytes = (DWORD)req->data - (DWORD)req->raw; } void addRRPtr(data5 *req) { for (;req->iterBegin != dnsCache[cacheInd].end(); req->iterBegin++) { data7 *cache = req->iterBegin->second; if (strcasecmp(cache->mapname, req->mapname)) break; req->data += pQu(req->data, req->query); req->data += pUShort(req->data, DNS_TYPE_PTR); req->data += pUShort(req->data, DNS_CLASS_IN); req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1); if (cache->dataType == LOCAL_PTR_AUTH || cache->dataType == LOCAL_PTR_NAUTH) { if (cache->expiry == LONG_MAX) req->data += pULong(req->data, ULONG_MAX); else if ((DWORD)(cache->expiry - time(NULL)) >= cfig.ttl) req->data += pULong(req->data, cfig.ttl - 1); else req->data += pULong(req->data, (cache->expiry - time(NULL))); } else req->data += pULong(req->data, cfig.ttl); if (!strchr(cache->hostname, '.')) sprintf(req->cname, "%s.%s", cache->hostname, cfig.zone); else strcpy(req->cname, cache->hostname); req->data += pUShort(req->data, qLen(req->cname)); req->data += pQu(req->data, req->cname); } req->bytes = (DWORD)req->data - (DWORD)req->raw; } void addRRServerA(data5 *req) { if (strcasecmp(req->query, req->cname)) { req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1); req->data += pQu(req->data, req->query); req->data += pUShort(req->data, DNS_TYPE_CNAME); req->data += pUShort(req->data, DNS_CLASS_IN); req->data += pULong(req->data, cfig.ttl); req->data += pUShort(req->data, qLen(req->cname)); req->data += pQu(req->data, req->cname); } req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1); req->data += pQu(req->data, req->cname); req->data += pUShort(req->data, DNS_TYPE_A); req->data += pUShort(req->data, DNS_CLASS_IN); req->data += pULong(req->data, cfig.ttl); req->data += pUShort(req->data, 4); req->data += pIP(req->data, network.dnsUdpConn[req->sockInd].server); for (;req->iterBegin != dnsCache[cacheInd].end(); req->iterBegin++) { data7 *cache = req->iterBegin->second; if (strcasecmp(cache->mapname, req->mapname)) break; if (cache->ip && cache->ip != network.dnsUdpConn[req->sockInd].server) { req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1); req->data += pQu(req->data, req->cname); req->data += pUShort(req->data, DNS_TYPE_A); req->data += pUShort(req->data, DNS_CLASS_IN); req->data += pULong(req->data, cfig.ttl); req->data += pUShort(req->data, 4); req->data += pIP(req->data, cache->ip); } } req->bytes = (DWORD)req->data - (DWORD)req->raw; } void addRRWildA(data5 *req, DWORD ip) { req->dnsp->header.ancount = htons(1); req->data += pQu(req->data, req->query); req->data += pUShort(req->data, DNS_TYPE_A); req->data += pUShort(req->data, DNS_CLASS_IN); req->data += pULong(req->data, cfig.ttl); req->data += pUShort(req->data, 4); req->data += pIP(req->data, ip); req->bytes = (DWORD)req->data - (DWORD)req->raw; } void addRRLocalhostA(data5 *req) { if (strcasecmp(req->query, req->mapname)) { req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1); req->data += pQu(req->data, req->query); req->data += pUShort(req->data, DNS_TYPE_CNAME); req->data += pUShort(req->data, DNS_CLASS_IN); req->data += pULong(req->data, cfig.ttl); req->data += pUShort(req->data, qLen(req->mapname)); req->data += pQu(req->data, req->mapname); } req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1); req->data += pQu(req->data, req->mapname); req->data += pUShort(req->data, DNS_TYPE_A); req->data += pUShort(req->data, DNS_CLASS_IN); req->data += pULong(req->data, cfig.ttl); req->data += pUShort(req->data, 4); req->data += pIP(req->data, req->cache.ip); req->bytes = (DWORD)req->data - (DWORD)req->raw; } void addRRLocalhostPtr(data5 *req) { req->data += pQu(req->data, req->query); req->data += pUShort(req->data, DNS_TYPE_PTR); req->data += pUShort(req->data, DNS_CLASS_IN); req->dnsp->header.ancount = htons(1); req->data += pULong(req->data, cfig.ttl); req->data += pUShort(req->data, qLen(req->cache.hostname)); req->data += pQu(req->data, req->cache.hostname); req->bytes = (DWORD)req->data - (DWORD)req->raw; } void addRRMX(data5 *req) { req->dnsp->header.ancount = 0; if (cfig.mxCount[cacheInd]) { for (int m = 0; m < cfig.mxCount[cacheInd]; m++) { //req->data += pQu(req->data, req->query); req->data += pQu(req->data, cfig.zone); req->data += pUShort(req->data, DNS_TYPE_MX); req->data += pUShort(req->data, DNS_CLASS_IN); req->data += pULong(req->data, cfig.ttl); req->data += pUShort(req->data, strlen(cfig.mxServers[cacheInd][m].hostname) + 4); req->data += pUShort(req->data, cfig.mxServers[cacheInd][m].pref); req->data += pQu(req->data, cfig.mxServers[cacheInd][m].hostname); req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1); } } else req->dnsp->header.rcode = RCODE_NAMEERROR; req->bytes = (DWORD)req->data - (DWORD)req->raw; } void addRRNSA(data5 *req) { //printf("%s=%u\n", cfig.ns, cfig.expireTime); if (cfig.authorized && cfig.expireTime > time(NULL)) { req->dnsp->header.at = 1; req->dnsp->header.aa = 1; req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1); req->data += pQu(req->data, cfig.zone); req->data += pUShort(req->data, DNS_TYPE_NS); req->data += pUShort(req->data, DNS_CLASS_IN); req->data += pULong(req->data, cfig.expire); req->data += pUShort(req->data, qLen(cfig.ns)); req->data += pQu(req->data, cfig.ns); req->data += pQu(req->data, cfig.servername_fqn); req->data += pUShort(req->data, DNS_TYPE_A); req->data += pUShort(req->data, DNS_CLASS_IN); req->data += pULong(req->data, cfig.expire); req->data += pUShort(req->data, 4); req->data += pIP(req->data, cfig.nsIP); } req->bytes = (DWORD)req->data - (DWORD)req->raw; } void addRRNSPtr(data5 *req) { if (cfig.authorized && cfig.expireTime > time(NULL)) { req->dnsp->header.at = 1; req->dnsp->header.aa = 1; req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1); req->data += pQu(req->data, cfig.authority); req->data += pUShort(req->data, DNS_TYPE_NS); req->data += pUShort(req->data, DNS_CLASS_IN); req->data += pULong(req->data, cfig.expire); req->data += pUShort(req->data, qLen(cfig.ns)); req->data += pQu(req->data, cfig.ns); req->data += pQu(req->data, cfig.ns); req->data += pUShort(req->data, DNS_TYPE_A); req->data += pUShort(req->data, DNS_CLASS_IN); req->data += pULong(req->data, cfig.expire); req->data += pUShort(req->data, 4); req->data += pIP(req->data, cfig.nsIP); } req->bytes = (DWORD)req->data - (DWORD)req->raw; } void addRRSOA(data5 *req, DWORD serial) { if (cfig.authorized) { req->dnsp->header.at = 1; req->dnsp->header.aa = 1; req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1); req->data += pQu(req->data, req->query); req->data += pUShort(req->data, DNS_TYPE_SOA); req->data += pUShort(req->data, DNS_CLASS_IN); req->data += pULong(req->data, cfig.ttl); char *data = req->data; req->data += 2; req->data += pQu(req->data, cfig.ns); sprintf(req->cname, "hostmaster.%s", cfig.zone); req->data += pQu(req->data, req->cname); req->data += pULong(req->data, serial); req->data += pULong(req->data, cfig.refresh); req->data += pULong(req->data, cfig.retry); req->data += pULong(req->data, cfig.expire); req->data += pULong(req->data, cfig.minimum); pUShort(data, ((DWORD)req->data - (DWORD)data) - 2); } req->bytes = (DWORD)req->data - (DWORD)req->raw; } void addAuth(data5 *req) { if (cfig.authorized && cfig.expireTime > time(NULL)) { req->dnsp->header.at = 1; req->dnsp->header.aa = 1; req->dnsp->header.nscount = htons(1); if (req->qtype == DNS_TYPE_PTR) req->data += pQu(req->data, cfig.authority); else req->data += pQu(req->data, cfig.zone); req->data += pUShort(req->data, DNS_TYPE_NS); req->data += pUShort(req->data, DNS_CLASS_IN); if (cfig.expire >= LONG_MAX) req->data += pULong(req->data, ULONG_MAX); else req->data += pULong(req->data, cfig.expire); req->data += pUShort(req->data, qLen(cfig.ns)); req->data += pQu(req->data, cfig.ns); addRRAd(req); } req->bytes = (DWORD)req->data - (DWORD)req->raw; } void addRRAd(data5 *req) { if (cfig.authorized && cfig.expireTime > time(NULL)) { req->dnsp->header.adcount = htons(1); req->data += pQu(req->data, cfig.ns); req->data += pUShort(req->data, DNS_TYPE_A); req->data += pUShort(req->data, DNS_CLASS_IN); req->data += pULong(req->data, cfig.ttl); req->data += pUShort(req->data, 4); req->data += pIP(req->data, cfig.nsIP); } req->bytes = (DWORD)req->data - (DWORD)req->raw; } void addRRAOne(data5 *req) { req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1); if (!strchr(req->iterBegin->second->mapname, '.')) sprintf(req->cname, "%s.%s", req->iterBegin->second->mapname, cfig.zone); else strcpy(req->cname, req->iterBegin->second->mapname); req->data += pQu(req->data, req->cname); req->data += pUShort(req->data, DNS_TYPE_A); req->data += pUShort(req->data, DNS_CLASS_IN); if (req->iterBegin->second->dataType == LOCAL_A) { if (req->iterBegin->second->expiry == LONG_MAX) req->data += pULong(req->data, ULONG_MAX - 1); else if ((DWORD)(req->iterBegin->second->expiry - time(NULL)) >= cfig.ttl) req->data += pULong(req->data, cfig.ttl - 1); else req->data += pULong(req->data, (req->iterBegin->second->expiry - time(NULL))); } else req->data += pULong(req->data, cfig.ttl); req->data += pUShort(req->data, 4); req->data += pIP(req->data, req->iterBegin->second->ip); req->bytes = (DWORD)req->data - (DWORD)req->raw; } void addRRPtrOne(data5 *req) { req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1); strcpy(req->cname, req->iterBegin->second->mapname); strcat(req->cname, arpa); req->data += pQu(req->data, req->cname); req->data += pUShort(req->data, DNS_TYPE_PTR); req->data += pUShort(req->data, DNS_CLASS_IN); if (req->iterBegin->second->dataType == LOCAL_PTR_AUTH || req->iterBegin->second->dataType == LOCAL_PTR_NAUTH) { if (req->iterBegin->second->expiry == LONG_MAX) req->data += pULong(req->data, ULONG_MAX - 1); else if ((DWORD)(req->iterBegin->second->expiry - time(NULL)) >= cfig.ttl) req->data += pULong(req->data, cfig.ttl - 1); else req->data += pULong(req->data, (req->iterBegin->second->expiry - time(NULL))); } else req->data += pULong(req->data, cfig.ttl); if (!strchr(req->iterBegin->second->hostname, '.')) sprintf(req->cname, "%s.%s", req->iterBegin->second->hostname, cfig.zone); else strcpy(req->cname, req->iterBegin->second->hostname); req->data += pUShort(req->data, qLen(req->cname)); req->data += pQu(req->data, req->cname); req->bytes = (DWORD)req->data - (DWORD)req->raw; } void addRRSTAOne(data5 *req) { req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1); if (!strchr(req->iterBegin->second->mapname, '.')) sprintf(req->cname, "%s.%s", req->iterBegin->second->mapname, cfig.zone); else strcpy(req->cname, req->iterBegin->second->mapname); req->data += pQu(req->data, req->cname); req->data += pUShort(req->data, DNS_TYPE_A); req->data += pUShort(req->data, DNS_CLASS_IN); req->data += pULong(req->data, cfig.ttl); req->data += pUShort(req->data, 4); req->data += pIP(req->data, req->iterBegin->second->ip); req->bytes = (DWORD)req->data - (DWORD)req->raw; } void addRRCNOne(data5 *req) { req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1); if (!strchr(req->iterBegin->second->mapname, '.')) sprintf(req->cname, "%s.%s", req->iterBegin->second->mapname, cfig.zone); else strcpy(req->cname, req->iterBegin->second->mapname); req->data += pQu(req->data, req->cname); req->data += pUShort(req->data, DNS_TYPE_CNAME); req->data += pUShort(req->data, DNS_CLASS_IN); req->data += pULong(req->data, cfig.ttl); if (!strchr(req->iterBegin->second->hostname, '.')) sprintf(req->cname, "%s.%s", req->iterBegin->second->hostname, cfig.zone); else strcpy(req->cname, req->iterBegin->second->hostname); req->data += pUShort(req->data, qLen(req->cname)); req->data += pQu(req->data, req->cname); req->bytes = (DWORD)req->data - (DWORD)req->raw; } void addRRMXOne(data5 *req, BYTE m) { //req->data += pQu(req->data, req->query); req->data += pQu(req->data, cfig.zone); req->data += pUShort(req->data, DNS_TYPE_MX); req->data += pUShort(req->data, DNS_CLASS_IN); req->data += pULong(req->data, cfig.ttl); req->data += pUShort(req->data, strlen(cfig.mxServers[cacheInd][m].hostname) + 4); req->data += pUShort(req->data, cfig.mxServers[cacheInd][m].pref); req->data += pQu(req->data, cfig.mxServers[cacheInd][m].hostname); req->dnsp->header.ancount = htons(htons(req->dnsp->header.ancount) + 1); req->bytes = (DWORD)req->data - (DWORD)req->raw; } void procHTTP(data19 *req) { 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)); time_t t = time(NULL); BYTE bp_chaddr[16]; dhcpMap::iterator p; int ind = 0; DWORD iip = 0; data7 *dhcpEntry = NULL; data7 *cache = NULL; DWORD memSize = 2048 + (135 * dhcpCache.size()) + ((cfig.dhcpSize - dhcpCache.size()) * 26); req->buffer = (char*)calloc(1, memSize); if (!req->buffer) { sprintf(logBuff, "Memory Error"); logDHCPMess(logBuff, 0); closesocket(req->sock); free(req); return; } errno = 0; req->bytes = recv(req->sock, req->buffer, memSize, 0); errno = WSAGetLastError(); if (errno) { sprintf(logBuff, "Client %s, HTTP Message Receive failed, Error %u", IP2String(tempbuff, req->addr.sin_addr.s_addr), errno); logDHCPMess(logBuff, 1); free(req->buffer); closesocket(req->sock); free(req); return; } else if (cfig.dnsLogLevel >= 2) { //sprintf(logBuff, "Client %s, HTTP Request Received", IP2String(tempbuff, req->addr.sin_addr.s_addr)); //logDHCPMess(logBuff, 2); //printf("%s\n", req->buffer); } char *fp = req->buffer; char *maxData = req->buffer + (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, "<html>\n<head>\n<META HTTP-EQUIV=\"Refresh\" CONTENT=\"60\">\n<META HTTP-EQUIV=\"Cache-Control\" CONTENT=\"no-cache\">\n</head>\n"); fp += sprintf(fp, "<body bgcolor=\"#cccccc\">\n<h2>%s</h2>\n", sVersion); fp += sprintf(fp, "<table id=\"active\" border=\"1\" width=\"800\" bgcolor=\"#b8b8b8\">\n"); fp += sprintf(fp, "<tr><th colspan=\"5\"><font size=\"5\"><i>Active Leases</i></font></th></tr>\n"); fp += sprintf(fp, "<tr><th>Mac Address</th><th>IP</th><th>Lease Expiry</th><th>Hostname (first 20 chars)</th><th>Vendor Class Identifier</th></tr>\n"); for (p = dhcpCache.begin(); p != dhcpCache.end() && fp < maxData; p++) { if ((dhcpEntry = p->second) && dhcpEntry->local && dhcpEntry->expiry >= t) { fp += sprintf(fp, "<tr>"); BYTE bp_hlen = fromUUE(bp_chaddr, dhcpEntry->mapname); fp += sprintf(fp, line200, hex2String(tempbuff, bp_chaddr, bp_hlen, ':')); fp += sprintf(fp, line200, IP2String(tempbuff, dhcpEntry->ip)); if (dhcpEntry->expiry >= LONG_MAX) fp += sprintf(fp, line200, "Infinity"); else { tm *ttm = localtime(&dhcpEntry->expiry); strftime(tempbuff, sizeof(tempbuff), "%d-%b-%y %X", ttm); fp += sprintf(fp, line200, tempbuff); } cache = findEntry(cacheInd, IP2String(tempbuff, htonl(dhcpEntry->ip))); if (cache && cache->hostname) { if (strlen(cache->hostname) <= 20) fp += sprintf(fp, line200, cache->hostname); else { memcpy(tempbuff, cache->hostname, 20); tempbuff[20] = 0; fp += sprintf(fp, line200, tempbuff); } } else fp += sprintf(fp, line200, " "); fp += sprintf(fp, "<td align = \"center\">"); fp += sprintf(fp, "%s ", vci[dhcpEntry->ip].vci); fp += sprintf(fp, "</td>"); fp += sprintf(fp, "</tr>\n"); } } fp += sprintf(fp, "</table>\n<br>\n<table id=\"freedynamic\" border=\"1\" width=\"600\" bgcolor=\"#b8b8b8\">\n"); fp += sprintf(fp, "<tr><th colspan=\"5\"><font size=\"5\"><i>Free Dynamic Leases</i></font></th></tr>\n"); BYTE colNum = 0; for (char rangeInd = 0; rangeInd < MAX_RANGES && cfig.dhcpRanges[rangeInd].rangeStart && fp < maxData; rangeInd++) { for (ind = 0, iip = cfig.dhcpRanges[rangeInd].rangeStart; iip <= cfig.dhcpRanges[rangeInd].rangeEnd; iip++, ind++) { if (cfig.dhcpRanges[rangeInd].expiry[ind] < t) { if (!colNum) { fp += sprintf(fp, "<tr>"); colNum = 1; } else if (colNum < 5) colNum++; else { fp += sprintf(fp, "</tr>\n<tr>"); colNum = 1; } fp += sprintf(fp, line200, IP2String(tempbuff, htonl(iip))); } } } if (colNum) fp += sprintf(fp, "</tr>\n"); fp += sprintf(fp, "</table>\n<br>\n<table id=\"freestatic\" border=\"1\" width=\"600\" bgcolor=\"#b8b8b8\">\n"); fp += sprintf(fp, "<tr><th colspan=\"5\"><font size=\"5\"><i>Free Static Leases</i></font></th></tr>\n"); fp += sprintf(fp, "<tr><th>Mac Address</th><th>IP</th><th>Mac Address</th><th>IP</th></tr>\n"); colNum = 0; for (p = dhcpCache.begin(); p != dhcpCache.end() && fp < maxData; p++) { if ((dhcpEntry = p->second) && dhcpEntry->fixed && dhcpEntry->expiry < t) { if (!colNum) { fp += sprintf(fp, "<tr>"); colNum = 1; } else if (colNum == 1) { colNum = 2; } else if (colNum == 2) { fp += sprintf(fp, "</tr>\n<tr>"); colNum = 1; } BYTE bp_hlen = fromUUE(bp_chaddr, dhcpEntry->mapname); fp += sprintf(fp, line200, hex2String(tempbuff, bp_chaddr, bp_hlen, ':')); fp += sprintf(fp, line200, IP2String(tempbuff, dhcpEntry->ip)); } } if (colNum) fp += sprintf(fp, "</tr>\n"); fp += sprintf(fp, "</table>\n</body>\n</html>"); memcpy((contentStart - 12), tempbuff, sprintf(tempbuff, "%u", (fp - contentStart))); req->bytes = fp - req->buffer; if (!(_beginthread(sendHTTP, 0, (void*)req) > 0)) { if (cfig.dnsLogLevel) { sprintf(logBuff, "Thread Creation Failed"); logDHCPMess(logBuff, 1); } send(req->sock, req->buffer, req->bytes, 0); closesocket(req->sock); free(req->buffer); free(req); } return; } void sendHTTP(void *lpParam) { //printf("Here\n"); data19 *req = (data19*)lpParam; send(req->sock, req->buffer, req->bytes, 0); Sleep(1000*(20)); closesocket(req->sock); free(req->buffer); free(req); _endthread(); return; } void procTCP(data5 *req) { 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->sock, req->raw, true); //printf("%u\n",req->bytes); if (req->bytes < 2) { sprintf(logBuff, "Error Getting TCP DNS Message"); logDNSMess(logBuff, 1); closesocket(req->sock); return; } WORD pktSize = fUShort(req->raw); req->data = req->raw + 2; req->dnsp = (dnsPacket*)(req->data); 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); addRRNone(req); req->dnsp->header.rcode = RCODE_NOTIMPL; sTCPmess(req); closesocket(req->sock); return; } if (req->dnsp->header.qr != 0 || ntohs(req->dnsp->header.qdcount) != 1 || ntohs(req->dnsp->header.ancount)) { sprintf(logBuff, "DNS Query Format Error"); logTCPMess(req, logBuff, 1); addRRNone(req); req->dnsp->header.rcode = RCODE_FORMATERROR; sTCPmess(req); closesocket(req->sock); return; } req->data = &req->dnsp->data; for (int i = 1; i <= ntohs(req->dnsp->header.qdcount); i++) { req->data += fQu(req->query, req->dnsp, req->data); req->qtype = fUShort(req->data); req->data += 2; req->qclass = fUShort(req->data); req->data += 2; } if (req->qclass != DNS_CLASS_IN) { sprintf(logBuff, "DNS Class %u not supported", req->qclass); logTCPMess(req, logBuff, 1); addRRNone(req); req->dnsp->header.rcode = RCODE_NOTIMPL; sTCPmess(req); closesocket(req->sock); return; } if (!req->qtype) { sprintf(logBuff, "missing query type"); logTCPMess(req, logBuff, 1); addRRNone(req); req->dnsp->header.rcode = RCODE_FORMATERROR; sTCPmess(req); closesocket(req->sock); return; } bool allowed = false; DWORD ip = req->addr.sin_addr.s_addr; for (int i = 0; i < MAX_SERVERS; i++) { if (ip == cfig.zoneServers[i] || ip == network.allServers[i]) { allowed = true; break; } } if (!allowed) { sprintf(logBuff, "DNS TCP Query, Access Denied"); logTCPMess(req, logBuff, 1); addRRNone(req); req->dnsp->header.rcode = RCODE_REFUSED; sTCPmess(req); closesocket(req->sock); return; } strcpy(req->mapname, req->query); strcpy(req->cname, req->query); bool AXFRError = false; if (req->qtype != DNS_TYPE_NS && req->qtype != DNS_TYPE_SOA && req->qtype != DNS_TYPE_AXFR && req->qtype != DNS_TYPE_IXFR) { addRRNone(req); req->dnsp->header.rcode = RCODE_NOTIMPL; sTCPmess(req); sprintf(logBuff, "DNS TCP Query Type %s not supported", strqtype(tempbuff, req->qtype)); logTCPMess(req, logBuff, 1); } else if (strcasecmp(req->mapname, cfig.zone) && strcasecmp(req->mapname, cfig.authority)) { addRRNone(req); req->dnsp->header.rcode = RCODE_NOTIMPL; sTCPmess(req); sprintf(logBuff, "%s, Forwarding TCP query not supported", req->query); logTCPMess(req, logBuff, 1); } else if (!cfig.authorized) { addRRNone(req); req->dnsp->header.rcode = RCODE_NOTAUTH; sTCPmess(req); sprintf(logBuff, "Server is not authorized for zone %s", req->query); logTCPMess(req, logBuff, 1); } else if (!dhcpService && cfig.expireTime < time(NULL)) { addRRNone(req); req->dnsp->header.rcode = RCODE_NOTAUTH; sTCPmess(req); sprintf(logBuff, "Zone %s expired", req->query); logTCPMess(req, logBuff, 1); } else { switch (req->qtype) { case DNS_TYPE_SOA: if (!strcasecmp(req->query, cfig.zone)) { addRRNone(req); req->dnsp->header.aa = 0; req->dnsp->header.at = 0; addRRSOA(req, cfig.serial1); sTCPmess(req); sprintf(logBuff, "SOA Sent for zone %s", req->query); logTCPMess(req, logBuff, 2); } else if (!strcasecmp(req->query, cfig.authority)) { addRRNone(req); req->dnsp->header.aa = 0; req->dnsp->header.at = 0; addRRSOA(req, cfig.serial2); sTCPmess(req); sprintf(logBuff, "SOA Sent for zone %s", req->query); logTCPMess(req, logBuff, 2); } break; case DNS_TYPE_NS: if (!strcasecmp(req->mapname, cfig.zone)) { addRRNone(req); req->dnsp->header.aa = 0; req->dnsp->header.at = 0; addRRNSA(req); addRRAd(req); sTCPmess(req); sprintf(logBuff, "NS Sent for Zone %s", req->query); logTCPMess(req, logBuff, 2); } else if (!strcasecmp(req->query, cfig.authority)) { addRRNone(req); req->dnsp->header.aa = 0; req->dnsp->header.at = 0; addRRNSPtr(req); addRRAd(req); sTCPmess(req); sprintf(logBuff, "NS Sent for Zone", req->query); logTCPMess(req, logBuff, 2); } break; case DNS_TYPE_AXFR: case DNS_TYPE_IXFR: if (!strcasecmp(req->mapname, cfig.zone)) { DWORD tempserial = cfig.serial1; WORD records = 0; addRRNone(req); req->data = &req->dnsp->data; req->dnsp->header.qdcount = 0; addRRSOA(req, cfig.serial1); if (!sTCPmess(req)) { AXFRError = true; break; } else records++; addRRNone(req); req->data = &req->dnsp->data; req->dnsp->header.qdcount = 0; addRRNSA(req); if (!sTCPmess(req)) { AXFRError = true; break; } else records++; time_t t = time(NULL); req->iterBegin = dnsCache[cacheInd].begin(); while (!AXFRError && req->iterBegin != dnsCache[cacheInd].end()) { addRRNone(req); req->dnsp->header.qdcount = 0; req->data = &req->dnsp->data; if (req->iterBegin->second->expiry > t) { switch (req->iterBegin->second->dataType) { case LOCAL_A: addRRAOne(req); break; case SERVER_A: if (network.dnsTcpConn[req->sockInd].server == req->iterBegin->second->ip) addRRSTAOne(req); else { req->iterBegin++; continue; } break; case STATIC_A_AUTH: //case STATIC_A_NAUTH: addRRSTAOne(req); break; case LOCAL_CNAME: case EXT_CNAME: addRRCNOne(req); break; default: req->iterBegin++; continue; } if (tempserial != cfig.serial1) { AXFRError = true; break; } if (!sTCPmess(req)) { AXFRError = true; break; } else records++; } req->iterBegin++; } for (int m = 0; m < cfig.mxCount[cacheInd]; m++) { addRRNone(req); req->dnsp->header.qdcount = 0; req->data = &req->dnsp->data; addRRMXOne(req, m); if (tempserial != cfig.serial1) { AXFRError = true; break; } if (!sTCPmess(req)) { AXFRError = true; break; } else records++; } addRRNone(req); req->data = &req->dnsp->data; req->dnsp->header.qdcount = 0; addRRSOA(req, cfig.serial1); if (!AXFRError && tempserial == cfig.serial1) { if (sTCPmess(req)) { records++; sprintf(logBuff, "Zone %s with %u RRs Sent", req->query, records); logTCPMess(req, logBuff, 2); } } } else if (!strcasecmp(req->query, cfig.authority)) { DWORD tempserial = cfig.serial2; WORD records = 0; addRRNone(req); req->data = &req->dnsp->data; req->dnsp->header.qdcount = 0; addRRSOA(req, cfig.serial2); if (!sTCPmess(req)) { AXFRError = true; break; } else records++; addRRNone(req); req->data = &req->dnsp->data; req->dnsp->header.qdcount = 0; addRRNSPtr(req); if (!sTCPmess(req)) { AXFRError = true; break; } else records++; time_t t = time(NULL); req->iterBegin = dnsCache[cacheInd].begin(); while (!AXFRError && req->iterBegin != dnsCache[cacheInd].end()) { addRRNone(req); req->dnsp->header.qdcount = 0; req->data = &req->dnsp->data; if (req->iterBegin->second->expiry > t) { switch (req->iterBegin->second->dataType) { case LOCAL_PTR_AUTH: case STATIC_PTR_AUTH: addRRPtrOne(req); break; case SERVER_PTR_AUTH: if (network.dnsTcpConn[req->sockInd].server == ntohl(my_inet_addr(req->iterBegin->second->mapname))) addRRPtrOne(req); else { req->iterBegin++; continue; } break; default: req->iterBegin++; continue; } if (tempserial != cfig.serial2) { AXFRError = true; break; } if (!sTCPmess(req)) { AXFRError = true; break; } else records++; } req->iterBegin++; } addRRNone(req); req->data = &req->dnsp->data; req->dnsp->header.qdcount = 0; addRRSOA(req, cfig.serial2); if (!AXFRError && tempserial == cfig.serial2) { if (sTCPmess(req)) { records++; sprintf(logBuff, "Zone %s with %u RRs Sent", req->query, records); logTCPMess(req, logBuff, 2); } } } break; } } closesocket(req->sock); return; } WORD sTCPmess(data5 *req) { errno = 0; req->dnsp->header.ra = 0; pUShort(req->raw, req->bytes - 2); if (req->bytes != send(req->sock, req->raw, req->bytes, 0) || WSAGetLastError()) return 0; return req->bytes; } WORD gdnmess(data5 *req, BYTE sockInd) { memset(req, 0, sizeof(data5)); req->sockLen = sizeof(req->addr); errno = 0; req->bytes = recvfrom(network.dnsUdpConn[sockInd].sock, req->raw, sizeof(req->raw), 0, (sockaddr*)&req->addr, &req->sockLen); errno = WSAGetLastError(); if (errno || req->bytes <= 0) return 0; req->sockInd = sockInd; req->dnsp = (dnsPacket*)req->raw; if (req->dnsp->header.opcode != OPCODE_STANDARD_QUERY) { if (cfig.dnsLogLevel) { 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); } logDNSMess(req, logBuff, 1); } addRRNone(req); req->dnsp->header.rcode = RCODE_NOTIMPL; return req->bytes; } if (req->dnsp->header.qr != 0 || ntohs(req->dnsp->header.qdcount) != 1 || ntohs(req->dnsp->header.ancount)) { if (cfig.dnsLogLevel) { sprintf(logBuff, "DNS Query Format Error"); logDNSMess(req, logBuff, 1); } addRRNone(req); req->dnsp->header.rcode = RCODE_FORMATERROR; return req->bytes; } req->data = &req->dnsp->data; for (int i = 1; i <= ntohs(req->dnsp->header.qdcount); i++) { req->data += fQu(req->query, req->dnsp, req->data); req->qtype = fUShort(req->data); req->data += 2; req->qclass = fUShort(req->data); req->data += 2; } if (req->qclass != DNS_CLASS_IN) { if (cfig.dnsLogLevel) { sprintf(logBuff, "DNS Class %u not supported", req->qclass); logDNSMess(req, logBuff, 1); } addRRNone(req); req->dnsp->header.rcode = RCODE_NOTIMPL; return req->bytes; } if (!req->qtype) { if (cfig.dnsLogLevel) { sprintf(logBuff, "missing query type"); logDNSMess(req, logBuff, 1); } addRRNone(req); req->dnsp->header.rcode = RCODE_FORMATERROR; return req->bytes; } req->qLen = strlen(req->query); DWORD iip = ntohl(req->addr.sin_addr.s_addr); for (int i = 0; i < MAX_RANGES && cfig.dnsRanges[i].rangeStart; i++) { if (iip >= cfig.dnsRanges[i].rangeStart && iip <= cfig.dnsRanges[i].rangeEnd) return req->bytes; } for (int i = 0; i < MAX_RANGES && cfig.dhcpRanges[i].rangeStart; i++) { if (iip >= cfig.dhcpRanges[i].rangeStart && iip <= cfig.dhcpRanges[i].rangeEnd) return req->bytes; } if (findEntry(cacheInd, IP2String(req->cname, iip))) return req->bytes; if (req->addr.sin_addr.s_addr == cfig.zoneServers[0] || req->addr.sin_addr.s_addr == cfig.zoneServers[1]) return req->bytes; addRRNone(req); req->dnsp->header.rcode = RCODE_REFUSED; if (cfig.dnsLogLevel) { sprintf(logBuff, "DNS UDP Query, Access Denied"); logDNSMess(req, logBuff, 1); } return req->bytes; } WORD sdnmess(data5 *req) { errno = 0; // If we are sending a response //sprintf(logBuff, "sending response with qr %d", req->dnsp->header.qr); //logDNSMess(req, logBuff, 1); if (cfig.defaultIP!=0 && req->dnsp->header.qr==1) { //sprintf(logBuff, "sending response with qdcount %d ancount %d nscount %d adcount %d", ntohs(req->dnsp->header.qdcount), ntohs(req->dnsp->header.ancount), ntohs(req->dnsp->header.nscount), ntohs(req->dnsp->header.adcount)); //logDNSMess(req, logBuff, 1); // If answer count is 0 if (req->dnsp->header.ancount == 0 /*&& req->dnsp->header.nscount && req->dnsp->header.adcount*/) { sprintf(logBuff, "adding default ip"); logDNSMess(req, logBuff, 1); addRRWildA(req, cfig.defaultIP); // Kill other name server respones req->dnsp->header.nscount=0; req->dnsp->header.adcount=0; req->dnsp->header.rcode=RCODE_NOERROR; } else { //sprintf(logBuff, "looping to search for blacklisted ips"); //logDNSMess(req, logBuff, 1); #if 1 tempbuff[0] = 0; extbuff[0] = 0; char *raw = &req->dnsp->data; WORD queueIndex; for (int i = 1; i <= ntohs(req->dnsp->header.qdcount); i++) { //sprintf(logBuff, "skipping question"); //logDNSMess(req, logBuff, 1); raw += fQu(extbuff, req->dnsp, raw); raw += 4; } for (int i = 1; i <= ntohs(req->dnsp->header.ancount); i++) { //sprintf(logBuff, "looking at response"); //logDNSMess(req, logBuff, 1); raw += fQu(extbuff, 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) { //sprintf(logBuff, "is an A type"); //logDNSMess(req, logBuff, 1); for (BYTE j=0; j <= 32 && cfig.nxdBlacklist[j]; j++) { //sprintf(logBuff, "comparing to nxdBlacklist ip"); //logDNSMess(req, logBuff, 1); if (fIP(raw)==cfig.nxdBlacklist[j]) { sprintf(logBuff, "clobbering"); logDNSMess(req, logBuff, 1); pIP(raw,cfig.defaultIP); } } } else if (type == DNS_TYPE_AAAA) { // Handle IPv6 } else if (type == DNS_TYPE_PTR) { // This is a name, not an IP } else if (type == DNS_TYPE_MX) { // Mail stuff } else if (type == DNS_TYPE_CNAME) { // Canonical names } raw += zLen; } #endif } } req->bytes = sendto(network.dnsUdpConn[req->sockInd].sock, req->raw, req->bytes, 0, (sockaddr*)&req->addr, sizeof(req->addr)); errno = WSAGetLastError(); if (errno || req->bytes <= 0) return 0; return req->bytes; } WORD scanloc(data5 *req) { if (!req->query[0]) return 0; strcpy(req->cname, req->query); strcpy(req->mapname, req->query); myLower(req->mapname); //printf("%s\n",req->query); switch (req->qtype) { case DNS_TYPE_PTR: { char *dp = strstr(req->mapname, arpa); if (dp) *dp = 0; else return 0; } break; case DNS_TYPE_A: req->localCode = makeLocal(req->mapname); if (req->localCode == 1) { sprintf(req->cname, "%s.%s", req->query, cfig.zone); } break; case DNS_TYPE_MX: if (!strcasecmp(req->query, cfig.zone) && (cfig.authorized || cfig.mxServers[cacheInd][0].hostname[0])) { addRRNone(req); addRRMX(req); addAuth(req); return 1; } else return 0; break; case DNS_TYPE_NS: if (cfig.authorized) { if (!strcasecmp(req->query, cfig.authority)) { addRRNone(req); addRRNSPtr(req); addRRAd(req); return 1; } else if (!strcasecmp(req->query, cfig.zone)) { addRRNone(req); addRRNSA(req); addRRAd(req); return 1; } } return 0; break; case DNS_TYPE_SOA: if (cfig.authorized) { if (!strcasecmp(req->query, cfig.authority)) { addRRNone(req); addRRSOA(req, cfig.serial2); return 1; } else if (!strcasecmp(req->query, cfig.zone)) { addRRNone(req); addRRSOA(req, cfig.serial1); return 1; } } return 0; break; case DNS_TYPE_AAAA: req->localCode = makeLocal(req->mapname); if (req->localCode && cfig.authorized) { if (cfig.dnsLogLevel) { sprintf(logBuff, "%s, DNS Query Type %s not supported", req->query, strqtype(tempbuff, req->qtype)); logDNSMess(req, logBuff, 1); } addRRNone(req); req->dnsp->header.rcode = RCODE_NOTIMPL; addAuth(req); return 1; } return 0; break; default: if (cfig.authorized) { char *dp = strstr(req->mapname, cfig.zoneSmall); if (!dp) dp = strstr(req->mapname, cfig.authority); if (dp && (!strcasecmp(dp, cfig.zoneSmall) || !strcasecmp(dp, cfig.authority))) { if (cfig.dnsLogLevel) { sprintf(logBuff, "%s, DNS Query Type %s not supported", req->query, strqtype(tempbuff, req->qtype)); logDNSMess(req, logBuff, 1); } addRRNone(req); req->dnsp->header.rcode = RCODE_NOTIMPL; addAuth(req); return 1; } return 0; } return 0; } time_t t = time(NULL); for (int m = 0; m < 3; m++) { //printf("%s has %u Entries\n", req->mapname, dnsCache[cacheInd].count(req->mapname)); req->iterBegin = dnsCache[cacheInd].find(req->mapname); if (req->iterBegin != dnsCache[cacheInd].end() && req->iterBegin->second->expiry > t) { memcpy(&req->cache, req->iterBegin->second, sizeof(data7)); //printf("mapname=%s, datatype=%i exp=%u\n",req->cache.mapname, req->cache.dataType,req->cache.expiry); switch (req->cache.dataType) { case LOCAL_A: case STATIC_A_AUTH: addRRNone(req); addRRA(req); addAuth(req); return 1; case LOCAL_PTR_AUTH: case STATIC_PTR_AUTH: case SERVER_PTR_AUTH: addRRNone(req); addRRPtr(req); addAuth(req); return 1; case LOCALHOST_A: addRRNone(req); addRRLocalhostA(req); addAuth(req); return 1; case LOCALHOST_PTR: addRRNone(req); addRRLocalhostPtr(req); addAuth(req); return 1; case STATIC_A_NAUTH: addRRNone(req); addRRA(req); return 1; case LOCAL_PTR_NAUTH: case SERVER_PTR_NAUTH: case STATIC_PTR_NAUTH: addRRNone(req); addRRPtr(req); return 1; case SERVER_A: addRRNone(req); addRRServerA(req); addAuth(req); return 1; case CACHED: addRRNone(req); addRRExt(req); return 1; case LOCAL_CNAME: case EXT_CNAME: if (!strchr(req->cache.hostname, '.')) sprintf(req->cname, "%s.%s", req->cache.hostname, cfig.zone); else strcpy(req->cname, req->cache.hostname); strcpy(req->mapname, req->cache.hostname); myLower(req->mapname); continue; default: break; } } break; } //printf("%u=%u\n", req->cache.dataType, req->localCode); if (req->cache.dataType == LOCAL_CNAME) { addRRNone(req); addRRA(req); addAuth(req); return 1; } else if (req->cache.dataType == EXT_CNAME) { //printf("%u=%u\n", req->cache.dataType, EXT_CNAME); req->data = &req->dnsp->data; req->data += pQu(req->data, req->cname); req->data += pUShort(req->data, DNS_TYPE_A); req->data += pUShort(req->data, DNS_CLASS_IN); req->bytes = (DWORD)req->data - (DWORD)req->raw; } else if (req->qtype == DNS_TYPE_A && cfig.wildHosts[0].wildcard[0]) { for (BYTE i = 0; i < 32 && 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; } } } return 0; } WORD fdnmess(data5 *req) { //checkSize(); req->qLen = strlen(req->cname); BYTE zoneDNS; int nRet = -1; char mapname[8]; sprintf(mapname, "%u", req->dnsp->header.xid); data7 *queue = findEntry(cacheInd, mapname, QUEUE); for (zoneDNS = 0; zoneDNS < 32 && cfig.dnsRoutes[zoneDNS].zLen; zoneDNS++) { if (req->qLen == cfig.dnsRoutes[zoneDNS].zLen && !strcasecmp(req->cname, cfig.dnsRoutes[zoneDNS].zone)) req->localCode = 4; 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->localCode = 4; } if (req->localCode == 4) { if (queue && cfig.dnsRoutes[zoneDNS].dns[1]) { cfig.dnsRoutes[zoneDNS].currentDNS = 1 - cfig.dnsRoutes[zoneDNS].currentDNS; } if (req->addr.sin_addr.s_addr != cfig.dnsRoutes[zoneDNS].dns[cfig.dnsRoutes[zoneDNS].currentDNS]) { req->target.sin_family = AF_INET; req->target.sin_addr.s_addr = cfig.dnsRoutes[zoneDNS].dns[cfig.dnsRoutes[zoneDNS].currentDNS]; req->target.sin_port = htons(IPPORT_DNS); errno = 0; nRet = sendto(network.forwConn.sock, req->raw, req->bytes, 0, (sockaddr*)&req->target, sizeof(req->target)); errno = WSAGetLastError(); if (errno || nRet <= 0) { if (cfig.dnsLogLevel) { sprintf(logBuff, "Error Forwarding UDP DNS Message to Child Server %s", IP2String(tempbuff, req->target.sin_addr.s_addr)); logDNSMess(req, logBuff, 1); } if (cfig.dnsRoutes[zoneDNS].dns[1]) { cfig.dnsRoutes[zoneDNS].currentDNS = 1 - cfig.dnsRoutes[zoneDNS].currentDNS; } return 0; } else { if (cfig.dnsLogLevel == 2) { sprintf(logBuff, "%s forwarded to Child Server %s", req->cname, IP2String(tempbuff, cfig.dnsRoutes[zoneDNS].dns[cfig.dnsRoutes[zoneDNS].currentDNS])); logDNSMess(req, logBuff, 2); } } } /* if (nRet <= 0) { addRRNone(req); req->dnsp->header.ra = 0; req->dnsp->header.rcode = RCODE_SERVERFAIL; return 0; } */ break; } } // printf("%u\n", req->localCode); if (req->localCode != 4) { if (cfig.authorized) { if (req->localCode == 3) { if (cfig.dnsLogLevel == 2) { sprintf(logBuff, "%s not found", req->query); logDNSMess(req, logBuff, 2); } addRRNone(req); req->dnsp->header.rcode = RCODE_NAMEERROR; addAuth(req); return 0; } else { sprintf(logBuff, "req->localCode not 3"); logMess(logBuff, 1); char *dp = 0; if (req->qtype != DNS_TYPE_PTR && req->qLen > cfig.zLen) { dp = req->cname + (req->qLen - cfig.zLen - 1); if (*dp != '.' || strcasecmp(dp + 1, cfig.zone)) dp = 0; } if (!dp && req->qLen > cfig.aLen) { dp = req->cname + (req->qLen - cfig.aLen - 1); if (*dp != '.' || strcasecmp(dp + 1, cfig.authority)) dp = 0; } //printf("%s=%s\n", req->cname, dp); if (dp) //if child zone matches { switch (req->qtype) { case DNS_TYPE_A: case DNS_TYPE_MX: case DNS_TYPE_PTR: if (cfig.dnsLogLevel == 2) { if (dp != strchr(req->cname, '.')) { if (cfig.dnsLogLevel == 2) { while (dp > req->cname) { dp--; if (*dp == '.') { dp++; break; } } sprintf(logBuff, "%s (Child Zone %s) not found", req->query, dp); logDNSMess(req, logBuff, 2); } } else { sprintf(logBuff, "%s not found", req->query); logDNSMess(req, logBuff, 2); } } addRRNone(req); req->dnsp->header.rcode = RCODE_NAMEERROR; addAuth(req); return 0; break; case DNS_TYPE_AXFR: case DNS_TYPE_NS: case DNS_TYPE_SOA: if (cfig.dnsLogLevel == 2) { if (dp != strchr(req->cname, '.')) { while (dp > req->cname) { dp--; if (*dp == '.') { dp++; break; } } sprintf(logBuff, "%s (Child Zone %s) not found", req->query, dp); logDNSMess(req, logBuff, 2); } else { sprintf(logBuff, "Child Zone %s not found", req->query); logDNSMess(req, logBuff, 2); } } addRRNone(req); req->dnsp->header.rcode = RCODE_NOTZONE; addAuth(req); return 0; break; default: if (cfig.dnsLogLevel == 2) { sprintf(logBuff, "DNS UDP Query Type %s not supported", strqtype(tempbuff, req->qtype)); logDNSMess(logBuff, 1); } addRRNone(req); req->dnsp->header.rcode = RCODE_NOTIMPL; addAuth(req); return 0; } } } } //if (cfig.authorized) if (!req->dnsp->header.rd) { addRRNone(req); req->dnsp->header.rcode = RCODE_NAMEERROR; if (cfig.dnsLogLevel) { sprintf(logBuff, "%s is not local (recursion not desired)", req->query); logDNSMess(req, logBuff, 2); } return 0; } if (!network.dns[0]) { addRRNone(req); req->dnsp->header.rcode = RCODE_NAMEERROR; req->dnsp->header.ra = 0; if (cfig.dnsLogLevel) { sprintf(logBuff, "%s not found (recursion not available)", req->query); logDNSMess(req, logBuff, 2); } return 0; } if (queue && network.dns[1] && queue->dnsIndex < MAX_SERVERS && cfig.currentDNS == queue->dnsIndex) { cfig.currentDNS++; if (cfig.currentDNS >= MAX_SERVERS || !network.dns[cfig.currentDNS]) cfig.currentDNS = 0; } if (req->addr.sin_addr.s_addr != network.dns[cfig.currentDNS]) { req->target.sin_family = AF_INET; req->target.sin_addr.s_addr = network.dns[cfig.currentDNS]; req->target.sin_port = htons(IPPORT_DNS); errno = 0; nRet = sendto(network.forwConn.sock, req->raw, req->bytes, 0, (sockaddr*)&req->target, sizeof(req->target)); errno = WSAGetLastError(); if (errno || nRet <= 0) { if (cfig.dnsLogLevel) { sprintf(logBuff, "Error forwading UDP DNS Message to Forwarding Server %s", IP2String(tempbuff, network.dns[cfig.currentDNS])); logDNSMess(req, logBuff, 1); } if (network.dns[1]) { cfig.currentDNS++; if (cfig.currentDNS >= MAX_SERVERS || !network.dns[cfig.currentDNS]) cfig.currentDNS = 0; } return 0; } else { if (cfig.dnsLogLevel == 2) { sprintf(logBuff, "%s forwarded to Forwarding Server %s", req->cname, IP2String(tempbuff, network.dns[cfig.currentDNS])); logDNSMess(req, logBuff, 2); } } } // if (nRet <= 0) // { // addRRNone(req); // req->dnsp->header.ra = 0; // req->dnsp->header.rcode = RCODE_SERVERFAIL; // return 0; // } } time_t t = time(NULL); if (!queue) { queue = (data7*)calloc(1, sizeof(data7)); if (queue) { queue->mapname = cloneString(mapname); queue->addr = (SOCKADDR_IN*)calloc(1, sizeof(req->addr)); queue->query = cloneString(req->query); if (!queue->mapname || !queue->addr || !queue->query) { if (queue->mapname) free(queue->mapname); if (queue->addr) free(queue->addr); if (queue->query) free(queue->query); free(queue); sprintf(logBuff, "Memory Allocation Error"); logDNSMess(logBuff, 1); return 0; } memcpy(queue->addr, &req->addr, sizeof(req->addr)); queue->expiry = 2 + t; queue->dataType = QUEUE; addEntry(cacheInd, queue); } else { sprintf(logBuff, "Memory Allocation Error"); logDNSMess(logBuff, 1); return 0; } } else { queue->expiry = 2 + t; memcpy(queue->addr, &req->addr, sizeof(req->addr)); if (strcasecmp(queue->query, req->query)) { char *query = cloneString(req->query); if (query) { free(queue->query); queue->query = query; } else { sprintf(logBuff, "Memory Allocation Error"); logDNSMess(logBuff, 1); return 0; } } } queue->sockInd = req->sockInd; if (req->localCode == 4) queue->dnsIndex = 128 + (2 * zoneDNS) + cfig.dnsRoutes[zoneDNS].currentDNS; else queue->dnsIndex = cfig.currentDNS; //printf("%u %u\n", zoneDNS, queue->dnsIndex); return (nRet); } WORD frdnmess(data5 *req) { memset(req, 0, sizeof(data5)); req->sockLen = sizeof(req->addr); errno = 0; req->bytes = recvfrom(network.forwConn.sock, req->raw, sizeof(req->raw), 0, (sockaddr*)&req->addr, &req->sockLen); //printf("%u\n", req->bytes); errno = WSAGetLastError(); if (errno || req->bytes <= 0) return 0; req->dnsp = (dnsPacket*)req->raw; char mapname[8]; WORD type = 0; sprintf(mapname, "%u", req->dnsp->header.xid); data7 *queue = findEntry(cacheInd, mapname); if (queue && queue->expiry) { queue->expiry = 0; if (queue->dnsIndex < MAX_SERVERS) { if (req->addr.sin_addr.s_addr != network.dns[cfig.currentDNS]) { for (BYTE i = 0; i < MAX_SERVERS && network.dns[i]; i++) { if (network.dns[i] == req->addr.sin_addr.s_addr) { cfig.currentDNS = i; break; } } } } else if (queue->dnsIndex >= 128 && queue->dnsIndex < 192) { data6 *dnsRoute = &cfig.dnsRoutes[(queue->dnsIndex - 128) / 2]; if (dnsRoute->dns[0] == req->addr.sin_addr.s_addr) dnsRoute->currentDNS = 0; else if (dnsRoute->dns[1] == req->addr.sin_addr.s_addr) dnsRoute->currentDNS = 1; } if (queue->dataType == DNS_CHECK) { if (cfig.dnsLogLevel) { if (queue->dnsIndex < MAX_SERVERS) { sprintf(logBuff, "Forwarding DNS Server %s responded", IP2String(tempbuff, req->addr.sin_addr.s_addr)); logDNSMess(logBuff, 1); } else if (queue->dnsIndex >= 128 && queue->dnsIndex < 192) { sprintf(logBuff, "Child DNS Server %s responded", IP2String(tempbuff, req->addr.sin_addr.s_addr)); logDNSMess(logBuff, 1); } } return 0; } else if (queue->dataType == QUEUE) { memcpy(&req->addr, queue->addr, sizeof(req->addr)); strcpy(req->query, queue->query); req->sockInd = queue->sockInd; req->cache.dnsIndex = queue->dnsIndex; req->data = &req->dnsp->data; for (int i = 1; i <= ntohs(req->dnsp->header.qdcount); i++) { req->data += fQu(req->cname, req->dnsp, req->data); type = fUShort(req->data); req->data += 4; //type and class } if ((type == DNS_TYPE_A || type == 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++) { req->data += fQu(tempbuff, req->dnsp, req->data); type = fUShort(req->data); //printf("%s %u=%u\n", tempbuff, type, DNS_TYPE_A); if (type == DNS_TYPE_A) { resultFound = true; strcpy(req->mapname, req->cname); myLower(req->mapname); makeLocal(req->mapname); } else if (type == DNS_TYPE_PTR) { strcpy(req->mapname, req->cname); myLower(req->mapname); char *dp = strstr(req->mapname, arpa); if (dp && !strcasecmp(dp, arpa)) { *dp = 0; resultFound = true; } } req->data += 4; //type and class if (!expiry || fULong(req->data) < (DWORD)expiry) expiry = fULong(req->data); req->data += 4; //ttl int zLen = fUShort(req->data); req->data += 2; //datalength req->data += zLen; } time_t t = time(NULL); if (resultFound) { WORD cacheSize = (DWORD)req->data - (DWORD)req->raw; if (cfig.minCache && expiry < cfig.minCache) expiry = cfig.minCache; if (cfig.maxCache && expiry > cfig.maxCache) expiry = cfig.maxCache; if (expiry < LONG_MAX - t) expiry += t; else expiry = LONG_MAX; data7 *cache = findEntry(cacheInd, req->mapname, CACHED); if (cache) { if (cache->bytes < cacheSize) { BYTE *response = (BYTE*)calloc(1, cacheSize); if (response) { if (cache->response) free(cache->response); cache->response = response; } else { sprintf(logBuff, "Memory Allocation Error"); logDNSMess(logBuff, 1); return 0; } } cache->expiry = expiry; } else { //checkSize(); cache = (data7*)calloc(1, sizeof(data7)); if (!cache) { sprintf(logBuff, "Memory Allocation Error"); logDNSMess(logBuff, 1); return 0; } cache->mapname = cloneString(req->mapname); cache->response = (BYTE*)calloc(1, cacheSize); if (!cache->mapname || !cache->response) { if (cache->mapname) free(cache->mapname); if (cache->response) free(cache->response); free(cache); sprintf(logBuff, "Memory Allocation Error"); logDNSMess(logBuff, 1); return 0; } cache->expiry = expiry; cache->dataType = CACHED; addEntry(cacheInd, cache); } memcpy(cache->response, req->dnsp, cacheSize); ((dnsPacket*)cache->response)->header.nscount = 0; ((dnsPacket*)cache->response)->header.adcount = 0; cache->bytes = cacheSize; } } req->cache.dataType = NON_CACHED; addRRExt(req); return 1; } } return 0; } void addToCache(BYTE ind, char *hostname, DWORD ip, time_t expiry, BYTE aType, BYTE pType, DWORD serial) { //printf("Adding to %u, %s=%s exp=%u\n",ind, hostname,IP2String(tempbuff, ip),expiry); char tempbuff[256]; char logBuff[256]; if (!hostname[0] || !ip) return; data7 *cache = NULL; hostMap::iterator p; if (pType) { IP2String(tempbuff, htonl(ip)); p = dnsCache[ind].find(tempbuff); for (;p != dnsCache[ind].end(); p++) { if (strcasecmp(p->second->mapname, tempbuff)) break; if (!strcasecmp(p->second->hostname, hostname)) { cache = p->second; break; } } if (!cache) { //checkSize(); cache = (data7*)calloc(1, sizeof(data7)); if (cache) { cache->mapname = cloneString(tempbuff); cache->hostname = cloneString(hostname); if (!cache->mapname || !cache->hostname) { if (cache->mapname) free(cache->mapname); if (cache->hostname) free(cache->hostname); free(cache); sprintf(logBuff, "Memory Allocation Error"); logDNSMess(logBuff, 1); return ; } cache->dataType = pType; cache->expiry = expiry; addEntry(ind, cache); } else { sprintf(logBuff, "Memory Allocation Error"); logDNSMess(logBuff, 1); return ; } } else { if (strcasecmp(hostname, cache->hostname)) { free(cache->hostname); cache->hostname = cloneString(hostname); } if (cache->expiry < expiry) cache->expiry = expiry; } cache->serial = serial; } if (aType) { cache = NULL; strcpy(tempbuff, hostname); makeLocal(tempbuff); myLower(tempbuff); p = dnsCache[ind].find(tempbuff); for (; p != dnsCache[ind].end(); p++) { if (strcasecmp(p->second->mapname, tempbuff)) break; if (p->second->ip == ip) { cache = p->second; break; } } if (!cache) { //checkSize(); cache = (data7*)calloc(1, sizeof(data7)); if (cache) { cache->mapname = cloneString(tempbuff); if (!cache->mapname) { sprintf(logBuff, "Memory Allocation Error"); free(cache); logDNSMess(logBuff, 1); return ; } cache->ip = ip; cache->dataType = aType; cache->expiry = expiry; addEntry(ind, cache); } else { sprintf(logBuff, "Memory Allocation Error"); logDNSMess(logBuff, 1); return ; } } else { cache->ip = ip; if (cache->expiry < expiry) cache->expiry = expiry; } cache->serial = serial; } } char* getResult(data5 *req) { tempbuff[0] = 0; extbuff[0] = 0; char *raw = &req->dnsp->data; WORD queueIndex; for (int i = 1; i <= ntohs(req->dnsp->header.qdcount); i++) { raw += fQu(extbuff, req->dnsp, raw); raw += 4; } for (int i = 1; i <= ntohs(req->dnsp->header.ancount); i++) { raw += fQu(extbuff, 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(tempbuff, fIP(raw)); else if (type == DNS_TYPE_AAAA) return IP62String(tempbuff, (BYTE*)raw); else if (type == DNS_TYPE_PTR) { fQu(tempbuff, req->dnsp, raw); return tempbuff; } else if (type == DNS_TYPE_MX) { fQu(tempbuff, req->dnsp, ++++raw); return tempbuff; } else if (type == DNS_TYPE_CNAME) { fQu(tempbuff, req->dnsp, raw); } raw += zLen; } if (tempbuff[0]) return tempbuff; else return NULL; } bool checkRange(char rangeInd, bool macFound, bool vendFound, bool userFound) { if (!cfig.hasFilter) return true; BYTE 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((!macFound && !rangeSet->macSize[0]) || (macFound && cfig.macArray[rangeSetInd])) if((!vendFound && !rangeSet->vendClassSize[0]) || (vendFound && cfig.vendArray[rangeSetInd])) if((!userFound && !rangeSet->userClassSize[0]) || (userFound && cfig.userArray[rangeSetInd])) return true; //printf("checkRange, returning false rangeInd=%i rangeSetInd=%i\n", rangeInd, rangeSetInd); return false; } DWORD resad(data9 *req) { time_t t = time(NULL); DWORD minRange = 0; DWORD maxRange = 0; if (req->dhcpp.header.bp_giaddr) { setLeaseExpiry(req->dhcpp.header.bp_giaddr, LONG_MAX); setLeaseExpiry(req->addr.sin_addr.s_addr, LONG_MAX); } DWORD iipNew = 0; DWORD iipExp = 0; DWORD rangeStart = 0; DWORD rangeEnd = 0; char rangeInd = -1; bool rangeFound = false; bool macFound = false; bool vendFound = false; bool userFound = false; memset(cfig.macArray, 0, sizeof(cfig.macArray)); memset(cfig.vendArray, 0, sizeof(cfig.vendArray)); memset(cfig.userArray, 0, sizeof(cfig.userArray)); if (cfig.hasFilter) { for (BYTE rangeSetInd = 0; rangeSetInd < MAX_RANGES && cfig.rangeSet[rangeSetInd].active; rangeSetInd++) { data14 *rangeSet = &cfig.rangeSet[rangeSetInd]; for (BYTE i = 0; i < 32 && rangeSet->macSize[i]; 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) { cfig.macArray[rangeSetInd] = true; macFound = true; //printf("mac Found, rangeSetInd=%i\n", rangeSetInd); break; } } for (BYTE i = 0; i < 32 && rangeSet->vendClassSize[i]; i++) { if(req->vendClassSize && rangeSet->vendClassSize[i] == req->vendClassSize && !memcmp(req->vendClass, rangeSet->vendClass[i], rangeSet->vendClassSize[i])) { cfig.vendArray[rangeSetInd] = true; vendFound = true; printf("vend Found, rangeSetInd=%i\n", rangeSetInd); break; } } for (BYTE i = 0; i < 32 && rangeSet->userClassSize[i]; i++) { if(req->userClassSize && rangeSet->userClassSize[i] == req->userClassSize && !memcmp(req->userClass, rangeSet->userClass[i], rangeSet->userClassSize[i])) { cfig.userArray[rangeSetInd] = true; userFound = true; //printf("user Found, rangeSetInd=%i\n", rangeSetInd); break; } } } } // printArray("macArray", (char*)cfig.macArray); // printArray("vendArray", (char*)cfig.vendArray); // printArray("userArray", (char*)cfig.userArray); if (chad(req)) { bool rangeOK = req->dhcpEntry->fixed; if (!rangeOK && req->dhcpEntry->rangeInd >= 0) rangeOK = checkRange(req->dhcpEntry->rangeInd, macFound, vendFound, userFound); if (rangeOK) { DWORD mask = INADDR_NONE; if (req->dhcpEntry->bitmask) mask = htonl(mask << (32 - req->dhcpEntry->bitmask)); else if (req->dhcpEntry->rangeInd >= 0) mask = cfig.dhcpRanges[req->dhcpEntry->rangeInd].mask; else mask = cfig.mask; if (req->dhcpp.header.bp_giaddr) calcRangeLimits(req->dhcpp.header.bp_giaddr, mask, &minRange, &maxRange); else if (htonl(network.dhcpConn[req->sockInd].mask) > htonl(mask)) calcRangeLimits(network.dhcpConn[req->sockInd].server, network.dhcpConn[req->sockInd].mask, &minRange, &maxRange); else calcRangeLimits(network.dhcpConn[req->sockInd].server, mask, &minRange, &maxRange); if (htonl(req->dhcpEntry->ip) >= minRange && htonl(req->dhcpEntry->ip) <= maxRange) { setLeaseExpiry(req->dhcpEntry, 20, false); return req->dhcpEntry->ip; } else if (req->dhcpEntry->fixed) { req->dhcpEntry->no_route = 1; setLeaseExpiry(req->dhcpEntry, 20, false); return req->dhcpEntry->ip; } } } if (req->hostname[0]) { char hostname[256]; strcpy(hostname, req->hostname); myLower(hostname); hostMap::iterator it = dnsCache[cacheInd].find(hostname); for (; it != dnsCache[cacheInd].end(); it++) { data7 *cache = it->second; //printf("%u\n", cache->mapname); if (strcasecmp(cache->mapname, hostname)) break; if (cache && cache->ip) { char k = getRangeInd(cache->ip); if (k >= 0) { if (checkRange(k, macFound, vendFound, userFound)) { char ind = getIndex(k, cache->ip); data13 *range = &cfig.dhcpRanges[k]; if (ind >= 0 && range->expiry[ind] <= t && !range->dhcpEntry[ind]) { if (req->dhcpp.header.bp_giaddr) calcRangeLimits(req->dhcpp.header.bp_giaddr, range->mask, &minRange, &maxRange); else if (htonl(network.dhcpConn[req->sockInd].mask) > htonl(range->mask)) calcRangeLimits(network.dhcpConn[req->sockInd].server, network.dhcpConn[req->sockInd].mask, &minRange, &maxRange); else calcRangeLimits(network.dhcpConn[req->sockInd].server, range->mask, &minRange, &maxRange); DWORD iip = htonl(cache->ip); if (iip >= minRange && iip <= maxRange) { iipNew = iip; rangeInd = k; break; } } } } } } } if (!iipNew && req->reqIP) { char k = getRangeInd(req->reqIP); if (k >= 0) { if (checkRange(k, macFound, vendFound, userFound)) { data13 *range = &cfig.dhcpRanges[k]; char ind = getIndex(k, req->reqIP); if (ind >= 0 && range->expiry[ind] <= t) { if (req->dhcpp.header.bp_giaddr) calcRangeLimits(req->dhcpp.header.bp_giaddr, range->mask, &minRange, &maxRange); else if (htonl(network.dhcpConn[req->sockInd].mask) > htonl(range->mask)) calcRangeLimits(network.dhcpConn[req->sockInd].server, network.dhcpConn[req->sockInd].mask, &minRange, &maxRange); else calcRangeLimits(network.dhcpConn[req->sockInd].server, range->mask, &minRange, &maxRange); DWORD iip = htonl(req->reqIP); if (iip >= minRange && iip <= maxRange) { iipNew = iip; rangeInd = k; } } } } } for (char k = 0; !iipNew && k < MAX_RANGES && cfig.dhcpRanges[k].rangeStart; k++) { if (checkRange(k, macFound, vendFound, userFound)) { data13 *range = &cfig.dhcpRanges[k]; rangeStart = range->rangeStart; rangeEnd = range->rangeEnd; if (req->dhcpp.header.bp_giaddr) calcRangeLimits(req->dhcpp.header.bp_giaddr, range->mask, &minRange, &maxRange); else if (htonl(network.dhcpConn[req->sockInd].mask) > htonl(range->mask)) calcRangeLimits(network.dhcpConn[req->sockInd].server, network.dhcpConn[req->sockInd].mask, &minRange, &maxRange); else calcRangeLimits(network.dhcpConn[req->sockInd].server, range->mask, &minRange, &maxRange); if (rangeStart < minRange) rangeStart = minRange; if (rangeEnd > maxRange) rangeEnd = maxRange; if (rangeStart <= rangeEnd) { rangeFound = true; for (DWORD m = rangeStart; m <= rangeEnd; m++) { if (!range->expiry[m - range->rangeStart]) { iipNew = m; rangeInd = k; break; } else if (!iipExp && range->expiry[m - range->rangeStart] < t) { iipExp = m; rangeInd = k; } } } } } if (!iipNew && iipExp) { char ind = iipExp - cfig.dhcpRanges[rangeInd].rangeStart; req->dhcpEntry = cfig.dhcpRanges[rangeInd].dhcpEntry[ind]; if (req->dhcpEntry) { dhcpCache.erase(req->dhcpEntry->mapname); free(req->dhcpEntry->mapname); req->dhcpEntry->mapname = cloneString(toUUE(tempbuff, req->dhcpp.header.bp_chaddr, req->dhcpp.header.bp_hlen)); if (!req->dhcpEntry->mapname) { sprintf(logBuff, "Memory Allocation Error"); logDHCPMess(logBuff, 1); return 0; } dhcpCache[req->dhcpEntry->mapname] = req->dhcpEntry; req->dhcpEntry->ip = htonl(iipExp); req->dhcpEntry->rangeInd = rangeInd; setLeaseExpiry(req->dhcpEntry, 20, false); if (!req->dhcpEntry->fixed) { if (req->dhcpp.header.bp_giaddr) req->dhcpEntry->source = req->dhcpp.header.bp_giaddr; else req->dhcpEntry->source = network.dhcpConn[req->sockInd].server; } return req->dhcpEntry->ip; } else iipNew = iipExp; } if (iipNew) { if (!req->dhcpEntry) { req->dhcpEntry = (data7*)calloc(1, sizeof(data7)); if (!req->dhcpEntry) { sprintf(logBuff, "Memory Allocation Error"); logDHCPMess(logBuff, 1); return 0; } req->dhcpEntry->mapname = cloneString(toUUE(tempbuff, req->dhcpp.header.bp_chaddr, req->dhcpp.header.bp_hlen)); if (!req->dhcpEntry->mapname) { sprintf(logBuff, "Memory Allocation Error"); free(req->dhcpEntry); logDHCPMess(logBuff, 1); return 0; } dhcpCache[req->dhcpEntry->mapname] = req->dhcpEntry; } req->dhcpEntry->ip = htonl(iipNew); req->dhcpEntry->rangeInd = rangeInd; setLeaseExpiry(req->dhcpEntry, 20, false); if (!req->dhcpEntry->fixed) { if (req->dhcpp.header.bp_giaddr) req->dhcpEntry->source = req->dhcpp.header.bp_giaddr; else req->dhcpEntry->source = network.dhcpConn[req->sockInd].server; } return req->dhcpEntry->ip; } if (!iipNew) { if (cfig.dhcpLogLevel) { if (rangeFound) { if (req->dhcpp.header.bp_giaddr) sprintf(logBuff, "No free leases for DHCP discover for %s (%s) from RelayAgent %s", hex2String(extbuff, req->dhcpp.header.bp_chaddr, req->dhcpp.header.bp_hlen, ':'), req->hostname, IP2String(tempbuff, req->dhcpp.header.bp_giaddr)); else sprintf(logBuff, "No free leases for DHCP discover for %s (%s) from interface %s", hex2String(extbuff, req->dhcpp.header.bp_chaddr, req->dhcpp.header.bp_hlen, ':'), req->hostname, IP2String(tempbuff, network.dhcpConn[req->sockInd].server)); } else { if (req->dhcpp.header.bp_giaddr) sprintf(logBuff, "No Matching DHCP Range for DHCP discover for %s (%s) from RelayAgent %s", hex2String(extbuff, req->dhcpp.header.bp_chaddr, req->dhcpp.header.bp_hlen, ':'), req->hostname, IP2String(tempbuff, req->dhcpp.header.bp_giaddr)); else sprintf(logBuff, "No Matching DHCP Range for DHCP discover for %s (%s) from interface %s", hex2String(extbuff, req->dhcpp.header.bp_chaddr, req->dhcpp.header.bp_hlen, ':'), req->hostname, IP2String(tempbuff, network.dhcpConn[req->sockInd].server)); } logMess(logBuff, 1); } } return 0; } DWORD chad(data9 *req) { req->dhcpEntry = dhcpCache[toUUE(tempbuff, req->dhcpp.header.bp_chaddr, req->dhcpp.header.bp_hlen)]; if (req->dhcpEntry && req->dhcpEntry->ip && (req->dhcpEntry->fixed || (req->dhcpp.header.bp_giaddr && req->dhcpEntry->source == req->dhcpp.header.bp_giaddr) || req->dhcpEntry->source == network.dhcpConn[req->sockInd].server)) { if (!req->hostname[0]) { data7 *cache = findEntry(cacheInd, IP2String(tempbuff, htonl(req->dhcpEntry->ip))); if (cache && cache->hostname) strcpy(req->hostname, cache->hostname); else sprintf(req->hostname, "%s", hex2String(tempbuff, req->dhcpp.header.bp_chaddr, req->dhcpp.header.bp_hlen, '-')); } return req->dhcpEntry->ip; } else return 0; } DWORD sdmess(data9 *req) { time_t t = time(NULL); //printf("Request=%u Req IP=%s\n",req->req_type, IP2String(tempbuff, req->dhcpp.header.bp_ciaddr)); if (req->req_type == DHCP_MESS_NONE) { req->dhcpp.header.bp_yiaddr = chad(req); if (!req->dhcpp.header.bp_yiaddr) { if (cfig.dhcpLogLevel) { sprintf(logBuff, "No Static Entry found for BOOTP request from client %s", hex2String(tempbuff, req->dhcpp.header.bp_chaddr, req->dhcpp.header.bp_hlen, ':')); logMess(logBuff, 1); } return 0; } } else if (req->req_type == DHCP_MESS_DECLINE) { if (chad(req) == req->dhcpp.header.bp_ciaddr) { setLeaseExpiry(req->dhcpp.header.bp_ciaddr, LONG_MAX); req->dhcpEntry->ip = 0; if (cfig.dhcpLogLevel) { sprintf(logBuff, "IP Address %s declined by Client %s (%s), locked", IP2String(tempbuff, req->dhcpp.header.bp_ciaddr), req->hostname, hex2String(extbuff, req->dhcpp.header.bp_chaddr, req->dhcpp.header.bp_hlen, ':')); logMess(logBuff, 1); } } return 0; } else if (req->req_type == DHCP_MESS_RELEASE) { if (chad(req) == req->dhcpp.header.bp_ciaddr) { updateDHCP(req); if (req->dhcpEntry->local && cfig.replication) sendRepl(req); if (cfig.dhcpLogLevel == 2) { sprintf(logBuff, "IP Address %s released by Client %s (%s)", IP2String(tempbuff, req->dhcpp.header.bp_ciaddr), req->hostname, hex2String(extbuff, req->dhcpp.header.bp_chaddr, req->dhcpp.header.bp_hlen, ':'), req->hostname); logMess(logBuff, 2); } } return 0; } else if (req->req_type == DHCP_MESS_INFORM) { recvRepl(req); return 0; } else if (req->req_type == DHCP_MESS_DISCOVER && strcasecmp(req->hostname, cfig.servername)) { 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 == chad(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 == chad(req) && req->dhcpEntry->expiry > t) { req->resp_type = DHCP_MESS_ACK; req->dhcpp.header.bp_yiaddr = req->dhcpp.header.bp_ciaddr; } else { req->resp_type = DHCP_MESS_NAK; if (cfig.dhcpLogLevel >= 1) { sprintf(logBuff, "DHCP Request from Client %s (%s), without Discover, NAK'd", hex2String(extbuff, req->dhcpp.header.bp_chaddr, req->dhcpp.header.bp_hlen, ':'), req->hostname); logMess(logBuff, 1); } //return 0; } } else { if (!req->hostname[0]) sprintf(req->hostname, "%s", hex2String(tempbuff, req->dhcpp.header.bp_chaddr, req->dhcpp.header.bp_hlen, '-')); if (cfig.dhcpLogLevel == 2) { if (req->dhcpp.header.bp_sname[0]) sprintf(logBuff, "DHCP Request from Client %s (%s), for Server %s, ignored", hex2String(extbuff, req->dhcpp.header.bp_chaddr, req->dhcpp.header.bp_hlen, ':'), req->hostname, req->dhcpp.header.bp_sname); else sprintf(logBuff, "DHCP Request from Client %s (%s), for Server %s, ignored", hex2String(extbuff, req->dhcpp.header.bp_chaddr, req->dhcpp.header.bp_hlen, ':'), req->hostname, IP2String(tempbuff, req->server)); logMess(logBuff, 2); } return 0; } } else if (req->dhcpp.header.bp_ciaddr && req->dhcpp.header.bp_ciaddr == chad(req) && req->dhcpEntry->expiry > t) { req->resp_type = DHCP_MESS_ACK; req->dhcpp.header.bp_yiaddr = req->dhcpp.header.bp_ciaddr; } else if (req->reqIP && req->reqIP == chad(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; if (cfig.dhcpLogLevel == 2) { sprintf(logBuff, "DHCP Request from Client %s (%s) without Discover, NAK'd", hex2String(extbuff, req->dhcpp.header.bp_chaddr, req->dhcpp.header.bp_hlen, ':'), req->hostname); logMess(logBuff, 1); } //return 0; } } else return 0; addOptions(req); int packSize = (DWORD)(req->vp) - (DWORD)&req->dhcpp; packSize++; if (req->req_type == DHCP_MESS_NONE) packSize = req->bytes; if (req->dhcpp.header.bp_giaddr) { req->addr.sin_port = htons(IPPORT_DHCPS); req->addr.sin_addr.s_addr = req->dhcpp.header.bp_giaddr; } else if (req->dhcpp.header.bp_broadcast || !req->addr.sin_addr.s_addr) { req->addr.sin_port = htons(IPPORT_DHCPC); req->addr.sin_addr.s_addr = INADDR_BROADCAST; } else { req->addr.sin_port = htons(IPPORT_DHCPC); } req->dhcpp.header.bp_op = BOOTP_REPLY; errno = 0; req->bytes = sendto(network.dhcpConn[req->sockInd].sock, req->raw, packSize, 0, //MSG_DONTROUTE, (sockaddr*)&req->addr, sizeof(req->addr)); 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; } DWORD alad(data9 *req) { time_t t = time(NULL); //printf("in\n"); if (req->dhcpEntry && (req->req_type == DHCP_MESS_NONE || req->resp_type == DHCP_MESS_ACK)) { if (req->reqIP || req->req_type == DHCP_MESS_NONE) { cfig.serial1 = t; cfig.serial2 = t; if (cfig.replication == 2) { if (cfig.expire > (DWORD)(LONG_MAX - t)) cfig.expireTime = LONG_MAX; else cfig.expireTime = t + cfig.expire; } else cfig.expireTime = LONG_MAX; } DWORD retVal = updateDHCP(req); if (retVal) { if (cfig.dhcpLogLevel == 2) { if (req->lease && req->reqIP) { sprintf(logBuff, "Client %s (%s) allotted %s for %u seconds", hex2String(extbuff, req->dhcpp.header.bp_chaddr, req->dhcpp.header.bp_hlen, ':'), req->hostname, IP2String(tempbuff, req->dhcpp.header.bp_yiaddr), req->lease); } else if (req->req_type) { sprintf(logBuff, "Client %s (%s) renewed %s for %u seconds", hex2String(extbuff, req->dhcpp.header.bp_chaddr, req->dhcpp.header.bp_hlen, ':'), req->hostname, IP2String(tempbuff, req->dhcpp.header.bp_yiaddr), req->lease); } else { sprintf(logBuff, "BOOTP Client %s (%s) allotted %s", hex2String(extbuff, req->dhcpp.header.bp_chaddr, req->dhcpp.header.bp_hlen, ':'), req->hostname, IP2String(tempbuff, req->dhcpp.header.bp_yiaddr)); } logMess(logBuff, 2); } sendRepl(req); return retVal; } } else if (cfig.dhcpLogLevel == 2 && req->resp_type == DHCP_MESS_OFFER) { sprintf(logBuff, "Client %s (%s) offered %s", hex2String(extbuff, req->dhcpp.header.bp_chaddr, req->dhcpp.header.bp_hlen, ':'), req->hostname, IP2String(tempbuff, req->dhcpp.header.bp_yiaddr)); logMess(logBuff, 2); } //printf("%u=out\n", req->resp_type); return 0; } void addOptions(data9 *req) { if (!req->messsize && req->req_type == DHCP_MESS_NONE) req->messsize = req->bytes; else if (!req->messsize) req->messsize = sizeof(dhcp_packet); 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); BYTE *opPointer = req->dhcpEntry->options; if (opPointer) { BYTE requestedOnly = *opPointer; opPointer++; while (*opPointer && *opPointer < UCHAR_MAX) { 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) { BYTE *opPointer = cfig.dhcpRanges[req->dhcpEntry->rangeInd].options; //printf("Range=%i Pointer=%u\n", req->dhcpEntry->rangeInd,opPointer); if (opPointer) { BYTE requestedOnly = *opPointer; opPointer++; while (*opPointer && *opPointer < UCHAR_MAX) { 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; } } } BYTE *opPointer = cfig.options; if (opPointer) { BYTE requestedOnly = *opPointer; opPointer++; while (*opPointer && *opPointer < UCHAR_MAX) { 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); memcpy(op.value, cfig.zone, op.size); pvdata(req, &op); if (!req->opAdded[DHCP_OPTION_IPADDRLEASE]) { op.opt_code = DHCP_OPTION_IPADDRLEASE; op.size = 4; pULong(op.value, cfig.lease); pvdata(req, &op); } if (!req->opAdded[DHCP_OPTION_NETMASK]) { op.opt_code = DHCP_OPTION_NETMASK; op.size = 4; if (req->dhcpEntry->rangeInd >= 0) pIP(op.value, cfig.dhcpRanges[req->dhcpEntry->rangeInd].mask); else pIP(op.value, network.dhcpConn[req->sockInd].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.replication == 1) { op.size = 8; pIP(op.value, network.dhcpConn[req->sockInd].server); pIP(op.value + 4, cfig.zoneServers[1]); pvdata(req, &op); } else if (cfig.replication == 2) { op.size = 8; pIP(op.value, network.dhcpConn[req->sockInd].server); 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 { for (i = 0; i < MAX_SERVERS; i++) if (!network.dns[i]) break; if (i > 0) { op.opt_code = DHCP_OPTION_DNS; op.size = i * 4; memcpy(op.value, network.dns, op.size); pvdata(req, &op); } } } /* if (!req->opAdded[DHCP_OPTION_HOSTNAME]) { op.opt_code = DHCP_OPTION_HOSTNAME; op.size = strlen(req->hostname); memcpy(op.value, req->hostname, op.size); pvdata(req, &op); } if (req->clientId.opt_code == DHCP_OPTION_CLIENTID) pvdata(req, &req->clientId); */ if (req->agentOption.opt_code == DHCP_OPTION_RELAYAGENTINFO) pvdata(req, &req->agentOption); } } *(req->vp) = DHCP_OPTION_END; } void pvdata(data9 *req, data3 *op) { if (!req->opAdded[op->opt_code] && (((DWORD)req->vp - (DWORD)&req->dhcpp) + op->size < req->messsize)) { if (op->opt_code == DHCP_OPTION_BOOTFILE) memcpy(req->dhcpp.header.bp_file, op->value, op->size); else if (op->opt_code == DHCP_OPTION_NEXTSERVER) req->dhcpp.header.bp_siaddr = fIP(op->value); else if(op->size) { if (op->opt_code == DHCP_OPTION_IPADDRLEASE) { if (!req->lease || req->lease > fULong(op->value)) req->lease = fULong(op->value); if (req->dhcpEntry->no_route || req->lease >= LONG_MAX) req->lease = ULONG_MAX; pULong(op->value, req->lease); } else if (op->opt_code == DHCP_OPTION_HOSTNAME) { memcpy(req->hostname, op->value, op->size); req->hostname[op->size] = 0; } memcpy(req->vp, op, (op->size + 2)); (req->vp) += 2; (req->vp) += op->size; } req->opAdded[op->opt_code] = true; } } DWORD updateDHCP(data9 *req) { time_t t = time(NULL); data8 *dhcpData = (data8*)calloc(1, sizeof(data8)); strcpy(dhcpData->hostname, req->hostname); memcpy(dhcpData->bp_chaddr, req->dhcpp.header.bp_chaddr, req->dhcpp.header.bp_hlen); dhcpData->bp_hlen = req->dhcpp.header.bp_hlen; dhcpData->ip = req->dhcpEntry->ip; if (!req->dhcpEntry->fixed) dhcpData->source = req->dhcpEntry->source; if (!req->req_type) { dhcpData->expiry = LONG_MAX; setLeaseExpiry(req->dhcpEntry, LONG_MAX, req->req_type == DHCP_MESS_REQUEST); } else if (req->lease > (DWORD)(LONG_MAX - t)) { dhcpData->expiry = LONG_MAX; setLeaseExpiry(req->dhcpEntry, LONG_MAX, req->req_type == DHCP_MESS_REQUEST); } else if (req->lease) { dhcpData->expiry = t + req->lease; setLeaseExpiry(req->dhcpEntry, req->lease, req->req_type == DHCP_MESS_REQUEST); } else { dhcpData->expiry = 0; req->dhcpEntry->expiry = 0; } addToCache(cacheInd, req->hostname, req->dhcpEntry->ip, dhcpData->expiry, LOCAL_A, NONE, cfig.serial1); if (makeLocal(req->dhcpEntry->ip)) addToCache(cacheInd, req->hostname, req->dhcpEntry->ip, dhcpData->expiry, NONE, LOCAL_PTR_AUTH, cfig.serial2); else addToCache(cacheInd, req->hostname, req->dhcpEntry->ip, dhcpData->expiry, NONE, LOCAL_PTR_NAUTH, cfig.serial2); if (req->dhcpEntry->dhcpInd) dhcpData->dhcpInd = req->dhcpEntry->dhcpInd; else { cfig.dhcpIndex++; req->dhcpEntry->dhcpInd = cfig.dhcpIndex; } dhcpData->local = req->dhcpEntry->local; if (!(_beginthread(updateStateFile, 0, (void*)dhcpData) > 0)) { free(dhcpData); } return req->dhcpEntry->ip; } void setLeaseExpiry(data7 *dhcpEntry, time_t expiry, bool active) { //printf("%u\n", active); time_t t = time(NULL); if (dhcpService && dhcpEntry && dhcpEntry->ip) { if (LONG_MAX - t < expiry) dhcpEntry->expiry = LONG_MAX; else dhcpEntry->expiry = t + expiry; if (active && !dhcpEntry->local) { dhcpAge.insert(pair<long, data7*>(dhcpEntry->expiry, dhcpEntry)); dhcpEntry->local = 1; } if (dhcpEntry->rangeInd >= 0 && dhcpEntry->rangeInd < MAX_RANGES) { DWORD iip = htonl(dhcpEntry->ip); if (iip >= cfig.dhcpRanges[dhcpEntry->rangeInd].rangeStart && iip <= cfig.dhcpRanges[dhcpEntry->rangeInd].rangeEnd) { int ind = iip - cfig.dhcpRanges[dhcpEntry->rangeInd].rangeStart; if (cfig.dhcpRanges[dhcpEntry->rangeInd].expiry[ind] != LONG_MAX) cfig.dhcpRanges[dhcpEntry->rangeInd].expiry[ind] = dhcpEntry->expiry; cfig.dhcpRanges[dhcpEntry->rangeInd].dhcpEntry[ind] = dhcpEntry; } } } } void setLeaseExpiry(DWORD ip, time_t expiry) { time_t t = time(NULL); if (dhcpService && ip) { DWORD iip = htonl(ip); for (char rangeInd = 0; rangeInd < MAX_RANGES && cfig.dhcpRanges[rangeInd].rangeStart; rangeInd++) { if (iip >= cfig.dhcpRanges[rangeInd].rangeStart && iip <= cfig.dhcpRanges[rangeInd].rangeEnd) { int ind = iip - cfig.dhcpRanges[rangeInd].rangeStart; if (cfig.dhcpRanges[rangeInd].expiry[ind] != LONG_MAX) { if (LONG_MAX - t < expiry) cfig.dhcpRanges[rangeInd].expiry[ind] = LONG_MAX; else cfig.dhcpRanges[rangeInd].expiry[ind] = t + expiry; } break; } } } } DWORD sendRepl(data9 *req) { data3 op; if (cfig.replication == 1) { req->target.sin_addr.s_addr = cfig.zoneServers[1]; } else if (cfig.replication == 2) { req->target.sin_addr.s_addr = cfig.zoneServers[0]; } else { return 0; } req->target.sin_port = htons(IPPORT_DHCPS); req->target.sin_family = AF_INET; BYTE *opPointer = req->dhcpp.vend_data; while ((*opPointer) < UCHAR_MAX && opPointer < req->vp) { if ((*opPointer) == DHCP_OPTION_MESSAGETYPE) { *(opPointer + 2) = DHCP_MESS_INFORM; break; } opPointer = opPointer + *(opPointer + 1) + 2; } if (opPointer >= req->vp) { op.opt_code = DHCP_OPTION_MESSAGETYPE; op.size = 1; op.value[0] = DHCP_MESS_INFORM; memcpy(req->vp, &op, (op.size + 2)); (req->vp) += 2; (req->vp) += op.size; } op.opt_code = DHCP_OPTION_SERIAL; op.size = 4; pULong(op.value, cfig.serial1); memcpy(req->vp, &op, (op.size + 2)); (req->vp) += 2; (req->vp) += op.size; //printf("Here1 %u\n",req->vp); *(req->vp) = 255; req->bytes = (DWORD)req->vp - (DWORD)req->raw; req->bytes++; //printf("Here2\n"); req->dhcpp.header.bp_op = BOOTP_REQUEST; errno = 0; //printf("%i\n", req->bytes); req->bytes = sendto(network.dhcpReplConn.sock, req->raw, req->bytes, 0, (sockaddr*)&req->target, sizeof(req->target)); //printf("Here3\n"); errno = WSAGetLastError(); if (errno || req->bytes <= 0) { if (cfig.dhcpLogLevel) { if (cfig.replication == 1) sprintf(logBuff, "Error %u Sending DHCP Update to Secondary Server", errno); else sprintf(logBuff, "Error %u Sending DHCP Update to Primary Server", errno); logDHCPMess(logBuff, 2); } return 0; } else if (cfig.dhcpLogLevel == 2) { if (cfig.replication == 1) sprintf(logBuff, "DHCP Update for host %s (%s) sent to Secondary Server", hex2String(extbuff, req->dhcpp.header.bp_chaddr, req->dhcpp.header.bp_hlen, ':'), IP2String(tempbuff, req->dhcpEntry->ip)); else sprintf(logBuff, "DHCP Update for host %s (%s) sent to Primary Server", hex2String(extbuff, req->dhcpp.header.bp_chaddr, req->dhcpp.header.bp_hlen, ':'), IP2String(tempbuff, req->dhcpEntry->ip)); logDHCPMess(logBuff, 2); } return req->dhcpp.header.bp_yiaddr; } DWORD sendRepl(data7 *dhcpEntry) { data9 req; data3 op; req.vp = req.dhcpp.vend_data; req.messsize = sizeof(dhcp_packet); req.dhcpEntry = dhcpEntry; if (cfig.replication == 1) req.target.sin_addr.s_addr = cfig.zoneServers[1]; else if (cfig.replication == 2) req.target.sin_addr.s_addr = cfig.zoneServers[0]; else return 0; req.target.sin_port = htons(IPPORT_DHCPS); req.target.sin_family = AF_INET; req.dhcpp.header.bp_op = BOOTP_REQUEST; req.dhcpp.header.bp_xid = time(NULL); req.dhcpp.header.bp_ciaddr = dhcpEntry->ip; req.dhcpp.header.bp_yiaddr = dhcpEntry->ip;; req.dhcpp.header.bp_hlen = fromUUE(req.dhcpp.header.bp_chaddr, dhcpEntry->mapname); 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; op.opt_code = DHCP_OPTION_MESSAGETYPE; op.size = 1; op.value[0] = DHCP_MESS_INFORM; memcpy(req.vp, &op, (op.size + 2)); (req.vp) += 2; (req.vp) += op.size; op.opt_code = DHCP_OPTION_SERIAL; op.size = 4; pULong(op.value, cfig.serial1); memcpy(req.vp, &op, (op.size + 2)); (req.vp) += 2; (req.vp) += op.size; op.opt_code = DHCP_OPTION_IPADDRLEASE; op.size = 4; pULong(op.value, 0); memcpy(req.vp, &op, (op.size + 2)); (req.vp) += 2; (req.vp) += op.size; data7 *cache = findEntry(cacheInd, IP2String(tempbuff, htonl(dhcpEntry->ip))); if (cache) { op.opt_code = DHCP_OPTION_HOSTNAME; op.size = strlen(cache->hostname); memcpy(op.value, cache->hostname, op.size); memcpy(req.vp, &op, (op.size + 2)); (req.vp) += 2; (req.vp) += op.size; } *(req.vp) = 255; req.bytes = (DWORD)req.vp - (DWORD)req.raw; req.bytes++; errno = 0; req.bytes = sendto(network.dhcpReplConn.sock, req.raw, req.bytes, 0, (sockaddr*)&req.target, sizeof(req.target)); errno = WSAGetLastError(); if (errno || req.bytes <= 0) { if (cfig.dhcpLogLevel) { if (cfig.replication == 1) sprintf(logBuff, "Error %u Sending DHCP Update to Secondary Server", errno); else sprintf(logBuff, "Error %u Sending DHCP Update to Primary Server", errno); logDHCPMess(logBuff, 2); } return 0; } else if (cfig.dhcpLogLevel == 2) { if (cfig.replication == 1) sprintf(logBuff, "DHCP Update for host %s (%s) sent to Secondary Server", hex2String(extbuff, req.dhcpp.header.bp_chaddr, req.dhcpp.header.bp_hlen, ':'), IP2String(tempbuff, req.dhcpEntry->ip)); else sprintf(logBuff, "DHCP Update for host %s (%s) sent to Primary Server", hex2String(extbuff, req.dhcpp.header.bp_chaddr, req.dhcpp.header.bp_hlen, ':'), IP2String(tempbuff, req.dhcpEntry->ip)); logDHCPMess(logBuff, 2); } return req.dhcpp.header.bp_yiaddr; } void recvRepl(data9 *req) { time_t t = time(NULL); //printf("Here 2\n"); DWORD ip = req->dhcpp.header.bp_yiaddr ? req->dhcpp.header.bp_yiaddr : req->dhcpp.header.bp_ciaddr; if (!cfig.replication || !ip || !req->lease) return; else if (cfig.replication == 1 && req->addr.sin_addr.s_addr != cfig.zoneServers[1]) return; else if (cfig.replication == 2 && req->addr.sin_addr.s_addr != cfig.zoneServers[0]) return; //printf("Here 3\n"); char rInd = -1; if (dhcpService) { rInd = getRangeInd(ip); req->dhcpEntry = dhcpCache[toUUE(tempbuff, req->dhcpp.header.bp_chaddr, req->dhcpp.header.bp_hlen)]; if (!req->dhcpEntry && rInd >= 0) { req->dhcpEntry = (data7*)calloc(1, sizeof(data7)); if (!req->dhcpEntry) { sprintf(logBuff, "Memory Allocation Error"); logDHCPMess(logBuff, 1); return; } req->dhcpEntry->mapname = cloneString(toUUE(tempbuff, req->dhcpp.header.bp_chaddr, req->dhcpp.header.bp_hlen)); if (!req->dhcpEntry->mapname) { sprintf(logBuff, "Memory Allocation Error"); free(req->dhcpEntry); logDHCPMess(logBuff, 1); return; } //req->dhcpEntry->dataType = DHCP; dhcpCache[req->dhcpEntry->mapname] = req->dhcpEntry; } } if (dhcpService && req->dhcpEntry) { req->dhcpEntry->ip = ip; req->dhcpEntry->rangeInd = rInd; //printf("Here 4\n"); if (updateDHCP(req)) { cfig.serial1 = req->serial; cfig.serial2 = req->serial; if (cfig.replication == 2) { if (cfig.expire > (DWORD)(LONG_MAX - t)) cfig.expireTime = LONG_MAX; else cfig.expireTime = t + cfig.expire; } else cfig.expireTime = LONG_MAX; } } else { cfig.serial1 = req->serial; cfig.serial2 = req->serial; if (cfig.replication == 2) { if (cfig.expire > (DWORD)(LONG_MAX - t)) cfig.expireTime = LONG_MAX; else cfig.expireTime = t + cfig.expire; } else cfig.expireTime = LONG_MAX; time_t expiry = 0; if (req->lease > (DWORD)(LONG_MAX - t)) expiry = LONG_MAX; else expiry = t + req->lease; addToCache(cacheInd, req->hostname, ip, expiry, LOCAL_A, NONE, cfig.serial1); if (makeLocal(ip)) addToCache(cacheInd, req->hostname, ip, expiry, NONE, LOCAL_PTR_AUTH, cfig.serial2); else addToCache(cacheInd, req->hostname, ip, expiry, NONE, LOCAL_PTR_NAUTH, cfig.serial2); } if (cfig.dhcpLogLevel == 2) { if (cfig.replication == 1) sprintf(logBuff, "DHCP Update received for %s (%s) from Secondary Server", hex2String(extbuff, req->dhcpp.header.bp_chaddr, req->dhcpp.header.bp_hlen, ':'), IP2String(tempbuff, req->dhcpEntry->ip)); else sprintf(logBuff, "DHCP Update received for %s (%s) from Primary Server", hex2String(extbuff, req->dhcpp.header.bp_chaddr, req->dhcpp.header.bp_hlen, ':'), IP2String(tempbuff, req->dhcpEntry->ip)); logDHCPMess(logBuff, 2); } } char getRangeInd(DWORD ip) { if (dhcpService && ip) { DWORD iip = htonl(ip); for (char k = 0; k < MAX_RANGES && cfig.dhcpRanges[k].rangeStart; k++) if (iip >= cfig.dhcpRanges[k].rangeStart && iip <= cfig.dhcpRanges[k].rangeEnd) return k; } return -1; } int getIndex(char rangeInd, DWORD ip) { if (dhcpService && ip && rangeInd >= 0 && rangeInd < MAX_RANGES) { DWORD iip = htonl(ip); if (iip >= cfig.dhcpRanges[rangeInd].rangeStart && iip <= cfig.dhcpRanges[rangeInd].rangeEnd) return (iip - cfig.dhcpRanges[rangeInd].rangeStart); } return -1; } void loadOptions(char *iniStr, char *sectionName, data20 *optionData) { optionData->options = 0; optionData->ip = 0; optionData->mask = 0; BYTE maxInd = sizeof(opData) / sizeof(data4); BYTE options[sizeof(dhcp_packet) - sizeof(dhcp_header)]; WORD buffsize = sizeof(options); BYTE *dp = options; *dp = 0; dp++; char *iniStrPtr = myGetToken(iniStr, 0); for (; iniStrPtr[0]; iniStrPtr = myGetToken(iniStrPtr, 1)) { char name[512]; char value[512]; BYTE hoption[256]; BYTE valueSize = sizeof(hoption) - 1; BYTE opTag = 0; BYTE opType = 0; BYTE valType = 0; bool tagFound = false; mySplit(name, value, iniStrPtr, '='); if (!name[0]) { sprintf(logBuff, "Warning: section [%s] invalid option %s ignored", sectionName, iniStrPtr); logMess(logBuff, 1); continue; } if (!strcasecmp(name, "DHCP_Range")) { if (!strcasecmp(sectionName, "DHCP-RANGE")) { addDHCPRange(value); } else { sprintf(logBuff, "Warning: section [%s] option %s not allowed in this section, option ignored", sectionName, iniStrPtr); logMess(logBuff, 1); } continue; } else if (!strcasecmp(name, "IP_Addr")) { if (!strcasecmp(sectionName, "DHCP-OPTIONS") || !strcasecmp(sectionName, "DHCP-RANGE")) { sprintf(logBuff, "Warning: section [%s] option %s not allowed in this section, option ignored", sectionName, iniStrPtr); logMess(logBuff, 1); } else if (!isIP(value)) { sprintf(logBuff, "Warning: section [%s] option %s Invalid IP Addr %s option ignored", sectionName, value); logMess(logBuff, 1); } else optionData->ip = my_inet_addr(value); continue; } else if (!strcasecmp(name, "Subnet_Mask")) { if (!isIP(value) || !checkMask(my_inet_addr(value))) { sprintf(logBuff, "Warning: section [%s] Invalid %s %s, option ignored", sectionName, name, value); logMess(logBuff, 1); continue; } else optionData->mask = my_inet_addr(value); } else if (!strcasecmp(name, "Filter_Mac_Range")) { if (!strcasecmp(sectionName, "DHCP-RANGE")) addMacRange(optionData->rangeSetInd, value); else { sprintf(logBuff, "Warning: section [%s] option %s not allowed in this section, option ignored", sectionName, iniStrPtr); logMess(logBuff, 1); } continue; } else if (!strcasecmp(name, "Filter_Vendor_Class")) { if (!strcasecmp(sectionName, "DHCP-RANGE")) { valueSize = strlen(value); addVendClass(optionData->rangeSetInd, value, valueSize); } else { sprintf(logBuff, "Warning: section [%s] option %s not allowed in this section, option ignored", sectionName, iniStrPtr); logMess(logBuff, 1); } continue; } else if (!strcasecmp(name, "Filter_User_Class")) { if (!strcasecmp(sectionName, "DHCP-RANGE")) { valueSize = strlen(value); addUserClass(optionData->rangeSetInd, value, valueSize); } else { sprintf(logBuff, "Warning: section [%s] option %s not allowed in this section, option ignored", sectionName, iniStrPtr); logMess(logBuff, 1); } continue; } if (!value[0]) valType = 8; else if (value[0] == '"' && value[strlen(value)-1] == '"') { valType = 1; value[0] = 32; value[strlen(value)-1] = 32; myTrim(value, value); if (strlen(value) <= 255) valueSize = strlen(value); else { sprintf(logBuff, "Warning: section [%s] option %s value too big, option ignored", sectionName, iniStrPtr); logMess(logBuff, 1); continue; } } else if (strchr(value, ':')) { valType = 2; valueSize = sizeof(hoption) - 1; char *errorPos = getHexValue(hoption, value, &valueSize); if (errorPos) { sprintf(logBuff, "Warning: section [%s] option %s position %u, Invalid char %c, option ignored", sectionName, name, ((DWORD)errorPos - (DWORD)value) + 1, *(errorPos)); logMess(logBuff, 1); continue; } else memcpy(value, hoption, valueSize); } else if (isInt(value) && atol(value) > USHRT_MAX) valType = 4; else if (isInt(value) && atoi(value) > UCHAR_MAX) valType = 5; else if (isInt(value)) valType = 6; else { if (myTokenize(tempbuff, value, "/,", true) && isIP(tempbuff)) { char *ptr = tempbuff; for (; *ptr; ptr = myGetToken(ptr, 1)) { if (!isIP(ptr) || (!my_inet_addr(ptr) && strcasecmp(ptr, "255.255.255.255") && strcasecmp(ptr, "0.0.0.0"))) break; } if (*ptr) { sprintf(logBuff, "Warning: section [%s] option %s invalid IP %s, entry ignored", sectionName, iniStrPtr, ptr); logMess(logBuff, 1); continue; } valType = 3; } else { if (strlen(value) <= 255) valueSize = strlen(value); else { sprintf(logBuff, "Warning: section [%s] option %s value too big, option ignored", sectionName, iniStrPtr); logMess(logBuff, 1); continue; } valType = 1; } } if (isInt(name)) { opTag = atoi(name); opType = 0; } for (BYTE 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, iniStrPtr); logMess(logBuff, 1); continue; } //sprintf(logBuff, "Tag %i ValType %i opType %i value=%s", opTag, valType, opType, value); //logMess(logBuff, 1); if (valType == 8) { 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, iniStrPtr); logMess(logBuff, 1); } continue; } switch (opType) { case 1: { if (valType != 1 && valType != 2) { sprintf(logBuff, "Warning: section [%s] option %s, need string value, option ignored", sectionName, iniStrPtr); logMess(logBuff, 1); } else if (opTag == DHCP_OPTION_DOMAINNAME) { sprintf(logBuff, "Warning: section [%s] option %u should be under [DOMAIN-NAME], ignored", sectionName, opTag); logMess(logBuff, 1); continue; } else if (buffsize > strlen(value) + 2) { *dp = opTag; dp++; *dp = strlen(value); dp++; memcpy(dp, value, valueSize); dp += (strlen(value)); buffsize -= (valueSize + 2); } else { sprintf(logBuff, "Warning: section [%s] option %s, no more space for options", sectionName, iniStrPtr); logMess(logBuff, 1); } } break; case 3: { if (valType == 2) { if (valueSize % 4) { sprintf(logBuff, "Warning: section [%s] option %s, hex value should be multiple of 4 hex bytes, option ignored", sectionName, iniStrPtr); logMess(logBuff, 1); continue; } if (buffsize > valueSize + 2) { *dp = opTag; dp++; *dp = valueSize; dp++; memcpy(dp, value, valueSize); dp += valueSize; buffsize -= (valueSize + 2); } else { sprintf(logBuff, "Warning: section [%s] option %s, no more space for options", sectionName, iniStrPtr); logMess(logBuff, 1); } } else { BYTE *lastOptionIndex = 0; myTokenize(tempbuff, value, "/,", true); char *ptr = tempbuff; for (; *ptr; ptr = myGetToken(ptr, 1)) { DWORD j = my_inet_addr(ptr); if (buffsize > 6) { if (lastOptionIndex) *(lastOptionIndex + 1) += 4; else { lastOptionIndex = dp; *dp = opTag; dp++; *dp = 4; dp++; buffsize -= 2; } dp += pIP(dp, j); buffsize -= 4; } else { sprintf(logBuff, "Warning: section [%s] option %s, no more space for options", sectionName, iniStrPtr); logMess(logBuff, 1); } } } } break; case 4: { DWORD j; if (valType == 2 && valueSize == 4) j = fULong(value); else if (valType >= 4 && valType <= 6) j = atol(value); else { sprintf(logBuff, "Warning: section [%s] option %s, value should be between 0 & %u, option ignored", sectionName, iniStrPtr, ULONG_MAX); logMess(logBuff, 1); continue; } if (opTag == DHCP_OPTION_IPADDRLEASE) { if (!strcasecmp(sectionName, "DHCP-OPTIONS")) { sprintf(logBuff, "Warning: section [%s] option %s not allowed in this section, please set it in [TIMINGS] section", sectionName, iniStrPtr); logDHCPMess(logBuff, 1); continue; } if (j == 0) j = ULONG_MAX; if (j > cfig.lease) { sprintf(logBuff, "Warning: section [%s] option %s value should be less then %u, ignored", sectionName, name, cfig.lease); logDHCPMess(logBuff, 1); continue; } } if (buffsize > 6) { *dp = opTag; dp++; *dp = 4; dp++; dp += pULong(dp, j); buffsize -= 6; //printf("%s=%u=%u\n",opData[op_index].opName,opData[op_index].opType,htonl(j)); } else { sprintf(logBuff, "Warning: section [%s] option %s, no more space for options", sectionName, iniStrPtr); logMess(logBuff, 1); } } break; case 5: { WORD j; if (valType == 2 && valueSize == 2) j = fUShort(value); else if (valType == 5 || valType == 6) j = atol(value); else { sprintf(logBuff, "Warning: section [%s] option %s, value should be between 0 & %u, option ignored", sectionName, iniStrPtr, USHRT_MAX); logMess(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, iniStrPtr); logMess(logBuff, 1); } } break; case 6: { BYTE j; if (valType == 2 && valueSize == 1) j = *value; else if (valType == 6) j = atol(value); else { sprintf(logBuff, "Warning: section [%s] option %s, value should be between 0 & %u, option ignored", sectionName, iniStrPtr, UCHAR_MAX); logMess(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, iniStrPtr); logMess(logBuff, 1); } } break; case 7: { BYTE j; if (valType == 2 && valueSize == 1 && *value < 2) j = *value; else if (valType == 1 && !strcasecmp(value, "yes")) j = 1; else if (valType == 1 && !strcasecmp(value, "no")) j = 0; else { sprintf(logBuff, "Warning: section [%s] option %s, value should be yes or no, option ignored", sectionName, iniStrPtr); logMess(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, iniStrPtr); logMess(logBuff, 1); } } break; default: { if (opType == 2 && valType != 2) { sprintf(logBuff, "Warning: section [%s] option %s, value should be hex string, option ignored", sectionName, iniStrPtr); logMess(logBuff, 1); continue; } if (buffsize > valueSize + 2) { *dp = opTag; dp++; *dp = valueSize; dp++; memcpy(dp, value, valueSize); dp += valueSize; buffsize -= (valueSize + 2); } else { sprintf(logBuff, "Warning: section [%s] option %s, no more space for options", sectionName, iniStrPtr); logMess(logBuff, 1); } } break; } //printf("%s\n", iniStrPtr); //printf("%u %s\n", ddp, hex2String(tempbuff, ddp, (*(ddp+1))+2, ':')); } //printf("%s=%s\n", sectionName, optionData->vendClass); *dp = DHCP_OPTION_END; dp++; WORD optionSize = ((DWORD)dp - (DWORD)options); if (optionSize > 2) { optionData->options = (BYTE*)calloc(1, optionSize); if (!optionData->options) { sprintf(logBuff, "DHCP Option Load, Memory Allocation Error"); logMess(logBuff, 1); } memcpy(optionData->options, options, optionSize); } } void lockOptions(char *iniStr) { char name[512]; char value[512]; char *iniStrPtr = myGetToken(iniStr, 0); for (; iniStrPtr[0]; iniStrPtr = myGetToken(iniStrPtr, 1)) { mySplit(name, value, iniStrPtr, '='); if (!name[0]) continue; int op_index; BYTE 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 && atoi(name) == opData[op_index].opTag)) break; if (op_index >= n) continue; if (opData[op_index].opType == 0) { //printf("Tag %s Locked\n", value); DWORD inetAddr = my_inet_addr(value); if (inetAddr != INADDR_ANY && inetAddr != INADDR_NONE) setLeaseExpiry(inetAddr, LONG_MAX); } } } char* myGetToken(char* buff, BYTE index) { while (*buff) { if (index) index--; else break; buff += strlen(buff) + 1; } return buff; } WORD myTokenize(char *target, char *source, char *sep, bool whiteSep) { bool found = true; char *dp = target; WORD kount = 0; while (*source) { if (sep && sep[0] && strchr(sep, (*source))) { found = true; source++; continue; } else if (whiteSep && *source <= 32) { 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) <= 32) source++; int i = 0; for (; i < 511 && source[i]; i++) target[i] = source[i]; target[i] = source[i]; i--; for (; i >= 0 && target[i] <= 32; i--) target[i] = 0; return target; } void mySplit(char *name, char *value, 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 *strqtype(char *buff, BYTE qtype) { switch (qtype) { case 1: strcpy(buff, "A"); break; case 2: strcpy(buff, "NS"); break; case 3: strcpy(buff, "MD"); break; case 4: strcpy(buff, "MF"); break; case 5: strcpy(buff, "CNAME"); break; case 6: strcpy(buff, "SOA"); break; case 7: strcpy(buff, "MB"); break; case 8: strcpy(buff, "MG"); break; case 9: strcpy(buff, "MR"); break; case 10: strcpy(buff, "NULL"); break; case 11: strcpy(buff, "WKS"); break; case 12: strcpy(buff, "PTR"); break; case 13: strcpy(buff, "HINFO"); break; case 14: strcpy(buff, "MINFO"); break; case 15: strcpy(buff, "MX"); break; case 16: strcpy(buff, "TXT"); break; case 28: strcpy(buff, "AAAA"); break; case 251: strcpy(buff, "IXFR"); break; case 252: strcpy(buff, "AXFR"); break; case 253: strcpy(buff, "MAILB"); break; case 254: strcpy(buff, "MAILA"); break; default: strcpy(buff, "ANY"); break; } return buff; } bool getSection(const char *sectionName, char *buffer, BYTE 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]; BYTE 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); } DWORD getClassNetwork(DWORD ip) { data15 data; data.ip = ip; data.octate[3] = 0; if (data.octate[0] < 192) data.octate[2] = 0; if (data.octate[0] < 128) data.octate[1] = 0; return data.ip; } /* char *IP2Auth(DWORD 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, DWORD ip) { data15 inaddr; inaddr.ip = ip; sprintf(target, "%u.%u.%u.%u", inaddr.octate[0], inaddr.octate[1], inaddr.octate[2], inaddr.octate[3]); //BYTE *octate = (BYTE*)&ip; //sprintf(target, "%u.%u.%u.%u", octate[0], octate[1], octate[2], octate[3]); return target; } bool addServer(DWORD *array, DWORD ip) { for (BYTE i = 0; i < MAX_SERVERS; i++) { if (!ip || array[i] == ip) return 0; else if (!array[i]) { array[i] = ip; return 1; } } return 0; } DWORD *findServer(DWORD *array, DWORD ip) { if (ip) { for (BYTE i = 0; i < MAX_SERVERS && array[i]; i++) { if (array[i] == ip) return &(array[i]); } } return 0; } bool isInt(char *string) { if (!(*string)) return false; for(; *string; string++) if (*string < '0' || *string > '9') return false; return true; } bool isIP(char *string) { int j = 0; for (; *string; string++) { if (*string == '.' && *(string + 1) != '.') j++; else if (*string < '0' || *string > '9') return 0; } if (j == 3) return 1; else return 0; } char *toBase64(BYTE *source, BYTE length) { BYTE 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; } BYTE getBaseValue(BYTE 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 = 255; return a; } BYTE fromBase64(BYTE *target, char *source) { //printf("SOURCE=%s\n", source); BYTE b = 0; BYTE shift = 4; BYTE 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, BYTE *source, BYTE length) { BYTE a = 0, b = 0, i = 0; char *dp = tempbuff; for (; length; length--, source++) { i += 2; a = (*source) >> i; *dp = a + b + 32; dp++; b = (*source) << (8 - i); b >>= 2; if (i == 6) { *dp = b + 32; dp++; i = b = 0; } } if (i) { *dp = b + 32; dp++; } *dp = 0; //printf("%s\n",tempbuff); return tempbuff; } BYTE fromUUE(BYTE *target, char *source) { //printf("SOURCE=%s\n", source); BYTE b = 0; BYTE shift = 4; BYTE bp_hlen = (3 * strlen(source))/4; *target = 0; if (*source) { b = *source - 32; *target = b << 2; source++; while (*source) { b = *source - 32; (*target) += (b >> (8 - shift)); target++; (*target) = (b << shift); shift += 2; if (shift > 8) { source++; if (*source) { b = *source - 32; *target = b << 2; shift = 4; } else break; } source++; } } //printf("SIZE=%u\n", bp_hlen); return bp_hlen; } char *hex2String(char *target, BYTE *hex, BYTE bytes, char sepChar) { char *dp = target; if (bytes) dp += sprintf(target, "%02x", *hex); else *target = 0; for (BYTE i = 1; i < bytes; i++) if (sepChar) dp += sprintf(dp, "%c%02x", sepChar, *(hex + i)); else dp += sprintf(dp, "%02x", *(hex + i)); return target; } char *IP62String(char *target, BYTE *source) { bool started = false; for (BYTE i = 0; i < 16; i += 2, source += 2) { if (source[0]) { target += sprintf(target, "%x", source[0]); target += sprintf(target, "%02x", source[1]); started = true; } else if (source[1] || started) { target += sprintf(target, "%0x", source[1]); started = true; } else if (i == 8) target += sprintf(target, ":"); if (i < 14 && started) target += sprintf(target, ":"); if (i == 6) started = false; } return NULL; } char *getHexValue(BYTE *target, char *source, BYTE *size) { if (*size) memset(target, 0, (*size)); if (*source == ':') source++; 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++; continue; } else if (*source) return source; else continue; source++; if ((*source) == ':') source++; else if (*source) return source; } if (*source) return source; return NULL; } char *myUpper(char *string) { char diff = 'a' - 'A'; WORD len = strlen(string); for (int i = 0; i < len; i++) if (string[i] >= 'a' && string[i] <= 'z') string[i] -= diff; return string; } char *myLower(char *string) { char diff = 'a' - 'A'; WORD len = strlen(string); for (int i = 0; i < len; i++) if (string[i] >= 'A' && string[i] <= 'Z') string[i] += diff; return string; } bool wildcmp(char *string, char *wild) { // Written by Jack Handy - jakkhandy@hotmail.com // slightly modified char *cp = NULL; char *mp = NULL; while ((*string) && (*wild != '*')) { if ((*wild != *string) && (*wild != '?')) { return 0; } wild++; string++; } while (*string) { if (*wild == '*') { if (!*++wild) return 1; mp = wild; cp = string + 1; } else if ((*wild == *string) || (*wild == '?')) { wild++; string++; } else { wild = mp; string = cp++; } } while (*wild == '*') wild++; return !(*wild); } BYTE makeLocal(DWORD ip) { if (cfig.rangeStart && htonl(ip) >= cfig.rangeStart && htonl(ip) <= cfig.rangeEnd) return 1; else if (getRangeInd(ip) >= 0) return 1; else return 0; } BYTE makeLocal(char *query) { if (!strcasecmp(query, cfig.zone)) return 3; else { char *dp = strchr(query, '.'); if (dp) { if (!strcasecmp(dp + 1, cfig.zone)) { *dp = 0; return 2; } return 0; } return 1; } return 0; } void checkSize(BYTE ind) { //printf("Start %u=%u\n",dnsCache[ind].size(),dnsAge[ind].size()); time_t t = time(NULL); data7 *cache = NULL; //BYTE maxDelete = 3; expiryMap::iterator p = dnsAge[ind].begin(); expiryMap::iterator q; //while (p != dnsAge[ind].end() && p->first < t && maxDelete > 0) while (p != dnsAge[ind].end() && p->first < t) { cache = p->second; //printf("processing %s=%i\n", cache->mapname, p->first - t); if (cache->expiry < t) { q = p; p++; dnsAge[ind].erase(q); if (cache->expiry) { if (cache->dnsIndex < MAX_SERVERS) { if (cfig.currentDNS == cache->dnsIndex) { if (network.dns[1]) { cfig.currentDNS++; if (cfig.currentDNS >= MAX_SERVERS || !network.dns[cfig.currentDNS]) cfig.currentDNS = 0; } } } else if (cache->dnsIndex >= 128 && cache->dnsIndex < 192) { data6 *dnsRoute = &cfig.dnsRoutes[(cache->dnsIndex - 128) / 2]; BYTE currentDNS = cache->dnsIndex % 2; if (dnsRoute->currentDNS == currentDNS && dnsRoute->dns[1]) dnsRoute->currentDNS = 1 - dnsRoute->currentDNS; } } //printf("t=%u expiry=%u DataType=%u Size=%u, Entry %s being deleted\n", t, cache->expiry, cache->dataType, dnsCache[ind].size(), cache->mapname); delDnsEntry(ind, cache); //maxDelete--; } else if (cache->expiry > p->first) { q = p; p++; dnsAge[ind].erase(q); dnsAge[ind].insert(pair<long, data7*>(cache->expiry, cache)); } else p++; } if (ind == cacheInd && dhcpService) { //printf("dhcpAge=%u\n", dhcpAge.size()); p = dhcpAge.begin(); while (p != dhcpAge.end() && p->first < t) { cache = p->second; //printf("processing %s=%i\n", cache->mapname, p->first - t); if (cache->local && cache->expiry < t) { q = p; p++; cache->local = 0; dhcpAge.erase(q); cfig.serial1 = time(NULL); cfig.serial2 = time(NULL); if (cfig.expire > (DWORD)(LONG_MAX - t)) cfig.expireTime = LONG_MAX; else cfig.expireTime = t + cfig.expire; sendRepl(cache); //printf("Lease released\n"); } else if (cache->expiry > p->first) { q = p; p++; dhcpAge.erase(q); dhcpAge.insert(pair<long, data7*>(cache->expiry, cache)); } else p++; } } //printf("Done %u=%u\n",dnsCache[ind].size(),dnsAge[ind].size()); } void calcRangeLimits(DWORD ip, DWORD mask, DWORD *rangeStart, DWORD *rangeEnd) { *rangeStart = htonl(ip & mask) + 1; *rangeEnd = htonl(ip | (~mask)) - 1; } bool checkMask(DWORD mask) { mask = htonl(mask); while (mask) { if (mask < (mask << 1)) return false; mask <<= 1; } return true; } DWORD calcMask(DWORD rangeStart, DWORD rangeEnd) { data15 ip1, ip2, mask; ip1.ip = htonl(rangeStart); ip2.ip = htonl(rangeEnd); for (BYTE 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; } data7 *findEntry(BYTE ind, char *key, BYTE entryType) { myLower(key); hostMap::iterator it = dnsCache[ind].find(key); while (it != dnsCache[ind].end() && !strcasecmp(it->second->mapname, key)) if (it->second->dataType == entryType) return it->second; else it++; return NULL; } data7 *findEntry(BYTE ind, char *key) { //printf("finding %u=%s\n",ind,key); myLower(key); hostMap::iterator it = dnsCache[ind].find(key); if (it != dnsCache[ind].end()) return it->second; else return NULL; } void addEntry(BYTE ind, data7 *entry) { myLower(entry->mapname); dnsCache[ind].insert(pair<string, data7*>(entry->mapname, entry)); if (entry->expiry && entry->expiry < LONG_MAX) dnsAge[ind].insert(pair<long, data7*>(entry->expiry, entry)); } void delDnsEntry(BYTE ind, data7* cache) { if (cache) { //printf("DataType=%u Size=%u, Entry %s being deleted\n", cache->dataType, dnsCache[ind].size(), cache->mapname); if (ind <= 1) { hostMap::iterator r = dnsCache[ind].find(cache->mapname); for (; r != dnsCache[ind].end(); r++) if (strcasecmp(r->second->mapname, cache->mapname)) break; else if (r->second == cache) { dnsCache[ind].erase(r); break; } switch (cache->dataType) { case QUEUE: if (cache->addr) free(cache->addr); if (cache->query) free(cache->query); if (cache->mapname) free(cache->mapname); break; case LOCAL_PTR_AUTH: case LOCAL_PTR_NAUTH: case LOCALHOST_PTR: case SERVER_PTR_AUTH: case SERVER_PTR_NAUTH: case STATIC_PTR_AUTH: case STATIC_PTR_NAUTH: case LOCAL_CNAME: case EXT_CNAME: case CACHED: if (cache->hostname) free(cache->hostname); if (cache->mapname) free(cache->mapname); break; default: if (cache->mapname) free(cache->mapname); break; } free(cache); } } return ; } char *cloneString(char *string) { char *s = (char*)calloc(1, strlen(string) + 1); if (s) { strcpy(s, string); } return s; } DWORD getSerial(char *zone) { time_t t = time(NULL); char tempbuff[256]; char logBuff[256]; DWORD serial1 = 0; data5 req; memset(&req, 0, sizeof(data5)); req.addr.sin_family = AF_INET; req.addr.sin_port = htons(IPPORT_DNS); timeval tv1; fd_set readfds1; if (cfig.replication == 2) req.addr.sin_addr.s_addr = cfig.zoneServers[0]; else req.addr.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.xid = (t % USHRT_MAX); req.data = &req.dnsp->data; req.data += pQu(req.data, zone); req.data += pUShort(req.data, DNS_TYPE_SOA); req.data += pUShort(req.data, DNS_CLASS_IN); req.bytes = (DWORD)req.data - (DWORD)req.raw; //pUShort(req.raw, req.bytes - 2); if ((req.bytes = sendto(req.sock, req.raw, req.bytes, 0, (sockaddr*)&req.addr, sizeof(req.addr))) <= 0) { closesocket(req.sock); sprintf(logBuff, "Failed to send request to Primary Server %s", IP2String(tempbuff, req.addr.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, NULL, NULL, &tv1); if (FD_ISSET(req.sock, &readfds1)) { req.sockLen = sizeof(req.addr); req.bytes = recvfrom(req.sock, req.raw, sizeof(req.raw), 0, (sockaddr*)&req.addr, &req.sockLen); if (req.bytes > 0 && req.dnsp->header.qr && !req.dnsp->header.rcode && ntohs(req.dnsp->header.ancount)) { req.data = &req.dnsp->data; for (int j = 1; j <= ntohs(req.dnsp->header.qdcount); j++) { req.data += fQu(tempbuff, req.dnsp, req.data); req.data += 4; } for (int i = 1; i <= ntohs(req.dnsp->header.ancount); i++) { req.data += fQu(tempbuff, req.dnsp, req.data); req.qtype = fUShort(req.data); req.data += 2; //type req.qclass = fUShort(req.data); req.data += 2; //class fULong(req.data); req.data += 4; //ttl req.data += 2; //datalength if (req.qtype == DNS_TYPE_SOA) { req.data += fQu(tempbuff, req.dnsp, req.data); req.data += fQu(tempbuff, req.dnsp, req.data); serial1 = fULong(req.data); } } } } closesocket(req.sock); return serial1; } void checkDNS(BYTE dnsIndex) { time_t t = time(NULL); //printf("DNS Index %u\n", dnsIndex); data5 req; memset(&req, 0, sizeof(data5)); strcpy(req.query, "1.0.0.127.in-addr.arpa"); req.addr.sin_family = AF_INET; req.addr.sin_port = htons(IPPORT_DNS); if (dnsIndex < MAX_SERVERS) { if (cfig.currentDNS == dnsIndex) req.addr.sin_addr.s_addr = network.dns[dnsIndex]; else return ; } else if (dnsIndex >= 128 && dnsIndex < 192) { BYTE childIndex = (dnsIndex - 128) / 2; data6 *dnsRoute = &cfig.dnsRoutes[childIndex]; BYTE currentDNS = dnsIndex % 2; if (dnsRoute->currentDNS == currentDNS) req.addr.sin_addr.s_addr = dnsRoute->dns[currentDNS]; else return ; } else return ; req.dnsp = (dnsPacket*)req.raw; req.dnsp->header.qdcount = htons(1); req.dnsp->header.xid = (t % USHRT_MAX); req.data = &req.dnsp->data; req.data += pQu(req.data, req.query); req.data += pUShort(req.data, DNS_TYPE_PTR); req.data += pUShort(req.data, DNS_CLASS_IN); req.bytes = (DWORD)req.data - (DWORD)req.raw; char mapname[8]; sprintf(mapname, "%u", req.dnsp->header.xid); data7 *queue = findEntry(cacheInd, mapname, DNS_CHECK); if (!queue) { if ((req.bytes = sendto(network.forwConn.sock, req.raw, req.bytes, 0, (sockaddr*)&req.addr, sizeof(req.addr))) > 0) { queue = (data7*)calloc(1, sizeof(data7)); if (queue) { queue->mapname = cloneString(mapname); if (!queue->mapname) { free(queue); return ; } queue->expiry = 2 + t; queue->dataType = DNS_CHECK; queue->sockInd = 255; queue->dnsIndex = dnsIndex; addEntry(cacheInd, queue); } else return ; if (cfig.dnsLogLevel) { if (dnsIndex < MAX_SERVERS) sprintf(logBuff, "Verification sent to Forwarding DNS Server %s", IP2String(tempbuff, req.addr.sin_addr.s_addr)); else sprintf(logBuff, "Verification sent to Child DNS Server %s", IP2String(tempbuff, req.addr.sin_addr.s_addr)); logDNSMess(logBuff, 1); } } } } char *getServerName(char *target, DWORD ip) { time_t t = time(NULL); data5 req; memset(&req, 0, sizeof(data5)); req.addr.sin_family = AF_INET; req.addr.sin_port = htons(IPPORT_DNS); req.addr.sin_addr.s_addr = ip; timeval tv1; fd_set readfds1; req.sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); req.dnsp = (dnsPacket*)req.raw; req.dnsp->header.qdcount = htons(1); req.dnsp->header.xid = (t % USHRT_MAX); req.data = &req.dnsp->data; IP2String(target, htonl(ip)); strcat(target, arpa); req.data += pQu(req.data, target); req.data += pUShort(req.data, DNS_TYPE_PTR); req.data += pUShort(req.data, DNS_CLASS_IN); req.bytes = (DWORD)req.data - (DWORD)req.raw; //pUShort(req.raw, req.bytes - 2); if ((req.bytes = sendto(req.sock, req.raw, req.bytes, 0, (sockaddr*)&req.addr, sizeof(req.addr))) <= 0) { closesocket(req.sock); return NULL; } FD_ZERO(&readfds1); tv1.tv_sec = 5; tv1.tv_usec = 0; FD_SET(req.sock, &readfds1); select(USHRT_MAX, &readfds1, NULL, NULL, &tv1); if (FD_ISSET(req.sock, &readfds1)) { req.sockLen = sizeof(req.addr); req.bytes = recvfrom(req.sock, req.raw, sizeof(req.raw), 0, (sockaddr*)&req.addr, &req.sockLen); if (req.bytes > 0 && req.dnsp->header.qr && !req.dnsp->header.rcode && ntohs(req.dnsp->header.ancount)) { closesocket(req.sock); return getResult(&req); } } closesocket(req.sock); return NULL; } WORD recvTcpDnsMess(SOCKET sock, char *target, bool ready) { timeval tv1; fd_set readfds1; if (!ready) { FD_ZERO(&readfds1); tv1.tv_sec = 5; tv1.tv_usec = 0; FD_SET(sock, &readfds1); if (!select(sock + 1, &readfds1, NULL, NULL, &tv1)) return 0; } errno = 0; WORD rcd = recv(sock, target, 2, 0); errno = WSAGetLastError(); if (errno) return 0; if (rcd == 2) { WORD bytes = fUShort(target) + rcd; char *ptr; while (rcd < bytes) { FD_ZERO(&readfds1); tv1.tv_sec = 5; tv1.tv_usec = 0; FD_SET(sock, &readfds1); ptr = target + rcd; if (select(sock + 1, &readfds1, NULL, NULL, &tv1)) { errno = 0; rcd += recv(sock, ptr, bytes - rcd, 0); errno = WSAGetLastError(); if (errno) return 0; } else return 0; } return rcd; } return 0; } void checkZone(void *lpParam) { char tempbuff[256]; char logBuff[256]; while (true) { if (!network.ready || network.busy) { Sleep(100); continue; } time_t t = time(NULL); sprintf(logBuff, "Checking Serial from Primary Server %s", IP2String(tempbuff, cfig.zoneServers[0])); logDNSMess(logBuff, 2); DWORD serial1 = getSerial(cfig.zone); DWORD serial2 = getSerial(cfig.authority); if (!serial1 || !serial2) { sprintf(logBuff, "Failed to get Serial from %s", IP2String(tempbuff, cfig.zoneServers[0])); logDNSMess(logBuff, 1); Sleep(1000*(cfig.retry)); continue; } else if (cfig.serial1 && cfig.serial1 == serial1 && cfig.serial2 && cfig.serial2 == serial2) { sprintf(logBuff, "Zone Refresh not required"); logDNSMess(logBuff, 2); if (cfig.expire > (DWORD)(LONG_MAX - t)) cfig.expireTime = LONG_MAX; else cfig.expireTime = t + cfig.expire; Sleep(1000*(cfig.refresh)); } else { serial1 = getZone(1 - cacheInd, cfig.zone); serial2 = getZone(1 - cacheInd, cfig.authority); if (!serial1 || !serial2) { sprintf(logBuff, "Waiting %u seconds to retry", cfig.retry); logDNSMess(logBuff, 1); Sleep(1000*(cfig.retry)); } else { newInd = 1 - cacheInd; cfig.serial1 = serial1; cfig.serial2 = serial2; if (cfig.expire > (DWORD)(LONG_MAX - t)) cfig.expireTime = LONG_MAX; else cfig.expireTime = t + cfig.expire; if (!lpParam) break; Sleep(1000*(cfig.refresh)); } } } _endthread(); return; } DWORD getZone(BYTE updateCache, char *zone) { char tempbuff[256]; char logBuff[256]; char hostname[256]; char cname[256]; DWORD serial1 = 0; DWORD serial2 = 0; DWORD hostExpiry = 0; DWORD refresh = 0; DWORD retry = 0; DWORD expire = 0; DWORD expiry; DWORD minimum = 0; int added = 0; char *data; char *dp; DWORD ip; data5 req; memset(&req, 0, sizeof(data5)); req.addr.sin_family = AF_INET; req.addr.sin_port = htons(IPPORT_DNS); req.addr.sin_addr.s_addr = cfig.zoneServers[0]; req.sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (req.sock == INVALID_SOCKET) { sprintf(logBuff, "Failed to Create Socket, Zone Transfer Failed", IP2String(tempbuff, req.addr.sin_addr.s_addr)); logDNSMess(logBuff, 1); return 0; } req.sockLen = sizeof(req.addr); time_t t = time(NULL); if (connect(req.sock, (sockaddr*)&req.addr, req.sockLen) >= 0) { req.data = req.raw; req.data += 2; req.dnsp = (dnsPacket*)req.data; req.dnsp->header.qdcount = htons(1); req.dnsp->header.xid = (t % USHRT_MAX); req.data = &req.dnsp->data; req.data += pQu(req.data, zone); req.data += pUShort(req.data, DNS_TYPE_AXFR); req.data += pUShort(req.data, DNS_CLASS_IN); req.bytes = (DWORD)req.data - (DWORD)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 send request to Replication Server %s, Zone Transfer Failed", IP2String(tempbuff, req.addr.sin_addr.s_addr)); logDNSMess(logBuff, 1); return 0; } if (!strcasecmp(zone, cfig.zone)) { for (; cfig.mxCount[updateCache]; cfig.mxCount[updateCache]--) strcpy(cfig.mxServers[updateCache][cfig.mxCount[updateCache]].hostname, ""); } while (true) { req.bytes = recvTcpDnsMess(req.sock, req.raw, false); //printf("bytes = %u\n", req.bytes); if (req.bytes < 2) break; WORD pktSize = fUShort(req.raw); if ((WORD)req.bytes < pktSize + 2) break; req.dnsp = (dnsPacket*)(req.raw + 2); req.data = &req.dnsp->data; if (!req.dnsp->header.qr || req.dnsp->header.rcode || !ntohs(req.dnsp->header.ancount)) break; for (int j = 1; j <= ntohs(req.dnsp->header.qdcount); j++) { req.data += fQu(hostname, req.dnsp, req.data); req.data += 4; } for (int i = 1; i <= ntohs(req.dnsp->header.ancount); i++) { //char *dp = req.data; req.data += fQu(hostname, req.dnsp, req.data); //printf("%s\n", hostname); req.qtype = fUShort(req.data); req.data += 2; //type req.qclass = fUShort(req.data); req.data += 2; //class expiry = fULong(req.data); req.data += 4; //ttl int zLen = fUShort(req.data); req.data += 2; //datalength data = req.data; req.data += zLen; switch (req.qtype) { case DNS_TYPE_SOA: data += fQu(hostname, req.dnsp, data); data += fQu(cname, req.dnsp, data); if (!serial1) { hostExpiry = expiry; serial1 = fULong(data); data += 4; refresh = fULong(data); data += 4; retry = fULong(data); data += 4; expire = fULong(data); data += 4; minimum = fULong(data); data += 4; added++; } else if (!serial2) serial2 = fULong(data); break; case DNS_TYPE_A: ip = fIP(data); makeLocal(hostname); if (dhcpService && expiry < hostExpiry) { char rInd = getRangeInd(ip); int ind = getIndex(rInd, ip); if (expiry > LONG_MAX) expiry = LONG_MAX; if (ind >= 0 && cfig.dhcpRanges[rInd].dhcpEntry[ind]) setLeaseExpiry(cfig.dhcpRanges[rInd].dhcpEntry[ind], expiry, false); else setLeaseExpiry(ip, 0); if (expiry < (DWORD)(LONG_MAX - t)) expiry += t; addToCache(updateCache, hostname, ip, expiry, LOCAL_A, NONE, serial1); added++; } else { setLeaseExpiry(ip, LONG_MAX); addToCache(updateCache, hostname, ip, LONG_MAX, STATIC_A_AUTH, NONE, serial1); added++; } break; case DNS_TYPE_PTR: myLower(hostname); dp = strstr(hostname, arpa); if (dp) { *dp = 0; ip = ntohl(my_inet_addr(hostname)); fQu(hostname, req.dnsp, data); makeLocal(hostname); if (dhcpService && expiry < hostExpiry) { char rInd = getRangeInd(ip); int ind = getIndex(rInd, ip); if (expiry > LONG_MAX) expiry = LONG_MAX; if (ind >= 0 && cfig.dhcpRanges[rInd].dhcpEntry[ind]) setLeaseExpiry(cfig.dhcpRanges[rInd].dhcpEntry[ind], expiry, false); else setLeaseExpiry(ip, 0); if (expiry < (DWORD)(LONG_MAX - t)) expiry += t; addToCache(updateCache, hostname, ip, expiry, NONE, LOCAL_PTR_AUTH, serial1); added++; } else { setLeaseExpiry(ip, LONG_MAX); addToCache(updateCache, hostname, ip, LONG_MAX, NONE, STATIC_PTR_AUTH, serial1); added++; } } break; case DNS_TYPE_MX: if (cfig.replication == 2 && makeLocal(hostname) == 3) { cfig.mxServers[updateCache][cfig.mxCount[updateCache]].pref = fUShort(data); data += sizeof(WORD); fQu(cname, req.dnsp, data); strcpy(cfig.mxServers[updateCache][cfig.mxCount[updateCache]].hostname, cname); cfig.mxCount[updateCache]++; added++; } break; case DNS_TYPE_NS: if (cfig.replication == 2) fQu(cfig.ns, req.dnsp, data); break; case DNS_TYPE_CNAME: if (cfig.replication == 2) { fQu(cname, req.dnsp, data); BYTE cname_type = 0; if (makeLocal(cname)) cname_type = LOCAL_CNAME; else cname_type = EXT_CNAME; makeLocal(hostname); data7 *cache = findEntry(updateCache, hostname, cname_type); if (!cache) { cache = (data7*)calloc(1, sizeof(data7)); if (cache) { cache->mapname = cloneString(hostname); cache->dataType = cname_type; cache->hostname = cloneString(cname); if (cache->mapname && cache->hostname) { addEntry(updateCache, cache); } else { sprintf(logBuff, "Memory Error"); logDNSMess(logBuff, 1); continue; } } else { sprintf(logBuff, "Memory Error"); logDNSMess(logBuff, 1); continue; } } else { if (strcasecmp(cname, cache->hostname)) { free(cache->hostname); cache->hostname = cloneString(cname); } } cache->expiry = LONG_MAX; cache->serial = serial1; added++; } break; } //printf("serial=%u %u %u\n", serial1, serial2, hostExpiry); } } strcpy(hostname, cfig.ns); makeLocal(hostname); data7 *cache = findEntry(updateCache, hostname, STATIC_A_AUTH); if (!cache) cache = findEntry(updateCache, hostname, STATIC_A_NAUTH); if (cache) cfig.nsIP = cache->ip; closesocket(req.sock); if (serial1 && serial1 == serial2 && hostExpiry) { if (cfig.replication == 2) { //printf("Here %u %u %u %u %u \n",hostExpiry,refresh,retry,expire,minimum); cfig.lease = hostExpiry; cfig.refresh = refresh; cfig.retry = retry; cfig.expire = expire; cfig.minimum = minimum; } if (cacheInd != updateCache) { if (!strcasecmp(zone, cfig.zone)) { hostMap::iterator q = dnsCache[updateCache].begin(); while (q != dnsCache[updateCache].end()) { //printf("%s=%u\n", q->second->mapname,q->second->serial); switch (q->second->dataType) { case LOCAL_A: case SERVER_A: case STATIC_A_AUTH: case LOCAL_CNAME: case EXT_CNAME: if (q->second->serial < serial1) q->second->expiry = 0; } q++; } } else if (!strcasecmp(zone, cfig.authority)) { hostMap::iterator q = dnsCache[updateCache].begin(); while (q != dnsCache[updateCache].end()) { //printf("%s=%u\n", q->second->mapname,q->second->serial); switch (q->second->dataType) { case LOCAL_PTR_AUTH: case STATIC_PTR_AUTH: case SERVER_PTR_AUTH: if (q->second->serial < serial1) q->second->expiry = 0; } q++; } } checkSize(updateCache); } //printf("Refresh ind %i serial %u size %i\n", updateCache, serial1, dnsCache[updateCache].size()); sprintf(logBuff, "Zone %s Transferred from %s, %u RRs imported", zone, IP2String(tempbuff, req.addr.sin_addr.s_addr), added); logDNSMess(logBuff, 2); return serial1; } else if (!serial1) { sprintf(logBuff, "Replication Server %s, Missing Serial", IP2String(tempbuff, req.addr.sin_addr.s_addr)); logDNSMess(logBuff, 1); } else if (serial1 != serial2) { sprintf(logBuff, "Replication Server %s, Serial Changed %u %u", IP2String(tempbuff, req.addr.sin_addr.s_addr), serial1, serial2); logDNSMess(logBuff, 1); } else { sprintf(logBuff, "Replication Server %s, Invalid AXFR data", IP2String(tempbuff, req.addr.sin_addr.s_addr)); logDNSMess(logBuff, 1); } } else { errno = WSAGetLastError(); sprintf(logBuff, "Server %s, Error %u", IP2String(tempbuff, req.addr.sin_addr.s_addr), errno); logDNSMess(logBuff, 1); closesocket(req.sock); } return 0; } void getSecondary() { char hostname[256]; DWORD ip; DWORD hostExpiry = 0; DWORD expiry; char *data; char *dp; WORD rr = 0; data5 req; memset(&req, 0, sizeof(data5)); req.addr.sin_family = AF_INET; req.addr.sin_port = htons(IPPORT_DNS); if (dhcpService && cfig.replication == 1) req.addr.sin_addr.s_addr = cfig.zoneServers[1]; else return; req.sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (req.sock == INVALID_SOCKET) return; req.sockLen = sizeof(req.addr); time_t t = time(NULL); if (connect(req.sock, (sockaddr*)&req.addr, req.sockLen) >= 0) { req.data = req.raw; req.data += 2; req.dnsp = (dnsPacket*)req.data; req.dnsp->header.qdcount = htons(1); req.dnsp->header.xid = (t % USHRT_MAX); req.data = &req.dnsp->data; req.data += pQu(req.data, cfig.authority); req.data += pUShort(req.data, DNS_TYPE_AXFR); req.data += pUShort(req.data, DNS_CLASS_IN); req.bytes = (DWORD)req.data - (DWORD)req.raw; pUShort(req.raw, req.bytes - 2); if (send(req.sock, req.raw, req.bytes, 0) < req.bytes) { closesocket(req.sock); return; } while (true) { req.bytes = recvTcpDnsMess(req.sock, req.raw, false); //printf("bytes = %u\n", req.bytes); if (req.bytes < 2) break; WORD pktSize = fUShort(req.raw); if ((WORD)req.bytes < pktSize + 2) break; req.dnsp = (dnsPacket*)(req.raw + 2); req.data = &req.dnsp->data; if (!req.dnsp->header.qr || req.dnsp->header.rcode || !ntohs(req.dnsp->header.ancount)) break; for (int j = 1; j <= ntohs(req.dnsp->header.qdcount); j++) { req.data += fQu(hostname, req.dnsp, req.data); req.data += 4; } for (int i = 1; i <= ntohs(req.dnsp->header.ancount); i++) { //char *dp = req.data; req.data += fQu(hostname, req.dnsp, req.data); //printf("%s\n", hostname); req.qtype = fUShort(req.data); req.data += 2; //type req.qclass = fUShort(req.data); req.data += 2; //class expiry = fULong(req.data); req.data += 4; //ttl int zLen = fUShort(req.data); req.data += 2; //datalength data = req.data; req.data += zLen; switch (req.qtype) { case DNS_TYPE_PTR: myLower(hostname); dp = strstr(hostname, arpa); if (dp) { *dp = 0; ip = ntohl(my_inet_addr(hostname)); fQu(hostname, req.dnsp, data); makeLocal(hostname); if (dhcpService && expiry < hostExpiry) { char rInd = getRangeInd(ip); int ind = getIndex(rInd, ip); if (expiry > LONG_MAX) expiry = LONG_MAX; if (ind >= 0 && cfig.dhcpRanges[rInd].dhcpEntry[ind]) setLeaseExpiry(cfig.dhcpRanges[rInd].dhcpEntry[ind], expiry, false); else setLeaseExpiry(ip, 0); if (expiry < (DWORD)(LONG_MAX - t)) expiry += t; addToCache(cacheInd, hostname, ip, expiry, LOCAL_A, NONE, cfig.serial1); addToCache(cacheInd, hostname, ip, expiry, NONE, LOCAL_PTR_AUTH, cfig.serial2); rr++; } } break; } } } sprintf(logBuff, "%u RRs imported from Secondary Server", rr); logDNSMess(logBuff, 2); } else { errno = WSAGetLastError(); sprintf(logBuff, "Server %s, Error %u", IP2String(tempbuff, req.addr.sin_addr.s_addr), errno); logDNSMess(logBuff, 1); } closesocket(req.sock); } void addDHCPRange(char *iniStrPtr) { DWORD rs = 0; DWORD re = 0; char name[512]; char value[512]; mySplit(name, value, iniStrPtr, '-'); if (name[0] && value[0] && isIP(name) && isIP(value)) { rs = htonl(my_inet_addr(name)); re = htonl(my_inet_addr(value)); if (rs && rs != INADDR_NONE && re && re != INADDR_NONE && rs <= re) { data13 *range; BYTE m = 0; BYTE rangeOK = 1; for (; m < MAX_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", iniStrPtr); logMess(logBuff, 1); rangeOK = 0; break; } } if (m < MAX_RANGES && rangeOK) { cfig.dhcpSize += (re - rs + 1); range = &cfig.dhcpRanges[m]; range->rangeStart = rs; range->rangeEnd = re; range->expiry = (time_t*)calloc((re - rs + 1), sizeof(time_t)); range->dhcpEntry = (data7**)calloc((re - rs + 1), sizeof(data7*)); if (!range->expiry || !range->dhcpEntry) { if (range->expiry) free(range->expiry); if (range->dhcpEntry) free(range->dhcpEntry); sprintf(logBuff, "DHCP Ranges Load, Memory Allocation Error"); logMess(logBuff, 1); return ; } } } else { sprintf(logBuff, "Section [RANGE_SET] Invalid DHCP range %s in ini file, ignored", iniStrPtr); logMess(logBuff, 1); } } else { sprintf(logBuff, "Section [RANGE_SET] Invalid DHCP range %s in ini file, ignored", iniStrPtr); logMess(logBuff, 1); } } void addVendClass(BYTE rangeSetInd, char *vendClass, BYTE vendClassSize) { // Strip surrounding quotation marks if (vendClassSize>2) { if (vendClass[0]=='"') { char* secondQuotationMark = strchr(vendClass+1,'"'); memcpy(vendClass,vendClass+1,(secondQuotationMark - vendClass - 1)); vendClass[(secondQuotationMark - vendClass)]='\0'; vendClassSize-=2; } } data14 *rangeSet = &cfig.rangeSet[rangeSetInd]; BYTE i = 0; for (; i <= 32 && rangeSet->vendClassSize[i]; i++); if (i >= 32 || !vendClassSize) return; rangeSet->vendClass[i] = (BYTE*)calloc(vendClassSize, 1); if(!rangeSet->vendClass[i]) { sprintf(logBuff, "Vendor Class Load, Memory Allocation Error"); logMess(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", hex2String(tempbuff, rangeSet->vendClass[i], rangeSet->vendClassSize[i], ':'), rangeSet->vendClassSize[i], rangeSetInd, i); } } void addUserClass(BYTE rangeSetInd, char *userClass, BYTE userClassSize) { // Strip surrounding quotation marks if (userClassSize>2) { if (userClass[0]=='"') { char* secondQuotationMark = strchr(userClass+1,'"'); memcpy(userClass,userClass+1,(secondQuotationMark - userClass - 1)); userClass[(secondQuotationMark - userClass)]='\0'; userClassSize-=2; } } data14 *rangeSet = &cfig.rangeSet[rangeSetInd]; BYTE i = 0; for (; i <= 32 && rangeSet->userClassSize[i]; i++); if (i >= 32 || !userClassSize) return; rangeSet->userClass[i] = (BYTE*)calloc(userClassSize, 1); if(!rangeSet->userClass[i]) { sprintf(logBuff, "Vendor Class Load, Memory Allocation Error"); logMess(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(BYTE rangeSetInd, char *macRange) { if (macRange[0]) { data14 *rangeSet = &cfig.rangeSet[rangeSetInd]; BYTE i = 0; for (; i <= 32 && rangeSet->macSize[i]; i++); if (i >= 32) return; char name[256]; char value[256]; mySplit(name, value, macRange, '-'); if(!name[0] || !value[0]) { sprintf(logBuff, "Section [RANGE_SET], invalid Filter_Mac_Range %s, ignored", macRange); logMess(logBuff, 1); } else { BYTE macSize1 = 16; BYTE macSize2 = 16; BYTE *macStart = (BYTE*)calloc(1, macSize1); BYTE *macEnd = (BYTE*)calloc(1, macSize2); if(!macStart || !macEnd) { sprintf(logBuff, "DHCP Range Load, Memory Allocation Error"); logMess(logBuff, 1); } else if (getHexValue(macStart, name, &macSize1) || getHexValue(macEnd, value, &macSize2)) { sprintf(logBuff, "Section [RANGE_SET], Invalid character in Filter_Mac_Range %s", macRange); logMess(logBuff, 1); free(macStart); free(macEnd); } else if (memcmp(macStart, macEnd, 16) > 0) { sprintf(logBuff, "Section [RANGE_SET], Invalid Filter_Mac_Range %s, (higher bound specified on left), ignored", macRange); logMess(logBuff, 1); free(macStart); free(macEnd); } else if (macSize1 != macSize2) { sprintf(logBuff, "Section [RANGE_SET], Invalid Filter_Mac_Range %s, (start/end size mismatched), ignored", macRange); logMess(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 init(void *lparam) { time_t t = time(NULL); char iniStr[16384]; char name[512]; char value[512]; memset(&cfig, 0, sizeof(cfig)); memset(&network, 0, sizeof(network)); GetModuleFileName(NULL, extbuff, _MAX_PATH); char *fileExt = strrchr(extbuff, '.'); *fileExt = 0; sprintf(leaFile, "%s.state", extbuff); sprintf(iniFile, "%s.ini", extbuff); fileExt = strrchr(extbuff, '\\'); *fileExt = 0; fileExt++; sprintf(logFile, "%s\\logs\\%s%%Y%%m%%d.log", extbuff, fileExt); //printf("log=%s\n", logFile); if (verbatim) { cfig.dnsLogLevel = 2; cfig.dhcpLogLevel = 2; printf("%s\n\n", sVersion); } else if (getSection("LOGGING", iniStr, 1, iniFile)) { cfig.dnsLogLevel = 1; cfig.dhcpLogLevel = 2; char *iniStrPtr = myGetToken(iniStr, 0); tempbuff[0] = 0; for (; iniStrPtr[0]; iniStrPtr = myGetToken(iniStrPtr, 1)) { mySplit(name, value, iniStrPtr, '='); if (name[0] && value[0]) { if (!strcasecmp(name, "DNSLogLevel")) { if (!strcasecmp(value, "None")) cfig.dnsLogLevel = 0; else if (!strcasecmp(value, "Errors")) 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, "Errors")) 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", iniStrPtr); } else sprintf(tempbuff, "Section [LOGGING], Invalid Entry %s ignored", iniStrPtr); } } if (/*!verbatim &&*/ (cfig.dnsLogLevel || cfig.dhcpLogLevel) && logFile[0]) { tm *ttm = localtime(&t); loggingDay = ttm->tm_yday; strftime(extbuff, sizeof(extbuff), logFile, ttm); printf("opening log file %s\n",extbuff); cfig.logfile = fopen(extbuff, "at"); if (cfig.logfile) { sprintf(logBuff, "%s Starting..", sVersion); logMess(logBuff, 1); if (tempbuff[0]) logMess(tempbuff, 0); } else { printf("failed to open log file %s\n",extbuff); } } WORD wVersionRequested = MAKEWORD(1, 1); WSAStartup(wVersionRequested, &cfig.wsaData); if (cfig.wsaData.wVersion != wVersionRequested) { sprintf(logBuff, "WSAStartup Error"); logMess(logBuff, 1); } if (getSection("SERVICES", iniStr, 1, iniFile)) { dhcpService = false; dnsService = false; char *iniStrPtr = myGetToken(iniStr, 0); for (int i = 0; i < 2 && iniStrPtr[0]; i++, iniStrPtr = myGetToken(iniStrPtr, 1)) if (!strcasecmp(iniStrPtr, "DNS")) dnsService = true; else if (!strcasecmp(iniStrPtr, "DHCP")) dhcpService = true; if (!dhcpService && !dnsService) { dhcpService = true; dnsService = true; } } if (dnsService) { if (verbatim) printf("Starting DNS...\n"); else { sprintf(logBuff, "Starting DNS Service"); logDNSMess(logBuff, 1); } } if (dhcpService) { if (verbatim) printf("Starting DHCP...\n"); else { sprintf(logBuff, "Starting DHCP Service"); logDNSMess(logBuff, 1); } } cfig.lease = 360000; cfig.ttl = 360000; cfig.refresh = 3600; cfig.retry = 100; cfig.expire = 360000; cfig.minimum = 100; if (getSection("TIMINGS", iniStr, 1, iniFile)) { char *iniStrPtr = myGetToken(iniStr, 0); for (; iniStrPtr[0]; iniStrPtr = myGetToken(iniStrPtr, 1)) { mySplit(name, value, iniStrPtr, '='); if (name[0] && value[0]) { if (atol(value) || !strcasecmp(value,"0")) { if (!strcasecmp(name, "Lease_Time")) { cfig.lease = atol(value); if (!cfig.lease) cfig.lease = ULONG_MAX; cfig.refresh = cfig.lease / 10; if (cfig.refresh > 36000) cfig.refresh = 36000; cfig.retry = cfig.refresh / 10; if (ULONG_MAX/24 > cfig.lease) cfig.expire = 24 * cfig.lease; else cfig.expire = ULONG_MAX; cfig.minimum = cfig.retry; } else if (!strcasecmp(name, "Time_to_Live")) { sprintf(logBuff, "Time_to_Live %d", atol(value)); logMess(logBuff, 1); cfig.ttl = atol(value); if (!cfig.ttl) cfig.ttl = ULONG_MAX; } else if (!strcasecmp(name, "Refresh")) cfig.refresh = atol(value); else if (!strcasecmp(name, "Retry")) cfig.retry = atol(value); else if (!strcasecmp(name, "Expire")) cfig.expire = atol(value); else if (!strcasecmp(name, "Minimum")) cfig.minimum = atol(value); else if (!strcasecmp(name, "MinCacheTime")) cfig.minCache = atol(value); else if (!strcasecmp(name, "MaxCacheTime")) cfig.maxCache = atol(value); else { sprintf(logBuff, "Section [TIMINGS], Invalid Entry: %s ignored", name); 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", iniStrPtr); logDNSMess(logBuff, 1); } } } if (!cfig.refresh) { cfig.refresh = ULONG_MAX; if (!cfig.retry) cfig.retry = 100; } else if (!cfig.retry) cfig.retry = cfig.refresh / 10; if (!cfig.expire) cfig.expire = ULONG_MAX; if (!cfig.minimum) cfig.minimum = cfig.retry; if (getSection("DOMAIN-NAME", iniStr, 1, iniFile)) { char *iniStrPtr = myGetToken(iniStr, 0); mySplit(name, value, iniStrPtr, '='); if (name[0] && value[0]) { data15 mask; data15 network; char left[64]; cfig.authority[0] = 0; myLower(value); mask.ip = 0; network.ip = 0; for (BYTE octateNum = 0; octateNum < 3; octateNum++) { mySplit(left, value, value, '.'); if (left[0] == '0' || (atoi(left) && atoi(left) < 256)) { for (int j = 2; j >= 0; j--) { network.octate[j + 1] = network.octate[j]; mask.octate[j + 1] = mask.octate[j]; } mask.octate[0] = 255; network.octate[0] = atoi(left); 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.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); strcpy(cfig.zoneSmall, name); myLower(cfig.zoneSmall); cfig.zLen = strlen(cfig.zone); } else { cfig.aLen = 0; cfig.authority[0] = 0; sprintf(logBuff, "Warning: Invalid Domain Name %s, ignored", iniStrPtr); logDNSMess(logBuff, 1); } } getServ(); getDServ(); if (getSection("ZONE-REPLICATION", iniStr, 1, iniFile)) { char *iniStrPtr = myGetToken(iniStr, 0); for (int i = 2; i < MAX_SERVERS && iniStrPtr[0]; iniStrPtr = myGetToken(iniStrPtr, 1)) { if (dnsService && !cfig.authorized) { sprintf(logBuff, "Section [REPLICATION-SERVERS], Server is not authorized, entry %s ignored", iniStrPtr); logMess(logBuff, 1); continue; } mySplit(name, value, iniStrPtr, '='); if (name[0] && value[0]) { if (chkQu(name) && !isIP(name) && isIP(value)) { if (!strcasecmp(name, "Primary")) cfig.zoneServers[0] = my_inet_addr(value); else if (!strcasecmp(name, "Secondary")) cfig.zoneServers[1] = my_inet_addr(value); else if (dnsService && !strcasecmp(name, "AXFRClient")) { cfig.zoneServers[i] = my_inet_addr(value); i++; } else { sprintf(logBuff, "Section [REPLICATION-SERVERS] Invalid Entry: %s ignored", iniStrPtr); logMess(logBuff, 1); } } else { sprintf(logBuff, "Section [REPLICATION-SERVERS] Invalid Entry: %s ignored", iniStrPtr); logMess(logBuff, 1); } } else { sprintf(logBuff, "Section [REPLICATION-SERVERS], Missing value, entry %s ignored", iniStrPtr); logMess(logBuff, 1); } } } if (!cfig.zoneServers[0] && cfig.zoneServers[1]) { sprintf(logBuff, "Section [REPLICATION-SERVERS] Missing Primary Server"); logMess(logBuff, 1); } else if (cfig.zoneServers[0] && !cfig.zoneServers[1]) { sprintf(logBuff, "Section [REPLICATION-SERVERS] Missing Secondary Server"); logMess(logBuff, 1); } else if (cfig.zoneServers[0] && cfig.zoneServers[1]) { if (findServer(network.staticServers, cfig.zoneServers[0]) && findServer(network.staticServers, cfig.zoneServers[1])) { sprintf(logBuff, "Section [REPLICATION-SERVERS] Primary & Secondary should be Different Boxes"); logMess(logBuff, 1); } else if (findServer(network.staticServers, cfig.zoneServers[0])) cfig.replication = 1; else if (findServer(network.staticServers, cfig.zoneServers[1])) cfig.replication = 2; else { sprintf(logBuff, "Section [REPLICATION-SERVERS] No Server IP not found on this Machine"); logMess(logBuff, 1); } } if (dhcpService) { if (getSection("DHCP-OPTIONS", iniStr, 1, iniFile)) { data20 optionData; loadOptions(iniStr, "DHCP-OPTIONS", &optionData); cfig.options = optionData.options; cfig.mask = optionData.mask; } for (BYTE i = 1; i <= MAX_RANGES ; i++) { if (getSection("DHCP-RANGE", iniStr, i, iniFile)) { BYTE m = 0; for (; m < MAX_RANGES && cfig.dhcpRanges[m].rangeStart; m++); data20 optionData; optionData.rangeSetInd = i - 1; loadOptions(iniStr, "DHCP-RANGE", &optionData); cfig.rangeSet[optionData.rangeSetInd].active = true; for (; m < MAX_RANGES && cfig.dhcpRanges[m].rangeStart; m++) { //printf("Range Start=%s rangeSetInd=%i\n", IP2String(tempbuff, htonl(cfig.dhcpRanges[m].rangeStart)), optionData.rangeSetInd); cfig.dhcpRanges[m].rangeSetInd = optionData.rangeSetInd; cfig.dhcpRanges[m].options = optionData.options; cfig.dhcpRanges[m].mask = optionData.mask; } } else break; } //printf("%s\n", IP2String(tempbuff, cfig.mask)); if (!cfig.mask) cfig.mask = my_inet_addr("255.255.255.0"); for (char rangeInd = 0; rangeInd < MAX_RANGES && cfig.dhcpRanges[rangeInd].rangeStart; rangeInd++) { if (!cfig.dhcpRanges[rangeInd].mask) cfig.dhcpRanges[rangeInd].mask = cfig.mask; for (DWORD iip = cfig.dhcpRanges[rangeInd].rangeStart; iip <= cfig.dhcpRanges[rangeInd].rangeEnd; iip++) { DWORD ip = htonl(iip); if ((cfig.dhcpRanges[rangeInd].mask | (~ip)) == ULONG_MAX || (cfig.dhcpRanges[rangeInd].mask | ip) == ULONG_MAX) cfig.dhcpRanges[rangeInd].expiry[iip - cfig.dhcpRanges[rangeInd].rangeStart] = LONG_MAX; } } for (BYTE m = 0; m < MAX_SERVERS && network.allServers[m]; m++) setLeaseExpiry(network.allServers[m], LONG_MAX); for (BYTE m = 0; m < MAX_SERVERS && network.dns[m]; m++) setLeaseExpiry(network.dns[m], LONG_MAX); if (getSection("DHCP-OPTIONS", iniStr, 1, iniFile)) lockOptions(iniStr); for (BYTE i = 1; i <= 32 ;i++) { if (getSection("DHCP-RANGE", iniStr, i, iniFile)) lockOptions(iniStr); } FILE *f = fopen(iniFile, "rt"); if (f) { char sectionName[512]; while (fgets(sectionName, 511, f)) { if (*sectionName == '[') { char *secend = strchr(sectionName, ']'); if (secend) { *secend = 0; sectionName[0] = 32; myTrim(sectionName, sectionName); } else continue; } else continue; BYTE hexValue[255]; BYTE hexValueSize = sizeof(hexValue); data20 optionData; if (!getHexValue(hexValue, sectionName, &hexValueSize)) { data7 *dhcpEntry = dhcpCache[toUUE(tempbuff, hexValue, hexValueSize)]; if (!dhcpEntry) { getSection(sectionName, iniStr, 1, iniFile); loadOptions(iniStr, sectionName, &optionData); lockOptions(iniStr); if (optionData.ip) { dhcpMap::iterator p = dhcpCache.begin(); for (; p != dhcpCache.end(); p++) { if (p->second && p->second->ip == optionData.ip) break; } if (p == dhcpCache.end()) { dhcpEntry = (data7*)calloc(1, sizeof(data7)); if (!dhcpEntry) { sprintf(logBuff, "Client Options Load, Memory Allocation Error"); logMess(logBuff, 1); return; } dhcpEntry->mapname = cloneString(toUUE(tempbuff, hexValue, hexValueSize)); if (!dhcpEntry->mapname) { sprintf(logBuff, "Client Data Load, Memory Allocation Error"); logMess(logBuff, 1); return; } DWORD tmask = htonl(optionData.mask); while (tmask) { (dhcpEntry->bitmask)++; tmask = tmask << 1; } dhcpEntry->ip = optionData.ip; dhcpEntry->options = optionData.options; dhcpEntry->rangeInd = getRangeInd(optionData.ip); dhcpEntry->fixed = 1; setLeaseExpiry(optionData.ip, LONG_MAX); dhcpCache[dhcpEntry->mapname] = dhcpEntry; //printf("%s=%s=%s\n", sectionName, dhcpEntry->mapname, IP2String(tempbuff, optionData.ip)); } else { sprintf(logBuff, "Static DHCP Host [%s] Duplicate IP Address %s, Entry ignored", sectionName, IP2String(tempbuff, optionData.ip)); logMess(logBuff, 1); } } else { sprintf(logBuff, "IP Address is missing in Static DHCP Host [%s], Entry ignored", sectionName); logMess(logBuff, 1); } } else { sprintf(logBuff, "Duplicate Static DHCP Host [%s] ignored", sectionName); logMess(logBuff, 1); } } else if (strchr(sectionName, ':')) { sprintf(logBuff, "Invalid Static DHCP Host MAC Addr [%s] ignored", sectionName); logMess(logBuff, 1); } } fclose(f); } f = fopen(leaFile, "rb"); if (f) { data8 dhcpData; while (fread(&dhcpData, sizeof(data8), 1, f)) { char rangeInd = -1; int ind = -1; if (!findServer(network.staticServers, dhcpData.ip) && !findServer(network.dns, dhcpData.ip)) { data7 *dhcpEntry = dhcpCache[toUUE(tempbuff, dhcpData.bp_chaddr, dhcpData.bp_hlen)]; if (dhcpEntry) { if (dhcpEntry->ip != dhcpData.ip) continue; } else { dhcpMap::iterator p = dhcpCache.begin(); for (; p != dhcpCache.end(); p++) { if (p->second && p->second->ip == dhcpData.ip) break; } if (p != dhcpCache.end()) { if (p->second->fixed || p->second->expiry > dhcpData.expiry) continue; else dhcpCache.erase(p); } } rangeInd = getRangeInd(dhcpData.ip); if(rangeInd >= 0) { ind = getIndex(rangeInd, dhcpData.ip); if (ind >= 0 && !dhcpEntry) { dhcpEntry = (data7*)calloc(1, sizeof(data7)); if (!dhcpEntry) { sprintf(logBuff, "Loading Existing Leases, Memory Allocation Error"); logDHCPMess(logBuff, 1); return; } dhcpEntry->mapname = cloneString(toUUE(tempbuff, dhcpData.bp_chaddr, dhcpData.bp_hlen)); if (!dhcpEntry->mapname) { sprintf(logBuff, "Loading Existing Leases, Memory Allocation Error"); free(dhcpEntry); logDHCPMess(logBuff, 1); return ; } //dhcpEntry->dataType = DHCP; dhcpCache[dhcpEntry->mapname] = dhcpEntry; } } if (dhcpEntry) { dhcpEntry->ip = dhcpData.ip; dhcpEntry->rangeInd = rangeInd; if (!dhcpEntry->fixed) dhcpEntry->source = dhcpData.source; if (dhcpData.expiry > t) { setLeaseExpiry(dhcpEntry, dhcpData.expiry - t, dhcpData.local); addToCache(cacheInd, dhcpData.hostname, dhcpEntry->ip, dhcpData.expiry, LOCAL_A, NONE, cfig.serial1); if (makeLocal(dhcpEntry->ip)) addToCache(cacheInd, dhcpData.hostname, dhcpEntry->ip, dhcpData.expiry, NONE, LOCAL_PTR_AUTH, cfig.serial2); else addToCache(cacheInd, dhcpData.hostname, dhcpEntry->ip, dhcpData.expiry, NONE, LOCAL_PTR_NAUTH, cfig.serial2); } else setLeaseExpiry(dhcpEntry, 0, false); } } } fclose(f); f = fopen(leaFile, "wb"); cfig.dhcpIndex = 0; if (f) { dhcpMap::iterator p = dhcpCache.begin(); for (; p != dhcpCache.end(); p++) { if (p->second && p->second->expiry) { memset(&dhcpData, 0, sizeof(data8)); dhcpData.bp_hlen = fromUUE(dhcpData.bp_chaddr, p->second->mapname); dhcpData.ip = p->second->ip; dhcpData.expiry = p->second->expiry; dhcpData.local = p->second->local; if (!p->second->fixed) dhcpData.source = p->second->source; data7 *cache = findEntry(cacheInd, IP2String(tempbuff, htonl(p->second->ip))); if (cache && cache->hostname) strcpy(dhcpData.hostname, cache->hostname); cfig.dhcpIndex++; dhcpData.dhcpInd = cfig.dhcpIndex; p->second->dhcpInd = cfig.dhcpIndex; fwrite(&dhcpData, sizeof(data8), 1, f); } } fclose(f); } } fEvent = CreateEvent( NULL, // default security descriptor FALSE, // ManualReset TRUE, // Signalled TEXT("AchalDualServerFileEvent")); // object name SetEvent(fEvent); for (int i = 0; i < MAX_RANGES && cfig.dhcpRanges[i].rangeStart;i++) { char *logPtr = logBuff; logPtr += sprintf(logPtr, "DHCP Range: "); logPtr += sprintf(logPtr, "%s", IP2String(tempbuff, htonl(cfig.dhcpRanges[i].rangeStart))); logPtr += sprintf(logPtr, "-%s", IP2String(tempbuff, htonl(cfig.dhcpRanges[i].rangeEnd))); logPtr += sprintf(logPtr, "/%s", IP2String(tempbuff, cfig.dhcpRanges[i].mask)); logDHCPMess(logBuff, 1); } if (cfig.lease >= LONG_MAX) sprintf(logBuff, "Max Lease: Infinity"); else sprintf(logBuff, "Max Lease: %u (sec)", cfig.lease); logDHCPMess(logBuff, 1); } if (dnsService) { addToCache(0, "localhost", my_inet_addr("127.0.0.1"), LONG_MAX, LOCALHOST_A, LOCALHOST_PTR, LONG_MAX); addToCache(1, "localhost", my_inet_addr("127.0.0.1"), LONG_MAX, LOCALHOST_A, LOCALHOST_PTR, LONG_MAX); for (int i = 0; cfig.replication != 2 && i < MAX_SERVERS && network.allServers[i]; i++) if (cfig.authorized && makeLocal(network.allServers[i])) { addToCache(0, cfig.servername, network.allServers[i], LONG_MAX, SERVER_A, SERVER_PTR_AUTH, LONG_MAX); addToCache(1, cfig.servername, network.allServers[i], LONG_MAX, SERVER_A, SERVER_PTR_AUTH, LONG_MAX); } else { addToCache(0, cfig.servername, network.allServers[i], LONG_MAX, SERVER_A, SERVER_PTR_NAUTH, LONG_MAX); addToCache(1, cfig.servername, network.allServers[i], LONG_MAX, SERVER_A, SERVER_PTR_NAUTH, LONG_MAX); } if (getSection("DNS-ALLOWED-HOSTS", iniStr, 1, iniFile)) { char *iniStrPtr = myGetToken(iniStr, 0); for (int i = 0; i < 32 && iniStrPtr[0]; iniStrPtr = myGetToken(iniStrPtr, 1)) { DWORD rs = 0; DWORD re = 0; mySplit(name, value, iniStrPtr, '-'); if (value[0] && isIP(value)) { rs = htonl(my_inet_addr(name)); re = htonl(my_inet_addr(value)); } else { rs = htonl(my_inet_addr(name)); re = rs; } //printf("%u=%u\n", rs, re); if (rs && rs != INADDR_NONE && re && re != INADDR_NONE && 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", iniStrPtr); logDNSMess(logBuff, 1); } } } if (cfig.replication != 2 && getSection("HOSTS", iniStr, 1, iniFile)) { char *iniStrPtr = myGetToken(iniStr, 0); for (; iniStrPtr[0]; iniStrPtr = myGetToken(iniStrPtr, 1)) { mySplit(name, value, iniStrPtr, '='); if (name[0] && value[0]) { if (chkQu(name) && !isIP(name) && isIP(value)) { DWORD inetAddr = my_inet_addr(value); if (!inetAddr) { sprintf(logBuff, "Section [HOSTS] Invalid Entry: %s ignored", iniStrPtr); logDNSMess(logBuff, 1); } else if (cfig.authorized && makeLocal(name) && makeLocal(inetAddr)) { addToCache(cacheInd, name, inetAddr, LONG_MAX, STATIC_A_AUTH, STATIC_PTR_AUTH, cfig.serial1); setLeaseExpiry(inetAddr, 0); } else if (cfig.authorized && makeLocal(name)) { addToCache(cacheInd, name, inetAddr, LONG_MAX, STATIC_A_AUTH, STATIC_PTR_NAUTH, cfig.serial1); setLeaseExpiry(inetAddr, 0); } else if (cfig.authorized && makeLocal(inetAddr)) { addToCache(cacheInd, name, inetAddr, LONG_MAX, STATIC_A_NAUTH, STATIC_PTR_AUTH, cfig.serial1); setLeaseExpiry(inetAddr, 0); } else { makeLocal(name); addToCache(cacheInd, name, inetAddr, LONG_MAX, STATIC_A_NAUTH, STATIC_PTR_NAUTH, cfig.serial1); setLeaseExpiry(inetAddr, 0); } } else { sprintf(logBuff, "Section [HOSTS] Invalid Entry: %s ignored", iniStrPtr); logDNSMess(logBuff, 1); } } else { sprintf(logBuff, "Section [HOSTS], Missing value, entry %s ignored", iniStrPtr); logDNSMess(logBuff, 1); } } } if (cfig.replication != 2 && getSection("ALIASES", iniStr, 1, iniFile)) { char *iniStrPtr = myGetToken(iniStr, 0); for (int i = 0; iniStrPtr[0]; iniStrPtr = myGetToken(iniStrPtr, 1)) { mySplit(name, value, iniStrPtr, '='); if (name[0] && value[0]) { if (chkQu(name) && chkQu(value)) { if (makeLocal(name)) { data7 *cache = findEntry(cacheInd, name); if (!cache) { cache = (data7*)calloc(1, sizeof(data7)); if (cache) { if (!makeLocal(value)) cache->dataType = EXT_CNAME; else cache->dataType = LOCAL_CNAME; mySplit(name, value, iniStrPtr, '='); makeLocal(name); cache->mapname = cloneString(name); cache->hostname = cloneString(value); if (!cache->mapname || !cache->hostname) { sprintf(logBuff, "Section [ALIASES] entry %s memory error", iniStrPtr); logDNSMess(logBuff, 1); } else { cache->expiry = LONG_MAX; cache->serial = cfig.serial1; addEntry(cacheInd, cache); i++; } } else { sprintf(logBuff, "Section [ALIASES] entry %s memory error", iniStrPtr); logDNSMess(logBuff, 1); } } else { sprintf(logBuff, "Section [ALIASES] duplicate entry %s ignored", iniStrPtr); 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", iniStrPtr); logDNSMess(logBuff, 1); } } else { sprintf(logBuff, "Section [ALIASES], Missing value, entry %s ignored", iniStrPtr); logDNSMess(logBuff, 1); } } } if (cfig.replication != 2 && getSection("MAIL-SERVERS", iniStr, 1, iniFile)) { char *iniStrPtr = myGetToken(iniStr, 0); for (cfig.mxCount[cacheInd] = 0; cfig.mxCount[cacheInd] < MAX_SERVERS && iniStrPtr[0]; iniStrPtr = myGetToken(iniStrPtr, 1)) { mySplit(name, value, iniStrPtr, '='); if (name[0] && value[0]) { if (chkQu(name) && atoi(value)) { cfig.mxServers[0][cfig.mxCount[cacheInd]].pref = atoi(value); cfig.mxServers[1][cfig.mxCount[cacheInd]].pref = atoi(value); if (!strchr(name, '.')) { strcat(name, "."); strcat(name, cfig.zone); } strcpy(cfig.mxServers[0][cfig.mxCount[cacheInd]].hostname, name); strcpy(cfig.mxServers[1][cfig.mxCount[cacheInd]].hostname, name); cfig.mxCount[cacheInd]++; } else { sprintf(logBuff, "Section [MAIL-SERVERS] Invalid Entry: %s ignored", iniStrPtr); logDNSMess(logBuff, 1); } } else { sprintf(logBuff, "Section [MAIL-SERVERS], Missing value, entry %s ignored", iniStrPtr); logDNSMess(logBuff, 1); } } cfig.mxCount[1] = cfig.mxCount[0]; } if (getSection("CHILD-ZONES", iniStr, 1, iniFile)) { char *iniStrPtr = myGetToken(iniStr, 0); for (int i = 0; i < 32 && iniStrPtr[0]; iniStrPtr = myGetToken(iniStrPtr, 1)) { mySplit(name, value, iniStrPtr, '='); if (name[0] && value[0]) { /* if (cfig.authorized) { char *dp = strstr(name, arpa); if (dp) { dp = strchr(name, '.'); if (!dp || strcasecmp(dp + 1, cfig.authority)) { sprintf(logBuff, "Section [CHILD-ZONES], Zone %s is not child of %s, Entry ignored", name, cfig.authority); logDNSMess(logBuff, 1); continue; } } else { dp = strchr(name, '.'); if (!dp || strcasecmp(dp + 1, cfig.zone)) { sprintf(logBuff, "Section [CHILD-ZONES], Zone %s is not child of %s, Entry ignored", name, cfig.zone); logDNSMess(logBuff, 1); continue; } } } */ int j = 0; for (; j < 32 && cfig.dnsRoutes[j].zone[0]; j++) { if (!strcasecmp(cfig.dnsRoutes[j].zone, name)) { sprintf(logBuff, "Section [CHILD-ZONES], Duplicate Entry for Child Zone %s ignored", name); logDNSMess(logBuff, 1); break; } } if (j < 32 && !cfig.dnsRoutes[j].zone[0]) { if (name[0] && chkQu(name) && value[0]) { char *value1 = strchr(value, ','); if (value1) { *value1 = 0; value1++; DWORD ip = my_inet_addr(myTrim(value, value)); DWORD ip1 = my_inet_addr(myTrim(value1, value1)); if (isIP(value) && ip && isIP(value1) && ip1) { 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 [CHILD-ZONES] Invalid Entry: %s ignored", iniStrPtr); logDNSMess(logBuff, 1); } } else { DWORD ip = my_inet_addr(value); if (isIP(value) && ip) { 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 [CHILD-ZONES] Invalid Entry: %s ignored", iniStrPtr); logDNSMess(logBuff, 1); } } } else { sprintf(logBuff, "Section [CHILD-ZONES] Invalid Entry: %s ignored", iniStrPtr); logDNSMess(logBuff, 1); } } } else { sprintf(logBuff, "Section [CHILD-ZONES], Missing value, entry %s ignored", iniStrPtr); logDNSMess(logBuff, 1); } } } if (getSection("WILD-HOSTS", iniStr, 1, iniFile)) { char *iniStrPtr = myGetToken(iniStr, 0); for (int i = 0; i < 32 && iniStrPtr[0]; iniStrPtr = myGetToken(iniStrPtr, 1)) { mySplit(name, value, iniStrPtr, '='); if (name[0] && value[0]) { if (chkQu(name) && isIP(value)) { DWORD ip = my_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", iniStrPtr); logDNSMess(logBuff, 1); } } else { sprintf(logBuff, "Section [WILD-HOSTS], Missing value, entry %s ignored", iniStrPtr); logDNSMess(logBuff, 1); } } } if (getSection("NXDOMAIN", iniStr, 1, iniFile)) { char *iniStrPtr = myGetToken(iniStr, 0); //-- read a line in for (int i = 0; i < 32 && iniStrPtr[0]; iniStrPtr = myGetToken(iniStrPtr, 1)) { mySplit(name, value, iniStrPtr, '='); //-- parse it if (name[0]) { // If DEFAULT_IP is named and there is an ip value in value if (!strcmp(name, "DEFAULT_IP") && value[0] && isIP(value)) { sprintf(logBuff, "Section [NXDOMAIN] setting default ip "); logDNSMess(logBuff, 1); cfig.defaultIP = my_inet_addr(value); } // If this is just a name and its an ip else if (!value[0] && isIP(name)) { BYTE i = 0; for (; i <= 32 && cfig.nxdBlacklist[i]; i++); if (i < 32) { sprintf(logBuff, "Section [NXDOMAIN] adding blacklist ip at %d ",i); logDNSMess(logBuff, 1); cfig.nxdBlacklist[i]=my_inet_addr(name); } else { sprintf(logBuff, "Section [NXDOMAIN] Too many blacklist entries: %s ignored", iniStrPtr); logDNSMess(logBuff, 1); } } else { sprintf(logBuff, "Section [NXDOMAIN] Invalid Entry: %s ignored", iniStrPtr); logDNSMess(logBuff, 1); } } else { sprintf(logBuff, "Section [NXDOMAIN], Missing value, entry %s ignored", iniStrPtr); logDNSMess(logBuff, 1); } } } for (int i = 0; i < 32 && cfig.dnsRoutes[i].dns[0]; i++) { char temp[256]; if (!cfig.dnsRoutes[i].dns[1]) sprintf(logBuff, "Child DNS Server: %s for Zone %s", IP2String(tempbuff, cfig.dnsRoutes[i].dns[0]), cfig.dnsRoutes[i].zone); else sprintf(logBuff, "Child DNS Servers: %s, %s for Zone %s", IP2String(temp, cfig.dnsRoutes[i].dns[0]), IP2String(tempbuff, 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, "Forwarding DNS Server: %s", IP2String(tempbuff, network.dns[i])); logDNSMess(logBuff, 1); } char temp[128]; for (int i = 0; i <= MAX_RANGES && cfig.dnsRanges[i].rangeStart; i++) { char *logPtr = logBuff; logPtr += sprintf(logPtr, "%s", "DNS Service Permitted Hosts: "); logPtr += sprintf(logPtr, "%s-", IP2String(tempbuff, htonl(cfig.dnsRanges[i].rangeStart))); logPtr += sprintf(logPtr, "%s", IP2String(tempbuff, htonl(cfig.dnsRanges[i].rangeEnd))); logDNSMess(logBuff, 1); } if (cfig.ttl >= LONG_MAX) sprintf(logBuff, "Default Host Expiry: Infinity"); else sprintf(logBuff, "Default Host Expiry: %u (sec)", cfig.ttl); 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 == ULONG_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); } } 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); } else sprintf(logBuff, "Domain Name: %s", cfig.zone); logDNSMess(logBuff, 1); if (!verbatim) { if (dnsService) { if (cfig.dnsLogLevel > 1) sprintf(logBuff, "DNS Logging: All"); else if (cfig.dnsLogLevel) sprintf(logBuff, "DNS Logging: Errors"); else sprintf(logBuff, "DNS Logging: None"); logMess(logBuff, 1); } if (dhcpService) { if (cfig.dhcpLogLevel > 1) sprintf(logBuff, "DHCP Logging: All"); else if (cfig.dhcpLogLevel) sprintf(logBuff, "DHCP Logging: Errors"); else sprintf(logBuff, "DHCP Logging: None"); logMess(logBuff, 1); } } if (dnsService) { cfig.serial1 = t; cfig.serial2 = t; cfig.expireTime = LONG_MAX; if (dhcpService) { if (cfig.replication == 1) getSecondary(); else if (cfig.replication == 2) _beginthread(checkZone, 0, (void*)0); } else if (cfig.replication == 2) { _beginthread(checkZone, 0, (void*)&cfig); } } if (getSection("PORT-OFFSET", iniStr, 1, iniFile)) { char *iniStrPtr = myGetToken(iniStr, 0); portOffset = atoi(iniStrPtr); if (portOffset) { sprintf(logBuff, "Using port offset %d", portOffset); logMess(logBuff, 1); } } sprintf(logBuff, "Detecting Static Interfaces.."); logMess(logBuff, 1); do { memset(&network, 0, sizeof(network)); getServ(); getDServ(); sprintf(cfig.servername_fqn, "%s.%s", cfig.servername, cfig.zone); strcpy(cfig.ns, cfig.servername_fqn); cfig.zLen = strlen(cfig.zone); bool ifSpecified = false; if (getSection("LISTEN-ON", iniStr, 1, iniFile)) { char *iniStrPtr = myGetToken(iniStr, 0); for (int i = 0; i < MAX_SERVERS && iniStrPtr[0]; iniStrPtr = myGetToken(iniStrPtr, 1)) { ifSpecified = true; DWORD addr = my_inet_addr(iniStrPtr); if (isIP(iniStrPtr) && addr) { for (BYTE m = 0; ; m++) { if (m >= MAX_SERVERS || !network.staticServers[m]) { if (findServer(network.allServers, addr)) { sprintf(logBuff, "Warning: Section [LISTEN-ON], Interface %s is not Static, ignored", iniStrPtr); logMess(logBuff, 1); } else { sprintf(logBuff, "Warning: Section [LISTEN-ON], Interface %s not available, ignored", iniStrPtr); logMess(logBuff, 1); } break; } else if (network.staticServers[m] == addr) { for (BYTE n = 0; n < MAX_SERVERS; n++) { if (network.listenServers[n] == addr) break; else if (!network.listenServers[n]) { network.listenServers[n] = network.staticServers[m]; network.listenMasks[n] = network.staticMasks[m]; break; } } break; } } } else { sprintf(logBuff, "Warning: Section [LISTEN-ON], Invalid Interface Address %s, ignored", iniStrPtr); logMess(logBuff, 1); } } } if (!ifSpecified) { BYTE k = 0; for (BYTE m = 0; m < MAX_SERVERS && network.allServers[m]; m++) { for (BYTE n = 0; n < MAX_SERVERS; n++) { if (network.allServers[m] == network.staticServers[n]) { network.listenServers[k] = network.staticServers[n]; network.listenMasks[k] = network.staticMasks[n]; k++; break; } else if (!network.staticServers[n]) { sprintf(logBuff, "Warning: Interface %s is not Static, not used", IP2String(tempbuff, network.allServers[m])); logMess(logBuff, 2); break; } } } } if (dhcpService) { int i = 0; for (int j = 0; j < MAX_SERVERS && network.listenServers[j]; j++) { BOOL bOptVal = TRUE; int bOptLen = sizeof(BOOL); network.dhcpConn[i].sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); if (network.dhcpConn[i].sock == INVALID_SOCKET) { sprintf(logBuff, "Failed to Create DHCP Socket"); logMess(logBuff, 1); continue; } network.dhcpConn[i].addr.sin_family = AF_INET; network.dhcpConn[i].addr.sin_addr.s_addr = network.listenServers[j]; network.dhcpConn[i].addr.sin_port = htons(IPPORT_DHCPS + portOffset); network.dhcpConn[i].broadCastVal = TRUE; network.dhcpConn[i].broadCastSize = sizeof(network.dhcpConn[i].broadCastVal); setsockopt(network.dhcpConn[i].sock, SOL_SOCKET, SO_BROADCAST, (char*)&network.dhcpConn[i].broadCastVal, network.dhcpConn[i].broadCastSize); setsockopt(network.dhcpConn[i].sock, SOL_SOCKET, SO_REUSEADDR, (char*)&bOptVal, bOptLen); //network.dhcpConn[i].donotRouteVal = TRUE; //network.dhcpConn[i].donotRouteSize = sizeof(network.dhcpConn[i].donotRouteVal); //setsockopt(network.dhcpConn[i].sock, SOL_SOCKET, SO_DONTROUTE, (char*)&network.dhcpConn[i].donotRouteVal, network.dhcpConn[i].donotRouteSize); int nRet = bind(network.dhcpConn[i].sock, (sockaddr*)&network.dhcpConn[i].addr, sizeof(struct sockaddr_in)); if (nRet == SOCKET_ERROR) { closesocket(network.dhcpConn[i].sock); sprintf(logBuff, "Warning: %s Port %d already in use", IP2String(tempbuff, network.listenServers[j]), (IPPORT_DHCPS + portOffset)); logMess(logBuff, 1); continue; } if (network.maxFD < network.dhcpConn[i].sock) network.maxFD = network.dhcpConn[i].sock; network.dhcpConn[i].server = network.listenServers[j]; network.dhcpConn[i].mask = network.listenMasks[j]; i++; } if (cfig.replication) { //printf("Here\n"); network.dhcpReplConn.sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); if (network.dhcpReplConn.sock == INVALID_SOCKET) { sprintf(logBuff, "Failed to Create DHCP Replication Socket"); logMess(logBuff, 1); } else { //printf("Socket %u\n", network.dhcpReplConn.sock); network.dhcpReplConn.addr.sin_family = AF_INET; if (cfig.replication == 1) network.dhcpReplConn.addr.sin_addr.s_addr = cfig.zoneServers[0]; else network.dhcpReplConn.addr.sin_addr.s_addr = cfig.zoneServers[1]; network.dhcpReplConn.addr.sin_port = 0; int nRet = bind(network.dhcpReplConn.sock, (sockaddr*)&network.dhcpReplConn.addr, sizeof(struct sockaddr_in)); if (nRet == SOCKET_ERROR) { sprintf(logBuff, "DHCP Replication Server, Bind Failed"); logMess(logBuff, 1); } else if (network.maxFD < network.dhcpReplConn.sock) network.maxFD = network.dhcpReplConn.sock; /* else network.dhcpReplConn.server = network.dhcpReplConn.addr.sin_addr.s_addr; */ } } } if (dnsService) { int i = 0; for (int j = 0; j < MAX_SERVERS && network.listenServers[j]; j++) { BOOL bOptVal = TRUE; int bOptLen = sizeof(BOOL); network.dnsUdpConn[i].sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); if (network.dnsUdpConn[i].sock == INVALID_SOCKET) { sprintf(logBuff, "Failed to Create Socket"); logDNSMess(logBuff, 1); continue; } //printf("Socket %u\n", network.dnsUdpConn[i].sock); network.dnsUdpConn[i].addr.sin_family = AF_INET; network.dnsUdpConn[i].addr.sin_addr.s_addr = network.listenServers[j]; network.dnsUdpConn[i].addr.sin_port = htons(IPPORT_DNS + portOffset); setsockopt(network.dnsUdpConn[i].sock, SOL_SOCKET, SO_REUSEADDR, (char*)&bOptVal, bOptLen); int nRet = bind(network.dnsUdpConn[i].sock, (sockaddr*)&network.dnsUdpConn[i].addr, sizeof(struct sockaddr_in) ); if (nRet == SOCKET_ERROR) { closesocket(network.dnsUdpConn[i].sock); sprintf(logBuff, "Warning: %s UDP Port %d already in use", IP2String(tempbuff, network.listenServers[j]), (IPPORT_DNS + portOffset)); logDNSMess(logBuff, 1); continue; } if (network.maxFD < network.dnsUdpConn[i].sock) network.maxFD = network.dnsUdpConn[i].sock; network.dnsUdpConn[i].server = network.listenServers[j]; if (!cfig.nsIP) cfig.nsIP = network.listenServers[j]; i++; } network.forwConn.sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); if (network.forwConn.sock == INVALID_SOCKET) { sprintf(logBuff, "Failed to Create Socket"); logDNSMess(logBuff, 1); } else { network.forwConn.addr.sin_family = AF_INET; //bind(network.forwConn.sock, (sockaddr*)&network.forwConn.addr, sizeof(struct sockaddr_in)); if (network.maxFD < network.forwConn.sock) network.maxFD = network.forwConn.sock; } i = 0; for (int j = 0; j < MAX_SERVERS && network.listenServers[j]; j++) { network.dnsTcpConn[i].sock = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP); if (network.dnsTcpConn[i].sock == INVALID_SOCKET) { sprintf(logBuff, "Failed to Create Socket"); logDNSMess(logBuff, 1); } else { BOOL bOptVal = TRUE; int bOptLen = sizeof(BOOL); //printf("Socket %u\n", network.dnsTcpConn[i].sock); network.dnsTcpConn[i].addr.sin_family = AF_INET; network.dnsTcpConn[i].addr.sin_addr.s_addr = network.listenServers[j]; network.dnsTcpConn[i].addr.sin_port = htons(IPPORT_DNS + portOffset); setsockopt(network.dnsTcpConn[i].sock, SOL_SOCKET, SO_REUSEADDR, (char *)&bOptVal, bOptLen); int nRet = bind(network.dnsTcpConn[i].sock, (sockaddr*)&network.dnsTcpConn[i].addr, sizeof(struct sockaddr_in)); if (nRet == SOCKET_ERROR) { closesocket(network.dnsTcpConn[i].sock); sprintf(logBuff, "Warning: %s TCP Port %d already in use", IP2String(tempbuff, network.listenServers[j]), (IPPORT_DNS + portOffset)); logDNSMess(logBuff, 1); } else { nRet = listen(network.dnsTcpConn[i].sock, SOMAXCONN); if (nRet == SOCKET_ERROR) { closesocket(network.dnsTcpConn[i].sock); sprintf(logBuff, "TCP Port 53 Error on Listen"); logDNSMess(logBuff, 1); } else { network.dnsTcpConn[i].server = network.listenServers[j]; if (network.maxFD < network.dnsTcpConn[i].sock) network.maxFD = network.dnsTcpConn[i].sock; i++; } } } } } if ((dhcpService && !network.dhcpConn[0].server) || (dnsService && !(network.dnsUdpConn[0].server && network.dnsTcpConn[0].server))) { sprintf(logBuff, "No Static Interface ready, Waiting..."); logMess(logBuff, 1); continue; } if (dhcpService) { network.httpConn.port = 6789; network.httpConn.server = network.dhcpConn[0].server; if (getSection("HTTP-INTERFACE", iniStr, 1, iniFile)) { char *iniStrPtr = myGetToken(iniStr, 0); if(iniStrPtr[0]) { mySplit(name, value, iniStrPtr, ':'); if (name[0] && isIP(name) && my_inet_addr(name)) network.httpConn.server = my_inet_addr(name); else { sprintf(logBuff, "Warning: Section [HTTP-INTERFACE], Invalid IP Address %s, ignored", name); logDHCPMess(logBuff, 1); } if (value[0]) { if (atoi(value)) network.httpConn.port = atoi(value); else { sprintf(logBuff, "Warning: Section [HTTP-INTERFACE], Invalid port %s, ignored", value); logDHCPMess(logBuff, 1); } } } } network.httpConn.sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (network.httpConn.sock == INVALID_SOCKET) { network.httpConn.server = 0; sprintf(logBuff, "Failed to Create Socket"); logDHCPMess(logBuff, 1); } else { //printf("Socket %u\n", network.httpConn.sock); network.httpConn.addr.sin_family = AF_INET; network.httpConn.addr.sin_addr.s_addr = network.httpConn.server; network.httpConn.addr.sin_port = htons(network.httpConn.port); int nRet = bind(network.httpConn.sock, (sockaddr*)&network.httpConn.addr, sizeof(struct sockaddr_in)); if (nRet == SOCKET_ERROR) { sprintf(logBuff, "Http Interface %s TCP Port %u not available", IP2String(tempbuff, network.httpConn.server), network.httpConn.port); logDHCPMess(logBuff, 1); network.httpConn.server = 0; closesocket(network.httpConn.sock); } else { nRet = listen(network.httpConn.sock, SOMAXCONN); if (nRet == SOCKET_ERROR) { sprintf(logBuff, "%s TCP Port %u Error on Listen", IP2String(tempbuff, network.httpConn.server), network.httpConn.port); logDHCPMess(logBuff, 1); closesocket(network.httpConn.sock); network.httpConn.server = 0; } else if (network.httpConn.sock > network.maxFD) network.maxFD = network.httpConn.sock; } } } network.maxFD++; char htmFile[_MAX_PATH]; GetModuleFileName(NULL, htmFile, _MAX_PATH); fileExt = strrchr(htmFile, '.'); strcpy(fileExt, ".htm"); if (dhcpService && network.httpConn.server) { sprintf(logBuff, "Lease Status URL: http://%s:%u", IP2String(tempbuff, network.httpConn.server), network.httpConn.port); logDHCPMess(logBuff, 1); FILE *f = fopen(htmFile, "wt"); if (f) { fprintf(f, "<script>this.location=\"http://%s:%u\";</script>", IP2String(tempbuff, network.httpConn.server), network.httpConn.port); fclose(f); } } else { FILE *f = fopen(htmFile, "wt"); if (f) { fprintf(f, "<html><body><h2>DHCP/HTTP Service is not running</h2></body></html>"); fclose(f); } } for (int i = 0; i < MAX_SERVERS && network.staticServers[i]; i++) { for (BYTE j = 0; j < MAX_SERVERS; j++) { if (network.dhcpConn[j].server == network.staticServers[i] || network.dnsUdpConn[j].server == network.staticServers[i]) { sprintf(logBuff, "Listening On: %s", IP2String(tempbuff, network.staticServers[i])); logMess(logBuff, 1); break; } } } // if (verbatim) // printf("\nAccepting requests..\n"); } while (detectChange()); _endthread(); return; } bool detectChange() { OVERLAPPED overlap; DWORD ret; HANDLE hand = NULL; overlap.hEvent = WSACreateEvent(); ret = NotifyAddrChange(&hand, &overlap); if (ret != NO_ERROR) { if (WSAGetLastError() != WSA_IO_PENDING) { printf("NotifyAddrChange error...%d\n", WSAGetLastError()); return true; } } network.ready = true; if ( WaitForSingleObject(overlap.hEvent, INFINITE) == WAIT_OBJECT_0 ) { //logMess("Here", 1); WSACloseEvent(overlap.hEvent); network.ready = false; while (network.busy) Sleep(10); sprintf(logBuff, "Network changed, re-detecting Static Interfaces.."); logMess(logBuff, 1); closeConn(); memset(&network, 0, sizeof(network)); } return true; } void getServ() { for (int i = 0; i < MAX_SERVERS; i++) { network.allServers[i] = 0; network.staticServers[i] = 0; network.staticMasks[i] = 0; } SOCKET sd = WSASocket(PF_INET, SOCK_DGRAM, 0, 0, 0, 0); if (sd == INVALID_SOCKET) return; INTERFACE_INFO InterfaceList[MAX_SERVERS]; unsigned long nBytesReturned; if (WSAIoctl(sd, SIO_GET_INTERFACE_LIST, 0, 0, &InterfaceList, sizeof(InterfaceList), &nBytesReturned, 0, 0) == SOCKET_ERROR) return ; int nNumInterfaces = nBytesReturned / sizeof(INTERFACE_INFO); for (int i = 0; i < nNumInterfaces; ++i) { sockaddr_in *pAddress = (sockaddr_in*)&(InterfaceList[i].iiAddress); u_long nFlags = InterfaceList[i].iiFlags; // if (!((nFlags & IFF_POINTTOPOINT))) if (!((nFlags & IFF_POINTTOPOINT) || (nFlags & IFF_LOOPBACK))) { //printf("%s\n", IP2String(tempbuff, pAddress->sin_addr.S_un.S_addr)); addServer(network.allServers, pAddress->sin_addr.s_addr); } } closesocket(sd); PIP_ADAPTER_INFO pAdapterInfo; PIP_ADAPTER_INFO pAdapter; pAdapterInfo = (IP_ADAPTER_INFO*) calloc(1, sizeof(IP_ADAPTER_INFO)); DWORD ulOutBufLen = sizeof(IP_ADAPTER_INFO); if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) { free(pAdapterInfo); pAdapterInfo = (IP_ADAPTER_INFO*)calloc(1, ulOutBufLen); } if ((GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) { pAdapter = pAdapterInfo; while (pAdapter) { //if (!pAdapter->DhcpEnabled) { IP_ADDR_STRING *sList = &pAdapter->IpAddressList; while (sList) { DWORD iaddr = my_inet_addr(sList->IpAddress.String); if (iaddr) { for (BYTE k = 0; k < MAX_SERVERS; k++) { if (network.staticServers[k] == iaddr) break; else if (!network.staticServers[k]) { network.staticServers[k] = iaddr; network.staticMasks[k] = my_inet_addr(sList->IpMask.String); break; } } } sList = sList->Next; } // IP_ADDR_STRING *rList = &pAdapter->GatewayList; // while (rList) // { // DWORD trouter = my_inet_addr(rList->IpAddress.String); // addServer(cfig.routers, trouter); // rList = rList->Next; // } } pAdapter = pAdapter->Next; } free(pAdapterInfo); } } void getDServ() { char iniStr[9192]; DWORD dservers[MAX_SERVERS]; for (int i = 0; i < MAX_SERVERS; i++) { network.dns[i] = 0; dservers[i] = 0; } if (getSection("DNS-SERVERS", iniStr, 1, iniFile)) { char *iniStrPtr = myGetToken(iniStr, 0); for (int i = 0; i < MAX_SERVERS && iniStrPtr[0]; iniStrPtr = myGetToken(iniStrPtr, 1)) { if (isIP(iniStrPtr)) { DWORD addr = my_inet_addr(iniStrPtr); if (addServer(dservers, addr)) i++; } else { sprintf(logBuff, "Section [DNS-SERVERS] Invalid Entry: %s ignored", iniStrPtr); logMess(logBuff, 1); } } } FIXED_INFO *FixedInfo; ULONG ulOutBufLen; IP_ADDR_STRING *pIPAddr; FixedInfo = (FIXED_INFO*) GlobalAlloc(GPTR, sizeof(FIXED_INFO)); ulOutBufLen = sizeof(FIXED_INFO); if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &ulOutBufLen)) { GlobalFree(FixedInfo); FixedInfo = (FIXED_INFO*)GlobalAlloc(GPTR, ulOutBufLen); } if (!GetNetworkParams(FixedInfo, &ulOutBufLen)) { if (!cfig.servername[0]) strcpy(cfig.servername, FixedInfo->HostName); //printf("d=%s", FixedInfo->DomainName); if (!cfig.zone[0]) { strcpy(cfig.zone, FixedInfo->DomainName); cfig.zLen = strlen(cfig.zone); } if (!cfig.zone[0]) { strcpy(cfig.zone, "workgroup"); cfig.zLen = strlen(cfig.zone); } if (!dservers[0]) { pIPAddr = &FixedInfo->DnsServerList; while (pIPAddr) { DWORD addr = my_inet_addr(pIPAddr->IpAddress.String); addServer(dservers, addr); pIPAddr = pIPAddr->Next; } } GlobalFree(FixedInfo); } for (int i = 0; i < MAX_SERVERS && dservers[i]; i++) { if (dnsService) { if (findServer(network.allServers, dservers[i])) continue; addServer(network.dns, dservers[i]); } else addServer(network.dns, dservers[i]); } return; } void updateStateFile(void *lpParam) { data8 *dhcpData = (data8*)lpParam; WaitForSingleObject(fEvent, INFINITE); if (dhcpData->dhcpInd) { FILE *f = fopen(leaFile, "rb+"); if (f) { if (fseek(f, (dhcpData->dhcpInd - 1)*sizeof(data8), SEEK_SET) >= 0) fwrite(dhcpData, sizeof(data8), 1, f); fclose(f); } } else { dhcpData->dhcpInd = cfig.dhcpIndex; FILE *f = fopen(leaFile, "ab"); if (f) { fwrite(dhcpData, sizeof(data8), 1, f); fclose(f); } } free(dhcpData); SetEvent(fEvent); _endthread(); return; } WORD gdmess(data9 *req, BYTE sockInd) { memset(req, 0, sizeof(data9)); req->sockInd = sockInd; req->sockLen = sizeof(req->addr); errno = 0; req->bytes = recvfrom(network.dhcpConn[req->sockInd].sock, req->raw, sizeof(req->raw), 0, (sockaddr*)&req->addr, &req->sockLen); //printf("start bytes=%u\n", req->bytes); errno = WSAGetLastError(); //printf("errno=%u\n", errno); if (errno || req->bytes <= 0 || req->dhcpp.header.bp_op != BOOTP_REQUEST) return 0; data3 *op; BYTE *raw = req->dhcpp.vend_data; BYTE *rawEnd = raw + (req->bytes - sizeof(dhcp_header)); for (; raw < rawEnd && *raw != DHCP_OPTION_END;) { op = (data3*)raw; //printf("OpCode=%u,MessType=%u\n", op->opt_code, op->value[0]); switch (op->opt_code) { case DHCP_OPTION_PAD: raw++; continue; case DHCP_OPTION_PARAMREQLIST: for (int ix = 0; ix < op->size; ix++) { req->paramreqlist[op->value[ix]] = 1; } break; case DHCP_OPTION_MESSAGETYPE: req->req_type = op->value[0]; break; case DHCP_OPTION_SERVERID: req->server = fIP(op->value); break; case DHCP_OPTION_IPADDRLEASE: req->lease = fULong(op->value); break; case DHCP_OPTION_MAXDHCPMSGSIZE: req->messsize = fUShort(op->value); break; case DHCP_OPTION_REQUESTEDIPADDR: req->reqIP = fIP(op->value); break; case DHCP_OPTION_HOSTNAME: if (op->size && strcasecmp((char*)op->value, "(none)") && strcasecmp((char*)op->value, cfig.servername)) { memcpy(req->hostname, op->value, op->size); req->hostname[op->size] = 0; if (char *ptr = strchr(req->hostname, '.')) *ptr = 0; } break; case DHCP_OPTION_VENDORCLASSID: memcpy(req->vendClass, op->value, op->size); req->vendClassSize = op->size; vciData v; memcpy(v.vci, req->vendClass, (op->size)+1); vci[req->reqIP] = v; break; case DHCP_OPTION_USERCLASS: memcpy(req->userClass, op->value, op->size); req->userClassSize = op->size; 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_SERIAL: req->serial = fULong(op->value); break; } raw += 2; raw += op->size; } 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 logMess(char *logBuff, BYTE dhcpLogLevel) { // WaitForSingleObject(lEvent, INFINITE); //if (verbatim) printf("%s\n", logBuff); /*else*/ if (cfig.logfile && (dhcpLogLevel <= cfig.dnsLogLevel || dhcpLogLevel <= cfig.dhcpLogLevel)) { time_t t = time(NULL); tm *ttm = localtime(&t); if (ttm->tm_yday != loggingDay) { loggingDay = ttm->tm_yday; strftime(extbuff, sizeof(extbuff), logFile, ttm); fprintf(cfig.logfile, "Logging Continued on file %s\n", extbuff); fclose(cfig.logfile); cfig.logfile = fopen(extbuff, "at"); if (cfig.logfile) fprintf(cfig.logfile, "%s\n\n", sVersion); else return; } strftime(extbuff, sizeof(extbuff), "%d-%b-%y %X", ttm); fprintf(cfig.logfile, "[%s] %s\n", extbuff, logBuff); fflush(cfig.logfile); } // SetEvent(lEvent); } void logDHCPMess(char *logBuff, BYTE dhcpLogLevel) { // WaitForSingleObject(lEvent, INFINITE); //if (verbatim) printf("%s\n", logBuff); /*else*/ if (cfig.logfile && dhcpLogLevel <= cfig.dhcpLogLevel) { time_t t = time(NULL); tm *ttm = localtime(&t); if (ttm->tm_yday != loggingDay) { loggingDay = ttm->tm_yday; strftime(extbuff, sizeof(extbuff), logFile, ttm); fprintf(cfig.logfile, "Logging Continued on file %s\n", extbuff); fclose(cfig.logfile); cfig.logfile = fopen(extbuff, "at"); if (cfig.logfile) fprintf(cfig.logfile, "%s\n\n", sVersion); else return; } strftime(extbuff, sizeof(extbuff), "%d-%b-%y %X", ttm); fprintf(cfig.logfile, "[%s] %s\n", extbuff, logBuff); fflush(cfig.logfile); } // SetEvent(lEvent); } void logDNSMess(char *logBuff, BYTE dnsLogLevel) { // WaitForSingleObject(lEvent, INFINITE); //if (verbatim) printf("%s\n", logBuff); /*else*/ if (cfig.logfile && dnsLogLevel <= cfig.dnsLogLevel) { time_t t = time(NULL); tm *ttm = localtime(&t); if (ttm->tm_yday != loggingDay) { loggingDay = ttm->tm_yday; strftime(extbuff, sizeof(extbuff), logFile, ttm); fprintf(cfig.logfile, "Logging Continued on file %s\n", extbuff); fclose(cfig.logfile); cfig.logfile = fopen(extbuff, "at"); if (cfig.logfile) fprintf(cfig.logfile, "%s\n\n", sVersion); else return; } strftime(extbuff, sizeof(extbuff), "%d-%b-%y %X", ttm); fprintf(cfig.logfile, "[%s] %s\n", extbuff, logBuff); fflush(cfig.logfile); } // SetEvent(lEvent); } void logDNSMess(data5 *req, char *logBuff, BYTE dnsLogLevel) { // WaitForSingleObject(lEvent, INFINITE); //if (verbatim) printf("%s\n", logBuff); /*else*/ if (cfig.logfile && dnsLogLevel <= cfig.dnsLogLevel) { time_t t = time(NULL); tm *ttm = localtime(&t); if (ttm->tm_yday != loggingDay) { loggingDay = ttm->tm_yday; strftime(extbuff, sizeof(extbuff), logFile, ttm); fprintf(cfig.logfile, "Logging Continued on file %s\n", extbuff); fclose(cfig.logfile); cfig.logfile = fopen(extbuff, "at"); if (cfig.logfile) fprintf(cfig.logfile, "%s\n\n", sVersion); else return; } strftime(extbuff, sizeof(extbuff), "%d-%b-%y %X", ttm); fprintf(cfig.logfile, "[%s] Client %s, %s\n", extbuff, inet_ntoa(req->addr.sin_addr), logBuff); fflush(cfig.logfile); } // SetEvent(lEvent); } void logTCPMess(data5 *req, char *logBuff, BYTE dnsLogLevel) { // WaitForSingleObject(lEvent, INFINITE); //if (verbatim) printf("%s\n", logBuff); /*else*/ if (cfig.logfile && dnsLogLevel <= cfig.dnsLogLevel) { time_t t = time(NULL); tm *ttm = localtime(&t); if (ttm->tm_yday != loggingDay) { loggingDay = ttm->tm_yday; strftime(extbuff, sizeof(extbuff), logFile, ttm); fprintf(cfig.logfile, "Logging Continued on file %s\n", extbuff); fclose(cfig.logfile); cfig.logfile = fopen(extbuff, "at"); if (cfig.logfile) fprintf(cfig.logfile, "%s\n\n", sVersion); else return; } strftime(extbuff, sizeof(extbuff), "%d-%b-%y %X", ttm); fprintf(cfig.logfile, "[%s] TCP Client %s, %s\n", extbuff, inet_ntoa(req->addr.sin_addr), logBuff); fflush(cfig.logfile); } // SetEvent(lEvent); }