source: rtems/c/src/lib/libnetworking/rtems/rtems_glue.c @ 96b39164

4.104.114.84.95
Last change on this file since 96b39164 was 96b39164, checked in by Joel Sherrill <joel.sherrill@…>, on 08/20/98 at 21:56:40

Added CVS Ids

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