1 /* vi: set sw=4 ts=4: */
3 * DHCP server config and lease file manipulation
5 * Rewrite by Russ Dill <Russ.Dill@asu.edu> July 2001
7 * Licensed under GPLv2, see file LICENSE in this source tree.
9 #include <netinet/ether.h>
14 /* on these functions, make sure your datatype matches */
15 static int FAST_FUNC
read_str(const char *line
, void *arg
)
20 *dest
= xstrdup(line
);
24 static int FAST_FUNC
read_u32(const char *line
, void *arg
)
26 *(uint32_t*)arg
= bb_strtou32(line
, NULL
, 10);
30 static int FAST_FUNC
read_staticlease(const char *const_line
, void *arg
)
35 struct ether_addr mac_bytes
; /* it's "struct { uint8_t mac[6]; }" */
39 line
= (char *) const_line
;
40 mac_string
= strtok_r(line
, " \t", &line
);
41 if (!mac_string
|| !ether_aton_r(mac_string
, &mac_bytes
))
45 ip_string
= strtok_r(NULL
, " \t", &line
);
46 if (!ip_string
|| !udhcp_str2nip(ip_string
, &nip
))
49 add_static_lease(arg
, (uint8_t*) &mac_bytes
, nip
);
51 log_static_leases(arg
);
57 struct config_keyword
{
59 int (*handler
)(const char *line
, void *var
) FAST_FUNC
;
64 static const struct config_keyword keywords
[] = {
65 /* keyword handler variable address default */
66 {"start" , udhcp_str2nip
, &server_config
.start_ip
, "192.168.0.20"},
67 {"end" , udhcp_str2nip
, &server_config
.end_ip
, "192.168.0.254"},
68 {"interface" , read_str
, &server_config
.interface
, "eth0"},
69 /* Avoid "max_leases value not sane" warning by setting default
70 * to default_end_ip - default_start_ip + 1: */
71 {"max_leases" , read_u32
, &server_config
.max_leases
, "235"},
72 {"auto_time" , read_u32
, &server_config
.auto_time
, "7200"},
73 {"decline_time" , read_u32
, &server_config
.decline_time
, "3600"},
74 {"conflict_time", read_u32
, &server_config
.conflict_time
, "3600"},
75 {"offer_time" , read_u32
, &server_config
.offer_time
, "60"},
76 {"min_lease" , read_u32
, &server_config
.min_lease_sec
, "60"},
77 {"lease_file" , read_str
, &server_config
.lease_file
, LEASES_FILE
},
78 {"pidfile" , read_str
, &server_config
.pidfile
, "/var/run/udhcpd.pid"},
79 {"siaddr" , udhcp_str2nip
, &server_config
.siaddr_nip
, "0.0.0.0"},
80 /* keywords with no defaults must be last! */
81 {"option" , udhcp_str2optset
, &server_config
.options
, ""},
82 {"opt" , udhcp_str2optset
, &server_config
.options
, ""},
83 {"notify_file" , read_str
, &server_config
.notify_file
, ""},
84 {"sname" , read_str
, &server_config
.sname
, ""},
85 {"boot_file" , read_str
, &server_config
.boot_file
, ""},
86 {"static_lease" , read_staticlease
, &server_config
.static_leases
, ""},
88 enum { KWS_WITH_DEFAULTS
= ARRAY_SIZE(keywords
) - 6 };
90 void FAST_FUNC
read_config(const char *file
)
93 const struct config_keyword
*k
;
97 for (i
= 0; i
< KWS_WITH_DEFAULTS
; i
++)
98 keywords
[i
].handler(keywords
[i
].def
, keywords
[i
].var
);
100 parser
= config_open(file
);
101 while (config_read(parser
, token
, 2, 2, "# \t", PARSE_NORMAL
)) {
102 for (k
= keywords
, i
= 0; i
< ARRAY_SIZE(keywords
); k
++, i
++) {
103 if (strcasecmp(token
[0], k
->keyword
) == 0) {
104 if (!k
->handler(token
[1], k
->var
)) {
105 bb_error_msg("can't parse line %u in %s",
106 parser
->lineno
, file
);
107 /* reset back to the default value */
108 k
->handler(k
->def
, k
->var
);
114 config_close(parser
);
116 server_config
.start_ip
= ntohl(server_config
.start_ip
);
117 server_config
.end_ip
= ntohl(server_config
.end_ip
);
120 void FAST_FUNC
write_leases(void)
127 fd
= open_or_warn(server_config
.lease_file
, O_WRONLY
|O_CREAT
|O_TRUNC
);
131 curr
= written_at
= time(NULL
);
133 written_at
= SWAP_BE64(written_at
);
134 full_write(fd
, &written_at
, sizeof(written_at
));
136 for (i
= 0; i
< server_config
.max_leases
; i
++) {
137 leasetime_t tmp_time
;
139 if (g_leases
[i
].lease_nip
== 0)
142 /* Screw with the time in the struct, for easier writing */
143 tmp_time
= g_leases
[i
].expires
;
145 g_leases
[i
].expires
-= curr
;
146 if ((signed_leasetime_t
) g_leases
[i
].expires
< 0)
147 g_leases
[i
].expires
= 0;
148 g_leases
[i
].expires
= htonl(g_leases
[i
].expires
);
150 /* No error check. If the file gets truncated,
151 * we lose some leases on restart. Oh well. */
152 full_write(fd
, &g_leases
[i
], sizeof(g_leases
[i
]));
154 /* Then restore it when done */
155 g_leases
[i
].expires
= tmp_time
;
159 if (server_config
.notify_file
) {
161 argv
[0] = server_config
.notify_file
;
162 argv
[1] = server_config
.lease_file
;
164 spawn_and_wait(argv
);
168 void FAST_FUNC
read_leases(const char *file
)
170 struct dyn_lease lease
;
171 int64_t written_at
, time_passed
;
173 #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
177 fd
= open_or_warn(file
, O_RDONLY
);
181 if (full_read(fd
, &written_at
, sizeof(written_at
)) != sizeof(written_at
))
183 written_at
= SWAP_BE64(written_at
);
185 time_passed
= time(NULL
) - written_at
;
186 /* Strange written_at, or lease file from old version of udhcpd
187 * which had no "written_at" field? */
188 if ((uint64_t)time_passed
> 12 * 60 * 60)
191 while (full_read(fd
, &lease
, sizeof(lease
)) == sizeof(lease
)) {
192 //FIXME: what if it matches some static lease?
193 uint32_t y
= ntohl(lease
.lease_nip
);
194 if (y
>= server_config
.start_ip
&& y
<= server_config
.end_ip
) {
195 signed_leasetime_t expires
= ntohl(lease
.expires
) - (signed_leasetime_t
)time_passed
;
198 /* NB: add_lease takes "relative time", IOW,
199 * lease duration, not lease deadline. */
200 if (add_lease(lease
.lease_mac
, lease
.lease_nip
,
202 lease
.hostname
, sizeof(lease
.hostname
)
205 bb_error_msg("too many leases while loading %s", file
);
208 #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
213 log1("Read %d leases", i
);