source: rtems/cpukit/libnetworking/rtems/rtems_glue.c @ 4787739

4.104.114.84.95
Last change on this file since 4787739 was 4787739, checked in by Ralf Corsepius <ralf.corsepius@…>, on Feb 3, 2005 at 5:35:38 AM

2005-02-03 Ralf Corsepius <ralf.corsepius@…>

PR 755/rtems

  • libnetworking/rtems_glue.c: Rename rtems_bsdnet_nameservers to _rtems_bsdnet_nameservers. Rename rtems_bsdnet_ntpservers to _rtems_bsdnet_ntpservers. Add new rtems_bsdnet_nameservers, rtems_bsdnet_ntpservers as pointers to _rtems_bsdnet_*servers arrays.
  • libnetworking/rtems/rtems_bsdnet_internal.h: Remove rtems_bsdnet_nameserver, rtems_bsdnet_nameserver_count.
  • libnetworking/rtems/rtems_bsdnet.h: Remove rtems_bsdnet_ntpserver, rtems_bsdnet_ntp_count.
  • libnetworking/rtems/bsdnet/servers.h: New.
  • libnetworking/opt_ipsec.h: New (BSD compatibility).
  • libnetworking/Makefile.am: Reflect changes above.
  • Property mode set to 100644
File size: 26.1 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 int nmbuf        = (64 * 1024) / MSIZE;
52       int nmbclusters  = (128 * 1024) / 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;
100long 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 (unsigned long 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 = malloc ((nmbclusters*MCLBYTES)+MCLBYTES-1);
153        if (p == NULL) {
154                printf ("Can't get network cluster memory.\n");
155                return -1;
156        }
157        p = (char *)(((unsigned long)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 = malloc (nmbclusters);
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 = malloc(nmbuf * MSIZE + MSIZE - 1);
178        p = (char *)(((unsigned int)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 ("Can't obtain network semaphore\n");
315#else
316        rtems_status_code sc;
317
318        sc = rtems_semaphore_obtain (networkSemaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
319        if (sc != RTEMS_SUCCESSFUL)
320                rtems_panic ("Can't obtain network semaphore: `%s'\n", rtems_status_text (sc));
321#endif
322}
323
324/*
325 * Release network mutex
326 */
327void
328rtems_bsdnet_semaphore_release (void)
329{
330#ifdef RTEMS_FAST_MUTEX
331        int i;
332
333        _Thread_Disable_dispatch();
334        i = _CORE_mutex_Surrender (
335                &the_networkSemaphore->Core_control.mutex,
336                networkSemaphore,
337                NULL
338                );
339        _Thread_Enable_dispatch();
340        if (i)
341                rtems_panic ("Can't release network semaphore\n");
342#else
343        rtems_status_code sc;
344
345        sc = rtems_semaphore_release (networkSemaphore);
346        if (sc != RTEMS_SUCCESSFUL)
347                rtems_panic ("Can't release network semaphore: `%s'\n", rtems_status_text (sc));
348#endif
349}
350
351/*
352 * Wait for something to happen to a socket buffer
353 */
354int
355sbwait(sb)
356        struct sockbuf *sb;
357{
358        rtems_event_set events;
359        rtems_id tid;
360        rtems_status_code sc;
361
362        /*
363         * Soak up any pending events.
364         * The sleep/wakeup synchronization in the FreeBSD
365         * kernel has no memory.
366         */
367        rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT, &events);
368
369        /*
370         * Set this task as the target of the wakeup operation.
371         */
372        rtems_task_ident (RTEMS_SELF, 0, &tid);
373        sb->sb_sel.si_pid = tid;
374
375        /*
376         * Show that socket is waiting
377         */
378        sb->sb_flags |= SB_WAIT;
379
380        /*
381         * Release the network semaphore.
382         */
383        rtems_bsdnet_semaphore_release ();
384
385        /*
386         * Wait for the wakeup event.
387         */
388        sc = rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, sb->sb_timeo, &events);
389
390        /*
391         * Reobtain the network semaphore.
392         */
393        rtems_bsdnet_semaphore_obtain ();
394
395        /*
396         * Return the status of the wait.
397         */
398        switch (sc) {
399        case RTEMS_SUCCESSFUL:  return 0;
400        case RTEMS_TIMEOUT:     return EWOULDBLOCK;
401        default:                return ENXIO;
402        }
403}
404
405
406/*
407 * Wake up the task waiting on a socket buffer.
408 */
409void
410sowakeup(so, sb)
411        register struct socket *so;
412        register struct sockbuf *sb;
413{
414        if (sb->sb_flags & SB_WAIT) {
415                sb->sb_flags &= ~SB_WAIT;
416                rtems_event_send (sb->sb_sel.si_pid, SBWAIT_EVENT);
417        }
418        if (sb->sb_wakeup) {
419                (*sb->sb_wakeup) (so, sb->sb_wakeuparg);
420        }
421}
422
423/*
424 * For now, a socket can be used by only one task at a time.
425 */
426int
427sb_lock(sb)
428        register struct sockbuf *sb;
429{
430        rtems_panic ("Socket buffer is already in use.");
431        return 0;
432}
433void
434wakeup (void *p)
435{
436        rtems_panic ("Wakeup called");
437}
438
439/*
440 * Wait for a connection/disconnection event.
441 */
442int
443soconnsleep (struct socket *so)
444{
445        rtems_event_set events;
446        rtems_id tid;
447        rtems_status_code sc;
448
449        /*
450         * Soak up any pending events.
451         * The sleep/wakeup synchronization in the FreeBSD
452         * kernel has no memory.
453         */
454        rtems_event_receive (SOSLEEP_EVENT, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT, &events);
455
456        /*
457         * Set this task as the target of the wakeup operation.
458         */
459        if (so->so_pgid)
460                rtems_panic ("Another task is already sleeping on that socket");
461        rtems_task_ident (RTEMS_SELF, 0, &tid);
462        so->so_pgid = tid;
463
464        /*
465         * Wait for the wakeup event.
466         */
467        sc = rtems_bsdnet_event_receive (SOSLEEP_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, so->so_rcv.sb_timeo, &events);
468
469        /*
470         * Relinquish ownership of the socket.
471         */
472        so->so_pgid = 0;
473
474        switch (sc) {
475        case RTEMS_SUCCESSFUL:  return 0;
476        case RTEMS_TIMEOUT:     return EWOULDBLOCK;
477        default:                return ENXIO;
478        }
479}
480
481/*
482 * Wake up a task waiting for a connection/disconnection to complete.
483 */
484void
485soconnwakeup (struct socket *so)
486{
487        if (so->so_pgid)
488                rtems_event_send (so->so_pgid, SOSLEEP_EVENT);
489}
490
491/*
492 * Send an event to the network daemon.
493 * This corresponds to sending a software interrupt in the BSD kernel.
494 */
495void
496rtems_bsdnet_schednetisr (int n)
497{
498        rtems_event_send (networkDaemonTid, 1 << n);
499}
500
501/*
502 * The network daemon
503 * This provides a context to run BSD software interrupts
504 */
505static void
506networkDaemon (void *task_argument)
507{
508        rtems_status_code sc;
509        rtems_event_set events;
510        rtems_interval now;
511        int ticksPassed;
512        uint32_t   timeout;
513        struct callout *c;
514
515        for (;;) {
516                c = calltodo.c_next;
517                if (c)
518                        timeout = c->c_time;
519                else
520                        timeout = RTEMS_NO_TIMEOUT;
521
522                sc = rtems_bsdnet_event_receive (NETISR_EVENTS,
523                                                RTEMS_EVENT_ANY | RTEMS_WAIT,
524                                                timeout,
525                                                &events);
526                if ( sc == RTEMS_SUCCESSFUL ) {
527                        if (events & NETISR_IP_EVENT)
528                                ipintr ();
529                        if (events & NETISR_ARP_EVENT)
530                                arpintr ();
531                }
532
533                rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
534                ticksPassed = now - ticksWhenCalloutsLastChecked;
535                if (ticksPassed != 0) {
536                        ticksWhenCalloutsLastChecked = now;
537
538                        c = calltodo.c_next;
539                        if (c) {
540                                c->c_time -= ticksPassed;
541                                while ((c = calltodo.c_next) != NULL && c->c_time <= 0) {
542                                        void *arg;
543                                        void (*func) (void *);
544
545                                        func = c->c_func;
546                                        arg = c->c_arg;
547                                        calltodo.c_next = c->c_next;
548                                        c->c_next = callfree;
549                                        callfree = c;
550                                        (*func)(arg);
551                                }
552                        }
553                }
554        }
555}
556
557/*
558 * Structure passed to task-start stub
559 */
560struct newtask {
561        void (*entry)(void *);
562        void *arg;
563};
564
565/*
566 * Task-start stub
567 */
568static void
569taskEntry (rtems_task_argument arg)
570{
571        struct newtask t;
572
573        /*
574         * Pick up task information and free
575         * the memory allocated to pass the
576         * information to this task.
577         */
578        t = *(struct newtask *)arg;
579        free ((struct newtask *)arg);
580
581        /*
582         * Enter the competition for the network semaphore
583         */
584        rtems_bsdnet_semaphore_obtain ();
585
586        /*
587         * Enter the task
588         */
589        (*t.entry)(t.arg);
590        rtems_panic ("Network task returned!\n");
591}
592
593/*
594 * Start a network task
595 */
596rtems_id
597rtems_bsdnet_newproc (char *name, int stacksize, void(*entry)(void *), void *arg)
598{
599        struct newtask *t;
600        char nm[4];
601        rtems_id tid;
602        rtems_status_code sc;
603
604        strncpy (nm, name, 4);
605        sc = rtems_task_create (rtems_build_name(nm[0], nm[1], nm[2], nm[3]),
606                networkDaemonPriority,
607                stacksize,
608                RTEMS_PREEMPT|RTEMS_NO_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0),
609                RTEMS_NO_FLOATING_POINT|RTEMS_LOCAL,
610                &tid);
611        if (sc != RTEMS_SUCCESSFUL)
612                rtems_panic ("Can't create network daemon `%s': `%s'\n", name, rtems_status_text (sc));
613
614        /*
615         * Set up task arguments
616         */
617        t = malloc (sizeof *t);
618        t->entry = entry;
619        t->arg = arg;
620
621        /*
622         * Start the task
623         */
624        sc = rtems_task_start (tid, taskEntry, (rtems_task_argument)t);
625        if (sc != RTEMS_SUCCESSFUL)
626                rtems_panic ("Can't start network daemon `%s': `%s'\n", name, rtems_status_text (sc));
627
628        /*
629         * Let our caller know the i.d. of the new task
630         */
631        return tid;
632}
633
634rtems_status_code rtems_bsdnet_event_receive (
635  rtems_event_set  event_in,
636  rtems_option     option_set,
637  rtems_interval   ticks,
638  rtems_event_set *event_out)
639{
640        rtems_status_code sc;
641
642        rtems_bsdnet_semaphore_release ();
643        sc = rtems_event_receive (event_in, option_set, ticks, event_out);
644        rtems_bsdnet_semaphore_obtain ();
645        return sc;
646}
647
648/*
649 * Return time since startup
650 */
651void
652microtime (struct timeval *t)
653{
654        rtems_interval now;
655
656        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
657        t->tv_sec = now / rtems_bsdnet_ticks_per_second;
658        t->tv_usec = (now % rtems_bsdnet_ticks_per_second) * rtems_bsdnet_microseconds_per_tick;
659}
660
661unsigned long
662rtems_bsdnet_seconds_since_boot (void)
663{
664        rtems_interval now;
665
666        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
667        return now / rtems_bsdnet_ticks_per_second;
668}
669
670/*
671 * Fake random number generator
672 */
673unsigned long
674rtems_bsdnet_random (void)
675{
676        rtems_interval now;
677
678        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
679        return (now * 99991);
680}
681
682/*
683 * Callout list processing
684 */
685void
686timeout(void (*ftn)(void *), void *arg, int ticks)
687{
688        register struct callout *new, *p, *t;
689
690        if (ticks <= 0)
691                ticks = 1;
692
693        /* Fill in the next free callout structure. */
694        if (callfree == NULL) {
695                callfree = malloc (sizeof *callfree);
696                if (callfree == NULL)
697                        rtems_panic ("No memory for timeout table entry");
698                callfree->c_next = NULL;
699        }
700
701        new = callfree;
702        callfree = new->c_next;
703        new->c_arg = arg;
704        new->c_func = ftn;
705
706        /*
707         * The time for each event is stored as a difference from the time
708         * of the previous event on the queue.  Walk the queue, correcting
709         * the ticks argument for queue entries passed.  Correct the ticks
710         * value for the queue entry immediately after the insertion point
711         * as well.  Watch out for negative c_time values; these represent
712         * overdue events.
713         */
714        for (p = &calltodo;
715            (t = p->c_next) != NULL && ticks > t->c_time; p = t)
716                if (t->c_time > 0)
717                        ticks -= t->c_time;
718        new->c_time = ticks;
719        if (t != NULL)
720                t->c_time -= ticks;
721
722        /* Insert the new entry into the queue. */
723        p->c_next = new;
724        new->c_next = t;
725}
726
727/*
728 * Ticks till specified time
729 * XXX: This version worries only about seconds, but that's good
730 * enough for the way the network code uses this routine.
731 */
732int
733hzto(struct timeval *tv)
734{
735        long diff = tv->tv_sec - rtems_bsdnet_seconds_since_boot();
736
737        if (diff <= 0)
738                return 1;
739        return diff * rtems_bsdnet_ticks_per_second;
740}
741
742/*
743 * Kernel debugging
744 */
745int rtems_bsdnet_log_priority;
746void
747rtems_bsdnet_log (int priority, const char *fmt, ...)
748{
749        va_list args;
750
751        if (priority & rtems_bsdnet_log_priority) {
752                va_start (args, fmt);
753                vprintf (fmt, args);
754                va_end (args);
755        }
756}
757
758/*
759 * IP header checksum routine for processors which don't have an inline version
760 */
761u_int
762in_cksum_hdr (const void *ip)
763{
764        uint32_t   sum;
765        const uint16_t   *sp;
766        int i;
767
768        sum = 0;
769        sp = (uint16_t   *)ip;
770        for (i = 0 ; i < 10 ; i++)
771                sum += *sp++;
772        while (sum > 0xFFFF)
773                sum = (sum & 0xffff) + (sum >> 16);
774        return ~sum & 0xFFFF;
775}
776
777/*
778 * Manipulate routing tables
779 */
780int rtems_bsdnet_rtrequest (
781    int req,
782    struct sockaddr *dst,
783    struct sockaddr *gateway,
784    struct sockaddr *netmask,
785    int flags,
786    struct rtentry **net_nrt)
787{
788        int error;
789
790        rtems_bsdnet_semaphore_obtain ();
791        error = rtrequest (req, dst, gateway, netmask, flags, net_nrt);
792        rtems_bsdnet_semaphore_release ();
793        if (error) {
794                errno = error;
795                return -1;
796        }
797        return 0;
798}
799
800static int
801rtems_bsdnet_setup (void)
802{
803        struct rtems_bsdnet_ifconfig *ifp;
804        short flags;
805        struct sockaddr_in address;
806        struct sockaddr_in netmask;
807        struct sockaddr_in broadcast;
808        struct sockaddr_in gateway;
809        int i;
810        extern char *strdup (const char *cp);
811
812        /*
813         * Set local parameters
814         */
815        if (rtems_bsdnet_config.hostname)
816                sethostname (rtems_bsdnet_config.hostname,
817                                        strlen (rtems_bsdnet_config.hostname));
818        if (rtems_bsdnet_config.domainname)
819                rtems_bsdnet_domain_name =
820                                        strdup (rtems_bsdnet_config.domainname);
821        if (rtems_bsdnet_config.log_host)
822                rtems_bsdnet_log_host_address.s_addr =
823                                inet_addr (rtems_bsdnet_config.log_host);
824        for (i = 0 ; i < sizeof rtems_bsdnet_config.name_server /
825                        sizeof rtems_bsdnet_config.name_server[0] ; i++) {
826                if (!rtems_bsdnet_config.name_server[i])
827                        break;
828                rtems_bsdnet_nameserver[rtems_bsdnet_nameserver_count++].s_addr
829                        = inet_addr (rtems_bsdnet_config.name_server[i]);
830        }
831        for (i = 0 ; i < sizeof rtems_bsdnet_config.ntp_server /
832                        sizeof rtems_bsdnet_config.ntp_server[0] ; i++) {
833                if (!rtems_bsdnet_config.ntp_server[i])
834                        break;
835                rtems_bsdnet_ntpserver[rtems_bsdnet_ntpserver_count++].s_addr
836                        = inet_addr (rtems_bsdnet_config.ntp_server[i]);
837        }
838
839        /*
840         * Configure interfaces
841         */
842        for (ifp = rtems_bsdnet_config.ifconfig ; ifp ; ifp = ifp->next) {
843                if (ifp->ip_address == NULL)
844                        continue;
845
846                /*
847                 * Bring interface up
848                 */
849                flags = IFF_UP;
850                if (rtems_bsdnet_ifconfig (ifp->name, SIOCSIFFLAGS, &flags) < 0) {
851                        printf ("Can't bring %s up: %s\n", ifp->name, strerror (errno));
852                        continue;
853                }
854
855                /*
856                 * Set interface netmask
857                 */
858                memset (&netmask, '\0', sizeof netmask);
859                netmask.sin_len = sizeof netmask;
860                netmask.sin_family = AF_INET;
861                netmask.sin_addr.s_addr = inet_addr (ifp->ip_netmask);
862                if (rtems_bsdnet_ifconfig (ifp->name, SIOCSIFNETMASK, &netmask) < 0) {
863                        printf ("Can't set %s netmask: %s\n", ifp->name, strerror (errno));
864                        continue;
865                }
866
867                /*
868                 * Set interface address
869                 */
870                memset (&address, '\0', sizeof address);
871                address.sin_len = sizeof address;
872                address.sin_family = AF_INET;
873                address.sin_addr.s_addr = inet_addr (ifp->ip_address);
874                if (rtems_bsdnet_ifconfig (ifp->name, SIOCSIFADDR, &address) < 0) {
875                        printf ("Can't set %s address: %s\n", ifp->name, strerror (errno));
876                        continue;
877                }
878
879                /*
880                 * Set interface broadcast address if the interface has the
881                 * broadcast flag set.
882                 */
883                if (rtems_bsdnet_ifconfig (ifp->name, SIOCGIFFLAGS, &flags) < 0) {
884                        printf ("Can't read %s flags: %s\n", ifp->name, strerror (errno));
885                        continue;
886                }
887                if (flags & IFF_BROADCAST) {
888                        memset (&broadcast, '\0', sizeof broadcast);
889                        broadcast.sin_len = sizeof broadcast;
890                        broadcast.sin_family = AF_INET;
891                        broadcast.sin_addr.s_addr =
892                                        address.sin_addr.s_addr | ~netmask.sin_addr.s_addr;
893                        if (rtems_bsdnet_ifconfig (ifp->name, SIOCSIFBRDADDR, &broadcast) < 0) {
894                                struct in_addr  in_addr;
895                                char                    buf[20];
896                                in_addr.s_addr = broadcast.sin_addr.s_addr;
897                                if (!inet_ntop(AF_INET, &in_addr, buf, sizeof(buf)))
898                                                strcpy(buf,"?.?.?.?");
899                                printf ("Can't set %s broadcast address %s: %s\n",
900                                        ifp->name, buf, strerror (errno));
901                        }
902                }
903        }
904
905        /*
906         * Set default route
907         */
908        if (rtems_bsdnet_config.gateway) {
909                address.sin_addr.s_addr = INADDR_ANY;
910                netmask.sin_addr.s_addr = INADDR_ANY;
911                memset (&gateway, '\0', sizeof gateway);
912                gateway.sin_len = sizeof gateway;
913                gateway.sin_family = AF_INET;
914                gateway.sin_addr.s_addr = inet_addr (rtems_bsdnet_config.gateway);
915                if (rtems_bsdnet_rtrequest (
916                                RTM_ADD,
917                                (struct sockaddr *)&address,
918                                (struct sockaddr *)&gateway,
919                                (struct sockaddr *)&netmask,
920                                (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL) < 0) {
921                        printf ("Can't set default route: %s\n", strerror (errno));
922                        return -1;
923                }
924        }
925        return 0;
926}
927
928/*
929 * Initialize the network
930 */
931int
932rtems_bsdnet_initialize_network (void)
933{
934        struct rtems_bsdnet_ifconfig *ifp;
935
936        /*
937         * Start network tasks.
938         * Initialize BSD network data structures.
939         */
940        if (rtems_bsdnet_initialize () < 0)
941                return -1;
942
943        /*
944         * Attach interfaces
945         */
946        for (ifp = rtems_bsdnet_config.ifconfig ; ifp ; ifp = ifp->next) {
947                rtems_bsdnet_attach (ifp);
948        }
949
950        /*
951         * Bring up the network
952         */
953        if (rtems_bsdnet_setup () < 0)
954                return -1;
955        if (rtems_bsdnet_config.bootp)
956                (*rtems_bsdnet_config.bootp)();
957        return 0;
958}
959
960/*
961 * Attach a network interface.
962 */
963void rtems_bsdnet_attach (struct rtems_bsdnet_ifconfig *ifp)
964{
965        if (ifp) {
966                rtems_bsdnet_semaphore_obtain ();
967                (ifp->attach)(ifp, 1);
968                rtems_bsdnet_semaphore_release ();
969        }
970}
971
972/*
973 * Detach a network interface.
974 */
975void rtems_bsdnet_detach (struct rtems_bsdnet_ifconfig *ifp)
976{
977        if (ifp) {
978                rtems_bsdnet_semaphore_obtain ();
979                (ifp->attach)(ifp, 0);
980                rtems_bsdnet_semaphore_release ();
981        }
982}
983
984/*
985 * Interface Configuration.
986 */
987int rtems_bsdnet_ifconfig (const char *ifname, uint32_t   cmd, void *param)
988{
989        int s, r = 0;
990        struct ifreq ifreq;
991
992        /*
993         * Configure interfaces
994         */
995        s = socket (AF_INET, SOCK_DGRAM, 0);
996        if (s < 0)
997                return -1;
998
999        strncpy (ifreq.ifr_name, ifname, IFNAMSIZ);
1000
1001        rtems_bsdnet_semaphore_obtain ();
1002
1003        switch (cmd) {
1004                case SIOCSIFADDR:
1005                case SIOCSIFNETMASK:
1006                        memcpy (&ifreq.ifr_addr, param, sizeof (struct sockaddr));
1007                        r = ioctl (s, cmd, &ifreq);
1008                        break;
1009
1010                case OSIOCGIFADDR:
1011                case SIOCGIFADDR:
1012                case OSIOCGIFNETMASK:
1013                case SIOCGIFNETMASK:
1014                        if ((r = ioctl (s, cmd, &ifreq)) < 0)
1015                                break;
1016                        memcpy (param, &ifreq.ifr_addr, sizeof (struct sockaddr));
1017                        break;
1018
1019                case SIOCGIFFLAGS:
1020                case SIOCSIFFLAGS:
1021                        if ((r = ioctl (s, SIOCGIFFLAGS, &ifreq)) < 0)
1022                                break;
1023                        if (cmd == SIOCGIFFLAGS) {
1024                                *((short*) param) = ifreq.ifr_flags;
1025                                break;
1026                        }
1027                        ifreq.ifr_flags |= *((short*) param);
1028                        if ( (*((short*) param) & IFF_UP ) == 0 ) {
1029                            /* set the interface down */
1030                            ifreq.ifr_flags &= ~(IFF_UP);
1031                        }
1032                        r = ioctl (s, SIOCSIFFLAGS, &ifreq);
1033                        break;
1034
1035                case SIOCSIFDSTADDR:
1036                        memcpy (&ifreq.ifr_dstaddr, param, sizeof (struct sockaddr));
1037                        r = ioctl (s, cmd, &ifreq);
1038                        break;
1039
1040                case OSIOCGIFDSTADDR:
1041                case SIOCGIFDSTADDR:
1042                        if ((r = ioctl (s, cmd, &ifreq)) < 0)
1043                                break;
1044                        memcpy (param, &ifreq.ifr_dstaddr, sizeof (struct sockaddr));
1045                        break;
1046
1047                case SIOCSIFBRDADDR:
1048                        memcpy (&ifreq.ifr_broadaddr, param, sizeof (struct sockaddr));
1049                        r = ioctl (s, cmd, &ifreq);
1050                        break;
1051
1052                case OSIOCGIFBRDADDR:
1053                case SIOCGIFBRDADDR:
1054                        if ((r = ioctl (s, cmd, &ifreq)) < 0)
1055                                break;
1056                        memcpy (param, &ifreq.ifr_broadaddr, sizeof (struct sockaddr));
1057                        break;
1058
1059                case SIOCSIFMETRIC:
1060                        ifreq.ifr_metric = *((int*) param);
1061                        r = ioctl (s, cmd, &ifreq);
1062                        break;
1063
1064                case SIOCGIFMETRIC:
1065                        if ((r = ioctl (s, cmd, &ifreq)) < 0)
1066                                break;
1067                        *((int*) param) = ifreq.ifr_metric;
1068                        break;
1069
1070                case SIOCSIFMTU:
1071                        ifreq.ifr_mtu = *((int*) param);
1072                        r = ioctl (s, cmd, &ifreq);
1073                        break;
1074
1075                case SIOCGIFMTU:
1076                        if ((r = ioctl (s, cmd, &ifreq)) < 0)
1077                                break;
1078                        *((int*) param) = ifreq.ifr_mtu;
1079                        break;
1080
1081                case SIOCSIFPHYS:
1082                        ifreq.ifr_phys = *((int*) param);
1083                        r = ioctl (s, cmd, &ifreq);
1084                        break;
1085
1086                case SIOCGIFPHYS:
1087                        if ((r = ioctl (s, cmd, &ifreq)) < 0)
1088                                break;
1089                        *((int*) param) = ifreq.ifr_phys;
1090                        break;
1091
1092                case SIOCSIFMEDIA:
1093                        ifreq.ifr_media = *((int*) param);
1094                        r = ioctl (s, cmd, &ifreq);
1095                        break;
1096
1097                case SIOCGIFMEDIA:
1098                        if ((r = ioctl (s, cmd, &ifreq)) < 0)
1099                                break;
1100                        *((int*) param) = ifreq.ifr_media;
1101                        break;
1102
1103                case SIOCAIFADDR:
1104                case SIOCDIFADDR:
1105                        r = ioctl(s, cmd, (struct freq *) param);
1106                        break;
1107
1108                default:
1109                        errno = EOPNOTSUPP;
1110                        r = -1;
1111                        break;
1112        }
1113
1114        rtems_bsdnet_semaphore_release ();
1115
1116        close (s);
1117        return r;
1118}
1119
1120/*
1121 * Parse a network driver name into a name and a unit number
1122 */
1123int
1124rtems_bsdnet_parse_driver_name (const struct rtems_bsdnet_ifconfig *config, char **namep)
1125{
1126        const char *cp = config->name;
1127        char c;
1128        int unitNumber = 0;
1129
1130        if (cp == NULL) {
1131                printf ("No network driver name.\n");
1132                return -1;
1133        }
1134        while ((c = *cp++) != '\0') {
1135                if ((c >= '0') && (c <= '9')) {
1136                        int len = cp - config->name;
1137                        if ((len < 2) || (len > 50))
1138                                break;
1139                        for (;;) {
1140                                unitNumber = (unitNumber * 10) + (c - '0');
1141                                c = *cp++;
1142                                if (c == '\0') {
1143                                        char *unitName = malloc (len);
1144                                        if (unitName == NULL) {
1145                                                printf ("No memory.\n");
1146                                                return -1;
1147                                        }
1148                                        strncpy (unitName, config->name, len - 1);
1149                                        unitName[len-1] = '\0';
1150                                        *namep = unitName;
1151                                        return unitNumber;
1152                                }
1153                                if ((c < '0') || (c > '9'))
1154                                        break;
1155                        }
1156                        break;
1157                }
1158        }
1159        printf ("Bad network driver name `%s'.\n", config->name);
1160        return -1;
1161}
1162
1163/*
1164 * Handle requests for more network memory
1165 * XXX: Another possibility would be to use a semaphore here with
1166 *      a release in the mbuf free macro.  I have chosen this `polling'
1167 *      approach because:
1168 *      1) It is simpler.
1169 *      2) It adds no complexity to the free macro.
1170 *      3) Running out of mbufs should be a rare
1171 *         condition -- predeployment testing of
1172 *         an application should indicate the
1173 *         required mbuf pool size.
1174 * XXX: Should there be a panic if a task is stuck in the loop for
1175 *      more than a minute or so?
1176 */
1177int
1178m_mballoc (int nmb, int nowait)
1179{
1180        if (nowait)
1181                return 0;
1182        m_reclaim ();
1183        if (mmbfree == NULL) {
1184                int try = 0;
1185                int print_limit = 30 * rtems_bsdnet_ticks_per_second;
1186
1187                mbstat.m_wait++;
1188                for (;;) {
1189                        rtems_bsdnet_semaphore_release ();
1190                        rtems_task_wake_after (1);
1191                        rtems_bsdnet_semaphore_obtain ();
1192                        if (mmbfree)
1193                                break;
1194                        if (++try >= print_limit) {
1195                                printf ("Still waiting for mbuf.\n");
1196                                try = 0;
1197                        }
1198                }
1199        }
1200        else {
1201                mbstat.m_drops++;
1202        }
1203        return 1;
1204}
1205
1206int
1207m_clalloc(ncl, nowait)
1208{
1209        if (nowait)
1210                return 0;
1211        m_reclaim ();
1212        if (mclfree == NULL) {
1213                int try = 0;
1214                int print_limit = 30 * rtems_bsdnet_ticks_per_second;
1215
1216                mbstat.m_wait++;
1217                for (;;) {
1218                        rtems_bsdnet_semaphore_release ();
1219                        rtems_task_wake_after (1);
1220                        rtems_bsdnet_semaphore_obtain ();
1221                        if (mclfree)
1222                                break;
1223                        if (++try >= print_limit) {
1224                                printf ("Still waiting for mbuf cluster.\n");
1225                                try = 0;
1226                        }
1227                }
1228        }
1229        else {
1230                mbstat.m_drops++;
1231        }
1232        return 1;
1233}
Note: See TracBrowser for help on using the repository browser.