2008-05-01 Maarten Van Es <maarten@mind.be>

* libnetworking/rtems/rtems_dhcp.c: Removed panic()s.  Added
	interface for rtems_dhcp_failsafe.
	* libnetworking/rtems/rtems_dhcp.h: Added interface for
	rtems_dhcp_failsafe.

2008-05-01  Arnout Vandecappelle <arnout@mind.be>

	* libnetworking/nfs/bootp_subr: Allow some errors for sosend() and
	return on timeout in bootpc_call().  Removed panic()s.
	* libnetworking/rtems/rtems_glue.c: Fix the cast for the
	SIOCAIFADDR ioctl call.
	* libnetworking/rtems/rtems_dhcp_failsafe.c,
	libnetworking/rtems/rtems_dhcp_failsafe.h: New.
	* libnetworking/Makefile.am, libnetworking/preinstall.am: Added
	rtems_dhcp_failsafe.c and rtems_dhcp_failsafe.h files.
This commit is contained in:
Chris Johns
2008-05-01 02:57:49 +00:00
parent fb8194045a
commit 50303dfbd1
9 changed files with 709 additions and 143 deletions

View File

@@ -1,3 +1,20 @@
2008-05-01 Maarten Van Es <maarten@mind.be>
* libnetworking/rtems/rtems_dhcp.c: Removed panic()s. Added
interface for rtems_dhcp_failsafe.
* libnetworking/rtems/rtems_dhcp.h: Added interface for
rtems_dhcp_failsafe.
2008-05-01 Arnout Vandecappelle <arnout@mind.be>
* libnetworking/nfs/bootp_subr: Allow some errors for sosend() and
return on timeout in bootpc_call(). Removed panic()s.
* libnetworking/rtems/rtems_glue.c: Fix the cast for the
SIOCAIFADDR ioctl call.
* libnetworking/rtems/rtems_dhcp_failsafe.c,
libnetworking/rtems/rtems_dhcp_failsafe.h: New.
* libnetworking/Makefile.am, libnetworking/preinstall.am: Added
rtems_dhcp_failsafe.c and rtems_dhcp_failsafe.h files.
2008-04-30 Joel Sherrill <joel.sherrill@oarcorp.com> 2008-04-30 Joel Sherrill <joel.sherrill@oarcorp.com>
* rtems/include/rtems/rtems/timer.h: Fix typo. * rtems/include/rtems/rtems/timer.h: Fix typo.

View File

@@ -112,12 +112,13 @@ include_nfsclient_HEADERS = nfsclient/nfsargs.h nfsclient/nfsdiskless.h
include_rtemsdir = $(includedir)/rtems include_rtemsdir = $(includedir)/rtems
include_rtems_HEADERS = rtems/rtems_bsdnet.h rtems/rtems_bsdnet_internal.h \ include_rtems_HEADERS = rtems/rtems_bsdnet.h rtems/rtems_bsdnet_internal.h \
rtems/dhcp.h rtems/tftp.h rtems/ftpfs.h rtems/mkrootfs.h rtems/dhcp.h rtems/rtems_dhcp_failsafe.h rtems/tftp.h rtems/ftpfs.h \
rtems/mkrootfs.h
include_rtems_HEADERS += rtems/rtems_mii_ioctl.h include_rtems_HEADERS += rtems/rtems_mii_ioctl.h
libnetworking_a_SOURCES += rtems/sghostname.c rtems/issetugid.c \ libnetworking_a_SOURCES += rtems/sghostname.c rtems/issetugid.c \
rtems/rtems_glue.c rtems/rtems_malloc_mbuf.c rtems/rtems_syscall.c \ rtems/rtems_glue.c rtems/rtems_malloc_mbuf.c rtems/rtems_syscall.c \
rtems/rtems_bootp.c rtems/rtems_dhcp.c \ rtems/rtems_bootp.c rtems/rtems_dhcp.c rtems/rtems_dhcp_failsafe.c \
rtems/rtems_showmbuf.c rtems/rtems_showroute.c rtems/rtems_showifstat.c \ rtems/rtems_showmbuf.c rtems/rtems_showroute.c rtems/rtems_showifstat.c \
rtems/rtems_showipstat.c rtems/rtems_showicmpstat.c \ rtems/rtems_showipstat.c rtems/rtems_showicmpstat.c \
rtems/rtems_showtcpstat.c rtems/rtems_showudpstat.c rtems/rtems_select.c \ rtems/rtems_showtcpstat.c rtems/rtems_showudpstat.c rtems/rtems_select.c \

View File

@@ -78,7 +78,7 @@
/* /*
* What is the longest we will wait before re-sending a request? * What is the longest we will wait before re-sending a request?
* Note this is also the frequency of "RPC timeout" messages. * Note this is also the frequency of "RPC timeout" messages.
* The re-send loop count sup linearly to this maximum, so the * The re-send loop counts up linearly to this maximum, so the
* first complaint will happen after (1+2+3+4+5)=15 seconds. * first complaint will happen after (1+2+3+4+5)=15 seconds.
*/ */
#define MAX_RESEND_DELAY 5 /* seconds */ #define MAX_RESEND_DELAY 5 /* seconds */
@@ -377,8 +377,7 @@ bootpc_call(call,reply,procp)
* but delay each re-send by an increasing amount. * but delay each re-send by an increasing amount.
* If the delay hits the maximum, start complaining. * If the delay hits the maximum, start complaining.
*/ */
timo = 0; for (timo=1; timo <= MAX_RESEND_DELAY; timo++) {
for (;;) {
/* Send BOOTP request (or re-send). */ /* Send BOOTP request (or re-send). */
aio.iov_base = (caddr_t) call; aio.iov_base = (caddr_t) call;
@@ -391,20 +390,24 @@ bootpc_call(call,reply,procp)
auio.uio_offset = 0; auio.uio_offset = 0;
auio.uio_resid = sizeof(*call); auio.uio_resid = sizeof(*call);
auio.uio_procp = procp; auio.uio_procp = procp;
error = sosend(so, nam, &auio, NULL, NULL, 0); error = sosend(so, nam, &auio, NULL, NULL, 0);
if (error) { if (error) {
printf("bootpc_call: sosend: %d\n", error); printf("bootpc_call: sosend: %d\n", error);
goto out; switch (error) {
case ENOBUFS: /* No buffer space available */
case ENETUNREACH: /* Network is unreachable */
case ENETDOWN: /* Network interface is not configured */
case EHOSTDOWN: /* Host is down */
case EHOSTUNREACH: /* Host is unreachable */
case EMSGSIZE: /* Message too long */
/* This is a possibly transient error.
We can still receive replies from previous attempts. */
break;
default:
goto out;
}
} }
/* Determine new timeout. */
if (timo < MAX_RESEND_DELAY)
timo++;
else
printf("BOOTP timeout for server 0x%x\n",
(int)ntohl(sin->sin_addr.s_addr));
/* /*
* Wait for up to timo seconds for a reply. * Wait for up to timo seconds for a reply.
* The socket receive timeout was set to 1 second. * The socket receive timeout was set to 1 second.
@@ -455,6 +458,9 @@ bootpc_call(call,reply,procp)
} /* while secs */ } /* while secs */
} /* forever send/receive */ } /* forever send/receive */
printf("BOOTP timeout for server 0x%x\n",
(int)ntohl(sin->sin_addr.s_addr));
error = ETIMEDOUT; error = ETIMEDOUT;
goto out; goto out;
@@ -482,18 +488,21 @@ bootpc_fakeup_interface(struct ifreq *ireq,struct socket *so,
* IFF_UP set blindly, interface selection can be clobbered. * IFF_UP set blindly, interface selection can be clobbered.
*/ */
error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, procp); error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, procp);
if (error) if (error) {
panic("bootpc_fakeup_interface: GIFFLAGS, error=%d", error); printf("bootpc_fakeup_interface: GIFFLAGS, error=%s\n", strerror(error));
return error;
}
ireq->ifr_flags |= IFF_UP; ireq->ifr_flags |= IFF_UP;
error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, procp); error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, procp);
if (error) if (error) {
panic("bootpc_fakeup_interface: SIFFLAGS, error=%d", error); printf("bootpc_fakeup_interface: SIFFLAGS, error=%s\n", strerror(error));
return error;
}
/* /*
* Do enough of ifconfig(8) so that the chosen interface * Do enough of ifconfig(8) so that the chosen interface
* can talk to the servers. (just set the address) * can talk to the servers. (just set the address)
*/ */
/* addr is 0.0.0.0 */ /* addr is 0.0.0.0 */
sin = (struct sockaddr_in *)&ireq->ifr_addr; sin = (struct sockaddr_in *)&ireq->ifr_addr;
@@ -502,8 +511,10 @@ bootpc_fakeup_interface(struct ifreq *ireq,struct socket *so,
sin->sin_family = AF_INET; sin->sin_family = AF_INET;
sin->sin_addr.s_addr = INADDR_ANY; sin->sin_addr.s_addr = INADDR_ANY;
error = ifioctl(so, SIOCSIFADDR, (caddr_t)ireq, procp); error = ifioctl(so, SIOCSIFADDR, (caddr_t)ireq, procp);
if (error) if (error) {
panic("bootpc_fakeup_interface: set if addr, error=%d", error); printf("bootpc_fakeup_interface: set if addr, error=%s\n", strerror(error));
return error;
}
/* netmask is 0.0.0.0 */ /* netmask is 0.0.0.0 */
@@ -513,8 +524,10 @@ bootpc_fakeup_interface(struct ifreq *ireq,struct socket *so,
sin->sin_family = AF_INET; sin->sin_family = AF_INET;
sin->sin_addr.s_addr = INADDR_ANY; sin->sin_addr.s_addr = INADDR_ANY;
error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, procp); error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, procp);
if (error) if (error) {
panic("bootpc_fakeup_interface: set if net addr, error=%d", error); printf("bootpc_fakeup_interface: set if netmask, error=%s\n", strerror(error));
return error;
}
/* Broadcast is 255.255.255.255 */ /* Broadcast is 255.255.255.255 */
@@ -524,8 +537,11 @@ bootpc_fakeup_interface(struct ifreq *ireq,struct socket *so,
sin->sin_family = AF_INET; sin->sin_family = AF_INET;
sin->sin_addr.s_addr = INADDR_BROADCAST; sin->sin_addr.s_addr = INADDR_BROADCAST;
error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, procp); error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, procp);
if (error) if (error) {
panic("bootpc_fakeup_interface: set if broadcast addr, error=%d", error); printf("bootpc_fakeup_interface: set broadcast addr, error=%s\n", strerror(error));
return error;
}
/* Add default route to 0.0.0.0 so we can send data */ /* Add default route to 0.0.0.0 so we can send data */
@@ -601,8 +617,10 @@ bootpc_adjust_interface(struct ifreq *ireq,struct socket *so,
*/ */
bcopy(netmask,&ireq->ifr_addr,sizeof(*netmask)); bcopy(netmask,&ireq->ifr_addr,sizeof(*netmask));
error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, procp); error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, procp);
if (error) if (error) {
panic("nfs_boot: set if netmask, error=%d", error); printf("bootpc_adjust_interface: set netmask, error=%s\n", strerror(error));
return error;
}
/* Broadcast is with host part of IP address all 1's */ /* Broadcast is with host part of IP address all 1's */
@@ -612,13 +630,17 @@ bootpc_adjust_interface(struct ifreq *ireq,struct socket *so,
sin->sin_family = AF_INET; sin->sin_family = AF_INET;
sin->sin_addr.s_addr = myaddr->sin_addr.s_addr | ~ netmask->sin_addr.s_addr; sin->sin_addr.s_addr = myaddr->sin_addr.s_addr | ~ netmask->sin_addr.s_addr;
error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, procp); error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, procp);
if (error) if (error) {
panic("bootpc_call: set if broadcast addr, error=%d", error); printf("bootpc_adjust_interface: set broadcast addr, error=%s\n", strerror(error));
return error;
}
bcopy(myaddr,&ireq->ifr_addr,sizeof(*myaddr)); bcopy(myaddr,&ireq->ifr_addr,sizeof(*myaddr));
error = ifioctl(so, SIOCSIFADDR, (caddr_t)ireq, procp); error = ifioctl(so, SIOCSIFADDR, (caddr_t)ireq, procp);
if (error) if (error) {
panic("nfs_boot: set if addr, error=%d", error); printf("bootpc_adjust_interface: set if addr, error=%s\n", strerror(error));
return error;
}
/* Add new default route */ /* Add new default route */
@@ -628,11 +650,10 @@ bootpc_adjust_interface(struct ifreq *ireq,struct socket *so,
(struct sockaddr *) &oldmask, (struct sockaddr *) &oldmask,
(RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL); (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL);
if (error) { if (error) {
printf("nfs_boot: add net route, error=%d\n", error); printf("bootpc_adjust_interface: add net route, error=%d\n", error);
return error;
} }
return 0; return error;
} }
#if !defined(__rtems__) #if !defined(__rtems__)
@@ -758,24 +779,30 @@ processOptions (unsigned char *optbuf, int optbufSize)
switch (code) { switch (code) {
case 1: case 1:
/* Subnet mask */ /* Subnet mask */
if (len!=4) if (len!=4) {
panic("bootpc: subnet mask len is %d",len); printf("bootpc: subnet mask len is %d\n",len);
continue;
}
bcopy (p, &dhcp_netmask.sin_addr, 4); bcopy (p, &dhcp_netmask.sin_addr, 4);
dhcp_gotnetmask = 1; dhcp_gotnetmask = 1;
break; break;
case 2: case 2:
/* Time offset */ /* Time offset */
if (len!=4) if (len!=4) {
panic("bootpc: time offset len is %d",len); printf("bootpc: time offset len is %d\n",len);
continue;
}
bcopy (p, &rtems_bsdnet_timeoffset, 4); bcopy (p, &rtems_bsdnet_timeoffset, 4);
rtems_bsdnet_timeoffset = ntohl (rtems_bsdnet_timeoffset); rtems_bsdnet_timeoffset = ntohl (rtems_bsdnet_timeoffset);
break; break;
case 3: case 3:
/* Routers */ /* Routers */
if (len % 4) if (len % 4) {
panic ("bootpc: Router Len is %d", len); printf ("bootpc: Router Len is %d\n", len);
continue;
}
if (len > 0) { if (len > 0) {
bcopy(p, &dhcp_gw.sin_addr, 4); bcopy(p, &dhcp_gw.sin_addr, 4);
dhcp_gotgw = 1; dhcp_gotgw = 1;
@@ -784,8 +811,10 @@ processOptions (unsigned char *optbuf, int optbufSize)
case 42: case 42:
/* NTP servers */ /* NTP servers */
if (len % 4) if (len % 4) {
panic ("bootpc: time server Len is %d", len); printf ("bootpc: time server Len is %d\n", len);
continue;
}
{ {
int tlen = 0; int tlen = 0;
while ((tlen < len) && while ((tlen < len) &&
@@ -804,8 +833,10 @@ processOptions (unsigned char *optbuf, int optbufSize)
case 6: case 6:
/* Domain Name servers */ /* Domain Name servers */
if (len % 4) if (len % 4) {
panic ("bootpc: DNS Len is %d", len); printf ("bootpc: DNS Len is %d", len);
continue;
}
{ {
int dlen = 0; int dlen = 0;
while ((dlen < len) && while ((dlen < len) &&
@@ -824,18 +855,23 @@ processOptions (unsigned char *optbuf, int optbufSize)
case 12: case 12:
/* Host name */ /* Host name */
if (len>=MAXHOSTNAMELEN) if (len>=MAXHOSTNAMELEN) {
panic ("bootpc: hostname >=%d bytes", MAXHOSTNAMELEN); printf ("bootpc: hostname >=%d bytes", MAXHOSTNAMELEN);
if (sethostname ((char *)p, len) < 0) continue;
panic("Can't set host name"); }
if (sethostname ((char *)p, len) < 0) {
printf("bootpc: Can't set host name");
}
printf("Hostname is %s\n", p); printf("Hostname is %s\n", p);
dhcp_hostname = bootp_strdup_realloc(dhcp_hostname,(char *)p); dhcp_hostname = bootp_strdup_realloc(dhcp_hostname,(char *)p);
break; break;
case 7: case 7:
/* Log servers */ /* Log servers */
if (len % 4) if (len % 4) {
panic ("bootpc: Log server Len is %d", len); printf ("bootpc: Log server Len is %d", len);
continue;
}
if (len > 0) { if (len > 0) {
bcopy(p, &rtems_bsdnet_log_host_address, 4); bcopy(p, &rtems_bsdnet_log_host_address, 4);
dhcp_gotlogserver = 1; dhcp_gotlogserver = 1;
@@ -856,8 +892,10 @@ processOptions (unsigned char *optbuf, int optbufSize)
case 52: case 52:
/* DHCP option override */ /* DHCP option override */
if (len != 1) if (len != 1) {
panic ("bootpc: DHCP option overload len is %d", len); printf ("bootpc: DHCP option overload len is %d", len);
continue;
}
dhcpOptionOverload = p[0]; dhcpOptionOverload = p[0];
break; break;
@@ -872,8 +910,10 @@ processOptions (unsigned char *optbuf, int optbufSize)
*/ */
case 54: case 54:
/* DHCP server */ /* DHCP server */
if (len != 4) if (len != 4) {
panic ("bootpc: DHCP server len is %d", len); printf ("bootpc: DHCP server len is %d", len);
continue;
}
bcopy(p, &rtems_bsdnet_bootp_server_address, 4); bcopy(p, &rtems_bsdnet_bootp_server_address, 4);
dhcp_gotserver = 1; dhcp_gotserver = 1;
break; break;
@@ -955,20 +995,23 @@ bootpc_init(int update_files)
if ((ifp->if_flags & if ((ifp->if_flags &
(IFF_LOOPBACK|IFF_POINTOPOINT)) == 0) (IFF_LOOPBACK|IFF_POINTOPOINT)) == 0)
break; break;
if (ifp == NULL) if (ifp == NULL) {
panic("bootpc_init: no suitable interface"); printf("bootpc_init: no suitable interface\n");
return;
}
bzero(&ireq,sizeof(ireq)); bzero(&ireq,sizeof(ireq));
sprintf(ireq.ifr_name, "%s%d", ifp->if_name,ifp->if_unit); sprintf(ireq.ifr_name, "%s%d", ifp->if_name,ifp->if_unit);
printf("bootpc_init: using network interface '%s'\n", printf("bootpc_init: using network interface '%s'\n",
ireq.ifr_name); ireq.ifr_name);
if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0,procp)) != 0) if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0,procp)) != 0) {
panic("nfs_boot: socreate, error=%d", error); printf("bootpc_init: socreate, error=%d", error);
return;
bootpc_fakeup_interface(&ireq,so,procp); }
if (bootpc_fakeup_interface(&ireq,so,procp) != 0) {
return;
}
printf("Bootpc testing starting\n");
/* Get HW address */ /* Get HW address */
for (ifa = ifp->if_addrlist;ifa; ifa = ifa->ifa_next) for (ifa = ifp->if_addrlist;ifa; ifa = ifa->ifa_next)
@@ -977,11 +1020,15 @@ bootpc_init(int update_files)
sdl->sdl_type == IFT_ETHER) sdl->sdl_type == IFT_ETHER)
break; break;
if (!sdl) if (!sdl) {
panic("bootpc: Unable to find HW address"); printf("bootpc: Unable to find HW address\n");
if (sdl->sdl_alen != EALEN ) return;
panic("bootpc: HW address len is %d, expected value is %d", }
sdl->sdl_alen,EALEN); if (sdl->sdl_alen != EALEN ) {
printf("bootpc: HW address len is %d, expected value is %d\n",
sdl->sdl_alen,EALEN);
return;
}
printf("bootpc hw address is "); printf("bootpc hw address is ");
delim=""; delim="";
@@ -1018,8 +1065,10 @@ bootpc_init(int update_files)
error = bootpc_call(&call,&reply,procp); error = bootpc_call(&call,&reply,procp);
if (error) if (error) {
panic("BOOTP call failed -- error %d", error); printf("BOOTP call failed -- error %d", error);
return;
}
/* /*
* Initialize network address structures * Initialize network address structures

View File

@@ -290,6 +290,10 @@ $(PROJECT_INCLUDE)/rtems/dhcp.h: rtems/dhcp.h $(PROJECT_INCLUDE)/rtems/$(dirstam
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/dhcp.h $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/dhcp.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/dhcp.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/dhcp.h
$(PROJECT_INCLUDE)/rtems/rtems_dhcp_failsafe.h: rtems/rtems_dhcp_failsafe.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems_dhcp_failsafe.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems_dhcp_failsafe.h
$(PROJECT_INCLUDE)/rtems/tftp.h: rtems/tftp.h $(PROJECT_INCLUDE)/rtems/$(dirstamp) $(PROJECT_INCLUDE)/rtems/tftp.h: rtems/tftp.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/tftp.h $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/tftp.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/tftp.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/tftp.h

View File

@@ -29,6 +29,8 @@ extern "C"
* Perform DHCP. * Perform DHCP.
*/ */
void rtems_bsdnet_do_dhcp (void); void rtems_bsdnet_do_dhcp (void);
int rtems_bsdnet_do_dhcp_timeout (void);
void rtems_bsdnet_dhcp_down (void);
/* /*
* Maintain a DHCP offer that has already been accepted. * Maintain a DHCP offer that has already been accepted.

View File

@@ -9,6 +9,12 @@
* Brendan Gannon, <bgannon@cybertec.com.au> * Brendan Gannon, <bgannon@cybertec.com.au>
*/ */
/*
* Added interface to terminate DHCP task, and removed panics.
* Arnout Vandecappelle <arnout@mind.be>, Essensium/Mind
* Maarten Van Es <maarten@mind.be>, Essensium/Mind
*/
/* /*
* Copyright (c) 1995 Gordon Ross, Adam Glass * Copyright (c) 1995 Gordon Ross, Adam Glass
* Copyright (c) 1992 Regents of the University of California. * Copyright (c) 1992 Regents of the University of California.
@@ -186,7 +192,6 @@ extern int bootpc_adjust_interface (struct ifreq *ireq,
struct proc *procp); struct proc *procp);
extern void *bootp_strdup_realloc (char *dst, extern void *bootp_strdup_realloc (char *dst,
const char *src); const char *src);
extern int nfs_diskless_valid;
/* /*
* Variables * Variables
@@ -271,6 +276,8 @@ process_options (unsigned char *optbuf, int optbufSize)
int code, ncode; int code, ncode;
char *p; char *p;
dhcp_message_type = 0;
ncode = optbuf[0]; ncode = optbuf[0];
while (j < optbufSize) while (j < optbufSize)
{ {
@@ -303,24 +310,30 @@ process_options (unsigned char *optbuf, int optbufSize)
{ {
case 1: case 1:
/* Subnet mask */ /* Subnet mask */
if (len != 4) if (len != 4) {
panic ("dhcpc: subnet mask len is %d", len); printf ("dhcpc: subnet mask len is %d\n", len);
continue;
}
memcpy (&dhcp_netmask.sin_addr, p, 4); memcpy (&dhcp_netmask.sin_addr, p, 4);
dhcp_gotnetmask = 1; dhcp_gotnetmask = 1;
break; break;
case 2: case 2:
/* Time offset */ /* Time offset */
if (len != 4) if (len != 4) {
panic ("dhcpc: time offset len is %d", len); printf ("dhcpc: time offset len is %d\n", len);
continue;
}
memcpy (&rtems_bsdnet_timeoffset, p, 4); memcpy (&rtems_bsdnet_timeoffset, p, 4);
rtems_bsdnet_timeoffset = ntohl (rtems_bsdnet_timeoffset); rtems_bsdnet_timeoffset = ntohl (rtems_bsdnet_timeoffset);
break; break;
case 3: case 3:
/* Routers */ /* Routers */
if (len % 4) if (len % 4) {
panic ("dhcpc: Router Len is %d", len); printf ("dhcpc: Router Len is %d\n", len);
continue;
}
if (len > 0) if (len > 0)
{ {
memcpy (&dhcp_gw.sin_addr, p, 4); memcpy (&dhcp_gw.sin_addr, p, 4);
@@ -330,8 +343,10 @@ process_options (unsigned char *optbuf, int optbufSize)
case 42: case 42:
/* NTP servers */ /* NTP servers */
if (len % 4) if (len % 4) {
panic ("dhcpc: time server Len is %d", len); printf ("dhcpc: time server Len is %d\n", len);
continue;
}
{ {
int tlen = 0; int tlen = 0;
while ((tlen < len) && while ((tlen < len) &&
@@ -349,8 +364,10 @@ process_options (unsigned char *optbuf, int optbufSize)
case 6: case 6:
/* Domain Name servers */ /* Domain Name servers */
if (len % 4) if (len % 4) {
panic ("dhcpc: DNS Len is %d", len); printf ("dhcpc: DNS Len is %d\n", len);
continue;
}
{ {
int dlen = 0; int dlen = 0;
while ((dlen < len) && while ((dlen < len) &&
@@ -368,10 +385,12 @@ process_options (unsigned char *optbuf, int optbufSize)
case 12: case 12:
/* Host name */ /* Host name */
if (len >= MAXHOSTNAMELEN) if (len >= MAXHOSTNAMELEN) {
panic ("dhcpc: hostname >= %d bytes", MAXHOSTNAMELEN); printf ("dhcpc: hostname >= %d bytes\n", MAXHOSTNAMELEN);
len = MAXHOSTNAMELEN-1;
}
if (sethostname (p, len) < 0) if (sethostname (p, len) < 0)
panic ("dhcpc: can't set host name"); printf ("dhcpc: can't set host name");
if (dhcp_hostname != NULL) if (dhcp_hostname != NULL)
{ {
dhcp_hostname = realloc (dhcp_hostname, len); dhcp_hostname = realloc (dhcp_hostname, len);
@@ -383,8 +402,10 @@ process_options (unsigned char *optbuf, int optbufSize)
case 7: case 7:
/* Log servers */ /* Log servers */
if (len % 4) if (len % 4) {
panic ("dhcpc: Log server Len is %d", len); printf ("dhcpc: Log server Len is %d\n", len);
continue;
}
if (len > 0) if (len > 0)
{ {
memcpy (&rtems_bsdnet_log_host_address, p, 4); memcpy (&rtems_bsdnet_log_host_address, p, 4);
@@ -406,7 +427,7 @@ process_options (unsigned char *optbuf, int optbufSize)
case 50: case 50:
/* DHCP Requested IP Address */ /* DHCP Requested IP Address */
if (len != 4) if (len != 4)
panic ("dhcpc: DHCP option requested IP len is %d", len); printf ("dhcpc: DHCP option requested IP len is %d", len);
/* /*
* although nothing happens here, this case keeps the client * although nothing happens here, this case keeps the client
* from complaining about unknown options. The Requested IP * from complaining about unknown options. The Requested IP
@@ -416,23 +437,29 @@ process_options (unsigned char *optbuf, int optbufSize)
case 51: case 51:
/* DHCP Lease Length */ /* DHCP Lease Length */
if (len != 4) if (len != 4) {
panic ("dhcpc: DHCP option lease-length len is %d", len); printf ("dhcpc: DHCP option lease-length len is %d", len);
continue;
}
memcpy (&dhcp_lease_time, &p[0], 4); memcpy (&dhcp_lease_time, &p[0], 4);
dhcp_lease_time = ntohl (dhcp_lease_time); dhcp_lease_time = ntohl (dhcp_lease_time);
break; break;
case 52: case 52:
/* DHCP option override */ /* DHCP option override */
if (len != 1) if (len != 1) {
panic ("dhcpc: DHCP option overload len is %d", len); printf ("dhcpc: DHCP option overload len is %d", len);
continue;
}
dhcp_option_overload = p[0]; dhcp_option_overload = p[0];
break; break;
case 53: case 53:
/* DHCP message */ /* DHCP message */
if (len != 1) if (len != 1) {
panic ("dhcpc: DHCP message len is %d", len); printf ("dhcpc: DHCP message len is %d", len);
continue;
}
dhcp_message_type = p[0]; dhcp_message_type = p[0];
break; break;
@@ -447,8 +474,10 @@ process_options (unsigned char *optbuf, int optbufSize)
*/ */
case 54: case 54:
/* DHCP server */ /* DHCP server */
if (len != 4) if (len != 4) {
panic ("dhcpc: DHCP server len is %d", len); printf ("dhcpc: DHCP server len is %d", len);
continue;
}
memcpy (&rtems_bsdnet_bootp_server_address, p, 4); memcpy (&rtems_bsdnet_bootp_server_address, p, 4);
dhcp_gotserver = 1; dhcp_gotserver = 1;
break; break;
@@ -667,13 +696,28 @@ dhcp_task (rtems_task_argument _sdl)
unsigned int timeout = 0; unsigned int timeout = 0;
int error; int error;
struct proc *procp = NULL; struct proc *procp = NULL;
int disconnected;
sdl = (struct sockaddr_dl *) _sdl; sdl = (struct sockaddr_dl *) _sdl;
count = dhcp_elapsed_time; count = dhcp_elapsed_time;
disconnected = 0;
while (TRUE) while (TRUE)
{ {
/*
* Sleep until the next poll
*/
timeout = TOD_MILLISECONDS_TO_TICKS (1000);
rtems_event_receive (RTEMS_EVENT_0,
RTEMS_WAIT | RTEMS_EVENT_ANY,
timeout, &event_out);
if(event_out & RTEMS_EVENT_0) break;
count++;
if (count >= (dhcp_lease_time / 2)) if (count >= (dhcp_lease_time / 2))
{ {
rtems_bsdnet_semaphore_obtain (); rtems_bsdnet_semaphore_obtain ();
@@ -684,10 +728,12 @@ dhcp_task (rtems_task_argument _sdl)
* Send the Request. * Send the Request.
*/ */
error = bootpc_call (&call, &dhcp_req, procp); error = bootpc_call (&call, &dhcp_req, procp);
if (error) {
if (error) rtems_bsdnet_semaphore_release ();
panic ("DHCP call failed -- error %d", error); printf ("DHCP call failed -- error %d", error);
continue;
}
/* /*
* Check for DHCP ACK/NACK * Check for DHCP ACK/NACK
*/ */
@@ -696,7 +742,8 @@ dhcp_task (rtems_task_argument _sdl)
sizeof (dhcp_magic_cookie)) != 0) sizeof (dhcp_magic_cookie)) != 0)
{ {
rtems_bsdnet_semaphore_release (); rtems_bsdnet_semaphore_release ();
panic ("DHCP server did not send Magic Cookie.\n"); printf ("DHCP server did not send Magic Cookie.\n");
continue;
} }
process_options (&dhcp_req.vend[4], sizeof (dhcp_req.vend) - 4); process_options (&dhcp_req.vend[4], sizeof (dhcp_req.vend) - 4);
@@ -704,23 +751,21 @@ dhcp_task (rtems_task_argument _sdl)
if (dhcp_message_type != DHCP_ACK) if (dhcp_message_type != DHCP_ACK)
{ {
rtems_bsdnet_semaphore_release (); rtems_bsdnet_semaphore_release ();
panic ("DHCP server did not accept the DHCP request"); printf ("DHCP server did not accept the DHCP request");
continue;
} }
rtems_bsdnet_semaphore_release (); rtems_bsdnet_semaphore_release ();
count = 0; count = 0;
} }
/*
* Sleep until the next poll
*/
timeout = TOD_MILLISECONDS_TO_TICKS (1000);
rtems_event_receive (RTEMS_EVENT_0,
RTEMS_WAIT | RTEMS_EVENT_ANY,
timeout, &event_out);
count++;
} }
dhcp_task_id = 0;
printf ("dhcpc: exiting lease renewal task.\n");
rtems_task_delete( RTEMS_SELF);
} }
/* /*
@@ -795,8 +840,12 @@ dhcp_interface_has_ip (struct ifreq *ireq, struct socket *so, struct proc *procp
* DCHP Client Routine * DCHP Client Routine
* - The first DHCP offer is always accepted * - The first DHCP offer is always accepted
* - No DHCP DECLINE message is sent if ARPing fails * - No DHCP DECLINE message is sent if ARPing fails
*
* return value:
* 0: ok
* < 0: failed to startup or configure interface
*/ */
void int
dhcp_init (int update_files) dhcp_init (int update_files)
{ {
struct dhcp_packet call; struct dhcp_packet call;
@@ -811,12 +860,6 @@ dhcp_init (int update_files)
struct ifaddr *ifa; struct ifaddr *ifa;
struct sockaddr_dl *sdl = NULL; struct sockaddr_dl *sdl = NULL;
struct proc *procp = NULL; struct proc *procp = NULL;
/*
* If already filled in, don't touch it here
*/
if (nfs_diskless_valid)
return;
/* /*
* If we are to update the files create the root * If we are to update the files create the root
@@ -834,13 +877,18 @@ dhcp_init (int update_files)
for (ifp = ifnet; ifp != 0; ifp = ifp->if_next) for (ifp = ifnet; ifp != 0; ifp = ifp->if_next)
if ((ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) == 0) if ((ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) == 0)
break; break;
if (ifp == NULL) if (ifp == NULL){
panic ("dhcpc_init: no suitable interface"); printf ("dhcpc_init: no suitable interface\n");
return -1;
}
memset (&ireq, 0, sizeof (ireq)); memset (&ireq, 0, sizeof (ireq));
sprintf (ireq.ifr_name, "%s%d", ifp->if_name, ifp->if_unit); sprintf (ireq.ifr_name, "%s%d", ifp->if_name, ifp->if_unit);
if ((error = socreate (AF_INET, &so, SOCK_DGRAM, 0, procp)) != 0) if ((error = socreate (AF_INET, &so, SOCK_DGRAM, 0, procp)) != 0) {
panic ("nfs_boot: socreate, error=%d", error); printf ("dhcpc_init: socreate, error=%d\n", error);
return -1;
}
if (!dhcp_interface_has_ip (&ireq, so, procp)) if (!dhcp_interface_has_ip (&ireq, so, procp))
bootpc_fakeup_interface (&ireq, so, procp); bootpc_fakeup_interface (&ireq, so, procp);
@@ -854,11 +902,15 @@ dhcp_init (int update_files)
sdl->sdl_type == IFT_ETHER) sdl->sdl_type == IFT_ETHER)
break; break;
if (!sdl) if (!sdl){
panic ("dhcpc: Unable to find HW address"); printf ("dhcpc_init: Unable to find HW address\n");
if (sdl->sdl_alen != EALEN) return -1;
panic ("dhcpc: HW address len is %d, expected value is %d", }
if (sdl->sdl_alen != EALEN) {
printf ("dhcpc_init: HW address len is %d, expected value is %d\n",
sdl->sdl_alen, EALEN); sdl->sdl_alen, EALEN);
return -1;
}
/* /*
* Build the DHCP Discover * Build the DHCP Discover
@@ -869,19 +921,25 @@ dhcp_init (int update_files)
* Send the Discover. * Send the Discover.
*/ */
error = bootpc_call (&call, &reply, procp); error = bootpc_call (&call, &reply, procp);
if (error) if (error) {
panic ("BOOTP call failed -- error %d", error); printf ("BOOTP call failed -- error %d\n", error);
return -1;
}
/* /*
* Check for DHCP OFFER * Check for DHCP OFFER
*/ */
if (memcmp (&reply.vend[0], dhcp_magic_cookie, sizeof (dhcp_magic_cookie)) != 0) if (memcmp (&reply.vend[0], dhcp_magic_cookie, sizeof (dhcp_magic_cookie)) != 0) {
panic ("DHCP server did not send Magic Cookie.\n"); printf ("DHCP server did not send Magic Cookie.\n");
return -1;
}
process_options (&reply.vend[4], sizeof (reply.vend) - 4); process_options (&reply.vend[4], sizeof (reply.vend) - 4);
if (dhcp_message_type != DHCP_OFFER) if (dhcp_message_type != DHCP_OFFER) {
panic ("DHCP server did not send a DHCP Offer.\n"); printf ("DHCP server did not send a DHCP Offer.\n");
return -1;
}
/* /*
* Send a DHCP REQUEST * Send a DHCP REQUEST
@@ -889,19 +947,25 @@ dhcp_init (int update_files)
dhcp_request_req (&call, &reply, sdl, TRUE); dhcp_request_req (&call, &reply, sdl, TRUE);
error = bootpc_call (&call, &reply, procp); error = bootpc_call (&call, &reply, procp);
if (error) if (error) {
panic ("BOOTP call failed -- error %d", error); printf ("BOOTP call failed -- error %d\n", error);
return -1;
}
/* /*
* Check for DHCP ACK/NACK * Check for DHCP ACK/NACK
*/ */
if (memcmp (&reply.vend[0], dhcp_magic_cookie, sizeof (dhcp_magic_cookie)) != 0) if (memcmp (&reply.vend[0], dhcp_magic_cookie, sizeof (dhcp_magic_cookie)) != 0) {
panic ("DHCP server did not send Magic Cookie.\n"); printf ("DHCP server did not send Magic Cookie.\n");
return -1;
}
process_options (&reply.vend[4], sizeof (reply.vend) - 4); process_options (&reply.vend[4], sizeof (reply.vend) - 4);
if (dhcp_message_type != DHCP_ACK) if (dhcp_message_type != DHCP_ACK) {
panic ("DHCP server did not accept the DHCP request"); printf ("DHCP server did not accept the DHCP request\n");
return -1;
}
/* /*
* Initialize network address structures * Initialize network address structures
@@ -1039,6 +1103,8 @@ dhcp_init (int update_files)
dhcp_start_task (sdl, &reply, 150); dhcp_start_task (sdl, &reply, 150);
soclose (so); soclose (so);
return 0;
} }
/* /*
@@ -1049,10 +1115,32 @@ dhcp_init (int update_files)
void rtems_bsdnet_do_dhcp (void) void rtems_bsdnet_do_dhcp (void)
{ {
rtems_bsdnet_semaphore_obtain (); rtems_bsdnet_semaphore_obtain ();
dhcp_init (TRUE); while( dhcp_init (TRUE) < 0 ) {
rtems_bsdnet_semaphore_release();
rtems_task_wake_after(TOD_MILLISECONDS_TO_TICKS(1000));
rtems_bsdnet_semaphore_obtain ();
}
rtems_bsdnet_semaphore_release (); rtems_bsdnet_semaphore_release ();
} }
int rtems_bsdnet_do_dhcp_timeout( void )
{
int return_value;
rtems_bsdnet_semaphore_obtain ();
return_value = dhcp_init (FALSE);
rtems_bsdnet_semaphore_release ();
return return_value;
}
void rtems_bsdnet_dhcp_down (void)
{
if(dhcp_task_id != 0) {
rtems_event_send (dhcp_task_id, RTEMS_EVENT_0);
}
}
void void
rtems_bsdnet_do_dhcp_refresh_only (unsigned long xid, rtems_bsdnet_do_dhcp_refresh_only (unsigned long xid,
unsigned long lease_time, unsigned long lease_time,
@@ -1092,8 +1180,10 @@ rtems_bsdnet_do_dhcp_refresh_only (unsigned long xid,
} }
} }
if (!match) if (!match) {
panic ("dhcpc: no matching interface"); printf ("dhcpc: no matching interface\n");
return;
}
for (ifa = mtif->if_addrlist; ifa != NULL; ifa = ifa->ifa_next) for (ifa = mtif->if_addrlist; ifa != NULL; ifa = ifa->ifa_next)
if (ifa->ifa_addr->sa_family == AF_LINK && if (ifa->ifa_addr->sa_family == AF_LINK &&
@@ -1101,8 +1191,10 @@ rtems_bsdnet_do_dhcp_refresh_only (unsigned long xid,
sdl->sdl_type == IFT_ETHER) sdl->sdl_type == IFT_ETHER)
break; break;
if (!match) if (!match) {
panic ("dhcpc: no matching interface"); printf ("dhcpc: no matching interface address\n");
return;
}
/* /*
* Set up given values in a simulated DHCP reply. * Set up given values in a simulated DHCP reply.

View File

@@ -0,0 +1,372 @@
/*
$Id$
Description: Wrapper around DHCP client to restart it when the interface
moves to another network.
Authors: Arnout Vandecappelle <arnout@mind.be>, Essensium/Mind
Maarten Van Es <maarten@mind.be>, Essensium/Mind
(C) Septentrio 2008
The license and distribution terms for this file may be
found in the file LICENSE in this distribution or at
http://www.rtems.com/license/LICENSE.
To use this functionality, call rtems_bsdnet_do_dhcp_failsafe() or set it
as the bootp member of the rtems_bsdnet_config structure.
The rtems_bsdnet_do_dhcp_failsafe() function provides the following
functionalities:
* It starts DHCP on the first non-loopback, non-point-to-point interface.
Before DHCP is started, any existing IP address on that interface is
removed, as well as the default route.
* If DHCP fails to acquire an address for whatever reason, the interface
is reconfigured with the static address provided in its
rtems_bsdnet_ifconfig structure, and the default route from
rtems_bsdnet_config is restored.
It is possible to change the address in the rtems_bsdnet_ifconfig structure
while the system is running.
* Optionally, after the interface is configured (either with DHCP or
statically), a task is started to monitor it. When the interface remains
disconnected (i.e. its IFF_RUNNING flag is off) for NETWORK_FAIL_TIMEOUT
seconds, the dhcp lease renewal is stopped. As soon as the interface is
connected again, DHCP is started again as above.
If NETWORK_FAIL_TIMEOUT is set to 0, the monitor task is not started.
* Optionally, when the interface is disconnected, it is also brought down
for NETWORK_DOWN_TIME seconds. Since this possibly makes the IFF_RUNNING
flag unuseable, the interface is brought up again before the flag is
polled.
If NETWORK_DOWN_TIME is set to 0, the interface is not brought down.
* Optionally, before DHCP is started, we wait for BROADCAST_DELAY seconds.
This is necessary to allow some routers to perform spanning tree discovery.
Note that DHCP doesn't work well with multiple interfaces: only one of them
is configured using DHCP, and we can't guarantee it's the same one that is
monitored by this function.
*/
#include <rtems.h>
#include <rtems/error.h>
#include <rtems/rtems_bsdnet.h>
#include <rtems/rtems_bsdnet_internal.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <rtems/dhcp.h>
struct proc; /* Unused parameter of some functions. */
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/route.h>
#include <netinet/in.h> /* for sockaddr_in */
#include <net/if.h> /* for if.h */
#include <net/if_var.h> /* for in_var.h */
#include <netinet/in_var.h> /* for in_aliasreq */
#include <sys/sockio.h> /* for ioctl definitions */
#include <arpa/inet.h> /* for inet_addr, inet_ntop */
#define NETWORK_FAIL_TIMEOUT 5 /* the number of seconds before the interface is considered disconnected */
#define NETWORK_DOWN_TIME 30 /* number of seconds the interface remains down */
#define BROADCAST_DELAY 0 /* Delay (seconds) before broadcasts are sent */
#define DHCP_MONITOR_PRIORITY 250 /* Low priority */
/*
* returns 0 when successful, negative value for failure
*/
static int remove_address(const char *if_name)
{
struct sockaddr_in address;
struct in_aliasreq ifra;
int retval = 0;
memset (&address, '\0', sizeof (address));
address.sin_len = sizeof (address);
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
/* Remove old default route to 0.0.0.0 */
if (rtems_bsdnet_rtrequest (RTM_DELETE, (struct sockaddr *)&address, NULL,
(struct sockaddr *)&address,
(RTF_UP | RTF_STATIC), NULL) < 0 ) {
printf ("Failed to delete default route: %s (%d)\n", strerror (errno), errno);
retval = -1;
}
/* Remove old ip-address */
if (rtems_bsdnet_ifconfig(if_name, SIOCGIFADDR, &address) < 0) {
printf ("Failed to get if address: %s (%d)\n", strerror (errno), errno);
return -1;
}
strncpy (ifra.ifra_name, if_name, IFNAMSIZ);
memcpy (&ifra.ifra_addr, &address, sizeof(address));
if (rtems_bsdnet_ifconfig(if_name, SIOCDIFADDR, &ifra)) {
printf ("Can't delete if address: %s (%d)\n", strerror (errno), errno);
return -1;
}
return retval;
}
#if NETWORK_DOWN_TIME
static int
dhcp_if_down (const char* ifname)
{
int flags;
if (rtems_bsdnet_ifconfig (ifname, SIOCGIFFLAGS, &flags) < 0) {
printf ("Can't get flags for %s: %s\n", ifname, strerror (errno));
return -1;
}
if (flags & IFF_UP) {
flags &= ~IFF_UP;
if (rtems_bsdnet_ifconfig (ifname, SIOCSIFFLAGS, &flags) < 0) {
printf ("Can't bring %s down: %s\n", ifname, strerror (errno));
return -1;
}
}
return 0;
}
#endif
static int
dhcp_if_up (const char* ifname)
{
int flags;
if (rtems_bsdnet_ifconfig (ifname, SIOCGIFFLAGS, &flags) < 0) {
printf ("Can't get flags for %s: %s\n", ifname, strerror (errno));
return -1;
}
if (!(flags & IFF_UP)) {
flags |= IFF_UP;
if (rtems_bsdnet_ifconfig (ifname, SIOCSIFFLAGS, &flags) < 0) {
printf ("Can't bring %s up: %s\n", ifname, strerror (errno));
return -1;
}
}
return 0;
}
static int
set_static_address (struct rtems_bsdnet_ifconfig *ifp)
{
short flags;
struct sockaddr_in address;
struct sockaddr_in netmask;
struct sockaddr_in broadcast;
struct sockaddr_in gateway;
if (ifp->ip_address != NULL) {
printf("Setting static address for interface %s.\n", ifp->name);
/*
* Bring interface up
*/
if (dhcp_if_up (ifp->name) < 0)
return -1;
/*
* Set interface netmask
*/
memset (&netmask, '\0', sizeof netmask);
netmask.sin_len = sizeof netmask;
netmask.sin_family = AF_INET;
netmask.sin_addr.s_addr = inet_addr (ifp->ip_netmask);
if (rtems_bsdnet_ifconfig (ifp->name, SIOCSIFNETMASK, &netmask) < 0) {
printf ("Can't set %s netmask: %s\n", ifp->name, strerror (errno));
return -1;
}
/*
* Set interface address
*/
memset (&address, '\0', sizeof address);
address.sin_len = sizeof address;
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr (ifp->ip_address);
if (rtems_bsdnet_ifconfig (ifp->name, SIOCSIFADDR, &address) < 0) {
printf ("Can't set %s address: %s\n", ifp->name, strerror (errno));
return -1;
}
/*
* Set interface broadcast address if the interface has the
* broadcast flag set.
*/
if (rtems_bsdnet_ifconfig (ifp->name, SIOCGIFFLAGS, &flags) < 0) {
printf ("Can't read %s flags: %s\n", ifp->name, strerror (errno));
return -1;
}
if (flags & IFF_BROADCAST) {
memset (&broadcast, '\0', sizeof broadcast);
broadcast.sin_len = sizeof broadcast;
broadcast.sin_family = AF_INET;
broadcast.sin_addr.s_addr = address.sin_addr.s_addr | ~netmask.sin_addr.s_addr;
if (rtems_bsdnet_ifconfig (ifp->name, SIOCSIFBRDADDR, &broadcast) < 0) {
struct in_addr in_addr;
char buf[20];
in_addr.s_addr = broadcast.sin_addr.s_addr;
if (!inet_ntop (AF_INET, &in_addr, buf, sizeof (buf)))
strcpy (buf, "?.?.?.?");
printf ("Can't set %s broadcast address %s: %s\n", ifp->name, buf, strerror (errno));
}
}
}
/*
* Set default route
*/
if (rtems_bsdnet_config.gateway) {
address.sin_addr.s_addr = INADDR_ANY;
netmask.sin_addr.s_addr = INADDR_ANY;
memset (&gateway, '\0', sizeof gateway);
gateway.sin_len = sizeof gateway;
gateway.sin_family = AF_INET;
gateway.sin_addr.s_addr = inet_addr (rtems_bsdnet_config.gateway);
if (rtems_bsdnet_rtrequest (RTM_ADD,
(struct sockaddr *) &address,
(struct sockaddr *) &gateway,
(struct sockaddr *) &netmask,
(RTF_UP | RTF_GATEWAY | RTF_STATIC),
NULL
) < 0) {
printf ("Can't set default route: %s\n", strerror (errno));
return -1;
}
}
return 0;
}
static void
do_dhcp_init (struct rtems_bsdnet_ifconfig *ifp)
{
#if BROADCAST_DELAY
/* Wait before sending broadcast. */
rtems_task_wake_after(TOD_MILLISECONDS_TO_TICKS(BROADCAST_DELAY * 1000));
#endif
printf ("starting dhcp client...\n");
remove_address(ifp->name);
if (rtems_bsdnet_do_dhcp_timeout () != 0) {
remove_address(ifp->name);
set_static_address (ifp); /* use static ip-address if dhcp failed */
}
}
/*
* Main dhcp monitor thread
*/
static void dhcp_monitor_task (rtems_task_argument ifp_arg)
{
struct rtems_bsdnet_ifconfig *ifp = (struct rtems_bsdnet_ifconfig *)ifp_arg;
char *ifname = ifp->name;
unsigned int downcount = 0;
int ifflags;
int must_renew = FALSE;
while (TRUE) {
if (rtems_bsdnet_ifconfig(ifname, SIOCGIFFLAGS, &ifflags) < 0) {
printf ("Failed to get if flags: %s (%d)\n", strerror (errno), errno);
goto error_out;
}
if ((ifflags & IFF_RUNNING) != 0) {
if(must_renew) {
must_renew = FALSE;
do_dhcp_init(ifp);
}
downcount = 0;
} else {
if (downcount < NETWORK_FAIL_TIMEOUT) {
downcount++;
if (downcount == NETWORK_FAIL_TIMEOUT) {
printf ("lost network connection...\n");
rtems_bsdnet_dhcp_down ();
must_renew = TRUE;
#if NETWORK_DOWN_TIME
dhcp_if_down(ifname);
rtems_task_wake_after(TOD_MILLISECONDS_TO_TICKS(NETWORK_DOWN_TIME * 1000));
dhcp_if_up(ifname);
downcount = 0;
#endif
}
}
}
rtems_task_wake_after(TOD_MILLISECONDS_TO_TICKS(1000));
}
error_out:
printf("Stopping dhcp monitoring application.\n");
rtems_task_delete(RTEMS_SELF);
}
/*
* initialize dhcp monitoring application
* start dhcp monitoring thread
*/
void rtems_bsdnet_do_dhcp_failsafe (void)
{
rtems_status_code sc;
rtems_id id;
struct rtems_bsdnet_ifconfig *ifp;
int ifflags;
/* Find a suitable interface */
for (ifp = rtems_bsdnet_config.ifconfig; ifp; ifp = ifp->next) {
if (rtems_bsdnet_ifconfig (ifp->name, SIOCGIFFLAGS, &ifflags) < 0)
continue;
if ((ifflags & (IFF_LOOPBACK | IFF_POINTOPOINT)) == 0)
break;
}
if (ifp == NULL){
printf ("dhcpc_failsafe: no suitable interface\n");
return;
}
printf("starting dhcp on interface %s\n", ifp->name);
do_dhcp_init(ifp);
#if NETWORK_FAIL_TIMEOUT
sc = rtems_task_create (rtems_build_name ('d','h','c','m'),
DHCP_MONITOR_PRIORITY,
2048,
RTEMS_PREEMPT |
RTEMS_NO_TIMESLICE |
RTEMS_NO_ASR |
RTEMS_INTERRUPT_LEVEL (0),
RTEMS_LOCAL,
&id);
if (sc != RTEMS_SUCCESSFUL) {
printf ("Failed to create dhcp monitor task, code %d\n", sc);
return;
}
sc = rtems_task_start (id, dhcp_monitor_task, (rtems_task_argument) ifp);
if (sc != RTEMS_SUCCESSFUL) {
printf ("Failed to start dhcp monitor task, code %d\n", sc);
}
#endif
}

View File

@@ -0,0 +1,29 @@
/*
$Id$
Description: Wrapper around DHCP client to restart it when the interface
moves to another network.
Authors: Arnout Vandecappelle <arnout@mind.be>, Essensium/Mind
Maarten Van Es <maarten@mind.be>, Essensium/Mind
(C) Septentrio 2008
The license and distribution terms for this file may be
found in the file LICENSE in this distribution or at
http://www.rtems.com/license/LICENSE.
*/
#ifndef _RTEMS_DHCP_FAILSAFE_H_
#define _RTEMS_DHCP_FAILSAFE_H_
#ifdef __cplusplus
extern "C" {
#endif
void rtems_bsdnet_do_dhcp_failsafe (void);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1127,7 +1127,7 @@ int rtems_bsdnet_ifconfig (const char *ifname, uint32_t cmd, void *param)
case SIOCAIFADDR: case SIOCAIFADDR:
case SIOCDIFADDR: case SIOCDIFADDR:
r = ioctl(s, cmd, (struct freq *) param); r = ioctl(s, cmd, (struct ifreq *) param);
break; break;
default: default: