int main()
{
	uint8_t mac[6];
	uint32_t timer = 0;
    
	/* Obtain the ethernet MAC address */
	eth_mac(mac);
    
	const char *ipaddr="192.168.0.150";
	uint16_t port_be = 0;
    
	interrupt_register(irq_timer, GUEST_TIMER_INT);
  
	/* Configure the virtual ethernet driver */
	struct pico_device* eth_dev = PICO_ZALLOC(sizeof(struct pico_device));
	if(!eth_dev) {
		return 0;
	}   
    
	eth_dev->send = eth_send;
	eth_dev->poll = eth_poll;
	eth_dev->link_state = eth_link_state;
    
	if( 0 != pico_device_init((struct pico_device *)eth_dev, "virt-eth", mac)) {
		printf ("\nDevice init failed.");
		PICO_FREE(eth_dev);
		return 0;
	}    
	
	/* picoTCP initialization */
	printf("\nInitializing pico stack\n");
	pico_stack_init();
	
	wolfSSL_Debugging_ON();
    
	pico_string_to_ipv4(ipaddr, &my_eth_addr.addr);
	pico_string_to_ipv4("255.255.255.0", &netmask.addr);
	pico_ipv4_link_add(eth_dev, my_eth_addr, netmask);

	port_be = short_be(LISTENING_PORT);
	
	/* WolfSSL initialization only, to make sure libwolfssl.a is needed */
	pico_https_setCertificate(cert_pem_2048, sizeof(cert_pem_2048));
	pico_https_setPrivateKey(privkey_pem_2048, sizeof(privkey_pem_2048));
	pico_https_server_start(0, serverWakeup);

	
	while (1){
		eth_watchdog(&timer, 500);
		/* pooling picoTCP stack */
		pico_stack_tick();
        
	}

	return 0;
}
示例#2
0
static struct pico_dns_ns *pico_dns_client_add_ns(struct pico_ip4 *ns_addr)
{
    struct pico_dns_ns *dns = NULL, *found = NULL, test = {{0}};

    dns = pico_zalloc(sizeof(struct pico_dns_ns));
    if (!dns) {
        pico_err = PICO_ERR_ENOMEM;
        return NULL;
    }

    dns->ns = *ns_addr;

    found = pico_tree_insert(&NSTable, dns);
    if (found) { /* nameserver already present */
        pico_free(dns);
        return found;
    }

    /* default NS found, remove it */
    pico_string_to_ipv4(PICO_DNS_NS_GOOGLE, &test.ns.addr);
    found = pico_tree_findKey(&NSTable, &test);
    if (found && (found->ns.addr != ns_addr->addr))
        pico_dns_client_del_ns(&found->ns);

    return dns;
}
示例#3
0
/* mirror ip address numbers
 * f.e. 192.168.0.1 => 1.0.168.192 */
static int8_t pico_dns_client_mirror(char *ptr)
{
    const unsigned char *addr = NULL;
    char *m = ptr;
    uint32_t ip = 0;
    int8_t i = 0;

    if (pico_string_to_ipv4(ptr, &ip) < 0)
        return -1;

    ptr = m;
    addr = (unsigned char *)&ip;
    for (i = 3; i >= 0; i--) {
        if (addr[i] > 99) {
            *ptr++ = (char)('0' + (addr[i] / 100));
            *ptr++ = (char)('0' + ((addr[i] % 100) / 10));
            *ptr++ = (char)('0' + ((addr[i] % 100) % 10));
        } else if(addr[i] > 9) {
            *ptr++ = (char)('0' + (addr[i] / 10));
            *ptr++ = (char)('0' + (addr[i] % 10));
        } else {
            *ptr++ = (char)('0' + addr[i]);
        }

        if(i > 0)
            *ptr++ = '.';
    }
    *ptr = '\0';

    return 0;
}
void
init_picotcp() {
	struct ether_addr mac;
	struct pico_device *dev = NULL;
	struct pico_ip4 addr;
	struct pico_ip4 netm;

	ether_aton_r(config.if_mac, &mac);

	pico_stack_init();

	dev = pico_netmap_create(config.if_name, "eth_if", (uint8_t *) &mac);

	pico_string_to_ipv4(config.if_addr,  &addr.addr);
	pico_string_to_ipv4("255.255.255.0", &netm.addr);
	pico_ipv4_link_add(dev, addr, netm);
}
int pico_dns_client_init()
{
  struct pico_ip4 default_ns;
  if (pico_string_to_ipv4(PICO_DNS_NS_GOOGLE, &default_ns.addr) != 0) {
    pico_err = PICO_ERR_EINVAL;
    return -1;
  }
  return pico_dns_client_nameserver(&default_ns, PICO_DNS_NS_ADD);
}
示例#6
0
void pre_init(void) {
    struct pico_ip4 netmask, ipaddr, gw, multicast, zero = {0};
    pico_device_eth *pico_driver;
    memset(&io_ops, 0, sizeof(io_ops));
    io_ops.dma_manager = (ps_dma_man_t) {
        .cookie = NULL,
        .dma_alloc_fn = malloc_dma_alloc,
        .dma_free_fn = malloc_dma_free,
        .dma_pin_fn = malloc_dma_pin,
        .dma_unpin_fn = malloc_dma_unpin,
        .dma_cache_op_fn = malloc_dma_cache_op
    };

    /* Initialise the PicoTCP stack */
    pico_stack_init();

    /* Create a driver. This utilises preallocated buffers, backed up by malloc above */
    pico_driver = pico_eth_create_no_malloc("eth0", ethdriver_init, NULL, io_ops, &_picotcp_driver);
    assert(pico_driver);

    pico_string_to_ipv4("0.0.0.0", &gw.addr);
    pico_string_to_ipv4(server_ip_addr, &ipaddr.addr);
    pico_string_to_ipv4(multicast_addr, &multicast.addr);
    pico_string_to_ipv4("255.255.255.0", &netmask.addr);

    pico_ipv4_link_add(pico_driver, ipaddr, netmask);
    pico_ipv4_route_add(zero, zero, gw, 1, NULL);

    if (pico_ipv4_is_multicast(multicast.addr)) {
        ZF_LOGE("Multicast not yet implemented\n");
        // PicoTCP usually deals with multicast at the socket layer, using pico_socket_setoption.
        // It can be done at the igmp level too by using igmp_state_change. See the picoTCP documentation
        // Eg: pico_igmp_state_change(&ipaddr, &multicast, .... );
    }

    /* Start the timer for tcp */
    // TCP runs off a tick for handling events and timeouts.
    timer_periodic(0, NS_IN_MS * PICO_TICK_MS);

    start_tcpecho();

}
示例#7
0
文件: tftp.c 项目: UIKit0/picotcp
struct command_t *parse_arguments_recursive(struct command_t *commands, char *arg)
{
    char *next;
    char *operation;
    char *filename;
    char *address;
    static union pico_address remote_address;
    int ret;

    if (!arg)
        return commands;

    next = cpy_arg(&operation, arg);
    switch (*operation) {
    case 'S':
    case 's':
        filename = address = NULL;
        break;
    case 'T':
    case 'R':
    case 't':
    case 'r':
        if (!next) {
            fprintf(stderr, "Incomplete client command %s (filename componet is missing)\n", arg);
            return NULL;
        }

        next = cpy_arg(&filename, next);
        if (!next) {
            fprintf(stderr, "Incomplete client command %s (address component is missing)\n", arg);
            return NULL;
        }

        next = cpy_arg(&address, next);
        if (!IPV6_MODE)
            ret = pico_string_to_ipv4(address, &remote_address.ip4.addr);
        else
            ret = pico_string_to_ipv6(address, remote_address.ip6.addr);

        if (ret < 0) {
            fprintf(stderr, "Invalid IP address %s\n", address);
            print_usage(2);
        }

        break;
    default:
        fprintf(stderr, "Invalid command %s\n", operation);
        return NULL;
    };

    return parse_arguments_recursive(add_command(commands, *operation, filename, &remote_address), next);
}
示例#8
0
END_TEST

START_TEST (arp_compare_test)
{
    struct pico_arp a, b;
    char ipstr[] = "192.168.1.1";

    memset(&a, 0, sizeof(a));
    pico_string_to_ipv4(ipstr, &b.ipv4.addr);

    fail_unless(arp_compare(&a, &b) == -1);
    fail_unless(arp_compare(&b, &a) == 1);
    fail_unless(arp_compare(&a, &a) == 0);
}
示例#9
0
END_TEST

START_TEST (arp_lookup_test)
{
    struct pico_ip4 ip;
    struct pico_eth *eth = NULL;
    char ipstr[] = "192.168.1.1";
    struct pico_arp entry;

    eth = pico_arp_lookup(&ip);
    fail_unless(eth == NULL);

    pico_string_to_ipv4(ipstr, &ip.addr);
    entry.ipv4 = ip;

    pico_stack_init();
    pico_arp_add_entry(&entry);
    entry.arp_status = PICO_ARP_STATUS_STALE;
    eth = pico_arp_lookup(&ip);
    fail_unless(eth == NULL);
}
示例#10
0
文件: echo.c 项目: seL4/camkes
int run(void)
{
    printf("%s instance starting up, going to be listening on %s:%d\n",
           get_instance_name(), ip_addr, ECHO_PORT);

    int socket_in = echo_control_open(false);
    if (socket_in == -1) {
        assert(!"Failed to open a socket for listening!");
    }

    listener_socket = echo_control_open(false);
    if (listener_socket == -1) {
        assert(!"Failed to open a socket for echoing!");
    }

    int ret = echo_control_bind(socket_in, PICOSERVER_ANY_ADDR_IPV4, ECHO_PORT);
    if (ret) {
        assert(!"Failed to bind a socket for listening!");
    }

    ret = echo_control_listen(socket_in, 1);
    if (ret) {
        assert(!"Failed to listen for incoming connections!");
    }

    uint32_t ip = 0;
    pico_string_to_ipv4(ip_addr, &ip);
    ret = echo_control_connect(listener_socket, ip, LISTENER_PORT);
    if (ret) {
        assert(!"Failed to connect to the listener!");
    }

    /* Now poll for events and handle them */
    seL4_Word badge;

    while (1) {
        seL4_Wait(echo_control_notification(), &badge);
        handle_picoserver_notification();
    }
}
示例#11
0
void app_tcpclient()
{
    char *daddr = NULL, *dport = NULL;
    uint16_t send_port = 0, listen_port = short_be(5555);
    int i = 0, ret = 0, yes = 1;
    struct pico_socket *s = NULL;
    struct pico_ip4 dst = {0};
    struct pico_ip4 inaddr = {0};

    ZF_LOGD("Connecting to: %s:%d\n", daddr, short_be(send_port));

    s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_TCP, &cb_tcpclient);

    if (!s) {
        ZF_LOGE("%s: error opening socket: %s\n", __FUNCTION__, strerror(pico_err));
    }

    pico_socket_setoption(s, PICO_TCP_NODELAY, &yes);

    ret = pico_socket_bind(s, &inaddr, &listen_port);

    if (ret < 0) {
        ZF_LOGE("%s: error binding socket to port %u: %s\n", __FUNCTION__, short_be(listen_port), strerror(pico_err));
    }

    // Set the destination address (string) above in the usual xxx.xxx.xxx.xxx ip4 way.
    pico_string_to_ipv4(daddr, &dst.addr);

    ret = pico_socket_connect(s, &dst, send_port);

    if (ret < 0) {
        ZF_LOGE("%s: error connecting to %s:%u: %s\n", __FUNCTION__, daddr, short_be(send_port), strerror(pico_err));
    }

    ZF_LOGD("TCP client connected\n");

}
示例#12
0
int pico_icmp4_ping(char *dst, int count, int interval, int timeout, int size, void (*cb)(struct pico_icmp4_stats *))
{
  static uint16_t next_id = 0x91c0;
  struct pico_icmp4_ping_cookie *cookie;

  if((dst == NULL) || (interval == 0) || (timeout == 0) || (count == 0)){
    pico_err = PICO_ERR_EINVAL;
    return -1;
  }

  cookie = pico_zalloc(sizeof(struct pico_icmp4_ping_cookie));
  if (!cookie) {
    pico_err = PICO_ERR_ENOMEM;
    return -1;
  }

  if (pico_string_to_ipv4(dst, &cookie->dst.addr) < 0) {
    pico_err = PICO_ERR_EINVAL;
    pico_free(cookie);
    return -1;
  }
  cookie->seq = 1;
  cookie->id = next_id++;
  cookie->err = PICO_PING_ERR_PENDING;
  cookie->size = (uint16_t)size;
  cookie->interval = interval;
  cookie->timeout = timeout;
  cookie->cb = cb;
  cookie->count = count;

  pico_tree_insert(&Pings,cookie);
  send_ping(cookie);

  return 0;

}
示例#13
0
int main(int argc, char **argv)
{
    unsigned char macaddr[6] = {
        0, 0, 0, 0xa, 0xb, 0x0
    };
    uint16_t *macaddr_low = (uint16_t *) (macaddr + 2);
    struct pico_device *dev = NULL;

    struct option long_options[] = {
        {"help", 0, 0, 'h'},
        {"vde", 1, 0, 'v'},
        {"barevde", 1, 0, 'b'},
        {"tun", 1, 0, 't'},
        {"route", 1, 0, 'r'},
        {"app", 1, 0, 'a'},
        {"loop", 0, 0, 'l'},
        {0, 0, 0, 0}
    };
    int option_idx = 0;
    int c;

    *macaddr_low ^= (uint16_t)getpid();
    printf("My macaddr base is: %02x %02x\n", macaddr[2], macaddr[3]);

    pico_stack_init();
    /* Parse args */
    while(1) {
        c = getopt_long(argc, argv, "v:b:t:a:r:hl", long_options, &option_idx);
        if (c < 0)
            break;

        switch(c) {
        case 'v':
        {
            char *nxt, *name = NULL, *sock = NULL, *addr = NULL, *nm = NULL, *gw = NULL;
            struct pico_ip4 ipaddr, netmask, gateway, zero = ZERO_IP4;
            printf("+++ OPTARG %s\n", optarg);
            do {
                nxt = cpy_arg(&name, optarg);
                if (!nxt) break;

                nxt = cpy_arg(&sock, nxt);
                if (!nxt) break;

                nxt = cpy_arg(&addr, nxt);
                if (!nxt) break;

                nxt = cpy_arg(&nm, nxt);
                if (!nxt) break;

                nxt = cpy_arg(&gw, nxt);
            } while(0);
            if (!nm) {
                fprintf(stderr, "Vde: bad configuration...\n");
                exit(1);
            }

            dev = pico_vde_create(sock, name, macaddr);
            NXT_MAC(macaddr);
            if (!dev) {
                perror("Creating vde");
                exit(1);
            }

            printf("Vde created.\n");
            pico_string_to_ipv4(addr, &ipaddr.addr);
            pico_string_to_ipv4(nm, &netmask.addr);
            pico_ipv4_link_add(dev, ipaddr, netmask);
            /* bcastAddr.addr = (ipaddr.addr) | (~netmask.addr); */
            if (gw && *gw) {
                pico_string_to_ipv4(gw, &gateway.addr);
                pico_ipv4_route_add(zero, zero, gateway, 1, NULL);
            }
        }
        break;
        }
    }
    if( pico_http_server_start(0, serverWakeup) < 0)
    {
        fprintf(stderr, "Unable to start the HTTP server on port 80\n");
    } else {
        printf("HTTP server started\n");
    }

    printf("%s: launching PicoTCP loop\n", __FUNCTION__);
    while(1) {
        pico_stack_tick();
        usleep(2000);
    }
}
示例#14
0
void app_mcastsend(char *arg)
{
    char *maddr = NULL, *laddr = NULL, *lport = NULL, *sport = NULL;
    uint16_t sendto_port = 0;
    struct pico_ip4 inaddr_link = {
        0
    }, inaddr_mcast = {
        0
    };
    char *new_arg = NULL, *p = NULL, *nxt = arg;
    struct pico_ip_mreq mreq = ZERO_MREQ;

    /* start of parameter parsing */
    if (nxt) {
        nxt = cpy_arg(&laddr, nxt);
        if (laddr) {
            pico_string_to_ipv4(laddr, &inaddr_link.addr);
        } else {
            goto out;
        }
    } else {
        /* no arguments */
        goto out;
    }

    if (nxt) {
        nxt = cpy_arg(&maddr, nxt);
        if (maddr) {
            pico_string_to_ipv4(maddr, &inaddr_mcast.addr);
        } else {
            goto out;
        }
    } else {
        /* missing multicast address */
        goto out;
    }

    if (nxt) {
        nxt = cpy_arg(&sport, nxt);
        if (sport && atoi(sport)) {
            sendto_port = short_be(atoi(sport));
        } else {
            /* incorrect send_port */
            goto out;
        }
    } else {
        /* missing send_port */
        goto out;
    }

    if (nxt) {
        nxt = cpy_arg(&lport, nxt);
        if (lport && atoi(lport)) {
            /* unused at this moment */
            /* listen_port = short_be(atoi(lport)); */
        } else {
            /* incorrect listen_port */
            goto out;
        }
    } else {
        /* missing listen_port */
        goto out;
    }

    picoapp_dbg("\n%s: mcastsend started. Sending packets to %08X:%u\n\n", __FUNCTION__, long_be(inaddr_mcast.addr), short_be(sendto_port));

    /* udpclient:dest_addr:sendto_port[:listen_port:datasize:loops:subloops] */
    new_arg = calloc(1, strlen(maddr) + 1 + strlen(sport) + 1 + strlen(lport) + strlen(":64:10:5:") + 1);
    p = strcat(new_arg, maddr);
    p = strcat(p + strlen(maddr), ":");
    p = strcat(p + 1, sport);
    p = strcat(p + strlen(sport), ":");
    p = strcat(p + 1, lport);
    p = strcat(p + strlen(lport), ":64:10:5:");

    app_udpclient(new_arg);

    mreq.mcast_group_addr = inaddr_mcast;
    mreq.mcast_link_addr = inaddr_link;
    if(pico_socket_setoption(udpclient_pas->s, PICO_IP_ADD_MEMBERSHIP, &mreq) < 0) {
        picoapp_dbg("%s: socket_setoption PICO_IP_ADD_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
        exit(1);
    }

    return;

out:
    picoapp_dbg("mcastsend expects the following format: mcastsend:link_addr:mcast_addr:sendto_port:listen_port\n");
    exit(255);
}
示例#15
0
END_TEST
START_TEST(tc_destination_is_mcast)
{
    struct pico_ip6 addr = {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 }};
    struct pico_ip6 mcast = {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 }};
    struct pico_ip4 addr4 = {0};
    struct pico_ip4 mcast4 = {0};
    struct pico_frame *f = pico_frame_alloc(sizeof(struct pico_ipv6_hdr));
    struct pico_ipv6_hdr *h = (struct pico_ipv6_hdr *)f->buffer;
    struct pico_ipv4_hdr *h4 = (struct pico_ipv4_hdr *)f->buffer;
    /* Test parameters */
    int ret = 0, count = 0;

    f->net_hdr = (uint8_t*) h;
    f->buffer[0] = 0x60; /* Ipv6 */

    STARTING();

    pico_string_to_ipv4("232.1.1.0", &(mcast4.addr)); /* 0 */
    pico_string_to_ipv4("10.20.0.1", &(addr4.addr));

    pico_string_to_ipv6("ff00:0:0:0:0:0:e801:100", (mcast.addr)); /* 0 */
    pico_string_to_ipv6("fe80:0:0:0:0:0:a28:100", (addr.addr)); /* 0 */

    TRYING("With IPv6 unicast addr\n");
    memcpy(h->dst.addr, addr.addr, PICO_SIZE_IP6);
    ret = destination_is_mcast(f);
    CHECKING(count);
    fail_unless(0 == ret, "Should've returned 0 since not an IPv6 multicast\n");
    SUCCESS();

    TRYING("With IPv6 multicast addr\n");
    memcpy(h->dst.addr, mcast.addr, PICO_SIZE_IP6);
    ret = destination_is_mcast(f);
    CHECKING(count);
    fail_unless(1 == ret, "Should've returned 1 since an IPv6 multicast\n");
    SUCCESS();

    pico_frame_discard(f);
    f = pico_frame_alloc(sizeof(struct pico_ipv4_hdr));
    h4 = (struct pico_ipv4_hdr *)f->buffer;
    f->net_hdr = (uint8_t *)h4;
    f->buffer[0] = 0x40; /* IPv4 */

    TRYING("With IPv4 unicast addr\n");
    h4->dst = addr4;
    ret = destination_is_bcast(f);
    CHECKING(count);
    fail_unless(0 == ret, "Should've returned 0 since not an IPv4 mcast address\n");
    SUCCESS();

    TRYING("With IPv4 multicast addr\n");
    h4->dst = mcast4;
    ret = destination_is_mcast(f);
    CHECKING(count);
    fail_unless(1 == ret, "Should've returned 1 since an IPv4 multicast\n");
    SUCCESS();

    BREAKING();
    ret = destination_is_bcast(NULL);
    CHECKING(count);
    fail_unless(0 == ret, "Should've returned 0 since NULL-pointer\n");
    SUCCESS();

    ENDING(count);
}
int pico_dns_client_nameserver(struct pico_ip4 *ns, uint8_t flag)
{
  struct pico_dns_ns test, *key = NULL;

  if (!ns) {
    pico_err = PICO_ERR_EINVAL;
    return -1;
  }

  switch (flag)
  {
    case PICO_DNS_NS_ADD:
      key = pico_zalloc(sizeof(struct pico_dns_ns));
      if (!key) {
        pico_err = PICO_ERR_ENOMEM;
        return -1;
      }
      key->ns = *ns;

      if(pico_tree_insert(&NSTable,key)){
        dns_dbg("DNS WARNING: nameserver %08X already added\n",ns->addr);
        pico_err = PICO_ERR_EINVAL;
        pico_free(key);
        return -1; /* Element key already exists */
      }
      dns_dbg("DNS: nameserver %08X added\n", ns->addr);
      /* If default NS found, remove it */
      pico_string_to_ipv4(PICO_DNS_NS_GOOGLE, &test.ns.addr);
      if (ns->addr != test.ns.addr) {

          key = pico_tree_findKey(&NSTable,&test);
        if (key) {
            if(pico_tree_delete(&NSTable,key)) {
            dns_dbg("DNS: default nameserver %08X removed\n", test.ns.addr);
            pico_free(key);
          } else {
            pico_err = PICO_ERR_EAGAIN;
            return -1;
          }
        }
      }
      break;

    case PICO_DNS_NS_DEL:
      test.ns = *ns;

      key = pico_tree_findKey(&NSTable,&test);
      if (!key) {
        dns_dbg("DNS WARNING: nameserver %08X not found\n", ns->addr);
        pico_err = PICO_ERR_EINVAL;
        return -1;
      }
      /* RB_REMOVE returns pointer to removed element, NULL to indicate error */

            if(pico_tree_delete(&NSTable,key)) {
        dns_dbg("DNS: nameserver %08X removed\n",key->ns.addr);
        pico_free(key);
      } else {
        pico_err = PICO_ERR_EAGAIN;
        return -1;
      }
      /* If no NS left, add default NS */
      if(pico_tree_first(&NSTable) == NULL){
        dns_dbg("DNS: add default nameserver\n");
        return pico_dns_client_init();
      }
      break;

    default:
      pico_err = PICO_ERR_EINVAL;
      return -1;
  }
  return 0;
}
示例#17
0
文件: tftp.c 项目: ajres/picotcp
void app_tftp(char *arg)
{
    char *nxt;
    char *mode, *addr, *file;
    int tftp_mode;
    struct pico_ip4 server;
    nxt = cpy_arg(&mode, arg);

    if ((*mode == 's') || (*mode == 'c') || (*mode == 'p')) { /* TEST BENCH SEND MODE */
        if (*mode == 's') {
            tftp_mode = TFTP_MODE_SRV;
            printf("tftp> Server\n");
        } else {
            if (*mode == 'c')
                tftp_mode = TFTP_MODE_CLI;

            if (*mode == 'p')
                tftp_mode = TFTP_MODE_PSH;

            printf("tftp> Client\n");
            if (!nxt) {
                printf("Usage: tftp:client:host:file:\n");
                exit(1);
            }

            nxt = cpy_arg(&addr, nxt);
            if (pico_string_to_ipv4(addr, &server.addr) < 0) {
                printf("invalid host %s\n", addr);
                exit(1);
            }

            if (!nxt) {
                printf("Usage: tftp:client:host:file:\n");
                exit(1);
            }

            nxt = cpy_arg(&file, nxt);
        }
    } else {
        printf("Usage: tftp:tx|rx|p:...\n");
    }



    if (tftp_mode == TFTP_MODE_SRV)
    {
        pico_tftp_listen(PICO_PROTO_IPV4, tftp_listen_cb);
    } else if (tftp_mode == TFTP_MODE_CLI)
    {
        if(pico_tftp_start_rx((union pico_address *)&server, short_be(PICO_TFTP_PORT), PICO_PROTO_IPV4, file, cb_tftp) < 0) {
            fprintf(stderr, "TFTP: Error in initialization\n");
            exit(1);
        }
    } else if (tftp_mode == TFTP_MODE_PSH)
    {
        if(pico_tftp_start_tx((union pico_address *)&server, short_be(PICO_TFTP_PORT), PICO_PROTO_IPV4, file, cb_tftp_tx) < 0) {
            fprintf(stderr, "TFTP: Error in initialization\n");
            exit(1);
        }
    } else {
        printf("Usage: tftp:tx|rx|p:...\n");
    }
}