Exemplo n.º 1
0
//Read in and initialize the leases
void LoadLeases(void)
{
   //We need to make sure the leases we load actually fit in the address pool, so we'll be
   //tracking the index to the lease file and the index to the allocated list
   int leaseindex, allocindex;
 
   // From Nick : I realized that there was a race condition in that code, 
   // particularly with the reading and saving of KEY_LEASE_NUMLEASES
   // I’ve added a function, which LoadLeases calls immediately on entry:
   WaitForMsgQueueToFinish (LL_ID_SETTINGS);

   nAllocatedIP = 0;
   ReadKey(TFTPD32_DHCP_KEY, KEY_LEASE_NUMLEASES, &nAllocatedIP, sizeof(nAllocatedIP), REG_DWORD, szTftpd32IniFile);

   if (nAllocatedIP > sParamDHCP.nPoolSize)
   {
      SVC_WARNING ("The pool size is too small for the number of leases, ignoring extra leases");
      nAllocatedIP = sParamDHCP.nPoolSize;
   }

   allocindex = 0;
   for(leaseindex = 0; leaseindex < nAllocatedIP; ++leaseindex)
   {
     char key [_MAX_PATH];
     char tmpval [_MAX_PATH];

     tFirstIP[allocindex] = malloc (sizeof(struct LL_IP));
     memset(tFirstIP[allocindex], 0, sizeof(struct LL_IP));

     tFirstIP[allocindex]->dwAllocNum = leaseindex;
     sprintf(key, "%s%d%s", KEY_LEASE_PREFIX, leaseindex, KEY_LEASE_MAC);
     if(ReadKey(TFTPD32_DHCP_KEY, key, tmpval, _MAX_PATH, REG_SZ, szTftpd32IniFile))
        atohaddr(tmpval, tFirstIP[allocindex]->sMacAddr, 6);
     sprintf(key, "%s%d%s", KEY_LEASE_PREFIX, leaseindex, KEY_LEASE_IP);
     if(ReadKey(TFTPD32_DHCP_KEY, key, tmpval, _MAX_PATH, REG_SZ, szTftpd32IniFile))
        tFirstIP[allocindex]->dwIP.s_addr = inet_addr(tmpval);
     sprintf(key, "%s%d%s", KEY_LEASE_PREFIX, leaseindex, KEY_LEASE_ALLOC);
     if(ReadKey(TFTPD32_DHCP_KEY, key, tmpval, _MAX_PATH, REG_SZ, szTftpd32IniFile))     
        tFirstIP[allocindex]->tAllocated = atotime(tmpval);
     sprintf(key, "%s%d%s", KEY_LEASE_PREFIX, leaseindex, KEY_LEASE_RENEW);
     if(ReadKey(TFTPD32_DHCP_KEY, key, tmpval, _MAX_PATH, REG_SZ, szTftpd32IniFile))
        tFirstIP[allocindex]->tRenewed = atotime(tmpval);

    // fix errors in date conversion (registry modified at hand)
    if (tFirstIP[allocindex]->tAllocated == -1) tFirstIP[allocindex]->tAllocated = 0;
    if (tFirstIP[allocindex]->tRenewed   == -1) tFirstIP[allocindex]->tRenewed   = 0;

     //If the address doesn't fit in the pool, don't add it after all
	 //Since we are assuming the leases were written in order, do a quick check for dups
	 //and invalid macaddrs
     if((!AddrFitsPool(&tFirstIP[allocindex]->dwIP)) || (IsMacEmpty(tFirstIP[allocindex])) ||
		((allocindex > 0) && (tFirstIP[allocindex]->dwIP.s_addr == tFirstIP[allocindex - 1]->dwIP.s_addr)))
     {
        free(tFirstIP[allocindex]);
        tFirstIP[allocindex] = NULL;
     }
     else
	 {
		tMAC[allocindex] = tFirstIP[allocindex];  //Copy to cross index
        ++allocindex;   //Move on to the next one
	 }
   }

   if(allocindex != nAllocatedIP)
      SetNumAllocated(allocindex);

    // ensure that data base is sorted (especially if we've dropped some leases in the load)
    qsort (tMAC, nAllocatedIP, sizeof *tMAC, MACCompare);
    qsort (tFirstIP, nAllocatedIP, sizeof *tFirstIP, QsortCompare);
    ReorderLeases();

} // LoadLeases
Exemplo n.º 2
0
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