static struct pico_dns_query *pico_dns_client_add_query(struct pico_dns_prefix *hdr, uint16_t len, struct pico_dns_query_suffix *suffix, void (*callback)(char *, void *), void *arg) { struct pico_dns_query *q = NULL, *found = NULL; q = pico_zalloc(sizeof(struct pico_dns_query)); if (!q) return NULL; q->query = (char *)hdr; q->len = len; q->id = short_be(hdr->id); q->qtype = short_be(suffix->qtype); q->qclass = short_be(suffix->qclass); q->retrans = 1; q->q_ns = *((struct pico_dns_ns *)pico_tree_first(&NSTable)); q->callback = callback; q->arg = arg; q->s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, &pico_dns_client_callback); if (!q->s) { pico_free(q); return NULL; } found = pico_tree_insert(&DNSTable, q); if (found) { pico_err = PICO_ERR_EAGAIN; pico_socket_close(q->s); pico_free(q); return NULL; } return q; }
void setup_udp_app() { struct pico_socket *listen_socket; struct pico_ip4 address; uint16_t port; int ret; port = short_be(atoi(config.port)); bzero(&address, sizeof(address)); listen_socket = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, &cb_udpconnect); if (!listen_socket) { printf("cannot open socket: %s", strerror(pico_err)); exit(1); } ret = pico_socket_bind(listen_socket, &address, &port); if (ret < 0) { printf("cannot bind socket to port %u: %s", short_be(port), strerror(pico_err)); exit(1); } return; }
END_TEST START_TEST(tc_pico_sntp_parse) { /* TODO: test this: static void pico_sntp_parse(char *buf, struct sntp_server_ns_cookie *ck) */ struct sntp_server_ns_cookie *ck; struct pico_socket *sock; struct pico_sntp_header header = { 0 }; ck = PICO_ZALLOC(sizeof(struct sntp_server_ns_cookie)); fail_unless (ck != NULL); ck->hostname = PICO_ZALLOC(sizeof(char) * 5); fail_unless (ck->hostname != NULL); ck->stamp = 0ull; ck->cb_synced = cb_synced; sock = pico_socket_open(0, 0, &pico_sntp_client_wakeup); ck->sock = sock; sock->priv = ck; header.mode = 4; /* server mode */ header.vn = 4; /* sntp version 4 */ header.stratum = 1; /* primary reference */ header.trs_ts.sec = long_be(SNTP_UNIX_OFFSET + 1390000000ul); header.trs_ts.frac = long_be(3865470566ul); /* value: 899msec */ fail_if(pico_sntp_parse((char *) &header, NULL) == 0); fail_if(pico_sntp_parse((char *) &header, ck) != 0); }
void start_tcpecho() { uint16_t listen_port = short_be(8777); int ret = 0, yes = 1; struct pico_socket *s = NULL; struct pico_ip4 ip4 = {0}; s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_TCP, &cb_tcpecho); 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, &ip4, &listen_port); if (ret < 0) { ZF_LOGE("%s: error binding socket to port %u: %s\n", __FUNCTION__, short_be(listen_port), strerror(pico_err)); } if (pico_socket_listen(s, 40) != 0) { ZF_LOGE("%s: error listening on port %u\n", __FUNCTION__, short_be(listen_port)); } ZF_LOGD("Launching PicoTCP echo server\n"); }
static struct pico_dhcp_server_setting *pico_dhcp_server_add_setting(struct pico_dhcp_server_setting *setting) { uint16_t port = PICO_DHCPD_PORT; struct pico_dhcp_server_setting *dhcps = NULL, *found = NULL, test = {0}; struct pico_ipv4_link *link = NULL; link = pico_ipv4_link_get(&setting->server_ip); if (!link) { pico_err = PICO_ERR_EINVAL; return NULL; } test.dev = setting->dev; found = pico_tree_findKey(&DHCPSettings, &test); if (found) { pico_err = PICO_ERR_EINVAL; return NULL; } dhcps = pico_zalloc(sizeof(struct pico_dhcp_server_setting)); if (!dhcps) { pico_err = PICO_ERR_ENOMEM; return NULL; } dhcps->lease_time = setting->lease_time; dhcps->pool_start = setting->pool_start; dhcps->pool_next = setting->pool_next; dhcps->pool_end = setting->pool_end; dhcps->dev = link->dev; dhcps->server_ip = link->address; dhcps->netmask = link->netmask; /* default values if not provided */ if (!dhcps->pool_start) dhcps->pool_start = (dhcps->server_ip.addr & dhcps->netmask.addr) | DHCP_SERVER_POOL_START; if (!dhcps->pool_end) dhcps->pool_end = (dhcps->server_ip.addr & dhcps->netmask.addr) | DHCP_SERVER_POOL_END; if (!dhcps->lease_time) dhcps->lease_time = DHCP_SERVER_LEASE_TIME; dhcps->pool_next = dhcps->pool_start; dhcps->s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, &pico_dhcpd_wakeup); if (!dhcps->s) { dhcps_dbg("DHCP server ERROR: failure opening socket (%s)\n", strerror(pico_err)); pico_free(dhcps); return NULL; } if (pico_socket_bind(dhcps->s, &dhcps->server_ip, &port) < 0) { dhcps_dbg("DHCP server ERROR: failure binding socket (%s)\n", strerror(pico_err)); pico_free(dhcps); return NULL; } pico_tree_insert(&DHCPSettings, dhcps); return dhcps; }
static int pico_dns_client_send(struct pico_dns_key *key) { struct pico_socket *s; int w = 0; dns_dbg("DNS: sending query to %08X\n", key->q_ns.ns.addr); s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, &pico_dns_client_callback); if (!s) return -1; key->s = s; if (pico_socket_connect(s, &key->q_ns.ns, short_be(PICO_DNS_NS_PORT)) != 0) return -1; w = pico_socket_send(s, key->q_hdr, key->len); if (w <= 0) return -1; return 0; }
END_TEST START_TEST(tc_sntp_receive_timeout) { struct sntp_server_ns_cookie *ck; struct pico_socket *sock; ck = PICO_ZALLOC(sizeof(struct sntp_server_ns_cookie)); fail_unless (ck != NULL); ck->hostname = PICO_ZALLOC(sizeof(char) * 5); fail_unless (ck->hostname != NULL); ck->stamp = 0ull; ck->cb_synced = cb_synced; sock = pico_socket_open(0, 0, &pico_sntp_client_wakeup); ck->sock = sock; sock->priv = ck; sntp_receive_timeout(0ull, ck); }
static inline struct pico_dhcp_server_setting *dhcps_try_open_socket(struct pico_dhcp_server_setting *dhcps) { uint16_t port = PICO_DHCPD_PORT; dhcps->s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, &pico_dhcpd_wakeup); if (!dhcps->s) { dhcps_dbg("DHCP server ERROR: failure opening socket (%s)\n", strerror(pico_err)); PICO_FREE(dhcps); return NULL; } if (pico_socket_bind(dhcps->s, &dhcps->server_ip, &port) < 0) { dhcps_dbg("DHCP server ERROR: failure binding socket (%s)\n", strerror(pico_err)); PICO_FREE(dhcps); return NULL; } pico_tree_insert(&DHCPSettings, dhcps); return dhcps; }
END_TEST START_TEST(tc_pico_sntp_cleanup) { struct sntp_server_ns_cookie *ck; struct pico_socket *sock; ck = PICO_ZALLOC(sizeof(struct sntp_server_ns_cookie)); fail_unless (ck != NULL); ck->hostname = PICO_ZALLOC(sizeof(char) * 5); fail_unless (ck->hostname != NULL); ck->stamp = 0ull; ck->cb_synced = cb_synced; sock = pico_socket_open(0, 0, &pico_sntp_client_wakeup); ck->sock = sock; sock->priv = ck; pico_sntp_cleanup(ck, PICO_ERR_NOERR); }
END_TEST START_TEST(tc_pico_sntp_client_wakeup) { /* TODO: test this: static void pico_sntp_client_wakeup(uint16_t ev, struct pico_socket *s) */ uint16_t event = PICO_SOCK_EV_ERR; struct sntp_server_ns_cookie *ck; struct pico_socket *sock; ck = PICO_ZALLOC(sizeof(struct sntp_server_ns_cookie)); fail_unless (ck != NULL); ck->hostname = PICO_ZALLOC(sizeof(char) * 5); fail_unless (ck->hostname != NULL); ck->stamp = 0ull; ck->cb_synced = cb_synced; sock = pico_socket_open(0, 0, &pico_sntp_client_wakeup); ck->sock = sock; sock->priv = ck; ck->cb_synced = cb_synced; printf("Started wakeup unit test\n"); pico_sntp_client_wakeup(event, sock); }
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"); }
END_TEST START_TEST (test_icmp4_incoming_ping) { int bufferlen = 76; uint8_t buffer[76] = { 0x45, 0x00, 0x00, 0x4c, 0x91, 0xc3, 0x40, 0x00, 0x40, 0x01, 0x24, 0xd0, 0xc0, 0xa8, 0x01, 0x66, 0xc0, 0xa8, 0x01, 0x64, 0x08, 0x00, 0x66, 0x3c, 0x91, 0xc2, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; int buffer2len = 76; int len; int cntr = 0; uint8_t buffer2[bufferlen]; struct pico_ip4 local = { .addr = long_be(0xc0a80164) }; struct pico_ip4 netmask = { .addr = long_be(0xffffff00) }; struct mock_device*mock; struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) buffer; printf("*********************** starting %s * \n", __func__); pico_stack_init(); mock = pico_mock_create(NULL); fail_if(mock == NULL, "No device created"); pico_ipv4_link_add(mock->dev, local, netmask); hdr->crc = 0; hdr->crc = short_be(pico_checksum(hdr, PICO_SIZE_IP4HDR)); pico_mock_network_write(mock, buffer, bufferlen); /* check if it is received */ pico_stack_tick(); pico_stack_tick(); pico_stack_tick(); pico_stack_tick(); pico_stack_tick(); pico_stack_tick(); len = pico_mock_network_read(mock, buffer2, buffer2len); /* inspect it */ while(cntr < len) { printf("0x%02x ", buffer2[cntr]); cntr++; if(cntr % 4 == 0) printf("\n"); } fail_unless(len == buffer2len, "ping reply lenght does not match, expected len: %d, got: %d", buffer2len, len); fail_unless(mock_ip_protocol(mock, buffer2, len) == 1); fail_unless(mock_icmp_type(mock, buffer2, len) == 0); fail_unless(mock_icmp_code(mock, buffer2, len) == 0); fail_unless(pico_checksum(buffer2 + 20, len - 20) == 0); } END_TEST START_TEST (test_icmp4_unreachable_send) { struct pico_ip4 local = { .addr = long_be(0x0a280064) }; struct pico_ip4 netmask = { .addr = long_be(0xffffff00) }; struct mock_device*mock; int len = 0; int bufferlen = 80; uint8_t buffer2[bufferlen]; uint8_t buffer[32] = { 0x45, 0x00, 0x00, 0x20, 0x91, 0xc0, 0x40, 0x00, 0x40, 0x11, 0x94, 0xb4, 0x0a, 0x28, 0x00, 0x05, 0x0a, 0x28, 0x00, 0x04, 0x15, 0xb3, 0x15, 0xb3, 0x00, 0x0c, 0x00, 0x00, 'e', 'l', 'l', 'o' }; /* fake packet with bad upper-layer-protocol */ uint8_t buffer3[20] = { 0x45, 0x00, 0x00, 0x14, 0x91, 0xc0, 0x40, 0x00, 0x40, 0xff, 0x94, 0xb4, 0x0a, 0x28, 0x00, 0x05, 0x0a, 0x28, 0x00, 0x04 }; struct pico_frame*f = PICO_ZALLOC(sizeof(struct pico_frame)); uint8_t nullbuf[8] = {}; printf("*********************** starting %s * \n", __func__); f->net_hdr = buffer; f->buffer = buffer; pico_stack_init(); mock = pico_mock_create(NULL); fail_if(mock == NULL, "No device created"); pico_ipv4_link_add(mock->dev, local, netmask); fail_if(pico_icmp4_dest_unreachable(f)); pico_stack_tick(); pico_stack_tick(); pico_stack_tick(); len = pico_mock_network_read(mock, buffer2, bufferlen); fail_unless(len == 56); fail_unless(mock_ip_protocol(mock, buffer2, len) == 1); fail_unless(mock_icmp_type(mock, buffer2, len) == 3); /* destination unreachable */ fail_unless(mock_icmp_code(mock, buffer2, len) == 1); /* host unreachable */ fail_unless(pico_checksum(buffer2 + 20, len - 20) == 0); fail_if(pico_icmp4_port_unreachable(f)); pico_stack_tick(); pico_stack_tick(); pico_stack_tick(); len = pico_mock_network_read(mock, buffer2, bufferlen); fail_unless(len == 56); fail_unless(mock_ip_protocol(mock, buffer2, len) == 1); fail_unless(mock_icmp_type(mock, buffer2, len) == 3); /* destination unreachable */ fail_unless(mock_icmp_code(mock, buffer2, len) == 3); /* port unreachable */ fail_unless(pico_checksum(buffer2 + 20, len - 20) == 0); fail_if(pico_icmp4_proto_unreachable(f)); pico_stack_tick(); pico_stack_tick(); pico_stack_tick(); len = pico_mock_network_read(mock, buffer2, bufferlen); fail_unless(len == 56); fail_unless(mock_ip_protocol(mock, buffer2, len) == 1); fail_unless(mock_icmp_type(mock, buffer2, len) == 3); /* destination unreachable */ fail_unless(mock_icmp_code(mock, buffer2, len) == 2); /* proto unreachable */ fail_unless(pico_checksum(buffer2 + 20, len - 20) == 0); fail_if(pico_icmp4_ttl_expired(f)); pico_stack_tick(); pico_stack_tick(); pico_stack_tick(); len = pico_mock_network_read(mock, buffer2, bufferlen); fail_unless(len == 56); fail_unless(mock_ip_protocol(mock, buffer2, len) == 1); fail_unless(mock_icmp_type(mock, buffer2, len) == 11); /* ttl expired */ fail_unless(mock_icmp_code(mock, buffer2, len) == 0); fail_unless(pico_checksum(buffer2 + 20, len - 20) == 0); f->net_hdr = buffer3; f->buffer = buffer3; fail_if(pico_icmp4_proto_unreachable(f)); pico_stack_tick(); pico_stack_tick(); pico_stack_tick(); len = pico_mock_network_read(mock, buffer2, bufferlen); fail_unless(len == 56); fail_unless(mock_ip_protocol(mock, buffer2, len) == 1); fail_unless(mock_icmp_type(mock, buffer2, len) == 3); /* destination unreachable */ fail_unless(mock_icmp_code(mock, buffer2, len) == 2); /* proto unreachable */ fail_unless(pico_checksum(buffer2 + 20, len - 20) == 0); #ifdef NOPE /* I don't know what was the intention, but the buffer is shorter than 48 bytes... */ fail_if(memcmp(buffer + 48, nullbuf, 8) == 0); /* there was no data */ #endif } END_TEST int icmp4_socket_unreach_status = 0; void icmp4_unreach_socket_cb(uint16_t ev, struct pico_socket *s) { if (ev == PICO_SOCK_EV_ERR) { icmp4_socket_unreach_status = 1; } } START_TEST (test_icmp4_unreachable_recv) { struct pico_ip4 local = { .addr = long_be(0x0a280064) }; struct pico_ip4 remote = { .addr = long_be(0x0a280065) }; struct pico_ip4 netmask = { .addr = long_be(0xffffff00) }; struct mock_device*mock; struct pico_socket*sock; uint16_t port = short_be(7777); /* put a host unreachable in the queue, run a few stack ticks */ uint8_t buffer[] = { 0x45, 0x00, 0x00, 0x20, 0x91, 0xc0, 0x40, 0x00, 0x40, 0x01, 0x94, 0xb4, 0x0a, 0x28, 0x00, 0x65, 0x0a, 0x28, 0x00, 0x64, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) buffer; printf("*********************** starting %s * \n", __func__); pico_stack_init(); mock = pico_mock_create(NULL); fail_if(mock == NULL, "No device created"); pico_ipv4_link_add(mock->dev, local, netmask); /* open a socket */ sock = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_TCP, &icmp4_unreach_socket_cb); fail_if(sock == NULL); fail_if(pico_socket_bind(sock, &local, &port)); pico_socket_connect(sock, &remote, port); pico_socket_write(sock, "fooo", 4); /* see if my callback was called with the proper code */ pico_stack_tick(); pico_stack_tick(); pico_stack_tick(); /* filling in the IP header and first 8 bytes */ hdr->crc = 0; hdr->crc = short_be(pico_checksum(hdr, PICO_SIZE_IP4HDR)); printf("read %d bytes\n", pico_mock_network_read(mock, buffer + 28, 28)); printf("wrote %d bytes\n", pico_mock_network_write(mock, buffer, 56)); pico_stack_tick(); pico_stack_tick(); pico_stack_tick(); fail_unless(icmp4_socket_unreach_status == 1); } END_TEST