// read configuration either from INI file (if it exists) or from the registry int DHCPReadConfig ( ) { int Ark; char szBuf[128]; memset (& sParamDHCP, 0, sizeof sParamDHCP); sParamDHCP.nLease = DHCP_DEFAULT_LEASE_TIME; for (Ark=0 ; Ark<SizeOfTab (tDHCPd32Entry) ; Ark++) ReadKey ( TFTPD32_DHCP_KEY, tDHCPd32Entry [Ark].szEntry, tDHCPd32Entry [Ark].pValue, tDHCPd32Entry [Ark].nBufSize, tDHCPd32Entry [Ark].nType, szTftpd32IniFile ); // custom items for (Ark=0 ; Ark < SizeOfTab (sParamDHCP.t) ; Ark++) { wsprintf (szBuf, "%s%d", KEY_DHCP_USER_OPTION_NB, Ark+1); ReadKey (TFTPD32_DHCP_KEY, szBuf, & sParamDHCP.t[Ark].nAddOption, sizeof sParamDHCP.t[Ark].nAddOption, REG_DWORD, szTftpd32IniFile); wsprintf (szBuf, "%s%d", KEY_DHCP_USER_OPTION_VALUE, Ark+1); ReadKey (TFTPD32_DHCP_KEY, szBuf, sParamDHCP.t[Ark].szAddOption, sizeof sParamDHCP.t[Ark].szAddOption, REG_SZ, szTftpd32IniFile); } if ( sParamDHCP.nPoolSize!=0 ) { tFirstIP = malloc (sParamDHCP.nPoolSize * sizeof *tFirstIP[0]) ; tMAC = malloc (sParamDHCP.nPoolSize * sizeof *tMAC[0]) ; if (tFirstIP == NULL || tMAC == NULL ) { SVC_ERROR ("Can not allocate memory"); return FALSE; } LoadLeases (); } if (sParamDHCP.nLease==0) { sParamDHCP.nLease=DHCP_DEFAULT_LEASE_TIME; LOG (12, "%d, Lease time not specified, set to 2 days", GetCurrentThreadId ()); } // compatability 3 -> 4 if (sParamDHCP.szWins[0]==0 && sParamDHCP.szDns1[0]!=0) { lstrcpy (sParamDHCP.szWins, sParamDHCP.szDns1); LOG (0, "WINS server copied from DNS servers"); } return TRUE; } // DHCPReadConfig
void ListenDhcpMessage (void *lpVoid) { struct dhcp_packet sDhcpPkt; char szHostname [128], *p; int Rc, nSize; struct S_WorkerParam *pParam = lpVoid; struct sockaddr_in SockFrom; int nFromLen = sizeof SockFrom; BOOL bUniCast; int True = 1; DHCPReadConfig (); Sleep (1000); //NJW Prompt to see if we should discover via ping before we start doing DHCP if(scanforleases) // && IDYES == CMsgBox(pParam->hWnd, "Should I reset the lease file and rediscover devices?", "Discover Devices", MB_YESNO)) { struct in_addr addr; int count; SetHourglass(TRUE); ReadKey(TFTPD32_DHCP_KEY, KEY_DHCP_POOL, & addr.s_addr, sizeof(addr.s_addr), REG_DWORD, szTftpd32IniFile); ReadKey(TFTPD32_DHCP_KEY, KEY_DHCP_POOLSIZE, &count, sizeof(count), REG_DWORD, szTftpd32IniFile); SetNumAllocated(0); FreeLeases(FALSE); if (sSettings.bPersLeases) LoadLeases (); if (sSettings.bPing) PingRange (&addr, count); // DHCPSaveConfig (); SetHourglass(FALSE); SVC_WARNING ("Lease file updated.\nDiscover Devices"); } // add broadcast permission to socket if (setsockopt (tThreads[TH_DHCP].skt, SOL_SOCKET, SO_BROADCAST, (char *) & True, sizeof True) != 0) { LOG (1, "can't set broadcast option.\nPlease, suppress DHCP server in the settings window"); LogToMonitor ("can't set broadcast option.\n"); tThreads[TH_DHCP].gRunning = FALSE; } while ( tThreads[TH_DHCP].gRunning ) { // send leases to GUI Dhcp_Send_Leases (tFirstIP, nAllocatedIP); memset (& sDhcpPkt, 0, sizeof sDhcpPkt); Rc = recvfrom ( tThreads[TH_DHCP].skt, (char *) & sDhcpPkt, sizeof sDhcpPkt, 0, (struct sockaddr *) & SockFrom, & nFromLen); // recv error // since Tftpd32 sends broadcasts, it receives its own message, just ignore it if (Rc < 0) { if (GetLastError () != WSAECONNRESET) { LOG (1, "Recv error %d", GetLastError ()); Sleep (500); } continue; } // recv failed // if msg is too short // If all bootP fields have been read if (Rc < offsetof ( struct dhcp_packet, options )) { LOG (5, "Message truncated (length was %d)", Rc); if ( tThreads[TH_DHCP].gRunning ) Sleep (500); continue; } // if pool is empty and MAC address not statically assigned : ignore request if ( sParamDHCP.nPoolSize == 0 && DHCP_StaticAssignation (& sDhcpPkt)==INADDR_NONE ) { Sleep (100); continue; } // handle only nul-terminated strings sDhcpPkt.sname[sizeof sDhcpPkt.sname - 1] = 0; sDhcpPkt.file [sizeof sDhcpPkt.file - 1] = 0; // read host name, truncate it if (gethostname (szHostname , sizeof szHostname )==SOCKET_ERROR) lstrcpy (szHostname, "Tftpd32DchpServer"); if ((p=strchr (szHostname, '.'))!=NULL) *p=0; szHostname [sizeof sDhcpPkt.sname - 1] = 0; if (sDhcpPkt.sname[0]!=0 && lstrcmp (sDhcpPkt.sname, szHostname)!=0) { LOG (2, "Packet addressed to %s", sDhcpPkt.sname); continue; } // we have only to answer to BOOTREQUEST msg if (sDhcpPkt.op != BOOTREQUEST) { LOG (2, "%d Request %d not processed", GetCurrentThreadId (),sDhcpPkt.op); continue ; } // if request OK and answer ready bUniCast = ( SockFrom.sin_addr.s_addr!=htonl (INADDR_NONE) && SockFrom.sin_addr.s_addr!=htonl (INADDR_ANY) // fix 5/02/2006 : 127.0.0.2 should be handle as a broadcast && SockFrom.sin_addr.S_un.S_un_b.s_b1 != 127 ) ; // class A 127 if (ProcessDHCPMessage ( & sDhcpPkt, & nSize ) ) {struct servent *lpServEnt; // BinDump ((char *)&sDhcpPkt, sizeof sDhcpPkt, "DHCP"); SockFrom.sin_family = AF_INET; // if no source address was specified reply with a broadcast if (!bUniCast) SockFrom.sin_addr.s_addr = htonl (INADDR_NONE); // Added : DHCP relay detection --> send replies to port 67 and 68 // Colin and others point ourt that this is wrong. I guess they are right. // However it should not be an issue and i am sure that the host receive an address ! if (sDhcpPkt.giaddr.s_addr!=htonl(INADDR_ANY) || sDhcpPkt.giaddr.s_addr!=htonl(INADDR_NONE)) { // sends to port 67 lpServEnt = getservbyname ("bootps", "udp") ; SockFrom.sin_port = (lpServEnt != NULL) ? lpServEnt->s_port : htons (BOOTPS_PORT); Rc = sendto (tThreads[TH_DHCP].skt, (char *) & sDhcpPkt, nSize, 0, (struct sockaddr *) & SockFrom, sizeof SockFrom); // and prepare for port 68 lpServEnt = getservbyname ("bootpc", "udp") ; SockFrom.sin_port = (lpServEnt != NULL) ? lpServEnt->s_port : htons (BOOTPC_PORT); } LOG (15, "Thread 0x%X: send %d bytes", GetCurrentThreadId(), nSize ); Rc = sendto (tThreads[TH_DHCP].skt, (char *) & sDhcpPkt, nSize, 0, (struct sockaddr *) & SockFrom, sizeof SockFrom); if (Rc<nSize) LOG (1, "sendto error %d: %s", GetLastError(), LastErrorText ()); } // ProcessDHCPMessage } // do it eternally LogToMonitor ("DHCP thread ends here\n"); _endthread (); } // ListenDhcpMessage