]> git.ipfire.org Git - thirdparty/dhcp.git/blame - client/dhclient.c
Update license.
[thirdparty/dhcp.git] / client / dhclient.c
CommitLineData
469cf3a4 1/* dhclient.c
95821729 2
9bdb9271 3 DHCP Client. */
95821729
TL
4
5/*
f39b6e00
TL
6 * Copyright (c) 1996-1999 Internet Software Consortium.
7 * Use is subject to license terms which appear in the file named
8 * ISC-LICENSE that should have accompanied this file when you
9 * received it. If a file named ISC-LICENSE did not accompany this
10 * file, or you are not sure the one you have is correct, you may
11 * obtain an applicable copy of the license at:
95821729 12 *
f39b6e00 13 * http://www.isc.org/isc-license-1.0.html.
95821729 14 *
f39b6e00
TL
15 * This file is part of the ISC DHCP distribution. The documentation
16 * associated with this file is listed in the file DOCUMENTATION,
17 * included in the top-level directory of this release.
95821729 18 *
f39b6e00
TL
19 * Support and other services are available for ISC products - see
20 * http://www.isc.org for more information.
95821729
TL
21 */
22
c1503c57 23#ifndef lint
339b0231 24static char ocopyright[] =
f39b6e00 25"$Id: dhclient.c,v 1.62 1999/03/16 05:50:30 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n";
c1503c57 26#endif /* not lint */
95821729 27
c1503c57 28#include "dhcpd.h"
e581d615 29
c1503c57 30TIME cur_time;
4a0d788a
TL
31TIME default_lease_time = 43200; /* 12 hours... */
32TIME max_lease_time = 86400; /* 24 hours... */
c1503c57 33struct tree_cache *global_options [256];
4a0d788a 34
cc26de46
TL
35char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
36char *path_dhclient_db = _PATH_DHCLIENT_DB;
37char *path_dhclient_pid = _PATH_DHCLIENT_PID;
38
36f5cb7c
TL
39int dhcp_max_agent_option_packet_length = 0;
40
b8cf055d
TL
41int interfaces_requested = 0;
42
79ec15b2 43int log_perror = 1;
c1503c57 44
cc26de46
TL
45struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
46struct iaddr iaddr_any = { 4, { 0, 0, 0, 0 } };
48d68880 47struct in_addr inaddr_any;
cc26de46 48struct sockaddr_in sockaddr_broadcast;
469cf3a4 49
cc26de46
TL
50/* ASSERT_STATE() does nothing now; it used to be
51 assert (state_is == state_shouldbe). */
52#define ASSERT_STATE(state_is, state_shouldbe) {}
469cf3a4 53
62d0cb47
TL
54static char copyright[] =
55"Copyright 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium.";
56static char arr [] = "All rights reserved.";
9ffa442c 57static char message [] = "Internet Software Consortium DHCP Client V3.0-alpha-990315";
62d0cb47
TL
58static char contrib [] = "\nPlease contribute if you find this software useful.";
59static char url [] = "For info, please visit http://www.isc.org/dhcp-contrib.html\n";
c1503c57 60
cc26de46
TL
61u_int16_t local_port;
62u_int16_t remote_port;
c1503c57 63int log_priority;
b00d3884 64int no_daemon;
126965a9 65int save_scripts;
c1503c57 66
c1503c57 67static void usage PROTO ((void));
95821729
TL
68
69int main (argc, argv, envp)
70 int argc;
c1503c57 71 char **argv, **envp;
95821729 72{
c1503c57 73 int i;
c1503c57 74 struct servent *ent;
cc26de46 75 struct interface_info *ip;
02d9e453 76 struct client_state *client;
66f973e4 77 int seed;
74f45f96 78 int quiet = 0;
6c6d5928 79
c1503c57
TL
80#ifdef SYSLOG_4_2
81 openlog ("dhclient", LOG_NDELAY);
b5ac808e 82 log_priority = LOG_DAEMON;
c1503c57
TL
83#else
84 openlog ("dhclient", LOG_NDELAY, LOG_DAEMON);
85#endif
95821729 86
66f973e4 87#if !(defined (DEBUG) || defined (SYSLOG_4_2) || defined (__CYGWIN32__))
c1503c57
TL
88 setlogmask (LOG_UPTO (LOG_INFO));
89#endif
90
91 for (i = 1; i < argc; i++) {
92 if (!strcmp (argv [i], "-p")) {
93 if (++i == argc)
94 usage ();
cc26de46 95 local_port = htons (atoi (argv [i]));
8ae2d595 96 log_debug ("binding to user-specified port %d",
cc26de46 97 ntohs (local_port));
b00d3884
TL
98 } else if (!strcmp (argv [i], "-d")) {
99 no_daemon = 1;
126965a9
TL
100 } else if (!strcmp (argv [i], "-D")) {
101 save_scripts = 1;
73530742
TL
102 } else if (!strcmp (argv [i], "-pf")) {
103 if (++i == argc)
104 usage ();
105 path_dhclient_pid = argv [i];
106 } else if (!strcmp (argv [i], "-cf")) {
107 if (++i == argc)
108 usage ();
109 path_dhclient_conf = argv [i];
110 } else if (!strcmp (argv [i], "-lf")) {
111 if (++i == argc)
112 usage ();
113 path_dhclient_db = argv [i];
62d0cb47
TL
114 } else if (!strcmp (argv [i], "-q")) {
115 quiet = 1;
116 quiet_interface_discovery = 1;
469cf3a4
TL
117 } else if (argv [i][0] == '-') {
118 usage ();
119 } else {
120 struct interface_info *tmp =
121 ((struct interface_info *)
122 dmalloc (sizeof *tmp, "specified_interface"));
123 if (!tmp)
8ae2d595 124 log_fatal ("Insufficient memory to %s %s",
469cf3a4
TL
125 "record interface", argv [i]);
126 memset (tmp, 0, sizeof *tmp);
127 strcpy (tmp -> name, argv [i]);
128 tmp -> next = interfaces;
129 tmp -> flags = INTERFACE_REQUESTED;
b8cf055d 130 interfaces_requested = 1;
469cf3a4
TL
131 interfaces = tmp;
132 }
c1503c57 133 }
62d0cb47
TL
134
135 if (!quiet) {
8ae2d595
TL
136 log_info (message);
137 log_info (copyright);
138 log_info (arr);
139 log_info (contrib);
140 log_info (url);
62d0cb47
TL
141 }
142
c1503c57 143 /* Default to the DHCP/BOOTP port. */
cc26de46 144 if (!local_port) {
c1503c57
TL
145 ent = getservbyname ("dhcpc", "udp");
146 if (!ent)
cc26de46 147 local_port = htons (68);
c1503c57 148 else
cc26de46 149 local_port = ent -> s_port;
66f973e4 150#ifndef __CYGWIN32__
c1503c57 151 endservent ();
66f973e4 152#endif
c1503c57 153 }
cc26de46 154 remote_port = htons (ntohs (local_port) - 1); /* XXX */
c1503c57 155
95821729
TL
156 /* Get the current time... */
157 GET_TIME (&cur_time);
158
b00d3884 159 sockaddr_broadcast.sin_family = AF_INET;
cc26de46
TL
160 sockaddr_broadcast.sin_port = remote_port;
161 sockaddr_broadcast.sin_addr.s_addr = INADDR_BROADCAST;
b00d3884
TL
162#ifdef HAVE_SA_LEN
163 sockaddr_broadcast.sin_len = sizeof sockaddr_broadcast;
164#endif
48d68880 165 inaddr_any.s_addr = INADDR_ANY;
469cf3a4 166
cc26de46
TL
167 /* Discover all the network interfaces. */
168 discover_interfaces (DISCOVER_UNCONFIGURED);
469cf3a4 169
cc26de46
TL
170 /* Parse the dhclient.conf file. */
171 read_client_conf ();
469cf3a4 172
cc26de46
TL
173 /* Parse the lease database. */
174 read_client_leases ();
469cf3a4 175
cc26de46
TL
176 /* Rewrite the lease database... */
177 rewrite_client_leases ();
469cf3a4 178
ce0ec46d
TL
179 /* XXX */
180/* config_counter(&snd_counter, &rcv_counter); */
181
cc26de46
TL
182 /* If no broadcast interfaces were discovered, call the script
183 and tell it so. */
184 if (!interfaces) {
02d9e453 185 script_init ((struct client_state *)0, "NBI",
9bdb9271 186 (struct string_list *)0);
02d9e453 187 script_go ((struct client_state *)0);
469cf3a4 188
8ae2d595 189 log_info ("No broadcast interfaces found - exiting.");
62d0cb47 190
cc26de46
TL
191 /* Nothing more to do. */
192 exit (0);
193 } else {
194 /* Call the script with the list of interfaces. */
195 for (ip = interfaces; ip; ip = ip -> next) {
5c2f78b4
TL
196 /* If interfaces were specified, don't configure
197 interfaces that weren't specified! */
198 if (interfaces_requested &&
199 ((ip -> flags & (INTERFACE_REQUESTED |
62d0cb47
TL
200 INTERFACE_AUTOMATIC)) !=
201 INTERFACE_REQUESTED))
5c2f78b4 202 continue;
02d9e453
TL
203 script_init (ip -> client,
204 "PREINIT", (struct string_list *)0);
f79e49f3 205 if (ip -> client -> alias)
02d9e453 206 script_write_params (ip -> client, "alias_",
f79e49f3 207 ip -> client -> alias);
02d9e453 208 script_go (ip -> client);
cc26de46
TL
209 }
210 }
469cf3a4 211
cc26de46
TL
212 /* At this point, all the interfaces that the script thinks
213 are relevant should be running, so now we once again call
214 discover_interfaces(), and this time ask it to actually set
215 up the interfaces. */
b8cf055d
TL
216 discover_interfaces (interfaces_requested
217 ? DISCOVER_REQUESTED
218 : DISCOVER_RUNNING);
cc26de46 219
66f973e4
TL
220 /* Make up a seed for the random number generator from current
221 time plus the sum of the last four bytes of each
222 interface's hardware address interpreted as an integer.
223 Not much entropy, but we're booting, so we're not likely to
224 find anything better. */
02d9e453 225 seed = 0;
66f973e4
TL
226 for (ip = interfaces; ip; ip = ip -> next) {
227 int junk;
228 memcpy (&junk,
229 &ip -> hw_address.haddr [ip -> hw_address.hlen -
230 sizeof seed], sizeof seed);
231 seed += junk;
232 }
233 srandom (seed + cur_time);
234
cc26de46
TL
235 /* Start a configuration state machine for each interface. */
236 for (ip = interfaces; ip; ip = ip -> next) {
02d9e453
TL
237 for (client = ip -> client; client; client = client -> next) {
238 client -> state = S_INIT;
239 state_reboot (client);
240 }
cc26de46 241 }
469cf3a4 242
84c4adde
TL
243 /* Set up the bootp packet handler... */
244 bootp_packet_handler = do_packet;
245
cc26de46 246 /* Start dispatching packets and timeouts... */
84c4adde
TL
247 dispatch ();
248
cc26de46
TL
249 /*NOTREACHED*/
250 return 0;
469cf3a4
TL
251}
252
c1503c57
TL
253static void usage ()
254{
8ae2d595 255 log_fatal ("Usage: dhclient [-d] [-D] [-q] [-c] [-p <port>]\n [-lf %s",
62d0cb47 256 "lease-file] [-pf pid-file] [-cf config-file] [interface]");
c1503c57
TL
257}
258
259void cleanup ()
260{
261}
262
02a015fb
TL
263struct class *find_class (s)
264 char *s;
265{
266 return (struct class *)0;
267}
268
269int check_collection (packet, collection)
270 struct packet *packet;
271 struct collection *collection;
272{
273 return 0;
274}
275
276void classify (packet, class)
277 struct packet *packet;
278 struct class *class;
279{
280}
281
73530742
TL
282int unbill_class (lease, class)
283 struct lease *lease;
284 struct class *class;
285{
286 return 0;
287}
288
469cf3a4
TL
289/* Individual States:
290 *
291 * Each routine is called from the dhclient_state_machine() in one of
292 * these conditions:
293 * -> entering INIT state
294 * -> recvpacket_flag == 0: timeout in this state
295 * -> otherwise: received a packet in this state
296 *
297 * Return conditions as handled by dhclient_state_machine():
298 * Returns 1, sendpacket_flag = 1: send packet, reset timer.
299 * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
300 * Returns 0: finish the nap which was interrupted for no good reason.
301 *
cc26de46
TL
302 * Several per-interface variables are used to keep track of the process:
303 * active_lease: the lease that is being used on the interface
304 * (null pointer if not configured yet).
305 * offered_leases: leases corresponding to DHCPOFFER messages that have
306 * been sent to us by DHCP servers.
307 * acked_leases: leases corresponding to DHCPACK messages that have been
308 * sent to us by DHCP servers.
309 * sendpacket: DHCP packet we're trying to send.
469cf3a4 310 * destination: IP address to send sendpacket to
cc26de46 311 * In addition, there are several relevant per-lease variables.
469cf3a4 312 * T1_expiry, T2_expiry, lease_expiry: lease milestones
cc26de46
TL
313 * In the active lease, these control the process of renewing the lease;
314 * In leases on the acked_leases list, this simply determines when we
315 * can no longer legitimately use the lease.
469cf3a4
TL
316 */
317
02d9e453
TL
318void state_reboot (cpp)
319 void *cpp;
deff2d59 320{
02d9e453 321 struct client_state *client = cpp;
84c4adde 322
deff2d59 323 /* If we don't remember an active lease, go straight to INIT. */
02d9e453
TL
324 if (!client -> active ||
325 client -> active -> is_bootp) {
326 state_init (client);
deff2d59
TL
327 return;
328 }
329
330 /* We are in the rebooting state. */
02d9e453 331 client -> state = S_REBOOTING;
deff2d59 332
5c2f78b4
TL
333 /* make_request doesn't initialize xid because it normally comes
334 from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
335 so pick an xid now. */
02d9e453 336 client -> xid = random ();
5c2f78b4 337
deff2d59
TL
338 /* Make a DHCPREQUEST packet, and set appropriate per-interface
339 flags. */
02d9e453
TL
340 make_request (client, client -> active);
341 client -> destination = iaddr_broadcast;
342 client -> first_sending = cur_time;
343 client -> interval = client -> config -> initial_interval;
deff2d59 344
b8cf055d 345 /* Zap the medium list... */
02d9e453 346 client -> medium = (struct string_list *)0;
b8cf055d
TL
347
348 /* Send out the first DHCPREQUEST packet. */
02d9e453 349 send_request (client);
deff2d59
TL
350}
351
352/* Called when a lease has completely expired and we've been unable to
353 renew it. */
cc26de46 354
02d9e453
TL
355void state_init (cpp)
356 void *cpp;
469cf3a4 357{
02d9e453 358 struct client_state *client = cpp;
84c4adde 359
469cf3a4
TL
360 ASSERT_STATE(state, S_INIT);
361
cc26de46
TL
362 /* Make a DHCPDISCOVER packet, and set appropriate per-interface
363 flags. */
02d9e453
TL
364 make_discover (client, client -> active);
365 client -> xid = client -> packet.xid;
366 client -> destination = iaddr_broadcast;
367 client -> state = S_SELECTING;
368 client -> first_sending = cur_time;
369 client -> interval = client -> config -> initial_interval;
cc26de46
TL
370
371 /* Add an immediate timeout to cause the first DHCPDISCOVER packet
372 to go out. */
02d9e453 373 send_discover (client);
469cf3a4
TL
374}
375
cc26de46
TL
376/* state_selecting is called when one or more DHCPOFFER packets have been
377 received and a configurable period of time has passed. */
378
02d9e453
TL
379void state_selecting (cpp)
380 void *cpp;
469cf3a4 381{
02d9e453 382 struct client_state *client = cpp;
b00d3884
TL
383 struct client_lease *lp, *next, *picked;
384
02d9e453 385
469cf3a4
TL
386 ASSERT_STATE(state, S_SELECTING);
387
cc26de46
TL
388 /* Cancel state_selecting and send_discover timeouts, since either
389 one could have got us here. */
02d9e453
TL
390 cancel_timeout (state_selecting, client);
391 cancel_timeout (send_discover, client);
cc26de46 392
b00d3884
TL
393 /* We have received one or more DHCPOFFER packets. Currently,
394 the only criterion by which we judge leases is whether or
395 not we get a response when we arp for them. */
396 picked = (struct client_lease *)0;
02d9e453 397 for (lp = client -> offered_leases; lp; lp = next) {
b00d3884
TL
398 next = lp -> next;
399
400 /* Check to see if we got an ARPREPLY for the address
401 in this particular lease. */
402 if (!picked) {
b00d3884
TL
403 picked = lp;
404 picked -> next = (struct client_lease *)0;
405 } else {
406 freeit:
02a015fb 407 destroy_client_lease (lp);
b00d3884
TL
408 }
409 }
02d9e453 410 client -> offered_leases = (struct client_lease *)0;
b00d3884
TL
411
412 /* If we just tossed all the leases we were offered, go back
413 to square one. */
414 if (!picked) {
02d9e453
TL
415 client -> state = S_INIT;
416 state_init (client);
b00d3884
TL
417 return;
418 }
419
66f973e4 420 /* If it was a BOOTREPLY, we can just take the address right now. */
2455808f 421 if (picked -> is_bootp) {
02d9e453 422 client -> new = picked;
66f973e4
TL
423
424 /* Make up some lease expiry times
425 XXX these should be configurable. */
02d9e453
TL
426 client -> new -> expiry = cur_time + 12000;
427 client -> new -> renewal += cur_time + 8000;
428 client -> new -> rebind += cur_time + 10000;
66f973e4 429
02d9e453 430 client -> state = S_REQUESTING;
66f973e4
TL
431
432 /* Bind to the address we received. */
02d9e453 433 bind_lease (client);
66f973e4
TL
434 return;
435 }
436
b00d3884 437 /* Go to the REQUESTING state. */
02d9e453
TL
438 client -> destination = iaddr_broadcast;
439 client -> state = S_REQUESTING;
440 client -> first_sending = cur_time;
441 client -> interval = client -> config -> initial_interval;
cc26de46 442
b00d3884 443 /* Make a DHCPREQUEST packet from the lease we picked. */
02d9e453
TL
444 make_request (client, picked);
445 client -> xid = client -> packet.xid;
469cf3a4 446
b00d3884 447 /* Toss the lease we picked - we'll get it back in a DHCPACK. */
02a015fb 448 destroy_client_lease (picked);
b00d3884 449
cc26de46 450 /* Add an immediate timeout to send the first DHCPREQUEST packet. */
02d9e453 451 send_request (client);
469cf3a4
TL
452}
453
cc26de46
TL
454/* state_requesting is called when we receive a DHCPACK message after
455 having sent out one or more DHCPREQUEST packets. */
469cf3a4 456
cc26de46
TL
457void dhcpack (packet)
458 struct packet *packet;
469cf3a4 459{
cc26de46 460 struct interface_info *ip = packet -> interface;
02d9e453 461 struct client_state *client;
cc26de46 462 struct client_lease *lease;
02a015fb
TL
463 struct option_cache *oc;
464 struct data_string ds;
cc26de46
TL
465 int i;
466
cc26de46
TL
467 /* If we're not receptive to an offer right now, or if the offer
468 has an unrecognizable transaction id, then just drop it. */
02d9e453
TL
469 for (client = ip -> client; client; client = client -> next) {
470 if (client -> xid == packet -> raw -> xid)
471 break;
472 }
473 if (!client ||
fcaec4ef 474 (packet -> interface -> hw_address.hlen !=
5c2f78b4 475 packet -> raw -> hlen) ||
fcaec4ef
TL
476 (memcmp (packet -> interface -> hw_address.haddr,
477 packet -> raw -> chaddr, packet -> raw -> hlen))) {
8ae2d595 478 log_debug ("DHCPACK in wrong transaction.");
cc26de46 479 return;
469cf3a4 480 }
469cf3a4 481
02d9e453
TL
482 if (client -> state != S_REBOOTING &&
483 client -> state != S_REQUESTING &&
484 client -> state != S_RENEWING &&
485 client -> state != S_REBINDING) {
8ae2d595 486 log_debug ("DHCPACK in wrong state.");
cc26de46 487 return;
469cf3a4
TL
488 }
489
8ae2d595 490 log_info ("DHCPACK from %s", piaddr (packet -> client_addr));
34fdad6c 491
cc26de46
TL
492 lease = packet_to_lease (packet);
493 if (!lease) {
8ae2d595 494 log_info ("packet_to_lease failed.");
cc26de46 495 return;
469cf3a4
TL
496 }
497
02d9e453 498 client -> new = lease;
cc26de46
TL
499
500 /* Stop resending DHCPREQUEST. */
02d9e453 501 cancel_timeout (send_request, client);
cc26de46
TL
502
503 /* Figure out the lease time. */
02d9e453 504 oc = lookup_option (client -> new -> options.dhcp_hash,
02a015fb
TL
505 DHO_DHCP_LEASE_TIME);
506 memset (&ds, 0, sizeof ds);
507 if (oc &&
508 evaluate_option_cache (&ds, packet,
02d9e453 509 &client -> new -> options, oc)) {
02a015fb 510 if (ds.len > 3)
02d9e453 511 client -> new -> expiry = getULong (ds.data);
02a015fb 512 else
02d9e453 513 client -> new -> expiry = 0;
02a015fb
TL
514 data_string_forget (&ds, "dhcpack");
515 } else
02d9e453 516 client -> new -> expiry = 0;
02a015fb 517
02d9e453 518 if (!client -> new -> expiry) {
8ae2d595 519 log_error ("no expiry time on offered lease.");
02a015fb
TL
520 /* XXX this is going to be bad - if this _does_
521 XXX happen, we should probably dynamically
522 XXX disqualify the DHCP server that gave us the
523 XXX bad packet from future selections and
524 XXX then go back into the init state. */
02d9e453 525 state_init (client);
02a015fb
TL
526 return;
527 }
cc26de46 528
62d0cb47
TL
529 /* A number that looks negative here is really just very large,
530 because the lease expiry offset is unsigned. */
531 if (client -> new -> expiry < 0)
532 client -> new -> expiry = TIME_MAX;
02a015fb 533 /* Take the server-provided renewal time if there is one. */
02d9e453 534 oc = lookup_option (client -> new -> options.dhcp_hash,
02a015fb
TL
535 DHO_DHCP_RENEWAL_TIME);
536 if (oc &&
537 evaluate_option_cache (&ds, packet,
02d9e453 538 &client -> new -> options, oc)) {
02a015fb 539 if (ds.len > 3)
02d9e453 540 client -> new -> renewal = getULong (ds.data);
02a015fb 541 else
02d9e453 542 client -> new -> renewal = 0;
2455808f 543 data_string_forget (&ds, "dhcpack");
02a015fb 544 } else
02d9e453 545 client -> new -> renewal = 0;
02a015fb
TL
546
547 /* If it wasn't specified by the server, calculate it. */
02d9e453
TL
548 if (!client -> new -> renewal)
549 client -> new -> renewal =
550 client -> new -> expiry / 2;
cc26de46
TL
551
552 /* Same deal with the rebind time. */
02d9e453 553 oc = lookup_option (client -> new -> options.dhcp_hash,
02a015fb
TL
554 DHO_DHCP_REBINDING_TIME);
555 if (oc &&
556 evaluate_option_cache (&ds, packet,
02d9e453 557 &client -> new -> options, oc)) {
02a015fb 558 if (ds.len > 3)
02d9e453 559 client -> new -> rebind = getULong (ds.data);
02a015fb 560 else
02d9e453 561 client -> new -> rebind = 0;
2455808f 562 data_string_forget (&ds, "dhcpack");
02a015fb 563 } else
02d9e453 564 client -> new -> rebind = 0;
02a015fb 565
02d9e453
TL
566 if (!client -> new -> rebind)
567 client -> new -> rebind =
568 client -> new -> renewal +
569 client -> new -> renewal / 2 +
570 client -> new -> renewal / 4;
cc26de46 571
02d9e453 572 client -> new -> expiry += cur_time;
62d0cb47
TL
573 /* Lease lengths can never be negative. */
574 if (client -> new -> expiry < cur_time)
575 client -> new -> expiry = TIME_MAX;
02d9e453 576 client -> new -> renewal += cur_time;
62d0cb47
TL
577 if (client -> new -> renewal < cur_time)
578 client -> new -> renewal = TIME_MAX;
02d9e453 579 client -> new -> rebind += cur_time;
62d0cb47
TL
580 if (client -> new -> rebind < cur_time)
581 client -> new -> rebind = TIME_MAX;
cc26de46 582
02d9e453 583 bind_lease (client);
66f973e4
TL
584}
585
02d9e453
TL
586void bind_lease (client)
587 struct client_state *client;
66f973e4 588{
02d9e453
TL
589 struct interface_info *ip = client -> interface;
590
9bdb9271 591 /* Remember the medium. */
02d9e453 592 client -> new -> medium = client -> medium;
9bdb9271 593
cc26de46 594 /* Run the client script with the new parameters. */
02d9e453 595 script_init (client, (client -> state == S_REQUESTING
cc26de46 596 ? "BOUND"
02d9e453 597 : (client -> state == S_RENEWING
cc26de46 598 ? "RENEW"
02d9e453 599 : (client -> state == S_REBOOTING
77967680 600 ? "REBOOT" : "REBIND"))),
02d9e453
TL
601 client -> new -> medium);
602 if (client -> active && client -> state != S_REBOOTING)
603 script_write_params (client, "old_", client -> active);
604 script_write_params (client, "new_", client -> new);
605 if (client -> alias)
606 script_write_params (client, "alias_", client -> alias);
e16f4c3e
TL
607
608 /* If the BOUND/RENEW code detects another machine using the
609 offered address, it exits nonzero. We need to send a
610 DHCPDECLINE and toss the lease. */
611 if (script_go (client)) {
612 make_decline (client, client -> new);
613 send_decline (client);
614 destroy_client_lease (client -> new);
7d3bc735 615 client -> new = (struct client_lease *)0;
e16f4c3e
TL
616 state_init (client);
617 return;
618 }
619
620 /* Write out the new lease. */
621 write_client_lease (client, client -> new, 0);
cc26de46
TL
622
623 /* Replace the old active lease with the new one. */
02d9e453
TL
624 if (client -> active)
625 destroy_client_lease (client -> active);
626 client -> active = client -> new;
627 client -> new = (struct client_lease *)0;
cc26de46
TL
628
629 /* Set up a timeout to start the renewal process. */
02d9e453
TL
630 add_timeout (client -> active -> renewal,
631 state_bound, client);
cc26de46 632
8ae2d595 633 log_info ("bound to %s -- renewal in %d seconds.",
02d9e453
TL
634 piaddr (client -> active -> address),
635 client -> active -> renewal - cur_time);
636 client -> state = S_BOUND;
b00d3884
TL
637 reinitialize_interfaces ();
638 go_daemon ();
cc26de46 639}
469cf3a4 640
cc26de46
TL
641/* state_bound is called when we've successfully bound to a particular
642 lease, but the renewal time on that lease has expired. We are
643 expected to unicast a DHCPREQUEST to the server that gave us our
644 original lease. */
469cf3a4 645
02d9e453
TL
646void state_bound (cpp)
647 void *cpp;
469cf3a4 648{
02d9e453 649 struct client_state *client = cpp;
02a015fb
TL
650 int i;
651 struct option_cache *oc;
652 struct data_string ds;
84c4adde 653
cc26de46 654 ASSERT_STATE(state, S_BOUND);
469cf3a4 655
cc26de46 656 /* T1 has expired. */
02d9e453
TL
657 make_request (client, client -> active);
658 client -> xid = client -> packet.xid;
469cf3a4 659
02a015fb 660 memset (&ds, 0, sizeof ds);
02d9e453 661 oc = lookup_option (client -> active -> options.dhcp_hash,
02a015fb
TL
662 DHO_DHCP_SERVER_IDENTIFIER);
663 if (oc &&
664 evaluate_option_cache (&ds, (struct packet *)0,
02d9e453 665 &client -> active -> options, oc)) {
02a015fb 666 if (ds.len > 3) {
02d9e453
TL
667 memcpy (client -> destination.iabuf, ds.data, 4);
668 client -> destination.len = 4;
02a015fb 669 } else
02d9e453 670 client -> destination = iaddr_broadcast;
cc26de46 671 } else
02d9e453 672 client -> destination = iaddr_broadcast;
469cf3a4 673
02d9e453
TL
674 client -> first_sending = cur_time;
675 client -> interval = client -> config -> initial_interval;
676 client -> state = S_RENEWING;
cc26de46
TL
677
678 /* Send the first packet immediately. */
02d9e453 679 send_request (client);
cc26de46 680}
469cf3a4 681
c1503c57
TL
682int commit_leases ()
683{
684 return 0;
685}
686
687int write_lease (lease)
688 struct lease *lease;
689{
690 return 0;
95821729
TL
691}
692
c1503c57
TL
693void db_startup ()
694{
695}
696
697void bootp (packet)
698 struct packet *packet;
699{
fa2b3e59
TL
700 struct iaddrlist *ap;
701
702 if (packet -> raw -> op != BOOTREPLY)
703 return;
704
705 /* If there's a reject list, make sure this packet's sender isn't
706 on it. */
707 for (ap = packet -> interface -> client -> config -> reject_list;
708 ap; ap = ap -> next) {
709 if (addr_eq (packet -> client_addr, ap -> addr)) {
8ae2d595 710 log_info ("BOOTREPLY from %s rejected.",
fa2b3e59
TL
711 piaddr (ap -> addr));
712 return;
713 }
714 }
715
716 dhcpoffer (packet);
66f973e4 717
c1503c57 718}
95821729 719
c1503c57
TL
720void dhcp (packet)
721 struct packet *packet;
95821729 722{
fa2b3e59 723 struct iaddrlist *ap;
ea65d407 724 void (*handler) PROTO ((struct packet *));
fa2b3e59
TL
725 char *type;
726
c1503c57
TL
727 switch (packet -> packet_type) {
728 case DHCPOFFER:
fa2b3e59
TL
729 handler = dhcpoffer;
730 type = "DHCPOFFER";
95821729 731 break;
c1503c57
TL
732
733 case DHCPNAK:
fa2b3e59
TL
734 handler = dhcpnak;
735 type = "DHCPNACK";
c1503c57
TL
736 break;
737
738 case DHCPACK:
fa2b3e59
TL
739 handler = dhcpack;
740 type = "DHCPACK";
c1503c57
TL
741 break;
742
95821729 743 default:
fa2b3e59
TL
744 return;
745 }
746
747 /* If there's a reject list, make sure this packet's sender isn't
748 on it. */
749 for (ap = packet -> interface -> client -> config -> reject_list;
750 ap; ap = ap -> next) {
751 if (addr_eq (packet -> client_addr, ap -> addr)) {
8ae2d595 752 log_info ("%s from %s rejected.",
fa2b3e59
TL
753 type, piaddr (ap -> addr));
754 return;
755 }
95821729 756 }
fa2b3e59 757 (*handler) (packet);
95821729
TL
758}
759
c1503c57
TL
760void dhcpoffer (packet)
761 struct packet *packet;
95821729 762{
cc26de46 763 struct interface_info *ip = packet -> interface;
02d9e453 764 struct client_state *client;
b00d3884 765 struct client_lease *lease, *lp;
cc26de46 766 int i;
e16f4c3e 767 int stop_selecting;
02a015fb 768 char *name = packet -> packet_type ? "DHCPOFFER" : "BOOTREPLY";
fa2b3e59 769 struct iaddrlist *ap;
02a015fb 770 struct option_cache *oc;
cc26de46 771
cc26de46 772#ifdef DEBUG_PACKET
c1503c57 773 dump_packet (packet);
cc26de46
TL
774#endif
775
02d9e453
TL
776 /* Find a client state that matches the xid... */
777 for (client = ip -> client; client; client = client -> next)
778 if (client -> xid == packet -> raw -> xid)
779 break;
780
cc26de46
TL
781 /* If we're not receptive to an offer right now, or if the offer
782 has an unrecognizable transaction id, then just drop it. */
02d9e453 783 if (!client ||
73530742 784 client -> state != S_SELECTING ||
fcaec4ef
TL
785 (packet -> interface -> hw_address.hlen !=
786 packet -> raw -> hlen) ||
787 (memcmp (packet -> interface -> hw_address.haddr,
788 packet -> raw -> chaddr, packet -> raw -> hlen))) {
8ae2d595 789 log_debug ("%s in wrong transaction.", name);
cc26de46
TL
790 return;
791 }
792
8ae2d595 793 log_info ("%s from %s", name, piaddr (packet -> client_addr));
34fdad6c 794
b8cf055d 795
cc26de46
TL
796 /* If this lease doesn't supply the minimum required parameters,
797 blow it off. */
02d9e453
TL
798 if (client -> config -> required_options) {
799 for (i = 0; client -> config -> required_options [i]; i++) {
02a015fb
TL
800 if (!lookup_option
801 (packet -> options.dhcp_hash,
02d9e453 802 client -> config -> required_options [i])) {
8ae2d595 803 log_info ("%s isn't satisfactory.", name);
02a015fb
TL
804 return;
805 }
cc26de46
TL
806 }
807 }
808
809 /* If we've already seen this lease, don't record it again. */
02d9e453 810 for (lease = client -> offered_leases; lease; lease = lease -> next) {
cc26de46
TL
811 if (lease -> address.len == sizeof packet -> raw -> yiaddr &&
812 !memcmp (lease -> address.iabuf,
813 &packet -> raw -> yiaddr, lease -> address.len)) {
8ae2d595 814 log_debug ("%s already seen.", name);
cc26de46
TL
815 return;
816 }
817 }
818
819 lease = packet_to_lease (packet);
820 if (!lease) {
8ae2d595 821 log_info ("packet_to_lease failed.");
cc26de46
TL
822 return;
823 }
824
66f973e4
TL
825 /* If this lease was acquired through a BOOTREPLY, record that
826 fact. */
02a015fb 827 if (!packet -> options_valid || !packet -> packet_type)
66f973e4
TL
828 lease -> is_bootp = 1;
829
9bdb9271 830 /* Record the medium under which this lease was offered. */
02d9e453 831 lease -> medium = client -> medium;
9bdb9271 832
b00d3884 833 /* Figure out when we're supposed to stop selecting. */
02d9e453
TL
834 stop_selecting = (client -> first_sending +
835 client -> config -> select_interval);
b00d3884
TL
836
837 /* If this is the lease we asked for, put it at the head of the
838 list, and don't mess with the arp request timeout. */
02d9e453 839 if (lease -> address.len == client -> requested_address.len &&
b00d3884 840 !memcmp (lease -> address.iabuf,
02d9e453
TL
841 client -> requested_address.iabuf,
842 client -> requested_address.len)) {
843 lease -> next = client -> offered_leases;
844 client -> offered_leases = lease;
b00d3884 845 } else {
b00d3884
TL
846 /* Put the lease at the end of the list. */
847 lease -> next = (struct client_lease *)0;
02d9e453
TL
848 if (!client -> offered_leases)
849 client -> offered_leases = lease;
b00d3884 850 else {
02d9e453 851 for (lp = client -> offered_leases; lp -> next;
b00d3884
TL
852 lp = lp -> next)
853 ;
854 lp -> next = lease;
855 }
856 }
857
cc26de46
TL
858 /* If the selecting interval has expired, go immediately to
859 state_selecting(). Otherwise, time out into
860 state_selecting at the select interval. */
b00d3884 861 if (stop_selecting <= 0)
cc26de46 862 state_selecting (ip);
84c4adde 863 else {
02d9e453
TL
864 add_timeout (stop_selecting, state_selecting, client);
865 cancel_timeout (send_discover, client);
84c4adde 866 }
95821729 867}
e581d615 868
cc26de46
TL
869/* Allocate a client_lease structure and initialize it from the parameters
870 in the specified packet. */
871
872struct client_lease *packet_to_lease (packet)
c1503c57 873 struct packet *packet;
e581d615 874{
cc26de46
TL
875 struct client_lease *lease;
876 int i;
02a015fb
TL
877 struct option_cache *oc;
878 struct data_string data;
cc26de46 879
02a015fb 880 lease = (struct client_lease *)new_client_lease ("packet_to_lease");
cc26de46
TL
881
882 if (!lease) {
8ae2d595 883 log_error ("dhcpoffer: no memory to record lease.\n");
cc26de46
TL
884 return (struct client_lease *)0;
885 }
886
887 memset (lease, 0, sizeof *lease);
888
889 /* Copy the lease options. */
02a015fb
TL
890 lease -> options = packet -> options;
891 memset (&packet -> options, 0, sizeof packet -> options);
cc26de46
TL
892
893 lease -> address.len = sizeof (packet -> raw -> yiaddr);
894 memcpy (lease -> address.iabuf, &packet -> raw -> yiaddr,
895 lease -> address.len);
896
02a015fb
TL
897 /* Figure out the overload flag. */
898 oc = lookup_option (lease -> options.dhcp_hash,
899 DHO_DHCP_OPTION_OVERLOAD);
900 memset (&data, 0, sizeof data);
901 if (oc &&
902 evaluate_option_cache (&data, packet, &lease -> options, oc)) {
903 if (data.len > 0)
904 i = data.data [0];
905 else
906 i = 0;
907 data_string_forget (&data, "packet_to_lease");
908 } else
909 i = 0;
910
cc26de46 911 /* If the server name was filled out, copy it. */
02a015fb 912 if (!(i & 2) && packet -> raw -> sname [0]) {
cc26de46
TL
913 int len;
914 /* Don't count on the NUL terminator. */
915 for (len = 0; len < 64; len++)
916 if (!packet -> raw -> sname [len])
917 break;
02a015fb 918 lease -> server_name = dmalloc (len + 1, "packet_to_lease");
cc26de46 919 if (!lease -> server_name) {
8ae2d595 920 log_error ("dhcpoffer: no memory for filename.\n");
02a015fb 921 destroy_client_lease (lease);
cc26de46
TL
922 return (struct client_lease *)0;
923 } else {
924 memcpy (lease -> server_name,
925 packet -> raw -> sname, len);
926 lease -> server_name [len] = 0;
927 }
928 }
929
930 /* Ditto for the filename. */
02a015fb 931 if ((i & 1) && packet -> raw -> file [0]) {
cc26de46
TL
932 int len;
933 /* Don't count on the NUL terminator. */
934 for (len = 0; len < 64; len++)
935 if (!packet -> raw -> file [len])
936 break;
02a015fb 937 lease -> filename = dmalloc (len + 1, "packet_to_lease");
cc26de46 938 if (!lease -> filename) {
8ae2d595 939 log_error ("dhcpoffer: no memory for filename.\n");
02a015fb 940 destroy_client_lease (lease);
cc26de46
TL
941 return (struct client_lease *)0;
942 } else {
943 memcpy (lease -> filename,
944 packet -> raw -> file, len);
945 lease -> filename [len] = 0;
946 }
947 }
948 return lease;
949}
e581d615 950
c1503c57
TL
951void dhcpnak (packet)
952 struct packet *packet;
953{
deff2d59 954 struct interface_info *ip = packet -> interface;
02d9e453
TL
955 struct client_state *client;
956
957 /* Find a client state that matches the xid... */
958 for (client = ip -> client; client; client = client -> next)
959 if (client -> xid == packet -> raw -> xid)
960 break;
deff2d59 961
deff2d59
TL
962 /* If we're not receptive to an offer right now, or if the offer
963 has an unrecognizable transaction id, then just drop it. */
02d9e453 964 if (!client ||
fcaec4ef
TL
965 (packet -> interface -> hw_address.hlen !=
966 packet -> raw -> hlen) ||
967 (memcmp (packet -> interface -> hw_address.haddr,
968 packet -> raw -> chaddr, packet -> raw -> hlen))) {
8ae2d595 969 log_debug ("DHCPNAK in wrong transaction.");
deff2d59
TL
970 return;
971 }
972
02d9e453
TL
973 if (client -> state != S_REBOOTING &&
974 client -> state != S_REQUESTING &&
975 client -> state != S_RENEWING &&
976 client -> state != S_REBINDING) {
8ae2d595 977 log_debug ("DHCPNAK in wrong state.");
deff2d59
TL
978 return;
979 }
980
8ae2d595 981 log_info ("DHCPNAK from %s", piaddr (packet -> client_addr));
34fdad6c 982
02d9e453 983 if (!client -> active) {
8ae2d595 984 log_info ("DHCPNAK with no active lease.\n");
deff2d59
TL
985 return;
986 }
987
02d9e453
TL
988 destroy_client_lease (client -> active);
989 client -> active = (struct client_lease *)0;
deff2d59
TL
990
991 /* Stop sending DHCPREQUEST packets... */
02d9e453 992 cancel_timeout (send_request, client);
deff2d59 993
02d9e453
TL
994 client -> state = S_INIT;
995 state_init (client);
e581d615
TL
996}
997
cc26de46 998/* Send out a DHCPDISCOVER packet, and set a timeout to send out another
66f973e4
TL
999 one after the right interval has expired. If we don't get an offer by
1000 the time we reach the panic interval, call the panic function. */
469cf3a4 1001
02d9e453
TL
1002void send_discover (cpp)
1003 void *cpp;
469cf3a4 1004{
02d9e453 1005 struct client_state *client = cpp;
84c4adde 1006
cc26de46
TL
1007 int result;
1008 int interval;
9bdb9271 1009 int increase = 1;
cc26de46
TL
1010
1011 /* Figure out how long it's been since we started transmitting. */
02d9e453 1012 interval = cur_time - client -> first_sending;
cc26de46
TL
1013
1014 /* If we're past the panic timeout, call the script and tell it
1015 we haven't found anything for this interface yet. */
02d9e453
TL
1016 if (interval > client -> config -> timeout) {
1017 state_panic (client);
b00d3884 1018 return;
cc26de46 1019 }
469cf3a4 1020
9bdb9271
TL
1021 /* If we're selecting media, try the whole list before doing
1022 the exponential backoff, but if we've already received an
1023 offer, stop looping, because we obviously have it right. */
02d9e453
TL
1024 if (!client -> offered_leases &&
1025 client -> config -> media) {
9bdb9271
TL
1026 int fail = 0;
1027 again:
02d9e453
TL
1028 if (client -> medium) {
1029 client -> medium = client -> medium -> next;
9bdb9271
TL
1030 increase = 0;
1031 }
02d9e453 1032 if (!client -> medium) {
9bdb9271 1033 if (fail)
8ae2d595 1034 log_fatal ("No valid media types for %s!",
02d9e453
TL
1035 client -> interface -> name);
1036 client -> medium =
1037 client -> config -> media;
9bdb9271
TL
1038 increase = 1;
1039 }
1040
8ae2d595 1041 log_info ("Trying medium \"%s\" %d",
02d9e453
TL
1042 client -> medium -> string, increase);
1043 script_init (client, "MEDIUM", client -> medium);
1044 if (script_go (client)) {
9bdb9271
TL
1045 goto again;
1046 }
1047 }
cc26de46 1048
9bdb9271
TL
1049 /* If we're supposed to increase the interval, do so. If it's
1050 currently zero (i.e., we haven't sent any packets yet), set
1051 it to one; otherwise, add to it a random number between
1052 zero and two times itself. On average, this means that it
1053 will double with every transmission. */
1054 if (increase) {
02d9e453
TL
1055 if (!client -> interval)
1056 client -> interval =
1057 client -> config -> initial_interval;
9bdb9271 1058 else {
02d9e453 1059 client -> interval +=
34fdad6c 1060 ((random () >> 2) %
02d9e453 1061 (2 * client -> interval));
9bdb9271 1062 }
cc26de46 1063
34fdad6c 1064 /* Don't backoff past cutoff. */
02d9e453
TL
1065 if (client -> interval >
1066 client -> config -> backoff_cutoff)
1067 client -> interval =
1068 ((client -> config -> backoff_cutoff / 2)
ae6ea807 1069 + ((random () >> 2) %
02d9e453
TL
1070 client -> config -> backoff_cutoff));
1071 } else if (!client -> interval)
1072 client -> interval = client -> config -> initial_interval;
9bdb9271 1073
cc26de46
TL
1074 /* If the backoff would take us to the panic timeout, just use that
1075 as the interval. */
02d9e453
TL
1076 if (cur_time + client -> interval >
1077 client -> first_sending + client -> config -> timeout)
1078 client -> interval =
1079 (client -> first_sending +
1080 client -> config -> timeout) - cur_time + 1;
cc26de46 1081
34fdad6c
TL
1082 /* Record the number of seconds since we started sending. */
1083 if (interval < 255)
02d9e453 1084 client -> packet.secs = interval;
34fdad6c 1085 else
02d9e453 1086 client -> packet.secs = 255;
34fdad6c 1087
8ae2d595 1088 log_info ("DHCPDISCOVER on %s to %s port %d interval %ld",
02d9e453 1089 client -> name ? client -> name : client -> interface -> name,
66f973e4 1090 inet_ntoa (sockaddr_broadcast.sin_addr),
02d9e453 1091 ntohs (sockaddr_broadcast.sin_port), client -> interval);
66f973e4 1092
cc26de46 1093 /* Send out a packet. */
02d9e453
TL
1094 result = send_packet (client -> interface, (struct packet *)0,
1095 &client -> packet,
1096 client -> packet_length,
cc26de46
TL
1097 inaddr_any, &sockaddr_broadcast,
1098 (struct hardware *)0);
469cf3a4 1099
02d9e453 1100 add_timeout (cur_time + client -> interval, send_discover, client);
469cf3a4
TL
1101}
1102
b00d3884
TL
1103/* state_panic gets called if we haven't received any offers in a preset
1104 amount of time. When this happens, we try to use existing leases that
1105 haven't yet expired, and failing that, we call the client script and
1106 hope it can do something. */
1107
02d9e453
TL
1108void state_panic (cpp)
1109 void *cpp;
b00d3884 1110{
02d9e453
TL
1111 struct client_state *client = cpp;
1112 struct client_lease *loop;
b00d3884
TL
1113 struct client_lease *lp;
1114
02d9e453
TL
1115 loop = lp = client -> active;
1116
8ae2d595 1117 log_info ("No DHCPOFFERS received.");
b00d3884 1118
deff2d59
TL
1119 /* We may not have an active lease, but we may have some
1120 predefined leases that we can try. */
02d9e453 1121 if (!client -> active && client -> leases)
deff2d59 1122 goto activate_next;
deff2d59 1123
b00d3884 1124 /* Run through the list of leases and see if one can be used. */
02d9e453
TL
1125 while (client -> active) {
1126 if (client -> active -> expiry > cur_time) {
8ae2d595 1127 log_info ("Trying recorded lease %s",
02d9e453 1128 piaddr (client -> active -> address));
b00d3884
TL
1129 /* Run the client script with the existing
1130 parameters. */
02d9e453
TL
1131 script_init (client, "TIMEOUT",
1132 client -> active -> medium);
1133 script_write_params (client, "new_", client -> active);
1134 if (client -> alias)
1135 script_write_params (client, "alias_",
1136 client -> alias);
b00d3884
TL
1137
1138 /* If the old lease is still good and doesn't
1139 yet need renewal, go into BOUND state and
1140 timeout at the renewal time. */
02d9e453 1141 if (!script_go (client)) {
b00d3884 1142 if (cur_time <
02d9e453
TL
1143 client -> active -> renewal) {
1144 client -> state = S_BOUND;
8ae2d595 1145 log_info ("bound: renewal in %d seconds.",
02d9e453 1146 client -> active -> renewal
b00d3884 1147 - cur_time);
02d9e453 1148 add_timeout ((client ->
b00d3884 1149 active -> renewal),
02d9e453 1150 state_bound, client);
b00d3884 1151 } else {
02d9e453 1152 client -> state = S_BOUND;
8ae2d595 1153 log_info ("bound: immediate renewal.");
02d9e453 1154 state_bound (client);
b00d3884
TL
1155 }
1156 reinitialize_interfaces ();
1157 go_daemon ();
1158 return;
1159 }
1160 }
1161
1162 /* If there are no other leases, give up. */
02d9e453
TL
1163 if (!client -> leases) {
1164 client -> leases = client -> active;
1165 client -> active = (struct client_lease *)0;
b00d3884
TL
1166 break;
1167 }
1168
deff2d59 1169 activate_next:
b00d3884
TL
1170 /* Otherwise, put the active lease at the end of the
1171 lease list, and try another lease.. */
02d9e453 1172 for (lp = client -> leases; lp -> next; lp = lp -> next)
b00d3884 1173 ;
02d9e453 1174 lp -> next = client -> active;
34fdad6c
TL
1175 if (lp -> next) {
1176 lp -> next -> next = (struct client_lease *)0;
1177 }
02d9e453
TL
1178 client -> active = client -> leases;
1179 client -> leases = client -> leases -> next;
b00d3884
TL
1180
1181 /* If we already tried this lease, we've exhausted the
1182 set of leases, so we might as well give up for
1183 now. */
02d9e453 1184 if (client -> active == loop)
b00d3884 1185 break;
66f973e4 1186 else if (!loop)
02d9e453 1187 loop = client -> active;
b00d3884
TL
1188 }
1189
1190 /* No leases were available, or what was available didn't work, so
1191 tell the shell script that we failed to allocate an address,
1192 and try again later. */
8ae2d595 1193 log_info ("No working leases in persistent database - sleeping.\n");
02d9e453
TL
1194 script_init (client, "FAIL", (struct string_list *)0);
1195 if (client -> alias)
1196 script_write_params (client, "alias_", client -> alias);
1197 script_go (client);
1198 client -> state = S_INIT;
1199 add_timeout (cur_time + client -> config -> retry_interval,
1200 state_init, client);
ae04fa03 1201 go_daemon ();
b00d3884
TL
1202}
1203
02d9e453
TL
1204void send_request (cpp)
1205 void *cpp;
e581d615 1206{
02d9e453 1207 struct client_state *client = cpp;
84c4adde 1208
c1503c57 1209 int result;
cc26de46
TL
1210 int interval;
1211 struct sockaddr_in destination;
1212 struct in_addr from;
1213
1214 /* Figure out how long it's been since we started transmitting. */
02d9e453 1215 interval = cur_time - client -> first_sending;
cc26de46 1216
34fdad6c
TL
1217 /* If we're in the INIT-REBOOT or REQUESTING state and we're
1218 past the reboot timeout, go to INIT and see if we can
1219 DISCOVER an address... */
1220 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
1221 means either that we're on a network with no DHCP server,
1222 or that our server is down. In the latter case, assuming
1223 that there is a backup DHCP server, DHCPDISCOVER will get
1224 us a new address, but we could also have successfully
1225 reused our old address. In the former case, we're hosed
1226 anyway. This is not a win-prone situation. */
02d9e453
TL
1227 if ((client -> state == S_REBOOTING ||
1228 client -> state == S_REQUESTING) &&
1229 interval > client -> config -> reboot_timeout) {
b8cf055d 1230 cancel:
02d9e453
TL
1231 client -> state = S_INIT;
1232 cancel_timeout (send_request, client);
1233 state_init (client);
deff2d59
TL
1234 return;
1235 }
1236
b8cf055d
TL
1237 /* If we're in the reboot state, make sure the media is set up
1238 correctly. */
02d9e453
TL
1239 if (client -> state == S_REBOOTING &&
1240 !client -> medium &&
1241 client -> active -> medium ) {
1242 script_init (client, "MEDIUM", client -> active -> medium);
b8cf055d
TL
1243
1244 /* If the medium we chose won't fly, go to INIT state. */
02d9e453 1245 if (script_go (client))
b8cf055d
TL
1246 goto cancel;
1247
1248 /* Record the medium. */
02d9e453 1249 client -> medium = client -> active -> medium;
b8cf055d
TL
1250 }
1251
cc26de46
TL
1252 /* If the lease has expired, relinquish the address and go back
1253 to the INIT state. */
02d9e453
TL
1254 if (client -> state != S_REQUESTING &&
1255 cur_time > client -> active -> expiry) {
cc26de46 1256 /* Run the client script with the new parameters. */
02d9e453
TL
1257 script_init (client, "EXPIRE", (struct string_list *)0);
1258 script_write_params (client, "old_", client -> active);
1259 if (client -> alias)
1260 script_write_params (client, "alias_",
1261 client -> alias);
1262 script_go (client);
1263
62d0cb47
TL
1264 /* Now do a preinit on the interface so that we can
1265 discover a new address. */
1266 script_init (client, "PREINIT", (struct string_list *)0);
1267 if (client -> alias)
1268 script_write_params (client, "alias_",
1269 client -> alias);
1270 script_go (client);
1271
02d9e453
TL
1272 client -> state = S_INIT;
1273 state_init (client);
cc26de46
TL
1274 return;
1275 }
1276
1277 /* Do the exponential backoff... */
02d9e453
TL
1278 if (!client -> interval)
1279 client -> interval = client -> config -> initial_interval;
34fdad6c 1280 else {
02d9e453
TL
1281 client -> interval += ((random () >> 2) %
1282 (2 * client -> interval));
34fdad6c
TL
1283 }
1284
1285 /* Don't backoff past cutoff. */
02d9e453
TL
1286 if (client -> interval >
1287 client -> config -> backoff_cutoff)
1288 client -> interval =
1289 ((client -> config -> backoff_cutoff / 2)
1290 + ((random () >> 2) % client -> interval));
cc26de46
TL
1291
1292 /* If the backoff would take us to the expiry time, just set the
1293 timeout to the expiry time. */
02d9e453
TL
1294 if (client -> state != S_REQUESTING &&
1295 cur_time + client -> interval > client -> active -> expiry)
1296 client -> interval =
1297 client -> active -> expiry - cur_time + 1;
cc26de46
TL
1298
1299 /* If the lease T2 time has elapsed, or if we're not yet bound,
1300 broadcast the DHCPREQUEST rather than unicasting. */
02d9e453 1301 if (client -> state == S_REQUESTING ||
62d0cb47 1302 client -> state == S_REBOOTING ||
02d9e453 1303 cur_time > client -> active -> rebind)
cc26de46
TL
1304 destination.sin_addr.s_addr = INADDR_BROADCAST;
1305 else
1306 memcpy (&destination.sin_addr.s_addr,
02d9e453 1307 client -> destination.iabuf,
cc26de46
TL
1308 sizeof destination.sin_addr.s_addr);
1309 destination.sin_port = remote_port;
b00d3884
TL
1310 destination.sin_family = AF_INET;
1311#ifdef HAVE_SA_LEN
1312 destination.sin_len = sizeof destination;
1313#endif
cc26de46 1314
7d3bc735
TL
1315 if (client -> state == S_RENEWING ||
1316 client -> state == S_REBINDING)
02d9e453 1317 memcpy (&from, client -> active -> address.iabuf,
cc26de46
TL
1318 sizeof from);
1319 else
1320 from.s_addr = INADDR_ANY;
1321
34fdad6c
TL
1322 /* Record the number of seconds since we started sending. */
1323 if (interval < 255)
02d9e453 1324 client -> packet.secs = interval;
34fdad6c 1325 else
02d9e453 1326 client -> packet.secs = 255;
34fdad6c 1327
8ae2d595 1328 log_info ("DHCPREQUEST on %s to %s port %d",
02d9e453 1329 client -> name ? client -> name : client -> interface -> name,
cc26de46
TL
1330 inet_ntoa (destination.sin_addr),
1331 ntohs (destination.sin_port));
1332
62d0cb47
TL
1333 if (destination.sin_addr.s_addr != INADDR_BROADCAST &&
1334 fallback_interface)
1335 result = send_packet (fallback_interface,
1336 (struct packet *)0,
1337 &client -> packet,
1338 client -> packet_length,
1339 from, &destination,
1340 (struct hardware *)0);
cc26de46 1341 else
cc26de46 1342 /* Send out a packet. */
02d9e453
TL
1343 result = send_packet (client -> interface, (struct packet *)0,
1344 &client -> packet,
1345 client -> packet_length,
cc26de46
TL
1346 from, &destination,
1347 (struct hardware *)0);
469cf3a4 1348
02d9e453
TL
1349 add_timeout (cur_time + client -> interval,
1350 send_request, client);
469cf3a4
TL
1351}
1352
02d9e453
TL
1353void send_decline (cpp)
1354 void *cpp;
b00d3884 1355{
02d9e453 1356 struct client_state *client = cpp;
84c4adde 1357
b00d3884
TL
1358 int result;
1359
8ae2d595 1360 log_info ("DHCPDECLINE on %s to %s port %d",
02d9e453 1361 client -> name ? client -> name : client -> interface -> name,
b00d3884
TL
1362 inet_ntoa (sockaddr_broadcast.sin_addr),
1363 ntohs (sockaddr_broadcast.sin_port));
1364
1365 /* Send out a packet. */
02d9e453
TL
1366 result = send_packet (client -> interface, (struct packet *)0,
1367 &client -> packet,
1368 client -> packet_length,
b00d3884
TL
1369 inaddr_any, &sockaddr_broadcast,
1370 (struct hardware *)0);
b00d3884
TL
1371}
1372
02d9e453
TL
1373void send_release (cpp)
1374 void *cpp;
b00d3884 1375{
02d9e453 1376 struct client_state *client = cpp;
84c4adde 1377
b00d3884
TL
1378 int result;
1379
8ae2d595 1380 log_info ("DHCPRELEASE on %s to %s port %d",
02d9e453 1381 client -> name ? client -> name : client -> interface -> name,
b00d3884
TL
1382 inet_ntoa (sockaddr_broadcast.sin_addr),
1383 ntohs (sockaddr_broadcast.sin_port));
1384
1385 /* Send out a packet. */
02d9e453
TL
1386 result = send_packet (client -> interface, (struct packet *)0,
1387 &client -> packet,
1388 client -> packet_length,
b00d3884
TL
1389 inaddr_any, &sockaddr_broadcast,
1390 (struct hardware *)0);
b00d3884
TL
1391}
1392
73530742 1393void make_client_options (client, lease, type, sid, rip, prl,
02a015fb 1394 options)
02d9e453 1395 struct client_state *client;
cc26de46 1396 struct client_lease *lease;
02a015fb
TL
1397 u_int8_t *type;
1398 struct option_cache *sid;
1399 struct iaddr *rip;
1400 u_int32_t *prl;
02a015fb 1401 struct option_state *options;
469cf3a4 1402{
deff2d59 1403 int i;
02a015fb
TL
1404 struct option_cache *oc;
1405 struct buffer *bp = (struct buffer *)0;
1406
1407 memset (options, 0, sizeof *options);
1408
1409 /* Send the server identifier if provided. */
1410 if (sid)
1411 save_option (options -> dhcp_hash, sid);
1412
2455808f
TL
1413 oc = (struct option_cache *)0;
1414
02a015fb
TL
1415 /* Send the requested address if provided. */
1416 if (rip) {
02d9e453 1417 client -> requested_address = *rip;
02a015fb
TL
1418 if (!(make_const_option_cache
1419 (&oc, (struct buffer **)0,
1420 rip -> iabuf, rip -> len,
1421 &dhcp_options [DHO_DHCP_REQUESTED_ADDRESS],
1422 "make_client_options")))
8ae2d595 1423 log_error ("can't make requested address option cache.");
02a015fb
TL
1424 else {
1425 save_option (options -> dhcp_hash, oc);
1426 option_cache_dereference (&oc, "make_client_options");
1427 }
b00d3884 1428 } else {
02d9e453 1429 client -> requested_address.len = 0;
cc26de46 1430 }
c1503c57 1431
02a015fb
TL
1432 if (!(make_const_option_cache
1433 (&oc, (struct buffer **)0,
1434 type, 1, &dhcp_options [DHO_DHCP_MESSAGE_TYPE],
1435 "make_client_options")))
8ae2d595 1436 log_error ("can't make message type.");
02a015fb
TL
1437 else {
1438 save_option (options -> dhcp_hash, oc);
1439 option_cache_dereference (&oc, "make_client_options");
1440 }
1441
1442 if (prl) {
1443 /* Figure out how many parameters were requested. */
1444 for (i = 0; prl [i]; i++)
1445 ;
1446 if (!buffer_allocate (&bp, i, "make_client_options"))
8ae2d595 1447 log_error ("can't make buffer for parameter request list.");
02a015fb
TL
1448 else {
1449 for (i = 0; prl [i]; i++)
1450 bp -> data [i] = prl [i];
1451 if (!(make_const_option_cache
1452 (&oc, &bp, (u_int8_t *)0, i,
1453 &dhcp_options [DHO_DHCP_PARAMETER_REQUEST_LIST],
1454 "make_client_options")))
8ae2d595 1455 log_error ("can't make option cache");
02a015fb
TL
1456 else {
1457 save_option (options -> dhcp_hash, oc);
1458 option_cache_dereference
1459 (&oc, "make_client_options");
1460 }
deff2d59
TL
1461 }
1462 }
1463
02a015fb
TL
1464 if (!(oc = lookup_option (options -> dhcp_hash,
1465 DHO_DHCP_LEASE_TIME))) {
1466 if (!buffer_allocate (&bp, sizeof (u_int32_t),
1467 "make_client_options"))
8ae2d595 1468 log_error ("can't make buffer for requested lease time.");
02a015fb
TL
1469 else {
1470 putULong (bp -> data,
02d9e453 1471 client -> config -> requested_lease);
02a015fb
TL
1472 if (!(make_const_option_cache
1473 (&oc, &bp, (u_int8_t *)0, sizeof (u_int32_t),
1474 &dhcp_options [DHO_DHCP_LEASE_TIME],
1475 "make_client_options")))
8ae2d595 1476 log_error ("can't make option cache");
02a015fb
TL
1477 else {
1478 save_option (options -> dhcp_hash, oc);
1479 option_cache_dereference
1480 (&oc, "make_client_options");
1481 }
1482 }
1483 }
2455808f
TL
1484 /* oc = (struct option_cache *)0; (we'd need this if we were
1485 going to use oc again */
02a015fb
TL
1486
1487 /* Run statements that need to be run on transmission. */
73530742
TL
1488 if (client -> config -> on_transmission)
1489 execute_statements_in_scope
1490 ((struct packet *)0, &lease -> options, options,
1491 client -> config -> on_transmission,
1492 (struct group *)0);
02a015fb
TL
1493}
1494
02d9e453
TL
1495void make_discover (client, lease)
1496 struct client_state *client;
02a015fb
TL
1497 struct client_lease *lease;
1498{
1499 struct dhcp_packet *raw;
1500 unsigned char discover = DHCPDISCOVER;
1501 int i;
1502 struct option_state options;
1503
02d9e453 1504 memset (&client -> packet, 0, sizeof (client -> packet));
02a015fb 1505
02d9e453
TL
1506 make_client_options (client,
1507 lease, &discover, (struct option_cache *)0,
02a015fb 1508 lease ? &lease -> address : (struct iaddr *)0,
02d9e453 1509 client -> config -> requested_options,
02a015fb
TL
1510 &options);
1511
c1503c57 1512 /* Set up the option buffer... */
02d9e453
TL
1513 client -> packet_length =
1514 cons_options ((struct packet *)0, &client -> packet, 0,
ce0ec46d
TL
1515 &options, (struct agent_options *)0,
1516 0, 0, 0, (struct data_string *)0);
02d9e453
TL
1517 if (client -> packet_length < BOOTP_MIN_LEN)
1518 client -> packet_length = BOOTP_MIN_LEN;
1519
1520 client -> packet.op = BOOTREQUEST;
1521 client -> packet.htype = client -> interface -> hw_address.htype;
1522 client -> packet.hlen = client -> interface -> hw_address.hlen;
1523 client -> packet.hops = 0;
1524 client -> packet.xid = random ();
1525 client -> packet.secs = 0; /* filled in by send_discover. */
02d9e453
TL
1526 memset (&(client -> packet.ciaddr),
1527 0, sizeof client -> packet.ciaddr);
1528 memset (&(client -> packet.yiaddr),
1529 0, sizeof client -> packet.yiaddr);
1530 memset (&(client -> packet.siaddr),
1531 0, sizeof client -> packet.siaddr);
1532 memset (&(client -> packet.giaddr),
1533 0, sizeof client -> packet.giaddr);
1534 memcpy (client -> packet.chaddr,
1535 client -> interface -> hw_address.haddr,
1536 client -> interface -> hw_address.hlen);
c1503c57
TL
1537
1538#ifdef DEBUG_PACKET
469cf3a4 1539 dump_packet (sendpkt);
02d9e453 1540 dump_raw ((unsigned char *)client -> packet,
cc26de46 1541 sendpkt->packet_length);
c1503c57 1542#endif
c1503c57
TL
1543}
1544
469cf3a4 1545
02d9e453
TL
1546void make_request (client, lease)
1547 struct client_state *client;
cc26de46 1548 struct client_lease *lease;
c1503c57 1549{
c1503c57 1550 unsigned char request = DHCPREQUEST;
ce0ec46d
TL
1551 int i, j;
1552 unsigned char *tmp, *digest;
1553 unsigned char *old_digest_loc;
02a015fb
TL
1554 struct option_state options;
1555 struct option_cache *oc;
c1503c57 1556
02d9e453 1557 memset (&client -> packet, 0, sizeof (client -> packet));
469cf3a4 1558
02d9e453 1559 if (client -> state == S_REQUESTING)
02a015fb
TL
1560 oc = lookup_option (lease -> options.dhcp_hash,
1561 DHO_DHCP_SERVER_IDENTIFIER);
1562 else
1563 oc = (struct option_cache *)0;
8dba80a6 1564
02d9e453
TL
1565 make_client_options (client, lease, &request, oc,
1566 ((client -> state == S_REQUESTING ||
1567 client -> state == S_REBOOTING)
02a015fb
TL
1568 ? &lease -> address
1569 : (struct iaddr *)0),
02d9e453 1570 client -> config -> requested_options,
02a015fb 1571 &options);
deff2d59 1572
c1503c57 1573 /* Set up the option buffer... */
02d9e453
TL
1574 client -> packet_length =
1575 cons_options ((struct packet *)0, &client -> packet, 0,
ce0ec46d
TL
1576 &options, (struct agent_options *)0,
1577 0, 0, 0, (struct data_string *)0);
02d9e453
TL
1578 if (client -> packet_length < BOOTP_MIN_LEN)
1579 client -> packet_length = BOOTP_MIN_LEN;
cc26de46 1580
02d9e453
TL
1581 client -> packet.op = BOOTREQUEST;
1582 client -> packet.htype = client -> interface -> hw_address.htype;
1583 client -> packet.hlen = client -> interface -> hw_address.hlen;
1584 client -> packet.hops = 0;
1585 client -> packet.xid = client -> xid;
1586 client -> packet.secs = 0; /* Filled in by send_request. */
7d3bc735
TL
1587 if (can_receive_unicast_unconfigured (client -> interface))
1588 client -> packet.flags = 0;
1589 else
1590 client -> packet.flags = htons (BOOTP_BROADCAST);
cc26de46
TL
1591
1592 /* If we own the address we're requesting, put it in ciaddr;
1593 otherwise set ciaddr to zero. */
02d9e453
TL
1594 if (client -> state == S_BOUND ||
1595 client -> state == S_RENEWING ||
62d0cb47 1596 client -> state == S_REBINDING) {
02d9e453 1597 memcpy (&client -> packet.ciaddr,
cc26de46 1598 lease -> address.iabuf, lease -> address.len);
339b0231 1599 client -> packet.flags = 0;
62d0cb47 1600 } else {
02d9e453
TL
1601 memset (&client -> packet.ciaddr, 0,
1602 sizeof client -> packet.ciaddr);
62d0cb47 1603 }
02d9e453
TL
1604
1605 memset (&client -> packet.yiaddr, 0,
1606 sizeof client -> packet.yiaddr);
1607 memset (&client -> packet.siaddr, 0,
1608 sizeof client -> packet.siaddr);
1609 memset (&client -> packet.giaddr, 0,
1610 sizeof client -> packet.giaddr);
1611 memcpy (client -> packet.chaddr,
1612 client -> interface -> hw_address.haddr,
1613 client -> interface -> hw_address.hlen);
c1503c57
TL
1614
1615#ifdef DEBUG_PACKET
469cf3a4 1616 dump_packet (sendpkt);
02d9e453 1617 dump_raw ((unsigned char *)client -> packet, sendpkt->packet_length);
c1503c57 1618#endif
469cf3a4 1619}
c1503c57 1620
02d9e453
TL
1621void make_decline (client, lease)
1622 struct client_state *client;
cc26de46 1623 struct client_lease *lease;
469cf3a4 1624{
cc26de46 1625 unsigned char decline = DHCPDECLINE;
deff2d59 1626 int i;
02a015fb 1627 struct option_cache *oc;
c1503c57 1628
02a015fb 1629 struct option_state options;
c1503c57 1630
02d9e453 1631 memset (&client -> packet, 0, sizeof (client -> packet));
469cf3a4 1632
02a015fb
TL
1633 oc = lookup_option (lease -> options.dhcp_hash,
1634 DHO_DHCP_SERVER_IDENTIFIER);
02d9e453 1635 make_client_options (client, lease, &decline, oc,
02a015fb 1636 &lease -> address, (u_int32_t *)0,
73530742 1637 &options);
ca25f4ab 1638
cc26de46 1639 /* Set up the option buffer... */
02d9e453
TL
1640 client -> packet_length =
1641 cons_options ((struct packet *)0, &client -> packet, 0,
ce0ec46d
TL
1642 &options, (struct agent_options *)0,
1643 0, 0, 0, (struct data_string *)0);
02d9e453
TL
1644 if (client -> packet_length < BOOTP_MIN_LEN)
1645 client -> packet_length = BOOTP_MIN_LEN;
cc26de46 1646
02d9e453
TL
1647 client -> packet.op = BOOTREQUEST;
1648 client -> packet.htype = client -> interface -> hw_address.htype;
1649 client -> packet.hlen = client -> interface -> hw_address.hlen;
1650 client -> packet.hops = 0;
1651 client -> packet.xid = client -> xid;
1652 client -> packet.secs = 0; /* Filled in by send_request. */
7d3bc735
TL
1653 if (can_receive_unicast_unconfigured (client -> interface))
1654 client -> packet.flags = 0;
1655 else
1656 client -> packet.flags = htons (BOOTP_BROADCAST);
cc26de46
TL
1657
1658 /* ciaddr must always be zero. */
02d9e453
TL
1659 memset (&client -> packet.ciaddr, 0,
1660 sizeof client -> packet.ciaddr);
1661 memset (&client -> packet.yiaddr, 0,
1662 sizeof client -> packet.yiaddr);
1663 memset (&client -> packet.siaddr, 0,
1664 sizeof client -> packet.siaddr);
1665 memset (&client -> packet.giaddr, 0,
1666 sizeof client -> packet.giaddr);
1667 memcpy (client -> packet.chaddr,
1668 client -> interface -> hw_address.haddr,
1669 client -> interface -> hw_address.hlen);
cc26de46
TL
1670
1671#ifdef DEBUG_PACKET
1672 dump_packet (sendpkt);
02d9e453 1673 dump_raw ((unsigned char *)client -> packet, sendpkt->packet_length);
cc26de46
TL
1674#endif
1675}
1676
02d9e453
TL
1677void make_release (client, lease)
1678 struct client_state *client;
cc26de46
TL
1679 struct client_lease *lease;
1680{
1681 unsigned char request = DHCPRELEASE;
deff2d59 1682 int i;
02a015fb 1683 struct option_cache *oc;
cc26de46 1684
02a015fb 1685 struct option_state options;
cc26de46 1686
02d9e453 1687 memset (&client -> packet, 0, sizeof (client -> packet));
469cf3a4 1688
02a015fb
TL
1689 oc = lookup_option (lease -> options.dhcp_hash,
1690 DHO_DHCP_SERVER_IDENTIFIER);
02d9e453 1691 make_client_options (client, lease, &request, oc,
02a015fb 1692 &lease -> address, (u_int32_t *)0,
73530742 1693 &options);
469cf3a4
TL
1694
1695 /* Set up the option buffer... */
02d9e453
TL
1696 client -> packet_length =
1697 cons_options ((struct packet *)0, &client -> packet, 0,
ce0ec46d
TL
1698 &options, (struct agent_options *)0,
1699 0, 0, 0, (struct data_string *)0);
02d9e453
TL
1700 if (client -> packet_length < BOOTP_MIN_LEN)
1701 client -> packet_length = BOOTP_MIN_LEN;
1702
1703 client -> packet.op = BOOTREQUEST;
1704 client -> packet.htype = client -> interface -> hw_address.htype;
1705 client -> packet.hlen = client -> interface -> hw_address.hlen;
1706 client -> packet.hops = 0;
74f45f96 1707 client -> packet.xid = random ();
02d9e453
TL
1708 client -> packet.secs = 0;
1709 client -> packet.flags = 0;
1710 memcpy (&client -> packet.ciaddr,
cc26de46 1711 lease -> address.iabuf, lease -> address.len);
02d9e453
TL
1712 memset (&client -> packet.yiaddr, 0,
1713 sizeof client -> packet.yiaddr);
1714 memset (&client -> packet.siaddr, 0,
1715 sizeof client -> packet.siaddr);
1716 memset (&client -> packet.giaddr, 0,
1717 sizeof client -> packet.giaddr);
1718 memcpy (client -> packet.chaddr,
1719 client -> interface -> hw_address.haddr,
1720 client -> interface -> hw_address.hlen);
469cf3a4
TL
1721
1722#ifdef DEBUG_PACKET
1723 dump_packet (sendpkt);
02d9e453
TL
1724 dump_raw ((unsigned char *)client -> packet,
1725 client -> packet_length);
469cf3a4 1726#endif
e581d615 1727}
cc26de46 1728
02a015fb 1729void destroy_client_lease (lease)
cc26de46
TL
1730 struct client_lease *lease;
1731{
1732 int i;
1733
1734 if (lease -> server_name)
02a015fb 1735 dfree (lease -> server_name, "destroy_client_lease");
cc26de46 1736 if (lease -> filename)
02a015fb
TL
1737 dfree (lease -> filename, "destroy_client_lease");
1738 option_state_dereference (&lease -> options);
1739 free_client_lease (lease, "destroy_client_lease");
cc26de46
TL
1740}
1741
1742FILE *leaseFile;
1743
1744void rewrite_client_leases ()
1745{
1746 struct interface_info *ip;
02d9e453 1747 struct client_state *client;
cc26de46
TL
1748 struct client_lease *lp;
1749
1750 if (leaseFile)
1751 fclose (leaseFile);
1752 leaseFile = fopen (path_dhclient_db, "w");
1753 if (!leaseFile)
8ae2d595 1754 log_fatal ("can't create %s: %m", path_dhclient_db);
b00d3884
TL
1755
1756 /* Write out all the leases attached to configured interfaces that
1757 we know about. */
cc26de46 1758 for (ip = interfaces; ip; ip = ip -> next) {
02d9e453
TL
1759 for (client = ip -> client; client; client = client -> next) {
1760 for (lp = client -> leases; lp; lp = lp -> next) {
1761 write_client_lease (client, lp, 1);
1762 }
1763 if (client -> active)
1764 write_client_lease (client,
1765 client -> active, 1);
cc26de46 1766 }
cc26de46 1767 }
b00d3884
TL
1768
1769 /* Write out any leases that are attached to interfaces that aren't
1770 currently configured. */
1771 for (ip = dummy_interfaces; ip; ip = ip -> next) {
02d9e453
TL
1772 for (client = ip -> client; client; client = client -> next) {
1773 for (lp = client -> leases; lp; lp = lp -> next) {
1774 write_client_lease (client, lp, 1);
1775 }
1776 if (client -> active)
1777 write_client_lease (client,
1778 client -> active, 1);
b00d3884 1779 }
b00d3884 1780 }
cc26de46
TL
1781 fflush (leaseFile);
1782}
1783
02d9e453
TL
1784void write_client_lease (client, lease, rewrite)
1785 struct client_state *client;
cc26de46 1786 struct client_lease *lease;
5c2f78b4 1787 int rewrite;
cc26de46
TL
1788{
1789 int i;
1790 struct tm *t;
5c2f78b4 1791 static int leases_written;
02a015fb
TL
1792 struct option_cache *oc;
1793 struct data_string ds;
5c2f78b4
TL
1794
1795 if (!rewrite) {
1796 if (leases_written++ > 20) {
1797 rewrite_client_leases ();
1798 leases_written = 0;
1799 }
1800 }
cc26de46 1801
b00d3884
TL
1802 /* If the lease came from the config file, we don't need to stash
1803 a copy in the lease database. */
1804 if (lease -> is_static)
1805 return;
1806
cc26de46
TL
1807 if (!leaseFile) { /* XXX */
1808 leaseFile = fopen (path_dhclient_db, "w");
1809 if (!leaseFile)
8ae2d595 1810 log_fatal ("can't create %s: %m", path_dhclient_db);
cc26de46
TL
1811 }
1812
1813 fprintf (leaseFile, "lease {\n");
66f973e4
TL
1814 if (lease -> is_bootp)
1815 fprintf (leaseFile, " bootp;\n");
02d9e453
TL
1816 fprintf (leaseFile, " interface \"%s\";\n",
1817 client -> interface -> name);
1818 if (client -> name)
1819 fprintf (leaseFile, " name \"%s\";\n", client -> name);
cc26de46
TL
1820 fprintf (leaseFile, " fixed-address %s;\n",
1821 piaddr (lease -> address));
1822 if (lease -> filename)
1823 fprintf (leaseFile, " filename \"%s\";\n",
1824 lease -> filename);
1825 if (lease -> server_name)
1826 fprintf (leaseFile, " server-name \"%s\";\n",
1827 lease -> filename);
9bdb9271
TL
1828 if (lease -> medium)
1829 fprintf (leaseFile, " medium \"%s\";\n",
1830 lease -> medium -> string);
2455808f
TL
1831
1832 memset (&ds, 0, sizeof ds);
02a015fb
TL
1833 for (i = 0; i < OPTION_HASH_SIZE; i++) {
1834 pair p;
1835 for (p = lease -> options.dhcp_hash [i]; p; p = p -> cdr) {
2455808f 1836 oc = (struct option_cache *)p -> car;
02a015fb
TL
1837 if (evaluate_option_cache (&ds, (struct packet *)0,
1838 &lease -> options, oc)) {
1839 fprintf (leaseFile,
1840 " option %s %s;\n",
2455808f 1841 oc -> option -> name,
02a015fb 1842 pretty_print_option
2455808f
TL
1843 (oc -> option -> code,
1844 ds.data, ds.len, 1, 1));
02a015fb
TL
1845 data_string_forget (&ds,
1846 "write_client_lease");
1847 }
cc26de46
TL
1848 }
1849 }
5c2f78b4
TL
1850
1851 /* Note: the following is not a Y2K bug - it's a Y1.9K bug. Until
1852 somebody invents a time machine, I think we can safely disregard
1853 it. */
cc26de46
TL
1854 t = gmtime (&lease -> renewal);
1855 fprintf (leaseFile,
1856 " renew %d %d/%d/%d %02d:%02d:%02d;\n",
1857 t -> tm_wday, t -> tm_year + 1900,
1858 t -> tm_mon + 1, t -> tm_mday,
1859 t -> tm_hour, t -> tm_min, t -> tm_sec);
1860 t = gmtime (&lease -> rebind);
1861 fprintf (leaseFile,
1862 " rebind %d %d/%d/%d %02d:%02d:%02d;\n",
1863 t -> tm_wday, t -> tm_year + 1900,
1864 t -> tm_mon + 1, t -> tm_mday,
1865 t -> tm_hour, t -> tm_min, t -> tm_sec);
1866 t = gmtime (&lease -> expiry);
1867 fprintf (leaseFile,
1868 " expire %d %d/%d/%d %02d:%02d:%02d;\n",
1869 t -> tm_wday, t -> tm_year + 1900,
1870 t -> tm_mon + 1, t -> tm_mday,
1871 t -> tm_hour, t -> tm_min, t -> tm_sec);
1872 fprintf (leaseFile, "}\n");
1873 fflush (leaseFile);
1874}
1875
1876/* Variables holding name of script and file pointer for writing to
1877 script. Needless to say, this is not reentrant - only one script
1878 can be invoked at a time. */
1879char scriptName [256];
1880FILE *scriptFile;
1881
02d9e453
TL
1882void script_init (client, reason, medium)
1883 struct client_state *client;
cc26de46 1884 char *reason;
9bdb9271 1885 struct string_list *medium;
cc26de46 1886{
b8cf055d
TL
1887 int fd;
1888#ifndef HAVE_MKSTEMP
cc26de46 1889
b8cf055d
TL
1890 do {
1891#endif
1892 strcpy (scriptName, "/tmp/dcsXXXXXX");
1893#ifdef HAVE_MKSTEMP
1894 fd = mkstemp (scriptName);
1895#else
8c135c14 1896 if (!mktemp (scriptName))
8ae2d595 1897 log_fatal ("can't create temporary client script %s: %m",
8c135c14 1898 scriptName);
b8cf055d
TL
1899 fd = creat (scriptName, 0600);
1900 } while (fd < 0);
1901#endif
1902
1903 scriptFile = fdopen (fd, "w");
cc26de46 1904 if (!scriptFile)
8ae2d595 1905 log_fatal ("can't write script file: %m");
cc26de46 1906 fprintf (scriptFile, "#!/bin/sh\n\n");
02d9e453
TL
1907 if (client) {
1908 if (client -> interface) {
1909 fprintf (scriptFile, "interface=\"%s\"\n",
1910 client -> interface -> name);
1911 fprintf (scriptFile, "export interface\n");
1912 }
1913 if (client -> name)
1914 fprintf (scriptFile, "client=\"%s\"\n",
1915 client -> name);
1916 fprintf (scriptFile, "export client\n");
cc26de46 1917 }
9bdb9271 1918 if (medium) {
d13e8f28 1919 fprintf (scriptFile, "medium=\"%s\"\n", medium -> string);
9bdb9271
TL
1920 fprintf (scriptFile, "export medium\n");
1921 }
cc26de46
TL
1922 fprintf (scriptFile, "reason=\"%s\"\n", reason);
1923 fprintf (scriptFile, "export reason\n");
1924}
1925
02d9e453
TL
1926void script_write_params (client, prefix, lease)
1927 struct client_state *client;
cc26de46
TL
1928 char *prefix;
1929 struct client_lease *lease;
1930{
1931 int i;
02a015fb
TL
1932 struct data_string data;
1933 struct option_cache *oc;
cc26de46
TL
1934
1935 fprintf (scriptFile, "%sip_address=\"%s\"\n",
1936 prefix, piaddr (lease -> address));
1937 fprintf (scriptFile, "export %sip_address\n", prefix);
c6abd205
TL
1938
1939 /* For the benefit of Linux (and operating systems which may
1940 have similar needs), compute the network address based on
1941 the supplied ip address and netmask, if provided. Also
1942 compute the broadcast address (the host address all ones
1943 broadcast address, not the host address all zeroes
1944 broadcast address). */
1945
02a015fb
TL
1946 memset (&data, 0, sizeof data);
1947 oc = lookup_option (lease -> options.dhcp_hash, DHO_SUBNET_MASK);
1948 if (oc && evaluate_option_cache (&data, (struct packet *)0,
1949 &lease -> options, oc)) {
1950 if (data.len > 3) {
1951 struct iaddr netmask, subnet, broadcast;
1952
1953 memcpy (netmask.iabuf, data.data, data.len);
1954 netmask.len = data.len;
1955 data_string_forget (&data, "script_write_params");
1956
1957 subnet = subnet_number (lease -> address, netmask);
1958 if (subnet.len) {
1959 fprintf (scriptFile,
1960 "%snetwork_number=\"%s\";\n",
1961 prefix, piaddr (subnet));
1962 fprintf (scriptFile,
1963 "export %snetwork_number\n", prefix);
1964
1965 oc = lookup_option (lease -> options.dhcp_hash,
1966 DHO_BROADCAST_ADDRESS);
1967 if (!oc ||
1968 !evaluate_option_cache (&data,
1969 (struct packet *)0,
1970 &lease -> options,
1971 oc)) {
1972 broadcast = broadcast_addr (subnet,
1973 netmask);
1974 if (broadcast.len) {
1975 fprintf (scriptFile,
1976 "%s%s=\"%s\";\n",
1977 prefix,
1978 "broadcast_address",
1979 piaddr (broadcast));
1980 fprintf (scriptFile,
1981 "export %s%s\n",
1982 prefix,
1983 "broadcast_address");
1984 }
c6abd205
TL
1985 }
1986 }
1987 }
2455808f 1988 data_string_forget (&data, "script_write_params");
c6abd205
TL
1989 }
1990
cc26de46
TL
1991 if (lease -> filename) {
1992 fprintf (scriptFile, "%sfilename=\"%s\";\n",
1993 prefix, lease -> filename);
1994 fprintf (scriptFile, "export %sfilename\n", prefix);
1995 }
1996 if (lease -> server_name) {
1997 fprintf (scriptFile, "%sserver_name=\"%s\";\n",
1998 prefix, lease -> server_name);
1999 fprintf (scriptFile, "export %sserver_name\n", prefix);
2000 }
02a015fb 2001
73530742
TL
2002 execute_statements_in_scope ((struct packet *)0, &lease -> options,
2003 &lease -> options,
2004 client -> config -> on_receipt,
2005 (struct group *)0);
02a015fb
TL
2006
2007 for (i = 0; i < OPTION_HASH_SIZE; i++) {
2008 pair hp;
2009
2010 for (hp = lease -> options.dhcp_hash [i]; hp; hp = hp -> cdr) {
2011 oc = (struct option_cache *)hp -> car;
2012
2013 if (evaluate_option_cache (&data, (struct packet *)0,
2014 &lease -> options, oc)) {
2015
2016 if (data.len) {
2017 char *s = (dhcp_option_ev_name
2018 (oc -> option));
2019
2020 fprintf (scriptFile,
2021 "%s%s=\"%s\"\n", prefix, s,
2022 (pretty_print_option
2455808f
TL
2023 (oc -> option -> code,
2024 data.data, data.len,
02a015fb
TL
2025 0, 0)));
2026 fprintf (scriptFile,
2027 "export %s%s\n", prefix, s);
66f973e4 2028 }
2455808f
TL
2029 data_string_forget (&data,
2030 "script_write_params");
66f973e4 2031 }
cc26de46
TL
2032 }
2033 }
2034 fprintf (scriptFile, "%sexpiry=\"%d\"\n",
2035 prefix, (int)lease -> expiry); /* XXX */
2036 fprintf (scriptFile, "export %sexpiry\n", prefix);
2037}
2038
02d9e453
TL
2039int script_go (client)
2040 struct client_state *client;
cc26de46
TL
2041{
2042 int rval;
2043
02d9e453 2044 if (client)
cc26de46 2045 fprintf (scriptFile, "%s\n",
02d9e453 2046 client -> config -> script_name);
cc26de46
TL
2047 else
2048 fprintf (scriptFile, "%s\n",
2049 top_level_config.script_name);
2050 fprintf (scriptFile, "exit $?\n");
2051 fclose (scriptFile);
2052 chmod (scriptName, 0700);
2053 rval = system (scriptName);
126965a9
TL
2054 if (!save_scripts)
2055 unlink (scriptName);
cc26de46
TL
2056 return rval;
2057}
2058
2059char *dhcp_option_ev_name (option)
2060 struct option *option;
2061{
2062 static char evbuf [256];
2063 int i;
2064
2065 if (strlen (option -> name) + 1 > sizeof evbuf)
8ae2d595 2066 log_fatal ("option %s name is larger than static buffer.");
cc26de46
TL
2067 for (i = 0; option -> name [i]; i++) {
2068 if (option -> name [i] == '-')
2069 evbuf [i] = '_';
2070 else
2071 evbuf [i] = option -> name [i];
2072 }
2073
2074 evbuf [i] = 0;
2075 return evbuf;
2076}
b00d3884
TL
2077
2078void go_daemon ()
2079{
2080 static int state = 0;
2081 int pid;
2082
2083 /* Don't become a daemon if the user requested otherwise. */
b8cf055d
TL
2084 if (no_daemon) {
2085 write_client_pid_file ();
b00d3884 2086 return;
b8cf055d 2087 }
b00d3884
TL
2088
2089 /* Only do it once. */
2090 if (state)
2091 return;
2092 state = 1;
2093
2094 /* Stop logging to stderr... */
2095 log_perror = 0;
2096
2097 /* Become a daemon... */
2098 if ((pid = fork ()) < 0)
8ae2d595 2099 log_fatal ("Can't fork daemon: %m");
b00d3884
TL
2100 else if (pid)
2101 exit (0);
2102 /* Become session leader and get pid... */
2103 pid = setsid ();
b8cf055d 2104
62d0cb47
TL
2105 /* Close standard I/O descriptors. */
2106 close(0);
2107 close(1);
2108 close(2);
2109
b8cf055d
TL
2110 write_client_pid_file ();
2111}
2112
2113void write_client_pid_file ()
2114{
2115 FILE *pf;
2116 int pfdesc;
2117
2118 pfdesc = open (path_dhclient_pid, O_CREAT | O_TRUNC | O_WRONLY, 0644);
2119
2120 if (pfdesc < 0) {
8ae2d595 2121 log_error ("Can't create %s: %m", path_dhclient_pid);
b8cf055d
TL
2122 return;
2123 }
2124
2125 pf = fdopen (pfdesc, "w");
2126 if (!pf)
8ae2d595 2127 log_error ("Can't fdopen %s: %m", path_dhclient_pid);
b8cf055d 2128 else {
19ea90f7 2129 fprintf (pf, "%ld\n", (long)getpid ());
b8cf055d
TL
2130 fclose (pf);
2131 }
2132}
2133
b8cf055d
TL
2134void client_location_changed ()
2135{
2136 struct interface_info *ip;
02d9e453 2137 struct client_state *client;
b8cf055d
TL
2138
2139 for (ip = interfaces; ip; ip = ip -> next) {
02d9e453
TL
2140 for (client = ip -> client; client; client = client -> next) {
2141 switch (client -> state) {
2142 case S_SELECTING:
2143 cancel_timeout (send_discover, client);
2144 break;
b8cf055d 2145
02d9e453
TL
2146 case S_BOUND:
2147 cancel_timeout (state_bound, client);
2148 break;
b8cf055d 2149
02d9e453
TL
2150 case S_REBOOTING:
2151 case S_REQUESTING:
2152 case S_RENEWING:
2153 cancel_timeout (send_request, client);
2154 break;
b8cf055d 2155
02d9e453
TL
2156 case S_INIT:
2157 case S_REBINDING:
2158 break;
2159 }
2160 client -> state = S_INIT;
2161 state_reboot (client);
b8cf055d 2162 }
b8cf055d
TL
2163 }
2164}