summaryrefslogtreecommitdiffstats
path: root/cpukit/libnetworking/rtems/rtems_glue.c
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2000-06-14 17:18:18 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2000-06-14 17:18:18 +0000
commit6f93bb49b4df8f573a8914219841a1d64fde2b6d (patch)
tree222185fa3f33d4bbda5c87ef3e9ed4ae83d61148 /cpukit/libnetworking/rtems/rtems_glue.c
parentPatch rtems-rc-20000614-2-cvs.diff from Ralf Corsepius (diff)
downloadrtems-6f93bb49b4df8f573a8914219841a1d64fde2b6d.tar.bz2
Patch from Chris Johns <cjohns@cybertec.com.au> to enhance network
initialization. This adds an interface which makes it easier to control the BSD stack from user code. The BSD stack initialise uses it. It is a sort of `function' interface for an ifconfig command. I also added support for attaching and removing interfaces. With hot swap PCI comming online support for hot swap PCI will be an important factor in "state of art" RTOS's. This is also part of a general move on my part to allow RTEMS to be configured at runtime by calls rather than table driven at initialisation.
Diffstat (limited to '')
-rw-r--r--cpukit/libnetworking/rtems/rtems_glue.c220
1 files changed, 179 insertions, 41 deletions
diff --git a/cpukit/libnetworking/rtems/rtems_glue.c b/cpukit/libnetworking/rtems/rtems_glue.c
index 4213b91a2c..31b44a6656 100644
--- a/cpukit/libnetworking/rtems/rtems_glue.c
+++ b/cpukit/libnetworking/rtems/rtems_glue.c
@@ -738,8 +738,7 @@ static int
rtems_bsdnet_setup (void)
{
struct rtems_bsdnet_ifconfig *ifp;
- int s;
- struct ifreq ifreq;
+ short flags;
struct sockaddr_in address;
struct sockaddr_in netmask;
struct sockaddr_in broadcast;
@@ -777,31 +776,17 @@ rtems_bsdnet_setup (void)
/*
* Configure interfaces
*/
- s = socket (AF_INET, SOCK_DGRAM, 0);
- if (s < 0) {
- printf ("Can't create initial socket: %s\n", strerror (errno));
- return -1;
- }
for (ifp = rtems_bsdnet_config.ifconfig ; ifp ; ifp = ifp->next) {
if (ifp->ip_address == NULL)
continue;
/*
- * Get the interface flags
- */
- strcpy (ifreq.ifr_name, ifp->name);
- if (ioctl (s, SIOCGIFFLAGS, &ifreq) < 0) {
- printf ("Can't get %s flags: %s\n", ifp->name, strerror (errno));
- return -1;
- }
-
- /*
* Bring interface up
*/
- ifreq.ifr_flags |= IFF_UP;
- if (ioctl (s, SIOCSIFFLAGS, &ifreq) < 0) {
+ flags = IFF_UP;
+ if (rtems_bsdnet_ifconfig (ifp->name, SIOCSIFFLAGS, &flags) < 0) {
printf ("Can't bring %s up: %s\n", ifp->name, strerror (errno));
- return -1;
+ continue;
}
/*
@@ -811,10 +796,9 @@ rtems_bsdnet_setup (void)
netmask.sin_len = sizeof netmask;
netmask.sin_family = AF_INET;
netmask.sin_addr.s_addr = inet_addr (ifp->ip_netmask);
- memcpy (&ifreq.ifr_addr, &netmask, sizeof netmask);
- if (ioctl (s, SIOCSIFNETMASK, &ifreq) < 0) {
+ if (rtems_bsdnet_ifconfig (ifp->name, SIOCSIFNETMASK, &netmask) < 0) {
printf ("Can't set %s netmask: %s\n", ifp->name, strerror (errno));
- return -1;
+ continue;
}
/*
@@ -824,30 +808,35 @@ rtems_bsdnet_setup (void)
address.sin_len = sizeof address;
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr (ifp->ip_address);
- memcpy (&ifreq.ifr_addr, &address, sizeof address);
- if (ioctl (s, SIOCSIFADDR, &ifreq) < 0) {
+ if (rtems_bsdnet_ifconfig (ifp->name, SIOCSIFADDR, &address) < 0) {
printf ("Can't set %s address: %s\n", ifp->name, strerror (errno));
- return -1;
+ continue;
}
/*
- * Set interface broadcast address
+ * Set interface broadcast address if the interface has the
+ * broadcast flag set.
*/
- 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;
- memcpy (&ifreq.ifr_broadaddr, &broadcast, sizeof broadcast);
- if (ioctl (s, SIOCSIFBRDADDR, &ifreq) < 0)
- printf ("Can't set %s broadcast address: %s\n", ifp->name, strerror (errno));
+ if (rtems_bsdnet_ifconfig (ifp->name, SIOCGIFFLAGS, &flags) < 0) {
+ printf ("Can't read %s flags: %s\n", ifp->name, strerror (errno));
+ continue;
+ }
+ 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;
+ in_addr.s_addr = broadcast.sin_addr.s_addr;
+ printf ("Can't set %s broadcast address %s: %s\n",
+ ifp->name, inet_ntoa (in_addr), strerror (errno));
+ }
+ }
}
/*
- * We're done with the dummy socket
- */
- close (s);
-
- /*
* Set default route
*/
if (rtems_bsdnet_config.gateway) {
@@ -889,9 +878,7 @@ rtems_bsdnet_initialize_network (void)
* Attach interfaces
*/
for (ifp = rtems_bsdnet_config.ifconfig ; ifp ; ifp = ifp->next) {
- rtems_bsdnet_semaphore_obtain ();
- (ifp->attach)(ifp);
- rtems_bsdnet_semaphore_release ();
+ rtems_bsdnet_attach (ifp);
}
/*
@@ -905,6 +892,157 @@ rtems_bsdnet_initialize_network (void)
}
/*
+ * Attach a network interface.
+ */
+void rtems_bsdnet_attach (struct rtems_bsdnet_ifconfig *ifp)
+{
+ if (ifp) {
+ rtems_bsdnet_semaphore_obtain ();
+ (ifp->attach)(ifp, 1);
+ rtems_bsdnet_semaphore_release ();
+ }
+}
+
+/*
+ * Detach a network interface.
+ */
+void rtems_bsdnet_detach (struct rtems_bsdnet_ifconfig *ifp)
+{
+ if (ifp) {
+ rtems_bsdnet_semaphore_obtain ();
+ (ifp->attach)(ifp, 0);
+ rtems_bsdnet_semaphore_release ();
+ }
+}
+
+/*
+ * Interface Configuration.
+ */
+int rtems_bsdnet_ifconfig (const char *ifname, unsigned32 cmd, void *param)
+{
+ int s, r = 0;
+ struct ifreq ifreq;
+
+ /*
+ * Configure interfaces
+ */
+ s = socket (AF_INET, SOCK_DGRAM, 0);
+ if (s < 0)
+ return -1;
+
+ strncpy (ifreq.ifr_name, ifname, IFNAMSIZ);
+
+ rtems_bsdnet_semaphore_obtain ();
+
+ switch (cmd) {
+ case SIOCSIFADDR:
+ case SIOCSIFNETMASK:
+ memcpy (&ifreq.ifr_addr, param, sizeof (struct sockaddr));
+ r = ioctl (s, cmd, &ifreq);
+ break;
+
+ case OSIOCGIFADDR:
+ case SIOCGIFADDR:
+ case OSIOCGIFNETMASK:
+ case SIOCGIFNETMASK:
+ if ((r = ioctl (s, cmd, &ifreq)) < 0)
+ break;
+ memcpy (param, &ifreq.ifr_addr, sizeof (struct sockaddr));
+ break;
+
+ case SIOCGIFFLAGS:
+ case SIOCSIFFLAGS:
+ if ((r = ioctl (s, SIOCGIFFLAGS, &ifreq)) < 0)
+ break;
+ if (cmd == SIOCGIFFLAGS) {
+ *((short*) param) = ifreq.ifr_flags;
+ break;
+ }
+ ifreq.ifr_flags |= *((short*) param);
+ r = ioctl (s, SIOCSIFFLAGS, &ifreq);
+ break;
+
+ case SIOCSIFDSTADDR:
+ memcpy (&ifreq.ifr_dstaddr, param, sizeof (struct sockaddr));
+ r = ioctl (s, cmd, &ifreq);
+ break;
+
+ case OSIOCGIFDSTADDR:
+ case SIOCGIFDSTADDR:
+ if ((r = ioctl (s, cmd, &ifreq)) < 0)
+ break;
+ memcpy (param, &ifreq.ifr_dstaddr, sizeof (struct sockaddr));
+ break;
+
+ case SIOCSIFBRDADDR:
+ memcpy (&ifreq.ifr_broadaddr, param, sizeof (struct sockaddr));
+ r = ioctl (s, cmd, &ifreq);
+ break;
+
+ case OSIOCGIFBRDADDR:
+ case SIOCGIFBRDADDR:
+ if ((r = ioctl (s, cmd, &ifreq)) < 0)
+ break;
+ memcpy (param, &ifreq.ifr_broadaddr, sizeof (struct sockaddr));
+ break;
+
+ case SIOCSIFMETRIC:
+ ifreq.ifr_metric = *((int*) param);
+ r = ioctl (s, cmd, &ifreq);
+ break;
+
+ case SIOCGIFMETRIC:
+ if ((r = ioctl (s, cmd, &ifreq)) < 0)
+ break;
+ *((int*) param) = ifreq.ifr_metric;
+ break;
+
+ case SIOCSIFMTU:
+ ifreq.ifr_mtu = *((int*) param);
+ r = ioctl (s, cmd, &ifreq);
+ break;
+
+ case SIOCGIFMTU:
+ if ((r = ioctl (s, cmd, &ifreq)) < 0)
+ break;
+ *((int*) param) = ifreq.ifr_mtu;
+ break;
+
+ case SIOCSIFPHYS:
+ ifreq.ifr_phys = *((int*) param);
+ r = ioctl (s, cmd, &ifreq);
+ break;
+
+ case SIOCGIFPHYS:
+ if ((r = ioctl (s, cmd, &ifreq)) < 0)
+ break;
+ *((int*) param) = ifreq.ifr_phys;
+ break;
+
+ case SIOCSIFMEDIA:
+ ifreq.ifr_media = *((int*) param);
+ r = ioctl (s, cmd, &ifreq);
+ break;
+
+ case SIOCGIFMEDIA:
+ if ((r = ioctl (s, cmd, &ifreq)) < 0)
+ break;
+ *((int*) param) = ifreq.ifr_media;
+ break;
+
+ default:
+ errno = EOPNOTSUPP;
+ r = -1;
+ break;
+ }
+
+ rtems_bsdnet_semaphore_release ();
+
+ close (s);
+ return r;
+}
+
+/*
* Parse a network driver name into a name and a unit number
*/
int