Finish remerging busybox udhcp and udhcp. Some cleanups as well.
No binary (build failed)
—
(log yok)
| @@ -9,6 +9,6 @@ Other Credits: | |
| -------------- | |
| Moreton Bay (http://www.moretonbay.com/) | |
| Lineo (http://opensource.lineo.com) | |
| - | Vladimir Oleynik <[email protected]>, optimize and more integrate for busybox |
| + | Vladimir Oleynik <[email protected]> Size optimizations |
| @@ -1,8 +1,6 @@ | |
| - | 0.9.10 |
| - | Size optimization (over 3k), more busybox integration |
| - | (Vladimir Oleynik <[email protected]> |
| - | |
| 0.9.9 (pending) | |
| + | + Various other size optimizations (Vladimir) |
| + | + Change strerror(errno) to %m (Vladimir N. Oleynik <[email protected]>) |
| + Fixed a little endian problem in mton (Bastian Blank <[email protected]>) | |
| + Fixed a arpping alignment problem (Rui He <[email protected]>) | |
| + Added sanity check for max_leases (udhcp bug #1285) (me) | |
| @@ -36,7 +34,7 @@ | |
| udhcp bug#1256 | |
| + Fixed reading of client id (David Poole <[email protected]>) | |
| + change sys_errlist[] to strerror() as it aparently doesn't exist | |
| - | (Erik Andersen <[email protected]>) |
| + | (Erik Andersen <[email protected]>) |
| + fixed get_raw_packet so it returns -2 on non fatal errors | |
| (Ted Lemon <[email protected]>) | |
| + Improved (hopefully) NAKing behavior (me) | |
| @@ -33,22 +33,14 @@ CONFIG_UDHCP_SHARED=n | |
| endif | |
| endif | |
| - | ifeq ($(CONFIG_UDHCPD), y) |
| - | CONFIG_UDHCP_LEASES_FILE=y |
| - | else |
| - | ifeq ($(CONFIG_UDHCPD), y) |
| - | CONFIG_UDHCP_LEASES_FILE=y |
| - | else |
| - | CONFIG_UDHCP_LEASES_FILE=n |
| - | endif |
| - | endif |
| - | |
| UDHCP-y:= | |
| - | UDHCP-$(CONFIG_UDHCP_SHARED) += options.c socket.c packet.c common.c |
| - | UDHCP-$(CONFIG_UDHCPC) += dhcpc.c clientpacket.c script.c |
| - | UDHCP-$(CONFIG_UDHCPD) += dhcpd.c arpping.c files.c leases.c serverpacket.c |
| + | UDHCP-$(CONFIG_UDHCP_SHARED) += common.c options.c packet.c pidfile.c \ |
| + | signalpipe.c socket.c |
| + | UDHCP-$(CONFIG_UDHCPC) += dhcpc.c clientpacket.c clientsocket.c \ |
| + | script.c |
| + | UDHCP-$(CONFIG_UDHCPD) += dhcpd.c arpping.c files.c leases.c \ |
| + | serverpacket.c |
| UDHCP-$(CONFIG_DUMPLEASES) += dumpleases.c | |
| - | UDHCP-$(CONFIG_UDHCP_LEASES_FILE) += leases_file.c |
| UDHCP_OBJS=$(patsubst %.c,$(UDHCP_DIR)%.o, $(UDHCP-y)) | |
| libraries-y+=$(UDHCP_DIR)$(UDHCP_AR) | |
| @@ -11,19 +11,22 @@ compile time options | |
| The Makefile contains three of the compile time options: | |
| - | DEBUG: If DEBUG is defined, udhcpd will output extra debugging |
| - | output, compile with -g, and not fork to the background when run. |
| - | SYSLOG: If SYSLOG is defined, udhcpd will log all its messages |
| - | syslog, otherwise, it will attempt to log them to stdout. |
| + | UDHCP_DEBUG: If UDHCP_DEBUG is defined, udhcpd will output extra |
| + | debugging output, compile with -g, and not fork to the background when |
| + | run. |
| + | UDHCP_SYSLOG: If UDHCP_SYSLOG is defined, udhcpd will log all its |
| + | messages syslog, otherwise, it will attempt to log them to stdout. |
| COMBINED_BINARY: If COMBINED_BINARY is define, one binary, udhcpd, | |
| is created. If called as udhcpd, the dhcp server will be started. | |
| If called as udhcpc, the dhcp client will be started. | |
| - | dhcpd.h contains the other two compile time options: |
| + | dhcpd.h contains the other three compile time options: |
| LEASE_TIME: The default lease time if not specified in the config | |
| file. | |
| + | |
| + | LEASES_FILE: The default file for storing leases. |
| DHCPD_CONFIG_FILE: The defualt config file to use. | |
| @@ -1,5 +1,6 @@ | |
| TODO | |
| ---- | |
| + | + Check for valid IP, netmask, hostname, paths, strings, etc |
| + Integrade README.*'s with manpages | |
| + using time(0) breaks if the system clock changes, find a portable solution | |
| + make failure of reading functions revert to previous value, not the default | |
| @@ -9,6 +10,7 @@ TODO | |
| + make sure packet generation works on a wide varitey of arches | |
| + Interoperability testing | |
| + Hooks within the DHCP server | |
| + | * Server notification when a lease is added/removed |
| + Additional bootp support in client/server | |
| + Make serverid option in server configurable | |
| + Possibly add failure message to DHCP NAK | |
| @@ -44,7 +44,11 @@ int arpping(u_int32_t yiaddr, u_int32_t ip, unsigned char *mac, char *interface) | |
| if ((s = socket (PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP))) == -1) { | |
| + | #ifdef IN_BUSYBOX |
| LOG(LOG_ERR, bb_msg_can_not_create_raw_socket); | |
| + | #else |
| + | LOG(LOG_ERR, "Could not open raw socket"); |
| + | #endif |
| return -1; | |
| } | |
| @@ -0,0 +1,62 @@ | |
| + | /* |
| + | * clientsocket.c -- DHCP client socket creation |
| + | * |
| + | * udhcp client |
| + | * |
| + | * Russ Dill <[email protected]> July 2001 |
| + | * |
| + | * This program is free software; you can redistribute it and/or modify |
| + | * it under the terms of the GNU General Public License as published by |
| + | * the Free Software Foundation; either version 2 of the License, or |
| + | * (at your option) any later version. |
| + | * |
| + | * This program is distributed in the hope that it will be useful, |
| + | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| + | * GNU General Public License for more details. |
| + | * |
| + | * You should have received a copy of the GNU General Public License |
| + | * along with this program; if not, write to the Free Software |
| + | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| + | */ |
| + | |
| + | #include <sys/types.h> |
| + | #include <sys/socket.h> |
| + | #include <unistd.h> |
| + | #include <netinet/in.h> |
| + | #include <features.h> |
| + | #if __GLIBC__ >=2 && __GLIBC_MINOR >= 1 |
| + | #include <netpacket/packet.h> |
| + | #include <net/ethernet.h> |
| + | #else |
| + | #include <asm/types.h> |
| + | #include <linux/if_packet.h> |
| + | #include <linux/if_ether.h> |
| + | #endif |
| + | |
| + | #include "clientsocket.h" |
| + | #include "common.h" |
| + | |
| + | |
| + | int raw_socket(int ifindex) |
| + | { |
| + | int fd; |
| + | struct sockaddr_ll sock; |
| + | |
| + | DEBUG(LOG_INFO, "Opening raw socket on ifindex %d", ifindex); |
| + | if ((fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0) { |
| + | DEBUG(LOG_ERR, "socket call failed: %m"); |
| + | return -1; |
| + | } |
| + | |
| + | sock.sll_family = AF_PACKET; |
| + | sock.sll_protocol = htons(ETH_P_IP); |
| + | sock.sll_ifindex = ifindex; |
| + | if (bind(fd, (struct sockaddr *) &sock, sizeof(sock)) < 0) { |
| + | DEBUG(LOG_ERR, "bind call failed: %m"); |
| + | close(fd); |
| + | return -1; |
| + | } |
| + | |
| + | return fd; |
| + | } |
| @@ -0,0 +1,7 @@ | |
| + | /* clientsocket.h */ |
| + | #ifndef _CLIENTSOCKET_H |
| + | #define _CLIENTSOCKET_H |
| + | |
| + | int raw_socket(int ifindex); |
| + | |
| + | #endif |
| @@ -1,8 +1,9 @@ | |
| /* common.c | |
| * | |
| - | * Functions to assist in the writing and removing of pidfiles. |
| + | * Functions for debugging and logging as well as some other |
| + | * simple helper functions. |
| * | |
| - | * Russ Dill <[email protected]> Soptember 2001 |
| + | * Russ Dill <[email protected]> 2001-2003 |
| * Rewrited by Vladimir Oleynik <[email protected]> (C) 2003 | |
| * | |
| * This program is free software; you can redistribute it and/or modify | |
| @@ -26,18 +27,54 @@ | |
| #include <string.h> | |
| #include <stdlib.h> | |
| #include <signal.h> | |
| + | #include <paths.h> |
| #include <sys/socket.h> | |
| + | #include <stdarg.h> |
| #include "common.h" | |
| + | #include "pidfile.h" |
| static int daemonized; | |
| - | #ifdef CONFIG_FEATURE_UDHCP_SYSLOG |
| + | /* |
| + | * This function makes sure our first socket calls |
| + | * aren't going to fd 1 (printf badness...) and are |
| + | * not later closed by daemon() |
| + | */ |
| + | static inline void sanitize_fds(void) |
| + | { |
| + | int zero; |
| + | if ((zero = open(_PATH_DEVNULL, O_RDWR, 0)) < 0) return; |
| + | while (zero < 3) zero = dup(zero); |
| + | close(zero); |
| + | } |
| + | |
| + | |
| + | void background(const char *pidfile) |
| + | { |
| + | #ifdef __uClinux__ |
| + | LOG(LOG_ERR, "Cannot background in uclinux (yet)"); |
| + | #else /* __uClinux__ */ |
| + | int pid_fd; |
| + | |
| + | if (!pidfile) return; |
| + | |
| + | pid_fd = pidfile_acquire(pidfile); /* hold lock during fork. */ |
| + | if (daemon(0, 0) == -1) { |
| + | perror("fork"); |
| + | exit(1); |
| + | } |
| + | daemonized++; |
| + | pidfile_write_release(pid_fd); |
| + | #endif /* __uClinux__ */ |
| + | } |
| + | |
| + | |
| + | #ifdef UDHCP_SYSLOG |
| void udhcp_logging(int level, const char *fmt, ...) | |
| { | |
| - | int e = errno; |
| va_list p; | |
| va_list p2; | |
| @@ -46,21 +83,34 @@ void udhcp_logging(int level, const char *fmt, ...) | |
| if(!daemonized) { | |
| vprintf(fmt, p); | |
| putchar('\n'); | |
| - | fflush(stdout); |
| - | errno = e; |
| } | |
| vsyslog(level, fmt, p2); | |
| va_end(p); | |
| } | |
| - | void start_log(const char *client_server) |
| + | |
| + | void start_log_and_pid(const char *client_server, const char *pidfile) |
| { | |
| - | openlog(bb_applet_name, LOG_PID | LOG_CONS, LOG_LOCAL0); |
| + | int pid_fd; |
| + | |
| + | /* Make sure our syslog fd isn't overwritten */ |
| + | sanitize_fds(); |
| + | |
| + | /* do some other misc startup stuff while we are here to save bytes */ |
| + | pid_fd = pidfile_acquire(pidfile); |
| + | pidfile_write_release(pid_fd); |
| + | |
| + | /* equivelent of doing a fflush after every \n */ |
| + | setlinebuf(stdout); |
| + | |
| + | openlog(client_server, LOG_PID | LOG_CONS, LOG_LOCAL0); |
| udhcp_logging(LOG_INFO, "%s (v%s) started", client_server, VERSION); | |
| } | |
| + | |
| #else | |
| + | |
| static char *syslog_level_msg[] = { | |
| [LOG_EMERG] = "EMERGENCY!", | |
| [LOG_ALERT] = "ALERT!", | |
| @@ -71,86 +121,36 @@ static char *syslog_level_msg[] = { | |
| [LOG_DEBUG] = "debug" | |
| }; | |
| + | |
| void udhcp_logging(int level, const char *fmt, ...) | |
| { | |
| - | int e = errno; |
| va_list p; | |
| va_start(p, fmt); | |
| if(!daemonized) { | |
| printf("%s, ", syslog_level_msg[level]); | |
| - | errno = e; |
| vprintf(fmt, p); | |
| putchar('\n'); | |
| - | fflush(stdout); |
| } | |
| va_end(p); | |
| } | |
| - | void start_log(const char *client_server) |
| + | |
| + | void start_log_and_pid(const char *client_server, const char *pidfile) |
| { | |
| - | udhcp_logging(LOG_INFO, "%s (v%s) started", client_server, VERSION); |
| - | } |
| - | #endif |
| + | int pid_fd; |
| - | static const char *saved_pidfile; |
| + | /* Make sure our syslog fd isn't overwritten */ |
| + | sanitize_fds(); |
| - | static void exit_fun(void) |
| - | { |
| - | if (saved_pidfile) unlink(saved_pidfile); |
| - | } |
| + | /* do some other misc startup stuff while we are here to save bytes */ |
| + | pid_fd = pidfile_acquire(pidfile); |
| + | pidfile_write_release(pid_fd); |
| - | void background(const char *pidfile) |
| - | { |
| - | #ifdef __uClinux__ |
| - | LOG(LOG_ERR, "Cannot background in uclinux (yet)"); |
| - | #else /* __uClinux__ */ |
| - | int pid_fd = -1; |
| - | |
| - | if (pidfile) { |
| - | pid_fd = open(pidfile, O_CREAT | O_WRONLY, 0644); |
| - | if (pid_fd < 0) { |
| - | LOG(LOG_ERR, "Unable to open pidfile %s: %m", pidfile); |
| - | } else { |
| - | lockf(pid_fd, F_LOCK, 0); |
| - | if(!saved_pidfile) |
| - | atexit(exit_fun); /* set atexit one only */ |
| - | saved_pidfile = pidfile; /* but may be rewrite */ |
| - | } |
| - | } |
| - | while (pid_fd >= 0 && pid_fd < 3) pid_fd = dup(pid_fd); /* don't let daemon close it */ |
| - | if (daemon(0, 0) == -1) { |
| - | perror("fork"); |
| - | exit(1); |
| - | } |
| - | daemonized++; |
| - | if (pid_fd >= 0) { |
| - | FILE *out; |
| - | |
| - | if ((out = fdopen(pid_fd, "w")) != NULL) { |
| - | fprintf(out, "%d\n", getpid()); |
| - | fclose(out); |
| - | } |
| - | lockf(pid_fd, F_UNLCK, 0); |
| - | close(pid_fd); |
| - | } |
| - | #endif /* __uClinux__ */ |
| - | } |
| + | /* equivelent of doing a fflush after every \n */ |
| + | setlinebuf(stdout); |
| - | /* Signal handler */ |
| - | int udhcp_signal_pipe[2]; |
| - | static void signal_handler(int sig) |
| - | { |
| - | if (send(udhcp_signal_pipe[1], &sig, sizeof(sig), MSG_DONTWAIT) < 0) { |
| - | LOG(LOG_ERR, "Could not send signal: %m"); |
| - | } |
| + | udhcp_logging(LOG_INFO, "%s (v%s) started", client_server, VERSION); |
| } | |
| + | #endif |
| - | void udhcp_set_signal_pipe(int sig_add) |
| - | { |
| - | socketpair(AF_UNIX, SOCK_STREAM, 0, udhcp_signal_pipe); |
| - | signal(SIGUSR1, signal_handler); |
| - | signal(SIGTERM, signal_handler); |
| - | if(sig_add) |
| - | signal(sig_add, signal_handler); |
| - | } |
| @@ -18,10 +18,14 @@ | |
| * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
| */ | |
| + | #ifndef _COMMON_H |
| + | #define _COMMON_H |
| + | |
| #include "version.h" | |
| - | #include "busybox.h" |
| + | #include "libbb_udhcp.h" |
| + | |
| - | #ifndef CONFIG_FEATURE_UDHCP_SYSLOG |
| + | #ifndef UDHCP_SYSLOG |
| enum syslog_levels { | |
| LOG_EMERG = 0, | |
| LOG_ALERT, | |
| @@ -35,18 +39,17 @@ enum syslog_levels { | |
| #include <syslog.h> | |
| #endif | |
| - | void start_log(const char *client_server); |
| + | void background(const char *pidfile); |
| + | void start_log_and_pid(const char *client_server, const char *pidfile); |
| void background(const char *pidfile); | |
| void udhcp_logging(int level, const char *fmt, ...); | |
| - | |
| - | extern int udhcp_signal_pipe[2]; |
| - | void udhcp_set_signal_pipe(int sig_add); |
| - | |
| - | |
| + | |
| #define LOG(level, str, args...) udhcp_logging(level, str, ## args) | |
| - | #ifdef CONFIG_FEATURE_UDHCP_DEBUG |
| - | # define DEBUG(level, str, args...) udhcp_logging(level, str, ## args) |
| + | #ifdef UDHCP_DEBUG |
| + | # define DEBUG(level, str, args...) LOG(level, str, ## args) |
| #else | |
| # define DEBUG(level, str, args...) do {;} while(0) | |
| #endif | |
| + | |
| + | #endif |
| @@ -38,9 +38,11 @@ | |
| #include "dhcpc.h" | |
| #include "options.h" | |
| #include "clientpacket.h" | |
| + | #include "clientsocket.h" |
| #include "script.h" | |
| #include "socket.h" | |
| #include "common.h" | |
| + | #include "signalpipe.h" |
| static int state; | |
| static unsigned long requested_ip; /* = 0 */ | |
| @@ -54,12 +56,6 @@ static int fd = -1; | |
| #define LISTEN_RAW 2 | |
| static int listen_mode; | |
| - | #ifdef CONFIG_INSTALL_NO_USR |
| - | #define DEFAULT_SCRIPT "/share/udhcpc/default.script" |
| - | #else |
| - | #define DEFAULT_SCRIPT "/usr/share/udhcpc/default.script" |
| - | #endif |
| - | |
| struct client_config_t client_config = { | |
| /* Default options. */ | |
| abort_if_no_lease: 0, | |
| @@ -78,7 +74,7 @@ struct client_config_t client_config = { | |
| #ifndef IN_BUSYBOX | |
| static void __attribute__ ((noreturn)) show_usage(void) | |
| { | |
| - | printf( |
| + | printf( |
| "Usage: udhcpc [OPTIONS]\n\n" | |
| " -c, --clientid=CLIENTID Client identifier\n" | |
| " -H, --hostname=HOSTNAME Client hostname\n" | |
| @@ -95,8 +91,8 @@ static void __attribute__ ((noreturn)) show_usage(void) | |
| " -s, --script=file Run file at dhcp events (default:\n" | |
| " " DEFAULT_SCRIPT ")\n" | |
| " -v, --version Display version\n" | |
| - | ); |
| - | exit(0); |
| + | ); |
| + | exit(0); |
| } | |
| #else | |
| #define show_usage bb_show_usage | |
| @@ -177,7 +173,11 @@ static void client_background(void) | |
| } | |
| + | #ifdef COMBINED_BINARY |
| int udhcpc_main(int argc, char *argv[]) | |
| + | #else |
| + | int main(int argc, char *argv[]) |
| + | #endif |
| { | |
| unsigned char *temp, *message; | |
| unsigned long t1 = 0, t2 = 0, xid = 0; | |
| @@ -258,18 +258,20 @@ int udhcpc_main(int argc, char *argv[]) | |
| client_config.script = optarg; | |
| break; | |
| case 'v': | |
| - | bb_error_msg("version %s\n", VERSION); |
| - | return(0); |
| + | printf("udhcpcd, version %s\n\n", VERSION); |
| + | return 0; |
| break; | |
| default: | |
| show_usage(); | |
| } | |
| } | |
| - | start_log("client"); |
| + | /* Start the log, sanitize fd's, and write a pid file */ |
| + | start_log_and_pid("udhcpc", client_config.pidfile); |
| + | |
| if (read_interface(client_config.interface, &client_config.ifindex, | |
| NULL, client_config.arp) < 0) | |
| - | return(1); |
| + | return 1; |
| if (!client_config.clientid) { | |
| client_config.clientid = xmalloc(6 + 3); | |
| @@ -279,8 +281,8 @@ int udhcpc_main(int argc, char *argv[]) | |
| memcpy(client_config.clientid + 3, client_config.arp, 6); | |
| } | |
| - | /* setup signal handlers */ |
| - | udhcp_set_signal_pipe(SIGUSR2); |
| + | /* setup the signal pipe */ |
| + | udhcp_sp_setup(); |
| state = INIT_SELECTING; | |
| run_script(NULL, "deconfig"); | |
| @@ -290,7 +292,6 @@ int udhcpc_main(int argc, char *argv[]) | |
| tv.tv_sec = timeout - time(0); | |
| tv.tv_usec = 0; | |
| - | FD_ZERO(&rfds); |
| if (listen_mode != LISTEN_NONE && fd < 0) { | |
| if (listen_mode == LISTEN_KERNEL) | |
| @@ -299,15 +300,13 @@ int udhcpc_main(int argc, char *argv[]) | |
| fd = raw_socket(client_config.ifindex); | |
| if (fd < 0) { | |
| LOG(LOG_ERR, "FATAL: couldn't listen on socket, %m"); | |
| - | return(0); |
| + | return 0; |
| } | |
| } | |
| - | if (fd >= 0) FD_SET(fd, &rfds); |
| - | FD_SET(udhcp_signal_pipe[0], &rfds); |
| + | max_fd = udhcp_sp_fd_set(&rfds, fd); |
| if (tv.tv_sec > 0) { | |
| DEBUG(LOG_INFO, "Waiting on select..."); | |
| - | max_fd = udhcp_signal_pipe[0] > fd ? udhcp_signal_pipe[0] : fd; |
| retval = select(max_fd + 1, &rfds, NULL, NULL, &tv); | |
| } else retval = 0; /* If we already timed out, fall through */ | |
| @@ -332,7 +331,7 @@ int udhcpc_main(int argc, char *argv[]) | |
| client_background(); | |
| } else if (client_config.abort_if_no_lease) { | |
| LOG(LOG_INFO, "No lease, failing."); | |
| - | return(1); |
| + | return 1; |
| } | |
| /* wait to try again */ | |
| packet_num = 0; | |
| @@ -474,7 +473,7 @@ int udhcpc_main(int argc, char *argv[]) | |
| state = BOUND; | |
| change_mode(LISTEN_NONE); | |
| if (client_config.quit_after_lease) | |
| - | return(0); |
| + | return 0; |
| if (!client_config.foreground) | |
| client_background(); | |
| @@ -494,11 +493,7 @@ int udhcpc_main(int argc, char *argv[]) | |
| break; | |
| /* case BOUND, RELEASED: - ignore all packets */ | |
| } | |
| - | } else if (retval > 0 && FD_ISSET(udhcp_signal_pipe[0], &rfds)) { |
| - | if (read(udhcp_signal_pipe[0], &sig, sizeof(sig)) < 0) { |
| - | DEBUG(LOG_ERR, "Could not read signal: %m"); |
| - | continue; /* probably just EINTR */ |
| - | } |
| + | } else if (retval > 0 && (sig = udhcp_sp_read(&rfds))) { |
| switch (sig) { | |
| case SIGUSR1: | |
| perform_renew(); | |
| @@ -508,7 +503,7 @@ int udhcpc_main(int argc, char *argv[]) | |
| break; | |
| case SIGTERM: | |
| LOG(LOG_INFO, "Received SIGTERM"); | |
| - | return(0); |
| + | return 0; |
| } | |
| } else if (retval == -1 && errno == EINTR) { | |
| /* a signal was caught */ | |
| @@ -2,6 +2,11 @@ | |
| #ifndef _DHCPC_H | |
| #define _DHCPC_H | |
| + | #define DEFAULT_SCRIPT "/usr/share/udhcpc/default.script" |
| + | |
| + | /* allow libbb_udhcp.h to redefine DEFAULT_SCRIPT */ |
| + | #include "libbb_udhcp.h" |
| + | |
| #define INIT_SELECTING 0 | |
| #define REQUESTING 1 | |
| #define BOUND 2 | |
| @@ -43,6 +43,7 @@ | |
| #include "files.h" | |
| #include "serverpacket.h" | |
| #include "common.h" | |
| + | #include "signalpipe.h" |
| /* globals */ | |
| @@ -50,7 +51,11 @@ struct dhcpOfferedAddr *leases; | |
| struct server_config_t server_config; | |
| + | #ifdef COMBINED_BINARY |
| int udhcpd_main(int argc, char *argv[]) | |
| + | #else |
| + | int main(int argc, char *argv[]) |
| + | #endif |
| { | |
| fd_set rfds; | |
| struct timeval tv; | |
| @@ -64,16 +69,13 @@ int udhcpd_main(int argc, char *argv[]) | |
| struct option_set *option; | |
| struct dhcpOfferedAddr *lease; | |
| int max_sock; | |
| - | int sig; |
| unsigned long num_ips; | |
| - | start_log("server"); |
| - | |
| memset(&server_config, 0, sizeof(struct server_config_t)); | |
| - | |
| - | if (argc < 2) |
| - | read_config(DHCPD_CONF_FILE); |
| - | else read_config(argv[1]); |
| + | read_config(argc < 2 ? DHCPD_CONF_FILE : argv[1]); |
| + | |
| + | /* Start the log, sanitize fd's, and write a pid file */ |
| + | start_log_and_pid("udhcpd", server_config.pidfile); |
| if ((option = find_option(server_config.options, DHCP_LEASE_TIME))) { | |
| memcpy(&server_config.lease, option->data + 2, 4); | |
| @@ -90,18 +92,19 @@ int udhcpd_main(int argc, char *argv[]) | |
| server_config.max_leases = num_ips; | |
| } | |
| - | leases = xcalloc(sizeof(struct dhcpOfferedAddr), server_config.max_leases); |
| + | leases = xcalloc(server_config.max_leases, sizeof(struct dhcpOfferedAddr)); |
| read_leases(server_config.lease_file); | |
| if (read_interface(server_config.interface, &server_config.ifindex, | |
| &server_config.server, server_config.arp) < 0) | |
| - | return(1); |
| + | return 1; |
| - | #ifndef CONFIG_FEATURE_UDHCP_DEBUG |
| - | background(server_config.pidfile); |
| + | #ifndef UDHCP_DEBUG |
| + | background(server_config.pidfile); /* hold lock during fork. */ |
| #endif | |
| - | udhcp_set_signal_pipe(0); |
| + | /* Setup the signal pipe */ |
| + | udhcp_sp_setup(); |
| timeout_end = time(0) + server_config.auto_time; | |
| while(1) { /* loop until universe collapses */ | |
| @@ -109,18 +112,15 @@ int udhcpd_main(int argc, char *argv[]) | |
| if (server_socket < 0) | |
| if ((server_socket = listen_socket(INADDR_ANY, SERVER_PORT, server_config.interface)) < 0) { | |
| LOG(LOG_ERR, "FATAL: couldn't create server socket, %m"); | |
| - | return(2); |
| + | return 2; |
| } | |
| - | FD_ZERO(&rfds); |
| - | FD_SET(server_socket, &rfds); |
| - | FD_SET(udhcp_signal_pipe[0], &rfds); |
| + | max_sock = udhcp_sp_fd_set(&rfds, server_socket); |
| if (server_config.auto_time) { | |
| tv.tv_sec = timeout_end - time(0); | |
| tv.tv_usec = 0; | |
| } | |
| if (!server_config.auto_time || tv.tv_sec > 0) { | |
| - | max_sock = server_socket > udhcp_signal_pipe[0] ? server_socket : udhcp_signal_pipe[0]; |
| retval = select(max_sock + 1, &rfds, NULL, NULL, | |
| server_config.auto_time ? &tv : NULL); | |
| } else retval = 0; /* If we already timed out, fall through */ | |
| @@ -134,20 +134,18 @@ int udhcpd_main(int argc, char *argv[]) | |
| continue; | |
| } | |
| - | if (FD_ISSET(udhcp_signal_pipe[0], &rfds)) { |
| - | if (read(udhcp_signal_pipe[0], &sig, sizeof(sig)) < 0) |
| - | continue; /* probably just EINTR */ |
| - | switch (sig) { |
| - | case SIGUSR1: |
| - | LOG(LOG_INFO, "Received a SIGUSR1"); |
| - | write_leases(); |
| - | /* why not just reset the timeout, eh */ |
| - | timeout_end = time(0) + server_config.auto_time; |
| - | continue; |
| - | case SIGTERM: |
| - | LOG(LOG_INFO, "Received a SIGTERM"); |
| - | return(0); |
| - | } |
| + | switch (udhcp_sp_read(&rfds)) { |
| + | case SIGUSR1: |
| + | LOG(LOG_INFO, "Received a SIGUSR1"); |
| + | write_leases(); |
| + | /* why not just reset the timeout, eh */ |
| + | timeout_end = time(0) + server_config.auto_time; |
| + | continue; |
| + | case SIGTERM: |
| + | LOG(LOG_INFO, "Received a SIGTERM"); |
| + | return 0; |
| + | case 0: break; /* no signal */ |
| + | default: continue; /* signal or error (probably EINTR) */ |
| } | |
| if ((bytes = get_packet(&packet, server_socket)) < 0) { /* this waits for a packet - idle */ | |
| @@ -251,3 +249,4 @@ int udhcpd_main(int argc, char *argv[]) | |
| return 0; | |
| } | |
| + | |
| @@ -16,6 +16,13 @@ | |
| #include "options.h" | |
| #include "common.h" | |
| + | /* |
| + | * Domain names may have 254 chars, and string options can be 254 |
| + | * chars long. However, 80 bytes will be enough for most, and won't |
| + | * hog up memory. If you have a special application, change it |
| + | */ |
| + | #define READ_CONFIG_BUF_SIZE 80 |
| + | |
| /* on these functions, make sure you datatype matches */ | |
| static int read_ip(const char *line, void *arg) | |
| { | |
| @@ -66,23 +73,23 @@ static int read_yn(const char *line, void *arg) | |
| return retval; | |
| } | |
| - | #define READ_CONFIG_BUF_SIZE 512 /* domainname may have 254 chars */ |
| /* read a dhcp option and add it to opt_list */ | |
| static int read_opt(const char *const_line, void *arg) | |
| { | |
| - | char line[READ_CONFIG_BUF_SIZE]; |
| struct option_set **opt_list = arg; | |
| char *opt, *val, *endptr; | |
| struct dhcp_option *option; | |
| int retval = 0, length; | |
| - | char buffer[256]; /* max opt length */ |
| - | u_int16_t result_u16; |
| - | u_int32_t result_u32; |
| - | void *valptr; |
| + | char buffer[8]; |
| + | char *line; |
| + | u_int16_t *result_u16 = (u_int16_t *) buffer; |
| + | u_int32_t *result_u32 = (u_int32_t *) buffer; |
| + | |
| + | /* Cheat, the only const line we'll actually get is "" */ |
| + | line = (char *) const_line; |
| + | if (!(opt = strtok(line, " \t="))) return 0; |
| - | if (!(opt = strtok(strcpy(line, const_line), " \t="))) return 0; |
| - | |
| for (option = dhcp_options; option->code; option++) | |
| if (!strcasecmp(option->name, opt)) | |
| break; | |
| @@ -90,11 +97,10 @@ static int read_opt(const char *const_line, void *arg) | |
| if (!option->code) return 0; | |
| do { | |
| - | val = strtok(NULL, ", \t"); |
| - | if(!val) |
| - | break; |
| + | if (!(val = strtok(NULL, ", \t"))) break; |
| length = option_lengths[option->flags & TYPE_MASK]; | |
| - | valptr = NULL; |
| + | retval = 0; |
| + | opt = buffer; /* new meaning for variable opt */ |
| switch (option->flags & TYPE_MASK) { | |
| case OPTION_IP: | |
| retval = read_ip(val, buffer); | |
| @@ -108,9 +114,8 @@ static int read_opt(const char *const_line, void *arg) | |
| length = strlen(val); | |
| if (length > 0) { | |
| if (length > 254) length = 254; | |
| - | endptr = buffer + length; |
| - | endptr[0] = 0; |
| - | valptr = val; |
| + | opt = val; |
| + | retval = 1; |
| } | |
| break; | |
| case OPTION_BOOLEAN: | |
| @@ -118,43 +123,36 @@ static int read_opt(const char *const_line, void *arg) | |
| break; | |
| case OPTION_U8: | |
| buffer[0] = strtoul(val, &endptr, 0); | |
| - | valptr = buffer; |
| + | retval = (endptr[0] == '\0'); |
| break; | |
| case OPTION_U16: | |
| - | result_u16 = htons(strtoul(val, &endptr, 0)); |
| - | valptr = &result_u16; |
| + | *result_u16 = htons(strtoul(val, &endptr, 0)); |
| + | retval = (endptr[0] == '\0'); |
| break; | |
| case OPTION_S16: | |
| - | result_u16 = htons(strtol(val, &endptr, 0)); |
| - | valptr = &result_u16; |
| + | *result_u16 = htons(strtol(val, &endptr, 0)); |
| + | retval = (endptr[0] == '\0'); |
| break; | |
| case OPTION_U32: | |
| - | result_u32 = htonl(strtoul(val, &endptr, 0)); |
| - | valptr = &result_u32; |
| + | *result_u32 = htonl(strtoul(val, &endptr, 0)); |
| + | retval = (endptr[0] == '\0'); |
| break; | |
| case OPTION_S32: | |
| - | result_u32 = htonl(strtol(val, &endptr, 0)); |
| - | valptr = &result_u32; |
| + | *result_u32 = htonl(strtol(val, &endptr, 0)); |
| + | retval = (endptr[0] == '\0'); |
| break; | |
| default: | |
| - | retval = 0; |
| break; | |
| } | |
| - | if (valptr) { |
| - | memcpy(buffer, valptr, length); |
| - | retval = (endptr[0] == '\0'); |
| - | } |
| if (retval) | |
| - | attach_option(opt_list, option, buffer, length); |
| - | else |
| - | break; |
| - | } while (option->flags & OPTION_LIST); |
| + | attach_option(opt_list, option, opt, length); |
| + | } while (retval && option->flags & OPTION_LIST); |
| return retval; | |
| } | |
| static const struct config_keyword keywords[] = { | |
| - | /* keyword handler variable address default */ |
| + | /* keyword handler variable address default */ |
| {"start", read_ip, &(server_config.start), "192.168.0.20"}, | |
| {"end", read_ip, &(server_config.end), "192.168.0.254"}, | |
| {"interface", read_str, &(server_config.interface), "eth0"}, | |
| @@ -167,7 +165,7 @@ static const struct config_keyword keywords[] = { | |
| {"conflict_time",read_u32,&(server_config.conflict_time),"3600"}, | |
| {"offer_time", read_u32, &(server_config.offer_time), "60"}, | |
| {"min_lease", read_u32, &(server_config.min_lease), "60"}, | |
| - | {"lease_file", read_str, &(server_config.lease_file), LEASES_FILE}, |
| + | {"lease_file", read_str, &(server_config.lease_file), LEASES_FILE}, |
| {"pidfile", read_str, &(server_config.pidfile), "/var/run/udhcpd.pid"}, | |
| {"notify_file", read_str, &(server_config.notify_file), ""}, | |
| {"siaddr", read_ip, &(server_config.siaddr), "0.0.0.0"}, | |
| @@ -181,9 +179,11 @@ static const struct config_keyword keywords[] = { | |
| int read_config(const char *file) | |
| { | |
| FILE *in; | |
| - | char buffer[READ_CONFIG_BUF_SIZE], orig[READ_CONFIG_BUF_SIZE]; |
| - | char *token, *line; |
| - | int i; |
| + | char buffer[READ_CONFIG_BUF_SIZE], *token, *line; |
| + | #ifdef UDHCP_DEBUG |
| + | char orig[READ_CONFIG_BUF_SIZE]; |
| + | #endif |
| + | int i, lm = 0; |
| for (i = 0; keywords[i].keyword[0]; i++) | |
| if (keywords[i].def[0]) | |
| @@ -195,27 +195,27 @@ int read_config(const char *file) | |
| } | |
| while (fgets(buffer, READ_CONFIG_BUF_SIZE, in)) { | |
| + | lm++; |
| if (strchr(buffer, '\n')) *(strchr(buffer, '\n')) = '\0'; | |
| + | #ifdef UDHCP_DEBUG |
| strcpy(orig, buffer); | |
| + | #endif |
| if (strchr(buffer, '#')) *(strchr(buffer, '#')) = '\0'; | |
| - | token = strtok(buffer, " \t"); |
| - | if(!token) |
| - | continue; |
| - | line = strtok(NULL, ""); |
| - | if(!line) |
| - | continue; |
| - | while(*line == '=' || isspace(*line)) |
| - | line++; |
| + | |
| + | if (!(token = strtok(buffer, " \t"))) continue; |
| + | if (!(line = strtok(NULL, ""))) continue; |
| + | |
| + | /* eat leading whitespace */ |
| + | line = line + strspn(line, " \t="); |
| /* eat trailing whitespace */ | |
| for (i = strlen(line); i > 0 && isspace(line[i - 1]); i--); | |
| line[i] = '\0'; | |
| - | if (*line == '\0') |
| - | continue; |
| for (i = 0; keywords[i].keyword[0]; i++) | |
| if (!strcasecmp(token, keywords[i].keyword)) | |
| if (!keywords[i].handler(line, keywords[i].var)) { | |
| - | LOG(LOG_ERR, "unable to parse '%s'", orig); |
| + | LOG(LOG_ERR, "Failure parsing line %d of %s", lm, file); |
| + | DEBUG(LOG_ERR, "unable to parse '%s'", orig); |
| /* reset back to the default value */ | |
| keywords[i].handler(keywords[i].def, keywords[i].var); | |
| } | |
| @@ -117,6 +117,7 @@ static int check_ip(u_int32_t addr) | |
| } else return 0; | |
| } | |
| + | |
| /* find an assignable address, it check_expired is true, we check all the expired leases as well. | |
| * Maybe this should try expired leases by age... */ | |
| u_int32_t find_address(int check_expired) | |
| @@ -9,8 +9,6 @@ struct dhcpOfferedAddr { | |
| u_int32_t expires; /* host order */ | |
| }; | |
| - | extern const char leases_file[]; |
| - | |
| extern unsigned char blank_chaddr[]; | |
| void clear_lease(u_int8_t *chaddr, u_int32_t yiaddr); | |
| @@ -1 +0,0 @@ | |
| - | const char leases_file[] = "/var/lib/misc/udhcpd.leases"; |
| @@ -1,5 +1,13 @@ | |
| /* libbb_udhcp.h - busybox compatability wrapper */ | |
| + | /* bit of a hack, do this no matter what the order of the includes. |
| + | * (for busybox) */ |
| + | |
| + | #ifdef CONFIG_INSTALL_NO_USR |
| + | #undef DEFUALT_SCRIPT |
| + | #define DEFAULT_SCRIPT "/share/udhcpc/default.script" |
| + | #endif |
| + | |
| #ifndef _LIBBB_UDHCP_H | |
| #define _LIBBB_UDHCP_H | |
| @@ -7,22 +15,16 @@ | |
| #include "busybox.h" | |
| #ifdef CONFIG_FEATURE_UDHCP_SYSLOG | |
| - | #define SYSLOG |
| + | #define UDHCP_SYSLOG |
| #endif | |
| #ifdef CONFIG_FEATURE_UDHCP_DEBUG | |
| - | #define DEBUG |
| + | #define UDHCP_DEBUG |
| #endif | |
| #define COMBINED_BINARY | |
| #include "version.h" | |
| - | #ifdef CONFIG_INSTALL_NO_USR |
| - | #define DEFAULT_SCRIPT "/share/udhcpc/default.script" |
| - | #else |
| - | #define DEFAULT_SCRIPT "/usr/share/udhcpc/default.script" |
| - | #endif |
| - | |
| #define xfopen bb_xfopen | |
| #else /* ! BB_VER */ | |
| @@ -36,8 +38,6 @@ | |
| #define xmalloc malloc | |
| #define xcalloc calloc | |
| - | #define DEFAULT_SCRIPT "/usr/share/udhcpc/default.script" |
| - | |
| static inline FILE *xfopen(const char *file, const char *mode) | |
| { | |
| FILE *fp; | |
| @@ -0,0 +1,75 @@ | |
| + | /* pidfile.c |
| + | * |
| + | * Functions to assist in the writing and removing of pidfiles. |
| + | * |
| + | * Russ Dill <[email protected]> Soptember 2001 |
| + | * |
| + | * This program is free software; you can redistribute it and/or modify |
| + | * it under the terms of the GNU General Public License as published by |
| + | * the Free Software Foundation; either version 2 of the License, or |
| + | * (at your option) any later version. |
| + | * |
| + | * This program is distributed in the hope that it will be useful, |
| + | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| + | * GNU General Public License for more details. |
| + | * |
| + | * You should have received a copy of the GNU General Public License |
| + | * along with this program; if not, write to the Free Software |
| + | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| + | */ |
| + | |
| + | #include <sys/types.h> |
| + | #include <sys/stat.h> |
| + | #include <fcntl.h> |
| + | #include <unistd.h> |
| + | #include <stdio.h> |
| + | #include <stdlib.h> |
| + | |
| + | #include "pidfile.h" |
| + | #include "common.h" |
| + | |
| + | static char *saved_pidfile; |
| + | |
| + | static void pidfile_delete(void) |
| + | { |
| + | if (saved_pidfile) unlink(saved_pidfile); |
| + | } |
| + | |
| + | |
| + | int pidfile_acquire(const char *pidfile) |
| + | { |
| + | int pid_fd; |
| + | if (!pidfile) return -1; |
| + | |
| + | pid_fd = open(pidfile, O_CREAT | O_WRONLY, 0644); |
| + | if (pid_fd < 0) { |
| + | LOG(LOG_ERR, "Unable to open pidfile %s: %m\n", pidfile); |
| + | } else { |
| + | lockf(pid_fd, F_LOCK, 0); |
| + | if (!saved_pidfile) |
| + | atexit(pidfile_delete); |
| + | saved_pidfile = (char *) pidfile; |
| + | } |
| + | |
| + | return pid_fd; |
| + | } |
| + | |
| + | |
| + | void pidfile_write_release(int pid_fd) |
| + | { |
| + | FILE *out; |
| + | |
| + | if (pid_fd < 0) return; |
| + | |
| + | if ((out = fdopen(pid_fd, "w")) != NULL) { |
| + | fprintf(out, "%d\n", getpid()); |
| + | fclose(out); |
| + | } |
| + | lockf(pid_fd, F_UNLCK, 0); |
| + | close(pid_fd); |
| + | } |
| + | |
| + | |
| + | |
| + | |
| @@ -0,0 +1,25 @@ | |
| + | /* pidfile.h |
| + | * |
| + | * Functions to assist in the writing and removing of pidfiles. |
| + | * |
| + | * Russ Dill <[email protected]> Soptember 2001 |
| + | * |
| + | * This program is free software; you can redistribute it and/or modify |
| + | * it under the terms of the GNU General Public License as published by |
| + | * the Free Software Foundation; either version 2 of the License, or |
| + | * (at your option) any later version. |
| + | * |
| + | * This program is distributed in the hope that it will be useful, |
| + | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| + | * GNU General Public License for more details. |
| + | * |
| + | * You should have received a copy of the GNU General Public License |
| + | * along with this program; if not, write to the Free Software |
| + | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| + | */ |
| + | |
| + | |
| + | int pidfile_acquire(const char *pidfile); |
| + | void pidfile_write_release(int pid_fd); |
| + | |
| @@ -32,7 +32,6 @@ | |
| #include "options.h" | |
| #include "dhcpd.h" | |
| #include "dhcpc.h" | |
| - | #include "script.h" |
| #include "common.h" | |
| /* get a rough idea of how long an option will be (rounding up...) */ | |
| @@ -56,14 +55,9 @@ static inline int upper_length(int length, int opt_index) | |
| } | |
| - | static int sprintip(char *dest, unsigned char *ip) |
| + | static int sprintip(char *dest, char *pre, unsigned char *ip) |
| { | |
| - | return sprintf(dest, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); |
| - | } |
| - | |
| - | static void asprintip(char **dest, char *pre, unsigned char *ip) |
| - | { |
| - | asprintf(dest, "%s%d.%d.%d.%d", pre, ip[0], ip[1], ip[2], ip[3]); |
| + | return sprintf(dest, "%s%d.%d.%d.%d", pre, ip[0], ip[1], ip[2], ip[3]); |
| } | |
| @@ -96,12 +90,12 @@ static void fill_options(char *dest, unsigned char *option, struct dhcp_option * | |
| for(;;) { | |
| switch (type) { | |
| case OPTION_IP_PAIR: | |
| - | dest += sprintip(dest, option); |
| + | dest += sprintip(dest, "", option); |
| *(dest++) = '/'; | |
| option += 4; | |
| optlen = 4; | |
| case OPTION_IP: /* Works regardless of host byte order. */ | |
| - | dest += sprintip(dest, option); |
| + | dest += sprintip(dest, "", option); |
| break; | |
| case OPTION_BOOLEAN: | |
| dest += sprintf(dest, *option ? "yes" : "no"); | |
| @@ -138,15 +132,6 @@ static void fill_options(char *dest, unsigned char *option, struct dhcp_option * | |
| } | |
| - | static char *find_env(const char *prefix, char *defaultstr) |
| - | { |
| - | char *ptr; |
| - | |
| - | ptr = getenv(prefix); |
| - | return ptr ? ptr : defaultstr; |
| - | } |
| - | |
| - | |
| /* put all the paramaters into an environment */ | |
| static char **fill_envp(struct dhcpMessage *packet) | |
| { | |
| @@ -167,21 +152,20 @@ static char **fill_envp(struct dhcpMessage *packet) | |
| if ((temp = get_option(packet, DHCP_OPTION_OVER))) | |
| over = *temp; | |
| if (!(over & FILE_FIELD) && packet->file[0]) num_options++; | |
| - | if (!(over & SNAME_FIELD) && packet->sname[0]) num_options++; |
| + | if (!(over & SNAME_FIELD) && packet->sname[0]) num_options++; |
| } | |
| - | envp = xmalloc((num_options + 5) * sizeof(char *)); |
| + | envp = xcalloc(sizeof(char *), num_options + 5); |
| j = 0; | |
| asprintf(&envp[j++], "interface=%s", client_config.interface); | |
| - | envp[j++] = find_env("PATH", "PATH=/bin:/usr/bin:/sbin:/usr/sbin"); |
| - | envp[j++] = find_env("HOME", "HOME=/"); |
| + | asprintf(&envp[j++], "%s=%s", "PATH", |
| + | getenv("PATH") ? : "/bin:/usr/bin:/sbin:/usr/sbin"); |
| + | asprintf(&envp[j++], "%s=%s", "HOME", getenv("HOME") ? : "/"); |
| - | if (packet == NULL) { |
| - | envp[j++] = NULL; |
| - | return envp; |
| - | } |
| + | if (packet == NULL) return envp; |
| - | asprintip(&envp[j++], "ip=", (unsigned char *) &packet->yiaddr); |
| + | envp[j] = xmalloc(sizeof("ip=255.255.255.255")); |
| + | sprintip(envp[j++], "ip=", (unsigned char *) &packet->yiaddr); |
| for (i = 0; dhcp_options[i].code; i++) { | |
| @@ -198,7 +182,8 @@ static char **fill_envp(struct dhcpMessage *packet) | |
| } | |
| } | |
| if (packet->siaddr) { | |
| - | asprintip(&envp[j++], "siaddr=", (unsigned char *) &packet->siaddr); |
| + | envp[j] = xmalloc(sizeof("siaddr=255.255.255.255")); |
| + | sprintip(envp[j++], "siaddr=", (unsigned char *) &packet->siaddr); |
| } | |
| if (!(over & FILE_FIELD) && packet->file[0]) { | |
| /* watch out for invalid packets */ | |
| @@ -210,7 +195,6 @@ static char **fill_envp(struct dhcpMessage *packet) | |
| packet->sname[sizeof(packet->sname) - 1] = '\0'; | |
| asprintf(&envp[j++], "sname=%s", packet->sname); | |
| } | |
| - | envp[j] = NULL; |
| return envp; | |
| } | |
| @@ -0,0 +1,78 @@ | |
| + | /* signalpipe.c |
| + | * |
| + | * Signal pipe infastructure. A reliable way of delivering signals. |
| + | * |
| + | * Russ Dill <[email protected]> Decemeber 2003 |
| + | * |
| + | * This program is free software; you can redistribute it and/or modify |
| + | * it under the terms of the GNU General Public License as published by |
| + | * the Free Software Foundation; either version 2 of the License, or |
| + | * (at your option) any later version. |
| + | * |
| + | * This program is distributed in the hope that it will be useful, |
| + | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| + | * GNU General Public License for more details. |
| + | * |
| + | * You should have received a copy of the GNU General Public License |
| + | * along with this program; if not, write to the Free Software |
| + | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| + | */ |
| + | |
| + | #include <unistd.h> |
| + | #include <signal.h> |
| + | #include <sys/types.h> |
| + | #include <sys/socket.h> |
| + | #include <sys/select.h> |
| + | |
| + | |
| + | #include "signalpipe.h" |
| + | #include "common.h" |
| + | |
| + | static int signal_pipe[2]; |
| + | |
| + | static void signal_handler(int sig) |
| + | { |
| + | if (send(signal_pipe[1], &sig, sizeof(sig), MSG_DONTWAIT) < 0) |
| + | DEBUG(LOG_ERR, "Could not send signal: %m"); |
| + | } |
| + | |
| + | |
| + | /* Call this before doing anything else. Sets up the socket pair |
| + | * and installs the signal handler */ |
| + | void udhcp_sp_setup(void) |
| + | { |
| + | socketpair(AF_UNIX, SOCK_STREAM, 0, signal_pipe); |
| + | signal(SIGUSR1, signal_handler); |
| + | signal(SIGUSR2, signal_handler); |
| + | signal(SIGTERM, signal_handler); |
| + | } |
| + | |
| + | |
| + | /* Quick little function to setup the rfds. Will return the |
| + | * max_fd for use with select. Limited in that you can only pass |
| + | * one extra fd */ |
| + | int udhcp_sp_fd_set(fd_set *rfds, int extra_fd) |
| + | { |
| + | FD_ZERO(rfds); |
| + | FD_SET(signal_pipe[0], rfds); |
| + | if (extra_fd >= 0) FD_SET(extra_fd, rfds); |
| + | return signal_pipe[0] > extra_fd ? signal_pipe[0] : extra_fd; |
| + | } |
| + | |
| + | |
| + | /* Read a signal from the signal pipe. Returns 0 if there is |
| + | * no signal, -1 on error (and sets errno appropriately), and |
| + | * your signal on success */ |
| + | int udhcp_sp_read(fd_set *rfds) |
| + | { |
| + | int sig; |
| + | |
| + | if (!FD_ISSET(signal_pipe[0], rfds)) |
| + | return 0; |
| + | |
| + | if (read(signal_pipe[0], &sig, sizeof(sig)) < 0) |
| + | return -1; |
| + | |
| + | return sig; |
| + | } |
| @@ -0,0 +1,22 @@ | |
| + | /* signalpipe.h |
| + | * |
| + | * Russ Dill <[email protected]> December 2003 |
| + | * |
| + | * This program is free software; you can redistribute it and/or modify |
| + | * it under the terms of the GNU General Public License as published by |
| + | * the Free Software Foundation; either version 2 of the License, or |
| + | * (at your option) any later version. |
| + | * |
| + | * This program is distributed in the hope that it will be useful, |
| + | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| + | * GNU General Public License for more details. |
| + | * |
| + | * You should have received a copy of the GNU General Public License |
| + | * along with this program; if not, write to the Free Software |
| + | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| + | */ |
| + | |
| + | void udhcp_sp_setup(void); |
| + | int udhcp_sp_fd_set(fd_set *rfds, int extra_fd); |
| + | int udhcp_sp_read(fd_set *rfds); |
| @@ -130,29 +130,3 @@ int listen_socket(unsigned int ip, int port, char *inf) | |
| return fd; | |
| } | |
| - | |
| - | |
| - | int raw_socket(int ifindex) |
| - | { |
| - | int fd; |
| - | struct sockaddr_ll sock; |
| - | |
| - | DEBUG(LOG_INFO, "Opening raw socket on ifindex %d", ifindex); |
| - | if ((fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0) { |
| - | DEBUG(LOG_ERR, "socket call failed: %m"); |
| - | return -1; |
| - | } |
| - | |
| - | while (fd >= 0 && fd < 3) fd = dup(fd); /* don't let daemon close fds on us */ |
| - | |
| - | sock.sll_family = AF_PACKET; |
| - | sock.sll_protocol = htons(ETH_P_IP); |
| - | sock.sll_ifindex = ifindex; |
| - | if (bind(fd, (struct sockaddr *) &sock, sizeof(sock)) < 0) { |
| - | DEBUG(LOG_ERR, "bind call failed: %m"); |
| - | close(fd); |
| - | return -1; |
| - | } |
| - | |
| - | return fd; |
| - | } |
| @@ -4,6 +4,5 @@ | |
| int read_interface(char *interface, int *ifindex, u_int32_t *addr, unsigned char *arp); | |
| int listen_socket(unsigned int ip, int port, char *inf); | |
| - | int raw_socket(int ifindex); |
| #endif | |