summaryrefslogtreecommitdiffstats
path: root/c/src/libnetworking/rtems
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/libnetworking/rtems')
-rw-r--r--c/src/libnetworking/rtems/rtems_bsdnet.h39
-rw-r--r--c/src/libnetworking/rtems/rtems_glue.c220
2 files changed, 216 insertions, 43 deletions
diff --git a/c/src/libnetworking/rtems/rtems_bsdnet.h b/c/src/libnetworking/rtems/rtems_bsdnet.h
index 5be2e932f9..7838835f0f 100644
--- a/c/src/libnetworking/rtems/rtems_bsdnet.h
+++ b/c/src/libnetworking/rtems/rtems_bsdnet.h
@@ -68,10 +68,17 @@ void rtems_bsdnet_show_tcp_stats (void);
*/
struct rtems_bsdnet_ifconfig {
/*
- * These two entries must be supplied for each interface.
+ * These three entries must be supplied for each interface.
*/
char *name;
- int (*attach)(struct rtems_bsdnet_ifconfig *conf);
+
+ /*
+ * This function now handles attaching and detaching an interface.
+ * The parameter attaching indicates the operation being invoked.
+ * For older attach functions which do not have the extra parameter
+ * it will be ignored.
+ */
+ int (*attach)(struct rtems_bsdnet_ifconfig *conf, int attaching);
/*
* Link to next interface
@@ -132,8 +139,36 @@ struct rtems_bsdnet_config {
char *name_server[3]; /* BOOTP */
char *ntp_server[3]; /* BOOTP */
};
+
+/*
+ * Default global device configuration structure. This is scanned
+ * by the initialize network function. Check the network demo's for
+ * an example of the structure. Like the RTEMS configuration tables,
+ * they are not part of RTEMS but part of your application or bsp
+ * code.
+ */
extern struct rtems_bsdnet_config rtems_bsdnet_config;
+
+/*
+ * Initialise the BSD stack, attach and `up' interfaces
+ * in the `rtems_bsdnet_config'. RTEMS must already be initialised.
+ */
int rtems_bsdnet_initialize_network (void);
+
+/*
+ * Dynamic interface control. Drivers must free any resources such as
+ * memory, interrupts, io regions claimed during the `attach' and/or
+ * `up' operations when asked to `detach'.
+ * You must configure the interface after attaching it.
+ */
+void rtems_bsdnet_attach (struct rtems_bsdnet_ifconfig *ifconfig);
+void rtems_bsdnet_detach (struct rtems_bsdnet_ifconfig *ifconfig);
+
+/*
+ * Interface configuration. The commands are listed in `sys/sockio.h'.
+ */
+int rtems_bsdnet_ifconfig (const char *ifname, unsigned32 cmd, void *param);
+
void rtems_bsdnet_do_bootp (void);
int rtems_bsdnet_synchronize_ntp (int interval, rtems_task_priority priority);
diff --git a/c/src/libnetworking/rtems/rtems_glue.c b/c/src/libnetworking/rtems/rtems_glue.c
index 4213b91a2c..31b44a6656 100644
--- a/c/src/libnetworking/rtems/rtems_glue.c
+++ b/c/src/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