Finish remerging busybox udhcp and udhcp. Some cleanups as well.

This commit is contained in:
Russ Dill 2003-12-18 22:25:38 +00:00
parent e30495654d
commit 4e864a36b6
25 changed files with 512 additions and 287 deletions

View File

@ -9,6 +9,6 @@ Other Credits:
--------------
Moreton Bay (http://www.moretonbay.com/)
Lineo (http://opensource.lineo.com)
Vladimir Oleynik <dzo@simtrea.ru>, optimize and more integrate for busybox
Vladimir Oleynik <dzo@simtrea.ru> Size optimizations

View File

@ -1,8 +1,6 @@
0.9.10
Size optimization (over 3k), more busybox integration
(Vladimir Oleynik <dzo@simtreas.ru>
0.9.9 (pending)
+ Various other size optimizations (Vladimir)
+ Change strerror(errno) to %m (Vladimir N. Oleynik <dzo@simtreas.ru>)
+ Fixed a little endian problem in mton (Bastian Blank <waldi@debian.org>)
+ Fixed a arpping alignment problem (Rui He <rhe@3eti.com>)
+ Added sanity check for max_leases (udhcp bug #1285) (me)
@ -36,7 +34,7 @@
udhcp bug#1256
+ Fixed reading of client id (David Poole <davep@portsmith.com>)
+ change sys_errlist[] to strerror() as it aparently doesn't exist
(Erik Andersen <andersen@codepoet.org>)
(Erik Andersen <andersee@codepoet.org>)
+ fixed get_raw_packet so it returns -2 on non fatal errors
(Ted Lemon <Ted.Lemon@nominum.com>)
+ Improved (hopefully) NAKing behavior (me)

View File

@ -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)

View File

@ -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.

View File

@ -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

View File

@ -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;
}

View File

@ -0,0 +1,62 @@
/*
* clientsocket.c -- DHCP client socket creation
*
* udhcp client
*
* Russ Dill <Russ.Dill@asu.edu> 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;
}

View File

@ -0,0 +1,7 @@
/* clientsocket.h */
#ifndef _CLIENTSOCKET_H
#define _CLIENTSOCKET_H
int raw_socket(int ifindex);
#endif

View File

@ -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 <Russ.Dill@asu.edu> Soptember 2001
* Russ Dill <Russ.Dill@asu.edu> 2001-2003
* Rewrited by Vladimir Oleynik <dzo@simtreas.ru> (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)
{
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);
udhcp_logging(LOG_INFO, "%s (v%s) started", client_server, VERSION);
}
#endif
static const char *saved_pidfile;
static void exit_fun(void)
{
if (saved_pidfile) unlink(saved_pidfile);
}
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__ */
}
/* 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");
}
}
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);
}

View File

@ -18,10 +18,14 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "version.h"
#include "busybox.h"
#ifndef _COMMON_H
#define _COMMON_H
#ifndef CONFIG_FEATURE_UDHCP_SYSLOG
#include "version.h"
#include "libbb_udhcp.h"
#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

View File

@ -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 */

View File

@ -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

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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)

View File

@ -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);

View File

@ -1 +0,0 @@
const char leases_file[] = "/var/lib/misc/udhcpd.leases";

View File

@ -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;

View File

@ -0,0 +1,75 @@
/* pidfile.c
*
* Functions to assist in the writing and removing of pidfiles.
*
* Russ Dill <Russ.Dill@asu.edu> 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);
}

View File

@ -0,0 +1,25 @@
/* pidfile.h
*
* Functions to assist in the writing and removing of pidfiles.
*
* Russ Dill <Russ.Dill@asu.edu> 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);

View File

@ -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;
}

View File

@ -0,0 +1,78 @@
/* signalpipe.c
*
* Signal pipe infastructure. A reliable way of delivering signals.
*
* Russ Dill <Russ.Dill@asu.edu> 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;
}

View File

@ -0,0 +1,22 @@
/* signalpipe.h
*
* Russ Dill <Russ.Dill@asu.edu> 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);

View File

@ -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;
}

View File

@ -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