]>
Commit | Line | Data |
---|---|---|
73a08a24 | 1 | /* dnsmasq is Copyright (c) 2000-2009 Simon Kelley |
9e4abcb5 SK |
2 | |
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 | |
824af85b SK |
5 | the Free Software Foundation; version 2 dated June, 1991, or |
6 | (at your option) version 3 dated 29 June, 2007. | |
7 | ||
9e4abcb5 SK |
8 | This program is distributed in the hope that it will be useful, |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
824af85b | 12 | |
73a08a24 SK |
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/>. | |
9e4abcb5 SK |
15 | */ |
16 | ||
9e4abcb5 SK |
17 | #include "dnsmasq.h" |
18 | ||
7622fc06 SK |
19 | #ifdef HAVE_DHCP |
20 | ||
5aabfc78 | 21 | static struct dhcp_lease *leases = NULL, *old_leases = NULL; |
5e9e0efb | 22 | static int dns_dirty, file_dirty, leases_left; |
9e4abcb5 | 23 | |
5aabfc78 | 24 | void lease_init(time_t now) |
9e4abcb5 | 25 | { |
9e4abcb5 | 26 | unsigned long ei; |
9e4abcb5 SK |
27 | struct in_addr addr; |
28 | struct dhcp_lease *lease; | |
5aabfc78 | 29 | int clid_len, hw_len, hw_type; |
208b65c5 | 30 | FILE *leasestream; |
5e9e0efb | 31 | |
5aabfc78 SK |
32 | /* These two each hold a DHCP option max size 255 |
33 | and get a terminating zero added */ | |
34 | daemon->dhcp_buff = safe_malloc(256); | |
35 | daemon->dhcp_buff2 = safe_malloc(256); | |
36 | ||
3be34541 | 37 | leases_left = daemon->dhcp_max; |
44a2a316 | 38 | |
208b65c5 SK |
39 | if (daemon->options & OPT_LEASE_RO) |
40 | { | |
41 | /* run "<lease_change_script> init" once to get the | |
42 | initial state of the database. If leasefile-ro is | |
43 | set without a script, we just do without any | |
44 | lease database. */ | |
1f15b81d SK |
45 | #ifdef HAVE_SCRIPT |
46 | if (daemon->lease_change_command) | |
208b65c5 | 47 | { |
1f15b81d SK |
48 | strcpy(daemon->dhcp_buff, daemon->lease_change_command); |
49 | strcat(daemon->dhcp_buff, " init"); | |
50 | leasestream = popen(daemon->dhcp_buff, "r"); | |
208b65c5 | 51 | } |
1f15b81d SK |
52 | else |
53 | #endif | |
54 | { | |
55 | file_dirty = dns_dirty = 0; | |
56 | return; | |
57 | } | |
58 | ||
208b65c5 SK |
59 | } |
60 | else | |
61 | { | |
62 | /* NOTE: need a+ mode to create file if it doesn't exist */ | |
63 | leasestream = daemon->lease_stream = fopen(daemon->lease_file, "a+"); | |
64 | ||
65 | if (!leasestream) | |
5aabfc78 | 66 | die(_("cannot open or create lease file %s: %s"), daemon->lease_file, EC_FILE); |
208b65c5 | 67 | |
7622fc06 | 68 | /* a+ mode leaves pointer at end. */ |
208b65c5 SK |
69 | rewind(leasestream); |
70 | } | |
7cebd20f | 71 | |
0a852541 SK |
72 | /* client-id max length is 255 which is 255*2 digits + 254 colons |
73 | borrow DNS packet buffer which is always larger than 1000 bytes */ | |
208b65c5 SK |
74 | if (leasestream) |
75 | while (fscanf(leasestream, "%lu %255s %16s %255s %764s", | |
76 | &ei, daemon->dhcp_buff2, daemon->namebuff, | |
77 | daemon->dhcp_buff, daemon->packet) == 5) | |
78 | { | |
79 | hw_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, DHCP_CHADDR_MAX, NULL, &hw_type); | |
80 | /* For backwards compatibility, no explict MAC address type means ether. */ | |
81 | if (hw_type == 0 && hw_len != 0) | |
82 | hw_type = ARPHRD_ETHER; | |
83 | ||
84 | addr.s_addr = inet_addr(daemon->namebuff); | |
85 | ||
86 | /* decode hex in place */ | |
87 | clid_len = 0; | |
88 | if (strcmp(daemon->packet, "*") != 0) | |
89 | clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL); | |
90 | ||
91 | if (!(lease = lease_allocate(addr))) | |
5aabfc78 SK |
92 | die (_("too many stored leases"), NULL, EC_MISC); |
93 | ||
5e9e0efb | 94 | #ifdef HAVE_BROKEN_RTC |
208b65c5 SK |
95 | if (ei != 0) |
96 | lease->expires = (time_t)ei + now; | |
97 | else | |
98 | lease->expires = (time_t)0; | |
99 | lease->length = ei; | |
5e9e0efb | 100 | #else |
208b65c5 SK |
101 | /* strictly time_t is opaque, but this hack should work on all sane systems, |
102 | even when sizeof(time_t) == 8 */ | |
103 | lease->expires = (time_t)ei; | |
5e9e0efb | 104 | #endif |
208b65c5 SK |
105 | |
106 | lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet, hw_len, hw_type, clid_len); | |
107 | ||
108 | if (strcmp(daemon->dhcp_buff, "*") != 0) | |
1f15b81d | 109 | lease_set_hostname(lease, daemon->dhcp_buff, 0); |
5aabfc78 SK |
110 | |
111 | /* set these correctly: the "old" events are generated later from | |
112 | the startup synthesised SIGHUP. */ | |
113 | lease->new = lease->changed = 0; | |
208b65c5 SK |
114 | } |
115 | ||
1f15b81d | 116 | #ifdef HAVE_SCRIPT |
208b65c5 SK |
117 | if (!daemon->lease_stream) |
118 | { | |
119 | int rc = 0; | |
9e4abcb5 | 120 | |
208b65c5 SK |
121 | /* shell returns 127 for "command not found", 126 for bad permissions. */ |
122 | if (!leasestream || (rc = pclose(leasestream)) == -1 || WEXITSTATUS(rc) == 127 || WEXITSTATUS(rc) == 126) | |
123 | { | |
124 | if (WEXITSTATUS(rc) == 127) | |
125 | errno = ENOENT; | |
126 | else if (WEXITSTATUS(rc) == 126) | |
127 | errno = EACCES; | |
5aabfc78 | 128 | die(_("cannot run lease-init script %s: %s"), daemon->lease_change_command, EC_FILE); |
208b65c5 SK |
129 | } |
130 | ||
131 | if (WEXITSTATUS(rc) != 0) | |
132 | { | |
133 | sprintf(daemon->dhcp_buff, "%d", WEXITSTATUS(rc)); | |
5aabfc78 | 134 | die(_("lease-init script returned exit code %s"), daemon->dhcp_buff, WEXITSTATUS(rc) + EC_INIT_OFFSET); |
208b65c5 | 135 | } |
9e4abcb5 | 136 | } |
1f15b81d | 137 | #endif |
7cebd20f SK |
138 | |
139 | /* Some leases may have expired */ | |
140 | file_dirty = 0; | |
141 | lease_prune(NULL, now); | |
142 | dns_dirty = 1; | |
44a2a316 SK |
143 | } |
144 | ||
5aabfc78 | 145 | void lease_update_from_configs(void) |
44a2a316 SK |
146 | { |
147 | /* changes to the config may change current leases. */ | |
148 | ||
149 | struct dhcp_lease *lease; | |
150 | struct dhcp_config *config; | |
b8187c80 SK |
151 | char *name; |
152 | ||
9e4abcb5 | 153 | for (lease = leases; lease; lease = lease->next) |
cdeda28f SK |
154 | if ((config = find_config(daemon->dhcp_conf, NULL, lease->clid, lease->clid_len, |
155 | lease->hwaddr, lease->hwaddr_len, lease->hwaddr_type, NULL)) && | |
b8187c80 SK |
156 | (config->flags & CONFIG_NAME) && |
157 | (!(config->flags & CONFIG_ADDR) || config->addr.s_addr == lease->addr.s_addr)) | |
9009d746 | 158 | lease_set_hostname(lease, config->hostname, 1); |
5aabfc78 | 159 | else if ((name = host_from_dns(lease->addr))) |
9009d746 | 160 | lease_set_hostname(lease, name, 1); /* updates auth flag only */ |
9e4abcb5 SK |
161 | } |
162 | ||
5aabfc78 | 163 | static void ourprintf(int *errp, char *format, ...) |
9e4abcb5 | 164 | { |
7cebd20f | 165 | va_list ap; |
5e9e0efb | 166 | |
7cebd20f SK |
167 | va_start(ap, format); |
168 | if (!(*errp) && vfprintf(daemon->lease_stream, format, ap) < 0) | |
169 | *errp = errno; | |
170 | va_end(ap); | |
171 | } | |
172 | ||
5aabfc78 | 173 | void lease_update_file(time_t now) |
7cebd20f SK |
174 | { |
175 | struct dhcp_lease *lease; | |
176 | time_t next_event; | |
177 | int i, err = 0; | |
178 | ||
208b65c5 | 179 | if (file_dirty != 0 && daemon->lease_stream) |
9e4abcb5 | 180 | { |
cdeda28f SK |
181 | errno = 0; |
182 | rewind(daemon->lease_stream); | |
183 | if (errno != 0 || ftruncate(fileno(daemon->lease_stream), 0) != 0) | |
7cebd20f | 184 | err = errno; |
9e4abcb5 SK |
185 | |
186 | for (lease = leases; lease; lease = lease->next) | |
187 | { | |
44a2a316 | 188 | #ifdef HAVE_BROKEN_RTC |
5aabfc78 | 189 | ourprintf(&err, "%u ", lease->length); |
44a2a316 | 190 | #else |
5aabfc78 | 191 | ourprintf(&err, "%lu ", (unsigned long)lease->expires); |
5e9e0efb | 192 | #endif |
7cebd20f | 193 | if (lease->hwaddr_type != ARPHRD_ETHER || lease->hwaddr_len == 0) |
5aabfc78 | 194 | ourprintf(&err, "%.2x-", lease->hwaddr_type); |
5e9e0efb SK |
195 | for (i = 0; i < lease->hwaddr_len; i++) |
196 | { | |
5aabfc78 | 197 | ourprintf(&err, "%.2x", lease->hwaddr[i]); |
7cebd20f | 198 | if (i != lease->hwaddr_len - 1) |
5aabfc78 | 199 | ourprintf(&err, ":"); |
5e9e0efb | 200 | } |
5aabfc78 SK |
201 | |
202 | ourprintf(&err, " %s ", inet_ntoa(lease->addr)); | |
1f15b81d SK |
203 | ourprintf(&err, "%s ", lease->hostname ? lease->hostname : "*"); |
204 | ||
0a852541 | 205 | if (lease->clid && lease->clid_len != 0) |
9e4abcb5 SK |
206 | { |
207 | for (i = 0; i < lease->clid_len - 1; i++) | |
5aabfc78 SK |
208 | ourprintf(&err, "%.2x:", lease->clid[i]); |
209 | ourprintf(&err, "%.2x\n", lease->clid[i]); | |
9e4abcb5 SK |
210 | } |
211 | else | |
5aabfc78 | 212 | ourprintf(&err, "*\n"); |
9e4abcb5 | 213 | } |
7cebd20f SK |
214 | |
215 | if (fflush(daemon->lease_stream) != 0 || | |
216 | fsync(fileno(daemon->lease_stream)) < 0) | |
217 | err = errno; | |
218 | ||
219 | if (!err) | |
220 | file_dirty = 0; | |
221 | } | |
222 | ||
223 | /* Set alarm for when the first lease expires + slop. */ | |
224 | for (next_event = 0, lease = leases; lease; lease = lease->next) | |
225 | if (lease->expires != 0 && | |
226 | (next_event == 0 || difftime(next_event, lease->expires + 10) > 0.0)) | |
227 | next_event = lease->expires + 10; | |
228 | ||
229 | if (err) | |
230 | { | |
231 | if (next_event == 0 || difftime(next_event, LEASE_RETRY + now) > 0.0) | |
232 | next_event = LEASE_RETRY + now; | |
233 | ||
7622fc06 | 234 | my_syslog(MS_DHCP | LOG_ERR, _("failed to write %s: %s (retry in %us)"), |
f2621c7f SK |
235 | daemon->lease_file, strerror(err), |
236 | (unsigned int)difftime(next_event, now)); | |
9e4abcb5 | 237 | } |
7cebd20f SK |
238 | |
239 | if (next_event != 0) | |
240 | alarm((unsigned)difftime(next_event, now)); | |
44a2a316 | 241 | } |
9e4abcb5 | 242 | |
5aabfc78 | 243 | void lease_update_dns(void) |
44a2a316 SK |
244 | { |
245 | struct dhcp_lease *lease; | |
246 | ||
824af85b | 247 | if (daemon->port != 0 && dns_dirty) |
9e4abcb5 SK |
248 | { |
249 | cache_unhash_dhcp(); | |
44a2a316 | 250 | |
9e4abcb5 SK |
251 | for (lease = leases; lease; lease = lease->next) |
252 | { | |
9009d746 SK |
253 | if (lease->fqdn) |
254 | cache_add_dhcp_entry(lease->fqdn, &lease->addr, lease->expires); | |
255 | ||
256 | if (!(daemon->options & OPT_DHCP_FQDN) && lease->hostname) | |
257 | cache_add_dhcp_entry(lease->hostname, &lease->addr, lease->expires); | |
9e4abcb5 SK |
258 | } |
259 | ||
260 | dns_dirty = 0; | |
261 | } | |
262 | } | |
263 | ||
264 | void lease_prune(struct dhcp_lease *target, time_t now) | |
265 | { | |
266 | struct dhcp_lease *lease, *tmp, **up; | |
267 | ||
268 | for (lease = leases, up = &leases; lease; lease = tmp) | |
269 | { | |
270 | tmp = lease->next; | |
271 | if ((lease->expires != 0 && difftime(now, lease->expires) > 0) || lease == target) | |
272 | { | |
5e9e0efb | 273 | file_dirty = 1; |
9e4abcb5 | 274 | if (lease->hostname) |
7cebd20f SK |
275 | dns_dirty = 1; |
276 | ||
277 | *up = lease->next; /* unlink */ | |
278 | ||
279 | /* Put on old_leases list 'till we | |
280 | can run the script */ | |
281 | lease->next = old_leases; | |
282 | old_leases = lease; | |
283 | ||
44a2a316 | 284 | leases_left++; |
9e4abcb5 SK |
285 | } |
286 | else | |
287 | up = &lease->next; | |
288 | } | |
289 | } | |
290 | ||
291 | ||
cdeda28f | 292 | struct dhcp_lease *lease_find_by_client(unsigned char *hwaddr, int hw_len, int hw_type, |
0a852541 | 293 | unsigned char *clid, int clid_len) |
9e4abcb5 | 294 | { |
9e4abcb5 SK |
295 | struct dhcp_lease *lease; |
296 | ||
0a852541 SK |
297 | if (clid) |
298 | for (lease = leases; lease; lease = lease->next) | |
299 | if (lease->clid && clid_len == lease->clid_len && | |
9e4abcb5 SK |
300 | memcmp(clid, lease->clid, clid_len) == 0) |
301 | return lease; | |
0a852541 SK |
302 | |
303 | for (lease = leases; lease; lease = lease->next) | |
304 | if ((!lease->clid || !clid) && | |
5e9e0efb | 305 | hw_len != 0 && |
cdeda28f SK |
306 | lease->hwaddr_len == hw_len && |
307 | lease->hwaddr_type == hw_type && | |
308 | memcmp(hwaddr, lease->hwaddr, hw_len) == 0) | |
0a852541 | 309 | return lease; |
9e4abcb5 SK |
310 | |
311 | return NULL; | |
312 | } | |
313 | ||
314 | struct dhcp_lease *lease_find_by_addr(struct in_addr addr) | |
315 | { | |
316 | struct dhcp_lease *lease; | |
317 | ||
318 | for (lease = leases; lease; lease = lease->next) | |
319 | if (lease->addr.s_addr == addr.s_addr) | |
320 | return lease; | |
321 | ||
322 | return NULL; | |
323 | } | |
324 | ||
325 | ||
7cebd20f | 326 | struct dhcp_lease *lease_allocate(struct in_addr addr) |
9e4abcb5 SK |
327 | { |
328 | struct dhcp_lease *lease; | |
5aabfc78 | 329 | if (!leases_left || !(lease = whine_malloc(sizeof(struct dhcp_lease)))) |
9e4abcb5 SK |
330 | return NULL; |
331 | ||
7cebd20f SK |
332 | memset(lease, 0, sizeof(struct dhcp_lease)); |
333 | lease->new = 1; | |
9e4abcb5 | 334 | lease->addr = addr; |
1b7ecd11 | 335 | lease->hwaddr_len = 256; /* illegal value */ |
9e4abcb5 | 336 | lease->expires = 1; |
5e9e0efb SK |
337 | #ifdef HAVE_BROKEN_RTC |
338 | lease->length = 0xffffffff; /* illegal value */ | |
339 | #endif | |
9e4abcb5 SK |
340 | lease->next = leases; |
341 | leases = lease; | |
342 | ||
5e9e0efb | 343 | file_dirty = 1; |
44a2a316 | 344 | leases_left--; |
9e4abcb5 SK |
345 | |
346 | return lease; | |
347 | } | |
348 | ||
5e9e0efb | 349 | void lease_set_expires(struct dhcp_lease *lease, unsigned int len, time_t now) |
9e4abcb5 | 350 | { |
5e9e0efb SK |
351 | time_t exp = now + (time_t)len; |
352 | ||
353 | if (len == 0xffffffff) | |
354 | { | |
355 | exp = 0; | |
356 | len = 0; | |
357 | } | |
358 | ||
9e4abcb5 | 359 | if (exp != lease->expires) |
0a852541 | 360 | { |
0a852541 | 361 | dns_dirty = 1; |
5e9e0efb SK |
362 | lease->expires = exp; |
363 | #ifndef HAVE_BROKEN_RTC | |
208b65c5 | 364 | lease->aux_changed = file_dirty = 1; |
5e9e0efb | 365 | #endif |
0a852541 | 366 | } |
5e9e0efb SK |
367 | |
368 | #ifdef HAVE_BROKEN_RTC | |
369 | if (len != lease->length) | |
370 | { | |
371 | lease->length = len; | |
208b65c5 | 372 | lease->aux_changed = file_dirty = 1; |
5e9e0efb SK |
373 | } |
374 | #endif | |
375 | } | |
9e4abcb5 | 376 | |
7cebd20f | 377 | void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr, |
cdeda28f | 378 | unsigned char *clid, int hw_len, int hw_type, int clid_len) |
9e4abcb5 | 379 | { |
cdeda28f SK |
380 | if (hw_len != lease->hwaddr_len || |
381 | hw_type != lease->hwaddr_type || | |
7cebd20f | 382 | (hw_len != 0 && memcmp(lease->hwaddr, hwaddr, hw_len) != 0)) |
9e4abcb5 | 383 | { |
cdeda28f SK |
384 | memcpy(lease->hwaddr, hwaddr, hw_len); |
385 | lease->hwaddr_len = hw_len; | |
386 | lease->hwaddr_type = hw_type; | |
208b65c5 | 387 | lease->changed = file_dirty = 1; /* run script on change */ |
9e4abcb5 | 388 | } |
0a852541 SK |
389 | |
390 | /* only update clid when one is available, stops packets | |
391 | without a clid removing the record. Lease init uses | |
392 | clid_len == 0 for no clid. */ | |
393 | if (clid_len != 0 && clid) | |
394 | { | |
395 | if (!lease->clid) | |
396 | lease->clid_len = 0; | |
397 | ||
398 | if (lease->clid_len != clid_len) | |
399 | { | |
208b65c5 | 400 | lease->aux_changed = file_dirty = 1; |
5aabfc78 SK |
401 | free(lease->clid); |
402 | if (!(lease->clid = whine_malloc(clid_len))) | |
7cebd20f | 403 | return; |
0a852541 SK |
404 | } |
405 | else if (memcmp(lease->clid, clid, clid_len) != 0) | |
208b65c5 SK |
406 | lease->aux_changed = file_dirty = 1; |
407 | ||
0a852541 SK |
408 | lease->clid_len = clid_len; |
409 | memcpy(lease->clid, clid, clid_len); | |
410 | } | |
208b65c5 | 411 | |
9e4abcb5 SK |
412 | } |
413 | ||
9009d746 SK |
414 | static void kill_name(struct dhcp_lease *lease) |
415 | { | |
416 | /* run script to say we lost our old name */ | |
417 | ||
418 | /* this shouldn't happen unless updates are very quick and the | |
419 | script very slow, we just avoid a memory leak if it does. */ | |
420 | free(lease->old_hostname); | |
421 | ||
422 | /* If we know the fqdn, pass that. The helper will derive the | |
423 | unqualified name from it, free the unqulaified name here. */ | |
424 | ||
425 | if (lease->fqdn) | |
426 | { | |
427 | lease->old_hostname = lease->fqdn; | |
428 | free(lease->hostname); | |
429 | } | |
430 | else | |
431 | lease->old_hostname = lease->hostname; | |
432 | ||
433 | lease->hostname = lease->fqdn = NULL; | |
434 | } | |
435 | ||
436 | void lease_set_hostname(struct dhcp_lease *lease, char *name, int auth) | |
9e4abcb5 SK |
437 | { |
438 | struct dhcp_lease *lease_tmp; | |
439 | char *new_name = NULL, *new_fqdn = NULL; | |
9009d746 | 440 | |
a222641c | 441 | if (lease->hostname && name && hostname_isequal(lease->hostname, name)) |
b8187c80 SK |
442 | { |
443 | lease->auth_name = auth; | |
444 | return; | |
445 | } | |
7cebd20f | 446 | |
9e4abcb5 SK |
447 | if (!name && !lease->hostname) |
448 | return; | |
449 | ||
450 | /* If a machine turns up on a new net without dropping the old lease, | |
451 | or two machines claim the same name, then we end up with two interfaces with | |
b8187c80 SK |
452 | the same name. Check for that here and remove the name from the old lease. |
453 | Don't allow a name from the client to override a name from dnsmasq config. */ | |
9e4abcb5 SK |
454 | |
455 | if (name) | |
456 | { | |
9009d746 SK |
457 | if ((new_name = whine_malloc(strlen(name) + 1))) |
458 | { | |
459 | char *suffix = get_domain(lease->addr); | |
460 | strcpy(new_name, name); | |
461 | if (suffix && (new_fqdn = whine_malloc(strlen(new_name) + strlen(suffix) + 2))) | |
462 | { | |
463 | strcpy(new_fqdn, name); | |
464 | strcat(new_fqdn, "."); | |
465 | strcat(new_fqdn, suffix); | |
466 | } | |
467 | } | |
468 | ||
469 | /* Depending on mode, we check either unqualified name or FQDN. */ | |
9e4abcb5 | 470 | for (lease_tmp = leases; lease_tmp; lease_tmp = lease_tmp->next) |
9e4abcb5 | 471 | { |
9009d746 SK |
472 | if (daemon->options & OPT_DHCP_FQDN) |
473 | { | |
474 | if (!new_fqdn || !lease_tmp->fqdn || !hostname_isequal(lease_tmp->fqdn, new_fqdn) ) | |
475 | continue; | |
476 | } | |
477 | else | |
478 | { | |
479 | if (!new_name || !lease_tmp->hostname || !hostname_isequal(lease_tmp->hostname, new_name) ) | |
480 | continue; | |
481 | } | |
482 | ||
483 | if (lease_tmp->auth_name && !auth) | |
484 | { | |
485 | free(new_name); | |
486 | free(new_fqdn); | |
487 | return; | |
488 | } | |
489 | ||
490 | kill_name(lease_tmp); | |
491 | break; | |
9e4abcb5 SK |
492 | } |
493 | } | |
494 | ||
495 | if (lease->hostname) | |
9009d746 | 496 | kill_name(lease); |
1697269c | 497 | |
9e4abcb5 SK |
498 | lease->hostname = new_name; |
499 | lease->fqdn = new_fqdn; | |
b8187c80 | 500 | lease->auth_name = auth; |
9e4abcb5 | 501 | |
5e9e0efb | 502 | file_dirty = 1; |
7cebd20f | 503 | dns_dirty = 1; |
208b65c5 | 504 | lease->changed = 1; /* run script on change */ |
7cebd20f SK |
505 | } |
506 | ||
824af85b SK |
507 | void lease_set_interface(struct dhcp_lease *lease, int interface) |
508 | { | |
509 | if (lease->last_interface == interface) | |
510 | return; | |
511 | ||
512 | lease->last_interface = interface; | |
513 | lease->changed = 1; | |
514 | } | |
515 | ||
5aabfc78 SK |
516 | void rerun_scripts(void) |
517 | { | |
518 | struct dhcp_lease *lease; | |
519 | ||
520 | for (lease = leases; lease; lease = lease->next) | |
521 | lease->changed = 1; | |
522 | } | |
523 | ||
7cebd20f SK |
524 | /* deleted leases get transferred to the old_leases list. |
525 | remove them here, after calling the lease change | |
1697269c SK |
526 | script. Also run the lease change script on new/modified leases. |
527 | ||
528 | Return zero if nothing to do. */ | |
5aabfc78 | 529 | int do_script_run(time_t now) |
7cebd20f SK |
530 | { |
531 | struct dhcp_lease *lease; | |
9e4abcb5 | 532 | |
9009d746 SK |
533 | #ifdef HAVE_DBUS |
534 | /* If we're going to be sending DBus signals, but the connection is not yet up, | |
535 | delay everything until it is. */ | |
536 | if ((daemon->options & OPT_DBUS) && !daemon->dbus) | |
537 | return 0; | |
538 | #endif | |
539 | ||
1697269c | 540 | if (old_leases) |
7cebd20f | 541 | { |
7cebd20f | 542 | lease = old_leases; |
1697269c SK |
543 | |
544 | /* If the lease still has an old_hostname, do the "old" action on that first */ | |
545 | if (lease->old_hostname) | |
546 | { | |
1f15b81d | 547 | #ifdef HAVE_SCRIPT |
5aabfc78 SK |
548 | queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now); |
549 | #endif | |
1697269c SK |
550 | free(lease->old_hostname); |
551 | lease->old_hostname = NULL; | |
552 | return 1; | |
553 | } | |
554 | else | |
555 | { | |
9009d746 | 556 | kill_name(lease); |
1f15b81d | 557 | #ifdef HAVE_SCRIPT |
9009d746 | 558 | queue_script(ACTION_DEL, lease, lease->old_hostname, now); |
1f15b81d SK |
559 | #endif |
560 | #ifdef HAVE_DBUS | |
561 | emit_dbus_signal(ACTION_DEL, lease, lease->old_hostname); | |
5aabfc78 | 562 | #endif |
1697269c SK |
563 | old_leases = lease->next; |
564 | ||
9009d746 | 565 | free(lease->old_hostname); |
5aabfc78 SK |
566 | free(lease->clid); |
567 | free(lease->vendorclass); | |
568 | free(lease->userclass); | |
1f15b81d | 569 | free(lease->supplied_hostname); |
1697269c SK |
570 | free(lease); |
571 | ||
572 | return 1; | |
573 | } | |
7cebd20f | 574 | } |
1697269c SK |
575 | |
576 | /* make sure we announce the loss of a hostname before its new location. */ | |
577 | for (lease = leases; lease; lease = lease->next) | |
578 | if (lease->old_hostname) | |
579 | { | |
1f15b81d | 580 | #ifdef HAVE_SCRIPT |
5aabfc78 SK |
581 | queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now); |
582 | #endif | |
1697269c SK |
583 | free(lease->old_hostname); |
584 | lease->old_hostname = NULL; | |
585 | return 1; | |
586 | } | |
587 | ||
7cebd20f | 588 | for (lease = leases; lease; lease = lease->next) |
208b65c5 SK |
589 | if (lease->new || lease->changed || |
590 | (lease->aux_changed && (daemon->options & OPT_LEASE_RO))) | |
7cebd20f | 591 | { |
1f15b81d | 592 | #ifdef HAVE_SCRIPT |
9009d746 SK |
593 | queue_script(lease->new ? ACTION_ADD : ACTION_OLD, lease, |
594 | lease->fqdn ? lease->fqdn : lease->hostname, now); | |
1f15b81d SK |
595 | #endif |
596 | #ifdef HAVE_DBUS | |
597 | emit_dbus_signal(lease->new ? ACTION_ADD : ACTION_OLD, lease, | |
598 | lease->fqdn ? lease->fqdn : lease->hostname); | |
5aabfc78 | 599 | #endif |
208b65c5 | 600 | lease->new = lease->changed = lease->aux_changed = 0; |
1697269c SK |
601 | |
602 | /* these are used for the "add" call, then junked, since they're not in the database */ | |
5aabfc78 SK |
603 | free(lease->vendorclass); |
604 | lease->vendorclass = NULL; | |
1697269c | 605 | |
5aabfc78 SK |
606 | free(lease->userclass); |
607 | lease->userclass = NULL; | |
1f15b81d SK |
608 | |
609 | free(lease->supplied_hostname); | |
610 | lease->supplied_hostname = NULL; | |
611 | ||
1697269c | 612 | return 1; |
7cebd20f | 613 | } |
1697269c SK |
614 | |
615 | return 0; /* nothing to do */ | |
7cebd20f | 616 | } |
7622fc06 SK |
617 | |
618 | #endif | |
7cebd20f SK |
619 | |
620 | ||
621 | ||
9e4abcb5 | 622 |