diff options
Diffstat (limited to 'c/src/libnetworking/rtems/rtems_glue.c')
-rw-r--r-- | c/src/libnetworking/rtems/rtems_glue.c | 220 |
1 files changed, 179 insertions, 41 deletions
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 |