Exemplo n.º 1
0
/*
 * Process BOOTREPLY packet.
 */
static void
handle_reply(void)
{
	struct bootp *bp = (struct bootp *) pktbuf;
	struct ifreq *ifr;
	struct sockaddr_in *sip;
	u_char canon_haddr[MAXHADDRLEN];
	unsigned char *ha;
	int len;

	if (debug) {
		report(LOG_INFO, "   reply for %s",
			   inet_ntoa(bp->bp_yiaddr));
	}
	/* Make sure client is directly accessible. */
	ifr = getif(s, &(bp->bp_yiaddr));
	if (!ifr) {
		report(LOG_NOTICE, "no interface for reply to %s",
			   inet_ntoa(bp->bp_yiaddr));
		return;
	}
#if 1	/* Experimental (see BUG above) */
/* #ifdef CATER_TO_OLD_CLIENTS ? */
	/*
	 * The giaddr field has been set to our "default" IP address
	 * which might not be on the same interface as the client.
	 * In case the client looks at giaddr, (which it should not)
	 * giaddr is now set to the address of the correct interface.
	 */
	sip = (struct sockaddr_in *) &(ifr->ifr_addr);
	bp->bp_giaddr = sip->sin_addr;
#endif

	/* Set up socket address for send to client. */
	clnt_addr.sin_family = AF_INET;
	clnt_addr.sin_addr = bp->bp_yiaddr;
	clnt_addr.sin_port = htons(bootpc_port);

	/* Create an ARP cache entry for the client. */
	ha = bp->bp_chaddr;
	len = bp->bp_hlen;
	if (len > MAXHADDRLEN)
		len = MAXHADDRLEN;
	if (bp->bp_htype == HTYPE_IEEE802) {
		haddr_conv802(ha, canon_haddr, len);
		ha = canon_haddr;
	}
	if (debug > 1)
		report(LOG_INFO, "setarp %s - %s",
			   inet_ntoa(bp->bp_yiaddr), haddrtoa(ha, len));
	setarp(s, &bp->bp_yiaddr, ha, len);

	/* Send reply with same size packet as request used. */
	if (sendto(s, pktbuf, pktlen, 0,
			   (struct sockaddr *) &clnt_addr,
			   sizeof(clnt_addr)) < 0)
	{
		report(LOG_ERR, "sendto: %s", get_network_errmsg());
	}
}
Exemplo n.º 2
0
//Completely renumbers and rewrites the lease list from current membory.  
void ReorderLeases()
{
   int i;
   AsyncSaveKey (TFTPD32_DHCP_KEY, 
				 KEY_LEASE_NUMLEASES, 
				 & nAllocatedIP, 
				 sizeof(nAllocatedIP), 
				 REG_DWORD, 
				 szTftpd32IniFile);

   for(i = 0; i < nAllocatedIP; ++i)
   {
      char key [_MAX_PATH];
      char* macaddr = haddrtoa(tFirstIP[i]->sMacAddr, 6, ':');
      char* addr = inet_ntoa(tFirstIP[i]->dwIP);
      char* alloc = timetoa(tFirstIP[i]->tAllocated);
      char* renew = timetoa(tFirstIP[i]->tRenewed);

      tFirstIP[i]->dwAllocNum = i;
      if (sSettings.bPersLeases)
	  {
		sprintf(key, "%s%d%s", KEY_LEASE_PREFIX, i, KEY_LEASE_MAC);
		SaveKey(TFTPD32_DHCP_KEY, key, macaddr, strlen(macaddr) + 1, REG_SZ, szTftpd32IniFile);
		  sprintf(key, "%s%d%s", KEY_LEASE_PREFIX, i, KEY_LEASE_IP);
		  SaveKey(TFTPD32_DHCP_KEY, key, addr, strlen(addr) + 1, REG_SZ, szTftpd32IniFile);
		  sprintf(key, "%s%d%s", KEY_LEASE_PREFIX, i, KEY_LEASE_ALLOC);
		  SaveKey(TFTPD32_DHCP_KEY, key, alloc, strlen(alloc) + 1, REG_SZ, szTftpd32IniFile);
		  sprintf(key, "%s%d%s", KEY_LEASE_PREFIX, i, KEY_LEASE_RENEW);
         AsyncSaveKey(TFTPD32_DHCP_KEY, key, renew, strlen(renew) + 1, REG_SZ, szTftpd32IniFile);
	  }
   }
}
Exemplo n.º 3
0
//Set the MAC address to all zeros
void ZeroMacAddr(struct LL_IP* pCur)
{
   char key [_MAX_PATH];
   char* macaddr;
   sprintf(key, "%s%d%s", KEY_LEASE_PREFIX, pCur->dwAllocNum, KEY_LEASE_MAC);

   memset(pCur->sMacAddr, 0, sizeof pCur->sMacAddr);
   macaddr = haddrtoa(pCur->sMacAddr, 6, ':');
   if (sSettings.bPersLeases)
      AsyncSaveKey(TFTPD32_DHCP_KEY, key, macaddr, strlen(macaddr), REG_SZ, szTftpd32IniFile);
}
Exemplo n.º 4
0
// DHCP Scan
// for debugging puropses only
void DHCPScan (void)
{
int  Ark;
time_t tNow;
 time (&tNow);
      for (Ark = 0 ;   Ark<nAllocatedIP  ;  Ark++ )
       LOG (15, "Item %d: IP %s, Mac %s, Age %d sec, %s",
               Ark,
               inet_ntoa (tFirstIP[Ark]->dwIP),
               haddrtoa(tFirstIP[Ark]->sMacAddr, 6,':'),
               tNow - tFirstIP[Ark]->tAllocated,
               tFirstIP[Ark]->tRenewed ? "Ack" : "Nak" );
} // DHCPScan
Exemplo n.º 5
0
// Assignation by MAC Address
DWORD DHCP_StaticAssignation (struct dhcp_packet *pPkt)
{
char          szIP[20];

return ( pPkt->htype==HTYPE_ETHER || pPkt->htype==HTYPE_IEEE802 )
        && pPkt->hlen==6
        && ReadKey ( TFTPD32_DHCP_KEY, 
                     haddrtoa(pPkt->chaddr, pPkt->hlen,':'), 
                     szIP, sizeof szIP, 
                     REG_SZ, 
                     szTftpd32IniFile )
        ?  inet_addr (szIP) : INADDR_NONE;

} // DHCP_StaticAssignation
Exemplo n.º 6
0
///////////////////////////////////////////
//  translation
///////////////////////////////////////////
// translate $IP$ and $MAC$ keywords
char *TranslateExp (const char *exp, char *to, struct in_addr ip, const char *tMac)
{
char *q;
int  Ark;
char sz [256];		// somewhat larger that DHCP_FILE_LEN (128 bytes)

	// truncate input
	Ark = strnlen ( to, DHCP_FILE_LEN -1 );  	to [Ark] = 0;

// LOG (1, "bootp file fmt is <%s>\n", exp);
// LOG (1, "rqst file is <%s>\n", to);
// LOG (1, "IP <%s>\n", inet_ntoa (ip));
// LOG (1, "MAC is <%s>\n", haddrtoa (tMac, 6, '.'));


    if ( (q=strstr (exp, "$IP$")) != NULL )
    {
       lstrcpyn (sz, exp, 1 + q - exp);
       lstrcat (sz, inet_ntoa (ip) );
       lstrcat (sz, q + sizeof "$IP$" - 1);
       lstrcpyn (to, sz, DHCP_FILE_LEN - 1);
    }
    else if ( (q=strstr (exp, "$MAC$")) != NULL )
    {
       lstrcpyn (sz, exp, 1 + q - exp);
       lstrcat (sz, haddrtoa (tMac, 6, '.') );
       lstrcat (sz, q + sizeof "$MAC$" - 1);
       lstrcpyn (to, sz, DHCP_FILE_LEN - 1);
    }
    else if ( (q=strstr (exp, "$BootFileName$")) != NULL )
    {
	   lstrcpyn (sz, exp, 1 + q - exp);
	   lstrcat (sz, to);
       lstrcat (sz, q + sizeof "$BootFileName$" - 1);
	   // replace to now
       lstrcpyn (to, sz, DHCP_FILE_LEN - 1);
    }
    else lstrcpyn (to, exp, DHCP_FILE_LEN - 1);

    // truncate 
    to [DHCP_FILE_LEN-1]=0;
return to;
} // TranslateExp 
Exemplo n.º 7
0
// frees an item (may crash if allocation in progess)
void DHCPDestroyItem (struct LL_IP *pCur)
{
	if (pCur!=NULL)
	{
		LOG (5, "Freeing item %s %s", 
							 inet_ntoa (pCur->dwIP),
							 haddrtoa  (pCur->sMacAddr, 6,':') ) ;
		// put item at the end of the list and resort array
		SetIP(pCur, INADDR_NONE);   // will be the last item
		memset(pCur->sMacAddr, 0, 6);
		qsort (tFirstIP, nAllocatedIP, sizeof *tFirstIP, QsortCompare);
		qsort (tMAC, nAllocatedIP, sizeof *tMAC, MACCompare);
		DecNumAllocated(); 
		ReorderLeases();
		free ( tFirstIP[nAllocatedIP] ); // free the last item
	}
 // wake up DHCP thread --> actualizes GUI with SendLeases
    WakeUpThread (TH_DHCP);
} // DHCPDestroyItem
Exemplo n.º 8
0
// Search in configuration file/registry by Mac Address
struct LL_IP *DHCPSearchByRegistry (const unsigned char *pMac, int nMacLen)
{
int           Rc;
HKEY          hKey;
char          szIP[20];
DWORD dwSize;

   if (nMacLen!=6) return NULL; // work only for Ethernet and Token Ring
   szIP[0] = 0;

   Rc = RegOpenKeyEx (HKEY_LOCAL_MACHINE,    // Key handle at root level.
                      TFTPD32_DHCP_KEY,      // Path name of child key.
                      0,                        // Reserved.
                      KEY_READ,                // Requesting read access.
                    & hKey) == ERROR_SUCCESS;                    // Address of key to be returned.
   
   if (Rc)  READKEY (haddrtoa(pMac, nMacLen), szIP);
   CloseHandle (hKey);

   if (isdigit (szIP[0]))    // entry has been found
        return DHCPReallocItem (NULL, inet_addr (szIP), pMac, nMacLen);
return NULL;
} // DHCPSearchByRegistry
Exemplo n.º 9
0
/*
 * Setup the arp cache so that IP address 'ia' will be temporarily
 * bound to hardware address 'ha' of length 'len'.
 *
 * s         socket fd
 * ia        protocol address
 * hafamily  HW address family
 * halen     HW address data
 */
void
setarp(int s, struct in_addr *ia, int hafamily, u_char *haddr, int halen)
{
#ifdef	SIOCSARP
#ifdef	WIN_TCP
	/* This is an SVR4 with different networking code from
	 * Wollongong WIN-TCP.  Not quite like the Lachman code.
	 * Code from: [email protected] (Andrew B. Sudell)
	 */
#undef	SIOCSARP
#define	SIOCSARP ARP_ADD
	struct arptab arpreq;		/* Arp table entry */

	bzero((caddr_t) &arpreq, sizeof(arpreq));
	arpreq.at_flags = ATF_COM;

	/* Set up IP address */
	arpreq.at_in = ia->s_addr;

	/* Set up Hardware Address */
	bcopy(haddr, arpreq.at_enaddr, halen);

	/* Set the Date Link type. */
	/* XXX - Translate (hafamily) to dltype somehow? */
	arpreq.at_dltype = DL_ETHER;

#else	/* WIN_TCP */
	/* Good old Berkeley way. */
	struct arpreq arpreq;		/* Arp request ioctl block */
	struct sockaddr_in *si;
	char *p;

	bzero((caddr_t) &arpreq, sizeof(arpreq));
	arpreq.arp_flags = ATF_INUSE | ATF_COM;

	/* Set up the protocol address. */
	arpreq.arp_pa.sa_family = AF_INET;
	si = (struct sockaddr_in *) &arpreq.arp_pa;
	si->sin_addr = *ia;

	/* Set up the hardware address. */
#ifdef	__linux__	/* XXX - Do others need this? -gwr */
	/*
	 * Linux requires the sa_family field set.
	 * [email protected] (Al Longyear)
	 */
	arpreq.arp_ha.sa_family = hafamily;
#endif	/* linux */

	/* This variable is just to help catch type mismatches. */
	p = arpreq.arp_ha.sa_data;
	bcopy(haddr, p, halen);
#endif	/* WIN_TCP */

#ifdef	SVR4
	/*
	 * And now the stuff for System V Rel 4.x which does not
	 * appear to allow SIOCxxx ioctls on a socket descriptor.
	 * Thanks to several people: (all sent the same fix)
	 *   Barney Wolff <*****@*****.**>,
	 *   [email protected] (Bj|rn Sj|holm),
	 *   Michael Kuschke <*****@*****.**>,
	 */
	{
		int fd;
		struct strioctl iocb;

		if ((fd=open("/dev/arp", O_RDWR)) < 0) {
			report(LOG_ERR, "open /dev/arp: %s\n", get_errmsg());
		}
		iocb.ic_cmd = SIOCSARP;
		iocb.ic_timout = 0;
		iocb.ic_dp = (char *)&arpreq;
		iocb.ic_len = sizeof(arpreq);
		if (ioctl(fd, I_STR, (caddr_t)&iocb) < 0) {
			report(LOG_ERR, "ioctl I_STR: %s\n", get_errmsg());
		}
		close (fd);
	}
#else	/* SVR4 */
	/*
	 * On SunOS, the ioctl sometimes returns ENXIO, and it
	 * appears to happen when the ARP cache entry you tried
	 * to add is already in the cache.  (Sigh...)
	 * XXX - Should this error simply be ignored? -gwr
	 */
	if (ioctl(s, SIOCSARP, (caddr_t) &arpreq) < 0) {
		report(LOG_ERR, "ioctl SIOCSARP: %s", get_errmsg());
	}
#endif	/* SVR4 */
#else	/* SIOCSARP */
#if defined(BSD) && (BSD >= 199306)
	bsd_arp_set(ia, haddr, halen);
#else
	/*
	 * Oh well, SIOCSARP is not defined.  Just run arp(8).
	 * Need to delete partial entry first on some systems.
	 * XXX - Gag!
	 */
	int status;
	char buf[256];
	char *a;
	extern char *inet_ntoa();

	a = inet_ntoa(*ia);
	snprintf(buf, sizeof(buf), "arp -d %s; arp -s %s %s temp",
			a, a, haddrtoa(haddr, halen));
	if (debug > 2)
		report(LOG_INFO, "%s", buf);
	status = system(buf);
	if (status)
		report(LOG_ERR, "arp failed, exit code=0x%x", status);
	return;
#endif	/* ! 4.4 BSD */
#endif	/* SIOCSARP */
}
Exemplo n.º 10
0
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