~cyphermox/ubuntu/precise/dnsmasq/dbus

« back to all changes in this revision

Viewing changes to src/isc.c

  • Committer: Bazaar Package Importer
  • Author(s): Simon Kelley
  • Date: 2005-05-04 13:25:23 UTC
  • mfrom: (0.2.1 upstream) (1.1.2 hoary)
  • Revision ID: james.westby@ubuntu.com-20050504132523-29x9nzdnkypp62nc
Tags: 2.22-2
Make the resolv.conf polling code resistant to 
backwards-moving system clocks. (closes: #306117) (closes: #300694)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* dnsmasq is Copyright (c) 2000 - 2005 by Simon Kelley
 
2
 
 
3
   This program is free software; you can redistribute it and/or modify
 
4
   it under the terms of the GNU General Public License as published by
 
5
   the Free Software Foundation; version 2 dated June, 1991.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
*/
 
12
 
 
13
 
 
14
/* Code in this file is based on contributions by John Volpe. */
 
15
 
 
16
#include "dnsmasq.h"
 
17
 
 
18
#ifdef HAVE_ISC_READER
 
19
 
 
20
struct isc_lease {
 
21
  char *name, *fqdn;
 
22
  time_t expires;
 
23
  struct in_addr addr;
 
24
  struct isc_lease *next;
 
25
};
 
26
 
 
27
static struct isc_lease *leases = NULL;
 
28
static off_t lease_file_size = (off_t)0;
 
29
static ino_t lease_file_inode = (ino_t)0;
 
30
static int logged_lease = 0;
 
31
 
 
32
static int next_token (char *token, int buffsize, FILE * fp)
 
33
{
 
34
  int c, count = 0;
 
35
  char *cp = token;
 
36
  
 
37
  while((c = getc(fp)) != EOF)
 
38
    {
 
39
      if (c == '#')
 
40
        do { c = getc(fp); } while (c != '\n' && c != EOF);
 
41
      
 
42
      if (c == ' ' || c == '\t' || c == '\n' || c == ';')
 
43
        {
 
44
          if (count)
 
45
            break;
 
46
        }
 
47
      else if ((c != '"') && (count<buffsize-1))
 
48
        {
 
49
          *cp++ = c;
 
50
          count++;
 
51
        }
 
52
    }
 
53
  
 
54
  *cp = 0;
 
55
  return count ? 1 : 0;
 
56
}
 
57
 
 
58
void load_dhcp(struct daemon *daemon, time_t now)
 
59
{
 
60
  char *hostname = daemon->namebuff;
 
61
  char token[MAXTOK], *dot;
 
62
  struct in_addr host_address;
 
63
  time_t ttd, tts;
 
64
  FILE *fp;
 
65
  struct isc_lease *lease, *tmp, **up;
 
66
  struct stat statbuf;
 
67
 
 
68
  if (stat(daemon->lease_file, &statbuf) == -1)
 
69
    {
 
70
      if (!logged_lease)
 
71
        syslog(LOG_WARNING, "failed to access %s: %m", daemon->lease_file);
 
72
      logged_lease = 1;
 
73
      return;
 
74
    }
 
75
  
 
76
  logged_lease = 0;
 
77
  
 
78
  if ((statbuf.st_size <= lease_file_size) &&
 
79
      (statbuf.st_ino == lease_file_inode))
 
80
    return;
 
81
  
 
82
  lease_file_size = statbuf.st_size;
 
83
  lease_file_inode = statbuf.st_ino;
 
84
  
 
85
  if (!(fp = fopen (daemon->lease_file, "r")))
 
86
    {
 
87
      syslog (LOG_ERR, "failed to load %s: %m", daemon->lease_file);
 
88
      return;
 
89
    }
 
90
  
 
91
  syslog (LOG_INFO, "reading %s", daemon->lease_file);
 
92
 
 
93
  while ((next_token(token, MAXTOK, fp)))
 
94
    {
 
95
      if (strcmp(token, "lease") == 0)
 
96
        {
 
97
          hostname[0] = '\0';
 
98
          ttd = tts = (time_t)(-1);
 
99
          if (next_token(token, MAXTOK, fp) && 
 
100
              (host_address.s_addr = inet_addr(token)) != (in_addr_t) -1)
 
101
            {
 
102
              if (next_token(token, MAXTOK, fp) && *token == '{')
 
103
                {
 
104
                  while (next_token(token, MAXTOK, fp) && *token != '}')
 
105
                    {
 
106
                      if ((strcmp(token, "client-hostname") == 0) ||
 
107
                          (strcmp(token, "hostname") == 0))
 
108
                        {
 
109
                          if (next_token(hostname, MAXDNAME, fp))
 
110
                            if (!canonicalise(hostname))
 
111
                              {
 
112
                                *hostname = 0;
 
113
                                syslog(LOG_ERR, "bad name in %s", daemon->lease_file); 
 
114
                              }
 
115
                        }
 
116
                      else if ((strcmp(token, "ends") == 0) ||
 
117
                               (strcmp(token, "starts") == 0))
 
118
                        {
 
119
                          struct tm lease_time;
 
120
                          int is_ends = (strcmp(token, "ends") == 0);
 
121
                          if (next_token(token, MAXTOK, fp) &&  /* skip weekday */
 
122
                              next_token(token, MAXTOK, fp) &&  /* Get date from lease file */
 
123
                              sscanf (token, "%d/%d/%d", 
 
124
                                      &lease_time.tm_year,
 
125
                                      &lease_time.tm_mon,
 
126
                                      &lease_time.tm_mday) == 3 &&
 
127
                              next_token(token, MAXTOK, fp) &&
 
128
                              sscanf (token, "%d:%d:%d:", 
 
129
                                      &lease_time.tm_hour,
 
130
                                      &lease_time.tm_min, 
 
131
                                      &lease_time.tm_sec) == 3)
 
132
                            {
 
133
                              /* There doesn't seem to be a universally available library function
 
134
                                 which converts broken-down _GMT_ time to seconds-in-epoch.
 
135
                                 The following was borrowed from ISC dhcpd sources, where
 
136
                                 it is noted that it might not be entirely accurate for odd seconds.
 
137
                                 Since we're trying to get the same answer as dhcpd, that's just
 
138
                                 fine here. */
 
139
                              static int months [11] = { 31, 59, 90, 120, 151, 181,
 
140
                                                         212, 243, 273, 304, 334 };
 
141
                              time_t time = ((((((365 * (lease_time.tm_year - 1970) + /* Days in years since '70 */
 
142
                                                  (lease_time.tm_year - 1969) / 4 +   /* Leap days since '70 */
 
143
                                                  (lease_time.tm_mon > 1                /* Days in months this year */
 
144
                                                   ? months [lease_time.tm_mon - 2]
 
145
                                                   : 0) +
 
146
                                                  (lease_time.tm_mon > 2 &&         /* Leap day this year */
 
147
                                                   !((lease_time.tm_year - 1972) & 3)) +
 
148
                                                  lease_time.tm_mday - 1) * 24) +   /* Day of month */
 
149
                                                lease_time.tm_hour) * 60) +
 
150
                                              lease_time.tm_min) * 60) + lease_time.tm_sec;
 
151
                              if (is_ends)
 
152
                                ttd = time;
 
153
                              else
 
154
                                tts = time;                         }
 
155
                        }
 
156
                    }
 
157
                  
 
158
                  /* missing info? */
 
159
                  if (!*hostname)
 
160
                    continue;
 
161
                  if (ttd == (time_t)(-1))
 
162
                    continue;
 
163
                  
 
164
                  /* We use 0 as infinite in ttd */
 
165
                  if ((tts != -1) && (ttd == tts - 1))
 
166
                    ttd = (time_t)0;
 
167
                  else if (difftime(now, ttd) > 0)
 
168
                    continue;
 
169
 
 
170
                  if ((dot = strchr(hostname, '.')))
 
171
                    { 
 
172
                      if (!daemon->domain_suffix || hostname_isequal(dot+1, daemon->domain_suffix))
 
173
                        {
 
174
                          syslog(LOG_WARNING, 
 
175
                                 "Ignoring DHCP lease for %s because it has an illegal domain part", 
 
176
                                 hostname);
 
177
                          continue;
 
178
                        }
 
179
                      *dot = 0;
 
180
                    }
 
181
 
 
182
                  for (lease = leases; lease; lease = lease->next)
 
183
                    if (hostname_isequal(lease->name, hostname))
 
184
                      {
 
185
                        lease->expires = ttd;
 
186
                        lease->addr = host_address;
 
187
                        break;
 
188
                      }
 
189
 
 
190
                  if (!lease && (lease = malloc(sizeof(struct isc_lease))))
 
191
                    {
 
192
                      lease->expires = ttd;
 
193
                      lease->addr = host_address;
 
194
                      lease->fqdn =  NULL;
 
195
                      lease->next = leases;
 
196
                      if (!(lease->name = malloc(strlen(hostname)+1)))
 
197
                        free(lease);
 
198
                      else
 
199
                        {
 
200
                          leases = lease;
 
201
                          strcpy(lease->name, hostname);
 
202
                          if (daemon->domain_suffix && 
 
203
                              (lease->fqdn = malloc(strlen(hostname) + strlen(daemon->domain_suffix) + 2)))
 
204
                            {
 
205
                              strcpy(lease->fqdn, hostname);
 
206
                              strcat(lease->fqdn, ".");
 
207
                              strcat(lease->fqdn, daemon->domain_suffix);
 
208
                            }
 
209
                        }
 
210
                    }
 
211
                }
 
212
            }
 
213
        }
 
214
    }
 
215
 
 
216
  fclose(fp);
 
217
  
 
218
  /* prune expired leases */
 
219
  for (lease = leases, up = &leases; lease; lease = tmp)
 
220
     {
 
221
       tmp = lease->next;
 
222
       if (lease->expires != (time_t)0 && difftime(now, lease->expires) > 0)
 
223
         {
 
224
           *up = lease->next; /* unlink */
 
225
           free(lease->name);
 
226
           if (lease->fqdn)
 
227
             free(lease->fqdn);
 
228
           free(lease);
 
229
         }
 
230
       else
 
231
         up = &lease->next;
 
232
     }
 
233
 
 
234
     
 
235
  /* remove all existing DHCP cache entries */
 
236
  cache_unhash_dhcp();
 
237
 
 
238
  for (lease = leases; lease; lease = lease->next)
 
239
    {
 
240
      cache_add_dhcp_entry(daemon, lease->fqdn, &lease->addr, lease->expires);
 
241
      cache_add_dhcp_entry(daemon, lease->name, &lease->addr, lease->expires);
 
242
    }
 
243
}
 
244
 
 
245
#endif
 
246