]>
Commit | Line | Data |
---|---|---|
1358b874 TL |
1 | /* db.c |
2 | ||
3 | Persistent database management routines for DHCPD... */ | |
4 | ||
5 | /* | |
f39b6e00 TL |
6 | * Copyright (c) 1996-1999 Internet Software Consortium. |
7 | * Use is subject to license terms which appear in the file named | |
8 | * ISC-LICENSE that should have accompanied this file when you | |
9 | * received it. If a file named ISC-LICENSE did not accompany this | |
10 | * file, or you are not sure the one you have is correct, you may | |
11 | * obtain an applicable copy of the license at: | |
1358b874 | 12 | * |
f39b6e00 | 13 | * http://www.isc.org/isc-license-1.0.html. |
1358b874 | 14 | * |
f39b6e00 TL |
15 | * This file is part of the ISC DHCP distribution. The documentation |
16 | * associated with this file is listed in the file DOCUMENTATION, | |
17 | * included in the top-level directory of this release. | |
1358b874 | 18 | * |
f39b6e00 TL |
19 | * Support and other services are available for ISC products - see |
20 | * http://www.isc.org for more information. | |
1358b874 TL |
21 | */ |
22 | ||
23 | #ifndef lint | |
24 | static char copyright[] = | |
f39b6e00 | 25 | "$Id: db.c,v 1.22 1999/03/16 05:50:43 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; |
1358b874 TL |
26 | #endif /* not lint */ |
27 | ||
28 | #include "dhcpd.h" | |
29 | ||
30 | FILE *db_file; | |
31 | ||
08804a9a TL |
32 | static int counting = 0; |
33 | static int count = 0; | |
34 | TIME write_time; | |
35 | ||
1358b874 TL |
36 | /* Write the specified lease to the current lease database file. */ |
37 | ||
38 | int write_lease (lease) | |
39 | struct lease *lease; | |
40 | { | |
41 | struct tm *t; | |
42 | char tbuf [64]; | |
a3115043 | 43 | int errors = 0; |
6fdff3b8 | 44 | int i; |
1358b874 | 45 | |
08804a9a TL |
46 | if (counting) |
47 | ++count; | |
1358b874 | 48 | errno = 0; |
a3115043 TL |
49 | fprintf (db_file, "lease %s {\n", piaddr (lease -> ip_addr)); |
50 | if (errno) { | |
51 | ++errors; | |
52 | } | |
1358b874 | 53 | |
3f165a40 TL |
54 | /* Note: the following is not a Y2K bug - it's a Y1.9K bug. Until |
55 | somebody invents a time machine, I think we can safely disregard | |
56 | it. */ | |
1358b874 | 57 | t = gmtime (&lease -> starts); |
f79741e8 | 58 | sprintf (tbuf, "%d %d/%02d/%02d %02d:%02d:%02d;", |
a3115043 TL |
59 | t -> tm_wday, t -> tm_year + 1900, |
60 | t -> tm_mon + 1, t -> tm_mday, | |
61 | t -> tm_hour, t -> tm_min, t -> tm_sec); | |
62 | errno = 0; | |
1358b874 | 63 | fprintf (db_file, "\tstarts %s\n", tbuf); |
a3115043 TL |
64 | if (errno) { |
65 | ++errors; | |
66 | } | |
1358b874 TL |
67 | |
68 | t = gmtime (&lease -> ends); | |
f79741e8 | 69 | sprintf (tbuf, "%d %d/%02d/%02d %02d:%02d:%02d;", |
a3115043 TL |
70 | t -> tm_wday, t -> tm_year + 1900, |
71 | t -> tm_mon + 1, t -> tm_mday, | |
72 | t -> tm_hour, t -> tm_min, t -> tm_sec); | |
73 | errno = 0; | |
1358b874 | 74 | fprintf (db_file, "\tends %s", tbuf); |
a3115043 TL |
75 | if (errno) { |
76 | ++errors; | |
77 | } | |
1358b874 | 78 | |
e2bfe7b3 TL |
79 | /* If this lease is billed to a class and is still valid, |
80 | write it out. */ | |
81 | if (lease -> billing_class && lease -> ends > cur_time) | |
82 | if (!write_billing_class (lease -> billing_class)) | |
83 | ++errors; | |
84 | ||
1358b874 | 85 | if (lease -> hardware_addr.hlen) { |
a3115043 TL |
86 | errno = 0; |
87 | fprintf (db_file, "\n\thardware %s %s;", | |
1358b874 TL |
88 | hardware_types [lease -> hardware_addr.htype], |
89 | print_hw_addr (lease -> hardware_addr.htype, | |
90 | lease -> hardware_addr.hlen, | |
91 | lease -> hardware_addr.haddr)); | |
a3115043 TL |
92 | if (errno) { |
93 | ++errors; | |
94 | } | |
1358b874 TL |
95 | } |
96 | if (lease -> uid_len) { | |
97 | int i; | |
a3115043 | 98 | errno = 0; |
17832ade | 99 | fprintf (db_file, "\n\tuid %2.2x", lease -> uid [0]); |
a3115043 TL |
100 | if (errno) { |
101 | ++errors; | |
102 | } | |
103 | for (i = 1; i < lease -> uid_len; i++) { | |
104 | errno = 0; | |
17832ade | 105 | fprintf (db_file, ":%2.2x", lease -> uid [i]); |
a3115043 TL |
106 | if (errno) { |
107 | ++errors; | |
108 | } | |
109 | } | |
110 | putc (';', db_file); | |
111 | } | |
112 | if (lease -> flags & BOOTP_LEASE) { | |
113 | errno = 0; | |
114 | fprintf (db_file, "\n\tdynamic-bootp;"); | |
115 | if (errno) { | |
4006d804 TL |
116 | ++errors; |
117 | } | |
118 | } | |
119 | if (lease -> flags & ABANDONED_LEASE) { | |
120 | errno = 0; | |
121 | fprintf (db_file, "\n\tabandoned;"); | |
122 | if (errno) { | |
a3115043 | 123 | ++errors; |
00d6d87c TL |
124 | } |
125 | } | |
126 | if (lease -> client_hostname) { | |
6fdff3b8 TL |
127 | for (i = 0; lease -> client_hostname [i]; i++) |
128 | if (lease -> client_hostname [i] < 33 || | |
129 | lease -> client_hostname [i] > 126) | |
130 | goto bad_client_hostname; | |
00d6d87c | 131 | errno = 0; |
200d216c | 132 | fprintf (db_file, "\n\tclient-hostname \"%s\";", |
00d6d87c TL |
133 | lease -> client_hostname); |
134 | if (errno) { | |
135 | ++errors; | |
136 | } | |
137 | } | |
6fdff3b8 | 138 | bad_client_hostname: |
00d6d87c | 139 | if (lease -> hostname) { |
6fdff3b8 TL |
140 | for (i = 0; lease -> hostname [i]; i++) |
141 | if (lease -> hostname [i] < 33 || | |
142 | lease -> hostname [i] > 126) | |
143 | goto bad_hostname; | |
144 | errno = 0; | |
00d6d87c | 145 | errno = 0; |
355f034a | 146 | fprintf (db_file, "\n\thostname \"%s\";", |
36b65b9c | 147 | lease -> hostname); |
00d6d87c TL |
148 | if (errno) { |
149 | ++errors; | |
a3115043 TL |
150 | } |
151 | } | |
6fdff3b8 | 152 | bad_hostname: |
a3115043 TL |
153 | errno = 0; |
154 | fputs ("\n}\n", db_file); | |
155 | if (errno) { | |
156 | ++errors; | |
1358b874 | 157 | } |
a3115043 | 158 | if (errors) |
8ae2d595 | 159 | log_info ("write_lease: unable to write lease %s", |
a3115043 TL |
160 | piaddr (lease -> ip_addr)); |
161 | return !errors; | |
1358b874 TL |
162 | } |
163 | ||
e2bfe7b3 TL |
164 | /* Write a spawned class to the database file. */ |
165 | ||
166 | int write_billing_class (class) | |
167 | struct class *class; | |
168 | { | |
169 | int errors = 0; | |
170 | int i; | |
171 | ||
172 | if (!class -> superclass) { | |
173 | errno = 0; | |
174 | fprintf (db_file, "\n\tbilling class \"%s\";", class -> name); | |
175 | return !errno; | |
176 | } | |
177 | ||
178 | errno = 0; | |
179 | fprintf (db_file, "\n\tbilling subclass \"%s\"", | |
180 | class -> superclass -> name); | |
181 | if (errno) | |
182 | ++errors; | |
183 | ||
184 | for (i = 0; i < class -> hash_string.len; i++) | |
185 | if (!isascii (class -> hash_string.data [i]) || | |
186 | !isprint (class -> hash_string.data [i])) | |
187 | break; | |
188 | if (i == class -> hash_string.len) { | |
189 | errno = 0; | |
190 | fprintf (db_file, " \"%*.*s\";", | |
191 | class -> hash_string.len, | |
192 | class -> hash_string.len, | |
193 | class -> hash_string.data); | |
194 | if (errno) | |
195 | ++errors; | |
196 | } else { | |
197 | errno = 0; | |
198 | fprintf (db_file, " %2.2x", class -> hash_string.data [0]); | |
199 | if (errno) | |
200 | ++errors; | |
201 | for (i = 1; i < class -> hash_string.len; i++) { | |
202 | errno = 0; | |
203 | fprintf (db_file, ":%2.2x", | |
204 | class -> hash_string.data [i]); | |
205 | if (errno) | |
206 | ++errors; | |
207 | } | |
208 | errno = 0; | |
209 | fprintf (db_file, ";"); | |
210 | if (errno) | |
211 | ++errors; | |
212 | } | |
213 | ||
214 | class -> dirty = 0; | |
215 | return !errors; | |
216 | } | |
217 | ||
1358b874 TL |
218 | /* Commit any leases that have been written out... */ |
219 | ||
220 | int commit_leases () | |
221 | { | |
a3115043 TL |
222 | /* Commit any outstanding writes to the lease database file. |
223 | We need to do this even if we're rewriting the file below, | |
224 | just in case the rewrite fails. */ | |
225 | if (fflush (db_file) == EOF) { | |
8ae2d595 | 226 | log_info ("commit_leases: unable to commit: %m"); |
a3115043 TL |
227 | return 0; |
228 | } | |
229 | if (fsync (fileno (db_file)) < 0) { | |
8ae2d595 | 230 | log_info ("commit_leases: unable to commit: %m"); |
a3115043 TL |
231 | return 0; |
232 | } | |
233 | ||
08804a9a TL |
234 | /* If we've written more than a thousand leases or if |
235 | we haven't rewritten the lease database in over an | |
236 | hour, rewrite it now. */ | |
237 | if (count > 1000 || (count && cur_time - write_time > 3600)) { | |
238 | count = 0; | |
239 | write_time = cur_time; | |
240 | new_lease_file (); | |
08804a9a | 241 | } |
1358b874 TL |
242 | return 1; |
243 | } | |
244 | ||
245 | void db_startup () | |
246 | { | |
247 | /* Read in the existing lease file... */ | |
248 | read_leases (); | |
249 | ||
b16b7f33 | 250 | GET_TIME (&write_time); |
1358b874 TL |
251 | new_lease_file (); |
252 | } | |
253 | ||
254 | void new_lease_file () | |
255 | { | |
256 | char newfname [512]; | |
257 | char backfname [512]; | |
258 | TIME t; | |
30856538 | 259 | int db_fd; |
1358b874 TL |
260 | |
261 | /* If we already have an open database, close it. */ | |
262 | if (db_file) { | |
263 | fclose (db_file); | |
264 | } | |
265 | ||
266 | /* Make a temporary lease file... */ | |
b16b7f33 TL |
267 | GET_TIME (&t); |
268 | sprintf (newfname, "%s.%d", path_dhcpd_db, (int)t); | |
30856538 TL |
269 | db_fd = open (newfname, O_WRONLY | O_TRUNC | O_CREAT, 0664); |
270 | if (db_fd < 0) { | |
8ae2d595 | 271 | log_fatal ("Can't create new lease file: %m"); |
30856538 TL |
272 | } |
273 | if ((db_file = fdopen (db_fd, "w")) == NULL) { | |
8ae2d595 | 274 | log_fatal ("Can't fdopen new lease file!"); |
1358b874 TL |
275 | } |
276 | ||
277 | /* Write out all the leases that we know of... */ | |
08804a9a | 278 | counting = 0; |
1358b874 TL |
279 | write_leases (); |
280 | ||
281 | /* Get the old database out of the way... */ | |
e2ac5814 | 282 | sprintf (backfname, "%s~", path_dhcpd_db); |
a3115043 | 283 | if (unlink (backfname) < 0 && errno != ENOENT) |
8ae2d595 | 284 | log_fatal ("Can't remove old lease database backup %s: %m", |
a3115043 | 285 | backfname); |
e2ac5814 | 286 | if (link (path_dhcpd_db, backfname) < 0) |
8ae2d595 | 287 | log_fatal ("Can't backup lease database %s to %s: %m", |
e2ac5814 | 288 | path_dhcpd_db, backfname); |
1358b874 TL |
289 | |
290 | /* Move in the new file... */ | |
e2ac5814 | 291 | if (rename (newfname, path_dhcpd_db) < 0) |
8ae2d595 | 292 | log_fatal ("Can't install new lease database %s to %s: %m", |
e2ac5814 | 293 | newfname, path_dhcpd_db); |
08804a9a TL |
294 | |
295 | counting = 1; | |
1358b874 | 296 | } |