Imported Upstream version 2.88
[platform/upstream/dnsmasq.git] / src / lease.c
1 /* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
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
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,
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.
12      
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/>.
15 */
16
17 #include "dnsmasq.h"
18
19 #ifdef HAVE_DHCP
20
21 static struct dhcp_lease *leases = NULL, *old_leases = NULL;
22 static int dns_dirty, file_dirty, leases_left;
23
24 static int read_leases(time_t now, FILE *leasestream)
25 {
26   unsigned long ei;
27   union all_addr addr;
28   struct dhcp_lease *lease;
29   int clid_len, hw_len, hw_type;
30   int items;
31   char *domain = NULL;
32
33   *daemon->dhcp_buff3 = *daemon->dhcp_buff2 = '\0';
34
35   /* client-id max length is 255 which is 255*2 digits + 254 colons
36      borrow DNS packet buffer which is always larger than 1000 bytes
37
38      Check various buffers are big enough for the code below */
39
40 #if (DHCP_BUFF_SZ < 255) || (MAXDNAME < 64) || (PACKETSZ+MAXDNAME+RRFIXEDSZ  < 764)
41 # error Buffer size breakage in leasefile parsing.
42 #endif
43
44     while ((items=fscanf(leasestream, "%255s %255s", daemon->dhcp_buff3, daemon->dhcp_buff2)) == 2)
45       {
46         *daemon->namebuff = *daemon->dhcp_buff = *daemon->packet = '\0';
47         hw_len = hw_type = clid_len = 0;
48         
49 #ifdef HAVE_DHCP6
50         if (strcmp(daemon->dhcp_buff3, "duid") == 0)
51           {
52             daemon->duid_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, 130, NULL, NULL);
53             if (daemon->duid_len < 0)
54               return 0;
55             daemon->duid = safe_malloc(daemon->duid_len);
56             memcpy(daemon->duid, daemon->dhcp_buff2, daemon->duid_len);
57             continue;
58           }
59 #endif
60         
61         if (fscanf(leasestream, " %64s %255s %764s",
62                    daemon->namebuff, daemon->dhcp_buff, daemon->packet) != 3)
63           {
64             my_syslog(MS_DHCP | LOG_WARNING, _("ignoring invalid line in lease database: %s %s %s %s ..."),
65                       daemon->dhcp_buff3, daemon->dhcp_buff2,
66                       daemon->namebuff, daemon->dhcp_buff);
67             continue;
68           }
69                 
70         if (inet_pton(AF_INET, daemon->namebuff, &addr.addr4))
71           {
72             if ((lease = lease4_allocate(addr.addr4)))
73               domain = get_domain(lease->addr);
74             
75             hw_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, DHCP_CHADDR_MAX, NULL, &hw_type);
76             /* For backwards compatibility, no explicit MAC address type means ether. */
77             if (hw_type == 0 && hw_len != 0)
78               hw_type = ARPHRD_ETHER; 
79           }
80 #ifdef HAVE_DHCP6
81         else if (inet_pton(AF_INET6, daemon->namebuff, &addr.addr6))
82           {
83             char *s = daemon->dhcp_buff2;
84             int lease_type = LEASE_NA;
85
86             if (s[0] == 'T')
87               {
88                 lease_type = LEASE_TA;
89                 s++;
90               }
91             
92             if ((lease = lease6_allocate(&addr.addr6, lease_type)))
93               {
94                 lease_set_iaid(lease, strtoul(s, NULL, 10));
95                 domain = get_domain6(&lease->addr6);
96               }
97           }
98 #endif
99         else
100           {
101             my_syslog(MS_DHCP | LOG_WARNING, _("ignoring invalid line in lease database, bad address: %s"),
102                       daemon->namebuff);
103             continue;
104           }
105         
106
107         if (!lease)
108           die (_("too many stored leases"), NULL, EC_MISC);
109
110         if (strcmp(daemon->packet, "*") != 0)
111           clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL);
112         
113         lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet, 
114                          hw_len, hw_type, clid_len, now, 0);
115         
116         if (strcmp(daemon->dhcp_buff, "*") !=  0)
117           lease_set_hostname(lease, daemon->dhcp_buff, 0, domain, NULL);
118
119         ei = atol(daemon->dhcp_buff3);
120
121 #ifdef HAVE_BROKEN_RTC
122         if (ei != 0)
123           lease->expires = (time_t)ei + now;
124         else
125           lease->expires = (time_t)0;
126         lease->length = ei;
127 #else
128         /* strictly time_t is opaque, but this hack should work on all sane systems,
129            even when sizeof(time_t) == 8 */
130         lease->expires = (time_t)ei;
131 #endif
132         
133         /* set these correctly: the "old" events are generated later from
134            the startup synthesised SIGHUP. */
135         lease->flags &= ~(LEASE_NEW | LEASE_CHANGED);
136         
137         *daemon->dhcp_buff3 = *daemon->dhcp_buff2 = '\0';
138       }
139     
140     return (items == 0 || items == EOF);
141 }
142
143 void lease_init(time_t now)
144 {
145   FILE *leasestream;
146
147   leases_left = daemon->dhcp_max;
148
149   if (option_bool(OPT_LEASE_RO))
150     {
151       /* run "<lease_change_script> init" once to get the
152          initial state of the database. If leasefile-ro is
153          set without a script, we just do without any
154          lease database. */
155 #ifdef HAVE_SCRIPT
156       if (daemon->lease_change_command)
157         {
158           strcpy(daemon->dhcp_buff, daemon->lease_change_command);
159           strcat(daemon->dhcp_buff, " init");
160           leasestream = popen(daemon->dhcp_buff, "r");
161         }
162       else
163 #endif
164         {
165           file_dirty = dns_dirty = 0;
166           return;
167         }
168
169     }
170   else
171     {
172       /* NOTE: need a+ mode to create file if it doesn't exist */
173       leasestream = daemon->lease_stream = fopen(daemon->lease_file, "a+");
174
175       if (!leasestream)
176         die(_("cannot open or create lease file %s: %s"), daemon->lease_file, EC_FILE);
177
178       /* a+ mode leaves pointer at end. */
179       rewind(leasestream);
180     }
181
182   if (leasestream)
183     {
184       if (!read_leases(now, leasestream))
185         my_syslog(MS_DHCP | LOG_ERR, _("failed to parse lease database cleanly"));
186       
187       if (ferror(leasestream))
188         die(_("failed to read lease file %s: %s"), daemon->lease_file, EC_FILE);
189     }
190   
191 #ifdef HAVE_SCRIPT
192   if (!daemon->lease_stream)
193     {
194       int rc = 0;
195
196       /* shell returns 127 for "command not found", 126 for bad permissions. */
197       if (!leasestream || (rc = pclose(leasestream)) == -1 || WEXITSTATUS(rc) == 127 || WEXITSTATUS(rc) == 126)
198         {
199           if (WEXITSTATUS(rc) == 127)
200             errno = ENOENT;
201           else if (WEXITSTATUS(rc) == 126)
202             errno = EACCES;
203
204           die(_("cannot run lease-init script %s: %s"), daemon->lease_change_command, EC_FILE);
205         }
206       
207       if (WEXITSTATUS(rc) != 0)
208         {
209           sprintf(daemon->dhcp_buff, "%d", WEXITSTATUS(rc));
210           die(_("lease-init script returned exit code %s"), daemon->dhcp_buff, WEXITSTATUS(rc) + EC_INIT_OFFSET);
211         }
212     }
213 #endif
214
215   /* Some leases may have expired */
216   file_dirty = 0;
217   lease_prune(NULL, now);
218   dns_dirty = 1;
219 }
220
221 void lease_update_from_configs(void)
222 {
223   /* changes to the config may change current leases. */
224   
225   struct dhcp_lease *lease;
226   struct dhcp_config *config;
227   char *name;
228   
229   for (lease = leases; lease; lease = lease->next)
230     if (lease->flags & (LEASE_TA | LEASE_NA))
231       continue;
232     else if ((config = find_config(daemon->dhcp_conf, NULL, lease->clid, lease->clid_len, 
233                                    lease->hwaddr, lease->hwaddr_len, lease->hwaddr_type, NULL, NULL)) && 
234              (config->flags & CONFIG_NAME) &&
235              (!(config->flags & CONFIG_ADDR) || config->addr.s_addr == lease->addr.s_addr))
236       lease_set_hostname(lease, config->hostname, 1, get_domain(lease->addr), NULL);
237     else if ((name = host_from_dns(lease->addr)))
238       lease_set_hostname(lease, name, 1, get_domain(lease->addr), NULL); /* updates auth flag only */
239 }
240
241 static void ourprintf(int *errp, char *format, ...)
242 {
243   va_list ap;
244   
245   va_start(ap, format);
246   if (!(*errp) && vfprintf(daemon->lease_stream, format, ap) < 0)
247     *errp = errno;
248   va_end(ap);
249 }
250
251 void lease_update_file(time_t now)
252 {
253   struct dhcp_lease *lease;
254   time_t next_event;
255   int i, err = 0;
256
257   if (file_dirty != 0 && daemon->lease_stream)
258     {
259       errno = 0;
260       rewind(daemon->lease_stream);
261       if (errno != 0 || ftruncate(fileno(daemon->lease_stream), 0) != 0)
262         err = errno;
263       
264       for (lease = leases; lease; lease = lease->next)
265         {
266
267 #ifdef HAVE_DHCP6
268           if (lease->flags & (LEASE_TA | LEASE_NA))
269             continue;
270 #endif
271
272 #ifdef HAVE_BROKEN_RTC
273           ourprintf(&err, "%u ", lease->length);
274 #else
275           ourprintf(&err, "%lu ", (unsigned long)lease->expires);
276 #endif
277
278           if (lease->hwaddr_type != ARPHRD_ETHER || lease->hwaddr_len == 0) 
279             ourprintf(&err, "%.2x-", lease->hwaddr_type);
280           for (i = 0; i < lease->hwaddr_len; i++)
281             {
282               ourprintf(&err, "%.2x", lease->hwaddr[i]);
283               if (i != lease->hwaddr_len - 1)
284                 ourprintf(&err, ":");
285             }
286           
287           inet_ntop(AF_INET, &lease->addr, daemon->addrbuff, ADDRSTRLEN); 
288
289           ourprintf(&err, " %s ", daemon->addrbuff);
290           ourprintf(&err, "%s ", lease->hostname ? lease->hostname : "*");
291                   
292           if (lease->clid && lease->clid_len != 0)
293             {
294               for (i = 0; i < lease->clid_len - 1; i++)
295                 ourprintf(&err, "%.2x:", lease->clid[i]);
296               ourprintf(&err, "%.2x\n", lease->clid[i]);
297             }
298           else
299             ourprintf(&err, "*\n");       
300         }
301       
302 #ifdef HAVE_DHCP6  
303       if (daemon->duid)
304         {
305           ourprintf(&err, "duid ");
306           for (i = 0; i < daemon->duid_len - 1; i++)
307             ourprintf(&err, "%.2x:", daemon->duid[i]);
308           ourprintf(&err, "%.2x\n", daemon->duid[i]);
309           
310           for (lease = leases; lease; lease = lease->next)
311             {
312               
313               if (!(lease->flags & (LEASE_TA | LEASE_NA)))
314                 continue;
315
316 #ifdef HAVE_BROKEN_RTC
317               ourprintf(&err, "%u ", lease->length);
318 #else
319               ourprintf(&err, "%lu ", (unsigned long)lease->expires);
320 #endif
321     
322               inet_ntop(AF_INET6, &lease->addr6, daemon->addrbuff, ADDRSTRLEN);
323          
324               ourprintf(&err, "%s%u %s ", (lease->flags & LEASE_TA) ? "T" : "",
325                         lease->iaid, daemon->addrbuff);
326               ourprintf(&err, "%s ", lease->hostname ? lease->hostname : "*");
327               
328               if (lease->clid && lease->clid_len != 0)
329                 {
330                   for (i = 0; i < lease->clid_len - 1; i++)
331                     ourprintf(&err, "%.2x:", lease->clid[i]);
332                   ourprintf(&err, "%.2x\n", lease->clid[i]);
333                 }
334               else
335                 ourprintf(&err, "*\n");   
336             }
337         }
338 #endif      
339           
340       if (fflush(daemon->lease_stream) != 0 ||
341           fsync(fileno(daemon->lease_stream)) < 0)
342         err = errno;
343       
344       if (!err)
345         file_dirty = 0;
346     }
347   
348   /* Set alarm for when the first lease expires. */
349   next_event = 0;
350
351 #ifdef HAVE_DHCP6
352   /* do timed RAs and determine when the next is, also pings to potential SLAAC addresses */
353   if (daemon->doing_ra)
354     {
355       time_t event;
356       
357       if ((event = periodic_slaac(now, leases)) != 0)
358         {
359           if (next_event == 0 || difftime(next_event, event) > 0.0)
360             next_event = event;
361         }
362       
363       if ((event = periodic_ra(now)) != 0)
364         {
365           if (next_event == 0 || difftime(next_event, event) > 0.0)
366             next_event = event;
367         }
368     }
369 #endif
370
371   for (lease = leases; lease; lease = lease->next)
372     if (lease->expires != 0 &&
373         (next_event == 0 || difftime(next_event, lease->expires) > 0.0))
374       next_event = lease->expires;
375    
376   if (err)
377     {
378       if (next_event == 0 || difftime(next_event, LEASE_RETRY + now) > 0.0)
379         next_event = LEASE_RETRY + now;
380       
381       my_syslog(MS_DHCP | LOG_ERR, _("failed to write %s: %s (retry in %u s)"), 
382                 daemon->lease_file, strerror(err),
383                 (unsigned int)difftime(next_event, now));
384     }
385
386   send_alarm(next_event, now);
387 }
388
389
390 static int find_interface_v4(struct in_addr local, int if_index, char *label,
391                              struct in_addr netmask, struct in_addr broadcast, void *vparam)
392 {
393   struct dhcp_lease *lease;
394   int prefix = netmask_length(netmask);
395
396   (void) label;
397   (void) broadcast;
398   (void) vparam;
399
400   for (lease = leases; lease; lease = lease->next)
401     if (!(lease->flags & (LEASE_TA | LEASE_NA)) &&
402         is_same_net(local, lease->addr, netmask) && 
403         prefix > lease->new_prefixlen) 
404       {
405         lease->new_interface = if_index;
406         lease->new_prefixlen = prefix;
407       }
408
409   return 1;
410 }
411
412 #ifdef HAVE_DHCP6
413 static int find_interface_v6(struct in6_addr *local,  int prefix,
414                              int scope, int if_index, int flags, 
415                              int preferred, int valid, void *vparam)
416 {
417   struct dhcp_lease *lease;
418
419   (void)scope;
420   (void)flags;
421   (void)preferred;
422   (void)valid;
423   (void)vparam;
424
425   for (lease = leases; lease; lease = lease->next)
426     if ((lease->flags & (LEASE_TA | LEASE_NA)))
427       if (is_same_net6(local, &lease->addr6, prefix) && prefix > lease->new_prefixlen) {
428         /* save prefix length for comparison, as we might get shorter matching
429          * prefix in upcoming netlink GETADDR responses
430          * */
431         lease->new_interface = if_index;
432         lease->new_prefixlen = prefix;
433       }
434
435   return 1;
436 }
437
438 void lease_ping_reply(struct in6_addr *sender, unsigned char *packet, char *interface)
439 {
440   /* We may be doing RA but not DHCPv4, in which case the lease
441      database may not exist and we have nothing to do anyway */
442   if (daemon->dhcp)
443     slaac_ping_reply(sender, packet, interface, leases);
444 }
445
446 void lease_update_slaac(time_t now)
447 {
448   /* Called when we construct a new RA-names context, to add putative
449      new SLAAC addresses to existing leases. */
450
451   struct dhcp_lease *lease;
452   
453   if (daemon->dhcp)
454     for (lease = leases; lease; lease = lease->next)
455       slaac_add_addrs(lease, now, 0);
456 }
457
458 #endif
459
460
461 /* Find interfaces associated with leases at start-up. This gets updated as
462    we do DHCP transactions, but information about directly-connected subnets
463    is useful from scrips and necessary for determining SLAAC addresses from
464    start-time. */
465 void lease_find_interfaces(time_t now)
466 {
467   struct dhcp_lease *lease;
468   
469   for (lease = leases; lease; lease = lease->next)
470     lease->new_prefixlen = lease->new_interface = 0;
471
472   iface_enumerate(AF_INET, &now, find_interface_v4);
473 #ifdef HAVE_DHCP6
474   iface_enumerate(AF_INET6, &now, find_interface_v6);
475 #endif
476
477   for (lease = leases; lease; lease = lease->next)
478     if (lease->new_interface != 0) 
479       lease_set_interface(lease, lease->new_interface, now);
480 }
481
482 #ifdef HAVE_DHCP6
483 void lease_make_duid(time_t now)
484 {
485   /* If we're not doing DHCPv6, and there are not v6 leases, don't add the DUID to the database */
486   if (!daemon->duid && daemon->doing_dhcp6)
487     {
488       file_dirty = 1;
489       make_duid(now);
490     }
491 }
492 #endif
493
494
495
496
497 void lease_update_dns(int force)
498 {
499   struct dhcp_lease *lease;
500
501   if (daemon->port != 0 && (dns_dirty || force))
502     {
503 #ifndef HAVE_BROKEN_RTC
504       /* force transfer to authoritative secondaries */
505       daemon->soa_sn++;
506 #endif
507       
508       cache_unhash_dhcp();
509
510       for (lease = leases; lease; lease = lease->next)
511         {
512           int prot = AF_INET;
513           
514 #ifdef HAVE_DHCP6
515           if (lease->flags & (LEASE_TA | LEASE_NA))
516             prot = AF_INET6;
517           else if (lease->hostname || lease->fqdn)
518             {
519               struct slaac_address *slaac;
520
521               for (slaac = lease->slaac_address; slaac; slaac = slaac->next)
522                 if (slaac->backoff == 0)
523                   {
524                     if (lease->fqdn)
525                       cache_add_dhcp_entry(lease->fqdn, AF_INET6, (union all_addr *)&slaac->addr, lease->expires);
526                     if (!option_bool(OPT_DHCP_FQDN) && lease->hostname)
527                       cache_add_dhcp_entry(lease->hostname, AF_INET6, (union all_addr *)&slaac->addr, lease->expires);
528                   }
529             }
530           
531           if (lease->fqdn)
532             cache_add_dhcp_entry(lease->fqdn, prot, 
533                                  prot == AF_INET ? (union all_addr *)&lease->addr : (union all_addr *)&lease->addr6,
534                                  lease->expires);
535              
536           if (!option_bool(OPT_DHCP_FQDN) && lease->hostname)
537             cache_add_dhcp_entry(lease->hostname, prot, 
538                                  prot == AF_INET ? (union all_addr *)&lease->addr : (union all_addr *)&lease->addr6, 
539                                  lease->expires);
540        
541 #else
542           if (lease->fqdn)
543             cache_add_dhcp_entry(lease->fqdn, prot, (union all_addr *)&lease->addr, lease->expires);
544           
545           if (!option_bool(OPT_DHCP_FQDN) && lease->hostname)
546             cache_add_dhcp_entry(lease->hostname, prot, (union all_addr *)&lease->addr, lease->expires);
547 #endif
548         }
549       
550       dns_dirty = 0;
551     }
552 }
553
554 void lease_prune(struct dhcp_lease *target, time_t now)
555 {
556   struct dhcp_lease *lease, *tmp, **up;
557
558   for (lease = leases, up = &leases; lease; lease = tmp)
559     {
560       tmp = lease->next;
561       if ((lease->expires != 0 && difftime(now, lease->expires) >= 0) || lease == target)
562         {
563           file_dirty = 1;
564           if (lease->hostname)
565             dns_dirty = 1;
566
567           daemon->metrics[lease->addr.s_addr ? METRIC_LEASES_PRUNED_4 : METRIC_LEASES_PRUNED_6]++;
568
569           *up = lease->next; /* unlink */
570           
571           /* Put on old_leases list 'till we
572              can run the script */
573           lease->next = old_leases;
574           old_leases = lease;
575           
576           leases_left++;
577         }
578       else
579         up = &lease->next;
580     }
581
582         
583   
584 struct dhcp_lease *lease_find_by_client(unsigned char *hwaddr, int hw_len, int hw_type,
585                                         unsigned char *clid, int clid_len)
586 {
587   struct dhcp_lease *lease;
588
589   if (clid)
590     for (lease = leases; lease; lease = lease->next)
591       {
592 #ifdef HAVE_DHCP6
593         if (lease->flags & (LEASE_TA | LEASE_NA))
594           continue;
595 #endif
596         if (lease->clid && clid_len == lease->clid_len &&
597             memcmp(clid, lease->clid, clid_len) == 0)
598           return lease;
599       }
600   
601   for (lease = leases; lease; lease = lease->next)      
602     {
603 #ifdef HAVE_DHCP6
604       if (lease->flags & (LEASE_TA | LEASE_NA))
605         continue;
606 #endif   
607       if ((!lease->clid || !clid) && 
608           hw_len != 0 && 
609           lease->hwaddr_len == hw_len &&
610           lease->hwaddr_type == hw_type &&
611           memcmp(hwaddr, lease->hwaddr, hw_len) == 0)
612         return lease;
613     }
614
615   return NULL;
616 }
617
618 struct dhcp_lease *lease_find_by_addr(struct in_addr addr)
619 {
620   struct dhcp_lease *lease;
621
622   for (lease = leases; lease; lease = lease->next)
623     {
624 #ifdef HAVE_DHCP6
625       if (lease->flags & (LEASE_TA | LEASE_NA))
626         continue;
627 #endif  
628       if (lease->addr.s_addr == addr.s_addr)
629         return lease;
630     }
631
632   return NULL;
633 }
634
635 #ifdef HAVE_DHCP6
636 /* find address for {CLID, IAID, address} */
637 struct dhcp_lease *lease6_find(unsigned char *clid, int clid_len, 
638                                int lease_type, unsigned int iaid,
639                                struct in6_addr *addr)
640 {
641   struct dhcp_lease *lease;
642   
643   for (lease = leases; lease; lease = lease->next)
644     {
645       if (!(lease->flags & lease_type) || lease->iaid != iaid)
646         continue;
647
648       if (!IN6_ARE_ADDR_EQUAL(&lease->addr6, addr))
649         continue;
650       
651       if ((clid_len != lease->clid_len ||
652            memcmp(clid, lease->clid, clid_len) != 0))
653         continue;
654       
655       return lease;
656     }
657   
658   return NULL;
659 }
660
661 /* reset "USED flags */
662 void lease6_reset(void)
663 {
664   struct dhcp_lease *lease;
665   
666   for (lease = leases; lease; lease = lease->next)
667     lease->flags &= ~LEASE_USED;
668 }
669
670 /* enumerate all leases belonging to {CLID, IAID} */
671 struct dhcp_lease *lease6_find_by_client(struct dhcp_lease *first, int lease_type,
672                                          unsigned char *clid, int clid_len,
673                                          unsigned int iaid)
674 {
675   struct dhcp_lease *lease;
676
677   if (!first)
678     first = leases;
679   else
680     first = first->next;
681
682   for (lease = first; lease; lease = lease->next)
683     {
684       if (lease->flags & LEASE_USED)
685         continue;
686
687       if (!(lease->flags & lease_type) || lease->iaid != iaid)
688         continue;
689  
690       if ((clid_len != lease->clid_len ||
691            memcmp(clid, lease->clid, clid_len) != 0))
692         continue;
693
694       return lease;
695     }
696   
697   return NULL;
698 }
699
700 struct dhcp_lease *lease6_find_by_addr(struct in6_addr *net, int prefix, u64 addr)
701 {
702   struct dhcp_lease *lease;
703     
704   for (lease = leases; lease; lease = lease->next)
705     {
706       if (!(lease->flags & (LEASE_TA | LEASE_NA)))
707         continue;
708       
709       if (is_same_net6(&lease->addr6, net, prefix) &&
710           (prefix == 128 || addr6part(&lease->addr6) == addr))
711         return lease;
712     }
713   
714   return NULL;
715
716
717 /* Find largest assigned address in context */
718 u64 lease_find_max_addr6(struct dhcp_context *context)
719 {
720   struct dhcp_lease *lease;
721   u64 addr = addr6part(&context->start6);
722   
723   if (!(context->flags & (CONTEXT_STATIC | CONTEXT_PROXY)))
724     for (lease = leases; lease; lease = lease->next)
725       {
726         if (!(lease->flags & (LEASE_TA | LEASE_NA)))
727           continue;
728
729         if (is_same_net6(&lease->addr6, &context->start6, 64) &&
730             addr6part(&lease->addr6) > addr6part(&context->start6) &&
731             addr6part(&lease->addr6) <= addr6part(&context->end6) &&
732             addr6part(&lease->addr6) > addr)
733           addr = addr6part(&lease->addr6);
734       }
735   
736   return addr;
737 }
738
739 #endif
740
741 /* Find largest assigned address in context */
742 struct in_addr lease_find_max_addr(struct dhcp_context *context)
743 {
744   struct dhcp_lease *lease;
745   struct in_addr addr = context->start;
746   
747   if (!(context->flags & (CONTEXT_STATIC | CONTEXT_PROXY)))
748     for (lease = leases; lease; lease = lease->next)
749       {
750 #ifdef HAVE_DHCP6
751         if (lease->flags & (LEASE_TA | LEASE_NA))
752           continue;
753 #endif
754         if (((unsigned)ntohl(lease->addr.s_addr)) > ((unsigned)ntohl(context->start.s_addr)) &&
755             ((unsigned)ntohl(lease->addr.s_addr)) <= ((unsigned)ntohl(context->end.s_addr)) &&
756             ((unsigned)ntohl(lease->addr.s_addr)) > ((unsigned)ntohl(addr.s_addr)))
757           addr = lease->addr;
758       }
759   
760   return addr;
761 }
762
763 static struct dhcp_lease *lease_allocate(void)
764 {
765   struct dhcp_lease *lease;
766   if (!leases_left || !(lease = whine_malloc(sizeof(struct dhcp_lease))))
767     return NULL;
768
769   memset(lease, 0, sizeof(struct dhcp_lease));
770   lease->flags = LEASE_NEW;
771   lease->expires = 1;
772 #ifdef HAVE_BROKEN_RTC
773   lease->length = 0xffffffff; /* illegal value */
774 #endif
775   lease->hwaddr_len = 256; /* illegal value */
776   lease->next = leases;
777   leases = lease;
778   
779   file_dirty = 1;
780   leases_left--;
781
782   return lease;
783 }
784
785 struct dhcp_lease *lease4_allocate(struct in_addr addr)
786 {
787   struct dhcp_lease *lease = lease_allocate();
788   if (lease)
789     {
790       lease->addr = addr;
791       daemon->metrics[METRIC_LEASES_ALLOCATED_4]++;
792     }
793   
794   return lease;
795 }
796
797 #ifdef HAVE_DHCP6
798 struct dhcp_lease *lease6_allocate(struct in6_addr *addrp, int lease_type)
799 {
800   struct dhcp_lease *lease = lease_allocate();
801
802   if (lease)
803     {
804       lease->addr6 = *addrp;
805       lease->flags |= lease_type;
806       lease->iaid = 0;
807
808       daemon->metrics[METRIC_LEASES_ALLOCATED_6]++;
809     }
810
811   return lease;
812 }
813 #endif
814
815 void lease_set_expires(struct dhcp_lease *lease, unsigned int len, time_t now)
816 {
817   time_t exp;
818
819   if (len == 0xffffffff)
820     {
821       exp = 0;
822       len = 0;
823     }
824   else
825     {
826       exp = now + (time_t)len;
827       /* Check for 2038 overflow. Make the lease
828          infinite in that case, as the least disruptive
829          thing we can do. */
830       if (difftime(exp, now) <= 0.0)
831         exp = 0;
832     }
833
834   if (exp != lease->expires)
835     {
836       dns_dirty = 1;
837       lease->expires = exp;
838 #ifndef HAVE_BROKEN_RTC
839       lease->flags |= LEASE_AUX_CHANGED | LEASE_EXP_CHANGED;
840       file_dirty = 1;
841 #endif
842     }
843   
844 #ifdef HAVE_BROKEN_RTC
845   if (len != lease->length)
846     {
847       lease->length = len;
848       lease->flags |= LEASE_AUX_CHANGED;
849       file_dirty = 1; 
850     }
851 #endif
852
853
854 #ifdef HAVE_DHCP6
855 void lease_set_iaid(struct dhcp_lease *lease, unsigned int iaid)
856 {
857   if (lease->iaid != iaid)
858     {
859       lease->iaid = iaid;
860       lease->flags |= LEASE_CHANGED;
861     }
862 }
863 #endif
864
865 void lease_set_hwaddr(struct dhcp_lease *lease, const unsigned char *hwaddr,
866                       const unsigned char *clid, int hw_len, int hw_type,
867                       int clid_len, time_t now, int force)
868 {
869 #ifdef HAVE_DHCP6
870   int change = force;
871   lease->flags |= LEASE_HAVE_HWADDR;
872 #endif
873
874   (void)force;
875   (void)now;
876
877   if (hw_len != lease->hwaddr_len ||
878       hw_type != lease->hwaddr_type || 
879       (hw_len != 0 && memcmp(lease->hwaddr, hwaddr, hw_len) != 0))
880     {
881       if (hw_len != 0)
882         memcpy(lease->hwaddr, hwaddr, hw_len);
883       lease->hwaddr_len = hw_len;
884       lease->hwaddr_type = hw_type;
885       lease->flags |= LEASE_CHANGED;
886       file_dirty = 1; /* run script on change */
887     }
888
889   /* only update clid when one is available, stops packets
890      without a clid removing the record. Lease init uses
891      clid_len == 0 for no clid. */
892   if (clid_len != 0 && clid)
893     {
894       if (!lease->clid)
895         lease->clid_len = 0;
896
897       if (lease->clid_len != clid_len)
898         {
899           lease->flags |= LEASE_AUX_CHANGED;
900           file_dirty = 1;
901           free(lease->clid);
902           if (!(lease->clid = whine_malloc(clid_len)))
903             return;
904 #ifdef HAVE_DHCP6
905           change = 1;
906 #endif     
907         }
908       else if (memcmp(lease->clid, clid, clid_len) != 0)
909         {
910           lease->flags |= LEASE_AUX_CHANGED;
911           file_dirty = 1;
912 #ifdef HAVE_DHCP6
913           change = 1;
914 #endif  
915         }
916       
917       lease->clid_len = clid_len;
918       memcpy(lease->clid, clid, clid_len);
919     }
920   
921 #ifdef HAVE_DHCP6
922   if (change)
923     slaac_add_addrs(lease, now, force);
924 #endif
925 }
926
927 static void kill_name(struct dhcp_lease *lease)
928 {
929   /* run script to say we lost our old name */
930   
931   /* this shouldn't happen unless updates are very quick and the
932      script very slow, we just avoid a memory leak if it does. */
933   free(lease->old_hostname);
934   
935   /* If we know the fqdn, pass that. The helper will derive the
936      unqualified name from it, free the unqualified name here. */
937
938   if (lease->fqdn)
939     {
940       lease->old_hostname = lease->fqdn;
941       free(lease->hostname);
942     }
943   else
944     lease->old_hostname = lease->hostname;
945
946   lease->hostname = lease->fqdn = NULL;
947 }
948
949 void lease_set_hostname(struct dhcp_lease *lease, const char *name, int auth, char *domain, char *config_domain)
950 {
951   struct dhcp_lease *lease_tmp;
952   char *new_name = NULL, *new_fqdn = NULL;
953
954   if (config_domain && (!domain || !hostname_isequal(domain, config_domain)))
955     my_syslog(MS_DHCP | LOG_WARNING, _("Ignoring domain %s for DHCP host name %s"), config_domain, name);
956   
957   if (lease->hostname && name && hostname_isequal(lease->hostname, name))
958     {
959       if (auth)
960         lease->flags |= LEASE_AUTH_NAME;
961       return;
962     }
963   
964   if (!name && !lease->hostname)
965     return;
966
967   /* If a machine turns up on a new net without dropping the old lease,
968      or two machines claim the same name, then we end up with two interfaces with
969      the same name. Check for that here and remove the name from the old lease.
970      Note that IPv6 leases are different. All the leases to the same DUID are 
971      allowed the same name.
972
973      Don't allow a name from the client to override a name from dnsmasq config. */
974   
975   if (name)
976     {
977       if ((new_name = whine_malloc(strlen(name) + 1)))
978         {
979           strcpy(new_name, name);
980           if (domain && (new_fqdn = whine_malloc(strlen(new_name) + strlen(domain) + 2)))
981             {
982               strcpy(new_fqdn, name);
983               strcat(new_fqdn, ".");
984               strcat(new_fqdn, domain);
985             }
986         }
987           
988       /* Depending on mode, we check either unqualified name or FQDN. */
989       for (lease_tmp = leases; lease_tmp; lease_tmp = lease_tmp->next)
990         {
991           if (option_bool(OPT_DHCP_FQDN))
992             {
993               if (!new_fqdn || !lease_tmp->fqdn || !hostname_isequal(lease_tmp->fqdn, new_fqdn))
994                 continue;
995             }
996           else
997             {
998               if (!new_name || !lease_tmp->hostname || !hostname_isequal(lease_tmp->hostname, new_name) )
999                 continue; 
1000             }
1001
1002           if (lease->flags & (LEASE_TA | LEASE_NA))
1003             {
1004               if (!(lease_tmp->flags & (LEASE_TA | LEASE_NA)))
1005                 continue;
1006
1007               /* another lease for the same DUID is OK for IPv6 */
1008               if (lease->clid_len == lease_tmp->clid_len &&
1009                   lease->clid && lease_tmp->clid &&
1010                   memcmp(lease->clid, lease_tmp->clid, lease->clid_len) == 0)
1011                 continue;             
1012             }
1013           else if (lease_tmp->flags & (LEASE_TA | LEASE_NA))
1014             continue;
1015                    
1016           if ((lease_tmp->flags & LEASE_AUTH_NAME) && !auth)
1017             {
1018               free(new_name);
1019               free(new_fqdn);
1020               return;
1021             }
1022         
1023           kill_name(lease_tmp);
1024           lease_tmp->flags |= LEASE_CHANGED; /* run script on change */
1025           break;
1026         }
1027     }
1028
1029   if (lease->hostname)
1030     kill_name(lease);
1031
1032   lease->hostname = new_name;
1033   lease->fqdn = new_fqdn;
1034   
1035   if (auth)
1036     lease->flags |= LEASE_AUTH_NAME;
1037   
1038   file_dirty = 1;
1039   dns_dirty = 1; 
1040   lease->flags |= LEASE_CHANGED; /* run script on change */
1041 }
1042
1043 void lease_set_interface(struct dhcp_lease *lease, int interface, time_t now)
1044 {
1045   (void)now;
1046
1047   if (lease->last_interface == interface)
1048     return;
1049
1050   lease->last_interface = interface;
1051   lease->flags |= LEASE_CHANGED; 
1052
1053 #ifdef HAVE_DHCP6
1054   slaac_add_addrs(lease, now, 0);
1055 #endif
1056 }
1057
1058 void rerun_scripts(void)
1059 {
1060   struct dhcp_lease *lease;
1061   
1062   for (lease = leases; lease; lease = lease->next)
1063     lease->flags |= LEASE_CHANGED; 
1064 }
1065
1066 /* deleted leases get transferred to the old_leases list.
1067    remove them here, after calling the lease change
1068    script. Also run the lease change script on new/modified leases.
1069
1070    Return zero if nothing to do. */
1071 int do_script_run(time_t now)
1072 {
1073   struct dhcp_lease *lease;
1074
1075   (void)now;
1076
1077 #ifdef HAVE_DBUS
1078   /* If we're going to be sending DBus signals, but the connection is not yet up,
1079      delay everything until it is. */
1080   if (option_bool(OPT_DBUS) && !daemon->dbus)
1081     return 0;
1082 #endif
1083
1084   if (old_leases)
1085     {
1086       lease = old_leases;
1087                   
1088       /* If the lease still has an old_hostname, do the "old" action on that first */
1089       if (lease->old_hostname)
1090         {
1091 #ifdef HAVE_SCRIPT
1092           queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now);
1093 #endif
1094           free(lease->old_hostname);
1095           lease->old_hostname = NULL;
1096           return 1;
1097         }
1098       else 
1099         {
1100 #ifdef HAVE_DHCP6
1101           struct slaac_address *slaac, *tmp;
1102           for (slaac = lease->slaac_address; slaac; slaac = tmp)
1103             {
1104               tmp = slaac->next;
1105               free(slaac);
1106             }
1107 #endif
1108           kill_name(lease);
1109 #ifdef HAVE_SCRIPT
1110           queue_script(ACTION_DEL, lease, lease->old_hostname, now);
1111 #endif
1112 #ifdef HAVE_DBUS
1113           emit_dbus_signal(ACTION_DEL, lease, lease->old_hostname);
1114 #endif
1115           old_leases = lease->next;
1116           
1117           free(lease->old_hostname); 
1118           free(lease->clid);
1119           free(lease->extradata);
1120           free(lease);
1121             
1122           return 1; 
1123         }
1124     }
1125   
1126   /* make sure we announce the loss of a hostname before its new location. */
1127   for (lease = leases; lease; lease = lease->next)
1128     if (lease->old_hostname)
1129       { 
1130 #ifdef HAVE_SCRIPT
1131         queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now);
1132 #endif
1133         free(lease->old_hostname);
1134         lease->old_hostname = NULL;
1135         return 1;
1136       }
1137   
1138   for (lease = leases; lease; lease = lease->next)
1139     if ((lease->flags & (LEASE_NEW | LEASE_CHANGED)) || 
1140         ((lease->flags & LEASE_AUX_CHANGED) && option_bool(OPT_LEASE_RO)) ||
1141         ((lease->flags & LEASE_EXP_CHANGED) && option_bool(OPT_LEASE_RENEW)))
1142       {
1143 #ifdef HAVE_SCRIPT
1144         queue_script((lease->flags & LEASE_NEW) ? ACTION_ADD : ACTION_OLD, lease, 
1145                      lease->fqdn ? lease->fqdn : lease->hostname, now);
1146 #endif
1147 #ifdef HAVE_DBUS
1148         emit_dbus_signal((lease->flags & LEASE_NEW) ? ACTION_ADD : ACTION_OLD, lease,
1149                          lease->fqdn ? lease->fqdn : lease->hostname);
1150 #endif
1151         lease->flags &= ~(LEASE_NEW | LEASE_CHANGED | LEASE_AUX_CHANGED | LEASE_EXP_CHANGED);
1152         
1153         /* this is used for the "add" call, then junked, since they're not in the database */
1154         free(lease->extradata);
1155         lease->extradata = NULL;
1156         
1157         return 1;
1158       }
1159
1160   return 0; /* nothing to do */
1161 }
1162
1163 #ifdef HAVE_SCRIPT
1164 /* delim == -1 -> delim = 0, but embedded 0s, creating extra records, are OK. */
1165 void lease_add_extradata(struct dhcp_lease *lease, unsigned char *data, unsigned int len, int delim)
1166 {
1167   unsigned int i;
1168   
1169   if (delim == -1)
1170     delim = 0;
1171   else
1172     /* check for embedded NULLs */
1173     for (i = 0; i < len; i++)
1174       if (data[i] == 0)
1175         {
1176           len = i;
1177           break;
1178         }
1179   
1180   if ((lease->extradata_size - lease->extradata_len) < (len + 1))
1181     {
1182       size_t newsz = lease->extradata_len + len + 100;
1183       unsigned char *new = whine_realloc(lease->extradata, newsz);
1184   
1185       if (!new)
1186         return;
1187       
1188       lease->extradata = new;
1189       lease->extradata_size = newsz;
1190     }
1191
1192   if (len != 0)
1193     memcpy(lease->extradata + lease->extradata_len, data, len);
1194   lease->extradata[lease->extradata_len + len] = delim;
1195   lease->extradata_len += len + 1; 
1196 }
1197 #endif
1198
1199 #endif /* HAVE_DHCP */