1/* PicoTCP Test application */
2#include <poll.h>
3#include <errno.h>
4#include <unistd.h>
5#include <signal.h>
6#include <getopt.h>
7#include <string.h>
8#include <errno.h>
9#include <fcntl.h>
10#include <libgen.h>
11#include <sys/types.h>
12#include <unistd.h>
13
14#include "utils.h"
15
16#include "pico_stack.h"
17#include "pico_config.h"
18#include "pico_dev_vde.h"
19#include "pico_ipv4.h"
20#include "pico_ipv6.h"
21#include "pico_socket.h"
22#include "pico_dev_tun.h"
23#include "pico_dev_tap.h"
24#include "pico_nat.h"
25#include "pico_icmp4.h"
26#include "pico_icmp6.h"
27#include "pico_dns_client.h"
28#include "pico_dev_loop.h"
29#include "pico_dhcp_client.h"
30#include "pico_dhcp_server.h"
31#include "pico_ipfilter.h"
32#include "pico_olsr.h"
33#include "pico_sntp_client.h"
34#include "pico_mdns.h"
35#include "pico_tftp.h"
36#include "pico_dev_radiotest.h"
37#include "pico_dev_radio_mgr.h"
38
39#include <poll.h>
40#include <errno.h>
41#include <unistd.h>
42#include <signal.h>
43#include <getopt.h>
44#include <string.h>
45#include <errno.h>
46#include <fcntl.h>
47#include <libgen.h>
48
49#ifdef FAULTY
50#include "pico_faulty.h"
51#endif
52
53void app_udpecho(char *args);
54void app_tcpecho(char *args);
55void app_udpclient(char *args);
56void app_tcpclient(char *args);
57void app_tcpbench(char *args);
58void app_natbox(char *args);
59void app_udpdnsclient(char *args);
60void app_udpnatclient(char *args);
61void app_mcastsend(char *args);
62void app_mcastreceive_ipv6(char *args);
63void app_mcastsend_ipv6(char *args);
64void app_mcastreceive(char *args);
65void app_ping(char *args);
66void app_dhcp_server(char *args);
67void app_dhcp_client(char *args);
68void app_dns_sd(char *arg, struct pico_ip4 addr);
69void app_mdns(char *arg, struct pico_ip4 addr);
70void app_sntp(char *args);
71void app_tftp(char *args);
72void app_slaacv4(char *args);
73void app_udpecho(char *args);
74void app_sendto_test(char *args);
75void app_noop(void);
76
77struct pico_ip4 ZERO_IP4 = {
78    0
79};
80struct pico_ip_mreq ZERO_MREQ = {
81    .mcast_group_addr = {{0}},
82    .mcast_link_addr  = {{0}}
83};
84struct pico_ip_mreq_source ZERO_MREQ_SRC = {
85    .mcast_group_addr.ip4  = {0},
86    .mcast_link_addr.ip4   = {0},
87    .mcast_source_addr.ip4 = {0}
88};
89struct pico_ip6 ZERO_IP6 = {
90    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
91};
92struct pico_ip_mreq ZERO_MREQ_IP6 = {
93    .mcast_group_addr.ip6 = {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }},
94    .mcast_link_addr.ip6  = {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }}
95};
96struct pico_ip_mreq_source ZERO_MREQ_SRC_IP6 = {
97    .mcast_group_addr.ip6 =  {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }},
98    .mcast_link_addr.ip6 =   {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }},
99    .mcast_source_addr.ip6 = {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }}
100};
101
102/* #define INFINITE_TCPTEST */
103#define picoapp_dbg(...) do {} while(0)
104/* #define picoapp_dbg printf */
105
106/* #define PICOAPP_IPFILTER 1 */
107
108int IPV6_MODE;
109
110
111struct pico_ip4 inaddr_any = {
112    0
113};
114struct pico_ip6 inaddr6_any = {{0}};
115
116char *cpy_arg(char **dst, char *str);
117
118void deferred_exit(pico_time __attribute__((unused)) now, void *arg)
119{
120    if (arg) {
121        free(arg);
122        arg = NULL;
123    }
124
125    printf("%s: quitting\n", __FUNCTION__);
126    exit(0);
127}
128
129
130
131/** From now on, parsing the command line **/
132#define NXT_MAC(x) ++ x[5]
133
134/* Copy a string until the separator,
135   terminate it and return the next index,
136   or NULL if it encounters a EOS */
137char *cpy_arg(char **dst, char *str)
138{
139    char *p, *nxt = NULL;
140    char *start = str;
141    char *end = start + strlen(start);
142    char sep = ':';
143
144    if (IPV6_MODE)
145        sep = ',';
146
147    p = str;
148    while (p) {
149        if ((*p == sep) || (*p == '\0')) {
150            *p = (char)0;
151            nxt = p + 1;
152            if ((*nxt == 0) || (nxt >= end))
153                nxt = 0;
154
155            printf("dup'ing %s\n", start);
156            *dst = strdup(start);
157            break;
158        }
159
160        p++;
161    }
162    return nxt;
163}
164
165static void __wakeup(uint16_t __attribute__((unused)) ev, struct pico_socket __attribute__((unused)) *s)
166{
167
168}
169
170
171static void usage(char *arg0)
172{
173    printf("Usage: %s [--vde name:sock:address:netmask[:gateway]] [--vde ...] [--tun name:address:netmask[:gateway]] [--tun ...] [--app name[:args]]\n\n\n", arg0);
174    printf("\tall arguments can be repeated, e.g. to run on multiple links or applications\n");
175    printf("\t* --app arguments must be at the end  *\n");
176    exit(255);
177}
178
179#define IF_APPNAME(x) if(strcmp(x, name) == 0)
180
181int main(int argc, char **argv)
182{
183    unsigned char macaddr[6] = {
184        0, 0, 0, 0xa, 0xb, 0x0
185    };
186    uint16_t *macaddr_low = (uint16_t *) (macaddr + 2);
187    struct pico_device *dev = NULL;
188    struct pico_ip4 addr4 = {
189        0
190    };
191    struct pico_ip4 bcastAddr = ZERO_IP4;
192
193    struct option long_options[] = {
194        {"help", 0, 0, 'h'},
195        {"vde", 1, 0, 'v'},
196        {"barevde", 1, 0, 'b'},
197        {"tun", 1, 0, 't'},
198        {"tap", 1, 0, 'T'},
199        {"route", 1, 0, 'r'},
200        {"app", 1, 0, 'a'},
201        {"dns", 1, 0, 'd'},
202        {"loop", 0, 0, 'l'},
203        {0, 0, 0, 0}
204    };
205    int option_idx = 0;
206    int c;
207    char *app = NULL, *p = argv[0];
208    /* parse till we find the name of the executable */
209    while (p) {
210        if (*p == '/')
211            app = p + 1;
212        else if (*p == '\0')
213            break;
214        else
215        {} /* do nothing */
216
217        p++;
218    }
219    if (strcmp(app, "picoapp6.elf") == 0)
220        IPV6_MODE = 1;
221
222    *macaddr_low = (uint16_t)(*macaddr_low ^ (uint16_t)((uint16_t)getpid() & (uint16_t)0xFFFFU));
223    printf("My macaddr base is: %02x %02x\n", macaddr[2], macaddr[3]);
224    printf("My macaddr is: %02x %02x %02x %02x %02x %02x\n", macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5]);
225
226#ifdef PICO_SUPPORT_MM
227    pico_mem_init(128 * 1024);
228#endif
229    pico_stack_init();
230    /* Parse args */
231    while(1) {
232        c = getopt_long(argc, argv, "6:v:b:t:T:a:r:hl", long_options, &option_idx);
233        if (c < 0)
234            break;
235
236        switch(c) {
237        case 'h':
238            usage(argv[0]);
239            break;
240        case 'T':
241        {
242            char *nxt, *name = NULL, *addr = NULL, *nm = NULL, *gw = NULL;
243            struct pico_ip4 ipaddr, netmask, gateway, zero = ZERO_IP4;
244            do {
245                nxt = cpy_arg(&name, optarg);
246                if (!nxt) break;
247
248                nxt = cpy_arg(&addr, nxt);
249                if (!nxt) break;
250
251                nxt = cpy_arg(&nm, nxt);
252                if (!nxt) break;
253
254                cpy_arg(&gw, nxt);
255            } while(0);
256            if (!nm) {
257                fprintf(stderr, "Tun: bad configuration...\n");
258                exit(1);
259            }
260
261            dev = pico_tap_create(name);
262            if (!dev) {
263                perror("Creating tap");
264                exit(1);
265            }
266
267            pico_string_to_ipv4(addr, &ipaddr.addr);
268            pico_string_to_ipv4(nm, &netmask.addr);
269            pico_ipv4_link_add(dev, ipaddr, netmask);
270            bcastAddr.addr = (ipaddr.addr) | (~netmask.addr);
271            if (gw && *gw) {
272                pico_string_to_ipv4(gw, &gateway.addr);
273                printf("Adding default route via %08x\n", gateway.addr);
274                pico_ipv4_route_add(zero, zero, gateway, 1, NULL);
275            }
276
277#ifdef PICO_SUPPORT_IPV6
278            if (IPV6_MODE) {
279                struct pico_ip6 ipaddr6 = {{0}}, netmask6 = {{0}}, gateway6 = {{0}}, zero6 = {{0}};
280                pico_string_to_ipv6(addr, ipaddr6.addr);
281                pico_string_to_ipv6(nm, netmask6.addr);
282                pico_ipv6_link_add(dev, ipaddr6, netmask6);
283                if (gw && *gw) {
284                    pico_string_to_ipv6(gw, gateway6.addr);
285                    pico_ipv6_route_add(zero6, zero6, gateway6, 1, NULL);
286                }
287
288                pico_ipv6_dev_routing_enable(dev);
289            }
290
291#endif
292        }
293        break;
294        case 't':
295        {
296            char *nxt, *name = NULL, *addr = NULL, *nm = NULL, *gw = NULL;
297            struct pico_ip4 ipaddr, netmask, gateway, zero = ZERO_IP4;
298            do {
299                nxt = cpy_arg(&name, optarg);
300                if (!nxt) break;
301
302                nxt = cpy_arg(&addr, nxt);
303                if (!nxt) break;
304
305                nxt = cpy_arg(&nm, nxt);
306                if (!nxt) break;
307
308                cpy_arg(&gw, nxt);
309            } while(0);
310            if (!nm) {
311                fprintf(stderr, "Tun: bad configuration...\n");
312                exit(1);
313            }
314
315            dev = pico_tun_create(name);
316            if (!dev) {
317                perror("Creating tun");
318                exit(1);
319            }
320
321            pico_string_to_ipv4(addr, &ipaddr.addr);
322            pico_string_to_ipv4(nm, &netmask.addr);
323            pico_ipv4_link_add(dev, ipaddr, netmask);
324            bcastAddr.addr = (ipaddr.addr) | (~netmask.addr);
325            if (gw && *gw) {
326                pico_string_to_ipv4(gw, &gateway.addr);
327                printf("Adding default route via %08x\n", gateway.addr);
328                pico_ipv4_route_add(zero, zero, gateway, 1, NULL);
329            }
330
331#ifdef PICO_SUPPORT_IPV6
332            if (IPV6_MODE) {
333                struct pico_ip6 ipaddr6 = {{0}}, netmask6 = {{0}}, gateway6 = {{0}}, zero6 = {{0}};
334                pico_string_to_ipv6(addr, ipaddr6.addr);
335                pico_string_to_ipv6(nm, netmask6.addr);
336                pico_ipv6_link_add(dev, ipaddr6, netmask6);
337                if (gw && *gw) {
338                    pico_string_to_ipv6(gw, gateway6.addr);
339                    pico_ipv6_route_add(zero6, zero6, gateway6, 1, NULL);
340                }
341
342                pico_ipv6_dev_routing_enable(dev);
343            }
344
345#endif
346        }
347        break;
348        case 'v':
349        {
350            char *nxt, *name = NULL, *sock = NULL, *addr = NULL, *nm = NULL, *gw = NULL, *addr6 = NULL, *nm6 = NULL, *gw6 = NULL, *loss_in = NULL, *loss_out = NULL;
351            struct pico_ip4 ipaddr, netmask, gateway, zero = ZERO_IP4;
352            uint32_t i_pc = 0, o_pc = 0;
353            printf("+++ OPTARG %s\n", optarg);
354            do {
355                nxt = cpy_arg(&name, optarg);
356                if (!nxt) break;
357
358                nxt = cpy_arg(&sock, nxt);
359                if (!nxt) break;
360
361                if (!IPV6_MODE) {
362                    nxt = cpy_arg(&addr, nxt);
363                    if (!nxt) break;
364
365                    nxt = cpy_arg(&nm, nxt);
366                    if (!nxt) break;
367
368                    nxt = cpy_arg(&gw, nxt);
369                    if (!nxt) break;
370
371                    nxt = cpy_arg(&loss_in, nxt);
372                    if (!nxt) break;
373
374                    nxt = cpy_arg(&loss_out, nxt);
375                    if (!nxt) break;
376                } else {
377                    nxt = cpy_arg(&addr6, nxt);
378                    if (!nxt) break;
379
380                    printf("addr6: %s\n", addr6);
381
382                    nxt = cpy_arg(&nm6, nxt);
383                    if (!nxt) break;
384
385                    nxt = cpy_arg(&gw6, nxt);
386                    if (!nxt) break;
387
388                    nxt = cpy_arg(&loss_in, nxt);
389                    if (!nxt) break;
390
391                    nxt = cpy_arg(&loss_out, nxt);
392                    if (!nxt) break;
393                }
394            } while(0);
395            if (!nm && !nm6) {
396                fprintf(stderr, "Vde: bad configuration...\n");
397                exit(1);
398            }
399
400            macaddr[4] ^= (uint8_t)(getpid() >> 8);
401            macaddr[5] ^= (uint8_t) (getpid() & 0xFF);
402            dev = pico_vde_create(sock, name, macaddr);
403            NXT_MAC(macaddr);
404            if (!dev) {
405                perror("Creating vde");
406                exit(1);
407            }
408
409            printf("Vde created.\n");
410
411            if (!IPV6_MODE) {
412                pico_string_to_ipv4(addr, &ipaddr.addr);
413                pico_string_to_ipv4(nm, &netmask.addr);
414                pico_ipv4_link_add(dev, ipaddr, netmask);
415                addr4 = ipaddr;
416                bcastAddr.addr = (ipaddr.addr) | (~netmask.addr);
417                if (gw && *gw) {
418                    pico_string_to_ipv4(gw, &gateway.addr);
419                    pico_ipv4_route_add(zero, zero, gateway, 1, NULL);
420                }
421            }
422
423#ifdef PICO_SUPPORT_IPV6
424            if (IPV6_MODE) {
425                struct pico_ip6 ipaddr6 = {{0}}, netmask6 = {{0}}, gateway6 = {{0}}, zero6 = {{0}};
426                printf("SETTING UP IPV6 ADDRESS\n");
427                pico_string_to_ipv6(addr6, ipaddr6.addr);
428                pico_string_to_ipv6(nm6, netmask6.addr);
429                pico_ipv6_link_add(dev, ipaddr6, netmask6);
430                if (gw6 && *gw6) {
431                    pico_string_to_ipv6(gw6, gateway6.addr);
432                    pico_ipv6_route_add(zero6, zero6, gateway6, 1, NULL);
433                }
434
435                pico_ipv6_dev_routing_enable(dev);
436            }
437
438#endif
439            if (loss_in && (strlen(loss_in) > 0)) {
440                i_pc = (uint32_t)atoi(loss_in);
441            }
442
443            if (loss_out && (strlen(loss_out) > 0)) {
444                o_pc = (uint32_t)atoi(loss_out);
445            }
446
447            if (i_pc || o_pc) {
448                printf(" ---------- >Setting vde packet loss %u:%u\n", i_pc, o_pc);
449                pico_vde_set_packetloss(dev, i_pc, o_pc);
450            }
451
452
453        }
454        break;
455
456        case '6':
457        {
458            char *nxt, *name = NULL, *area0 = NULL, *area1 = NULL, *dump = NULL;
459            const char pan_addr[] = "2aaa:abcd::0";
460            uint8_t n_id, n_area0, n_area1;
461            struct pico_ip6 pan;
462
463            /* Copy required command line arguments */
464            nxt = cpy_arg(&name, optarg);
465            if (!nxt)
466                goto check;
467            nxt = cpy_arg(&area0, nxt);
468            if (!nxt)
469                goto check;
470            nxt = cpy_arg(&area1, nxt);
471            if (!nxt)
472                goto check;
473
474            /* Check required arguments */
475check:      if (!name || !area0 || !area1) {
476                fprintf(stderr, "Usage: -6,id,area\n");
477                exit(1);
478            }
479
480            n_id = (uint8_t) atoi(name);
481            n_area0 = (uint8_t) atoi(area0);
482            n_area1 = (uint8_t) atoi(area1);
483
484            if (nxt) {
485                nxt = cpy_arg(&dump, nxt);
486            }
487
488            printf("%d:%d:%d\n", n_id, n_area0, n_area1);
489
490            if (!n_id) {
491                printf("Starting radio-network...\n");
492                pico_radio_mgr_start();
493            } else {
494                dev = pico_radiotest_create(n_id, n_area0, n_area1, 0, dump);
495                if (!dev) {
496                    exit(1);
497                }
498
499                printf("Radiotest created.\n");
500
501                /* Add a routable link */
502                pico_string_to_ipv6(pan_addr, pan.addr);
503                pico_ipv6_link_add_local(dev, &pan);
504
505                /* Enable routing on first device */
506                if (n_id == 1) {
507                    pico_ipv6_dev_routing_enable(dev);
508                }
509            }
510            break;
511        }
512        case 'b':
513        {
514            char *nxt, *name = NULL, *sock = NULL;
515            printf("+++ OPTARG %s\n", optarg);
516            do {
517                nxt = cpy_arg(&name, optarg);
518                if (!nxt) break;
519
520                nxt = cpy_arg(&sock, nxt);
521            } while(0);
522            if (!sock) {
523                fprintf(stderr, "Vde: bad configuration...\n");
524                exit(1);
525            }
526
527            macaddr[4] ^= (uint8_t)(getpid() >> 8);
528            macaddr[5] ^= (uint8_t)(getpid() & 0xFF);
529            dev = pico_vde_create(sock, name, macaddr);
530            NXT_MAC(macaddr);
531            if (!dev) {
532                if (sock)
533                    free(sock);
534
535                if (name)
536                    free(name);
537
538                perror("Creating vde");
539                exit(1);
540            }
541
542            if (sock)
543                free(sock);
544
545            if (name)
546                free(name);
547
548            printf("Vde created.\n");
549        }
550        break;
551        case 'l':
552        {
553            struct pico_ip4 ipaddr, netmask;
554
555            dev = pico_loop_create();
556            if (!dev) {
557                perror("Creating loop");
558                exit(1);
559            }
560
561            pico_string_to_ipv4("127.0.0.1", &ipaddr.addr);
562            pico_string_to_ipv4("255.0.0.0", &netmask.addr);
563            pico_ipv4_link_add(dev, ipaddr, netmask);
564            printf("Loopback created\n");
565#ifdef PICO_SUPPORT_IPV6
566            if (IPV6_MODE) {
567                struct pico_ip6 ipaddr6 = {{0}}, netmask6 = {{0}};
568                pico_string_to_ipv6("::1", ipaddr6.addr);
569                pico_string_to_ipv6("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", netmask6.addr);
570                pico_ipv6_link_add(dev, ipaddr6, netmask6);
571            }
572
573            pico_ipv6_dev_routing_enable(dev);
574
575#endif
576        }
577        break;
578        case 'r':
579        {
580            char *nxt, *addr, *nm, *gw;
581            struct pico_ip4 ipaddr, netmask, gateway;
582            /* XXX adjust for IPv6 */
583            addr = NULL, nm = NULL, gw = NULL;
584            printf("+++ ROUTEOPTARG %s\n", optarg);
585            do {
586                nxt = cpy_arg(&addr, optarg);
587                if (!nxt) break;
588
589                nxt = cpy_arg(&nm, nxt);
590                if (!nxt) break;
591
592                nxt = cpy_arg(&gw, nxt);
593            } while(0);
594            if (!addr || !nm || !gw) {
595                fprintf(stderr, "--route expects addr:nm:gw:\n");
596                usage(argv[0]);
597            }
598
599            pico_string_to_ipv4(addr, &ipaddr.addr);
600            pico_string_to_ipv4(nm, &netmask.addr);
601            pico_string_to_ipv4(gw, &gateway.addr);
602            if (pico_ipv4_route_add(ipaddr, netmask, gateway, 1, NULL) == 0)
603                fprintf(stderr, "ROUTE ADDED *** to %s via %s\n", addr, gw);
604            else
605                fprintf(stderr, "ROUTE ADD: ERROR %s \n", strerror(pico_err));
606
607            break;
608        }
609        case 'd':
610        {
611            /* Add a DNS nameserver IP address */
612            char *straddr;
613            struct pico_ip4 ipaddr;
614            printf("DNS nameserver address = %s\n", optarg);
615            cpy_arg(&straddr, optarg);
616            pico_string_to_ipv4(straddr, &ipaddr.addr);
617            pico_dns_client_nameserver(&ipaddr, PICO_DNS_NS_ADD);
618            break;
619        }
620        case 'a':
621        {
622            char *name = NULL, *args = NULL;
623            printf("+++ OPTARG %s\n", optarg);
624            args = cpy_arg(&name, optarg);
625
626            printf("+++ NAME: %s ARGS: %s\n", name, args);
627            IF_APPNAME("udpecho") {
628                app_udpecho(args);
629            } else IF_APPNAME("tcpecho") {
630                app_tcpecho(args);
631            } else IF_APPNAME("udpclient") {
632                app_udpclient(args);
633            } else IF_APPNAME("tcpclient") {
634                app_tcpclient(args);
635            } else IF_APPNAME("tcpbench") {
636                app_tcpbench(args);
637            } else IF_APPNAME("natbox") {
638                app_natbox(args);
639            } else IF_APPNAME("udpdnsclient") {
640                app_udpdnsclient(args);
641            } else IF_APPNAME("udpnatclient") {
642                app_udpnatclient(args);
643            } else IF_APPNAME("mcastsend") {
644#ifndef PICO_SUPPORT_MCAST
645                return 0;
646#endif
647                app_mcastsend(args);
648            } else IF_APPNAME("mcastreceive") {
649#ifndef PICO_SUPPORT_MCAST
650                return 0;
651#endif
652                app_mcastreceive(args);
653            }
654            else IF_APPNAME("mcastsend_ipv6") {
655#ifndef PICO_SUPPORT_MCAST
656                return 0;
657#endif
658                app_mcastsend_ipv6(args);
659            } else IF_APPNAME("mcastreceive_ipv6") {
660#ifndef PICO_SUPPORT_MCAST
661                return 0;
662#endif
663                app_mcastreceive_ipv6(args);
664            }
665
666#ifdef PICO_SUPPORT_PING
667            else IF_APPNAME("ping") {
668                app_ping(args);
669            }
670#endif
671            else IF_APPNAME("dhcpserver") {
672#ifndef PICO_SUPPORT_DHCPD
673                return 0;
674#else
675                app_dhcp_server(args);
676#endif
677            } else IF_APPNAME("dhcpclient") {
678#ifndef PICO_SUPPORT_DHCPC
679                return 0;
680#else
681                app_dhcp_client(args);
682#endif
683            } else IF_APPNAME("dns_sd") {
684#ifndef PICO_SUPPORT_DNS_SD
685                return 0;
686#else
687                app_dns_sd(args, addr4);
688#endif
689            } else IF_APPNAME("mdns") {
690#ifndef PICO_SUPPORT_MDNS
691                return 0;
692#else
693                app_mdns(args, addr4);
694#endif
695#ifdef PICO_SUPPORT_SNTP_CLIENT
696            } else IF_APPNAME("sntp") {
697                app_sntp(args);
698#endif
699            } else IF_APPNAME("bcast") {
700                struct pico_ip4 any = {
701                    .addr = 0xFFFFFFFFu
702                };
703
704                struct pico_socket *s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, &__wakeup);
705                pico_socket_sendto(s, "abcd", 5u, &any, 1000);
706
707                pico_socket_sendto(s, "abcd", 5u, &bcastAddr, 1000);
708#ifdef PICO_SUPPORT_TFTP
709            } else IF_APPNAME("tftp") {
710                app_tftp(args);
711#endif
712            } else IF_APPNAME("noop") {
713                app_noop();
714#ifdef PICO_SUPPORT_OLSR
715            } else IF_APPNAME("olsr") {
716                dev = pico_get_device("pic0");
717                if(dev) {
718                    pico_olsr_add(dev);
719                }
720
721                dev = pico_get_device("pic1");
722                if(dev) {
723                    pico_olsr_add(dev);
724                }
725
726                app_noop();
727#endif
728            } else IF_APPNAME("slaacv4") {
729#ifndef PICO_SUPPORT_SLAACV4
730                return 0;
731#else
732                app_slaacv4(args);
733#endif
734            } else IF_APPNAME("udp_sendto_test") {
735                app_sendto_test(args);
736            } else {
737                fprintf(stderr, "Unknown application %s\n", name);
738                usage(argv[0]);
739            }
740        }
741        break;
742        }
743    }
744    if (!dev) {
745        printf("nodev");
746        usage(argv[0]);
747    }
748
749#ifdef FAULTY
750    atexit(memory_stats);
751#endif
752    printf("%s: launching PicoTCP loop\n", __FUNCTION__);
753    while(1) {
754        pico_stack_tick();
755        usleep(2000);
756    }
757}
758