source: rtems-docs/networking/using_networking_rtems_app.rst @ 170418a

4.115
Last change on this file since 170418a was bc37517, checked in by Chris Johns <chrisj@…>, on 04/11/16 at 06:32:30

Fix indenting.

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