source: rtems/c/src/libnetworking/rtems/rtems_glue.c @ cca4400

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

Merged Eric Norum's select patch that was based on 4.0 and resolved
all conflicts.

  • Property mode set to 100644
File size: 19.2 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 * 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;
[847375f]75char *rtems_bsdnet_bootp_server_name;
[39e6e65a]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         */
[cca4400]236        rtems_register_libio_handler (LIBIO_FLAGS_HANDLER_SOCK,
[39e6e65a]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         * Release the network semaphore.
300         */
301        rtems_bsdnet_semaphore_release ();
302
303        /*
304         * Wait for the wakeup event.
305         */
306        sc = rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, sb->sb_timeo, &events);
307
308        /*
309         * Reobtain the network semaphore.
310         */
311        rtems_bsdnet_semaphore_obtain ();
312
313        /*
314         * Return the status of the wait.
315         */
316        switch (sc) {
317        case RTEMS_SUCCESSFUL:  return 0;
318        case RTEMS_TIMEOUT:     return EWOULDBLOCK;
319        default:                return ENXIO;
320        }
321}
322
323
324/*
325 * Wake up the task waiting on a socket buffer.
326 */
327void
328sowakeup(so, sb)
329        register struct socket *so;
330        register struct sockbuf *sb;
331{
[cca4400]332        rtems_id tid;
333
334        if ((tid = sb->sb_sel.si_pid) != 0) {
335                sb->sb_sel.si_pid = 0;
336                rtems_event_send (tid, SBWAIT_EVENT);
[39e6e65a]337        }
338}
339
340/*
341 * For now, a socket can be used by only one task at a time.
342 */
343int
344sb_lock(sb)
345        register struct sockbuf *sb;
346{
347        rtems_panic ("Socket buffer is already in use.");
348        return 0;
349}
350void
351wakeup (void *p)
352{
353        rtems_panic ("Wakeup called");
354}
355
356/*
357 * Wait for a connection/disconnection event.
358 */
[91b1c8e6]359int
[39e6e65a]360soconnsleep (struct socket *so)
361{
362        rtems_event_set events;
363        rtems_id tid;
[91b1c8e6]364        rtems_status_code sc;
[39e6e65a]365
366        /*
367         * Soak up any pending events.
368         * The sleep/wakeup synchronization in the FreeBSD
369         * kernel has no memory.
370         */
371        rtems_event_receive (SOSLEEP_EVENT, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT, &events);
372
373        /*
374         * Set this task as the target of the wakeup operation.
375         */
376        if (so->so_pgid)
377                rtems_panic ("Another task is already sleeping on that socket");
378        rtems_task_ident (RTEMS_SELF, 0, &tid);
379        so->so_pgid = tid;
380
381        /*
382         * Wait for the wakeup event.
383         */
[91b1c8e6]384        sc = rtems_bsdnet_event_receive (SOSLEEP_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, so->so_rcv.sb_timeo, &events);
[39e6e65a]385
386        /*
387         * Relinquish ownership of the socket.
388         */
389        so->so_pgid = 0;
[91b1c8e6]390
391        switch (sc) {
392        case RTEMS_SUCCESSFUL:  return 0;
393        case RTEMS_TIMEOUT:     return EWOULDBLOCK;
394        default:                return ENXIO;
395        }
[39e6e65a]396}
397
398/*
399 * Wake up a task waiting for a connection/disconnection to complete.
400 */
401void
402soconnwakeup (struct socket *so)
403{
404        if (so->so_pgid)
405                rtems_event_send (so->so_pgid, SOSLEEP_EVENT);
406}
407
408/*
409 * Send an event to the network daemon.
410 * This corresponds to sending a software interrupt in the BSD kernel.
411 */
412void
413rtems_bsdnet_schednetisr (int n)
414{
415        rtems_event_send (networkDaemonTid, 1 << n);
416}
417
418/*
419 * The network daemon
420 * This provides a context to run BSD software interrupts
421 */
422static void
423networkDaemon (void *task_argument)
424{
425        rtems_event_set events;
426        rtems_interval now;
427        int ticksPassed;
428        unsigned32 timeout;
429        struct callout *c;
430
431        for (;;) {
432                c = calltodo.c_next;
433                if (c)
434                        timeout = c->c_time;
435                else
436                        timeout = RTEMS_NO_TIMEOUT;
437                rtems_bsdnet_event_receive (NETISR_EVENTS,
438                                                RTEMS_EVENT_ANY | RTEMS_WAIT,
439                                                timeout,
440                                                &events);
441                if (events & NETISR_IP_EVENT)
442                        ipintr ();
443                if (events & NETISR_ARP_EVENT)
444                        arpintr ();
445                rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
446                ticksPassed = now - ticksWhenCalloutsLastChecked;
447                if (ticksPassed != 0) {
448                        ticksWhenCalloutsLastChecked = now;
449                       
450                        c = calltodo.c_next;
451                        if (c) {
452                                c->c_time -= ticksPassed;
453                                while ((c = calltodo.c_next) != NULL && c->c_time <= 0) {
454                                        void *arg;
455                                        void (*func) (void *);
456
457                                        func = c->c_func;
458                                        arg = c->c_arg;
459                                        calltodo.c_next = c->c_next;
460                                        c->c_next = callfree;
461                                        callfree = c;
462                                        (*func)(arg);
463                                }
464                        }
465                }
466        }
467}
468
469/*
470 * Structure passed to task-start stub
471 */
472struct newtask {
473        void (*entry)(void *);
474        void *arg;
475};
476
477/*
478 * Task-start stub
479 */
480static void
481taskEntry (rtems_task_argument arg)
482{
483        struct newtask t;
484       
485        /*
486         * Pick up task information and free
487         * the memory allocated to pass the
488         * information to this task.
489         */
490        t = *(struct newtask *)arg;
491        free ((struct newtask *)arg);
492
493        /*
494         * Enter the competition for the network semaphore
495         */
496        rtems_bsdnet_semaphore_obtain ();
497
498        /*
499         * Enter the task
500         */
501        (*t.entry)(t.arg);
502        rtems_panic ("Network task returned!\n");
503}
504
505/*
506 * Start a network task
507 */
508rtems_id
509rtems_bsdnet_newproc (char *name, int stacksize, void(*entry)(void *), void *arg)
510{
511        struct newtask *t;
512        char nm[4];
513        rtems_id tid;
514        rtems_status_code sc;
515
516        strncpy (nm, name, 4);
517        sc = rtems_task_create (rtems_build_name(nm[0], nm[1], nm[2], nm[3]),
518                networkDaemonPriority,
519                stacksize,
520                RTEMS_PREEMPT|RTEMS_NO_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0),
521                RTEMS_NO_FLOATING_POINT|RTEMS_LOCAL,
522                &tid);
523        if (sc != RTEMS_SUCCESSFUL)
524                rtems_panic ("Can't create network daemon `%s': `%s'\n", name, rtems_status_text (sc));
525
526        /*
527         * Set up task arguments
528         */
529        t = malloc (sizeof *t);
530        t->entry = entry;
531        t->arg = arg;
532
533        /*
534         * Start the task
535         */
536        sc = rtems_task_start (tid, taskEntry, (rtems_task_argument)t);
537        if (sc != RTEMS_SUCCESSFUL)
538                rtems_panic ("Can't start network daemon `%s': `%s'\n", name, rtems_status_text (sc));
539
540        /*
541         * Let our caller know the i.d. of the new task
542         */
543        return tid;
544}
545
546rtems_status_code rtems_bsdnet_event_receive (
547  rtems_event_set  event_in,
548  rtems_option     option_set,
549  rtems_interval   ticks,
550  rtems_event_set *event_out)
551{
552        rtems_status_code sc;
553
554        rtems_bsdnet_semaphore_release ();
555        sc = rtems_event_receive (event_in, option_set, ticks, event_out);
556        rtems_bsdnet_semaphore_obtain ();
557        return sc;
558}
559
560/*
561 * Return time since startup
562 */
563void
564microtime (struct timeval *t)
565{
566        rtems_interval now;
567
568        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
569        t->tv_sec = now / rtems_bsdnet_ticks_per_second;
570        t->tv_usec = (now % rtems_bsdnet_ticks_per_second) * rtems_bsdnet_microseconds_per_tick;
571}
572
573unsigned long
574rtems_bsdnet_seconds_since_boot (void)
575{
576        rtems_interval now;
577
578        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
579        return now / rtems_bsdnet_ticks_per_second;
580}
581
582/*
583 * Fake random number generator
584 */
585unsigned long
586rtems_bsdnet_random (void)
587{
588        rtems_interval now;
589
590        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
591        return (now * 99991);
592}
593
594/*
595 * Callout list processing
596 */
597void
598timeout(void (*ftn)(void *), void *arg, int ticks)
599{
600        register struct callout *new, *p, *t;
601
602        if (ticks <= 0)
603                ticks = 1;
604
605        /* Fill in the next free callout structure. */
606        if (callfree == NULL) {
607                callfree = malloc (sizeof *callfree);
608                if (callfree == NULL)
609                        rtems_panic ("No memory for timeout table entry");
610                callfree->c_next = NULL;
611        }
612
613        new = callfree;
614        callfree = new->c_next;
615        new->c_arg = arg;
616        new->c_func = ftn;
617
618        /*
619         * The time for each event is stored as a difference from the time
620         * of the previous event on the queue.  Walk the queue, correcting
621         * the ticks argument for queue entries passed.  Correct the ticks
622         * value for the queue entry immediately after the insertion point
623         * as well.  Watch out for negative c_time values; these represent
624         * overdue events.
625         */
626        for (p = &calltodo;
627            (t = p->c_next) != NULL && ticks > t->c_time; p = t)
628                if (t->c_time > 0)
629                        ticks -= t->c_time;
630        new->c_time = ticks;
631        if (t != NULL)
632                t->c_time -= ticks;
633
634        /* Insert the new entry into the queue. */
635        p->c_next = new;
636        new->c_next = t;
637}
638
639/*
640 * Ticks till specified time
641 * FIXME: This version worries only about seconds, but that's good
642 * enough for the way the network code uses this routine.
643 */
644int
645hzto(struct timeval *tv)
646{
647        long diff = tv->tv_sec - rtems_bsdnet_seconds_since_boot();
648
649        if (diff <= 0)
650                return 1;
651        return diff * rtems_bsdnet_ticks_per_second;
652}
653
654/*
655 * Kernel debugging
656 */
657int rtems_bsdnet_log_priority;
658void
659rtems_bsdnet_log (int priority, const char *fmt, ...)
660{
661        va_list args;
662       
663        if (priority & rtems_bsdnet_log_priority) {
664                va_start (args, fmt);
665                vprintf (fmt, args);
666                va_end (args);
667        }
668}
669
670/*
671 * Hack alert: kmem_malloc `knows' that its
672 * first invocation is to get mbuf clusters!
673 */
674int mb_map_full;
675vm_map_t mb_map;
676vm_offset_t
677kmem_malloc (vm_map_t *map, vm_size_t size, boolean_t waitflag)
678{
679        void *p;
680       
681        /*
682         * Can't get memory if we're already running.
683         */
684        if (networkDaemonTid) {
685                if (waitflag == M_WAITOK)
[109b17f4]686                        rtems_panic (
687"Network mbuf space can not be enlarged after rtems_bsdnet_initialize() has\n"
688"returned.  Enlarge the initial mbuf/cluster size in rtems_bsdnet_config.");
[39e6e65a]689                return 0;
690        }
691
692#define ROUNDSIZE 2048
693        p = malloc (size+ROUNDSIZE);
694        p = (void *)((unsigned long)p & ~(ROUNDSIZE-1));
695        if ((p == NULL) && (waitflag == M_WAITOK))
696                rtems_panic ("Can't get initial network memory!");
697        if (mbutl == NULL)
698                mbutl = p;
699        return (vm_offset_t)p;
700}
701
702/*
703 * IP header checksum routine for processors which don't have an inline version
704 */
705u_int
706in_cksum_hdr (const void *ip)
707{
708        rtems_unsigned32 sum;
709        const rtems_unsigned16 *sp;
710        int i;
711
712        sum = 0;
713        sp = (rtems_unsigned16 *)ip;
714        for (i = 0 ; i < 10 ; i++)
715                sum += *sp++;
716        while (sum > 0xFFFF)
717                sum = (sum & 0xffff) + (sum >> 16);
718        return ~sum & 0xFFFF;
719}
720
721/*
722 * Manipulate routing tables
723 */
724int rtems_bsdnet_rtrequest (
725    int req,
726    struct sockaddr *dst,
727    struct sockaddr *gateway,
728    struct sockaddr *netmask,
729    int flags,
730    struct rtentry **net_nrt)
731{
732        int error;
733
734        rtems_bsdnet_semaphore_obtain ();
735        error = rtrequest (req, dst, gateway, netmask, flags, net_nrt);
736        rtems_bsdnet_semaphore_release ();
737        if (error) {
738                errno = error;
739                return -1;
740        }
741        return 0;
742}
743
744static void
745rtems_bsdnet_setup (void)
746{
747        struct rtems_bsdnet_ifconfig *ifp;
748        int s;
749        struct ifreq ifreq;
750        struct sockaddr_in address;
751        struct sockaddr_in netmask;
752        struct sockaddr_in broadcast;
753        struct sockaddr_in gateway;
754        int i;
755
756        /*
757         * Set local parameters
758         */
759        if (rtems_bsdnet_config.hostname)
760                sethostname (rtems_bsdnet_config.hostname,
761                                        strlen (rtems_bsdnet_config.hostname));
762        if (rtems_bsdnet_config.domainname)
763                rtems_bsdnet_domain_name =
764                                        strdup (rtems_bsdnet_config.domainname);
765        if (rtems_bsdnet_config.log_host)
766                rtems_bsdnet_log_host_address.s_addr =
767                                inet_addr (rtems_bsdnet_config.log_host);
768        for (i = 0 ; i < sizeof rtems_bsdnet_config.name_server /
769                        sizeof rtems_bsdnet_config.name_server[0] ; i++) {
770                if (!rtems_bsdnet_config.name_server[i])
771                        break;
772                rtems_bsdnet_nameserver[rtems_bsdnet_nameserver_count++].s_addr
773                        = inet_addr (rtems_bsdnet_config.name_server[i]);
774        }
775
776        /*
777         * Configure interfaces
778         */
779        s = socket (AF_INET, SOCK_DGRAM, 0);
780        if (s < 0)
781                rtems_panic ("Can't create initial socket: %s", strerror (errno));
782        for (ifp = rtems_bsdnet_config.ifconfig ; ifp ; ifp = ifp->next) {
783                if (ifp->ip_address == NULL)
784                        continue;
785
786                /*
787                 * Get the interface flags
788                 */
789                strcpy (ifreq.ifr_name, ifp->name);
790                if (ioctl (s, SIOCGIFFLAGS, &ifreq) < 0)
791                        rtems_panic ("Can't get %s flags: %s", ifp->name, strerror (errno));
792
793                /*
794                 * Bring interface up
795                 */
796                ifreq.ifr_flags |= IFF_UP;
797                if (ioctl (s, SIOCSIFFLAGS, &ifreq) < 0)
798                        rtems_panic ("Can't bring %s up: %s", ifp->name, strerror (errno));
799
800                /*
801                 * Set interface netmask
802                 */
803                memset (&netmask, '\0', sizeof netmask);
804                netmask.sin_len = sizeof netmask;
805                netmask.sin_family = AF_INET;
806                netmask.sin_addr.s_addr = inet_addr (ifp->ip_netmask);
807                memcpy (&ifreq.ifr_addr, &netmask, sizeof netmask);
808                if (ioctl (s, SIOCSIFNETMASK, &ifreq) < 0)
809                        rtems_panic ("Can't set %s netmask: %s", ifp->name, strerror (errno));
810
811                /*
812                 * Set interface address
813                 */
814                memset (&address, '\0', sizeof address);
815                address.sin_len = sizeof address;
816                address.sin_family = AF_INET;
817                address.sin_addr.s_addr = inet_addr (ifp->ip_address);
818                memcpy (&ifreq.ifr_addr, &address, sizeof address);
819                if (ioctl (s, SIOCSIFADDR, &ifreq) < 0)
820                        rtems_panic ("Can't set %s address: %s", ifp->name, strerror (errno));
821
822                /*
823                 * Set interface broadcast address
824                 */
825                memset (&broadcast, '\0', sizeof broadcast);
826                broadcast.sin_len = sizeof broadcast;
827                broadcast.sin_family = AF_INET;
828                broadcast.sin_addr.s_addr = address.sin_addr.s_addr | ~netmask.sin_addr.s_addr;
829                memcpy (&ifreq.ifr_broadaddr, &broadcast, sizeof broadcast);
830                if (ioctl (s, SIOCSIFBRDADDR, &ifreq) < 0)
831                        rtems_panic ("Can't set %s broadcast address: %s", ifp->name, strerror (errno));
832        }
833
834        /*
835         * We're done with the dummy socket
836         */
837        close (s);
838
839        /*
840         * Set default route
841         */
842        if (rtems_bsdnet_config.gateway) {
843                address.sin_addr.s_addr = INADDR_ANY;
844                netmask.sin_addr.s_addr = INADDR_ANY;
845                memset (&gateway, '\0', sizeof gateway);
846                gateway.sin_len = sizeof gateway;
847                gateway.sin_family = AF_INET;
848                gateway.sin_addr.s_addr = inet_addr (rtems_bsdnet_config.gateway);
849                if (rtems_bsdnet_rtrequest (
850                                RTM_ADD,
851                                (struct sockaddr *)&address,
852                                (struct sockaddr *)&gateway,
853                                (struct sockaddr *)&netmask,
854                                (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL) < 0)
855                        rtems_panic ("Can't set default route: %s", strerror (errno));
856        }
857}
858
859/*
860 * Initialize the network
861 */
862int
863rtems_bsdnet_initialize_network (void)
864{
865        struct rtems_bsdnet_ifconfig *ifp;
866
867        /*
868         * Start network tasks.
869         * Initialize BSD network data structures.
870         */
871        rtems_bsdnet_initialize ();
872
873        /*
874         * Attach interfaces
875         */
876        for (ifp = rtems_bsdnet_config.ifconfig ; ifp ; ifp = ifp->next) {
877                rtems_bsdnet_semaphore_obtain ();
878                (ifp->attach)(ifp);
879                rtems_bsdnet_semaphore_release ();
880        }
881
882        /*
883         * Bring up the network
884         */
885        rtems_bsdnet_setup ();
886        if (rtems_bsdnet_config.bootp)
887                (*rtems_bsdnet_config.bootp)();
888        return 0;
889}
Note: See TracBrowser for help on using the repository browser.