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