summaryrefslogtreecommitdiffstats
path: root/c/src/exec/libnetworking
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>1998-11-19 17:35:49 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>1998-11-19 17:35:49 +0000
commit847375f3ad4af55b9bd4d8a6daff313165de5fd8 (patch)
tree53d4acf4aaffaaaa6e7aafa52f2457fdf2758e44 /c/src/exec/libnetworking
parentChanged BOOTP -> BOOTP/DHCP. (diff)
downloadrtems-847375f3ad4af55b9bd4d8a6daff313165de5fd8.tar.bz2
Patch from Eric Norum <eric@skatter.usask.ca>:
1) Socket timeout field changed from `short' to `long'. This makes longer timeouts possible. With a 1 kHz system clock the old system allowed timeouts only up to a little over 30 seconds! This change is a slightly cleaned-up version of the patch proposed by Ian Lance Taylor. 2) Major changes to BOOTP/DHCP reply handling. Now supports much of RFC2132. These changes were done at the request of, and with the assistance of, Erik Ivanenko. If you're making changes, you might want to change the network supplement Essentially just do a global search and replace of BOOTP with BOOTP/DHCP.
Diffstat (limited to 'c/src/exec/libnetworking')
-rw-r--r--c/src/exec/libnetworking/kern/uipc_socket.c7
-rw-r--r--c/src/exec/libnetworking/nfs/bootp_subr.c381
-rw-r--r--c/src/exec/libnetworking/rtems/rtems_bsdnet.h1
-rw-r--r--c/src/exec/libnetworking/rtems/rtems_glue.c1
-rw-r--r--c/src/exec/libnetworking/sys/socketvar.h4
5 files changed, 220 insertions, 174 deletions
diff --git a/c/src/exec/libnetworking/kern/uipc_socket.c b/c/src/exec/libnetworking/kern/uipc_socket.c
index 895d1c7d45..04489f4017 100644
--- a/c/src/exec/libnetworking/kern/uipc_socket.c
+++ b/c/src/exec/libnetworking/kern/uipc_socket.c
@@ -49,6 +49,7 @@
#include <sys/resourcevar.h>
#include <sys/signalvar.h>
#include <sys/sysctl.h>
+#include <limits.h>
static int somaxconn = SOMAXCONN;
SYSCTL_INT(_kern, KERN_SOMAXCONN, somaxconn, CTLFLAG_RW, &somaxconn, 0, "");
@@ -948,14 +949,14 @@ sosetopt(so, level, optname, m0)
case SO_RCVTIMEO:
{
struct timeval *tv;
- short val;
+ unsigned long val;
if (m == NULL || m->m_len < sizeof (*tv)) {
error = EINVAL;
goto bad;
}
tv = mtod(m, struct timeval *);
- if (tv->tv_sec > SHRT_MAX / hz - hz) {
+ if (tv->tv_sec >= (ULONG_MAX - hz) / hz) {
error = EDOM;
goto bad;
}
@@ -1065,7 +1066,7 @@ sogetopt(so, level, optname, mp)
case SO_SNDTIMEO:
case SO_RCVTIMEO:
{
- int val = (optname == SO_SNDTIMEO ?
+ unsigned long val = (optname == SO_SNDTIMEO ?
so->so_snd.sb_timeo : so->so_rcv.sb_timeo);
m->m_len = sizeof(struct timeval);
diff --git a/c/src/exec/libnetworking/nfs/bootp_subr.c b/c/src/exec/libnetworking/nfs/bootp_subr.c
index cb7d3d3407..f6831eed71 100644
--- a/c/src/exec/libnetworking/nfs/bootp_subr.c
+++ b/c/src/exec/libnetworking/nfs/bootp_subr.c
@@ -682,6 +682,162 @@ static void printip(char *prefix,struct in_addr addr)
ip >> 24, (ip >> 16) & 255 ,(ip >> 8) & 255 ,ip & 255 );
}
+static int dhcpOptionOverload = 0;
+static char dhcp_gotgw = 0;
+static char dhcp_gotnetmask = 0;
+static char dhcp_gotserver = 0;
+static char dhcp_gotlogserver = 0;
+static struct sockaddr_in dhcp_netmask;
+static struct sockaddr_in dhcp_gw;
+
+static void
+processOptions (unsigned char *optbuf, int optbufSize)
+{
+ int j = 0;
+ int len;
+ int code, ncode;
+ char *p;
+
+ ncode = optbuf[0];
+ while (j < optbufSize) {
+ code = optbuf[j] = ncode;
+ if (code == 255)
+ return;
+ if (code == 0) {
+ j++;
+ continue;
+ }
+ len = optbuf[j+1];
+ j += 2;
+ if ((len + j) >= optbufSize) {
+ printf ("Truncated field for code %d", code);
+ return;
+ }
+ ncode = optbuf[j+len];
+ optbuf[j+len] = '\0';
+ p = &optbuf[j];
+ j += len;
+
+ /*
+ * Process the option
+ */
+ switch (code) {
+ case 1:
+ /* Subnet mask */
+ if (len!=4)
+ panic("bootpc: subnet mask len is %d",len);
+ bcopy (p, &dhcp_netmask.sin_addr, 4);
+ dhcp_gotnetmask = 1;
+ break;
+
+ case 2: /* Time offset, unused */
+ break;
+
+ case 3:
+ /* Routers */
+ if (len % 4)
+ panic ("bootpc: Router Len is %d", len);
+ if (len > 0) {
+ bcopy(p, &dhcp_gw.sin_addr, 4);
+ dhcp_gotgw = 1;
+ }
+ break;
+
+ case 6:
+ /* Domain Name servers */
+ if (len % 4)
+ panic ("bootpc: DNS Len is %d", len);
+ {
+ int dlen = 0;
+ while ((dlen < len) &&
+ (rtems_bsdnet_nameserver_count < sizeof rtems_bsdnet_config.name_server /
+ sizeof rtems_bsdnet_config.name_server[0])) {
+ bcopy (p+dlen,
+ &rtems_bsdnet_nameserver[rtems_bsdnet_nameserver_count],
+ 4);
+ printip("Domain Name Server",
+ rtems_bsdnet_nameserver[rtems_bsdnet_nameserver_count]);
+ rtems_bsdnet_nameserver_count++;
+ dlen += 4;
+ }
+ }
+ break;
+
+ case 12:
+ /* Host name */
+ if (len>=MAXHOSTNAMELEN)
+ panic ("bootpc: hostname >=%d bytes", MAXHOSTNAMELEN);
+ if (sethostname (p, len) < 0)
+ panic("Can't set host name");
+ printf("Hostname is %s\n", p);
+ break;
+
+ case 7:
+ /* Log servers */
+ if (len % 4)
+ panic ("bootpc: Log server Len is %d", len);
+ if (len > 0) {
+ bcopy(p, &rtems_bsdnet_log_host_address, 4);
+ dhcp_gotlogserver = 1;
+ }
+ break;
+
+ case 15:
+ /* Domain name */
+ if (p[0]) {
+ rtems_bsdnet_domain_name = strdup (p);
+ printf("Domain name is %s\n", rtems_bsdnet_domain_name);
+ }
+ break;
+
+ case 16: /* Swap server IP address. unused */
+ break;
+
+ case 52:
+ /* DHCP option override */
+ if (len != 1)
+ panic ("bootpc: DHCP option overload len is %d", len);
+ dhcpOptionOverload = p[0];
+ break;
+
+ case 128: /* Site-specific option for DHCP servers that
+ * a) don't supply tag 54
+ * and
+ * b) don't supply the server address in siaddr
+ * For example, on Solaris 2.6 in.dhcpd, include in the dhcptab:
+ * Bootsrv s Site,128,IP,1,1
+ * and use that symbol in the macro that defines the client:
+ * Bootsrv=<tftp-server-ip-address>
+ */
+ case 54:
+ /* DHCP server */
+ if (len != 4)
+ panic ("bootpc: DHCP server len is %d", len);
+ bcopy(p, &rtems_bsdnet_bootp_server_address, 4);
+ dhcp_gotserver = 1;
+ break;
+
+ case 66:
+ /* DHCP server name option */
+ if (p[0])
+ rtems_bsdnet_bootp_server_name = strdup (p);
+ break;
+
+ case 67:
+ /* DHCP bootfile option */
+ if (p[0])
+ rtems_bsdnet_bootp_boot_file_name = strdup (p);
+ break;
+
+ default:
+ printf ("Ignoring BOOTP/DHCP option code %d\n", code);
+ break;
+ }
+ }
+}
+
+#define EALEN 6
+
void
bootpc_init(void)
{
@@ -692,27 +848,9 @@ bootpc_init(void)
struct ifreq ireq;
struct ifnet *ifp;
struct socket *so;
- int error;
- int code,ncode,len;
int j;
- char *p;
- unsigned int ip;
-
+ int error;
struct sockaddr_in myaddr;
- struct sockaddr_in netmask;
- struct sockaddr_in gw;
- int gotgw=0;
- int gotnetmask=0;
-#if !defined(__rtems__)
- int gotrootpath=0;
- int gotswappath=0;
-#endif
- char lookup_path[24];
-
-#define EALEN 6
-#if !defined(__rtems__)
- unsigned char ea[EALEN];
-#endif
struct ifaddr *ifa;
struct sockaddr_dl *sdl = NULL;
char *delim;
@@ -725,12 +863,6 @@ bootpc_init(void)
return;
/*
- * Bump time if 0.
- if (!time.tv_sec)
- time.tv_sec++;
- */
-
- /*
* Find a network interface.
*/
for (ifp = ifnet; ifp != 0; ifp = ifp->if_next)
@@ -803,166 +935,77 @@ bootpc_init(void)
if (error)
panic("BOOTP call failed -- error %d", error);
+ /*
+ * Initialize network address structures
+ */
bzero(&myaddr,sizeof(myaddr));
- bzero(&netmask,sizeof(netmask));
- bzero(&gw,sizeof(gw));
-
+ bzero(&dhcp_netmask,sizeof(dhcp_netmask));
+ bzero(&dhcp_gw,sizeof(dhcp_gw));
myaddr.sin_len = sizeof(myaddr);
myaddr.sin_family = AF_INET;
+ dhcp_netmask.sin_len = sizeof(dhcp_netmask);
+ dhcp_netmask.sin_family = AF_INET;
+ dhcp_gw.sin_len = sizeof(dhcp_gw);
+ dhcp_gw.sin_family= AF_INET;
- netmask.sin_len = sizeof(netmask);
- netmask.sin_family = AF_INET;
-
- gw.sin_len = sizeof(gw);
- gw.sin_family= AF_INET;
-
- rtems_bsdnet_bootp_server_address = reply.siaddr;
- rtems_bsdnet_log_host_address = reply.siaddr;
-
+ /*
+ * Set our address
+ */
myaddr.sin_addr = reply.yiaddr;
-
- ip = ntohl(myaddr.sin_addr.s_addr);
- sprintf(lookup_path,"swap.%d.%d.%d.%d",
- ip >> 24, (ip >> 16) & 255 ,(ip >> 8) & 255 ,ip & 255 );
-
printip("My ip address",myaddr.sin_addr);
- printip("Server ip address",reply.siaddr);
-
- gw.sin_addr = reply.giaddr;
- printip("Gateway ip address",reply.giaddr);
-
- if (reply.sname[0])
- printf("Server name is %s\n",reply.sname);
- if (reply.file[0])
- printf("boot file is %s\n",reply.file);
- rtems_bsdnet_bootp_boot_file_name = strdup (reply.file);
+ /*
+ * Process BOOTP/DHCP options
+ */
if (reply.vend[0]==99 && reply.vend[1]==130 &&
reply.vend[2]==83 && reply.vend[3]==99) {
- j=4;
- ncode = reply.vend[j];
- while (j<sizeof(reply.vend)) {
- code = reply.vend[j] = ncode;
- if (code==255)
- break;
- if (code==0) {
- j++;
- continue;
- }
- len = reply.vend[j+1];
- j+=2;
- if (len+j>=sizeof(reply.vend)) {
- printf("Truncated field");
- break;
- }
- ncode = reply.vend[j+len];
- reply.vend[j+len]='\0';
- p = &reply.vend[j];
- switch (code) {
- case 1:
- if (len!=4)
- panic("bootpc: subnet mask len is %d",len);
- bcopy(&reply.vend[j],&netmask.sin_addr,4);
- gotnetmask=1;
- printip("Subnet mask",netmask.sin_addr);
- break;
- case 6:
- /* Domain Name servers */
- if (len % 4)
- panic("bootpc: DNS Len is %d",len);
- {
- int dlen = 0;
- while ((dlen < len) &&
- (rtems_bsdnet_nameserver_count < sizeof rtems_bsdnet_config.name_server /
- sizeof rtems_bsdnet_config.name_server[0])) {
- bcopy(&reply.vend[j+dlen],
- &rtems_bsdnet_nameserver[rtems_bsdnet_nameserver_count],
- 4);
- printip("Domain Name Server",
- rtems_bsdnet_nameserver[rtems_bsdnet_nameserver_count]);
- rtems_bsdnet_nameserver_count++;
- dlen += 4;
- }
- }
- break;
- case 16: /* Swap server IP address. unused */
- case 2:
- /* Time offset */
- break;
- case 3:
- /* Routers */
- if (len % 4)
- panic("bootpc: Router Len is %d",len);
- if (len > 0) {
- bcopy(&reply.vend[j],&gw.sin_addr,4);
- printip("Router",gw.sin_addr);
- gotgw=1;
- }
- break;
- case 7:
- /* Log servers */
- if (len % 4)
- panic("bootpc: Log server len is %d",len);
- if (len > 0) {
- bcopy(&reply.vend[j],&rtems_bsdnet_log_host_address,4);
- printip("Log server",rtems_bsdnet_log_host_address);
- }
- break;
- case 12:
- if (len>=MAXHOSTNAMELEN)
- panic("bootpc: hostname >=%d bytes",MAXHOSTNAMELEN);
- if (sethostname (&reply.vend[j], len) < 0)
- panic("Can't set host name");
- printf("Hostname is %.*s\n",len,&reply.vend[j]);
- break;
- case 15:
- /* Domain name */
- rtems_bsdnet_domain_name = strdup (&reply.vend[j]);
- if (rtems_bsdnet_domain_name)
- printf("Domain name is %s\n", rtems_bsdnet_domain_name);
- break;
- default:
- printf("Ignoring field type %d\n",code);
- }
- j+=len;
- }
+ processOptions (&reply.vend[4], sizeof(reply.vend) - 4);
+ }
+ if (dhcpOptionOverload & 1) {
+ processOptions (reply.file, sizeof reply.file);
+ }
+ else {
+ if (reply.file[0])
+ rtems_bsdnet_bootp_boot_file_name = strdup (reply.file);
+ }
+ if (dhcpOptionOverload & 2) {
+ processOptions (reply.sname, sizeof reply.sname);
}
+ else {
+ if (reply.sname[0])
+ rtems_bsdnet_bootp_server_name = strdup (reply.sname);
+ }
+ if (rtems_bsdnet_bootp_server_name)
+ printf ("Server name is %s\n", rtems_bsdnet_bootp_server_name);
+ if (rtems_bsdnet_bootp_boot_file_name)
+ printf ("Boot file is %s\n", rtems_bsdnet_bootp_boot_file_name);
- if (!gotnetmask) {
+ /*
+ * Use defaults if values were not supplied by BOOTP/DHCP options
+ */
+ if (!dhcp_gotnetmask) {
if (IN_CLASSA(ntohl(myaddr.sin_addr.s_addr)))
- netmask.sin_addr.s_addr = htonl(IN_CLASSA_NET);
+ dhcp_netmask.sin_addr.s_addr = htonl(IN_CLASSA_NET);
else if (IN_CLASSB(ntohl(myaddr.sin_addr.s_addr)))
- netmask.sin_addr.s_addr = htonl(IN_CLASSB_NET);
+ dhcp_netmask.sin_addr.s_addr = htonl(IN_CLASSB_NET);
else
- netmask.sin_addr.s_addr = htonl(IN_CLASSC_NET);
- }
- if (!gotgw) {
- /* Use proxyarp */
- gw.sin_addr.s_addr = myaddr.sin_addr.s_addr;
+ dhcp_netmask.sin_addr.s_addr = htonl(IN_CLASSC_NET);
}
+ printip ("Subnet mask", dhcp_netmask.sin_addr);
+ if (!dhcp_gotserver)
+ rtems_bsdnet_bootp_server_address = reply.siaddr;
+ printip ("Server ip address" ,rtems_bsdnet_bootp_server_address);
+ if (!dhcp_gotgw)
+ dhcp_gw.sin_addr = reply.giaddr;
+ printip ("Gateway ip address", dhcp_gw.sin_addr);
+ if (!dhcp_gotlogserver)
+ rtems_bsdnet_log_host_address = rtems_bsdnet_bootp_server_address;
+ printip ("Log server ip address", rtems_bsdnet_log_host_address);
-#if 0
- bootpboot_p_iflist();
- bootpboot_p_rtlist();
-#endif
+ /*
+ * Configure the interface with the new settings
+ */
error = bootpc_adjust_interface(&ireq,so,
- &myaddr,&netmask,&gw,procp);
-
+ &myaddr,&dhcp_netmask,&dhcp_gw,procp);
soclose(so);
-
-#if 0
- bootpboot_p_iflist();
- bootpboot_p_rtlist();
-#endif
-
-
-#if 0
- myaddr.sin_addr.s_addr | ~ netmask.sin_addr.s_addr;
-#endif
-
-#if 0
- bootpboot_p_iflist();
- bootpboot_p_rtlist();
-#endif
- return;
}
diff --git a/c/src/exec/libnetworking/rtems/rtems_bsdnet.h b/c/src/exec/libnetworking/rtems/rtems_bsdnet.h
index 73ad92fa30..6447749f80 100644
--- a/c/src/exec/libnetworking/rtems/rtems_bsdnet.h
+++ b/c/src/exec/libnetworking/rtems/rtems_bsdnet.h
@@ -11,6 +11,7 @@
* Values that may be obtained by BOOTP
*/
extern struct in_addr rtems_bsdnet_bootp_server_address;
+extern char *rtems_bsdnet_bootp_server_name;
extern char *rtems_bsdnet_bootp_boot_file_name;
/*
diff --git a/c/src/exec/libnetworking/rtems/rtems_glue.c b/c/src/exec/libnetworking/rtems/rtems_glue.c
index dd80a13d08..aea0a548b2 100644
--- a/c/src/exec/libnetworking/rtems/rtems_glue.c
+++ b/c/src/exec/libnetworking/rtems/rtems_glue.c
@@ -85,6 +85,7 @@ int nfs_diskless_valid;
struct in_addr rtems_bsdnet_log_host_address;
struct in_addr rtems_bsdnet_bootp_server_address;
char *rtems_bsdnet_bootp_boot_file_name;
+char *rtems_bsdnet_bootp_server_name;
char *rtems_bsdnet_domain_name;
struct in_addr rtems_bsdnet_nameserver[sizeof rtems_bsdnet_config.name_server /
sizeof rtems_bsdnet_config.name_server[0]];
diff --git a/c/src/exec/libnetworking/sys/socketvar.h b/c/src/exec/libnetworking/sys/socketvar.h
index 257fee012b..0eae3d4aa5 100644
--- a/c/src/exec/libnetworking/sys/socketvar.h
+++ b/c/src/exec/libnetworking/sys/socketvar.h
@@ -72,7 +72,7 @@ struct socket {
short so_incqlen; /* number of unaccepted incomplete
connections */
short so_qlimit; /* max number queued connections */
- short so_timeo; /* connection timeout */
+ u_long so_timeo; /* connection timeout */
u_short so_error; /* error affecting connection */
pid_t so_pgid; /* pgid for signals */
u_long so_oobmark; /* chars to oob mark */
@@ -88,7 +88,7 @@ struct socket {
struct mbuf *sb_mb; /* the mbuf chain */
struct selinfo sb_sel; /* process selecting read/write */
short sb_flags; /* flags, see below */
- short sb_timeo; /* timeout for read/write */
+ u_long sb_timeo; /* timeout for read/write */
} so_rcv, so_snd;
#define SB_MAX (256*1024) /* default for max chars in sockbuf */
#define SB_LOCK 0x01 /* lock on data queue */