Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/networking/udhcp/dhcpd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 984 - (hide annotations) (download)
Sun May 30 11:32:42 2010 UTC (14 years ago) by niro
File MIME type: text/plain
File size: 7811 byte(s)
-updated to busybox-1.16.1 and enabled blkid/uuid support in default config
1 niro 532 /* vi: set sw=4 ts=4: */
2     /* dhcpd.c
3     *
4     * udhcp Server
5     * Copyright (C) 1999 Matthew Ramsay <matthewr@moreton.com.au>
6     * Chris Trew <ctrew@moreton.com.au>
7     *
8     * Rewrite by Russ Dill <Russ.Dill@asu.edu> July 2001
9     *
10     * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
11     */
12    
13 niro 816 #include <syslog.h>
14 niro 532 #include "common.h"
15 niro 816 #include "dhcpc.h"
16 niro 532 #include "dhcpd.h"
17     #include "options.h"
18    
19    
20     /* globals */
21 niro 984 struct dyn_lease *g_leases;
22 niro 816 /* struct server_config_t server_config is in bb_common_bufsiz1 */
23 niro 532
24    
25 niro 816 int udhcpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
26     int udhcpd_main(int argc UNUSED_PARAM, char **argv)
27 niro 532 {
28     fd_set rfds;
29 niro 984 int server_socket = -1, retval, max_sock;
30     struct dhcp_packet packet;
31     uint8_t *state;
32     uint32_t static_lease_ip;
33 niro 816 unsigned timeout_end;
34     unsigned num_ips;
35     unsigned opt;
36 niro 532 struct option_set *option;
37 niro 984 struct dyn_lease *lease, fake_lease;
38     IF_FEATURE_UDHCP_PORT(char *str_P;)
39 niro 532
40 niro 816 #if ENABLE_FEATURE_UDHCP_PORT
41     SERVER_PORT = 67;
42     CLIENT_PORT = 68;
43     #endif
44 niro 532
45 niro 984 #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
46     opt_complementary = "vv";
47     #endif
48     opt = getopt32(argv, "fSv"
49     IF_FEATURE_UDHCP_PORT("P:", &str_P)
50     #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
51     , &dhcp_verbose
52     #endif
53     );
54 niro 816 argv += optind;
55     if (!(opt & 1)) { /* no -f */
56     bb_daemonize_or_rexec(0, argv);
57 niro 984 logmode = LOGMODE_NONE;
58 niro 816 }
59     if (opt & 2) { /* -S */
60 niro 984 openlog(applet_name, LOG_PID, LOG_DAEMON);
61 niro 816 logmode |= LOGMODE_SYSLOG;
62     }
63     #if ENABLE_FEATURE_UDHCP_PORT
64 niro 984 if (opt & 8) { /* -P */
65 niro 816 SERVER_PORT = xatou16(str_P);
66     CLIENT_PORT = SERVER_PORT + 1;
67     }
68     #endif
69     /* Would rather not do read_config before daemonization -
70     * otherwise NOMMU machines will parse config twice */
71     read_config(argv[0] ? argv[0] : DHCPD_CONF_FILE);
72    
73     /* Make sure fd 0,1,2 are open */
74     bb_sanitize_stdio();
75     /* Equivalent of doing a fflush after every \n */
76     setlinebuf(stdout);
77    
78     /* Create pidfile */
79     write_pidfile(server_config.pidfile);
80 niro 984 /* if (!..) bb_perror_msg("can't create pidfile %s", pidfile); */
81 niro 816
82     bb_info_msg("%s (v"BB_VER") started", applet_name);
83    
84     option = find_option(server_config.options, DHCP_LEASE_TIME);
85 niro 984 server_config.max_lease_sec = LEASE_TIME;
86 niro 816 if (option) {
87 niro 984 move_from_unaligned32(server_config.max_lease_sec, option->data + OPT_DATA);
88     server_config.max_lease_sec = ntohl(server_config.max_lease_sec);
89 niro 532 }
90    
91     /* Sanity check */
92 niro 816 num_ips = server_config.end_ip - server_config.start_ip + 1;
93 niro 532 if (server_config.max_leases > num_ips) {
94 niro 816 bb_error_msg("max_leases=%u is too big, setting to %u",
95     (unsigned)server_config.max_leases, num_ips);
96 niro 532 server_config.max_leases = num_ips;
97     }
98    
99 niro 984 g_leases = xzalloc(server_config.max_leases * sizeof(g_leases[0]));
100 niro 532 read_leases(server_config.lease_file);
101    
102 niro 984 if (udhcp_read_interface(server_config.interface,
103     &server_config.ifindex,
104     &server_config.server_nip,
105     server_config.server_mac)
106     ) {
107 niro 816 retval = 1;
108     goto ret;
109     }
110 niro 532
111     /* Setup the signal pipe */
112     udhcp_sp_setup();
113    
114 niro 816 timeout_end = monotonic_sec() + server_config.auto_time;
115 niro 532 while (1) { /* loop until universe collapses */
116 niro 984 int bytes;
117     struct timeval tv;
118 niro 532
119     if (server_socket < 0) {
120 niro 816 server_socket = udhcp_listen_socket(/*INADDR_ANY,*/ SERVER_PORT,
121     server_config.interface);
122 niro 532 }
123    
124     max_sock = udhcp_sp_fd_set(&rfds, server_socket);
125     if (server_config.auto_time) {
126 niro 816 tv.tv_sec = timeout_end - monotonic_sec();
127 niro 532 tv.tv_usec = 0;
128     }
129 niro 816 retval = 0;
130 niro 532 if (!server_config.auto_time || tv.tv_sec > 0) {
131     retval = select(max_sock + 1, &rfds, NULL, NULL,
132     server_config.auto_time ? &tv : NULL);
133 niro 816 }
134 niro 532 if (retval == 0) {
135     write_leases();
136 niro 816 timeout_end = monotonic_sec() + server_config.auto_time;
137 niro 532 continue;
138 niro 816 }
139     if (retval < 0 && errno != EINTR) {
140 niro 984 log1("Error on select");
141 niro 532 continue;
142     }
143    
144     switch (udhcp_sp_read(&rfds)) {
145     case SIGUSR1:
146     bb_info_msg("Received a SIGUSR1");
147     write_leases();
148     /* why not just reset the timeout, eh */
149 niro 816 timeout_end = monotonic_sec() + server_config.auto_time;
150 niro 532 continue;
151     case SIGTERM:
152     bb_info_msg("Received a SIGTERM");
153 niro 816 goto ret0;
154 niro 984 case 0: /* no signal: read a packet */
155     break;
156     default: /* signal or error (probably EINTR): back to select */
157     continue;
158 niro 532 }
159    
160 niro 984 bytes = udhcp_recv_kernel_packet(&packet, server_socket);
161 niro 816 if (bytes < 0) {
162 niro 984 /* bytes can also be -2 ("bad packet data") */
163 niro 532 if (bytes == -1 && errno != EINTR) {
164 niro 984 log1("Read error: %s, reopening socket", strerror(errno));
165 niro 532 close(server_socket);
166     server_socket = -1;
167     }
168     continue;
169     }
170    
171 niro 984 if (packet.hlen != 6) {
172     bb_error_msg("MAC length != 6, ignoring packet");
173     continue;
174     }
175    
176 niro 816 state = get_option(&packet, DHCP_MESSAGE_TYPE);
177     if (state == NULL) {
178 niro 984 bb_error_msg("no message type option, ignoring packet");
179 niro 532 continue;
180     }
181    
182     /* Look for a static lease */
183 niro 984 static_lease_ip = get_static_nip_by_mac(server_config.static_leases, &packet.chaddr);
184 niro 532 if (static_lease_ip) {
185     bb_info_msg("Found static lease: %x", static_lease_ip);
186    
187 niro 984 memcpy(&fake_lease.lease_mac, &packet.chaddr, 6);
188     fake_lease.lease_nip = static_lease_ip;
189     fake_lease.expires = 0;
190 niro 532
191 niro 984 lease = &fake_lease;
192 niro 532 } else {
193 niro 984 lease = find_lease_by_mac(packet.chaddr);
194 niro 532 }
195    
196     switch (state[0]) {
197     case DHCPDISCOVER:
198 niro 984 log1("Received DISCOVER");
199 niro 532
200 niro 816 if (send_offer(&packet) < 0) {
201 niro 532 bb_error_msg("send OFFER failed");
202     }
203     break;
204 niro 984 case DHCPREQUEST: {
205     uint8_t *server_id_opt, *requested_opt;
206     uint32_t server_id_net = server_id_net; /* for compiler */
207     uint32_t requested_nip = requested_nip; /* for compiler */
208 niro 532
209 niro 984 log1("Received REQUEST");
210 niro 532
211 niro 984 requested_opt = get_option(&packet, DHCP_REQUESTED_IP);
212     server_id_opt = get_option(&packet, DHCP_SERVER_ID);
213     if (requested_opt)
214     move_from_unaligned32(requested_nip, requested_opt);
215     if (server_id_opt)
216     move_from_unaligned32(server_id_net, server_id_opt);
217 niro 532
218     if (lease) {
219 niro 984 if (server_id_opt) {
220 niro 532 /* SELECTING State */
221 niro 984 if (server_id_net == server_config.server_nip
222     && requested_opt
223     && requested_nip == lease->lease_nip
224 niro 816 ) {
225 niro 984 send_ACK(&packet, lease->lease_nip);
226 niro 532 }
227 niro 984 } else if (requested_opt) {
228 niro 816 /* INIT-REBOOT State */
229 niro 984 if (lease->lease_nip == requested_nip)
230     send_ACK(&packet, lease->lease_nip);
231 niro 816 else
232     send_NAK(&packet);
233 niro 984 } else if (lease->lease_nip == packet.ciaddr) {
234 niro 816 /* RENEWING or REBINDING State */
235 niro 984 send_ACK(&packet, lease->lease_nip);
236 niro 816 } else { /* don't know what to do!!!! */
237     send_NAK(&packet);
238 niro 532 }
239    
240     /* what to do if we have no record of the client */
241 niro 984 } else if (server_id_opt) {
242 niro 532 /* SELECTING State */
243    
244 niro 984 } else if (requested_opt) {
245 niro 532 /* INIT-REBOOT State */
246 niro 984 lease = find_lease_by_nip(requested_nip);
247 niro 816 if (lease) {
248 niro 984 if (is_expired_lease(lease)) {
249 niro 532 /* probably best if we drop this lease */
250 niro 984 memset(lease->lease_mac, 0, sizeof(lease->lease_mac));
251     } else {
252     /* make some contention for this address */
253 niro 816 send_NAK(&packet);
254 niro 984 }
255 niro 816 } else {
256 niro 984 uint32_t r = ntohl(requested_nip);
257 niro 816 if (r < server_config.start_ip
258     || r > server_config.end_ip
259     ) {
260     send_NAK(&packet);
261     }
262     /* else remain silent */
263     }
264 niro 532
265     } else {
266 niro 816 /* RENEWING or REBINDING State */
267 niro 532 }
268     break;
269 niro 984 }
270 niro 532 case DHCPDECLINE:
271 niro 984 log1("Received DECLINE");
272 niro 532 if (lease) {
273 niro 984 memset(lease->lease_mac, 0, sizeof(lease->lease_mac));
274     lease->expires = time(NULL) + server_config.decline_time;
275 niro 532 }
276     break;
277     case DHCPRELEASE:
278 niro 984 log1("Received RELEASE");
279 niro 816 if (lease)
280 niro 984 lease->expires = time(NULL);
281 niro 532 break;
282     case DHCPINFORM:
283 niro 984 log1("Received INFORM");
284 niro 532 send_inform(&packet);
285     break;
286     default:
287     bb_info_msg("Unsupported DHCP message (%02x) - ignoring", state[0]);
288     }
289     }
290 niro 816 ret0:
291     retval = 0;
292     ret:
293     /*if (server_config.pidfile) - server_config.pidfile is never NULL */
294     remove_pidfile(server_config.pidfile);
295     return retval;
296 niro 532 }