1
/* dnsmasq is Copyright (c) 2000 - 2005 by Simon Kelley
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 dated June, 1991.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
14
/* Code in this file is based on contributions by John Volpe. */
18
#ifdef HAVE_ISC_READER
24
struct isc_lease *next;
27
static struct isc_lease *leases = NULL;
28
static off_t lease_file_size = (off_t)0;
29
static ino_t lease_file_inode = (ino_t)0;
30
static int logged_lease = 0;
32
static int next_token (char *token, int buffsize, FILE * fp)
37
while((c = getc(fp)) != EOF)
40
do { c = getc(fp); } while (c != '\n' && c != EOF);
42
if (c == ' ' || c == '\t' || c == '\n' || c == ';')
47
else if ((c != '"') && (count<buffsize-1))
58
void load_dhcp(struct daemon *daemon, time_t now)
60
char *hostname = daemon->namebuff;
61
char token[MAXTOK], *dot;
62
struct in_addr host_address;
65
struct isc_lease *lease, *tmp, **up;
68
if (stat(daemon->lease_file, &statbuf) == -1)
71
syslog(LOG_WARNING, "failed to access %s: %m", daemon->lease_file);
78
if ((statbuf.st_size <= lease_file_size) &&
79
(statbuf.st_ino == lease_file_inode))
82
lease_file_size = statbuf.st_size;
83
lease_file_inode = statbuf.st_ino;
85
if (!(fp = fopen (daemon->lease_file, "r")))
87
syslog (LOG_ERR, "failed to load %s: %m", daemon->lease_file);
91
syslog (LOG_INFO, "reading %s", daemon->lease_file);
93
while ((next_token(token, MAXTOK, fp)))
95
if (strcmp(token, "lease") == 0)
98
ttd = tts = (time_t)(-1);
99
if (next_token(token, MAXTOK, fp) &&
100
(host_address.s_addr = inet_addr(token)) != (in_addr_t) -1)
102
if (next_token(token, MAXTOK, fp) && *token == '{')
104
while (next_token(token, MAXTOK, fp) && *token != '}')
106
if ((strcmp(token, "client-hostname") == 0) ||
107
(strcmp(token, "hostname") == 0))
109
if (next_token(hostname, MAXDNAME, fp))
110
if (!canonicalise(hostname))
113
syslog(LOG_ERR, "bad name in %s", daemon->lease_file);
116
else if ((strcmp(token, "ends") == 0) ||
117
(strcmp(token, "starts") == 0))
119
struct tm lease_time;
120
int is_ends = (strcmp(token, "ends") == 0);
121
if (next_token(token, MAXTOK, fp) && /* skip weekday */
122
next_token(token, MAXTOK, fp) && /* Get date from lease file */
123
sscanf (token, "%d/%d/%d",
126
&lease_time.tm_mday) == 3 &&
127
next_token(token, MAXTOK, fp) &&
128
sscanf (token, "%d:%d:%d:",
131
&lease_time.tm_sec) == 3)
133
/* There doesn't seem to be a universally available library function
134
which converts broken-down _GMT_ time to seconds-in-epoch.
135
The following was borrowed from ISC dhcpd sources, where
136
it is noted that it might not be entirely accurate for odd seconds.
137
Since we're trying to get the same answer as dhcpd, that's just
139
static int months [11] = { 31, 59, 90, 120, 151, 181,
140
212, 243, 273, 304, 334 };
141
time_t time = ((((((365 * (lease_time.tm_year - 1970) + /* Days in years since '70 */
142
(lease_time.tm_year - 1969) / 4 + /* Leap days since '70 */
143
(lease_time.tm_mon > 1 /* Days in months this year */
144
? months [lease_time.tm_mon - 2]
146
(lease_time.tm_mon > 2 && /* Leap day this year */
147
!((lease_time.tm_year - 1972) & 3)) +
148
lease_time.tm_mday - 1) * 24) + /* Day of month */
149
lease_time.tm_hour) * 60) +
150
lease_time.tm_min) * 60) + lease_time.tm_sec;
161
if (ttd == (time_t)(-1))
164
/* We use 0 as infinite in ttd */
165
if ((tts != -1) && (ttd == tts - 1))
167
else if (difftime(now, ttd) > 0)
170
if ((dot = strchr(hostname, '.')))
172
if (!daemon->domain_suffix || hostname_isequal(dot+1, daemon->domain_suffix))
175
"Ignoring DHCP lease for %s because it has an illegal domain part",
182
for (lease = leases; lease; lease = lease->next)
183
if (hostname_isequal(lease->name, hostname))
185
lease->expires = ttd;
186
lease->addr = host_address;
190
if (!lease && (lease = malloc(sizeof(struct isc_lease))))
192
lease->expires = ttd;
193
lease->addr = host_address;
195
lease->next = leases;
196
if (!(lease->name = malloc(strlen(hostname)+1)))
201
strcpy(lease->name, hostname);
202
if (daemon->domain_suffix &&
203
(lease->fqdn = malloc(strlen(hostname) + strlen(daemon->domain_suffix) + 2)))
205
strcpy(lease->fqdn, hostname);
206
strcat(lease->fqdn, ".");
207
strcat(lease->fqdn, daemon->domain_suffix);
218
/* prune expired leases */
219
for (lease = leases, up = &leases; lease; lease = tmp)
222
if (lease->expires != (time_t)0 && difftime(now, lease->expires) > 0)
224
*up = lease->next; /* unlink */
235
/* remove all existing DHCP cache entries */
238
for (lease = leases; lease; lease = lease->next)
240
cache_add_dhcp_entry(daemon, lease->fqdn, &lease->addr, lease->expires);
241
cache_add_dhcp_entry(daemon, lease->name, &lease->addr, lease->expires);