Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sbin/dhclient/dhclient.c
39481 views
1
/* $OpenBSD: dhclient.c,v 1.63 2005/02/06 17:10:13 krw Exp $ */
2
3
/*-
4
* SPDX-License-Identifier: BSD-3-Clause
5
*
6
* Copyright 2004 Henning Brauer <[email protected]>
7
* Copyright (c) 1995, 1996, 1997, 1998, 1999
8
* The Internet Software Consortium. All rights reserved.
9
*
10
* Redistribution and use in source and binary forms, with or without
11
* modification, are permitted provided that the following conditions
12
* are met:
13
*
14
* 1. Redistributions of source code must retain the above copyright
15
* notice, this list of conditions and the following disclaimer.
16
* 2. Redistributions in binary form must reproduce the above copyright
17
* notice, this list of conditions and the following disclaimer in the
18
* documentation and/or other materials provided with the distribution.
19
* 3. Neither the name of The Internet Software Consortium nor the names
20
* of its contributors may be used to endorse or promote products derived
21
* from this software without specific prior written permission.
22
*
23
* THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
24
* CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
25
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27
* DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
28
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
31
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
32
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
34
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35
* SUCH DAMAGE.
36
*
37
* This software has been written for the Internet Software Consortium
38
* by Ted Lemon <[email protected]> in cooperation with Vixie
39
* Enterprises. To learn more about the Internet Software Consortium,
40
* see ``http://www.vix.com/isc''. To learn more about Vixie
41
* Enterprises, see ``http://www.vix.com''.
42
*
43
* This client was substantially modified and enhanced by Elliot Poger
44
* for use on Linux while he was working on the MosquitoNet project at
45
* Stanford.
46
*
47
* The current version owes much to Elliot's Linux enhancements, but
48
* was substantially reorganized and partially rewritten by Ted Lemon
49
* so as to use the same networking framework that the Internet Software
50
* Consortium DHCP server uses. Much system-specific configuration code
51
* was moved into a shell script so that as support for more operating
52
* systems is added, it will not be necessary to port and maintain
53
* system-specific configuration code to these operating systems - instead,
54
* the shell script can invoke the native tools to accomplish the same
55
* purpose.
56
*/
57
58
#include <sys/cdefs.h>
59
#include "dhcpd.h"
60
#include "privsep.h"
61
62
#include <sys/capsicum.h>
63
#include <sys/endian.h>
64
65
#include <capsicum_helpers.h>
66
#include <libgen.h>
67
68
#include <net80211/ieee80211_freebsd.h>
69
70
71
#ifndef _PATH_VAREMPTY
72
#define _PATH_VAREMPTY "/var/empty"
73
#endif
74
75
#define PERIOD 0x2e
76
#define hyphenchar(c) ((c) == 0x2d)
77
#define bslashchar(c) ((c) == 0x5c)
78
#define periodchar(c) ((c) == PERIOD)
79
#define asterchar(c) ((c) == 0x2a)
80
#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) || \
81
((c) >= 0x61 && (c) <= 0x7a))
82
#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
83
#define whitechar(c) ((c) == ' ' || (c) == '\t')
84
85
#define borderchar(c) (alphachar(c) || digitchar(c))
86
#define middlechar(c) (borderchar(c) || hyphenchar(c))
87
#define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
88
89
#define CLIENT_PATH "PATH=/usr/bin:/usr/sbin:/bin:/sbin"
90
91
cap_channel_t *capsyslog;
92
93
time_t cur_time; /* Seconds since epoch. */
94
struct timespec time_now; /* CLOCK_MONOTONIC. */
95
static time_t default_lease_time = 43200; /* 12 hours... */
96
97
const char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
98
char *path_dhclient_db = NULL;
99
100
int log_perror = 1;
101
static int privfd;
102
static int nullfd = -1;
103
104
static char hostname[_POSIX_HOST_NAME_MAX + 1];
105
106
static struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
107
static struct in_addr inaddr_any, inaddr_broadcast;
108
109
static char *path_dhclient_pidfile;
110
struct pidfh *pidfile;
111
112
/*
113
* ASSERT_STATE() does nothing now; it used to be
114
* assert (state_is == state_shouldbe).
115
*/
116
#define ASSERT_STATE(state_is, state_shouldbe) {}
117
118
/*
119
* We need to check that the expiry, renewal and rebind times are not beyond
120
* the end of time (~2038 when a 32-bit time_t is being used).
121
*/
122
#define TIME_MAX ((((time_t) 1 << (sizeof(time_t) * CHAR_BIT - 2)) - 1) * 2 + 1)
123
124
static struct timespec arp_timeout = { .tv_sec = 0, .tv_nsec = 250 * 1000 * 1000 };
125
static const struct timespec zero_timespec = { .tv_sec = 0, .tv_nsec = 0 };
126
int log_priority;
127
static int no_daemon;
128
static int unknown_ok = 1;
129
static int routefd;
130
131
struct interface_info *ifi;
132
133
int findproto(char *, int);
134
struct sockaddr *get_ifa(char *, int);
135
void routehandler(struct protocol *);
136
void usage(void);
137
int check_option(struct client_lease *l, int option);
138
int check_classless_option(unsigned char *data, int len);
139
int ipv4addrs(const char * buf);
140
int res_hnok(const char *dn);
141
int check_search(const char *srch);
142
const char *option_as_string(unsigned int code, unsigned char *data, int len);
143
int fork_privchld(int, int);
144
145
#define ROUNDUP(a) \
146
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
147
#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
148
149
/* Minimum MTU is 68 as per RFC791, p. 24 */
150
#define MIN_MTU 68
151
152
static time_t scripttime;
153
154
int
155
findproto(char *cp, int n)
156
{
157
struct sockaddr *sa;
158
unsigned i;
159
160
if (n == 0)
161
return -1;
162
for (i = 1; i; i <<= 1) {
163
if (i & n) {
164
sa = (struct sockaddr *)cp;
165
switch (i) {
166
case RTA_IFA:
167
case RTA_DST:
168
case RTA_GATEWAY:
169
case RTA_NETMASK:
170
if (sa->sa_family == AF_INET)
171
return AF_INET;
172
if (sa->sa_family == AF_INET6)
173
return AF_INET6;
174
break;
175
case RTA_IFP:
176
break;
177
}
178
ADVANCE(cp, sa);
179
}
180
}
181
return (-1);
182
}
183
184
struct sockaddr *
185
get_ifa(char *cp, int n)
186
{
187
struct sockaddr *sa;
188
unsigned i;
189
190
if (n == 0)
191
return (NULL);
192
for (i = 1; i; i <<= 1)
193
if (i & n) {
194
sa = (struct sockaddr *)cp;
195
if (i == RTA_IFA)
196
return (sa);
197
ADVANCE(cp, sa);
198
}
199
200
return (NULL);
201
}
202
203
static struct iaddr defaddr = { .len = 4 };
204
static uint8_t curbssid[6];
205
206
static void
207
disassoc(void *arg)
208
{
209
struct interface_info *_ifi = arg;
210
211
/*
212
* Clear existing state.
213
*/
214
if (_ifi->client->active != NULL) {
215
script_init("EXPIRE", NULL);
216
script_write_params("old_",
217
_ifi->client->active);
218
if (_ifi->client->alias)
219
script_write_params("alias_",
220
_ifi->client->alias);
221
script_go();
222
}
223
_ifi->client->state = S_INIT;
224
}
225
226
void
227
routehandler(struct protocol *p __unused)
228
{
229
char msg[2048], *addr;
230
struct rt_msghdr *rtm;
231
struct if_msghdr *ifm;
232
struct ifa_msghdr *ifam;
233
struct if_announcemsghdr *ifan;
234
struct ieee80211_join_event *jev;
235
struct client_lease *l;
236
time_t t = time(NULL);
237
struct sockaddr_in *sa;
238
struct iaddr a;
239
ssize_t n;
240
int linkstat;
241
242
n = read(routefd, &msg, sizeof(msg));
243
rtm = (struct rt_msghdr *)msg;
244
if (n < (ssize_t)sizeof(rtm->rtm_msglen) ||
245
n < (ssize_t)rtm->rtm_msglen ||
246
rtm->rtm_version != RTM_VERSION)
247
return;
248
249
switch (rtm->rtm_type) {
250
case RTM_NEWADDR:
251
case RTM_DELADDR:
252
ifam = (struct ifa_msghdr *)rtm;
253
254
if (ifam->ifam_index != ifi->index)
255
break;
256
if (findproto((char *)(ifam + 1), ifam->ifam_addrs) != AF_INET)
257
break;
258
if (scripttime == 0 || t < scripttime + 10)
259
break;
260
261
sa = (struct sockaddr_in*)get_ifa((char *)(ifam + 1), ifam->ifam_addrs);
262
if (sa == NULL)
263
break;
264
265
if ((a.len = sizeof(struct in_addr)) > sizeof(a.iabuf))
266
error("king bula sez: len mismatch");
267
memcpy(a.iabuf, &sa->sin_addr, a.len);
268
if (addr_eq(a, defaddr))
269
break;
270
271
for (l = ifi->client->active; l != NULL; l = l->next)
272
if (addr_eq(a, l->address))
273
break;
274
275
if (l == NULL) /* added/deleted addr is not the one we set */
276
break;
277
278
addr = inet_ntoa(sa->sin_addr);
279
if (rtm->rtm_type == RTM_NEWADDR) {
280
/*
281
* XXX: If someone other than us adds our address,
282
* should we assume they are taking over from us,
283
* delete the lease record, and exit without modifying
284
* the interface?
285
*/
286
warning("My address (%s) was re-added", addr);
287
} else {
288
warning("My address (%s) was deleted, dhclient exiting",
289
addr);
290
goto die;
291
}
292
break;
293
case RTM_IFINFO:
294
ifm = (struct if_msghdr *)rtm;
295
if (ifm->ifm_index != ifi->index)
296
break;
297
if ((rtm->rtm_flags & RTF_UP) == 0) {
298
warning("Interface %s is down, dhclient exiting",
299
ifi->name);
300
goto die;
301
}
302
linkstat = interface_link_status(ifi->name);
303
if (linkstat != ifi->linkstat) {
304
debug("%s link state %s -> %s", ifi->name,
305
ifi->linkstat ? "up" : "down",
306
linkstat ? "up" : "down");
307
ifi->linkstat = linkstat;
308
if (linkstat)
309
state_reboot(ifi);
310
}
311
break;
312
case RTM_IFANNOUNCE:
313
ifan = (struct if_announcemsghdr *)rtm;
314
if (ifan->ifan_what == IFAN_DEPARTURE &&
315
ifan->ifan_index == ifi->index) {
316
warning("Interface %s is gone, dhclient exiting",
317
ifi->name);
318
goto die;
319
}
320
break;
321
case RTM_IEEE80211:
322
ifan = (struct if_announcemsghdr *)rtm;
323
if (ifan->ifan_index != ifi->index)
324
break;
325
switch (ifan->ifan_what) {
326
case RTM_IEEE80211_ASSOC:
327
case RTM_IEEE80211_REASSOC:
328
/*
329
* Use assoc/reassoc event to kick state machine
330
* in case we roam. Otherwise fall back to the
331
* normal state machine just like a wired network.
332
*/
333
jev = (struct ieee80211_join_event *) &ifan[1];
334
if (memcmp(curbssid, jev->iev_addr, 6)) {
335
disassoc(ifi);
336
state_reboot(ifi);
337
}
338
memcpy(curbssid, jev->iev_addr, 6);
339
break;
340
}
341
break;
342
default:
343
break;
344
}
345
return;
346
347
die:
348
script_init("FAIL", NULL);
349
if (ifi->client->alias)
350
script_write_params("alias_", ifi->client->alias);
351
script_go();
352
if (pidfile != NULL)
353
pidfile_remove(pidfile);
354
exit(1);
355
}
356
357
static void
358
init_casper(void)
359
{
360
cap_channel_t *casper;
361
362
casper = cap_init();
363
if (casper == NULL)
364
error("unable to start casper");
365
366
capsyslog = cap_service_open(casper, "system.syslog");
367
cap_close(casper);
368
if (capsyslog == NULL)
369
error("unable to open system.syslog service");
370
}
371
372
int
373
main(int argc, char *argv[])
374
{
375
u_int capmode;
376
int ch, fd, quiet = 0, i = 0;
377
int pipe_fd[2];
378
int immediate_daemon = 0;
379
struct passwd *pw;
380
pid_t otherpid;
381
cap_rights_t rights;
382
383
init_casper();
384
385
/* Initially, log errors to stderr as well as to syslogd. */
386
cap_openlog(capsyslog, getprogname(), LOG_PID | LOG_NDELAY, DHCPD_LOG_FACILITY);
387
cap_setlogmask(capsyslog, LOG_UPTO(LOG_DEBUG));
388
389
while ((ch = getopt(argc, argv, "bc:dl:np:qu")) != -1)
390
switch (ch) {
391
case 'b':
392
immediate_daemon = 1;
393
break;
394
case 'c':
395
path_dhclient_conf = optarg;
396
break;
397
case 'd':
398
no_daemon = 1;
399
break;
400
case 'l':
401
path_dhclient_db = optarg;
402
break;
403
case 'n':
404
arp_timeout = zero_timespec;
405
break;
406
case 'p':
407
path_dhclient_pidfile = optarg;
408
break;
409
case 'q':
410
quiet = 1;
411
break;
412
case 'u':
413
unknown_ok = 0;
414
break;
415
default:
416
usage();
417
}
418
419
argc -= optind;
420
argv += optind;
421
422
if (argc != 1)
423
usage();
424
425
if (path_dhclient_pidfile == NULL) {
426
asprintf(&path_dhclient_pidfile,
427
"%s/dhclient/dhclient.%s.pid", _PATH_VARRUN, *argv);
428
if (path_dhclient_pidfile == NULL)
429
error("asprintf");
430
}
431
pidfile = pidfile_open(path_dhclient_pidfile, 0644, &otherpid);
432
if (pidfile == NULL) {
433
if (errno == EEXIST)
434
error("dhclient already running, pid: %d.", otherpid);
435
if (errno == EAGAIN)
436
error("dhclient already running.");
437
warning("Cannot open or create pidfile: %m");
438
}
439
440
if ((ifi = calloc(1, sizeof(struct interface_info))) == NULL)
441
error("calloc");
442
if (strlcpy(ifi->name, argv[0], IFNAMSIZ) >= IFNAMSIZ)
443
error("Interface name too long");
444
if (path_dhclient_db == NULL && asprintf(&path_dhclient_db, "%s.%s",
445
_PATH_DHCLIENT_DB, ifi->name) == -1)
446
error("asprintf");
447
448
if (quiet)
449
log_perror = 0;
450
451
tzset();
452
clock_gettime(CLOCK_MONOTONIC, &time_now);
453
cur_time = time(NULL);
454
455
inaddr_broadcast.s_addr = INADDR_BROADCAST;
456
inaddr_any.s_addr = INADDR_ANY;
457
458
read_client_conf();
459
460
/* The next bit is potentially very time-consuming, so write out
461
the pidfile right away. We will write it out again with the
462
correct pid after daemonizing. */
463
if (pidfile != NULL)
464
pidfile_write(pidfile);
465
466
if (!interface_link_status(ifi->name)) {
467
fprintf(stderr, "%s: no link ...", ifi->name);
468
fflush(stderr);
469
sleep(1);
470
while (!interface_link_status(ifi->name)) {
471
fprintf(stderr, ".");
472
fflush(stderr);
473
if (++i > 10) {
474
fprintf(stderr, " giving up\n");
475
exit(1);
476
}
477
sleep(1);
478
}
479
fprintf(stderr, " got link\n");
480
}
481
ifi->linkstat = 1;
482
483
if ((nullfd = open(_PATH_DEVNULL, O_RDWR, 0)) == -1)
484
error("cannot open %s: %m", _PATH_DEVNULL);
485
486
if ((pw = getpwnam("_dhcp")) == NULL) {
487
warning("no such user: _dhcp, falling back to \"nobody\"");
488
if ((pw = getpwnam("nobody")) == NULL)
489
error("no such user: nobody");
490
}
491
492
/*
493
* Obtain hostname before entering capability mode - it won't be
494
* possible then, as reading kern.hostname is not permitted.
495
*/
496
if (gethostname(hostname, sizeof(hostname)) < 0)
497
hostname[0] = '\0';
498
499
priv_script_init("PREINIT", NULL);
500
if (ifi->client->alias)
501
priv_script_write_params("alias_", ifi->client->alias);
502
priv_script_go();
503
504
/* set up the interface */
505
discover_interfaces(ifi);
506
507
if (pipe(pipe_fd) == -1)
508
error("pipe");
509
510
fork_privchld(pipe_fd[0], pipe_fd[1]);
511
512
close(ifi->ufdesc);
513
ifi->ufdesc = -1;
514
close(ifi->wfdesc);
515
ifi->wfdesc = -1;
516
517
close(pipe_fd[0]);
518
privfd = pipe_fd[1];
519
cap_rights_init(&rights, CAP_READ, CAP_WRITE);
520
if (caph_rights_limit(privfd, &rights) < 0)
521
error("can't limit private descriptor: %m");
522
523
if ((fd = open(path_dhclient_db, O_RDONLY|O_EXLOCK|O_CREAT, 0)) == -1)
524
error("can't open and lock %s: %m", path_dhclient_db);
525
read_client_leases();
526
rewrite_client_leases();
527
close(fd);
528
529
if ((routefd = socket(PF_ROUTE, SOCK_RAW, 0)) != -1)
530
add_protocol("AF_ROUTE", routefd, routehandler, ifi);
531
if (shutdown(routefd, SHUT_WR) < 0)
532
error("can't shutdown route socket: %m");
533
cap_rights_init(&rights, CAP_EVENT, CAP_READ);
534
if (caph_rights_limit(routefd, &rights) < 0)
535
error("can't limit route socket: %m");
536
537
endpwent();
538
539
setproctitle("%s", ifi->name);
540
541
/* setgroups(2) is not permitted in capability mode. */
542
if (setgroups(0, NULL) != 0)
543
error("can't restrict groups: %m");
544
545
if (caph_enter_casper() < 0)
546
error("can't enter capability mode: %m");
547
548
/*
549
* If we are not in capability mode (i.e., Capsicum or libcasper is
550
* disabled), try to restrict filesystem access. This will fail if
551
* kern.chroot_allow_open_directories is 0 or the process is jailed.
552
*/
553
if (cap_getmode(&capmode) < 0 || capmode == 0) {
554
if (chroot(_PATH_VAREMPTY) == -1)
555
error("chroot");
556
if (chdir("/") == -1)
557
error("chdir(\"/\")");
558
}
559
560
if (setegid(pw->pw_gid) || setgid(pw->pw_gid) ||
561
seteuid(pw->pw_uid) || setuid(pw->pw_uid))
562
error("can't drop privileges: %m");
563
564
if (immediate_daemon)
565
go_daemon();
566
567
ifi->client->state = S_INIT;
568
state_reboot(ifi);
569
570
bootp_packet_handler = do_packet;
571
572
dispatch();
573
574
/* not reached */
575
return (0);
576
}
577
578
void
579
usage(void)
580
{
581
582
fprintf(stderr, "usage: %s [-bdnqu] ", getprogname());
583
fprintf(stderr, "[-c conffile] [-l leasefile] interface\n");
584
exit(1);
585
}
586
587
/*
588
* Individual States:
589
*
590
* Each routine is called from the dhclient_state_machine() in one of
591
* these conditions:
592
* -> entering INIT state
593
* -> recvpacket_flag == 0: timeout in this state
594
* -> otherwise: received a packet in this state
595
*
596
* Return conditions as handled by dhclient_state_machine():
597
* Returns 1, sendpacket_flag = 1: send packet, reset timer.
598
* Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
599
* Returns 0: finish the nap which was interrupted for no good reason.
600
*
601
* Several per-interface variables are used to keep track of the process:
602
* active_lease: the lease that is being used on the interface
603
* (null pointer if not configured yet).
604
* offered_leases: leases corresponding to DHCPOFFER messages that have
605
* been sent to us by DHCP servers.
606
* acked_leases: leases corresponding to DHCPACK messages that have been
607
* sent to us by DHCP servers.
608
* sendpacket: DHCP packet we're trying to send.
609
* destination: IP address to send sendpacket to
610
* In addition, there are several relevant per-lease variables.
611
* T1_expiry, T2_expiry, lease_expiry: lease milestones
612
* In the active lease, these control the process of renewing the lease;
613
* In leases on the acked_leases list, this simply determines when we
614
* can no longer legitimately use the lease.
615
*/
616
617
void
618
state_reboot(void *ipp)
619
{
620
struct interface_info *ip = ipp;
621
622
/* If we don't remember an active lease, go straight to INIT. */
623
if (!ip->client->active || ip->client->active->is_bootp) {
624
state_init(ip);
625
return;
626
}
627
628
/* We are in the rebooting state. */
629
ip->client->state = S_REBOOTING;
630
631
/* make_request doesn't initialize xid because it normally comes
632
from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
633
so pick an xid now. */
634
ip->client->xid = arc4random();
635
636
/* Make a DHCPREQUEST packet, and set appropriate per-interface
637
flags. */
638
make_request(ip, ip->client->active);
639
ip->client->destination = iaddr_broadcast;
640
ip->client->first_sending = cur_time;
641
ip->client->interval = ip->client->config->initial_interval;
642
643
/* Zap the medium list... */
644
ip->client->medium = NULL;
645
646
/* Send out the first DHCPREQUEST packet. */
647
send_request(ip);
648
}
649
650
/*
651
* Called when a lease has completely expired and we've
652
* been unable to renew it.
653
*/
654
void
655
state_init(void *ipp)
656
{
657
struct interface_info *ip = ipp;
658
659
ASSERT_STATE(state, S_INIT);
660
661
/* Make a DHCPDISCOVER packet, and set appropriate per-interface
662
flags. */
663
make_discover(ip, ip->client->active);
664
ip->client->xid = ip->client->packet.xid;
665
ip->client->destination = iaddr_broadcast;
666
ip->client->state = S_SELECTING;
667
ip->client->first_sending = cur_time;
668
ip->client->interval = ip->client->config->initial_interval;
669
670
/* Add an immediate timeout to cause the first DHCPDISCOVER packet
671
to go out. */
672
send_discover(ip);
673
}
674
675
/*
676
* state_selecting is called when one or more DHCPOFFER packets
677
* have been received and a configurable period of time has passed.
678
*/
679
void
680
state_selecting(void *ipp)
681
{
682
struct interface_info *ip = ipp;
683
struct client_lease *lp, *next, *picked;
684
685
ASSERT_STATE(state, S_SELECTING);
686
687
/* Cancel state_selecting and send_discover timeouts, since either
688
one could have got us here. */
689
cancel_timeout(state_selecting, ip);
690
cancel_timeout(send_discover, ip);
691
692
/* We have received one or more DHCPOFFER packets. Currently,
693
the only criterion by which we judge leases is whether or
694
not we get a response when we arp for them. */
695
picked = NULL;
696
for (lp = ip->client->offered_leases; lp; lp = next) {
697
next = lp->next;
698
699
/* Check to see if we got an ARPREPLY for the address
700
in this particular lease. */
701
if (!picked) {
702
script_init("ARPCHECK", lp->medium);
703
script_write_params("check_", lp);
704
705
/* If the ARPCHECK code detects another
706
machine using the offered address, it exits
707
nonzero. We need to send a DHCPDECLINE and
708
toss the lease. */
709
if (script_go()) {
710
make_decline(ip, lp);
711
send_decline(ip);
712
goto freeit;
713
}
714
picked = lp;
715
picked->next = NULL;
716
} else {
717
freeit:
718
free_client_lease(lp);
719
}
720
}
721
ip->client->offered_leases = NULL;
722
723
/* If we just tossed all the leases we were offered, go back
724
to square one. */
725
if (!picked) {
726
ip->client->state = S_INIT;
727
state_init(ip);
728
return;
729
}
730
731
/* If it was a BOOTREPLY, we can just take the address right now. */
732
if (!picked->options[DHO_DHCP_MESSAGE_TYPE].len) {
733
ip->client->new = picked;
734
735
/* Make up some lease expiry times
736
XXX these should be configurable. */
737
ip->client->new->expiry = cur_time + 12000;
738
ip->client->new->renewal += cur_time + 8000;
739
ip->client->new->rebind += cur_time + 10000;
740
741
ip->client->state = S_REQUESTING;
742
743
/* Bind to the address we received. */
744
bind_lease(ip);
745
return;
746
}
747
748
/* Go to the REQUESTING state. */
749
ip->client->destination = iaddr_broadcast;
750
ip->client->state = S_REQUESTING;
751
ip->client->first_sending = cur_time;
752
ip->client->interval = ip->client->config->initial_interval;
753
754
/* Make a DHCPREQUEST packet from the lease we picked. */
755
make_request(ip, picked);
756
ip->client->xid = ip->client->packet.xid;
757
758
/* Toss the lease we picked - we'll get it back in a DHCPACK. */
759
free_client_lease(picked);
760
761
/* Add an immediate timeout to send the first DHCPREQUEST packet. */
762
send_request(ip);
763
}
764
765
/* state_requesting is called when we receive a DHCPACK message after
766
having sent out one or more DHCPREQUEST packets. */
767
768
void
769
dhcpack(struct packet *packet)
770
{
771
struct interface_info *ip = packet->interface;
772
struct client_lease *lease;
773
774
/* If we're not receptive to an offer right now, or if the offer
775
has an unrecognizable transaction id, then just drop it. */
776
if (packet->interface->client->xid != packet->raw->xid ||
777
(packet->interface->hw_address.hlen != packet->raw->hlen) ||
778
(memcmp(packet->interface->hw_address.haddr,
779
packet->raw->chaddr, packet->raw->hlen)))
780
return;
781
782
if (ip->client->state != S_REBOOTING &&
783
ip->client->state != S_REQUESTING &&
784
ip->client->state != S_RENEWING &&
785
ip->client->state != S_REBINDING)
786
return;
787
788
note("DHCPACK from %s", piaddr(packet->client_addr));
789
790
lease = packet_to_lease(packet);
791
if (!lease) {
792
note("packet_to_lease failed.");
793
return;
794
}
795
796
ip->client->new = lease;
797
798
/* Stop resending DHCPREQUEST. */
799
cancel_timeout(send_request, ip);
800
801
/* Figure out the lease time. */
802
if (ip->client->config->default_actions[DHO_DHCP_LEASE_TIME] ==
803
ACTION_SUPERSEDE)
804
ip->client->new->expiry = getULong(
805
ip->client->config->defaults[DHO_DHCP_LEASE_TIME].data);
806
else if (ip->client->new->options[DHO_DHCP_LEASE_TIME].len >= 4)
807
ip->client->new->expiry = getULong(
808
ip->client->new->options[DHO_DHCP_LEASE_TIME].data);
809
else
810
ip->client->new->expiry = default_lease_time;
811
/* A number that looks negative here is really just very large,
812
because the lease expiry offset is unsigned. Also make sure that
813
the addition of cur_time below does not overflow (a 32 bit) time_t. */
814
if (ip->client->new->expiry < 0 ||
815
ip->client->new->expiry > TIME_MAX - cur_time)
816
ip->client->new->expiry = TIME_MAX - cur_time;
817
/* XXX should be fixed by resetting the client state */
818
if (ip->client->new->expiry < 60)
819
ip->client->new->expiry = 60;
820
821
/* Unless overridden in the config, take the server-provided renewal
822
* time if there is one. Otherwise figure it out according to the spec.
823
* Also make sure the renewal time does not exceed the expiry time.
824
*/
825
if (ip->client->config->default_actions[DHO_DHCP_RENEWAL_TIME] ==
826
ACTION_SUPERSEDE)
827
ip->client->new->renewal = getULong(
828
ip->client->config->defaults[DHO_DHCP_RENEWAL_TIME].data);
829
else if (ip->client->new->options[DHO_DHCP_RENEWAL_TIME].len >= 4)
830
ip->client->new->renewal = getULong(
831
ip->client->new->options[DHO_DHCP_RENEWAL_TIME].data);
832
else
833
ip->client->new->renewal = ip->client->new->expiry / 2;
834
if (ip->client->new->renewal < 0 ||
835
ip->client->new->renewal > ip->client->new->expiry / 2)
836
ip->client->new->renewal = ip->client->new->expiry / 2;
837
838
/* Same deal with the rebind time. */
839
if (ip->client->config->default_actions[DHO_DHCP_REBINDING_TIME] ==
840
ACTION_SUPERSEDE)
841
ip->client->new->rebind = getULong(
842
ip->client->config->defaults[DHO_DHCP_REBINDING_TIME].data);
843
else if (ip->client->new->options[DHO_DHCP_REBINDING_TIME].len >= 4)
844
ip->client->new->rebind = getULong(
845
ip->client->new->options[DHO_DHCP_REBINDING_TIME].data);
846
else
847
ip->client->new->rebind = ip->client->new->renewal / 4 * 7;
848
if (ip->client->new->rebind < 0 ||
849
ip->client->new->rebind > ip->client->new->renewal / 4 * 7)
850
ip->client->new->rebind = ip->client->new->renewal / 4 * 7;
851
852
/* Convert the time offsets into seconds-since-the-epoch */
853
ip->client->new->expiry += cur_time;
854
ip->client->new->renewal += cur_time;
855
ip->client->new->rebind += cur_time;
856
857
bind_lease(ip);
858
}
859
860
void
861
bind_lease(struct interface_info *ip)
862
{
863
struct option_data *opt;
864
865
/* Remember the medium. */
866
ip->client->new->medium = ip->client->medium;
867
868
opt = &ip->client->new->options[DHO_INTERFACE_MTU];
869
if (opt->len == sizeof(u_int16_t)) {
870
u_int16_t mtu = 0;
871
u_int16_t old_mtu = 0;
872
bool supersede = (ip->client->config->default_actions[DHO_INTERFACE_MTU] ==
873
ACTION_SUPERSEDE);
874
875
if (supersede)
876
mtu = getUShort(ip->client->config->defaults[DHO_INTERFACE_MTU].data);
877
else
878
mtu = be16dec(opt->data);
879
880
if (ip->client->active) {
881
opt = &ip->client->active->options[DHO_INTERFACE_MTU];
882
if (opt->len == sizeof(u_int16_t)) {
883
old_mtu = be16dec(opt->data);
884
}
885
}
886
887
if (mtu < MIN_MTU) {
888
/* Treat 0 like a user intentionally doesn't want to change MTU and,
889
* therefore, warning is not needed */
890
if (!supersede || mtu != 0)
891
warning("mtu size %u < %d: ignored", (unsigned)mtu, MIN_MTU);
892
} else if (ip->client->state != S_RENEWING || mtu != old_mtu) {
893
interface_set_mtu_unpriv(privfd, mtu);
894
}
895
}
896
897
/* Write out the new lease. */
898
write_client_lease(ip, ip->client->new, 0);
899
900
/* Run the client script with the new parameters. */
901
script_init((ip->client->state == S_REQUESTING ? "BOUND" :
902
(ip->client->state == S_RENEWING ? "RENEW" :
903
(ip->client->state == S_REBOOTING ? "REBOOT" : "REBIND"))),
904
ip->client->new->medium);
905
if (ip->client->active && ip->client->state != S_REBOOTING)
906
script_write_params("old_", ip->client->active);
907
script_write_params("new_", ip->client->new);
908
if (ip->client->alias)
909
script_write_params("alias_", ip->client->alias);
910
script_go();
911
912
/* Replace the old active lease with the new one. */
913
if (ip->client->active)
914
free_client_lease(ip->client->active);
915
ip->client->active = ip->client->new;
916
ip->client->new = NULL;
917
918
/* Set up a timeout to start the renewal process. */
919
add_timeout(ip->client->active->renewal, state_bound, ip);
920
921
note("bound to %s -- renewal in %d seconds.",
922
piaddr(ip->client->active->address),
923
(int)(ip->client->active->renewal - cur_time));
924
ip->client->state = S_BOUND;
925
reinitialize_interfaces();
926
go_daemon();
927
}
928
929
/*
930
* state_bound is called when we've successfully bound to a particular
931
* lease, but the renewal time on that lease has expired. We are
932
* expected to unicast a DHCPREQUEST to the server that gave us our
933
* original lease.
934
*/
935
void
936
state_bound(void *ipp)
937
{
938
struct interface_info *ip = ipp;
939
u_int8_t *dp = NULL;
940
int len;
941
942
ASSERT_STATE(state, S_BOUND);
943
944
/* T1 has expired. */
945
make_request(ip, ip->client->active);
946
ip->client->xid = ip->client->packet.xid;
947
948
if (ip->client->config->default_actions[DHO_DHCP_SERVER_IDENTIFIER] ==
949
ACTION_SUPERSEDE) {
950
dp = ip->client->config->defaults[DHO_DHCP_SERVER_IDENTIFIER].data;
951
len = ip->client->config->defaults[DHO_DHCP_SERVER_IDENTIFIER].len;
952
} else {
953
dp = ip->client->active->options[DHO_DHCP_SERVER_IDENTIFIER].data;
954
len = ip->client->active->options[DHO_DHCP_SERVER_IDENTIFIER].len;
955
}
956
if (len == 4) {
957
memcpy(ip->client->destination.iabuf, dp, len);
958
ip->client->destination.len = len;
959
} else
960
ip->client->destination = iaddr_broadcast;
961
962
ip->client->first_sending = cur_time;
963
ip->client->interval = ip->client->config->initial_interval;
964
ip->client->state = S_RENEWING;
965
966
/* Send the first packet immediately. */
967
send_request(ip);
968
}
969
970
void
971
bootp(struct packet *packet)
972
{
973
struct iaddrlist *ap;
974
975
if (packet->raw->op != BOOTREPLY)
976
return;
977
978
/* If there's a reject list, make sure this packet's sender isn't
979
on it. */
980
for (ap = packet->interface->client->config->reject_list;
981
ap; ap = ap->next) {
982
if (addr_eq(packet->client_addr, ap->addr)) {
983
note("BOOTREPLY from %s rejected.", piaddr(ap->addr));
984
return;
985
}
986
}
987
dhcpoffer(packet);
988
}
989
990
void
991
dhcp(struct packet *packet)
992
{
993
struct iaddrlist *ap;
994
void (*handler)(struct packet *);
995
const char *type;
996
997
switch (packet->packet_type) {
998
case DHCPOFFER:
999
handler = dhcpoffer;
1000
type = "DHCPOFFER";
1001
break;
1002
case DHCPNAK:
1003
handler = dhcpnak;
1004
type = "DHCPNACK";
1005
break;
1006
case DHCPACK:
1007
handler = dhcpack;
1008
type = "DHCPACK";
1009
break;
1010
default:
1011
return;
1012
}
1013
1014
/* If there's a reject list, make sure this packet's sender isn't
1015
on it. */
1016
for (ap = packet->interface->client->config->reject_list;
1017
ap; ap = ap->next) {
1018
if (addr_eq(packet->client_addr, ap->addr)) {
1019
note("%s from %s rejected.", type, piaddr(ap->addr));
1020
return;
1021
}
1022
}
1023
(*handler)(packet);
1024
}
1025
1026
void
1027
dhcpoffer(struct packet *packet)
1028
{
1029
struct interface_info *ip = packet->interface;
1030
struct client_lease *lease, *lp;
1031
int i;
1032
struct timespec arp_timeout_needed;
1033
time_t stop_selecting;
1034
struct timespec stop_time;
1035
const char *name = packet->options[DHO_DHCP_MESSAGE_TYPE].len ?
1036
"DHCPOFFER" : "BOOTREPLY";
1037
1038
clock_gettime(CLOCK_MONOTONIC, &time_now);
1039
1040
/* If we're not receptive to an offer right now, or if the offer
1041
has an unrecognizable transaction id, then just drop it. */
1042
if (ip->client->state != S_SELECTING ||
1043
packet->interface->client->xid != packet->raw->xid ||
1044
(packet->interface->hw_address.hlen != packet->raw->hlen) ||
1045
(memcmp(packet->interface->hw_address.haddr,
1046
packet->raw->chaddr, packet->raw->hlen)))
1047
return;
1048
1049
note("%s from %s", name, piaddr(packet->client_addr));
1050
1051
/* If this lease doesn't supply the minimum required parameters,
1052
blow it off. */
1053
for (i = 0; ip->client->config->required_options[i]; i++) {
1054
if (!packet->options[ip->client->config->
1055
required_options[i]].len) {
1056
note("%s isn't satisfactory.", name);
1057
return;
1058
}
1059
}
1060
1061
/* If we've already seen this lease, don't record it again. */
1062
for (lease = ip->client->offered_leases;
1063
lease; lease = lease->next) {
1064
if (lease->address.len == sizeof(packet->raw->yiaddr) &&
1065
!memcmp(lease->address.iabuf,
1066
&packet->raw->yiaddr, lease->address.len)) {
1067
debug("%s already seen.", name);
1068
return;
1069
}
1070
}
1071
1072
lease = packet_to_lease(packet);
1073
if (!lease) {
1074
note("packet_to_lease failed.");
1075
return;
1076
}
1077
1078
/* If this lease was acquired through a BOOTREPLY, record that
1079
fact. */
1080
if (!packet->options[DHO_DHCP_MESSAGE_TYPE].len)
1081
lease->is_bootp = 1;
1082
1083
/* Record the medium under which this lease was offered. */
1084
lease->medium = ip->client->medium;
1085
1086
/* Send out an ARP Request for the offered IP address. */
1087
script_init("ARPSEND", lease->medium);
1088
script_write_params("check_", lease);
1089
/* If the script can't send an ARP request without waiting,
1090
we'll be waiting when we do the ARPCHECK, so don't wait now. */
1091
if (script_go())
1092
arp_timeout_needed = zero_timespec;
1093
1094
else
1095
arp_timeout_needed = arp_timeout;
1096
1097
/* Figure out when we're supposed to stop selecting. */
1098
stop_selecting =
1099
ip->client->first_sending + ip->client->config->select_interval;
1100
1101
/* If this is the lease we asked for, put it at the head of the
1102
list, and don't mess with the arp request timeout. */
1103
if (lease->address.len == ip->client->requested_address.len &&
1104
!memcmp(lease->address.iabuf,
1105
ip->client->requested_address.iabuf,
1106
ip->client->requested_address.len)) {
1107
lease->next = ip->client->offered_leases;
1108
ip->client->offered_leases = lease;
1109
} else {
1110
/* If we already have an offer, and arping for this
1111
offer would take us past the selection timeout,
1112
then don't extend the timeout - just hope for the
1113
best. */
1114
1115
struct timespec interm_struct;
1116
timespecadd(&time_now, &arp_timeout_needed, &interm_struct);
1117
1118
if (ip->client->offered_leases &&
1119
interm_struct.tv_sec >= stop_selecting)
1120
arp_timeout_needed = zero_timespec;
1121
1122
/* Put the lease at the end of the list. */
1123
lease->next = NULL;
1124
if (!ip->client->offered_leases)
1125
ip->client->offered_leases = lease;
1126
else {
1127
for (lp = ip->client->offered_leases; lp->next;
1128
lp = lp->next)
1129
; /* nothing */
1130
lp->next = lease;
1131
}
1132
}
1133
1134
/*
1135
* Wait until stop_selecting seconds past the epoch, or until
1136
* arp_timeout_needed past now, whichever is longer. Note that
1137
* the first case only occurs if select-timeout is set to nonzero
1138
* in dhclient.conf.
1139
*/
1140
struct timespec time_left =
1141
{.tv_sec = stop_selecting - cur_time, .tv_nsec = 0};
1142
if (timespeccmp(&time_left, &arp_timeout_needed, <)) {
1143
timespecadd(&time_now, &arp_timeout_needed, &stop_time);
1144
} else {
1145
timespecadd(&time_now, &time_left, &stop_time);
1146
}
1147
add_timeout_timespec(stop_time, state_selecting, ip);
1148
cancel_timeout(send_discover, ip);
1149
}
1150
1151
/* Allocate a client_lease structure and initialize it from the parameters
1152
in the specified packet. */
1153
1154
struct client_lease *
1155
packet_to_lease(struct packet *packet)
1156
{
1157
struct interface_info *ip = packet->interface;
1158
struct client_lease *lease;
1159
int i, j;
1160
1161
lease = malloc(sizeof(struct client_lease));
1162
1163
if (!lease) {
1164
warning("dhcpoffer: no memory to record lease.");
1165
return (NULL);
1166
}
1167
1168
memset(lease, 0, sizeof(*lease));
1169
1170
/* Copy the lease options. */
1171
for (i = 0; i < 256; i++) {
1172
if (packet->options[i].len) {
1173
int ignored = 0;
1174
for (j = 0; ip->client->config->ignored_options[j]; j++)
1175
if (i ==
1176
ip->client->config->ignored_options[j]) {
1177
ignored = 1;
1178
break;
1179
}
1180
if (ignored)
1181
continue;
1182
lease->options[i].data =
1183
malloc(packet->options[i].len + 1);
1184
if (!lease->options[i].data) {
1185
warning("dhcpoffer: no memory for option %d", i);
1186
free_client_lease(lease);
1187
return (NULL);
1188
} else {
1189
memcpy(lease->options[i].data,
1190
packet->options[i].data,
1191
packet->options[i].len);
1192
lease->options[i].len =
1193
packet->options[i].len;
1194
lease->options[i].data[lease->options[i].len] =
1195
0;
1196
}
1197
if (!check_option(lease,i)) {
1198
/* ignore a bogus lease offer */
1199
warning("Invalid lease option - ignoring offer");
1200
free_client_lease(lease);
1201
return (NULL);
1202
}
1203
}
1204
}
1205
1206
lease->address.len = sizeof(packet->raw->yiaddr);
1207
memcpy(lease->address.iabuf, &packet->raw->yiaddr, lease->address.len);
1208
1209
lease->nextserver.len = sizeof(packet->raw->siaddr);
1210
memcpy(lease->nextserver.iabuf, &packet->raw->siaddr, lease->nextserver.len);
1211
1212
/* If the server name was filled out, copy it.
1213
Do not attempt to validate the server name as a host name.
1214
RFC 2131 merely states that sname is NUL-terminated (which do
1215
do not assume) and that it is the server's host name. Since
1216
the ISC client and server allow arbitrary characters, we do
1217
as well. */
1218
if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1219
!(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)) &&
1220
packet->raw->sname[0]) {
1221
lease->server_name = malloc(DHCP_SNAME_LEN + 1);
1222
if (!lease->server_name) {
1223
warning("dhcpoffer: no memory for server name.");
1224
free_client_lease(lease);
1225
return (NULL);
1226
}
1227
memcpy(lease->server_name, packet->raw->sname, DHCP_SNAME_LEN);
1228
lease->server_name[DHCP_SNAME_LEN]='\0';
1229
}
1230
1231
/* Ditto for the filename. */
1232
if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1233
!(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)) &&
1234
packet->raw->file[0]) {
1235
/* Don't count on the NUL terminator. */
1236
lease->filename = malloc(DHCP_FILE_LEN + 1);
1237
if (!lease->filename) {
1238
warning("dhcpoffer: no memory for filename.");
1239
free_client_lease(lease);
1240
return (NULL);
1241
}
1242
memcpy(lease->filename, packet->raw->file, DHCP_FILE_LEN);
1243
lease->filename[DHCP_FILE_LEN]='\0';
1244
}
1245
return lease;
1246
}
1247
1248
void
1249
dhcpnak(struct packet *packet)
1250
{
1251
struct interface_info *ip = packet->interface;
1252
1253
/* If we're not receptive to an offer right now, or if the offer
1254
has an unrecognizable transaction id, then just drop it. */
1255
if (packet->interface->client->xid != packet->raw->xid ||
1256
(packet->interface->hw_address.hlen != packet->raw->hlen) ||
1257
(memcmp(packet->interface->hw_address.haddr,
1258
packet->raw->chaddr, packet->raw->hlen)))
1259
return;
1260
1261
if (ip->client->state != S_REBOOTING &&
1262
ip->client->state != S_REQUESTING &&
1263
ip->client->state != S_RENEWING &&
1264
ip->client->state != S_REBINDING)
1265
return;
1266
1267
note("DHCPNAK from %s", piaddr(packet->client_addr));
1268
1269
if (!ip->client->active) {
1270
note("DHCPNAK with no active lease.\n");
1271
return;
1272
}
1273
1274
free_client_lease(ip->client->active);
1275
ip->client->active = NULL;
1276
1277
/* Stop sending DHCPREQUEST packets... */
1278
cancel_timeout(send_request, ip);
1279
1280
ip->client->state = S_INIT;
1281
state_init(ip);
1282
}
1283
1284
/* Send out a DHCPDISCOVER packet, and set a timeout to send out another
1285
one after the right interval has expired. If we don't get an offer by
1286
the time we reach the panic interval, call the panic function. */
1287
1288
void
1289
send_discover(void *ipp)
1290
{
1291
struct interface_info *ip = ipp;
1292
int interval, increase = 1;
1293
1294
/* Figure out how long it's been since we started transmitting. */
1295
interval = cur_time - ip->client->first_sending;
1296
1297
/* If we're past the panic timeout, call the script and tell it
1298
we haven't found anything for this interface yet. */
1299
if (interval > ip->client->config->timeout) {
1300
state_panic(ip);
1301
return;
1302
}
1303
1304
/* If we're selecting media, try the whole list before doing
1305
the exponential backoff, but if we've already received an
1306
offer, stop looping, because we obviously have it right. */
1307
if (!ip->client->offered_leases &&
1308
ip->client->config->media) {
1309
int fail = 0;
1310
again:
1311
if (ip->client->medium) {
1312
ip->client->medium = ip->client->medium->next;
1313
increase = 0;
1314
}
1315
if (!ip->client->medium) {
1316
if (fail)
1317
error("No valid media types for %s!", ip->name);
1318
ip->client->medium = ip->client->config->media;
1319
increase = 1;
1320
}
1321
1322
note("Trying medium \"%s\" %d", ip->client->medium->string,
1323
increase);
1324
script_init("MEDIUM", ip->client->medium);
1325
if (script_go())
1326
goto again;
1327
}
1328
1329
/*
1330
* If we're supposed to increase the interval, do so. If it's
1331
* currently zero (i.e., we haven't sent any packets yet), set
1332
* it to one; otherwise, add to it a random number between zero
1333
* and two times itself. On average, this means that it will
1334
* double with every transmission.
1335
*/
1336
if (increase) {
1337
if (!ip->client->interval)
1338
ip->client->interval =
1339
ip->client->config->initial_interval;
1340
else {
1341
ip->client->interval += (arc4random() >> 2) %
1342
(2 * ip->client->interval);
1343
}
1344
1345
/* Don't backoff past cutoff. */
1346
if (ip->client->interval >
1347
ip->client->config->backoff_cutoff)
1348
ip->client->interval =
1349
((ip->client->config->backoff_cutoff / 2)
1350
+ ((arc4random() >> 2) %
1351
ip->client->config->backoff_cutoff));
1352
} else if (!ip->client->interval)
1353
ip->client->interval =
1354
ip->client->config->initial_interval;
1355
1356
/* If the backoff would take us to the panic timeout, just use that
1357
as the interval. */
1358
if (cur_time + ip->client->interval >
1359
ip->client->first_sending + ip->client->config->timeout)
1360
ip->client->interval =
1361
(ip->client->first_sending +
1362
ip->client->config->timeout) - cur_time + 1;
1363
1364
/* Record the number of seconds since we started sending. */
1365
if (interval < 65536)
1366
ip->client->packet.secs = htons(interval);
1367
else
1368
ip->client->packet.secs = htons(65535);
1369
ip->client->secs = ip->client->packet.secs;
1370
1371
note("DHCPDISCOVER on %s to %s port %d interval %d",
1372
ip->name, inet_ntoa(inaddr_broadcast), REMOTE_PORT,
1373
(int)ip->client->interval);
1374
1375
/* Send out a packet. */
1376
send_packet_unpriv(privfd, &ip->client->packet,
1377
ip->client->packet_length, inaddr_any, inaddr_broadcast);
1378
1379
add_timeout(cur_time + ip->client->interval, send_discover, ip);
1380
}
1381
1382
/*
1383
* state_panic gets called if we haven't received any offers in a preset
1384
* amount of time. When this happens, we try to use existing leases
1385
* that haven't yet expired, and failing that, we call the client script
1386
* and hope it can do something.
1387
*/
1388
void
1389
state_panic(void *ipp)
1390
{
1391
struct interface_info *ip = ipp;
1392
struct client_lease *loop = ip->client->active;
1393
struct client_lease *lp;
1394
1395
note("No DHCPOFFERS received.");
1396
1397
/* We may not have an active lease, but we may have some
1398
predefined leases that we can try. */
1399
if (!ip->client->active && ip->client->leases)
1400
goto activate_next;
1401
1402
/* Run through the list of leases and see if one can be used. */
1403
while (ip->client->active) {
1404
if (ip->client->active->expiry > cur_time) {
1405
note("Trying recorded lease %s",
1406
piaddr(ip->client->active->address));
1407
/* Run the client script with the existing
1408
parameters. */
1409
script_init("TIMEOUT",
1410
ip->client->active->medium);
1411
script_write_params("new_", ip->client->active);
1412
if (ip->client->alias)
1413
script_write_params("alias_",
1414
ip->client->alias);
1415
1416
/* If the old lease is still good and doesn't
1417
yet need renewal, go into BOUND state and
1418
timeout at the renewal time. */
1419
if (!script_go()) {
1420
if (cur_time <
1421
ip->client->active->renewal) {
1422
ip->client->state = S_BOUND;
1423
note("bound: renewal in %d seconds.",
1424
(int)(ip->client->active->renewal -
1425
cur_time));
1426
add_timeout(
1427
ip->client->active->renewal,
1428
state_bound, ip);
1429
} else {
1430
ip->client->state = S_BOUND;
1431
note("bound: immediate renewal.");
1432
state_bound(ip);
1433
}
1434
reinitialize_interfaces();
1435
go_daemon();
1436
return;
1437
}
1438
}
1439
1440
/* If there are no other leases, give up. */
1441
if (!ip->client->leases) {
1442
ip->client->leases = ip->client->active;
1443
ip->client->active = NULL;
1444
break;
1445
}
1446
1447
activate_next:
1448
/* Otherwise, put the active lease at the end of the
1449
lease list, and try another lease.. */
1450
for (lp = ip->client->leases; lp->next; lp = lp->next)
1451
;
1452
lp->next = ip->client->active;
1453
if (lp->next)
1454
lp->next->next = NULL;
1455
ip->client->active = ip->client->leases;
1456
ip->client->leases = ip->client->leases->next;
1457
1458
/* If we already tried this lease, we've exhausted the
1459
set of leases, so we might as well give up for
1460
now. */
1461
if (ip->client->active == loop)
1462
break;
1463
else if (!loop)
1464
loop = ip->client->active;
1465
}
1466
1467
/* No leases were available, or what was available didn't work, so
1468
tell the shell script that we failed to allocate an address,
1469
and try again later. */
1470
note("No working leases in persistent database - sleeping.\n");
1471
script_init("FAIL", NULL);
1472
if (ip->client->alias)
1473
script_write_params("alias_", ip->client->alias);
1474
script_go();
1475
ip->client->state = S_INIT;
1476
add_timeout(cur_time + ip->client->config->retry_interval, state_init,
1477
ip);
1478
go_daemon();
1479
}
1480
1481
void
1482
send_request(void *ipp)
1483
{
1484
struct interface_info *ip = ipp;
1485
struct in_addr from, to;
1486
int interval;
1487
1488
/* Figure out how long it's been since we started transmitting. */
1489
interval = cur_time - ip->client->first_sending;
1490
1491
/* If we're in the INIT-REBOOT or REQUESTING state and we're
1492
past the reboot timeout, go to INIT and see if we can
1493
DISCOVER an address... */
1494
/* XXX In the INIT-REBOOT state, if we don't get an ACK, it
1495
means either that we're on a network with no DHCP server,
1496
or that our server is down. In the latter case, assuming
1497
that there is a backup DHCP server, DHCPDISCOVER will get
1498
us a new address, but we could also have successfully
1499
reused our old address. In the former case, we're hosed
1500
anyway. This is not a win-prone situation. */
1501
if ((ip->client->state == S_REBOOTING ||
1502
ip->client->state == S_REQUESTING) &&
1503
interval > ip->client->config->reboot_timeout) {
1504
cancel:
1505
ip->client->state = S_INIT;
1506
cancel_timeout(send_request, ip);
1507
state_init(ip);
1508
return;
1509
}
1510
1511
/* If we're in the reboot state, make sure the media is set up
1512
correctly. */
1513
if (ip->client->state == S_REBOOTING &&
1514
!ip->client->medium &&
1515
ip->client->active->medium ) {
1516
script_init("MEDIUM", ip->client->active->medium);
1517
1518
/* If the medium we chose won't fly, go to INIT state. */
1519
if (script_go())
1520
goto cancel;
1521
1522
/* Record the medium. */
1523
ip->client->medium = ip->client->active->medium;
1524
}
1525
1526
/* If the lease has expired, relinquish the address and go back
1527
to the INIT state. */
1528
if (ip->client->state != S_REQUESTING &&
1529
cur_time > ip->client->active->expiry) {
1530
/* Run the client script with the new parameters. */
1531
script_init("EXPIRE", NULL);
1532
script_write_params("old_", ip->client->active);
1533
if (ip->client->alias)
1534
script_write_params("alias_", ip->client->alias);
1535
script_go();
1536
1537
/* Now do a preinit on the interface so that we can
1538
discover a new address. */
1539
script_init("PREINIT", NULL);
1540
if (ip->client->alias)
1541
script_write_params("alias_", ip->client->alias);
1542
script_go();
1543
1544
ip->client->state = S_INIT;
1545
state_init(ip);
1546
return;
1547
}
1548
1549
/* Do the exponential backoff... */
1550
if (!ip->client->interval)
1551
ip->client->interval = ip->client->config->initial_interval;
1552
else
1553
ip->client->interval += ((arc4random() >> 2) %
1554
(2 * ip->client->interval));
1555
1556
/* Don't backoff past cutoff. */
1557
if (ip->client->interval >
1558
ip->client->config->backoff_cutoff)
1559
ip->client->interval =
1560
((ip->client->config->backoff_cutoff / 2) +
1561
((arc4random() >> 2) % ip->client->interval));
1562
1563
/* If the backoff would take us to the expiry time, just set the
1564
timeout to the expiry time. */
1565
if (ip->client->state != S_REQUESTING &&
1566
cur_time + ip->client->interval >
1567
ip->client->active->expiry)
1568
ip->client->interval =
1569
ip->client->active->expiry - cur_time + 1;
1570
1571
/* If the lease T2 time has elapsed, or if we're not yet bound,
1572
broadcast the DHCPREQUEST rather than unicasting. */
1573
if (ip->client->state == S_REQUESTING ||
1574
ip->client->state == S_REBOOTING ||
1575
cur_time > ip->client->active->rebind)
1576
to.s_addr = INADDR_BROADCAST;
1577
else
1578
memcpy(&to.s_addr, ip->client->destination.iabuf,
1579
sizeof(to.s_addr));
1580
1581
if (ip->client->state != S_REQUESTING &&
1582
ip->client->state != S_REBOOTING)
1583
memcpy(&from, ip->client->active->address.iabuf,
1584
sizeof(from));
1585
else
1586
from.s_addr = INADDR_ANY;
1587
1588
/* Record the number of seconds since we started sending. */
1589
if (ip->client->state == S_REQUESTING)
1590
ip->client->packet.secs = ip->client->secs;
1591
else {
1592
if (interval < 65536)
1593
ip->client->packet.secs = htons(interval);
1594
else
1595
ip->client->packet.secs = htons(65535);
1596
}
1597
1598
note("DHCPREQUEST on %s to %s port %d", ip->name, inet_ntoa(to),
1599
REMOTE_PORT);
1600
1601
/* Send out a packet. */
1602
send_packet_unpriv(privfd, &ip->client->packet,
1603
ip->client->packet_length, from, to);
1604
1605
add_timeout(cur_time + ip->client->interval, send_request, ip);
1606
}
1607
1608
void
1609
send_decline(void *ipp)
1610
{
1611
struct interface_info *ip = ipp;
1612
1613
note("DHCPDECLINE on %s to %s port %d", ip->name,
1614
inet_ntoa(inaddr_broadcast), REMOTE_PORT);
1615
1616
/* Send out a packet. */
1617
send_packet_unpriv(privfd, &ip->client->packet,
1618
ip->client->packet_length, inaddr_any, inaddr_broadcast);
1619
}
1620
1621
void
1622
make_discover(struct interface_info *ip, struct client_lease *lease)
1623
{
1624
unsigned char discover = DHCPDISCOVER;
1625
struct tree_cache *options[256];
1626
struct tree_cache option_elements[256];
1627
int i;
1628
1629
memset(option_elements, 0, sizeof(option_elements));
1630
memset(options, 0, sizeof(options));
1631
memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1632
1633
/* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
1634
i = DHO_DHCP_MESSAGE_TYPE;
1635
options[i] = &option_elements[i];
1636
options[i]->value = &discover;
1637
options[i]->len = sizeof(discover);
1638
options[i]->buf_size = sizeof(discover);
1639
options[i]->timeout = 0xFFFFFFFF;
1640
1641
/* Request the options we want */
1642
i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1643
options[i] = &option_elements[i];
1644
options[i]->value = ip->client->config->requested_options;
1645
options[i]->len = ip->client->config->requested_option_count;
1646
options[i]->buf_size =
1647
ip->client->config->requested_option_count;
1648
options[i]->timeout = 0xFFFFFFFF;
1649
1650
/* If we had an address, try to get it again. */
1651
if (lease) {
1652
ip->client->requested_address = lease->address;
1653
i = DHO_DHCP_REQUESTED_ADDRESS;
1654
options[i] = &option_elements[i];
1655
options[i]->value = lease->address.iabuf;
1656
options[i]->len = lease->address.len;
1657
options[i]->buf_size = lease->address.len;
1658
options[i]->timeout = 0xFFFFFFFF;
1659
} else
1660
ip->client->requested_address.len = 0;
1661
1662
/* Send any options requested in the config file. */
1663
for (i = 0; i < 256; i++)
1664
if (!options[i] &&
1665
ip->client->config->send_options[i].data) {
1666
options[i] = &option_elements[i];
1667
options[i]->value =
1668
ip->client->config->send_options[i].data;
1669
options[i]->len =
1670
ip->client->config->send_options[i].len;
1671
options[i]->buf_size =
1672
ip->client->config->send_options[i].len;
1673
options[i]->timeout = 0xFFFFFFFF;
1674
}
1675
1676
/* send host name if not set via config file. */
1677
if (!options[DHO_HOST_NAME]) {
1678
if (hostname[0] != '\0') {
1679
size_t len;
1680
char* posDot = strchr(hostname, '.');
1681
if (posDot != NULL)
1682
len = posDot - hostname;
1683
else
1684
len = strlen(hostname);
1685
options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1686
options[DHO_HOST_NAME]->value = hostname;
1687
options[DHO_HOST_NAME]->len = len;
1688
options[DHO_HOST_NAME]->buf_size = len;
1689
options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1690
}
1691
}
1692
1693
/* set unique client identifier */
1694
char client_ident[sizeof(ip->hw_address.haddr) + 1];
1695
if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1696
int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1697
ip->hw_address.hlen : sizeof(client_ident)-1;
1698
client_ident[0] = ip->hw_address.htype;
1699
memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1700
options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1701
options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1702
options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1703
options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1704
options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1705
}
1706
1707
/* Set up the option buffer... */
1708
ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1709
options, 0, 0, 0, NULL, 0);
1710
if (ip->client->packet_length < BOOTP_MIN_LEN)
1711
ip->client->packet_length = BOOTP_MIN_LEN;
1712
1713
ip->client->packet.op = BOOTREQUEST;
1714
ip->client->packet.htype = ip->hw_address.htype;
1715
ip->client->packet.hlen = ip->hw_address.hlen;
1716
ip->client->packet.hops = 0;
1717
ip->client->packet.xid = arc4random();
1718
ip->client->packet.secs = 0; /* filled in by send_discover. */
1719
ip->client->packet.flags = 0;
1720
1721
memset(&(ip->client->packet.ciaddr),
1722
0, sizeof(ip->client->packet.ciaddr));
1723
memset(&(ip->client->packet.yiaddr),
1724
0, sizeof(ip->client->packet.yiaddr));
1725
memset(&(ip->client->packet.siaddr),
1726
0, sizeof(ip->client->packet.siaddr));
1727
memset(&(ip->client->packet.giaddr),
1728
0, sizeof(ip->client->packet.giaddr));
1729
memcpy(ip->client->packet.chaddr,
1730
ip->hw_address.haddr, ip->hw_address.hlen);
1731
}
1732
1733
1734
void
1735
make_request(struct interface_info *ip, struct client_lease * lease)
1736
{
1737
unsigned char request = DHCPREQUEST;
1738
struct tree_cache *options[256];
1739
struct tree_cache option_elements[256];
1740
int i;
1741
1742
memset(options, 0, sizeof(options));
1743
memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1744
1745
/* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1746
i = DHO_DHCP_MESSAGE_TYPE;
1747
options[i] = &option_elements[i];
1748
options[i]->value = &request;
1749
options[i]->len = sizeof(request);
1750
options[i]->buf_size = sizeof(request);
1751
options[i]->timeout = 0xFFFFFFFF;
1752
1753
/* Request the options we want */
1754
i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1755
options[i] = &option_elements[i];
1756
options[i]->value = ip->client->config->requested_options;
1757
options[i]->len = ip->client->config->requested_option_count;
1758
options[i]->buf_size =
1759
ip->client->config->requested_option_count;
1760
options[i]->timeout = 0xFFFFFFFF;
1761
1762
/* If we are requesting an address that hasn't yet been assigned
1763
to us, use the DHCP Requested Address option. */
1764
if (ip->client->state == S_REQUESTING) {
1765
/* Send back the server identifier... */
1766
i = DHO_DHCP_SERVER_IDENTIFIER;
1767
options[i] = &option_elements[i];
1768
options[i]->value = lease->options[i].data;
1769
options[i]->len = lease->options[i].len;
1770
options[i]->buf_size = lease->options[i].len;
1771
options[i]->timeout = 0xFFFFFFFF;
1772
}
1773
if (ip->client->state == S_REQUESTING ||
1774
ip->client->state == S_REBOOTING) {
1775
ip->client->requested_address = lease->address;
1776
i = DHO_DHCP_REQUESTED_ADDRESS;
1777
options[i] = &option_elements[i];
1778
options[i]->value = lease->address.iabuf;
1779
options[i]->len = lease->address.len;
1780
options[i]->buf_size = lease->address.len;
1781
options[i]->timeout = 0xFFFFFFFF;
1782
} else
1783
ip->client->requested_address.len = 0;
1784
1785
/* Send any options requested in the config file. */
1786
for (i = 0; i < 256; i++)
1787
if (!options[i] &&
1788
ip->client->config->send_options[i].data) {
1789
options[i] = &option_elements[i];
1790
options[i]->value =
1791
ip->client->config->send_options[i].data;
1792
options[i]->len =
1793
ip->client->config->send_options[i].len;
1794
options[i]->buf_size =
1795
ip->client->config->send_options[i].len;
1796
options[i]->timeout = 0xFFFFFFFF;
1797
}
1798
1799
/* send host name if not set via config file. */
1800
if (!options[DHO_HOST_NAME]) {
1801
if (hostname[0] != '\0') {
1802
size_t len;
1803
char* posDot = strchr(hostname, '.');
1804
if (posDot != NULL)
1805
len = posDot - hostname;
1806
else
1807
len = strlen(hostname);
1808
options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1809
options[DHO_HOST_NAME]->value = hostname;
1810
options[DHO_HOST_NAME]->len = len;
1811
options[DHO_HOST_NAME]->buf_size = len;
1812
options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1813
}
1814
}
1815
1816
/* set unique client identifier */
1817
char client_ident[sizeof(ip->hw_address.haddr) + 1];
1818
if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1819
int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1820
ip->hw_address.hlen : sizeof(client_ident)-1;
1821
client_ident[0] = ip->hw_address.htype;
1822
memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1823
options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1824
options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1825
options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1826
options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1827
options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1828
}
1829
1830
/* Set up the option buffer... */
1831
ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1832
options, 0, 0, 0, NULL, 0);
1833
if (ip->client->packet_length < BOOTP_MIN_LEN)
1834
ip->client->packet_length = BOOTP_MIN_LEN;
1835
1836
ip->client->packet.op = BOOTREQUEST;
1837
ip->client->packet.htype = ip->hw_address.htype;
1838
ip->client->packet.hlen = ip->hw_address.hlen;
1839
ip->client->packet.hops = 0;
1840
ip->client->packet.xid = ip->client->xid;
1841
ip->client->packet.secs = 0; /* Filled in by send_request. */
1842
1843
/* If we own the address we're requesting, put it in ciaddr;
1844
otherwise set ciaddr to zero. */
1845
if (ip->client->state == S_BOUND ||
1846
ip->client->state == S_RENEWING ||
1847
ip->client->state == S_REBINDING) {
1848
memcpy(&ip->client->packet.ciaddr,
1849
lease->address.iabuf, lease->address.len);
1850
ip->client->packet.flags = 0;
1851
} else {
1852
memset(&ip->client->packet.ciaddr, 0,
1853
sizeof(ip->client->packet.ciaddr));
1854
ip->client->packet.flags = 0;
1855
}
1856
1857
memset(&ip->client->packet.yiaddr, 0,
1858
sizeof(ip->client->packet.yiaddr));
1859
memset(&ip->client->packet.siaddr, 0,
1860
sizeof(ip->client->packet.siaddr));
1861
memset(&ip->client->packet.giaddr, 0,
1862
sizeof(ip->client->packet.giaddr));
1863
memcpy(ip->client->packet.chaddr,
1864
ip->hw_address.haddr, ip->hw_address.hlen);
1865
}
1866
1867
void
1868
make_decline(struct interface_info *ip, struct client_lease *lease)
1869
{
1870
struct tree_cache *options[256], message_type_tree;
1871
struct tree_cache requested_address_tree;
1872
struct tree_cache server_id_tree, client_id_tree;
1873
unsigned char decline = DHCPDECLINE;
1874
int i;
1875
1876
memset(options, 0, sizeof(options));
1877
memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1878
1879
/* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1880
i = DHO_DHCP_MESSAGE_TYPE;
1881
options[i] = &message_type_tree;
1882
options[i]->value = &decline;
1883
options[i]->len = sizeof(decline);
1884
options[i]->buf_size = sizeof(decline);
1885
options[i]->timeout = 0xFFFFFFFF;
1886
1887
/* Send back the server identifier... */
1888
i = DHO_DHCP_SERVER_IDENTIFIER;
1889
options[i] = &server_id_tree;
1890
options[i]->value = lease->options[i].data;
1891
options[i]->len = lease->options[i].len;
1892
options[i]->buf_size = lease->options[i].len;
1893
options[i]->timeout = 0xFFFFFFFF;
1894
1895
/* Send back the address we're declining. */
1896
i = DHO_DHCP_REQUESTED_ADDRESS;
1897
options[i] = &requested_address_tree;
1898
options[i]->value = lease->address.iabuf;
1899
options[i]->len = lease->address.len;
1900
options[i]->buf_size = lease->address.len;
1901
options[i]->timeout = 0xFFFFFFFF;
1902
1903
/* Send the uid if the user supplied one. */
1904
i = DHO_DHCP_CLIENT_IDENTIFIER;
1905
if (ip->client->config->send_options[i].len) {
1906
options[i] = &client_id_tree;
1907
options[i]->value = ip->client->config->send_options[i].data;
1908
options[i]->len = ip->client->config->send_options[i].len;
1909
options[i]->buf_size = ip->client->config->send_options[i].len;
1910
options[i]->timeout = 0xFFFFFFFF;
1911
}
1912
1913
1914
/* Set up the option buffer... */
1915
ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1916
options, 0, 0, 0, NULL, 0);
1917
if (ip->client->packet_length < BOOTP_MIN_LEN)
1918
ip->client->packet_length = BOOTP_MIN_LEN;
1919
1920
ip->client->packet.op = BOOTREQUEST;
1921
ip->client->packet.htype = ip->hw_address.htype;
1922
ip->client->packet.hlen = ip->hw_address.hlen;
1923
ip->client->packet.hops = 0;
1924
ip->client->packet.xid = ip->client->xid;
1925
ip->client->packet.secs = 0; /* Filled in by send_request. */
1926
ip->client->packet.flags = 0;
1927
1928
/* ciaddr must always be zero. */
1929
memset(&ip->client->packet.ciaddr, 0,
1930
sizeof(ip->client->packet.ciaddr));
1931
memset(&ip->client->packet.yiaddr, 0,
1932
sizeof(ip->client->packet.yiaddr));
1933
memset(&ip->client->packet.siaddr, 0,
1934
sizeof(ip->client->packet.siaddr));
1935
memset(&ip->client->packet.giaddr, 0,
1936
sizeof(ip->client->packet.giaddr));
1937
memcpy(ip->client->packet.chaddr,
1938
ip->hw_address.haddr, ip->hw_address.hlen);
1939
}
1940
1941
void
1942
free_client_lease(struct client_lease *lease)
1943
{
1944
int i;
1945
1946
if (lease->server_name)
1947
free(lease->server_name);
1948
if (lease->filename)
1949
free(lease->filename);
1950
for (i = 0; i < 256; i++) {
1951
if (lease->options[i].len)
1952
free(lease->options[i].data);
1953
}
1954
free(lease);
1955
}
1956
1957
static FILE *leaseFile;
1958
1959
void
1960
rewrite_client_leases(void)
1961
{
1962
struct client_lease *lp;
1963
cap_rights_t rights;
1964
1965
if (!leaseFile) {
1966
leaseFile = fopen(path_dhclient_db, "w");
1967
if (!leaseFile)
1968
error("can't create %s: %m", path_dhclient_db);
1969
cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_FSYNC,
1970
CAP_FTRUNCATE, CAP_SEEK, CAP_WRITE);
1971
if (caph_rights_limit(fileno(leaseFile), &rights) < 0) {
1972
error("can't limit lease descriptor: %m");
1973
}
1974
if (caph_fcntls_limit(fileno(leaseFile), CAP_FCNTL_GETFL) < 0) {
1975
error("can't limit lease descriptor fcntls: %m");
1976
}
1977
} else {
1978
fflush(leaseFile);
1979
rewind(leaseFile);
1980
}
1981
1982
for (lp = ifi->client->leases; lp; lp = lp->next)
1983
write_client_lease(ifi, lp, 1);
1984
if (ifi->client->active)
1985
write_client_lease(ifi, ifi->client->active, 1);
1986
1987
fflush(leaseFile);
1988
ftruncate(fileno(leaseFile), ftello(leaseFile));
1989
fsync(fileno(leaseFile));
1990
}
1991
1992
void
1993
write_client_lease(struct interface_info *ip, struct client_lease *lease,
1994
int rewrite)
1995
{
1996
static int leases_written;
1997
struct tm *t;
1998
int i;
1999
2000
if (!rewrite) {
2001
if (leases_written++ > 20) {
2002
rewrite_client_leases();
2003
leases_written = 0;
2004
}
2005
}
2006
2007
/* If the lease came from the config file, we don't need to stash
2008
a copy in the lease database. */
2009
if (lease->is_static)
2010
return;
2011
2012
if (!leaseFile) { /* XXX */
2013
leaseFile = fopen(path_dhclient_db, "w");
2014
if (!leaseFile)
2015
error("can't create %s: %m", path_dhclient_db);
2016
}
2017
2018
fprintf(leaseFile, "lease {\n");
2019
if (lease->is_bootp)
2020
fprintf(leaseFile, " bootp;\n");
2021
fprintf(leaseFile, " interface \"%s\";\n", ip->name);
2022
fprintf(leaseFile, " fixed-address %s;\n", piaddr(lease->address));
2023
if (lease->nextserver.len == sizeof(inaddr_any) &&
2024
0 != memcmp(lease->nextserver.iabuf, &inaddr_any,
2025
sizeof(inaddr_any)))
2026
fprintf(leaseFile, " next-server %s;\n",
2027
piaddr(lease->nextserver));
2028
if (lease->filename)
2029
fprintf(leaseFile, " filename \"%s\";\n", lease->filename);
2030
if (lease->server_name)
2031
fprintf(leaseFile, " server-name \"%s\";\n",
2032
lease->server_name);
2033
if (lease->medium)
2034
fprintf(leaseFile, " medium \"%s\";\n", lease->medium->string);
2035
for (i = 0; i < 256; i++)
2036
if (lease->options[i].len)
2037
fprintf(leaseFile, " option %s %s;\n",
2038
dhcp_options[i].name,
2039
pretty_print_option(i, lease->options[i].data,
2040
lease->options[i].len, 1, 1));
2041
2042
t = gmtime(&lease->renewal);
2043
fprintf(leaseFile, " renew %d %d/%d/%d %02d:%02d:%02d;\n",
2044
t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
2045
t->tm_hour, t->tm_min, t->tm_sec);
2046
t = gmtime(&lease->rebind);
2047
fprintf(leaseFile, " rebind %d %d/%d/%d %02d:%02d:%02d;\n",
2048
t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
2049
t->tm_hour, t->tm_min, t->tm_sec);
2050
t = gmtime(&lease->expiry);
2051
fprintf(leaseFile, " expire %d %d/%d/%d %02d:%02d:%02d;\n",
2052
t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
2053
t->tm_hour, t->tm_min, t->tm_sec);
2054
fprintf(leaseFile, "}\n");
2055
fflush(leaseFile);
2056
}
2057
2058
void
2059
script_init(const char *reason, struct string_list *medium)
2060
{
2061
size_t len, mediumlen = 0;
2062
struct imsg_hdr hdr;
2063
struct buf *buf;
2064
int errs;
2065
2066
if (medium != NULL && medium->string != NULL)
2067
mediumlen = strlen(medium->string);
2068
2069
hdr.code = IMSG_SCRIPT_INIT;
2070
hdr.len = sizeof(struct imsg_hdr) +
2071
sizeof(size_t) + mediumlen +
2072
sizeof(size_t) + strlen(reason);
2073
2074
if ((buf = buf_open(hdr.len)) == NULL)
2075
error("buf_open: %m");
2076
2077
errs = 0;
2078
errs += buf_add(buf, &hdr, sizeof(hdr));
2079
errs += buf_add(buf, &mediumlen, sizeof(mediumlen));
2080
if (mediumlen > 0)
2081
errs += buf_add(buf, medium->string, mediumlen);
2082
len = strlen(reason);
2083
errs += buf_add(buf, &len, sizeof(len));
2084
errs += buf_add(buf, reason, len);
2085
2086
if (errs)
2087
error("buf_add: %m");
2088
2089
if (buf_close(privfd, buf) == -1)
2090
error("buf_close: %m");
2091
}
2092
2093
void
2094
priv_script_init(const char *reason, char *medium)
2095
{
2096
struct interface_info *ip = ifi;
2097
2098
if (ip) {
2099
ip->client->scriptEnvsize = 100;
2100
if (ip->client->scriptEnv == NULL)
2101
ip->client->scriptEnv =
2102
malloc(ip->client->scriptEnvsize * sizeof(char *));
2103
if (ip->client->scriptEnv == NULL)
2104
error("script_init: no memory for environment");
2105
2106
ip->client->scriptEnv[0] = strdup(CLIENT_PATH);
2107
if (ip->client->scriptEnv[0] == NULL)
2108
error("script_init: no memory for environment");
2109
2110
ip->client->scriptEnv[1] = NULL;
2111
2112
script_set_env(ip->client, "", "interface", ip->name);
2113
2114
if (medium)
2115
script_set_env(ip->client, "", "medium", medium);
2116
2117
script_set_env(ip->client, "", "reason", reason);
2118
}
2119
}
2120
2121
void
2122
priv_script_write_params(const char *prefix, struct client_lease *lease)
2123
{
2124
struct interface_info *ip = ifi;
2125
u_int8_t dbuf[1500], *dp = NULL;
2126
int i;
2127
size_t len;
2128
char tbuf[128];
2129
2130
script_set_env(ip->client, prefix, "ip_address",
2131
piaddr(lease->address));
2132
2133
if (ip->client->config->default_actions[DHO_SUBNET_MASK] ==
2134
ACTION_SUPERSEDE) {
2135
dp = ip->client->config->defaults[DHO_SUBNET_MASK].data;
2136
len = ip->client->config->defaults[DHO_SUBNET_MASK].len;
2137
} else {
2138
dp = lease->options[DHO_SUBNET_MASK].data;
2139
len = lease->options[DHO_SUBNET_MASK].len;
2140
}
2141
if (len && (len < sizeof(lease->address.iabuf))) {
2142
struct iaddr netmask, subnet, broadcast;
2143
2144
memcpy(netmask.iabuf, dp, len);
2145
netmask.len = len;
2146
subnet = subnet_number(lease->address, netmask);
2147
if (subnet.len) {
2148
script_set_env(ip->client, prefix, "network_number",
2149
piaddr(subnet));
2150
if (!lease->options[DHO_BROADCAST_ADDRESS].len) {
2151
broadcast = broadcast_addr(subnet, netmask);
2152
if (broadcast.len)
2153
script_set_env(ip->client, prefix,
2154
"broadcast_address",
2155
piaddr(broadcast));
2156
}
2157
}
2158
}
2159
2160
if (lease->filename)
2161
script_set_env(ip->client, prefix, "filename", lease->filename);
2162
if (lease->server_name)
2163
script_set_env(ip->client, prefix, "server_name",
2164
lease->server_name);
2165
for (i = 0; i < 256; i++) {
2166
len = 0;
2167
2168
if (ip->client->config->defaults[i].len) {
2169
if (lease->options[i].len) {
2170
switch (
2171
ip->client->config->default_actions[i]) {
2172
case ACTION_DEFAULT:
2173
dp = lease->options[i].data;
2174
len = lease->options[i].len;
2175
break;
2176
case ACTION_SUPERSEDE:
2177
supersede:
2178
dp = ip->client->
2179
config->defaults[i].data;
2180
len = ip->client->
2181
config->defaults[i].len;
2182
break;
2183
case ACTION_PREPEND:
2184
len = ip->client->
2185
config->defaults[i].len +
2186
lease->options[i].len;
2187
if (len >= sizeof(dbuf)) {
2188
warning("no space to %s %s",
2189
"prepend option",
2190
dhcp_options[i].name);
2191
goto supersede;
2192
}
2193
dp = dbuf;
2194
memcpy(dp,
2195
ip->client->
2196
config->defaults[i].data,
2197
ip->client->
2198
config->defaults[i].len);
2199
memcpy(dp + ip->client->
2200
config->defaults[i].len,
2201
lease->options[i].data,
2202
lease->options[i].len);
2203
dp[len] = '\0';
2204
break;
2205
case ACTION_APPEND:
2206
/*
2207
* When we append, we assume that we're
2208
* appending to text. Some MS servers
2209
* include a NUL byte at the end of
2210
* the search string provided.
2211
*/
2212
len = ip->client->
2213
config->defaults[i].len +
2214
lease->options[i].len;
2215
if (len >= sizeof(dbuf)) {
2216
warning("no space to %s %s",
2217
"append option",
2218
dhcp_options[i].name);
2219
goto supersede;
2220
}
2221
memcpy(dbuf,
2222
lease->options[i].data,
2223
lease->options[i].len);
2224
for (dp = dbuf + lease->options[i].len;
2225
dp > dbuf; dp--, len--)
2226
if (dp[-1] != '\0')
2227
break;
2228
memcpy(dp,
2229
ip->client->
2230
config->defaults[i].data,
2231
ip->client->
2232
config->defaults[i].len);
2233
dp = dbuf;
2234
dp[len] = '\0';
2235
}
2236
} else {
2237
dp = ip->client->
2238
config->defaults[i].data;
2239
len = ip->client->
2240
config->defaults[i].len;
2241
}
2242
} else if (lease->options[i].len) {
2243
len = lease->options[i].len;
2244
dp = lease->options[i].data;
2245
} else {
2246
len = 0;
2247
}
2248
if (len) {
2249
char name[256];
2250
2251
if (dhcp_option_ev_name(name, sizeof(name),
2252
&dhcp_options[i]))
2253
script_set_env(ip->client, prefix, name,
2254
pretty_print_option(i, dp, len, 0, 0));
2255
}
2256
}
2257
snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry);
2258
script_set_env(ip->client, prefix, "expiry", tbuf);
2259
}
2260
2261
void
2262
script_write_params(const char *prefix, struct client_lease *lease)
2263
{
2264
size_t fn_len = 0, sn_len = 0, pr_len = 0;
2265
struct imsg_hdr hdr;
2266
struct buf *buf;
2267
int errs, i;
2268
2269
if (lease->filename != NULL)
2270
fn_len = strlen(lease->filename);
2271
if (lease->server_name != NULL)
2272
sn_len = strlen(lease->server_name);
2273
if (prefix != NULL)
2274
pr_len = strlen(prefix);
2275
2276
hdr.code = IMSG_SCRIPT_WRITE_PARAMS;
2277
hdr.len = sizeof(hdr) + sizeof(*lease) +
2278
sizeof(fn_len) + fn_len + sizeof(sn_len) + sn_len +
2279
sizeof(pr_len) + pr_len;
2280
2281
for (i = 0; i < 256; i++) {
2282
hdr.len += sizeof(lease->options[i].len);
2283
hdr.len += lease->options[i].len;
2284
}
2285
2286
scripttime = time(NULL);
2287
2288
if ((buf = buf_open(hdr.len)) == NULL)
2289
error("buf_open: %m");
2290
2291
errs = 0;
2292
errs += buf_add(buf, &hdr, sizeof(hdr));
2293
errs += buf_add(buf, lease, sizeof(*lease));
2294
errs += buf_add(buf, &fn_len, sizeof(fn_len));
2295
errs += buf_add(buf, lease->filename, fn_len);
2296
errs += buf_add(buf, &sn_len, sizeof(sn_len));
2297
errs += buf_add(buf, lease->server_name, sn_len);
2298
errs += buf_add(buf, &pr_len, sizeof(pr_len));
2299
errs += buf_add(buf, prefix, pr_len);
2300
2301
for (i = 0; i < 256; i++) {
2302
errs += buf_add(buf, &lease->options[i].len,
2303
sizeof(lease->options[i].len));
2304
errs += buf_add(buf, lease->options[i].data,
2305
lease->options[i].len);
2306
}
2307
2308
if (errs)
2309
error("buf_add: %m");
2310
2311
if (buf_close(privfd, buf) == -1)
2312
error("buf_close: %m");
2313
}
2314
2315
int
2316
script_go(void)
2317
{
2318
struct imsg_hdr hdr;
2319
struct buf *buf;
2320
int ret;
2321
2322
hdr.code = IMSG_SCRIPT_GO;
2323
hdr.len = sizeof(struct imsg_hdr);
2324
2325
if ((buf = buf_open(hdr.len)) == NULL)
2326
error("buf_open: %m");
2327
2328
if (buf_add(buf, &hdr, sizeof(hdr)))
2329
error("buf_add: %m");
2330
2331
if (buf_close(privfd, buf) == -1)
2332
error("buf_close: %m");
2333
2334
bzero(&hdr, sizeof(hdr));
2335
buf_read(privfd, &hdr, sizeof(hdr));
2336
if (hdr.code != IMSG_SCRIPT_GO_RET)
2337
error("unexpected msg type %u", hdr.code);
2338
if (hdr.len != sizeof(hdr) + sizeof(int))
2339
error("received corrupted message");
2340
buf_read(privfd, &ret, sizeof(ret));
2341
2342
scripttime = time(NULL);
2343
2344
return (ret);
2345
}
2346
2347
int
2348
priv_script_go(void)
2349
{
2350
char *scriptName, *argv[2], **envp, *epp[3], reason[] = "REASON=NBI";
2351
static char client_path[] = CLIENT_PATH;
2352
struct interface_info *ip = ifi;
2353
int pid, wpid, wstatus;
2354
2355
scripttime = time(NULL);
2356
2357
if (ip) {
2358
scriptName = ip->client->config->script_name;
2359
envp = ip->client->scriptEnv;
2360
} else {
2361
scriptName = top_level_config.script_name;
2362
epp[0] = reason;
2363
epp[1] = client_path;
2364
epp[2] = NULL;
2365
envp = epp;
2366
}
2367
2368
argv[0] = scriptName;
2369
argv[1] = NULL;
2370
2371
pid = fork();
2372
if (pid < 0) {
2373
error("fork: %m");
2374
wstatus = 0;
2375
} else if (pid) {
2376
do {
2377
wpid = wait(&wstatus);
2378
} while (wpid != pid && wpid > 0);
2379
if (wpid < 0) {
2380
error("wait: %m");
2381
wstatus = 0;
2382
}
2383
} else {
2384
execve(scriptName, argv, envp);
2385
error("execve (%s, ...): %m", scriptName);
2386
}
2387
2388
if (ip)
2389
script_flush_env(ip->client);
2390
2391
return (WIFEXITED(wstatus) ?
2392
WEXITSTATUS(wstatus) : 128 + WTERMSIG(wstatus));
2393
}
2394
2395
void
2396
script_set_env(struct client_state *client, const char *prefix,
2397
const char *name, const char *value)
2398
{
2399
int i, namelen;
2400
size_t j;
2401
2402
/* No `` or $() command substitution allowed in environment values! */
2403
for (j=0; j < strlen(value); j++)
2404
switch (value[j]) {
2405
case '`':
2406
case '$':
2407
warning("illegal character (%c) in value '%s'",
2408
value[j], value);
2409
/* Ignore this option */
2410
return;
2411
}
2412
2413
namelen = strlen(name);
2414
2415
for (i = 0; client->scriptEnv[i]; i++)
2416
if (strncmp(client->scriptEnv[i], name, namelen) == 0 &&
2417
client->scriptEnv[i][namelen] == '=')
2418
break;
2419
2420
if (client->scriptEnv[i])
2421
/* Reuse the slot. */
2422
free(client->scriptEnv[i]);
2423
else {
2424
/* New variable. Expand if necessary. */
2425
if (i >= client->scriptEnvsize - 1) {
2426
char **newscriptEnv;
2427
int newscriptEnvsize = client->scriptEnvsize + 50;
2428
2429
newscriptEnv = realloc(client->scriptEnv,
2430
newscriptEnvsize);
2431
if (newscriptEnv == NULL) {
2432
free(client->scriptEnv);
2433
client->scriptEnv = NULL;
2434
client->scriptEnvsize = 0;
2435
error("script_set_env: no memory for variable");
2436
}
2437
client->scriptEnv = newscriptEnv;
2438
client->scriptEnvsize = newscriptEnvsize;
2439
}
2440
/* need to set the NULL pointer at end of array beyond
2441
the new slot. */
2442
client->scriptEnv[i + 1] = NULL;
2443
}
2444
/* Allocate space and format the variable in the appropriate slot. */
2445
client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 +
2446
strlen(value) + 1);
2447
if (client->scriptEnv[i] == NULL)
2448
error("script_set_env: no memory for variable assignment");
2449
snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) +
2450
1 + strlen(value) + 1, "%s%s=%s", prefix, name, value);
2451
}
2452
2453
void
2454
script_flush_env(struct client_state *client)
2455
{
2456
int i;
2457
2458
for (i = 0; client->scriptEnv[i]; i++) {
2459
free(client->scriptEnv[i]);
2460
client->scriptEnv[i] = NULL;
2461
}
2462
client->scriptEnvsize = 0;
2463
}
2464
2465
int
2466
dhcp_option_ev_name(char *buf, size_t buflen, struct option *option)
2467
{
2468
size_t i;
2469
2470
for (i = 0; option->name[i]; i++) {
2471
if (i + 1 == buflen)
2472
return 0;
2473
if (option->name[i] == '-')
2474
buf[i] = '_';
2475
else
2476
buf[i] = option->name[i];
2477
}
2478
2479
buf[i] = 0;
2480
return 1;
2481
}
2482
2483
void
2484
go_daemon(void)
2485
{
2486
static int state = 0;
2487
cap_rights_t rights;
2488
2489
if (no_daemon || state)
2490
return;
2491
2492
state = 1;
2493
2494
/* Stop logging to stderr... */
2495
log_perror = 0;
2496
2497
if (daemonfd(-1, nullfd) == -1)
2498
error("daemon");
2499
2500
cap_rights_init(&rights);
2501
2502
if (pidfile != NULL) {
2503
pidfile_write(pidfile);
2504
2505
if (caph_rights_limit(pidfile_fileno(pidfile), &rights) < 0)
2506
error("can't limit pidfile descriptor: %m");
2507
}
2508
2509
if (nullfd != -1) {
2510
close(nullfd);
2511
nullfd = -1;
2512
}
2513
2514
if (caph_rights_limit(STDIN_FILENO, &rights) < 0)
2515
error("can't limit stdin: %m");
2516
cap_rights_init(&rights, CAP_WRITE);
2517
if (caph_rights_limit(STDOUT_FILENO, &rights) < 0)
2518
error("can't limit stdout: %m");
2519
if (caph_rights_limit(STDERR_FILENO, &rights) < 0)
2520
error("can't limit stderr: %m");
2521
}
2522
2523
int
2524
check_option(struct client_lease *l, int option)
2525
{
2526
const char *opbuf;
2527
const char *sbuf;
2528
2529
/* we use this, since this is what gets passed to dhclient-script */
2530
2531
opbuf = pretty_print_option(option, l->options[option].data,
2532
l->options[option].len, 0, 0);
2533
2534
sbuf = option_as_string(option, l->options[option].data,
2535
l->options[option].len);
2536
2537
switch (option) {
2538
case DHO_SUBNET_MASK:
2539
case DHO_TIME_SERVERS:
2540
case DHO_NAME_SERVERS:
2541
case DHO_ROUTERS:
2542
case DHO_DOMAIN_NAME_SERVERS:
2543
case DHO_LOG_SERVERS:
2544
case DHO_COOKIE_SERVERS:
2545
case DHO_LPR_SERVERS:
2546
case DHO_IMPRESS_SERVERS:
2547
case DHO_RESOURCE_LOCATION_SERVERS:
2548
case DHO_SWAP_SERVER:
2549
case DHO_BROADCAST_ADDRESS:
2550
case DHO_NIS_SERVERS:
2551
case DHO_NTP_SERVERS:
2552
case DHO_NETBIOS_NAME_SERVERS:
2553
case DHO_NETBIOS_DD_SERVER:
2554
case DHO_FONT_SERVERS:
2555
case DHO_DHCP_SERVER_IDENTIFIER:
2556
case DHO_NISPLUS_SERVERS:
2557
case DHO_MOBILE_IP_HOME_AGENT:
2558
case DHO_SMTP_SERVER:
2559
case DHO_POP_SERVER:
2560
case DHO_NNTP_SERVER:
2561
case DHO_WWW_SERVER:
2562
case DHO_FINGER_SERVER:
2563
case DHO_IRC_SERVER:
2564
case DHO_STREETTALK_SERVER:
2565
case DHO_STREETTALK_DA_SERVER:
2566
if (!ipv4addrs(opbuf)) {
2567
warning("Invalid IP address in option: %s", opbuf);
2568
return (0);
2569
}
2570
return (1) ;
2571
case DHO_HOST_NAME:
2572
case DHO_NIS_DOMAIN:
2573
case DHO_NISPLUS_DOMAIN:
2574
case DHO_TFTP_SERVER_NAME:
2575
if (!res_hnok(sbuf)) {
2576
warning("Bogus Host Name option %d: %s (%s)", option,
2577
sbuf, opbuf);
2578
l->options[option].len = 0;
2579
free(l->options[option].data);
2580
}
2581
return (1);
2582
case DHO_DOMAIN_NAME:
2583
case DHO_DOMAIN_SEARCH:
2584
if (!res_hnok(sbuf)) {
2585
if (!check_search(sbuf)) {
2586
warning("Bogus domain search list %d: %s (%s)",
2587
option, sbuf, opbuf);
2588
l->options[option].len = 0;
2589
free(l->options[option].data);
2590
}
2591
}
2592
return (1);
2593
case DHO_PAD:
2594
case DHO_TIME_OFFSET:
2595
case DHO_BOOT_SIZE:
2596
case DHO_MERIT_DUMP:
2597
case DHO_ROOT_PATH:
2598
case DHO_EXTENSIONS_PATH:
2599
case DHO_IP_FORWARDING:
2600
case DHO_NON_LOCAL_SOURCE_ROUTING:
2601
case DHO_POLICY_FILTER:
2602
case DHO_MAX_DGRAM_REASSEMBLY:
2603
case DHO_DEFAULT_IP_TTL:
2604
case DHO_PATH_MTU_AGING_TIMEOUT:
2605
case DHO_PATH_MTU_PLATEAU_TABLE:
2606
case DHO_INTERFACE_MTU:
2607
case DHO_ALL_SUBNETS_LOCAL:
2608
case DHO_PERFORM_MASK_DISCOVERY:
2609
case DHO_MASK_SUPPLIER:
2610
case DHO_ROUTER_DISCOVERY:
2611
case DHO_ROUTER_SOLICITATION_ADDRESS:
2612
case DHO_STATIC_ROUTES:
2613
case DHO_TRAILER_ENCAPSULATION:
2614
case DHO_ARP_CACHE_TIMEOUT:
2615
case DHO_IEEE802_3_ENCAPSULATION:
2616
case DHO_DEFAULT_TCP_TTL:
2617
case DHO_TCP_KEEPALIVE_INTERVAL:
2618
case DHO_TCP_KEEPALIVE_GARBAGE:
2619
case DHO_VENDOR_ENCAPSULATED_OPTIONS:
2620
case DHO_NETBIOS_NODE_TYPE:
2621
case DHO_NETBIOS_SCOPE:
2622
case DHO_X_DISPLAY_MANAGER:
2623
case DHO_DHCP_REQUESTED_ADDRESS:
2624
case DHO_DHCP_LEASE_TIME:
2625
case DHO_DHCP_OPTION_OVERLOAD:
2626
case DHO_DHCP_MESSAGE_TYPE:
2627
case DHO_DHCP_PARAMETER_REQUEST_LIST:
2628
case DHO_DHCP_MESSAGE:
2629
case DHO_DHCP_MAX_MESSAGE_SIZE:
2630
case DHO_DHCP_RENEWAL_TIME:
2631
case DHO_DHCP_REBINDING_TIME:
2632
case DHO_DHCP_CLASS_IDENTIFIER:
2633
case DHO_DHCP_CLIENT_IDENTIFIER:
2634
case DHO_BOOTFILE_NAME:
2635
case DHO_DHCP_USER_CLASS_ID:
2636
case DHO_URL:
2637
case DHO_SIP_SERVERS:
2638
case DHO_V_I_VENDOR_CLASS:
2639
case DHO_V_I_VENDOR_OPTS:
2640
case DHO_END:
2641
return (1);
2642
case DHO_CLASSLESS_ROUTES:
2643
return (check_classless_option(l->options[option].data,
2644
l->options[option].len));
2645
default:
2646
warning("unknown dhcp option value 0x%x", option);
2647
return (unknown_ok);
2648
}
2649
}
2650
2651
/* RFC 3442 The Classless Static Routes option checks */
2652
int
2653
check_classless_option(unsigned char *data, int len)
2654
{
2655
int i = 0;
2656
unsigned char width;
2657
in_addr_t addr, mask;
2658
2659
if (len < 5) {
2660
warning("Too small length: %d", len);
2661
return (0);
2662
}
2663
while(i < len) {
2664
width = data[i++];
2665
if (width == 0) {
2666
i += 4;
2667
continue;
2668
} else if (width < 9) {
2669
addr = (in_addr_t)(data[i] << 24);
2670
i += 1;
2671
} else if (width < 17) {
2672
addr = (in_addr_t)(data[i] << 24) +
2673
(in_addr_t)(data[i + 1] << 16);
2674
i += 2;
2675
} else if (width < 25) {
2676
addr = (in_addr_t)(data[i] << 24) +
2677
(in_addr_t)(data[i + 1] << 16) +
2678
(in_addr_t)(data[i + 2] << 8);
2679
i += 3;
2680
} else if (width < 33) {
2681
addr = (in_addr_t)(data[i] << 24) +
2682
(in_addr_t)(data[i + 1] << 16) +
2683
(in_addr_t)(data[i + 2] << 8) +
2684
data[i + 3];
2685
i += 4;
2686
} else {
2687
warning("Incorrect subnet width: %d", width);
2688
return (0);
2689
}
2690
mask = (in_addr_t)(~0) << (32 - width);
2691
addr = ntohl(addr);
2692
mask = ntohl(mask);
2693
2694
/*
2695
* From RFC 3442:
2696
* ... After deriving a subnet number and subnet mask
2697
* from each destination descriptor, the DHCP client
2698
* MUST zero any bits in the subnet number where the
2699
* corresponding bit in the mask is zero...
2700
*/
2701
if ((addr & mask) != addr) {
2702
addr &= mask;
2703
data[i - 1] = (unsigned char)(
2704
(addr >> (((32 - width)/8)*8)) & 0xFF);
2705
}
2706
i += 4;
2707
}
2708
if (i > len) {
2709
warning("Incorrect data length: %d (must be %d)", len, i);
2710
return (0);
2711
}
2712
return (1);
2713
}
2714
2715
int
2716
res_hnok(const char *dn)
2717
{
2718
int pch = PERIOD, ch = *dn++;
2719
2720
while (ch != '\0') {
2721
int nch = *dn++;
2722
2723
if (periodchar(ch)) {
2724
;
2725
} else if (periodchar(pch)) {
2726
if (!borderchar(ch))
2727
return (0);
2728
} else if (periodchar(nch) || nch == '\0') {
2729
if (!borderchar(ch))
2730
return (0);
2731
} else {
2732
if (!middlechar(ch))
2733
return (0);
2734
}
2735
pch = ch, ch = nch;
2736
}
2737
return (1);
2738
}
2739
2740
int
2741
check_search(const char *srch)
2742
{
2743
int pch = PERIOD, ch = *srch++;
2744
int domains = 1;
2745
2746
/* 256 char limit re resolv.conf(5) */
2747
if (strlen(srch) > 256)
2748
return (0);
2749
2750
while (whitechar(ch))
2751
ch = *srch++;
2752
2753
while (ch != '\0') {
2754
int nch = *srch++;
2755
2756
if (periodchar(ch) || whitechar(ch)) {
2757
;
2758
} else if (periodchar(pch)) {
2759
if (!borderchar(ch))
2760
return (0);
2761
} else if (periodchar(nch) || nch == '\0') {
2762
if (!borderchar(ch))
2763
return (0);
2764
} else {
2765
if (!middlechar(ch))
2766
return (0);
2767
}
2768
if (!whitechar(ch)) {
2769
pch = ch;
2770
} else {
2771
while (whitechar(nch)) {
2772
nch = *srch++;
2773
}
2774
if (nch != '\0')
2775
domains++;
2776
pch = PERIOD;
2777
}
2778
ch = nch;
2779
}
2780
/* 6 domain limit re resolv.conf(5) */
2781
if (domains > 6)
2782
return (0);
2783
return (1);
2784
}
2785
2786
/* Does buf consist only of dotted decimal ipv4 addrs?
2787
* return how many if so,
2788
* otherwise, return 0
2789
*/
2790
int
2791
ipv4addrs(const char * buf)
2792
{
2793
struct in_addr jnk;
2794
int count = 0;
2795
2796
while (inet_aton(buf, &jnk) == 1){
2797
count++;
2798
while (periodchar(*buf) || digitchar(*buf))
2799
buf++;
2800
if (*buf == '\0')
2801
return (count);
2802
while (*buf == ' ')
2803
buf++;
2804
}
2805
return (0);
2806
}
2807
2808
2809
const char *
2810
option_as_string(unsigned int code, unsigned char *data, int len)
2811
{
2812
static char optbuf[32768]; /* XXX */
2813
char *op = optbuf;
2814
int opleft = sizeof(optbuf);
2815
unsigned char *dp = data;
2816
2817
if (code > 255)
2818
error("option_as_string: bad code %d", code);
2819
2820
for (; dp < data + len; dp++) {
2821
if (!isascii(*dp) || !isprint(*dp)) {
2822
if (dp + 1 != data + len || *dp != 0) {
2823
snprintf(op, opleft, "\\%03o", *dp);
2824
op += 4;
2825
opleft -= 4;
2826
}
2827
} else if (*dp == '"' || *dp == '\'' || *dp == '$' ||
2828
*dp == '`' || *dp == '\\') {
2829
*op++ = '\\';
2830
*op++ = *dp;
2831
opleft -= 2;
2832
} else {
2833
*op++ = *dp;
2834
opleft--;
2835
}
2836
}
2837
if (opleft < 1)
2838
goto toobig;
2839
*op = 0;
2840
return optbuf;
2841
toobig:
2842
warning("dhcp option too large");
2843
return "<error>";
2844
}
2845
2846
int
2847
fork_privchld(int fd, int fd2)
2848
{
2849
struct pollfd pfd[1];
2850
int nfds;
2851
2852
switch (fork()) {
2853
case -1:
2854
error("cannot fork");
2855
case 0:
2856
break;
2857
default:
2858
return (0);
2859
}
2860
2861
setproctitle("%s [priv]", ifi->name);
2862
2863
setsid();
2864
dup2(nullfd, STDIN_FILENO);
2865
dup2(nullfd, STDOUT_FILENO);
2866
dup2(nullfd, STDERR_FILENO);
2867
close(nullfd);
2868
close(fd2);
2869
close(ifi->rfdesc);
2870
ifi->rfdesc = -1;
2871
2872
for (;;) {
2873
pfd[0].fd = fd;
2874
pfd[0].events = POLLIN;
2875
if ((nfds = poll(pfd, 1, INFTIM)) == -1)
2876
if (errno != EINTR)
2877
error("poll error");
2878
2879
if (nfds == 0 || !(pfd[0].revents & POLLIN))
2880
continue;
2881
2882
dispatch_imsg(ifi, fd);
2883
}
2884
}
2885
2886