source: rtems/c/src/lib/libnetworking/rtems/rtems_glue.c @ 73f6236

4.104.114.84.95
Last change on this file since 73f6236 was 73f6236, checked in by Joel Sherrill <joel.sherrill@…>, on Mar 1, 1999 at 10:40:08 PM

Patch from Eric Norum <eric@…> to eliminate external
IO handlers scheme that was implemented originally just to support
sockets. The file system IO switch is more general and works fine.

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