Annotation of embedaddon/dnsmasq/src/lease.c, revision 1.1.1.4

1.1.1.4 ! misho       1: /* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
1.1       misho       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: 
1.1.1.4 ! misho      24: static int read_leases(time_t now, FILE *leasestream)
1.1       misho      25: {
                     26:   unsigned long ei;
1.1.1.4 ! misho      27:   union all_addr addr;
1.1       misho      28:   struct dhcp_lease *lease;
                     29:   int clid_len, hw_len, hw_type;
1.1.1.4 ! misho      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.
1.1       misho      42: #endif
                     43: 
1.1.1.4 ! misho      44:     while ((items=fscanf(leasestream, "%255s %255s", daemon->dhcp_buff3, daemon->dhcp_buff2)) == 2)
1.1       misho      45:       {
1.1.1.4 ! misho      46:        *daemon->namebuff = *daemon->dhcp_buff = *daemon->packet = '\0';
        !            47:        hw_len = hw_type = clid_len = 0;
        !            48:        
1.1       misho      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);
1.1.1.4 ! misho      53:            if (daemon->duid_len < 0)
        !            54:              return 0;
1.1       misho      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:          {
1.1.1.4 ! misho      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:            
1.1       misho      75:            hw_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, DHCP_CHADDR_MAX, NULL, &hw_type);
1.1.1.4 ! misho      76:            /* For backwards compatibility, no explicit MAC address type means ether. */
1.1       misho      77:            if (hw_type == 0 && hw_len != 0)
                     78:              hw_type = ARPHRD_ETHER; 
                     79:          }
                     80: #ifdef HAVE_DHCP6
1.1.1.4 ! misho      81:        else if (inet_pton(AF_INET6, daemon->namebuff, &addr.addr6))
1.1       misho      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:            
1.1.1.4 ! misho      92:            if ((lease = lease6_allocate(&addr.addr6, lease_type)))
1.1       misho      93:              {
1.1.1.4 ! misho      94:                lease_set_iaid(lease, strtoul(s, NULL, 10));
        !            95:                domain = get_domain6(&lease->addr6);
1.1       misho      96:              }
                     97:          }
                     98: #endif
                     99:        else
1.1.1.4 ! misho     100:          {
        !           101:            my_syslog(MS_DHCP | LOG_WARNING, _("ignoring invalid line in lease database, bad address: %s"),
        !           102:                      daemon->namebuff);
        !           103:            continue;
        !           104:          }
        !           105:        
1.1       misho     106: 
                    107:        if (!lease)
                    108:          die (_("too many stored leases"), NULL, EC_MISC);
1.1.1.4 ! misho     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: 
1.1       misho     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);
1.1.1.4 ! misho     136:        
        !           137:        *daemon->dhcp_buff3 = *daemon->dhcp_buff2 = '\0';
1.1       misho     138:       }
1.1.1.4 ! misho     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:     }
1.1       misho     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;
1.1.1.4 ! misho     203: 
1.1       misho     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)
1.1.1.2   misho     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, 
1.1.1.4 ! misho     233:                                   lease->hwaddr, lease->hwaddr_len, lease->hwaddr_type, NULL, NULL)) && 
1.1.1.2   misho     234:             (config->flags & CONFIG_NAME) &&
                    235:             (!(config->flags & CONFIG_ADDR) || config->addr.s_addr == lease->addr.s_addr))
1.1       misho     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: }
1.1.1.4 ! misho     240: 
1.1       misho     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:     
1.1.1.2   misho     322:              inet_ntop(AF_INET6, &lease->addr6, daemon->addrbuff, ADDRSTRLEN);
1.1       misho     323:         
                    324:              ourprintf(&err, "%s%u %s ", (lease->flags & LEASE_TA) ? "T" : "",
1.1.1.2   misho     325:                        lease->iaid, daemon->addrbuff);
1.1       misho     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:   
1.1.1.2   misho     348:   /* Set alarm for when the first lease expires. */
1.1       misho     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 &&
1.1.1.2   misho     373:        (next_event == 0 || difftime(next_event, lease->expires) > 0.0))
                    374:       next_event = lease->expires;
1.1       misho     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 %us)"), 
                    382:                daemon->lease_file, strerror(err),
                    383:                (unsigned int)difftime(next_event, now));
                    384:     }
                    385: 
                    386:   send_alarm(next_event, now);
                    387: }
                    388: 
                    389: 
1.1.1.2   misho     390: static int find_interface_v4(struct in_addr local, int if_index, char *label,
1.1       misho     391:                             struct in_addr netmask, struct in_addr broadcast, void *vparam)
                    392: {
                    393:   struct dhcp_lease *lease;
1.1.1.3   misho     394:   int prefix = netmask_length(netmask);
                    395: 
1.1.1.2   misho     396:   (void) label;
1.1       misho     397:   (void) broadcast;
                    398:   (void) vparam;
                    399: 
                    400:   for (lease = leases; lease; lease = lease->next)
1.1.1.3   misho     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: 
1.1       misho     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;
1.1.1.3   misho     418: 
1.1       misho     419:   (void)scope;
                    420:   (void)flags;
                    421:   (void)preferred;
                    422:   (void)valid;
1.1.1.3   misho     423:   (void)vparam;
1.1       misho     424: 
                    425:   for (lease = leases; lease; lease = lease->next)
                    426:     if ((lease->flags & (LEASE_TA | LEASE_NA)))
1.1.1.3   misho     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: 
1.1       misho     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: {
1.1.1.4 ! misho     448:   /* Called when we construct a new RA-names context, to add putative
1.1       misho     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: {
1.1.1.3   misho     467:   struct dhcp_lease *lease;
                    468:   
                    469:   for (lease = leases; lease; lease = lease->next)
                    470:     lease->new_prefixlen = lease->new_interface = 0;
                    471: 
1.1       misho     472:   iface_enumerate(AF_INET, &now, find_interface_v4);
                    473: #ifdef HAVE_DHCP6
                    474:   iface_enumerate(AF_INET6, &now, find_interface_v6);
1.1.1.2   misho     475: #endif
1.1.1.3   misho     476: 
                    477:   for (lease = leases; lease; lease = lease->next)
                    478:     if (lease->new_interface != 0) 
                    479:       lease_set_interface(lease, lease->new_interface, now);
1.1.1.2   misho     480: }
1.1       misho     481: 
1.1.1.2   misho     482: #ifdef HAVE_DHCP6
                    483: void lease_make_duid(time_t now)
                    484: {
1.1       misho     485:   /* If we're not doing DHCPv6, and there are not v6 leases, don't add the DUID to the database */
1.1.1.2   misho     486:   if (!daemon->duid && daemon->doing_dhcp6)
1.1       misho     487:     {
                    488:       file_dirty = 1;
                    489:       make_duid(now);
                    490:     }
                    491: }
1.1.1.2   misho     492: #endif
                    493: 
1.1       misho     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)
1.1.1.4 ! misho     525:                      cache_add_dhcp_entry(lease->fqdn, AF_INET6, (union all_addr *)&slaac->addr, lease->expires);
1.1       misho     526:                    if (!option_bool(OPT_DHCP_FQDN) && lease->hostname)
1.1.1.4 ! misho     527:                      cache_add_dhcp_entry(lease->hostname, AF_INET6, (union all_addr *)&slaac->addr, lease->expires);
1.1       misho     528:                  }
                    529:            }
                    530:          
                    531:          if (lease->fqdn)
                    532:            cache_add_dhcp_entry(lease->fqdn, prot, 
1.1.1.4 ! misho     533:                                 prot == AF_INET ? (union all_addr *)&lease->addr : (union all_addr *)&lease->addr6,
1.1       misho     534:                                 lease->expires);
                    535:             
                    536:          if (!option_bool(OPT_DHCP_FQDN) && lease->hostname)
                    537:            cache_add_dhcp_entry(lease->hostname, prot, 
1.1.1.4 ! misho     538:                                 prot == AF_INET ? (union all_addr *)&lease->addr : (union all_addr *)&lease->addr6, 
1.1       misho     539:                                 lease->expires);
1.1.1.2   misho     540:        
                    541: #else
                    542:          if (lease->fqdn)
1.1.1.4 ! misho     543:            cache_add_dhcp_entry(lease->fqdn, prot, (union all_addr *)&lease->addr, lease->expires);
1.1.1.2   misho     544:          
                    545:          if (!option_bool(OPT_DHCP_FQDN) && lease->hostname)
1.1.1.4 ! misho     546:            cache_add_dhcp_entry(lease->hostname, prot, (union all_addr *)&lease->addr, lease->expires);
1.1.1.2   misho     547: #endif
1.1       misho     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;
1.1.1.4 ! misho     561:       if ((lease->expires != 0 && difftime(now, lease->expires) >= 0) || lease == target)
1.1       misho     562:        {
                    563:          file_dirty = 1;
                    564:          if (lease->hostname)
                    565:            dns_dirty = 1;
1.1.1.4 ! misho     566: 
        !           567:          daemon->metrics[lease->addr.s_addr ? METRIC_LEASES_PRUNED_4 : METRIC_LEASES_PRUNED_6]++;
        !           568: 
1.1       misho     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, 
1.1.1.4 ! misho     638:                               int lease_type, unsigned int iaid,
        !           639:                               struct in6_addr *addr)
1.1       misho     640: {
                    641:   struct dhcp_lease *lease;
                    642:   
                    643:   for (lease = leases; lease; lease = lease->next)
                    644:     {
1.1.1.2   misho     645:       if (!(lease->flags & lease_type) || lease->iaid != iaid)
1.1       misho     646:        continue;
                    647: 
1.1.1.2   misho     648:       if (!IN6_ARE_ADDR_EQUAL(&lease->addr6, addr))
1.1       misho     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} */
1.1.1.4 ! misho     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)
1.1       misho     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: 
1.1.1.2   misho     687:       if (!(lease->flags & lease_type) || lease->iaid != iaid)
1.1       misho     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:       
1.1.1.2   misho     709:       if (is_same_net6(&lease->addr6, net, prefix) &&
                    710:          (prefix == 128 || addr6part(&lease->addr6) == addr))
1.1       misho     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: 
1.1.1.2   misho     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);
1.1       misho     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
1.1.1.2   misho     775:   lease->hwaddr_len = 256; /* illegal value */
1.1       misho     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)
1.1.1.4 ! misho     789:     {
        !           790:       lease->addr = addr;
        !           791:       daemon->metrics[METRIC_LEASES_ALLOCATED_4]++;
        !           792:     }
1.1.1.2   misho     793:   
1.1       misho     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:     {
1.1.1.2   misho     804:       lease->addr6 = *addrp;
1.1       misho     805:       lease->flags |= lease_type;
1.1.1.2   misho     806:       lease->iaid = 0;
1.1.1.4 ! misho     807: 
        !           808:       daemon->metrics[METRIC_LEASES_ALLOCATED_6]++;
1.1       misho     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: {
1.1.1.2   misho     817:   time_t exp;
                    818: 
1.1       misho     819:   if (len == 0xffffffff)
                    820:     {
                    821:       exp = 0;
                    822:       len = 0;
                    823:     }
1.1.1.2   misho     824:   else
                    825:     {
                    826:       exp = now + (time_t)len;
                    827:       /* Check for 2038 overflow. Make the lease
1.1.1.4 ! misho     828:         infinite in that case, as the least disruptive
1.1.1.2   misho     829:         thing we can do. */
                    830:       if (difftime(exp, now) <= 0.0)
                    831:        exp = 0;
                    832:     }
                    833: 
1.1       misho     834:   if (exp != lease->expires)
                    835:     {
                    836:       dns_dirty = 1;
                    837:       lease->expires = exp;
                    838: #ifndef HAVE_BROKEN_RTC
1.1.1.4 ! misho     839:       lease->flags |= LEASE_AUX_CHANGED | LEASE_EXP_CHANGED;
1.1       misho     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: 
1.1.1.2   misho     854: #ifdef HAVE_DHCP6
1.1.1.4 ! misho     855: void lease_set_iaid(struct dhcp_lease *lease, unsigned int iaid)
1.1.1.2   misho     856: {
                    857:   if (lease->iaid != iaid)
                    858:     {
                    859:       lease->iaid = iaid;
                    860:       lease->flags |= LEASE_CHANGED;
                    861:     }
                    862: }
                    863: #endif
                    864: 
1.1.1.3   misho     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)
1.1       misho     868: {
                    869: #ifdef HAVE_DHCP6
                    870:   int change = force;
                    871:   lease->flags |= LEASE_HAVE_HWADDR;
                    872: #endif
                    873: 
                    874:   (void)force;
1.1.1.2   misho     875:   (void)now;
1.1       misho     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: 
1.1.1.3   misho     949: void lease_set_hostname(struct dhcp_lease *lease, const char *name, int auth, char *domain, char *config_domain)
1.1       misho     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:          break;
                   1025:        }
                   1026:     }
                   1027: 
                   1028:   if (lease->hostname)
                   1029:     kill_name(lease);
                   1030: 
                   1031:   lease->hostname = new_name;
                   1032:   lease->fqdn = new_fqdn;
                   1033:   
                   1034:   if (auth)
                   1035:     lease->flags |= LEASE_AUTH_NAME;
                   1036:   
                   1037:   file_dirty = 1;
                   1038:   dns_dirty = 1; 
                   1039:   lease->flags |= LEASE_CHANGED; /* run script on change */
                   1040: }
                   1041: 
                   1042: void lease_set_interface(struct dhcp_lease *lease, int interface, time_t now)
                   1043: {
1.1.1.2   misho    1044:   (void)now;
                   1045: 
1.1       misho    1046:   if (lease->last_interface == interface)
                   1047:     return;
                   1048: 
                   1049:   lease->last_interface = interface;
                   1050:   lease->flags |= LEASE_CHANGED; 
                   1051: 
                   1052: #ifdef HAVE_DHCP6
                   1053:   slaac_add_addrs(lease, now, 0);
                   1054: #endif
                   1055: }
                   1056: 
                   1057: void rerun_scripts(void)
                   1058: {
                   1059:   struct dhcp_lease *lease;
                   1060:   
                   1061:   for (lease = leases; lease; lease = lease->next)
                   1062:     lease->flags |= LEASE_CHANGED; 
                   1063: }
                   1064: 
                   1065: /* deleted leases get transferred to the old_leases list.
                   1066:    remove them here, after calling the lease change
                   1067:    script. Also run the lease change script on new/modified leases.
                   1068: 
                   1069:    Return zero if nothing to do. */
                   1070: int do_script_run(time_t now)
                   1071: {
                   1072:   struct dhcp_lease *lease;
                   1073: 
1.1.1.2   misho    1074:   (void)now;
                   1075: 
1.1       misho    1076: #ifdef HAVE_DBUS
                   1077:   /* If we're going to be sending DBus signals, but the connection is not yet up,
                   1078:      delay everything until it is. */
                   1079:   if (option_bool(OPT_DBUS) && !daemon->dbus)
                   1080:     return 0;
                   1081: #endif
                   1082: 
                   1083:   if (old_leases)
                   1084:     {
                   1085:       lease = old_leases;
                   1086:                   
                   1087:       /* If the lease still has an old_hostname, do the "old" action on that first */
                   1088:       if (lease->old_hostname)
                   1089:        {
                   1090: #ifdef HAVE_SCRIPT
                   1091:          queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now);
                   1092: #endif
                   1093:          free(lease->old_hostname);
                   1094:          lease->old_hostname = NULL;
                   1095:          return 1;
                   1096:        }
                   1097:       else 
                   1098:        {
                   1099: #ifdef HAVE_DHCP6
                   1100:          struct slaac_address *slaac, *tmp;
                   1101:          for (slaac = lease->slaac_address; slaac; slaac = tmp)
                   1102:            {
                   1103:              tmp = slaac->next;
                   1104:              free(slaac);
                   1105:            }
                   1106: #endif
                   1107:          kill_name(lease);
                   1108: #ifdef HAVE_SCRIPT
                   1109:          queue_script(ACTION_DEL, lease, lease->old_hostname, now);
                   1110: #endif
                   1111: #ifdef HAVE_DBUS
                   1112:          emit_dbus_signal(ACTION_DEL, lease, lease->old_hostname);
                   1113: #endif
                   1114:          old_leases = lease->next;
                   1115:          
                   1116:          free(lease->old_hostname); 
                   1117:          free(lease->clid);
                   1118:          free(lease->extradata);
                   1119:          free(lease);
                   1120:            
                   1121:          return 1; 
                   1122:        }
                   1123:     }
                   1124:   
                   1125:   /* make sure we announce the loss of a hostname before its new location. */
                   1126:   for (lease = leases; lease; lease = lease->next)
                   1127:     if (lease->old_hostname)
                   1128:       {        
                   1129: #ifdef HAVE_SCRIPT
                   1130:        queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now);
                   1131: #endif
                   1132:        free(lease->old_hostname);
                   1133:        lease->old_hostname = NULL;
                   1134:        return 1;
                   1135:       }
                   1136:   
                   1137:   for (lease = leases; lease; lease = lease->next)
                   1138:     if ((lease->flags & (LEASE_NEW | LEASE_CHANGED)) || 
1.1.1.4 ! misho    1139:        ((lease->flags & LEASE_AUX_CHANGED) && option_bool(OPT_LEASE_RO)) ||
        !          1140:        ((lease->flags & LEASE_EXP_CHANGED) && option_bool(OPT_LEASE_RENEW)))
1.1       misho    1141:       {
                   1142: #ifdef HAVE_SCRIPT
                   1143:        queue_script((lease->flags & LEASE_NEW) ? ACTION_ADD : ACTION_OLD, lease, 
                   1144:                     lease->fqdn ? lease->fqdn : lease->hostname, now);
                   1145: #endif
                   1146: #ifdef HAVE_DBUS
                   1147:        emit_dbus_signal((lease->flags & LEASE_NEW) ? ACTION_ADD : ACTION_OLD, lease,
                   1148:                         lease->fqdn ? lease->fqdn : lease->hostname);
                   1149: #endif
1.1.1.4 ! misho    1150:        lease->flags &= ~(LEASE_NEW | LEASE_CHANGED | LEASE_AUX_CHANGED | LEASE_EXP_CHANGED);
1.1       misho    1151:        
                   1152:        /* this is used for the "add" call, then junked, since they're not in the database */
                   1153:        free(lease->extradata);
                   1154:        lease->extradata = NULL;
                   1155:        
                   1156:        return 1;
                   1157:       }
                   1158: 
                   1159:   return 0; /* nothing to do */
                   1160: }
                   1161: 
                   1162: #ifdef HAVE_SCRIPT
1.1.1.4 ! misho    1163: /* delim == -1 -> delim = 0, but embedded 0s, creating extra records, are OK. */
1.1       misho    1164: void lease_add_extradata(struct dhcp_lease *lease, unsigned char *data, unsigned int len, int delim)
                   1165: {
                   1166:   unsigned int i;
                   1167:   
1.1.1.3   misho    1168:   if (delim == -1)
                   1169:     delim = 0;
                   1170:   else
1.1.1.4 ! misho    1171:     /* check for embedded NULLs */
1.1.1.3   misho    1172:     for (i = 0; i < len; i++)
                   1173:       if (data[i] == 0)
                   1174:        {
                   1175:          len = i;
                   1176:          break;
                   1177:        }
                   1178:   
1.1       misho    1179:   if ((lease->extradata_size - lease->extradata_len) < (len + 1))
                   1180:     {
                   1181:       size_t newsz = lease->extradata_len + len + 100;
                   1182:       unsigned char *new = whine_malloc(newsz);
                   1183:   
                   1184:       if (!new)
                   1185:        return;
                   1186:       
                   1187:       if (lease->extradata)
                   1188:        {
                   1189:          memcpy(new, lease->extradata, lease->extradata_len);
                   1190:          free(lease->extradata);
                   1191:        }
                   1192: 
                   1193:       lease->extradata = new;
                   1194:       lease->extradata_size = newsz;
                   1195:     }
                   1196: 
                   1197:   if (len != 0)
                   1198:     memcpy(lease->extradata + lease->extradata_len, data, len);
                   1199:   lease->extradata[lease->extradata_len + len] = delim;
                   1200:   lease->extradata_len += len + 1; 
                   1201: }
                   1202: #endif
                   1203: 
                   1204: #endif
                   1205:          
                   1206: 
                   1207:       
                   1208: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>