~cyphermox/ubuntu/precise/dnsmasq/dbus

« back to all changes in this revision

Viewing changes to src/lease.c

  • Committer: Bazaar Package Importer
  • Author(s): Simon Kelley
  • Date: 2006-06-25 18:03:13 UTC
  • mfrom: (0.2.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20060625180313-gvm8q6gd804kjvgk
Tags: 2.33-1
 * New upstream.
 * Remove bashism from Makefile (closes: #375409)
 * Added Provides: $named to LSB header in init script.
 * Add --dns-forward-max flag. (closes: #377506)
                        

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
  struct in_addr addr;
22
22
  struct dhcp_lease *lease;
23
23
  int flags, clid_len, hw_len, hw_type;
 
24
  FILE *leasestream;
24
25
  
25
26
  leases = old_leases = NULL;
26
27
  leases_left = daemon->dhcp_max;
27
28
 
28
 
  /* NOTE: need a+ mode to create file if it doesn't exist */
29
 
  if (!(daemon->lease_stream = fopen(daemon->lease_file, "a+")))
30
 
    die(_("cannot open or create leases file: %s"), NULL);
31
 
     
32
 
  flags = fcntl(fileno(daemon->lease_stream), F_GETFD);
33
 
  if (flags != -1)
34
 
    fcntl(fileno(daemon->lease_stream), F_SETFD, flags | FD_CLOEXEC); 
 
29
  if (daemon->options & OPT_LEASE_RO)
 
30
    {
 
31
      /* run "<lease_change_script> init" once to get the
 
32
         initial state of the database. If leasefile-ro is
 
33
         set without a script, we just do without any 
 
34
         lease database. */
 
35
      if (!daemon->lease_change_command)
 
36
        {
 
37
          file_dirty = dns_dirty = 0;
 
38
          return;
 
39
        }
 
40
      strcpy(daemon->dhcp_buff, daemon->lease_change_command);
 
41
      strcat(daemon->dhcp_buff, " init");
 
42
      leasestream = popen(daemon->dhcp_buff, "r");
 
43
    }
 
44
  else
 
45
    {
 
46
      /* NOTE: need a+ mode to create file if it doesn't exist */
 
47
      leasestream = daemon->lease_stream = fopen(daemon->lease_file, "a+");
 
48
      
 
49
      if (!leasestream)
 
50
        die(_("cannot open or create lease file %s: %s"), daemon->lease_file);
 
51
      
 
52
      flags = fcntl(fileno(leasestream), F_GETFD);
 
53
      if (flags != -1)
 
54
        fcntl(fileno(leasestream), F_SETFD, flags | FD_CLOEXEC); 
 
55
      
 
56
      /* a+ mode lease pointer at end. */
 
57
      rewind(leasestream);
 
58
    }
35
59
  
36
 
  /* a+ mode lease pointer at end. */
37
 
  rewind(daemon->lease_stream);
38
 
 
39
60
  /* client-id max length is 255 which is 255*2 digits + 254 colons 
40
61
     borrow DNS packet buffer which is always larger than 1000 bytes */
41
 
  while (fscanf(daemon->lease_stream, "%lu %255s %16s %255s %764s",
42
 
                &ei, daemon->dhcp_buff2, daemon->namebuff, 
43
 
                daemon->dhcp_buff, daemon->packet) == 5)
44
 
    {
45
 
      hw_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, DHCP_CHADDR_MAX, NULL, &hw_type);
46
 
      /* For backwards compatibility, no explict MAC address type means ether. */
47
 
      if (hw_type == 0 && hw_len != 0)
48
 
        hw_type = ARPHRD_ETHER;
49
 
 
50
 
      addr.s_addr = inet_addr(daemon->namebuff);
51
 
 
52
 
      /* decode hex in place */
53
 
      clid_len = 0;
54
 
      if (strcmp(daemon->packet, "*") != 0)
55
 
        clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL);
56
 
      
57
 
      if (!(lease = lease_allocate(addr)))
58
 
        die (_("too many stored leases"), NULL);
59
 
      /* not actually new */
60
 
      lease->new = 0;
61
 
 
 
62
  if (leasestream)
 
63
    while (fscanf(leasestream, "%lu %255s %16s %255s %764s",
 
64
                  &ei, daemon->dhcp_buff2, daemon->namebuff, 
 
65
                  daemon->dhcp_buff, daemon->packet) == 5)
 
66
      {
 
67
        hw_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, DHCP_CHADDR_MAX, NULL, &hw_type);
 
68
        /* For backwards compatibility, no explict MAC address type means ether. */
 
69
        if (hw_type == 0 && hw_len != 0)
 
70
          hw_type = ARPHRD_ETHER;
 
71
        
 
72
        addr.s_addr = inet_addr(daemon->namebuff);
 
73
        
 
74
        /* decode hex in place */
 
75
        clid_len = 0;
 
76
        if (strcmp(daemon->packet, "*") != 0)
 
77
          clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL);
 
78
        
 
79
        if (!(lease = lease_allocate(addr)))
 
80
          die (_("too many stored leases"), NULL);
 
81
        /* not actually new */
 
82
        lease->new = 0;
 
83
        
62
84
#ifdef HAVE_BROKEN_RTC
63
 
      if (ei != 0)
64
 
        lease->expires = (time_t)ei + now;
65
 
      else
66
 
        lease->expires = (time_t)0;
67
 
      lease->length = ei;
 
85
        if (ei != 0)
 
86
          lease->expires = (time_t)ei + now;
 
87
        else
 
88
          lease->expires = (time_t)0;
 
89
        lease->length = ei;
68
90
#else
69
 
      /* strictly time_t is opaque, but this hack should work on all sane systems,
70
 
         even when sizeof(time_t) == 8 */
71
 
      lease->expires = (time_t)ei;
 
91
        /* strictly time_t is opaque, but this hack should work on all sane systems,
 
92
           even when sizeof(time_t) == 8 */
 
93
        lease->expires = (time_t)ei;
72
94
#endif
73
 
 
74
 
      lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet, hw_len, hw_type, clid_len);
75
 
 
76
 
      if (strcmp(daemon->dhcp_buff, "*") !=  0)
77
 
        lease_set_hostname(lease, daemon->dhcp_buff, daemon->domain_suffix, 0);
 
95
        
 
96
        lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet, hw_len, hw_type, clid_len);
 
97
        
 
98
        if (strcmp(daemon->dhcp_buff, "*") !=  0)
 
99
          lease_set_hostname(lease, daemon->dhcp_buff, daemon->domain_suffix, 0);
 
100
      }
 
101
  
 
102
  if (!daemon->lease_stream)
 
103
    {
 
104
      int rc = 0;
 
105
 
 
106
      /* shell returns 127 for "command not found", 126 for bad permissions. */
 
107
      if (!leasestream || (rc = pclose(leasestream)) == -1 || WEXITSTATUS(rc) == 127 || WEXITSTATUS(rc) == 126)
 
108
        {
 
109
          if (WEXITSTATUS(rc) == 127)
 
110
            errno = ENOENT;
 
111
          else if (WEXITSTATUS(rc) == 126)
 
112
            errno = EACCES;
 
113
          die(_("cannot run lease-init script %s: %s"), daemon->lease_change_command);
 
114
        }
 
115
      
 
116
      if (WEXITSTATUS(rc) != 0)
 
117
        {
 
118
          sprintf(daemon->dhcp_buff, "%d", WEXITSTATUS(rc));
 
119
          die(_("lease-init script returned exit code %s"), daemon->dhcp_buff);
 
120
        }
78
121
    }
79
122
 
80
123
  /* Some leases may have expired */
117
160
  time_t next_event;
118
161
  int i, err = 0;
119
162
 
120
 
  if (file_dirty != 0)
 
163
  if (file_dirty != 0 && daemon->lease_stream)
121
164
    {
122
165
      errno = 0;
123
166
      rewind(daemon->lease_stream);
298
341
      dns_dirty = 1;
299
342
      lease->expires = exp;
300
343
#ifndef HAVE_BROKEN_RTC
301
 
      file_dirty = 1;
 
344
      lease->aux_changed = file_dirty = 1;
302
345
#endif
303
346
    }
304
347
  
306
349
  if (len != lease->length)
307
350
    {
308
351
      lease->length = len;
309
 
      file_dirty = 1;
 
352
      lease->aux_changed = file_dirty = 1; 
310
353
    }
311
354
#endif
312
355
318
361
      hw_type != lease->hwaddr_type || 
319
362
      (hw_len != 0 && memcmp(lease->hwaddr, hwaddr, hw_len) != 0))
320
363
    {
321
 
      file_dirty = 1;
322
364
      memcpy(lease->hwaddr, hwaddr, hw_len);
323
365
      lease->hwaddr_len = hw_len;
324
366
      lease->hwaddr_type = hw_type;
325
 
      lease->old = 1; /* run script on change */
 
367
      lease->changed = file_dirty = 1; /* run script on change */
326
368
    }
327
369
 
328
370
  /* only update clid when one is available, stops packets
335
377
 
336
378
      if (lease->clid_len != clid_len)
337
379
        {
338
 
          file_dirty = 1;
 
380
          lease->aux_changed = file_dirty = 1;
339
381
          if (lease->clid)
340
382
            free(lease->clid);
341
383
          if (!(lease->clid = malloc(clid_len)))
342
384
            return;
343
385
        }
344
386
      else if (memcmp(lease->clid, clid, clid_len) != 0)
345
 
        file_dirty = 1;
346
 
      
 
387
        lease->aux_changed = file_dirty = 1;
 
388
          
347
389
      lease->clid_len = clid_len;
348
390
      memcpy(lease->clid, clid, clid_len);
349
391
    }
 
392
 
350
393
}
351
394
 
352
395
void lease_set_hostname(struct dhcp_lease *lease, char *name, char *suffix, int auth)
375
418
          {
376
419
            if (lease_tmp->auth_name && !auth)
377
420
              return;
378
 
            lease_tmp->old = 1; /* call script on change */
 
421
            lease_tmp->changed = 1; /* call script on change */
379
422
            new_name = lease_tmp->hostname;
380
423
            lease_tmp->hostname = NULL;
381
424
            if (lease_tmp->fqdn)
408
451
  
409
452
  file_dirty = 1;
410
453
  dns_dirty = 1; 
411
 
  lease->old = 1; /* run script on change */
 
454
  lease->changed = 1; /* run script on change */
412
455
}
413
456
 
414
457
 
417
460
{
418
461
  if (daemon->lease_change_command)
419
462
    {
420
 
      char *mac = print_mac(daemon, lease->hwaddr, lease->hwaddr_len);
421
463
      char *addr = inet_ntoa(lease->addr);
422
464
      char *com = strrchr(daemon->lease_change_command, '/');
423
 
      pid_t pid = fork();
424
 
 
 
465
      char *p;
 
466
      pid_t pid;
 
467
      int i;
 
468
 
 
469
      /* stringify MAC into dhcp_buff */
 
470
      p = daemon->dhcp_buff;
 
471
      if (lease->hwaddr_type != ARPHRD_ETHER || lease->hwaddr_len == 0) 
 
472
        p += sprintf(p, "%.2x-", lease->hwaddr_type);
 
473
      for (i = 0; i < lease->hwaddr_len; i++)
 
474
        {
 
475
          p += sprintf(p, "%.2x", lease->hwaddr[i]);
 
476
          if (i != lease->hwaddr_len - 1)
 
477
            p += sprintf(p, ":");
 
478
        }
 
479
      
 
480
      /* and CLID into namebuff */
 
481
      p = daemon->namebuff;
 
482
      if (lease->clid)
 
483
        for (i = 0; i < lease->clid_len; i++)
 
484
          {
 
485
            p += sprintf(p, "%.2x", lease->clid[i]);
 
486
            if (i != lease->clid_len - 1) 
 
487
              p += sprintf(p, ":");
 
488
          }
 
489
      
 
490
      /* and expiry or length into dhcp_buff2 */
 
491
#ifdef HAVE_BROKEN_RTC
 
492
      sprintf(daemon->dhcp_buff2, "%u ", lease->length);
 
493
#else
 
494
      sprintf(daemon->dhcp_buff2, "%lu ", (unsigned long)lease->expires);
 
495
#endif
 
496
 
 
497
      pid = fork();
 
498
      
425
499
      if (pid == -1)
426
500
        return 0; /* fork error */
427
501
      else if (pid != 0)
428
502
        return pid;
 
503
      
 
504
      if (lease->clid && lease->clid_len != 0)
 
505
        setenv("DNSMASQ_CLIENT_ID", daemon->namebuff, 1);
 
506
      else
 
507
        unsetenv("DNSMASQ_CLIENT_ID");
 
508
 
 
509
#ifdef HAVE_BROKEN_RTC
 
510
      setenv("DNSMASQ_LEASE_LENGTH", daemon->dhcp_buff2, 1);
 
511
      unsetenv("DNSMASQ_LEASE_EXPIRES");
 
512
#else
 
513
      setenv("DNSMASQ_LEASE_EXPIRES", daemon->dhcp_buff2, 1); 
 
514
      unsetenv("DNSMASQ_LEASE_LENGTH");
 
515
#endif
429
516
 
430
517
      execl(daemon->lease_change_command, 
431
518
            com ? com+1 : daemon->lease_change_command,
432
 
            action, mac, addr, lease->hostname, (char*)NULL);
 
519
            action, daemon->dhcp_buff, addr, lease->hostname, (char*)NULL);
433
520
      
434
521
      /* log socket should still be open, right? */
435
522
      syslog(LOG_ERR, _("failed to execute %s: %m"), 
470
557
    }
471
558
 
472
559
  for (lease = leases; lease; lease = lease->next)
473
 
    if (lease->new || lease->old)
 
560
    if (lease->new || lease->changed || 
 
561
        (lease->aux_changed && (daemon->options & OPT_LEASE_RO)))
474
562
      {
475
563
        if (daemon->script_pid != 0)
476
564
          return; /* busy */
479
567
        daemon->script_pid = run_script(daemon, lease->new ? "add" : "old", lease);
480
568
#endif
481
569
 
482
 
        lease->new = lease->old = 0;
 
570
        lease->new = lease->changed = lease->aux_changed = 0;
483
571
      }
484
572
}
485
573