📄 dhcpc.c
字号:
*buf_ptr++=(UINT8)(localmachine.localip>>8);
*buf_ptr++=(UINT8)(localmachine.localip);
}else{
buf_ptr+=4; /* skip 4 bytes, buffer zeroed already */
}
/* yiaddr, siaddr, giaddr, skip */
buf_ptr+=12;
/* chaddr */
*buf_ptr++=localmachine.localHW[5];
*buf_ptr++=localmachine.localHW[4];
*buf_ptr++=localmachine.localHW[3];
*buf_ptr++=localmachine.localHW[2];
*buf_ptr++=localmachine.localHW[1];
*buf_ptr++=localmachine.localHW[0];
buf_ptr+=10;
/* sname and file, skip */
buf_ptr+=192;
/* options field. First magic cookie */
*buf_ptr++=99;
*buf_ptr++=130;
*buf_ptr++=83;
*buf_ptr++=99;
/* message type */
*buf_ptr++=DHCP_OPT_MSG_TYPE;
*buf_ptr++=1;
*buf_ptr++=msg_type;
/* next depends on what state we're in and message type */
switch(msg_type){
case DHCP_REQUEST:
case DHCP_DECLINE: /* sent only from REQUESTING state */
/* Requested IP address MUST NOT be sent in RENEWING and
* REBINDING states (RFC2123 page 31)
*/
if((dhcpc_state!=DHCP_STATE_RENEWING)
&&(dhcpc_state!=DHCP_STATE_REBINDING)){
*buf_ptr++=DHCP_OPT_REQUESTED_IP;
*buf_ptr++=4;
*buf_ptr++=(UINT8)(dhcpc_requested_ip>>24);
*buf_ptr++=(UINT8)(dhcpc_requested_ip>>16);
*buf_ptr++=(UINT8)(dhcpc_requested_ip>>8);
*buf_ptr++=(UINT8)(dhcpc_requested_ip);
}
/* server identifier, only when not in INIT_REBOOT state
*(RFC2131, Section 4.3.2) or RENEWING, REBINDING
* state (RFC2131 page 31)
*/
if((dhcpc_state!=DHCP_STATE_INIT_REBOOT)
&&(dhcpc_state!=DHCP_STATE_REBOOTING) /* for retransmissions */
&&(dhcpc_state!=DHCP_STATE_RENEWING)
&&(dhcpc_state!=DHCP_STATE_REBINDING)){
*buf_ptr++=DHCP_OPT_SERV_IDENT;
*buf_ptr++=4;
*buf_ptr++=(UINT8)(dhcpc_server_identifier>>24);
*buf_ptr++=(UINT8)(dhcpc_server_identifier>>16);
*buf_ptr++=(UINT8)(dhcpc_server_identifier>>8);
*buf_ptr++=(UINT8)(dhcpc_server_identifier);
}
/* go through to request parameters we're interested in, but
* only if we're not sending DECLINE message (parameter list
* MUST NOT be sent in such a message)
*/
if(msg_type==DHCP_DECLINE)
break;
case DHCP_DISCOVER:
/* parameter request list. These also MUST be transmitted
* with DHCP REQUEST message */
*buf_ptr++=DHCP_OPT_PARAM_REQUEST;
*buf_ptr++=7; /* number of parameters we're requesting */
*buf_ptr++=DHCP_OPT_SUBNET_MASK;
*buf_ptr++=DHCP_OPT_ROUTER;
*buf_ptr++=DHCP_OPT_DNS_SERVER;
*buf_ptr++=DHCP_OPT_HOST_NAME;
*buf_ptr++=DHCP_OPT_LEASE_TIME;
*buf_ptr++=DHCP_OPT_T1_VALUE;
*buf_ptr++=DHCP_OPT_T2_VALUE;
break;
default:
break;
}
/* end option */
*buf_ptr++=DHCP_OPT_END;
while(buf_ptr<(net_buf+UDP_APP_OFFSET+300))
*buf_ptr++=0x00;
/* send message. Send unicast when server's IP is available (only
* in selected states, check RFC) and allowed (also check RFCs).
* Check RFCs in any case :-)
*/
if((dhcpc_state==DHCP_STATE_BOUND)
||(dhcpc_state==DHCP_STATE_RENEWING))
return (INT8)udp_send(dhcpc_soc_handle,dhcpc_server_identifier,DHCP_SERVER_PORT,net_buf+UDP_APP_OFFSET,NETWORK_TX_BUFFER_SIZE-UDP_APP_OFFSET,buf_ptr-(net_buf+UDP_APP_OFFSET));
else
return (INT8)udp_send(dhcpc_soc_handle,IP_BROADCAST_ADDRESS,DHCP_SERVER_PORT,net_buf+UDP_APP_OFFSET,NETWORK_TX_BUFFER_SIZE-UDP_APP_OFFSET,buf_ptr-(net_buf+UDP_APP_OFFSET));
}
/** \brief Processes received parameter from DHCP server
* \author
* \li Vladan Jovanovic (vladan.jovanovic@violasystems.com)
* \date 23.05.2003
* \param n Number of bytes to read&process.
* \return Returns last for 4 bytes that were read as a 32-bit variable
*
* This is internal function that get's invoked to read a received
* parameter in DHCP message. Introduced to optimize code a little
* as 4 byte parameters are often returned by DHCP server (netmask,
* gateway, server identifier, T1, T2, lease expiration time, DNS IP,..)
*/
UINT32 dhcpc_read_n_bytes(UINT8 n){
UINT32 ret_value=0;
/* read n bytes and return value of last of them (max 4, can be less)*/
while(n--){
ret_value=(ret_value<<8)|RECEIVE_NETWORK_B();
}
return ret_value;
}
/** \brief DHCP event listener, parses all DHCP replies
* \author
* \li Vladan Jovanovic (vladan.jovanovic@violasystems.com)
* \date 23.05.2003
*
* This is internal function invoked by OpenTCP UDP module when
* DHCP reply on a given UDP port is received. This function parses
* the response, checks for correctnes and performs certain actions
* based on the current state of DHCP client.
*/
INT32 dhcpc_eventlistener(INT8 cbhandle, UINT8 event, UINT32 ipaddr, UINT16 port, UINT16 buffindex, UINT16 datalen)
{
UINT32 temp;
UINT32 yiaddr; /* assigned IP */
UINT8 i;
UINT8 msg_type=0;
buffindex =0;
port =0;
if(cbhandle!=dhcpc_soc_handle){
DEBUGOUT("DHCP Client: Not my handle!!!!\r\n");
return (-1);
}
switch(event){
case UDP_EVENT_DATA:
DEBUGOUT("DHCP Client: Received data....");
/* initial correctness checking */
if(datalen<236){
DEBUGOUT("length not OK, dumping packet\r\n");
return (-1);
}
/* op */
if(RECEIVE_NETWORK_B()!=BOOT_REPLY){
DEBUGOUT("op not BOOT_REPLY, dumping packet\r\n");
return (-1);
}
/* skip htype, hlen, hops */
(void)RECEIVE_NETWORK_B();
(void)RECEIVE_NETWORK_B();
(void)RECEIVE_NETWORK_B();
/* check xid */
temp=0;
temp|=((UINT32)RECEIVE_NETWORK_B())<<24;
temp|=((UINT32)RECEIVE_NETWORK_B())<<16;
temp|=((UINT32)RECEIVE_NETWORK_B())<<8;
temp|=RECEIVE_NETWORK_B();
if(temp!=0xAABBCCDD){
DEBUGOUT("xid not OK, dumping packet\r\n");
return (-1);
}
/* skip secs, flags, ciaddr and find yiaddr*/
for(i=0;i<12;i++)
yiaddr=(yiaddr<<8)|RECEIVE_NETWORK_B();
/* skip siaddr, giaddr, chaddr, sname, file.
* We get all the info we need from options.
*/
for(i=0;i<216;i++)
RECEIVE_NETWORK_B();
/* check magic cookie */
temp=0;
temp|=((UINT32)RECEIVE_NETWORK_B())<<24;
temp|=((UINT32)RECEIVE_NETWORK_B())<<16;
temp|=((UINT32)RECEIVE_NETWORK_B())<<8;
temp|=RECEIVE_NETWORK_B();
if(temp!=0x63825363){
DEBUGOUT("magic cookie not OK, dumping packet\r\n");
return (-1);
}
DEBUGOUT("initial check OK, proceeding...\r\n");
/* process further received message, depends on state we're in */
switch(dhcpc_state){
case DHCP_STATE_SELECTING:
/* select first DHCPOFFER */
dhcpc_server_identifier=0;
DEBUGOUT("DHCP Client state=SELECTING; ");
/* iterate through parameters and try to find if
* this really is DHCPOFFER. Besides that, we're
* only interested in SERVERIDENTIFIER option (which
* is actually server's IP address)
*/
while((i=RECEIVE_NETWORK_B())!=DHCP_OPT_END){
/* there are still options to process*/
switch(i){
case DHCP_OPT_MSG_TYPE:
RECEIVE_NETWORK_B();
msg_type=RECEIVE_NETWORK_B();
break;
case DHCP_OPT_SERV_IDENT:
RECEIVE_NETWORK_B();
/* Read SERVER IDENTIFIER */
dhcpc_server_identifier|=((UINT32)RECEIVE_NETWORK_B())<<24;
dhcpc_server_identifier|=((UINT32)RECEIVE_NETWORK_B())<<16;
dhcpc_server_identifier|=((UINT32)RECEIVE_NETWORK_B())<<8;
dhcpc_server_identifier|=RECEIVE_NETWORK_B();
break;
case DHCP_OPT_OVERLOAD:
/* we can't process overloaded messages */
DEBUGOUT("Overloaded DHCP message, can't process...\r\n");
return (-1);
break;
default:
/* not interesting parameter for now */
if(i==DHCP_OPT_PAD)
break;
i=RECEIVE_NETWORK_B(); /* parameter length */
while(i--){
(void)RECEIVE_NETWORK_B();
}
break;
}
}
/* ok, processed all, got what we were looking for ? */
if((!dhcpc_server_identifier)||(msg_type!=DHCP_OFFER)){
DEBUGOUT(" Not a DHCP offer or no server identifier; Aborting...\r\n");
return(-1);
}
DEBUGOUT(" DHCP offer valid, sending DHCP REQUEST; State SELECTING-->REQUESTING\r\n");
/* we have the offer, contact the server! */
dhcpc_state=DHCP_STATE_REQUESTING;
dhcpc_requested_ip=yiaddr; /* offered IP ! */
(void)dhcpc_send_message(DHCP_REQUEST);
dhcpc_t1=4; /* 4 secs for first retransmission */
dhcpc_t2=8; /* next one after 8 secs */
break;
case DHCP_STATE_REQUESTING:
/* wait for DHCPACK */
DEBUGOUT("DHCP Client state=REQUESTING; ");
/* is message from the same server who sent the offer
* and assigned IP == offered IP? This will also reject
* subsequent DHCPOFFERs from slow DHCP servers.
*/
if((dhcpc_server_identifier!=ipaddr)||(yiaddr!=dhcpc_requested_ip)){
DEBUGOUT("Server or requested IP not the same, dumping..\r\n");
return (-1);
}
/* ok, go through param list and process them. We expect to get
* all the params here and that this is DHCPACK message
*/
DEBUGOUT("Received params: ");
while((i=RECEIVE_NETWORK_B())!=DHCP_OPT_END){
switch(i){
case DHCP_OPT_PAD:
break;
case DHCP_OPT_SUBNET_MASK:
temp=dhcpc_read_n_bytes(RECEIVE_NETWORK_B());
/* temp holds subnet mask, for now just show it and set params*/
localmachine.netmask=temp;
DEBUGOUT("Subnet mask;");
break;
case DHCP_OPT_ROUTER:
temp=dhcpc_read_n_bytes(RECEIVE_NETWORK_B());
/* temp holds gateway IP */
localmachine.defgw=temp;
DEBUGOUT("Gateway IP; ");
break;
case DHCP_OPT_DNS_SERVER:
temp=dhcpc_read_n_bytes(RECEIVE_NETWORK_B());
DEBUGOUT("DNS IP;");
break;
case DHCP_OPT_HOST_NAME:
/* Read host name here and store it */
i=RECEIVE_NETWORK_B(); /* length of host name */
while(i--){
/* read host name. Store this if necessary */
(void)RECEIVE_NETWORK_B();
}
DEBUGOUT("Host name; ");
break;
case DHCP_OPT_LEASE_TIME:
temp=dhcpc_read_n_bytes(RECEIVE_NETWORK_B());
/* time calculation from RFC! These values can also
* be received directly in options
*/
dhcpc_t1=(UINT32)((UINT16)(0.5)*temp);
dhcpc_t2=(UINT32)((UINT16)(0.875)*temp);
DEBUGOUT("Lease time;");
break;
case DHCP_OPT_OVERLOAD:
DEBUGOUT("Overloaded DHCP message, can't process...\r\n");
return (-1);
break;
case DHCP_OPT_MSG_TYPE:
/* if this is DHCPACK we can switch state and assume
* that the parameters are OK
*/
RECEIVE_NETWORK_B();
if(RECEIVE_NETWORK_B()==DHCP_ACK){
DEBUGOUT("DHCP_ACK Message!; State REQUESTING-->BOUND; ");
dhcpc_state=DHCP_STATE_BOUND;
/* we should actually probe the received IP with
* ARP first, but let's wait with that for
* now.....
*/
localmachine.localip=dhcpc_requested_ip;
/* dhcpc_requested_ip holds the assigned IP
* address. USE IT OR LOOSE IT!
*/
DEBUGOUT("IP address;");
}else{
DEBUGOUT("NOT DHCPACK message; dumping...\r\n");
return(-1);
}
break;
case DHCP_OPT_T1_VALUE:
DEBUGOUT("T1;");
dhcpc_t1=dhcpc_read_n_bytes(RECEIVE_NETWORK_B());
break;
case DHCP_OPT_T2_VALUE:
DEBUGOUT("T2; ");
dhcpc_t2=dhcpc_read_n_bytes(RECEIVE_NETWORK_B());
break;
default:
dhcpc_read_n_bytes(RECEIVE_NETWORK_B());
break;
}
}
DEBUGOUT("\r\n");
break;
case DHCP_STATE_RENEWING:
case DHCP_STATE_REBINDING:
case DHCP_STATE_REBOOTING:
/* wait for DHCPACK. If we get DHCPNAK restart. Here
* we're only interested in ACK and T1 and T2 parameters.
* NOTE: other parameters can change as well during time(
* DNS, gateway etc. Add cases similar to those in
* REQUESTING state here as well if you want those.
*/
DEBUGOUT("DHCP Client state=REQUESTING or REBINDING; ");
while((i=RECEIVE_NETWORK_B())!=DHCP_OPT_END){
switch(i){
case DHCP_OPT_PAD:
break;
case DHCP_OPT_LEASE_TIME:
DEBUGOUT("Lease time; ");
temp=dhcpc_read_n_bytes(RECEIVE_NETWORK_B());
/* time calculation from RFC! These values can also
* be received directly in options
*/
dhcpc_t1=(UINT32)((UINT16)(0.5)*temp);
dhcpc_t2=(UINT32)((UINT16)(0.875)*temp);
break;
case DHCP_OPT_MSG_TYPE:
RECEIVE_NETWORK_B();
i=RECEIVE_NETWORK_B();
if(i==DHCP_NAK){
DEBUGOUT("DHCP_NAK received; State --> INIT\r\n");
dhcpc_state=DHCP_STATE_INIT;
localmachine.localip=0;
return(-1);
}
if(i==DHCP_ACK){
DEBUGOUT("DHCP_ACK received; State --> BOUND\r\n");
dhcpc_state=DHCP_STATE_BOUND;
}
break;
case DHCP_OPT_T1_VALUE:
DEBUGOUT("T1; ");
dhcpc_t1=dhcpc_read_n_bytes(RECEIVE_NETWORK_B());
break;
case DHCP_OPT_T2_VALUE:
DEBUGOUT("T2; ");
dhcpc_t2=dhcpc_read_n_bytes(RECEIVE_NETWORK_B());
break;
default:
dhcpc_read_n_bytes(RECEIVE_NETWORK_B());
break;
}
}
break;
default:
/* dump frames when in all other states */
break;
}
break;
default:
/* should never get here */
DEBUGOUT("DHCP Client: Unknown UDP event :-( \r\n");
break;
}
return 1;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -