aboutsummaryrefslogtreecommitdiff
path: root/networking/udhcp/dhcpc.c
diff options
context:
space:
mode:
Diffstat (limited to 'networking/udhcp/dhcpc.c')
-rw-r--r--networking/udhcp/dhcpc.c120
1 files changed, 22 insertions, 98 deletions
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index c97e422e2..4612c4100 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -19,9 +19,7 @@
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */ 20 */
21 21
22#include <stdio.h>
23#include <sys/time.h> 22#include <sys/time.h>
24#include <sys/types.h>
25#include <sys/file.h> 23#include <sys/file.h>
26#include <unistd.h> 24#include <unistd.h>
27#include <getopt.h> 25#include <getopt.h>
@@ -40,11 +38,9 @@
40#include "dhcpc.h" 38#include "dhcpc.h"
41#include "options.h" 39#include "options.h"
42#include "clientpacket.h" 40#include "clientpacket.h"
43#include "packet.h"
44#include "script.h" 41#include "script.h"
45#include "socket.h" 42#include "socket.h"
46#include "debug.h" 43#include "common.h"
47#include "pidfile.h"
48 44
49static int state; 45static int state;
50static unsigned long requested_ip; /* = 0 */ 46static unsigned long requested_ip; /* = 0 */
@@ -52,7 +48,6 @@ static unsigned long server_addr;
52static unsigned long timeout; 48static unsigned long timeout;
53static int packet_num; /* = 0 */ 49static int packet_num; /* = 0 */
54static int fd = -1; 50static int fd = -1;
55static int signal_pipe[2];
56 51
57#define LISTEN_NONE 0 52#define LISTEN_NONE 0
58#define LISTEN_KERNEL 1 53#define LISTEN_KERNEL 1
@@ -80,34 +75,6 @@ struct client_config_t client_config = {
80 arp: "\0\0\0\0\0\0", /* appease gcc-3.0 */ 75 arp: "\0\0\0\0\0\0", /* appease gcc-3.0 */
81}; 76};
82 77
83#ifndef IN_BUSYBOX
84static void __attribute__ ((noreturn)) bb_show_usage(void)
85{
86 printf(
87"Usage: udhcpc [OPTIONS]\n\n"
88" -c, --clientid=CLIENTID Client identifier\n"
89" -H, --hostname=HOSTNAME Client hostname\n"
90" -h Alias for -H\n"
91" -f, --foreground Do not fork after getting lease\n"
92" -b, --background Fork to background if lease cannot be\n"
93" immediately negotiated.\n"
94" -i, --interface=INTERFACE Interface to use (default: eth0)\n"
95" -n, --now Exit with failure if lease cannot be\n"
96" immediately negotiated.\n"
97" -p, --pidfile=file Store process ID of daemon in file\n"
98" -q, --quit Quit after obtaining lease\n"
99" -r, --request=IP IP address to request (default: none)\n"
100" -s, --script=file Run file at dhcp events (default:\n"
101" " DEFAULT_SCRIPT ")\n"
102" -v, --version Display version\n"
103 );
104 exit(0);
105}
106#else
107extern void bb_show_usage(void) __attribute__ ((noreturn));
108#endif
109
110
111/* just a little helper */ 78/* just a little helper */
112static void change_mode(int new_mode) 79static void change_mode(int new_mode)
113{ 80{
@@ -172,46 +139,15 @@ static void perform_release(void)
172} 139}
173 140
174 141
175/* Exit and cleanup */ 142static void client_background(void)
176static void exit_client(int retval)
177{
178 pidfile_delete(client_config.pidfile);
179 CLOSE_LOG();
180 exit(retval);
181}
182
183
184/* Signal handler */
185static void signal_handler(int sig)
186{
187 if (send(signal_pipe[1], &sig, sizeof(sig), MSG_DONTWAIT) < 0) {
188 LOG(LOG_ERR, "Could not send signal: %s",
189 strerror(errno));
190 }
191}
192
193
194static void background(void)
195{ 143{
196 int pid_fd; 144 background(client_config.pidfile);
197
198 pid_fd = pidfile_acquire(client_config.pidfile); /* hold lock during fork. */
199 while (pid_fd >= 0 && pid_fd < 3) pid_fd = dup(pid_fd); /* don't let daemon close it */
200 if (daemon(0, 0) == -1) {
201 perror("fork");
202 exit_client(1);
203 }
204 client_config.foreground = 1; /* Do not fork again. */ 145 client_config.foreground = 1; /* Do not fork again. */
205 client_config.background_if_no_lease = 0; 146 client_config.background_if_no_lease = 0;
206 pidfile_write_release(pid_fd);
207} 147}
208 148
209 149
210#ifdef COMBINED_BINARY
211int udhcpc_main(int argc, char *argv[]) 150int udhcpc_main(int argc, char *argv[])
212#else
213int main(int argc, char *argv[])
214#endif
215{ 151{
216 unsigned char *temp, *message; 152 unsigned char *temp, *message;
217 unsigned long t1 = 0, t2 = 0, xid = 0; 153 unsigned long t1 = 0, t2 = 0, xid = 0;
@@ -222,12 +158,11 @@ int main(int argc, char *argv[])
222 int c, len; 158 int c, len;
223 struct dhcpMessage packet; 159 struct dhcpMessage packet;
224 struct in_addr temp_addr; 160 struct in_addr temp_addr;
225 int pid_fd;
226 time_t now; 161 time_t now;
227 int max_fd; 162 int max_fd;
228 int sig; 163 int sig;
229 164
230 static struct option arg_options[] = { 165 static const struct option arg_options[] = {
231 {"clientid", required_argument, 0, 'c'}, 166 {"clientid", required_argument, 0, 'c'},
232 {"foreground", no_argument, 0, 'f'}, 167 {"foreground", no_argument, 0, 'f'},
233 {"background", no_argument, 0, 'b'}, 168 {"background", no_argument, 0, 'b'},
@@ -240,7 +175,6 @@ int main(int argc, char *argv[])
240 {"request", required_argument, 0, 'r'}, 175 {"request", required_argument, 0, 'r'},
241 {"script", required_argument, 0, 's'}, 176 {"script", required_argument, 0, 's'},
242 {"version", no_argument, 0, 'v'}, 177 {"version", no_argument, 0, 'v'},
243 {"help", no_argument, 0, '?'},
244 {0, 0, 0, 0} 178 {0, 0, 0, 0}
245 }; 179 };
246 180
@@ -294,23 +228,18 @@ int main(int argc, char *argv[])
294 client_config.script = optarg; 228 client_config.script = optarg;
295 break; 229 break;
296 case 'v': 230 case 'v':
297 printf("udhcpcd, version %s\n\n", VERSION); 231 bb_error_msg("version %s\n", VERSION);
298 exit_client(0); 232 return(0);
299 break; 233 break;
300 default: 234 default:
301 bb_show_usage(); 235 bb_show_usage();
302 } 236 }
303 } 237 }
304 238
305 OPEN_LOG("udhcpc"); 239 start_log("client");
306 LOG(LOG_INFO, "udhcp client (v%s) started", VERSION);
307
308 pid_fd = pidfile_acquire(client_config.pidfile);
309 pidfile_write_release(pid_fd);
310
311 if (read_interface(client_config.interface, &client_config.ifindex, 240 if (read_interface(client_config.interface, &client_config.ifindex,
312 NULL, client_config.arp) < 0) 241 NULL, client_config.arp) < 0)
313 exit_client(1); 242 return(1);
314 243
315 if (!client_config.clientid) { 244 if (!client_config.clientid) {
316 client_config.clientid = xmalloc(6 + 3); 245 client_config.clientid = xmalloc(6 + 3);
@@ -321,10 +250,7 @@ int main(int argc, char *argv[])
321 } 250 }
322 251
323 /* setup signal handlers */ 252 /* setup signal handlers */
324 socketpair(AF_UNIX, SOCK_STREAM, 0, signal_pipe); 253 udhcp_set_signal_pipe(SIGUSR2);
325 signal(SIGUSR1, signal_handler);
326 signal(SIGUSR2, signal_handler);
327 signal(SIGTERM, signal_handler);
328 254
329 state = INIT_SELECTING; 255 state = INIT_SELECTING;
330 run_script(NULL, "deconfig"); 256 run_script(NULL, "deconfig");
@@ -342,16 +268,16 @@ int main(int argc, char *argv[])
342 else 268 else
343 fd = raw_socket(client_config.ifindex); 269 fd = raw_socket(client_config.ifindex);
344 if (fd < 0) { 270 if (fd < 0) {
345 LOG(LOG_ERR, "FATAL: couldn't listen on socket, %s", strerror(errno)); 271 LOG(LOG_ERR, "FATAL: couldn't listen on socket, %m");
346 exit_client(0); 272 return(0);
347 } 273 }
348 } 274 }
349 if (fd >= 0) FD_SET(fd, &rfds); 275 if (fd >= 0) FD_SET(fd, &rfds);
350 FD_SET(signal_pipe[0], &rfds); 276 FD_SET(udhcp_signal_pipe[0], &rfds);
351 277
352 if (tv.tv_sec > 0) { 278 if (tv.tv_sec > 0) {
353 DEBUG(LOG_INFO, "Waiting on select...\n"); 279 DEBUG(LOG_INFO, "Waiting on select...\n");
354 max_fd = signal_pipe[0] > fd ? signal_pipe[0] : fd; 280 max_fd = udhcp_signal_pipe[0] > fd ? udhcp_signal_pipe[0] : fd;
355 retval = select(max_fd + 1, &rfds, NULL, NULL, &tv); 281 retval = select(max_fd + 1, &rfds, NULL, NULL, &tv);
356 } else retval = 0; /* If we already timed out, fall through */ 282 } else retval = 0; /* If we already timed out, fall through */
357 283
@@ -372,10 +298,10 @@ int main(int argc, char *argv[])
372 } else { 298 } else {
373 if (client_config.background_if_no_lease) { 299 if (client_config.background_if_no_lease) {
374 LOG(LOG_INFO, "No lease, forking to background."); 300 LOG(LOG_INFO, "No lease, forking to background.");
375 background(); 301 client_background();
376 } else if (client_config.abort_if_no_lease) { 302 } else if (client_config.abort_if_no_lease) {
377 LOG(LOG_INFO, "No lease, failing."); 303 LOG(LOG_INFO, "No lease, failing.");
378 exit_client(1); 304 return(1);
379 } 305 }
380 /* wait to try again */ 306 /* wait to try again */
381 packet_num = 0; 307 packet_num = 0;
@@ -453,7 +379,7 @@ int main(int argc, char *argv[])
453 else len = get_raw_packet(&packet, fd); 379 else len = get_raw_packet(&packet, fd);
454 380
455 if (len == -1 && errno != EINTR) { 381 if (len == -1 && errno != EINTR) {
456 DEBUG(LOG_INFO, "error on read, %s, reopening socket", strerror(errno)); 382 DEBUG(LOG_INFO, "error on read, %m, reopening socket");
457 change_mode(listen_mode); /* just close and reopen */ 383 change_mode(listen_mode); /* just close and reopen */
458 } 384 }
459 if (len < 0) continue; 385 if (len < 0) continue;
@@ -517,9 +443,9 @@ int main(int argc, char *argv[])
517 state = BOUND; 443 state = BOUND;
518 change_mode(LISTEN_NONE); 444 change_mode(LISTEN_NONE);
519 if (client_config.quit_after_lease) 445 if (client_config.quit_after_lease)
520 exit_client(0); 446 return(0);
521 if (!client_config.foreground) 447 if (!client_config.foreground)
522 background(); 448 client_background();
523 449
524 } else if (*message == DHCPNAK) { 450 } else if (*message == DHCPNAK) {
525 /* return to init state */ 451 /* return to init state */
@@ -537,10 +463,9 @@ int main(int argc, char *argv[])
537 break; 463 break;
538 /* case BOUND, RELEASED: - ignore all packets */ 464 /* case BOUND, RELEASED: - ignore all packets */
539 } 465 }
540 } else if (retval > 0 && FD_ISSET(signal_pipe[0], &rfds)) { 466 } else if (retval > 0 && FD_ISSET(udhcp_signal_pipe[0], &rfds)) {
541 if (read(signal_pipe[0], &sig, sizeof(sig)) < 0) { 467 if (read(udhcp_signal_pipe[0], &sig, sizeof(sig)) < 0) {
542 DEBUG(LOG_ERR, "Could not read signal: %s", 468 DEBUG(LOG_ERR, "Could not read signal: %m");
543 strerror(errno));
544 continue; /* probably just EINTR */ 469 continue; /* probably just EINTR */
545 } 470 }
546 switch (sig) { 471 switch (sig) {
@@ -552,7 +477,7 @@ int main(int argc, char *argv[])
552 break; 477 break;
553 case SIGTERM: 478 case SIGTERM:
554 LOG(LOG_INFO, "Received SIGTERM"); 479 LOG(LOG_INFO, "Received SIGTERM");
555 exit_client(0); 480 return(0);
556 } 481 }
557 } else if (retval == -1 && errno == EINTR) { 482 } else if (retval == -1 && errno == EINTR) {
558 /* a signal was caught */ 483 /* a signal was caught */
@@ -564,4 +489,3 @@ int main(int argc, char *argv[])
564 } 489 }
565 return 0; 490 return 0;
566} 491}
567