00001
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
#include <stdio.h>
00071
#include <stdlib.h>
00072
#include <string.h>
00073
#include <time.h>
00074
#include <io.h>
00075
#include <ctype.h>
00076
#include <errno.h>
00077
00078
#define DHCP_COMPILATION
00079
00080
#include "wattcp.h"
00081
#include "strings.h"
00082
#include "language.h"
00083
#include "misc.h"
00084
#include "timer.h"
00085
#include "udp_dom.h"
00086
#include "netaddr.h"
00087
#include "bsdname.h"
00088
#include "ip4_out.h"
00089
#include "syslog2.h"
00090
#include "sock_ini.h"
00091
#include "printk.h"
00092
#include "tftp.h"
00093
#include "pctcp.h"
00094
#include "pcsed.h"
00095
#include "pcarp.h"
00096
#include "pcqueue.h"
00097
#include "pcdbug.h"
00098
#include "pcpkt.h"
00099
#include "pcconfig.h"
00100
#include "pcbootp.h"
00101
#include "pcdhcp.h"
00102
00103
#if defined(USE_DHCP)
00104
00105
#define BROADCAST_FLAG intel16 (0x8000)
00106
00107 BOOL dhcp_did_gratuitous_arp = FALSE;
00108
00109
static WattDHCPConfigFunc config_func = NULL;
00110
00111
static DWORD exchange_id;
00112
static DWORD router, nameserver;
00113
static DWORD dhcp_server = 0;
00114
static DWORD dhcp_renewal = 0;
00115
static DWORD dhcp_rebind = 0;
00116
static DWORD dhcp_iplease = 0;
00117
static DWORD suggest_lease = 0;
00118
static DWORD old_ip_addr = 0;
00119
00120
static BOOL bcast_flag = TRUE;
00121
static BOOL got_offer = FALSE;
00122
static BOOL configured = FALSE;
00123
static BOOL arp_check_ip = FALSE;
00124
static BOOL cfg_read = FALSE;
00125
static BOOL cfg_saved = FALSE;
00126
00127
static int dhcp_timeout = 10;
00128
static int max_retries = 3;
00129
static int discover_loops = 0;
00130
00131
static struct dhcp dhcp_in, dhcp_out;
00132
00133
static void (*DHCP_state) (
int) = NULL;
00134
static time_t renewal_timeout;
00135
static time_t rebind_timeout;
00136
static time_t lease_timeout;
00137
static DWORD send_timeout;
00138
static BOOL trace_on = FALSE;
00139
00140
static char config_file [MAX_VALUELEN+1] =
"";
00141
static sock_type *sock = NULL;
00142
00143
00144
00145
static const BYTE default_request_list[] = {
00146 DHCP_OPT_SUBNET_MASK,
00147 DHCP_OPT_ROUTERS_ON_SNET,
00148 DHCP_OPT_DNS_SRV,
00149 DHCP_OPT_COOKIE_SRV,
00150 DHCP_OPT_LPR_SRV,
00151 DHCP_OPT_HOST_NAME,
00152 DHCP_OPT_DOMAIN_NAME,
00153 DHCP_OPT_IP_DEFAULT_TTL,
00154 DHCP_OPT_IF_MTU,
00155 DHCP_OPT_ARP_CACHE_TIMEOUT,
00156 DHCP_OPT_ETHERNET_ENCAPSULATION,
00157 DHCP_OPT_TCP_DEFAULT_TTL,
00158
#if defined(USE_BSD_API)
00159
DHCP_OPT_LOG_SRV,
00160 DHCP_OPT_NBIOS_NAME_SRV,
00161 DHCP_OPT_NBIOS_NODE_TYPE,
00162 DHCP_OPT_NBIOS_SCOPE,
00163
#endif
00164
#if defined(USE_TFTP)
00165
DHCP_OPT_TFTP_SERVER,
00166 DHCP_OPT_BOOT_FILENAME
00167
#endif
00168
};
00169
00170
static struct DHCP_list request_list = {
00171 (
BYTE*) &default_request_list,
00172
sizeof (default_request_list)
00173 };
00174
00175
static struct DHCP_list extra_options = { NULL, 0 };
00176
static struct DHCP_list user_class = { NULL, 0 };
00177
static struct DHCP_list vend_class = { (
BYTE*)
"Watt-32", 7 };
00178
00179
static void DHCP_state_INIT (
int event);
00180
static void DHCP_state_BOUND (
int event);
00181
static void DHCP_state_RENEWING (
int event);
00182
static void DHCP_state_REQUESTING (
int event);
00183
static void DHCP_state_SELECTING (
int event);
00184
static void DHCP_state_REBINDING (
int event);
00185
00186
static void dhcp_fsm (
void);
00187
static void dhcp_options_add (
const BYTE *opt,
unsigned max);
00188
static void dhcp_set_timers (
void);
00189
static void change_ip_addr (
void);
00190
static BYTE *
put_request_list (
BYTE *opt,
int filled);
00191
static int write_config (
void);
00192
static void erase_config (
void);
00193
00194
#define DHCP_SEND(end) sock_fastwrite (sock, (const BYTE*)&dhcp_out, \
00195
end - (BYTE*)&dhcp_out)
00196
00197
#if defined(USE_DEBUG)
00198
#define TRACE(x) do { if (trace_on) (*_printf) x; } while (0)
00199
#define INET_NTOA(x) _inet_ntoa (NULL, x)
00200
#else
00201
#define TRACE(x) ((void)0)
00202
#define INET_NTOA(x) ((void)0)
00203
#endif
00204
00205
#if defined(USE_DEBUG)
00206
00209 static const char *
state_name (
void)
00210 {
00211
return (DHCP_state ==
DHCP_state_INIT ?
"INIT" :
00212 DHCP_state ==
DHCP_state_BOUND ?
"BOUND" :
00213 DHCP_state ==
DHCP_state_RENEWING ?
"RENEWING" :
00214 DHCP_state ==
DHCP_state_REQUESTING ?
"REQUESTING" :
00215 DHCP_state ==
DHCP_state_SELECTING ?
"SELECTING" :
00216 DHCP_state ==
DHCP_state_REBINDING ?
"REBINDING" :
"??");
00217 }
00218
00222 static const char *
period (
DWORD sec)
00223 {
00224
static char buf[20];
00225
DWORD hours = sec / 3600UL;
00226
00227
if (sec < 60UL)
00228 sprintf (buf,
"%lus", sec);
00229
else if (sec < 3600UL)
00230 sprintf (buf,
"%lu:%02lu", sec/60, sec % 60);
00231
else sprintf (buf,
"%lu:%02lu:%02lu", hours, sec/60-hours*60, sec % 60);
00232
return (buf);
00233 }
00234
#endif
00235
00239 static BYTE *
make_boot_header (
void)
00240 {
00241
DWORD my_ip = 0UL;
00242
00243
if (DHCP_state ==
DHCP_state_BOUND ||
00244 DHCP_state ==
DHCP_state_RENEWING ||
00245 DHCP_state ==
DHCP_state_REBINDING)
00246 my_ip = intel (
my_ip_addr);
00247
00248 memset (&dhcp_out, 0,
sizeof(dhcp_out));
00249
00250
_eth_get_hwtype (&dhcp_out.
dh_htype, &dhcp_out.
dh_hlen);
00251
00252 dhcp_out.
dh_op = BOOTP_REQUEST;
00253 dhcp_out.
dh_xid = exchange_id;
00254 dhcp_out.
dh_secs = 0;
00255 dhcp_out.
dh_flags = bcast_flag ? BROADCAST_FLAG : 0;
00256 dhcp_out.
dh_yiaddr = 0;
00257 dhcp_out.
dh_ciaddr = my_ip;
00258 dhcp_out.
dh_giaddr = 0;
00259 memcpy (dhcp_out.
dh_chaddr,
_eth_addr,
_eth_mac_len);
00260 *(
DWORD*) &dhcp_out.
dh_opt[0] = DHCP_MAGIC_COOKIE;
00261
return (&dhcp_out.
dh_opt[4]);
00262 }
00263
00267 static BYTE *
put_hardware_opt (
BYTE *opt)
00268 {
00269
BYTE hw_type, hw_len;
00270
00271
_eth_get_hwtype (&hw_type, &hw_len);
00272 *opt++ = DHCP_OPT_CLIENT_ID;
00273 *opt++ = hw_len + 1;
00274 *opt++ = hw_type;
00275 memcpy (opt,
_eth_addr, hw_len);
00276 opt += hw_len;
00277
return (opt);
00278 }
00279
00283 static int DHCP_discover (
void)
00284 {
00285
BYTE *opt, *start;
00286
00287 exchange_id =
set_timeout (0);
00288 opt = start =
make_boot_header();
00289 *opt++ = DHCP_OPT_MSG_TYPE;
00290 *opt++ = 1;
00291 *opt++ = DHCP_DISCOVER;
00292
00293 opt =
put_hardware_opt (opt);
00294
00295 *opt++ = DHCP_OPT_MAX_MSG_SIZE;
00296 *opt++ = 2;
00297 *(
WORD*)opt = intel16 (
sizeof(
struct dhcp));
00298 opt += 2;
00299
00300
if (suggest_lease)
00301 {
00302 *opt++ = DHCP_OPT_IP_ADDR_LEASE_TIME;
00303 *opt++ =
sizeof (suggest_lease);
00304 *(
DWORD*)opt = intel (suggest_lease);
00305 opt +=
sizeof (suggest_lease);
00306 }
00307 opt =
put_request_list (opt, opt-start);
00308 *opt++ = DHCP_OPT_END;
00309
return DHCP_SEND (opt);
00310 }
00311
00315 static int DHCP_request (BOOL renew)
00316 {
00317
BYTE *opt =
make_boot_header();
00318
00319 *opt++ = DHCP_OPT_MSG_TYPE;
00320 *opt++ = 1;
00321 *opt++ = DHCP_REQUEST;
00322
00323
if (!renew)
00324 {
00325 *opt++ = DHCP_OPT_SRV_IDENTIFIER;
00326 *opt++ =
sizeof (dhcp_server);
00327 *(
DWORD*)opt = intel (dhcp_server);
00328 opt +=
sizeof (dhcp_server);
00329 *opt++ = DHCP_OPT_REQUESTED_IP_ADDR;
00330 *opt++ =
sizeof (
my_ip_addr);
00331 *(
DWORD*)opt = intel (
my_ip_addr);
00332 opt +=
sizeof (
my_ip_addr);
00333 }
00334
00335
00336
00337 opt =
put_hardware_opt (opt);
00338
00339
00340
00341
00342
#if 0
00343
if (dhcp_iplease && dhcp_iplease < (
DWORD)-1)
00344 {
00345 *opt++ = DHCP_OPT_IP_ADDR_LEASE_TIME;
00346 *opt++ =
sizeof (dhcp_iplease);
00347 *(
DWORD*)opt = intel (dhcp_iplease);
00348 opt +=
sizeof (dhcp_iplease);
00349 }
00350
#endif
00351
00352
if (user_class.data)
00353 {
00354 *opt++ = DHCP_OPT_USER_CLASS;
00355 *opt++ = user_class.size;
00356 memcpy (opt, user_class.data, user_class.size);
00357 opt += user_class.size;
00358 }
00359
00360
if (vend_class.data)
00361 {
00362 *opt++ = DHCP_OPT_CLASS_ID;
00363 *opt++ = vend_class.size;
00364 memcpy (opt, vend_class.data, vend_class.size);
00365 opt += vend_class.size;
00366 }
00367
00368 *opt++ = DHCP_OPT_END;
00369 TRACE ((
"DHCP req: renew(%d) dst(%s)\n",
00370 renew, INET_NTOA(sock->
udp.hisaddr)));
00371
return DHCP_SEND (opt);
00372 }
00373
00379 static int DHCP_release_decline (
int msg_type,
const char *msg)
00380 {
00381
BYTE *opt;
00382
00383 exchange_id =
set_timeout (0);
00384 opt =
make_boot_header();
00385
00386 *opt++ = DHCP_OPT_MSG_TYPE;
00387 *opt++ = 1;
00388 *opt++ = msg_type;
00389 *opt++ = DHCP_OPT_SRV_IDENTIFIER;
00390 *opt++ =
sizeof (dhcp_server);
00391 *(
DWORD*)opt = intel (dhcp_server);
00392 opt +=
sizeof (dhcp_server);
00393
00394
if (msg)
00395 {
00396
const BYTE *end = &dhcp_out.
dh_opt [
sizeof(dhcp_out.
dh_opt)-1];
00397 size_t len = strlen (msg);
00398
00399 len = min (len, 255);
00400 len = min (len, (size_t)(end-opt-3));
00401 *opt++ = DHCP_OPT_MSG;
00402 *opt++ = (
BYTE)len;
00403 memcpy (opt, msg, len);
00404 opt += len;
00405 }
00406 *opt++ = DHCP_OPT_END;
00407
return DHCP_SEND (opt);
00408 }
00409
00417 static BOOL
DHCP_arp_check (
DWORD my_ip)
00418 {
00419
eth_address eth;
00420
DWORD bcast_ip;
00421
00422
if (
_pktserial)
00423
return (TRUE);
00424
00425 bcast_ip = my_ip | ~
sin_mask;
00426
00427
00428
00429
_arp_reply (NULL, intel(bcast_ip), intel(my_ip));
00430 dhcp_did_gratuitous_arp = TRUE;
00431
00432
if (!arp_check_ip)
00433
return (TRUE);
00434
00435
00436
00437 TRACE ((
"Checking ARP.."));
00438
00439
if (!
_arp_check_own_ip(ð))
00440 {
00441 TRACE ((
"station %s claims to have my IP %s! Declining..\n",
00442
MAC_address(ð), INET_NTOA(my_ip)));
00443
if (!trace_on)
00444 outsnl (
"Someone claims to have my IP! Declining..\7");
00445
return (FALSE);
00446 }
00447 TRACE ((
"\n"));
00448
return (TRUE);
00449 }
00450
00455 static int DHCP_offer (
const struct dhcp *in)
00456 {
00457
int len;
00458
DWORD ip;
00459
const BYTE *opt = (
const BYTE*) &in->
dh_opt[4];
00460
00461
while (opt < in->
dh_opt +
sizeof(in->
dh_opt))
00462 {
00463
switch (*opt)
00464 {
00465
case DHCP_OPT_PAD:
00466 opt++;
00467
continue;
00468
00469
case DHCP_OPT_SUBNET_MASK:
00470
sin_mask = intel (*(
DWORD*)(opt+2));
00471 TRACE ((
"Net-mask: %s\n", INET_NTOA(
sin_mask)));
00472
break;
00473
00474
case DHCP_OPT_TIME_OFFSET:
00475
#if defined(USE_DEBUG)
00476
{
00477
long ofs = *(
long*)(opt+2);
00478 TRACE ((
"Time-ofs: %.2fh\n", (
double)ofs/3600.0));
00479 }
00480
#endif
00481
break;
00482
00483
case DHCP_OPT_ROUTERS_ON_SNET:
00484 {
00485
static BOOL gw_added = FALSE;
00486
00487
if (!gw_added)
00488
_arp_kill_gateways();
00489 gw_added = TRUE;
00490 router = intel (*(
DWORD*)(opt+2));
00491
_arp_add_gateway (NULL, router);
00492 TRACE ((
"Gateway: %s\n", INET_NTOA(router)));
00493 }
00494
break;
00495
00496
case DHCP_OPT_DNS_SRV:
00497 {
00498
static BOOL dns_added = FALSE;
00499
00500
for (len = 0; len < *(opt+1); len +=
sizeof(
DWORD))
00501 {
00502 ip = intel (*(
DWORD*)(opt+2+len));
00503
if (!dns_added)
00504 last_nameserver = 0;
00505
00506
00507
00508
00509
00510
if (len == 0)
00511 {
00512 nameserver = ip;
00513 _add_server (&last_nameserver,
00514 MAX_NAMESERVERS, def_nameservers, ip);
00515 }
00516 dns_added = TRUE;
00517 TRACE ((
"DNS: %s\n", INET_NTOA(ip)));
00518 }
00519 }
00520
break;
00521
00522
#if defined(USE_BSD_API)
00523
case DHCP_OPT_LOG_SRV:
00524
if (!syslog_host_name[0] &&
00525 opt[1] % 4 == 0)
00526 {
00527 ip = intel (*(
DWORD*)(opt+2));
00528
StrLcpy (syslog_host_name,
_inet_ntoa(NULL,ip),
00529
sizeof(syslog_host_name));
00530 TRACE ((
"Syslog: %s\n", syslog_host_name));
00531 }
00532
break;
00533
00534
case DHCP_OPT_NBIOS_NAME_SRV:
00535 ip = intel (*(
DWORD*)(opt+2));
00536 TRACE ((
"WINS: %s\n", INET_NTOA(ip)));
00538
break;
00539
00540
case DHCP_OPT_NBIOS_NODE_TYPE:
00541 TRACE ((
"NBT node: %02X\n", opt[2]));
00542
break;
00543
00544
case DHCP_OPT_NBIOS_SCOPE:
00545 TRACE ((
"NBT scope: %.*s\n", opt[1], opt+2));
00546
break;
00547
#endif
00548
case DHCP_OPT_HOST_NAME:
00549
00550
00551 len = min (opt[1],
sizeof(
hostname));
00552 memcpy (
hostname, opt+2, len);
00553
hostname[len] =
'\0';
00554 TRACE ((
"Host name: `%s'\n",
hostname));
00555
break;
00556
00557
case DHCP_OPT_DOMAIN_NAME:
00558 len = min (opt[1],
sizeof(
defaultdomain)-1);
00559
setdomainname ((
const char*)(opt+2), len+1);
00560 TRACE ((
"Domain: `%s'\n", def_domain));
00561
break;
00562
00563
case DHCP_OPT_IP_DEFAULT_TTL:
00564
case DHCP_OPT_TCP_DEFAULT_TTL:
00565
_default_ttl = opt[2];
00566
break;
00567
00568
case DHCP_OPT_MSG_TYPE:
00569
if (opt[2] == DHCP_OFFER)
00570 got_offer = TRUE;
00571
break;
00572
00573
case DHCP_OPT_MSG:
00574 outsn ((
const char*)(opt+2), *(opt+1));
00575
break;
00576
00577
case DHCP_OPT_SRV_IDENTIFIER:
00578 dhcp_server = intel (*(
DWORD*)(opt+2));
00579 TRACE ((
"Server: %s\n", INET_NTOA(dhcp_server)));
00580
break;
00581
00582
case DHCP_OPT_IP_ADDR_LEASE_TIME:
00583 dhcp_iplease = intel (*(
DWORD*)(opt+2));
00584 TRACE ((
"IP lease: %s\n",
period(dhcp_iplease)));
00585
break;
00586
00587
case DHCP_OPT_T1_VALUE:
00588 dhcp_renewal = intel (*(
DWORD*)(opt+2));
00589 TRACE ((
"Renewal: %s\n",
period(dhcp_renewal)));
00590
break;
00591
00592
case DHCP_OPT_T2_VALUE:
00593 dhcp_rebind = intel (*(
DWORD*)(opt+2));
00594 TRACE ((
"Rebind: %s\n",
period(dhcp_rebind)));
00595
break;
00596
00597
case DHCP_OPT_TCP_KEEPALIVE_INTERVAL:
00598
#if !defined(USE_UDP_ONLY)
00599
tcp_keep_intvl = intel (*(
DWORD*)(opt+2));
00600
#endif
00601
break;
00602
00603
case DHCP_OPT_OVERLOAD:
00604
switch (opt[2])
00605 {
00606
case 1:
00607 TRACE ((
"Overload: `dh_file' options\n"));
00608
dhcp_options_add (in->
dh_file,
sizeof(in->
dh_file));
00609
break;
00610
case 2:
00611 TRACE ((
"Overload: `dh_sname' options\n"));
00612
dhcp_options_add (in->
dh_sname,
sizeof(in->
dh_sname));
00613
break;
00614
case 3:
00615 TRACE ((
"Overload: `dh_file/dh_sname' options\n"));
00616
dhcp_options_add (in->
dh_file,
sizeof(in->
dh_file));
00617
dhcp_options_add (in->
dh_sname,
sizeof(in->
dh_sname));
00618
break;
00619 }
00620
break;
00621
00622
#if defined(USE_TFTP)
00623
case DHCP_OPT_TFTP_SERVER:
00624 {
00625
const char *serv;
00626 len = opt[1];
00627 serv = tftp_set_server ((
const char*)(opt+2), len);
00628 TRACE ((
"TFTP-serv: `%s'\n", serv));
00629 }
00630
break;
00631
00632
case DHCP_OPT_BOOT_FILENAME:
00633 {
00634
const char *file;
00635 len = opt[1];
00636 file = tftp_set_boot_fname ((
const char*)(opt+2), len);
00637 TRACE ((
"BOOT-file: `%s'\n", file));
00638 }
00639
break;
00640
#endif
00641
00642
case DHCP_OPT_USER_CLASS:
00643
case DHCP_OPT_CLASS_ID:
00644
break;
00645
00646
case DHCP_OPT_GRUB_MENU:
00647 TRACE ((
"GRUB: %.*s\n", opt[1], opt+2));
00648
break;
00649
00650
case DHCP_OPT_ETHERNET_ENCAPSULATION:
00651 TRACE ((
"Encap: %s\n", opt[2] ?
"IEEE 802.3" :
"Ethernet II"));
00652
if (opt[2] != 0)
00653 outsnl (_LANG(
"Only Ethernet II encapsulation supported"));
00654
break;
00655
00656
case DHCP_OPT_END:
00657 TRACE ((
"got end-option\n"));
00658
return (got_offer);
00659
00660
default:
00661 TRACE ((
"Ignoring option %d\n", *opt));
00662
break;
00663 }
00664 opt += *(opt+1) + 2;
00665 }
00666
00667
if (extra_options.data)
00668 {
00669
struct dhcp ext;
00670
00671 len = min (extra_options.size,
sizeof(ext.
dh_opt));
00672 extra_options.data [len] = DHCP_OPT_END;
00673 memcpy (ext.
dh_opt, extra_options.data, len);
00674
DHCP_offer (&ext);
00675 }
00676
return (got_offer);
00677 }
00678
00682 static int DHCP_is_ack (
void)
00683 {
00684
const BYTE *opt = (
const BYTE*) &dhcp_in.
dh_opt[4];
00685
00686
return (opt[0] == DHCP_OPT_MSG_TYPE && opt[1] == 1 && opt[2] == DHCP_ACK);
00687 }
00688
00692 static int DHCP_is_nack (
void)
00693 {
00694
const BYTE *opt = (
const BYTE*) &dhcp_in.
dh_opt[4];
00695
00696
return (opt[0] == DHCP_OPT_MSG_TYPE && opt[1] == 1 && opt[2] == DHCP_NAK);
00697 }
00698
00705 void DHCP_release (BOOL force)
00706 {
00707
if (force)
00708 {
00709 TRACE ((
"Sending DHCP release 01\n"));
00710
DHCP_release_decline (DHCP_RELEASE, NULL);
00711 }
00712
else if (configured)
00713 {
00714
00715
00716
00717
00718
if (!(cfg_saved &&
00719 (lease_timeout && (lease_timeout - time(NULL) > DHCP_MIN_LEASE))))
00720 {
00721 TRACE ((
"Sending DHCP release 02\n"));
00722
DHCP_release_decline (DHCP_RELEASE, NULL);
00723 }
00724 }
00725
delwattcpd (
dhcp_fsm);
00726
if (sock)
00727 {
00728
sock_close (sock);
00729 free (sock);
00730 sock = NULL;
00731 }
00732 }
00733
00737 DWORD DHCP_get_server (
void)
00738 {
00739
return (dhcp_server);
00740 }
00741
00745 static sock_type *
dhcp_open (
const char *msg, BOOL use_broadcast)
00746 {
00747
struct _udp_Socket *sock = malloc (
sizeof(*sock));
00748
DWORD host;
00749
00750
if (!sock)
00751 {
00752 outs (_LANG(
"DHCP: malloc failed\n"));
00753
return (NULL);
00754 }
00755
00756
if (msg && (trace_on || debug_on))
00757 outs (msg);
00758
00759
if (use_broadcast)
00760 host = IP_BCAST_ADDR;
00761
else host = dhcp_server;
00762
00763
if (!
udp_open (sock, IPPORT_BOOTPC, host, IPPORT_BOOTPS, NULL))
00764 {
00765
if (trace_on || debug_on)
00766 {
00767 outs (
"DHCP: ");
00768 outsnl (sock->err_msg);
00769 }
00770 free (sock);
00771 sock = NULL;
00772 }
00773 TRACE ((
"DHCP open: bc(%d) srvr(%s)\n",
00774 use_broadcast, INET_NTOA(dhcp_server)));
00775
return (
sock_type*)sock;
00776 }
00777
00781 static void arp_add_server (
void)
00782 {
00783
if ((
_pktdevclass == PDCLASS_ETHER ||
_pktdevclass == PDCLASS_TOKEN) &&
00784 memcmp(sock->
udp.his_ethaddr,
_eth_brdcast,
sizeof(
_eth_brdcast)))
00785 {
00786
const eth_address *eth = (
const eth_address*) sock->
udp.his_ethaddr;
00787
_arp_add_cache (dhcp_server, eth, TRUE);
00788 }
00789 }
00790
00795 static void DHCP_state_BOUND (
int event)
00796 {
00797
if (event == EVENT_T1_TIMEOUT)
00798 {
00799 old_ip_addr =
my_ip_addr;
00800 got_offer = FALSE;
00801
00802 TRACE ((
"Sending DHCP request 01\n"));
00803
DHCP_request (1);
00804 DHCP_state =
DHCP_state_RENEWING;
00805 }
00806 }
00807
00814 static void DHCP_state_REQUESTING (
int event)
00815 {
00816
if (event == EVENT_SEND_TIMEOUT)
00817 {
00818 TRACE ((
"Sending DHCP request 00\n"));
00819
DHCP_request (0);
00820
00821
00822
00823
00824
00825
00826
00827
00828 send_timeout =
set_timeout (
Random(4000,6000));
00829 }
00830
else if (event == EVENT_ACK)
00831 {
00832 TRACE ((
"Got DHCP ack while requesting\n"));
00833
00834
if (!
DHCP_arp_check(
my_ip_addr))
00835 {
00836
my_ip_addr = 0;
00837
DHCP_release_decline (DHCP_DECLINE,
"IP is not free");
00838 send_timeout =
set_timeout (
Random(4000,6000));
00839 DHCP_state =
DHCP_state_INIT;
00840 }
00841
else
00842 {
00843
DHCP_offer (&dhcp_in);
00844 configured = 1;
00845
if (dhcp_server)
00846
arp_add_server();
00847
dhcp_set_timers();
00848 send_timeout = 0UL;
00849 DHCP_state =
DHCP_state_BOUND;
00850 }
00851 }
00852
else if (event == EVENT_NAK)
00853 {
00854 send_timeout =
set_timeout (
Random(4000,6000));
00855
my_ip_addr = 0UL;
00856 DHCP_state =
DHCP_state_INIT;
00857 }
00858 }
00859
00865 static void DHCP_state_REBINDING (
int event)
00866 {
00867
if (event == EVENT_ACK)
00868 {
00869 TRACE ((
"Got DHCP ack while rebinding\n"));
00870
dhcp_set_timers();
00871
DHCP_offer (&dhcp_in);
00872
change_ip_addr();
00873 DHCP_state =
DHCP_state_BOUND;
00874 }
00875
else if (event == EVENT_NAK)
00876 {
00877 send_timeout =
set_timeout (
Random(4000,6000));
00878
my_ip_addr = 0UL;
00879 DHCP_state =
DHCP_state_INIT;
00880 }
00881 }
00882
00890 static void DHCP_state_RENEWING (
int event)
00891 {
00892
if (event == EVENT_SEND_TIMEOUT)
00893 {
00894 TRACE ((
"Sending DHCP request for renew\n"));
00895
DHCP_request (1);
00896 }
00897
else if (event == EVENT_T2_TIMEOUT)
00898 {
00899 TRACE ((
"Sending DHCP request for rebind\n"));
00900 bcast_flag = TRUE;
00901
DHCP_request (1);
00902 DHCP_state =
DHCP_state_REBINDING;
00903 }
00904
else if (event == EVENT_ACK)
00905 {
00906 TRACE ((
"Got DHCP ack while renewing\n"));
00907
dhcp_set_timers();
00908
DHCP_offer (&dhcp_in);
00909
change_ip_addr();
00910 DHCP_state =
DHCP_state_BOUND;
00911 }
00912
else if (event == EVENT_NAK)
00913 {
00914 TRACE ((
"Got DHCP nack while renewing\n"));
00915 send_timeout =
set_timeout (
Random(4000,6000));
00916
my_ip_addr = 0;
00917 DHCP_state =
DHCP_state_INIT;
00918 }
00919 }
00920
00926 static void DHCP_state_SELECTING (
int event)
00927 {
00928
if (event == EVENT_OFFER && !got_offer &&
DHCP_offer(&dhcp_in))
00929 {
00930 TRACE ((
"Got DHCP offer\n"));
00931 send_timeout =
set_timeout (
Random(100,500));
00932
00933
if (dhcp_renewal == 0L)
00934 dhcp_renewal = dhcp_iplease / 2;
00935
if (dhcp_rebind == 0)
00936 dhcp_rebind = dhcp_iplease * 7 / 8;
00937
00938
00939
00940
00941
my_ip_addr = ((
_udp_Socket*)sock)->myaddr = intel (dhcp_in.
dh_yiaddr);
00942 TRACE ((
"my_ip_addr = %s\n", INET_NTOA(
my_ip_addr)));
00943 send_timeout =
set_timeout (100);
00944 DHCP_state =
DHCP_state_REQUESTING;
00945 }
00946
else if (event == EVENT_SEND_TIMEOUT)
00947 {
00948 DHCP_state =
DHCP_state_INIT;
00949 (*DHCP_state) (event);
00950 }
00951 }
00952
00957 static void DHCP_state_INIT (
int event)
00958 {
00959
if (event == EVENT_SEND_TIMEOUT)
00960 {
00961 discover_loops++;
00962 exchange_id =
set_timeout (0);
00963
00964 TRACE ((
"Sending DHCP discover (%d)\n", discover_loops));
00965
00966 send_timeout =
set_timeout (1000 * dhcp_timeout);
00967
DHCP_discover();
00968 DHCP_state =
DHCP_state_SELECTING;
00969 }
00970 }
00971
00972
#ifdef NOT_USED
00973
00976 static void DHCP_state_REBOOTING (
int event)
00977 {
00978
if (event == EVENT_ACK)
00979 {
00980 DHCP_state =
DHCP_state_BOUND;
00981 }
00982
else if (event == EVENT_NAK)
00983 {
00984 send_timeout =
set_timeout (
Random(4000,6000));
00985 DHCP_state =
DHCP_state_INIT;
00986 }
00987 }
00988
#endif
00989
00993 static void dhcp_fsm (
void)
00994 {
00995
if (
sock_dataready(sock))
00996 {
00997
int len =
sock_fastread (sock, (
BYTE*)&dhcp_in,
sizeof(dhcp_in));
00998
00999
if (len >= DHCP_MIN_SIZE &&
01000 dhcp_in.dh_op == BOOTP_REPLY &&
01001 dhcp_in.dh_xid == dhcp_out.
dh_xid &&
01002 !memcmp(dhcp_in.dh_chaddr,
_eth_addr,
01003
sizeof(
eth_address)))
01004 {
01005
if (
DHCP_is_ack())
01006 {
01007 TRACE ((
"%s/ACK: ",
state_name()));
01008 (*DHCP_state) (EVENT_ACK);
01009 }
01010
else if (
DHCP_is_nack())
01011 {
01012 TRACE ((
"%s/NAK: ",
state_name()));
01013 (*DHCP_state) (EVENT_NAK);
01014 }
01015
else
01016 {
01017 TRACE ((
"%s/OFFER: ",
state_name()));
01018 (*DHCP_state) (EVENT_OFFER);
01019 }
01020 }
01021 }
01022
01023
if (
chk_timeout(send_timeout))
01024 {
01025 send_timeout = 0UL;
01026 TRACE ((
"%s/SEND_TIMEOUT: ",
state_name()));
01027 (*DHCP_state) (EVENT_SEND_TIMEOUT);
01028 }
01029
01030
if (renewal_timeout && time(NULL) >= renewal_timeout)
01031 {
01032 renewal_timeout = 0UL;
01033 TRACE ((
"%s/T1_TIMEOUT: ",
state_name()));
01034 (*DHCP_state) (EVENT_T1_TIMEOUT);
01035 }
01036
01037
if (rebind_timeout && time(NULL) >= rebind_timeout)
01038 {
01039 rebind_timeout = 0UL;
01040 TRACE ((
"%s/T2_TIMEOUT: ",
state_name()));
01041 (*DHCP_state) (EVENT_T2_TIMEOUT);
01042 }
01043 }
01044
01054 int DHCP_do_boot (
void)
01055 {
01056
int save_mtu = _mtu;
01057
01058
if (cfg_read)
01059
return (1);
01060
01061 outs (_LANG(
"Configuring through DHCP.."));
01062
if (!sock)
01063 sock =
dhcp_open (NULL, bcast_flag);
01064
if (!sock)
01065
return (0);
01066
01067
if (DHCP_state !=
DHCP_state_RENEWING &&
01068 DHCP_state !=
DHCP_state_REBINDING)
01069 {
01070
my_ip_addr = 0;
01071
sin_mask = 0;
01072 }
01073
01074 _mtu = ETH_MAX_DATA;
01075 discover_loops = 0;
01076
01077
erase_config();
01078
addwattcpd (
dhcp_fsm);
01079
01080
01081
01082 send_timeout =
set_timeout (100);
01083
01084
if (DHCP_state !=
DHCP_state_RENEWING &&
01085 DHCP_state !=
DHCP_state_REBINDING)
01086 DHCP_state =
DHCP_state_INIT;
01087
01088
while (DHCP_state !=
DHCP_state_BOUND)
01089 {
01090
tcp_tick (NULL);
01091
if (discover_loops >= max_retries)
01092
break;
01093 }
01094
01095 got_offer = FALSE;
01096 _mtu = save_mtu;
01097
01098
if (
my_ip_addr)
01099 {
01100 cfg_saved =
write_config() > 0;
01101
return (1);
01102 }
01103
return (0);
01104 }
01105
01109 static void dhcp_options_add (
const BYTE *opt,
unsigned max)
01110 {
01111
int len = 0;
01112
char *add;
01113
const BYTE *end = opt + max;
01114
01115 extra_options.data = (
BYTE*) realloc (extra_options.data, max);
01116
if (!extra_options.data)
01117
return;
01118
01119 add = (
char*)&extra_options.data + extra_options.size;
01120
01121
01122
01123
01124
while (opt < end)
01125 {
01126
if (*opt == DHCP_OPT_PAD)
01127
continue;
01128
if (*opt == DHCP_OPT_END)
01129
return;
01130
01131 len = opt[1];
01132 memcpy (add, opt, len+2);
01133 add += len + 2;
01134 opt += len + 2;
01135 extra_options.size += len + 2;
01136 }
01137 }
01138
01142 static void dhcp_set_timers (
void)
01143 {
01144 time_t now = time (NULL);
01145
01146
if (dhcp_iplease == 0UL)
01147 lease_timeout = (time_t)-1;
01148
else lease_timeout = now + dhcp_iplease;
01149
01150
if (dhcp_renewal == 0UL)
01151 renewal_timeout = (time_t)-1;
01152
else renewal_timeout = now + dhcp_renewal;
01153
01154
if (dhcp_rebind == 0UL)
01155 rebind_timeout = (time_t)-1;
01156
else
01157 {
01158 rebind_timeout = now + dhcp_rebind;
01159
if (rebind_timeout == renewal_timeout)
01160 rebind_timeout += 10;
01161 }
01162
if (dhcp_iplease == 0UL)
01163 TRACE ((
"Infinite lease!!\n"));
01164 }
01165
01169 static void change_ip_addr (
void)
01170 {
01171
if (
my_ip_addr == old_ip_addr)
01172
return;
01173
01174
#if !defined(USE_UDP_ONLY)
01175
{
01176
_tcp_Socket *tcp;
01177
for (tcp =
_tcp_allsocs; tcp; tcp = tcp->next)
01178
if (tcp->myaddr)
01179 tcp->myaddr =
my_ip_addr;
01180 }
01181
#endif
01182
01183 {
01184
_udp_Socket *udp;
01185
for (udp =
_udp_allsocs; udp; udp = udp->next)
01186
if (udp->myaddr)
01187 udp->myaddr =
my_ip_addr;
01188 }
01189 }
01190
01195 static int set_request_list (
char *options)
01196 {
01197
static BOOL init = FALSE;
01198
int num = 0;
01199
int maxreq = 312 - 27;
01200
BYTE *list, *start, *tok, *end;
01201
01202
if (init || (list = calloc(maxreq,1)) == NULL)
01203
return (0);
01204
01205 init = TRUE;
01206 start = list;
01207 end = start + maxreq - 1;
01208 tok = (
BYTE*) strtok (options,
", \t");
01209
01210
while (tok && list < end)
01211 {
01212 *list = ATOI ((
const char*)tok);
01213 tok = (
BYTE*) strtok (NULL,
", \t");
01214
01215
01216
01217
01218
if (num == 0 && *list ==
'0')
01219
break;
01220 num++;
01221 list++;
01222 }
01223
01224 request_list.data = start;
01225 request_list.size = num;
01226
01227
#if 0
01228 {
01229
int i;
01230
for (i = 0; i < request_list.size; i++)
01231 printf (
"%2d, ", request_list.data[i]);
01232 puts (
"");
01233 }
01234
#endif
01235
return (1);
01236 }
01237
01241 static BYTE *
put_request_list (
BYTE *opt,
int filled)
01242 {
01243 size_t size = min (request_list.size,
sizeof(dhcp_out.
dh_opt)-filled-1);
01244
01245
if (size > 0 && request_list.data)
01246 {
01247 size = min (size, 255);
01248 *opt++ = DHCP_OPT_PARAM_REQUEST;
01249 *opt++ = (
BYTE)size;
01250 memcpy (opt, request_list.data, size);
01251 opt += size;
01252 }
01253
return (opt);
01254 }
01255
01261 static int set_user_class (
const char *value)
01262 {
01263
static BOOL init = FALSE;
01264
int total = 0;
01265
int maxreq =
sizeof(dhcp_out.
dh_opt) - 27;
01266
char *list, *list_start;
01267
char *list_end;
01268
const char *value_end;
01269
01270
if (init || (list = (
char*)calloc(maxreq,1)) == NULL)
01271
return (0);
01272
01273 init = TRUE;
01274 list_start = list;
01275 list_end = list + maxreq - 1;
01276 value_end = value + strlen (value);
01277
01278
while (list < list_end && value < value_end)
01279 {
01280
const char *comma = strchr (value,
',');
01281
int size;
01282
01283
if (comma)
01284 size = comma - value;
01285
else size = strlen (value);
01286 *list++ = size;
01287 memcpy (list, value, size);
01288 list += size;
01289 value += size + 1;
01290 total += size + 1;
01291 }
01292
01293 user_class.data = (
BYTE*) list_start;
01294 user_class.size = total;
01295
01296
#if 0
01297 {
01298 size_t i;
01299
for (i = 0; i < user_class.size; i++)
01300 {
01301
int ch = user_class.data[i];
01302
01303
if (isprint(ch))
01304 printf (
"%c", ch);
01305
else printf (
"\\x%02X", ch);
01306 }
01307 puts (
"");
01308 }
01309
#endif
01310
return (1);
01311 }
01312
01316 static int set_vend_class (
const char *value)
01317 {
01319 ARGSUSED (value);
01320
return (0);
01321 }
01322
01323
01324
01325
static void (*prev_hook) (
const char*,
const char*) = NULL;
01326
01327
01328
01329
01330
static time_t cfg_dhcp_iplease;
01331
static time_t cfg_dhcp_renewal;
01332
static time_t cfg_dhcp_rebind;
01333
01339 static void DHCP_cfg_hook (
const char *name,
const char *value)
01340 {
01341
static const struct config_table dhcp_cfg[] = {
01342 {
"REQ_LIST",
ARG_FUNC, (
void*)
set_request_list },
01343 {
"TRACE",
ARG_ATOI, (
void*)&trace_on },
01344 {
"BCAST",
ARG_ATOI, (
void*)&bcast_flag },
01345 {
"TIMEOUT",
ARG_ATOI, (
void*)&dhcp_timeout },
01346 {
"RETRIES",
ARG_ATOI, (
void*)&max_retries },
01347 {
"ARPCHECK",
ARG_ATOI, (
void*)&arp_check_ip },
01348 {
"HOST",
ARG_RESOLVE,(
void*)&dhcp_server },
01349 {
"USERCLASS",
ARG_FUNC, (
void*)
set_user_class },
01350 {
"VENDCLASS",
ARG_FUNC, (
void*)
set_vend_class },
01351 {
"CONFIG",
ARG_STRCPY, (
void*)&config_file },
01352 { NULL, 0, NULL }
01353 };
01354
01355
if (!
parse_config_table(&dhcp_cfg[0],
"DHCP.", name, value) && prev_hook)
01356 (*prev_hook) (name, value);
01357 }
01358
01362 static void DHCP_exit (
void)
01363 {
01364
if (
_watt_fatal_error)
01365
return;
01366
01367 DO_FREE (user_class.data);
01368 DO_FREE (extra_options.data);
01369 DO_FREE (sock);
01370
if (request_list.data != (
BYTE*)&default_request_list)
01371 DO_FREE (request_list.data);
01372
01373
#if defined(USE_BSD_API)
01374
syslog_host_name[0] =
'\0';
01375
#endif
01376
}
01377
01381 void DHCP_init (
void)
01382 {
01383 prev_hook = usr_init;
01384 usr_init =
DHCP_cfg_hook;
01385 RUNDOWN_ADD (
DHCP_exit, 259);
01386 }
01387
01391 static void set_my_ip (
const char *value)
01392 {
01393 TRACE ((
"DHCP: using previous address %s\n", value));
01394
my_ip_addr =
aton (value);
01395 }
01396
01397
static void set_netmask (
const char *value)
01398 {
01399 TRACE ((
"DHCP: using previous netmask %s\n", value));
01400
sin_mask =
aton (value);
01401 }
01402
01403
static void set_gateway (
const char *value)
01404 {
01405 router =
aton (value);
01406
if (router)
01407 {
01408
_arp_kill_gateways();
01409 TRACE ((
"DHCP: using previous gateway %s\n", value));
01410
_arp_add_gateway (NULL, router);
01411 }
01412
else
01413 TRACE ((
"DHCP: previous gateway is 0.0.0.0!\n"));
01414 }
01415
01416
static void set_nameserv (
const char *value)
01417 {
01418 TRACE ((
"DHCP: using previous nameserv %s\n", value));
01419 nameserver =
aton (value);
01420 _add_server (&last_nameserver, MAX_NAMESERVERS, def_nameservers, nameserver);
01421 }
01422
01423
static void set_server (
const char *value)
01424 {
01425 TRACE ((
"DHCP: using previous server %s\n", value));
01426 dhcp_server =
aton (value);
01427 }
01428
01429
static void set_domain (
const char *value)
01430 {
01431 TRACE ((
"DHCP: using previous domain %s\n", value));
01432
setdomainname (value, strlen(value)+1);
01433 }
01434
01435
static void set_lease (
const char *value)
01436 {
01437 cfg_dhcp_iplease = ATOL (value);
01438 }
01439
01440
static void set_renew (
const char *value)
01441 {
01442 cfg_dhcp_renewal = ATOL (value);
01443 }
01444
01445
static void set_rebind (
const char *value)
01446 {
01447 cfg_dhcp_rebind = ATOL (value);
01448 }
01449
01461 static BOOL
eval_timers (
void)
01462 {
01463 time_t now = time (NULL);
01464
01465 TRACE ((
"DHCP: IP-lease expires %s", ctime(&cfg_dhcp_iplease)));
01466 TRACE ((
"DHCP: rebinding expires %s", ctime(&cfg_dhcp_rebind)));
01467 TRACE ((
"DHCP: renewal expires %s", ctime(&cfg_dhcp_renewal)));
01468
01469
if (cfg_dhcp_iplease < now)
01470 dhcp_iplease = DHCP_MIN_LEASE;
01471
else dhcp_iplease = (
DWORD)(cfg_dhcp_iplease - now);
01472
01473
if (cfg_dhcp_renewal < now)
01474 dhcp_renewal = dhcp_iplease / 2;
01475
else dhcp_renewal = (
DWORD)(cfg_dhcp_renewal - now);
01476
01477
if (cfg_dhcp_rebind < now)
01478 dhcp_rebind = dhcp_iplease * 7 / 8;
01479
else dhcp_rebind = (
DWORD)(cfg_dhcp_rebind - now);
01480
01481 discover_loops = 0;
01482
01483
if (now < cfg_dhcp_renewal)
01484 {
01485 TRACE ((
"DHCP: BOUND\n"));
01486 DHCP_state =
DHCP_state_BOUND;
01487
return (TRUE);
01488 }
01489
01490
if (now >= cfg_dhcp_renewal && now < cfg_dhcp_rebind)
01491 {
01492 TRACE ((
"DHCP: RENEWING\n"));
01493 DHCP_state =
DHCP_state_BOUND;
01494 (*DHCP_state) (EVENT_T1_TIMEOUT);
01495
return (FALSE);
01496 }
01497
01498
if (now >= cfg_dhcp_rebind && now < cfg_dhcp_iplease)
01499 {
01500 TRACE ((
"DHCP: REBINDING\n"));
01501 DHCP_state =
DHCP_state_RENEWING;
01502 (*DHCP_state) (EVENT_T2_TIMEOUT);
01503
return (FALSE);
01504 }
01505
return (FALSE);
01506 }
01507
01514 static const struct config_table
transient_cfg[] = {
01515 {
"DHCP.LEASE",
ARG_FUNC, (
void*)set_lease },
01516 {
"DHCP.RENEW",
ARG_FUNC, (
void*)set_renew },
01517 {
"DHCP.REBIND",
ARG_FUNC, (
void*)set_rebind },
01518 {
"DHCP.MY_IP",
ARG_FUNC, (
void*)
set_my_ip },
01519 {
"DHCP.NETMASK",
ARG_FUNC, (
void*)set_netmask },
01520 {
"DHCP.GATEWAY",
ARG_FUNC, (
void*)set_gateway },
01521 {
"DHCP.NAMESERV",
ARG_FUNC, (
void*)set_nameserv },
01522 {
"DHCP.SERVER",
ARG_FUNC, (
void*)set_server },
01523 {
"DHCP.DOMAIN",
ARG_FUNC, (
void*)set_domain },
01524 {
"DHCP.HOSTNAME",
ARG_STRCPY, (
void*)
hostname },
01525
#if defined(USE_BSD_API)
01526
{
"DHCP.LOGHOST",
ARG_STRCPY, (
void*)&syslog_host_name },
01527
#endif
01528
{
"DHCP.DEF_TTL",
ARG_ATOI, (
void*)&
_default_ttl },
01529
#if !defined(USE_UDP_ONLY)
01530
{
"DHCP.TCP_KEEP",
ARG_ATOI, (
void*)&
tcp_keep_intvl },
01531
#endif
01532
{ NULL, 0, NULL }
01533 };
01534
01535
01536
01537
01538
static const char *get_config_file (
void)
01539 {
01540
if (config_file[0])
01541
return (config_file);
01542
return ExpandVarStr (
"$(TEMP)\\W32DHCP.TMP");
01543 }
01544
01545
01546
01547
01548
static void std_erase_config (
void)
01549 {
01550 unlink (get_config_file());
01551 }
01552
01553
01554
01555
01556
static int std_read_config (
void)
01557 {
01558 WFILE file;
01559
const char *fname = get_config_file();
01560
01561
if (!FOPEN(file, fname))
01562 {
01563 TRACE ((
"`%s' not found\n", fname));
01564
return (0);
01565 }
01566
01567 prev_hook = usr_init;
01568 usr_init = NULL;
01569 tcp_parse_file (file, &transient_cfg[0]);
01570 usr_init = prev_hook;
01571
01572 FCLOSE (file);
01573
return (1);
01574 }
01575
01581 static int std_write_config (
void)
01582 {
01583
char buf[20];
01584 FILE *file;
01585 time_t tim, now = time (NULL);
01586
int rc = 0;
01587
const char *fname = get_config_file();
01588
01589
if (access(fname,0))
01590 {
01591 file = fopen (fname,
"w+t");
01592
if (!file)
01593
goto fail;
01594
01595 rc = fprintf (file,
01596
"#\n"
01597
"# GENERATED FILE. DO NOT EDIT!\n"
01598
"#\n"
01599
"# DHCP transient configuration; values that must\n"
01600
"# be known between consecutive runs of applications.\n"
01601
"# Version: %s\n"
01602
"#\n", wattcpVersion());
01603 }
01604
else
01605 {
01606
#if defined(WIN32)
01607
SetFileAttributes (fname, FILE_ATTRIBUTE_NORMAL);
01608
#else
01609
_dos_setfileattr (fname, _A_NORMAL);
01610
#endif
01611
file = fopen (fname,
"at");
01612
if (!file)
01613
goto fail;
01614 }
01615
01616 rc += fprintf (file,
"# This file saved at %s#\n", ctime(&now));
01617
01618 tim = dhcp_iplease + now;
01619 rc += fprintf (file,
"DHCP.LEASE = %-20lu # lease expires %s",
01620 (
DWORD)tim, ctime(&tim));
01621
01622 tim = dhcp_renewal + now;
01623 rc += fprintf (file,
"DHCP.RENEW = %-20lu # renew expires %s",
01624 (
DWORD)tim, ctime(&tim));
01625
01626 tim = dhcp_rebind + now;
01627 rc += fprintf (file,
01628
"DHCP.REBIND = %-20lu # rebind expires %s"
01629
"DHCP.MY_IP = %-20s # assigned ip-address\n",
01630 (
DWORD)tim, ctime(&tim),
_inet_ntoa(buf,
my_ip_addr));
01631
01632 rc += fprintf (file,
"DHCP.NETMASK = %-20s # assigned netmask\n",
01633
_inet_ntoa(buf,
sin_mask));
01634
01635 rc += fprintf (file,
"DHCP.GATEWAY = %-20s # assigned gateway\n",
01636
_inet_ntoa(buf,router));
01637
01638 rc += fprintf (file,
"DHCP.NAMESERV = %-20s # assigned nameserver\n",
01639
_inet_ntoa(buf,nameserver));
01640
01641 rc += fprintf (file,
"DHCP.SERVER = %-20s # DHCP server\n",
01642
_inet_ntoa(buf,dhcp_server));
01643
01644 rc += fprintf (file,
"DHCP.HOSTNAME = %-20s # assigned hostname\n",
01645
hostname);
01646
01647 rc += fprintf (file,
"DHCP.DOMAIN = %-20s # assigned domain\n",
01648 def_domain);
01649
01650
#if defined(USE_BSD_API)
01651
if (syslog_host_name[0])
01652 rc += fprintf (file,
"DHCP.LOGHOST = %-20s # assigned syslog host\n",
01653 syslog_host_name);
01654
#endif
01655
01656 rc += fprintf (file,
"DHCP.DEF_TTL = %-20d # default TTL\n",
01657
_default_ttl);
01658
01659
#if !defined(USE_UDP_ONLY)
01660
rc += fprintf (file,
"DHCP.TCP_KEEP = %-20d # TCP keepalive interval\n",
01661
tcp_keep_intvl);
01662
#endif
01663
01664 fclose (file);
01665
return (rc);
01666
01667 fail:
01668 TCP_CONSOLE_MSG (0, (
"Writing %s failed; %s\n", fname, strerror(errno)));
01669
return (0);
01670 }
01671
01672
01673
01674
01675
static void usr_erase_config (
void)
01676 {
01677 (*config_func) (DHCP_OP_ERASE, NULL);
01678 }
01679
01680
static int usr_read_config (
void)
01681 {
01682
struct DHCP_config cfg;
01683
01684 memset (&cfg, 0,
sizeof(cfg));
01685
01686
if (!(*config_func)(DHCP_OP_READ, &cfg))
01687
return (0);
01688
01689 TRACE ((
"DHCP: using previous address %s\n", INET_NTOA(cfg.my_ip)));
01690
my_ip_addr = cfg.my_ip;
01691
01692 TRACE ((
"DHCP: using previous netmask %s\n", INET_NTOA(cfg.netmask)));
01693
sin_mask = cfg.netmask;
01694
01695
if (!
_arp_have_default_gw())
01696 {
01697 TRACE ((
"DHCP: using previous gateway %s\n", INET_NTOA(cfg.gateway)));
01698 router = cfg.gateway;
01699
_arp_add_gateway (NULL, router);
01700 }
01701
else
01702 TRACE ((
"DHCP: already have default gateway\n"));
01703
01704 TRACE ((
"DHCP: using previous nameserv %s\n", INET_NTOA(cfg.nameserver)));
01705 nameserver = cfg.nameserver;
01706 _add_server (&last_nameserver, MAX_NAMESERVERS, def_nameservers, nameserver);
01707
01708 TRACE ((
"DHCP: using previous server %s\n", INET_NTOA(cfg.server)));
01709 dhcp_server = cfg.server;
01710
01711 cfg_dhcp_iplease = cfg.iplease;
01712 cfg_dhcp_renewal = cfg.renewal;
01713 cfg_dhcp_rebind = cfg.rebind;
01714
01715
_default_ttl = cfg.default_ttl;
01716
#if !defined(USE_UDP_ONLY)
01717
tcp_keep_intvl = cfg.tcp_keep_intvl;
01718
#endif
01719
01720
StrLcpy (hostname, cfg.hostname,
sizeof(hostname));
01721
01722 TRACE ((
"DHCP: using previous domain %s\n", cfg.domain));
01723
setdomainname (cfg.domain, strlen(cfg.domain)+1);
01724
01725
#if defined(USE_BSD_API)
01726
if (cfg.loghost[0])
01727
StrLcpy (syslog_host_name, cfg.loghost,
sizeof(syslog_host_name));
01728
#endif
01729
01730
return (1);
01731 }
01732
01733
static int usr_write_config (
void)
01734 {
01735
struct DHCP_config cfg;
01736 time_t now = time (NULL);
01737
01738 memset (&cfg, 0,
sizeof(cfg));
01739 cfg.my_ip =
my_ip_addr;
01740 cfg.netmask =
sin_mask;
01741 cfg.gateway = router;
01742 cfg.nameserver = nameserver;
01743 cfg.server = dhcp_server;
01744 cfg.iplease = (
DWORD)now + dhcp_iplease;
01745 cfg.renewal = (
DWORD)now + dhcp_renewal;
01746 cfg.rebind = (
DWORD)now + dhcp_rebind;
01747 cfg.default_ttl =
_default_ttl;
01748
#if !defined(USE_UDP_ONLY)
01749
cfg.tcp_keep_intvl =
tcp_keep_intvl;
01750
#endif
01751
01752
StrLcpy (cfg.hostname, hostname,
sizeof(cfg.hostname));
01753
StrLcpy (cfg.domain, def_domain,
sizeof(cfg.domain));
01754
01755
#if defined(USE_BSD_API)
01756
if (syslog_host_name[0])
01757
StrLcpy (cfg.loghost, syslog_host_name,
sizeof(cfg.loghost));
01758
#endif
01759
01760
return (*config_func) (DHCP_OP_WRITE, &cfg);
01761 }
01762
01766 static void erase_config (
void)
01767 {
01768 config_func ? usr_erase_config() : std_erase_config();
01769 }
01770
01776 int DHCP_read_config (
void)
01777 {
01778 cfg_read = FALSE;
01779
01780
if (config_func ? usr_read_config() : std_read_config() > 0)
01781 {
01782 sock =
dhcp_open (NULL, bcast_flag);
01783
if (!sock)
01784
return (0);
01785
01786
if (
eval_timers())
01787 {
01788 cfg_read = TRUE;
01789
dhcp_set_timers();
01790
return (1);
01791 }
01792 TRACE ((
"DHCP: config too old.\n"));
01793 sock->
udp.myaddr = 0;
01794 sock->
udp.hisaddr = IP_BCAST_ADDR;
01795 }
01796
01797
01798
01799
01800
return (0);
01801 }
01802
01807 static int write_config (
void)
01808 {
01809
return (config_func ? usr_write_config() :
std_write_config());
01810 }
01811
01815 WattDHCPConfigFunc
dhcp_set_config_func (WattDHCPConfigFunc fn)
01816 {
01817 WattDHCPConfigFunc old_fn = config_func;
01818 config_func = fn;
01819
return (old_fn);
01820 }
01821
#endif