~ubuntu-branches/debian/sid/isc-dhcp/sid

« back to all changes in this revision

Viewing changes to .pc/dhclient-script-exit-status/client/dhclient.c

  • Committer: Package Import Robot
  • Author(s): Andrew Pollock
  • Date: 2012-03-13 22:04:53 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20120313220453-3f7mz58hopqeu2ew
Tags: 4.2.2.dfsg.1-3
* debian/control: remove transitional packages
* debian/rules: apply the intent of Pierre Chifflier's patch to enable
  hardening options (closes: #644413)
* debian/control: also add inetutils-ping to the dependencies for
  isc-dhcp-client on hurd (closes: #648140)
* Convert to 3.0 (quilt) source format:
  - debian/control: remove build-dep on dpatch
  - debian/rules: stop including dpatch.make
  - debian/rules: remove dpatch-related target dependencies
  - convert patches from dpatch to pure quilt
  - remove debian/README.source
* debian/rules: cleaned up the target names a bit to reflect the lack of
  patching going on now
* repack bind.tar.gz in upstream source tarball to patch configure.in for
  FTBFS on kFreeBSD and remove RFCs (closes: #643569, #645760)
* debian/watch: add dversionmangle to deal with dfsg upstream tarball
* Updated Dutch debconf template translation (closes: #651396)
* Added Polish debconf template translation (closes: #659372)
* Updated Brazilian Portugeuse debconf template translation (closes: #663494)
* debian/control: bumped Standards-Version (no changes)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* dhclient.c
 
2
 
 
3
   DHCP Client. */
 
4
 
 
5
/*
 
6
 * Copyright (c) 2004-2011 by Internet Systems Consortium, Inc. ("ISC")
 
7
 * Copyright (c) 1995-2003 by Internet Software Consortium
 
8
 *
 
9
 * Permission to use, copy, modify, and distribute this software for any
 
10
 * purpose with or without fee is hereby granted, provided that the above
 
11
 * copyright notice and this permission notice appear in all copies.
 
12
 *
 
13
 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
 
14
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 
15
 * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
 
16
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 
17
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 
18
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 
19
 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
20
 *
 
21
 *   Internet Systems Consortium, Inc.
 
22
 *   950 Charter Street
 
23
 *   Redwood City, CA 94063
 
24
 *   <info@isc.org>
 
25
 *   https://www.isc.org/
 
26
 *
 
27
 * This code is based on the original client state machine that was
 
28
 * written by Elliot Poger.  The code has been extensively hacked on
 
29
 * by Ted Lemon since then, so any mistakes you find are probably his
 
30
 * fault and not Elliot's.
 
31
 */
 
32
 
 
33
#include "dhcpd.h"
 
34
#include <syslog.h>
 
35
#include <signal.h>
 
36
#include <errno.h>
 
37
#include <sys/time.h>
 
38
#include <sys/wait.h>
 
39
#include <limits.h>
 
40
#include <dns/result.h>
 
41
 
 
42
TIME default_lease_time = 43200; /* 12 hours... */
 
43
TIME max_lease_time = 86400; /* 24 hours... */
 
44
 
 
45
const char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
 
46
const char *path_dhclient_db = NULL;
 
47
const char *path_dhclient_pid = NULL;
 
48
static char path_dhclient_script_array[] = _PATH_DHCLIENT_SCRIPT;
 
49
char *path_dhclient_script = path_dhclient_script_array;
 
50
 
 
51
/* False (default) => we write and use a pid file */
 
52
isc_boolean_t no_pid_file = ISC_FALSE;
 
53
 
 
54
int dhcp_max_agent_option_packet_length = 0;
 
55
 
 
56
int interfaces_requested = 0;
 
57
 
 
58
struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
 
59
struct iaddr iaddr_any = { 4, { 0, 0, 0, 0 } };
 
60
struct in_addr inaddr_any;
 
61
struct sockaddr_in sockaddr_broadcast;
 
62
struct in_addr giaddr;
 
63
struct data_string default_duid;
 
64
int duid_type = 0;
 
65
 
 
66
/* ASSERT_STATE() does nothing now; it used to be
 
67
   assert (state_is == state_shouldbe). */
 
68
#define ASSERT_STATE(state_is, state_shouldbe) {}
 
69
 
 
70
static const char copyright[] =
 
71
"Copyright 2004-2011 Internet Systems Consortium.";
 
72
static const char arr [] = "All rights reserved.";
 
73
static const char message [] = "Internet Systems Consortium DHCP Client";
 
74
static const char url [] = 
 
75
"For info, please visit https://www.isc.org/software/dhcp/";
 
76
 
 
77
u_int16_t local_port = 0;
 
78
u_int16_t remote_port = 0;
 
79
int no_daemon = 0;
 
80
struct string_list *client_env = NULL;
 
81
int client_env_count = 0;
 
82
int onetry = 0;
 
83
int quiet = 1;
 
84
int nowait = 0;
 
85
int stateless = 0;
 
86
int wanted_ia_na = -1;          /* the absolute value is the real one. */
 
87
int wanted_ia_ta = 0;
 
88
int wanted_ia_pd = 0;
 
89
char *mockup_relay = NULL;
 
90
 
 
91
void run_stateless(int exit_mode);
 
92
 
 
93
static void usage(void);
 
94
 
 
95
static isc_result_t write_duid(struct data_string *duid);
 
96
static void add_reject(struct packet *packet);
 
97
 
 
98
static int check_domain_name(const char *ptr, size_t len, int dots);
 
99
static int check_domain_name_list(const char *ptr, size_t len, int dots);
 
100
static int check_option_values(struct universe *universe, unsigned int opt,
 
101
                               const char *ptr, size_t len);
 
102
 
 
103
int
 
104
main(int argc, char **argv) {
 
105
        int fd;
 
106
        int i;
 
107
        struct interface_info *ip;
 
108
        struct client_state *client;
 
109
        unsigned seed;
 
110
        char *server = NULL;
 
111
        isc_result_t status;
 
112
        int exit_mode = 0;
 
113
        int release_mode = 0;
 
114
        struct timeval tv;
 
115
        omapi_object_t *listener;
 
116
        isc_result_t result;
 
117
        int persist = 0;
 
118
        int no_dhclient_conf = 0;
 
119
        int no_dhclient_db = 0;
 
120
        int no_dhclient_pid = 0;
 
121
        int no_dhclient_script = 0;
 
122
#ifdef DHCPv6
 
123
        int local_family_set = 0;
 
124
#endif /* DHCPv6 */
 
125
        char *s;
 
126
 
 
127
        /* Initialize client globals. */
 
128
        memset(&default_duid, 0, sizeof(default_duid));
 
129
 
 
130
        /* Make sure that file descriptors 0 (stdin), 1, (stdout), and
 
131
           2 (stderr) are open. To do this, we assume that when we
 
132
           open a file the lowest available file descriptor is used. */
 
133
        fd = open("/dev/null", O_RDWR);
 
134
        if (fd == 0)
 
135
                fd = open("/dev/null", O_RDWR);
 
136
        if (fd == 1)
 
137
                fd = open("/dev/null", O_RDWR);
 
138
        if (fd == 2)
 
139
                log_perror = 0; /* No sense logging to /dev/null. */
 
140
        else if (fd != -1)
 
141
                close(fd);
 
142
 
 
143
        openlog("dhclient", LOG_NDELAY, LOG_DAEMON);
 
144
 
 
145
#if !(defined(DEBUG) || defined(__CYGWIN32__))
 
146
        setlogmask(LOG_UPTO(LOG_INFO));
 
147
#endif
 
148
 
 
149
        /* Set up the isc and dns library managers */
 
150
        status = dhcp_context_create();
 
151
        if (status != ISC_R_SUCCESS)
 
152
                log_fatal("Can't initialize context: %s",
 
153
                          isc_result_totext(status));
 
154
 
 
155
        /* Set up the OMAPI. */
 
156
        status = omapi_init();
 
157
        if (status != ISC_R_SUCCESS)
 
158
                log_fatal("Can't initialize OMAPI: %s",
 
159
                          isc_result_totext(status));
 
160
 
 
161
        /* Set up the OMAPI wrappers for various server database internal
 
162
           objects. */
 
163
        dhcp_common_objects_setup();
 
164
 
 
165
        dhcp_interface_discovery_hook = dhclient_interface_discovery_hook;
 
166
        dhcp_interface_shutdown_hook = dhclient_interface_shutdown_hook;
 
167
        dhcp_interface_startup_hook = dhclient_interface_startup_hook;
 
168
 
 
169
        for (i = 1; i < argc; i++) {
 
170
                if (!strcmp(argv[i], "-r")) {
 
171
                        release_mode = 1;
 
172
                        no_daemon = 1;
 
173
#ifdef DHCPv6
 
174
                } else if (!strcmp(argv[i], "-4")) {
 
175
                        if (local_family_set && local_family != AF_INET)
 
176
                                log_fatal("Client can only do v4 or v6, not "
 
177
                                          "both.");
 
178
                        local_family_set = 1;
 
179
                        local_family = AF_INET;
 
180
                } else if (!strcmp(argv[i], "-6")) {
 
181
                        if (local_family_set && local_family != AF_INET6)
 
182
                                log_fatal("Client can only do v4 or v6, not "
 
183
                                          "both.");
 
184
                        local_family_set = 1;
 
185
                        local_family = AF_INET6;
 
186
#endif /* DHCPv6 */
 
187
                } else if (!strcmp(argv[i], "-x")) { /* eXit, no release */
 
188
                        release_mode = 0;
 
189
                        no_daemon = 0;
 
190
                        exit_mode = 1;
 
191
                } else if (!strcmp(argv[i], "-p")) {
 
192
                        if (++i == argc)
 
193
                                usage();
 
194
                        local_port = validate_port(argv[i]);
 
195
                        log_debug("binding to user-specified port %d",
 
196
                                  ntohs(local_port));
 
197
                } else if (!strcmp(argv[i], "-d")) {
 
198
                        no_daemon = 1;
 
199
                        quiet = 0;
 
200
                } else if (!strcmp(argv[i], "-pf")) {
 
201
                        if (++i == argc)
 
202
                                usage();
 
203
                        path_dhclient_pid = argv[i];
 
204
                        no_dhclient_pid = 1;
 
205
                } else if (!strcmp(argv[i], "--no-pid")) {
 
206
                        no_pid_file = ISC_TRUE;
 
207
                } else if (!strcmp(argv[i], "-cf")) {
 
208
                        if (++i == argc)
 
209
                                usage();
 
210
                        path_dhclient_conf = argv[i];
 
211
                        no_dhclient_conf = 1;
 
212
                } else if (!strcmp(argv[i], "-lf")) {
 
213
                        if (++i == argc)
 
214
                                usage();
 
215
                        path_dhclient_db = argv[i];
 
216
                        no_dhclient_db = 1;
 
217
                } else if (!strcmp(argv[i], "-sf")) {
 
218
                        if (++i == argc)
 
219
                                usage();
 
220
                        path_dhclient_script = argv[i];
 
221
                        no_dhclient_script = 1;
 
222
                } else if (!strcmp(argv[i], "-1")) {
 
223
                        onetry = 1;
 
224
                } else if (!strcmp(argv[i], "-q")) {
 
225
                        quiet = 1;
 
226
                } else if (!strcmp(argv[i], "-s")) {
 
227
                        if (++i == argc)
 
228
                                usage();
 
229
                        server = argv[i];
 
230
                } else if (!strcmp(argv[i], "-g")) {
 
231
                        if (++i == argc)
 
232
                                usage();
 
233
                        mockup_relay = argv[i];
 
234
                } else if (!strcmp(argv[i], "-nw")) {
 
235
                        nowait = 1;
 
236
                } else if (!strcmp(argv[i], "-n")) {
 
237
                        /* do not start up any interfaces */
 
238
                        interfaces_requested = -1;
 
239
                } else if (!strcmp(argv[i], "-w")) {
 
240
                        /* do not exit if there are no broadcast interfaces. */
 
241
                        persist = 1;
 
242
                } else if (!strcmp(argv[i], "-e")) {
 
243
                        struct string_list *tmp;
 
244
                        if (++i == argc)
 
245
                                usage();
 
246
                        tmp = dmalloc(strlen(argv[i]) + sizeof *tmp, MDL);
 
247
                        if (!tmp)
 
248
                                log_fatal("No memory for %s", argv[i]);
 
249
                        strcpy(tmp->string, argv[i]);
 
250
                        tmp->next = client_env;
 
251
                        client_env = tmp;
 
252
                        client_env_count++;
 
253
#ifdef DHCPv6
 
254
                } else if (!strcmp(argv[i], "-S")) {
 
255
                        if (local_family_set && (local_family == AF_INET)) {
 
256
                                usage();
 
257
                        }
 
258
                        local_family_set = 1;
 
259
                        local_family = AF_INET6;
 
260
                        wanted_ia_na = 0;
 
261
                        stateless = 1;
 
262
                } else if (!strcmp(argv[i], "-N")) {
 
263
                        if (local_family_set && (local_family == AF_INET)) {
 
264
                                usage();
 
265
                        }
 
266
                        local_family_set = 1;
 
267
                        local_family = AF_INET6;
 
268
                        if (wanted_ia_na < 0) {
 
269
                                wanted_ia_na = 0;
 
270
                        }
 
271
                        wanted_ia_na++;
 
272
                } else if (!strcmp(argv[i], "-T")) {
 
273
                        if (local_family_set && (local_family == AF_INET)) {
 
274
                                usage();
 
275
                        }
 
276
                        local_family_set = 1;
 
277
                        local_family = AF_INET6;
 
278
                        if (wanted_ia_na < 0) {
 
279
                                wanted_ia_na = 0;
 
280
                        }
 
281
                        wanted_ia_ta++;
 
282
                } else if (!strcmp(argv[i], "-P")) {
 
283
                        if (local_family_set && (local_family == AF_INET)) {
 
284
                                usage();
 
285
                        }
 
286
                        local_family_set = 1;
 
287
                        local_family = AF_INET6;
 
288
                        if (wanted_ia_na < 0) {
 
289
                                wanted_ia_na = 0;
 
290
                        }
 
291
                        wanted_ia_pd++;
 
292
                } else if (!strcmp(argv[i], "-D")) {
 
293
                        if (local_family_set && (local_family == AF_INET)) {
 
294
                                usage();
 
295
                        }
 
296
                        local_family_set = 1;
 
297
                        local_family = AF_INET6;
 
298
                        if (++i == argc)
 
299
                                usage();
 
300
                        if (!strcasecmp(argv[i], "LL")) {
 
301
                                duid_type = DUID_LL;
 
302
                        } else if (!strcasecmp(argv[i], "LLT")) {
 
303
                                duid_type = DUID_LLT;
 
304
                        } else {
 
305
                                usage();
 
306
                        }
 
307
#endif /* DHCPv6 */
 
308
                } else if (!strcmp(argv[i], "-v")) {
 
309
                        quiet = 0;
 
310
                } else if (!strcmp(argv[i], "--version")) {
 
311
                        log_info("isc-dhclient-%s", PACKAGE_VERSION);
 
312
                        exit(0);
 
313
                } else if (argv[i][0] == '-') {
 
314
                    usage();
 
315
                } else if (interfaces_requested < 0) {
 
316
                    usage();
 
317
                } else {
 
318
                    struct interface_info *tmp = NULL;
 
319
 
 
320
                    status = interface_allocate(&tmp, MDL);
 
321
                    if (status != ISC_R_SUCCESS)
 
322
                        log_fatal("Can't record interface %s:%s",
 
323
                                  argv[i], isc_result_totext(status));
 
324
                    if (strlen(argv[i]) >= sizeof(tmp->name))
 
325
                            log_fatal("%s: interface name too long (is %ld)",
 
326
                                      argv[i], (long)strlen(argv[i]));
 
327
                    strcpy(tmp->name, argv[i]);
 
328
                    if (interfaces) {
 
329
                            interface_reference(&tmp->next,
 
330
                                                interfaces, MDL);
 
331
                            interface_dereference(&interfaces, MDL);
 
332
                    }
 
333
                    interface_reference(&interfaces, tmp, MDL);
 
334
                    tmp->flags = INTERFACE_REQUESTED;
 
335
                    interfaces_requested++;
 
336
                }
 
337
        }
 
338
 
 
339
        if (wanted_ia_na < 0) {
 
340
                wanted_ia_na = 1;
 
341
        }
 
342
 
 
343
        /* Support only one (requested) interface for Prefix Delegation. */
 
344
        if (wanted_ia_pd && (interfaces_requested != 1)) {
 
345
                usage();
 
346
        }
 
347
 
 
348
        if (!no_dhclient_conf && (s = getenv("PATH_DHCLIENT_CONF"))) {
 
349
                path_dhclient_conf = s;
 
350
        }
 
351
        if (!no_dhclient_db && (s = getenv("PATH_DHCLIENT_DB"))) {
 
352
                path_dhclient_db = s;
 
353
        }
 
354
        if (!no_dhclient_pid && (s = getenv("PATH_DHCLIENT_PID"))) {
 
355
                path_dhclient_pid = s;
 
356
        }
 
357
        if (!no_dhclient_script && (s = getenv("PATH_DHCLIENT_SCRIPT"))) {
 
358
                path_dhclient_script = s;
 
359
        }
 
360
 
 
361
        /* Set up the initial dhcp option universe. */
 
362
        initialize_common_option_spaces();
 
363
 
 
364
        /* Assign v4 or v6 specific running parameters. */
 
365
        if (local_family == AF_INET)
 
366
                dhcpv4_client_assignments();
 
367
#ifdef DHCPv6
 
368
        else if (local_family == AF_INET6)
 
369
                dhcpv6_client_assignments();
 
370
#endif /* DHCPv6 */
 
371
        else
 
372
                log_fatal("Impossible condition at %s:%d.", MDL);
 
373
 
 
374
        /*
 
375
         * convert relative path names to absolute, for files that need
 
376
         * to be reopened after chdir() has been called
 
377
         */
 
378
        if (path_dhclient_db[0] != '/') {
 
379
                char *path = dmalloc(PATH_MAX, MDL);
 
380
                if (path == NULL)
 
381
                        log_fatal("No memory for filename\n");
 
382
                path_dhclient_db = realpath(path_dhclient_db, path);
 
383
                if (path_dhclient_db == NULL)
 
384
                        log_fatal("%s: %s", path, strerror(errno));
 
385
        }
 
386
 
 
387
        if (path_dhclient_script[0] != '/') {
 
388
                char *path = dmalloc(PATH_MAX, MDL);
 
389
                if (path == NULL)
 
390
                        log_fatal("No memory for filename\n");
 
391
                path_dhclient_script = realpath(path_dhclient_script, path);
 
392
                if (path_dhclient_script == NULL)
 
393
                        log_fatal("%s: %s", path, strerror(errno));
 
394
        }
 
395
 
 
396
        /*
 
397
         * See if we should  kill off any currently running client
 
398
         * we don't try to kill it off if the user told us not
 
399
         * to write a pid file - we assume they are controlling
 
400
         * the process in some other fashion.
 
401
         */
 
402
        if ((release_mode || exit_mode) && (no_pid_file == ISC_FALSE)) {
 
403
                FILE *pidfd;
 
404
                pid_t oldpid;
 
405
                long temp;
 
406
                int e;
 
407
 
 
408
                oldpid = 0;
 
409
                if ((pidfd = fopen(path_dhclient_pid, "r")) != NULL) {
 
410
                        e = fscanf(pidfd, "%ld\n", &temp);
 
411
                        oldpid = (pid_t)temp;
 
412
 
 
413
                        if (e != 0 && e != EOF) {
 
414
                                if (oldpid)
 
415
                                        kill(oldpid, SIGTERM);
 
416
                        }
 
417
                        fclose(pidfd);
 
418
                }
 
419
        }
 
420
 
 
421
        if (!quiet) {
 
422
                log_info("%s %s", message, PACKAGE_VERSION);
 
423
                log_info(copyright);
 
424
                log_info(arr);
 
425
                log_info(url);
 
426
                log_info("%s", "");
 
427
        } else {
 
428
                log_perror = 0;
 
429
                quiet_interface_discovery = 1;
 
430
        }
 
431
 
 
432
        /* If we're given a relay agent address to insert, for testing
 
433
           purposes, figure out what it is. */
 
434
        if (mockup_relay) {
 
435
                if (!inet_aton(mockup_relay, &giaddr)) {
 
436
                        struct hostent *he;
 
437
                        he = gethostbyname(mockup_relay);
 
438
                        if (he) {
 
439
                                memcpy(&giaddr, he->h_addr_list[0],
 
440
                                       sizeof giaddr);
 
441
                        } else {
 
442
                                log_fatal("%s: no such host", mockup_relay);
 
443
                        }
 
444
                }
 
445
        }
 
446
 
 
447
        /* Get the current time... */
 
448
        gettimeofday(&cur_tv, NULL);
 
449
 
 
450
        sockaddr_broadcast.sin_family = AF_INET;
 
451
        sockaddr_broadcast.sin_port = remote_port;
 
452
        if (server) {
 
453
                if (!inet_aton(server, &sockaddr_broadcast.sin_addr)) {
 
454
                        struct hostent *he;
 
455
                        he = gethostbyname(server);
 
456
                        if (he) {
 
457
                                memcpy(&sockaddr_broadcast.sin_addr,
 
458
                                       he->h_addr_list[0],
 
459
                                       sizeof sockaddr_broadcast.sin_addr);
 
460
                        } else
 
461
                                sockaddr_broadcast.sin_addr.s_addr =
 
462
                                        INADDR_BROADCAST;
 
463
                }
 
464
        } else {
 
465
                sockaddr_broadcast.sin_addr.s_addr = INADDR_BROADCAST;
 
466
        }
 
467
 
 
468
        inaddr_any.s_addr = INADDR_ANY;
 
469
 
 
470
        /* Stateless special case. */
 
471
        if (stateless) {
 
472
                if (release_mode || (wanted_ia_na > 0) ||
 
473
                    wanted_ia_ta || wanted_ia_pd ||
 
474
                    (interfaces_requested != 1)) {
 
475
                        usage();
 
476
                }
 
477
                run_stateless(exit_mode);
 
478
                return 0;
 
479
        }
 
480
 
 
481
        /* Discover all the network interfaces. */
 
482
        discover_interfaces(DISCOVER_UNCONFIGURED);
 
483
 
 
484
        /* Parse the dhclient.conf file. */
 
485
        read_client_conf();
 
486
 
 
487
        /* Parse the lease database. */
 
488
        read_client_leases();
 
489
 
 
490
        /* Rewrite the lease database... */
 
491
        rewrite_client_leases();
 
492
 
 
493
        /* XXX */
 
494
/*      config_counter(&snd_counter, &rcv_counter); */
 
495
 
 
496
        /*
 
497
         * If no broadcast interfaces were discovered, call the script
 
498
         * and tell it so.
 
499
         */
 
500
        if (!interfaces) {
 
501
                /*
 
502
                 * Call dhclient-script with the NBI flag,
 
503
                 * in case somebody cares.
 
504
                 */
 
505
                script_init(NULL, "NBI", NULL);
 
506
                script_go(NULL);
 
507
 
 
508
                /*
 
509
                 * If we haven't been asked to persist, waiting for new
 
510
                 * interfaces, then just exit.
 
511
                 */
 
512
                if (!persist) {
 
513
                        /* Nothing more to do. */
 
514
                        log_info("No broadcast interfaces found - exiting.");
 
515
                        exit(0);
 
516
                }
 
517
        } else if (!release_mode && !exit_mode) {
 
518
                /* Call the script with the list of interfaces. */
 
519
                for (ip = interfaces; ip; ip = ip->next) {
 
520
                        /*
 
521
                         * If interfaces were specified, don't configure
 
522
                         * interfaces that weren't specified!
 
523
                         */
 
524
                        if ((interfaces_requested > 0) &&
 
525
                            ((ip->flags & (INTERFACE_REQUESTED |
 
526
                                           INTERFACE_AUTOMATIC)) !=
 
527
                             INTERFACE_REQUESTED))
 
528
                                continue;
 
529
 
 
530
                        if (local_family == AF_INET6) {
 
531
                                script_init(ip->client, "PREINIT6", NULL);
 
532
                        } else {
 
533
                                script_init(ip->client, "PREINIT", NULL);
 
534
                                if (ip->client->alias != NULL)
 
535
                                        script_write_params(ip->client,
 
536
                                                            "alias_",
 
537
                                                            ip->client->alias);
 
538
                        }
 
539
                        script_go(ip->client);
 
540
                }
 
541
        }
 
542
 
 
543
        /* At this point, all the interfaces that the script thinks
 
544
           are relevant should be running, so now we once again call
 
545
           discover_interfaces(), and this time ask it to actually set
 
546
           up the interfaces. */
 
547
        discover_interfaces(interfaces_requested != 0
 
548
                            ? DISCOVER_REQUESTED
 
549
                            : DISCOVER_RUNNING);
 
550
 
 
551
        /* Make up a seed for the random number generator from current
 
552
           time plus the sum of the last four bytes of each
 
553
           interface's hardware address interpreted as an integer.
 
554
           Not much entropy, but we're booting, so we're not likely to
 
555
           find anything better. */
 
556
        seed = 0;
 
557
        for (ip = interfaces; ip; ip = ip->next) {
 
558
                int junk;
 
559
                memcpy(&junk,
 
560
                       &ip->hw_address.hbuf[ip->hw_address.hlen -
 
561
                                            sizeof seed], sizeof seed);
 
562
                seed += junk;
 
563
        }
 
564
        srandom(seed + cur_time + (unsigned)getpid());
 
565
 
 
566
        /* Start a configuration state machine for each interface. */
 
567
#ifdef DHCPv6
 
568
        if (local_family == AF_INET6) {
 
569
                /* Establish a default DUID.  This may be moved to the
 
570
                 * DHCPv4 area later.
 
571
                 */
 
572
                if (default_duid.len == 0) {
 
573
                        if (default_duid.buffer != NULL)
 
574
                                data_string_forget(&default_duid, MDL);
 
575
 
 
576
                        form_duid(&default_duid, MDL);
 
577
                        write_duid(&default_duid);
 
578
                }
 
579
 
 
580
                for (ip = interfaces ; ip != NULL ; ip = ip->next) {
 
581
                        for (client = ip->client ; client != NULL ;
 
582
                             client = client->next) {
 
583
                                if (release_mode) {
 
584
                                        start_release6(client);
 
585
                                        continue;
 
586
                                } else if (exit_mode) {
 
587
                                        unconfigure6(client, "STOP6");
 
588
                                        continue;
 
589
                                }
 
590
 
 
591
                                /* If we have a previous binding, Confirm
 
592
                                 * that we can (or can't) still use it.
 
593
                                 */
 
594
                                if ((client->active_lease != NULL) &&
 
595
                                    !client->active_lease->released)
 
596
                                        start_confirm6(client);
 
597
                                else
 
598
                                        start_init6(client);
 
599
                        }
 
600
                }
 
601
        } else
 
602
#endif /* DHCPv6 */
 
603
        {
 
604
                for (ip = interfaces ; ip ; ip = ip->next) {
 
605
                        ip->flags |= INTERFACE_RUNNING;
 
606
                        for (client = ip->client ; client ;
 
607
                             client = client->next) {
 
608
                                if (exit_mode)
 
609
                                        state_stop(client);
 
610
                                else if (release_mode)
 
611
                                        do_release(client);
 
612
                                else {
 
613
                                        client->state = S_INIT;
 
614
 
 
615
                                        if (top_level_config.initial_delay>0)
 
616
                                        {
 
617
                                                tv.tv_sec = 0;
 
618
                                                if (top_level_config.
 
619
                                                    initial_delay>1)
 
620
                                                        tv.tv_sec = cur_time
 
621
                                                        + random()
 
622
                                                        % (top_level_config.
 
623
                                                           initial_delay-1);
 
624
                                                tv.tv_usec = random()
 
625
                                                        % 1000000;
 
626
                                                /*
 
627
                                                 * this gives better
 
628
                                                 * distribution than just
 
629
                                                 *whole seconds
 
630
                                                 */
 
631
                                                add_timeout(&tv, state_reboot,
 
632
                                                            client, 0, 0);
 
633
                                        } else {
 
634
                                                state_reboot(client);
 
635
                                        }
 
636
                                }
 
637
                        }
 
638
                }
 
639
        }
 
640
 
 
641
        if (exit_mode)
 
642
                return 0;
 
643
        if (release_mode) {
 
644
#ifndef DHCPv6
 
645
                return 0;
 
646
#else
 
647
                if (local_family == AF_INET6) {
 
648
                        if (onetry)
 
649
                                return 0;
 
650
                } else
 
651
                        return 0;
 
652
#endif /* DHCPv6 */
 
653
        }
 
654
 
 
655
        /* Start up a listener for the object management API protocol. */
 
656
        if (top_level_config.omapi_port != -1) {
 
657
                listener = NULL;
 
658
                result = omapi_generic_new(&listener, MDL);
 
659
                if (result != ISC_R_SUCCESS)
 
660
                        log_fatal("Can't allocate new generic object: %s\n",
 
661
                                  isc_result_totext(result));
 
662
                result = omapi_protocol_listen(listener,
 
663
                                               (unsigned)
 
664
                                               top_level_config.omapi_port,
 
665
                                               1);
 
666
                if (result != ISC_R_SUCCESS)
 
667
                        log_fatal("Can't start OMAPI protocol: %s",
 
668
                                  isc_result_totext (result));
 
669
        }
 
670
 
 
671
        /* Set up the bootp packet handler... */
 
672
        bootp_packet_handler = do_packet;
 
673
#ifdef DHCPv6
 
674
        dhcpv6_packet_handler = do_packet6;
 
675
#endif /* DHCPv6 */
 
676
 
 
677
#if defined(DEBUG_MEMORY_LEAKAGE) || defined(DEBUG_MALLOC_POOL) || \
 
678
                defined(DEBUG_MEMORY_LEAKAGE_ON_EXIT)
 
679
        dmalloc_cutoff_generation = dmalloc_generation;
 
680
        dmalloc_longterm = dmalloc_outstanding;
 
681
        dmalloc_outstanding = 0;
 
682
#endif
 
683
 
 
684
        /* If we're not supposed to wait before getting the address,
 
685
           don't. */
 
686
        if (nowait)
 
687
                go_daemon();
 
688
 
 
689
        /* If we're not going to daemonize, write the pid file
 
690
           now. */
 
691
        if (no_daemon || nowait)
 
692
                write_client_pid_file();
 
693
 
 
694
        /* Start dispatching packets and timeouts... */
 
695
        dispatch();
 
696
 
 
697
        /*NOTREACHED*/
 
698
        return 0;
 
699
}
 
700
 
 
701
static void usage()
 
702
{
 
703
        log_info("%s %s", message, PACKAGE_VERSION);
 
704
        log_info(copyright);
 
705
        log_info(arr);
 
706
        log_info(url);
 
707
 
 
708
 
 
709
        log_fatal("Usage: dhclient "
 
710
#ifdef DHCPv6
 
711
                  "[-4|-6] [-SNTP1dvrx] [-nw] [-p <port>] [-D LL|LLT]\n"
 
712
#else /* DHCPv6 */
 
713
                  "[-1dvrx] [-nw] [-p <port>]\n"
 
714
#endif /* DHCPv6 */
 
715
                  "                [-s server-addr] [-cf config-file] "
 
716
                  "[-lf lease-file]\n"
 
717
                  "                [-pf pid-file] [--no-pid] [-e VAR=val]\n"
 
718
                  "                [-sf script-file] [interface]");
 
719
}
 
720
 
 
721
void run_stateless(int exit_mode)
 
722
{
 
723
#ifdef DHCPv6
 
724
        struct client_state *client;
 
725
        omapi_object_t *listener;
 
726
        isc_result_t result;
 
727
 
 
728
        /* Discover the network interface. */
 
729
        discover_interfaces(DISCOVER_REQUESTED);
 
730
 
 
731
        if (!interfaces)
 
732
                usage();
 
733
 
 
734
        /* Parse the dhclient.conf file. */
 
735
        read_client_conf();
 
736
 
 
737
        /* Parse the lease database. */
 
738
        read_client_leases();
 
739
 
 
740
        /* Establish a default DUID. */
 
741
        if (default_duid.len == 0) {
 
742
                if (default_duid.buffer != NULL)
 
743
                        data_string_forget(&default_duid, MDL);
 
744
 
 
745
                form_duid(&default_duid, MDL);
 
746
        }
 
747
 
 
748
        /* Start a configuration state machine. */
 
749
        for (client = interfaces->client ;
 
750
             client != NULL ;
 
751
             client = client->next) {
 
752
                if (exit_mode) {
 
753
                        unconfigure6(client, "STOP6");
 
754
                        continue;
 
755
                }
 
756
                start_info_request6(client);
 
757
        }
 
758
        if (exit_mode)
 
759
                return;
 
760
 
 
761
        /* Start up a listener for the object management API protocol. */
 
762
        if (top_level_config.omapi_port != -1) {
 
763
                listener = NULL;
 
764
                result = omapi_generic_new(&listener, MDL);
 
765
                if (result != ISC_R_SUCCESS)
 
766
                        log_fatal("Can't allocate new generic object: %s\n",
 
767
                                  isc_result_totext(result));
 
768
                result = omapi_protocol_listen(listener,
 
769
                                               (unsigned)
 
770
                                               top_level_config.omapi_port,
 
771
                                               1);
 
772
                if (result != ISC_R_SUCCESS)
 
773
                        log_fatal("Can't start OMAPI protocol: %s",
 
774
                                  isc_result_totext(result));
 
775
        }
 
776
 
 
777
        /* Set up the packet handler... */
 
778
        dhcpv6_packet_handler = do_packet6;
 
779
 
 
780
#if defined(DEBUG_MEMORY_LEAKAGE) || defined(DEBUG_MALLOC_POOL) || \
 
781
                defined(DEBUG_MEMORY_LEAKAGE_ON_EXIT)
 
782
        dmalloc_cutoff_generation = dmalloc_generation;
 
783
        dmalloc_longterm = dmalloc_outstanding;
 
784
        dmalloc_outstanding = 0;
 
785
#endif
 
786
 
 
787
        /* If we're not supposed to wait before getting the address,
 
788
           don't. */
 
789
        if (nowait)
 
790
                go_daemon();
 
791
 
 
792
        /* If we're not going to daemonize, write the pid file
 
793
           now. */
 
794
        if (no_daemon || nowait)
 
795
                write_client_pid_file();
 
796
 
 
797
        /* Start dispatching packets and timeouts... */
 
798
        dispatch();
 
799
 
 
800
        /*NOTREACHED*/
 
801
#endif /* DHCPv6 */
 
802
        return;
 
803
}
 
804
 
 
805
isc_result_t find_class (struct class **c,
 
806
                const char *s, const char *file, int line)
 
807
{
 
808
        return 0;
 
809
}
 
810
 
 
811
int check_collection (packet, lease, collection)
 
812
        struct packet *packet;
 
813
        struct lease *lease;
 
814
        struct collection *collection;
 
815
{
 
816
        return 0;
 
817
}
 
818
 
 
819
void classify (packet, class)
 
820
        struct packet *packet;
 
821
        struct class *class;
 
822
{
 
823
}
 
824
 
 
825
int unbill_class (lease, class)
 
826
        struct lease *lease;
 
827
        struct class *class;
 
828
{
 
829
        return 0;
 
830
}
 
831
 
 
832
int find_subnet (struct subnet **sp,
 
833
                 struct iaddr addr, const char *file, int line)
 
834
{
 
835
        return 0;
 
836
}
 
837
 
 
838
/* Individual States:
 
839
 *
 
840
 * Each routine is called from the dhclient_state_machine() in one of
 
841
 * these conditions:
 
842
 * -> entering INIT state
 
843
 * -> recvpacket_flag == 0: timeout in this state
 
844
 * -> otherwise: received a packet in this state
 
845
 *
 
846
 * Return conditions as handled by dhclient_state_machine():
 
847
 * Returns 1, sendpacket_flag = 1: send packet, reset timer.
 
848
 * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
 
849
 * Returns 0: finish the nap which was interrupted for no good reason.
 
850
 *
 
851
 * Several per-interface variables are used to keep track of the process:
 
852
 *   active_lease: the lease that is being used on the interface
 
853
 *                 (null pointer if not configured yet).
 
854
 *   offered_leases: leases corresponding to DHCPOFFER messages that have
 
855
 *                   been sent to us by DHCP servers.
 
856
 *   acked_leases: leases corresponding to DHCPACK messages that have been
 
857
 *                 sent to us by DHCP servers.
 
858
 *   sendpacket: DHCP packet we're trying to send.
 
859
 *   destination: IP address to send sendpacket to
 
860
 * In addition, there are several relevant per-lease variables.
 
861
 *   T1_expiry, T2_expiry, lease_expiry: lease milestones
 
862
 * In the active lease, these control the process of renewing the lease;
 
863
 * In leases on the acked_leases list, this simply determines when we
 
864
 * can no longer legitimately use the lease.
 
865
 */
 
866
 
 
867
void state_reboot (cpp)
 
868
        void *cpp;
 
869
{
 
870
        struct client_state *client = cpp;
 
871
 
 
872
        /* If we don't remember an active lease, go straight to INIT. */
 
873
        if (!client -> active ||
 
874
            client -> active -> is_bootp ||
 
875
            client -> active -> expiry <= cur_time) {
 
876
                state_init (client);
 
877
                return;
 
878
        }
 
879
 
 
880
        /* We are in the rebooting state. */
 
881
        client -> state = S_REBOOTING;
 
882
 
 
883
        /*
 
884
         * make_request doesn't initialize xid because it normally comes
 
885
         * from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
 
886
         * so pick an xid now.
 
887
         */
 
888
        client -> xid = random ();
 
889
 
 
890
        /*
 
891
         * Make a DHCPREQUEST packet, and set
 
892
         * appropriate per-interface flags.
 
893
         */
 
894
        make_request (client, client -> active);
 
895
        client -> destination = iaddr_broadcast;
 
896
        client -> first_sending = cur_time;
 
897
        client -> interval = client -> config -> initial_interval;
 
898
 
 
899
        /* Zap the medium list... */
 
900
        client -> medium = NULL;
 
901
 
 
902
        /* Send out the first DHCPREQUEST packet. */
 
903
        send_request (client);
 
904
}
 
905
 
 
906
/* Called when a lease has completely expired and we've been unable to
 
907
   renew it. */
 
908
 
 
909
void state_init (cpp)
 
910
        void *cpp;
 
911
{
 
912
        struct client_state *client = cpp;
 
913
 
 
914
        ASSERT_STATE(state, S_INIT);
 
915
 
 
916
        /* Make a DHCPDISCOVER packet, and set appropriate per-interface
 
917
           flags. */
 
918
        make_discover (client, client -> active);
 
919
        client -> xid = client -> packet.xid;
 
920
        client -> destination = iaddr_broadcast;
 
921
        client -> state = S_SELECTING;
 
922
        client -> first_sending = cur_time;
 
923
        client -> interval = client -> config -> initial_interval;
 
924
 
 
925
        /* Add an immediate timeout to cause the first DHCPDISCOVER packet
 
926
           to go out. */
 
927
        send_discover (client);
 
928
}
 
929
 
 
930
/*
 
931
 * state_selecting is called when one or more DHCPOFFER packets have been
 
932
 * received and a configurable period of time has passed.
 
933
 */
 
934
 
 
935
void state_selecting (cpp)
 
936
        void *cpp;
 
937
{
 
938
        struct client_state *client = cpp;
 
939
        struct client_lease *lp, *next, *picked;
 
940
 
 
941
 
 
942
        ASSERT_STATE(state, S_SELECTING);
 
943
 
 
944
        /*
 
945
         * Cancel state_selecting and send_discover timeouts, since either
 
946
         * one could have got us here.
 
947
         */
 
948
        cancel_timeout (state_selecting, client);
 
949
        cancel_timeout (send_discover, client);
 
950
 
 
951
        /*
 
952
         * We have received one or more DHCPOFFER packets.   Currently,
 
953
         * the only criterion by which we judge leases is whether or
 
954
         * not we get a response when we arp for them.
 
955
         */
 
956
        picked = NULL;
 
957
        for (lp = client -> offered_leases; lp; lp = next) {
 
958
                next = lp -> next;
 
959
 
 
960
                /*
 
961
                 * Check to see if we got an ARPREPLY for the address
 
962
                 * in this particular lease.
 
963
                 */
 
964
                if (!picked) {
 
965
                        picked = lp;
 
966
                        picked -> next = NULL;
 
967
                } else {
 
968
                        destroy_client_lease (lp);
 
969
                }
 
970
        }
 
971
        client -> offered_leases = NULL;
 
972
 
 
973
        /*
 
974
         * If we just tossed all the leases we were offered, go back
 
975
         * to square one.
 
976
         */
 
977
        if (!picked) {
 
978
                client -> state = S_INIT;
 
979
                state_init (client);
 
980
                return;
 
981
        }
 
982
 
 
983
        /* If it was a BOOTREPLY, we can just take the address right now. */
 
984
        if (picked -> is_bootp) {
 
985
                client -> new = picked;
 
986
 
 
987
                /* Make up some lease expiry times
 
988
                   XXX these should be configurable. */
 
989
                client -> new -> expiry = cur_time + 12000;
 
990
                client -> new -> renewal += cur_time + 8000;
 
991
                client -> new -> rebind += cur_time + 10000;
 
992
 
 
993
                client -> state = S_REQUESTING;
 
994
 
 
995
                /* Bind to the address we received. */
 
996
                bind_lease (client);
 
997
                return;
 
998
        }
 
999
 
 
1000
        /* Go to the REQUESTING state. */
 
1001
        client -> destination = iaddr_broadcast;
 
1002
        client -> state = S_REQUESTING;
 
1003
        client -> first_sending = cur_time;
 
1004
        client -> interval = client -> config -> initial_interval;
 
1005
 
 
1006
        /* Make a DHCPREQUEST packet from the lease we picked. */
 
1007
        make_request (client, picked);
 
1008
        client -> xid = client -> packet.xid;
 
1009
 
 
1010
        /* Toss the lease we picked - we'll get it back in a DHCPACK. */
 
1011
        destroy_client_lease (picked);
 
1012
 
 
1013
        /* Add an immediate timeout to send the first DHCPREQUEST packet. */
 
1014
        send_request (client);
 
1015
}
 
1016
 
 
1017
/* state_requesting is called when we receive a DHCPACK message after
 
1018
   having sent out one or more DHCPREQUEST packets. */
 
1019
 
 
1020
void dhcpack (packet)
 
1021
        struct packet *packet;
 
1022
{
 
1023
        struct interface_info *ip = packet -> interface;
 
1024
        struct client_state *client;
 
1025
        struct client_lease *lease;
 
1026
        struct option_cache *oc;
 
1027
        struct data_string ds;
 
1028
 
 
1029
        /* If we're not receptive to an offer right now, or if the offer
 
1030
           has an unrecognizable transaction id, then just drop it. */
 
1031
        for (client = ip -> client; client; client = client -> next) {
 
1032
                if (client -> xid == packet -> raw -> xid)
 
1033
                        break;
 
1034
        }
 
1035
        if (!client ||
 
1036
            (packet -> interface -> hw_address.hlen - 1 !=
 
1037
             packet -> raw -> hlen) ||
 
1038
            (memcmp (&packet -> interface -> hw_address.hbuf [1],
 
1039
                     packet -> raw -> chaddr, packet -> raw -> hlen))) {
 
1040
#if defined (DEBUG)
 
1041
                log_debug ("DHCPACK in wrong transaction.");
 
1042
#endif
 
1043
                return;
 
1044
        }
 
1045
 
 
1046
        if (client -> state != S_REBOOTING &&
 
1047
            client -> state != S_REQUESTING &&
 
1048
            client -> state != S_RENEWING &&
 
1049
            client -> state != S_REBINDING) {
 
1050
#if defined (DEBUG)
 
1051
                log_debug ("DHCPACK in wrong state.");
 
1052
#endif
 
1053
                return;
 
1054
        }
 
1055
 
 
1056
        log_info ("DHCPACK from %s", piaddr (packet -> client_addr));
 
1057
 
 
1058
        lease = packet_to_lease (packet, client);
 
1059
        if (!lease) {
 
1060
                log_info ("packet_to_lease failed.");
 
1061
                return;
 
1062
        }
 
1063
 
 
1064
        client -> new = lease;
 
1065
 
 
1066
        /* Stop resending DHCPREQUEST. */
 
1067
        cancel_timeout (send_request, client);
 
1068
 
 
1069
        /* Figure out the lease time. */
 
1070
        oc = lookup_option (&dhcp_universe, client -> new -> options,
 
1071
                            DHO_DHCP_LEASE_TIME);
 
1072
        memset (&ds, 0, sizeof ds);
 
1073
        if (oc &&
 
1074
            evaluate_option_cache (&ds, packet, (struct lease *)0, client,
 
1075
                                   packet -> options, client -> new -> options,
 
1076
                                   &global_scope, oc, MDL)) {
 
1077
                if (ds.len > 3)
 
1078
                        client -> new -> expiry = getULong (ds.data);
 
1079
                else
 
1080
                        client -> new -> expiry = 0;
 
1081
                data_string_forget (&ds, MDL);
 
1082
        } else
 
1083
                        client -> new -> expiry = 0;
 
1084
 
 
1085
        if (client->new->expiry == 0) {
 
1086
                struct timeval tv;
 
1087
 
 
1088
                log_error ("no expiry time on offered lease.");
 
1089
 
 
1090
                /* Quench this (broken) server.  Return to INIT to reselect. */
 
1091
                add_reject(packet);
 
1092
 
 
1093
                /* 1/2 second delay to restart at INIT. */
 
1094
                tv.tv_sec = cur_tv.tv_sec;
 
1095
                tv.tv_usec = cur_tv.tv_usec + 500000;
 
1096
 
 
1097
                if (tv.tv_usec >= 1000000) {
 
1098
                        tv.tv_sec++;
 
1099
                        tv.tv_usec -= 1000000;
 
1100
                }
 
1101
 
 
1102
                add_timeout(&tv, state_init, client, 0, 0);
 
1103
                return;
 
1104
        }
 
1105
 
 
1106
        /*
 
1107
         * A number that looks negative here is really just very large,
 
1108
         * because the lease expiry offset is unsigned.
 
1109
         */
 
1110
        if (client->new->expiry < 0)
 
1111
                client->new->expiry = TIME_MAX;
 
1112
 
 
1113
        /* Take the server-provided renewal time if there is one. */
 
1114
        oc = lookup_option (&dhcp_universe, client -> new -> options,
 
1115
                            DHO_DHCP_RENEWAL_TIME);
 
1116
        if (oc &&
 
1117
            evaluate_option_cache (&ds, packet, (struct lease *)0, client,
 
1118
                                   packet -> options, client -> new -> options,
 
1119
                                   &global_scope, oc, MDL)) {
 
1120
                if (ds.len > 3)
 
1121
                        client -> new -> renewal = getULong (ds.data);
 
1122
                else
 
1123
                        client -> new -> renewal = 0;
 
1124
                data_string_forget (&ds, MDL);
 
1125
        } else
 
1126
                        client -> new -> renewal = 0;
 
1127
 
 
1128
        /* If it wasn't specified by the server, calculate it. */
 
1129
        if (!client -> new -> renewal)
 
1130
                client -> new -> renewal = client -> new -> expiry / 2 + 1;
 
1131
 
 
1132
        if (client -> new -> renewal <= 0)
 
1133
                client -> new -> renewal = TIME_MAX;
 
1134
 
 
1135
        /* Now introduce some randomness to the renewal time: */
 
1136
        if (client->new->renewal <= ((TIME_MAX / 3) - 3))
 
1137
                client->new->renewal = (((client->new->renewal * 3) + 3) / 4) +
 
1138
                                (((random() % client->new->renewal) + 3) / 4);
 
1139
 
 
1140
        /* Same deal with the rebind time. */
 
1141
        oc = lookup_option (&dhcp_universe, client -> new -> options,
 
1142
                            DHO_DHCP_REBINDING_TIME);
 
1143
        if (oc &&
 
1144
            evaluate_option_cache (&ds, packet, (struct lease *)0, client,
 
1145
                                   packet -> options, client -> new -> options,
 
1146
                                   &global_scope, oc, MDL)) {
 
1147
                if (ds.len > 3)
 
1148
                        client -> new -> rebind = getULong (ds.data);
 
1149
                else
 
1150
                        client -> new -> rebind = 0;
 
1151
                data_string_forget (&ds, MDL);
 
1152
        } else
 
1153
                        client -> new -> rebind = 0;
 
1154
 
 
1155
        if (client -> new -> rebind <= 0) {
 
1156
                if (client -> new -> expiry <= TIME_MAX / 7)
 
1157
                        client -> new -> rebind =
 
1158
                                        client -> new -> expiry * 7 / 8;
 
1159
                else
 
1160
                        client -> new -> rebind =
 
1161
                                        client -> new -> expiry / 8 * 7;
 
1162
        }
 
1163
 
 
1164
        /* Make sure our randomness didn't run the renewal time past the
 
1165
           rebind time. */
 
1166
        if (client -> new -> renewal > client -> new -> rebind) {
 
1167
                if (client -> new -> rebind <= TIME_MAX / 3)
 
1168
                        client -> new -> renewal =
 
1169
                                        client -> new -> rebind * 3 / 4;
 
1170
                else
 
1171
                        client -> new -> renewal =
 
1172
                                        client -> new -> rebind / 4 * 3;
 
1173
        }
 
1174
 
 
1175
        client -> new -> expiry += cur_time;
 
1176
        /* Lease lengths can never be negative. */
 
1177
        if (client -> new -> expiry < cur_time)
 
1178
                client -> new -> expiry = TIME_MAX;
 
1179
        client -> new -> renewal += cur_time;
 
1180
        if (client -> new -> renewal < cur_time)
 
1181
                client -> new -> renewal = TIME_MAX;
 
1182
        client -> new -> rebind += cur_time;
 
1183
        if (client -> new -> rebind < cur_time)
 
1184
                client -> new -> rebind = TIME_MAX;
 
1185
 
 
1186
        bind_lease (client);
 
1187
}
 
1188
 
 
1189
void bind_lease (client)
 
1190
        struct client_state *client;
 
1191
{
 
1192
        struct timeval tv;
 
1193
 
 
1194
        /* Remember the medium. */
 
1195
        client -> new -> medium = client -> medium;
 
1196
 
 
1197
        /* Run the client script with the new parameters. */
 
1198
        script_init (client, (client -> state == S_REQUESTING
 
1199
                          ? "BOUND"
 
1200
                          : (client -> state == S_RENEWING
 
1201
                             ? "RENEW"
 
1202
                             : (client -> state == S_REBOOTING
 
1203
                                ? "REBOOT" : "REBIND"))),
 
1204
                     client -> new -> medium);
 
1205
        if (client -> active && client -> state != S_REBOOTING)
 
1206
                script_write_params (client, "old_", client -> active);
 
1207
        script_write_params (client, "new_", client -> new);
 
1208
        if (client -> alias)
 
1209
                script_write_params (client, "alias_", client -> alias);
 
1210
 
 
1211
        /* If the BOUND/RENEW code detects another machine using the
 
1212
           offered address, it exits nonzero.  We need to send a
 
1213
           DHCPDECLINE and toss the lease. */
 
1214
        if (script_go (client)) {
 
1215
                make_decline (client, client -> new);
 
1216
                send_decline (client);
 
1217
                destroy_client_lease (client -> new);
 
1218
                client -> new = (struct client_lease *)0;
 
1219
                state_init (client);
 
1220
                return;
 
1221
        }
 
1222
 
 
1223
        /* Write out the new lease if it has been long enough. */
 
1224
        if (!client->last_write ||
 
1225
            (cur_time - client->last_write) >= MIN_LEASE_WRITE)
 
1226
                write_client_lease(client, client->new, 0, 0);
 
1227
 
 
1228
        /* Replace the old active lease with the new one. */
 
1229
        if (client -> active)
 
1230
                destroy_client_lease (client -> active);
 
1231
        client -> active = client -> new;
 
1232
        client -> new = (struct client_lease *)0;
 
1233
 
 
1234
        /* Set up a timeout to start the renewal process. */
 
1235
        tv.tv_sec = client->active->renewal;
 
1236
        tv.tv_usec = ((client->active->renewal - cur_tv.tv_sec) > 1) ?
 
1237
                        random() % 1000000 : cur_tv.tv_usec;
 
1238
        add_timeout(&tv, state_bound, client, 0, 0);
 
1239
 
 
1240
        log_info ("bound to %s -- renewal in %ld seconds.",
 
1241
              piaddr (client -> active -> address),
 
1242
              (long)(client -> active -> renewal - cur_time));
 
1243
        client -> state = S_BOUND;
 
1244
        reinitialize_interfaces ();
 
1245
        go_daemon ();
 
1246
#if defined (NSUPDATE)
 
1247
        if (client->config->do_forward_update)
 
1248
                dhclient_schedule_updates(client, &client->active->address, 1);
 
1249
#endif
 
1250
}
 
1251
 
 
1252
/* state_bound is called when we've successfully bound to a particular
 
1253
   lease, but the renewal time on that lease has expired.   We are
 
1254
   expected to unicast a DHCPREQUEST to the server that gave us our
 
1255
   original lease. */
 
1256
 
 
1257
void state_bound (cpp)
 
1258
        void *cpp;
 
1259
{
 
1260
        struct client_state *client = cpp;
 
1261
        struct option_cache *oc;
 
1262
        struct data_string ds;
 
1263
 
 
1264
        ASSERT_STATE(state, S_BOUND);
 
1265
 
 
1266
        /* T1 has expired. */
 
1267
        make_request (client, client -> active);
 
1268
        client -> xid = client -> packet.xid;
 
1269
 
 
1270
        memset (&ds, 0, sizeof ds);
 
1271
        oc = lookup_option (&dhcp_universe, client -> active -> options,
 
1272
                            DHO_DHCP_SERVER_IDENTIFIER);
 
1273
        if (oc &&
 
1274
            evaluate_option_cache (&ds, (struct packet *)0, (struct lease *)0,
 
1275
                                   client, (struct option_state *)0,
 
1276
                                   client -> active -> options,
 
1277
                                   &global_scope, oc, MDL)) {
 
1278
                if (ds.len > 3) {
 
1279
                        memcpy (client -> destination.iabuf, ds.data, 4);
 
1280
                        client -> destination.len = 4;
 
1281
                } else
 
1282
                        client -> destination = iaddr_broadcast;
 
1283
 
 
1284
                data_string_forget (&ds, MDL);
 
1285
        } else
 
1286
                client -> destination = iaddr_broadcast;
 
1287
 
 
1288
        client -> first_sending = cur_time;
 
1289
        client -> interval = client -> config -> initial_interval;
 
1290
        client -> state = S_RENEWING;
 
1291
 
 
1292
        /* Send the first packet immediately. */
 
1293
        send_request (client);
 
1294
}
 
1295
 
 
1296
/* state_stop is called when we've been told to shut down.   We unconfigure
 
1297
   the interfaces, and then stop operating until told otherwise. */
 
1298
 
 
1299
void state_stop (cpp)
 
1300
        void *cpp;
 
1301
{
 
1302
        struct client_state *client = cpp;
 
1303
 
 
1304
        /* Cancel all timeouts. */
 
1305
        cancel_timeout(state_selecting, client);
 
1306
        cancel_timeout(send_discover, client);
 
1307
        cancel_timeout(send_request, client);
 
1308
        cancel_timeout(state_bound, client);
 
1309
 
 
1310
        /* If we have an address, unconfigure it. */
 
1311
        if (client->active) {
 
1312
                script_init(client, "STOP", client->active->medium);
 
1313
                script_write_params(client, "old_", client->active);
 
1314
                if (client->alias)
 
1315
                        script_write_params(client, "alias_", client->alias);
 
1316
                script_go(client);
 
1317
        }
 
1318
}
 
1319
 
 
1320
int commit_leases ()
 
1321
{
 
1322
        return 0;
 
1323
}
 
1324
 
 
1325
int write_lease (lease)
 
1326
        struct lease *lease;
 
1327
{
 
1328
        return 0;
 
1329
}
 
1330
 
 
1331
int write_host (host)
 
1332
        struct host_decl *host;
 
1333
{
 
1334
        return 0;
 
1335
}
 
1336
 
 
1337
void db_startup (testp)
 
1338
        int testp;
 
1339
{
 
1340
}
 
1341
 
 
1342
void bootp (packet)
 
1343
        struct packet *packet;
 
1344
{
 
1345
        struct iaddrmatchlist *ap;
 
1346
        char addrbuf[4*16];
 
1347
        char maskbuf[4*16];
 
1348
 
 
1349
        if (packet -> raw -> op != BOOTREPLY)
 
1350
                return;
 
1351
 
 
1352
        /* If there's a reject list, make sure this packet's sender isn't
 
1353
           on it. */
 
1354
        for (ap = packet -> interface -> client -> config -> reject_list;
 
1355
             ap; ap = ap -> next) {
 
1356
                if (addr_match(&packet->client_addr, &ap->match)) {
 
1357
 
 
1358
                        /* piaddr() returns its result in a static
 
1359
                           buffer sized 4*16 (see common/inet.c). */
 
1360
 
 
1361
                        strcpy(addrbuf, piaddr(ap->match.addr));
 
1362
                        strcpy(maskbuf, piaddr(ap->match.mask));
 
1363
 
 
1364
                        log_info("BOOTREPLY from %s rejected by rule %s "
 
1365
                                 "mask %s.", piaddr(packet->client_addr),
 
1366
                                 addrbuf, maskbuf);
 
1367
                        return;
 
1368
                }
 
1369
        }
 
1370
 
 
1371
        dhcpoffer (packet);
 
1372
 
 
1373
}
 
1374
 
 
1375
void dhcp (packet)
 
1376
        struct packet *packet;
 
1377
{
 
1378
        struct iaddrmatchlist *ap;
 
1379
        void (*handler) (struct packet *);
 
1380
        const char *type;
 
1381
        char addrbuf[4*16];
 
1382
        char maskbuf[4*16];
 
1383
 
 
1384
        switch (packet -> packet_type) {
 
1385
              case DHCPOFFER:
 
1386
                handler = dhcpoffer;
 
1387
                type = "DHCPOFFER";
 
1388
                break;
 
1389
 
 
1390
              case DHCPNAK:
 
1391
                handler = dhcpnak;
 
1392
                type = "DHCPNACK";
 
1393
                break;
 
1394
 
 
1395
              case DHCPACK:
 
1396
                handler = dhcpack;
 
1397
                type = "DHCPACK";
 
1398
                break;
 
1399
 
 
1400
              default:
 
1401
                return;
 
1402
        }
 
1403
 
 
1404
        /* If there's a reject list, make sure this packet's sender isn't
 
1405
           on it. */
 
1406
        for (ap = packet -> interface -> client -> config -> reject_list;
 
1407
             ap; ap = ap -> next) {
 
1408
                if (addr_match(&packet->client_addr, &ap->match)) {
 
1409
 
 
1410
                        /* piaddr() returns its result in a static
 
1411
                           buffer sized 4*16 (see common/inet.c). */
 
1412
 
 
1413
                        strcpy(addrbuf, piaddr(ap->match.addr));
 
1414
                        strcpy(maskbuf, piaddr(ap->match.mask));
 
1415
 
 
1416
                        log_info("%s from %s rejected by rule %s mask %s.",
 
1417
                                 type, piaddr(packet->client_addr),
 
1418
                                 addrbuf, maskbuf);
 
1419
                        return;
 
1420
                }
 
1421
        }
 
1422
        (*handler) (packet);
 
1423
}
 
1424
 
 
1425
#ifdef DHCPv6
 
1426
void
 
1427
dhcpv6(struct packet *packet) {
 
1428
        struct iaddrmatchlist *ap;
 
1429
        struct client_state *client;
 
1430
        char addrbuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")];
 
1431
 
 
1432
        /* Silently drop bogus messages. */
 
1433
        if (packet->dhcpv6_msg_type >= dhcpv6_type_name_max)
 
1434
                return;
 
1435
 
 
1436
        /* Discard, with log, packets from quenched sources. */
 
1437
        for (ap = packet->interface->client->config->reject_list ;
 
1438
             ap ; ap = ap->next) {
 
1439
                if (addr_match(&packet->client_addr, &ap->match)) {
 
1440
                        strcpy(addrbuf, piaddr(packet->client_addr));
 
1441
                        log_info("%s from %s rejected by rule %s",
 
1442
                                 dhcpv6_type_names[packet->dhcpv6_msg_type],
 
1443
                                 addrbuf,
 
1444
                                 piaddrmask(&ap->match.addr, &ap->match.mask));
 
1445
                        return;
 
1446
                }
 
1447
        }
 
1448
 
 
1449
        /* Screen out nonsensical messages. */
 
1450
        switch(packet->dhcpv6_msg_type) {
 
1451
              case DHCPV6_ADVERTISE:
 
1452
              case DHCPV6_RECONFIGURE:
 
1453
                if (stateless)
 
1454
                  return;
 
1455
              /* Falls through */
 
1456
              case DHCPV6_REPLY:
 
1457
                log_info("RCV: %s message on %s from %s.",
 
1458
                         dhcpv6_type_names[packet->dhcpv6_msg_type],
 
1459
                         packet->interface->name, piaddr(packet->client_addr));
 
1460
                break;
 
1461
 
 
1462
              default:
 
1463
                return;
 
1464
        }
 
1465
 
 
1466
        /* Find a client state that matches the incoming XID. */
 
1467
        for (client = packet->interface->client ; client ;
 
1468
             client = client->next) {
 
1469
                if (memcmp(&client->dhcpv6_transaction_id,
 
1470
                           packet->dhcpv6_transaction_id, 3) == 0) {
 
1471
                        client->v6_handler(packet, client);
 
1472
                        return;
 
1473
                }
 
1474
        }
 
1475
 
 
1476
        /* XXX: temporary log for debugging */
 
1477
        log_info("Packet received, but nothing done with it.");
 
1478
}
 
1479
#endif /* DHCPv6 */
 
1480
 
 
1481
void dhcpoffer (packet)
 
1482
        struct packet *packet;
 
1483
{
 
1484
        struct interface_info *ip = packet -> interface;
 
1485
        struct client_state *client;
 
1486
        struct client_lease *lease, *lp;
 
1487
        struct option **req;
 
1488
        int i;
 
1489
        int stop_selecting;
 
1490
        const char *name = packet -> packet_type ? "DHCPOFFER" : "BOOTREPLY";
 
1491
        char obuf [1024];
 
1492
        struct timeval tv;
 
1493
 
 
1494
#ifdef DEBUG_PACKET
 
1495
        dump_packet (packet);
 
1496
#endif
 
1497
 
 
1498
        /* Find a client state that matches the xid... */
 
1499
        for (client = ip -> client; client; client = client -> next)
 
1500
                if (client -> xid == packet -> raw -> xid)
 
1501
                        break;
 
1502
 
 
1503
        /* If we're not receptive to an offer right now, or if the offer
 
1504
           has an unrecognizable transaction id, then just drop it. */
 
1505
        if (!client ||
 
1506
            client -> state != S_SELECTING ||
 
1507
            (packet -> interface -> hw_address.hlen - 1 !=
 
1508
             packet -> raw -> hlen) ||
 
1509
            (memcmp (&packet -> interface -> hw_address.hbuf [1],
 
1510
                     packet -> raw -> chaddr, packet -> raw -> hlen))) {
 
1511
#if defined (DEBUG)
 
1512
                log_debug ("%s in wrong transaction.", name);
 
1513
#endif
 
1514
                return;
 
1515
        }
 
1516
 
 
1517
        sprintf (obuf, "%s from %s", name, piaddr (packet -> client_addr));
 
1518
 
 
1519
 
 
1520
        /* If this lease doesn't supply the minimum required DHCPv4 parameters,
 
1521
         * ignore it.
 
1522
         */
 
1523
        req = client->config->required_options;
 
1524
        if (req != NULL) {
 
1525
                for (i = 0 ; req[i] != NULL ; i++) {
 
1526
                        if ((req[i]->universe == &dhcp_universe) &&
 
1527
                            !lookup_option(&dhcp_universe, packet->options,
 
1528
                                           req[i]->code)) {
 
1529
                                struct option *option = NULL;
 
1530
                                unsigned code = req[i]->code;
 
1531
 
 
1532
                                option_code_hash_lookup(&option,
 
1533
                                                        dhcp_universe.code_hash,
 
1534
                                                        &code, 0, MDL);
 
1535
 
 
1536
                                if (option)
 
1537
                                        log_info("%s: no %s option.", obuf,
 
1538
                                                 option->name);
 
1539
                                else
 
1540
                                        log_info("%s: no unknown-%u option.",
 
1541
                                                 obuf, code);
 
1542
 
 
1543
                                option_dereference(&option, MDL);
 
1544
 
 
1545
                                return;
 
1546
                        }
 
1547
                }
 
1548
        }
 
1549
 
 
1550
        /* If we've already seen this lease, don't record it again. */
 
1551
        for (lease = client -> offered_leases; lease; lease = lease -> next) {
 
1552
                if (lease -> address.len == sizeof packet -> raw -> yiaddr &&
 
1553
                    !memcmp (lease -> address.iabuf,
 
1554
                             &packet -> raw -> yiaddr, lease -> address.len)) {
 
1555
                        log_debug ("%s: already seen.", obuf);
 
1556
                        return;
 
1557
                }
 
1558
        }
 
1559
 
 
1560
        lease = packet_to_lease (packet, client);
 
1561
        if (!lease) {
 
1562
                log_info ("%s: packet_to_lease failed.", obuf);
 
1563
                return;
 
1564
        }
 
1565
 
 
1566
        /* If this lease was acquired through a BOOTREPLY, record that
 
1567
           fact. */
 
1568
        if (!packet -> options_valid || !packet -> packet_type)
 
1569
                lease -> is_bootp = 1;
 
1570
 
 
1571
        /* Record the medium under which this lease was offered. */
 
1572
        lease -> medium = client -> medium;
 
1573
 
 
1574
        /* Figure out when we're supposed to stop selecting. */
 
1575
        stop_selecting = (client -> first_sending +
 
1576
                          client -> config -> select_interval);
 
1577
 
 
1578
        /* If this is the lease we asked for, put it at the head of the
 
1579
           list, and don't mess with the arp request timeout. */
 
1580
        if (lease -> address.len == client -> requested_address.len &&
 
1581
            !memcmp (lease -> address.iabuf,
 
1582
                     client -> requested_address.iabuf,
 
1583
                     client -> requested_address.len)) {
 
1584
                lease -> next = client -> offered_leases;
 
1585
                client -> offered_leases = lease;
 
1586
        } else {
 
1587
                /* Put the lease at the end of the list. */
 
1588
                lease -> next = (struct client_lease *)0;
 
1589
                if (!client -> offered_leases)
 
1590
                        client -> offered_leases = lease;
 
1591
                else {
 
1592
                        for (lp = client -> offered_leases; lp -> next;
 
1593
                             lp = lp -> next)
 
1594
                                ;
 
1595
                        lp -> next = lease;
 
1596
                }
 
1597
        }
 
1598
 
 
1599
        /* If the selecting interval has expired, go immediately to
 
1600
           state_selecting().  Otherwise, time out into
 
1601
           state_selecting at the select interval. */
 
1602
        if (stop_selecting <= cur_tv.tv_sec)
 
1603
                state_selecting (client);
 
1604
        else {
 
1605
                tv.tv_sec = stop_selecting;
 
1606
                tv.tv_usec = cur_tv.tv_usec;
 
1607
                add_timeout(&tv, state_selecting, client, 0, 0);
 
1608
                cancel_timeout(send_discover, client);
 
1609
        }
 
1610
        log_info("%s", obuf);
 
1611
}
 
1612
 
 
1613
/* Allocate a client_lease structure and initialize it from the parameters
 
1614
   in the specified packet. */
 
1615
 
 
1616
struct client_lease *packet_to_lease (packet, client)
 
1617
        struct packet *packet;
 
1618
        struct client_state *client;
 
1619
{
 
1620
        struct client_lease *lease;
 
1621
        unsigned i;
 
1622
        struct option_cache *oc;
 
1623
        struct option *option = NULL;
 
1624
        struct data_string data;
 
1625
 
 
1626
        lease = (struct client_lease *)new_client_lease (MDL);
 
1627
 
 
1628
        if (!lease) {
 
1629
                log_error ("packet_to_lease: no memory to record lease.\n");
 
1630
                return (struct client_lease *)0;
 
1631
        }
 
1632
 
 
1633
        memset (lease, 0, sizeof *lease);
 
1634
 
 
1635
        /* Copy the lease options. */
 
1636
        option_state_reference (&lease -> options, packet -> options, MDL);
 
1637
 
 
1638
        lease -> address.len = sizeof (packet -> raw -> yiaddr);
 
1639
        memcpy (lease -> address.iabuf, &packet -> raw -> yiaddr,
 
1640
                lease -> address.len);
 
1641
 
 
1642
        memset (&data, 0, sizeof data);
 
1643
 
 
1644
        if (client -> config -> vendor_space_name) {
 
1645
                i = DHO_VENDOR_ENCAPSULATED_OPTIONS;
 
1646
 
 
1647
                /* See if there was a vendor encapsulation option. */
 
1648
                oc = lookup_option (&dhcp_universe, lease -> options, i);
 
1649
                if (oc &&
 
1650
                    client -> config -> vendor_space_name &&
 
1651
                    evaluate_option_cache (&data, packet,
 
1652
                                           (struct lease *)0, client,
 
1653
                                           packet -> options, lease -> options,
 
1654
                                           &global_scope, oc, MDL)) {
 
1655
                        if (data.len) {
 
1656
                                if (!option_code_hash_lookup(&option,
 
1657
                                                dhcp_universe.code_hash,
 
1658
                                                &i, 0, MDL))
 
1659
                                        log_fatal("Unable to find VENDOR "
 
1660
                                                  "option (%s:%d).", MDL);
 
1661
                                parse_encapsulated_suboptions
 
1662
                                        (packet -> options, option,
 
1663
                                         data.data, data.len, &dhcp_universe,
 
1664
                                         client -> config -> vendor_space_name
 
1665
                                                );
 
1666
 
 
1667
                                option_dereference(&option, MDL);
 
1668
                        }
 
1669
                        data_string_forget (&data, MDL);
 
1670
                }
 
1671
        } else
 
1672
                i = 0;
 
1673
 
 
1674
        /* Figure out the overload flag. */
 
1675
        oc = lookup_option (&dhcp_universe, lease -> options,
 
1676
                            DHO_DHCP_OPTION_OVERLOAD);
 
1677
        if (oc &&
 
1678
            evaluate_option_cache (&data, packet, (struct lease *)0, client,
 
1679
                                   packet -> options, lease -> options,
 
1680
                                   &global_scope, oc, MDL)) {
 
1681
                if (data.len > 0)
 
1682
                        i = data.data [0];
 
1683
                else
 
1684
                        i = 0;
 
1685
                data_string_forget (&data, MDL);
 
1686
        } else
 
1687
                i = 0;
 
1688
 
 
1689
        /* If the server name was filled out, copy it. */
 
1690
        if (!(i & 2) && packet -> raw -> sname [0]) {
 
1691
                unsigned len;
 
1692
                /* Don't count on the NUL terminator. */
 
1693
                for (len = 0; len < DHCP_SNAME_LEN; len++)
 
1694
                        if (!packet -> raw -> sname [len])
 
1695
                                break;
 
1696
                lease -> server_name = dmalloc (len + 1, MDL);
 
1697
                if (!lease -> server_name) {
 
1698
                        log_error ("dhcpoffer: no memory for server name.\n");
 
1699
                        destroy_client_lease (lease);
 
1700
                        return (struct client_lease *)0;
 
1701
                } else {
 
1702
                        memcpy (lease -> server_name,
 
1703
                                packet -> raw -> sname, len);
 
1704
                        lease -> server_name [len] = 0;
 
1705
                }
 
1706
        }
 
1707
 
 
1708
        /* Ditto for the filename. */
 
1709
        if (!(i & 1) && packet -> raw -> file [0]) {
 
1710
                unsigned len;
 
1711
                /* Don't count on the NUL terminator. */
 
1712
                for (len = 0; len < DHCP_FILE_LEN; len++)
 
1713
                        if (!packet -> raw -> file [len])
 
1714
                                break;
 
1715
                lease -> filename = dmalloc (len + 1, MDL);
 
1716
                if (!lease -> filename) {
 
1717
                        log_error ("dhcpoffer: no memory for filename.\n");
 
1718
                        destroy_client_lease (lease);
 
1719
                        return (struct client_lease *)0;
 
1720
                } else {
 
1721
                        memcpy (lease -> filename,
 
1722
                                packet -> raw -> file, len);
 
1723
                        lease -> filename [len] = 0;
 
1724
                }
 
1725
        }
 
1726
 
 
1727
        execute_statements_in_scope ((struct binding_value **)0,
 
1728
                                     (struct packet *)packet,
 
1729
                                     (struct lease *)0, client,
 
1730
                                     lease -> options, lease -> options,
 
1731
                                     &global_scope,
 
1732
                                     client -> config -> on_receipt,
 
1733
                                     (struct group *)0);
 
1734
 
 
1735
        return lease;
 
1736
}
 
1737
 
 
1738
void dhcpnak (packet)
 
1739
        struct packet *packet;
 
1740
{
 
1741
        struct interface_info *ip = packet -> interface;
 
1742
        struct client_state *client;
 
1743
 
 
1744
        /* Find a client state that matches the xid... */
 
1745
        for (client = ip -> client; client; client = client -> next)
 
1746
                if (client -> xid == packet -> raw -> xid)
 
1747
                        break;
 
1748
 
 
1749
        /* If we're not receptive to an offer right now, or if the offer
 
1750
           has an unrecognizable transaction id, then just drop it. */
 
1751
        if (!client ||
 
1752
            (packet -> interface -> hw_address.hlen - 1 !=
 
1753
             packet -> raw -> hlen) ||
 
1754
            (memcmp (&packet -> interface -> hw_address.hbuf [1],
 
1755
                     packet -> raw -> chaddr, packet -> raw -> hlen))) {
 
1756
#if defined (DEBUG)
 
1757
                log_debug ("DHCPNAK in wrong transaction.");
 
1758
#endif
 
1759
                return;
 
1760
        }
 
1761
 
 
1762
        if (client -> state != S_REBOOTING &&
 
1763
            client -> state != S_REQUESTING &&
 
1764
            client -> state != S_RENEWING &&
 
1765
            client -> state != S_REBINDING) {
 
1766
#if defined (DEBUG)
 
1767
                log_debug ("DHCPNAK in wrong state.");
 
1768
#endif
 
1769
                return;
 
1770
        }
 
1771
 
 
1772
        log_info ("DHCPNAK from %s", piaddr (packet -> client_addr));
 
1773
 
 
1774
        if (!client -> active) {
 
1775
#if defined (DEBUG)
 
1776
                log_info ("DHCPNAK with no active lease.\n");
 
1777
#endif
 
1778
                return;
 
1779
        }
 
1780
 
 
1781
        /* If we get a DHCPNAK, we use the EXPIRE dhclient-script state
 
1782
         * to indicate that we want all old bindings to be removed.  (It
 
1783
         * is possible that we may get a NAK while in the RENEW state,
 
1784
         * so we might have bindings active at that time)
 
1785
         */
 
1786
        script_init(client, "EXPIRE", NULL);
 
1787
        script_write_params(client, "old_", client->active);
 
1788
        if (client->alias)
 
1789
                script_write_params(client, "alias_", client->alias);
 
1790
        script_go(client);
 
1791
 
 
1792
        destroy_client_lease (client -> active);
 
1793
        client -> active = (struct client_lease *)0;
 
1794
 
 
1795
        /* Stop sending DHCPREQUEST packets... */
 
1796
        cancel_timeout (send_request, client);
 
1797
 
 
1798
        /* On some scripts, 'EXPIRE' causes the interface to be ifconfig'd
 
1799
         * down (this expunges any routes and arp cache).  This makes the
 
1800
         * interface unusable by state_init(), which we call next.  So, we
 
1801
         * need to 'PREINIT' the interface to bring it back up.
 
1802
         */
 
1803
        script_init(client, "PREINIT", NULL);
 
1804
        if (client->alias)
 
1805
                script_write_params(client, "alias_", client->alias);
 
1806
        script_go(client);
 
1807
 
 
1808
        client -> state = S_INIT;
 
1809
        state_init (client);
 
1810
}
 
1811
 
 
1812
/* Send out a DHCPDISCOVER packet, and set a timeout to send out another
 
1813
   one after the right interval has expired.  If we don't get an offer by
 
1814
   the time we reach the panic interval, call the panic function. */
 
1815
 
 
1816
void send_discover (cpp)
 
1817
        void *cpp;
 
1818
{
 
1819
        struct client_state *client = cpp;
 
1820
 
 
1821
        int result;
 
1822
        int interval;
 
1823
        int increase = 1;
 
1824
        struct timeval tv;
 
1825
 
 
1826
        /* Figure out how long it's been since we started transmitting. */
 
1827
        interval = cur_time - client -> first_sending;
 
1828
 
 
1829
        /* If we're past the panic timeout, call the script and tell it
 
1830
           we haven't found anything for this interface yet. */
 
1831
        if (interval > client -> config -> timeout) {
 
1832
                state_panic (client);
 
1833
                return;
 
1834
        }
 
1835
 
 
1836
        /* If we're selecting media, try the whole list before doing
 
1837
           the exponential backoff, but if we've already received an
 
1838
           offer, stop looping, because we obviously have it right. */
 
1839
        if (!client -> offered_leases &&
 
1840
            client -> config -> media) {
 
1841
                int fail = 0;
 
1842
              again:
 
1843
                if (client -> medium) {
 
1844
                        client -> medium = client -> medium -> next;
 
1845
                        increase = 0;
 
1846
                }
 
1847
                if (!client -> medium) {
 
1848
                        if (fail)
 
1849
                                log_fatal ("No valid media types for %s!",
 
1850
                                       client -> interface -> name);
 
1851
                        client -> medium =
 
1852
                                client -> config -> media;
 
1853
                        increase = 1;
 
1854
                }
 
1855
 
 
1856
                log_info ("Trying medium \"%s\" %d",
 
1857
                          client -> medium -> string, increase);
 
1858
                script_init (client, "MEDIUM", client -> medium);
 
1859
                if (script_go (client)) {
 
1860
                        fail = 1;
 
1861
                        goto again;
 
1862
                }
 
1863
        }
 
1864
 
 
1865
        /* If we're supposed to increase the interval, do so.  If it's
 
1866
           currently zero (i.e., we haven't sent any packets yet), set
 
1867
           it to initial_interval; otherwise, add to it a random number
 
1868
           between zero and two times itself.  On average, this means
 
1869
           that it will double with every transmission. */
 
1870
        if (increase) {
 
1871
                if (!client->interval)
 
1872
                        client->interval = client->config->initial_interval;
 
1873
                else
 
1874
                        client->interval += random() % (2 * client->interval);
 
1875
 
 
1876
                /* Don't backoff past cutoff. */
 
1877
                if (client->interval > client->config->backoff_cutoff)
 
1878
                        client->interval = (client->config->backoff_cutoff / 2)
 
1879
                                 + (random() % client->config->backoff_cutoff);
 
1880
        } else if (!client->interval)
 
1881
                client->interval = client->config->initial_interval;
 
1882
 
 
1883
        /* If the backoff would take us to the panic timeout, just use that
 
1884
           as the interval. */
 
1885
        if (cur_time + client -> interval >
 
1886
            client -> first_sending + client -> config -> timeout)
 
1887
                client -> interval =
 
1888
                        (client -> first_sending +
 
1889
                         client -> config -> timeout) - cur_time + 1;
 
1890
 
 
1891
        /* Record the number of seconds since we started sending. */
 
1892
        if (interval < 65536)
 
1893
                client -> packet.secs = htons (interval);
 
1894
        else
 
1895
                client -> packet.secs = htons (65535);
 
1896
        client -> secs = client -> packet.secs;
 
1897
 
 
1898
        log_info ("DHCPDISCOVER on %s to %s port %d interval %ld",
 
1899
              client -> name ? client -> name : client -> interface -> name,
 
1900
              inet_ntoa (sockaddr_broadcast.sin_addr),
 
1901
              ntohs (sockaddr_broadcast.sin_port), (long)(client -> interval));
 
1902
 
 
1903
        /* Send out a packet. */
 
1904
        result = send_packet (client -> interface, (struct packet *)0,
 
1905
                              &client -> packet,
 
1906
                              client -> packet_length,
 
1907
                              inaddr_any, &sockaddr_broadcast,
 
1908
                              (struct hardware *)0);
 
1909
 
 
1910
        /*
 
1911
         * If we used 0 microseconds here, and there were other clients on the
 
1912
         * same network with a synchronized local clock (ntp), and a similar
 
1913
         * zero-microsecond-scheduler behavior, then we could be participating
 
1914
         * in a sub-second DOS ttck.
 
1915
         */
 
1916
        tv.tv_sec = cur_tv.tv_sec + client->interval;
 
1917
        tv.tv_usec = client->interval > 1 ? random() % 1000000 : cur_tv.tv_usec;
 
1918
        add_timeout(&tv, send_discover, client, 0, 0);
 
1919
}
 
1920
 
 
1921
/* state_panic gets called if we haven't received any offers in a preset
 
1922
   amount of time.   When this happens, we try to use existing leases that
 
1923
   haven't yet expired, and failing that, we call the client script and
 
1924
   hope it can do something. */
 
1925
 
 
1926
void state_panic (cpp)
 
1927
        void *cpp;
 
1928
{
 
1929
        struct client_state *client = cpp;
 
1930
        struct client_lease *loop;
 
1931
        struct client_lease *lp;
 
1932
        struct timeval tv;
 
1933
 
 
1934
        loop = lp = client -> active;
 
1935
 
 
1936
        log_info ("No DHCPOFFERS received.");
 
1937
 
 
1938
        /* We may not have an active lease, but we may have some
 
1939
           predefined leases that we can try. */
 
1940
        if (!client -> active && client -> leases)
 
1941
                goto activate_next;
 
1942
 
 
1943
        /* Run through the list of leases and see if one can be used. */
 
1944
        while (client -> active) {
 
1945
                if (client -> active -> expiry > cur_time) {
 
1946
                        log_info ("Trying recorded lease %s",
 
1947
                              piaddr (client -> active -> address));
 
1948
                        /* Run the client script with the existing
 
1949
                           parameters. */
 
1950
                        script_init (client, "TIMEOUT",
 
1951
                                     client -> active -> medium);
 
1952
                        script_write_params (client, "new_", client -> active);
 
1953
                        if (client -> alias)
 
1954
                                script_write_params (client, "alias_",
 
1955
                                                     client -> alias);
 
1956
 
 
1957
                        /* If the old lease is still good and doesn't
 
1958
                           yet need renewal, go into BOUND state and
 
1959
                           timeout at the renewal time. */
 
1960
                        if (!script_go (client)) {
 
1961
                            if (cur_time < client -> active -> renewal) {
 
1962
                                client -> state = S_BOUND;
 
1963
                                log_info ("bound: renewal in %ld %s.",
 
1964
                                          (long)(client -> active -> renewal -
 
1965
                                                 cur_time), "seconds");
 
1966
                                tv.tv_sec = client->active->renewal;
 
1967
                                tv.tv_usec = ((client->active->renewal -
 
1968
                                                    cur_time) > 1) ?
 
1969
                                                random() % 1000000 :
 
1970
                                                cur_tv.tv_usec;
 
1971
                                add_timeout(&tv, state_bound, client, 0, 0);
 
1972
                            } else {
 
1973
                                client -> state = S_BOUND;
 
1974
                                log_info ("bound: immediate renewal.");
 
1975
                                state_bound (client);
 
1976
                            }
 
1977
                            reinitialize_interfaces ();
 
1978
                            go_daemon ();
 
1979
                            return;
 
1980
                        }
 
1981
                }
 
1982
 
 
1983
                /* If there are no other leases, give up. */
 
1984
                if (!client -> leases) {
 
1985
                        client -> leases = client -> active;
 
1986
                        client -> active = (struct client_lease *)0;
 
1987
                        break;
 
1988
                }
 
1989
 
 
1990
        activate_next:
 
1991
                /* Otherwise, put the active lease at the end of the
 
1992
                   lease list, and try another lease.. */
 
1993
                for (lp = client -> leases; lp -> next; lp = lp -> next)
 
1994
                        ;
 
1995
                lp -> next = client -> active;
 
1996
                if (lp -> next) {
 
1997
                        lp -> next -> next = (struct client_lease *)0;
 
1998
                }
 
1999
                client -> active = client -> leases;
 
2000
                client -> leases = client -> leases -> next;
 
2001
 
 
2002
                /* If we already tried this lease, we've exhausted the
 
2003
                   set of leases, so we might as well give up for
 
2004
                   now. */
 
2005
                if (client -> active == loop)
 
2006
                        break;
 
2007
                else if (!loop)
 
2008
                        loop = client -> active;
 
2009
        }
 
2010
 
 
2011
        /* No leases were available, or what was available didn't work, so
 
2012
           tell the shell script that we failed to allocate an address,
 
2013
           and try again later. */
 
2014
        if (onetry) {
 
2015
                if (!quiet)
 
2016
                        log_info ("Unable to obtain a lease on first try.%s",
 
2017
                                  "  Exiting.");
 
2018
                exit (2);
 
2019
        }
 
2020
 
 
2021
        log_info ("No working leases in persistent database - sleeping.");
 
2022
        script_init (client, "FAIL", (struct string_list *)0);
 
2023
        if (client -> alias)
 
2024
                script_write_params (client, "alias_", client -> alias);
 
2025
        script_go (client);
 
2026
        client -> state = S_INIT;
 
2027
        tv.tv_sec = cur_tv.tv_sec + ((client->config->retry_interval + 1) / 2 +
 
2028
                    (random() % client->config->retry_interval));
 
2029
        tv.tv_usec = ((tv.tv_sec - cur_tv.tv_sec) > 1) ?
 
2030
                        random() % 1000000 : cur_tv.tv_usec;
 
2031
        add_timeout(&tv, state_init, client, 0, 0);
 
2032
        go_daemon ();
 
2033
}
 
2034
 
 
2035
void send_request (cpp)
 
2036
        void *cpp;
 
2037
{
 
2038
        struct client_state *client = cpp;
 
2039
 
 
2040
        int result;
 
2041
        int interval;
 
2042
        struct sockaddr_in destination;
 
2043
        struct in_addr from;
 
2044
        struct timeval tv;
 
2045
 
 
2046
        /* Figure out how long it's been since we started transmitting. */
 
2047
        interval = cur_time - client -> first_sending;
 
2048
 
 
2049
        /* If we're in the INIT-REBOOT or REQUESTING state and we're
 
2050
           past the reboot timeout, go to INIT and see if we can
 
2051
           DISCOVER an address... */
 
2052
        /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
 
2053
           means either that we're on a network with no DHCP server,
 
2054
           or that our server is down.  In the latter case, assuming
 
2055
           that there is a backup DHCP server, DHCPDISCOVER will get
 
2056
           us a new address, but we could also have successfully
 
2057
           reused our old address.  In the former case, we're hosed
 
2058
           anyway.  This is not a win-prone situation. */
 
2059
        if ((client -> state == S_REBOOTING ||
 
2060
             client -> state == S_REQUESTING) &&
 
2061
            interval > client -> config -> reboot_timeout) {
 
2062
        cancel:
 
2063
                client -> state = S_INIT;
 
2064
                cancel_timeout (send_request, client);
 
2065
                state_init (client);
 
2066
                return;
 
2067
        }
 
2068
 
 
2069
        /* If we're in the reboot state, make sure the media is set up
 
2070
           correctly. */
 
2071
        if (client -> state == S_REBOOTING &&
 
2072
            !client -> medium &&
 
2073
            client -> active -> medium ) {
 
2074
                script_init (client, "MEDIUM", client -> active -> medium);
 
2075
 
 
2076
                /* If the medium we chose won't fly, go to INIT state. */
 
2077
                if (script_go (client))
 
2078
                        goto cancel;
 
2079
 
 
2080
                /* Record the medium. */
 
2081
                client -> medium = client -> active -> medium;
 
2082
        }
 
2083
 
 
2084
        /* If the lease has expired, relinquish the address and go back
 
2085
           to the INIT state. */
 
2086
        if (client -> state != S_REQUESTING &&
 
2087
            cur_time > client -> active -> expiry) {
 
2088
                /* Run the client script with the new parameters. */
 
2089
                script_init (client, "EXPIRE", (struct string_list *)0);
 
2090
                script_write_params (client, "old_", client -> active);
 
2091
                if (client -> alias)
 
2092
                        script_write_params (client, "alias_",
 
2093
                                             client -> alias);
 
2094
                script_go (client);
 
2095
 
 
2096
                /* Now do a preinit on the interface so that we can
 
2097
                   discover a new address. */
 
2098
                script_init (client, "PREINIT", (struct string_list *)0);
 
2099
                if (client -> alias)
 
2100
                        script_write_params (client, "alias_",
 
2101
                                             client -> alias);
 
2102
                script_go (client);
 
2103
 
 
2104
                client -> state = S_INIT;
 
2105
                state_init (client);
 
2106
                return;
 
2107
        }
 
2108
 
 
2109
        /* Do the exponential backoff... */
 
2110
        if (!client -> interval)
 
2111
                client -> interval = client -> config -> initial_interval;
 
2112
        else {
 
2113
                client -> interval += ((random () >> 2) %
 
2114
                                       (2 * client -> interval));
 
2115
        }
 
2116
 
 
2117
        /* Don't backoff past cutoff. */
 
2118
        if (client -> interval >
 
2119
            client -> config -> backoff_cutoff)
 
2120
                client -> interval =
 
2121
                        ((client -> config -> backoff_cutoff / 2)
 
2122
                         + ((random () >> 2) %
 
2123
                                        client -> config -> backoff_cutoff));
 
2124
 
 
2125
        /* If the backoff would take us to the expiry time, just set the
 
2126
           timeout to the expiry time. */
 
2127
        if (client -> state != S_REQUESTING &&
 
2128
            cur_time + client -> interval > client -> active -> expiry)
 
2129
                client -> interval =
 
2130
                        client -> active -> expiry - cur_time + 1;
 
2131
 
 
2132
        /* If the lease T2 time has elapsed, or if we're not yet bound,
 
2133
           broadcast the DHCPREQUEST rather than unicasting. */
 
2134
        if (client -> state == S_REQUESTING ||
 
2135
            client -> state == S_REBOOTING ||
 
2136
            cur_time > client -> active -> rebind)
 
2137
                destination.sin_addr = sockaddr_broadcast.sin_addr;
 
2138
        else
 
2139
                memcpy (&destination.sin_addr.s_addr,
 
2140
                        client -> destination.iabuf,
 
2141
                        sizeof destination.sin_addr.s_addr);
 
2142
        destination.sin_port = remote_port;
 
2143
        destination.sin_family = AF_INET;
 
2144
#ifdef HAVE_SA_LEN
 
2145
        destination.sin_len = sizeof destination;
 
2146
#endif
 
2147
 
 
2148
        if (client -> state == S_RENEWING ||
 
2149
            client -> state == S_REBINDING)
 
2150
                memcpy (&from, client -> active -> address.iabuf,
 
2151
                        sizeof from);
 
2152
        else
 
2153
                from.s_addr = INADDR_ANY;
 
2154
 
 
2155
        /* Record the number of seconds since we started sending. */
 
2156
        if (client -> state == S_REQUESTING)
 
2157
                client -> packet.secs = client -> secs;
 
2158
        else {
 
2159
                if (interval < 65536)
 
2160
                        client -> packet.secs = htons (interval);
 
2161
                else
 
2162
                        client -> packet.secs = htons (65535);
 
2163
        }
 
2164
 
 
2165
        log_info ("DHCPREQUEST on %s to %s port %d",
 
2166
              client -> name ? client -> name : client -> interface -> name,
 
2167
              inet_ntoa (destination.sin_addr),
 
2168
              ntohs (destination.sin_port));
 
2169
 
 
2170
        if (destination.sin_addr.s_addr != INADDR_BROADCAST &&
 
2171
            fallback_interface)
 
2172
                result = send_packet (fallback_interface,
 
2173
                                      (struct packet *)0,
 
2174
                                      &client -> packet,
 
2175
                                      client -> packet_length,
 
2176
                                      from, &destination,
 
2177
                                      (struct hardware *)0);
 
2178
        else
 
2179
                /* Send out a packet. */
 
2180
                result = send_packet (client -> interface, (struct packet *)0,
 
2181
                                      &client -> packet,
 
2182
                                      client -> packet_length,
 
2183
                                      from, &destination,
 
2184
                                      (struct hardware *)0);
 
2185
 
 
2186
        tv.tv_sec = cur_tv.tv_sec + client->interval;
 
2187
        tv.tv_usec = ((tv.tv_sec - cur_tv.tv_sec) > 1) ?
 
2188
                        random() % 1000000 : cur_tv.tv_usec;
 
2189
        add_timeout(&tv, send_request, client, 0, 0);
 
2190
}
 
2191
 
 
2192
void send_decline (cpp)
 
2193
        void *cpp;
 
2194
{
 
2195
        struct client_state *client = cpp;
 
2196
 
 
2197
        int result;
 
2198
 
 
2199
        log_info ("DHCPDECLINE on %s to %s port %d",
 
2200
              client -> name ? client -> name : client -> interface -> name,
 
2201
              inet_ntoa (sockaddr_broadcast.sin_addr),
 
2202
              ntohs (sockaddr_broadcast.sin_port));
 
2203
 
 
2204
        /* Send out a packet. */
 
2205
        result = send_packet (client -> interface, (struct packet *)0,
 
2206
                              &client -> packet,
 
2207
                              client -> packet_length,
 
2208
                              inaddr_any, &sockaddr_broadcast,
 
2209
                              (struct hardware *)0);
 
2210
}
 
2211
 
 
2212
void send_release (cpp)
 
2213
        void *cpp;
 
2214
{
 
2215
        struct client_state *client = cpp;
 
2216
 
 
2217
        int result;
 
2218
        struct sockaddr_in destination;
 
2219
        struct in_addr from;
 
2220
 
 
2221
        memcpy (&from, client -> active -> address.iabuf,
 
2222
                sizeof from);
 
2223
        memcpy (&destination.sin_addr.s_addr,
 
2224
                client -> destination.iabuf,
 
2225
                sizeof destination.sin_addr.s_addr);
 
2226
        destination.sin_port = remote_port;
 
2227
        destination.sin_family = AF_INET;
 
2228
#ifdef HAVE_SA_LEN
 
2229
        destination.sin_len = sizeof destination;
 
2230
#endif
 
2231
 
 
2232
        /* Set the lease to end now, so that we don't accidentally
 
2233
           reuse it if we restart before the old expiry time. */
 
2234
        client -> active -> expiry =
 
2235
                client -> active -> renewal =
 
2236
                client -> active -> rebind = cur_time;
 
2237
        if (!write_client_lease (client, client -> active, 1, 1)) {
 
2238
                log_error ("Can't release lease: lease write failed.");
 
2239
                return;
 
2240
        }
 
2241
 
 
2242
        log_info ("DHCPRELEASE on %s to %s port %d",
 
2243
              client -> name ? client -> name : client -> interface -> name,
 
2244
              inet_ntoa (destination.sin_addr),
 
2245
              ntohs (destination.sin_port));
 
2246
 
 
2247
        if (fallback_interface)
 
2248
                result = send_packet (fallback_interface,
 
2249
                                      (struct packet *)0,
 
2250
                                      &client -> packet,
 
2251
                                      client -> packet_length,
 
2252
                                      from, &destination,
 
2253
                                      (struct hardware *)0);
 
2254
        else
 
2255
                /* Send out a packet. */
 
2256
                result = send_packet (client -> interface, (struct packet *)0,
 
2257
                                      &client -> packet,
 
2258
                                      client -> packet_length,
 
2259
                                      from, &destination,
 
2260
                                      (struct hardware *)0);
 
2261
}
 
2262
 
 
2263
void
 
2264
make_client_options(struct client_state *client, struct client_lease *lease,
 
2265
                    u_int8_t *type, struct option_cache *sid,
 
2266
                    struct iaddr *rip, struct option **prl,
 
2267
                    struct option_state **op)
 
2268
{
 
2269
        unsigned i;
 
2270
        struct option_cache *oc;
 
2271
        struct option *option = NULL;
 
2272
        struct buffer *bp = (struct buffer *)0;
 
2273
 
 
2274
        /* If there are any leftover options, get rid of them. */
 
2275
        if (*op)
 
2276
                option_state_dereference (op, MDL);
 
2277
 
 
2278
        /* Allocate space for options. */
 
2279
        option_state_allocate (op, MDL);
 
2280
 
 
2281
        /* Send the server identifier if provided. */
 
2282
        if (sid)
 
2283
                save_option (&dhcp_universe, *op, sid);
 
2284
 
 
2285
        oc = (struct option_cache *)0;
 
2286
 
 
2287
        /* Send the requested address if provided. */
 
2288
        if (rip) {
 
2289
                client -> requested_address = *rip;
 
2290
                i = DHO_DHCP_REQUESTED_ADDRESS;
 
2291
                if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash,
 
2292
                                              &i, 0, MDL) &&
 
2293
                      make_const_option_cache(&oc, NULL, rip->iabuf, rip->len,
 
2294
                                              option, MDL)))
 
2295
                        log_error ("can't make requested address cache.");
 
2296
                else {
 
2297
                        save_option (&dhcp_universe, *op, oc);
 
2298
                        option_cache_dereference (&oc, MDL);
 
2299
                }
 
2300
                option_dereference(&option, MDL);
 
2301
        } else {
 
2302
                client -> requested_address.len = 0;
 
2303
        }
 
2304
 
 
2305
        i = DHO_DHCP_MESSAGE_TYPE;
 
2306
        if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash, &i, 0,
 
2307
                                      MDL) &&
 
2308
              make_const_option_cache(&oc, NULL, type, 1, option, MDL)))
 
2309
                log_error ("can't make message type.");
 
2310
        else {
 
2311
                save_option (&dhcp_universe, *op, oc);
 
2312
                option_cache_dereference (&oc, MDL);
 
2313
        }
 
2314
        option_dereference(&option, MDL);
 
2315
 
 
2316
        if (prl) {
 
2317
                int len;
 
2318
 
 
2319
                /* Probe the length of the list. */
 
2320
                len = 0;
 
2321
                for (i = 0 ; prl[i] != NULL ; i++)
 
2322
                        if (prl[i]->universe == &dhcp_universe)
 
2323
                                len++;
 
2324
 
 
2325
                if (!buffer_allocate (&bp, len, MDL))
 
2326
                        log_error ("can't make parameter list buffer.");
 
2327
                else {
 
2328
                        unsigned code = DHO_DHCP_PARAMETER_REQUEST_LIST;
 
2329
 
 
2330
                        len = 0;
 
2331
                        for (i = 0 ; prl[i] != NULL ; i++)
 
2332
                                if (prl[i]->universe == &dhcp_universe)
 
2333
                                        bp->data[len++] = prl[i]->code;
 
2334
 
 
2335
                        if (!(option_code_hash_lookup(&option,
 
2336
                                                      dhcp_universe.code_hash,
 
2337
                                                      &code, 0, MDL) &&
 
2338
                              make_const_option_cache(&oc, &bp, NULL, len,
 
2339
                                                      option, MDL)))
 
2340
                                log_error ("can't make option cache");
 
2341
                        else {
 
2342
                                save_option (&dhcp_universe, *op, oc);
 
2343
                                option_cache_dereference (&oc, MDL);
 
2344
                        }
 
2345
                        option_dereference(&option, MDL);
 
2346
                }
 
2347
        }
 
2348
 
 
2349
        /* Run statements that need to be run on transmission. */
 
2350
        if (client -> config -> on_transmission)
 
2351
                execute_statements_in_scope
 
2352
                        ((struct binding_value **)0,
 
2353
                         (struct packet *)0, (struct lease *)0, client,
 
2354
                         (lease ? lease -> options : (struct option_state *)0),
 
2355
                         *op, &global_scope,
 
2356
                         client -> config -> on_transmission,
 
2357
                         (struct group *)0);
 
2358
}
 
2359
 
 
2360
void make_discover (client, lease)
 
2361
        struct client_state *client;
 
2362
        struct client_lease *lease;
 
2363
{
 
2364
        unsigned char discover = DHCPDISCOVER;
 
2365
        struct option_state *options = (struct option_state *)0;
 
2366
 
 
2367
        memset (&client -> packet, 0, sizeof (client -> packet));
 
2368
 
 
2369
        make_client_options (client,
 
2370
                             lease, &discover, (struct option_cache *)0,
 
2371
                             lease ? &lease -> address : (struct iaddr *)0,
 
2372
                             client -> config -> requested_options,
 
2373
                             &options);
 
2374
 
 
2375
        /* Set up the option buffer... */
 
2376
        client -> packet_length =
 
2377
                cons_options ((struct packet *)0, &client -> packet,
 
2378
                              (struct lease *)0, client,
 
2379
                              /* maximum packet size */1500,
 
2380
                              (struct option_state *)0,
 
2381
                              options,
 
2382
                              /* scope */ &global_scope,
 
2383
                              /* overload */ 0,
 
2384
                              /* terminate */0,
 
2385
                              /* bootpp    */0,
 
2386
                              (struct data_string *)0,
 
2387
                              client -> config -> vendor_space_name);
 
2388
 
 
2389
        option_state_dereference (&options, MDL);
 
2390
        if (client -> packet_length < BOOTP_MIN_LEN)
 
2391
                client -> packet_length = BOOTP_MIN_LEN;
 
2392
 
 
2393
        client -> packet.op = BOOTREQUEST;
 
2394
        client -> packet.htype = client -> interface -> hw_address.hbuf [0];
 
2395
        client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
 
2396
        client -> packet.hops = 0;
 
2397
        client -> packet.xid = random ();
 
2398
        client -> packet.secs = 0; /* filled in by send_discover. */
 
2399
 
 
2400
        if (can_receive_unicast_unconfigured (client -> interface))
 
2401
                client -> packet.flags = 0;
 
2402
        else
 
2403
                client -> packet.flags = htons (BOOTP_BROADCAST);
 
2404
 
 
2405
        memset (&(client -> packet.ciaddr),
 
2406
                0, sizeof client -> packet.ciaddr);
 
2407
        memset (&(client -> packet.yiaddr),
 
2408
                0, sizeof client -> packet.yiaddr);
 
2409
        memset (&(client -> packet.siaddr),
 
2410
                0, sizeof client -> packet.siaddr);
 
2411
        client -> packet.giaddr = giaddr;
 
2412
        if (client -> interface -> hw_address.hlen > 0)
 
2413
            memcpy (client -> packet.chaddr,
 
2414
                    &client -> interface -> hw_address.hbuf [1],
 
2415
                    (unsigned)(client -> interface -> hw_address.hlen - 1));
 
2416
 
 
2417
#ifdef DEBUG_PACKET
 
2418
        dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
 
2419
#endif
 
2420
}
 
2421
 
 
2422
 
 
2423
void make_request (client, lease)
 
2424
        struct client_state *client;
 
2425
        struct client_lease *lease;
 
2426
{
 
2427
        unsigned char request = DHCPREQUEST;
 
2428
        struct option_cache *oc;
 
2429
 
 
2430
        memset (&client -> packet, 0, sizeof (client -> packet));
 
2431
 
 
2432
        if (client -> state == S_REQUESTING)
 
2433
                oc = lookup_option (&dhcp_universe, lease -> options,
 
2434
                                    DHO_DHCP_SERVER_IDENTIFIER);
 
2435
        else
 
2436
                oc = (struct option_cache *)0;
 
2437
 
 
2438
        if (client -> sent_options)
 
2439
                option_state_dereference (&client -> sent_options, MDL);
 
2440
 
 
2441
        make_client_options (client, lease, &request, oc,
 
2442
                             ((client -> state == S_REQUESTING ||
 
2443
                               client -> state == S_REBOOTING)
 
2444
                              ? &lease -> address
 
2445
                              : (struct iaddr *)0),
 
2446
                             client -> config -> requested_options,
 
2447
                             &client -> sent_options);
 
2448
 
 
2449
        /* Set up the option buffer... */
 
2450
        client -> packet_length =
 
2451
                cons_options ((struct packet *)0, &client -> packet,
 
2452
                              (struct lease *)0, client,
 
2453
                              /* maximum packet size */1500,
 
2454
                              (struct option_state *)0,
 
2455
                              client -> sent_options,
 
2456
                              /* scope */ &global_scope,
 
2457
                              /* overload */ 0,
 
2458
                              /* terminate */0,
 
2459
                              /* bootpp    */0,
 
2460
                              (struct data_string *)0,
 
2461
                              client -> config -> vendor_space_name);
 
2462
 
 
2463
        if (client -> packet_length < BOOTP_MIN_LEN)
 
2464
                client -> packet_length = BOOTP_MIN_LEN;
 
2465
 
 
2466
        client -> packet.op = BOOTREQUEST;
 
2467
        client -> packet.htype = client -> interface -> hw_address.hbuf [0];
 
2468
        client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
 
2469
        client -> packet.hops = 0;
 
2470
        client -> packet.xid = client -> xid;
 
2471
        client -> packet.secs = 0; /* Filled in by send_request. */
 
2472
 
 
2473
        /* If we own the address we're requesting, put it in ciaddr;
 
2474
           otherwise set ciaddr to zero. */
 
2475
        if (client -> state == S_BOUND ||
 
2476
            client -> state == S_RENEWING ||
 
2477
            client -> state == S_REBINDING) {
 
2478
                memcpy (&client -> packet.ciaddr,
 
2479
                        lease -> address.iabuf, lease -> address.len);
 
2480
                client -> packet.flags = 0;
 
2481
        } else {
 
2482
                memset (&client -> packet.ciaddr, 0,
 
2483
                        sizeof client -> packet.ciaddr);
 
2484
                if (can_receive_unicast_unconfigured (client -> interface))
 
2485
                        client -> packet.flags = 0;
 
2486
                else
 
2487
                        client -> packet.flags = htons (BOOTP_BROADCAST);
 
2488
        }
 
2489
 
 
2490
        memset (&client -> packet.yiaddr, 0,
 
2491
                sizeof client -> packet.yiaddr);
 
2492
        memset (&client -> packet.siaddr, 0,
 
2493
                sizeof client -> packet.siaddr);
 
2494
        if (client -> state != S_BOUND &&
 
2495
            client -> state != S_RENEWING)
 
2496
                client -> packet.giaddr = giaddr;
 
2497
        else
 
2498
                memset (&client -> packet.giaddr, 0,
 
2499
                        sizeof client -> packet.giaddr);
 
2500
        if (client -> interface -> hw_address.hlen > 0)
 
2501
            memcpy (client -> packet.chaddr,
 
2502
                    &client -> interface -> hw_address.hbuf [1],
 
2503
                    (unsigned)(client -> interface -> hw_address.hlen - 1));
 
2504
 
 
2505
#ifdef DEBUG_PACKET
 
2506
        dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
 
2507
#endif
 
2508
}
 
2509
 
 
2510
void make_decline (client, lease)
 
2511
        struct client_state *client;
 
2512
        struct client_lease *lease;
 
2513
{
 
2514
        unsigned char decline = DHCPDECLINE;
 
2515
        struct option_cache *oc;
 
2516
 
 
2517
        struct option_state *options = (struct option_state *)0;
 
2518
 
 
2519
        /* Create the options cache. */
 
2520
        oc = lookup_option (&dhcp_universe, lease -> options,
 
2521
                            DHO_DHCP_SERVER_IDENTIFIER);
 
2522
        make_client_options(client, lease, &decline, oc, &lease->address,
 
2523
                            NULL, &options);
 
2524
 
 
2525
        /* Consume the options cache into the option buffer. */
 
2526
        memset (&client -> packet, 0, sizeof (client -> packet));
 
2527
        client -> packet_length =
 
2528
                cons_options ((struct packet *)0, &client -> packet,
 
2529
                              (struct lease *)0, client, 0,
 
2530
                              (struct option_state *)0, options,
 
2531
                              &global_scope, 0, 0, 0, (struct data_string *)0,
 
2532
                              client -> config -> vendor_space_name);
 
2533
 
 
2534
        /* Destroy the options cache. */
 
2535
        option_state_dereference (&options, MDL);
 
2536
 
 
2537
        if (client -> packet_length < BOOTP_MIN_LEN)
 
2538
                client -> packet_length = BOOTP_MIN_LEN;
 
2539
 
 
2540
        client -> packet.op = BOOTREQUEST;
 
2541
        client -> packet.htype = client -> interface -> hw_address.hbuf [0];
 
2542
        client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
 
2543
        client -> packet.hops = 0;
 
2544
        client -> packet.xid = client -> xid;
 
2545
        client -> packet.secs = 0; /* Filled in by send_request. */
 
2546
        if (can_receive_unicast_unconfigured (client -> interface))
 
2547
                client -> packet.flags = 0;
 
2548
        else
 
2549
                client -> packet.flags = htons (BOOTP_BROADCAST);
 
2550
 
 
2551
        /* ciaddr must always be zero. */
 
2552
        memset (&client -> packet.ciaddr, 0,
 
2553
                sizeof client -> packet.ciaddr);
 
2554
        memset (&client -> packet.yiaddr, 0,
 
2555
                sizeof client -> packet.yiaddr);
 
2556
        memset (&client -> packet.siaddr, 0,
 
2557
                sizeof client -> packet.siaddr);
 
2558
        client -> packet.giaddr = giaddr;
 
2559
        memcpy (client -> packet.chaddr,
 
2560
                &client -> interface -> hw_address.hbuf [1],
 
2561
                client -> interface -> hw_address.hlen);
 
2562
 
 
2563
#ifdef DEBUG_PACKET
 
2564
        dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
 
2565
#endif
 
2566
}
 
2567
 
 
2568
void make_release (client, lease)
 
2569
        struct client_state *client;
 
2570
        struct client_lease *lease;
 
2571
{
 
2572
        unsigned char request = DHCPRELEASE;
 
2573
        struct option_cache *oc;
 
2574
 
 
2575
        struct option_state *options = (struct option_state *)0;
 
2576
 
 
2577
        memset (&client -> packet, 0, sizeof (client -> packet));
 
2578
 
 
2579
        oc = lookup_option (&dhcp_universe, lease -> options,
 
2580
                            DHO_DHCP_SERVER_IDENTIFIER);
 
2581
        make_client_options(client, lease, &request, oc, NULL, NULL, &options);
 
2582
 
 
2583
        /* Set up the option buffer... */
 
2584
        client -> packet_length =
 
2585
                cons_options ((struct packet *)0, &client -> packet,
 
2586
                              (struct lease *)0, client,
 
2587
                              /* maximum packet size */1500,
 
2588
                              (struct option_state *)0,
 
2589
                              options,
 
2590
                              /* scope */ &global_scope,
 
2591
                              /* overload */ 0,
 
2592
                              /* terminate */0,
 
2593
                              /* bootpp    */0,
 
2594
                              (struct data_string *)0,
 
2595
                              client -> config -> vendor_space_name);
 
2596
 
 
2597
        if (client -> packet_length < BOOTP_MIN_LEN)
 
2598
                client -> packet_length = BOOTP_MIN_LEN;
 
2599
        option_state_dereference (&options, MDL);
 
2600
 
 
2601
        client -> packet.op = BOOTREQUEST;
 
2602
        client -> packet.htype = client -> interface -> hw_address.hbuf [0];
 
2603
        client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
 
2604
        client -> packet.hops = 0;
 
2605
        client -> packet.xid = random ();
 
2606
        client -> packet.secs = 0;
 
2607
        client -> packet.flags = 0;
 
2608
        memcpy (&client -> packet.ciaddr,
 
2609
                lease -> address.iabuf, lease -> address.len);
 
2610
        memset (&client -> packet.yiaddr, 0,
 
2611
                sizeof client -> packet.yiaddr);
 
2612
        memset (&client -> packet.siaddr, 0,
 
2613
                sizeof client -> packet.siaddr);
 
2614
        client -> packet.giaddr = giaddr;
 
2615
        memcpy (client -> packet.chaddr,
 
2616
                &client -> interface -> hw_address.hbuf [1],
 
2617
                client -> interface -> hw_address.hlen);
 
2618
 
 
2619
#ifdef DEBUG_PACKET
 
2620
        dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
 
2621
#endif
 
2622
}
 
2623
 
 
2624
void destroy_client_lease (lease)
 
2625
        struct client_lease *lease;
 
2626
{
 
2627
        if (lease -> server_name)
 
2628
                dfree (lease -> server_name, MDL);
 
2629
        if (lease -> filename)
 
2630
                dfree (lease -> filename, MDL);
 
2631
        option_state_dereference (&lease -> options, MDL);
 
2632
        free_client_lease (lease, MDL);
 
2633
}
 
2634
 
 
2635
FILE *leaseFile = NULL;
 
2636
int leases_written = 0;
 
2637
 
 
2638
void rewrite_client_leases ()
 
2639
{
 
2640
        struct interface_info *ip;
 
2641
        struct client_state *client;
 
2642
        struct client_lease *lp;
 
2643
 
 
2644
        if (leaseFile != NULL)
 
2645
                fclose (leaseFile);
 
2646
        leaseFile = fopen (path_dhclient_db, "w");
 
2647
        if (leaseFile == NULL) {
 
2648
                log_error ("can't create %s: %m", path_dhclient_db);
 
2649
                return;
 
2650
        }
 
2651
 
 
2652
        /* If there is a default duid, write it out. */
 
2653
        if (default_duid.len != 0)
 
2654
                write_duid(&default_duid);
 
2655
 
 
2656
        /* Write out all the leases attached to configured interfaces that
 
2657
           we know about. */
 
2658
        for (ip = interfaces; ip; ip = ip -> next) {
 
2659
                for (client = ip -> client; client; client = client -> next) {
 
2660
                        for (lp = client -> leases; lp; lp = lp -> next) {
 
2661
                                write_client_lease (client, lp, 1, 0);
 
2662
                        }
 
2663
                        if (client -> active)
 
2664
                                write_client_lease (client,
 
2665
                                                    client -> active, 1, 0);
 
2666
 
 
2667
                        if (client->active_lease != NULL)
 
2668
                                write_client6_lease(client,
 
2669
                                                    client->active_lease,
 
2670
                                                    1, 0);
 
2671
 
 
2672
                        /* Reset last_write after rewrites. */
 
2673
                        client->last_write = 0;
 
2674
                }
 
2675
        }
 
2676
 
 
2677
        /* Write out any leases that are attached to interfaces that aren't
 
2678
           currently configured. */
 
2679
        for (ip = dummy_interfaces; ip; ip = ip -> next) {
 
2680
                for (client = ip -> client; client; client = client -> next) {
 
2681
                        for (lp = client -> leases; lp; lp = lp -> next) {
 
2682
                                write_client_lease (client, lp, 1, 0);
 
2683
                        }
 
2684
                        if (client -> active)
 
2685
                                write_client_lease (client,
 
2686
                                                    client -> active, 1, 0);
 
2687
 
 
2688
                        if (client->active_lease != NULL)
 
2689
                                write_client6_lease(client,
 
2690
                                                    client->active_lease,
 
2691
                                                    1, 0);
 
2692
 
 
2693
                        /* Reset last_write after rewrites. */
 
2694
                        client->last_write = 0;
 
2695
                }
 
2696
        }
 
2697
        fflush (leaseFile);
 
2698
}
 
2699
 
 
2700
void write_lease_option (struct option_cache *oc,
 
2701
                         struct packet *packet, struct lease *lease,
 
2702
                         struct client_state *client_state,
 
2703
                         struct option_state *in_options,
 
2704
                         struct option_state *cfg_options,
 
2705
                         struct binding_scope **scope,
 
2706
                         struct universe *u, void *stuff)
 
2707
{
 
2708
        const char *name, *dot;
 
2709
        struct data_string ds;
 
2710
        char *preamble = stuff;
 
2711
 
 
2712
        memset (&ds, 0, sizeof ds);
 
2713
 
 
2714
        if (u != &dhcp_universe) {
 
2715
                name = u -> name;
 
2716
                dot = ".";
 
2717
        } else {
 
2718
                name = "";
 
2719
                dot = "";
 
2720
        }
 
2721
        if (evaluate_option_cache (&ds, packet, lease, client_state,
 
2722
                                   in_options, cfg_options, scope, oc, MDL)) {
 
2723
                fprintf(leaseFile, "%soption %s%s%s %s;\n", preamble,
 
2724
                        name, dot, oc->option->name,
 
2725
                        pretty_print_option(oc->option, ds.data, ds.len,
 
2726
                                            1, 1));
 
2727
                data_string_forget (&ds, MDL);
 
2728
        }
 
2729
}
 
2730
 
 
2731
/* Write an option cache to the lease store. */
 
2732
static void
 
2733
write_options(struct client_state *client, struct option_state *options,
 
2734
              const char *preamble)
 
2735
{
 
2736
        int i;
 
2737
 
 
2738
        for (i = 0; i < options->universe_count; i++) {
 
2739
                option_space_foreach(NULL, NULL, client, NULL, options,
 
2740
                                     &global_scope, universes[i],
 
2741
                                     (char *)preamble, write_lease_option);
 
2742
        }
 
2743
}
 
2744
 
 
2745
/* Write the default DUID to the lease store. */
 
2746
static isc_result_t
 
2747
write_duid(struct data_string *duid)
 
2748
{
 
2749
        char *str;
 
2750
        int stat;
 
2751
 
 
2752
        if ((duid == NULL) || (duid->len <= 2))
 
2753
                return DHCP_R_INVALIDARG;
 
2754
 
 
2755
        if (leaseFile == NULL) {        /* XXX? */
 
2756
                leaseFile = fopen(path_dhclient_db, "w");
 
2757
                if (leaseFile == NULL) {
 
2758
                        log_error("can't create %s: %m", path_dhclient_db);
 
2759
                        return ISC_R_IOERROR;
 
2760
                }
 
2761
        }
 
2762
 
 
2763
        /* It would make more sense to write this as a hex string,
 
2764
         * but our function to do that (print_hex_n) uses a fixed
 
2765
         * length buffer...and we can't guarantee a duid would be
 
2766
         * less than the fixed length.
 
2767
         */
 
2768
        str = quotify_buf(duid->data, duid->len, MDL);
 
2769
        if (str == NULL)
 
2770
                return ISC_R_NOMEMORY;
 
2771
 
 
2772
        stat = fprintf(leaseFile, "default-duid \"%s\";\n", str);
 
2773
        dfree(str, MDL);
 
2774
        if (stat <= 0)
 
2775
                return ISC_R_IOERROR;
 
2776
 
 
2777
        if (fflush(leaseFile) != 0)
 
2778
                return ISC_R_IOERROR;
 
2779
 
 
2780
        return ISC_R_SUCCESS;
 
2781
}
 
2782
 
 
2783
/* Write a DHCPv6 lease to the store. */
 
2784
isc_result_t
 
2785
write_client6_lease(struct client_state *client, struct dhc6_lease *lease,
 
2786
                    int rewrite, int sync)
 
2787
{
 
2788
        struct dhc6_ia *ia;
 
2789
        struct dhc6_addr *addr;
 
2790
        int stat;
 
2791
        const char *ianame;
 
2792
 
 
2793
        /* This should include the current lease. */
 
2794
        if (!rewrite && (leases_written++ > 20)) {
 
2795
                rewrite_client_leases();
 
2796
                leases_written = 0;
 
2797
                return ISC_R_SUCCESS;
 
2798
        }
 
2799
 
 
2800
        if (client == NULL || lease == NULL)
 
2801
                return DHCP_R_INVALIDARG;
 
2802
 
 
2803
        if (leaseFile == NULL) {        /* XXX? */
 
2804
                leaseFile = fopen(path_dhclient_db, "w");
 
2805
                if (leaseFile == NULL) {
 
2806
                        log_error("can't create %s: %m", path_dhclient_db);
 
2807
                        return ISC_R_IOERROR;
 
2808
                }
 
2809
        }
 
2810
 
 
2811
        stat = fprintf(leaseFile, "lease6 {\n");
 
2812
        if (stat <= 0)
 
2813
                return ISC_R_IOERROR;
 
2814
 
 
2815
        stat = fprintf(leaseFile, "  interface \"%s\";\n",
 
2816
                       client->interface->name);
 
2817
        if (stat <= 0)
 
2818
                return ISC_R_IOERROR;
 
2819
 
 
2820
        for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
 
2821
                switch (ia->ia_type) {
 
2822
                        case D6O_IA_NA:
 
2823
                        default:
 
2824
                                ianame = "ia-na";
 
2825
                                break;
 
2826
                        case D6O_IA_TA:
 
2827
                                ianame = "ia-ta";
 
2828
                                break;
 
2829
                        case D6O_IA_PD:
 
2830
                                ianame = "ia-pd";
 
2831
                                break;
 
2832
                }
 
2833
                stat = fprintf(leaseFile, "  %s %s {\n",
 
2834
                               ianame, print_hex_1(4, ia->iaid, 12));
 
2835
                if (stat <= 0)
 
2836
                        return ISC_R_IOERROR;
 
2837
 
 
2838
                if (ia->ia_type != D6O_IA_TA)
 
2839
                        stat = fprintf(leaseFile, "    starts %d;\n"
 
2840
                                                  "    renew %u;\n"
 
2841
                                                  "    rebind %u;\n",
 
2842
                                       (int)ia->starts, ia->renew, ia->rebind);
 
2843
                else
 
2844
                        stat = fprintf(leaseFile, "    starts %d;\n",
 
2845
                                       (int)ia->starts);
 
2846
                if (stat <= 0)
 
2847
                        return ISC_R_IOERROR;
 
2848
 
 
2849
                for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
 
2850
                        if (ia->ia_type != D6O_IA_PD)
 
2851
                                stat = fprintf(leaseFile,
 
2852
                                               "    iaaddr %s {\n",
 
2853
                                               piaddr(addr->address));
 
2854
                        else
 
2855
                                stat = fprintf(leaseFile,
 
2856
                                               "    iaprefix %s/%d {\n",
 
2857
                                               piaddr(addr->address),
 
2858
                                               (int)addr->plen);
 
2859
                        if (stat <= 0)
 
2860
                                return ISC_R_IOERROR;
 
2861
 
 
2862
                        stat = fprintf(leaseFile, "      starts %d;\n"
 
2863
                                                  "      preferred-life %u;\n"
 
2864
                                                  "      max-life %u;\n",
 
2865
                                       (int)addr->starts, addr->preferred_life,
 
2866
                                       addr->max_life);
 
2867
                        if (stat <= 0)
 
2868
                                return ISC_R_IOERROR;
 
2869
 
 
2870
                        if (addr->options != NULL)
 
2871
                                write_options(client, addr->options, "      ");
 
2872
 
 
2873
                        stat = fprintf(leaseFile, "    }\n");
 
2874
                        if (stat <= 0)
 
2875
                                return ISC_R_IOERROR;
 
2876
                }
 
2877
 
 
2878
                if (ia->options != NULL)
 
2879
                        write_options(client, ia->options, "    ");
 
2880
 
 
2881
                stat = fprintf(leaseFile, "  }\n");
 
2882
                if (stat <= 0)
 
2883
                        return ISC_R_IOERROR;
 
2884
        }
 
2885
 
 
2886
        if (lease->released) {
 
2887
                stat = fprintf(leaseFile, "  released;\n");
 
2888
                if (stat <= 0)
 
2889
                        return ISC_R_IOERROR;
 
2890
        }
 
2891
 
 
2892
        if (lease->options != NULL)
 
2893
                write_options(client, lease->options, "  ");
 
2894
 
 
2895
        stat = fprintf(leaseFile, "}\n");
 
2896
        if (stat <= 0)
 
2897
                return ISC_R_IOERROR;
 
2898
 
 
2899
        if (fflush(leaseFile) != 0)
 
2900
                return ISC_R_IOERROR;
 
2901
 
 
2902
        if (sync) {
 
2903
                if (fsync(fileno(leaseFile)) < 0) {
 
2904
                        log_error("write_client_lease: fsync(): %m");
 
2905
                        return ISC_R_IOERROR;
 
2906
                }
 
2907
        }
 
2908
 
 
2909
        return ISC_R_SUCCESS;
 
2910
}
 
2911
 
 
2912
int write_client_lease (client, lease, rewrite, makesure)
 
2913
        struct client_state *client;
 
2914
        struct client_lease *lease;
 
2915
        int rewrite;
 
2916
        int makesure;
 
2917
{
 
2918
        struct data_string ds;
 
2919
        int errors = 0;
 
2920
        char *s;
 
2921
        const char *tval;
 
2922
 
 
2923
        if (!rewrite) {
 
2924
                if (leases_written++ > 20) {
 
2925
                        rewrite_client_leases ();
 
2926
                        leases_written = 0;
 
2927
                }
 
2928
        }
 
2929
 
 
2930
        /* If the lease came from the config file, we don't need to stash
 
2931
           a copy in the lease database. */
 
2932
        if (lease -> is_static)
 
2933
                return 1;
 
2934
 
 
2935
        if (leaseFile == NULL) {        /* XXX */
 
2936
                leaseFile = fopen (path_dhclient_db, "w");
 
2937
                if (leaseFile == NULL) {
 
2938
                        log_error ("can't create %s: %m", path_dhclient_db);
 
2939
                        return 0;
 
2940
                }
 
2941
        }
 
2942
 
 
2943
        errno = 0;
 
2944
        fprintf (leaseFile, "lease {\n");
 
2945
        if (lease -> is_bootp) {
 
2946
                fprintf (leaseFile, "  bootp;\n");
 
2947
                if (errno) {
 
2948
                        ++errors;
 
2949
                        errno = 0;
 
2950
                }
 
2951
        }
 
2952
        fprintf (leaseFile, "  interface \"%s\";\n",
 
2953
                 client -> interface -> name);
 
2954
        if (errno) {
 
2955
                ++errors;
 
2956
                errno = 0;
 
2957
        }
 
2958
        if (client -> name) {
 
2959
                fprintf (leaseFile, "  name \"%s\";\n", client -> name);
 
2960
                if (errno) {
 
2961
                        ++errors;
 
2962
                        errno = 0;
 
2963
                }
 
2964
        }
 
2965
        fprintf (leaseFile, "  fixed-address %s;\n",
 
2966
                 piaddr (lease -> address));
 
2967
        if (errno) {
 
2968
                ++errors;
 
2969
                errno = 0;
 
2970
        }
 
2971
        if (lease -> filename) {
 
2972
                s = quotify_string (lease -> filename, MDL);
 
2973
                if (s) {
 
2974
                        fprintf (leaseFile, "  filename \"%s\";\n", s);
 
2975
                        if (errno) {
 
2976
                                ++errors;
 
2977
                                errno = 0;
 
2978
                        }
 
2979
                        dfree (s, MDL);
 
2980
                } else
 
2981
                        errors++;
 
2982
 
 
2983
        }
 
2984
        if (lease->server_name != NULL) {
 
2985
                s = quotify_string(lease->server_name, MDL);
 
2986
                if (s != NULL) {
 
2987
                        fprintf(leaseFile, "  server-name \"%s\";\n", s);
 
2988
                        if (errno) {
 
2989
                                ++errors;
 
2990
                                errno = 0;
 
2991
                        }
 
2992
                        dfree(s, MDL);
 
2993
                } else
 
2994
                        ++errors;
 
2995
        }
 
2996
        if (lease -> medium) {
 
2997
                s = quotify_string (lease -> medium -> string, MDL);
 
2998
                if (s) {
 
2999
                        fprintf (leaseFile, "  medium \"%s\";\n", s);
 
3000
                        if (errno) {
 
3001
                                ++errors;
 
3002
                                errno = 0;
 
3003
                        }
 
3004
                        dfree (s, MDL);
 
3005
                } else
 
3006
                        errors++;
 
3007
        }
 
3008
        if (errno != 0) {
 
3009
                errors++;
 
3010
                errno = 0;
 
3011
        }
 
3012
 
 
3013
        memset (&ds, 0, sizeof ds);
 
3014
 
 
3015
        write_options(client, lease->options, "  ");
 
3016
 
 
3017
        tval = print_time(lease->renewal);
 
3018
        if (tval == NULL ||
 
3019
            fprintf(leaseFile, "  renew %s\n", tval) < 0)
 
3020
                errors++;
 
3021
 
 
3022
        tval = print_time(lease->rebind);
 
3023
        if (tval == NULL ||
 
3024
            fprintf(leaseFile, "  rebind %s\n", tval) < 0)
 
3025
                errors++;
 
3026
 
 
3027
        tval = print_time(lease->expiry);
 
3028
        if (tval == NULL ||
 
3029
            fprintf(leaseFile, "  expire %s\n", tval) < 0)
 
3030
                errors++;
 
3031
 
 
3032
        if (fprintf(leaseFile, "}\n") < 0)
 
3033
                errors++;
 
3034
 
 
3035
        if (fflush(leaseFile) != 0)
 
3036
                errors++;
 
3037
 
 
3038
        client->last_write = cur_time;
 
3039
 
 
3040
        if (!errors && makesure) {
 
3041
                if (fsync (fileno (leaseFile)) < 0) {
 
3042
                        log_info ("write_client_lease: %m");
 
3043
                        return 0;
 
3044
                }
 
3045
        }
 
3046
 
 
3047
        return errors ? 0 : 1;
 
3048
}
 
3049
 
 
3050
/* Variables holding name of script and file pointer for writing to
 
3051
   script.   Needless to say, this is not reentrant - only one script
 
3052
   can be invoked at a time. */
 
3053
char scriptName [256];
 
3054
FILE *scriptFile;
 
3055
 
 
3056
void script_init (client, reason, medium)
 
3057
        struct client_state *client;
 
3058
        const char *reason;
 
3059
        struct string_list *medium;
 
3060
{
 
3061
        struct string_list *sl, *next;
 
3062
 
 
3063
        if (client) {
 
3064
                for (sl = client -> env; sl; sl = next) {
 
3065
                        next = sl -> next;
 
3066
                        dfree (sl, MDL);
 
3067
                }
 
3068
                client -> env = (struct string_list *)0;
 
3069
                client -> envc = 0;
 
3070
 
 
3071
                if (client -> interface) {
 
3072
                        client_envadd (client, "", "interface", "%s",
 
3073
                                       client -> interface -> name);
 
3074
                }
 
3075
                if (client -> name)
 
3076
                        client_envadd (client,
 
3077
                                       "", "client", "%s", client -> name);
 
3078
                if (medium)
 
3079
                        client_envadd (client,
 
3080
                                       "", "medium", "%s", medium -> string);
 
3081
 
 
3082
                client_envadd (client, "", "reason", "%s", reason);
 
3083
                client_envadd (client, "", "pid", "%ld", (long int)getpid ());
 
3084
        }
 
3085
}
 
3086
 
 
3087
void client_option_envadd (struct option_cache *oc,
 
3088
                           struct packet *packet, struct lease *lease,
 
3089
                           struct client_state *client_state,
 
3090
                           struct option_state *in_options,
 
3091
                           struct option_state *cfg_options,
 
3092
                           struct binding_scope **scope,
 
3093
                           struct universe *u, void *stuff)
 
3094
{
 
3095
        struct envadd_state *es = stuff;
 
3096
        struct data_string data;
 
3097
        memset (&data, 0, sizeof data);
 
3098
 
 
3099
        if (evaluate_option_cache (&data, packet, lease, client_state,
 
3100
                                   in_options, cfg_options, scope, oc, MDL)) {
 
3101
                if (data.len) {
 
3102
                        char name [256];
 
3103
                        if (dhcp_option_ev_name (name, sizeof name,
 
3104
                                                 oc->option)) {
 
3105
                                const char *value;
 
3106
                                size_t length;
 
3107
                                value = pretty_print_option(oc->option,
 
3108
                                                            data.data,
 
3109
                                                            data.len, 0, 0);
 
3110
                                length = strlen(value);
 
3111
 
 
3112
                                if (check_option_values(oc->option->universe,
 
3113
                                                        oc->option->code,
 
3114
                                                        value, length) == 0) {
 
3115
                                        client_envadd(es->client, es->prefix,
 
3116
                                                      name, "%s", value);
 
3117
                                } else {
 
3118
                                        log_error("suspect value in %s "
 
3119
                                                  "option - discarded",
 
3120
                                                  name);
 
3121
                                }
 
3122
                                data_string_forget (&data, MDL);
 
3123
                        }
 
3124
                }
 
3125
        }
 
3126
}
 
3127
 
 
3128
void script_write_params (client, prefix, lease)
 
3129
        struct client_state *client;
 
3130
        const char *prefix;
 
3131
        struct client_lease *lease;
 
3132
{
 
3133
        int i;
 
3134
        struct data_string data;
 
3135
        struct option_cache *oc;
 
3136
        struct envadd_state es;
 
3137
 
 
3138
        es.client = client;
 
3139
        es.prefix = prefix;
 
3140
 
 
3141
        client_envadd (client,
 
3142
                       prefix, "ip_address", "%s", piaddr (lease -> address));
 
3143
 
 
3144
        /* For the benefit of Linux (and operating systems which may
 
3145
           have similar needs), compute the network address based on
 
3146
           the supplied ip address and netmask, if provided.  Also
 
3147
           compute the broadcast address (the host address all ones
 
3148
           broadcast address, not the host address all zeroes
 
3149
           broadcast address). */
 
3150
 
 
3151
        memset (&data, 0, sizeof data);
 
3152
        oc = lookup_option (&dhcp_universe, lease -> options, DHO_SUBNET_MASK);
 
3153
        if (oc && evaluate_option_cache (&data, (struct packet *)0,
 
3154
                                         (struct lease *)0, client,
 
3155
                                         (struct option_state *)0,
 
3156
                                         lease -> options,
 
3157
                                         &global_scope, oc, MDL)) {
 
3158
                if (data.len > 3) {
 
3159
                        struct iaddr netmask, subnet, broadcast;
 
3160
 
 
3161
                        /*
 
3162
                         * No matter the length of the subnet-mask option,
 
3163
                         * use only the first four octets.  Note that
 
3164
                         * subnet-mask options longer than 4 octets are not
 
3165
                         * in conformance with RFC 2132, but servers with this
 
3166
                         * flaw do exist.
 
3167
                         */
 
3168
                        memcpy(netmask.iabuf, data.data, 4);
 
3169
                        netmask.len = 4;
 
3170
                        data_string_forget (&data, MDL);
 
3171
 
 
3172
                        subnet = subnet_number (lease -> address, netmask);
 
3173
                        if (subnet.len) {
 
3174
                            client_envadd (client, prefix, "network_number",
 
3175
                                           "%s", piaddr (subnet));
 
3176
 
 
3177
                            oc = lookup_option (&dhcp_universe,
 
3178
                                                lease -> options,
 
3179
                                                DHO_BROADCAST_ADDRESS);
 
3180
                            if (!oc ||
 
3181
                                !(evaluate_option_cache
 
3182
                                  (&data, (struct packet *)0,
 
3183
                                   (struct lease *)0, client,
 
3184
                                   (struct option_state *)0,
 
3185
                                   lease -> options,
 
3186
                                   &global_scope, oc, MDL))) {
 
3187
                                broadcast = broadcast_addr (subnet, netmask);
 
3188
                                if (broadcast.len) {
 
3189
                                    client_envadd (client,
 
3190
                                                   prefix, "broadcast_address",
 
3191
                                                   "%s", piaddr (broadcast));
 
3192
                                }
 
3193
                            }
 
3194
                        }
 
3195
                }
 
3196
                data_string_forget (&data, MDL);
 
3197
        }
 
3198
 
 
3199
        if (lease->filename) {
 
3200
                if (check_option_values(NULL, DHO_ROOT_PATH,
 
3201
                                        lease->filename,
 
3202
                                        strlen(lease->filename)) == 0) {
 
3203
                        client_envadd(client, prefix, "filename",
 
3204
                                      "%s", lease->filename);
 
3205
                } else {
 
3206
                        log_error("suspect value in %s "
 
3207
                                  "option - discarded",
 
3208
                                  lease->filename);
 
3209
                }
 
3210
        }
 
3211
 
 
3212
        if (lease->server_name) {
 
3213
                if (check_option_values(NULL, DHO_HOST_NAME,
 
3214
                                        lease->server_name,
 
3215
                                        strlen(lease->server_name)) == 0 ) {
 
3216
                        client_envadd (client, prefix, "server_name",
 
3217
                                       "%s", lease->server_name);
 
3218
                } else {
 
3219
                        log_error("suspect value in %s "
 
3220
                                  "option - discarded",
 
3221
                                  lease->server_name);
 
3222
                }
 
3223
        }
 
3224
                                
 
3225
 
 
3226
        for (i = 0; i < lease -> options -> universe_count; i++) {
 
3227
                option_space_foreach ((struct packet *)0, (struct lease *)0,
 
3228
                                      client, (struct option_state *)0,
 
3229
                                      lease -> options, &global_scope,
 
3230
                                      universes [i],
 
3231
                                      &es, client_option_envadd);
 
3232
        }
 
3233
        client_envadd (client, prefix, "expiry", "%d", (int)(lease -> expiry));
 
3234
}
 
3235
 
 
3236
int script_go (client)
 
3237
        struct client_state *client;
 
3238
{
 
3239
        char *scriptName;
 
3240
        char *argv [2];
 
3241
        char **envp;
 
3242
        char reason [] = "REASON=NBI";
 
3243
        static char client_path [] = CLIENT_PATH;
 
3244
        int i;
 
3245
        struct string_list *sp, *next;
 
3246
        int pid, wpid, wstatus;
 
3247
 
 
3248
        if (client)
 
3249
                scriptName = client -> config -> script_name;
 
3250
        else
 
3251
                scriptName = top_level_config.script_name;
 
3252
 
 
3253
        envp = dmalloc (((client ? client -> envc : 2) +
 
3254
                         client_env_count + 2) * sizeof (char *), MDL);
 
3255
        if (!envp) {
 
3256
                log_error ("No memory for client script environment.");
 
3257
                return 0;
 
3258
        }
 
3259
        i = 0;
 
3260
        /* Copy out the environment specified on the command line,
 
3261
           if any. */
 
3262
        for (sp = client_env; sp; sp = sp -> next) {
 
3263
                envp [i++] = sp -> string;
 
3264
        }
 
3265
        /* Copy out the environment specified by dhclient. */
 
3266
        if (client) {
 
3267
                for (sp = client -> env; sp; sp = sp -> next) {
 
3268
                        envp [i++] = sp -> string;
 
3269
                }
 
3270
        } else {
 
3271
                envp [i++] = reason;
 
3272
        }
 
3273
        /* Set $PATH. */
 
3274
        envp [i++] = client_path;
 
3275
        envp [i] = (char *)0;
 
3276
 
 
3277
        argv [0] = scriptName;
 
3278
        argv [1] = (char *)0;
 
3279
 
 
3280
        pid = fork ();
 
3281
        if (pid < 0) {
 
3282
                log_error ("fork: %m");
 
3283
                wstatus = 0;
 
3284
        } else if (pid) {
 
3285
                do {
 
3286
                        wpid = wait (&wstatus);
 
3287
                } while (wpid != pid && wpid > 0);
 
3288
                if (wpid < 0) {
 
3289
                        log_error ("wait: %m");
 
3290
                        wstatus = 0;
 
3291
                }
 
3292
        } else {
 
3293
                /* We don't want to pass an open file descriptor for
 
3294
                 * dhclient.leases when executing dhclient-script.
 
3295
                 */
 
3296
                if (leaseFile != NULL)
 
3297
                        fclose(leaseFile);
 
3298
                execve (scriptName, argv, envp);
 
3299
                log_error ("execve (%s, ...): %m", scriptName);
 
3300
                exit (0);
 
3301
        }
 
3302
 
 
3303
        if (client) {
 
3304
                for (sp = client -> env; sp; sp = next) {
 
3305
                        next = sp -> next;
 
3306
                        dfree (sp, MDL);
 
3307
                }
 
3308
                client -> env = (struct string_list *)0;
 
3309
                client -> envc = 0;
 
3310
        }
 
3311
        dfree (envp, MDL);
 
3312
        gettimeofday(&cur_tv, NULL);
 
3313
        return (WIFEXITED (wstatus) ?
 
3314
                WEXITSTATUS (wstatus) : -WTERMSIG (wstatus));
 
3315
}
 
3316
 
 
3317
void client_envadd (struct client_state *client,
 
3318
                    const char *prefix, const char *name, const char *fmt, ...)
 
3319
{
 
3320
        char spbuf [1024];
 
3321
        char *s;
 
3322
        unsigned len;
 
3323
        struct string_list *val;
 
3324
        va_list list;
 
3325
 
 
3326
        va_start (list, fmt);
 
3327
        len = vsnprintf (spbuf, sizeof spbuf, fmt, list);
 
3328
        va_end (list);
 
3329
 
 
3330
        val = dmalloc (strlen (prefix) + strlen (name) + 1 /* = */ +
 
3331
                       len + sizeof *val, MDL);
 
3332
        if (!val)
 
3333
                return;
 
3334
        s = val -> string;
 
3335
        strcpy (s, prefix);
 
3336
        strcat (s, name);
 
3337
        s += strlen (s);
 
3338
        *s++ = '=';
 
3339
        if (len >= sizeof spbuf) {
 
3340
                va_start (list, fmt);
 
3341
                vsnprintf (s, len + 1, fmt, list);
 
3342
                va_end (list);
 
3343
        } else
 
3344
                strcpy (s, spbuf);
 
3345
        val -> next = client -> env;
 
3346
        client -> env = val;
 
3347
        client -> envc++;
 
3348
}
 
3349
 
 
3350
int dhcp_option_ev_name (buf, buflen, option)
 
3351
        char *buf;
 
3352
        size_t buflen;
 
3353
        struct option *option;
 
3354
{
 
3355
        int i, j;
 
3356
        const char *s;
 
3357
 
 
3358
        j = 0;
 
3359
        if (option -> universe != &dhcp_universe) {
 
3360
                s = option -> universe -> name;
 
3361
                i = 0;
 
3362
        } else {
 
3363
                s = option -> name;
 
3364
                i = 1;
 
3365
        }
 
3366
 
 
3367
        do {
 
3368
                while (*s) {
 
3369
                        if (j + 1 == buflen)
 
3370
                                return 0;
 
3371
                        if (*s == '-')
 
3372
                                buf [j++] = '_';
 
3373
                        else
 
3374
                                buf [j++] = *s;
 
3375
                        ++s;
 
3376
                }
 
3377
                if (!i) {
 
3378
                        s = option -> name;
 
3379
                        if (j + 1 == buflen)
 
3380
                                return 0;
 
3381
                        buf [j++] = '_';
 
3382
                }
 
3383
                ++i;
 
3384
        } while (i != 2);
 
3385
 
 
3386
        buf [j] = 0;
 
3387
        return 1;
 
3388
}
 
3389
 
 
3390
void go_daemon ()
 
3391
{
 
3392
        static int state = 0;
 
3393
        int pid;
 
3394
 
 
3395
        /* Don't become a daemon if the user requested otherwise. */
 
3396
        if (no_daemon) {
 
3397
                write_client_pid_file ();
 
3398
                return;
 
3399
        }
 
3400
 
 
3401
        /* Only do it once. */
 
3402
        if (state)
 
3403
                return;
 
3404
        state = 1;
 
3405
 
 
3406
        /* Stop logging to stderr... */
 
3407
        log_perror = 0;
 
3408
 
 
3409
        /* Become a daemon... */
 
3410
        if ((pid = fork ()) < 0)
 
3411
                log_fatal ("Can't fork daemon: %m");
 
3412
        else if (pid)
 
3413
                exit (0);
 
3414
        /* Become session leader and get pid... */
 
3415
        pid = setsid ();
 
3416
 
 
3417
        /* Close standard I/O descriptors. */
 
3418
        close(0);
 
3419
        close(1);
 
3420
        close(2);
 
3421
 
 
3422
        /* Reopen them on /dev/null. */
 
3423
        open("/dev/null", O_RDWR);
 
3424
        open("/dev/null", O_RDWR);
 
3425
        open("/dev/null", O_RDWR);
 
3426
 
 
3427
        write_client_pid_file ();
 
3428
 
 
3429
        IGNORE_RET (chdir("/"));
 
3430
}
 
3431
 
 
3432
void write_client_pid_file ()
 
3433
{
 
3434
        FILE *pf;
 
3435
        int pfdesc;
 
3436
 
 
3437
        /* nothing to do if the user doesn't want a pid file */
 
3438
        if (no_pid_file == ISC_TRUE) {
 
3439
                return;
 
3440
        }
 
3441
 
 
3442
        pfdesc = open (path_dhclient_pid, O_CREAT | O_TRUNC | O_WRONLY, 0644);
 
3443
 
 
3444
        if (pfdesc < 0) {
 
3445
                log_error ("Can't create %s: %m", path_dhclient_pid);
 
3446
                return;
 
3447
        }
 
3448
 
 
3449
        pf = fdopen (pfdesc, "w");
 
3450
        if (!pf) {
 
3451
                close(pfdesc);
 
3452
                log_error ("Can't fdopen %s: %m", path_dhclient_pid);
 
3453
        } else {
 
3454
                fprintf (pf, "%ld\n", (long)getpid ());
 
3455
                fclose (pf);
 
3456
        }
 
3457
}
 
3458
 
 
3459
void client_location_changed ()
 
3460
{
 
3461
        struct interface_info *ip;
 
3462
        struct client_state *client;
 
3463
 
 
3464
        for (ip = interfaces; ip; ip = ip -> next) {
 
3465
                for (client = ip -> client; client; client = client -> next) {
 
3466
                        switch (client -> state) {
 
3467
                              case S_SELECTING:
 
3468
                                cancel_timeout (send_discover, client);
 
3469
                                break;
 
3470
 
 
3471
                              case S_BOUND:
 
3472
                                cancel_timeout (state_bound, client);
 
3473
                                break;
 
3474
 
 
3475
                              case S_REBOOTING:
 
3476
                              case S_REQUESTING:
 
3477
                              case S_RENEWING:
 
3478
                                cancel_timeout (send_request, client);
 
3479
                                break;
 
3480
 
 
3481
                              case S_INIT:
 
3482
                              case S_REBINDING:
 
3483
                              case S_STOPPED:
 
3484
                                break;
 
3485
                        }
 
3486
                        client -> state = S_INIT;
 
3487
                        state_reboot (client);
 
3488
                }
 
3489
        }
 
3490
}
 
3491
 
 
3492
void do_release(client)
 
3493
        struct client_state *client;
 
3494
{
 
3495
        struct data_string ds;
 
3496
        struct option_cache *oc;
 
3497
 
 
3498
        /* Pick a random xid. */
 
3499
        client -> xid = random ();
 
3500
 
 
3501
        /* is there even a lease to release? */
 
3502
        if (client -> active) {
 
3503
                /* Make a DHCPRELEASE packet, and set appropriate per-interface
 
3504
                   flags. */
 
3505
                make_release (client, client -> active);
 
3506
 
 
3507
                memset (&ds, 0, sizeof ds);
 
3508
                oc = lookup_option (&dhcp_universe,
 
3509
                                    client -> active -> options,
 
3510
                                    DHO_DHCP_SERVER_IDENTIFIER);
 
3511
                if (oc &&
 
3512
                    evaluate_option_cache (&ds, (struct packet *)0,
 
3513
                                           (struct lease *)0, client,
 
3514
                                           (struct option_state *)0,
 
3515
                                           client -> active -> options,
 
3516
                                           &global_scope, oc, MDL)) {
 
3517
                        if (ds.len > 3) {
 
3518
                                memcpy (client -> destination.iabuf,
 
3519
                                        ds.data, 4);
 
3520
                                client -> destination.len = 4;
 
3521
                        } else
 
3522
                                client -> destination = iaddr_broadcast;
 
3523
 
 
3524
                        data_string_forget (&ds, MDL);
 
3525
                } else
 
3526
                        client -> destination = iaddr_broadcast;
 
3527
                client -> first_sending = cur_time;
 
3528
                client -> interval = client -> config -> initial_interval;
 
3529
 
 
3530
                /* Zap the medium list... */
 
3531
                client -> medium = (struct string_list *)0;
 
3532
 
 
3533
                /* Send out the first and only DHCPRELEASE packet. */
 
3534
                send_release (client);
 
3535
 
 
3536
                /* Do the client script RELEASE operation. */
 
3537
                script_init (client,
 
3538
                             "RELEASE", (struct string_list *)0);
 
3539
                if (client -> alias)
 
3540
                        script_write_params (client, "alias_",
 
3541
                                             client -> alias);
 
3542
                script_write_params (client, "old_", client -> active);
 
3543
                script_go (client);
 
3544
        }
 
3545
 
 
3546
        /* Cancel any timeouts. */
 
3547
        cancel_timeout (state_bound, client);
 
3548
        cancel_timeout (send_discover, client);
 
3549
        cancel_timeout (state_init, client);
 
3550
        cancel_timeout (send_request, client);
 
3551
        cancel_timeout (state_reboot, client);
 
3552
        client -> state = S_STOPPED;
 
3553
}
 
3554
 
 
3555
int dhclient_interface_shutdown_hook (struct interface_info *interface)
 
3556
{
 
3557
        do_release (interface -> client);
 
3558
 
 
3559
        return 1;
 
3560
}
 
3561
 
 
3562
int dhclient_interface_discovery_hook (struct interface_info *tmp)
 
3563
{
 
3564
        struct interface_info *last, *ip;
 
3565
        /* See if we can find the client from dummy_interfaces */
 
3566
        last = 0;
 
3567
        for (ip = dummy_interfaces; ip; ip = ip -> next) {
 
3568
                if (!strcmp (ip -> name, tmp -> name)) {
 
3569
                        /* Remove from dummy_interfaces */
 
3570
                        if (last) {
 
3571
                                ip = (struct interface_info *)0;
 
3572
                                interface_reference (&ip, last -> next, MDL);
 
3573
                                interface_dereference (&last -> next, MDL);
 
3574
                                if (ip -> next) {
 
3575
                                        interface_reference (&last -> next,
 
3576
                                                             ip -> next, MDL);
 
3577
                                        interface_dereference (&ip -> next,
 
3578
                                                               MDL);
 
3579
                                }
 
3580
                        } else {
 
3581
                                ip = (struct interface_info *)0;
 
3582
                                interface_reference (&ip,
 
3583
                                                     dummy_interfaces, MDL);
 
3584
                                interface_dereference (&dummy_interfaces, MDL);
 
3585
                                if (ip -> next) {
 
3586
                                        interface_reference (&dummy_interfaces,
 
3587
                                                             ip -> next, MDL);
 
3588
                                        interface_dereference (&ip -> next,
 
3589
                                                               MDL);
 
3590
                                }
 
3591
                        }
 
3592
                        /* Copy "client" to tmp */
 
3593
                        if (ip -> client) {
 
3594
                                tmp -> client = ip -> client;
 
3595
                                tmp -> client -> interface = tmp;
 
3596
                        }
 
3597
                        interface_dereference (&ip, MDL);
 
3598
                        break;
 
3599
                }
 
3600
                last = ip;
 
3601
        }
 
3602
        return 1;
 
3603
}
 
3604
 
 
3605
isc_result_t dhclient_interface_startup_hook (struct interface_info *interface)
 
3606
{
 
3607
        struct interface_info *ip;
 
3608
        struct client_state *client;
 
3609
 
 
3610
        /* This code needs some rethinking.   It doesn't test against
 
3611
           a signal name, and it just kind of bulls into doing something
 
3612
           that may or may not be appropriate. */
 
3613
 
 
3614
        if (interfaces) {
 
3615
                interface_reference (&interface -> next, interfaces, MDL);
 
3616
                interface_dereference (&interfaces, MDL);
 
3617
        }
 
3618
        interface_reference (&interfaces, interface, MDL);
 
3619
 
 
3620
        discover_interfaces (DISCOVER_UNCONFIGURED);
 
3621
 
 
3622
        for (ip = interfaces; ip; ip = ip -> next) {
 
3623
                /* If interfaces were specified, don't configure
 
3624
                   interfaces that weren't specified! */
 
3625
                if (ip -> flags & INTERFACE_RUNNING ||
 
3626
                   (ip -> flags & (INTERFACE_REQUESTED |
 
3627
                                     INTERFACE_AUTOMATIC)) !=
 
3628
                     INTERFACE_REQUESTED)
 
3629
                        continue;
 
3630
                script_init (ip -> client,
 
3631
                             "PREINIT", (struct string_list *)0);
 
3632
                if (ip -> client -> alias)
 
3633
                        script_write_params (ip -> client, "alias_",
 
3634
                                             ip -> client -> alias);
 
3635
                script_go (ip -> client);
 
3636
        }
 
3637
 
 
3638
        discover_interfaces (interfaces_requested != 0
 
3639
                             ? DISCOVER_REQUESTED
 
3640
                             : DISCOVER_RUNNING);
 
3641
 
 
3642
        for (ip = interfaces; ip; ip = ip -> next) {
 
3643
                if (ip -> flags & INTERFACE_RUNNING)
 
3644
                        continue;
 
3645
                ip -> flags |= INTERFACE_RUNNING;
 
3646
                for (client = ip->client ; client ; client = client->next) {
 
3647
                        client->state = S_INIT;
 
3648
                        state_reboot(client);
 
3649
                }
 
3650
        }
 
3651
        return ISC_R_SUCCESS;
 
3652
}
 
3653
 
 
3654
/* The client should never receive a relay agent information option,
 
3655
   so if it does, log it and discard it. */
 
3656
 
 
3657
int parse_agent_information_option (packet, len, data)
 
3658
        struct packet *packet;
 
3659
        int len;
 
3660
        u_int8_t *data;
 
3661
{
 
3662
        return 1;
 
3663
}
 
3664
 
 
3665
/* The client never sends relay agent information options. */
 
3666
 
 
3667
unsigned cons_agent_information_options (cfg_options, outpacket,
 
3668
                                         agentix, length)
 
3669
        struct option_state *cfg_options;
 
3670
        struct dhcp_packet *outpacket;
 
3671
        unsigned agentix;
 
3672
        unsigned length;
 
3673
{
 
3674
        return length;
 
3675
}
 
3676
 
 
3677
static void shutdown_exit (void *foo)
 
3678
{
 
3679
        exit (0);
 
3680
}
 
3681
 
 
3682
#if defined (NSUPDATE)
 
3683
/*
 
3684
 * If the first query fails, the updater MUST NOT delete the DNS name.  It
 
3685
 * may be that the host whose lease on the server has expired has moved
 
3686
 * to another network and obtained a lease from a different server,
 
3687
 * which has caused the client's A RR to be replaced. It may also be
 
3688
 * that some other client has been configured with a name that matches
 
3689
 * the name of the DHCP client, and the policy was that the last client
 
3690
 * to specify the name would get the name.  In this case, the DHCID RR
 
3691
 * will no longer match the updater's notion of the client-identity of
 
3692
 * the host pointed to by the DNS name.
 
3693
 *   -- "Interaction between DHCP and DNS"
 
3694
 */
 
3695
 
 
3696
/* The first and second stages are pretty similar so we combine them */
 
3697
void
 
3698
client_dns_remove_action(dhcp_ddns_cb_t *ddns_cb,
 
3699
                         isc_result_t    eresult)
 
3700
{
 
3701
 
 
3702
        isc_result_t result;
 
3703
 
 
3704
        if ((eresult == ISC_R_SUCCESS) &&
 
3705
            (ddns_cb->state == DDNS_STATE_REM_FW_YXDHCID)) {
 
3706
                /* Do the second stage of the FWD removal */
 
3707
                ddns_cb->state = DDNS_STATE_REM_FW_NXRR;
 
3708
 
 
3709
                result = ddns_modify_fwd(ddns_cb);
 
3710
                if (result == ISC_R_SUCCESS) {
 
3711
                        return;
 
3712
                }
 
3713
        }
 
3714
 
 
3715
        /* If we are done or have an error clean up */
 
3716
        ddns_cb_free(ddns_cb, MDL);
 
3717
        return;
 
3718
}
 
3719
 
 
3720
void
 
3721
client_dns_remove(struct client_state *client,
 
3722
                  struct iaddr        *addr)
 
3723
{
 
3724
        dhcp_ddns_cb_t *ddns_cb;
 
3725
        isc_result_t result;
 
3726
 
 
3727
        /* if we have an old ddns request for this client, cancel it */
 
3728
        if (client->ddns_cb != NULL) {
 
3729
                ddns_cancel(client->ddns_cb);
 
3730
                client->ddns_cb = NULL;
 
3731
        }
 
3732
        
 
3733
        ddns_cb = ddns_cb_alloc(MDL);
 
3734
        if (ddns_cb != NULL) {
 
3735
                ddns_cb->address = *addr;
 
3736
                ddns_cb->timeout = 0;
 
3737
 
 
3738
                ddns_cb->state = DDNS_STATE_REM_FW_YXDHCID;
 
3739
                ddns_cb->flags = DDNS_UPDATE_ADDR;
 
3740
                ddns_cb->cur_func = client_dns_remove_action;
 
3741
 
 
3742
                result = client_dns_update(client, ddns_cb);
 
3743
 
 
3744
                if (result != ISC_R_TIMEDOUT) {
 
3745
                        ddns_cb_free(ddns_cb, MDL);
 
3746
                }
 
3747
        }
 
3748
}
 
3749
#endif
 
3750
 
 
3751
isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
 
3752
                                     control_object_state_t newstate)
 
3753
{
 
3754
        struct interface_info *ip;
 
3755
        struct client_state *client;
 
3756
        struct timeval tv;
 
3757
 
 
3758
        /* Do the right thing for each interface. */
 
3759
        for (ip = interfaces; ip; ip = ip -> next) {
 
3760
            for (client = ip -> client; client; client = client -> next) {
 
3761
                switch (newstate) {
 
3762
                  case server_startup:
 
3763
                    return ISC_R_SUCCESS;
 
3764
 
 
3765
                  case server_running:
 
3766
                    return ISC_R_SUCCESS;
 
3767
 
 
3768
                  case server_shutdown:
 
3769
                    if (client -> active &&
 
3770
                        client -> active -> expiry > cur_time) {
 
3771
#if defined (NSUPDATE)
 
3772
                            if (client->config->do_forward_update) {
 
3773
                                    client_dns_remove(client,
 
3774
                                                      &client->active->address);
 
3775
                            }
 
3776
#endif
 
3777
                            do_release (client);
 
3778
                    }
 
3779
                    break;
 
3780
 
 
3781
                  case server_hibernate:
 
3782
                    state_stop (client);
 
3783
                    break;
 
3784
 
 
3785
                  case server_awaken:
 
3786
                    state_reboot (client);
 
3787
                    break;
 
3788
                }
 
3789
            }
 
3790
        }
 
3791
 
 
3792
        if (newstate == server_shutdown) {
 
3793
                tv.tv_sec = cur_tv.tv_sec;
 
3794
                tv.tv_usec = cur_tv.tv_usec + 1;
 
3795
                add_timeout(&tv, shutdown_exit, 0, 0, 0);
 
3796
        }
 
3797
        return ISC_R_SUCCESS;
 
3798
}
 
3799
 
 
3800
#if defined (NSUPDATE)
 
3801
/*
 
3802
 * Called after a timeout if the DNS update failed on the previous try.
 
3803
 * Starts the retry process.  If the retry times out it will schedule
 
3804
 * this routine to run again after a 10x wait.
 
3805
 */
 
3806
void
 
3807
client_dns_update_timeout (void *cp)
 
3808
{
 
3809
        dhcp_ddns_cb_t *ddns_cb = (dhcp_ddns_cb_t *)cp;
 
3810
        struct client_state *client = (struct client_state *)ddns_cb->lease;
 
3811
        isc_result_t status = ISC_R_FAILURE;
 
3812
 
 
3813
        if ((client != NULL) &&
 
3814
            ((client->active != NULL) ||
 
3815
             (client->active_lease != NULL)))
 
3816
                status = client_dns_update(client, ddns_cb);
 
3817
 
 
3818
        /*
 
3819
         * A status of timedout indicates that we started the update and
 
3820
         * have released control of the control block.  Any other status
 
3821
         * indicates that we should clean up the control block.  We either
 
3822
         * got a success which indicates that we didn't really need to
 
3823
         * send an update or some other error in which case we weren't able
 
3824
         * to start the update process.  In both cases we still own
 
3825
         * the control block and should free it.
 
3826
         */
 
3827
        if (status != ISC_R_TIMEDOUT) {
 
3828
                if (client != NULL) {
 
3829
                        client->ddns_cb = NULL;
 
3830
                }
 
3831
                ddns_cb_free(ddns_cb, MDL);
 
3832
        }
 
3833
}
 
3834
 
 
3835
/*
 
3836
 * If the first query succeeds, the updater can conclude that it
 
3837
 * has added a new name whose only RRs are the A and DHCID RR records.
 
3838
 * The A RR update is now complete (and a client updater is finished,
 
3839
 * while a server might proceed to perform a PTR RR update).
 
3840
 *   -- "Interaction between DHCP and DNS"
 
3841
 *
 
3842
 * If the second query succeeds, the updater can conclude that the current
 
3843
 * client was the last client associated with the domain name, and that
 
3844
 * the name now contains the updated A RR. The A RR update is now
 
3845
 * complete (and a client updater is finished, while a server would
 
3846
 * then proceed to perform a PTR RR update).
 
3847
 *   -- "Interaction between DHCP and DNS"
 
3848
 *
 
3849
 * If the second query fails with NXRRSET, the updater must conclude
 
3850
 * that the client's desired name is in use by another host.  At this
 
3851
 * juncture, the updater can decide (based on some administrative
 
3852
 * configuration outside of the scope of this document) whether to let
 
3853
 * the existing owner of the name keep that name, and to (possibly)
 
3854
 * perform some name disambiguation operation on behalf of the current
 
3855
 * client, or to replace the RRs on the name with RRs that represent
 
3856
 * the current client. If the configured policy allows replacement of
 
3857
 * existing records, the updater submits a query that deletes the
 
3858
 * existing A RR and the existing DHCID RR, adding A and DHCID RRs that
 
3859
 * represent the IP address and client-identity of the new client.
 
3860
 *   -- "Interaction between DHCP and DNS"
 
3861
 */
 
3862
 
 
3863
/* The first and second stages are pretty similar so we combine them */
 
3864
void
 
3865
client_dns_update_action(dhcp_ddns_cb_t *ddns_cb,
 
3866
                         isc_result_t    eresult)
 
3867
{
 
3868
        isc_result_t result;
 
3869
        struct timeval tv;
 
3870
 
 
3871
        switch(eresult) {
 
3872
        case ISC_R_SUCCESS:
 
3873
        default:
 
3874
                /* Either we succeeded or broke in a bad way, clean up */
 
3875
                break;
 
3876
 
 
3877
        case DNS_R_YXRRSET:
 
3878
                /*
 
3879
                 * This is the only difference between the two stages,
 
3880
                 * check to see if it is the first stage, in which case
 
3881
                 * start the second stage
 
3882
                 */
 
3883
                if (ddns_cb->state == DDNS_STATE_ADD_FW_NXDOMAIN) {
 
3884
                        ddns_cb->state = DDNS_STATE_ADD_FW_YXDHCID;
 
3885
                        ddns_cb->cur_func = client_dns_update_action;
 
3886
 
 
3887
                        result = ddns_modify_fwd(ddns_cb);
 
3888
                        if (result == ISC_R_SUCCESS) {
 
3889
                                return;
 
3890
                        }
 
3891
                }
 
3892
                break;
 
3893
 
 
3894
        case ISC_R_TIMEDOUT:
 
3895
                /*
 
3896
                 * We got a timeout response from the DNS module.  Schedule
 
3897
                 * another attempt for later.  We forget the name, dhcid and
 
3898
                 * zone so if it gets changed we will get the new information.
 
3899
                 */
 
3900
                data_string_forget(&ddns_cb->fwd_name, MDL);
 
3901
                data_string_forget(&ddns_cb->dhcid, MDL);
 
3902
                if (ddns_cb->zone != NULL) {
 
3903
                        forget_zone((struct dns_zone **)&ddns_cb->zone);
 
3904
                }
 
3905
 
 
3906
                /* Reset to doing the first stage */
 
3907
                ddns_cb->state    = DDNS_STATE_ADD_FW_NXDOMAIN;
 
3908
                ddns_cb->cur_func = client_dns_update_action;
 
3909
 
 
3910
                /* and update our timer */
 
3911
                if (ddns_cb->timeout < 3600)
 
3912
                        ddns_cb->timeout *= 10;
 
3913
                tv.tv_sec = cur_tv.tv_sec + ddns_cb->timeout;
 
3914
                tv.tv_usec = cur_tv.tv_usec;
 
3915
                add_timeout(&tv, client_dns_update_timeout,
 
3916
                            ddns_cb, NULL, NULL);
 
3917
                return;
 
3918
        }
 
3919
 
 
3920
        ddns_cb_free(ddns_cb, MDL);
 
3921
        return;
 
3922
}
 
3923
 
 
3924
/* See if we should do a DNS update, and if so, do it. */
 
3925
 
 
3926
isc_result_t
 
3927
client_dns_update(struct client_state *client, dhcp_ddns_cb_t *ddns_cb)
 
3928
{
 
3929
        struct data_string client_identifier;
 
3930
        struct option_cache *oc;
 
3931
        int ignorep;
 
3932
        int result;
 
3933
        isc_result_t rcode;
 
3934
 
 
3935
        /* If we didn't send an FQDN option, we certainly aren't going to
 
3936
           be doing an update. */
 
3937
        if (!client -> sent_options)
 
3938
                return ISC_R_SUCCESS;
 
3939
 
 
3940
        /* If we don't have a lease, we can't do an update. */
 
3941
        if ((client->active == NULL) && (client->active_lease == NULL))
 
3942
                return ISC_R_SUCCESS;
 
3943
 
 
3944
        /* If we set the no client update flag, don't do the update. */
 
3945
        if ((oc = lookup_option (&fqdn_universe, client -> sent_options,
 
3946
                                  FQDN_NO_CLIENT_UPDATE)) &&
 
3947
            evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
 
3948
                                           (struct lease *)0, client,
 
3949
                                           client -> sent_options,
 
3950
                                           (struct option_state *)0,
 
3951
                                           &global_scope, oc, MDL))
 
3952
                return ISC_R_SUCCESS;
 
3953
 
 
3954
        /* If we set the "server, please update" flag, or didn't set it
 
3955
           to false, don't do the update. */
 
3956
        if (!(oc = lookup_option (&fqdn_universe, client -> sent_options,
 
3957
                                  FQDN_SERVER_UPDATE)) ||
 
3958
            evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
 
3959
                                           (struct lease *)0, client,
 
3960
                                           client -> sent_options,
 
3961
                                           (struct option_state *)0,
 
3962
                                           &global_scope, oc, MDL))
 
3963
                return ISC_R_SUCCESS;
 
3964
 
 
3965
        /* If no FQDN option was supplied, don't do the update. */
 
3966
        if (!(oc = lookup_option (&fqdn_universe, client -> sent_options,
 
3967
                                  FQDN_FQDN)) ||
 
3968
            !evaluate_option_cache (&ddns_cb->fwd_name, (struct packet *)0,
 
3969
                                    (struct lease *)0, client,
 
3970
                                    client -> sent_options,
 
3971
                                    (struct option_state *)0,
 
3972
                                    &global_scope, oc, MDL))
 
3973
                return ISC_R_SUCCESS;
 
3974
 
 
3975
        /* If this is a DHCPv6 client update, make a dhcid string out of
 
3976
         * the DUID.  If this is a DHCPv4 client update, choose either
 
3977
         * the client identifier, if there is one, or the interface's
 
3978
         * MAC address.
 
3979
         */
 
3980
        result = 0;
 
3981
        memset(&client_identifier, 0, sizeof(client_identifier));
 
3982
        if (client->active_lease != NULL) {
 
3983
                if (((oc =
 
3984
                      lookup_option(&dhcpv6_universe, client->sent_options,
 
3985
                                    D6O_CLIENTID)) != NULL) &&
 
3986
                    evaluate_option_cache(&client_identifier, NULL, NULL,
 
3987
                                          client, client->sent_options, NULL,
 
3988
                                          &global_scope, oc, MDL)) {
 
3989
                        /* RFC4701 defines type '2' as being for the DUID
 
3990
                         * field.  We aren't using RFC4701 DHCID RR's yet,
 
3991
                         * but this is as good a value as any.
 
3992
                         */
 
3993
                        result = get_dhcid(&ddns_cb->dhcid, 2,
 
3994
                                           client_identifier.data,
 
3995
                                           client_identifier.len);
 
3996
                        data_string_forget(&client_identifier, MDL);
 
3997
                } else
 
3998
                        log_fatal("Impossible condition at %s:%d.", MDL);
 
3999
        } else {
 
4000
                if (((oc =
 
4001
                      lookup_option(&dhcp_universe, client->sent_options,
 
4002
                                    DHO_DHCP_CLIENT_IDENTIFIER)) != NULL) &&
 
4003
                    evaluate_option_cache(&client_identifier, NULL, NULL,
 
4004
                                          client, client->sent_options, NULL,
 
4005
                                          &global_scope, oc, MDL)) {
 
4006
                        result = get_dhcid(&ddns_cb->dhcid,
 
4007
                                           DHO_DHCP_CLIENT_IDENTIFIER,
 
4008
                                           client_identifier.data,
 
4009
                                           client_identifier.len);
 
4010
                        data_string_forget(&client_identifier, MDL);
 
4011
                } else
 
4012
                        result = get_dhcid(&ddns_cb->dhcid, 0,
 
4013
                                           client->interface->hw_address.hbuf,
 
4014
                                           client->interface->hw_address.hlen);
 
4015
        }
 
4016
        if (!result) {
 
4017
                return ISC_R_SUCCESS;
 
4018
        }
 
4019
 
 
4020
        /*
 
4021
         * Perform updates.
 
4022
         */
 
4023
        if (ddns_cb->fwd_name.len && ddns_cb->dhcid.len) {
 
4024
                rcode = ddns_modify_fwd(ddns_cb);
 
4025
        } else
 
4026
                rcode = ISC_R_FAILURE;
 
4027
 
 
4028
        /*
 
4029
         * A success from the modify routine means we are performing
 
4030
         * async processing, for which we use the timedout error message.
 
4031
         */
 
4032
        if (rcode == ISC_R_SUCCESS) {
 
4033
                rcode = ISC_R_TIMEDOUT;
 
4034
        }
 
4035
 
 
4036
        return rcode;
 
4037
}
 
4038
 
 
4039
 
 
4040
/*
 
4041
 * Schedule the first update.  They will continue to retry occasionally
 
4042
 * until they no longer time out (or fail).
 
4043
 */
 
4044
void
 
4045
dhclient_schedule_updates(struct client_state *client,
 
4046
                          struct iaddr        *addr,
 
4047
                          int                  offset)
 
4048
{
 
4049
        dhcp_ddns_cb_t *ddns_cb;
 
4050
        struct timeval tv;
 
4051
 
 
4052
        if (!client->config->do_forward_update)
 
4053
                return;
 
4054
 
 
4055
        /* cancel any outstanding ddns requests */
 
4056
        if (client->ddns_cb != NULL) {
 
4057
                ddns_cancel(client->ddns_cb);
 
4058
                client->ddns_cb = NULL;
 
4059
        }
 
4060
 
 
4061
        ddns_cb = ddns_cb_alloc(MDL);
 
4062
 
 
4063
        if (ddns_cb != NULL) {
 
4064
                ddns_cb->lease = (void *)client;
 
4065
                ddns_cb->address = *addr;
 
4066
                ddns_cb->timeout = 1;
 
4067
 
 
4068
                /*
 
4069
                 * XXX: DNS TTL is a problem we need to solve properly.
 
4070
                 * Until that time, 300 is a placeholder default for
 
4071
                 * something that is less insane than a value scaled
 
4072
                 * by lease timeout.
 
4073
                 */
 
4074
                ddns_cb->ttl = 300;
 
4075
 
 
4076
                ddns_cb->state = DDNS_STATE_ADD_FW_NXDOMAIN;
 
4077
                ddns_cb->cur_func = client_dns_update_action;
 
4078
                ddns_cb->flags = DDNS_UPDATE_ADDR | DDNS_INCLUDE_RRSET;
 
4079
 
 
4080
                client->ddns_cb = ddns_cb;
 
4081
 
 
4082
                tv.tv_sec = cur_tv.tv_sec + offset;
 
4083
                tv.tv_usec = cur_tv.tv_usec;
 
4084
                add_timeout(&tv, client_dns_update_timeout,
 
4085
                            ddns_cb, NULL, NULL);
 
4086
        } else {
 
4087
                log_error("Unable to allocate dns update state for %s",
 
4088
                          piaddr(*addr));
 
4089
        }
 
4090
}
 
4091
#endif
 
4092
 
 
4093
void
 
4094
dhcpv4_client_assignments(void)
 
4095
{
 
4096
        struct servent *ent;
 
4097
 
 
4098
        if (path_dhclient_pid == NULL)
 
4099
                path_dhclient_pid = _PATH_DHCLIENT_PID;
 
4100
        if (path_dhclient_db == NULL)
 
4101
                path_dhclient_db = _PATH_DHCLIENT_DB;
 
4102
 
 
4103
        /* Default to the DHCP/BOOTP port. */
 
4104
        if (!local_port) {
 
4105
                /* If we're faking a relay agent, and we're not using loopback,
 
4106
                   use the server port, not the client port. */
 
4107
                if (mockup_relay && giaddr.s_addr != htonl (INADDR_LOOPBACK)) {
 
4108
                        local_port = htons(67);
 
4109
                } else {
 
4110
                        ent = getservbyname ("dhcpc", "udp");
 
4111
                        if (!ent)
 
4112
                                local_port = htons (68);
 
4113
                        else
 
4114
                                local_port = ent -> s_port;
 
4115
#ifndef __CYGWIN32__
 
4116
                        endservent ();
 
4117
#endif
 
4118
                }
 
4119
        }
 
4120
 
 
4121
        /* If we're faking a relay agent, and we're not using loopback,
 
4122
           we're using the server port, not the client port. */
 
4123
        if (mockup_relay && giaddr.s_addr != htonl (INADDR_LOOPBACK)) {
 
4124
                remote_port = local_port;
 
4125
        } else
 
4126
                remote_port = htons (ntohs (local_port) - 1);   /* XXX */
 
4127
}
 
4128
 
 
4129
/*
 
4130
 * The following routines are used to check that certain
 
4131
 * strings are reasonable before we pass them to the scripts.
 
4132
 * This avoids some problems with scripts treating the strings
 
4133
 * as commands - see ticket 23722
 
4134
 * The domain checking code should be done as part of assembling
 
4135
 * the string but we are doing it here for now due to time
 
4136
 * constraints.
 
4137
 */
 
4138
 
 
4139
static int check_domain_name(const char *ptr, size_t len, int dots)
 
4140
{
 
4141
        const char *p;
 
4142
 
 
4143
        /* not empty or complete length not over 255 characters   */
 
4144
        if ((len == 0) || (len > 256))
 
4145
                return(-1);
 
4146
 
 
4147
        /* consists of [[:alnum:]-]+ labels separated by [.]      */
 
4148
        /* a [_] is against RFC but seems to be "widely used"...  */
 
4149
        for (p=ptr; (*p != 0) && (len-- > 0); p++) {
 
4150
                if ((*p == '-') || (*p == '_')) {
 
4151
                        /* not allowed at begin or end of a label */
 
4152
                        if (((p - ptr) == 0) || (len == 0) || (p[1] == '.'))
 
4153
                                return(-1);
 
4154
                } else if (*p == '.') {
 
4155
                        /* each label has to be 1-63 characters;
 
4156
                           we allow [.] at the end ('foo.bar.')   */
 
4157
                        size_t d = p - ptr;
 
4158
                        if ((d <= 0) || (d >= 64))
 
4159
                                return(-1);
 
4160
                        ptr = p + 1; /* jump to the next label    */
 
4161
                        if ((dots > 0) && (len > 0))
 
4162
                                dots--;
 
4163
                } else if (isalnum((unsigned char)*p) == 0) {
 
4164
                        /* also numbers at the begin are fine     */
 
4165
                        return(-1);
 
4166
                }
 
4167
        }
 
4168
        return(dots ? -1 : 0);
 
4169
}
 
4170
 
 
4171
static int check_domain_name_list(const char *ptr, size_t len, int dots)
 
4172
{
 
4173
        const char *p;
 
4174
        int ret = -1; /* at least one needed */
 
4175
 
 
4176
        if ((ptr == NULL) || (len == 0))
 
4177
                return(-1);
 
4178
 
 
4179
        for (p=ptr; (*p != 0) && (len > 0); p++, len--) {
 
4180
                if (*p != ' ')
 
4181
                        continue;
 
4182
                if (p > ptr) {
 
4183
                        if (check_domain_name(ptr, p - ptr, dots) != 0)
 
4184
                                return(-1);
 
4185
                        ret = 0;
 
4186
                }
 
4187
                ptr = p + 1;
 
4188
        }
 
4189
        if (p > ptr)
 
4190
                return(check_domain_name(ptr, p - ptr, dots));
 
4191
        else
 
4192
                return(ret);
 
4193
}
 
4194
 
 
4195
static int check_option_values(struct universe *universe,
 
4196
                               unsigned int opt,
 
4197
                               const char *ptr,
 
4198
                               size_t len)
 
4199
{
 
4200
        if (ptr == NULL)
 
4201
                return(-1);
 
4202
 
 
4203
        /* just reject options we want to protect, will be escaped anyway */
 
4204
        if ((universe == NULL) || (universe == &dhcp_universe)) {
 
4205
                switch(opt) {
 
4206
                      case DHO_DOMAIN_NAME:
 
4207
#ifdef ACCEPT_LIST_IN_DOMAIN_NAME
 
4208
                              return check_domain_name_list(ptr, len, 0);
 
4209
#else
 
4210
                              return check_domain_name(ptr, len, 0);
 
4211
#endif
 
4212
                      case DHO_HOST_NAME:
 
4213
                      case DHO_NIS_DOMAIN:
 
4214
                      case DHO_NETBIOS_SCOPE:
 
4215
                        return check_domain_name(ptr, len, 0);
 
4216
                        break;
 
4217
                      case DHO_DOMAIN_SEARCH:
 
4218
                        return check_domain_name_list(ptr, len, 0);
 
4219
                        break;
 
4220
                      case DHO_ROOT_PATH:
 
4221
                        if (len == 0)
 
4222
                                return(-1);
 
4223
                        for (; (*ptr != 0) && (len-- > 0); ptr++) {
 
4224
                                if(!(isalnum((unsigned char)*ptr) ||
 
4225
                                     *ptr == '#'  || *ptr == '%' ||
 
4226
                                     *ptr == '+'  || *ptr == '-' ||
 
4227
                                     *ptr == '_'  || *ptr == ':' ||
 
4228
                                     *ptr == '.'  || *ptr == ',' ||
 
4229
                                     *ptr == '@'  || *ptr == '~' ||
 
4230
                                     *ptr == '\\' || *ptr == '/' ||
 
4231
                                     *ptr == '['  || *ptr == ']' ||
 
4232
                                     *ptr == '='  || *ptr == ' '))
 
4233
                                        return(-1);
 
4234
                        }
 
4235
                        return(0);
 
4236
                        break;
 
4237
                }
 
4238
        }
 
4239
 
 
4240
#ifdef DHCPv6
 
4241
        if (universe == &dhcpv6_universe) {
 
4242
                switch(opt) {
 
4243
                      case D6O_SIP_SERVERS_DNS:
 
4244
                      case D6O_DOMAIN_SEARCH:
 
4245
                      case D6O_NIS_DOMAIN_NAME:
 
4246
                      case D6O_NISP_DOMAIN_NAME:
 
4247
                        return check_domain_name_list(ptr, len, 0);
 
4248
                        break;
 
4249
                }
 
4250
        }
 
4251
#endif
 
4252
 
 
4253
        return(0);
 
4254
}
 
4255
 
 
4256
static void
 
4257
add_reject(struct packet *packet) {
 
4258
        struct iaddrmatchlist *list;
 
4259
        
 
4260
        list = dmalloc(sizeof(struct iaddrmatchlist), MDL);
 
4261
        if (!list)
 
4262
                log_fatal ("no memory for reject list!");
 
4263
 
 
4264
        /*
 
4265
         * client_addr is misleading - it is set to source address in common
 
4266
         * code.
 
4267
         */
 
4268
        list->match.addr = packet->client_addr;
 
4269
        /* Set mask to indicate host address. */
 
4270
        list->match.mask.len = list->match.addr.len;
 
4271
        memset(list->match.mask.iabuf, 0xff, sizeof(list->match.mask.iabuf));
 
4272
 
 
4273
        /* Append to reject list for the source interface. */
 
4274
        list->next = packet->interface->client->config->reject_list;
 
4275
        packet->interface->client->config->reject_list = list;
 
4276
 
 
4277
        /*
 
4278
         * We should inform user that we won't be accepting this server
 
4279
         * anymore.
 
4280
         */
 
4281
        log_info("Server added to list of rejected servers.");
 
4282
}