source: rtems-docs/networking/using_networking_rtems_app.rst @ 9aafb39

4.115
Last change on this file since 9aafb39 was 489740f, checked in by Chris Johns <chrisj@…>, on 05/20/16 at 02:47:09

Set SPDX License Identifier in each source file.

  • Property mode set to 100644
File size: 32.0 KB
Line 
1.. comment SPDX-License-Identifier: CC-BY-SA-4.0
2
3.. COMMENT: Written by Eric Norum
4.. COMMENT: COPYRIGHT (c) 1988-2002.
5.. COMMENT: On-Line Applications Research Corporation (OAR).
6.. COMMENT: All rights reserved.
7
8Using Networking in an RTEMS Application
9########################################
10
11Makefile changes
12================
13
14Including the required managers
15-------------------------------
16
17The FreeBSD networking code requires several RTEMS managers in the application:
18
19.. code-block:: c
20
21    MANAGERS = io event semaphore
22
23Increasing the size of the heap
24-------------------------------
25
26The networking tasks allocate a lot of memory.  For most applications the heap
27should be at least 256 kbytes.  The amount of memory set aside for the heap can
28be adjusted by setting the ``CFLAGS_LD`` definition as shown below:
29
30.. code-block:: c
31
32    CFLAGS_LD += -Wl,--defsym -Wl,HeapSize=0x80000
33
34This sets aside 512 kbytes of memory for the heap.
35
36System Configuration
37====================
38
39The networking tasks allocate some RTEMS objects.  These must be accounted for
40in the application configuration table.  The following lists the requirements.
41
42*TASKS*
43    One network task plus a receive and transmit task for each device.
44
45*SEMAPHORES*
46    One network semaphore plus one syslog mutex semaphore if the application
47    uses openlog/syslog.
48
49*EVENTS*
50    The network stack uses ``RTEMS_EVENT_24`` and ``RTEMS_EVENT_25``.  This has
51    no effect on the application configuration, but application tasks which
52    call the network functions should not use these events for other purposes.
53
54Initialization
55==============
56
57Additional include files
58------------------------
59
60The source file which declares the network configuration structures and calls
61the network initialization function must include
62
63.. code-block:: c
64
65    #include <rtems/rtems_bsdnet.h>
66
67Network Configuration
68---------------------
69
70The network configuration is specified by declaring and initializing the
71``rtems_bsdnet_config`` structure.
72
73.. code-block:: c
74
75    struct rtems_bsdnet_config {
76        /*
77         * This entry points to the head of the ifconfig chain.
78         */
79        struct rtems_bsdnet_ifconfig *ifconfig;
80        /*
81         * This entry should be rtems_bsdnet_do_bootp if BOOTP
82         * is being used to configure the network, and NULL
83         * if BOOTP is not being used.
84         */
85        void                          (*bootp)(void);
86         /*
87          * The remaining items can be initialized to 0, in
88          * which case the default value will be used.
89          */
90        rtems_task_priority           network_task_priority;  /* 100        */
91        unsigned long                 mbuf_bytecount;         /* 64 kbytes  */
92        unsigned long                 mbuf_cluster_bytecount; /* 128 kbytes */
93        char                          *hostname;              /* BOOTP      */
94        char                          *domainname;            /* BOOTP      */
95        char                          *gateway;               /* BOOTP      */
96        char                          *log_host;              /* BOOTP      */
97        char                          *name_server[3];        /* BOOTP      */
98        char                          *ntp_server[3];         /* BOOTP      */
99        unsigned long                 sb_efficiency;          /* 2          */
100        /* UDP TX: 9216 bytes */
101        unsigned long                 udp_tx_buf_size;
102        /* UDP RX: 40 * (1024 + sizeof(struct sockaddr_in)) */
103        unsigned long                 udp_rx_buf_size;
104        /* TCP TX: 16 * 1024 bytes */
105        unsigned long                 tcp_tx_buf_size;
106        /* TCP TX: 16 * 1024 bytes */
107        unsigned long                 tcp_rx_buf_size;
108        /* Default Network Tasks CPU Affinity */
109        #ifdef RTEMS_SMP
110             const cpu_set_t         *network_task_cpuset;
111             size_t                   network_task_cpuset_size;
112        #endif
113    };
114
115The structure entries are described in the following table.  If your
116application uses BOOTP/DHCP to obtain network configuration information and if
117you are happy with the default values described below, you need to provide only
118the first two entries in this structure.
119
120``struct rtems_bsdnet_ifconfig *ifconfig``
121    A pointer to the first configuration structure of the first network device.
122    This structure is described in the following section.  You must provide a
123    value for this entry since there is no default value for it.
124
125``void (*bootp)(void)``
126    This entry should be set to ``rtems_bsdnet_do_bootp`` if your application
127    by default uses the BOOTP/DHCP client protocol to obtain network
128    configuration information.  It should be set to ``NULL`` if your
129    application does not use BOOTP/DHCP.  You can also use
130    ``rtems_bsdnet_do_bootp_rootfs`` to have a set of standard files created
131    with the information return by the BOOTP/DHCP protocol. The IP address is
132    added to :file:`/etc/hosts` with the host name and domain returned. If no
133    host name or domain is returned ``me.mydomain`` is used. The BOOTP/DHCP
134    server's address is also added to :file:`/etc/hosts`. The domain name
135    server listed in the BOOTP/DHCP information are added to
136    :file:`/etc/resolv.conf`. A``search`` record is also added if a domain is
137    returned. The files are created if they do not exist.  The default
138    ``rtems_bsdnet_do_bootp`` and ``rtems_bsdnet_do_bootp_rootfs`` handlers
139    will loop for-ever waiting for a BOOTP/DHCP server to respond. If an error
140    is detected such as not valid interface or valid hardware address the
141    target will reboot allowing any hardware reset to correct itself.  You can
142    provide your own custom handler which allows you to perform an
143    initialization that meets your specific system requirements. For example
144    you could try BOOTP/DHCP then enter a configuration tool if no server is
145    found allowing the user to switch to a static configuration.
146
147``int network_task_priority``
148    The priority at which the network task and network device
149    receive and transmit tasks will run.
150    If a value of 0 is specified the tasks will run at priority 100.
151
152``unsigned long mbuf_bytecount``
153    The number of bytes to allocate from the heap for use as mbufs.
154    If a value of 0 is specified, 64 kbytes will be allocated.
155
156``unsigned long mbuf_cluster_bytecount``
157    The number of bytes to allocate from the heap for use as mbuf clusters.
158    If a value of 0 is specified, 128 kbytes will be allocated.
159
160``char *hostname``
161    The host name of the system.
162    If this, or any of the following, entries are ``NULL`` the value
163    may be obtained from a BOOTP/DHCP server.
164
165``char *domainname``
166    The name of the Internet domain to which the system belongs.
167
168``char *gateway``
169    The Internet host number of the network gateway machine, specified in
170    'dotted decimal' (``129.128.4.1``) form.
171
172``char *log_host``
173    The Internet host number of the machine to which ``syslog`` messages will
174    be sent.
175
176``char *name_server[3]``
177    The Internet host numbers of up to three machines to be used as Internet
178    Domain Name Servers.
179
180``char *ntp_server[3]``
181    The Internet host numbers of up to three machines to be used as
182    Network Time Protocol (NTP) Servers.
183
184``unsigned long sb_efficiency``
185    This is the first of five configuration parameters related to the amount of
186    memory each socket may consume for buffers.  The TCP/IP stack reserves
187    buffers (e.g. mbufs) for each open socket.  The TCP/IP stack has different
188    limits for the transmit and receive buffers associated with each TCP and
189    UDP socket.  By tuning these parameters, the application developer can make
190    trade-offs between memory consumption and performance.  The default
191    parameters favor performance over memory consumption.  See
192    http://www.rtems.org/ml/rtems-users/2004/february/msg00200.html for more
193    details but note that after the RTEMS 4.8 release series, the
194    ``sb_efficiency`` default was changed from ``8`` to ``2``.  The user should
195    also be aware of the ``SO_SNDBUF`` and ``SO_RCVBUF`` IO control operations.
196    These can be used to specify the send and receive buffer sizes for a
197    specific socket.  There is no standard IO control to change the
198    ``sb_efficiency`` factor.  The ``sb_efficiency`` parameter is a buffering
199    factor used in the implementation of the TCP/IP stack.  The default is
200    ``2`` which indicates double buffering.  When allocating memory for each
201    socket, this number is multiplied by the buffer sizes for that socket.
202
203``unsigned long udp_tx_buf_size``
204    This configuration parameter specifies the maximum amount of buffer memory
205    which may be used for UDP sockets to transmit with.  The default size is
206    9216 bytes which corresponds to the maximum datagram size.
207
208``unsigned long udp_rx_buf_size``
209    This configuration parameter specifies the maximum amount of buffer memory
210    which may be used for UDP sockets to receive into.  The default size is the
211    following length in bytes:
212
213    .. code-block:: c
214
215        40 * (1024 + sizeof(struct sockaddr_in)
216
217``unsigned long tcp_tx_buf_size``
218    This configuration parameter specifies the maximum amount of buffer memory
219    which may be used for TCP sockets to transmit with.  The default size is
220    sixteen kilobytes.
221
222``unsigned long tcp_rx_buf_size``
223    This configuration parameter specifies the maximum amount of buffer memory
224    which may be used for TCP sockets to receive into.  The default size is
225    sixteen kilobytes.
226
227``const cpu_set_t *network_task_cpuset``
228    This configuration parameter specifies the CPU affinity of the network
229    task. If set to ``0`` the network task can be scheduled on any CPU. Only
230    available in SMP configurations.
231
232``size_t network_task_cpuset_size``
233    This configuration parameter specifies the size of the
234    ``network_task_cpuset`` used. Only available in SMP configurations.
235
236In addition, the following fields in the ``rtems_bsdnet_ifconfig`` are of
237interest.
238
239*int port*
240    The I/O port number (ex: 0x240) on which the external Ethernet can be
241    accessed.
242
243*int irno*
244    The interrupt number of the external Ethernet controller.
245
246*int bpar*
247    The address of the shared memory on the external Ethernet controller.
248
249Network device configuration
250----------------------------
251
252Network devices are specified and configured by declaring and initializing a
253``struct rtems_bsdnet_ifconfig`` structure for each network device.
254
255The structure entries are described in the following table.  An application
256which uses a single network interface, gets network configuration information
257from a BOOTP/DHCP server, and uses the default values for all driver parameters
258needs to initialize only the first two entries in the structure.
259
260``char *name``
261    The full name of the network device.  This name consists of the driver name
262    and the unit number (e.g. ``"scc1"``).  The ``bsp.h`` include file usually
263    defines ``RTEMS_BSP_NETWORK_DRIVER_NAME`` as the name of the primary (or
264    only) network driver.
265
266``int (*attach)(struct rtems_bsdnet_ifconfig *conf)``
267
268    The address of the driver ``attach`` function.  The network initialization
269    function calls this function to configure the driver and attach it to the
270    network stack.  The ``bsp.h`` include file usually defines
271    ``RTEMS_BSP_NETWORK_DRIVER_ATTACH`` as the name of the attach function of
272    the primary (or only) network driver.
273
274``struct rtems_bsdnet_ifconfig *next``
275    A pointer to the network device configuration structure for the next
276    network interface, or ``NULL`` if this is the configuration structure of
277    the last network interface.
278
279``char *ip_address``
280    The Internet address of the device, specified in 'dotted decimal'
281    (``129.128.4.2``) form, or ``NULL`` if the device configuration information
282    is being obtained from a BOOTP/DHCP server.
283
284``char *ip_netmask``
285    The Internet inetwork mask of the device, specified in 'dotted decimal'
286    (``255.255.255.0``) form, or ``NULL`` if the device configuration
287    information is being obtained from a BOOTP/DHCP server.
288
289``void *hardware_address``
290    The hardware address of the device, or ``NULL`` if the driver is to obtain
291    the hardware address in some other way (usually by reading it from the
292    device or from the bootstrap ROM).
293
294``int ignore_broadcast``
295    Zero if the device is to accept broadcast packets, non-zero if the device
296    is to ignore broadcast packets.
297
298``int mtu``
299    The maximum transmission unit of the device, or zero if the driver is to
300    choose a default value (typically 1500 for Ethernet devices).
301
302``int rbuf_count``
303    The number of receive buffers to use, or zero if the driver is to choose a
304    default value
305
306``int xbuf_count``
307    The number of transmit buffers to use, or zero if the driver is to choose a
308    default value Keep in mind that some network devices may use 4 or more
309    transmit descriptors for a single transmit buffer.
310
311A complete network configuration specification can be as simple as the one
312shown in the following example.  This configuration uses a single network
313interface, gets network configuration information from a BOOTP/DHCP server, and
314uses the default values for all driver parameters.
315
316.. code-block:: c
317
318    static struct rtems_bsdnet_ifconfig netdriver_config = {
319        RTEMS_BSP_NETWORK_DRIVER_NAME,
320        RTEMS_BSP_NETWORK_DRIVER_ATTACH
321    };
322    struct rtems_bsdnet_config rtems_bsdnet_config = {
323        &netdriver_config,
324        rtems_bsdnet_do_bootp,
325    };
326
327Network initialization
328----------------------
329
330The networking tasks must be started before any network I/O operations can be
331performed. This is done by calling:
332
333.. code-block:: c
334
335    rtems_bsdnet_initialize_network ();
336
337This function is declared in ``rtems/rtems_bsdnet.h``.  t returns 0 on success
338and -1 on failure with an error code in ``errno``.  It is not possible to undo
339the effects of a partial initialization, though, so the function can be called
340only once irregardless of the return code.  Consequently, if the condition for
341the failure can be corrected, the system must be reset to permit another
342network initialization attempt.
343
344Application Programming Interface
345=================================
346
347The RTEMS network package provides almost a complete set of BSD network
348services.  The network functions work like their BSD counterparts with the
349following exceptions:
350
351- A given socket can be read or written by only one task at a time.
352
353- The ``select`` function only works for file descriptors associated with
354  sockets.
355
356- You must call ``openlog`` before calling any of the ``syslog`` functions.
357
358- *Some of the network functions are not thread-safe.* For example the
359  following functions return a pointer to a static buffer which remains valid
360  only until the next call:
361
362  ``gethostbyaddr``
363  ``gethostbyname``
364  ``inet_ntoa`` (``inet_ntop`` is thread-safe, though).
365
366- The RTEMS network package gathers statistics.
367
368- Addition of a mechanism to "tap onto" an interface and monitor every packet
369  received and transmitted.
370
371- Addition of ``SO_SNDWAKEUP`` and ``SO_RCVWAKEUP`` socket options.
372
373Some of the new features are discussed in more detail in the following
374sections.
375
376Network Statistics
377------------------
378
379There are a number of functions to print statistics gathered by the network
380stack.  These function are declared in ``rtems/rtems_bsdnet.h``.
381
382``rtems_bsdnet_show_if_stats``
383    Display statistics gathered by network interfaces.
384
385``rtems_bsdnet_show_ip_stats``
386    Display IP packet statistics.
387
388``rtems_bsdnet_show_icmp_stats``
389    Display ICMP packet statistics.
390
391``rtems_bsdnet_show_tcp_stats``
392    Display TCP packet statistics.
393
394``rtems_bsdnet_show_udp_stats``
395    Display UDP packet statistics.
396
397``rtems_bsdnet_show_mbuf_stats``
398    Display mbuf statistics.
399
400``rtems_bsdnet_show_inet_routes``
401    Display the routing table.
402
403Tapping Into an Interface
404-------------------------
405
406RTEMS add two new ioctls to the BSD networking code, ``SIOCSIFTAP`` and
407``SIOCGIFTAP``.  These may be used to set and get a *tap function*.  The tap
408function will be called for every Ethernet packet received by the interface.
409
410These are called like other interface ioctls, such as ``SIOCSIFADDR``.  When
411setting the tap function with ``SIOCSIFTAP``, set the ifr_tap field of the
412ifreq struct to the tap function.  When retrieving the tap function with
413``SIOCGIFTAP``, the current tap function will be returned in the ifr_tap field.
414To stop tapping packets, call ``SIOCSIFTAP`` with a ``ifr_tap`` field of ``0``.
415
416The tap function is called like this:
417
418.. code-block:: c
419
420    int tap (struct ifnet *, struct ether_header *, struct mbuf *)
421
422The tap function should return ``1`` if the packet was fully handled, in which
423case the caller will simply discard the mbuf.  The tap function should return
424``0`` if the packet should be passed up to the higher networking layers.
425
426The tap function is called with the network semaphore locked.  It must not make
427any calls on the application levels of the networking level itself.  It is safe
428to call other non-networking RTEMS functions.
429
430Socket Options
431--------------
432
433RTEMS adds two new ``SOL_SOCKET`` level options for ``setsockopt`` and
434``getsockopt``: ``SO_SNDWAKEUP`` and ``SO_RCVWAKEUP``.  For both, the option
435value should point to a sockwakeup structure.  The sockwakeup structure has the
436following fields:
437
438.. code-block:: c
439
440    void    (*sw_pfn) (struct socket *, caddr_t);
441    caddr_t sw_arg;
442
443These options are used to set a callback function to be called when, for
444example, there is data available from the socket (``SO_RCVWAKEUP``) and when
445there is space available to accept data written to the socket
446(``SO_SNDWAKEUP``).
447
448If ``setsockopt`` is called with the ``SO_RCVWAKEUP`` option, and the
449``sw_pfn`` field is not zero, then when there is data available to be read from
450the socket, the function pointed to by the ``sw_pfn`` field will be called.  A
451pointer to the socket structure will be passed as the first argument to the
452function.  The ``sw_arg`` field set by the ``SO_RCVWAKEUP`` call will be passed
453as the second argument to the function.
454
455If ``setsockopt`` is called with the ``SO_SNDWAKEUP`` function, and the
456``sw_pfn`` field is not zero, then when there is space available to accept data
457written to the socket, the function pointed to by the ``sw_pfn`` field will be
458called.  The arguments passed to the function will be as with ``SO_SNDWAKEUP``.
459
460When the function is called, the network semaphore will be locked and the
461callback function runs in the context of the networking task.  The function
462must be careful not to call any networking functions.  It is OK to call an
463RTEMS function; for example, it is OK to send an RTEMS event.
464
465The purpose of these callback functions is to permit a more efficient
466alternative to the select call when dealing with a large number of sockets.
467
468The callbacks are called by the same criteria that the select function uses for
469indicating "ready" sockets. In Stevens *Unix Network Programming* on page
470153-154 in the section "Under what Conditions Is a Descriptor Ready?" you will
471find the definitive list of conditions for readable and writable that also
472determine when the functions are called.
473
474When the number of received bytes equals or exceeds the socket receive buffer
475"low water mark" (default 1 byte) you get a readable callback. If there are 100
476bytes in the receive buffer and you only read 1, you will not immediately get
477another callback. However, you will get another callback after you read the
478remaining 99 bytes and at least 1 more byte arrives. Using a non-blocking
479socket you should probably read until it produces error ``EWOULDBLOCK`` and
480then allow the readable callback to tell you when more data has arrived.
481(Condition 1.a.)
482
483For sending, when the socket is connected and the free space becomes at or
484above the "low water mark" for the send buffer (default 4096 bytes) you will
485receive a writable callback. You don't get continuous callbacks if you don't
486write anything. Using a non-blocking write socket, you can then call write
487until it returns a value less than the amount of data requested to be sent or
488it produces error ``EWOULDBLOCK`` (indicating buffer full and no longer
489writable). When this happens you can try the write again, but it is often
490better to go do other things and let the writable callback tell you when space
491is available to send again. You only get a writable callback when the free
492space transitions to above the "low water mark" and not every time you write to
493a non-full send buffer. (Condition 2.a.)
494
495The remaining conditions enumerated by Stevens handle the fact that sockets
496become readable and/or writable when connects, disconnects and errors occur,
497not just when data is received or sent. For example, when a server "listening"
498socket becomes readable it indicates that a client has connected and accept can
499be called without blocking, not that network data was received (Condition 1.c).
500
501Adding an IP Alias
502------------------
503
504The following code snippet adds an IP alias:
505
506.. code-block:: c
507
508    void addAlias(const char *pName, const char *pAddr, const char *pMask)
509    {
510        struct ifaliasreq   aliasreq;
511        struct sockaddr_in *in;
512
513        /* initialize alias request */
514        memset(&aliasreq, 0, sizeof(aliasreq));
515        sprintf(aliasreq.ifra_name, pName);
516
517        /* initialize alias address */
518        in = (struct sockaddr_in *)&aliasreq.ifra_addr;
519        in->sin_family = AF_INET;
520        in->sin_len    = sizeof(aliasreq.ifra_addr);
521        in->sin_addr.s_addr = inet_addr(pAddr);
522
523        /* initialize alias mask */
524        in = (struct sockaddr_in *)&aliasreq.ifra_mask;
525        in->sin_family = AF_INET;
526        in->sin_len    = sizeof(aliasreq.ifra_mask);
527        in->sin_addr.s_addr = inet_addr(pMask);
528
529        /* call to setup the alias */
530        rtems_bsdnet_ifconfig(pName, SIOCAIFADDR, &aliasreq);
531    }
532
533Thanks to Mike Seirs <mailto:mikes@poliac.com> for this example code.
534
535Adding a Default Route
536----------------------
537
538The function provided in this section is functionally equivalent to the command
539``route add default gw yyy.yyy.yyy.yyy``:
540
541.. code-block:: c
542
543    void mon_ifconfig(int argc, char *argv[],  unsigned32 command_arg, bool verbose)
544    {
545        struct sockaddr_in  ipaddr;
546        struct sockaddr_in  dstaddr;
547        struct sockaddr_in  netmask;
548        struct sockaddr_in  broadcast;
549        char               *iface;
550        int                 f_ip        = 0;
551        int                 f_ptp       = 0;
552        int                 f_netmask   = 0;
553        int                 f_up        = 0;
554        int                 f_down      = 0;
555        int                 f_bcast     = 0;
556        int                 cur_idx;
557        int                 rc;
558        int                 flags;
559
560        bzero((void*) &ipaddr, sizeof(ipaddr));
561        bzero((void*) &dstaddr, sizeof(dstaddr));
562        bzero((void*) &netmask, sizeof(netmask));
563        bzero((void*) &broadcast, sizeof(broadcast));
564        ipaddr.sin_len = sizeof(ipaddr);
565        ipaddr.sin_family = AF_INET;
566        dstaddr.sin_len = sizeof(dstaddr);
567        dstaddr.sin_family = AF_INET;
568        netmask.sin_len = sizeof(netmask);
569        netmask.sin_family = AF_INET;
570        broadcast.sin_len = sizeof(broadcast);
571        broadcast.sin_family = AF_INET;
572        cur_idx = 0;
573
574        if (argc <= 1) {
575            /* display all interfaces */
576            iface = NULL;
577            cur_idx += 1;
578        } else {
579            iface = argv[1];
580            if (isdigit(*argv[2])) {
581                if (inet_pton(AF_INET, argv[2], &ipaddr.sin_addr) < 0) {
582                    printf("bad ip address: %s\n", argv[2]);
583                    return;
584                }
585                f_ip = 1;
586                cur_idx += 3;
587            } else {
588                cur_idx += 2;
589            }
590        }
591
592        if ((f_down !=0) && (f_ip != 0)) {
593            f_up = 1;
594        }
595
596        while(argc > cur_idx) {
597            if (strcmp(argv[cur_idx], "up") == 0) {
598                f_up = 1;
599                if (f_down != 0) {
600                    printf("Can't make interface up and down\n");
601                }
602            } else if(strcmp(argv[cur_idx], "down") == 0) {
603                f_down = 1;
604                if (f_up != 0) {
605                    printf("Can't make interface up and down\n");
606                }
607            } else if(strcmp(argv[cur_idx], "netmask") == 0) {
608                if ((cur_idx + 1) >= argc) {
609                    printf("No netmask address\n");
610                    return;
611                }
612                if (inet_pton(AF_INET, argv[cur_idx+1], &netmask.sin_addr) < 0) {
613                    printf("bad netmask: %s\n", argv[cur_idx]);
614                    return;
615                }
616                f_netmask = 1;
617                cur_idx += 1;
618            } else if(strcmp(argv[cur_idx], "broadcast") == 0) {
619                if ((cur_idx + 1) >= argc) {
620                    printf("No broadcast address\n");
621                    return;
622                }
623                if (inet_pton(AF_INET, argv[cur_idx+1], &broadcast.sin_addr) < 0) {
624                    printf("bad broadcast: %s\n", argv[cur_idx]);
625                    return;
626                }
627               f_bcast = 1;
628               cur_idx += 1;
629            } else if(strcmp(argv[cur_idx], "pointopoint") == 0) {
630                if ((cur_idx + 1) >= argc) {
631                    printf("No pointopoint address\n");
632                    return;
633                }
634                if (inet_pton(AF_INET, argv[cur_idx+1], &dstaddr.sin_addr) < 0) {
635                    printf("bad pointopoint: %s\n", argv[cur_idx]);
636                    return;
637                }
638                f_ptp = 1;
639                cur_idx += 1;
640            } else {
641                printf("Bad parameter: %s\n", argv[cur_idx]);
642                return;
643            }
644            cur_idx += 1;
645        }
646
647        printf("ifconfig ");
648
649        if (iface != NULL) {
650            printf("%s ", iface);
651            if (f_ip != 0) {
652                char str[256];
653                inet_ntop(AF_INET, &ipaddr.sin_addr, str, 256);
654                printf("%s ", str);
655            }
656            if (f_netmask != 0) {
657                char str[256];
658                inet_ntop(AF_INET, &netmask.sin_addr, str, 256);
659                printf("netmask %s ", str);
660            }
661            if (f_bcast != 0) {
662                char str[256];
663                inet_ntop(AF_INET, &broadcast.sin_addr, str, 256);
664                printf("broadcast %s ", str);
665            }
666            if (f_ptp != 0) {
667                char str[256];
668                inet_ntop(AF_INET, &dstaddr.sin_addr, str, 256);
669                printf("pointopoint %s ", str);
670            }
671            if (f_up != 0) {
672                printf("up\n");
673            } else if (f_down != 0) {
674                printf("down\n");
675            } else {
676                printf("\n");
677            }
678        }
679
680        if ((iface == NULL) || ((f_ip == 0) && (f_down == 0) && (f_up == 0))) {
681            rtems_bsdnet_show_if_stats();
682            return;
683        }
684
685        flags = 0;
686        if (f_netmask) {
687            rc = rtems_bsdnet_ifconfig(iface, SIOCSIFNETMASK, &netmask);
688            if (rc < 0) {
689                printf("Could not set netmask: %s\n", strerror(errno));
690                return;
691            }
692        }
693        if (f_bcast) {
694            rc = rtems_bsdnet_ifconfig(iface, SIOCSIFBRDADDR, &broadcast);
695            if (rc < 0) {
696                printf("Could not set broadcast: %s\n", strerror(errno));
697                return;
698            }
699        }
700        if (f_ptp) {
701            rc = rtems_bsdnet_ifconfig(iface, SIOCSIFDSTADDR, &dstaddr);
702            if (rc < 0) {
703                printf("Could not set destination address: %s\n", strerror(errno));
704                return;
705            }
706            flags |= IFF_POINTOPOINT;
707        }
708
709        /* This must come _after_ setting the netmask, broadcast addresses */
710        if (f_ip) {
711            rc = rtems_bsdnet_ifconfig(iface, SIOCSIFADDR, &ipaddr);
712            if (rc < 0) {
713                printf("Could not set IP address: %s\n", strerror(errno));
714                return;
715            }
716        }
717        if (f_up != 0) {
718            flags |= IFF_UP;
719        }
720        if (f_down != 0) {
721            printf("Warning: taking interfaces down is not supported\n");
722        }
723
724        rc = rtems_bsdnet_ifconfig(iface, SIOCSIFFLAGS, &flags);
725        if (rc < 0) {
726            printf("Could not set interface flags: %s\n", strerror(errno));
727            return;
728        }
729    }
730
731    void mon_route(int argc, char *argv[],  unsigned32 command_arg, bool verbose)
732    {
733        int                cmd;
734        struct sockaddr_in dst;
735        struct sockaddr_in gw;
736        struct sockaddr_in netmask;
737        int                f_host;
738        int                f_gw       = 0;
739        int                cur_idx;
740        int                flags;
741        int                rc;
742
743        memset(&dst, 0, sizeof(dst));
744        memset(&gw, 0, sizeof(gw));
745        memset(&netmask, 0, sizeof(netmask));
746        dst.sin_len = sizeof(dst);
747        dst.sin_family = AF_INET;
748        dst.sin_addr.s_addr = inet_addr("0.0.0.0");
749        gw.sin_len = sizeof(gw);
750        gw.sin_family = AF_INET;
751        gw.sin_addr.s_addr = inet_addr("0.0.0.0");
752        netmask.sin_len = sizeof(netmask);
753        netmask.sin_family = AF_INET;
754        netmask.sin_addr.s_addr = inet_addr("255.255.255.0");
755
756        if (argc < 2) {
757            rtems_bsdnet_show_inet_routes();
758            return;
759        }
760
761        if (strcmp(argv[1], "add") == 0) {
762            cmd = RTM_ADD;
763        } else if (strcmp(argv[1], "del") == 0) {
764            cmd = RTM_DELETE;
765        } else {
766            printf("invalid command: %s\n", argv[1]);
767            printf("\tit should be 'add' or 'del'\n");
768            return;
769        }
770
771        if (argc < 3) {
772            printf("not enough arguments\n");
773            return;
774        }
775
776        if (strcmp(argv[2], "-host") == 0) {
777            f_host = 1;
778        } else if (strcmp(argv[2], "-net") == 0) {
779            f_host = 0;
780        } else {
781            printf("Invalid type: %s\n", argv[1]);
782            printf("\tit should be '-host' or '-net'\n");
783            return;
784        }
785
786        if (argc < 4) {
787            printf("not enough arguments\n");
788            return;
789        }
790
791        inet_pton(AF_INET, argv[3], &dst.sin_addr);
792
793        cur_idx = 4;
794        while(cur_idx < argc) {
795            if (strcmp(argv[cur_idx], "gw") == 0) {
796                if ((cur_idx +1) >= argc) {
797                    printf("no gateway address\n");
798                    return;
799                }
800                f_gw = 1;
801                inet_pton(AF_INET, argv[cur_idx + 1], &gw.sin_addr);
802                cur_idx += 1;
803            } else if(strcmp(argv[cur_idx], "netmask") == 0) {
804                if ((cur_idx +1) >= argc) {
805                    printf("no netmask address\n");
806                    return;
807                }
808                f_gw = 1;
809                inet_pton(AF_INET, argv[cur_idx + 1], &netmask.sin_addr);
810                cur_idx += 1;
811            } else {
812                printf("Unknown argument\n");
813                return;
814            }
815            cur_idx += 1;
816        }
817
818        flags = RTF_STATIC;
819        if (f_gw != 0) {
820            flags |= RTF_GATEWAY;
821        }
822        if (f_host != 0) {
823            flags |= RTF_HOST;
824        }
825
826        rc = rtems_bsdnet_rtrequest(cmd, &dst, &gw, &netmask, flags, NULL);
827        if (rc < 0) {
828            printf("Error adding route\n");
829        }
830    }
831
832Thanks to Jay Monkman <mailto:jtm@smoothmsmoothie.com> for this example
833code.
834
835Time Synchronization Using NTP
836------------------------------
837
838.. code-block:: c
839
840    int rtems_bsdnet_synchronize_ntp (int interval, rtems_task_priority priority);
841
842If the interval argument is ``0`` the routine synchronizes the RTEMS
843time-of-day clock with the first NTP server in the ``rtems_bsdnet_ntpserve``
844array and returns.  The priority argument is ignored.
845
846If the interval argument is greater than 0, the routine also starts an RTEMS
847task at the specified priority and polls the NTP server every 'interval'
848seconds.  NOTE: This mode of operation has not yet been implemented.
849
850On successful synchronization of the RTEMS time-of-day clock the routine
851returns ``0``.  If an error occurs a message is printed and the routine returns
852``-1`` with an error code in errno.  There is no timeout - if there is no
853response from an NTP server the routine will wait forever.
Note: See TracBrowser for help on using the repository browser.