source: MondoRescue/branches/3.3/mindi-busybox/networking/udhcp/files.c@ 3909

Last change on this file since 3909 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

File size: 6.6 KB
Line 
1/* vi: set sw=4 ts=4: */
2/*
3 * DHCP server config and lease file manipulation
4 *
5 * Rewrite by Russ Dill <Russ.Dill@asu.edu> July 2001
6 *
7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */
9#include <netinet/ether.h>
10
11#include "common.h"
12#include "dhcpd.h"
13
14/* on these functions, make sure your datatype matches */
15static int FAST_FUNC read_str(const char *line, void *arg)
16{
17 char **dest = arg;
18
19 free(*dest);
20 *dest = xstrdup(line);
21 return 1;
22}
23
24static int FAST_FUNC read_u32(const char *line, void *arg)
25{
26 *(uint32_t*)arg = bb_strtou32(line, NULL, 10);
27 return errno == 0;
28}
29
30static int FAST_FUNC read_staticlease(const char *const_line, void *arg)
31{
32 char *line;
33 char *mac_string;
34 char *ip_string;
35 struct ether_addr mac_bytes; /* it's "struct { uint8_t mac[6]; }" */
36 uint32_t nip;
37
38 /* Read mac */
39 line = (char *) const_line;
40 mac_string = strtok_r(line, " \t", &line);
41 if (!mac_string || !ether_aton_r(mac_string, &mac_bytes))
42 return 0;
43
44 /* Read ip */
45 ip_string = strtok_r(NULL, " \t", &line);
46 if (!ip_string || !udhcp_str2nip(ip_string, &nip))
47 return 0;
48
49 add_static_lease(arg, (uint8_t*) &mac_bytes, nip);
50
51 log_static_leases(arg);
52
53 return 1;
54}
55
56
57struct config_keyword {
58 const char *keyword;
59 int (*handler)(const char *line, void *var) FAST_FUNC;
60 unsigned ofs;
61 const char *def;
62};
63
64#define OFS(field) offsetof(struct server_config_t, field)
65
66static const struct config_keyword keywords[] = {
67 /* keyword handler variable address default */
68 {"start" , udhcp_str2nip , OFS(start_ip ), "192.168.0.20"},
69 {"end" , udhcp_str2nip , OFS(end_ip ), "192.168.0.254"},
70 {"interface" , read_str , OFS(interface ), "eth0"},
71 /* Avoid "max_leases value not sane" warning by setting default
72 * to default_end_ip - default_start_ip + 1: */
73 {"max_leases" , read_u32 , OFS(max_leases ), "235"},
74 {"auto_time" , read_u32 , OFS(auto_time ), "7200"},
75 {"decline_time" , read_u32 , OFS(decline_time ), "3600"},
76 {"conflict_time", read_u32 , OFS(conflict_time), "3600"},
77 {"offer_time" , read_u32 , OFS(offer_time ), "60"},
78 {"min_lease" , read_u32 , OFS(min_lease_sec), "60"},
79 {"lease_file" , read_str , OFS(lease_file ), LEASES_FILE},
80 {"pidfile" , read_str , OFS(pidfile ), "/var/run/udhcpd.pid"},
81 {"siaddr" , udhcp_str2nip , OFS(siaddr_nip ), "0.0.0.0"},
82 /* keywords with no defaults must be last! */
83 {"option" , udhcp_str2optset, OFS(options ), ""},
84 {"opt" , udhcp_str2optset, OFS(options ), ""},
85 {"notify_file" , read_str , OFS(notify_file ), NULL},
86 {"sname" , read_str , OFS(sname ), NULL},
87 {"boot_file" , read_str , OFS(boot_file ), NULL},
88 {"static_lease" , read_staticlease, OFS(static_leases), ""},
89};
90enum { KWS_WITH_DEFAULTS = ARRAY_SIZE(keywords) - 6 };
91
92void FAST_FUNC read_config(const char *file)
93{
94 parser_t *parser;
95 const struct config_keyword *k;
96 unsigned i;
97 char *token[2];
98
99 for (i = 0; i < KWS_WITH_DEFAULTS; i++)
100 keywords[i].handler(keywords[i].def, (char*)&server_config + keywords[i].ofs);
101
102 parser = config_open(file);
103 while (config_read(parser, token, 2, 2, "# \t", PARSE_NORMAL)) {
104 for (k = keywords, i = 0; i < ARRAY_SIZE(keywords); k++, i++) {
105 if (strcasecmp(token[0], k->keyword) == 0) {
106 if (!k->handler(token[1], (char*)&server_config + k->ofs)) {
107 bb_error_msg("can't parse line %u in %s",
108 parser->lineno, file);
109 /* reset back to the default value */
110 k->handler(k->def, (char*)&server_config + k->ofs);
111 }
112 break;
113 }
114 }
115 }
116 config_close(parser);
117
118 server_config.start_ip = ntohl(server_config.start_ip);
119 server_config.end_ip = ntohl(server_config.end_ip);
120}
121
122void FAST_FUNC write_leases(void)
123{
124 int fd;
125 unsigned i;
126 leasetime_t curr;
127 int64_t written_at;
128
129 fd = open_or_warn(server_config.lease_file, O_WRONLY|O_CREAT|O_TRUNC);
130 if (fd < 0)
131 return;
132
133 curr = written_at = time(NULL);
134
135 written_at = SWAP_BE64(written_at);
136 full_write(fd, &written_at, sizeof(written_at));
137
138 for (i = 0; i < server_config.max_leases; i++) {
139 leasetime_t tmp_time;
140
141 if (g_leases[i].lease_nip == 0)
142 continue;
143
144 /* Screw with the time in the struct, for easier writing */
145 tmp_time = g_leases[i].expires;
146
147 g_leases[i].expires -= curr;
148 if ((signed_leasetime_t) g_leases[i].expires < 0)
149 g_leases[i].expires = 0;
150 g_leases[i].expires = htonl(g_leases[i].expires);
151
152 /* No error check. If the file gets truncated,
153 * we lose some leases on restart. Oh well. */
154 full_write(fd, &g_leases[i], sizeof(g_leases[i]));
155
156 /* Then restore it when done */
157 g_leases[i].expires = tmp_time;
158 }
159 close(fd);
160
161 if (server_config.notify_file) {
162 char *argv[3];
163 argv[0] = server_config.notify_file;
164 argv[1] = server_config.lease_file;
165 argv[2] = NULL;
166 spawn_and_wait(argv);
167 }
168}
169
170void FAST_FUNC read_leases(const char *file)
171{
172 struct dyn_lease lease;
173 int64_t written_at, time_passed;
174 int fd;
175#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
176 unsigned i = 0;
177#endif
178
179 fd = open_or_warn(file, O_RDONLY);
180 if (fd < 0)
181 return;
182
183 if (full_read(fd, &written_at, sizeof(written_at)) != sizeof(written_at))
184 goto ret;
185 written_at = SWAP_BE64(written_at);
186
187 time_passed = time(NULL) - written_at;
188 /* Strange written_at, or lease file from old version of udhcpd
189 * which had no "written_at" field? */
190 if ((uint64_t)time_passed > 12 * 60 * 60)
191 goto ret;
192
193 while (full_read(fd, &lease, sizeof(lease)) == sizeof(lease)) {
194 uint32_t y = ntohl(lease.lease_nip);
195 if (y >= server_config.start_ip && y <= server_config.end_ip) {
196 signed_leasetime_t expires = ntohl(lease.expires) - (signed_leasetime_t)time_passed;
197 uint32_t static_nip;
198
199 if (expires <= 0)
200 /* We keep expired leases: add_lease() will add
201 * a lease with 0 seconds remaining.
202 * Fewer IP address changes this way for mass reboot scenario.
203 */
204 expires = 0;
205
206 /* Check if there is a different static lease for this IP or MAC */
207 static_nip = get_static_nip_by_mac(server_config.static_leases, lease.lease_mac);
208 if (static_nip) {
209 /* NB: we do not add lease even if static_nip == lease.lease_nip.
210 */
211 continue;
212 }
213 if (is_nip_reserved(server_config.static_leases, lease.lease_nip))
214 continue;
215
216 /* NB: add_lease takes "relative time", IOW,
217 * lease duration, not lease deadline. */
218 if (add_lease(lease.lease_mac, lease.lease_nip,
219 expires,
220 lease.hostname, sizeof(lease.hostname)
221 ) == 0
222 ) {
223 bb_error_msg("too many leases while loading %s", file);
224 break;
225 }
226#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
227 i++;
228#endif
229 }
230 }
231 log1("read %d leases", i);
232 ret:
233 close(fd);
234}
Note: See TracBrowser for help on using the repository browser.