Main Page   Modules   Data Structures   File List   Data Fields   Globals   Related Pages   Examples  

/opentcp/dhcp/dhcpc.c

Go to the documentation of this file.
00001 /*
00002  *Copyright (c) 2000-2002 Viola Systems Ltd.
00003  *All rights reserved.
00004  *
00005  *Redistribution and use in source and binary forms, with or without 
00006  *modification, are permitted provided that the following conditions 
00007  *are met:
00008  *
00009  *1. Redistributions of source code must retain the above copyright 
00010  *notice, this list of conditions and the following disclaimer.
00011  *
00012  *2. Redistributions in binary form must reproduce the above copyright 
00013  *notice, this list of conditions and the following disclaimer in the 
00014  *documentation and/or other materials provided with the distribution.
00015  *
00016  *3. The end-user documentation included with the redistribution, if 
00017  *any, must include the following acknowledgment:
00018  *      "This product includes software developed by Viola 
00019  *      Systems (http://www.violasystems.com/)."
00020  *
00021  *Alternately, this acknowledgment may appear in the software itself, 
00022  *if and wherever such third-party acknowledgments normally appear.
00023  *
00024  *4. The names "OpenTCP" and "Viola Systems" must not be used to 
00025  *endorse or promote products derived from this software without prior 
00026  *written permission. For written permission, please contact 
00027  *opentcp@opentcp.org.
00028  *
00029  *5. Products derived from this software may not be called "OpenTCP", 
00030  *nor may "OpenTCP" appear in their name, without prior written 
00031  *permission of the Viola Systems Ltd.
00032  *
00033  *THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 
00034  *WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
00035  *MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
00036  *IN NO EVENT SHALL VIOLA SYSTEMS LTD. OR ITS CONTRIBUTORS BE LIABLE 
00037  *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
00038  *CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
00039  *SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
00040  *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
00041  *WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
00042  *OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
00043  *EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00044  *====================================================================
00045  *
00046  *OpenTCP is the unified open source TCP/IP stack available on a series 
00047  *of 8/16-bit microcontrollers, please see <http://www.opentcp.org>.
00048  *
00049  *For more information on how to network-enable your devices, or how to 
00050  *obtain commercial technical support for OpenTCP, please see 
00051  *<http://www.violasystems.com/>.
00052  */
00053 
00071 #include<inet/datatypes.h>
00072 #include<inet/debug.h>
00073 #include<inet/system.h>
00074 #include<inet/tcp_ip.h>
00075 #include<inet/timers.h>
00076 #include<inet/arp.h>
00077 #include<inet/ethernet.h>
00078 #include<inet/dhcp/dhcpc.h>
00079 
00087 UINT8 dhcpc_state;
00088 
00094 UINT8 dhcpc_timer_handle;
00095 
00100 INT8 dhcpc_soc_handle;
00101 
00106 UINT8   dhcpc_initialized=0;
00107 
00115 UINT32 dhcpc_t1;
00116 
00124 UINT32 dhcpc_t2;
00125 
00131 UINT32 dhcpc_server_identifier;
00132 
00140 UINT32 dhcpc_requested_ip;
00141 
00142 INT32 dhcpc_eventlistener(INT8 cbhandle, UINT8 event, UINT32 ipaddr, UINT16 port, UINT16 buffindex, UINT16 datalen);
00143 INT8 dhcpc_send_message(UINT8 msg_type);
00144 
00158 INT8 dhcpc_init(void)
00159 {
00160         
00161         /* If we already have some IP address (stored from some previous
00162          * requests, try obtaining it again */  
00163         if((localmachine.localip!=0)&&(localmachine.localip!=0xffffffff)){
00164                 dhcpc_state=DHCP_STATE_INIT_REBOOT;
00165         }else{
00166                 /* start from beginning */
00167                 dhcpc_state=DHCP_STATE_INIT;
00168                 }
00169         
00170         dhcpc_soc_handle=udp_getsocket(0,dhcpc_eventlistener,UDP_OPT_SEND_CS|UDP_OPT_CHECK_CS);
00171         
00172         if(dhcpc_soc_handle<0){
00173                 DEBUGOUT("DHCP client not able to obtain socket!\r\n");
00174                 return (-1);
00175         }       
00176         
00177         /* open socket for communication immediately */
00178         udp_open(dhcpc_soc_handle,DHCP_CLIENT_PORT);
00179         
00180         /* get timer handle */
00181         dhcpc_timer_handle=get_timer();
00182         
00183         /* initialize timer for 1 sec intervals */
00184         init_timer(dhcpc_timer_handle,TIMERTIC*1);      /* on every second */
00185         
00186         dhcpc_initialized=1;
00187         DEBUGOUT("DHCP Client initialized\r\n");
00188         
00189         return (0);
00190 }
00191 
00201 void dhcpc_run(void){
00202         UINT8 sec=0;
00203         
00204         if(!dhcpc_initialized)
00205                 return;
00206                 
00207         if(!check_timer(dhcpc_timer_handle))
00208                 sec=1;
00209         
00210         switch(dhcpc_state){
00211                 case DHCP_STATE_INIT_REBOOT:
00212                         dhcpc_state=DHCP_STATE_REBOOTING;
00213                         dhcpc_t1=4;     /* next retransmission in 4 secs */
00214                         dhcpc_t2=8;     /* after that after 8 secs retrs */
00215                         dhcpc_requested_ip=localmachine.localip;
00216                         dhcpc_send_message(DHCP_REQUEST);
00217                         break;
00218 
00219                 case DHCP_STATE_REBOOTING:
00220                         if(sec)
00221                                 dhcpc_t1--;
00222                         
00223                         if(!dhcpc_t1){
00224                                 if(dhcpc_t2>=32){
00225                                         /* we need to restart, we don't want to wait more
00226                                          * than 30 secs for retransmissions
00227                                          */
00228                                          dhcpc_state=DHCP_STATE_INIT_REBOOT;
00229                                 }else{
00230                                         dhcpc_t1=dhcpc_t2;
00231                                         dhcpc_t2<<=1;   /* exponential backoff retransmission */
00232                                         dhcpc_send_message(DHCP_REQUEST);
00233                                 }                       
00234                         }               
00235                         break;
00236                 case DHCP_STATE_INIT:
00237                         /* switch to selecting, send DHCPDISCOVER and initialize
00238                          * timeout timer
00239                          */
00240                         DEBUGOUT("DHCP State=INIT; Sending DHCPDISCOVER message; State INIT-->SELECTING\r\n");
00241                         dhcpc_state=DHCP_STATE_SELECTING;
00242                         dhcpc_send_message(DHCP_DISCOVER);
00243                         /* T1 will be timeout timer. T2 will hold next timeout value */
00244                         dhcpc_t1=4;     /* next retransmission after 4 secs */
00245                         dhcpc_t2=8;     /* after 4 secs expire, this will be next timeout */
00246                         break;
00247                 case DHCP_STATE_SELECTING:
00248                         /* one second expired ? */
00249                         if(sec)
00250                                 dhcpc_t1--;
00251                         
00252                         /* timeout expired without receiving DHCPOFFER ? */
00253                         if(!dhcpc_t1){
00254                                 DEBUGOUT("DHCP State=SELECTING; ");
00255                                 /* yes, retransmit or restart the process */
00256                                 if(dhcpc_t2>=32){
00257                                         /* we need to restart, we don't want to wait more
00258                                          * than 30 secs for retransmissions
00259                                          */
00260                                          dhcpc_state=DHCP_STATE_INIT;
00261                                          DEBUGOUT("Timeout for retransmissions too big; State SELECTING-->INIT\r\n");
00262                                 }else{
00263                                         DEBUGOUT("Retransmitting DHCPDISCOVER\r\n");
00264                                         dhcpc_t1=dhcpc_t2;
00265                                         dhcpc_t2<<=1;   /* exponential backoff retransmission */
00266                                         dhcpc_send_message(DHCP_DISCOVER);
00267                                 }
00268                         }
00269                         break;
00270                 case DHCP_STATE_REQUESTING:
00271                         /* DHCPREQUEST sent, waiting for proper response. Retransmit
00272                          * if necessary
00273                          */
00274                         if(sec)
00275                                 dhcpc_t1--;
00276                          
00277                         if(!dhcpc_t1){
00278                                 /* timeout occured without receiving DHCPACK */
00279                                 DEBUGOUT("DHCP State=REQUESTING; ");
00280                                 if(dhcpc_t2>=32){
00281                                         /* we need to restart, we don't want to wait more
00282                                          * than 30 secs for retransmissions. Restart whole
00283                                          * process
00284                                          */
00285                                          dhcpc_state=DHCP_STATE_INIT;
00286                                          DEBUGOUT("Timeout for retransmits too big; State REQUESTING-->INIT\r\n");
00287                                 }else{
00288                                         DEBUGOUT("Retransmitting DHCPREQUEST\r\n");
00289                                         dhcpc_t1=dhcpc_t2;
00290                                         dhcpc_t2<<=1;   /* exponential backoff retransmission */
00291                                         dhcpc_send_message(DHCP_REQUEST);
00292                                 }                               
00293                         } 
00294                         break;
00295                 case DHCP_STATE_BOUND:
00296                         /* wait for T1 to expire */
00297                         if(sec){
00298                                 dhcpc_t1--;
00299                                 dhcpc_t2--;
00300                         }
00301                         if(!dhcpc_t1){
00302                                 DEBUGOUT("DHCP State=BOUND; Starting renewing process; State BOUND-->RENEWING\r\n");
00303                                 /* T1 expired, start renewing process */
00304                                 dhcpc_state=DHCP_STATE_RENEWING;
00305                                 
00306                                 dhcpc_send_message(DHCP_REQUEST);
00307                                 
00308                                 /* T1 will be used for retransmissions untill we
00309                                  * return to BOUND state or reset to INIT state
00310                                  */
00311                                 dhcpc_t1=10;    /* fixed 10sec retransmissions */
00312                         }
00313                         break;
00314                 case DHCP_STATE_RENEWING:
00315                         if(sec){
00316                                 dhcpc_t1--;
00317                                 dhcpc_t2--;
00318                         }
00319                         
00320                         if(!dhcpc_t2){
00321                                 DEBUGOUT("DHCP State=RENEWING; T2 expired; State RENEWING-->REBINDING\r\n");
00322                                 /* oh no, T2 also expired. switch to rebinding state. This
00323                                  * is our last attempt to retain this IP address.
00324                                  */
00325                                 dhcpc_state=DHCP_STATE_REBINDING;
00326                                 
00327                                 dhcpc_send_message(DHCP_REQUEST);
00328                                 
00329                                 /* dhcpc_t1 will be used for timeouts */
00330                                 dhcpc_t1=5;     /* 5 second retransmits */
00331                                 
00332                                 /* dhcpc_t2 will be used for fixed numer of retries. This
00333                                  * is a bit different than per RFC, but we don't want 
00334                                  * another 32-bit timer value for keeping lease time.
00335                                  */
00336                                 dhcpc_t2=10;
00337                         }else
00338                                 if(!dhcpc_t1){
00339                                         DEBUGOUT("DHCP State=RENEWING; Retransmitting DHCPREQUEST\r\n");        
00340                                         /* retransmit DHCP REQUEST messages */
00341                                         dhcpc_send_message(DHCP_REQUEST);
00342                                         dhcpc_t1=10;
00343                                 }
00344                         break;
00345                 case DHCP_STATE_REBINDING:
00346                         if(sec)
00347                                 dhcpc_t1--;
00348                         
00349                         if(!dhcpc_t1){
00350                         
00351                                 dhcpc_t1=5;     /* 5 second retransmits */
00352                                 
00353                                 dhcpc_t2--;     /* retransmit count */
00354                                 
00355                                 if(!dhcpc_t2){
00356                                         DEBUGOUT("DHCP State=REBINDING; Lease time expired; State REBINDING-->INIT\r\n");
00357                                         /* used up retransmission. Assume that lease time
00358                                          * expired by now. Restart the process
00359                                          */
00360                                          dhcpc_state=DHCP_STATE_INIT;
00361                                          localmachine.localip=0;        /* can't use this any more */
00362                                 }else{
00363                                         DEBUGOUT("DHCP State=REBINDING; Retransmitting DHCPREQUEST\r\n");
00364                                         /* still have some time */
00365                                         dhcpc_send_message(DHCP_REQUEST);
00366                                 }
00367                         }
00368                         break;
00369                 default:
00370                         break;
00371         }
00372         
00373         if(sec){
00374                 init_timer(dhcpc_timer_handle,TIMERTIC*1);
00375         }
00376 }
00377 
00389 INT8 dhcpc_send_message(UINT8 msg_type)
00390 {
00391 
00392         UINT16 index;
00393         UINT8 *buf_ptr; /* transmit buffer pointer */
00394         
00395         /* first clear transmit buffer to all zeroes */
00396         for(index=UDP_APP_OFFSET;index<NETWORK_TX_BUFFER_SIZE;index++)
00397                 net_buf[index]=0;
00398                 
00399         buf_ptr=net_buf+UDP_APP_OFFSET;
00400         
00401         /* create DHCP message */
00402         
00403         *buf_ptr++=BOOT_REQUEST;
00404         *buf_ptr++=0x01;                /* htype=ethernet */
00405         *buf_ptr++=0x06;                /* hlen=6 for ethernet */
00406         *buf_ptr++=0x00;                /* hops=0 by clients */
00407         
00408         /* xid, use constant value for all requests (allowed by RFC) */
00409         *buf_ptr++=0xAA;
00410         *buf_ptr++=0xBB;
00411         *buf_ptr++=0xCC;
00412         *buf_ptr++=0xDD;
00413         
00414         /* seconds from boot. Fixed for now */
00415         *buf_ptr++=0x00;
00416         *buf_ptr++=0x00;
00417         
00418         /* flags, use broadcast */
00419         *buf_ptr++=0x80;
00420         *buf_ptr++=0x00;
00421         
00422         /* ciaddr. Sent only if client is in BOUND, RENEW or REBINDING
00423          * state (RFC2131)
00424          */
00425         if((dhcpc_state==DHCP_STATE_BOUND)
00426                 ||(dhcpc_state==DHCP_STATE_RENEWING)
00427                 ||(dhcpc_state==DHCP_STATE_REBINDING)){
00428                 *buf_ptr++=(UINT8)(localmachine.localip>>24);
00429                 *buf_ptr++=(UINT8)(localmachine.localip>>16);
00430                 *buf_ptr++=(UINT8)(localmachine.localip>>8);
00431                 *buf_ptr++=(UINT8)(localmachine.localip);               
00432         }else{
00433                 buf_ptr+=4;     /* skip 4 bytes, buffer zeroed already */
00434         }
00435         
00436         /* yiaddr, siaddr, giaddr, skip */
00437         buf_ptr+=12;
00438         
00439         /* chaddr */
00440         *buf_ptr++=localmachine.localHW[5];
00441         *buf_ptr++=localmachine.localHW[4];
00442         *buf_ptr++=localmachine.localHW[3];
00443         *buf_ptr++=localmachine.localHW[2];
00444         *buf_ptr++=localmachine.localHW[1];
00445         *buf_ptr++=localmachine.localHW[0];
00446         buf_ptr+=10;
00447         
00448         /* sname and file, skip */
00449         buf_ptr+=192;
00450         
00451         /* options field. First magic cookie */
00452         *buf_ptr++=99;
00453         *buf_ptr++=130;
00454         *buf_ptr++=83;
00455         *buf_ptr++=99;
00456 
00457         /* message type */
00458         *buf_ptr++=DHCP_OPT_MSG_TYPE;
00459         *buf_ptr++=1;
00460         *buf_ptr++=msg_type;
00461                 
00462         /* next depends on what state we're in and message type */
00463         switch(msg_type){
00464 
00465                 case DHCP_REQUEST:
00466                 case DHCP_DECLINE: /* sent only from REQUESTING state */
00467 
00468                         /* Requested IP address MUST NOT be sent in RENEWING and
00469                          * REBINDING states (RFC2123 page 31)
00470                          */
00471                         if((dhcpc_state!=DHCP_STATE_RENEWING)
00472                                 &&(dhcpc_state!=DHCP_STATE_REBINDING)){
00473                                 *buf_ptr++=DHCP_OPT_REQUESTED_IP;
00474                                 *buf_ptr++=4;
00475                                 *buf_ptr++=(UINT8)(dhcpc_requested_ip>>24);
00476                                 *buf_ptr++=(UINT8)(dhcpc_requested_ip>>16);
00477                                 *buf_ptr++=(UINT8)(dhcpc_requested_ip>>8);
00478                                 *buf_ptr++=(UINT8)(dhcpc_requested_ip);
00479                         }       
00480                         /* server identifier, only when not in INIT_REBOOT state 
00481                          *(RFC2131, Section 4.3.2) or RENEWING, REBINDING
00482                          * state (RFC2131 page 31)
00483                          */
00484                         if((dhcpc_state!=DHCP_STATE_INIT_REBOOT)
00485                                 &&(dhcpc_state!=DHCP_STATE_REBOOTING)   /* for retransmissions */                       
00486                                 &&(dhcpc_state!=DHCP_STATE_RENEWING)
00487                                 &&(dhcpc_state!=DHCP_STATE_REBINDING)){
00488                                 *buf_ptr++=DHCP_OPT_SERV_IDENT;
00489                                 *buf_ptr++=4;
00490                                 *buf_ptr++=(UINT8)(dhcpc_server_identifier>>24);
00491                                 *buf_ptr++=(UINT8)(dhcpc_server_identifier>>16);
00492                                 *buf_ptr++=(UINT8)(dhcpc_server_identifier>>8);
00493                                 *buf_ptr++=(UINT8)(dhcpc_server_identifier);
00494                         }       
00495                         /* go through to request parameters we're interested in, but
00496                          * only if we're not sending DECLINE message (parameter list
00497                          * MUST NOT be sent in such a message)
00498                          */
00499                          if(msg_type==DHCP_DECLINE)
00500                                 break;
00501                         
00502                 case DHCP_DISCOVER:             
00503                         /* parameter request list. These also MUST be transmitted
00504                          * with DHCP REQUEST message */
00505                         *buf_ptr++=DHCP_OPT_PARAM_REQUEST;
00506                         *buf_ptr++=7;   /* number of parameters we're requesting */
00507                         *buf_ptr++=DHCP_OPT_SUBNET_MASK;
00508                         *buf_ptr++=DHCP_OPT_ROUTER;
00509                         *buf_ptr++=DHCP_OPT_DNS_SERVER;
00510                         *buf_ptr++=DHCP_OPT_HOST_NAME;
00511                         *buf_ptr++=DHCP_OPT_LEASE_TIME;
00512                         *buf_ptr++=DHCP_OPT_T1_VALUE;
00513                         *buf_ptr++=DHCP_OPT_T2_VALUE;
00514                         break;                  
00515 
00516                 default:
00517                         break;
00518         }
00519         
00520         /* end option */
00521         *buf_ptr++=DHCP_OPT_END;
00522         while(buf_ptr<(net_buf+UDP_APP_OFFSET+300))
00523                 *buf_ptr++=0x00;
00524                 
00525         /* send message. Send unicast when server's IP is available (only
00526          * in selected states, check RFC) and allowed (also check RFCs).
00527          * Check RFCs in any case :-)
00528          */
00529         if((dhcpc_state==DHCP_STATE_BOUND)
00530                 ||(dhcpc_state==DHCP_STATE_RENEWING))
00531                 return 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));
00532         else
00533                 return 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));
00534 
00535 }
00536 
00549 UINT32 dhcpc_read_n_bytes(UINT8 n){
00550         UINT32 ret_value=0;
00551         /* read n bytes and return value of last of them (max 4, can be less)*/
00552         while(n--){
00553                 ret_value=(ret_value<<8)|RECEIVE_NETWORK_B();
00554         }
00555         return ret_value;
00556 }
00557 
00568 INT32 dhcpc_eventlistener(INT8 cbhandle, UINT8 event, UINT32 ipaddr, UINT16 port, UINT16 buffindex, UINT16 datalen)
00569 {
00570         UINT32 temp;
00571         UINT32 yiaddr;  /* assigned IP */
00572         UINT8 i;
00573         UINT8 msg_type=0;
00574         
00575         if(cbhandle!=dhcpc_soc_handle){
00576                 DEBUGOUT("DHCP Client: Not my handle!!!!\r\n");
00577                 return (-1);
00578         }
00579         
00580         switch(event){
00581                 case UDP_EVENT_DATA:
00582                         DEBUGOUT("DHCP Client: Received data....");
00583                         /* initial correctness checking */
00584                         if(datalen<236){
00585                                 DEBUGOUT("length not OK, dumping packet\r\n");
00586                                 return (-1);
00587                                 }
00588                         
00589                         /* op */
00590                         if(RECEIVE_NETWORK_B()!=BOOT_REPLY){
00591                                 DEBUGOUT("op not BOOT_REPLY, dumping packet\r\n");
00592                                 return (-1);
00593                                 }
00594                                 
00595                         /* skip htype, hlen, hops */
00596                         RECEIVE_NETWORK_B();
00597                         RECEIVE_NETWORK_B();
00598                         RECEIVE_NETWORK_B();
00599                         
00600                         /* check xid */
00601                         temp=0;
00602                         temp|=((UINT32)RECEIVE_NETWORK_B())<<24;
00603                         temp|=((UINT32)RECEIVE_NETWORK_B())<<16;
00604                         temp|=((UINT32)RECEIVE_NETWORK_B())<<8;
00605                         temp|=RECEIVE_NETWORK_B();
00606                         if(temp!=0xAABBCCDD){
00607                                 DEBUGOUT("xid not OK, dumping packet\r\n");
00608                                 return (-1);
00609                                 }
00610                                 
00611                         /* skip secs, flags, ciaddr and find yiaddr*/
00612                         for(i=0;i<12;i++)
00613                                 yiaddr=(yiaddr<<8)|RECEIVE_NETWORK_B();
00614                          
00615                          /* skip siaddr, giaddr, chaddr, sname, file. 
00616                           * We get all the info we need from options.
00617                           */
00618                         for(i=0;i<216;i++)
00619                                 RECEIVE_NETWORK_B();
00620                         
00621                         /* check magic cookie */
00622                         temp=0;
00623                         temp|=((UINT32)RECEIVE_NETWORK_B())<<24;
00624                         temp|=((UINT32)RECEIVE_NETWORK_B())<<16;
00625                         temp|=((UINT32)RECEIVE_NETWORK_B())<<8;
00626                         temp|=RECEIVE_NETWORK_B();
00627                         if(temp!=0x63825363){
00628                                 DEBUGOUT("magic cookie not OK, dumping packet\r\n");
00629                                 return (-1);
00630                                 }
00631                         DEBUGOUT("initial check OK, proceeding...\r\n");
00632                         /* process further received message, depends on state we're in */
00633                         switch(dhcpc_state){
00634                                 case DHCP_STATE_SELECTING:
00635                                         /* select first DHCPOFFER */
00636                                         dhcpc_server_identifier=0;
00637                                         DEBUGOUT("DHCP Client state=SELECTING; ");
00638                                         /* iterate through parameters and try to find if 
00639                                          * this really is DHCPOFFER. Besides that, we're
00640                                          * only interested in SERVERIDENTIFIER option (which
00641                                          * is actually server's IP address)
00642                                          */
00643                                         while((i=RECEIVE_NETWORK_B())!=DHCP_OPT_END){
00644                                                 /* there are still options to process*/
00645                                                 switch(i){
00646                                                         case DHCP_OPT_MSG_TYPE:
00647                                                                 RECEIVE_NETWORK_B();
00648                                                                 msg_type=RECEIVE_NETWORK_B();   
00649                                                                 break;
00650                                                         case DHCP_OPT_SERV_IDENT:
00651                                                                 RECEIVE_NETWORK_B();
00652                                                                 /* Read SERVER IDENTIFIER */
00653                                                                 dhcpc_server_identifier|=((UINT32)RECEIVE_NETWORK_B())<<24;
00654                                                                 dhcpc_server_identifier|=((UINT32)RECEIVE_NETWORK_B())<<16;
00655                                                                 dhcpc_server_identifier|=((UINT32)RECEIVE_NETWORK_B())<<8;
00656                                                                 dhcpc_server_identifier|=RECEIVE_NETWORK_B();
00657                                                                 break;
00658                                                         case DHCP_OPT_OVERLOAD:
00659                                                                 /* we can't process overloaded messages */
00660                                                                 DEBUGOUT("Overloaded DHCP message, can't process...\r\n");
00661                                                                 return (-1);
00662                                                                 break;
00663                                                         default:
00664                                                                 /* not interesting parameter for now */
00665                                                                 if(i==DHCP_OPT_PAD)
00666                                                                         break;
00667                                                                 i=RECEIVE_NETWORK_B();  /* parameter length */
00668                                                                 while(i--){
00669                                                                         RECEIVE_NETWORK_B();
00670                                                                 }
00671                                                                 break;
00672                                                 }
00673                                         }
00674                                         /* ok, processed all, got what we were looking for ? */
00675                                         if((!dhcpc_server_identifier)||(msg_type!=DHCP_OFFER)){
00676                                                 DEBUGOUT(" Not a DHCP offer or no server identifier; Aborting...\r\n");
00677                                                 return(-1);
00678                                         }
00679                                         
00680                                         DEBUGOUT(" DHCP offer valid, sending DHCP REQUEST; State SELECTING-->REQUESTING\r\n");
00681                                         /* we have the offer, contact the server! */
00682                                         dhcpc_state=DHCP_STATE_REQUESTING;
00683                                         dhcpc_requested_ip=yiaddr;      /* offered IP ! */
00684                                         
00685                                         dhcpc_send_message(DHCP_REQUEST);
00686                                         
00687                                         dhcpc_t1=4;     /* 4 secs for first retransmission */
00688                                         dhcpc_t2=8;     /* next one after 8 secs */
00689                                         break;
00690 
00691                                 case DHCP_STATE_REQUESTING:
00692                                         /* wait for DHCPACK */
00693                                         
00694                                         DEBUGOUT("DHCP Client state=REQUESTING; ");
00695 
00696                                         /* is message from the same server who sent the offer 
00697                                          * and assigned IP == offered IP? This will also reject
00698                                          * subsequent DHCPOFFERs from slow DHCP servers.
00699                                          */
00700                                         if((dhcpc_server_identifier!=ipaddr)||(yiaddr!=dhcpc_requested_ip)){
00701                                                 DEBUGOUT("Server or requested IP not the same, dumping..\r\n");
00702                                                 return (-1);
00703                                         }
00704                                         
00705                                         /* ok, go through param list and process them. We expect to get
00706                                          * all the params here and that this is DHCPACK message
00707                                          */
00708                                         DEBUGOUT("Received params: ");
00709                                         while((i=RECEIVE_NETWORK_B())!=DHCP_OPT_END){
00710                                                 
00711                                                 switch(i){
00712                                                         case DHCP_OPT_PAD:
00713                                                                 break;
00714                                                         case DHCP_OPT_SUBNET_MASK:
00715                                                                 temp=dhcpc_read_n_bytes(RECEIVE_NETWORK_B());
00716                                                                 /* temp holds subnet mask, for now just show it and set params*/
00717                                                                 localmachine.netmask=temp;
00718                                                                 DEBUGOUT("Subnet mask;");
00719                                                                 break;
00720                                                         case DHCP_OPT_ROUTER:
00721                                                                 temp=dhcpc_read_n_bytes(RECEIVE_NETWORK_B());
00722                                                                 /* temp holds gateway IP */
00723                                                                 localmachine.defgw=temp;
00724                                                                 DEBUGOUT("Gateway IP; ");
00725                                                                 break;
00726                                                         case DHCP_OPT_DNS_SERVER:
00727                                                                 temp=dhcpc_read_n_bytes(RECEIVE_NETWORK_B());
00728                                                                 DEBUGOUT("DNS IP;");
00729                                                                 break;
00730                                                         case DHCP_OPT_HOST_NAME:
00731                                                                 /* Read host name here and store it */
00732                                                                 i=RECEIVE_NETWORK_B();  /* length of host name */
00733                                                                 while(i--){
00734                                                                         /* read host name. Store this if necessary */
00735                                                                         RECEIVE_NETWORK_B();
00736                                                                 }
00737                                                                 DEBUGOUT("Host name; ");
00738                                                                 break;
00739                                                         case DHCP_OPT_LEASE_TIME:
00740                                                                 temp=dhcpc_read_n_bytes(RECEIVE_NETWORK_B());
00741                                                                 /* time calculation from RFC! These values can also
00742                                                                  * be received directly in options
00743                                                                  */
00744                                                                 dhcpc_t1=0.5*temp;
00745                                                                 dhcpc_t2=0.875*temp;
00746                                                                 DEBUGOUT("Lease time;"); 
00747                                                                 break;
00748                                                         case DHCP_OPT_OVERLOAD:
00749                                                                 DEBUGOUT("Overloaded DHCP message, can't process...\r\n");
00750                                                                 return (-1);
00751                                                                 break;
00752                                                         case DHCP_OPT_MSG_TYPE:
00753                                                                 /* if this is DHCPACK we can switch state and assume
00754                                                                  * that the parameters are OK
00755                                                                  */
00756                                                                 RECEIVE_NETWORK_B();
00757                                                                 if(RECEIVE_NETWORK_B()==DHCP_ACK){
00758                                                                         DEBUGOUT("DHCP_ACK Message!; State REQUESTING-->BOUND; ");
00759                                                                         dhcpc_state=DHCP_STATE_BOUND;
00760                                                                         
00761                                                                         /* we should actually probe the received IP with
00762                                                                          * ARP first, but let's wait with that for 
00763                                                                          * now.....
00764                                                                          */
00765                                                                         localmachine.localip=dhcpc_requested_ip;
00766                                                                         /* dhcpc_requested_ip holds the assigned IP
00767                                                                          * address. USE IT OR LOOSE IT!
00768                                                                          */
00769                                                                         DEBUGOUT("IP address;");
00770                                                                 }else{
00771                                                                         DEBUGOUT("NOT DHCPACK message; dumping...\r\n");
00772                                                                         return(-1);
00773                                                                 }       
00774                                                                 break;
00775                                                         case DHCP_OPT_T1_VALUE:
00776                                                                 DEBUGOUT("T1;");
00777                                                                 dhcpc_t1=dhcpc_read_n_bytes(RECEIVE_NETWORK_B());
00778                                                                 break;
00779                                                         case DHCP_OPT_T2_VALUE:
00780                                                                 DEBUGOUT("T2; ");
00781                                                                 dhcpc_t2=dhcpc_read_n_bytes(RECEIVE_NETWORK_B());
00782                                                                 break;
00783                                                         default:
00784                                                                 dhcpc_read_n_bytes(RECEIVE_NETWORK_B());
00785                                                                 break;
00786                                                 }
00787                                         }
00788                                         DEBUGOUT("\r\n");
00789                                         break;
00790                                 case DHCP_STATE_RENEWING:
00791                                 case DHCP_STATE_REBINDING:
00792                                 case DHCP_STATE_REBOOTING:
00793                                         /* wait for DHCPACK. If we get DHCPNAK restart. Here
00794                                          * we're only interested in ACK and T1 and T2 parameters.
00795                                          * NOTE: other parameters can change as well during time(
00796                                          * DNS, gateway etc. Add cases similar to those in
00797                                          * REQUESTING state here as well if you want those.
00798                                          */
00799                                         DEBUGOUT("DHCP Client state=REQUESTING or REBINDING; ");
00800                                         while((i=RECEIVE_NETWORK_B())!=DHCP_OPT_END){
00801                                                 switch(i){
00802                                                         case DHCP_OPT_PAD:
00803                                                                 break;
00804                                                         case DHCP_OPT_LEASE_TIME:
00805                                                                 DEBUGOUT("Lease time; ");
00806                                                                 temp=dhcpc_read_n_bytes(RECEIVE_NETWORK_B());
00807                                                                 /* time calculation from RFC! These values can also
00808                                                                  * be received directly in options
00809                                                                  */
00810                                                                 dhcpc_t1=0.5*temp;
00811                                                                 dhcpc_t2=0.875*temp; 
00812                                                                 break;                                                          
00813                                                         case DHCP_OPT_MSG_TYPE:
00814                                                                 RECEIVE_NETWORK_B();
00815                                                                 i=RECEIVE_NETWORK_B();
00816                                                                 if(i==DHCP_NAK){
00817                                                                         DEBUGOUT("DHCP_NAK received; State --> INIT\r\n");
00818                                                                         dhcpc_state=DHCP_STATE_INIT;
00819                                                                         localmachine.localip=0;
00820                                                                         return(-1);
00821                                                                 }
00822                                                                 if(i==DHCP_ACK){
00823                                                                         DEBUGOUT("DHCP_ACK received; State --> BOUND\r\n");
00824                                                                         dhcpc_state=DHCP_STATE_BOUND;
00825                                                                 }
00826                                                                 break;
00827                                                         case DHCP_OPT_T1_VALUE:
00828                                                                 DEBUGOUT("T1; ");
00829                                                                 dhcpc_t1=dhcpc_read_n_bytes(RECEIVE_NETWORK_B());
00830                                                                 break;
00831                                                         case DHCP_OPT_T2_VALUE:
00832                                                                 DEBUGOUT("T2; ");
00833                                                                 dhcpc_t2=dhcpc_read_n_bytes(RECEIVE_NETWORK_B());
00834                                                                 break;
00835                                                         default:
00836                                                                 dhcpc_read_n_bytes(RECEIVE_NETWORK_B());
00837                                                                 break;
00838                                                 }
00839                                         }
00840                                         break;
00841                                 default:
00842                                         /* dump frames when in all other states */
00843                                         break;                          
00844                         }
00845                         break;
00846                 default:
00847                         /* should never get here */
00848                         DEBUGOUT("DHCP Client: Unknown UDP event :-( \r\n");
00849                         break;
00850         }
00851         return 1;
00852 
00853 }

Generated on Sun Aug 3 20:32:59 2003 for OpenTCP by doxygen1.2.18