source: rtems/cpukit/libnetworking/rtems/rtems_glue.c @ 1ff9922

4.104.114.95
Last change on this file since 1ff9922 was 1ff9922, checked in by Chris Johns <chrisj@…>, on 12/22/07 at 08:27:18

2007-12-22 Chris Johns <chrisj@…>

  • configure.ac: fixed bug that always enabled strict order mutexes.
  • score/inline/rtems/score/coremutex.inl: Fixed coding standard.
  • score/src/coremutex.c: Add the holder's thread to the lock_mutex list if the mutex is initialised locked.
  • libnetworking/rtems/rtems_glue.c: Changed semaphore error message to show the error is an rtems-net error.
  • libmisc/monitor/mon-network.c: Removed warnings.
  • telnetd/icmds.c: Changed shell_* to rtems_shell_*.
  • score/Makefile.am: Fixed typo that stopped 'make tags' working.
  • libmisc/shell/err.c, libmisc/shell/err.h, libmisc/shell/errx.c, libmisc/shell/extern-cp.h, libmisc/shell/fts.c, libmisc/shell/fts.h, libmisc/shell/main_cp.c, libmisc/shell/utils-cp.c, libmisc/shell/verr.c, libmisc/shell/verrx.c, libmisc/shell/vwarn.c, libmisc/shell/vwarnx.c, libmisc/shell/warn.c, libmisc/shell/warnx.c: New. Ported from BSD.
  • libmisc/shell/shellconfig.h: Add the cp command.
  • libmisc/Makefile.am: Add the new files to the shell.
  • libmisc/shell/shell.c, libmisc/shell/shell.h: Add scripting support.
  • libblock/src/flashdisk.c: Fixed disk drive count size setting bug.
  • Property mode set to 100644
File size: 26.5 KB
Line 
1/*
2 *  $Id$
3 */
4
5#if HAVE_CONFIG_H
6#include "config.h"
7#endif
8
9#define RTEMS_FAST_MUTEX
10
11#ifdef RTEMS_FAST_MUTEX
12#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__ 1
13#endif
14
15#include <string.h>
16#include <stdarg.h>
17#include <stdio.h>
18#include <errno.h>
19
20#include <rtems.h>
21#include <rtems/libio.h>
22#include <rtems/error.h>
23#include <rtems/rtems_bsdnet.h>
24#include <sys/types.h>
25#include <sys/param.h>
26#include <sys/domain.h>
27#include <sys/mbuf.h>
28#include <sys/socketvar.h>
29#include <sys/socket.h>
30#include <sys/sockio.h>
31#include <sys/callout.h>
32#include <sys/proc.h>
33#include <sys/ioctl.h>
34#include <net/if.h>
35#include <net/route.h>
36#include <netinet/in.h>
37#include <vm/vm.h>
38#include <arpa/inet.h>
39
40#include <net/netisr.h>
41#include <net/route.h>
42
43/*
44 * Sysctl init all.
45 */
46void sysctl_register_all(void *arg);
47
48/*
49 * Memory allocation
50 */
51static uint32_t nmbuf       = (64L * 1024L) / MSIZE;
52       uint32_t nmbclusters = (128L * 1024L) / MCLBYTES;
53
54/*
55 * Network task synchronization
56 */
57static rtems_id networkSemaphore;
58#ifdef RTEMS_FAST_MUTEX
59Semaphore_Control   *the_networkSemaphore;
60#endif
61static rtems_id networkDaemonTid;
62static uint32_t   networkDaemonPriority;
63static void networkDaemon (void *task_argument);
64
65/*
66 * Network timing
67 */
68int                     rtems_bsdnet_ticks_per_second;
69int                     rtems_bsdnet_microseconds_per_tick;
70
71/*
72 * Callout processing
73 */
74static rtems_interval   ticksWhenCalloutsLastChecked;
75struct callout *callfree = NULL;
76struct callout calltodo;
77
78/*
79 * FreeBSD variables
80 */
81int nfs_diskless_valid;
82
83/*
84 * BOOTP values
85 */
86struct in_addr rtems_bsdnet_log_host_address = {0};
87struct in_addr rtems_bsdnet_bootp_server_address = {0};
88char *rtems_bsdnet_bootp_boot_file_name = 0;
89char *rtems_bsdnet_bootp_server_name = 0;
90char *rtems_bsdnet_domain_name = 0;
91char *rtems_bsdnet_bootp_cmdline = 0;
92static struct in_addr _rtems_bsdnet_nameserver[sizeof rtems_bsdnet_config.name_server /
93                        sizeof rtems_bsdnet_config.name_server[0]];
94struct in_addr *rtems_bsdnet_nameserver = _rtems_bsdnet_nameserver;
95int rtems_bsdnet_nameserver_count = 0;
96static struct in_addr _rtems_bsdnet_ntpserver[sizeof rtems_bsdnet_config.ntp_server /
97                        sizeof rtems_bsdnet_config.ntp_server[0]];
98struct in_addr *rtems_bsdnet_ntpserver = _rtems_bsdnet_ntpserver;
99int rtems_bsdnet_ntpserver_count = 0;
100int32_t rtems_bsdnet_timeoffset = 0;
101
102/*
103 * Perform FreeBSD memory allocation.
104 * FIXME: This should be modified to keep memory allocation statistics.
105 */
106#undef malloc
107#undef free
108extern void *malloc (size_t);
109extern void free (void *);
110void *
111rtems_bsdnet_malloc (size_t size, int type, int flags)
112{
113        void *p;
114        int try = 0;
115
116        for (;;) {
117                p = malloc (size);
118                if (p || (flags & M_NOWAIT))
119                        return p;
120                rtems_bsdnet_semaphore_release ();
121                if (++try >= 30) {
122                        rtems_bsdnet_malloc_starvation();
123                        try = 0;
124                }
125        rtems_task_wake_after (rtems_bsdnet_ticks_per_second);
126                rtems_bsdnet_semaphore_obtain ();
127        }
128}
129
130/*
131 * Free FreeBSD memory
132 * FIXME: This should be modified to keep memory allocation statistics.
133 */
134void
135rtems_bsdnet_free (void *addr, int type)
136{
137        free (addr);
138}
139
140/*
141 * Do the initializations required by the BSD code
142 */
143static int
144bsd_init (void)
145{
146        int i;
147        char *p;
148
149        /*
150         * Set up mbuf cluster data strutures
151         */
152        p = rtems_bsdnet_malloc_mbuf ((nmbclusters*MCLBYTES)+MCLBYTES-1, MBUF_MALLOC_NMBCLUSTERS);
153        if (p == NULL) {
154                printf ("Can't get network cluster memory.\n");
155                return -1;
156        }
157        p = (char *)(((intptr_t)p + (MCLBYTES-1)) & ~(MCLBYTES-1));
158        mbutl = (struct mbuf *)p;
159        for (i = 0; i < nmbclusters; i++) {
160                ((union mcluster *)p)->mcl_next = mclfree;
161                mclfree = (union mcluster *)p;
162                p += MCLBYTES;
163                mbstat.m_clfree++;
164        }
165        mbstat.m_clusters = nmbclusters;
166        mclrefcnt = rtems_bsdnet_malloc_mbuf (nmbclusters, MBUF_MALLOC_MCLREFCNT);
167        if (mclrefcnt == NULL) {
168                printf ("Can't get mbuf cluster reference counts memory.\n");
169                return -1;
170        }
171        memset (mclrefcnt, '\0', nmbclusters);
172
173        /*
174         * Set up mbuf data structures
175         */
176
177        p = rtems_bsdnet_malloc_mbuf(nmbuf * MSIZE + MSIZE - 1,MBUF_MALLOC_MBUF);
178        p = (char *)(((uintptr_t)p + MSIZE - 1) & ~(MSIZE - 1));
179        if (p == NULL) {
180                printf ("Can't get network memory.\n");
181                return -1;
182        }
183        for (i = 0; i < nmbuf; i++) {
184                ((struct mbuf *)p)->m_next = mmbfree;
185                mmbfree = (struct mbuf *)p;
186                p += MSIZE;
187        }
188        mbstat.m_mbufs = nmbuf;
189        mbstat.m_mtypes[MT_FREE] = nmbuf;
190
191        /*
192         * Set up domains
193         */
194        {
195        extern struct domain routedomain;
196        extern struct domain inetdomain;
197
198        routedomain.dom_next = domains;
199        domains = &routedomain;
200        inetdomain.dom_next = domains;
201        domains = &inetdomain;
202        domaininit (NULL);
203        }
204
205  /*
206   * Setup the sysctl, normally done by a SYSINIT call.
207   */
208  sysctl_register_all(0);
209
210        /*
211         * Set up interfaces
212         */
213        ifinit (NULL);
214        return 0;
215}
216
217/*
218 * Initialize and start network operations
219 */
220static int
221rtems_bsdnet_initialize (void)
222{
223        rtems_status_code sc;
224
225        /*
226         * Set the priority of all network tasks
227         */
228        if (rtems_bsdnet_config.network_task_priority == 0)
229                networkDaemonPriority = 100;
230        else
231                networkDaemonPriority = rtems_bsdnet_config.network_task_priority;
232
233        /*
234         * Set the memory allocation limits
235         */
236        if (rtems_bsdnet_config.mbuf_bytecount)
237                nmbuf = rtems_bsdnet_config.mbuf_bytecount / MSIZE;
238        if (rtems_bsdnet_config.mbuf_cluster_bytecount)
239                nmbclusters = rtems_bsdnet_config.mbuf_cluster_bytecount / MCLBYTES;
240
241        /*
242         * Create the task-synchronization semaphore
243         */
244        sc = rtems_semaphore_create (rtems_build_name('B', 'S', 'D', 'n'),
245                                        0,
246                                        RTEMS_PRIORITY |
247                                                RTEMS_BINARY_SEMAPHORE |
248                                                RTEMS_INHERIT_PRIORITY |
249                                                RTEMS_NO_PRIORITY_CEILING |
250                                                RTEMS_LOCAL,
251                                        0,
252                                        &networkSemaphore);
253        if (sc != RTEMS_SUCCESSFUL) {
254                printf ("Can't create network seamphore: `%s'\n", rtems_status_text (sc));
255                return -1;
256        }
257#ifdef RTEMS_FAST_MUTEX
258        {
259        Objects_Locations location;
260        the_networkSemaphore = _Semaphore_Get( networkSemaphore, &location );
261        _Thread_Enable_dispatch();
262        }
263#endif
264
265        /*
266         * Compute clock tick conversion factors
267         */
268        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &rtems_bsdnet_ticks_per_second);
269        if (rtems_bsdnet_ticks_per_second <= 0)
270                rtems_bsdnet_ticks_per_second = 1;
271        rtems_bsdnet_microseconds_per_tick = 1000000 / rtems_bsdnet_ticks_per_second;
272
273        /*
274         * Ensure that `seconds' is greater than 0
275         */
276    while (rtems_bsdnet_seconds_since_boot() == 0)
277        rtems_task_wake_after(1);
278
279        /*
280         * Set up BSD-style sockets
281         */
282        if (bsd_init () < 0)
283                return -1;
284
285        /*
286         * Start network daemon
287         */
288        networkDaemonTid = rtems_bsdnet_newproc ("ntwk", 4096, networkDaemon, NULL);
289
290        /*
291         * Let other network tasks begin
292         */
293        rtems_bsdnet_semaphore_release ();
294        return 0;
295}
296
297/*
298 * Obtain network mutex
299 */
300void
301rtems_bsdnet_semaphore_obtain (void)
302{
303#ifdef RTEMS_FAST_MUTEX
304        ISR_Level level;
305        _ISR_Disable (level);
306        _CORE_mutex_Seize (
307                &the_networkSemaphore->Core_control.mutex,
308                networkSemaphore,
309                1,              /* wait */
310                0,              /* forever */
311                level
312                );
313        if (_Thread_Executing->Wait.return_code)
314                rtems_panic ("rtems-net: can't obtain network sema: %d\n",
315                 _Thread_Executing->Wait.return_code);
316#else
317        rtems_status_code sc;
318
319        sc = rtems_semaphore_obtain (networkSemaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
320        if (sc != RTEMS_SUCCESSFUL)
321                rtems_panic ("rtems-net: can't obtain network semaphore: `%s'\n",
322                 rtems_status_text (sc));
323#endif
324}
325
326/*
327 * Release network mutex
328 */
329void
330rtems_bsdnet_semaphore_release (void)
331{
332#ifdef RTEMS_FAST_MUTEX
333        int i;
334
335        _Thread_Disable_dispatch();
336        i = _CORE_mutex_Surrender (
337                &the_networkSemaphore->Core_control.mutex,
338                networkSemaphore,
339                NULL
340                );
341        _Thread_Enable_dispatch();
342        if (i)
343                rtems_panic ("rtems-net: can't release network sema: %i\n");
344#else
345        rtems_status_code sc;
346
347        sc = rtems_semaphore_release (networkSemaphore);
348        if (sc != RTEMS_SUCCESSFUL)
349                rtems_panic ("rtems-net: can't release network semaphore: `%s'\n",
350                 rtems_status_text (sc));
351#endif
352}
353
354/*
355 * Wait for something to happen to a socket buffer
356 */
357int
358sbwait(sb)
359        struct sockbuf *sb;
360{
361        rtems_event_set events;
362        rtems_id tid;
363        rtems_status_code sc;
364
365        /*
366         * Soak up any pending events.
367         * The sleep/wakeup synchronization in the FreeBSD
368         * kernel has no memory.
369         */
370        rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT, &events);
371
372        /*
373         * Set this task as the target of the wakeup operation.
374         */
375        rtems_task_ident (RTEMS_SELF, 0, &tid);
376        sb->sb_sel.si_pid = tid;
377
378        /*
379         * Show that socket is waiting
380         */
381        sb->sb_flags |= SB_WAIT;
382
383        /*
384         * Release the network semaphore.
385         */
386        rtems_bsdnet_semaphore_release ();
387
388        /*
389         * Wait for the wakeup event.
390         */
391        sc = rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, sb->sb_timeo, &events);
392
393        /*
394         * Reobtain the network semaphore.
395         */
396        rtems_bsdnet_semaphore_obtain ();
397
398        /*
399         * Return the status of the wait.
400         */
401        switch (sc) {
402        case RTEMS_SUCCESSFUL:  return 0;
403        case RTEMS_TIMEOUT:     return EWOULDBLOCK;
404        default:                return ENXIO;
405        }
406}
407
408
409/*
410 * Wake up the task waiting on a socket buffer.
411 */
412void
413sowakeup(so, sb)
414        register struct socket *so;
415        register struct sockbuf *sb;
416{
417        if (sb->sb_flags & SB_WAIT) {
418                sb->sb_flags &= ~SB_WAIT;
419                rtems_event_send (sb->sb_sel.si_pid, SBWAIT_EVENT);
420        }
421        if (sb->sb_wakeup) {
422                (*sb->sb_wakeup) (so, sb->sb_wakeuparg);
423        }
424}
425
426/*
427 * For now, a socket can be used by only one task at a time.
428 */
429int
430sb_lock(sb)
431        register struct sockbuf *sb;
432{
433        rtems_panic ("Socket buffer is already in use.");
434        return 0;
435}
436void
437wakeup (void *p)
438{
439        rtems_panic ("Wakeup called");
440}
441
442/*
443 * Wait for a connection/disconnection event.
444 */
445int
446soconnsleep (struct socket *so)
447{
448        rtems_event_set events;
449        rtems_id tid;
450        rtems_status_code sc;
451
452        /*
453         * Soak up any pending events.
454         * The sleep/wakeup synchronization in the FreeBSD
455         * kernel has no memory.
456         */
457        rtems_event_receive (SOSLEEP_EVENT, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT, &events);
458
459        /*
460         * Set this task as the target of the wakeup operation.
461         */
462        if (so->so_pgid)
463                rtems_panic ("Another task is already sleeping on that socket");
464        rtems_task_ident (RTEMS_SELF, 0, &tid);
465        so->so_pgid = tid;
466
467        /*
468         * Wait for the wakeup event.
469         */
470        sc = rtems_bsdnet_event_receive (SOSLEEP_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, so->so_rcv.sb_timeo, &events);
471
472        /*
473         * Relinquish ownership of the socket.
474         */
475        so->so_pgid = 0;
476
477        switch (sc) {
478        case RTEMS_SUCCESSFUL:  return 0;
479        case RTEMS_TIMEOUT:     return EWOULDBLOCK;
480        default:                return ENXIO;
481        }
482}
483
484/*
485 * Wake up a task waiting for a connection/disconnection to complete.
486 */
487void
488soconnwakeup (struct socket *so)
489{
490        if (so->so_pgid)
491                rtems_event_send (so->so_pgid, SOSLEEP_EVENT);
492}
493
494/*
495 * Send an event to the network daemon.
496 * This corresponds to sending a software interrupt in the BSD kernel.
497 */
498void
499rtems_bsdnet_schednetisr (int n)
500{
501        rtems_event_send (networkDaemonTid, 1 << n);
502}
503
504/*
505 * The network daemon
506 * This provides a context to run BSD software interrupts
507 */
508static void
509networkDaemon (void *task_argument)
510{
511        rtems_status_code sc;
512        rtems_event_set events;
513        rtems_interval now;
514        int ticksPassed;
515        uint32_t   timeout;
516        struct callout *c;
517
518        for (;;) {
519                c = calltodo.c_next;
520                if (c)
521                        timeout = c->c_time;
522                else
523                        timeout = RTEMS_NO_TIMEOUT;
524
525                sc = rtems_bsdnet_event_receive (NETISR_EVENTS,
526                                                RTEMS_EVENT_ANY | RTEMS_WAIT,
527                                                timeout,
528                                                &events);
529                if ( sc == RTEMS_SUCCESSFUL ) {
530                        if (events & NETISR_IP_EVENT)
531                                ipintr ();
532                        if (events & NETISR_ARP_EVENT)
533                                arpintr ();
534                }
535
536                rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
537                ticksPassed = now - ticksWhenCalloutsLastChecked;
538                if (ticksPassed != 0) {
539                        ticksWhenCalloutsLastChecked = now;
540
541                        c = calltodo.c_next;
542                        if (c) {
543                                c->c_time -= ticksPassed;
544                                while ((c = calltodo.c_next) != NULL && c->c_time <= 0) {
545                                        void *arg;
546                                        void (*func) (void *);
547
548                                        func = c->c_func;
549                                        arg = c->c_arg;
550                                        calltodo.c_next = c->c_next;
551                                        c->c_next = callfree;
552                                        callfree = c;
553                                        (*func)(arg);
554                                }
555                        }
556                }
557        }
558}
559
560/*
561 * Structure passed to task-start stub
562 */
563struct newtask {
564        void (*entry)(void *);
565        void *arg;
566};
567
568/*
569 * Task-start stub
570 */
571static void
572taskEntry (rtems_task_argument arg)
573{
574        struct newtask t;
575
576        /*
577         * Pick up task information and free
578         * the memory allocated to pass the
579         * information to this task.
580         */
581        t = *(struct newtask *)arg;
582        free ((struct newtask *)arg);
583
584        /*
585         * Enter the competition for the network semaphore
586         */
587        rtems_bsdnet_semaphore_obtain ();
588
589        /*
590         * Enter the task
591         */
592        (*t.entry)(t.arg);
593        rtems_panic ("Network task returned!\n");
594}
595
596/*
597 * Start a network task
598 */
599rtems_id
600rtems_bsdnet_newproc (char *name, int stacksize, void(*entry)(void *), void *arg)
601{
602        struct newtask *t;
603        char nm[4];
604        rtems_id tid;
605        rtems_status_code sc;
606
607        strncpy (nm, name, 4);
608        sc = rtems_task_create (rtems_build_name(nm[0], nm[1], nm[2], nm[3]),
609                networkDaemonPriority,
610                stacksize,
611                RTEMS_PREEMPT|RTEMS_NO_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0),
612                RTEMS_NO_FLOATING_POINT|RTEMS_LOCAL,
613                &tid);
614        if (sc != RTEMS_SUCCESSFUL)
615                rtems_panic ("Can't create network daemon `%s': `%s'\n", name, rtems_status_text (sc));
616
617        /*
618         * Set up task arguments
619         */
620        t = malloc (sizeof *t);
621        t->entry = entry;
622        t->arg = arg;
623
624        /*
625         * Start the task
626         */
627        sc = rtems_task_start (tid, taskEntry, (rtems_task_argument)t);
628        if (sc != RTEMS_SUCCESSFUL)
629                rtems_panic ("Can't start network daemon `%s': `%s'\n", name, rtems_status_text (sc));
630
631        /*
632         * Let our caller know the i.d. of the new task
633         */
634        return tid;
635}
636
637rtems_status_code rtems_bsdnet_event_receive (
638  rtems_event_set  event_in,
639  rtems_option     option_set,
640  rtems_interval   ticks,
641  rtems_event_set *event_out)
642{
643        rtems_status_code sc;
644
645        rtems_bsdnet_semaphore_release ();
646        sc = rtems_event_receive (event_in, option_set, ticks, event_out);
647        rtems_bsdnet_semaphore_obtain ();
648        return sc;
649}
650
651/*
652 * Return time since startup
653 */
654void
655microtime (struct timeval *t)
656{
657        rtems_interval now;
658
659        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
660        t->tv_sec = now / rtems_bsdnet_ticks_per_second;
661        t->tv_usec = (now % rtems_bsdnet_ticks_per_second) * rtems_bsdnet_microseconds_per_tick;
662}
663
664unsigned long
665rtems_bsdnet_seconds_since_boot (void)
666{
667        rtems_interval now;
668
669        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
670        return now / rtems_bsdnet_ticks_per_second;
671}
672
673/*
674 * Fake random number generator
675 */
676unsigned long
677rtems_bsdnet_random (void)
678{
679        rtems_interval now;
680
681        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
682        return (now * 99991);
683}
684
685/*
686 * Callout list processing
687 */
688void
689rtems_bsdnet_timeout(void (*ftn)(void *), void *arg, int ticks)
690{
691        register struct callout *new, *p, *t;
692
693        if (ticks <= 0)
694                ticks = 1;
695
696        /* Fill in the next free callout structure. */
697        if (callfree == NULL) {
698                callfree = malloc (sizeof *callfree);
699                if (callfree == NULL)
700                        rtems_panic ("No memory for timeout table entry");
701                callfree->c_next = NULL;
702        }
703
704        new = callfree;
705        callfree = new->c_next;
706        new->c_arg = arg;
707        new->c_func = ftn;
708
709        /*
710         * The time for each event is stored as a difference from the time
711         * of the previous event on the queue.  Walk the queue, correcting
712         * the ticks argument for queue entries passed.  Correct the ticks
713         * value for the queue entry immediately after the insertion point
714         * as well.  Watch out for negative c_time values; these represent
715         * overdue events.
716         */
717        for (p = &calltodo;
718            (t = p->c_next) != NULL && ticks > t->c_time; p = t)
719                if (t->c_time > 0)
720                        ticks -= t->c_time;
721        new->c_time = ticks;
722        if (t != NULL)
723                t->c_time -= ticks;
724
725        /* Insert the new entry into the queue. */
726        p->c_next = new;
727        new->c_next = t;
728}
729
730/*
731 * Ticks till specified time
732 * XXX: This version worries only about seconds, but that's good
733 * enough for the way the network code uses this routine.
734 */
735int
736hzto(struct timeval *tv)
737{
738        long diff = tv->tv_sec - rtems_bsdnet_seconds_since_boot();
739
740        if (diff <= 0)
741                return 1;
742        return diff * rtems_bsdnet_ticks_per_second;
743}
744
745/*
746 * Kernel debugging
747 */
748int rtems_bsdnet_log_priority;
749void
750rtems_bsdnet_log (int priority, const char *fmt, ...)
751{
752        va_list args;
753
754        if (priority & rtems_bsdnet_log_priority) {
755                va_start (args, fmt);
756                vprintf (fmt, args);
757                va_end (args);
758        }
759}
760
761/*
762 * IP header checksum routine for processors which don't have an inline version
763 */
764u_int
765in_cksum_hdr (const void *ip)
766{
767        uint32_t   sum;
768        const uint16_t   *sp;
769        int i;
770
771        sum = 0;
772        sp = (uint16_t   *)ip;
773        for (i = 0 ; i < 10 ; i++)
774                sum += *sp++;
775        while (sum > 0xFFFF)
776                sum = (sum & 0xffff) + (sum >> 16);
777        return ~sum & 0xFFFF;
778}
779
780/*
781 * Manipulate routing tables
782 */
783int rtems_bsdnet_rtrequest (
784    int req,
785    struct sockaddr *dst,
786    struct sockaddr *gateway,
787    struct sockaddr *netmask,
788    int flags,
789    struct rtentry **net_nrt)
790{
791        int error;
792
793        rtems_bsdnet_semaphore_obtain ();
794        error = rtrequest (req, dst, gateway, netmask, flags, net_nrt);
795        rtems_bsdnet_semaphore_release ();
796        if (error) {
797                errno = error;
798                return -1;
799        }
800        return 0;
801}
802
803static int
804rtems_bsdnet_setup (void)
805{
806        struct rtems_bsdnet_ifconfig *ifp;
807        short flags;
808        struct sockaddr_in address;
809        struct sockaddr_in netmask;
810        struct sockaddr_in broadcast;
811        struct sockaddr_in gateway;
812        int i;
813        int any_if_configured = 0;
814
815        /*
816         * Set local parameters
817         */
818        if (rtems_bsdnet_config.hostname)
819                sethostname (rtems_bsdnet_config.hostname,
820                                        strlen (rtems_bsdnet_config.hostname));
821        if (rtems_bsdnet_config.domainname)
822                rtems_bsdnet_domain_name =
823                                        strdup (rtems_bsdnet_config.domainname);
824        if (rtems_bsdnet_config.log_host)
825                rtems_bsdnet_log_host_address.s_addr =
826                                inet_addr (rtems_bsdnet_config.log_host);
827        for (i = 0 ; i < sizeof rtems_bsdnet_config.name_server /
828                        sizeof rtems_bsdnet_config.name_server[0] ; i++) {
829                if (!rtems_bsdnet_config.name_server[i])
830                        break;
831                rtems_bsdnet_nameserver[rtems_bsdnet_nameserver_count++].s_addr
832                        = inet_addr (rtems_bsdnet_config.name_server[i]);
833        }
834        for (i = 0 ; i < sizeof rtems_bsdnet_config.ntp_server /
835                        sizeof rtems_bsdnet_config.ntp_server[0] ; i++) {
836                if (!rtems_bsdnet_config.ntp_server[i])
837                        break;
838                rtems_bsdnet_ntpserver[rtems_bsdnet_ntpserver_count++].s_addr
839                        = inet_addr (rtems_bsdnet_config.ntp_server[i]);
840        }
841
842        /*
843         * Configure interfaces
844         */
845        for (ifp = rtems_bsdnet_config.ifconfig ; ifp ; ifp = ifp->next) {
846                if (ifp->ip_address == NULL)
847                        continue;
848
849                /*
850                 * Bring interface up
851                 */
852                flags = IFF_UP;
853                if (rtems_bsdnet_ifconfig (ifp->name, SIOCSIFFLAGS, &flags) < 0) {
854                        printf ("Can't bring %s up: %s\n", ifp->name, strerror (errno));
855                        continue;
856                }
857
858                /*
859                 * Set interface netmask
860                 */
861                memset (&netmask, '\0', sizeof netmask);
862                netmask.sin_len = sizeof netmask;
863                netmask.sin_family = AF_INET;
864                netmask.sin_addr.s_addr = inet_addr (ifp->ip_netmask);
865                if (rtems_bsdnet_ifconfig (ifp->name, SIOCSIFNETMASK, &netmask) < 0) {
866                        printf ("Can't set %s netmask: %s\n", ifp->name, strerror (errno));
867                        continue;
868                }
869
870                /*
871                 * Set interface address
872                 */
873                memset (&address, '\0', sizeof address);
874                address.sin_len = sizeof address;
875                address.sin_family = AF_INET;
876                address.sin_addr.s_addr = inet_addr (ifp->ip_address);
877                if (rtems_bsdnet_ifconfig (ifp->name, SIOCSIFADDR, &address) < 0) {
878                        printf ("Can't set %s address: %s\n", ifp->name, strerror (errno));
879                        continue;
880                }
881
882                /*
883                 * Set interface broadcast address if the interface has the
884                 * broadcast flag set.
885                 */
886                if (rtems_bsdnet_ifconfig (ifp->name, SIOCGIFFLAGS, &flags) < 0) {
887                        printf ("Can't read %s flags: %s\n", ifp->name, strerror (errno));
888                        continue;
889                }
890
891                any_if_configured = 1;
892
893                if (flags & IFF_BROADCAST) {
894                        memset (&broadcast, '\0', sizeof broadcast);
895                        broadcast.sin_len = sizeof broadcast;
896                        broadcast.sin_family = AF_INET;
897                        broadcast.sin_addr.s_addr =
898                                        address.sin_addr.s_addr | ~netmask.sin_addr.s_addr;
899                        if (rtems_bsdnet_ifconfig (ifp->name, SIOCSIFBRDADDR, &broadcast) < 0) {
900                                struct in_addr  in_addr;
901                                char                    buf[20];
902                                in_addr.s_addr = broadcast.sin_addr.s_addr;
903                                if (!inet_ntop(AF_INET, &in_addr, buf, sizeof(buf)))
904                                                strcpy(buf,"?.?.?.?");
905                                printf ("Can't set %s broadcast address %s: %s\n",
906                                        ifp->name, buf, strerror (errno));
907                        }
908                }
909        }
910
911        /*
912         * Set default route
913         */
914        if (rtems_bsdnet_config.gateway && any_if_configured) {
915                address.sin_addr.s_addr = INADDR_ANY;
916                netmask.sin_addr.s_addr = INADDR_ANY;
917                memset (&gateway, '\0', sizeof gateway);
918                gateway.sin_len = sizeof gateway;
919                gateway.sin_family = AF_INET;
920                gateway.sin_addr.s_addr = inet_addr (rtems_bsdnet_config.gateway);
921                if (rtems_bsdnet_rtrequest (
922                                RTM_ADD,
923                                (struct sockaddr *)&address,
924                                (struct sockaddr *)&gateway,
925                                (struct sockaddr *)&netmask,
926                                (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL) < 0) {
927                        printf ("Can't set default route: %s\n", strerror (errno));
928                        return -1;
929                }
930        }
931        return 0;
932}
933
934/*
935 * Initialize the network
936 */
937int
938rtems_bsdnet_initialize_network (void)
939{
940        struct rtems_bsdnet_ifconfig *ifp;
941
942        /*
943         * Start network tasks.
944         * Initialize BSD network data structures.
945         */
946        if (rtems_bsdnet_initialize () < 0)
947                return -1;
948
949        /*
950         * Attach interfaces
951         */
952        for (ifp = rtems_bsdnet_config.ifconfig ; ifp ; ifp = ifp->next) {
953                rtems_bsdnet_attach (ifp);
954        }
955
956        /*
957         * Bring up the network
958         */
959        if (rtems_bsdnet_setup () < 0)
960                return -1;
961        if (rtems_bsdnet_config.bootp)
962                (*rtems_bsdnet_config.bootp)();
963        return 0;
964}
965
966/*
967 * Attach a network interface.
968 */
969void rtems_bsdnet_attach (struct rtems_bsdnet_ifconfig *ifp)
970{
971        if (ifp) {
972                rtems_bsdnet_semaphore_obtain ();
973                (ifp->attach)(ifp, 1);
974                rtems_bsdnet_semaphore_release ();
975        }
976}
977
978/*
979 * Detach a network interface.
980 */
981void rtems_bsdnet_detach (struct rtems_bsdnet_ifconfig *ifp)
982{
983        if (ifp) {
984                rtems_bsdnet_semaphore_obtain ();
985                (ifp->attach)(ifp, 0);
986                rtems_bsdnet_semaphore_release ();
987        }
988}
989
990/*
991 * Interface Configuration.
992 */
993int rtems_bsdnet_ifconfig (const char *ifname, uint32_t   cmd, void *param)
994{
995        int s, r = 0;
996        struct ifreq ifreq;
997
998        /*
999         * Configure interfaces
1000         */
1001        s = socket (AF_INET, SOCK_DGRAM, 0);
1002        if (s < 0)
1003                return -1;
1004
1005        strncpy (ifreq.ifr_name, ifname, IFNAMSIZ);
1006
1007        rtems_bsdnet_semaphore_obtain ();
1008
1009        switch (cmd) {
1010                case SIOCSIFADDR:
1011                case SIOCSIFNETMASK:
1012                        memcpy (&ifreq.ifr_addr, param, sizeof (struct sockaddr));
1013                        r = ioctl (s, cmd, &ifreq);
1014                        break;
1015
1016                case OSIOCGIFADDR:
1017                case SIOCGIFADDR:
1018                case OSIOCGIFNETMASK:
1019                case SIOCGIFNETMASK:
1020                        if ((r = ioctl (s, cmd, &ifreq)) < 0)
1021                                break;
1022                        memcpy (param, &ifreq.ifr_addr, sizeof (struct sockaddr));
1023                        break;
1024
1025                case SIOCGIFFLAGS:
1026                case SIOCSIFFLAGS:
1027                        if ((r = ioctl (s, SIOCGIFFLAGS, &ifreq)) < 0)
1028                                break;
1029                        if (cmd == SIOCGIFFLAGS) {
1030                                *((short*) param) = ifreq.ifr_flags;
1031                                break;
1032                        }
1033                        ifreq.ifr_flags |= *((short*) param);
1034                        if ( (*((short*) param) & IFF_UP ) == 0 ) {
1035                            /* set the interface down */
1036                            ifreq.ifr_flags &= ~(IFF_UP);
1037                        }
1038                        r = ioctl (s, SIOCSIFFLAGS, &ifreq);
1039                        break;
1040
1041                case SIOCSIFDSTADDR:
1042                        memcpy (&ifreq.ifr_dstaddr, param, sizeof (struct sockaddr));
1043                        r = ioctl (s, cmd, &ifreq);
1044                        break;
1045
1046                case OSIOCGIFDSTADDR:
1047                case SIOCGIFDSTADDR:
1048                        if ((r = ioctl (s, cmd, &ifreq)) < 0)
1049                                break;
1050                        memcpy (param, &ifreq.ifr_dstaddr, sizeof (struct sockaddr));
1051                        break;
1052
1053                case SIOCSIFBRDADDR:
1054                        memcpy (&ifreq.ifr_broadaddr, param, sizeof (struct sockaddr));
1055                        r = ioctl (s, cmd, &ifreq);
1056                        break;
1057
1058                case OSIOCGIFBRDADDR:
1059                case SIOCGIFBRDADDR:
1060                        if ((r = ioctl (s, cmd, &ifreq)) < 0)
1061                                break;
1062                        memcpy (param, &ifreq.ifr_broadaddr, sizeof (struct sockaddr));
1063                        break;
1064
1065                case SIOCSIFMETRIC:
1066                        ifreq.ifr_metric = *((int*) param);
1067                        r = ioctl (s, cmd, &ifreq);
1068                        break;
1069
1070                case SIOCGIFMETRIC:
1071                        if ((r = ioctl (s, cmd, &ifreq)) < 0)
1072                                break;
1073                        *((int*) param) = ifreq.ifr_metric;
1074                        break;
1075
1076                case SIOCSIFMTU:
1077                        ifreq.ifr_mtu = *((int*) param);
1078                        r = ioctl (s, cmd, &ifreq);
1079                        break;
1080
1081                case SIOCGIFMTU:
1082                        if ((r = ioctl (s, cmd, &ifreq)) < 0)
1083                                break;
1084                        *((int*) param) = ifreq.ifr_mtu;
1085                        break;
1086
1087                case SIOCSIFPHYS:
1088                        ifreq.ifr_phys = *((int*) param);
1089                        r = ioctl (s, cmd, &ifreq);
1090                        break;
1091
1092                case SIOCGIFPHYS:
1093                        if ((r = ioctl (s, cmd, &ifreq)) < 0)
1094                                break;
1095                        *((int*) param) = ifreq.ifr_phys;
1096                        break;
1097
1098                case SIOCSIFMEDIA:
1099                        ifreq.ifr_media = *((int*) param);
1100                        r = ioctl (s, cmd, &ifreq);
1101                        break;
1102
1103                case SIOCGIFMEDIA:
1104                        /* 'param' passes the phy index they want to
1105                         * look at...
1106                         */
1107                        ifreq.ifr_media = *((int*) param);
1108                        if ((r = ioctl (s, cmd, &ifreq)) < 0)
1109                                break;
1110                        *((int*) param) = ifreq.ifr_media;
1111                        break;
1112
1113                case SIOCAIFADDR:
1114                case SIOCDIFADDR:
1115                        r = ioctl(s, cmd, (struct freq *) param);
1116                        break;
1117
1118                default:
1119                        errno = EOPNOTSUPP;
1120                        r = -1;
1121                        break;
1122        }
1123
1124        rtems_bsdnet_semaphore_release ();
1125
1126        close (s);
1127        return r;
1128}
1129
1130/*
1131 * Parse a network driver name into a name and a unit number
1132 */
1133int
1134rtems_bsdnet_parse_driver_name (const struct rtems_bsdnet_ifconfig *config, char **namep)
1135{
1136        const char *cp = config->name;
1137        char c;
1138        int unitNumber = 0;
1139
1140        if (cp == NULL) {
1141                printf ("No network driver name.\n");
1142                return -1;
1143        }
1144        while ((c = *cp++) != '\0') {
1145                if ((c >= '0') && (c <= '9')) {
1146                        int len = cp - config->name;
1147                        if ((len < 2) || (len > 50))
1148                                break;
1149                        for (;;) {
1150                                unitNumber = (unitNumber * 10) + (c - '0');
1151                                c = *cp++;
1152                                if (c == '\0') {
1153                                        char *unitName = malloc (len);
1154                                        if (unitName == NULL) {
1155                                                printf ("No memory.\n");
1156                                                return -1;
1157                                        }
1158                                        strncpy (unitName, config->name, len - 1);
1159                                        unitName[len-1] = '\0';
1160                                        *namep = unitName;
1161                                        return unitNumber;
1162                                }
1163                                if ((c < '0') || (c > '9'))
1164                                        break;
1165                        }
1166                        break;
1167                }
1168        }
1169        printf ("Bad network driver name `%s'.\n", config->name);
1170        return -1;
1171}
1172
1173/*
1174 * Handle requests for more network memory
1175 * XXX: Another possibility would be to use a semaphore here with
1176 *      a release in the mbuf free macro.  I have chosen this `polling'
1177 *      approach because:
1178 *      1) It is simpler.
1179 *      2) It adds no complexity to the free macro.
1180 *      3) Running out of mbufs should be a rare
1181 *         condition -- predeployment testing of
1182 *         an application should indicate the
1183 *         required mbuf pool size.
1184 * XXX: Should there be a panic if a task is stuck in the loop for
1185 *      more than a minute or so?
1186 */
1187int
1188m_mballoc (int nmb, int nowait)
1189{
1190        if (nowait)
1191                return 0;
1192        m_reclaim ();
1193        if (mmbfree == NULL) {
1194                int try = 0;
1195                int print_limit = 30 * rtems_bsdnet_ticks_per_second;
1196
1197                mbstat.m_wait++;
1198                for (;;) {
1199                        rtems_bsdnet_semaphore_release ();
1200                        rtems_task_wake_after (1);
1201                        rtems_bsdnet_semaphore_obtain ();
1202                        if (mmbfree)
1203                                break;
1204                        if (++try >= print_limit) {
1205                                printf ("Still waiting for mbuf.\n");
1206                                try = 0;
1207                        }
1208                }
1209        }
1210        else {
1211                mbstat.m_drops++;
1212        }
1213        return 1;
1214}
1215
1216int
1217m_clalloc(ncl, nowait)
1218{
1219        if (nowait)
1220                return 0;
1221        m_reclaim ();
1222        if (mclfree == NULL) {
1223                int try = 0;
1224                int print_limit = 30 * rtems_bsdnet_ticks_per_second;
1225
1226                mbstat.m_wait++;
1227                for (;;) {
1228                        rtems_bsdnet_semaphore_release ();
1229                        rtems_task_wake_after (1);
1230                        rtems_bsdnet_semaphore_obtain ();
1231                        if (mclfree)
1232                                break;
1233                        if (++try >= print_limit) {
1234                                printf ("Still waiting for mbuf cluster.\n");
1235                                try = 0;
1236                        }
1237                }
1238        }
1239        else {
1240                mbstat.m_drops++;
1241        }
1242        return 1;
1243}
Note: See TracBrowser for help on using the repository browser.