예제 #1
0
파일: bootpd.c 프로젝트: madnessw/thesnow
int ProcessDHCPMessage (struct dhcp_packet *pDhcpPkt, int *pSize)
{
unsigned char *p=NULL;
struct LL_IP  *pCurIP=NULL, *pProposedIP=NULL;	// Thanks Sam Leitch !
int            Ark, nDhcpType = 0;
struct in_addr sRequestedAddr;
DWORD sStaticIP;

    if (IsDHCP (*pDhcpPkt))
    {
       // search DHCP message type
       p = DHCPSearchOptionsField (pDhcpPkt->options, DHO_DHCP_MESSAGE_TYPE, NULL);
       if (p!=NULL)        nDhcpType = *p;
     }
    if (pDhcpPkt->yiaddr.s_addr!=INADDR_ANY  &&  pDhcpPkt->yiaddr.s_addr!=INADDR_NONE )
            return FALSE ; // address already assigned

     // the tab has one undef raw
     for (Ark=0 ; Ark<SizeOfTab(tDHCPType)-1 && nDhcpType!=tDHCPType[Ark].nType ; Ark++) ;
     LOG (5, "Rcvd %s Msg for IP %s, Mac %s",
                      tDHCPType[Ark].sType,
                      inet_ntoa (pDhcpPkt->ciaddr),
                      haddrtoa(pDhcpPkt->chaddr, pDhcpPkt->hlen,':'));


    // if (sParamDHCP.nPoolSize==0) return FALSE;   // no allocation pool --> listen only

     switch (nDhcpType)
     {
        case 0           :    // BootP
            if(sParamDHCP.nIgnoreBootp)
            {
               LOG (5, "Ignoring Bootp request");
               break;
            }
        case DHCPDISCOVER :
            sStaticIP = DHCP_StaticAssignation (pDhcpPkt);
			if (sStaticIP != INADDR_NONE)
			{
               LOG (0, "%s: statically assigned to address %s", 
								haddrtoa(pDhcpPkt->chaddr, pDhcpPkt->hlen,':'), 
								inet_ntoa (* (struct in_addr *) & sStaticIP) );
               pDhcpPkt->yiaddr.s_addr = sStaticIP;
			}
			else
			{
               p  = DHCPSearchOptionsField (pDhcpPkt->options, DHO_DHCP_REQUESTED_ADDRESS, NULL);
               if (p!=NULL)
              {
                   pDhcpPkt->ciaddr = * (struct in_addr *) p;
                   LOG (5, "Client requested address %s", inet_ntoa (pDhcpPkt->ciaddr));
              }
              pProposedIP  = DHCP_IPAllocate (nDhcpType, & pDhcpPkt->ciaddr, pDhcpPkt->chaddr, pDhcpPkt->hlen);
              if (pProposedIP == NULL)
              {
                  LOG (1, "no more address or address previously allocated by another server");
                  return FALSE;
              }
              pDhcpPkt->yiaddr.s_addr = pProposedIP->dwIP.s_addr;
              LOG (2, "%s: proposed address %s", IsDHCP(*pDhcpPkt) ? "DHCP" : "BOOTP", inet_ntoa (pProposedIP->dwIP) );

              //If this is a bootp, there is no other response from the client.  
              //Since we don't want leases expiring (or being mistaken for unAcked DHCP offers),
              //set renewed to a distant time
              if(nDhcpType == 0  &&  sStaticIP == INADDR_NONE)     // patched by Rolf Offermanns
                  ForceRenewTime(pProposedIP, 0x66666666);         // fixed by Sam Leitch
            } // dynamically assigned address

            // populate the packet to be returned
            pDhcpPkt->op = BOOTREPLY;
            // translate $IP$ and $MAC$ from boot file name
            TranslateExp (sParamDHCP.szBootFile, pDhcpPkt->file, pDhcpPkt->yiaddr, pDhcpPkt->chaddr);
           *pSize = DHCPOptionsReply (pDhcpPkt, DHCPOFFER);
            break ;

		//NJW Changed how requests are handled to mimic linux -- requests are responded to even if we didn't originally allocate, but only if the requested address is in our pool range

        case DHCPREQUEST :
         {BOOL bSERVER = FALSE;  // TRUE if Tftpd32 has assigned this address
           // Static Allocation ?
             // search field REQUEST ADDR in options
            sStaticIP = DHCP_StaticAssignation (pDhcpPkt);
			if (sStaticIP != INADDR_NONE)
			{
			    // populate the packet to be returned
                   pDhcpPkt->op = BOOTREPLY;
                   pDhcpPkt->yiaddr.s_addr = sStaticIP;
                 // translate $IP$ and $MAC$ from boot file name
                 TranslateExp (sParamDHCP.szBootFile, pDhcpPkt->file, pDhcpPkt->yiaddr, pDhcpPkt->chaddr);
                   *pSize = DHCPOptionsReply (pDhcpPkt, DHCPACK);
				   break;
			}

           // has tftpd32 dinamically assigned this address
           pCurIP = DHCPSearchByMacAddress (pDhcpPkt->chaddr, pDhcpPkt->hlen);
           if (pCurIP==NULL)  return FALSE; // not attributed by Tftpd32 --> do not answer
           // search field REQUEST ADDR in options
            // if specified should fit database
			p  = DHCPSearchOptionsField (pDhcpPkt->options, DHO_DHCP_REQUESTED_ADDRESS, NULL);
            if (p!=NULL)
			{
				pDhcpPkt->ciaddr = * (struct in_addr *) p;
			}

			if(AddrFitsPool(&pDhcpPkt->ciaddr))
			{
				//Look up the address, if it's not found, or the owner is this macaddr,
				//or the lease was expired, allow the serving.
				BOOL wasexpired = FALSE;
				pProposedIP = DHCPSearchByIP(&pDhcpPkt->ciaddr, &wasexpired);
				bSERVER = !pProposedIP || wasexpired || (0 == memcmp(pProposedIP->sMacAddr, pDhcpPkt->chaddr, 6));
			}

			if (bSERVER)
			{

				pProposedIP  = DHCP_IPAllocate (nDhcpType, & pDhcpPkt->ciaddr, pDhcpPkt->chaddr, pDhcpPkt->hlen);
				if (pProposedIP == NULL)
				{
					  LOG (1, "no more addresses or address previously allocated by another server");
					  return FALSE;
				}
				if (pProposedIP->tAllocated==0) SetAllocTime(pProposedIP);
				SetRenewTime(pProposedIP);
				LOG (5, "Previously allocated address %s acked", inet_ntoa (pProposedIP->dwIP));
				// populate the packet to be returned
				pDhcpPkt->op = BOOTREPLY;
				pDhcpPkt->yiaddr.s_addr = pProposedIP->dwIP.s_addr;
                TranslateExp (sParamDHCP.szBootFile, pDhcpPkt->file, pDhcpPkt->yiaddr, pDhcpPkt->chaddr);
				*pSize = DHCPOptionsReply (pDhcpPkt, DHCPACK);
			}
			else
			{
				LOG (5, "Client requested address %s which was not allocated by tftpd32 and is either outside our pool or is used by someone else",
							  inet_ntoa (pDhcpPkt->ciaddr) );
				return FALSE ; // do not answer
 			}
           } // Block for bSERVER declaration
           break;


        case DHCPDECLINE :
             // search current item and its precedent
          pCurIP = DHCPSearchByMacAddress (pDhcpPkt->chaddr, pDhcpPkt->hlen);
           if (pCurIP!=NULL)
           {
             p  = DHCPSearchOptionsField (pDhcpPkt->options, DHO_DHCP_REQUESTED_ADDRESS, NULL);
             if (p!=NULL) 
              {
                 sRequestedAddr.s_addr = * (DWORD *) p;
                 if ( pCurIP->dwIP.s_addr==sRequestedAddr.s_addr) 
                 {
                     DHCPDestroyItem (pCurIP);
                     LOG (5, "item destroyed");
                 }
             }
           }
		   //The decline is sent when an address is already in use.  Do an ARP and 
		   //add a lease for the in-use address
		   {
			 ULONG mac[2];
			 ULONG maclen = 6;
			// search field REQUEST ADDR in options
			// if specified should fit database
			p  = DHCPSearchOptionsField (pDhcpPkt->options, DHO_DHCP_REQUESTED_ADDRESS, NULL);
			if (p!=NULL)
			{
				pDhcpPkt->ciaddr = * (struct in_addr *) p;
			}

			 if(NO_ERROR == SendARP(pDhcpPkt->ciaddr.s_addr, 0, mac, &maclen))
			 {
				pProposedIP  = DHCP_IPAllocate (nDhcpType, & pDhcpPkt->ciaddr, (unsigned char*)mac, maclen);
				if (pProposedIP)
				{
					if (pProposedIP->tAllocated==0) SetAllocTime(pProposedIP);
					ForceRenewTime(pProposedIP, 0x66666666);   //Give a bootp lease, since the device may not do dhcp      
					LOG (5, "Added lease for existing address %s", inet_ntoa (pProposedIP->dwIP));
				}
			 }
		   }
           break;

        case DHCPRELEASE :
            // do not destroy the item but mark it free
           pCurIP = DHCPSearchByMacAddress (pDhcpPkt->chaddr, pDhcpPkt->hlen);
           if (pCurIP!=NULL) // then mac address found in table
           {
                ZeroAllocTime(pCurIP);
                ZeroRenewTime(pCurIP);
                LOG (5, "item %s released", haddrtoa(pDhcpPkt->chaddr, pDhcpPkt->hlen,':') );
           }
           break;
       } // switch type


DHCPScan();

// answer only to BootP, Request or discover msg
return  (nDhcpType==0 || nDhcpType==DHCPDISCOVER || nDhcpType==DHCPREQUEST);
} // ProcessDHCPMessage
예제 #2
0
static int ProcessMsg (SOCKET s, const struct S_ConsoleMsg *pmsg)
{
struct LL_TftpInfo *pTftp;
int                 uServices;

LogToMonitor ("TFTPd console receive msg %d\n", pmsg->type);
    switch (pmsg->type)
    {
        case C_CONS_KILL_TRF :
            LOG (1, "transfer %d must be killed", pmsg->u.kill.dwTransferId);
            for ( pTftp=pTftpFirst ; 
                  pTftp!=NULL && pTftp->tm.dwTransferId != pmsg->u.kill.dwTransferId ;
                  pTftp = pTftp->next );
			if (pTftp != NULL) { nak (pTftp, ECANCELLED); pTftp->st.ret_code=TFTP_TRF_STOPPED; }
            break;
            
        case C_TFTP_TERMINATE :
LogToMonitor ("terminating TFTP service\n");
            tThreads[TH_TFTP].gRunning = FALSE;
            WakeUpThread (TH_TFTP);
            break;
        
        case C_DHCP_TERMINATE :
LogToMonitor ("terminating DHCP service\n");
            tThreads[TH_DHCP].gRunning = FALSE;
            // wake up DHCP thread
	        WakeUpThread (TH_DHCP);
            break;
            
        case C_TERMINATE :
LogToMonitor ("stopping services\n");
            TerminateWorkerThreads (FALSE); // keep management threads
            break;  

        case C_SUSPEND :
LogToMonitor ("suspending services\n");
            TerminateWorkerThreads (TRUE); // keep management threads
            break;            
            
        case C_START :
LogToMonitor ("starting services\n");
			StartMultiWorkerThreads (TRUE);
            break;            
            
        case C_DHCP_RRQ_SETTINGS :
LogToMonitor ("sending DHCP settings\n");
            SendMsg (s, C_DHCP_RPLY_SETTINGS, & sParamDHCP, sizeof sParamDHCP);
            break;
            
        case C_TFTP_RRQ_SETTINGS :
LogToMonitor ("sending TFTP settings\n");
            SendMsg (s, C_TFTP_RPLY_SETTINGS, & sSettings, sizeof sSettings);
            break;
            
        case C_DHCP_WRQ_SETTINGS :
LogToMonitor ("storing new DHCP settings\n");
            DHCPSaveConfig ( & pmsg->u.dhcp_settings );
            break;
            
        case C_TFTP_WRQ_SETTINGS :
LogToMonitor ("storing new TFTP settings\n");
			{static struct S_RestartTable sRestart;
			    sRestart.newservices = pmsg->u.tftp_settings.uServices;
				sRestart.oldservices = sSettings.uServices;
				sRestart.flapservices = 0;
				if (   sSettings.Port != pmsg->u.tftp_settings.Port
		            || lstrcmp (sSettings.szTftpLocalIP, pmsg->u.tftp_settings.szTftpLocalIP )!=0 )
					sRestart.flapservices |= TFTPD32_TFTP_SERVER;
				// restart syslog if its settings log has changed
				if (     sSettings.uServices &  TFTPD32_SYSLOG_SERVER 
					  && (   sSettings.bSyslogPipe != pmsg->u.tftp_settings.bSyslogPipe
					      || strcmp(sSettings.szSyslogFile,pmsg->u.tftp_settings.szSyslogFile)!= 0 )
				   )
					 sRestart.flapservices |= TFTPD32_SYSLOG_SERVER;

            sSettings = pmsg->u.tftp_settings;

            if ( IsValidDirectory ( pmsg->u.tftp_settings.szBaseDirectory ) )
                    lstrcpyn ( sSettings.szWorkingDirectory, 
                               pmsg->u.tftp_settings.szBaseDirectory, 
                               sizeof sSettings.szWorkingDirectory );
			_beginthread ( Tftpd32UpdateServices, 0, (void *) & sRestart );            
			Tftpd32SaveSettings ();
			}
			break;

        case C_TFTP_RESTORE_DEFAULT_SETTINGS :
LogToMonitor ("restore default settings\n");
            Tftpd32DestroySettings ();
            break;
            
        case C_TFTP_CHG_WORKING_DIR :
LogToMonitor ("changing working directory to <%s>\n", pmsg->u.working_dir);
            if ( IsValidDirectory ( pmsg->u.working_dir ) )
                    lstrcpyn ( sSettings.szWorkingDirectory, 
                               pmsg->u.working_dir, 
                               sizeof sSettings.szWorkingDirectory );
            break;
        case C_RRQ_WORKING_DIR :
LogToMonitor ("sending working directory <%s>\n", sSettings.szWorkingDirectory);
            SendMsg (s, C_REPLY_WORKING_DIR, 
                     sSettings.szWorkingDirectory, 
                     1 + lstrlen (sSettings.szWorkingDirectory) );
            break;
        
        case C_DELETE_ASSIGNATION :
LogToMonitor ("deleting DHCP entry %X\n", pmsg->u.del_lease.ip);
            { struct in_addr  addr;
              BOOL   dummy;
                addr.s_addr = pmsg->u.del_lease.ip;
                DHCPDestroyItem ( DHCPSearchByIP ( & addr, &dummy  ) );
            }
            break;

		case C_RRQ_GET_SERVICES :
LogToMonitor ("sending running services\n");
			uServices = GetRunningThreads ();
            SendMsg (s, 
				     C_REPLY_GET_SERVICES, 
					 & uServices,
					 sizeof uServices );
            break;

		case C_RRQ_GET_INTERFACES :
LogToMonitor ("sending IP interfaces");
			AnswerIPList ();
			break;

        case C_RRQ_DIRECTORY_CONTENT :
LogToMonitor ("sending Directory content");
            SendDirectoryContent ();
            break;

        case C_TFTP_GET_FULL_STAT :
LogToMonitor ("sending Directory content");
            ConsoleTftpGetStatistics ();
            break;

		default :
LogToMonitor ("Service received unknown message %d\n", pmsg->type);
            break;

    }   
return 1;    
} // ReadMsg
예제 #3
0
파일: bootpd.c 프로젝트: madnessw/thesnow
struct LL_IP *DHCP_IPAllocate2(struct in_addr *pPreviousAddr, const unsigned char *pMac, int nMacLen)
{
time_t  tNow;
int     Ark;
struct LL_IP *pCurIP /*, *pOldestIP*/;
#define TWO_MINUTES 120
	
//If true, the client has requested an IP address that we should try to honor
int useprev = (pPreviousAddr->s_addr != INADDR_ANY) && (AddrFitsPool(pPreviousAddr));

   // search for the previously allocated mac address
   if (nMacLen>=6) // Ethernet Mac address
   {
	   // search if mac the mac address is already known
       pCurIP = DHCPSearchByMacAddress (pMac, nMacLen);
	   if(pCurIP) 
	   {
		   //We found the previous MAC record.  If the address requested is invalid, use
		   //the address in the record.  If it is valid, erase the record, since we should
		   //give the requested address
		   if(!useprev || (pPreviousAddr->s_addr == pCurIP->dwIP.s_addr))
		   {
				LOG (12, "Reply with previously allocated : %s", inet_ntoa (pCurIP->dwIP));
				SetAllocTime(pCurIP);
				return pCurIP;
		   }
		   else //Remove the old address, and continue with the allocation logic
		   {
			   //Destroying the item takes care of the macaddr table as well.
			   DHCPDestroyItem (pCurIP);
			   pCurIP = NULL;
		   }
       } // mac address found

    } // mac address not valid


    // search if requested address can be granted
	if(useprev)
    {
		// is the address already allocated but not renewed (or expired)
		BOOL wasexpired=FALSE;
		pCurIP = DHCPSearchByIP (pPreviousAddr, &wasexpired);
		if (pCurIP!=NULL)
		{
			//Only allocate if it's to the same address, or the lease expired,
			//otherwise reset for the real allocation
			if(wasexpired || (0 == memcmp(pCurIP->sMacAddr, pMac, nMacLen)))
			{
				LOG (5, "Request for %s granted", inet_ntoa (pCurIP->dwIP));
				pCurIP = DHCPReallocItem (pCurIP, pPreviousAddr->s_addr, pMac, nMacLen);
				return pCurIP ;
			}
			else
				pCurIP = NULL;
		}
		else	//Address not allocated before, just grant it
		{
			pCurIP = DHCPReallocItem (NULL, pPreviousAddr->s_addr, pMac, nMacLen);
			LOG (12, "Reply with requested address : %s", inet_ntoa (pCurIP->dwIP));
			return pCurIP;
		} //
   } // Requested address asked

  // A new IP address should be allocated :
  // First check if the pool is large enough in order to allocate a new address
   if (sParamDHCP.nPoolSize>0   &&  nAllocatedIP < sParamDHCP.nPoolSize)
   {
    // search for an "hole" in the struct or take last elem + 1
    // if an item was allocated and the first item is the first in pool
   //Don't allocate ip addresses ending in 0 or 255
    if (nAllocatedIP>0   &&  tFirstIP[0]->dwIP.s_addr == sParamDHCP.dwAddr.s_addr)
     {
          for ( Ark=1 ;
                Ark<nAllocatedIP
               &&  ntohl (tFirstIP[Ark]->dwIP.s_addr) == AddrInc(tFirstIP[Ark-1]->dwIP);
               Ark ++ );
           pCurIP = DHCPReallocItem (NULL, htonl (AddrInc(tFirstIP[Ark-1]->dwIP)), pMac, nMacLen);
       }
      else   pCurIP = DHCPReallocItem (NULL, sParamDHCP.dwAddr.s_addr, pMac, nMacLen);
       // New address : ntohl (tFirstIP[Ark]->dwIP.s_addr) + 1
    // it is OK if Ark has reach nAllocatedIP
      LOG (12, "Reply with new : %s", inet_ntoa (pCurIP->dwIP));
    return pCurIP;
    } // new allocation

    // no free address, have to reuse an "old" one
    // try addresses which have not been acknowledged (tAllocated+2 minutes),
    // or that have expired
    //
   time (&tNow);
   for (Ark=0 ;   Ark<nAllocatedIP;   Ark++)
    {
        pCurIP = tFirstIP[Ark];
        if (    pCurIP->tAllocated+TWO_MINUTES < tNow
            &&  ((pCurIP->tRenewed==0) || (tNow > pCurIP->tRenewed + (sParamDHCP.nLease * 60))))
        {
               pCurIP = DHCPReallocItem (pCurIP, pCurIP->dwIP.s_addr, pMac, nMacLen);
             LOG (12, "Reply with reuse : %s", inet_ntoa (pCurIP->dwIP));
                return pCurIP;
        }

    } // reuse an unacknowledged address

/* Since we are replacing holes, unacked, and expired addresses, all addresses are currently used
   // search for the oldest one (use tAllocated and tRenewed)
   for (Ark=0, pOldestIP=NULL ;   Ark<nAllocatedIP;   Ark++)
    {
        pCurIP = tFirstIP[Ark];
        if (        pCurIP->tRenewed!=0
                &&  pCurIP->tRenewed < (unsigned) (pOldestIP==NULL ? 0xFFFFFFFF : pOldestIP->tRenewed )
                &&  PingApi (&pCurIP->dwIP, DHCP_PINGTIMEOUT, NULL)==PINGAPI_TIMEOUT
                &&  PingApi (&pCurIP->dwIP, DHCP_PINGTIMEOUT, NULL)==PINGAPI_TIMEOUT
                &&  PingApi (&pCurIP->dwIP, DHCP_PINGTIMEOUT, NULL)==PINGAPI_TIMEOUT
           )  pOldestIP=pCurIP;
    } // search for oldest item in pOldestIP
    if (pOldestIP != NULL)
    {
       pCurIP = DHCPReallocItem (pOldestIP, pOldestIP->dwIP.s_addr, pMac, nMacLen);
       LOG (12, "Reply with reuse : %s", inet_ntoa (pCurIP->dwIP));
       return pCurIP;  // can be NULL
    }
*/
return NULL;
} // DHCP_IPAllocate2