source: rtems/cpukit/libnetworking/rtems/rtems_glue.c @ 6c980128

4.104.114.84.95
Last change on this file since 6c980128 was 91b1c8e6, checked in by Joel Sherrill <joel.sherrill@…>, on 12/07/98 at 17:42:52

Patch from Ian Lance Taylor <ian@…>:

RTEMS permits using the SO_SNDTIMEO and SO_RCVTIMEO socket options to
set a timeout for most socket I/O operations. However, in RTEMS
4.0.0, those options do not affect connect or accept. I don't know of
any way to put a timeout on those calls in RTEMS 4.0.0; can anybody
point to one.

Since it is frequently useful to have a timeout on accept, and
sometimes useful to have a timeout on connect shorter than the BSD
system default of 75 seconds, the following patch causes SO_RCVTIMEO
to affect connect and accept.

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