⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dhcp.c

📁 ATmega103、ATmega128做的开发板web server源码
💻 C
📖 第 1 页 / 共 2 页
字号:
          
      case REBINDING:
      
        if (dhcpStatus.minEvent)                         //only run if min has changed
        {
          sendDHCPREQUEST();
          dhcpStatus.minEvent=0; 
        }
        if (readUDP(68,&dhcpBuffer))                     //check for new data on port 68
        {
          if ( msg_data == DHCPACK && checkXID())
          {
           
            /*start using ip address assigned by dhcpserver*/
            ID.IP0=TOINT(dhcpBuffer.data[DHCP_FIELD_YIADDR],dhcpBuffer.data[DHCP_FIELD_YIADDR+1]);
            ID.IP1=TOINT(dhcpBuffer.data[DHCP_FIELD_YIADDR+2],dhcpBuffer.data[DHCP_FIELD_YIADDR+3]);
          
            /*write leased ip address to EEPROM */
            EEputInt(DHCP_EEADDRESS,ID.IP0);
            EEputInt(DHCP_EEADDRESS+2,ID.IP1);
            
            /* read server identifier option */
	        dhcpStatus.sId0 = TOINT(pdata[2],pdata[3]);
            dhcpStatus.sId1 = TOINT(pdata[4],pdata[5]);
                          
            dhcpMAC(dhcpStatus.sId0,dhcpStatus.sId1);   //dhcpserver (ip,mac) is stored permanently in ARP-table
            calcT1();
            dhcpStatus.min=0;
            dhcpState=BOUND; 
          }
          else if (msg_data == DHCPNAK && checkXID())
          {
            dhcpState=INIT;
            break;
          }
        }
        if (dhcpStatus.min>=dhcpStatus.nextEvent)        //leasetime expired, go to state INIT
        {
          dhcpStatus.min=0;
          dhcpState=INIT;                               
        }  
		break;

            
      case BOUND:
      
        if (dhcpStatus.min>=dhcpStatus.nextEvent)        //T1 has occured, enter state RENEWING
        {
          dhcpStatus.nextEvent=(unsigned int) dhcpStatus.nextEvent*DHCP_T2;
          dhcpStatus.min=0;
          dhcpState=RENEWING;
        }
        break;
    }
  }
}

/*called on every timer0 interrupt*/
void checkDHCP(void)
{
  dhcpStatus.cnt++;                                      
  
  /*if arpWait is set, retransmition of dhcprequest id required*/
  if (dhcpStatus.arpWait)                             
  {
    dhcpStatus.arpWait=0;
    sendDHCPREQUEST();   
  }
  
  if (dhcpStatus.cnt>DHCP_MINUTE)                 //when one minute is reached, increment min and set minEvent
  {
    dhcpStatus.cnt=0;
    dhcpStatus.min++;
    dhcpStatus.minEvent=1;
  }
}

/* Waits for timout or UDP datagram on port 68, returns 1 if data, 0 if timeout */
unsigned char wait(unsigned char time)
{  
  if (time>3)
  {
    time=3;
  }
  
  TCCR1B|=(1<<CTC1 | 1<<CS12 | 1<<CS10);          //clear counter on compare match, clock divided by 1024
  OCR1A=(time*21845)-1;                           //wait time is a multiple of 21845/(clkfreq/1024) sec 
  TIFR|=(1<<OCF1A);                               //output compare flag 1A is cleared by writing a logic one
  TCNT1=0;                                        //clear the counter
  
  for (;;)
  {
    if (readUDP(68,&dhcpBuffer))                   //poll UDP buffer, port 68
    {
      return 1;
    }
    else if (TIFR&(1<<OCF1A))                      //output compare flag 1A is set, timeout
    {
      return 0;
    }     
  }
}

/*sends a discover message */
void sendDHCPDISCOVER(void)
{
//  unsigned char pos=4;
  unsigned char *pdata;
  
  /*generate random xid*/
  dhcpStatus.XID0=rand();   
  dhcpStatus.XID1=rand();
  dhcpStatus.XID2=rand();
  dhcpStatus.XID3=rand();
  
  stdDHCPMessage();                               //consturct the std. header fields
  pdata = &dhcpBuffer.data[DHCP_FIELD_OPTIONS+4];
  *pdata++ = DHCP_OPTION_MSGTYPE;
  *pdata++ = 1;    
  *pdata++ = DHCPDISCOVER;
  *pdata++ = DHCP_OPTION_END;
  sendUDP(dhcpBuffer.data,DHCP_FIELD_OPTIONS+8,0xffff,0xffff,68,67); 
}


/*sends a request message, the message sent is depent upon the current state*/
void sendDHCPREQUEST(void)
{
//  unsigned char pos=4;                            //start writing after "magic cookie"
	unsigned char *pdata = &dhcpBuffer.data[DHCP_FIELD_CIADDR];
  stdDHCPMessage();
  
  if (dhcpState==RENEWING || dhcpState==REBINDING) //include client-id if state is RENEWING or REBINDING
  { 
    pdata[DHCP_FIELD_CIADDR]=HI(ID.IP0);
    pdata[DHCP_FIELD_CIADDR+1]=LO(ID.IP0);
    pdata[DHCP_FIELD_CIADDR+2]=HI(ID.IP1);
    pdata[DHCP_FIELD_CIADDR+3]=LO(ID.IP1);
  }
  	pdata = &dhcpBuffer.data[DHCP_FIELD_OPTIONS + 4];
  /*write options*/
  *pdata++ = DHCP_OPTION_MSGTYPE;
  *pdata++ = 1;    
  *pdata++ = DHCPREQUEST;
  
  if (dhcpState!=RENEWING && dhcpState!=REBINDING) //include requested IP in all states except RENEWING and REBINDING
  {
    *pdata++ = DHCP_OPTION_REQIP;
	*pdata++ = 4; 
    *pdata++ = HI(dhcpStatus.ip0);
    *pdata++ = LO(dhcpStatus.ip0);
    *pdata++ = HI(dhcpStatus.ip1);
    *pdata++ = LO(dhcpStatus.ip1);    
  }
  
  if (dhcpState==SELECTING)                        //include server-id if current state is SELECTING
  {
    *pdata++ = DHCP_OPTION_SERVERID;
    *pdata++ = 4; 
    *pdata++ = HI(dhcpStatus.sId0);
    *pdata++ = LO(dhcpStatus.sId0);
    *pdata++ = HI(dhcpStatus.sId1);
    *pdata++ = LO(dhcpStatus.sId1);
  }
  *pdata++ = DHCP_OPTION_END;
  
  if (dhcpState==RENEWING)                        //unicast message if state is renewing
  {
    if (!sendUDP(dhcpBuffer.data,DHCP_FIELD_OPTIONS + 17,dhcpStatus.sId0,dhcpStatus.sId1,68,67))
      {
      /*if the mac is not in the ARP table, set arpWait for later retranMaxsmition*/
      dhcpStatus.arpWait=1;                       
      }
  }
  else
  {        
	sendUDP(dhcpBuffer.data,DHCP_FIELD_OPTIONS + 17 ,0xffff,0xffff,68,67);
  }                                                
}  

/* writes standard values to message buffer */
void stdDHCPMessage(void)
{
  unsigned int * piDHCPData=(unsigned int *) dhcpBuffer.data;
  unsigned long * plDHCPData=(unsigned long *) dhcpBuffer.data;

	piDHCPData[TO_UINT(DHCP_FIELD_OP)] = 0x0101;        //bootrequest + 10MB ethernet
	piDHCPData[TO_UINT(DHCP_FIELD_HLEN)] = 0x0006;      //mac address is 6 bytes + hops
	plDHCPData[TO_UINT(DHCP_FIELD_XID)] = (*(unsigned long *)dhcpStatus.XID0);
	piDHCPData[TO_UINT(DHCP_FIELD_SECS)]=0;
	piDHCPData[TO_UINT(DHCP_FIELD_FLAGS)]=0;
	plDHCPData[TO_ULONG(DHCP_FIELD_CIADDR)]=0;
	plDHCPData[TO_ULONG(DHCP_FIELD_YIADDR)]=0;
	plDHCPData[TO_ULONG(DHCP_FIELD_SIADDR)]=0; 
	plDHCPData[TO_ULONG(DHCP_FIELD_GIADDR)]=0;
	piDHCPData[TO_UINT(DHCP_FIELD_CHADDR)] = TOINT(LO(ID.MAC0),HI(ID.MAC0));	// Swap bytes before storing to buffer
	piDHCPData[TO_UINT(DHCP_FIELD_CHADDR+2)] = TOINT(LO(ID.MAC1),HI(ID.MAC1));
	piDHCPData[TO_UINT(DHCP_FIELD_CHADDR+4)] = TOINT(LO(ID.MAC2),HI(ID.MAC2));
	piDHCPData[TO_UINT(DHCP_FIELD_OPTIONS)] = TOINT(DHCP_MAGIC_COOKIE1,DHCP_MAGIC_COOKIE0);	 // Unsigned value, ignore compiler warning
	piDHCPData[TO_UINT(DHCP_FIELD_OPTIONS+2)] = TOINT(DHCP_MAGIC_COOKIE3,DHCP_MAGIC_COOKIE2);
}
    
/*searces for an option in the received dhcp message*/
int findOption(unsigned char opt)
{
  unsigned char currentOpt=0;
  int pos=4;                        
  
  currentOpt=dhcpBuffer.data[DHCP_FIELD_OPTIONS+pos];
  while (currentOpt!=opt)
  {
    if (currentOpt==DHCP_OPTION_END)                     //if end of options, return not found (-1)
    {
      return -1; 
    }
    pos+=dhcpBuffer.data[DHCP_FIELD_OPTIONS+pos+1]+2;
    currentOpt=dhcpBuffer.data[DHCP_FIELD_OPTIONS+pos];    
  }
  return pos;
}
  
/* Returns 1 if replied XID equals requested XID, 0 otherwise */
unsigned char checkXID(void)
{	
  unsigned long data  = (*(unsigned long *)dhcpBuffer.data[DHCP_FIELD_XID]);
  unsigned long xid  = (*(unsigned long *)dhcpStatus.XID0);
  
  return (data == xid);
}

/*calculate when state RENEWING should be entered*/
void calcT1(void)
{
  unsigned int pos=findOption(DHCP_OPTION_LEASETIME);
  unsigned long temp  = SwapEndian(*(unsigned long *)dhcpBuffer.data[DHCP_FIELD_OPTIONS+pos+2]);

  temp=(temp*DHCP_T1)/60;
  
  if (temp>0xffff)
  {
    dhcpStatus.nextEvent=0xffff;
  }
  else
  {
    dhcpStatus.nextEvent=(unsigned int) temp;           //next event, state transmition from BOUND to RENEWING, in minutes  
  }
}   

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -