source: rtems/cpukit/libnetworking/rtems/rtems_glue.c @ 547b04f

4.104.114.84.95
Last change on this file since 547b04f was 547b04f, checked in by Eric Norum <WENorum@…>, on 01/28/05 at 19:52:19

Remove dead variable.

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