~ubuntu-branches/debian/lenny/dnsmasq/lenny

« back to all changes in this revision

Viewing changes to src/lease.c

  • Committer: Bazaar Package Importer
  • Author(s): Simon Kelley
  • Date: 2008-07-20 19:27:11 UTC
  • mfrom: (0.3.1 upstream) (9.1.4 hardy)
  • Revision ID: james.westby@ubuntu.com-20080720192711-b0lg0kl8egyg0v1b
Tags: 2.45-1
New upstream - fixes regression when min-port not set.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* dnsmasq is Copyright (c) 2000-2006 Simon Kelley
 
1
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley
2
2
 
3
3
   This program is free software; you can redistribute it and/or modify
4
4
   it under the terms of the GNU General Public License as published by
5
 
   the Free Software Foundation; version 2 dated June, 1991.
6
 
 
 
5
   the Free Software Foundation; version 2 dated June, 1991, or
 
6
   (at your option) version 3 dated 29 June, 2007.
 
7
 
7
8
   This program is distributed in the hope that it will be useful,
8
9
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
10
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
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/>.
11
15
*/
12
16
 
13
17
#include "dnsmasq.h"
14
18
 
15
 
static struct dhcp_lease *leases, *old_leases;
 
19
static struct dhcp_lease *leases = NULL, *old_leases = NULL;
16
20
static int dns_dirty, file_dirty, leases_left;
17
21
 
18
 
void lease_init(struct daemon *daemon, time_t now)
 
22
void lease_init(time_t now)
19
23
{
20
24
  unsigned long ei;
21
25
  struct in_addr addr;
22
26
  struct dhcp_lease *lease;
23
 
  int flags, clid_len, hw_len, hw_type;
 
27
  int clid_len, hw_len, hw_type;
24
28
  FILE *leasestream;
25
29
  
26
 
  leases = old_leases = NULL;
 
30
  /* These two each hold a DHCP option max size 255
 
31
     and get a terminating zero added */
 
32
  daemon->dhcp_buff = safe_malloc(256);
 
33
  daemon->dhcp_buff2 = safe_malloc(256); 
 
34
  
27
35
  leases_left = daemon->dhcp_max;
28
36
 
29
37
  if (daemon->options & OPT_LEASE_RO)
47
55
      leasestream = daemon->lease_stream = fopen(daemon->lease_file, "a+");
48
56
      
49
57
      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); 
 
58
        die(_("cannot open or create lease file %s: %s"), daemon->lease_file, EC_FILE);
55
59
      
56
60
      /* a+ mode lease pointer at end. */
57
61
      rewind(leasestream);
77
81
          clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL);
78
82
        
79
83
        if (!(lease = lease_allocate(addr)))
80
 
          die (_("too many stored leases"), NULL);
81
 
        /* not actually new */
82
 
        lease->new = 0;
83
 
        
 
84
          die (_("too many stored leases"), NULL, EC_MISC);
 
85
        
84
86
#ifdef HAVE_BROKEN_RTC
85
87
        if (ei != 0)
86
88
          lease->expires = (time_t)ei + now;
96
98
        lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet, hw_len, hw_type, clid_len);
97
99
        
98
100
        if (strcmp(daemon->dhcp_buff, "*") !=  0)
99
 
          lease_set_hostname(lease, daemon->dhcp_buff, daemon->domain_suffix, 0);
 
101
          {
 
102
            char *p;
 
103
            /* unprotect spaces */
 
104
            for (p = strchr(daemon->dhcp_buff, '*'); p; p = strchr(p, '*'))
 
105
              *p = ' ';
 
106
            lease_set_hostname(lease, daemon->dhcp_buff, daemon->domain_suffix, 0);
 
107
          }
 
108
 
 
109
        /* set these correctly: the "old" events are generated later from
 
110
           the startup synthesised SIGHUP. */
 
111
        lease->new = lease->changed = 0;
100
112
      }
101
113
  
102
114
  if (!daemon->lease_stream)
110
122
            errno = ENOENT;
111
123
          else if (WEXITSTATUS(rc) == 126)
112
124
            errno = EACCES;
113
 
          die(_("cannot run lease-init script %s: %s"), daemon->lease_change_command);
 
125
          die(_("cannot run lease-init script %s: %s"), daemon->lease_change_command, EC_FILE);
114
126
        }
115
127
      
116
128
      if (WEXITSTATUS(rc) != 0)
117
129
        {
118
130
          sprintf(daemon->dhcp_buff, "%d", WEXITSTATUS(rc));
119
 
          die(_("lease-init script returned exit code %s"), daemon->dhcp_buff);
 
131
          die(_("lease-init script returned exit code %s"), daemon->dhcp_buff, WEXITSTATUS(rc) + EC_INIT_OFFSET);
120
132
        }
121
133
    }
122
134
 
126
138
  dns_dirty = 1;
127
139
}
128
140
 
129
 
void lease_update_from_configs(struct daemon *daemon)
 
141
void lease_update_from_configs(void)
130
142
{
131
143
  /* changes to the config may change current leases. */
132
144
  
140
152
        (config->flags & CONFIG_NAME) &&
141
153
        (!(config->flags & CONFIG_ADDR) || config->addr.s_addr == lease->addr.s_addr))
142
154
      lease_set_hostname(lease, config->hostname, daemon->domain_suffix, 1);
143
 
    else if ((name = host_from_dns(daemon, lease->addr)))
 
155
    else if ((name = host_from_dns(lease->addr)))
144
156
      lease_set_hostname(lease, name, daemon->domain_suffix, 1); /* updates auth flag only */
145
157
}
146
158
 
147
 
static void ourprintf(struct daemon *daemon, int *errp, char *format, ...)
 
159
static void ourprintf(int *errp, char *format, ...)
148
160
{
149
161
  va_list ap;
150
162
  
154
166
  va_end(ap);
155
167
}
156
168
 
157
 
void lease_update_file(struct daemon *daemon, time_t now)
 
169
void lease_update_file(time_t now)
158
170
{
159
171
  struct dhcp_lease *lease;
160
172
  time_t next_event;
161
173
  int i, err = 0;
 
174
  char *p;
162
175
 
163
176
  if (file_dirty != 0 && daemon->lease_stream)
164
177
    {
170
183
      for (lease = leases; lease; lease = lease->next)
171
184
        {
172
185
#ifdef HAVE_BROKEN_RTC
173
 
          ourprintf(daemon, &err, "%u ", lease->length);
 
186
          ourprintf(&err, "%u ", lease->length);
174
187
#else
175
 
          ourprintf(daemon, &err, "%lu ", (unsigned long)lease->expires);
 
188
          ourprintf(&err, "%lu ", (unsigned long)lease->expires);
176
189
#endif
177
190
          if (lease->hwaddr_type != ARPHRD_ETHER || lease->hwaddr_len == 0) 
178
 
            ourprintf(daemon, &err, "%.2x-", lease->hwaddr_type);
 
191
            ourprintf(&err, "%.2x-", lease->hwaddr_type);
179
192
          for (i = 0; i < lease->hwaddr_len; i++)
180
193
            {
181
 
              ourprintf(daemon, &err, "%.2x", lease->hwaddr[i]);
 
194
              ourprintf(&err, "%.2x", lease->hwaddr[i]);
182
195
              if (i != lease->hwaddr_len - 1)
183
 
                ourprintf(daemon, &err, ":");
 
196
                ourprintf(&err, ":");
184
197
            }
185
 
          ourprintf(daemon, &err, " %s %s ", inet_ntoa(lease->addr),
186
 
                    lease->hostname && strlen(lease->hostname) != 0 ? lease->hostname : "*");
 
198
 
 
199
          ourprintf(&err, " %s ", inet_ntoa(lease->addr));
 
200
          
 
201
          /* substitute * for space: "*" is an illegal name, as is " " */
 
202
          if (lease->hostname)
 
203
            for (p = lease->hostname; *p; p++)
 
204
              ourprintf(&err, "%c", *p == ' ' ? '*' : *p);
 
205
          else
 
206
            ourprintf(&err, "*");
 
207
          ourprintf(&err, " ");
187
208
          
188
209
          if (lease->clid && lease->clid_len != 0)
189
210
            {
190
211
              for (i = 0; i < lease->clid_len - 1; i++)
191
 
                ourprintf(daemon, &err, "%.2x:", lease->clid[i]);
192
 
              ourprintf(daemon, &err, "%.2x\n", lease->clid[i]);
 
212
                ourprintf(&err, "%.2x:", lease->clid[i]);
 
213
              ourprintf(&err, "%.2x\n", lease->clid[i]);
193
214
            }
194
215
          else
195
 
            ourprintf(daemon, &err, "*\n");       
 
216
            ourprintf(&err, "*\n");       
196
217
        }
197
218
      
198
219
      if (fflush(daemon->lease_stream) != 0 ||
214
235
      if (next_event == 0 || difftime(next_event, LEASE_RETRY + now) > 0.0)
215
236
        next_event = LEASE_RETRY + now;
216
237
      
217
 
      syslog(LOG_ERR, _("failed to write %s: %s (retry in %us)"), 
218
 
             daemon->lease_file, strerror(err),
219
 
             (unsigned int)difftime(next_event, now));
 
238
      my_syslog(LOG_ERR, _("failed to write %s: %s (retry in %us)"), 
 
239
                daemon->lease_file, strerror(err),
 
240
                (unsigned int)difftime(next_event, now));
220
241
    }
221
242
 
222
243
  if (next_event != 0)
223
244
    alarm((unsigned)difftime(next_event, now)); 
224
245
}
225
246
 
226
 
void lease_update_dns(struct daemon *daemon)
 
247
void lease_update_dns(void)
227
248
{
228
249
  struct dhcp_lease *lease;
229
250
  
230
 
  if (dns_dirty)
 
251
  if (daemon->port != 0 && dns_dirty)
231
252
    {
232
253
      cache_unhash_dhcp();
233
254
      
234
255
      for (lease = leases; lease; lease = lease->next)
235
256
        {
236
 
          cache_add_dhcp_entry(daemon, lease->fqdn, &lease->addr, lease->expires);
237
 
          cache_add_dhcp_entry(daemon, lease->hostname, &lease->addr, lease->expires);
 
257
          cache_add_dhcp_entry(lease->fqdn, &lease->addr, lease->expires);
 
258
          cache_add_dhcp_entry(lease->hostname, &lease->addr, lease->expires);
238
259
        }
239
260
      
240
261
      dns_dirty = 0;
306
327
struct dhcp_lease *lease_allocate(struct in_addr addr)
307
328
{
308
329
  struct dhcp_lease *lease;
309
 
  if (!leases_left || !(lease = malloc(sizeof(struct dhcp_lease))))
 
330
  if (!leases_left || !(lease = whine_malloc(sizeof(struct dhcp_lease))))
310
331
    return NULL;
311
332
 
312
333
  memset(lease, 0, sizeof(struct dhcp_lease));
313
334
  lease->new = 1;
314
335
  lease->addr = addr;
315
 
  lease->hwaddr_len = 225; /* illegal value */
 
336
  lease->hwaddr_len = 256; /* illegal value */
316
337
  lease->expires = 1;
317
338
#ifdef HAVE_BROKEN_RTC
318
339
  lease->length = 0xffffffff; /* illegal value */
378
399
      if (lease->clid_len != clid_len)
379
400
        {
380
401
          lease->aux_changed = file_dirty = 1;
381
 
          if (lease->clid)
382
 
            free(lease->clid);
383
 
          if (!(lease->clid = malloc(clid_len)))
 
402
          free(lease->clid);
 
403
          if (!(lease->clid = whine_malloc(clid_len)))
384
404
            return;
385
405
        }
386
406
      else if (memcmp(lease->clid, clid, clid_len) != 0)
420
440
              return;
421
441
            /* this shouldn't happen unless updates are very quick and the
422
442
               script very slow, we just avoid a memory leak if it does. */
423
 
            if (lease_tmp->old_hostname)
424
 
              free(lease_tmp->old_hostname);
 
443
            free(lease_tmp->old_hostname);
425
444
            lease_tmp->old_hostname = lease_tmp->hostname;
426
445
            lease_tmp->hostname = NULL;
427
446
            if (lease_tmp->fqdn)
432
451
            break;
433
452
          }
434
453
     
435
 
      if (!new_name && (new_name = malloc(strlen(name) + 1)))
 
454
      if (!new_name && (new_name = whine_malloc(strlen(name) + 1)))
436
455
        strcpy(new_name, name);
437
456
      
438
 
      if (suffix && !new_fqdn && (new_fqdn = malloc(strlen(name) + strlen(suffix) + 2)))
 
457
      if (suffix && !new_fqdn && (new_fqdn = whine_malloc(strlen(name) + strlen(suffix) + 2)))
439
458
        {
440
459
          strcpy(new_fqdn, name);
441
460
          strcat(new_fqdn, ".");
446
465
  if (lease->hostname)
447
466
    {
448
467
      /* run script to say we lost our old name */
449
 
      if (lease->old_hostname)
450
 
        free(lease->old_hostname);
 
468
      free(lease->old_hostname);
451
469
      lease->old_hostname = lease->hostname;
452
470
    }
453
471
 
454
 
  if (lease->fqdn)
455
 
    free(lease->fqdn);
 
472
  free(lease->fqdn);
456
473
  
457
474
  lease->hostname = new_name;
458
475
  lease->fqdn = new_fqdn;
463
480
  lease->changed = 1; /* run script on change */
464
481
}
465
482
 
 
483
void lease_set_interface(struct dhcp_lease *lease, int interface)
 
484
{
 
485
  if (lease->last_interface == interface)
 
486
    return;
 
487
 
 
488
  lease->last_interface = interface;
 
489
  lease->changed = 1;
 
490
}
 
491
 
 
492
void rerun_scripts(void)
 
493
{
 
494
  struct dhcp_lease *lease;
 
495
  
 
496
  for (lease = leases; lease; lease = lease->next)
 
497
    lease->changed = 1;
 
498
}
 
499
 
466
500
/* deleted leases get transferred to the old_leases list.
467
501
   remove them here, after calling the lease change
468
502
   script. Also run the lease change script on new/modified leases.
469
503
 
470
504
   Return zero if nothing to do. */
471
 
int do_script_run(struct daemon *daemon)
 
505
int do_script_run(time_t now)
472
506
{
473
507
  struct dhcp_lease *lease;
474
508
 
479
513
      /* If the lease still has an old_hostname, do the "old" action on that first */
480
514
      if (lease->old_hostname)
481
515
        {
482
 
          queue_script(daemon, ACTION_OLD_HOSTNAME, lease, lease->old_hostname);
 
516
#ifndef NO_FORK
 
517
          queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now);
 
518
#endif
483
519
          free(lease->old_hostname);
484
520
          lease->old_hostname = NULL;
485
521
          return 1;
486
522
        }
487
523
      else 
488
524
        {
489
 
          queue_script(daemon, ACTION_DEL, lease, lease->hostname);
 
525
#ifndef NO_FORK
 
526
          queue_script(ACTION_DEL, lease, lease->hostname, now);
 
527
#endif
490
528
          old_leases = lease->next;
491
529
          
492
 
          if (lease->hostname)
493
 
            free(lease->hostname); 
494
 
          if (lease->fqdn)
495
 
            free(lease->fqdn);
496
 
          if (lease->clid)
497
 
            free(lease->clid);
498
 
          if (lease->vendorclass)
499
 
            free(lease->vendorclass);
500
 
          if (lease->userclass)
501
 
            free(lease->userclass);
 
530
          free(lease->hostname); 
 
531
          free(lease->fqdn);
 
532
          free(lease->clid);
 
533
          free(lease->vendorclass);
 
534
          free(lease->userclass);
502
535
          free(lease);
503
536
            
504
537
          return 1; 
509
542
  for (lease = leases; lease; lease = lease->next)
510
543
    if (lease->old_hostname)
511
544
      { 
512
 
        queue_script(daemon, ACTION_OLD_HOSTNAME, lease, lease->old_hostname);
 
545
#ifndef NO_FORK
 
546
        queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now);
 
547
#endif
513
548
        free(lease->old_hostname);
514
549
        lease->old_hostname = NULL;
515
550
        return 1;
519
554
    if (lease->new || lease->changed || 
520
555
        (lease->aux_changed && (daemon->options & OPT_LEASE_RO)))
521
556
      {
522
 
        queue_script(daemon, lease->new ? ACTION_ADD : ACTION_OLD, lease, lease->hostname);
 
557
#ifndef NO_FORK
 
558
        queue_script(lease->new ? ACTION_ADD : ACTION_OLD, lease, lease->hostname, now);
 
559
#endif
523
560
        lease->new = lease->changed = lease->aux_changed = 0;
524
561
        
525
562
        /* these are used for the "add" call, then junked, since they're not in the database */
526
 
        if (lease->vendorclass)
527
 
          {
528
 
            free(lease->vendorclass);
529
 
            lease->vendorclass = NULL;
530
 
          }
531
 
        if (lease->userclass)
532
 
          {
533
 
            free(lease->userclass);
534
 
            lease->userclass = NULL;
535
 
          }
 
563
        free(lease->vendorclass);
 
564
        lease->vendorclass = NULL;
536
565
        
 
566
        free(lease->userclass);
 
567
        lease->userclass = NULL;
 
568
                
537
569
        return 1;
538
570
      }
539
571