mirror of
https://git.busybox.net/udhcp
synced 2025-05-08 13:43:45 +08:00
remerge with busybox
This commit is contained in:
parent
4d1bfe0b76
commit
9b98f2c1ab
1
AUTHORS
1
AUTHORS
@ -9,5 +9,6 @@ Other Credits:
|
||||
--------------
|
||||
Moreton Bay (http://www.moretonbay.com/)
|
||||
Lineo (http://opensource.lineo.com)
|
||||
Vladimir Oleynik <dzo@simtrea.ru> Size optimizations
|
||||
|
||||
|
||||
|
@ -1,4 +1,6 @@
|
||||
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)
|
||||
@ -32,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
|
||||
(andersee <andersee@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)
|
||||
|
20
Makefile
20
Makefile
@ -8,22 +8,22 @@ USRSHAREDIR=${prefix}/share
|
||||
|
||||
# Uncomment this to get a shared binary. Call as udhcpd for the server,
|
||||
# and udhcpc for the client
|
||||
#COMBINED_BINARY=1
|
||||
COMBINED_BINARY=1
|
||||
|
||||
# Uncomment this for extra output and to compile with debugging symbols
|
||||
#DEBUG=1
|
||||
#UDHCP_DEBUG=1
|
||||
|
||||
# Uncomment this to output messages to syslog, otherwise, messages go to stdout
|
||||
CFLAGS += -DSYSLOG
|
||||
#CFLAGS += -DUDHCP_SYSLOG
|
||||
|
||||
#CROSS_COMPILE=arm-uclibc-
|
||||
CC = $(CROSS_COMPILE)gcc
|
||||
LD = $(CROSS_COMPILE)gcc
|
||||
INSTALL = install
|
||||
|
||||
OBJS_SHARED = options.o socket.o packet.o pidfile.o
|
||||
OBJS_SHARED = common.o options.o packet.o pidfile.o signalpipe.o socket.o
|
||||
DHCPD_OBJS = dhcpd.o arpping.o files.o leases.o serverpacket.o
|
||||
DHCPC_OBJS = dhcpc.o clientpacket.o script.o
|
||||
DHCPC_OBJS = dhcpc.o clientpacket.o clientsocket.o script.o
|
||||
|
||||
ifdef COMBINED_BINARY
|
||||
EXEC1 = udhcpd
|
||||
@ -44,14 +44,14 @@ BOOT_PROGRAMS = udhcpc
|
||||
DAEMONS = udhcpd
|
||||
COMMANDS = dumpleases
|
||||
|
||||
ifdef SYSLOG
|
||||
CFLAGS += -DSYSLOG
|
||||
ifdef UDHCP_SYSLOG
|
||||
CFLAGS += -DUDHCP_SYSLOG
|
||||
endif
|
||||
|
||||
CFLAGS += -W -Wall -Wstrict-prototypes
|
||||
CFLAGS += -W -Wall -Wstrict-prototypes -D_GNU_SOURCE
|
||||
|
||||
ifdef DEBUG
|
||||
CFLAGS += -g -DDEBUG
|
||||
ifdef UDHCP_DEBUG
|
||||
CFLAGS += -g -DUDHCP_DEBUG
|
||||
STRIP=true
|
||||
else
|
||||
CFLAGS += -Os -fomit-frame-pointer
|
||||
|
13
README
13
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.
|
||||
|
||||
|
11
arpping.c
11
arpping.c
@ -5,22 +5,19 @@
|
||||
* by Yoichi Hariguchi <yoichi@fore.com>
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/if_ether.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "dhcpd.h"
|
||||
#include "debug.h"
|
||||
#include "arpping.h"
|
||||
#include "common.h"
|
||||
|
||||
/* args: yiaddr - what IP to ping
|
||||
* ip - our ip
|
||||
@ -47,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;
|
||||
}
|
||||
|
||||
@ -84,7 +85,7 @@ int arpping(u_int32_t yiaddr, u_int32_t ip, unsigned char *mac, char *interface)
|
||||
FD_SET(s, &fdset);
|
||||
tm.tv_sec = timeout;
|
||||
if (select(s + 1, &fdset, (fd_set *) NULL, (fd_set *) NULL, &tm) < 0) {
|
||||
DEBUG(LOG_ERR, "Error on ARPING request: %s", strerror(errno));
|
||||
DEBUG(LOG_ERR, "Error on ARPING request: %m");
|
||||
if (errno != EINTR) rv = 0;
|
||||
} else if (FD_ISSET(s, &fdset)) {
|
||||
if (recv(s, &arp, sizeof(arp), 0) < 0 ) rv = 0;
|
||||
|
@ -35,17 +35,14 @@
|
||||
#include <unistd.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
#include "dhcpd.h"
|
||||
#include "packet.h"
|
||||
#include "clientpacket.h"
|
||||
#include "options.h"
|
||||
#include "dhcpc.h"
|
||||
#include "debug.h"
|
||||
#include "common.h"
|
||||
|
||||
|
||||
/* Create a random xid */
|
||||
@ -58,8 +55,7 @@ unsigned long random_xid(void)
|
||||
|
||||
fd = open("/dev/urandom", 0);
|
||||
if (fd < 0 || read(fd, &seed, sizeof(seed)) < 0) {
|
||||
LOG(LOG_WARNING, "Could not load seed from /dev/urandom: %s",
|
||||
strerror(errno));
|
||||
LOG(LOG_WARNING, "Could not load seed from /dev/urandom: %m");
|
||||
seed = time(0);
|
||||
}
|
||||
if (fd >= 0) close(fd);
|
||||
@ -95,9 +91,9 @@ static void add_requests(struct dhcpMessage *packet)
|
||||
int i, len = 0;
|
||||
|
||||
packet->options[end + OPT_CODE] = DHCP_PARAM_REQ;
|
||||
for (i = 0; options[i].code; i++)
|
||||
if (options[i].flags & OPTION_REQ)
|
||||
packet->options[end + OPT_DATA + len++] = options[i].code;
|
||||
for (i = 0; dhcp_options[i].code; i++)
|
||||
if (dhcp_options[i].flags & OPTION_REQ)
|
||||
packet->options[end + OPT_DATA + len++] = dhcp_options[i].code;
|
||||
packet->options[end + OPT_LEN] = len;
|
||||
packet->options[end + OPT_DATA + len] = DHCP_END;
|
||||
|
||||
@ -250,4 +246,3 @@ int get_raw_packet(struct dhcpMessage *payload, int fd)
|
||||
return bytes - (sizeof(packet.ip) + sizeof(packet.udp));
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
#ifndef _CLIENTPACKET_H
|
||||
#define _CLIENTPACKET_H
|
||||
|
||||
#include "packet.h"
|
||||
|
||||
unsigned long random_xid(void);
|
||||
int send_discover(unsigned long xid, unsigned long requested);
|
||||
int send_selecting(unsigned long xid, unsigned long server, unsigned long requested);
|
||||
|
62
clientsocket.c
Normal file
62
clientsocket.c
Normal 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;
|
||||
}
|
7
clientsocket.h
Normal file
7
clientsocket.h
Normal file
@ -0,0 +1,7 @@
|
||||
/* clientsocket.h */
|
||||
#ifndef _CLIENTSOCKET_H
|
||||
#define _CLIENTSOCKET_H
|
||||
|
||||
int raw_socket(int ifindex);
|
||||
|
||||
#endif
|
156
common.c
Normal file
156
common.c
Normal file
@ -0,0 +1,156 @@
|
||||
/* common.c
|
||||
*
|
||||
* Functions for debugging and logging as well as some other
|
||||
* simple helper functions.
|
||||
*
|
||||
* 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
|
||||
* 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 <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#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;
|
||||
|
||||
|
||||
/*
|
||||
* 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, ...)
|
||||
{
|
||||
va_list p;
|
||||
va_list p2;
|
||||
|
||||
va_start(p, fmt);
|
||||
__va_copy(p2, p);
|
||||
if(!daemonized) {
|
||||
vprintf(fmt, p);
|
||||
putchar('\n');
|
||||
}
|
||||
vsyslog(level, fmt, p2);
|
||||
va_end(p);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
||||
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!",
|
||||
[LOG_CRIT] = "critical!",
|
||||
[LOG_WARNING] = "warning",
|
||||
[LOG_ERR] = "error",
|
||||
[LOG_INFO] = "info",
|
||||
[LOG_DEBUG] = "debug"
|
||||
};
|
||||
|
||||
|
||||
void udhcp_logging(int level, const char *fmt, ...)
|
||||
{
|
||||
va_list p;
|
||||
|
||||
va_start(p, fmt);
|
||||
if(!daemonized) {
|
||||
printf("%s, ", syslog_level_msg[level]);
|
||||
vprintf(fmt, p);
|
||||
putchar('\n');
|
||||
}
|
||||
va_end(p);
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
|
55
common.h
Normal file
55
common.h
Normal file
@ -0,0 +1,55 @@
|
||||
/* common.h
|
||||
*
|
||||
* Russ Dill <Russ.Dill@asu.edu> Soptember 2001
|
||||
* Rewrited by Vladimir Oleynik <dzo@simtreas.ru> (C) 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.
|
||||
*/
|
||||
|
||||
#ifndef _COMMON_H
|
||||
#define _COMMON_H
|
||||
|
||||
#include "version.h"
|
||||
#include "libbb_udhcp.h"
|
||||
|
||||
|
||||
#ifndef UDHCP_SYSLOG
|
||||
enum syslog_levels {
|
||||
LOG_EMERG = 0,
|
||||
LOG_ALERT,
|
||||
LOG_CRIT,
|
||||
LOG_WARNING,
|
||||
LOG_ERR,
|
||||
LOG_INFO,
|
||||
LOG_DEBUG
|
||||
};
|
||||
#else
|
||||
#include <syslog.h>
|
||||
#endif
|
||||
|
||||
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, ...);
|
||||
|
||||
#define LOG(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
|
41
debug.h
41
debug.h
@ -1,41 +0,0 @@
|
||||
#ifndef _DEBUG_H
|
||||
#define _DEBUG_H
|
||||
|
||||
#include "libbb_udhcp.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef SYSLOG
|
||||
#include <syslog.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef SYSLOG
|
||||
# define LOG(level, str, args...) do { printf(str, ## args); \
|
||||
printf("\n"); \
|
||||
syslog(level, str, ## args); } while(0)
|
||||
# define OPEN_LOG(name) openlog(name, 0, 0)
|
||||
#define CLOSE_LOG() closelog()
|
||||
#else
|
||||
# define LOG_EMERG "EMERGENCY!"
|
||||
# define LOG_ALERT "ALERT!"
|
||||
# define LOG_CRIT "critical!"
|
||||
# define LOG_WARNING "warning"
|
||||
# define LOG_ERR "error"
|
||||
# define LOG_INFO "info"
|
||||
# define LOG_DEBUG "debug"
|
||||
# define LOG(level, str, args...) do { printf("%s, ", level); \
|
||||
printf(str, ## args); \
|
||||
printf("\n"); } while(0)
|
||||
# define OPEN_LOG(name) do {;} while(0)
|
||||
#define CLOSE_LOG() do {;} while(0)
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
# undef DEBUG
|
||||
# define DEBUG(level, str, args...) LOG(level, str, ## args)
|
||||
# define DEBUGGING
|
||||
#else
|
||||
# define DEBUG(level, str, args...) do {;} while(0)
|
||||
#endif
|
||||
|
||||
#endif
|
97
dhcpc.c
97
dhcpc.c
@ -19,9 +19,7 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/file.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
@ -40,11 +38,11 @@
|
||||
#include "dhcpc.h"
|
||||
#include "options.h"
|
||||
#include "clientpacket.h"
|
||||
#include "packet.h"
|
||||
#include "clientsocket.h"
|
||||
#include "script.h"
|
||||
#include "socket.h"
|
||||
#include "debug.h"
|
||||
#include "pidfile.h"
|
||||
#include "common.h"
|
||||
#include "signalpipe.h"
|
||||
|
||||
static int state;
|
||||
static unsigned long requested_ip; /* = 0 */
|
||||
@ -52,15 +50,12 @@ static unsigned long server_addr;
|
||||
static unsigned long timeout;
|
||||
static int packet_num; /* = 0 */
|
||||
static int fd = -1;
|
||||
static int signal_pipe[2];
|
||||
|
||||
#define LISTEN_NONE 0
|
||||
#define LISTEN_KERNEL 1
|
||||
#define LISTEN_RAW 2
|
||||
static int listen_mode;
|
||||
|
||||
#define DEFAULT_SCRIPT "/usr/share/udhcpc/default.script"
|
||||
|
||||
struct client_config_t client_config = {
|
||||
/* Default options. */
|
||||
abort_if_no_lease: 0,
|
||||
@ -135,6 +130,7 @@ static void perform_renew(void)
|
||||
state = INIT_SELECTING;
|
||||
break;
|
||||
case INIT_SELECTING:
|
||||
break;
|
||||
}
|
||||
|
||||
/* start things over */
|
||||
@ -169,38 +165,11 @@ static void perform_release(void)
|
||||
}
|
||||
|
||||
|
||||
/* Exit and cleanup */
|
||||
static void exit_client(int retval)
|
||||
static void client_background(void)
|
||||
{
|
||||
pidfile_delete(client_config.pidfile);
|
||||
CLOSE_LOG();
|
||||
exit(retval);
|
||||
}
|
||||
|
||||
|
||||
/* Signal handler */
|
||||
static void signal_handler(int sig)
|
||||
{
|
||||
if (send(signal_pipe[1], &sig, sizeof(sig), MSG_DONTWAIT) < 0) {
|
||||
LOG(LOG_ERR, "Could not send signal: %s",
|
||||
strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void background(void)
|
||||
{
|
||||
int pid_fd;
|
||||
|
||||
pid_fd = pidfile_acquire(client_config.pidfile); /* hold lock during fork. */
|
||||
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_client(1);
|
||||
}
|
||||
background(client_config.pidfile);
|
||||
client_config.foreground = 1; /* Do not fork again. */
|
||||
client_config.background_if_no_lease = 0;
|
||||
pidfile_write_release(pid_fd);
|
||||
}
|
||||
|
||||
|
||||
@ -219,12 +188,11 @@ int main(int argc, char *argv[])
|
||||
int c, len;
|
||||
struct dhcpMessage packet;
|
||||
struct in_addr temp_addr;
|
||||
int pid_fd;
|
||||
time_t now;
|
||||
int max_fd;
|
||||
int sig;
|
||||
|
||||
static struct option arg_options[] = {
|
||||
static const struct option arg_options[] = {
|
||||
{"clientid", required_argument, 0, 'c'},
|
||||
{"foreground", no_argument, 0, 'f'},
|
||||
{"background", no_argument, 0, 'b'},
|
||||
@ -237,7 +205,6 @@ int main(int argc, char *argv[])
|
||||
{"request", required_argument, 0, 'r'},
|
||||
{"script", required_argument, 0, 's'},
|
||||
{"version", no_argument, 0, 'v'},
|
||||
{"help", no_argument, 0, '?'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
@ -292,22 +259,19 @@ int main(int argc, char *argv[])
|
||||
break;
|
||||
case 'v':
|
||||
printf("udhcpcd, version %s\n\n", VERSION);
|
||||
exit_client(0);
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
show_usage();
|
||||
}
|
||||
}
|
||||
|
||||
OPEN_LOG("udhcpc");
|
||||
LOG(LOG_INFO, "udhcp client (v%s) started", VERSION);
|
||||
|
||||
pid_fd = pidfile_acquire(client_config.pidfile);
|
||||
pidfile_write_release(pid_fd);
|
||||
/* 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)
|
||||
exit_client(1);
|
||||
return 1;
|
||||
|
||||
if (!client_config.clientid) {
|
||||
client_config.clientid = xmalloc(6 + 3);
|
||||
@ -317,11 +281,8 @@ int main(int argc, char *argv[])
|
||||
memcpy(client_config.clientid + 3, client_config.arp, 6);
|
||||
}
|
||||
|
||||
/* setup signal handlers */
|
||||
socketpair(AF_UNIX, SOCK_STREAM, 0, signal_pipe);
|
||||
signal(SIGUSR1, signal_handler);
|
||||
signal(SIGUSR2, signal_handler);
|
||||
signal(SIGTERM, signal_handler);
|
||||
/* setup the signal pipe */
|
||||
udhcp_sp_setup();
|
||||
|
||||
state = INIT_SELECTING;
|
||||
run_script(NULL, "deconfig");
|
||||
@ -331,7 +292,6 @@ int 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)
|
||||
@ -339,16 +299,14 @@ int main(int argc, char *argv[])
|
||||
else
|
||||
fd = raw_socket(client_config.ifindex);
|
||||
if (fd < 0) {
|
||||
LOG(LOG_ERR, "FATAL: couldn't listen on socket, %s", strerror(errno));
|
||||
exit_client(0);
|
||||
LOG(LOG_ERR, "FATAL: couldn't listen on socket, %m");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (fd >= 0) FD_SET(fd, &rfds);
|
||||
FD_SET(signal_pipe[0], &rfds);
|
||||
max_fd = udhcp_sp_fd_set(&rfds, fd);
|
||||
|
||||
if (tv.tv_sec > 0) {
|
||||
DEBUG(LOG_INFO, "Waiting on select...\n");
|
||||
max_fd = signal_pipe[0] > fd ? signal_pipe[0] : fd;
|
||||
DEBUG(LOG_INFO, "Waiting on select...");
|
||||
retval = select(max_fd + 1, &rfds, NULL, NULL, &tv);
|
||||
} else retval = 0; /* If we already timed out, fall through */
|
||||
|
||||
@ -367,12 +325,13 @@ int main(int argc, char *argv[])
|
||||
timeout = now + ((packet_num == 2) ? 4 : 2);
|
||||
packet_num++;
|
||||
} else {
|
||||
run_script(NULL, "leasefail");
|
||||
if (client_config.background_if_no_lease) {
|
||||
LOG(LOG_INFO, "No lease, forking to background.");
|
||||
background();
|
||||
client_background();
|
||||
} else if (client_config.abort_if_no_lease) {
|
||||
LOG(LOG_INFO, "No lease, failing.");
|
||||
exit_client(1);
|
||||
return 1;
|
||||
}
|
||||
/* wait to try again */
|
||||
packet_num = 0;
|
||||
@ -450,7 +409,7 @@ int main(int argc, char *argv[])
|
||||
else len = get_raw_packet(&packet, fd);
|
||||
|
||||
if (len == -1 && errno != EINTR) {
|
||||
DEBUG(LOG_INFO, "error on read, %s, reopening socket", strerror(errno));
|
||||
DEBUG(LOG_INFO, "error on read, %m, reopening socket");
|
||||
change_mode(listen_mode); /* just close and reopen */
|
||||
}
|
||||
if (len < 0) continue;
|
||||
@ -514,9 +473,9 @@ int main(int argc, char *argv[])
|
||||
state = BOUND;
|
||||
change_mode(LISTEN_NONE);
|
||||
if (client_config.quit_after_lease)
|
||||
exit_client(0);
|
||||
return 0;
|
||||
if (!client_config.foreground)
|
||||
background();
|
||||
client_background();
|
||||
|
||||
} else if (*message == DHCPNAK) {
|
||||
/* return to init state */
|
||||
@ -534,12 +493,7 @@ int main(int argc, char *argv[])
|
||||
break;
|
||||
/* case BOUND, RELEASED: - ignore all packets */
|
||||
}
|
||||
} else if (retval > 0 && FD_ISSET(signal_pipe[0], &rfds)) {
|
||||
if (read(signal_pipe[0], &sig, sizeof(sig)) < 0) {
|
||||
DEBUG(LOG_ERR, "Could not read signal: %s",
|
||||
strerror(errno));
|
||||
continue; /* probably just EINTR */
|
||||
}
|
||||
} else if (retval > 0 && (sig = udhcp_sp_read(&rfds))) {
|
||||
switch (sig) {
|
||||
case SIGUSR1:
|
||||
perform_renew();
|
||||
@ -549,7 +503,7 @@ int main(int argc, char *argv[])
|
||||
break;
|
||||
case SIGTERM:
|
||||
LOG(LOG_INFO, "Received SIGTERM");
|
||||
exit_client(0);
|
||||
return 0;
|
||||
}
|
||||
} else if (retval == -1 && errno == EINTR) {
|
||||
/* a signal was caught */
|
||||
@ -561,4 +515,3 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
3
dhcpc.h
3
dhcpc.h
@ -2,6 +2,9 @@
|
||||
#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
|
||||
|
102
dhcpd.c
102
dhcpd.c
@ -25,12 +25,9 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/stat.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
@ -39,40 +36,19 @@
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "dhcpd.h"
|
||||
#include "arpping.h"
|
||||
#include "socket.h"
|
||||
#include "options.h"
|
||||
#include "files.h"
|
||||
#include "leases.h"
|
||||
#include "packet.h"
|
||||
#include "serverpacket.h"
|
||||
#include "pidfile.h"
|
||||
#include "common.h"
|
||||
#include "signalpipe.h"
|
||||
|
||||
|
||||
/* globals */
|
||||
struct dhcpOfferedAddr *leases;
|
||||
struct server_config_t server_config;
|
||||
static int signal_pipe[2];
|
||||
|
||||
/* Exit and cleanup */
|
||||
static void exit_server(int retval)
|
||||
{
|
||||
pidfile_delete(server_config.pidfile);
|
||||
CLOSE_LOG();
|
||||
exit(retval);
|
||||
}
|
||||
|
||||
|
||||
/* Signal handler */
|
||||
static void signal_handler(int sig)
|
||||
{
|
||||
if (send(signal_pipe[1], &sig, sizeof(sig), MSG_DONTWAIT) < 0) {
|
||||
LOG(LOG_ERR, "Could not send signal: %s",
|
||||
strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef COMBINED_BINARY
|
||||
@ -92,22 +68,14 @@ int main(int argc, char *argv[])
|
||||
unsigned long timeout_end;
|
||||
struct option_set *option;
|
||||
struct dhcpOfferedAddr *lease;
|
||||
int pid_fd;
|
||||
int max_sock;
|
||||
int sig;
|
||||
unsigned long num_ips;
|
||||
|
||||
OPEN_LOG("udhcpd");
|
||||
LOG(LOG_INFO, "udhcp server (v%s) started", VERSION);
|
||||
|
||||
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]);
|
||||
|
||||
pid_fd = pidfile_acquire(server_config.pidfile);
|
||||
pidfile_write_release(pid_fd);
|
||||
/* 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);
|
||||
@ -118,51 +86,41 @@ int main(int argc, char *argv[])
|
||||
/* Sanity check */
|
||||
num_ips = ntohl(server_config.end) - ntohl(server_config.start);
|
||||
if (server_config.max_leases > num_ips) {
|
||||
LOG(LOG_ERR, "max_leases value (%lu) not sane, setting to %lu instead",
|
||||
LOG(LOG_ERR, "max_leases value (%lu) not sane, "
|
||||
"setting to %lu instead",
|
||||
server_config.max_leases, num_ips);
|
||||
server_config.max_leases = num_ips;
|
||||
}
|
||||
|
||||
leases = xmalloc(sizeof(struct dhcpOfferedAddr) * server_config.max_leases);
|
||||
memset(leases, 0, 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)
|
||||
exit_server(1);
|
||||
return 1;
|
||||
|
||||
#ifndef DEBUGGING
|
||||
pid_fd = pidfile_acquire(server_config.pidfile); /* hold lock during fork. */
|
||||
if (daemon(0, 0) == -1) {
|
||||
perror("fork");
|
||||
exit_server(1);
|
||||
}
|
||||
pidfile_write_release(pid_fd);
|
||||
#ifndef UDHCP_DEBUG
|
||||
background(server_config.pidfile); /* hold lock during fork. */
|
||||
#endif
|
||||
|
||||
|
||||
socketpair(AF_UNIX, SOCK_STREAM, 0, signal_pipe);
|
||||
signal(SIGUSR1, signal_handler);
|
||||
signal(SIGTERM, signal_handler);
|
||||
/* Setup the signal pipe */
|
||||
udhcp_sp_setup();
|
||||
|
||||
timeout_end = time(0) + server_config.auto_time;
|
||||
while(1) { /* loop until universe collapses */
|
||||
|
||||
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, %s", strerror(errno));
|
||||
exit_server(0);
|
||||
LOG(LOG_ERR, "FATAL: couldn't create server socket, %m");
|
||||
return 2;
|
||||
}
|
||||
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(server_socket, &rfds);
|
||||
FD_SET(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 > signal_pipe[0] ? server_socket : 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 */
|
||||
@ -176,25 +134,23 @@ int main(int argc, char *argv[])
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FD_ISSET(signal_pipe[0], &rfds)) {
|
||||
if (read(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");
|
||||
exit_server(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 */
|
||||
if (bytes == -1 && errno != EINTR) {
|
||||
DEBUG(LOG_INFO, "error on read, %s, reopening socket", strerror(errno));
|
||||
DEBUG(LOG_INFO, "error on read, %m, reopening socket");
|
||||
close(server_socket);
|
||||
server_socket = -1;
|
||||
}
|
||||
|
181
files.c
181
files.c
@ -11,14 +11,20 @@
|
||||
#include <ctype.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "dhcpd.h"
|
||||
#include "files.h"
|
||||
#include "options.h"
|
||||
#include "leases.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(char *line, void *arg)
|
||||
static int read_ip(const char *line, void *arg)
|
||||
{
|
||||
struct in_addr *addr = arg;
|
||||
struct hostent *host;
|
||||
@ -33,7 +39,7 @@ static int read_ip(char *line, void *arg)
|
||||
}
|
||||
|
||||
|
||||
static int read_str(char *line, void *arg)
|
||||
static int read_str(const char *line, void *arg)
|
||||
{
|
||||
char **dest = arg;
|
||||
|
||||
@ -44,7 +50,7 @@ static int read_str(char *line, void *arg)
|
||||
}
|
||||
|
||||
|
||||
static int read_u32(char *line, void *arg)
|
||||
static int read_u32(const char *line, void *arg)
|
||||
{
|
||||
u_int32_t *dest = arg;
|
||||
char *endptr;
|
||||
@ -53,7 +59,7 @@ static int read_u32(char *line, void *arg)
|
||||
}
|
||||
|
||||
|
||||
static int read_yn(char *line, void *arg)
|
||||
static int read_yn(const char *line, void *arg)
|
||||
{
|
||||
char *dest = arg;
|
||||
int retval = 1;
|
||||
@ -69,87 +75,84 @@ static int read_yn(char *line, void *arg)
|
||||
|
||||
|
||||
/* read a dhcp option and add it to opt_list */
|
||||
static int read_opt(char *line, void *arg)
|
||||
static int read_opt(const char *const_line, void *arg)
|
||||
{
|
||||
struct option_set **opt_list = arg;
|
||||
char *opt, *val, *endptr;
|
||||
struct dhcp_option *option = NULL;
|
||||
int retval = 0, length = 0;
|
||||
char buffer[255];
|
||||
u_int16_t result_u16;
|
||||
u_int32_t result_u32;
|
||||
int i;
|
||||
struct dhcp_option *option;
|
||||
int retval = 0, length;
|
||||
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;
|
||||
|
||||
for (i = 0; options[i].code; i++)
|
||||
if (!strcmp(options[i].name, opt))
|
||||
option = &(options[i]);
|
||||
|
||||
if (!option) return 0;
|
||||
for (option = dhcp_options; option->code; option++)
|
||||
if (!strcasecmp(option->name, opt))
|
||||
break;
|
||||
|
||||
if (!option->code) return 0;
|
||||
|
||||
do {
|
||||
val = strtok(NULL, ", \t");
|
||||
if (val) {
|
||||
length = option_lengths[option->flags & TYPE_MASK];
|
||||
retval = 0;
|
||||
switch (option->flags & TYPE_MASK) {
|
||||
case OPTION_IP:
|
||||
retval = read_ip(val, buffer);
|
||||
break;
|
||||
case OPTION_IP_PAIR:
|
||||
retval = read_ip(val, buffer);
|
||||
if (!(val = strtok(NULL, ", \t/-"))) retval = 0;
|
||||
if (retval) retval = read_ip(val, buffer + 4);
|
||||
break;
|
||||
case OPTION_STRING:
|
||||
length = strlen(val);
|
||||
if (length > 0) {
|
||||
if (length > 254) length = 254;
|
||||
memcpy(buffer, val, length);
|
||||
retval = 1;
|
||||
}
|
||||
break;
|
||||
case OPTION_BOOLEAN:
|
||||
retval = read_yn(val, buffer);
|
||||
break;
|
||||
case OPTION_U8:
|
||||
buffer[0] = strtoul(val, &endptr, 0);
|
||||
retval = (endptr[0] == '\0');
|
||||
break;
|
||||
case OPTION_U16:
|
||||
result_u16 = htons(strtoul(val, &endptr, 0));
|
||||
memcpy(buffer, &result_u16, 2);
|
||||
retval = (endptr[0] == '\0');
|
||||
break;
|
||||
case OPTION_S16:
|
||||
result_u16 = htons(strtol(val, &endptr, 0));
|
||||
memcpy(buffer, &result_u16, 2);
|
||||
retval = (endptr[0] == '\0');
|
||||
break;
|
||||
case OPTION_U32:
|
||||
result_u32 = htonl(strtoul(val, &endptr, 0));
|
||||
memcpy(buffer, &result_u32, 4);
|
||||
retval = (endptr[0] == '\0');
|
||||
break;
|
||||
case OPTION_S32:
|
||||
result_u32 = htonl(strtol(val, &endptr, 0));
|
||||
memcpy(buffer, &result_u32, 4);
|
||||
retval = (endptr[0] == '\0');
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if (!(val = strtok(NULL, ", \t"))) break;
|
||||
length = option_lengths[option->flags & TYPE_MASK];
|
||||
retval = 0;
|
||||
opt = buffer; /* new meaning for variable opt */
|
||||
switch (option->flags & TYPE_MASK) {
|
||||
case OPTION_IP:
|
||||
retval = read_ip(val, buffer);
|
||||
break;
|
||||
case OPTION_IP_PAIR:
|
||||
retval = read_ip(val, buffer);
|
||||
if (!(val = strtok(NULL, ", \t/-"))) retval = 0;
|
||||
if (retval) retval = read_ip(val, buffer + 4);
|
||||
break;
|
||||
case OPTION_STRING:
|
||||
length = strlen(val);
|
||||
if (length > 0) {
|
||||
if (length > 254) length = 254;
|
||||
opt = val;
|
||||
retval = 1;
|
||||
}
|
||||
if (retval)
|
||||
attach_option(opt_list, option, buffer, length);
|
||||
};
|
||||
} while (val && retval && option->flags & OPTION_LIST);
|
||||
break;
|
||||
case OPTION_BOOLEAN:
|
||||
retval = read_yn(val, buffer);
|
||||
break;
|
||||
case OPTION_U8:
|
||||
buffer[0] = strtoul(val, &endptr, 0);
|
||||
retval = (endptr[0] == '\0');
|
||||
break;
|
||||
case OPTION_U16:
|
||||
*result_u16 = htons(strtoul(val, &endptr, 0));
|
||||
retval = (endptr[0] == '\0');
|
||||
break;
|
||||
case OPTION_S16:
|
||||
*result_u16 = htons(strtol(val, &endptr, 0));
|
||||
retval = (endptr[0] == '\0');
|
||||
break;
|
||||
case OPTION_U32:
|
||||
*result_u32 = htonl(strtoul(val, &endptr, 0));
|
||||
retval = (endptr[0] == '\0');
|
||||
break;
|
||||
case OPTION_S32:
|
||||
*result_u32 = htonl(strtol(val, &endptr, 0));
|
||||
retval = (endptr[0] == '\0');
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (retval)
|
||||
attach_option(opt_list, option, opt, length);
|
||||
} while (retval && option->flags & OPTION_LIST);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
static struct config_keyword keywords[] = {
|
||||
/* keyword[14] handler variable address default[20] */
|
||||
static const struct config_keyword keywords[] = {
|
||||
/* 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"},
|
||||
@ -173,11 +176,14 @@ static struct config_keyword keywords[] = {
|
||||
};
|
||||
|
||||
|
||||
int read_config(char *file)
|
||||
int read_config(const char *file)
|
||||
{
|
||||
FILE *in;
|
||||
char buffer[80], orig[80], *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])
|
||||
@ -188,16 +194,16 @@ int read_config(char *file)
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (fgets(buffer, 80, in)) {
|
||||
while (fgets(buffer, READ_CONFIG_BUF_SIZE, in)) {
|
||||
lm++;
|
||||
if (strchr(buffer, '\n')) *(strchr(buffer, '\n')) = '\0';
|
||||
strncpy(orig, buffer, 80);
|
||||
#ifdef UDHCP_DEBUG
|
||||
strcpy(orig, buffer);
|
||||
#endif
|
||||
if (strchr(buffer, '#')) *(strchr(buffer, '#')) = '\0';
|
||||
token = buffer + strspn(buffer, " \t");
|
||||
if (*token == '\0') continue;
|
||||
line = token + strcspn(token, " \t=");
|
||||
if (*line == '\0') continue;
|
||||
*line = '\0';
|
||||
line++;
|
||||
|
||||
if (!(token = strtok(buffer, " \t"))) continue;
|
||||
if (!(line = strtok(NULL, ""))) continue;
|
||||
|
||||
/* eat leading whitespace */
|
||||
line = line + strspn(line, " \t=");
|
||||
@ -208,7 +214,8 @@ int read_config(char *file)
|
||||
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);
|
||||
}
|
||||
@ -258,7 +265,7 @@ void write_leases(void)
|
||||
}
|
||||
|
||||
|
||||
void read_leases(char *file)
|
||||
void read_leases(const char *file)
|
||||
{
|
||||
FILE *fp;
|
||||
unsigned int i = 0;
|
||||
|
10
files.h
10
files.h
@ -3,15 +3,15 @@
|
||||
#define _FILES_H
|
||||
|
||||
struct config_keyword {
|
||||
char keyword[14];
|
||||
int (*handler)(char *line, void *var);
|
||||
const char *keyword;
|
||||
int (* const handler)(const char *line, void *var);
|
||||
void *var;
|
||||
char def[30];
|
||||
const char *def;
|
||||
};
|
||||
|
||||
|
||||
int read_config(char *file);
|
||||
int read_config(const char *file);
|
||||
void write_leases(void);
|
||||
void read_leases(char *file);
|
||||
void read_leases(const char *file);
|
||||
|
||||
#endif
|
||||
|
34
leases.c
34
leases.c
@ -9,12 +9,13 @@
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "dhcpd.h"
|
||||
#include "files.h"
|
||||
#include "options.h"
|
||||
#include "leases.h"
|
||||
#include "arpping.h"
|
||||
#include "common.h"
|
||||
|
||||
|
||||
unsigned char blank_chaddr[] = {[0 ... 15] = 0};
|
||||
|
||||
@ -102,6 +103,21 @@ struct dhcpOfferedAddr *find_lease_by_yiaddr(u_int32_t yiaddr)
|
||||
}
|
||||
|
||||
|
||||
/* check is an IP is taken, if it is, add it to the lease table */
|
||||
static int check_ip(u_int32_t addr)
|
||||
{
|
||||
struct in_addr temp;
|
||||
|
||||
if (arpping(addr, server_config.server, server_config.arp, server_config.interface) == 0) {
|
||||
temp.s_addr = addr;
|
||||
LOG(LOG_INFO, "%s belongs to someone, reserving it for %ld seconds",
|
||||
inet_ntoa(temp), server_config.conflict_time);
|
||||
add_lease(blank_chaddr, addr, server_config.conflict_time);
|
||||
return 1;
|
||||
} 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)
|
||||
@ -133,19 +149,3 @@ u_int32_t find_address(int check_expired)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* check is an IP is taken, if it is, add it to the lease table */
|
||||
int check_ip(u_int32_t addr)
|
||||
{
|
||||
struct in_addr temp;
|
||||
|
||||
if (arpping(addr, server_config.server, server_config.arp, server_config.interface) == 0) {
|
||||
temp.s_addr = addr;
|
||||
LOG(LOG_INFO, "%s belongs to someone, reserving it for %ld seconds",
|
||||
inet_ntoa(temp), server_config.conflict_time);
|
||||
add_lease(blank_chaddr, addr, server_config.conflict_time);
|
||||
return 1;
|
||||
} else return 0;
|
||||
}
|
||||
|
||||
|
1
leases.h
1
leases.h
@ -18,7 +18,6 @@ struct dhcpOfferedAddr *oldest_expired_lease(void);
|
||||
struct dhcpOfferedAddr *find_lease_by_chaddr(u_int8_t *chaddr);
|
||||
struct dhcpOfferedAddr *find_lease_by_yiaddr(u_int32_t yiaddr);
|
||||
u_int32_t find_address(int check_expired);
|
||||
int check_ip(u_int32_t addr);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -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;
|
||||
|
12
options.c
12
options.c
@ -3,19 +3,17 @@
|
||||
* Rewrite by Russ Dill <Russ.Dill@asu.edu> July 2001
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "dhcpd.h"
|
||||
#include "files.h"
|
||||
#include "options.h"
|
||||
#include "leases.h"
|
||||
#include "common.h"
|
||||
|
||||
|
||||
/* supported options are easily added here */
|
||||
struct dhcp_option options[] = {
|
||||
struct dhcp_option dhcp_options[] = {
|
||||
/* name[10] flags code */
|
||||
{"subnet", OPTION_IP | OPTION_REQ, 0x01},
|
||||
{"timezone", OPTION_S32, 0x02},
|
||||
@ -160,9 +158,9 @@ int add_simple_option(unsigned char *optionptr, unsigned char code, u_int32_t da
|
||||
u16 = (u_int16_t *) &aligned;
|
||||
u32 = &aligned;
|
||||
|
||||
for (i = 0; options[i].code; i++)
|
||||
if (options[i].code == code) {
|
||||
length = option_lengths[options[i].flags & TYPE_MASK];
|
||||
for (i = 0; dhcp_options[i].code; i++)
|
||||
if (dhcp_options[i].code == code) {
|
||||
length = option_lengths[dhcp_options[i].flags & TYPE_MASK];
|
||||
}
|
||||
|
||||
if (!length) {
|
||||
|
@ -27,7 +27,7 @@ struct dhcp_option {
|
||||
unsigned char code;
|
||||
};
|
||||
|
||||
extern struct dhcp_option options[];
|
||||
extern struct dhcp_option dhcp_options[];
|
||||
extern int option_lengths[];
|
||||
|
||||
unsigned char *get_option(struct dhcpMessage *packet, int code);
|
||||
|
9
packet.c
9
packet.c
@ -15,9 +15,9 @@
|
||||
#include <errno.h>
|
||||
|
||||
#include "packet.h"
|
||||
#include "debug.h"
|
||||
#include "dhcpd.h"
|
||||
#include "options.h"
|
||||
#include "common.h"
|
||||
|
||||
|
||||
void init_header(struct dhcpMessage *packet, char type)
|
||||
@ -123,7 +123,7 @@ int raw_packet(struct dhcpMessage *payload, u_int32_t source_ip, int source_port
|
||||
struct udp_dhcp_packet packet;
|
||||
|
||||
if ((fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0) {
|
||||
DEBUG(LOG_ERR, "socket call failed: %s", strerror(errno));
|
||||
DEBUG(LOG_ERR, "socket call failed: %m");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -136,7 +136,7 @@ int raw_packet(struct dhcpMessage *payload, u_int32_t source_ip, int source_port
|
||||
dest.sll_halen = 6;
|
||||
memcpy(dest.sll_addr, dest_arp, 6);
|
||||
if (bind(fd, (struct sockaddr *)&dest, sizeof(struct sockaddr_ll)) < 0) {
|
||||
DEBUG(LOG_ERR, "bind call failed: %s", strerror(errno));
|
||||
DEBUG(LOG_ERR, "bind call failed: %m");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
@ -159,7 +159,7 @@ int raw_packet(struct dhcpMessage *payload, u_int32_t source_ip, int source_port
|
||||
|
||||
result = sendto(fd, &packet, sizeof(struct udp_dhcp_packet), 0, (struct sockaddr *) &dest, sizeof(dest));
|
||||
if (result <= 0) {
|
||||
DEBUG(LOG_ERR, "write on socket failed: %s", strerror(errno));
|
||||
DEBUG(LOG_ERR, "write on socket failed: %m");
|
||||
}
|
||||
close(fd);
|
||||
return result;
|
||||
@ -200,4 +200,3 @@ int kernel_packet(struct dhcpMessage *payload, u_int32_t source_ip, int source_p
|
||||
close(fd);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
30
pidfile.c
30
pidfile.c
@ -23,25 +23,35 @@
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "pidfile.h"
|
||||
#include "common.h"
|
||||
|
||||
int pidfile_acquire(char *pidfile)
|
||||
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 == NULL) return -1;
|
||||
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: %s\n",
|
||||
pidfile, strerror(errno));
|
||||
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;
|
||||
}
|
||||
|
||||
@ -61,9 +71,5 @@ void pidfile_write_release(int pid_fd)
|
||||
}
|
||||
|
||||
|
||||
void pidfile_delete(char *pidfile)
|
||||
{
|
||||
if (pidfile) unlink(pidfile);
|
||||
}
|
||||
|
||||
|
||||
|
@ -20,7 +20,6 @@
|
||||
*/
|
||||
|
||||
|
||||
int pidfile_acquire(char *pidfile);
|
||||
int pidfile_acquire(const char *pidfile);
|
||||
void pidfile_write_release(int pid_fd);
|
||||
void pidfile_delete(char *pidfile);
|
||||
|
||||
|
76
script.c
76
script.c
@ -28,17 +28,14 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "options.h"
|
||||
#include "dhcpd.h"
|
||||
#include "dhcpc.h"
|
||||
#include "packet.h"
|
||||
#include "options.h"
|
||||
#include "debug.h"
|
||||
#include "common.h"
|
||||
|
||||
/* get a rough idea of how long an option will be (rounding up...) */
|
||||
static int max_option_length[] = {
|
||||
static const int max_option_length[] = {
|
||||
[OPTION_IP] = sizeof("255.255.255.255 "),
|
||||
[OPTION_IP_PAIR] = sizeof("255.255.255.255 ") * 2,
|
||||
[OPTION_STRING] = 1,
|
||||
@ -51,10 +48,10 @@ static int max_option_length[] = {
|
||||
};
|
||||
|
||||
|
||||
static int upper_length(int length, struct dhcp_option *option)
|
||||
static inline int upper_length(int length, int opt_index)
|
||||
{
|
||||
return max_option_length[option->flags & TYPE_MASK] *
|
||||
(length / option_lengths[option->flags & TYPE_MASK]);
|
||||
return max_option_length[opt_index] *
|
||||
(length / option_lengths[opt_index]);
|
||||
}
|
||||
|
||||
|
||||
@ -135,20 +132,6 @@ static void fill_options(char *dest, unsigned char *option, struct dhcp_option *
|
||||
}
|
||||
|
||||
|
||||
static char *find_env(const char *prefix, char *defaultstr)
|
||||
{
|
||||
extern char **environ;
|
||||
char **ptr;
|
||||
const int len = strlen(prefix);
|
||||
|
||||
for (ptr = environ; *ptr != NULL; ptr++) {
|
||||
if (strncmp(prefix, *ptr, len) == 0)
|
||||
return *ptr;
|
||||
}
|
||||
return defaultstr;
|
||||
}
|
||||
|
||||
|
||||
/* put all the paramaters into an environment */
|
||||
static char **fill_envp(struct dhcpMessage *packet)
|
||||
{
|
||||
@ -162,43 +145,40 @@ static char **fill_envp(struct dhcpMessage *packet)
|
||||
if (packet == NULL)
|
||||
num_options = 0;
|
||||
else {
|
||||
for (i = 0; options[i].code; i++)
|
||||
if (get_option(packet, options[i].code))
|
||||
for (i = 0; dhcp_options[i].code; i++)
|
||||
if (get_option(packet, dhcp_options[i].code))
|
||||
num_options++;
|
||||
if (packet->siaddr) num_options++;
|
||||
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;
|
||||
envp[j++] = xmalloc(sizeof("interface=") + strlen(client_config.interface));
|
||||
sprintf(envp[0], "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++], "interface=%s", client_config.interface);
|
||||
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;
|
||||
|
||||
envp[j] = xmalloc(sizeof("ip=255.255.255.255"));
|
||||
sprintip(envp[j++], "ip=", (unsigned char *) &packet->yiaddr);
|
||||
|
||||
|
||||
for (i = 0; options[i].code; i++) {
|
||||
if (!(temp = get_option(packet, options[i].code)))
|
||||
for (i = 0; dhcp_options[i].code; i++) {
|
||||
if (!(temp = get_option(packet, dhcp_options[i].code)))
|
||||
continue;
|
||||
envp[j] = xmalloc(upper_length(temp[OPT_LEN - 2], &options[i]) + strlen(options[i].name) + 2);
|
||||
fill_options(envp[j++], temp, &options[i]);
|
||||
envp[j] = xmalloc(upper_length(temp[OPT_LEN - 2],
|
||||
dhcp_options[i].flags & TYPE_MASK) + strlen(dhcp_options[i].name) + 2);
|
||||
fill_options(envp[j++], temp, &dhcp_options[i]);
|
||||
|
||||
/* Fill in a subnet bits option for things like /24 */
|
||||
if (options[i].code == DHCP_SUBNET) {
|
||||
envp[j] = xmalloc(sizeof("mask=32"));
|
||||
if (dhcp_options[i].code == DHCP_SUBNET) {
|
||||
memcpy(&subnet, temp, 4);
|
||||
sprintf(envp[j++], "mask=%d", mton(&subnet));
|
||||
asprintf(&envp[j++], "mask=%d", mton(&subnet));
|
||||
}
|
||||
}
|
||||
if (packet->siaddr) {
|
||||
@ -208,16 +188,13 @@ static char **fill_envp(struct dhcpMessage *packet)
|
||||
if (!(over & FILE_FIELD) && packet->file[0]) {
|
||||
/* watch out for invalid packets */
|
||||
packet->file[sizeof(packet->file) - 1] = '\0';
|
||||
envp[j] = xmalloc(sizeof("boot_file=") + strlen(packet->file));
|
||||
sprintf(envp[j++], "boot_file=%s", packet->file);
|
||||
asprintf(&envp[j++], "boot_file=%s", packet->file);
|
||||
}
|
||||
if (!(over & SNAME_FIELD) && packet->sname[0]) {
|
||||
/* watch out for invalid packets */
|
||||
packet->sname[sizeof(packet->sname) - 1] = '\0';
|
||||
envp[j] = xmalloc(sizeof("sname=") + strlen(packet->sname));
|
||||
sprintf(envp[j++], "sname=%s", packet->sname);
|
||||
asprintf(&envp[j++], "sname=%s", packet->sname);
|
||||
}
|
||||
envp[j] = NULL;
|
||||
return envp;
|
||||
}
|
||||
|
||||
@ -232,7 +209,7 @@ void run_script(struct dhcpMessage *packet, const char *name)
|
||||
return;
|
||||
|
||||
/* call script */
|
||||
pid = fork();
|
||||
pid = vfork();
|
||||
if (pid) {
|
||||
waitpid(pid, NULL, 0);
|
||||
return;
|
||||
@ -242,11 +219,12 @@ void run_script(struct dhcpMessage *packet, const char *name)
|
||||
/* close fd's? */
|
||||
|
||||
/* exec script */
|
||||
#ifndef __uClinux__
|
||||
DEBUG(LOG_INFO, "execle'ing %s", client_config.script);
|
||||
#endif /* __uClinux__ */
|
||||
execle(client_config.script, client_config.script,
|
||||
name, NULL, envp);
|
||||
LOG(LOG_ERR, "script %s failed: %s",
|
||||
client_config.script, strerror(errno));
|
||||
LOG(LOG_ERR, "script %s failed: %m", client_config.script);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
@ -25,11 +25,10 @@
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "packet.h"
|
||||
#include "debug.h"
|
||||
#include "serverpacket.h"
|
||||
#include "dhcpd.h"
|
||||
#include "options.h"
|
||||
#include "leases.h"
|
||||
#include "common.h"
|
||||
|
||||
/* send a packet to giaddr using the kernel ip stack */
|
||||
static int send_packet_to_relay(struct dhcpMessage *payload)
|
||||
@ -258,6 +257,3 @@ int send_inform(struct dhcpMessage *oldpacket)
|
||||
|
||||
return send_packet(&packet, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef _SERVERPACKET_H
|
||||
#define _SERVERPACKET_H
|
||||
|
||||
#include "packet.h"
|
||||
|
||||
int sendOffer(struct dhcpMessage *oldpacket);
|
||||
int sendNAK(struct dhcpMessage *oldpacket);
|
||||
|
78
signalpipe.c
Normal file
78
signalpipe.c
Normal 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;
|
||||
}
|
22
signalpipe.h
Normal file
22
signalpipe.h
Normal 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);
|
41
socket.c
41
socket.c
@ -41,7 +41,8 @@
|
||||
#include <linux/if_ether.h>
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
#include "socket.h"
|
||||
#include "common.h"
|
||||
|
||||
int read_interface(char *interface, int *ifindex, u_int32_t *addr, unsigned char *arp)
|
||||
{
|
||||
@ -60,8 +61,7 @@ int read_interface(char *interface, int *ifindex, u_int32_t *addr, unsigned char
|
||||
*addr = our_ip->sin_addr.s_addr;
|
||||
DEBUG(LOG_INFO, "%s (our ip) = %s", ifr.ifr_name, inet_ntoa(our_ip->sin_addr));
|
||||
} else {
|
||||
LOG(LOG_ERR, "SIOCGIFADDR failed, is the interface up and configured?: %s",
|
||||
strerror(errno));
|
||||
LOG(LOG_ERR, "SIOCGIFADDR failed, is the interface up and configured?: %m");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -70,7 +70,7 @@ int read_interface(char *interface, int *ifindex, u_int32_t *addr, unsigned char
|
||||
DEBUG(LOG_INFO, "adapter index %d", ifr.ifr_ifindex);
|
||||
*ifindex = ifr.ifr_ifindex;
|
||||
} else {
|
||||
LOG(LOG_ERR, "SIOCGIFINDEX failed!: %s", strerror(errno));
|
||||
LOG(LOG_ERR, "SIOCGIFINDEX failed!: %m");
|
||||
return -1;
|
||||
}
|
||||
if (ioctl(fd, SIOCGIFHWADDR, &ifr) == 0) {
|
||||
@ -78,11 +78,11 @@ int read_interface(char *interface, int *ifindex, u_int32_t *addr, unsigned char
|
||||
DEBUG(LOG_INFO, "adapter hardware address %02x:%02x:%02x:%02x:%02x:%02x",
|
||||
arp[0], arp[1], arp[2], arp[3], arp[4], arp[5]);
|
||||
} else {
|
||||
LOG(LOG_ERR, "SIOCGIFHWADDR failed!: %s", strerror(errno));
|
||||
LOG(LOG_ERR, "SIOCGIFHWADDR failed!: %m");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
LOG(LOG_ERR, "socket failed!: %s", strerror(errno));
|
||||
LOG(LOG_ERR, "socket failed!: %m");
|
||||
return -1;
|
||||
}
|
||||
close(fd);
|
||||
@ -97,9 +97,9 @@ int listen_socket(unsigned int ip, int port, char *inf)
|
||||
struct sockaddr_in addr;
|
||||
int n = 1;
|
||||
|
||||
DEBUG(LOG_INFO, "Opening listen socket on 0x%08x:%d %s\n", ip, port, inf);
|
||||
DEBUG(LOG_INFO, "Opening listen socket on 0x%08x:%d %s", ip, port, inf);
|
||||
if ((fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
|
||||
DEBUG(LOG_ERR, "socket call failed: %s", strerror(errno));
|
||||
DEBUG(LOG_ERR, "socket call failed: %m");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -130,28 +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\n", ifindex);
|
||||
if ((fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0) {
|
||||
DEBUG(LOG_ERR, "socket call failed: %s", strerror(errno));
|
||||
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: %s", strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user