updates for 0.9.4

This commit is contained in:
Russ Dill 2001-08-27 21:23:45 +00:00
parent 94b1de2e09
commit b29c784729
15 changed files with 321 additions and 278 deletions

View File

@ -1,5 +1,10 @@
0.9.4 (pending)
0.9.4 (010827)
+ Force broadcast to broken clients that request unicast (ie, MSFT 98)
+ Make install rules (Adam J. Richter <adam@yggdrasil.com>)
+ One scripts, instead of many (Adam)
+ Removed script paramater info files (env vars only) (Adam)
+ Controlling of forking behavior in client (Adam)
+ General script.c/dhcpc.c cleanups (Adam)
0.9.3 (010820)
+ Increased debugging verbosity (me)

View File

@ -1,5 +1,11 @@
# udhcp makefile
prefix=/usr
SBINDIR=/sbin
USRSBINDIR=${prefix}/sbin
USRBINDIR=${prefix}/bin
USRSHAREDIR=${prefix}/share
# Uncomment this to get a shared binary. Call as udhcpd for the server,
# and udhcpc for the client
#COMBINED_BINARY=1
@ -8,13 +14,14 @@
#DEBUG=1
# Uncomment this to output messages to syslog, otherwise, messages go to stdout
#CFLAGS += -DSYSLOG
CFLAGS += -DSYSLOG
#CROSS_COMPILE=arm-uclibc-
CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)gcc
INSTALL = install
VER := 0.9.3
VER := 0.9.4
OBJS_SHARED = options.o socket.o packet.o
@ -36,6 +43,10 @@ endif
EXEC3 = dumpleases
OBJS3 = dumpleases.o
BOOT_PROGRAMS = udhcpc
DAEMONS = udhcpd
COMMANDS = dumpleases
ifdef SYSLOG
CFLAGS += -DSYSLOG
endif
@ -46,10 +57,14 @@ ifdef DEBUG
CFLAGS += -g -DDEBUG
else
CFLAGS += -Os -fomit-frame-pointer
STRIP=-s
endif
all: $(EXEC1) $(EXEC2) $(EXEC3)
$(OBJS1) $(OBJS2) $(OBJS3): *.h Makefile
$(EXEC1) $(EXEC2) $(EXEC3): Makefile
.c.o:
$(CC) -c $(CFLAGS) $<
@ -63,8 +78,21 @@ $(EXEC3): $(OBJS3)
$(LD) $(LDFLAGS) $(OBJS3) -o $(EXEC3)
install: all
$(INSTALL) $(STRIP) $(DAEMONS) $(USRSBINDIR)
$(INSTALL) $(STRIP) $(COMMANDS) $(USRBINDIR)
ifdef COMBINED_BINARY
ln -sf $(USRSBINDIR)/$(DAEMONS) $(SBINDIR)/$(BOOT_PROGRAMS)
else
$(INSTALL) $(STRIP) $(BOOT_PROGRAMS) $(SBINDIR)
endif
mkdir -p $(USRSHAREDIR)/udhcpc
for name in bound deconfig renew script ; do \
$(INSTALL) samples/sample.$$name \
$(USRSHAREDIR)/udhcpc/default.$$name ; \
done
clean:
-rm -f udhcpd udhcpc dumpleases *.o core
$(OBJS1) $(OBJS2) $(OBJS3): *.h Makefile
$(EXEC1) $(EXEC2) $(EXEC3): Makefile

48
README
View File

@ -1,11 +1,14 @@
Moreton Bay Server README
udhcp server/client package readme
-------------------------
The Moreton Bay DHCP Server is designed deliberately to be a small,
lean, DHCP server. It does however, strive to be a fully functional,
and compliant server.
The udhcp server/client package is primarily geared towards embedded
systems. It does however, strive to be fully functional, and RFC
compliant.
The Moreton Bay DHCP Server employs a number of simple config files:
udhcp server (udhcpd)
--------------------
The udhcp server employs a number of simple config files:
udhcpd.leased
------------
@ -62,30 +65,30 @@ options for the udhcp client are:
If the requested IP address cannot be obtained, the client accepts the
address that the server offers.
When an event occurs, udhcpc calls one one of the scripts. The scripts
aro by default contained in /etc/udhcpc/ but this can be changed via the
command line arguments. The three scripts that are called are:
When an event occurs, udhcpc calls the action script. The script by
default is /usr/share/udhcpc/default.script but this can be changed via
the command line arguments. The three possible arguments to the script
are:
<prefix>deconfig: This script is called when udhcpc starts, and
deconfig: This argument is used when udhcpc starts, and
when a leases is lost. The script should put the interface in an
up, but deconfigured state, ie: ifconfig $interface 0.0.0.0.
<prefix>bound: This script is called when udhcpc moves from an
bound: This argument is used when udhcpc moves from an
unbound, to a bound state. All of the paramaters are set in
enviromental variables, as well as written to a file,
<dir>/<prefix>info (ie, /etc/udhcpc/ext.info). This script should
configure the interface, and set any other relavent parameter
(default gateway, dns server, etc).
enviromental variables, The script should configure the interface,
and set any other relavent parameters (default gateway, dns server,
etc).
<prefix>renew: This script is called when a DHCP lease is renewed.
All of the paramaters are set in enviromental variables, as well
as written to the info file. This is called when the interface is
already configured, so the ip address will not change, however,
the other DHCP paramaters, such as the default gateway, subnet mask,
and dns server may change.
renew: This argument is used when a DHCP lease is renewed. All of
the paramaters are set in enviromental variables. This argument is
used when the interface is already configured, so the IP address,
will not change, however, the other DHCP paramaters, such as the
default gateway, subnet mask, and dns server may change.
The paramaters for the config file and enviromental variables are as follows:
The paramaters for enviromental variables are as follows:
$1 - What action the script should perform
interface - The interface this was obtained on
ip - The obtained IP
subnet - The assigend subnet mask
@ -144,6 +147,3 @@ dhcpd.h contains the other two compile time options:
Have fun!
-Moreton Bay DHCP Server development team.

3
TODO
View File

@ -1,11 +1,12 @@
TODO
----
+ Make sure get_raw_packet only accepts packets on the specified interface
+ FIXED: little/big endian issue probable cause for segmentation fault on i86 platform
+ N/A: makeiplist basic functionality works.. more user friendly interface required
+ REPLACED: browseiplist incomplete
+ better standard linux distro support
+ make config file a command line option
+ make forking a command line option
+ IMPLEMENTED: make forking a command line option
+ make sure packet generation works on a wide varitey of arches
+ Interoperability testing
+ Hooks within the DHCP server

View File

@ -8,7 +8,9 @@
#ifdef SYSLOG
# define LOG(level, str, args...) syslog(level, str, ## args)
# 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

213
dhcpc.c
View File

@ -22,6 +22,7 @@
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/file.h>
#include <unistd.h>
#include <getopt.h>
#include <stdlib.h>
@ -45,36 +46,55 @@
#include "debug.h"
static int state;
static unsigned long requested_ip = 0;
static unsigned long requested_ip; /* = 0 */
static unsigned long server_addr;
static unsigned long timeout;
static int packet_num = 0;
static int packet_num; /* = 0 */
static int pid_fd;
#define LISTEN_NONE 0
#define LISTEN_KERNEL 1
#define LISTEN_RAW 2
static int listen_mode = LISTEN_RAW;
struct client_config_t client_config;
#define DEFAULT_SCRIPT "/usr/share/udhcpc/default.script"
struct client_config_t client_config = {
/* Default options. */
abort_if_no_lease: 0,
foreground: 0,
interface: "eth0",
pidfile: NULL,
script: DEFAULT_SCRIPT,
clientid: NULL,
hostname: NULL,
ifindex: 0,
arp: "\0\0\0\0\0\0", /* appease gcc-3.0 */
};
static void print_usage(void)
{
printf("Usage: udhcpcd [OPTIONS]\n\n");
printf(" -d, --dir=PATH Path containing DHCP client scripts (default: /etc/udhcpc/)\n");
printf(" -p, --prefix=PREFIX Prefix to add to scripts (default: none)\n");
printf(" -i, --interface=INTERFACE Interface to use (default: eth0)\n");
printf(" -r, --request=IP IP address to request (default: none)\n");
printf(" -c, --clientid=CLIENTID Client identifier\n");
printf(" -H, --hostname=HOSTNAME Client hostname\n");
printf(" -v, --version Display version\n");
printf(
"Usage: udhcpcd [OPTIONS]\n\n"
" -c, --clientid=CLIENTID Client identifier\n"
" -H, --hostname=HOSTNAME Client hostname\n"
" -f, --foreground Do not fork after getting lease\n"
" -i, --interface=INTERFACE Interface to use (default: eth0)\n"
" -n, --now Exit with failure if lease cannot be\n"
" immediately negotiated.\n"
" -p, --pidfile=file Store process ID of daemon in file\n"
" -r, --request=IP IP address to request (default: none)\n"
" -s, --script=file Run file at dhcp events (default:\n"
" " DEFAULT_SCRIPT ")\n"
" -v, --version Display version\n"
);
}
/* SIGUSR1 handler (renew) */
static void renew_requested(int pid)
static void renew_requested(int sig)
{
pid = 0;
sig = 0;
LOG(LOG_INFO, "Received SIGUSR1");
if (state == BOUND || state == RENEWING || state == REBINDING ||
state == RELEASED) {
@ -95,14 +115,14 @@ static void renew_requested(int pid)
/* SIGUSR2 handler (release) */
static void release_requested(int pid)
static void release_requested(int sig)
{
pid = 0;
sig = 0;
LOG(LOG_INFO, "Received SIGUSR2");
/* send release packet */
if (state == BOUND || state == RENEWING || state == REBINDING) {
send_release(server_addr, requested_ip); /* unicast */
script_deconfig();
run_script(NULL, "deconfig");
}
listen_mode = 0;
@ -110,6 +130,61 @@ static void release_requested(int pid)
timeout = 0xffffffff;
}
static void pidfile_acquire(void)
{
if (client_config.pidfile == NULL) return;
pid_fd = open(client_config.pidfile, O_CREAT | O_WRONLY, 0644);
if (pid_fd < 0) {
LOG(LOG_ERR, "Unable to open pidfile %s: %s\n",
client_config.pidfile, strerror(errno));
} else {
lockf(pid_fd, F_LOCK, 0);
}
}
static void pidfile_write_release(void)
{
FILE *out;
if (client_config.pidfile == NULL || 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);
}
static void background(void)
{
if (!client_config.foreground) {
pidfile_acquire(); /* hold lock during fork. */
switch(fork()) {
case -1:
perror("fork");
exit(1);
/*NOTREACHED*/
case 0:
break; /* child continues */
default:
exit(0); /* parent exits */
/*NOTREACHED*/
}
close(0);
close(1);
close(2);
setsid();
client_config.foreground = 1; /* Do not fork again. */
pidfile_write_release();
}
}
#ifdef COMBINED_BINARY
int udhcpc(int argc, char *argv[])
#else
@ -128,49 +203,26 @@ int main(int argc, char *argv[])
struct in_addr temp_addr;
static struct option options[] = {
{"dir", 1, 0, 'd'},
{"prefix", 1, 0, 'p'},
{"interface", 1, 0, 'i'},
{"request", 1, 0, 'r'},
{"clientid", 1, 0, 'c'},
{"hostname", 1, 0, 'H'},
{"version", 0, 0, 'v'},
{"help", 0, 0, 'h'},
{"clientid", required_argument, 0, 'c'},
{"foreground", no_argument, 0, 'f'},
{"hostname", required_argument, 0, 'H'},
{"help", no_argument, 0, 'h'},
{"interface", required_argument, 0, 'i'},
{"now", no_argument, 0, 'n'},
{"pidfile", required_argument, 0, 'p'},
{"request", required_argument, 0, 'r'},
{"script", required_argument, 0, 's'},
{"version", no_argument, 0, 'v'},
{0, 0, 0, 0}
};
/* default options */
client_config.dir = strdup("/etc/udhcpc/");
client_config.prefix = strdup("");
strcpy(client_config.interface, "eth0");
client_config.clientid = NULL;
/* get options */
while (1) {
int option_index = 0;
c = getopt_long(argc, argv, "d:p:i:r:c:H:vh", options, &option_index);
c = getopt_long(argc, argv, "c:fH:hi:np:r:s:v", options, &option_index);
if (c == -1) break;
switch (c) {
case 'd':
if (client_config.dir) free(client_config.dir);
client_config.dir = malloc(strlen(optarg + 2));
strcpy(client_config.dir, optarg);
if (optarg[strlen(optarg) - 1] != '/')
strcat(client_config.dir, "/");
break;
case 'p':
if (client_config.prefix) free(client_config.prefix);
client_config.prefix = strdup(optarg);
break;
case 'i':
strncpy(client_config.interface, optarg, 10);
client_config.interface[9] = '\0';
break;
case 'r':
requested_ip = inet_addr(optarg);
break;
case 'c':
len = strlen(optarg) > 255 ? 255 : strlen(optarg);
if (client_config.clientid) free(client_config.clientid);
@ -179,6 +231,9 @@ int main(int argc, char *argv[])
client_config.clientid[OPT_LEN] = len;
strncpy(client_config.clientid + 2, optarg, len);
break;
case 'f':
client_config.foreground = 1;
break;
case 'H':
len = strlen(optarg) > 255 ? 255 : strlen(optarg);
if (client_config.hostname) free(client_config.hostname);
@ -187,14 +242,36 @@ int main(int argc, char *argv[])
client_config.hostname[OPT_LEN] = len;
strncpy(client_config.hostname + 2, optarg, len);
break;
case 'v': printf("udhcpcd, version %s\n\n", VERSION); break;
case 'h': print_usage(); return 0;
case 'h':
print_usage();
return 0;
case 'i':
client_config.interface = optarg;
break;
case 'n':
client_config.abort_if_no_lease = 1;
break;
case 'p':
client_config.pidfile = optarg;
break;
case 'r':
requested_ip = inet_addr(optarg);
break;
case 's':
client_config.script = optarg;
break;
case 'v':
printf("udhcpcd, version %s\n\n", VERSION);
break;
}
}
OPEN_LOG("udhcpc");
LOG(LOG_INFO, "Moreton Bay DHCP Client (v%s) started", VERSION);
pidfile_acquire();
pidfile_write_release();
if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) >= 0) {
strcpy(ifr.ifr_name, client_config.interface);
if (ioctl(fd, SIOCGIFINDEX, &ifr) == 0) {
@ -225,15 +302,7 @@ int main(int argc, char *argv[])
signal(SIGUSR2, release_requested);
state = INIT_SELECTING;
script_deconfig();
#ifndef DEBUGGING
if (fork()) return 0;
else {
close(0);
setsid();
}
#endif
run_script(NULL, "deconfig");
for (;;) {
if (fd > 0) {
@ -276,6 +345,11 @@ int main(int argc, char *argv[])
timeout = time(0) + ((packet_num == 2) ? 10 : 2);
packet_num++;
} else {
if (client_config.abort_if_no_lease) {
LOG(LOG_INFO,
"No lease, failing.");
exit(1);
}
/* wait to try again */
packet_num = 0;
timeout = time(0) + 60;
@ -327,7 +401,7 @@ int main(int argc, char *argv[])
/* timed out, enter init state */
state = INIT_SELECTING;
LOG(LOG_INFO, "Lease lost, entering init state");
script_deconfig();
run_script(NULL, "deconfig");
timeout = time(0);
packet_num = 0;
listen_mode = LISTEN_RAW;
@ -406,17 +480,18 @@ int main(int argc, char *argv[])
start = time(0);
timeout = t1 + start;
requested_ip = packet.yiaddr;
if (state == RENEWING || state == REBINDING)
script_renew(&packet);
else script_bound(&packet);
run_script(&packet,
((state == RENEWING || state == REBINDING) ? "renew" : "bound"));
state = BOUND;
listen_mode = LISTEN_NONE;
background();
} else if (*message == DHCPNAK) {
/* return to init state */
LOG(LOG_INFO, "Received DHCP NAK");
if (state != REQUESTING) script_deconfig();
if (state != REQUESTING)
run_script(NULL, "deconfig");
state = INIT_SELECTING;
timeout = time(0);
requested_ip = 0;

View File

@ -24,9 +24,11 @@
struct client_config_t {
char *dir; /* Path containing DHCP client scripts */
char *prefix; /* Prefix to add to scripts */
char interface[10]; /* The name of the interface to use */
char foreground; /* Do not fork */
char abort_if_no_lease; /* Abort if no lease */
char *interface; /* The name of the interface to use */
char *pidfile; /* Optionally store the process ID */
char *script; /* User script to run at dhcp events */
char *clientid; /* Optional client id to use */
char *hostname; /* Optional hostname to use */
int ifindex; /* Index number of the interface to use */

View File

@ -5,6 +5,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "debug.h"
#include "dhcpd.h"

View File

@ -5,15 +5,18 @@
#include "packet.h"
#define TYPE_MASK 0x0F
#define OPTION_IP 0x01
#define OPTION_IP_PAIR 0x02
#define OPTION_STRING 0x03
#define OPTION_BOOLEAN 0x04
#define OPTION_U8 0x05
#define OPTION_U16 0x06
#define OPTION_S16 0x07
#define OPTION_U32 0x08
#define OPTION_S32 0x09
enum {
OPTION_IP=1,
OPTION_IP_PAIR,
OPTION_STRING,
OPTION_BOOLEAN,
OPTION_U8,
OPTION_U16,
OPTION_S16,
OPTION_U32,
OPTION_S32
};
#define OPTION_LIST 0x80
@ -33,4 +36,4 @@ int add_simple_option(unsigned char *optionptr, unsigned char code, u_int32_t da
struct option_set *find_option(struct option_set *opt_list, char code);
void attach_option(struct option_set **opt_list, struct dhcp_option *option, char *buffer, int length);
#endif
#endif

View File

@ -2,10 +2,8 @@ The files in this dir are:
udhcpd.conf: A sample udhpcd configuration file.
sample.script
sample.deconfig
sample.bound
sample.renew : sample scripts for the udhcpc client, to use
them, invoke udhcpc with: "udhcpc -p sample."
and copy the files to /etc/udhcpc/
sample.info: A sample paramater file generated by udhcpc
sample.renew : sample scripts for the udhcpc client.

View File

@ -1,7 +1,7 @@
#!/bin/sh
# Sample udhcpc renew script
RESOLV_CONF="/etc/udhcpc/resolv.conf"
RESOLV_CONF="/etc/resolv.conf"
[ -n "$broadcast" ] && BROADCAST="broadcast $broadcast"
[ -n "$subnet" ] && NETMASK="netmask $subnet"

View File

@ -1,9 +0,0 @@
interface eth0
ip 192.168.10.22
subnet 255.255.255.0
router 192.168.10.2
dns 192.168.10.2 192.168.10.10
wins 192.168.10.10
lease 36000
dhcptype 5
serverid 192.168.10.11

7
samples/sample.script Normal file
View File

@ -0,0 +1,7 @@
#!/bin/sh
# Currently, we only dispatch according to command. However, a more
# elaborate system might dispatch by command and interface or do some
# common initialization first, especially if more dhcp event notifications
# are added.
exec /usr/share/udhcpc/default.$1

224
script.c
View File

@ -45,28 +45,28 @@ static int max_option_length(char *option, struct dhcp_option *type)
switch (type->flags & TYPE_MASK) {
case OPTION_IP:
case OPTION_IP_PAIR:
size = (option[OPT_LEN - 2] / 4) * strlen("255.255.255.255 ");
size = (option[OPT_LEN - 2] / 4) * sizeof("255.255.255.255 ");
break;
case OPTION_STRING:
size = option[OPT_LEN - 2] + 1;
break;
case OPTION_BOOLEAN:
size = option[OPT_LEN - 2] * strlen("yes ");
size = option[OPT_LEN - 2] * sizeof("yes ");
break;
case OPTION_U8:
size = option[OPT_LEN - 2] * strlen("255 ");
size = option[OPT_LEN - 2] * sizeof("255 ");
break;
case OPTION_U16:
size = (option[OPT_LEN - 2] / 2) * strlen("65535 ");
size = (option[OPT_LEN - 2] / 2) * sizeof("65535 ");
break;
case OPTION_S16:
size = (option[OPT_LEN - 2] / 2) * strlen("-32768 ");
size = (option[OPT_LEN - 2] / 2) * sizeof("-32768 ");
break;
case OPTION_U32:
size = (option[OPT_LEN - 2] / 4) * strlen("4294967295 ");
size = (option[OPT_LEN - 2] / 4) * sizeof("4294967295 ");
break;
case OPTION_S32:
size = (option[OPT_LEN - 2] / 4) * strlen("-2147483684 ");
size = (option[OPT_LEN - 2] / 4) * sizeof("-2147483684 ");
break;
}
@ -74,126 +74,105 @@ static int max_option_length(char *option, struct dhcp_option *type)
}
/* Fill dest with the text of option 'option' */
static void fill_options(char *dest, char *option, struct dhcp_option *type)
/* Fill dest with the text of option 'option'. */
static void fill_options(char *dest, unsigned char *option, struct dhcp_option *type_p)
{
int pos;
int type, optlen;
u_int16_t val_u16;
int16_t val_s16;
u_int32_t val_u32;
int32_t val_s32;
struct in_addr in;
if ((type->flags & TYPE_MASK) == OPTION_STRING) {
strncpy(dest, option, option[OPT_LEN - 2]);
dest[(int) option[OPT_LEN - 2]] = '\0';
return;
}
dest[0] = '\0';
for (pos = 0; pos < option[OPT_LEN - 2]; pos += option_lengths[type->flags & TYPE_MASK]) {
if (pos) strcat(dest, " ");
switch (type->flags & TYPE_MASK) {
case OPTION_IP:
memcpy(&in.s_addr, option + pos, 4);
strcat(dest, inet_ntoa(in));
break;
int len = option[OPT_LEN - 2];
dest += sprintf(dest, "%s=", type_p->name);
type = type_p->flags & TYPE_MASK;
optlen = option_lengths[type];
for(;;) {
switch (type) {
case OPTION_IP: /* Works regardless of host byte order. */
dest += sprintf(dest, "%d.%d.%d.%d",
option[0], option[1],
option[2], option[3]);
break;
case OPTION_IP_PAIR:
memcpy(&in.s_addr, option + pos, 4);
strcat(dest, inet_ntoa(in));
memcpy(&in.s_addr, option + pos + 4, 4);
strcat(dest, inet_ntoa(in));
dest += sprintf(dest, "%d.%d.%d.%d, %d.%d.%d.%d",
option[0], option[1],
option[2], option[3],
option[4], option[5],
option[6], option[7]);
break;
case OPTION_BOOLEAN:
strcat(dest, option[pos] ? "yes" : "no");
dest += sprintf(dest, *option ? "yes" : "no");
break;
case OPTION_U8:
sprintf(dest + strlen(dest), "%u", option[pos]);
dest += sprintf(dest, "%u", *option);
break;
case OPTION_U16:
memcpy(&val_u16, option + pos, 2);
sprintf(dest + strlen(dest), "%u", ntohs(val_u16));
memcpy(&val_u16, option, 2);
dest += sprintf(dest, "%u", ntohs(val_u16));
break;
case OPTION_S16:
memcpy(&val_s16, option + pos, 2);
sprintf(dest + strlen(dest), "%d", ntohs(val_s16));
memcpy(&val_s16, option, 2);
dest += sprintf(dest, "%d", ntohs(val_s16));
break;
case OPTION_U32:
memcpy(&val_u32, option + pos, 4);
sprintf(dest + strlen(dest), "%lu", (unsigned long) ntohl(val_u32));
memcpy(&val_u32, option, 4);
dest += sprintf(dest, "%lu", (unsigned long) ntohl(val_u32));
break;
case OPTION_S32:
memcpy(&val_s32, option + pos, 4);
sprintf(dest + strlen(dest), "%ld", (long) ntohl(val_s32));
memcpy(&val_s32, option, 4);
dest += sprintf(dest, "%ld", (long) ntohl(val_s32));
break;
case OPTION_STRING:
memcpy(dest, option, len);
dest[len] = '\0';
return; /* Short circuit this case */
}
option += optlen;
len -= optlen;
if (len <= 0) break;
*(dest++) = ' ';
}
}
/* write out the paramaters to a file */
static void write_pars(struct dhcpMessage *packet)
{
char file[strlen(client_config.dir) +
(client_config.prefix ? strlen(client_config.prefix) : 0) +
strlen("info") + 1];
int i;
char *temp, *buff;
FILE *fp;
struct in_addr addr;
strcpy(file, client_config.dir);
if (client_config.prefix) strcat(file, client_config.prefix);
strcat(file, "info");
if (!(fp = fopen(file, "w"))) {
LOG(LOG_ERR, "Could not open %s for writing", file);
return;
}
fprintf(fp, "interface %s\n", client_config.interface);
addr.s_addr = packet->yiaddr;
fprintf(fp, "ip %s\n", inet_ntoa(addr));
for (i = 0; options[i].code; i++) {
if ((temp = get_option(packet, options[i].code))) {
buff = malloc(max_option_length(temp, &options[i]));
fill_options(buff, temp, &options[i]);
fprintf(fp, "%s %s\n", options[i].name, buff);
free(buff);
}
}
fclose(fp);
}
/* put all the paramaters into an environment */
static char **fill_envp(struct dhcpMessage *packet)
{
int num_options = 0;
int i, j;
struct in_addr addr;
unsigned char *addr;
char **envp, *temp;
for (i = 0; options[i].code; i++)
if (get_option(packet, options[i].code))
num_options++;
if (packet == NULL)
num_options = 0;
else {
for (i = 0; options[i].code; i++)
if (get_option(packet, options[i].code))
num_options++;
}
envp = malloc((num_options + 3) * sizeof(char *));
envp = malloc((num_options + 5) * sizeof(char *));
envp[0] = malloc(strlen("interface=") + strlen(client_config.interface) + 1);
sprintf(envp[0], "interface=%s", client_config.interface);
addr.s_addr = packet->yiaddr;
envp[1] = malloc(strlen("ip=255.255.255.255"));
sprintf(envp[1], "ip=%s", inet_ntoa(addr));
for (i = 0, j = 2; options[i].code; i++) {
envp[2] = getenv("PATH") ? getenv("PATH") : "PATH=/bin:/usr/bin:/sbin:/usr/sbin";
envp[3] = getenv("HOME") ? getenv("HOME") : "HOME=/";
if (packet == NULL) {
envp[4] = NULL;
return envp;
}
addr = (unsigned char*) &packet->yiaddr;
sprintf (envp[1], "ip=%d.%d.%d.%d",
addr[0], addr[1], addr[2], addr[3]);
for (i = 0, j = 4; options[i].code; i++) {
if ((temp = get_option(packet, options[i].code))) {
envp[j] = malloc(max_option_length(temp, &options[i]) +
strlen(options[i].name + 1));
strcpy(envp[j], options[i].name);
strcat(envp[j], "=");
fill_options(envp[j] + strlen(envp[j]), temp, &options[i]);
strlen(options[i].name) + 2);
fill_options(envp[j], temp, &options[i]);
j++;
}
}
@ -202,47 +181,17 @@ static char **fill_envp(struct dhcpMessage *packet)
}
/* Call the deconfic script */
void script_deconfig(void)
{
int pid;
char **envp;
char file[255 + 5];
/* call script */
pid = fork();
if (pid) {
waitpid(pid, NULL, 0);
return;
} else if (pid == 0) {
envp = malloc(sizeof(char *) * 2);
envp[0] = malloc(strlen("interface=") + strlen(client_config.interface) + 1);
sprintf(envp[0], "interface=%s", client_config.interface);
envp[1] = NULL;
/* close fd's? */
/* exec script */
sprintf(file, "%s%sdeconfig", client_config.dir, client_config.prefix);
DEBUG(LOG_INFO, "execle'ing %s", file);
execle(file, "deconfig", NULL, envp);
LOG(LOG_ERR, "script %s failed: %s", file, sys_errlist[errno]);
exit(0);
}
}
/* Call a script with a par file and env vars */
static void par_script(struct dhcpMessage *packet, char *name)
void run_script(struct dhcpMessage *packet, const char *name)
{
int pid;
char **envp;
char file[255 + 5];
write_pars(packet);
if (client_config.script == NULL)
return;
/* call script */
pid = fork();
pid = fork();
if (pid) {
waitpid(pid, NULL, 0);
return;
@ -252,26 +201,11 @@ static void par_script(struct dhcpMessage *packet, char *name)
/* close fd's? */
/* exec script */
sprintf(file, "%s%s%s", client_config.dir, client_config.prefix, name);
DEBUG(LOG_INFO, "execle'ing %s", file);
execle(file, name, NULL, envp);
LOG(LOG_ERR, "script %s failed: %s", file, sys_errlist[errno]);
exit(0);
DEBUG(LOG_INFO, "execle'ing %s", client_config.script);
execle(client_config.script, client_config.script,
name, NULL, envp);
LOG(LOG_ERR, "script %s failed: %s",
client_config.script, strerror(errno));
exit(1);
}
}
/* call the renew script */
void script_renew(struct dhcpMessage *packet)
{
par_script(packet, "renew");
}
/* call the bound script */
void script_bound(struct dhcpMessage *packet)
{
par_script(packet, "bound");
}

View File

@ -1,10 +1,6 @@
#ifndef _SCRIPT_H
#define _SCRIPT_H
void script_deconfig(void);
void script_renew(struct dhcpMessage *packet);
void script_bound(struct dhcpMessage *packet);
void run_script(struct dhcpMessage *packet, const char *name);
#endif