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