[BusyBox] udhcpc troubles
Ilguiz Latypov
ilatypov at superbt.com
Tue Jul 16 08:56:03 UTC 2002
Please ignore the rest if your embedded platform's CPU has MMU.
I didn't have a chance to try udhcp client/server application or
user/dhcpcd module from uClinux distribution. I managed to get the
non-embedded client dhcpcd work by hacking its code.
I changed the code to emulate the daemon mode by automatic restart of the
executable file. This is a dangerous technique as the data segment will
not be the same in two processes. With dhcpcd this was luckily
circumvented because the code implements a state machine.
If you want to try dhcpcd, download it from
http://www.phystech.com/download/, apply the attached patch and run
aclocal && automake && autoconf
./configure --host=YOUR_TARGET_HOST_STRING \
--build=i686-pc-linux-gnu --with-kernel=YOUR_KERNEL
make
Ilguiz
On Tue, 16 Jul 2002, Michael Hauser wrote:
> If i start the client the first client process terminates and a second
> client process starts immimmediately.
========================================================================
Index: client.c
===================================================================
RCS file: /usr/local/cvsroot/user/dhcpcd/client.c,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -u -r1.1.1.1 -r1.3
--- client.c 14 Apr 2002 07:07:20 -0000 1.1.1.1
+++ client.c 21 Apr 2002 04:57:16 -0000 1.3
@@ -49,6 +49,7 @@
#include "buildmsg.h"
#include "udpipgen.h"
#include "pathnames.h"
+#include "config.h"
#include <linux/version.h>
@@ -148,10 +149,10 @@
{
DhcpOptions.len[*p] = p[1];
if ( DhcpOptions.val[*p] )
- free(DhcpOptions.val[*p]);
+ xfree(DhcpOptions.val[*p]);
else
DhcpOptions.num++;
- DhcpOptions.val[*p] = malloc(p[1]+1);
+ DhcpOptions.val[*p] = xmalloc(p[1]+1);
memset(DhcpOptions.val[*p],0,p[1]+1);
memcpy(DhcpOptions.val[*p],p+2,p[1]);
}
@@ -233,7 +234,7 @@
if ( ! DhcpMsgRecv->yiaddr ) DhcpMsgRecv->yiaddr=DhcpMsgSend->ciaddr;
if ( ! DhcpOptions.val[dhcpServerIdentifier] ) /* did not get dhcpServerIdentifier */
{ /* make it the same as IP address of the sender */
- DhcpOptions.val[dhcpServerIdentifier] = malloc(4);
+ DhcpOptions.val[dhcpServerIdentifier] = xmalloc(4);
memcpy(DhcpOptions.val[dhcpServerIdentifier],&ipRecv->ip_src.s_addr,4);
DhcpOptions.len[dhcpServerIdentifier] = 4;
DhcpOptions.num++;
@@ -247,7 +248,7 @@
}
if ( ! DhcpOptions.val[dns] ) /* did not get DNS */
{ /* make it the same as dhcpServerIdentifier */
- DhcpOptions.val[dns] = malloc(4);
+ DhcpOptions.val[dns] = xmalloc(4);
memcpy(DhcpOptions.val[dns],DhcpOptions.val[dhcpServerIdentifier],4);
DhcpOptions.len[dns] = 4;
DhcpOptions.num++;
@@ -261,7 +262,7 @@
}
if ( ! DhcpOptions.val[subnetMask] ) /* did not get subnetMask */
{
- DhcpOptions.val[subnetMask] = malloc(4);
+ DhcpOptions.val[subnetMask] = xmalloc(4);
((unsigned char *)DhcpOptions.val[subnetMask])[0] = 255;
if ( ((unsigned char *)&DhcpMsgRecv->yiaddr)[0] < 128 )
{
@@ -290,7 +291,7 @@
if ( ! DhcpOptions.val[broadcastAddr] ) /* did not get broadcastAddr */
{
int br = DhcpMsgRecv->yiaddr | ~*((int *)DhcpOptions.val[subnetMask]);
- DhcpOptions.val[broadcastAddr] = malloc(4);
+ DhcpOptions.val[broadcastAddr] = xmalloc(4);
memcpy(DhcpOptions.val[broadcastAddr],&br,4);
DhcpOptions.len[broadcastAddr] = 4;
DhcpOptions.num++;
@@ -305,7 +306,7 @@
#if 0
if ( ! DhcpOptions.val[routersOnSubnet] )
{
- DhcpOptions.val[routersOnSubnet] = malloc(4);
+ DhcpOptions.val[routersOnSubnet] = xmalloc(4);
if ( DhcpMsgRecv->giaddr )
memcpy(DhcpOptions.val[routersOnSubnet],&DhcpMsgRecv->giaddr,4);
else
@@ -332,7 +333,7 @@
}
else /* did not get dhcpIPaddrLeaseTime */
{
- DhcpOptions.val[dhcpIPaddrLeaseTime] = malloc(4);
+ DhcpOptions.val[dhcpIPaddrLeaseTime] = xmalloc(4);
memcpy(DhcpOptions.val[dhcpIPaddrLeaseTime],&nleaseTime,4);
DhcpOptions.len[dhcpIPaddrLeaseTime] = 4;
DhcpOptions.num++;
@@ -355,7 +356,7 @@
{
unsigned t2 = 0.5*ntohl(*(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime]);
int t1 = htonl(t2);
- DhcpOptions.val[dhcpT1value] = malloc(4);
+ DhcpOptions.val[dhcpT1value] = xmalloc(4);
memcpy(DhcpOptions.val[dhcpT1value],&t1,4);
DhcpOptions.len[dhcpT1value] = 4;
DhcpOptions.num++;
@@ -378,7 +379,7 @@
{
unsigned t2 = 0.875*ntohl(*(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime]);
int t1 = htonl(t2);
- DhcpOptions.val[dhcpT2value] = malloc(4);
+ DhcpOptions.val[dhcpT2value] = xmalloc(4);
memcpy(DhcpOptions.val[dhcpT2value],&t1,4);
DhcpOptions.len[dhcpT2value] = 4;
DhcpOptions.num++;
@@ -911,7 +912,7 @@
#endif
dname++;
dname_len=dname-hp->h_name;
- DhcpOptions.val[hostName]=(char *)malloc(dname_len+1);
+ DhcpOptions.val[hostName]=(char *)xmalloc(dname_len+1);
DhcpOptions.len[hostName]=dname_len;
memcpy((char *)DhcpOptions.val[hostName],
hp->h_name,dname_len);
@@ -972,7 +973,7 @@
dname_len=strlen(dname);
if ( dname_len )
{
- DhcpOptions.val[domainName]=(char *)malloc(dname_len+1);
+ DhcpOptions.val[domainName]=(char *)xmalloc(dname_len+1);
DhcpOptions.len[domainName]=dname_len;
memcpy((char *)DhcpOptions.val[domainName],
dname,dname_len);
Index: configure.in
===================================================================
RCS file: /usr/local/cvsroot/user/dhcpcd/configure.in,v
retrieving revision 1.1.1.1
retrieving revision 1.4
diff -u -r1.1.1.1 -r1.4
--- configure.in 14 Apr 2002 07:07:20 -0000 1.1.1.1
+++ configure.in 21 May 2002 16:24:21 -0000 1.4
@@ -1,10 +1,11 @@
dnl Process this file with autoconf to produce a configure script.
-AC_INIT(peekfd.c)
+AC_INIT(dhcpcd, 1.3.22)
+AM_CONFIG_HEADER(config.h)
dnl
dnl Version
dnl
-DHCPCD_VERSION=1.3.22
+DHCPCD_VERSION="$PACKAGE_VERSION"
AC_SUBST(DHCPCD_VERSION)
dnl
@@ -47,7 +48,7 @@
;;
esac
-LDFLAGS="-s -O2"
+LDFLAGS="$LDFLAGS -s -O2"
dnl
dnl Checks for programs.
@@ -78,5 +79,50 @@
AC_PROG_GCC_TRADITIONAL
AC_FUNC_MEMCMP
AC_CHECK_FUNCS(select socket uname)
+
+dnl uClinux has only a stub fork() which calls vfork(). This fact
+dnl is not reflected in autoconf-2.53.
+AC_DEFUN([AC_FORK_IS_A_STUB_IN_UCLINUX],
+[AC_BEFORE([$0], [AC_FUNC_FORK])dnl
+case $host in
+ (*-uClinux | *-uclinux)
+ ac_cv_func_fork=no
+ AC_MSG_NOTICE([uClinux has only a stub fork() that calls vfork()])
+ AC_DEFINE(HAVE_VFORK, 1,
+ [indicates that the vfork() call is available])dnl
+ AC_DEFINE(HAVE_WORKING_VFORK, 1,
+ [indicates that the vfork() call works as expected])dnl
+ ;;
+ (*)
+ # Check for presence of fork() and vfork() in the C library
+ # and define HAVE_FORK and HAVE_VFORK accordingly.
+ # Also, run tests if compiling native code or make assumptions
+ # to determine if fork() and vfork() work when they exist.
+ # Set or unset HAVE_WORKING_FORK and HAVE_WORKING_VFORK.
+ AC_FUNC_FORK[]dnl
+ ;;
+esac
+])# AC_FORK_IS_A_STUB_IN_UCLINUX
+AC_FORK_IS_A_STUB_IN_UCLINUX
+
+AH_BOTTOM([
+#ifdef HAVE_WORKING_FORK
+
+/* fork() exists and works */
+# define FINISHVOID(code) _exit(code)
+# define FINISH(code) _exit(code)
+
+#elif defined(HAVE_WORKING_VFORK)
+
+# define fork vfork
+# define FINISHVOID(code) return
+# define FINISH(code) return (!code)
+
+#else
+
+# error fork() or vfork() are not found in the standard C library \
+ or are not working or are assumed to not work on the target \
+ platform.
+#endif])
AC_OUTPUT([Makefile dhcpcd.spec])
Index: dhcpcd.c
===================================================================
RCS file: /usr/local/cvsroot/user/dhcpcd/dhcpcd.c,v
retrieving revision 1.1.1.1
retrieving revision 1.7
diff -u -r1.1.1.1 -r1.7
--- dhcpcd.c 14 Apr 2002 07:07:20 -0000 1.1.1.1
+++ dhcpcd.c 22 Apr 2002 23:31:48 -0000 1.7
@@ -32,10 +32,31 @@
#include <arpa/inet.h>
#include <errno.h>
#include <ctype.h>
+#include "config.h"
#include "pathnames.h"
#include "client.h"
#include "signals.h"
+/* #define DEBUG_EXEC 1 */
+
+#if DEBUG_EXEC - 0
+# include <stdio.h>
+# define DEBUG_LOG(fmt, args...) do { \
+ char c; \
+ fprintf(stderr, "%s (%d): " fmt, \
+ __FUNCTION__, __LINE__ , ##args); \
+ read(0, &c, 1); \
+ } while (0)
+# define D(x) x
+
+#else
+
+# define DEBUG_LOG(fmt, args...) do { } while (0)
+# define D(x)
+#endif
+
+#define DEBUG_MARK() DEBUG_LOG("debug mark")
+
struct in_addr inform_ipaddr;
char *ProgramName = NULL;
char **ProgramEnviron= NULL;
@@ -91,6 +112,12 @@
int s = 1;
int k = 1;
int i = 1;
+#ifndef HAVE_WORKING_FORK
+ int spawned = 0;
+# define ISSPAWNED ( spawned )
+#else
+# define ISSPAWNED ( 0 )
+#endif /* !HAVE_WORKING_FORK */
if ( getuid() )
{
@@ -108,7 +135,7 @@
break;
case 'k':
s++;
- killFlag=SIGHUP;
+ killFlag=SIGTERM;
goto prgs;
case 'n':
s++;
@@ -272,6 +299,12 @@
s++;
TestCase=1;
goto prgs;
+#ifndef HAVE_WORKING_FORK
+ case 'f':
+ s++;
+ spawned=1;
+ goto prgs;
+#endif /* !HAVE_WORKING_FORK */
case 'l':
if ( argc[i][s+1] ) goto usage;
i++;
@@ -301,7 +334,7 @@
while ( IfNameExt[s] )
if ( IfNameExt[s] == ':' )
{
- IfName=(char *)malloc(s+1);
+ IfName=(char *)xmalloc(s+1);
memcpy(IfName,IfNameExt,s);
IfName[s]=0;
IfName_len=s;
@@ -313,11 +346,12 @@
ProgramName=argc[0];
ProgramEnviron=argv;
umask(022);
- if ( killFlag ) killPid(killFlag);
- if ( ! TestCase ) checkIfAlreadyRunning();
- if ( versionFlag ) print_version();
+ if ( ! ISSPAWNED && killFlag ) killPid(killFlag);
+ if ( ! ISSPAWNED && ! TestCase ) checkIfAlreadyRunning();
+ if ( ! ISSPAWNED && versionFlag ) print_version();
openlog(PROGRAM_NAME,LOG_PID|LOG_CONS,LOG_LOCAL0);
signalSetup();
+ signal(SIGHUP, SIG_IGN);
if ( mkdir(ConfigDir,S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) && errno != EEXIST )
{
syslog(LOG_ERR,"mkdir(\"%s\",0): %m\n",ConfigDir);
@@ -326,22 +360,63 @@
magic_cookie = htonl(MAGIC_COOKIE);
dhcpMsgSize = htons(sizeof(dhcpMessage));
nleaseTime = htonl(LeaseTime);
- alarm(TimeOut);
- do
- if ( (currState=(void *(*)())currState()) == NULL ) exit(1);
- while ( currState != &dhcpBound );
+ if ( ! ISSPAWNED )
+ {
+ alarm(TimeOut);
+ do
+ if ( (currState=(void *(*)())currState()) == NULL ) exit(1);
+ while ( currState != &dhcpBound );
+ alarm(0);
+ }
#if 0
if ( TestCase ) exit(0);
#endif
- alarm(0);
+ DEBUG_MARK();
#ifdef DEBUG
writePidFile(getpid());
#else
- s=fork();
- if ( s )
+
+ if ( ! ISSPAWNED )
{
- writePidFile(s);
- exit(0); /* got into bound state. */
+ DEBUG_MARK();
+ s=fork();
+ if ( s )
+ {
+ DEBUG_MARK();
+ writePidFile(s);
+#ifndef HAVE_WORKING_FORK
+ /* I added this delay to let the child configure the interface
+ again. This is necessary because fork() is not available,
+ and we execute the same binary in the child process. The
+ second instance of dhcpcd will have to go through "reboot"
+ state because I don't see any other way to ensure that the
+ data segment is in the same state with parent.
+ */
+ usleep(1000000L);
+#endif
+ exit(0); /* got into bound state. */
+ }
+# ifndef HAVE_WORKING_FORK
+ {
+ char **newargc;
+ newargc = xmalloc((argn + 1) * sizeof(char *));
+ if ( newargc != NULL )
+ {
+ memcpy(newargc, argc, argn * sizeof(char *));
+ newargc[argn] = "-f";
+ newargc[argn + 1] = NULL;
+ DEBUG_MARK();
+ signal(SIGHUP, SIG_IGN);
+ execvp(newargc[0], newargc);
+ fprintf(stderr, "Could not start %s in child mode\n", newargc[0]);
+ }
+ else
+ {
+ fprintf(stderr, "Could not allocate %d pointers\n", argn + 1);
+ }
+ exit(127);
+ }
+# endif /* !HAVE_WORKING_FORK */
}
setsid();
if ( (i=open("/dev/null",O_RDWR,0)) >= 0 )
@@ -351,7 +426,8 @@
(void)dup2(i,STDERR_FILENO);
if ( i > 2 ) (void)close(i);
}
-#endif
+
+#endif /* DEBUG */
chdir("/");
do currState=(void *(*)())currState(); while ( currState );
deletePidFile();
Index: dhcpcd.h
===================================================================
RCS file: /usr/local/cvsroot/user/dhcpcd/dhcpcd.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- dhcpcd.h 14 Apr 2002 07:07:20 -0000 1.1.1.1
+++ dhcpcd.h 21 Apr 2002 00:28:58 -0000 1.2
@@ -38,4 +38,59 @@
#define DEFAULT_TIMEOUT 60
#define DEFAULT_LEASETIME 0xffffffff /* infinite lease time */
+/*
+#define DEBUG_EXEC 1
+#define DEBUG_MALLOC 1
+*/
+
+#if DEBUG_EXEC - 0
+# include <stdio.h>
+# define DEBUG_LOG(fmt, args...) do { \
+ syslog(LOG_INFO, "%s (%d): " fmt "\n", \
+ __FUNCTION__, __LINE__ , ##args); \
+ } while (0)
+# define D(x) x
+
+#else
+
+# define DEBUG_LOG(fmt, args...) do { } while (0)
+# define D(x)
+#endif
+
+#define DEBUG_MARK() DEBUG_LOG("debug mark")
+
+#if DEBUG_MALLOC - 0
+# define xmalloc(n) ( { \
+ void *ptr; \
+ ptr = malloc(n); \
+ syslog(LOG_INFO, "%s (%d): malloc(%ld) %p\n", \
+ __FUNCTION__, __LINE__ , (long)n, ptr); \
+ ptr ; \
+ } )
+# define xstrdup(s) ( { \
+ char *ptr; \
+ ptr = strdup(s); \
+ syslog(LOG_INFO, "%s (%d): strdup(%s) %p\n", \
+ __FUNCTION__, __LINE__ , s, ptr); \
+ ptr ; \
+ } )
+# define xfree(p) ( \
+ syslog(LOG_INFO, "%s (%d): free %p\n", \
+ __FUNCTION__, __LINE__ , p), \
+ free(p), \
+ p = NULL \
+ )
+# define DEBUG_MALLOC_LOG(fmt, args...) do { \
+ syslog(LOG_INFO, "%s (%d): " fmt "\n", \
+ __FUNCTION__, __LINE__ , ##args); \
+ } while (0)
+#else
+# define xmalloc(n) malloc(n)
+# define xstrdup(s) strdup(s)
+# define xfree(p) free(p)
+# define DEBUG_MALLOC_LOG(fmt, args...) do { } while (0)
+#endif
+
+
+
#endif
Index: pathnames.h
===================================================================
RCS file: /usr/local/cvsroot/user/dhcpcd/pathnames.h,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -u -r1.1.1.1 -r1.3
--- pathnames.h 14 Apr 2002 07:07:20 -0000 1.1.1.1
+++ pathnames.h 19 Apr 2002 16:21:35 -0000 1.3
@@ -26,13 +26,22 @@
#include <paths.h>
#include "dhcpcd.h"
+#ifdef EMBED
+# define CONFIG_DIR "/var/dhcpc"
+# define EXEC_ON_CHANGE "/etc/"PROGRAM_NAME".exe"
+# define RESOLV_CONF "/etc/config/resolv.conf"
+# define NIS_CONF "/etc/config/yp.conf"
+# define NTP_CONF "/etc/config/ntp.conf"
+#else
+# define CONFIG_DIR "/etc/dhcpc"
+# define EXEC_ON_CHANGE "%s/"PROGRAM_NAME".exe"
+# define RESOLV_CONF "/etc/resolv.conf"
+# define NIS_CONF "/etc/yp.conf"
+# define NTP_CONF "/etc/ntp.conf"
+#endif
+
#define PID_FILE_PATH "%s/"PROGRAM_NAME"-%s.pid"
-#define CONFIG_DIR "/etc/dhcpc"
#define DHCP_CACHE_FILE "%s/"PROGRAM_NAME"-%s.cache"
#define DHCP_HOSTINFO "%s/"PROGRAM_NAME"-%s.info"
-#define EXEC_ON_CHANGE "%s/"PROGRAM_NAME".exe"
-#define RESOLV_CONF "/etc/resolv.conf"
-#define NIS_CONF "/etc/yp.conf"
-#define NTP_CONF "/etc/ntp.conf"
#endif
========================================================================
More information about the busybox
mailing list