From 4e864a36b611f56c6b347be1dace4e5e805a3eb8 Mon Sep 17 00:00:00 2001 From: Russ Dill Date: Thu, 18 Dec 2003 22:25:38 +0000 Subject: [PATCH] Finish remerging busybox udhcp and udhcp. Some cleanups as well. --- networking/udhcp/AUTHORS | 2 +- networking/udhcp/ChangeLog | 8 +- networking/udhcp/Makefile.in | 20 ++--- networking/udhcp/README | 13 +-- networking/udhcp/TODO | 2 + networking/udhcp/arpping.c | 4 + networking/udhcp/clientsocket.c | 62 ++++++++++++++ networking/udhcp/clientsocket.h | 7 ++ networking/udhcp/common.c | 142 ++++++++++++++++---------------- networking/udhcp/common.h | 23 +++--- networking/udhcp/dhcpc.c | 51 ++++++------ networking/udhcp/dhcpc.h | 5 ++ networking/udhcp/dhcpd.c | 61 +++++++------- networking/udhcp/files.c | 98 +++++++++++----------- networking/udhcp/leases.c | 1 + networking/udhcp/leases.h | 2 - networking/udhcp/leases_file.c | 1 - networking/udhcp/libbb_udhcp.h | 20 ++--- networking/udhcp/pidfile.c | 75 +++++++++++++++++ networking/udhcp/pidfile.h | 25 ++++++ networking/udhcp/script.c | 44 ++++------ networking/udhcp/signalpipe.c | 78 ++++++++++++++++++ networking/udhcp/signalpipe.h | 22 +++++ networking/udhcp/socket.c | 26 ------ networking/udhcp/socket.h | 1 - 25 files changed, 509 insertions(+), 284 deletions(-) create mode 100644 networking/udhcp/clientsocket.c create mode 100644 networking/udhcp/clientsocket.h delete mode 100644 networking/udhcp/leases_file.c create mode 100644 networking/udhcp/pidfile.c create mode 100644 networking/udhcp/pidfile.h create mode 100644 networking/udhcp/signalpipe.c create mode 100644 networking/udhcp/signalpipe.h diff --git a/networking/udhcp/AUTHORS b/networking/udhcp/AUTHORS index 3772aedb3..bb58de13e 100644 --- a/networking/udhcp/AUTHORS +++ b/networking/udhcp/AUTHORS @@ -9,6 +9,6 @@ Other Credits: -------------- Moreton Bay (http://www.moretonbay.com/) Lineo (http://opensource.lineo.com) -Vladimir Oleynik , optimize and more integrate for busybox +Vladimir Oleynik Size optimizations diff --git a/networking/udhcp/ChangeLog b/networking/udhcp/ChangeLog index 9ee97534f..f1aac060e 100644 --- a/networking/udhcp/ChangeLog +++ b/networking/udhcp/ChangeLog @@ -1,8 +1,6 @@ -0.9.10 - Size optimization (over 3k), more busybox integration - (Vladimir Oleynik - 0.9.9 (pending) ++ Various other size optimizations (Vladimir) ++ Change strerror(errno) to %m (Vladimir N. Oleynik ) + Fixed a little endian problem in mton (Bastian Blank ) + Fixed a arpping alignment problem (Rui He ) + Added sanity check for max_leases (udhcp bug #1285) (me) @@ -36,7 +34,7 @@ udhcp bug#1256 + Fixed reading of client id (David Poole ) + change sys_errlist[] to strerror() as it aparently doesn't exist - (Erik Andersen ) + (Erik Andersen ) + fixed get_raw_packet so it returns -2 on non fatal errors (Ted Lemon ) + Improved (hopefully) NAKing behavior (me) diff --git a/networking/udhcp/Makefile.in b/networking/udhcp/Makefile.in index d06e809c9..4d3f27093 100644 --- a/networking/udhcp/Makefile.in +++ b/networking/udhcp/Makefile.in @@ -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) diff --git a/networking/udhcp/README b/networking/udhcp/README index 5f4bb78a8..eddb24be7 100644 --- a/networking/udhcp/README +++ b/networking/udhcp/README @@ -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. diff --git a/networking/udhcp/TODO b/networking/udhcp/TODO index f88694a86..6febe5ab4 100644 --- a/networking/udhcp/TODO +++ b/networking/udhcp/TODO @@ -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 diff --git a/networking/udhcp/arpping.c b/networking/udhcp/arpping.c index e20395a9e..363408d6e 100644 --- a/networking/udhcp/arpping.c +++ b/networking/udhcp/arpping.c @@ -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; } diff --git a/networking/udhcp/clientsocket.c b/networking/udhcp/clientsocket.c new file mode 100644 index 000000000..7c1b6e87c --- /dev/null +++ b/networking/udhcp/clientsocket.c @@ -0,0 +1,62 @@ +/* + * clientsocket.c -- DHCP client socket creation + * + * udhcp client + * + * Russ Dill 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 +#include +#include +#include +#include +#if __GLIBC__ >=2 && __GLIBC_MINOR >= 1 +#include +#include +#else +#include +#include +#include +#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; +} diff --git a/networking/udhcp/clientsocket.h b/networking/udhcp/clientsocket.h new file mode 100644 index 000000000..17a55c154 --- /dev/null +++ b/networking/udhcp/clientsocket.h @@ -0,0 +1,7 @@ +/* clientsocket.h */ +#ifndef _CLIENTSOCKET_H +#define _CLIENTSOCKET_H + +int raw_socket(int ifindex); + +#endif diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index babd980e3..bfdc7ba8d 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c @@ -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 Soptember 2001 + * Russ Dill 2001-2003 * Rewrited by Vladimir Oleynik (C) 2003 * * This program is free software; you can redistribute it and/or modify @@ -26,18 +27,54 @@ #include #include #include +#include #include +#include #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); -} diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index 768f551b0..78eb1c147 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h @@ -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 #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 diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 55664abf9..a180cc514 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c @@ -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 */ diff --git a/networking/udhcp/dhcpc.h b/networking/udhcp/dhcpc.h index e23d9d4fe..7145cbd8b 100644 --- a/networking/udhcp/dhcpc.h +++ b/networking/udhcp/dhcpc.h @@ -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 diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index c21cb72a2..aabab38b0 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c @@ -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; } + diff --git a/networking/udhcp/files.c b/networking/udhcp/files.c index f24f01cb6..6d72863ee 100644 --- a/networking/udhcp/files.c +++ b/networking/udhcp/files.c @@ -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); } diff --git a/networking/udhcp/leases.c b/networking/udhcp/leases.c index 341abab49..add114f6c 100644 --- a/networking/udhcp/leases.c +++ b/networking/udhcp/leases.c @@ -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) diff --git a/networking/udhcp/leases.h b/networking/udhcp/leases.h index d54cd11cc..24d860867 100644 --- a/networking/udhcp/leases.h +++ b/networking/udhcp/leases.h @@ -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); diff --git a/networking/udhcp/leases_file.c b/networking/udhcp/leases_file.c deleted file mode 100644 index 96e2f2d1b..000000000 --- a/networking/udhcp/leases_file.c +++ /dev/null @@ -1 +0,0 @@ -const char leases_file[] = "/var/lib/misc/udhcpd.leases"; diff --git a/networking/udhcp/libbb_udhcp.h b/networking/udhcp/libbb_udhcp.h index 73e21464f..9b5d5a846 100644 --- a/networking/udhcp/libbb_udhcp.h +++ b/networking/udhcp/libbb_udhcp.h @@ -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; diff --git a/networking/udhcp/pidfile.c b/networking/udhcp/pidfile.c new file mode 100644 index 000000000..d656c7ad0 --- /dev/null +++ b/networking/udhcp/pidfile.c @@ -0,0 +1,75 @@ +/* pidfile.c + * + * Functions to assist in the writing and removing of pidfiles. + * + * Russ Dill 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 +#include +#include +#include +#include +#include + +#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); +} + + + + diff --git a/networking/udhcp/pidfile.h b/networking/udhcp/pidfile.h new file mode 100644 index 000000000..7f8e8aedc --- /dev/null +++ b/networking/udhcp/pidfile.h @@ -0,0 +1,25 @@ +/* pidfile.h + * + * Functions to assist in the writing and removing of pidfiles. + * + * Russ Dill 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); + diff --git a/networking/udhcp/script.c b/networking/udhcp/script.c index 9c766a2e2..dcd2cad2d 100644 --- a/networking/udhcp/script.c +++ b/networking/udhcp/script.c @@ -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; } diff --git a/networking/udhcp/signalpipe.c b/networking/udhcp/signalpipe.c new file mode 100644 index 000000000..4f3292b9d --- /dev/null +++ b/networking/udhcp/signalpipe.c @@ -0,0 +1,78 @@ +/* signalpipe.c + * + * Signal pipe infastructure. A reliable way of delivering signals. + * + * Russ Dill 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 +#include +#include +#include +#include + + +#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; +} diff --git a/networking/udhcp/signalpipe.h b/networking/udhcp/signalpipe.h new file mode 100644 index 000000000..70c1e5715 --- /dev/null +++ b/networking/udhcp/signalpipe.h @@ -0,0 +1,22 @@ +/* signalpipe.h + * + * Russ Dill 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); diff --git a/networking/udhcp/socket.c b/networking/udhcp/socket.c index 60190a044..c19838a7b 100644 --- a/networking/udhcp/socket.c +++ b/networking/udhcp/socket.c @@ -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; -} diff --git a/networking/udhcp/socket.h b/networking/udhcp/socket.h index 333994b8f..d259ef770 100644 --- a/networking/udhcp/socket.h +++ b/networking/udhcp/socket.h @@ -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 -- 2.25.1