source: rtems/c/src/exec/libnetworking/rtems/rtems_glue.c @ ecec2ba

4.104.114.84.9
Last change on this file since ecec2ba was ecec2ba, checked in by Joel Sherrill <joel.sherrill@…>, on Feb 5, 1999 at 12:29:23 AM

Patch from Eric Norum to correct bug induced by select() patch.

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