1
/* dnsmasq is Copyright (c) 2000-2006 Simon Kelley
1
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley
3
3
This program is free software; you can redistribute it and/or modify
4
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 dated June, 1991.
5
the Free Software Foundation; version 2 dated June, 1991, or
6
(at your option) version 3 dated 29 June, 2007.
7
8
This program is distributed in the hope that it will be useful,
8
9
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
10
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
11
GNU General Public License for more details.
13
You should have received a copy of the GNU General Public License
14
along with this program. If not, see <http://www.gnu.org/licenses/>.
13
17
#include "dnsmasq.h"
15
static struct dhcp_lease *leases, *old_leases;
19
static struct dhcp_lease *leases = NULL, *old_leases = NULL;
16
20
static int dns_dirty, file_dirty, leases_left;
18
void lease_init(struct daemon *daemon, time_t now)
22
void lease_init(time_t now)
21
25
struct in_addr addr;
22
26
struct dhcp_lease *lease;
23
int flags, clid_len, hw_len, hw_type;
27
int clid_len, hw_len, hw_type;
26
leases = old_leases = NULL;
30
/* These two each hold a DHCP option max size 255
31
and get a terminating zero added */
32
daemon->dhcp_buff = safe_malloc(256);
33
daemon->dhcp_buff2 = safe_malloc(256);
27
35
leases_left = daemon->dhcp_max;
29
37
if (daemon->options & OPT_LEASE_RO)
47
55
leasestream = daemon->lease_stream = fopen(daemon->lease_file, "a+");
50
die(_("cannot open or create lease file %s: %s"), daemon->lease_file);
52
flags = fcntl(fileno(leasestream), F_GETFD);
54
fcntl(fileno(leasestream), F_SETFD, flags | FD_CLOEXEC);
58
die(_("cannot open or create lease file %s: %s"), daemon->lease_file, EC_FILE);
56
60
/* a+ mode lease pointer at end. */
57
61
rewind(leasestream);
77
81
clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL);
79
83
if (!(lease = lease_allocate(addr)))
80
die (_("too many stored leases"), NULL);
81
/* not actually new */
84
die (_("too many stored leases"), NULL, EC_MISC);
84
86
#ifdef HAVE_BROKEN_RTC
86
88
lease->expires = (time_t)ei + now;
96
98
lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet, hw_len, hw_type, clid_len);
98
100
if (strcmp(daemon->dhcp_buff, "*") != 0)
99
lease_set_hostname(lease, daemon->dhcp_buff, daemon->domain_suffix, 0);
103
/* unprotect spaces */
104
for (p = strchr(daemon->dhcp_buff, '*'); p; p = strchr(p, '*'))
106
lease_set_hostname(lease, daemon->dhcp_buff, daemon->domain_suffix, 0);
109
/* set these correctly: the "old" events are generated later from
110
the startup synthesised SIGHUP. */
111
lease->new = lease->changed = 0;
102
114
if (!daemon->lease_stream)
111
123
else if (WEXITSTATUS(rc) == 126)
113
die(_("cannot run lease-init script %s: %s"), daemon->lease_change_command);
125
die(_("cannot run lease-init script %s: %s"), daemon->lease_change_command, EC_FILE);
116
128
if (WEXITSTATUS(rc) != 0)
118
130
sprintf(daemon->dhcp_buff, "%d", WEXITSTATUS(rc));
119
die(_("lease-init script returned exit code %s"), daemon->dhcp_buff);
131
die(_("lease-init script returned exit code %s"), daemon->dhcp_buff, WEXITSTATUS(rc) + EC_INIT_OFFSET);
140
152
(config->flags & CONFIG_NAME) &&
141
153
(!(config->flags & CONFIG_ADDR) || config->addr.s_addr == lease->addr.s_addr))
142
154
lease_set_hostname(lease, config->hostname, daemon->domain_suffix, 1);
143
else if ((name = host_from_dns(daemon, lease->addr)))
155
else if ((name = host_from_dns(lease->addr)))
144
156
lease_set_hostname(lease, name, daemon->domain_suffix, 1); /* updates auth flag only */
147
static void ourprintf(struct daemon *daemon, int *errp, char *format, ...)
159
static void ourprintf(int *errp, char *format, ...)
170
183
for (lease = leases; lease; lease = lease->next)
172
185
#ifdef HAVE_BROKEN_RTC
173
ourprintf(daemon, &err, "%u ", lease->length);
186
ourprintf(&err, "%u ", lease->length);
175
ourprintf(daemon, &err, "%lu ", (unsigned long)lease->expires);
188
ourprintf(&err, "%lu ", (unsigned long)lease->expires);
177
190
if (lease->hwaddr_type != ARPHRD_ETHER || lease->hwaddr_len == 0)
178
ourprintf(daemon, &err, "%.2x-", lease->hwaddr_type);
191
ourprintf(&err, "%.2x-", lease->hwaddr_type);
179
192
for (i = 0; i < lease->hwaddr_len; i++)
181
ourprintf(daemon, &err, "%.2x", lease->hwaddr[i]);
194
ourprintf(&err, "%.2x", lease->hwaddr[i]);
182
195
if (i != lease->hwaddr_len - 1)
183
ourprintf(daemon, &err, ":");
196
ourprintf(&err, ":");
185
ourprintf(daemon, &err, " %s %s ", inet_ntoa(lease->addr),
186
lease->hostname && strlen(lease->hostname) != 0 ? lease->hostname : "*");
199
ourprintf(&err, " %s ", inet_ntoa(lease->addr));
201
/* substitute * for space: "*" is an illegal name, as is " " */
203
for (p = lease->hostname; *p; p++)
204
ourprintf(&err, "%c", *p == ' ' ? '*' : *p);
206
ourprintf(&err, "*");
207
ourprintf(&err, " ");
188
209
if (lease->clid && lease->clid_len != 0)
190
211
for (i = 0; i < lease->clid_len - 1; i++)
191
ourprintf(daemon, &err, "%.2x:", lease->clid[i]);
192
ourprintf(daemon, &err, "%.2x\n", lease->clid[i]);
212
ourprintf(&err, "%.2x:", lease->clid[i]);
213
ourprintf(&err, "%.2x\n", lease->clid[i]);
195
ourprintf(daemon, &err, "*\n");
216
ourprintf(&err, "*\n");
198
219
if (fflush(daemon->lease_stream) != 0 ||
214
235
if (next_event == 0 || difftime(next_event, LEASE_RETRY + now) > 0.0)
215
236
next_event = LEASE_RETRY + now;
217
syslog(LOG_ERR, _("failed to write %s: %s (retry in %us)"),
218
daemon->lease_file, strerror(err),
219
(unsigned int)difftime(next_event, now));
238
my_syslog(LOG_ERR, _("failed to write %s: %s (retry in %us)"),
239
daemon->lease_file, strerror(err),
240
(unsigned int)difftime(next_event, now));
222
243
if (next_event != 0)
223
244
alarm((unsigned)difftime(next_event, now));
226
void lease_update_dns(struct daemon *daemon)
247
void lease_update_dns(void)
228
249
struct dhcp_lease *lease;
251
if (daemon->port != 0 && dns_dirty)
232
253
cache_unhash_dhcp();
234
255
for (lease = leases; lease; lease = lease->next)
236
cache_add_dhcp_entry(daemon, lease->fqdn, &lease->addr, lease->expires);
237
cache_add_dhcp_entry(daemon, lease->hostname, &lease->addr, lease->expires);
257
cache_add_dhcp_entry(lease->fqdn, &lease->addr, lease->expires);
258
cache_add_dhcp_entry(lease->hostname, &lease->addr, lease->expires);
306
327
struct dhcp_lease *lease_allocate(struct in_addr addr)
308
329
struct dhcp_lease *lease;
309
if (!leases_left || !(lease = malloc(sizeof(struct dhcp_lease))))
330
if (!leases_left || !(lease = whine_malloc(sizeof(struct dhcp_lease))))
312
333
memset(lease, 0, sizeof(struct dhcp_lease));
314
335
lease->addr = addr;
315
lease->hwaddr_len = 225; /* illegal value */
336
lease->hwaddr_len = 256; /* illegal value */
316
337
lease->expires = 1;
317
338
#ifdef HAVE_BROKEN_RTC
318
339
lease->length = 0xffffffff; /* illegal value */
378
399
if (lease->clid_len != clid_len)
380
401
lease->aux_changed = file_dirty = 1;
383
if (!(lease->clid = malloc(clid_len)))
403
if (!(lease->clid = whine_malloc(clid_len)))
386
406
else if (memcmp(lease->clid, clid, clid_len) != 0)
421
441
/* this shouldn't happen unless updates are very quick and the
422
442
script very slow, we just avoid a memory leak if it does. */
423
if (lease_tmp->old_hostname)
424
free(lease_tmp->old_hostname);
443
free(lease_tmp->old_hostname);
425
444
lease_tmp->old_hostname = lease_tmp->hostname;
426
445
lease_tmp->hostname = NULL;
427
446
if (lease_tmp->fqdn)
463
480
lease->changed = 1; /* run script on change */
483
void lease_set_interface(struct dhcp_lease *lease, int interface)
485
if (lease->last_interface == interface)
488
lease->last_interface = interface;
492
void rerun_scripts(void)
494
struct dhcp_lease *lease;
496
for (lease = leases; lease; lease = lease->next)
466
500
/* deleted leases get transferred to the old_leases list.
467
501
remove them here, after calling the lease change
468
502
script. Also run the lease change script on new/modified leases.
470
504
Return zero if nothing to do. */
471
int do_script_run(struct daemon *daemon)
505
int do_script_run(time_t now)
473
507
struct dhcp_lease *lease;
479
513
/* If the lease still has an old_hostname, do the "old" action on that first */
480
514
if (lease->old_hostname)
482
queue_script(daemon, ACTION_OLD_HOSTNAME, lease, lease->old_hostname);
517
queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now);
483
519
free(lease->old_hostname);
484
520
lease->old_hostname = NULL;
489
queue_script(daemon, ACTION_DEL, lease, lease->hostname);
526
queue_script(ACTION_DEL, lease, lease->hostname, now);
490
528
old_leases = lease->next;
493
free(lease->hostname);
498
if (lease->vendorclass)
499
free(lease->vendorclass);
500
if (lease->userclass)
501
free(lease->userclass);
530
free(lease->hostname);
533
free(lease->vendorclass);
534
free(lease->userclass);
509
542
for (lease = leases; lease; lease = lease->next)
510
543
if (lease->old_hostname)
512
queue_script(daemon, ACTION_OLD_HOSTNAME, lease, lease->old_hostname);
546
queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now);
513
548
free(lease->old_hostname);
514
549
lease->old_hostname = NULL;
519
554
if (lease->new || lease->changed ||
520
555
(lease->aux_changed && (daemon->options & OPT_LEASE_RO)))
522
queue_script(daemon, lease->new ? ACTION_ADD : ACTION_OLD, lease, lease->hostname);
558
queue_script(lease->new ? ACTION_ADD : ACTION_OLD, lease, lease->hostname, now);
523
560
lease->new = lease->changed = lease->aux_changed = 0;
525
562
/* these are used for the "add" call, then junked, since they're not in the database */
526
if (lease->vendorclass)
528
free(lease->vendorclass);
529
lease->vendorclass = NULL;
531
if (lease->userclass)
533
free(lease->userclass);
534
lease->userclass = NULL;
563
free(lease->vendorclass);
564
lease->vendorclass = NULL;
566
free(lease->userclass);
567
lease->userclass = NULL;