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