forked from Imagelibrary/rtems
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:
@@ -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>
|
||||
|
||||
* rtems/include/rtems/rtems/timer.h: Fix typo.
|
||||
|
||||
@@ -112,12 +112,13 @@ include_nfsclient_HEADERS = nfsclient/nfsargs.h nfsclient/nfsdiskless.h
|
||||
include_rtemsdir = $(includedir)/rtems
|
||||
|
||||
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
|
||||
|
||||
libnetworking_a_SOURCES += rtems/sghostname.c rtems/issetugid.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_showipstat.c rtems/rtems_showicmpstat.c \
|
||||
rtems/rtems_showtcpstat.c rtems/rtems_showudpstat.c rtems/rtems_select.c \
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
/*
|
||||
* What is the longest we will wait before re-sending a request?
|
||||
* 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.
|
||||
*/
|
||||
#define MAX_RESEND_DELAY 5 /* seconds */
|
||||
@@ -377,8 +377,7 @@ bootpc_call(call,reply,procp)
|
||||
* but delay each re-send by an increasing amount.
|
||||
* If the delay hits the maximum, start complaining.
|
||||
*/
|
||||
timo = 0;
|
||||
for (;;) {
|
||||
for (timo=1; timo <= MAX_RESEND_DELAY; timo++) {
|
||||
/* Send BOOTP request (or re-send). */
|
||||
|
||||
aio.iov_base = (caddr_t) call;
|
||||
@@ -391,19 +390,23 @@ bootpc_call(call,reply,procp)
|
||||
auio.uio_offset = 0;
|
||||
auio.uio_resid = sizeof(*call);
|
||||
auio.uio_procp = procp;
|
||||
|
||||
error = sosend(so, nam, &auio, NULL, NULL, 0);
|
||||
if (error) {
|
||||
printf("bootpc_call: sosend: %d\n", error);
|
||||
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.
|
||||
@@ -455,6 +458,9 @@ bootpc_call(call,reply,procp)
|
||||
} /* while secs */
|
||||
} /* forever send/receive */
|
||||
|
||||
printf("BOOTP timeout for server 0x%x\n",
|
||||
(int)ntohl(sin->sin_addr.s_addr));
|
||||
|
||||
error = ETIMEDOUT;
|
||||
goto out;
|
||||
|
||||
@@ -482,18 +488,21 @@ bootpc_fakeup_interface(struct ifreq *ireq,struct socket *so,
|
||||
* IFF_UP set blindly, interface selection can be clobbered.
|
||||
*/
|
||||
error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, procp);
|
||||
if (error)
|
||||
panic("bootpc_fakeup_interface: GIFFLAGS, error=%d", error);
|
||||
if (error) {
|
||||
printf("bootpc_fakeup_interface: GIFFLAGS, error=%s\n", strerror(error));
|
||||
return error;
|
||||
}
|
||||
ireq->ifr_flags |= IFF_UP;
|
||||
error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, procp);
|
||||
if (error)
|
||||
panic("bootpc_fakeup_interface: SIFFLAGS, error=%d", error);
|
||||
if (error) {
|
||||
printf("bootpc_fakeup_interface: SIFFLAGS, error=%s\n", strerror(error));
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do enough of ifconfig(8) so that the chosen interface
|
||||
* can talk to the servers. (just set the address)
|
||||
*/
|
||||
|
||||
/* addr is 0.0.0.0 */
|
||||
|
||||
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_addr.s_addr = INADDR_ANY;
|
||||
error = ifioctl(so, SIOCSIFADDR, (caddr_t)ireq, procp);
|
||||
if (error)
|
||||
panic("bootpc_fakeup_interface: set if addr, error=%d", error);
|
||||
if (error) {
|
||||
printf("bootpc_fakeup_interface: set if addr, error=%s\n", strerror(error));
|
||||
return error;
|
||||
}
|
||||
|
||||
/* 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_addr.s_addr = INADDR_ANY;
|
||||
error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, procp);
|
||||
if (error)
|
||||
panic("bootpc_fakeup_interface: set if net addr, error=%d", error);
|
||||
if (error) {
|
||||
printf("bootpc_fakeup_interface: set if netmask, error=%s\n", strerror(error));
|
||||
return error;
|
||||
}
|
||||
|
||||
/* 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_addr.s_addr = INADDR_BROADCAST;
|
||||
error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, procp);
|
||||
if (error)
|
||||
panic("bootpc_fakeup_interface: set if broadcast addr, error=%d", error);
|
||||
if (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 */
|
||||
|
||||
@@ -601,8 +617,10 @@ bootpc_adjust_interface(struct ifreq *ireq,struct socket *so,
|
||||
*/
|
||||
bcopy(netmask,&ireq->ifr_addr,sizeof(*netmask));
|
||||
error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, procp);
|
||||
if (error)
|
||||
panic("nfs_boot: set if netmask, error=%d", error);
|
||||
if (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 */
|
||||
|
||||
@@ -612,13 +630,17 @@ bootpc_adjust_interface(struct ifreq *ireq,struct socket *so,
|
||||
sin->sin_family = AF_INET;
|
||||
sin->sin_addr.s_addr = myaddr->sin_addr.s_addr | ~ netmask->sin_addr.s_addr;
|
||||
error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, procp);
|
||||
if (error)
|
||||
panic("bootpc_call: set if broadcast addr, error=%d", error);
|
||||
if (error) {
|
||||
printf("bootpc_adjust_interface: set broadcast addr, error=%s\n", strerror(error));
|
||||
return error;
|
||||
}
|
||||
|
||||
bcopy(myaddr,&ireq->ifr_addr,sizeof(*myaddr));
|
||||
error = ifioctl(so, SIOCSIFADDR, (caddr_t)ireq, procp);
|
||||
if (error)
|
||||
panic("nfs_boot: set if addr, error=%d", error);
|
||||
if (error) {
|
||||
printf("bootpc_adjust_interface: set if addr, error=%s\n", strerror(error));
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Add new default route */
|
||||
|
||||
@@ -628,11 +650,10 @@ bootpc_adjust_interface(struct ifreq *ireq,struct socket *so,
|
||||
(struct sockaddr *) &oldmask,
|
||||
(RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL);
|
||||
if (error) {
|
||||
printf("nfs_boot: add net route, error=%d\n", error);
|
||||
return error;
|
||||
printf("bootpc_adjust_interface: add net route, error=%d\n", error);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
#if !defined(__rtems__)
|
||||
@@ -758,24 +779,30 @@ processOptions (unsigned char *optbuf, int optbufSize)
|
||||
switch (code) {
|
||||
case 1:
|
||||
/* Subnet mask */
|
||||
if (len!=4)
|
||||
panic("bootpc: subnet mask len is %d",len);
|
||||
if (len!=4) {
|
||||
printf("bootpc: subnet mask len is %d\n",len);
|
||||
continue;
|
||||
}
|
||||
bcopy (p, &dhcp_netmask.sin_addr, 4);
|
||||
dhcp_gotnetmask = 1;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
/* Time offset */
|
||||
if (len!=4)
|
||||
panic("bootpc: time offset len is %d",len);
|
||||
if (len!=4) {
|
||||
printf("bootpc: time offset len is %d\n",len);
|
||||
continue;
|
||||
}
|
||||
bcopy (p, &rtems_bsdnet_timeoffset, 4);
|
||||
rtems_bsdnet_timeoffset = ntohl (rtems_bsdnet_timeoffset);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
/* Routers */
|
||||
if (len % 4)
|
||||
panic ("bootpc: Router Len is %d", len);
|
||||
if (len % 4) {
|
||||
printf ("bootpc: Router Len is %d\n", len);
|
||||
continue;
|
||||
}
|
||||
if (len > 0) {
|
||||
bcopy(p, &dhcp_gw.sin_addr, 4);
|
||||
dhcp_gotgw = 1;
|
||||
@@ -784,8 +811,10 @@ processOptions (unsigned char *optbuf, int optbufSize)
|
||||
|
||||
case 42:
|
||||
/* NTP servers */
|
||||
if (len % 4)
|
||||
panic ("bootpc: time server Len is %d", len);
|
||||
if (len % 4) {
|
||||
printf ("bootpc: time server Len is %d\n", len);
|
||||
continue;
|
||||
}
|
||||
{
|
||||
int tlen = 0;
|
||||
while ((tlen < len) &&
|
||||
@@ -804,8 +833,10 @@ processOptions (unsigned char *optbuf, int optbufSize)
|
||||
|
||||
case 6:
|
||||
/* Domain Name servers */
|
||||
if (len % 4)
|
||||
panic ("bootpc: DNS Len is %d", len);
|
||||
if (len % 4) {
|
||||
printf ("bootpc: DNS Len is %d", len);
|
||||
continue;
|
||||
}
|
||||
{
|
||||
int dlen = 0;
|
||||
while ((dlen < len) &&
|
||||
@@ -824,18 +855,23 @@ processOptions (unsigned char *optbuf, int optbufSize)
|
||||
|
||||
case 12:
|
||||
/* Host name */
|
||||
if (len>=MAXHOSTNAMELEN)
|
||||
panic ("bootpc: hostname >=%d bytes", MAXHOSTNAMELEN);
|
||||
if (sethostname ((char *)p, len) < 0)
|
||||
panic("Can't set host name");
|
||||
if (len>=MAXHOSTNAMELEN) {
|
||||
printf ("bootpc: hostname >=%d bytes", MAXHOSTNAMELEN);
|
||||
continue;
|
||||
}
|
||||
if (sethostname ((char *)p, len) < 0) {
|
||||
printf("bootpc: Can't set host name");
|
||||
}
|
||||
printf("Hostname is %s\n", p);
|
||||
dhcp_hostname = bootp_strdup_realloc(dhcp_hostname,(char *)p);
|
||||
break;
|
||||
|
||||
case 7:
|
||||
/* Log servers */
|
||||
if (len % 4)
|
||||
panic ("bootpc: Log server Len is %d", len);
|
||||
if (len % 4) {
|
||||
printf ("bootpc: Log server Len is %d", len);
|
||||
continue;
|
||||
}
|
||||
if (len > 0) {
|
||||
bcopy(p, &rtems_bsdnet_log_host_address, 4);
|
||||
dhcp_gotlogserver = 1;
|
||||
@@ -856,8 +892,10 @@ processOptions (unsigned char *optbuf, int optbufSize)
|
||||
|
||||
case 52:
|
||||
/* DHCP option override */
|
||||
if (len != 1)
|
||||
panic ("bootpc: DHCP option overload len is %d", len);
|
||||
if (len != 1) {
|
||||
printf ("bootpc: DHCP option overload len is %d", len);
|
||||
continue;
|
||||
}
|
||||
dhcpOptionOverload = p[0];
|
||||
break;
|
||||
|
||||
@@ -872,8 +910,10 @@ processOptions (unsigned char *optbuf, int optbufSize)
|
||||
*/
|
||||
case 54:
|
||||
/* DHCP server */
|
||||
if (len != 4)
|
||||
panic ("bootpc: DHCP server len is %d", len);
|
||||
if (len != 4) {
|
||||
printf ("bootpc: DHCP server len is %d", len);
|
||||
continue;
|
||||
}
|
||||
bcopy(p, &rtems_bsdnet_bootp_server_address, 4);
|
||||
dhcp_gotserver = 1;
|
||||
break;
|
||||
@@ -955,19 +995,22 @@ bootpc_init(int update_files)
|
||||
if ((ifp->if_flags &
|
||||
(IFF_LOOPBACK|IFF_POINTOPOINT)) == 0)
|
||||
break;
|
||||
if (ifp == NULL)
|
||||
panic("bootpc_init: no suitable interface");
|
||||
if (ifp == NULL) {
|
||||
printf("bootpc_init: no suitable interface\n");
|
||||
return;
|
||||
}
|
||||
bzero(&ireq,sizeof(ireq));
|
||||
sprintf(ireq.ifr_name, "%s%d", ifp->if_name,ifp->if_unit);
|
||||
printf("bootpc_init: using network interface '%s'\n",
|
||||
ireq.ifr_name);
|
||||
|
||||
if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0,procp)) != 0)
|
||||
panic("nfs_boot: socreate, error=%d", error);
|
||||
|
||||
bootpc_fakeup_interface(&ireq,so,procp);
|
||||
|
||||
printf("Bootpc testing starting\n");
|
||||
if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0,procp)) != 0) {
|
||||
printf("bootpc_init: socreate, error=%d", error);
|
||||
return;
|
||||
}
|
||||
if (bootpc_fakeup_interface(&ireq,so,procp) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get HW address */
|
||||
|
||||
@@ -977,11 +1020,15 @@ bootpc_init(int update_files)
|
||||
sdl->sdl_type == IFT_ETHER)
|
||||
break;
|
||||
|
||||
if (!sdl)
|
||||
panic("bootpc: Unable to find HW address");
|
||||
if (sdl->sdl_alen != EALEN )
|
||||
panic("bootpc: HW address len is %d, expected value is %d",
|
||||
if (!sdl) {
|
||||
printf("bootpc: Unable to find HW address\n");
|
||||
return;
|
||||
}
|
||||
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 ");
|
||||
delim="";
|
||||
@@ -1018,8 +1065,10 @@ bootpc_init(int update_files)
|
||||
|
||||
error = bootpc_call(&call,&reply,procp);
|
||||
|
||||
if (error)
|
||||
panic("BOOTP call failed -- error %d", error);
|
||||
if (error) {
|
||||
printf("BOOTP call failed -- error %d", error);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize network address structures
|
||||
|
||||
@@ -290,6 +290,10 @@ $(PROJECT_INCLUDE)/rtems/dhcp.h: rtems/dhcp.h $(PROJECT_INCLUDE)/rtems/$(dirstam
|
||||
$(INSTALL_DATA) $< $(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)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/tftp.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/tftp.h
|
||||
|
||||
@@ -29,6 +29,8 @@ extern "C"
|
||||
* Perform DHCP.
|
||||
*/
|
||||
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.
|
||||
|
||||
@@ -9,6 +9,12 @@
|
||||
* 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) 1992 Regents of the University of California.
|
||||
@@ -186,7 +192,6 @@ extern int bootpc_adjust_interface (struct ifreq *ireq,
|
||||
struct proc *procp);
|
||||
extern void *bootp_strdup_realloc (char *dst,
|
||||
const char *src);
|
||||
extern int nfs_diskless_valid;
|
||||
|
||||
/*
|
||||
* Variables
|
||||
@@ -271,6 +276,8 @@ process_options (unsigned char *optbuf, int optbufSize)
|
||||
int code, ncode;
|
||||
char *p;
|
||||
|
||||
dhcp_message_type = 0;
|
||||
|
||||
ncode = optbuf[0];
|
||||
while (j < optbufSize)
|
||||
{
|
||||
@@ -303,24 +310,30 @@ process_options (unsigned char *optbuf, int optbufSize)
|
||||
{
|
||||
case 1:
|
||||
/* Subnet mask */
|
||||
if (len != 4)
|
||||
panic ("dhcpc: subnet mask len is %d", len);
|
||||
if (len != 4) {
|
||||
printf ("dhcpc: subnet mask len is %d\n", len);
|
||||
continue;
|
||||
}
|
||||
memcpy (&dhcp_netmask.sin_addr, p, 4);
|
||||
dhcp_gotnetmask = 1;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
/* Time offset */
|
||||
if (len != 4)
|
||||
panic ("dhcpc: time offset len is %d", len);
|
||||
if (len != 4) {
|
||||
printf ("dhcpc: time offset len is %d\n", len);
|
||||
continue;
|
||||
}
|
||||
memcpy (&rtems_bsdnet_timeoffset, p, 4);
|
||||
rtems_bsdnet_timeoffset = ntohl (rtems_bsdnet_timeoffset);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
/* Routers */
|
||||
if (len % 4)
|
||||
panic ("dhcpc: Router Len is %d", len);
|
||||
if (len % 4) {
|
||||
printf ("dhcpc: Router Len is %d\n", len);
|
||||
continue;
|
||||
}
|
||||
if (len > 0)
|
||||
{
|
||||
memcpy (&dhcp_gw.sin_addr, p, 4);
|
||||
@@ -330,8 +343,10 @@ process_options (unsigned char *optbuf, int optbufSize)
|
||||
|
||||
case 42:
|
||||
/* NTP servers */
|
||||
if (len % 4)
|
||||
panic ("dhcpc: time server Len is %d", len);
|
||||
if (len % 4) {
|
||||
printf ("dhcpc: time server Len is %d\n", len);
|
||||
continue;
|
||||
}
|
||||
{
|
||||
int tlen = 0;
|
||||
while ((tlen < len) &&
|
||||
@@ -349,8 +364,10 @@ process_options (unsigned char *optbuf, int optbufSize)
|
||||
|
||||
case 6:
|
||||
/* Domain Name servers */
|
||||
if (len % 4)
|
||||
panic ("dhcpc: DNS Len is %d", len);
|
||||
if (len % 4) {
|
||||
printf ("dhcpc: DNS Len is %d\n", len);
|
||||
continue;
|
||||
}
|
||||
{
|
||||
int dlen = 0;
|
||||
while ((dlen < len) &&
|
||||
@@ -368,10 +385,12 @@ process_options (unsigned char *optbuf, int optbufSize)
|
||||
|
||||
case 12:
|
||||
/* Host name */
|
||||
if (len >= MAXHOSTNAMELEN)
|
||||
panic ("dhcpc: hostname >= %d bytes", MAXHOSTNAMELEN);
|
||||
if (len >= MAXHOSTNAMELEN) {
|
||||
printf ("dhcpc: hostname >= %d bytes\n", MAXHOSTNAMELEN);
|
||||
len = MAXHOSTNAMELEN-1;
|
||||
}
|
||||
if (sethostname (p, len) < 0)
|
||||
panic ("dhcpc: can't set host name");
|
||||
printf ("dhcpc: can't set host name");
|
||||
if (dhcp_hostname != NULL)
|
||||
{
|
||||
dhcp_hostname = realloc (dhcp_hostname, len);
|
||||
@@ -383,8 +402,10 @@ process_options (unsigned char *optbuf, int optbufSize)
|
||||
|
||||
case 7:
|
||||
/* Log servers */
|
||||
if (len % 4)
|
||||
panic ("dhcpc: Log server Len is %d", len);
|
||||
if (len % 4) {
|
||||
printf ("dhcpc: Log server Len is %d\n", len);
|
||||
continue;
|
||||
}
|
||||
if (len > 0)
|
||||
{
|
||||
memcpy (&rtems_bsdnet_log_host_address, p, 4);
|
||||
@@ -406,7 +427,7 @@ process_options (unsigned char *optbuf, int optbufSize)
|
||||
case 50:
|
||||
/* DHCP Requested IP Address */
|
||||
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
|
||||
* from complaining about unknown options. The Requested IP
|
||||
@@ -416,23 +437,29 @@ process_options (unsigned char *optbuf, int optbufSize)
|
||||
|
||||
case 51:
|
||||
/* DHCP Lease Length */
|
||||
if (len != 4)
|
||||
panic ("dhcpc: DHCP option lease-length len is %d", len);
|
||||
if (len != 4) {
|
||||
printf ("dhcpc: DHCP option lease-length len is %d", len);
|
||||
continue;
|
||||
}
|
||||
memcpy (&dhcp_lease_time, &p[0], 4);
|
||||
dhcp_lease_time = ntohl (dhcp_lease_time);
|
||||
break;
|
||||
|
||||
case 52:
|
||||
/* DHCP option override */
|
||||
if (len != 1)
|
||||
panic ("dhcpc: DHCP option overload len is %d", len);
|
||||
if (len != 1) {
|
||||
printf ("dhcpc: DHCP option overload len is %d", len);
|
||||
continue;
|
||||
}
|
||||
dhcp_option_overload = p[0];
|
||||
break;
|
||||
|
||||
case 53:
|
||||
/* DHCP message */
|
||||
if (len != 1)
|
||||
panic ("dhcpc: DHCP message len is %d", len);
|
||||
if (len != 1) {
|
||||
printf ("dhcpc: DHCP message len is %d", len);
|
||||
continue;
|
||||
}
|
||||
dhcp_message_type = p[0];
|
||||
break;
|
||||
|
||||
@@ -447,8 +474,10 @@ process_options (unsigned char *optbuf, int optbufSize)
|
||||
*/
|
||||
case 54:
|
||||
/* DHCP server */
|
||||
if (len != 4)
|
||||
panic ("dhcpc: DHCP server len is %d", len);
|
||||
if (len != 4) {
|
||||
printf ("dhcpc: DHCP server len is %d", len);
|
||||
continue;
|
||||
}
|
||||
memcpy (&rtems_bsdnet_bootp_server_address, p, 4);
|
||||
dhcp_gotserver = 1;
|
||||
break;
|
||||
@@ -667,13 +696,28 @@ dhcp_task (rtems_task_argument _sdl)
|
||||
unsigned int timeout = 0;
|
||||
int error;
|
||||
struct proc *procp = NULL;
|
||||
int disconnected;
|
||||
|
||||
sdl = (struct sockaddr_dl *) _sdl;
|
||||
|
||||
count = dhcp_elapsed_time;
|
||||
disconnected = 0;
|
||||
|
||||
|
||||
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))
|
||||
{
|
||||
rtems_bsdnet_semaphore_obtain ();
|
||||
@@ -684,9 +728,11 @@ dhcp_task (rtems_task_argument _sdl)
|
||||
* Send the Request.
|
||||
*/
|
||||
error = bootpc_call (&call, &dhcp_req, procp);
|
||||
|
||||
if (error)
|
||||
panic ("DHCP call failed -- error %d", error);
|
||||
if (error) {
|
||||
rtems_bsdnet_semaphore_release ();
|
||||
printf ("DHCP call failed -- error %d", error);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for DHCP ACK/NACK
|
||||
@@ -696,7 +742,8 @@ dhcp_task (rtems_task_argument _sdl)
|
||||
sizeof (dhcp_magic_cookie)) != 0)
|
||||
{
|
||||
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);
|
||||
@@ -704,23 +751,21 @@ dhcp_task (rtems_task_argument _sdl)
|
||||
if (dhcp_message_type != DHCP_ACK)
|
||||
{
|
||||
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 ();
|
||||
|
||||
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
|
||||
* - The first DHCP offer is always accepted
|
||||
* - 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)
|
||||
{
|
||||
struct dhcp_packet call;
|
||||
@@ -812,12 +861,6 @@ dhcp_init (int update_files)
|
||||
struct sockaddr_dl *sdl = 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
|
||||
* file structure.
|
||||
@@ -834,13 +877,18 @@ dhcp_init (int update_files)
|
||||
for (ifp = ifnet; ifp != 0; ifp = ifp->if_next)
|
||||
if ((ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) == 0)
|
||||
break;
|
||||
if (ifp == NULL)
|
||||
panic ("dhcpc_init: no suitable interface");
|
||||
if (ifp == NULL){
|
||||
printf ("dhcpc_init: no suitable interface\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset (&ireq, 0, sizeof (ireq));
|
||||
sprintf (ireq.ifr_name, "%s%d", ifp->if_name, ifp->if_unit);
|
||||
|
||||
if ((error = socreate (AF_INET, &so, SOCK_DGRAM, 0, procp)) != 0)
|
||||
panic ("nfs_boot: socreate, error=%d", error);
|
||||
if ((error = socreate (AF_INET, &so, SOCK_DGRAM, 0, procp)) != 0) {
|
||||
printf ("dhcpc_init: socreate, error=%d\n", error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!dhcp_interface_has_ip (&ireq, so, procp))
|
||||
bootpc_fakeup_interface (&ireq, so, procp);
|
||||
@@ -854,11 +902,15 @@ dhcp_init (int update_files)
|
||||
sdl->sdl_type == IFT_ETHER)
|
||||
break;
|
||||
|
||||
if (!sdl)
|
||||
panic ("dhcpc: Unable to find HW address");
|
||||
if (sdl->sdl_alen != EALEN)
|
||||
panic ("dhcpc: HW address len is %d, expected value is %d",
|
||||
if (!sdl){
|
||||
printf ("dhcpc_init: Unable to find HW address\n");
|
||||
return -1;
|
||||
}
|
||||
if (sdl->sdl_alen != EALEN) {
|
||||
printf ("dhcpc_init: HW address len is %d, expected value is %d\n",
|
||||
sdl->sdl_alen, EALEN);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Build the DHCP Discover
|
||||
@@ -869,19 +921,25 @@ dhcp_init (int update_files)
|
||||
* Send the Discover.
|
||||
*/
|
||||
error = bootpc_call (&call, &reply, procp);
|
||||
if (error)
|
||||
panic ("BOOTP call failed -- error %d", error);
|
||||
if (error) {
|
||||
printf ("BOOTP call failed -- error %d\n", error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for DHCP OFFER
|
||||
*/
|
||||
if (memcmp (&reply.vend[0], dhcp_magic_cookie, sizeof (dhcp_magic_cookie)) != 0)
|
||||
panic ("DHCP server did not send Magic Cookie.\n");
|
||||
if (memcmp (&reply.vend[0], dhcp_magic_cookie, sizeof (dhcp_magic_cookie)) != 0) {
|
||||
printf ("DHCP server did not send Magic Cookie.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
process_options (&reply.vend[4], sizeof (reply.vend) - 4);
|
||||
|
||||
if (dhcp_message_type != DHCP_OFFER)
|
||||
panic ("DHCP server did not send a DHCP Offer.\n");
|
||||
if (dhcp_message_type != DHCP_OFFER) {
|
||||
printf ("DHCP server did not send a DHCP Offer.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a DHCP REQUEST
|
||||
@@ -889,19 +947,25 @@ dhcp_init (int update_files)
|
||||
dhcp_request_req (&call, &reply, sdl, TRUE);
|
||||
|
||||
error = bootpc_call (&call, &reply, procp);
|
||||
if (error)
|
||||
panic ("BOOTP call failed -- error %d", error);
|
||||
if (error) {
|
||||
printf ("BOOTP call failed -- error %d\n", error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for DHCP ACK/NACK
|
||||
*/
|
||||
if (memcmp (&reply.vend[0], dhcp_magic_cookie, sizeof (dhcp_magic_cookie)) != 0)
|
||||
panic ("DHCP server did not send Magic Cookie.\n");
|
||||
if (memcmp (&reply.vend[0], dhcp_magic_cookie, sizeof (dhcp_magic_cookie)) != 0) {
|
||||
printf ("DHCP server did not send Magic Cookie.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
process_options (&reply.vend[4], sizeof (reply.vend) - 4);
|
||||
|
||||
if (dhcp_message_type != DHCP_ACK)
|
||||
panic ("DHCP server did not accept the DHCP request");
|
||||
if (dhcp_message_type != DHCP_ACK) {
|
||||
printf ("DHCP server did not accept the DHCP request\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize network address structures
|
||||
@@ -1039,6 +1103,8 @@ dhcp_init (int update_files)
|
||||
dhcp_start_task (sdl, &reply, 150);
|
||||
|
||||
soclose (so);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1049,10 +1115,32 @@ dhcp_init (int update_files)
|
||||
void rtems_bsdnet_do_dhcp (void)
|
||||
{
|
||||
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 ();
|
||||
}
|
||||
|
||||
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
|
||||
rtems_bsdnet_do_dhcp_refresh_only (unsigned long xid,
|
||||
unsigned long lease_time,
|
||||
@@ -1092,8 +1180,10 @@ rtems_bsdnet_do_dhcp_refresh_only (unsigned long xid,
|
||||
}
|
||||
}
|
||||
|
||||
if (!match)
|
||||
panic ("dhcpc: no matching interface");
|
||||
if (!match) {
|
||||
printf ("dhcpc: no matching interface\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (ifa = mtif->if_addrlist; ifa != NULL; ifa = ifa->ifa_next)
|
||||
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)
|
||||
break;
|
||||
|
||||
if (!match)
|
||||
panic ("dhcpc: no matching interface");
|
||||
if (!match) {
|
||||
printf ("dhcpc: no matching interface address\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up given values in a simulated DHCP reply.
|
||||
|
||||
372
cpukit/libnetworking/rtems/rtems_dhcp_failsafe.c
Normal file
372
cpukit/libnetworking/rtems/rtems_dhcp_failsafe.c
Normal 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
|
||||
}
|
||||
|
||||
29
cpukit/libnetworking/rtems/rtems_dhcp_failsafe.h
Normal file
29
cpukit/libnetworking/rtems/rtems_dhcp_failsafe.h
Normal 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
|
||||
@@ -1127,7 +1127,7 @@ int rtems_bsdnet_ifconfig (const char *ifname, uint32_t cmd, void *param)
|
||||
|
||||
case SIOCAIFADDR:
|
||||
case SIOCDIFADDR:
|
||||
r = ioctl(s, cmd, (struct freq *) param);
|
||||
r = ioctl(s, cmd, (struct ifreq *) param);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user