aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2016-10-04 00:37:50 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2016-10-04 00:56:58 +0200
commit2bf2931d526fbd3998b9ffe99cdbad5d5ea6d290 (patch)
treeb3a9944d558acea501d9b06b8221b6b45ba4a787
parent095ddf7669a05b52839ccbfd2c324de718241747 (diff)
downloadbusybox-w32-2bf2931d526fbd3998b9ffe99cdbad5d5ea6d290.tar.gz
busybox-w32-2bf2931d526fbd3998b9ffe99cdbad5d5ea6d290.tar.bz2
busybox-w32-2bf2931d526fbd3998b9ffe99cdbad5d5ea6d290.zip
dhcp: merge files.c into dhcpd.c
Added NOINLINE to two function, since my version of gcc would actualy increase code size otherwise. I see no size changes. Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/udhcp/Kbuild.src2
-rw-r--r--networking/udhcp/dhcpd.c223
-rw-r--r--networking/udhcp/dhcpd.h6
-rw-r--r--networking/udhcp/files.c234
4 files changed, 222 insertions, 243 deletions
diff --git a/networking/udhcp/Kbuild.src b/networking/udhcp/Kbuild.src
index b8767baea..bfa776860 100644
--- a/networking/udhcp/Kbuild.src
+++ b/networking/udhcp/Kbuild.src
@@ -13,7 +13,7 @@ lib-$(CONFIG_UDHCPC) += common.o packet.o signalpipe.o socket.o
13lib-$(CONFIG_UDHCPD) += common.o packet.o signalpipe.o socket.o 13lib-$(CONFIG_UDHCPD) += common.o packet.o signalpipe.o socket.o
14 14
15lib-$(CONFIG_UDHCPC) += dhcpc.o 15lib-$(CONFIG_UDHCPC) += dhcpc.o
16lib-$(CONFIG_UDHCPD) += dhcpd.o arpping.o files.o leases.o static_leases.o 16lib-$(CONFIG_UDHCPD) += dhcpd.o arpping.o leases.o static_leases.o
17lib-$(CONFIG_DUMPLEASES) += dumpleases.o 17lib-$(CONFIG_DUMPLEASES) += dumpleases.o
18lib-$(CONFIG_DHCPRELAY) += dhcprelay.o 18lib-$(CONFIG_DHCPRELAY) += dhcprelay.o
19 19
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c
index e93a9f1da..8bd65df52 100644
--- a/networking/udhcp/dhcpd.c
+++ b/networking/udhcp/dhcpd.c
@@ -33,11 +33,232 @@
33//usage: "\n -P N Use port N (default 67)" 33//usage: "\n -P N Use port N (default 67)"
34//usage: ) 34//usage: )
35 35
36#include <netinet/ether.h>
36#include <syslog.h> 37#include <syslog.h>
37#include "common.h" 38#include "common.h"
38#include "dhcpc.h" 39#include "dhcpc.h"
39#include "dhcpd.h" 40#include "dhcpd.h"
40 41
42/* on these functions, make sure your datatype matches */
43static int FAST_FUNC read_str(const char *line, void *arg)
44{
45 char **dest = arg;
46
47 free(*dest);
48 *dest = xstrdup(line);
49 return 1;
50}
51
52static int FAST_FUNC read_u32(const char *line, void *arg)
53{
54 *(uint32_t*)arg = bb_strtou32(line, NULL, 10);
55 return errno == 0;
56}
57
58static int FAST_FUNC read_staticlease(const char *const_line, void *arg)
59{
60 char *line;
61 char *mac_string;
62 char *ip_string;
63 struct ether_addr mac_bytes; /* it's "struct { uint8_t mac[6]; }" */
64 uint32_t nip;
65
66 /* Read mac */
67 line = (char *) const_line;
68 mac_string = strtok_r(line, " \t", &line);
69 if (!mac_string || !ether_aton_r(mac_string, &mac_bytes))
70 return 0;
71
72 /* Read ip */
73 ip_string = strtok_r(NULL, " \t", &line);
74 if (!ip_string || !udhcp_str2nip(ip_string, &nip))
75 return 0;
76
77 add_static_lease(arg, (uint8_t*) &mac_bytes, nip);
78
79 log_static_leases(arg);
80
81 return 1;
82}
83
84struct config_keyword {
85 const char *keyword;
86 int (*handler)(const char *line, void *var) FAST_FUNC;
87 unsigned ofs;
88 const char *def;
89};
90
91#define OFS(field) offsetof(struct server_config_t, field)
92
93static const struct config_keyword keywords[] = {
94 /* keyword handler variable address default */
95 {"start" , udhcp_str2nip , OFS(start_ip ), "192.168.0.20"},
96 {"end" , udhcp_str2nip , OFS(end_ip ), "192.168.0.254"},
97 {"interface" , read_str , OFS(interface ), "eth0"},
98 /* Avoid "max_leases value not sane" warning by setting default
99 * to default_end_ip - default_start_ip + 1: */
100 {"max_leases" , read_u32 , OFS(max_leases ), "235"},
101 {"auto_time" , read_u32 , OFS(auto_time ), "7200"},
102 {"decline_time" , read_u32 , OFS(decline_time ), "3600"},
103 {"conflict_time", read_u32 , OFS(conflict_time), "3600"},
104 {"offer_time" , read_u32 , OFS(offer_time ), "60"},
105 {"min_lease" , read_u32 , OFS(min_lease_sec), "60"},
106 {"lease_file" , read_str , OFS(lease_file ), LEASES_FILE},
107 {"pidfile" , read_str , OFS(pidfile ), "/var/run/udhcpd.pid"},
108 {"siaddr" , udhcp_str2nip , OFS(siaddr_nip ), "0.0.0.0"},
109 /* keywords with no defaults must be last! */
110 {"option" , udhcp_str2optset, OFS(options ), ""},
111 {"opt" , udhcp_str2optset, OFS(options ), ""},
112 {"notify_file" , read_str , OFS(notify_file ), NULL},
113 {"sname" , read_str , OFS(sname ), NULL},
114 {"boot_file" , read_str , OFS(boot_file ), NULL},
115 {"static_lease" , read_staticlease, OFS(static_leases), ""},
116};
117enum { KWS_WITH_DEFAULTS = ARRAY_SIZE(keywords) - 6 };
118
119static NOINLINE void read_config(const char *file)
120{
121 parser_t *parser;
122 const struct config_keyword *k;
123 unsigned i;
124 char *token[2];
125
126 for (i = 0; i < KWS_WITH_DEFAULTS; i++)
127 keywords[i].handler(keywords[i].def, (char*)&server_config + keywords[i].ofs);
128
129 parser = config_open(file);
130 while (config_read(parser, token, 2, 2, "# \t", PARSE_NORMAL)) {
131 for (k = keywords, i = 0; i < ARRAY_SIZE(keywords); k++, i++) {
132 if (strcasecmp(token[0], k->keyword) == 0) {
133 if (!k->handler(token[1], (char*)&server_config + k->ofs)) {
134 bb_error_msg("can't parse line %u in %s",
135 parser->lineno, file);
136 /* reset back to the default value */
137 k->handler(k->def, (char*)&server_config + k->ofs);
138 }
139 break;
140 }
141 }
142 }
143 config_close(parser);
144
145 server_config.start_ip = ntohl(server_config.start_ip);
146 server_config.end_ip = ntohl(server_config.end_ip);
147}
148
149static void write_leases(void)
150{
151 int fd;
152 unsigned i;
153 leasetime_t curr;
154 int64_t written_at;
155
156 fd = open_or_warn(server_config.lease_file, O_WRONLY|O_CREAT|O_TRUNC);
157 if (fd < 0)
158 return;
159
160 curr = written_at = time(NULL);
161
162 written_at = SWAP_BE64(written_at);
163 full_write(fd, &written_at, sizeof(written_at));
164
165 for (i = 0; i < server_config.max_leases; i++) {
166 leasetime_t tmp_time;
167
168 if (g_leases[i].lease_nip == 0)
169 continue;
170
171 /* Screw with the time in the struct, for easier writing */
172 tmp_time = g_leases[i].expires;
173
174 g_leases[i].expires -= curr;
175 if ((signed_leasetime_t) g_leases[i].expires < 0)
176 g_leases[i].expires = 0;
177 g_leases[i].expires = htonl(g_leases[i].expires);
178
179 /* No error check. If the file gets truncated,
180 * we lose some leases on restart. Oh well. */
181 full_write(fd, &g_leases[i], sizeof(g_leases[i]));
182
183 /* Then restore it when done */
184 g_leases[i].expires = tmp_time;
185 }
186 close(fd);
187
188 if (server_config.notify_file) {
189 char *argv[3];
190 argv[0] = server_config.notify_file;
191 argv[1] = server_config.lease_file;
192 argv[2] = NULL;
193 spawn_and_wait(argv);
194 }
195}
196
197static NOINLINE void read_leases(const char *file)
198{
199 struct dyn_lease lease;
200 int64_t written_at, time_passed;
201 int fd;
202#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
203 unsigned i = 0;
204#endif
205
206 fd = open_or_warn(file, O_RDONLY);
207 if (fd < 0)
208 return;
209
210 if (full_read(fd, &written_at, sizeof(written_at)) != sizeof(written_at))
211 goto ret;
212 written_at = SWAP_BE64(written_at);
213
214 time_passed = time(NULL) - written_at;
215 /* Strange written_at, or lease file from old version of udhcpd
216 * which had no "written_at" field? */
217 if ((uint64_t)time_passed > 12 * 60 * 60)
218 goto ret;
219
220 while (full_read(fd, &lease, sizeof(lease)) == sizeof(lease)) {
221 uint32_t y = ntohl(lease.lease_nip);
222 if (y >= server_config.start_ip && y <= server_config.end_ip) {
223 signed_leasetime_t expires = ntohl(lease.expires) - (signed_leasetime_t)time_passed;
224 uint32_t static_nip;
225
226 if (expires <= 0)
227 /* We keep expired leases: add_lease() will add
228 * a lease with 0 seconds remaining.
229 * Fewer IP address changes this way for mass reboot scenario.
230 */
231 expires = 0;
232
233 /* Check if there is a different static lease for this IP or MAC */
234 static_nip = get_static_nip_by_mac(server_config.static_leases, lease.lease_mac);
235 if (static_nip) {
236 /* NB: we do not add lease even if static_nip == lease.lease_nip.
237 */
238 continue;
239 }
240 if (is_nip_reserved(server_config.static_leases, lease.lease_nip))
241 continue;
242
243 /* NB: add_lease takes "relative time", IOW,
244 * lease duration, not lease deadline. */
245 if (add_lease(lease.lease_mac, lease.lease_nip,
246 expires,
247 lease.hostname, sizeof(lease.hostname)
248 ) == 0
249 ) {
250 bb_error_msg("too many leases while loading %s", file);
251 break;
252 }
253#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
254 i++;
255#endif
256 }
257 }
258 log1("read %d leases", i);
259 ret:
260 close(fd);
261}
41 262
42/* Send a packet to a specific mac address and ip address by creating our own ip packet */ 263/* Send a packet to a specific mac address and ip address by creating our own ip packet */
43static void send_packet_to_client(struct dhcp_packet *dhcp_pkt, int force_broadcast) 264static void send_packet_to_client(struct dhcp_packet *dhcp_pkt, int force_broadcast)
@@ -290,12 +511,10 @@ static NOINLINE void send_inform(struct dhcp_packet *oldpacket)
290 send_packet(&packet, /*force_bcast:*/ 0); 511 send_packet(&packet, /*force_bcast:*/ 0);
291} 512}
292 513
293
294/* globals */ 514/* globals */
295struct dyn_lease *g_leases; 515struct dyn_lease *g_leases;
296/* struct server_config_t server_config is in bb_common_bufsiz1 */ 516/* struct server_config_t server_config is in bb_common_bufsiz1 */
297 517
298
299int udhcpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 518int udhcpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
300int udhcpd_main(int argc UNUSED_PARAM, char **argv) 519int udhcpd_main(int argc UNUSED_PARAM, char **argv)
301{ 520{
diff --git a/networking/udhcp/dhcpd.h b/networking/udhcp/dhcpd.h
index 9dd5bef9e..08c9e8c63 100644
--- a/networking/udhcp/dhcpd.h
+++ b/networking/udhcp/dhcpd.h
@@ -117,12 +117,6 @@ void log_static_leases(struct static_lease **st_lease_pp) FAST_FUNC;
117# define log_static_leases(st_lease_pp) ((void)0) 117# define log_static_leases(st_lease_pp) ((void)0)
118#endif 118#endif
119 119
120
121void read_config(const char *file) FAST_FUNC;
122void write_leases(void) FAST_FUNC;
123void read_leases(const char *file) FAST_FUNC;
124
125
126POP_SAVED_FUNCTION_VISIBILITY 120POP_SAVED_FUNCTION_VISIBILITY
127 121
128#endif 122#endif
diff --git a/networking/udhcp/files.c b/networking/udhcp/files.c
deleted file mode 100644
index b22425352..000000000
--- a/networking/udhcp/files.c
+++ /dev/null
@@ -1,234 +0,0 @@
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}