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; }
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; }
/* 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); }
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(); }
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); }
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); }
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); }
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(); } }
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"); }
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; }
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); } }
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); }
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; }
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"); } }