21
21
struct in_addr addr;
22
22
struct dhcp_lease *lease;
23
23
int flags, clid_len, hw_len, hw_type;
25
26
leases = old_leases = NULL;
26
27
leases_left = daemon->dhcp_max;
28
/* NOTE: need a+ mode to create file if it doesn't exist */
29
if (!(daemon->lease_stream = fopen(daemon->lease_file, "a+")))
30
die(_("cannot open or create leases file: %s"), NULL);
32
flags = fcntl(fileno(daemon->lease_stream), F_GETFD);
34
fcntl(fileno(daemon->lease_stream), F_SETFD, flags | FD_CLOEXEC);
29
if (daemon->options & OPT_LEASE_RO)
31
/* run "<lease_change_script> init" once to get the
32
initial state of the database. If leasefile-ro is
33
set without a script, we just do without any
35
if (!daemon->lease_change_command)
37
file_dirty = dns_dirty = 0;
40
strcpy(daemon->dhcp_buff, daemon->lease_change_command);
41
strcat(daemon->dhcp_buff, " init");
42
leasestream = popen(daemon->dhcp_buff, "r");
46
/* NOTE: need a+ mode to create file if it doesn't exist */
47
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);
56
/* a+ mode lease pointer at end. */
36
/* a+ mode lease pointer at end. */
37
rewind(daemon->lease_stream);
39
60
/* client-id max length is 255 which is 255*2 digits + 254 colons
40
61
borrow DNS packet buffer which is always larger than 1000 bytes */
41
while (fscanf(daemon->lease_stream, "%lu %255s %16s %255s %764s",
42
&ei, daemon->dhcp_buff2, daemon->namebuff,
43
daemon->dhcp_buff, daemon->packet) == 5)
45
hw_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, DHCP_CHADDR_MAX, NULL, &hw_type);
46
/* For backwards compatibility, no explict MAC address type means ether. */
47
if (hw_type == 0 && hw_len != 0)
48
hw_type = ARPHRD_ETHER;
50
addr.s_addr = inet_addr(daemon->namebuff);
52
/* decode hex in place */
54
if (strcmp(daemon->packet, "*") != 0)
55
clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL);
57
if (!(lease = lease_allocate(addr)))
58
die (_("too many stored leases"), NULL);
59
/* not actually new */
63
while (fscanf(leasestream, "%lu %255s %16s %255s %764s",
64
&ei, daemon->dhcp_buff2, daemon->namebuff,
65
daemon->dhcp_buff, daemon->packet) == 5)
67
hw_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, DHCP_CHADDR_MAX, NULL, &hw_type);
68
/* For backwards compatibility, no explict MAC address type means ether. */
69
if (hw_type == 0 && hw_len != 0)
70
hw_type = ARPHRD_ETHER;
72
addr.s_addr = inet_addr(daemon->namebuff);
74
/* decode hex in place */
76
if (strcmp(daemon->packet, "*") != 0)
77
clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL);
79
if (!(lease = lease_allocate(addr)))
80
die (_("too many stored leases"), NULL);
81
/* not actually new */
62
84
#ifdef HAVE_BROKEN_RTC
64
lease->expires = (time_t)ei + now;
66
lease->expires = (time_t)0;
86
lease->expires = (time_t)ei + now;
88
lease->expires = (time_t)0;
69
/* strictly time_t is opaque, but this hack should work on all sane systems,
70
even when sizeof(time_t) == 8 */
71
lease->expires = (time_t)ei;
91
/* strictly time_t is opaque, but this hack should work on all sane systems,
92
even when sizeof(time_t) == 8 */
93
lease->expires = (time_t)ei;
74
lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet, hw_len, hw_type, clid_len);
76
if (strcmp(daemon->dhcp_buff, "*") != 0)
77
lease_set_hostname(lease, daemon->dhcp_buff, daemon->domain_suffix, 0);
96
lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet, hw_len, hw_type, clid_len);
98
if (strcmp(daemon->dhcp_buff, "*") != 0)
99
lease_set_hostname(lease, daemon->dhcp_buff, daemon->domain_suffix, 0);
102
if (!daemon->lease_stream)
106
/* shell returns 127 for "command not found", 126 for bad permissions. */
107
if (!leasestream || (rc = pclose(leasestream)) == -1 || WEXITSTATUS(rc) == 127 || WEXITSTATUS(rc) == 126)
109
if (WEXITSTATUS(rc) == 127)
111
else if (WEXITSTATUS(rc) == 126)
113
die(_("cannot run lease-init script %s: %s"), daemon->lease_change_command);
116
if (WEXITSTATUS(rc) != 0)
118
sprintf(daemon->dhcp_buff, "%d", WEXITSTATUS(rc));
119
die(_("lease-init script returned exit code %s"), daemon->dhcp_buff);
80
123
/* Some leases may have expired */
418
461
if (daemon->lease_change_command)
420
char *mac = print_mac(daemon, lease->hwaddr, lease->hwaddr_len);
421
463
char *addr = inet_ntoa(lease->addr);
422
464
char *com = strrchr(daemon->lease_change_command, '/');
469
/* stringify MAC into dhcp_buff */
470
p = daemon->dhcp_buff;
471
if (lease->hwaddr_type != ARPHRD_ETHER || lease->hwaddr_len == 0)
472
p += sprintf(p, "%.2x-", lease->hwaddr_type);
473
for (i = 0; i < lease->hwaddr_len; i++)
475
p += sprintf(p, "%.2x", lease->hwaddr[i]);
476
if (i != lease->hwaddr_len - 1)
477
p += sprintf(p, ":");
480
/* and CLID into namebuff */
481
p = daemon->namebuff;
483
for (i = 0; i < lease->clid_len; i++)
485
p += sprintf(p, "%.2x", lease->clid[i]);
486
if (i != lease->clid_len - 1)
487
p += sprintf(p, ":");
490
/* and expiry or length into dhcp_buff2 */
491
#ifdef HAVE_BROKEN_RTC
492
sprintf(daemon->dhcp_buff2, "%u ", lease->length);
494
sprintf(daemon->dhcp_buff2, "%lu ", (unsigned long)lease->expires);
426
500
return 0; /* fork error */
427
501
else if (pid != 0)
504
if (lease->clid && lease->clid_len != 0)
505
setenv("DNSMASQ_CLIENT_ID", daemon->namebuff, 1);
507
unsetenv("DNSMASQ_CLIENT_ID");
509
#ifdef HAVE_BROKEN_RTC
510
setenv("DNSMASQ_LEASE_LENGTH", daemon->dhcp_buff2, 1);
511
unsetenv("DNSMASQ_LEASE_EXPIRES");
513
setenv("DNSMASQ_LEASE_EXPIRES", daemon->dhcp_buff2, 1);
514
unsetenv("DNSMASQ_LEASE_LENGTH");
430
517
execl(daemon->lease_change_command,
431
518
com ? com+1 : daemon->lease_change_command,
432
action, mac, addr, lease->hostname, (char*)NULL);
519
action, daemon->dhcp_buff, addr, lease->hostname, (char*)NULL);
434
521
/* log socket should still be open, right? */
435
522
syslog(LOG_ERR, _("failed to execute %s: %m"),