source: rtems/c/src/lib/libnetworking/rtems/rtems_glue.c @ 109b17f4

4.104.114.84.95
Last change on this file since 109b17f4 was 109b17f4, checked in by Joel Sherrill <joel.sherrill@…>, on 09/10/98 at 12:23:08

Patch from Eric Norum <eric@…> to fix a cryptic error
message after comments from Eric Valette <valette@…>.

  • Property mode set to 100644
File size: 19.7 KB
RevLine 
[96b39164]1/*
2 *  $Id$
3 */
4
[39e6e65a]5#include <string.h>
6#include <stdarg.h>
7#include <stdio.h>
8#include <errno.h>
9
10#include <rtems.h>
11#include <rtems/libio.h>
12#include <rtems/error.h>
13#include <rtems/rtems_bsdnet.h>
14#include <sys/types.h>
15#include <sys/param.h>
16#include <sys/domain.h>
17#include <sys/mbuf.h>
18#include <sys/socketvar.h>
19#include <sys/socket.h>
20#include <sys/sockio.h>
21#include <sys/callout.h>
22#include <sys/proc.h>
[33679ec4]23#include <sys/ioctl.h>
[39e6e65a]24#include <net/if.h>
25#include <net/route.h>
26#include <netinet/in.h>
27#include <vm/vm.h>
28#include <arpa/inet.h>
29
30#include <net/netisr.h>
31#include <net/route.h>
32
33/*
34 * Events used by networking routines.
35 * Everything will break if the application
36 * tries to use these events or if the `sleep'
37 * events are equal to any of the NETISR * events.
38 */
39#define SBWAIT_EVENT    RTEMS_EVENT_24
40#define SOSLEEP_EVENT   RTEMS_EVENT_25
41#define NETISR_IP_EVENT         (1 << NETISR_IP)
42#define NETISR_ARP_EVENT        (1 << NETISR_ARP)
43#define NETISR_EVENTS   (NETISR_IP_EVENT|NETISR_ARP_EVENT)
44
45
46/*
47 * Memory allocation
48 */
49static int nmbuf        = (64 * 1024) / MSIZE;
50       int nmbclusters  = (128 * 1024) / MCLBYTES;
51
52/*
53 * Socket buffering parameters
54 */
55unsigned long sb_efficiency = 8;
56
57/*
58 * Network task synchronization
59 */
60static rtems_id networkSemaphore;
61static rtems_id networkDaemonTid;
62static rtems_unsigned32 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;
75static struct callout *callfree, calltodo;
76
77/*
78 * FreeBSD variables
79 */
80int nfs_diskless_valid;
81
82/*
83 * BOOTP values
84 */
85struct in_addr rtems_bsdnet_log_host_address;
86struct in_addr rtems_bsdnet_bootp_server_address;
87char *rtems_bsdnet_bootp_boot_file_name;
88char *rtems_bsdnet_domain_name;
89struct in_addr rtems_bsdnet_nameserver[sizeof rtems_bsdnet_config.name_server /
90                        sizeof rtems_bsdnet_config.name_server[0]];
91int rtems_bsdnet_nameserver_count;
92
93extern rtems_libio_handler_t rtems_bsdnet_io_handler;
94
95/*
96 * Perform FreeBSD memory allocation.
97 * FIXME: This should be modified to keep memory allocation statistics.
98 */
99#undef malloc
100#undef free
101extern void *malloc (size_t);
102extern void free (void *);
103void *
104rtems_bsdnet_malloc (unsigned long size, int type, int flags)
105{
106        void *p;
107
108        for (;;) {
109                p = malloc (size);
110                if (p)
111                        return p;
112                if (flags & M_NOWAIT)
113                        return p;
114                /*
115                 * FIXME: This should be redone as:
116                 * static volatile int rtems_bsdnet_need_memory;
117                 *     
118                 *      rtems_bsdnet_need_memory = 1;
119                 *      message_queue_receive
120                 *
121                 * Then in rtems_bsdnet_freee:
122                 *      free (....);
123                 *      if (rtems_bsdnet_need_memory)
124                 *              rtems_bsdnet_need_memory = 0;
125                 *              message_queue_broadcast
126                 */
127                rtems_task_wake_after (rtems_bsdnet_ticks_per_second);
128        }
129}
130
131/*
132 * Free FreeBSD memory
133 * FIXME: This should be modified to keep memory allocation statistics.
134 */
135void
136rtems_bsdnet_free (void *addr, int type)
137{
138        free (addr);
139}
140
141/*
142 * Do the initializations required by the BSD code
143 * FIXME: Maybe we should use a different memory allocation scheme that
144 * would let us share space between mbufs and mbuf clusters.
145 * For now, we'll just take the easy way out!
146 */
147static void
148bsd_init ()
149{
150        /*
151         * Set up mbuf data strutures
152         * Cluster allocation *must* come first -- see comment on kmem_malloc().
153         */
154        m_clalloc (nmbclusters, M_DONTWAIT);
155        mclrefcnt = malloc (nmbclusters);
156        if (mclrefcnt == NULL)
157                rtems_panic ("No memory for mbuf cluster reference counts.");
158        memset (mclrefcnt, '\0', nmbclusters);
159        m_mballoc (nmbuf, M_DONTWAIT);
160        mbstat.m_mtypes[MT_FREE] = nmbuf;
161
162
163        /*
164         * Set up domains
165         */
166        {
167        extern struct domain routedomain;
168        extern struct domain inetdomain;
169
170        routedomain.dom_next = domains;
171        domains = &routedomain;
172        inetdomain.dom_next = domains;
173        domains = &inetdomain;
174        domaininit (NULL);
175        }
176
177        /*
178         * Set up interfaces
179         */
180        ifinit (NULL);
181}
182
183/*
184 * Initialize and start network operations
185 */
186static void
187rtems_bsdnet_initialize (void)
188{
189        rtems_status_code sc;
190
191        /*
192         * Set the priority of all network tasks
193         */
194        if (rtems_bsdnet_config.network_task_priority == 0)
195                networkDaemonPriority = 100;
196        else
197                networkDaemonPriority = rtems_bsdnet_config.network_task_priority;
198
199        /*
200         * Set the memory allocation limits
201         */
202        if (rtems_bsdnet_config.mbuf_bytecount)
203                nmbuf = rtems_bsdnet_config.mbuf_bytecount / MSIZE;
204        if (rtems_bsdnet_config.mbuf_cluster_bytecount)
205                nmbclusters = rtems_bsdnet_config.mbuf_cluster_bytecount / MCLBYTES;
206
207        /*
208         * Create the task-synchronization semaphore
209         */
210        sc = rtems_semaphore_create (rtems_build_name('B', 'S', 'D', 'n'),
211                                        0,
212                                        RTEMS_FIFO |
213                                                RTEMS_BINARY_SEMAPHORE |
214                                                RTEMS_NO_INHERIT_PRIORITY |
215                                                RTEMS_NO_PRIORITY_CEILING |
216                                                RTEMS_LOCAL,
217                                        0,
218                                        &networkSemaphore);
219        if (sc != RTEMS_SUCCESSFUL)
220                rtems_panic ("Can't create network seamphore: `%s'\n", rtems_status_text (sc));
221
222        /*
223         * Compute clock tick conversion factors
224         */
225        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &rtems_bsdnet_ticks_per_second);
226        if (rtems_bsdnet_ticks_per_second <= 0)
227                rtems_bsdnet_ticks_per_second = 1;
228        rtems_bsdnet_microseconds_per_tick = 1000000 / rtems_bsdnet_ticks_per_second;
229
230        /*
231         * Ensure that `seconds' is greater than 0
232         */
233        rtems_task_wake_after (rtems_bsdnet_ticks_per_second);
234
235        /*
236         * Set up BSD-style sockets
237         */
238        bsd_init ();
239
240        /*
241         * Start network daemon
242         */
243        networkDaemonTid = rtems_bsdnet_newproc ("ntwk", 4096, networkDaemon, NULL);
244
245        /*
246         * Register as an external I/O handler
247         */
248        rtems_register_libio_handler (RTEMS_FILE_DESCRIPTOR_TYPE_SOCKET,
249                                                &rtems_bsdnet_io_handler);
250
251        /*
252         * Let other network tasks begin
253         */
254        rtems_bsdnet_semaphore_release ();
255}
256
257rtems_id TaskWithSemaphore;
258/*
259 * Obtain network mutex
260 */
261void
262rtems_bsdnet_semaphore_obtain (void)
263{
264        rtems_status_code sc;
265
266        sc = rtems_semaphore_obtain (networkSemaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
267rtems_task_ident (RTEMS_SELF, 0, &TaskWithSemaphore);
268        if (sc != RTEMS_SUCCESSFUL)
269                rtems_panic ("Can't obtain network semaphore: `%s'\n", rtems_status_text (sc));
270}
271
272/*
273 * Release network mutex
274 */
275void
276rtems_bsdnet_semaphore_release (void)
277{
278        rtems_status_code sc;
279
280TaskWithSemaphore = 0;
281        sc = rtems_semaphore_release (networkSemaphore);
282        if (sc != RTEMS_SUCCESSFUL)
283                rtems_panic ("Can't release network semaphore: `%s'\n", rtems_status_text (sc));
284                                                                                }
285
286/*
287 * Wait for something to happen to a socket buffer
288 */
289int
290sbwait(sb)
291        struct sockbuf *sb;
292{
293        rtems_event_set events;
294        rtems_id tid;
295        rtems_status_code sc;
296
297        /*
298         * Soak up any pending events.
299         * The sleep/wakeup synchronization in the FreeBSD
300         * kernel has no memory.
301         */
302        rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT, &events);
303
304        /*
305         * Set this task as the target of the wakeup operation.
306         */
307        if (sb->sb_sel.si_pid)
308                rtems_panic ("Another task is already sleeping on that socket buffer");
309        rtems_task_ident (RTEMS_SELF, 0, &tid);
310        sb->sb_sel.si_pid = tid;
311
312        /*
313         * Mark the socket buffer as waiting.
314         */
315        sb->sb_flags |= SB_WAIT;
316
317        /*
318         * Release the network semaphore.
319         */
320        rtems_bsdnet_semaphore_release ();
321
322        /*
323         * Wait for the wakeup event.
324         */
325        sc = rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, sb->sb_timeo, &events);
326
327        /*
328         * Reobtain the network semaphore.
329         */
330        rtems_bsdnet_semaphore_obtain ();
331
332        /*
333         * Relinquish ownership of the socket buffer
334         */
335        sb->sb_flags &= ~SB_WAIT;
336        sb->sb_sel.si_pid = 0;
337
338        /*
339         * Return the status of the wait.
340         */
341        switch (sc) {
342        case RTEMS_SUCCESSFUL:  return 0;
343        case RTEMS_TIMEOUT:     return EWOULDBLOCK;
344        default:                return ENXIO;
345        }
346}
347
348
349/*
350 * Wake up the task waiting on a socket buffer.
351 */
352void
353sowakeup(so, sb)
354        register struct socket *so;
355        register struct sockbuf *sb;
356{
357        if (sb->sb_flags & SB_WAIT) {
358                sb->sb_flags &= ~SB_WAIT;
359                rtems_event_send (sb->sb_sel.si_pid, SBWAIT_EVENT);
360        }
361}
362
363/*
364 * For now, a socket can be used by only one task at a time.
365 */
366int
367sb_lock(sb)
368        register struct sockbuf *sb;
369{
370        rtems_panic ("Socket buffer is already in use.");
371        return 0;
372}
373void
374wakeup (void *p)
375{
376        rtems_panic ("Wakeup called");
377}
378
379/*
380 * Wait for a connection/disconnection event.
381 */
382void
383soconnsleep (struct socket *so)
384{
385        rtems_event_set events;
386        rtems_id tid;
387
388        /*
389         * Soak up any pending events.
390         * The sleep/wakeup synchronization in the FreeBSD
391         * kernel has no memory.
392         */
393        rtems_event_receive (SOSLEEP_EVENT, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT, &events);
394
395        /*
396         * Set this task as the target of the wakeup operation.
397         */
398        if (so->so_pgid)
399                rtems_panic ("Another task is already sleeping on that socket");
400        rtems_task_ident (RTEMS_SELF, 0, &tid);
401        so->so_pgid = tid;
402
403        /*
404         * Wait for the wakeup event.
405         */
406        rtems_bsdnet_event_receive (SOSLEEP_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, RTEMS_NO_TIMEOUT, &events);
407
408        /*
409         * Relinquish ownership of the socket.
410         */
411        so->so_pgid = 0;
412}
413
414/*
415 * Wake up a task waiting for a connection/disconnection to complete.
416 */
417void
418soconnwakeup (struct socket *so)
419{
420        if (so->so_pgid)
421                rtems_event_send (so->so_pgid, SOSLEEP_EVENT);
422}
423
424/*
425 * Send an event to the network daemon.
426 * This corresponds to sending a software interrupt in the BSD kernel.
427 */
428void
429rtems_bsdnet_schednetisr (int n)
430{
431        rtems_event_send (networkDaemonTid, 1 << n);
432}
433
434/*
435 * The network daemon
436 * This provides a context to run BSD software interrupts
437 */
438static void
439networkDaemon (void *task_argument)
440{
441        rtems_event_set events;
442        rtems_interval now;
443        int ticksPassed;
444        unsigned32 timeout;
445        struct callout *c;
446
447        for (;;) {
448                c = calltodo.c_next;
449                if (c)
450                        timeout = c->c_time;
451                else
452                        timeout = RTEMS_NO_TIMEOUT;
453                rtems_bsdnet_event_receive (NETISR_EVENTS,
454                                                RTEMS_EVENT_ANY | RTEMS_WAIT,
455                                                timeout,
456                                                &events);
457                if (events & NETISR_IP_EVENT)
458                        ipintr ();
459                if (events & NETISR_ARP_EVENT)
460                        arpintr ();
461                rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
462                ticksPassed = now - ticksWhenCalloutsLastChecked;
463                if (ticksPassed != 0) {
464                        ticksWhenCalloutsLastChecked = now;
465                       
466                        c = calltodo.c_next;
467                        if (c) {
468                                c->c_time -= ticksPassed;
469                                while ((c = calltodo.c_next) != NULL && c->c_time <= 0) {
470                                        void *arg;
471                                        void (*func) (void *);
472
473                                        func = c->c_func;
474                                        arg = c->c_arg;
475                                        calltodo.c_next = c->c_next;
476                                        c->c_next = callfree;
477                                        callfree = c;
478                                        (*func)(arg);
479                                }
480                        }
481                }
482        }
483}
484
485/*
486 * Structure passed to task-start stub
487 */
488struct newtask {
489        void (*entry)(void *);
490        void *arg;
491};
492
493/*
494 * Task-start stub
495 */
496static void
497taskEntry (rtems_task_argument arg)
498{
499        struct newtask t;
500       
501        /*
502         * Pick up task information and free
503         * the memory allocated to pass the
504         * information to this task.
505         */
506        t = *(struct newtask *)arg;
507        free ((struct newtask *)arg);
508
509        /*
510         * Enter the competition for the network semaphore
511         */
512        rtems_bsdnet_semaphore_obtain ();
513
514        /*
515         * Enter the task
516         */
517        (*t.entry)(t.arg);
518        rtems_panic ("Network task returned!\n");
519}
520
521/*
522 * Start a network task
523 */
524rtems_id
525rtems_bsdnet_newproc (char *name, int stacksize, void(*entry)(void *), void *arg)
526{
527        struct newtask *t;
528        char nm[4];
529        rtems_id tid;
530        rtems_status_code sc;
531
532        strncpy (nm, name, 4);
533        sc = rtems_task_create (rtems_build_name(nm[0], nm[1], nm[2], nm[3]),
534                networkDaemonPriority,
535                stacksize,
536                RTEMS_PREEMPT|RTEMS_NO_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0),
537                RTEMS_NO_FLOATING_POINT|RTEMS_LOCAL,
538                &tid);
539        if (sc != RTEMS_SUCCESSFUL)
540                rtems_panic ("Can't create network daemon `%s': `%s'\n", name, rtems_status_text (sc));
541
542        /*
543         * Set up task arguments
544         */
545        t = malloc (sizeof *t);
546        t->entry = entry;
547        t->arg = arg;
548
549        /*
550         * Start the task
551         */
552        sc = rtems_task_start (tid, taskEntry, (rtems_task_argument)t);
553        if (sc != RTEMS_SUCCESSFUL)
554                rtems_panic ("Can't start network daemon `%s': `%s'\n", name, rtems_status_text (sc));
555
556        /*
557         * Let our caller know the i.d. of the new task
558         */
559        return tid;
560}
561
562rtems_status_code rtems_bsdnet_event_receive (
563  rtems_event_set  event_in,
564  rtems_option     option_set,
565  rtems_interval   ticks,
566  rtems_event_set *event_out)
567{
568        rtems_status_code sc;
569
570        rtems_bsdnet_semaphore_release ();
571        sc = rtems_event_receive (event_in, option_set, ticks, event_out);
572        rtems_bsdnet_semaphore_obtain ();
573        return sc;
574}
575
576/*
577 * Return time since startup
578 */
579void
580microtime (struct timeval *t)
581{
582        rtems_interval now;
583
584        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
585        t->tv_sec = now / rtems_bsdnet_ticks_per_second;
586        t->tv_usec = (now % rtems_bsdnet_ticks_per_second) * rtems_bsdnet_microseconds_per_tick;
587}
588
589unsigned long
590rtems_bsdnet_seconds_since_boot (void)
591{
592        rtems_interval now;
593
594        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
595        return now / rtems_bsdnet_ticks_per_second;
596}
597
598/*
599 * Fake random number generator
600 */
601unsigned long
602rtems_bsdnet_random (void)
603{
604        rtems_interval now;
605
606        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
607        return (now * 99991);
608}
609
610/*
611 * Callout list processing
612 */
613void
614timeout(void (*ftn)(void *), void *arg, int ticks)
615{
616        register struct callout *new, *p, *t;
617
618        if (ticks <= 0)
619                ticks = 1;
620
621        /* Fill in the next free callout structure. */
622        if (callfree == NULL) {
623                callfree = malloc (sizeof *callfree);
624                if (callfree == NULL)
625                        rtems_panic ("No memory for timeout table entry");
626                callfree->c_next = NULL;
627        }
628
629        new = callfree;
630        callfree = new->c_next;
631        new->c_arg = arg;
632        new->c_func = ftn;
633
634        /*
635         * The time for each event is stored as a difference from the time
636         * of the previous event on the queue.  Walk the queue, correcting
637         * the ticks argument for queue entries passed.  Correct the ticks
638         * value for the queue entry immediately after the insertion point
639         * as well.  Watch out for negative c_time values; these represent
640         * overdue events.
641         */
642        for (p = &calltodo;
643            (t = p->c_next) != NULL && ticks > t->c_time; p = t)
644                if (t->c_time > 0)
645                        ticks -= t->c_time;
646        new->c_time = ticks;
647        if (t != NULL)
648                t->c_time -= ticks;
649
650        /* Insert the new entry into the queue. */
651        p->c_next = new;
652        new->c_next = t;
653}
654
655/*
656 * Ticks till specified time
657 * FIXME: This version worries only about seconds, but that's good
658 * enough for the way the network code uses this routine.
659 */
660int
661hzto(struct timeval *tv)
662{
663        long diff = tv->tv_sec - rtems_bsdnet_seconds_since_boot();
664
665        if (diff <= 0)
666                return 1;
667        return diff * rtems_bsdnet_ticks_per_second;
668}
669
670/*
671 * Kernel debugging
672 */
673int rtems_bsdnet_log_priority;
674void
675rtems_bsdnet_log (int priority, const char *fmt, ...)
676{
677        va_list args;
678       
679        if (priority & rtems_bsdnet_log_priority) {
680                va_start (args, fmt);
681                vprintf (fmt, args);
682                va_end (args);
683        }
684}
685
686/*
687 * Hack alert: kmem_malloc `knows' that its
688 * first invocation is to get mbuf clusters!
689 */
690int mb_map_full;
691vm_map_t mb_map;
692vm_offset_t
693kmem_malloc (vm_map_t *map, vm_size_t size, boolean_t waitflag)
694{
695        void *p;
696       
697        /*
698         * Can't get memory if we're already running.
699         */
700        if (networkDaemonTid) {
701                if (waitflag == M_WAITOK)
[109b17f4]702                        rtems_panic (
703"Network mbuf space can not be enlarged after rtems_bsdnet_initialize() has\n"
704"returned.  Enlarge the initial mbuf/cluster size in rtems_bsdnet_config.");
[39e6e65a]705                return 0;
706        }
707
708#define ROUNDSIZE 2048
709        p = malloc (size+ROUNDSIZE);
710        p = (void *)((unsigned long)p & ~(ROUNDSIZE-1));
711        if ((p == NULL) && (waitflag == M_WAITOK))
712                rtems_panic ("Can't get initial network memory!");
713        if (mbutl == NULL)
714                mbutl = p;
715        return (vm_offset_t)p;
716}
717
718/*
719 * IP header checksum routine for processors which don't have an inline version
720 */
721u_int
722in_cksum_hdr (const void *ip)
723{
724        rtems_unsigned32 sum;
725        const rtems_unsigned16 *sp;
726        int i;
727
728        sum = 0;
729        sp = (rtems_unsigned16 *)ip;
730        for (i = 0 ; i < 10 ; i++)
731                sum += *sp++;
732        while (sum > 0xFFFF)
733                sum = (sum & 0xffff) + (sum >> 16);
734        return ~sum & 0xFFFF;
735}
736
737/*
738 * Manipulate routing tables
739 */
740int rtems_bsdnet_rtrequest (
741    int req,
742    struct sockaddr *dst,
743    struct sockaddr *gateway,
744    struct sockaddr *netmask,
745    int flags,
746    struct rtentry **net_nrt)
747{
748        int error;
749
750        rtems_bsdnet_semaphore_obtain ();
751        error = rtrequest (req, dst, gateway, netmask, flags, net_nrt);
752        rtems_bsdnet_semaphore_release ();
753        if (error) {
754                errno = error;
755                return -1;
756        }
757        return 0;
758}
759
760static void
761rtems_bsdnet_setup (void)
762{
763        struct rtems_bsdnet_ifconfig *ifp;
764        int s;
765        struct ifreq ifreq;
766        struct sockaddr_in address;
767        struct sockaddr_in netmask;
768        struct sockaddr_in broadcast;
769        struct sockaddr_in gateway;
770        int i;
771
772        /*
773         * Set local parameters
774         */
775        if (rtems_bsdnet_config.hostname)
776                sethostname (rtems_bsdnet_config.hostname,
777                                        strlen (rtems_bsdnet_config.hostname));
778        if (rtems_bsdnet_config.domainname)
779                rtems_bsdnet_domain_name =
780                                        strdup (rtems_bsdnet_config.domainname);
781        if (rtems_bsdnet_config.log_host)
782                rtems_bsdnet_log_host_address.s_addr =
783                                inet_addr (rtems_bsdnet_config.log_host);
784        for (i = 0 ; i < sizeof rtems_bsdnet_config.name_server /
785                        sizeof rtems_bsdnet_config.name_server[0] ; i++) {
786                if (!rtems_bsdnet_config.name_server[i])
787                        break;
788                rtems_bsdnet_nameserver[rtems_bsdnet_nameserver_count++].s_addr
789                        = inet_addr (rtems_bsdnet_config.name_server[i]);
790        }
791
792        /*
793         * Configure interfaces
794         */
795        s = socket (AF_INET, SOCK_DGRAM, 0);
796        if (s < 0)
797                rtems_panic ("Can't create initial socket: %s", strerror (errno));
798        for (ifp = rtems_bsdnet_config.ifconfig ; ifp ; ifp = ifp->next) {
799                if (ifp->ip_address == NULL)
800                        continue;
801
802                /*
803                 * Get the interface flags
804                 */
805                strcpy (ifreq.ifr_name, ifp->name);
806                if (ioctl (s, SIOCGIFFLAGS, &ifreq) < 0)
807                        rtems_panic ("Can't get %s flags: %s", ifp->name, strerror (errno));
808
809                /*
810                 * Bring interface up
811                 */
812                ifreq.ifr_flags |= IFF_UP;
813                if (ioctl (s, SIOCSIFFLAGS, &ifreq) < 0)
814                        rtems_panic ("Can't bring %s up: %s", ifp->name, strerror (errno));
815
816                /*
817                 * Set interface netmask
818                 */
819                memset (&netmask, '\0', sizeof netmask);
820                netmask.sin_len = sizeof netmask;
821                netmask.sin_family = AF_INET;
822                netmask.sin_addr.s_addr = inet_addr (ifp->ip_netmask);
823                memcpy (&ifreq.ifr_addr, &netmask, sizeof netmask);
824                if (ioctl (s, SIOCSIFNETMASK, &ifreq) < 0)
825                        rtems_panic ("Can't set %s netmask: %s", ifp->name, strerror (errno));
826
827                /*
828                 * Set interface address
829                 */
830                memset (&address, '\0', sizeof address);
831                address.sin_len = sizeof address;
832                address.sin_family = AF_INET;
833                address.sin_addr.s_addr = inet_addr (ifp->ip_address);
834                memcpy (&ifreq.ifr_addr, &address, sizeof address);
835                if (ioctl (s, SIOCSIFADDR, &ifreq) < 0)
836                        rtems_panic ("Can't set %s address: %s", ifp->name, strerror (errno));
837
838                /*
839                 * Set interface broadcast address
840                 */
841                memset (&broadcast, '\0', sizeof broadcast);
842                broadcast.sin_len = sizeof broadcast;
843                broadcast.sin_family = AF_INET;
844                broadcast.sin_addr.s_addr = address.sin_addr.s_addr | ~netmask.sin_addr.s_addr;
845                memcpy (&ifreq.ifr_broadaddr, &broadcast, sizeof broadcast);
846                if (ioctl (s, SIOCSIFBRDADDR, &ifreq) < 0)
847                        rtems_panic ("Can't set %s broadcast address: %s", ifp->name, strerror (errno));
848        }
849
850        /*
851         * We're done with the dummy socket
852         */
853        close (s);
854
855        /*
856         * Set default route
857         */
858        if (rtems_bsdnet_config.gateway) {
859                address.sin_addr.s_addr = INADDR_ANY;
860                netmask.sin_addr.s_addr = INADDR_ANY;
861                memset (&gateway, '\0', sizeof gateway);
862                gateway.sin_len = sizeof gateway;
863                gateway.sin_family = AF_INET;
864                gateway.sin_addr.s_addr = inet_addr (rtems_bsdnet_config.gateway);
865                if (rtems_bsdnet_rtrequest (
866                                RTM_ADD,
867                                (struct sockaddr *)&address,
868                                (struct sockaddr *)&gateway,
869                                (struct sockaddr *)&netmask,
870                                (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL) < 0)
871                        rtems_panic ("Can't set default route: %s", strerror (errno));
872        }
873}
874
875/*
876 * Initialize the network
877 */
878int
879rtems_bsdnet_initialize_network (void)
880{
881        struct rtems_bsdnet_ifconfig *ifp;
882
883        /*
884         * Start network tasks.
885         * Initialize BSD network data structures.
886         */
887        rtems_bsdnet_initialize ();
888
889        /*
890         * Attach interfaces
891         */
892        for (ifp = rtems_bsdnet_config.ifconfig ; ifp ; ifp = ifp->next) {
893                rtems_bsdnet_semaphore_obtain ();
894                (ifp->attach)(ifp);
895                rtems_bsdnet_semaphore_release ();
896        }
897
898        /*
899         * Bring up the network
900         */
901        rtems_bsdnet_setup ();
902        if (rtems_bsdnet_config.bootp)
903                (*rtems_bsdnet_config.bootp)();
904        return 0;
905}
Note: See TracBrowser for help on using the repository browser.