00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00199 #include <cfg/os.h>
00200 #include <sys/thread.h>
00201 #include <sys/event.h>
00202 #include <sys/timer.h>
00203 #include <sys/confnet.h>
00204 #include <sys/confos.h>
00205 
00206 #include <stdlib.h>
00207 #include <string.h>
00208 #include <time.h>
00209 #include <memdebug.h>
00210 
00211 #include <arpa/inet.h>
00212 #include <netinet/in.h>
00213 #include <netdb.h>
00214 #include <net/route.h>
00215 #include <sys/socket.h>
00216 #include <pro/dhcp.h>
00217 
00218 #ifdef NUTDEBUG
00219 #include <net/netdebug.h>
00220 #endif
00221 
00222 #if 0
00223 
00224 #define NUTDEBUG
00225 #include <stdio.h>
00226 #define __tcp_trs stdout
00227 static uint_fast8_t __tcp_trf = 1;
00228 #endif
00229 
00234 
00241 
00247 #ifndef DHCP_SERVERPORT
00248 #define DHCP_SERVERPORT      67
00249 #endif
00250 
00256 #ifndef DHCP_CLIENTPORT
00257 #define DHCP_CLIENTPORT      68
00258 #endif
00259 
00269 #ifndef MAX_DHCP_MSGSIZE
00270 #define MAX_DHCP_MSGSIZE    576
00271 #endif
00272 
00280 #ifndef MIN_DHCP_MSGSIZE
00281 #define MIN_DHCP_MSGSIZE    300
00282 #endif
00283 
00299 #ifndef MAX_DHCP_BUFSIZE
00300 #define MAX_DHCP_BUFSIZE    1728
00301 #endif
00302 
00312 #ifndef MIN_DHCP_WAIT
00313 #define MIN_DHCP_WAIT       4000
00314 #endif
00315 
00324 #ifndef MAX_DHCP_WAIT
00325 #define MAX_DHCP_WAIT       64000
00326 #endif
00327 
00336 #ifndef MAX_DCHP_RETRIES
00337 #define MAX_DCHP_RETRIES    3
00338 #endif
00339 
00348 #ifndef MAX_DCHP_RELEASE_RETRIES
00349 #define MAX_DCHP_RELEASE_RETRIES    0
00350 #endif
00351 
00359 #ifndef DHCP_DEFAULT_LEASE
00360 #define DHCP_DEFAULT_LEASE  43200
00361 #endif
00362 
00368 #ifndef MAX_DHCP_NAPTIME
00369 #define MAX_DHCP_NAPTIME    4294967
00370 #endif
00371 
00377 #ifndef NUT_THREAD_DHCPSTACK
00378 #if defined(__AVR__)
00379 #if defined(__GNUC__)
00380 
00381 #define NUT_THREAD_DHCPSTACK    288
00382 #else
00383 
00384 #define NUT_THREAD_DHCPSTACK    512
00385 #endif
00386 #else
00387 
00388 
00389 #define NUT_THREAD_DHCPSTACK    512
00390 #endif
00391 #endif
00392 
00401 
00404 #define DHCP_DISCOVER   1
00405 
00410 #define DHCP_OFFER      2
00411 
00419 #define DHCP_REQUEST    3
00420 
00425 #define DHCP_DECLINE    4
00426 
00431 #define DHCP_ACK        5
00432 
00437 #define DHCP_NAK        6
00438 
00441 #define DHCP_RELEASE    7
00442 
00447 #define DHCP_INFORM     8
00448 
00458 
00465 #define DHCPOPT_PAD          0
00466 
00470 #define DHCPOPT_NETMASK      1
00471 
00475 #define DHCPOPT_GATEWAY      3
00476 
00480 #define DHCPOPT_DNS          6
00481 
00485 #define DHCPOPT_HOSTNAME     12
00486 
00490 #define DHCPOPT_DOMAIN       15
00491 
00495 #define DHCPOPT_BROADCAST    28
00496 
00500 #define DHCPOPT_REQESTIP     50
00501 
00505 #define DHCPOPT_LEASETIME    51
00506 
00510 #define DHCPOPT_MSGTYPE      53
00511 
00515 #define DHCPOPT_SID          54
00516 
00520 #define DHCPOPT_PARAMREQUEST 55
00521 
00525 #define DHCPOPT_MAXMSGSIZE   57
00526 
00530 #define DHCPOPT_RENEWALTIME  58
00531 
00535 #define DHCPOPT_REBINDTIME   59
00536 
00540 #define DHCPOPT_END          255
00541 
00547 typedef struct bootp BOOTP;
00548 
00552 struct __attribute__ ((packed)) bootp {
00553     uint8_t bp_op;              
00554     uint8_t bp_htype;           
00555     uint8_t bp_hlen;            
00556     uint8_t bp_hops;            
00557     uint32_t bp_xid;              
00558     uint16_t bp_secs;            
00559     uint16_t bp_flags;           
00560     uint32_t bp_ciaddr;           
00561     uint32_t bp_yiaddr;           
00562     uint32_t bp_siaddr;           
00563     uint32_t bp_giaddr;           
00564     uint8_t bp_chaddr[16];      
00565     char bp_sname[64];          
00566     char bp_file[128];          
00567     uint8_t bp_options[312];    
00568 };
00569 
00573 typedef struct dyn_cfg DYNCFG;
00574 
00578 struct dyn_cfg {
00579     uint8_t dyn_msgtyp;         
00580     uint32_t dyn_yiaddr;          
00581     uint32_t dyn_netmask;         
00582     uint32_t dyn_broadcast;       
00583     uint32_t dyn_gateway;         
00584     uint32_t dyn_pdns;            
00585     uint32_t dyn_sdns;            
00586     uint32_t dyn_sid;             
00587     uint32_t dyn_renewalTime;     
00588     uint32_t dyn_rebindTime;      
00589     uint32_t dyn_leaseTime;       
00590     uint8_t *dyn_hostname;      
00591     uint8_t *dyn_domain;        
00592 };
00593 
00600 static DYNCFG *dhcpConfig;
00601 
00608 static HANDLE dhcpThread;
00609 
00613 static uint8_t dhcpState;
00614 
00618 static int dhcpError;
00619 
00625 static HANDLE dhcpWake;
00626 
00632 static HANDLE dhcpDone;
00633 
00639 static uint32_t dhcpApiTimeout;
00640 
00647 static uint32_t dhcpApiStart;
00648 
00655 #ifdef __arm__
00656 static NUTDEVICE *dhcpDev;
00657 #endif
00658 
00670 static void copy_str(uint8_t ** dst, void *src, int len)
00671 {
00672     if (*dst) {
00673         free(*dst);
00674     }
00675     if ((*dst = malloc(len + 1)) != 0) {
00676         if (len) {
00677             memcpy(*dst, src, len);
00678         }
00679         *(*dst + len) = 0;
00680     }
00681 }
00682 
00690 static void ReleaseDynCfg(DYNCFG * dyncfg)
00691 {
00692     if (dyncfg) {
00693         if (dyncfg->dyn_hostname) {
00694             free(dyncfg->dyn_hostname);
00695         }
00696         if (dyncfg->dyn_domain) {
00697             free(dyncfg->dyn_domain);
00698         }
00699         free(dyncfg);
00700     }
00701 }
00702 
00714 static DYNCFG *ParseReply(BOOTP *bp, int len)
00715 {
00716     uint8_t *op;
00717     int left;
00718     DYNCFG *cfgp;
00719 
00720     
00721     if ((cfgp = malloc(sizeof(DYNCFG))) == 0) {
00722         return 0;
00723     }
00724     memset(cfgp, 0, sizeof(DYNCFG));
00725     cfgp->dyn_leaseTime = DHCP_DEFAULT_LEASE;
00726 
00727     
00728     memcpy(&cfgp->dyn_yiaddr, &bp->bp_yiaddr, 4);
00729 
00730     
00731 
00732 
00733 
00734     op = bp->bp_options + 4;
00735     left = len - (sizeof(*bp) - sizeof(bp->bp_options)) - 4;
00736     while (*op != DHCPOPT_END && left > 0) {
00737         uint8_t ol;
00738 
00739 #ifdef NUTDEBUG
00740         if (__tcp_trf) {
00741             fprintf(__tcp_trs, "[DHCP-Opt-%u]", *op);
00742         }
00743 #endif
00744         
00745         if (*op == DHCPOPT_PAD) {
00746             op++;
00747             left--;
00748             continue;
00749         }
00750 
00751         
00752         if ((ol = *(op + 1)) > left) {
00753             break;
00754         }
00755 
00756         
00757         if (*op == DHCPOPT_MSGTYPE) {
00758             if (ol != 1) {
00759                 break;
00760             }
00761             cfgp->dyn_msgtyp = *(op + 2);
00762 
00763 #ifdef NUTDEBUG
00764             if (__tcp_trf & NET_DBG_DHCP) {
00765                 switch(cfgp->dyn_msgtyp) {
00766                     case DHCP_OFFER:
00767                         fprintf(__tcp_trs, "+MSGT-OFFER+\n");
00768                         break;
00769                     case DHCP_ACK:
00770                         fprintf(__tcp_trs, "+MSGT-ACK+\n");
00771                         break;
00772                     case DHCP_NAK:
00773                         fprintf(__tcp_trs, "-MSGT-NAK-\n");
00774                         break;
00775                     default:
00776                         fprintf(__tcp_trs, "#MSGT-UNK#\n");
00777                         break;
00778                 }
00779             }
00780 #endif
00781         }
00782         
00783         else if (*op == DHCPOPT_HOSTNAME) {
00784             copy_str(&cfgp->dyn_hostname, op + 2, ol);
00785         }
00786         
00787         else if (*op == DHCPOPT_DOMAIN) {
00788             copy_str(&cfgp->dyn_domain, op + 2, ol);
00789         }
00790 
00791         
00792         else if (ol >= 4) {
00793             
00794             uint32_t lval = *(op + 2);
00795             lval += (uint32_t)(*(op + 3)) << 8;
00796             lval += (uint32_t)(*(op + 4)) << 16;
00797             lval += (uint32_t)(*(op + 5)) << 24;
00798 
00799             
00800             if (*op == DHCPOPT_NETMASK) {
00801                 cfgp->dyn_netmask = lval;
00802             }
00803             
00804             else if (*op == DHCPOPT_BROADCAST) {
00805                 cfgp->dyn_broadcast = lval;
00806             }
00807             
00808 
00809 
00810             else if (*op == DHCPOPT_GATEWAY) {
00811                 cfgp->dyn_gateway = lval;
00812             }
00813             
00814 
00815             else if (*op == DHCPOPT_DNS) {
00816                 cfgp->dyn_pdns = lval;
00817                 if (ol >= 8) {
00818                     cfgp->dyn_sdns = *(op + 6);
00819                     cfgp->dyn_sdns += (uint32_t)(*(op + 7)) << 8;
00820                     cfgp->dyn_sdns += (uint32_t)(*(op + 8)) << 16;
00821                     cfgp->dyn_sdns += (uint32_t)(*(op + 9)) << 24;
00822                 }
00823             }
00824             
00825             else if (*op == DHCPOPT_SID) {
00826                 cfgp->dyn_sid = lval;
00827             }
00828             
00829             else if (*op == DHCPOPT_RENEWALTIME) {
00830                 cfgp->dyn_renewalTime = ntohl(lval);
00831             }
00832             
00833             else if (*op == DHCPOPT_REBINDTIME) {
00834                 cfgp->dyn_rebindTime = ntohl(lval);
00835             }
00836             
00837             else if (*op == DHCPOPT_LEASETIME) {
00838                 cfgp->dyn_leaseTime = ntohl(lval);
00839             }
00840         }
00841         op += ol + 2;
00842         left -= ol + 2;
00843     }
00844 
00845     
00846 
00847 
00848 
00849     if (*op != DHCPOPT_END ||
00850         (cfgp->dyn_msgtyp != DHCP_OFFER &&
00851          cfgp->dyn_msgtyp != DHCP_ACK &&
00852          cfgp->dyn_msgtyp != DHCP_NAK)) {
00853 #ifdef NUTDEBUG
00854         if (__tcp_trf & NET_DBG_DHCP) {
00855             fprintf(__tcp_trs, "[DHCP-Parse Error]");
00856         }
00857 #endif
00858         ReleaseDynCfg(cfgp);
00859         return 0;
00860     }
00861 
00862     
00863     if (cfgp->dyn_renewalTime == 0) {
00864         cfgp->dyn_renewalTime = cfgp->dyn_leaseTime / 2;
00865     }
00866     if (cfgp->dyn_rebindTime == 0) {
00867         cfgp->dyn_rebindTime = cfgp->dyn_renewalTime +  
00868             cfgp->dyn_renewalTime / 2 + 
00869             cfgp->dyn_renewalTime / 4;
00870     }
00871     return cfgp;
00872 }
00873 
00884 static size_t DhcpAddOption(uint8_t * op, uint8_t ot, void *ov, uint8_t len)
00885 {
00886     *op++ = ot;
00887     *op++ = len;
00888     memcpy(op, ov, len);
00889 
00890     return 2 + len;
00891 }
00892 
00902 static size_t DhcpAddByteOption(uint8_t * op, uint8_t ot, uint8_t ov)
00903 {
00904     *op++ = ot;
00905     *op++ = 1;
00906     *op++ = ov;
00907 
00908     return 3;
00909 }
00910 
00921 static size_t DhcpAddShortOption(uint8_t * op, uint8_t ot, uint16_t ov)
00922 {
00923     *op++ = ot;
00924     *op++ = 2;
00925     ov = htons(ov);
00926     memcpy(op, &ov, 2);
00927 
00928     return 4;
00929 }
00930 
00943 static size_t DhcpAddParmReqOption(uint8_t * op)
00944 {
00945     *op++ = DHCPOPT_PARAMREQUEST;
00946     *op++ = 3;                  
00947     *op++ = DHCPOPT_NETMASK;    
00948     *op++ = DHCPOPT_GATEWAY;    
00949     *op++ = DHCPOPT_DNS;        
00950     return 5;                   
00951 }
00952 
00974 static unsigned int DhcpPrepHeader(BOOTP *bp, uint8_t msgtyp, uint32_t xid, uint32_t ciaddr, uint16_t secs)
00975 {
00976     uint8_t *op;
00977 
00978     memset(bp, 0, sizeof(*bp));
00979     
00980     bp->bp_op = 1;
00981     
00982     bp->bp_htype = 1;
00983     bp->bp_hlen = 6;
00984     memcpy(bp->bp_chaddr, confnet.cdn_mac, 6);
00985     
00986     bp->bp_xid = xid;
00987     
00988     bp->bp_secs = htons(secs);
00989 
00990 #ifdef DHCP_BROADCAST_FLAG
00991     
00992 
00993 
00994 
00995 
00996     bp->bp_flags = htons(0x8000);
00997 #endif
00998 
00999     bp->bp_ciaddr = ciaddr;
01000 
01001     
01002     op = bp->bp_options;
01003     *op++ = 0x63;
01004     *op++ = 0x82;
01005     *op++ = 0x53;
01006     *op++ = 0x63;
01007 
01008     
01009     return DhcpAddByteOption(op, DHCPOPT_MSGTYPE, msgtyp) + 4;
01010 }
01011 
01030 static int DhcpSendMessage(UDPSOCKET * sock, uint32_t addr, BOOTP *bp, size_t len)
01031 {
01032     
01033     bp->bp_options[len++] = DHCPOPT_END;
01034 
01035     
01036 
01037     if ((len += sizeof(BOOTP) - sizeof(bp->bp_options)) < MIN_DHCP_MSGSIZE) {
01038         len = MIN_DHCP_MSGSIZE;
01039     }
01040 #ifdef NUTDEBUG
01041     if (__tcp_trf & NET_DBG_DHCP) {
01042         fprintf(__tcp_trs, "[DHCP-Send to %s]", inet_ntoa(addr));
01043     }
01044 #endif
01045     if (NutUdpSendTo(sock, addr, DHCP_SERVERPORT, bp, len) < 0) {
01046         dhcpError = DHCPERR_TRANSMIT;
01047         return -1;
01048     }
01049     return 0;
01050 }
01051 
01065 static int DhcpRecvMessage(UDPSOCKET * sock, uint32_t xid, BOOTP *bp, uint32_t tmo)
01066 {
01067     int rc;
01068     uint16_t port;
01069     uint32_t addr;
01070     uint32_t etim;
01071     uint32_t wtim;
01072 
01073     
01074     etim = NutGetMillis();
01075     
01076     wtim = tmo;
01077     for (;;) {
01078         rc = NutUdpReceiveFrom(sock, &addr, &port, bp, sizeof(BOOTP), wtim);
01079 #ifdef NUTDEBUG
01080         if (__tcp_trf & NET_DBG_DHCP) {
01081             if (rc > 0) {
01082                 fprintf(__tcp_trs, "[DHCP-Recv from %s]", inet_ntoa(addr));
01083             } else if (rc < 0) {
01084                 fprintf(__tcp_trs, "[DHCP-Recv Error]");
01085             } else {
01086                 fprintf(__tcp_trs, "[DHCP-Recv Timeout %lu]", tmo);
01087             }
01088         }
01089 #endif
01090         
01091         if (rc <= 0) {
01092             if (rc < 0) {
01093                 dhcpError = DHCPERR_RECEIVE;
01094             }
01095             break;
01096         }
01097         
01098 
01099         if (rc > sizeof(BOOTP) - sizeof(bp->bp_options) + 5) {
01100             
01101             if (bp->bp_op == 2 && bp->bp_xid == xid) {
01102                 
01103                 break;
01104             }
01105         }
01106         
01107 
01108         wtim = NutGetMillis() - etim;
01109         if (wtim >= tmo - 250) {
01110             
01111             rc = 0;
01112             break;
01113         }
01114         wtim = tmo - wtim;
01115     }
01116     return rc;
01117 }
01118 
01133 static int DhcpBroadcastDiscover(UDPSOCKET * sock, BOOTP *bp, uint32_t xid, uint32_t raddr, uint16_t secs)
01134 {
01135     size_t optlen;
01136     int len;
01137     uint8_t *op = bp->bp_options;
01138 
01139     optlen = DhcpPrepHeader(bp, DHCP_DISCOVER, xid, 0, secs);
01140 
01141     
01142     if (raddr) {
01143         optlen += DhcpAddOption(op + optlen, DHCPOPT_REQESTIP, &raddr, sizeof(raddr));
01144     }
01145 
01146     optlen += DhcpAddParmReqOption(op + optlen);
01147 
01148     
01149 
01150 
01151 
01152     len = strlen(confos.hostname);
01153     if (len > 0) {
01154         optlen += DhcpAddOption(op + optlen, DHCPOPT_HOSTNAME, confos.hostname, len);
01155     }
01156 
01157     
01158     optlen += DhcpAddShortOption(op + optlen, DHCPOPT_MAXMSGSIZE, MAX_DHCP_MSGSIZE);
01159 
01160     return DhcpSendMessage(sock, INADDR_BROADCAST, bp, optlen);
01161 }
01162 
01163 
01183 static int DhcpSendRequest(UDPSOCKET * sock, uint32_t daddr, BOOTP *bp, uint32_t xid,        
01184                            uint32_t caddr, uint32_t raddr, uint32_t sid, uint16_t secs)
01185 {
01186     size_t optlen;
01187     int len;
01188     uint8_t *op = bp->bp_options;
01189 
01190     
01191     optlen = DhcpPrepHeader(bp, DHCP_REQUEST, xid, caddr, secs);
01192 
01193     
01194     if (raddr) {
01195         optlen += DhcpAddOption(op + optlen, DHCPOPT_REQESTIP, &raddr, sizeof(raddr));
01196     }
01197     if (sid) {
01198         optlen += DhcpAddOption(op + optlen, DHCPOPT_SID, &sid, sizeof(sid));
01199     }
01200     optlen += DhcpAddParmReqOption(op + optlen);
01201 
01202     
01203     
01204     len = strlen(confos.hostname);
01205     if (len > 0) {
01206         optlen += DhcpAddOption(op + optlen, DHCPOPT_HOSTNAME, confos.hostname, len);
01207     }
01208 
01209     return DhcpSendMessage(sock, daddr, bp, optlen);
01210 }
01211 
01230 static int DhcpBroadcastRequest(UDPSOCKET * sock, BOOTP *bp, uint32_t xid, 
01231                                 uint32_t caddr, uint32_t raddr, uint32_t sid, uint16_t secs)
01232 {
01233     return DhcpSendRequest(sock, INADDR_BROADCAST, bp, xid, caddr, raddr, sid, secs);
01234 }
01235 
01251 static int DhcpSendRelease(UDPSOCKET * sock, uint32_t daddr, BOOTP *bp, uint32_t xid, uint32_t caddr, uint32_t sid)
01252 {
01253     size_t optlen;
01254     uint8_t *op = bp->bp_options;
01255 
01256     
01257     optlen = DhcpPrepHeader(bp, DHCP_RELEASE, xid, caddr, 0);
01258 
01259     
01260     if (sid) {
01261         optlen += DhcpAddOption(op + optlen, DHCPOPT_SID, &sid, sizeof(sid));
01262     }
01263     return DhcpSendMessage(sock, daddr, bp, optlen);
01264 }
01265 
01278 static int DhcpSendInform(UDPSOCKET * sock, uint32_t daddr, BOOTP *bp, uint32_t xid, uint32_t caddr)
01279 {
01280     size_t optlen;
01281     size_t len;
01282     uint8_t *op = bp->bp_options;
01283 
01284     
01285     optlen = DhcpPrepHeader(bp, DHCP_INFORM, xid, caddr, 0);
01286 
01287     
01288     optlen += DhcpAddParmReqOption(op + optlen);
01289 
01290     
01291     len = strlen(confos.hostname);
01292     if (len > 0) {
01293         optlen += DhcpAddOption(op + optlen, DHCPOPT_HOSTNAME, confos.hostname, len);
01294     }
01295 
01296     
01297     optlen += DhcpAddShortOption(op + optlen, DHCPOPT_MAXMSGSIZE, MAX_DHCP_MSGSIZE);
01298 
01299     return DhcpSendMessage(sock, daddr, bp, optlen);
01300 }
01301 
01302 
01313 static DYNCFG *CheckOffer(DYNCFG * dyncfg, BOOTP *bp, size_t len)
01314 {
01315     DYNCFG *offer;
01316 
01317 #ifdef NUTDEBUG
01318     if (__tcp_trf & NET_DBG_DHCP) fprintf(__tcp_trs, "\n[chkoffer %s ", inet_ntoa( dyncfg->dyn_yiaddr));
01319 #endif
01320 
01321     
01322 
01323     if ((offer = ParseReply(bp, len)) == 0) {
01324 #ifdef NUTDEBUG
01325         if (__tcp_trf & NET_DBG_DHCP) fprintf(__tcp_trs, "TAKE: %s]", inet_ntoa( offer->dyn_yiaddr));
01326 #endif
01327         return dyncfg;
01328     }
01329 
01330     
01331     if (offer->dyn_msgtyp != DHCP_OFFER) {
01332         ReleaseDynCfg(offer);
01333 #ifdef NUTDEBUG
01334         if (__tcp_trf & NET_DBG_DHCP) fprintf(__tcp_trs, "NO-OFFER]");
01335 #endif
01336         return dyncfg;
01337     }
01338 
01339     
01340     if (dyncfg == 0) {
01341         dyncfg = offer;
01342 #ifdef NUTDEBUG
01343         if (__tcp_trf & NET_DBG_DHCP) fprintf(__tcp_trs, "FIRST: %s]", inet_ntoa(offer->dyn_yiaddr));
01344 #endif
01345     }
01346 
01347     
01348 
01349 
01350     else {
01351         
01352 
01353 
01354 #ifdef NUTDEBUG
01355         if (__tcp_trf & NET_DBG_DHCP) fprintf(__tcp_trs, "PREV ");
01356 #endif
01357         if (confnet.cdn_ip_addr & confnet.cdn_ip_mask) {
01358             if (dyncfg->dyn_yiaddr != confnet.cdn_ip_addr &&    
01359                 offer->dyn_yiaddr == confnet.cdn_ip_addr) {
01360                 ReleaseDynCfg(dyncfg);
01361                 dyncfg = offer;
01362 #ifdef NUTDEBUG
01363                 if (__tcp_trf & NET_DBG_DHCP) fprintf(__tcp_trs, "OLD: %s]", inet_ntoa( dyncfg->dyn_yiaddr));
01364 #endif
01365             }
01366         }
01367         
01368         else if (offer->dyn_leaseTime > dyncfg->dyn_leaseTime) {
01369             ReleaseDynCfg(dyncfg);
01370             dyncfg = offer;
01371 #ifdef NUTDEBUG
01372             if (__tcp_trf & NET_DBG_DHCP) fprintf(__tcp_trs, "LONG: %s]", inet_ntoa( dyncfg->dyn_yiaddr));
01373 #endif
01374         }
01375         
01376         else {
01377             ReleaseDynCfg(offer);
01378 #ifdef NUTDEBUG
01379             if (__tcp_trf & NET_DBG_DHCP) fprintf(__tcp_trs, "DSIC]");
01380 #endif
01381         }
01382     }
01383     return dyncfg;
01384 }
01385 
01386 #ifdef NUTDEBUG
01387 void DhcpStateDebug( uint_fast8_t n, uint_fast8_t s, int li, int lt, ureg_t retries)
01388 {
01389     if (__tcp_trf & NET_DBG_DHCP) {
01390         if( n)
01391             fprintf(__tcp_trs, "\n[%u.DHCP-", retries + 1);
01392         else
01393             fprintf(__tcp_trs, "\n->[%u.DHCP-", retries + 1);
01394 
01395         switch (dhcpState) {
01396         case DHCPST_INIT:
01397             fprintf(__tcp_trs, "INIT]");
01398             break;
01399         case DHCPST_SELECTING:
01400             fprintf(__tcp_trs, "SELECTING]");
01401             break;
01402         case DHCPST_REQUESTING:
01403             fprintf(__tcp_trs, "REQUESTING]");
01404             break;
01405         case DHCPST_REBOOTING:
01406             fprintf(__tcp_trs, "REBOOTING %s]", inet_ntoa(li));
01407             break;
01408         case DHCPST_BOUND:
01409             fprintf(__tcp_trs, "BOUND %lu]", NutGetSeconds() - lt);
01410             break;
01411         case DHCPST_RENEWING:
01412             fprintf(__tcp_trs, "RENEWING %lu]", NutGetSeconds() - lt);
01413             break;
01414         case DHCPST_REBINDING:
01415             fprintf(__tcp_trs, "REBINDING %lu]", NutGetSeconds() - lt);
01416             break;
01417         case DHCPST_INFORMING:
01418             fprintf(__tcp_trs, "INFORMING]");
01419             break;
01420         case DHCPST_RELEASING:
01421             fprintf(__tcp_trs, "RELEASING]");
01422             break;
01423         case DHCPST_IDLE:
01424             if (dhcpError) {
01425                 fprintf(__tcp_trs, "ERROR %u]", dhcpError);
01426             } else {
01427                 fprintf(__tcp_trs, "IDLE]");
01428             }
01429             break;
01430         default:
01431             fprintf(__tcp_trs, "UNKNOWN %u]", dhcpState);
01432             break;
01433         }
01434     }
01435 }
01436 #endif
01437 
01451 THREAD(NutDhcpClient, arg)
01452 {
01453     DYNCFG *reply = 0;
01454     UDPSOCKET *sock = 0;
01455     BOOTP *bp = 0;
01456     int n;
01457     uint32_t xid;
01458     IFNET *nif;
01459     uint16_t secs = 0;
01460     uint32_t aqsTime = NutGetSeconds();
01461     uint32_t leaseTime = 0;
01462     uint32_t napTime;
01463     ureg_t retries;
01464     uint32_t tmo = MIN_DHCP_WAIT;
01465     uint32_t last_ip = confnet.cdn_ip_addr;
01466     uint32_t server_ip;
01467 
01468     
01469 
01470 
01471 
01472 #ifdef __arm__
01473     nif = dhcpDev->dev_icb;
01474 #else
01475     nif = ((NUTDEVICE *) arg)->dev_icb;
01476 #endif
01477 
01478     
01479 
01480 
01481 
01482 
01483 
01484 
01485     xid = 0;
01486     for (retries = 0; retries < sizeof(xid); retries++) {
01487         xid <<= 8;
01488         xid += nif->if_mac[5 - retries];
01489     }
01490     retries = 0;
01491 
01492     for (;;) {
01493 
01494 #ifdef NUTDEBUG
01495         DhcpStateDebug( 0, dhcpState, last_ip, leaseTime, retries);
01496 #endif
01497 
01498         
01499 
01500 
01501         server_ip = INADDR_BROADCAST;   
01502         if (retries) {
01503             
01504             tmo += tmo;
01505             if (tmo > MAX_DHCP_WAIT) {
01506                 tmo = MAX_DHCP_WAIT;
01507             }
01508         } else {
01509             
01510             tmo = MIN_DHCP_WAIT;
01511             
01512 
01513 
01514 
01515             if (dhcpState != DHCPST_REQUESTING) {
01516                 xid++;
01517             }
01518 
01519             
01520 
01521             if (dhcpConfig && dhcpConfig->dyn_sid) {
01522                 server_ip = dhcpConfig->dyn_sid;
01523             }
01524         }
01525 
01526         
01527 
01528 
01529         if (dhcpState != DHCPST_IDLE && dhcpApiTimeout != NUT_WAIT_INFINITE) {
01530             uint32_t tt = NutGetMillis() - dhcpApiStart;
01531 
01532             if (dhcpApiTimeout <= tt) {
01533                 dhcpError = DHCPERR_TIMEOUT;
01534                 dhcpState = DHCPST_IDLE;
01535                 continue;
01536             }
01537             if ((tt = dhcpApiTimeout - tt) < tmo) {
01538                 tmo = tt;
01539             }
01540         }
01541 
01542         
01543 
01544 
01545         if ((dhcpState == DHCPST_SELECTING) || (dhcpState == DHCPST_RENEWING) || (dhcpState == DHCPST_REBINDING)) {
01546             
01547             if (retries) {
01548                 if (NutGetSeconds() - aqsTime > 0xffffUL) {
01549                     secs = 0xffff;
01550                 } else {
01551                     secs = (uint16_t) (NutGetSeconds() - aqsTime);
01552                 }
01553             }
01554             
01555             else {
01556                 aqsTime = NutGetSeconds();
01557                 secs = 0;
01558             }
01559         }
01560 
01561         
01562 
01563 
01564         if ((dhcpState == DHCPST_BOUND) || (dhcpState == DHCPST_IDLE)) {
01565             if (sock) {
01566                 NutUdpDestroySocket(sock);
01567                 sock = 0;
01568             }
01569             if (bp) {
01570                 free(bp);
01571                 bp = 0;
01572             }
01573         }
01574 
01575         
01576 
01577 
01578         else {
01579             
01580 
01581 
01582             if (dhcpConfig == 0 && nif->if_local_ip) {
01583                 
01584 
01585                 dhcpState = DHCPST_IDLE;
01586                 continue;
01587             }
01588 
01589             if ((sock == 0) || (bp == 0)) {
01590                 if (sock == 0) {
01591                     sock = NutUdpCreateSocket(DHCP_CLIENTPORT);
01592                 }
01593                 if (bp == 0) {
01594                     bp = malloc(sizeof(BOOTP));
01595                 }
01596                 if ((sock == 0) || (bp == 0)) {
01597                     
01598                     dhcpError = DHCPERR_SYSTEM;
01599                     dhcpState = DHCPST_IDLE;
01600                     
01601 
01602 
01603                     continue;
01604                 }
01605 #if MAX_DHCP_BUFSIZE
01606                 {
01607                     uint16_t max_ms = MAX_DHCP_BUFSIZE;
01608                     NutUdpSetSockOpt(sock, SO_RCVBUF, &max_ms, sizeof(max_ms));
01609                 }
01610 #endif
01611             }
01612         }
01613 
01614         
01615 
01616 
01617         if (dhcpState == DHCPST_INIT) {
01618             
01619             retries = 0;
01620             
01621             xid++;
01622             
01623             if ((last_ip & confnet.cdn_ip_mask) == 0) {
01624                 
01625                 dhcpState = DHCPST_SELECTING;
01626             } else {
01627                 
01628 
01629                 dhcpState = DHCPST_REBOOTING;
01630             }
01631         }
01632 
01633 #ifdef NUTDEBUG
01634 
01635 #endif
01636         
01637 
01638 
01639         else if (dhcpState == DHCPST_SELECTING) {
01640 #ifdef NUTDEBUG
01641             if (__tcp_trf & NET_DBG_DHCP) fprintf(__tcp_trs, "[SEL: TICK %p]", dhcpConfig);
01642 #endif
01643 
01644             if (retries++ > MAX_DCHP_RETRIES) {
01645                 if( dhcpConfig) {
01646                     
01647                     reply = 0;
01648                     leaseTime = aqsTime;
01649                     dhcpState = DHCPST_BOUND;
01650                 }
01651                 else {
01652                     
01653                     dhcpError = DHCPERR_TIMEOUT;
01654                     dhcpState = DHCPST_IDLE;
01655                 }
01656             }
01657             
01658             else if (DhcpBroadcastDiscover(sock, bp, xid, last_ip, secs) < 0) {
01659                 
01660 #ifdef NUTDEBUG
01661                 if (__tcp_trf & NET_DBG_DHCP) fprintf(__tcp_trs, "[SEL-TXERR]");
01662 #endif
01663                 dhcpState = DHCPST_IDLE;
01664             } else {
01665                 
01666                 while ((n = DhcpRecvMessage(sock, xid, bp, tmo)) > 0) {
01667                     
01668                     if ((dhcpConfig = CheckOffer(dhcpConfig, bp, n)) != 0) {
01669 #ifdef NUTDEBUG
01670                         if (__tcp_trf & NET_DBG_DHCP) fprintf(__tcp_trs, "[SEL-OFFER n=%d]", n);
01671 #endif
01672                         
01673 
01674                         if (dhcpApiTimeout < MIN_DHCP_WAIT * 3) {
01675 #ifdef NUTDEBUG
01676                             if (__tcp_trf & NET_DBG_DHCP) fprintf(__tcp_trs, "[NOTL]");
01677 #endif
01678                             break;
01679                         }
01680                         
01681 
01682                         tmo = MIN_DHCP_WAIT;
01683                     }
01684                 }
01685                 
01686                 if (n < 0) {
01687 #ifdef NUTDEBUG
01688                     if (__tcp_trf & NET_DBG_DHCP) fprintf(__tcp_trs, "[SEL-FATERR]");
01689 #endif
01690                     dhcpState = DHCPST_IDLE;
01691                 }
01692                 
01693 
01694                 else if (dhcpConfig) {
01695                     
01696                     retries = MAX_DCHP_RETRIES+1;
01697 
01698 #ifdef NUTDEBUG
01699                     if (__tcp_trf & NET_DBG_DHCP) fprintf(__tcp_trs, "[SEL-WAIT]");
01700 #endif
01701                 }
01702             }
01703         }
01704 
01705         
01706 
01707 
01708         else if (dhcpState == DHCPST_REQUESTING) {
01709             if (retries++ > MAX_DCHP_RETRIES) {
01710                 
01711                 dhcpState = DHCPST_INIT;
01712             }
01713             
01714 
01715             else if (DhcpBroadcastRequest(sock, bp, xid, 0, dhcpConfig->dyn_yiaddr, dhcpConfig->dyn_sid, secs) < 0) {
01716                 
01717                 dhcpState = DHCPST_IDLE;
01718             } else if ((n = DhcpRecvMessage(sock, xid, bp, tmo)) < 0) {
01719                 
01720                 dhcpState = DHCPST_IDLE;
01721             } else if (n > 0 && (reply = ParseReply(bp, n)) != 0) {
01722                 
01723                 if (reply->dyn_msgtyp == DHCP_ACK) {
01724                     ReleaseDynCfg(dhcpConfig);
01725                     dhcpConfig = reply;
01726                     reply = 0;
01727                     leaseTime = aqsTime;
01728                     dhcpState = DHCPST_BOUND;
01729                 }
01730                 
01731 
01732                 else if (reply->dyn_msgtyp == DHCP_NAK) {
01733 #ifdef NUTDEBUG
01734         if (__tcp_trf & NET_DBG_DHCP) fprintf(__tcp_trs, "[DHCP-NAK1]");
01735 #endif
01736                     dhcpState = DHCPST_INIT;
01737                 }
01738             }
01739         }
01740 
01741         
01742 
01743 
01744         else if (dhcpState == DHCPST_REBOOTING) {
01745             if (++retries > MAX_DCHP_RETRIES) {
01746                 
01747                 last_ip = 0;
01748                 dhcpState = DHCPST_INIT;
01749             }
01750             
01751             else if (DhcpBroadcastRequest(sock, bp, xid, 0, last_ip, 0, secs) < 0) {
01752                 
01753 #ifdef NUTDEBUG
01754                     if (__tcp_trf & NET_DBG_DHCP) fprintf(__tcp_trs, "[BC-FATAL]");
01755 #endif
01756                 dhcpState = DHCPST_IDLE;
01757             } else if ((n = DhcpRecvMessage(sock, xid, bp, tmo)) < 0) {
01758                 
01759 #ifdef NUTDEBUG
01760                     if (__tcp_trf & NET_DBG_DHCP) fprintf(__tcp_trs, "[RCV-FATAL]");
01761 #endif
01762                 dhcpState = DHCPST_IDLE;
01763             } else if (n > 0 && (reply = ParseReply(bp, n)) != 0) {
01764                 if (reply->dyn_msgtyp == DHCP_ACK) {
01765                     ReleaseDynCfg(dhcpConfig);
01766                     dhcpConfig = reply;
01767                     reply = 0;
01768                     leaseTime = aqsTime;
01769                     dhcpState = DHCPST_BOUND;
01770 #ifdef NUTDEBUG
01771                     if (__tcp_trf & NET_DBG_DHCP) fprintf(__tcp_trs, "[OK]");
01772 #endif
01773                 } else if (reply->dyn_msgtyp == DHCP_NAK) {
01774                     
01775 
01776 
01777 #ifdef NUTDEBUG
01778                     if (__tcp_trf & NET_DBG_DHCP) fprintf(__tcp_trs, "[DHCP-NAK2]");
01779 #endif
01780                     last_ip = 0;
01781                     dhcpState = DHCPST_INIT;
01782                 }
01783             }
01784         }
01785 
01786         
01787 
01788 
01789         else if (dhcpState == DHCPST_BOUND) {
01790             retries = 0;
01791             NutEventBroadcast(&dhcpDone);
01792             if (dhcpConfig->dyn_renewalTime <= NutGetSeconds() - leaseTime) {
01793                 dhcpState = DHCPST_RENEWING;
01794             } else {
01795                 
01796                 napTime = dhcpConfig->dyn_renewalTime - (NutGetSeconds() - leaseTime);
01797                 if (napTime > MAX_DHCP_NAPTIME) {
01798                     napTime = MAX_DHCP_NAPTIME;
01799                 }
01800                 NutEventWait(&dhcpWake, napTime * 1000UL);
01801             }
01802         }
01803 
01804         
01805 
01806 
01807         else if (dhcpState == DHCPST_RENEWING) {
01808             retries++;
01809             if (tmo / 1000 > dhcpConfig->dyn_rebindTime - (NutGetSeconds() - leaseTime)) {
01810                 tmo = dhcpConfig->dyn_rebindTime - (NutGetSeconds() - leaseTime) * 1000;
01811             }
01812             if (dhcpConfig->dyn_rebindTime <= NutGetSeconds() - leaseTime) {
01813                 retries = 0;
01814                 dhcpState = DHCPST_REBINDING;
01815             }
01816             
01817 
01818             else if (DhcpSendRequest(sock, dhcpConfig->dyn_sid, bp, xid, dhcpConfig->dyn_yiaddr, dhcpConfig->dyn_yiaddr, 0, secs) <
01819                      0) {
01820                 
01821                 retries = 0;
01822                 dhcpState = DHCPST_REBINDING;
01823             } else if ((n = DhcpRecvMessage(sock, xid, bp, tmo)) < 0) {
01824                 
01825                 dhcpState = DHCPST_IDLE;
01826             } else if (n > 0 && (reply = ParseReply(bp, n)) != 0) {
01827                 if (reply->dyn_msgtyp == DHCP_ACK) {
01828                     
01829                     ReleaseDynCfg(dhcpConfig);
01830                     dhcpConfig = reply;
01831                     reply = 0;
01832                     leaseTime = aqsTime;
01833                     dhcpState = DHCPST_BOUND;
01834                 } else if (reply->dyn_msgtyp == DHCP_NAK) {
01835                     
01836 #ifdef NUTDEBUG
01837                     if (__tcp_trf & NET_DBG_DHCP) fprintf(__tcp_trs, "[DHCP-UXNAK]");
01838 #endif
01839                     retries = 0;
01840                     dhcpState = DHCPST_REBINDING;
01841                 }
01842             }
01843         }
01844 
01845         
01846 
01847 
01848         else if (dhcpState == DHCPST_REBINDING) {
01849             retries++;
01850             if (tmo > dhcpConfig->dyn_rebindTime - (NutGetSeconds() - leaseTime)) {
01851                 tmo = dhcpConfig->dyn_rebindTime - NutGetSeconds() - leaseTime;
01852             }
01853             if (dhcpConfig->dyn_rebindTime <= NutGetSeconds() - leaseTime) {
01854                 retries = 0;
01855                 dhcpState = DHCPST_REBINDING;
01856             }
01857             
01858 
01859             else if (DhcpBroadcastRequest(sock, bp, xid, dhcpConfig->dyn_yiaddr, dhcpConfig->dyn_yiaddr, 0, secs) < 0) {
01860                 
01861                 dhcpState = DHCPST_IDLE;
01862             } else if ((n = DhcpRecvMessage(sock, xid, bp, tmo)) < 0) {
01863                 
01864                 dhcpState = DHCPST_IDLE;
01865             } else if (n > 0 && (reply = ParseReply(bp, n)) != 0) {
01866                 if (reply->dyn_msgtyp == DHCP_ACK) {
01867                     
01868                     ReleaseDynCfg(dhcpConfig);
01869                     dhcpConfig = reply;
01870                     reply = 0;
01871                     leaseTime = aqsTime;
01872                     dhcpState = DHCPST_BOUND;
01873                 } else if (reply->dyn_msgtyp == DHCP_NAK) {
01874                     
01875 
01876 
01877 
01878 
01879 
01880 
01881 
01882 
01883 #ifdef NUTDEBUG
01884                     if (__tcp_trf & NET_DBG_DHCP) fprintf(__tcp_trs, "[DHCP-NAK3]");
01885 #endif
01886                     dhcpState = DHCPST_INIT;
01887                 }
01888             }
01889         }
01890 
01891         
01892 
01893 
01894         else if (dhcpState == DHCPST_INFORMING) {
01895             if (retries++ > MAX_DCHP_RETRIES) {
01896                 dhcpState = DHCPST_IDLE;
01897             } else if (DhcpSendInform(sock, server_ip, bp, xid, nif->if_local_ip) < 0) {
01898                 if (server_ip == INADDR_BROADCAST) {
01899                     dhcpState = DHCPST_IDLE;
01900                 }
01901             } else if ((n = DhcpRecvMessage(sock, xid, bp, tmo)) != 0) {
01902                 if (n > 0 &&    
01903                     (reply = ParseReply(bp, n)) != 0 && 
01904                     reply->dyn_msgtyp == DHCP_ACK) {    
01905                     
01906                     ReleaseDynCfg(dhcpConfig);
01907                     dhcpConfig = reply;
01908                     reply = 0;
01909                 }
01910                 dhcpState = DHCPST_IDLE;
01911             }
01912         }
01913 
01914         
01915 
01916 
01917         else if (dhcpState == DHCPST_RELEASING) {
01918             if (dhcpConfig == 0 ||      
01919                 retries++ > MAX_DCHP_RELEASE_RETRIES || 
01920                 DhcpSendRelease(sock, server_ip, bp, xid, dhcpConfig->dyn_yiaddr, dhcpConfig->dyn_sid) < 0) {
01921                 if (server_ip == INADDR_BROADCAST) {
01922                     dhcpState = DHCPST_IDLE;
01923                 }
01924             } else if ((n = DhcpRecvMessage(sock, xid, bp, tmo)) < 0) {
01925                 
01926                 dhcpState = DHCPST_IDLE;
01927             } else if (n > 0 && (reply = ParseReply(bp, n)) != 0) {
01928                 if (reply->dyn_msgtyp == DHCP_ACK) {
01929                     dhcpState = DHCPST_IDLE;
01930                 } else if (reply->dyn_msgtyp == DHCP_NAK) {
01931 #ifdef NUTDEBUG
01932                     if (__tcp_trf & NET_DBG_DHCP) fprintf(__tcp_trs, "[DHCP-FNAK]");
01933 #endif
01934                     dhcpState = DHCPST_IDLE;
01935                 }
01936             }
01937         }
01938 
01939         
01940 
01941 
01942 
01943 
01944 
01945 
01946         else if (dhcpState == DHCPST_IDLE) {
01947             ReleaseDynCfg(dhcpConfig);
01948             dhcpConfig = 0;
01949             retries = 0;
01950             NutEventBroadcast(&dhcpDone);
01951             NutEventWait(&dhcpWake, NUT_WAIT_INFINITE);
01952         }
01953 
01954         
01955         if (reply) {
01956             ReleaseDynCfg(reply);
01957             reply = 0;
01958         }
01959     }
01960 }
01961 
01976 static int DhcpKick(CONST char *name, uint8_t state, uint32_t timeout)
01977 {
01978     NUTDEVICE *dev;
01979     IFNET *nif;
01980 
01981     
01982     if ((dev = NutDeviceLookup(name)) == 0 ||   
01983         dev->dev_type != IFTYP_NET ||   
01984         (nif = dev->dev_icb) == 0 ||    
01985         nif->if_type != IFT_ETHER) {    
01986         dhcpError = DHCPERR_BADDEV;
01987         return -1;
01988     }
01989 
01990     
01991     dhcpApiStart = NutGetMillis();
01992     dhcpApiTimeout = timeout;
01993 
01994     dhcpState = state;
01995     if (dhcpThread == 0) {
01996 #ifdef __arm__
01997         dhcpDev = dev;
01998 #endif
01999         dhcpThread = NutThreadCreate("dhcpc", NutDhcpClient, dev,
02000             (NUT_THREAD_DHCPSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD);
02001     }
02002     NutEventPost(&dhcpWake);
02003     NutEventWait(&dhcpDone, NUT_WAIT_INFINITE);
02004 
02005     return 0;
02006 }
02007 
02047 int NutDhcpIfConfig(CONST char *name, uint8_t * mac, uint32_t timeout)
02048 {
02049     uint8_t mac0[6];
02050     uint8_t macF[6];
02051     NUTDEVICE *dev;
02052     IFNET *nif;
02053 
02054     
02055 
02056 
02057     if ((dev = NutDeviceLookup(name)) == 0 ||   
02058         dev->dev_type != IFTYP_NET ||   
02059         (nif = dev->dev_icb) == 0 ||    
02060         nif->if_type != IFT_ETHER) {    
02061         dhcpError = DHCPERR_BADDEV;
02062         return -1;
02063     }
02064 
02065     
02066 
02067 
02068 
02069     memset(mac0, 0x00, sizeof(mac0));   
02070     memset(macF, 0xFF, sizeof(macF));   
02071     if (memcmp(nif->if_mac, mac0, 6) == 0 || memcmp(nif->if_mac, macF, 6) == 0) {
02072         
02073 
02074 
02075 
02076         if (mac) {
02077             memcpy(confnet.cdn_mac, mac, sizeof(confnet.cdn_mac));
02078         }
02079 
02080         
02081 
02082 
02083 
02084 
02085 
02086         else if (NutNetLoadConfig(name)) {
02087             dhcpError = DHCPERR_NOMAC;
02088             return -1;
02089         }
02090 
02091         
02092 
02093 
02094 
02095         memcpy(nif->if_mac, confnet.cdn_mac, 6);
02096         NutSleep(500);
02097     }
02098 
02099     
02100 
02101 
02102 
02103 
02104     nif->if_local_ip = 0;
02105     nif->if_mask = confnet.cdn_ip_mask;
02106 
02107     
02108 
02109 
02110     if ((confnet.cdn_cip_addr & confnet.cdn_ip_mask) != 0) {
02111         
02112         (void)NutDhcpRelease(name, (3*MIN_DHCP_WAIT));
02113         confnet.cdn_ip_addr = confnet.cdn_cip_addr;
02114         NutNetIfConfig2(name,
02115                         confnet.cdn_mac,
02116                         confnet.cdn_ip_addr,
02117                         confnet.cdn_ip_mask,
02118                         confnet.cdn_gateway);
02119         return 0;
02120     }
02121 
02122     
02123 
02124 
02125 
02126 
02127     if (DhcpKick(name, DHCPST_INIT, timeout) == 0) {
02128         
02129 
02130 
02131 
02132         if (dhcpState == DHCPST_BOUND) {
02133 #ifdef NUTDEBUG
02134             if (__tcp_trf & NET_DBG_DHCP) {
02135                 fprintf(__tcp_trs, "[DHCP-Config %s]", inet_ntoa(dhcpConfig->dyn_yiaddr));
02136             }
02137 #endif
02138             NutNetIfSetup(dev, dhcpConfig->dyn_yiaddr, dhcpConfig->dyn_netmask, dhcpConfig->dyn_gateway);
02139             NutDnsConfig2(NULL, NULL, dhcpConfig->dyn_pdns, dhcpConfig->dyn_sdns);
02140             return 0;
02141         }
02142 
02143         
02144 
02145 
02146 
02147         if (nif->if_local_ip) {
02148 #ifdef NUTDEBUG
02149             if (__tcp_trf & NET_DBG_DHCP) {
02150                 fprintf(__tcp_trs, "[DHCP-External %s]", inet_ntoa(nif->if_local_ip));
02151             }
02152 #endif
02153             return 0;
02154         }
02155 
02156         
02157 
02158 
02159 
02160         if ((confnet.cdn_ip_addr & confnet.cdn_ip_mask) != 0) {
02161 #ifdef NUTDEBUG
02162             if (__tcp_trf & NET_DBG_DHCP) {
02163                 fprintf(__tcp_trs, "[DHCP-Reusing %s]", inet_ntoa(confnet.cdn_ip_addr));
02164             }
02165 #endif
02166             NutNetIfConfig2(name, confnet.cdn_mac, confnet.cdn_ip_addr, confnet.cdn_ip_mask, confnet.cdn_gateway);
02167             return 0;
02168         }
02169     }
02170     return -1;
02171 }
02172 
02189 int NutDhcpRelease(CONST char *name, uint32_t timeout)
02190 {
02191     
02192     if (dhcpState != DHCPST_BOUND) {
02193         dhcpError = DHCPERR_STATE;
02194         return -1;
02195     }
02196 
02197     
02198     return DhcpKick(name, DHCPST_RELEASING, timeout);
02199 }
02200 
02211 int NutDhcpInform(CONST char *name, uint32_t timeout)
02212 {
02213     
02214     if (dhcpState != DHCPST_IDLE) {
02215         dhcpError = DHCPERR_STATE;
02216         return -1;
02217     }
02218 
02219     
02220     return DhcpKick(name, DHCPST_INFORMING, timeout);
02221 }
02222 
02240 int NutDhcpStatus(CONST char *name)
02241 {
02242     return dhcpState;
02243 }
02244 
02263 int NutDhcpError(CONST char *name)
02264 {
02265     int rc = dhcpError;
02266     dhcpError = 0;
02267     return rc;
02268 }
02269 
02277 int NutDhcpIsConfigured(void)
02278 {
02279     return (dhcpState == DHCPST_BOUND);
02280 }
02281