Milos RTOS v0.3.4a
Real Time Operating System
dhcp.c
Go to the documentation of this file.
00001 /***************************************************************************
00002  * dhcp.c
00003  * (C) 2011 Ivan Meleca
00004  * www.milos.it
00005  *
00006 
00007 #   This program is free software; you can redistribute it and/or modify
00008 #   it under the terms of the GNU General Public License as published by
00009 #   the Free Software Foundation; either version 2 of the License, or
00010 #   (at your option) any later version.
00011 #
00012 #   This program is distributed in the hope that it will be useful,
00013 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 #   GNU General Public License for more details.
00016 #
00017 #   You should have received a copy of the GNU General Public License
00018 #   along with this program; if not, write to the Free Software
00019 #   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00020 
00021 ***************************************************************************/
00022 
00023 #include "dhcp.h"
00024 #include "socket.h"
00025 #include "route.h"
00026 #include <core/heap.h>
00027 #include <core/system.h>
00028 #include <common/mem.h>
00029 
00030 #if __CONFIG_COMPILE_NET
00031 
00045 typedef __TYPEDEF_PRE struct __dhcpBootpTag
00046 {
00047     u8 op;                  
00048     u8 hw_addr_type;        
00049     u8 hw_addr_len;         
00050     u8 hops;                
00051     u32 xid;                
00052     u16 secs;               
00053     u16 flags;              
00054     u32 ciaddr;             
00055     u32 yiaddr;             
00056     u32 siaddr;             
00057     u32 giaddr;             
00058     u8 chaddr[16];          
00059     __STRING sname[64];     
00060     __STRING file[128];     
00061     u8 options[312];        
00063 } __TYPEDEF_POST __DHCP_BOOTP, *__PDHCP_BOOTP;
00064 
00068 typedef struct __dhcpLeaseTag
00069 {
00070     u32 curr_timer;         
00071     u32 renewal;            
00072     u32 rebind;             
00073     u32 lease;              
00075 } __DHCP_LEASE;
00076 
00080 typedef struct __dhcpTag
00081 {
00082     u8 state;               
00083     u8 next_state;          
00084     u8 retries;             
00085     u8 wait;                
00086     u32 timer;              
00087     u32 secs;               
00088     u32 xid;                
00089     __PDHCP_BOOTP bootp;    
00090     __PSOCKET sock;         
00091     __DHCP_LEASE lease;     
00093 } __DHCP, *__PDHCP;
00094 
00109 #define __DHCP_STATE_IDLE                   0
00110 #define __DHCP_STATE_INIT                   1
00111 #define __DHCP_STATE_SELECTING              2
00112 #define __DHCP_STATE_REQUESTING             3
00113 #define __DHCP_STATE_INIT_REBOOT            4
00114 #define __DHCP_STATE_REBOOTING              5
00115 #define __DHCP_STATE_BOUND                  6
00116 #define __DHCP_STATE_RENEWING               7
00117 #define __DHCP_STATE_REBINDING              8
00118 #define __DHCP_STATE_WAIT                   9
00119 
00129 #define __DHCP_OFFER_TIMEOUT                5
00130 #define __DHCP_REQUEST_TIMEOUT              5
00131 #define __DHCP_ACK_TIMEOUT                  5
00132 #define __DHCP_REBOOT_ACK_TIMEOUT           10
00133 #define __DHCP_ON_DISCOVER_FAIL_WAIT        5
00134 #define __DHCP_ON_REQUEST_FAIL_WAIT         5
00135 #define __DHCP_ON_OFFER_TIMEOUT_WAIT        5
00136 #define __DHCP_ON_ACK_TIMEOUT_WAIT          5
00137 #define __DHCP_DEFAULT_LEASE_TIME           43200
00138 
00147 #define __DHCP_CLIENT_PORT                  68
00148 #define __DHCP_SERVER_PORT                  67
00149 
00159 #define __DHCP_MSGTYPE_DISCOVER             1
00160 #define __DHCP_MSGTYPE_OFFER                2
00161 #define __DHCP_MSGTYPE_REQUEST              3
00162 #define __DHCP_MSGTYPE_DECLINE              4
00163 #define __DHCP_MSGTYPE_ACK                  5
00164 #define __DHCP_MSGTYPE_NAK                  6
00165 #define __DHCP_MSGTYPE_RELEASE              7
00166 #define __DHCP_MSGTYPE_INFORM               8
00167 
00177 #define __DHCP_OPT_PAD                      0
00178 #define __DHCP_OPT_NETMASK                  1
00179 #define __DHCP_OPT_GATEWAY                  3
00180 #define __DHCP_OPT_DNS                      6
00181 #define __DHCP_OPT_HOSTNAME                 12
00182 #define __DHCP_OPT_DOMAIN                   15
00183 #define __DHCP_OPT_BROADCAST                28
00184 #define __DHCP_OPT_REQIP                    50
00185 #define __DHCP_OPT_LEASETIME                51
00186 #define __DHCP_OPT_MSGTYPE                  53
00187 #define __DHCP_OPT_SID                      54
00188 #define __DHCP_OPT_PARAMSREQUEST            55
00189 #define __DHCP_OPT_MAXMSGSIZE               57
00190 #define __DHCP_OPT_RENEWALTIME              58
00191 #define __DHCP_OPT_REBINDTIME               59
00192 #define __DHCP_OPT_END                      255
00193 
00207 #define __dhcpAdd8bitOption(op, t, v, len)  {*(op++)=t;*(op++)=1;*(op++)=v;len+=3;}
00208 #define __dhcpAdd16bitOption(op, t, v, len) {*(op++)=t;*(op++)=2;v=__htons(v);__memCpy(op,&v,2);op+=2;len+=4;}
00209 #define __dhcpAdd32bitOption(op, t, v, len) {*(op++)=t;*(op++)=4;v=__htonl(v);__memCpy(op,&v,4);op+=4;len+=6;}
00210 #define __dhcpAddOption(op, t, l, v, len)   {*(op++)=t;*(op++)=l;__memCpy(op,v,l);op+=l;len+=l+2;}
00211 #define __dhcpRenewXid(dhcp)                {dhcp->xid = __systemGetTickCount() * __systemGetTickCount();}
00212 
00234 __STATIC __VOID __dhcpSetState(__PDHCP dhcp, u8 state)
00235 {
00236     dhcp->state = state;
00237 
00238 #if __NET_DEBUG_DHCP
00239     NETOUT(__NET_DEBUG_DHCP, ("[DHCP] new state: "));
00240 
00241     switch (state)
00242     {
00243         case __DHCP_STATE_IDLE:
00244             NETMSG(__NET_DEBUG_DHCP, ("IDLE"));
00245             break;
00246         case __DHCP_STATE_INIT:
00247             NETMSG(__NET_DEBUG_DHCP, ("INIT"));
00248             break;
00249         case __DHCP_STATE_SELECTING:
00250             NETMSG(__NET_DEBUG_DHCP, ("SELECTING"));
00251             break;
00252         case __DHCP_STATE_REQUESTING:
00253             NETMSG(__NET_DEBUG_DHCP, ("REQUESTING"));
00254             break;
00255         case __DHCP_STATE_INIT_REBOOT:
00256             NETMSG(__NET_DEBUG_DHCP, ("REBOOT"));
00257             break;
00258         case __DHCP_STATE_REBOOTING:
00259             NETMSG(__NET_DEBUG_DHCP, ("REBOOTING"));
00260             break;
00261         case __DHCP_STATE_BOUND:
00262             NETMSG(__NET_DEBUG_DHCP, ("BOUND"));
00263             break;
00264         case __DHCP_STATE_RENEWING:
00265             NETMSG(__NET_DEBUG_DHCP, ("RENEWING"));
00266             break;
00267         case __DHCP_STATE_REBINDING:
00268             NETMSG(__NET_DEBUG_DHCP, ("REBINDING"));
00269             break;
00270         case __DHCP_STATE_WAIT:
00271             NETMSG(__NET_DEBUG_DHCP, ("WAIT"));
00272             break;
00273     }
00274 #endif /* __NET_DEBUG_DHCP */
00275 
00276 }
00277 
00289 __STATIC __BOOL __dhcpOpenSocket(__PDHCP dhcp)
00290 {
00291     if (!dhcp->sock)
00292     {
00293         dhcp->sock = __socketCreate(__SOCK_TYPE_UDP, __DHCP_CLIENT_PORT);
00294         if (!dhcp->sock) return __FALSE;
00295     }
00296 
00297     return __TRUE;
00298 }
00299 
00310 __STATIC __VOID __dhcpCloseSocket(__PDHCP dhcp)
00311 {
00312     __socketClose(dhcp->sock);
00313     __socketDestroy(dhcp->sock);
00314     dhcp->sock = __NULL;
00315 }
00316 
00328 __STATIC i32 __dhcpSendBootp(__PSOCKET sock, u32 addr, __PDHCP_BOOTP bootp, u16 opt_len)
00329 {
00330     u16 len;
00331     bootp->options[opt_len++] = 0xFF;
00332 
00333     len = sizeof(__DHCP_BOOTP) - sizeof(bootp->options) + opt_len;
00334 
00335     if (len < 300) len = 300;
00336 
00337     if (__socketSendTo(sock, addr, __DHCP_SERVER_PORT, bootp, len) == len)
00338     {
00339         return 0;
00340     }
00341 
00342     return -1;
00343 }
00344 
00358 __STATIC u16 __dhcpPrepareBootp(__PDHCP_BOOTP bootp, u8 msgtype, u32 xid, u8* mac, u32 ciaddr, u16 sec)
00359 {
00360     u8 values[3] = {1,3,6};
00361     u8* options;
00362     u16 len = 0;
00363     u16 val;
00364 
00365     bootp->op = 1;
00366     bootp->hw_addr_type = 1;
00367     bootp->hw_addr_len = 6;
00368     bootp->hops = 0;
00369     bootp->xid = xid;
00370     bootp->secs = sec;
00371     bootp->flags = __htons(0x8000); /* TODO check if needed */
00372     __memCpy(bootp->chaddr, mac, 6);
00373 
00374     options = bootp->options;
00375 
00376     /* Magic cookie */
00377     *(options++) = 0x63;
00378     *(options++) = 0x82;
00379     *(options++) = 0x53;
00380     *(options++) = 0x63;
00381 
00382     len = 4;
00383 
00384     /* Message type */
00385     __dhcpAdd8bitOption(options, __DHCP_OPT_MSGTYPE, msgtype, len);
00386 
00387     /* Data requested from DHCP server */
00388     __dhcpAddOption(options, __DHCP_OPT_PARAMSREQUEST, 3, values, len);
00389 
00390     /* Hostname TODO take the value from somewhere else */
00391     __dhcpAddOption(options, __DHCP_OPT_HOSTNAME, 5, (u8*) "milos", len);
00392 
00393     /* Max. DHCP message size we will accept */
00394     val = 576;
00395     __dhcpAdd16bitOption(options, __DHCP_OPT_MAXMSGSIZE, val, len);
00396 
00397     return len;
00398 }
00399 
00407 __STATIC i32 __dhcpSendDiscover(__PNETIF netif)
00408 {
00409     __PDHCP dhcp = (__PDHCP) netif->dhcp;
00410     __PDHCP_BOOTP bootp;
00411     u16 len = 0;
00412 
00413     if (!__dhcpOpenSocket(dhcp)) return -1;
00414 
00415     if (dhcp->bootp == __NULL)
00416     {
00417         dhcp->bootp = __heapAlloc(sizeof(__DHCP_BOOTP));
00418         if (!dhcp->bootp)
00419         {
00420             __dhcpCloseSocket(dhcp);
00421             return -1;
00422         }
00423     }
00424 
00425     __memSet(dhcp->bootp, 0, sizeof(__DHCP_BOOTP));
00426 
00427     __dhcpRenewXid(dhcp);
00428     bootp = dhcp->bootp;
00429 
00430     len = __dhcpPrepareBootp(bootp, __DHCP_MSGTYPE_DISCOVER, dhcp->xid, netif->addr.type.mac, 0, 0);
00431 
00432     return __dhcpSendBootp(dhcp->sock, 0xFFFFFFFF, bootp, len);
00433 }
00434 
00445 __STATIC __VOID __dhcpWait(__PDHCP dhcp, u8 next_state, u8 wait)
00446 {
00447     __dhcpSetState(dhcp, __DHCP_STATE_WAIT);
00448     dhcp->next_state = next_state;
00449     dhcp->timer = __systemGetSecondsCount();
00450     dhcp->wait = wait;
00451 }
00452 
00462 __STATIC i32 __dhcpRecvBootp(__PDHCP dhcp)
00463 {
00464     u32 addr;
00465     u16 port;
00466     i32 ret;
00467 
00468     if (!__dhcpOpenSocket(dhcp)) return -1;
00469 
00470     if (dhcp->bootp == __NULL)
00471     {
00472         dhcp->bootp = __heapAlloc(sizeof(__DHCP_BOOTP));
00473         if (!dhcp->bootp) return -1;
00474     }
00475 
00476     __memSet(dhcp->bootp, 0, sizeof(__DHCP_BOOTP));
00477 
00478     ret = __socketRecvFrom(dhcp->sock, &addr, &port, dhcp->bootp, sizeof(__DHCP_BOOTP));
00479 
00480     if (ret > 0)
00481     {
00482         /* Check for (at least) the size of a BOOTP structure plus 4 byte for
00483          * the magic cookie plus 1 byte for the termination 0xFF */
00484         if (ret > sizeof(__DHCP_BOOTP) - sizeof(dhcp->bootp->options) + 4 + 1)
00485         {
00486             /* Packet should be OK */
00487             return 0;
00488         }
00489     }
00490 
00491     return -1;
00492 }
00493 
00501 __STATIC u8 __dhcpGetMsgIdFromBootp(__PDHCP_BOOTP bootp)
00502 {
00503     u8* options;
00504     u32 len;
00505 
00506     options = bootp->options;
00507     options += 4;
00508     len = sizeof(bootp->options);
00509 
00510     while (*options != __DHCP_OPT_END && len--)
00511     {
00512         if (*(options+1) > len) return __FALSE;
00513 
00514         switch (*options)
00515         {
00516             /* Message type */
00517             case __DHCP_OPT_MSGTYPE:
00518                 /* Check size */
00519                 if (*(++options) != 1) return __FALSE;
00520                 return (*(++options));
00521         }
00522     }
00523 
00524     return 0;
00525 }
00526 
00535 __STATIC __BOOL __dhcpProcessAck(__PNETIF netif, __PDHCP dhcp)
00536 {
00537     u32 ip = dhcp->bootp->yiaddr;
00538     u32 gw;
00539     u32 dns;
00540     u32 mask;
00541     u8* options;
00542     u32 len;
00543 
00544     dns = gw = mask = 0;
00545 
00546     options = dhcp->bootp->options;
00547     options += 4;
00548     len = sizeof(dhcp->bootp->options);
00549 
00550     __memSet(&dhcp->lease, 0, sizeof(__DHCP_LEASE));
00551 
00552     while (*options != __DHCP_OPT_END && len--)
00553     {
00554         if (*(options+1) > len) return __FALSE;
00555 
00556         switch (*options)
00557         {
00558             /* DNS */
00559             case __DHCP_OPT_DNS:
00560                 /* Check size */
00561                 if (*(++options) != 4) return __FALSE;
00562                 __memCpy(&dns, ++options, 4);
00563                 options += 4;
00564                 break;
00565 
00566             /* Gateway */
00567             case __DHCP_OPT_GATEWAY:
00568                 /* Check size */
00569                 if (*(++options) != 4) return __FALSE;
00570                 __memCpy(&gw, ++options, 4);
00571                 options += 4;
00572                 break;
00573 
00574             /* Network mask */
00575             case __DHCP_OPT_NETMASK:
00576                 /* Check size */
00577                 if (*(++options) != 4) return __FALSE;
00578                 __memCpy(&mask, ++options, 4);
00579                 options += 4;
00580                 break;
00581 
00582             case __DHCP_OPT_LEASETIME:
00583                 /* Check size */
00584                 if (*(++options) != 4) return __FALSE;
00585                 __memCpy(&dhcp->lease.lease, ++options, 4);
00586                 options += 4;
00587 
00588                 dhcp->lease.lease = __ntohl(dhcp->lease.lease);
00589                 break;
00590 
00591             case __DHCP_OPT_RENEWALTIME:
00592                 if (*(++options) != 4) return __FALSE;
00593                 __memCpy(&dhcp->lease.renewal, ++options, 4);
00594                 options += 4;
00595 
00596                 dhcp->lease.renewal = __ntohl(dhcp->lease.renewal);
00597                 break;
00598 
00599             case __DHCP_OPT_REBINDTIME:
00600                 if (*(++options) != 4) return __FALSE;
00601                 __memCpy(&dhcp->lease.rebind, ++options, 4);
00602                 options += 4;
00603 
00604                 dhcp->lease.rebind = __ntohl(dhcp->lease.rebind);
00605                 break;
00606 
00607             default:
00608                 ++options;
00609                 options += *options;
00610                 ++options;
00611                 break;
00612         }
00613     }
00614 
00615     if (dhcp->lease.lease == 0)
00616         dhcp->lease.lease = __DHCP_DEFAULT_LEASE_TIME;
00617 
00618     if (dhcp->lease.renewal == 0)
00619         dhcp->lease.renewal = dhcp->lease.lease / 2;
00620 
00621     if (dhcp->lease.rebind == 0)
00622         dhcp->lease.rebind = (dhcp->lease.lease - ((dhcp->lease.renewal / 2) / 2));
00623 
00624     dhcp->lease.curr_timer = __systemGetSecondsCount();
00625 
00626     netif->ip = ip;
00627     netif->mask = mask;
00628     netif->dns1 = dns;
00629     netif->gateway = gw;
00630 
00631     __routeAdd(netif, 0, 0, netif->gateway);
00632     __routeAdd(netif, netif->ip, netif->mask, 0);
00633 
00634     __dhcpCloseSocket(dhcp);
00635     __heapFree(dhcp->bootp);
00636     dhcp->bootp = __NULL;
00637 
00638     return __TRUE;
00639 }
00640 
00652 __STATIC __BOOL __dhcpProcessOffer(__PNETIF netif, __PDHCP dhcp)
00653 {
00654     u32 ouraddr = __ntohl(dhcp->bootp->yiaddr);
00655     u32 servaddr = __ntohl(dhcp->bootp->siaddr);
00656     u32 len;
00657     i32 ret;
00658     u8* options;
00659 
00660     /* Don't get too greedy. By now just accept the first offer. */
00661     __memSet(dhcp->bootp, 0, sizeof(__DHCP_BOOTP));
00662 
00663     len = __dhcpPrepareBootp(dhcp->bootp, __DHCP_MSGTYPE_REQUEST, dhcp->xid, netif->addr.type.mac, 0, 0);
00664 
00665     options = dhcp->bootp->options + len;
00666 
00667     __dhcpAdd32bitOption(options, __DHCP_OPT_SID, servaddr, len);
00668     __dhcpAdd32bitOption(options, __DHCP_OPT_REQIP, ouraddr, len);
00669 
00670     ret = __dhcpSendBootp(dhcp->sock, 0xFFFFFFFF, dhcp->bootp, len);
00671 
00672     return (ret == 0) ? __TRUE : __FALSE;
00673 }
00674 
00684 __STATIC __BOOL __dhcpRenew(__PNETIF netif, __PDHCP dhcp, u32 serv_addr)
00685 {
00686     u32 ouraddr = netif->ip;
00687     u32 servaddr = serv_addr;
00688     u32 len;
00689     i32 ret;
00690 
00691     if (!__dhcpOpenSocket(dhcp)) return __FALSE;
00692 
00693     if (dhcp->bootp == __NULL)
00694     {
00695         dhcp->bootp = __heapAllocZero(sizeof(__DHCP_BOOTP));
00696         if (!dhcp->bootp) return __FALSE;
00697     }
00698 
00699     __dhcpRenewXid(dhcp);
00700 
00701     len = __dhcpPrepareBootp(dhcp->bootp, __DHCP_MSGTYPE_REQUEST, dhcp->xid, netif->addr.type.mac, 0, 0);
00702 
00703     dhcp->bootp->ciaddr = ouraddr;
00704 
00705     ret = __dhcpSendBootp(dhcp->sock, servaddr, dhcp->bootp, len);
00706 
00707     return (ret == 0) ? __TRUE : __FALSE;
00708 }
00709 
00720 __STATIC __VOID __dhcpReceiveAck(__PNETIF netif, __PDHCP dhcp, u8 success_state, u8 fail_state)
00721 {
00722     /* Read bootp from socket */
00723     if (__dhcpRecvBootp(dhcp) == 0)
00724     {
00725         /* Check for BOOTP == REPLY and same XID */
00726         if (dhcp->bootp->op == 2 && dhcp->bootp->xid == dhcp->xid)
00727         {
00728             /* If msg id == ACK */
00729             if (__dhcpGetMsgIdFromBootp(dhcp->bootp) == __DHCP_MSGTYPE_ACK)
00730             {
00731                 NETMSG(__NET_DEBUG_DHCP, ("[DHCP] ACK received"));
00732                 if (__dhcpProcessAck(netif, dhcp))
00733                 {
00734                     __dhcpSetState(dhcp, success_state);
00735                 }
00736             } else if (__dhcpGetMsgIdFromBootp(dhcp->bootp) == __DHCP_MSGTYPE_NAK)
00737             {
00738                 NETMSG(__NET_DEBUG_DHCP, ("[DHCP] NAK received"));
00739                 __dhcpWait(dhcp, fail_state, 1);
00740             }
00741         }
00742     }
00743 }
00744 
00765 __VOID __dhcpSm(__PNETIF netif)
00766 {
00767     __PDHCP dhcp;
00768 
00769     if (!netif->dhcp)
00770     {
00771         /* first time here */
00772         netif->dhcp = (__PDHCP) __heapAllocZero(sizeof(__DHCP));
00773         if (!netif->dhcp) return;
00774 
00775         dhcp = (__PDHCP) netif->dhcp;
00776         __dhcpSetState(dhcp, __DHCP_STATE_INIT);
00777     }
00778 
00779     dhcp = (__PDHCP) netif->dhcp;
00780 
00781     switch (dhcp->state)
00782     {
00783         /*
00784          * Do nothing.
00785          */
00786         case __DHCP_STATE_IDLE:
00787             return;
00788 
00789         /*
00790          * Try to send a discover packet. If sent, jump to __DHCP_STATE_SELECTING.
00791          */
00792         case __DHCP_STATE_INIT:
00793 
00794             /* Send DHCP discover */
00795             if (__dhcpSendDiscover(netif) == 0)
00796             {
00797                 __dhcpSetState(dhcp, __DHCP_STATE_SELECTING);
00798                 dhcp->timer = __systemGetSecondsCount();
00799             } else {
00800                 __dhcpWait(dhcp, __DHCP_STATE_INIT, __DHCP_ON_DISCOVER_FAIL_WAIT);
00801             }
00802             break;
00803 
00804         /*
00805          * Wait for an OFFER.
00806          */
00807         case __DHCP_STATE_SELECTING:
00808             /* Wait for DHCPOFFER or timeout */
00809             if (__systemGetSecondsCount() - dhcp->timer > __DHCP_OFFER_TIMEOUT)
00810             {
00811                 __dhcpWait(dhcp, __DHCP_STATE_INIT, __DHCP_ON_OFFER_TIMEOUT_WAIT);
00812                 break;
00813             }
00814 
00815             /* Read bootp from socket */
00816             if (__dhcpRecvBootp(dhcp) == 0)
00817             {
00818                 /* Check for BOOTP == REPLY and same XID */
00819                 if (dhcp->bootp->op == 2 && dhcp->bootp->xid == dhcp->xid)
00820                 {
00821                     /* If Msg id == OFFER */
00822                     if (__dhcpGetMsgIdFromBootp(dhcp->bootp) == __DHCP_MSGTYPE_OFFER)
00823                     {
00824                         /* Send request */
00825                         if (__dhcpProcessOffer(netif, dhcp))
00826                         {
00827                             __dhcpSetState(dhcp, __DHCP_STATE_REQUESTING);
00828                             dhcp->timer = __systemGetSecondsCount();
00829                         }
00830                     }
00831                 }
00832             }
00833 
00834             /*
00835              * If the BOOTP received has errors or it's not for us, let the timeout counter
00836              * throw us out of here
00837              */
00838             break;
00839 
00840         /*
00841          * Request sent. Wait for ACK, NAK or timeout.
00842          */
00843         case __DHCP_STATE_REQUESTING:
00844             /* Waiting for ACK or NACK */
00845             if (__systemGetSecondsCount() - dhcp->timer > __DHCP_ACK_TIMEOUT)
00846             {
00847                 __dhcpWait(dhcp, __DHCP_STATE_INIT, __DHCP_ON_ACK_TIMEOUT_WAIT);
00848                 break;
00849             }
00850 
00851             __dhcpReceiveAck(netif, dhcp, __DHCP_STATE_BOUND, __DHCP_STATE_INIT);
00852             break;
00853 
00854 
00855         /*
00856          * Start reboot procedure. Try to renew the address.
00857          */
00858         case __DHCP_STATE_INIT_REBOOT:
00859             if (__dhcpRenew(netif, dhcp, netif->gateway))
00860             {
00861                 dhcp->timer = __systemGetSecondsCount();
00862                 __dhcpSetState(dhcp, __DHCP_STATE_REBOOTING);
00863             } else {
00864                 /* Failed to send renew request, go to INIT */
00865                 __dhcpWait(dhcp, __DHCP_STATE_INIT, __DHCP_ON_ACK_TIMEOUT_WAIT);
00866             }
00867             break;
00868 
00869         /*
00870          * Request sent, wait for ACK, NAK or timeout.
00871          */
00872         case __DHCP_STATE_REBOOTING:
00873             /* Waiting for ACK or NACK */
00874             if (__systemGetSecondsCount() - dhcp->timer > __DHCP_REBOOT_ACK_TIMEOUT)
00875             {
00876                 if (dhcp->retries)
00877                 {
00878                     dhcp->retries--;
00879                     __dhcpWait(dhcp, __DHCP_STATE_INIT_REBOOT, __DHCP_ON_ACK_TIMEOUT_WAIT);
00880                     break;
00881                 } else {
00882                     __dhcpWait(dhcp, __DHCP_STATE_INIT, __DHCP_ON_ACK_TIMEOUT_WAIT);
00883                     break;
00884                 }
00885             }
00886 
00887             __dhcpReceiveAck(netif, dhcp, __DHCP_STATE_BOUND, __DHCP_STATE_INIT);
00888             break;
00889 
00890         /*
00891          * Request accepted.
00892          */
00893         case __DHCP_STATE_BOUND:
00894             /* Check timer for renewal */
00895             if (__systemGetSecondsCount() - dhcp->lease.curr_timer > dhcp->lease.renewal)
00896             {
00897                 /* Send request to the current server */
00898                 if (__dhcpRenew(netif, dhcp, netif->gateway))
00899                 {
00900                     dhcp->timer = __systemGetSecondsCount();
00901                     __dhcpSetState(dhcp, __DHCP_STATE_RENEWING);
00902                 }
00903             }
00904             break;
00905 
00906         /*
00907          * Start the renew procedure. The request was already sent from the BOUND state.
00908          * Here wait for the server ACK and check for the rebind timer to timeout. If so,
00909          * broadcast a request to any DHCP server and then transit to the REBINDING state.
00910          */
00911         case __DHCP_STATE_RENEWING:
00912             /* T1 elapsed */
00913             if (__systemGetSecondsCount() - dhcp->lease.curr_timer > dhcp->lease.rebind)
00914             {
00915                 /* No response, broadcast request and go to rebinding */
00916                 if (__dhcpRenew(netif, dhcp, 0xFFFFFFFF))
00917                 {
00918                     dhcp->timer = __systemGetSecondsCount();
00919                     __dhcpSetState(dhcp, __DHCP_STATE_REBINDING);
00920                     break;
00921                 } else {
00922                     /* Failed to send renew request, go to INIT */
00923                     __dhcpWait(dhcp, __DHCP_STATE_INIT, __DHCP_ON_ACK_TIMEOUT_WAIT);
00924                     break;
00925                 }
00926             }
00927 
00928             /* Wait for ACK or NACK, or timeout */
00929             if (__systemGetSecondsCount() - dhcp->timer > __DHCP_ACK_TIMEOUT)
00930             {
00931                 __dhcpRenew(netif, dhcp, netif->gateway);
00932                 dhcp->timer = __systemGetSecondsCount();
00933             }
00934 
00935             __dhcpReceiveAck(netif, dhcp, __DHCP_STATE_BOUND, __DHCP_STATE_INIT);
00936             break;
00937 
00938         /*
00939          * Wait for an ACK from a DHCP server, while sending periodic requests.
00940          * If the lease expires, go to the INIT state.
00941          */
00942         case __DHCP_STATE_REBINDING:
00943             /* No server is answering our requests, check for lease expiration */
00944             if (__systemGetSecondsCount() - dhcp->lease.curr_timer > dhcp->lease.lease)
00945             {
00946                 /* Go to INIT */
00947                 __dhcpSetState(dhcp, __DHCP_STATE_INIT);
00948                 break;
00949             }
00950 
00951             if (__systemGetSecondsCount() - dhcp->timer > __DHCP_ACK_TIMEOUT)
00952             {
00953                 __dhcpRenew(netif, dhcp, 0xFFFFFFFF);
00954                 dhcp->timer = __systemGetSecondsCount();
00955             }
00956 
00957             __dhcpReceiveAck(netif, dhcp, __DHCP_STATE_BOUND, __DHCP_STATE_INIT);
00958             break;
00959 
00960         case __DHCP_STATE_WAIT:
00961             if (__systemGetSecondsCount() - dhcp->timer >= dhcp->wait)
00962             {
00963                 __dhcpSetState(dhcp, dhcp->next_state);
00964             }
00965             break;
00966     }
00967 }
00968 
00976 __VOID __dhcpInitReboot(__PNETIF netif)
00977 {
00978     __PDHCP dhcp = netif->dhcp;
00979 
00980     /* Check if we had a valid address from DHCP */
00981     if (netif->ip && netif->gateway && netif->mask)
00982     {
00983         /* jump to init reboot */
00984         if (dhcp)
00985         {
00986             dhcp->retries = 5;
00987             __dhcpSetState(dhcp, __DHCP_STATE_INIT_REBOOT);
00988         }
00989     }
00990 }
00991 
01000 #endif /* __CONFIG_COMPILE_NET */
 All Data Structures Files Functions Variables Typedefs Defines