diff options
Diffstat (limited to 'cpukit/libnetworking/rtems/rtems_glue.c')
-rw-r--r-- | cpukit/libnetworking/rtems/rtems_glue.c | 1264 |
1 files changed, 0 insertions, 1264 deletions
diff --git a/cpukit/libnetworking/rtems/rtems_glue.c b/cpukit/libnetworking/rtems/rtems_glue.c deleted file mode 100644 index ee6c8f57a8..0000000000 --- a/cpukit/libnetworking/rtems/rtems_glue.c +++ /dev/null @@ -1,1264 +0,0 @@ -#include <machine/rtems-bsd-kernel-space.h> - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#define RTEMS_FAST_MUTEX - -#include <string.h> -#include <stdarg.h> -#include <stdio.h> -#include <errno.h> - -#include <rtems.h> -#include <rtems/libio.h> -#include <rtems/error.h> -#include <rtems/thread.h> -#include <rtems/rtems_bsdnet.h> -#include <sys/types.h> -#include <sys/param.h> -#include <sys/domain.h> -#include <sys/mbuf.h> -#include <sys/socketvar.h> -#include <sys/socket.h> -#include <sys/sockio.h> -#include <sys/callout.h> -#include <sys/proc.h> -#include <sys/sockio.h> -#include <sys/systm.h> -#include <net/if.h> -#include <net/route.h> -#include <netinet/in.h> -#include <vm/vm.h> - -#include <net/netisr.h> -#include <net/route.h> - -#include "loop.h" - -/* - * Memory allocation - */ -static uint32_t nmbuf = (64L * 1024L) / _SYS_MBUF_LEGACY_MSIZE; - uint32_t nmbclusters = (128L * 1024L) / MCLBYTES; - -/* - * Network task synchronization - */ -static rtems_recursive_mutex networkMutex = - RTEMS_RECURSIVE_MUTEX_INITIALIZER("_Network"); -static rtems_id networkDaemonTid; -static uint32_t networkDaemonPriority; -#ifdef RTEMS_SMP -static const cpu_set_t *networkDaemonCpuset = 0; -static size_t networkDaemonCpusetSize = 0; -#endif -static void networkDaemon (void *task_argument); - -/* - * Network timing - */ -int rtems_bsdnet_ticks_per_second; -int rtems_bsdnet_microseconds_per_tick; - -/* - * Callout processing - */ -static rtems_interval ticksWhenCalloutsLastChecked; -struct callout *callfree = NULL; -struct callout calltodo; - -/* - * FreeBSD variables - */ -int nfs_diskless_valid; - -/* - * BOOTP values - */ -struct in_addr rtems_bsdnet_log_host_address = {0}; -struct in_addr rtems_bsdnet_bootp_server_address = {0}; -char *rtems_bsdnet_bootp_boot_file_name = 0; -char *rtems_bsdnet_bootp_server_name = 0; -char *rtems_bsdnet_domain_name = 0; -char *rtems_bsdnet_bootp_cmdline = 0; -static struct in_addr _rtems_bsdnet_nameserver[sizeof rtems_bsdnet_config.name_server / - sizeof rtems_bsdnet_config.name_server[0]]; -struct in_addr *rtems_bsdnet_nameserver = _rtems_bsdnet_nameserver; -int rtems_bsdnet_nameserver_count = 0; -static struct in_addr _rtems_bsdnet_ntpserver[sizeof rtems_bsdnet_config.ntp_server / - sizeof rtems_bsdnet_config.ntp_server[0]]; -struct in_addr *rtems_bsdnet_ntpserver = _rtems_bsdnet_ntpserver; -int rtems_bsdnet_ntpserver_count = 0; -int32_t rtems_bsdnet_timeoffset = 0; - -static const struct sockaddr_in address_template = { - sizeof(address_template), - AF_INET, - 0, - { INADDR_ANY }, - { 0, 0, 0, 0, 0, 0, 0, 0 } -}; - -static void -rtems_bsdnet_initialize_sockaddr_in(struct sockaddr_in *addr) -{ - memcpy(addr, &address_template, sizeof(*addr)); -} - -uint32_t -rtems_bsdnet_semaphore_release_recursive(void) -{ - uint32_t nest_count; - - nest_count = networkMutex._nest_level; - networkMutex._nest_level = 0; - rtems_recursive_mutex_unlock(&networkMutex); - return nest_count; -} - -void -rtems_bsdnet_semaphore_obtain_recursive(uint32_t nest_count) -{ - rtems_recursive_mutex_lock(&networkMutex); - networkMutex._nest_level = nest_count; -} - -/* - * Perform FreeBSD memory allocation. - * FIXME: This should be modified to keep memory allocation statistics. - */ -#undef malloc -#undef free -extern void *malloc (size_t); -extern void free (void *); -void * -rtems_bsdnet_malloc (size_t size, int type, int flags) -{ - void *p; - int try = 0; - - for (;;) { - uint32_t nest_count; - - p = malloc (size); - if (p || (flags & M_NOWAIT)) - return p; - nest_count = rtems_bsdnet_semaphore_release_recursive (); - if (++try >= 30) { - rtems_bsdnet_malloc_starvation(); - try = 0; - } - rtems_task_wake_after (rtems_bsdnet_ticks_per_second); - rtems_bsdnet_semaphore_obtain_recursive (nest_count); - } -} - -/* - * Free FreeBSD memory - * FIXME: This should be modified to keep memory allocation statistics. - */ -void -rtems_bsdnet_free (void *addr, int type) -{ - free (addr); -} - -/* - * Externs for BSD data we have to access during initialization - */ -extern struct domain routedomain; -extern struct domain inetdomain; - -/* - * Do the initializations required by the BSD code - */ -static int -bsd_init (void) -{ - int i; - char *p; - - /* - * Set up mbuf cluster data strutures - */ - p = rtems_bsdnet_malloc_mbuf ((nmbclusters*MCLBYTES)+MCLBYTES-1, MBUF_MALLOC_NMBCLUSTERS); - if (p == NULL) { - printf ("Can't get network cluster memory.\n"); - return -1; - } - p = (char *)(((intptr_t)p + (MCLBYTES-1)) & ~(MCLBYTES-1)); - mbutl = (struct mbuf *)p; - for (i = 0; i < nmbclusters; i++) { - ((union mcluster *)p)->mcl_next = mclfree; - mclfree = (union mcluster *)p; - p += MCLBYTES; - mbstat.m_clfree++; - } - mbstat.m_clusters = nmbclusters; - mclrefcnt = rtems_bsdnet_malloc_mbuf (nmbclusters, MBUF_MALLOC_MCLREFCNT); - if (mclrefcnt == NULL) { - printf ("Can't get mbuf cluster reference counts memory.\n"); - return -1; - } - memset (mclrefcnt, '\0', nmbclusters); - - /* - * Set up mbuf data structures - */ - - p = rtems_bsdnet_malloc_mbuf(nmbuf * _SYS_MBUF_LEGACY_MSIZE + _SYS_MBUF_LEGACY_MSIZE - 1,MBUF_MALLOC_MBUF); - p = (char *)(((uintptr_t)p + _SYS_MBUF_LEGACY_MSIZE - 1) & ~(_SYS_MBUF_LEGACY_MSIZE - 1)); - if (p == NULL) { - printf ("Can't get network memory.\n"); - return -1; - } - for (i = 0; i < nmbuf; i++) { - ((struct mbuf *)p)->m_next = mmbfree; - mmbfree = (struct mbuf *)p; - p += _SYS_MBUF_LEGACY_MSIZE; - } - mbstat.m_mbufs = nmbuf; - mbstat.m_mtypes[MT_FREE] = nmbuf; - - /* - * Set up domains - */ - { - - routedomain.dom_next = domains; - domains = &routedomain; - inetdomain.dom_next = domains; - domains = &inetdomain; - domaininit (NULL); - } - - /* - * Setup the sysctl, normally done by a SYSINIT call. - */ - sysctl_register_all(0); - - /* - * Set up interfaces - */ - ifinit (NULL); - return 0; -} - -/* - * Initialize and start network operations - */ -static int -rtems_bsdnet_initialize (void) -{ - rtems_bsdnet_semaphore_obtain (); - - /* - * Set the priority of all network tasks - */ - if (rtems_bsdnet_config.network_task_priority == 0) - networkDaemonPriority = 100; -#ifdef RTEMS_MULTIPROCESSING - /* - * Allow network tasks to run with priority 0 (PRIORITY_PSEUDO_ISR) using - * UINT32_MAX for the network task priority in the network configuration. - * This enables MPCI via a TCP/IP network. - */ - else if (rtems_bsdnet_config.network_task_priority != UINT32_MAX) -#else - else -#endif - networkDaemonPriority = rtems_bsdnet_config.network_task_priority; - - /* - * Default network task CPU affinity - */ -#ifdef RTEMS_SMP - networkDaemonCpuset = rtems_bsdnet_config.network_task_cpuset; - networkDaemonCpusetSize = rtems_bsdnet_config.network_task_cpuset_size; -#endif - - /* - * Set the memory allocation limits - */ - if (rtems_bsdnet_config.mbuf_bytecount) - nmbuf = rtems_bsdnet_config.mbuf_bytecount / _SYS_MBUF_LEGACY_MSIZE; - if (rtems_bsdnet_config.mbuf_cluster_bytecount) - nmbclusters = rtems_bsdnet_config.mbuf_cluster_bytecount / MCLBYTES; - - rtems_set_udp_buffer_sizes( - rtems_bsdnet_config.udp_tx_buf_size, - rtems_bsdnet_config.udp_rx_buf_size - ); - - rtems_set_tcp_buffer_sizes( - rtems_bsdnet_config.tcp_tx_buf_size, - rtems_bsdnet_config.tcp_rx_buf_size - ); - - rtems_set_sb_efficiency( rtems_bsdnet_config.sb_efficiency ); - - /* - * Compute clock tick conversion factors - */ - rtems_bsdnet_ticks_per_second = rtems_clock_get_ticks_per_second(); - if (rtems_bsdnet_ticks_per_second <= 0) - rtems_bsdnet_ticks_per_second = 1; - rtems_bsdnet_microseconds_per_tick = - 1000000 / rtems_bsdnet_ticks_per_second; - - /* - * Set up BSD-style sockets - */ - if (bsd_init () < 0) { - rtems_bsdnet_semaphore_release (); - return -1; - } - - /* - * Start network daemon - */ - networkDaemonTid = rtems_bsdnet_newproc ("ntwk", 4096, networkDaemon, NULL); - - /* - * Let other network tasks begin - */ - rtems_bsdnet_semaphore_release (); - - rtems_bsdnet_initialize_loop(); - - return 0; -} - -/* - * Obtain network mutex - */ -void -rtems_bsdnet_semaphore_obtain (void) -{ - rtems_recursive_mutex_lock(&networkMutex); -} - -/* - * Release network mutex - */ -void -rtems_bsdnet_semaphore_release (void) -{ - rtems_recursive_mutex_unlock(&networkMutex); -} - -static int -rtems_bsdnet_sleep(rtems_event_set in, rtems_interval ticks) -{ - rtems_status_code sc; - rtems_event_set out; - rtems_event_set out2; - - in |= RTEMS_EVENT_SYSTEM_NETWORK_CLOSE; - - /* - * Soak up any pending events. The sleep/wakeup synchronization in the - * FreeBSD kernel has no memory. - */ - rtems_event_system_receive(in, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, - RTEMS_NO_TIMEOUT, &out); - - /* - * Wait for the wakeup event. - */ - sc = rtems_bsdnet_event_receive(in, RTEMS_EVENT_ANY | RTEMS_WAIT, - ticks, &out); - - /* - * Get additional events that may have been received between the - * rtems_event_system_receive() and the rtems_bsdnet_semaphore_obtain(). - */ - rtems_event_system_receive(in, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, - RTEMS_NO_TIMEOUT, &out2); - out |= out2; - - if (out & RTEMS_EVENT_SYSTEM_NETWORK_CLOSE) - return (ENXIO); - - if (sc == RTEMS_SUCCESSFUL) - return (0); - - return (EWOULDBLOCK); -} - -/* - * Wait for something to happen to a socket buffer - */ -int -sbwait(struct sockbuf *sb) -{ - int error; - - /* - * Set this task as the target of the wakeup operation. - */ - sb->sb_sel.si_pid = rtems_task_self(); - - /* - * Show that socket is waiting - */ - sb->sb_flags |= SB_WAIT; - - error = rtems_bsdnet_sleep(SBWAIT_EVENT, sb->sb_timeo); - if (error != ENXIO) - sb->sb_flags &= ~SB_WAIT; - - return (error); -} - - -/* - * Wake up the task waiting on a socket buffer. - */ -void -sowakeup( - struct socket *so, - struct sockbuf *sb) -{ - if (sb->sb_flags & SB_WAIT) { - rtems_event_system_send (sb->sb_sel.si_pid, SBWAIT_EVENT); - } - if (sb->sb_wakeup) { - (*sb->sb_wakeup) (so, sb->sb_wakeuparg); - } -} - -/* - * For now, a socket can be used by only one task at a time. - */ -int -sb_lock(struct sockbuf *sb) -{ - rtems_panic ("Socket buffer is already in use."); - return 0; -} -void -wakeup (void *p) -{ - rtems_panic ("Wakeup called"); -} - -/* - * Wait for a connection/disconnection event. - */ -int -soconnsleep (struct socket *so) -{ - int error; - - /* - * Set this task as the target of the wakeup operation. - */ - if (so->so_pgid) - rtems_panic ("Another task is already sleeping on that socket"); - so->so_pgid = rtems_task_self(); - - error = rtems_bsdnet_sleep(SOSLEEP_EVENT, so->so_rcv.sb_timeo); - if (error != ENXIO) - so->so_pgid = 0; - - return (error); -} - -/* - * Wake up a task waiting for a connection/disconnection to complete. - */ -void -soconnwakeup (struct socket *so) -{ - if (so->so_pgid) - rtems_event_system_send (so->so_pgid, SOSLEEP_EVENT); -} - -/* - * Send an event to the network daemon. - * This corresponds to sending a software interrupt in the BSD kernel. - */ -void -rtems_bsdnet_schednetisr (int n) -{ - rtems_event_system_send (networkDaemonTid, 1 << n); -} - -/* - * The network daemon - * This provides a context to run BSD software interrupts - */ -static void -networkDaemon (void *task_argument) -{ - rtems_status_code sc; - rtems_event_set events; - rtems_interval now; - int ticksPassed; - uint32_t timeout; - struct callout *c; - - for (;;) { - c = calltodo.c_next; - if (c) - timeout = c->c_time; - else - timeout = RTEMS_NO_TIMEOUT; - - sc = rtems_bsdnet_event_receive (NETISR_EVENTS, - RTEMS_EVENT_ANY | RTEMS_WAIT, - timeout, - &events); - if ( sc == RTEMS_SUCCESSFUL ) { - if (events & NETISR_IP_EVENT) - ipintr (); - if (events & NETISR_ARP_EVENT) - arpintr (); - } - - now = rtems_clock_get_ticks_since_boot(); - ticksPassed = now - ticksWhenCalloutsLastChecked; - if (ticksPassed != 0) { - ticksWhenCalloutsLastChecked = now; - - c = calltodo.c_next; - if (c) { - c->c_time -= ticksPassed; - while ((c = calltodo.c_next) != NULL && c->c_time <= 0) { - void *arg; - void (*func) (void *); - - func = c->c_func; - arg = c->c_arg; - calltodo.c_next = c->c_next; - c->c_next = callfree; - callfree = c; - (*func)(arg); - } - } - } - } -} - -/* - * Structure passed to task-start stub - */ -struct newtask { - void (*entry)(void *); - void *arg; -}; - -/* - * Task-start stub - */ -static void -taskEntry (rtems_task_argument arg) -{ - struct newtask t; - - /* - * Pick up task information and free - * the memory allocated to pass the - * information to this task. - */ - t = *(struct newtask *)arg; - free ((struct newtask *)arg); - - /* - * Enter the competition for the network semaphore - */ - rtems_bsdnet_semaphore_obtain (); - - /* - * Enter the task - */ - (*t.entry)(t.arg); - rtems_panic ("Network task returned!\n"); -} - - -/* - * Start a network task - */ -#ifdef RTEMS_SMP -rtems_id -rtems_bsdnet_newproc (char *name, int stacksize, void(*entry)(void *), void *arg) -{ - return rtems_bsdnet_newproc_affinity( name, stacksize, entry, arg, - networkDaemonCpuset, networkDaemonCpusetSize ); -} - -rtems_id -rtems_bsdnet_newproc_affinity (char *name, int stacksize, void(*entry)(void *), - void *arg, const cpu_set_t *set, const size_t setsize) -#else -rtems_id -rtems_bsdnet_newproc (char *name, int stacksize, void(*entry)(void *), void *arg) -#endif -{ - struct newtask *t; - char nm[4]; - rtems_id tid; - rtems_status_code sc; - - strncpy (nm, name, 4); - sc = rtems_task_create (rtems_build_name(nm[0], nm[1], nm[2], nm[3]), - networkDaemonPriority, - stacksize, - RTEMS_PREEMPT|RTEMS_NO_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0), -#ifdef RTEMS_MULTIPROCESSING - RTEMS_SYSTEM_TASK | -#endif - RTEMS_NO_FLOATING_POINT|RTEMS_LOCAL, - &tid); - if (sc != RTEMS_SUCCESSFUL) - rtems_panic ("Can't create network daemon `%s': `%s'\n", name, rtems_status_text (sc)); - -#ifdef RTEMS_SMP - /* - * Use the default affinity or use the user-provided CPU set - */ - if ( set != 0 ) - rtems_task_set_affinity( tid, setsize, set ); -#endif - - /* - * Set up task arguments - */ - t = malloc (sizeof *t); - t->entry = entry; - t->arg = arg; - - /* - * Start the task - */ - sc = rtems_task_start (tid, taskEntry, (rtems_task_argument)t); - if (sc != RTEMS_SUCCESSFUL) - rtems_panic ("Can't start network daemon `%s': `%s'\n", name, rtems_status_text (sc)); - - /* - * Let our caller know the i.d. of the new task - */ - return tid; -} - -rtems_status_code rtems_bsdnet_event_receive ( - rtems_event_set event_in, - rtems_option option_set, - rtems_interval ticks, - rtems_event_set *event_out) -{ - rtems_status_code sc; - - rtems_bsdnet_semaphore_release (); - sc = rtems_event_system_receive (event_in, option_set, ticks, event_out); - rtems_bsdnet_semaphore_obtain (); - return sc; -} - -/* - * Fake random number generator - */ -unsigned long -rtems_bsdnet_random (void) -{ - rtems_interval now; - - now = rtems_clock_get_ticks_since_boot(); - return (now * 99991); -} - -/* - * Callout list processing - */ -void -rtems_bsdnet_timeout(void (*ftn)(void *), void *arg, int ticks) -{ - register struct callout *new, *p, *t; - - if (ticks <= 0) - ticks = 1; - - /* Fill in the next free callout structure. */ - if (callfree == NULL) { - callfree = malloc (sizeof *callfree); - if (callfree == NULL) - rtems_panic ("No memory for timeout table entry"); - callfree->c_next = NULL; - } - - new = callfree; - callfree = new->c_next; - new->c_arg = arg; - new->c_func = ftn; - - /* - * The time for each event is stored as a difference from the time - * of the previous event on the queue. Walk the queue, correcting - * the ticks argument for queue entries passed. Correct the ticks - * value for the queue entry immediately after the insertion point - * as well. Watch out for negative c_time values; these represent - * overdue events. - */ - for (p = &calltodo; - (t = p->c_next) != NULL && ticks > t->c_time; p = t) - if (t->c_time > 0) - ticks -= t->c_time; - new->c_time = ticks; - if (t != NULL) - t->c_time -= ticks; - - /* Insert the new entry into the queue. */ - p->c_next = new; - new->c_next = t; -} - -/* - * Ticks till specified time - * XXX: This version worries only about seconds, but that's good - * enough for the way the network code uses this routine. - */ -int -hzto(struct timeval *tv) -{ - long diff = tv->tv_sec - rtems_bsdnet_seconds_since_boot(); - - if (diff <= 0) - return 1; - return diff * rtems_bsdnet_ticks_per_second; -} - -/* - * Kernel debugging - */ -int rtems_bsdnet_log_priority; -void -rtems_bsdnet_log (int priority, const char *fmt, ...) -{ - va_list args; - - if (priority & rtems_bsdnet_log_priority) { - va_start (args, fmt); - vprintf (fmt, args); - va_end (args); - } -} - -/* - * IP header checksum routine for processors which don't have an inline version - */ - -struct ip; - -u_int in_cksum_hdr(const struct ip *); - -u_int -in_cksum_hdr (const struct ip *ip) -{ - uint32_t sum; - const uint16_t *sp; - int i; - - sum = 0; - sp = (uint16_t *)ip; - for (i = 0 ; i < 10 ; i++) - sum += *sp++; - while (sum > 0xFFFF) - sum = (sum & 0xffff) + (sum >> 16); - return ~sum & 0xFFFF; -} - -/* - * Manipulate routing tables - */ -int rtems_bsdnet_rtrequest ( - int req, - struct sockaddr *dst, - struct sockaddr *gateway, - struct sockaddr *netmask, - int flags, - struct rtentry **net_nrt) -{ - int error; - - rtems_bsdnet_semaphore_obtain (); - error = rtrequest (req, dst, gateway, netmask, flags, net_nrt); - rtems_bsdnet_semaphore_release (); - if (error) { - errno = error; - return -1; - } - return 0; -} - -static bool -rtems_bsdnet_setup_interface( - const char *name, - const char *ip_address, - const char *ip_netmask -) -{ - struct sockaddr_in address; - struct sockaddr_in netmask; - short flags; - - /* - * Bring interface up - */ - flags = IFF_UP; - if (rtems_bsdnet_ifconfig (name, SIOCSIFFLAGS, &flags) < 0) { - printf ("Can't bring %s up: %s\n", name, strerror (errno)); - return false; - } - - /* - * Set interface netmask - */ - rtems_bsdnet_initialize_sockaddr_in(&netmask); - netmask.sin_addr.s_addr = inet_addr (ip_netmask); - if (rtems_bsdnet_ifconfig (name, SIOCSIFNETMASK, &netmask) < 0) { - printf ("Can't set %s netmask: %s\n", name, strerror (errno)); - return false; - } - - /* - * Set interface address - */ - rtems_bsdnet_initialize_sockaddr_in(&address); - address.sin_addr.s_addr = inet_addr (ip_address); - if (rtems_bsdnet_ifconfig (name, SIOCSIFADDR, &address) < 0) { - printf ("Can't set %s address: %s\n", name, strerror (errno)); - return false; - } - - /* - * Set interface broadcast address if the interface has the - * broadcast flag set. - */ - if (rtems_bsdnet_ifconfig (name, SIOCGIFFLAGS, &flags) < 0) { - printf ("Can't read %s flags: %s\n", name, strerror (errno)); - return false; - } - - if (flags & IFF_BROADCAST) { - struct sockaddr_in broadcast; - - rtems_bsdnet_initialize_sockaddr_in(&broadcast); - broadcast.sin_addr.s_addr = - address.sin_addr.s_addr | ~netmask.sin_addr.s_addr; - if (rtems_bsdnet_ifconfig (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", - name, buf, strerror (errno)); - } - } - - return true; -} - -static int -rtems_bsdnet_setup (void) -{ - struct rtems_bsdnet_ifconfig *ifp; - int i; - bool any_if_configured = false; - - /* - * Set local parameters - */ - if (rtems_bsdnet_config.hostname) - sethostname (rtems_bsdnet_config.hostname, - strlen (rtems_bsdnet_config.hostname)); - if (rtems_bsdnet_config.domainname) - rtems_bsdnet_domain_name = - strdup (rtems_bsdnet_config.domainname); - if (rtems_bsdnet_config.log_host) - rtems_bsdnet_log_host_address.s_addr = - inet_addr (rtems_bsdnet_config.log_host); - for (i = 0 ; i < sizeof rtems_bsdnet_config.name_server / - sizeof rtems_bsdnet_config.name_server[0] ; i++) { - if (!rtems_bsdnet_config.name_server[i]) - break; - rtems_bsdnet_nameserver[rtems_bsdnet_nameserver_count++].s_addr - = inet_addr (rtems_bsdnet_config.name_server[i]); - } - for (i = 0 ; i < sizeof rtems_bsdnet_config.ntp_server / - sizeof rtems_bsdnet_config.ntp_server[0] ; i++) { - if (!rtems_bsdnet_config.ntp_server[i]) - break; - rtems_bsdnet_ntpserver[rtems_bsdnet_ntpserver_count++].s_addr - = inet_addr (rtems_bsdnet_config.ntp_server[i]); - } - - /* - * Configure interfaces - */ - any_if_configured |= rtems_bsdnet_setup_interface( - "lo0", - "127.0.0.1", - "255.0.0.0" - ); - for (ifp = rtems_bsdnet_config.ifconfig ; ifp ; ifp = ifp->next) { - if (ifp->ip_address == NULL) - continue; - - any_if_configured |= rtems_bsdnet_setup_interface( - ifp->name, - ifp->ip_address, - ifp->ip_netmask - ); - } - - /* - * Set default route - */ - if (rtems_bsdnet_config.gateway && any_if_configured) { - struct sockaddr_in address; - struct sockaddr_in netmask; - struct sockaddr_in gateway; - - rtems_bsdnet_initialize_sockaddr_in(&address); - rtems_bsdnet_initialize_sockaddr_in(&netmask); - rtems_bsdnet_initialize_sockaddr_in(&gateway); - - 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; -} - -/* - * Initialize the network - */ -int -rtems_bsdnet_initialize_network(void) -{ - struct rtems_bsdnet_ifconfig *ifp; - - /* - * Start network tasks. - * Initialize BSD network data structures. - */ - if (rtems_bsdnet_initialize () < 0) - return -1; - - /* - * Attach interfaces - */ - for (ifp = rtems_bsdnet_config.ifconfig ; ifp ; ifp = ifp->next) { - rtems_bsdnet_attach (ifp); - } - - /* - * Bring up the network - */ - if (rtems_bsdnet_setup () < 0) - return -1; - if (rtems_bsdnet_config.bootp) - (*rtems_bsdnet_config.bootp)(); - return 0; -} - -/* - * 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, uint32_t 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); - if ( (*((short*) param) & IFF_UP ) == 0 ) { - /* set the interface down */ - ifreq.ifr_flags &= ~(IFF_UP); - } - 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: - /* 'param' passes the phy index they want to - * look at... - */ - ifreq.ifr_media = *((int*) param); - if ((r = ioctl (s, cmd, &ifreq)) < 0) - break; - *((int*) param) = ifreq.ifr_media; - break; - - case SIOCAIFADDR: - case SIOCDIFADDR: - r = ioctl(s, cmd, (struct ifreq *) param); - break; - - default: - errno = EOPNOTSUPP; - r = -1; - break; - } - - rtems_bsdnet_semaphore_release (); - - close (s); - return r; -} - -/** - * @brief Splits a network interface name with interface configuration @a - * config into the unit name and number parts. - * - * Memory for the unit name will be allocated from the heap and copied to @a - * namep. If @a namep is NULL nothing will be allocated and copied. - * - * Returns the unit number or -1 on error. - */ -int -rtems_bsdnet_parse_driver_name (const struct rtems_bsdnet_ifconfig *config, char **namep) -{ - const char *cp = config->name; - char c; - int unitNumber = 0; - - if (cp == NULL) { - printf ("No network driver name.\n"); - return -1; - } - while ((c = *cp++) != '\0') { - if ((c >= '0') && (c <= '9')) { - int len = cp - config->name; - if ((len < 2) || (len > 50)) - break; - for (;;) { - unitNumber = (unitNumber * 10) + (c - '0'); - c = *cp++; - if (c == '\0') { - if (namep != NULL) { - char *unitName = malloc (len); - if (unitName == NULL) { - printf ("No memory.\n"); - return -1; - } - strncpy (unitName, config->name, len - 1); - unitName[len-1] = '\0'; - *namep = unitName; - } - return unitNumber; - } - if ((c < '0') || (c > '9')) - break; - } - break; - } - } - printf ("Bad network driver name `%s'.\n", config->name); - return -1; -} - -/* - * Handle requests for more network memory - * XXX: Another possibility would be to use a semaphore here with - * a release in the mbuf free macro. I have chosen this `polling' - * approach because: - * 1) It is simpler. - * 2) It adds no complexity to the free macro. - * 3) Running out of mbufs should be a rare - * condition -- predeployment testing of - * an application should indicate the - * required mbuf pool size. - * XXX: Should there be a panic if a task is stuck in the loop for - * more than a minute or so? - */ -int -m_mballoc(int nmb, int nowait) -{ - if (nowait) - return 0; - m_reclaim (); - if (mmbfree == NULL) { - int try = 0; - int print_limit = 30 * rtems_bsdnet_ticks_per_second; - - mbstat.m_wait++; - for (;;) { - uint32_t nest_count = rtems_bsdnet_semaphore_release_recursive (); - rtems_task_wake_after (1); - rtems_bsdnet_semaphore_obtain_recursive (nest_count); - if (mmbfree) - break; - if (++try >= print_limit) { - printf ("Still waiting for mbuf.\n"); - try = 0; - } - } - } - else { - mbstat.m_drops++; - } - return 1; -} - -int -m_clalloc(int ncl, int nowait) -{ - if (nowait) - return 0; - m_reclaim (); - if (mclfree == NULL) { - int try = 0; - int print_limit = 30 * rtems_bsdnet_ticks_per_second; - - mbstat.m_wait++; - for (;;) { - uint32_t nest_count = rtems_bsdnet_semaphore_release_recursive (); - rtems_task_wake_after (1); - rtems_bsdnet_semaphore_obtain_recursive (nest_count); - if (mclfree) - break; - if (++try >= print_limit) { - printf ("Still waiting for mbuf cluster.\n"); - try = 0; - } - } - } - else { - mbstat.m_drops++; - } - return 1; -} - |