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; }
int ipfilter(struct pico_frame *f) { struct filter_node temp; struct pico_ipv4_hdr *ipv4_hdr = (struct pico_ipv4_hdr *) f->net_hdr; struct pico_trans *trans; struct pico_icmp4_hdr *icmp_hdr; memset(&temp, 0u, sizeof(struct filter_node)); temp.fdev = f->dev; temp.out_addr = ipv4_hdr->dst.addr; temp.in_addr = ipv4_hdr->src.addr; if ((ipv4_hdr->proto == PICO_PROTO_TCP) || (ipv4_hdr->proto == PICO_PROTO_UDP)) { trans = (struct pico_trans *) f->transport_hdr; temp.out_port = short_be(trans->dport); temp.in_port = short_be(trans->sport); } else if(ipv4_hdr->proto == PICO_PROTO_ICMP4) { icmp_hdr = (struct pico_icmp4_hdr *) f->transport_hdr; if(icmp_hdr->type == PICO_ICMP_UNREACH && icmp_hdr->type == PICO_ICMP_UNREACH_FILTER_PROHIB) return 0; } temp.proto = ipv4_hdr->proto; temp.priority = f->priority; temp.tos = ipv4_hdr->tos; return ipfilter_apply_filter(f, &temp); }
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; }
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"); }
void pico_dns_fill_rr_suffix(struct pico_dns_answer_suffix *suf, uint16_t qtype, uint16_t qclass, uint32_t ttl, uint16_t rdlength) { suf->qtype = short_be(qtype); suf->qclass = short_be(qclass); suf->ttl = long_be(ttl); suf->rdlength = short_be(rdlength); }
void pico_dns_fill_header(struct pico_dns_header *hdr, uint16_t qdcount, uint16_t ancount) { /* hdr->id should be filled by caller */ if(qdcount > 0) { hdr->qr = PICO_DNS_QR_QUERY; hdr->aa = PICO_DNS_AA_NO_AUTHORITY; } else { hdr->qr = PICO_DNS_QR_RESPONSE; hdr->aa = PICO_DNS_AA_IS_AUTHORITY; } hdr->opcode = PICO_DNS_OPCODE_QUERY; hdr->tc = PICO_DNS_TC_NO_TRUNCATION; hdr->rd = PICO_DNS_RD_NO_DESIRE; hdr->ra = PICO_DNS_RA_NO_SUPPORT; hdr->z = 0; /* Z, AD, CD are 0 */ hdr->rcode = PICO_DNS_RCODE_NO_ERROR; hdr->qdcount = short_be(qdcount); hdr->ancount = short_be(ancount); hdr->nscount = short_be(0); hdr->arcount = short_be(0); }
static int pico_dns_client_query_prefix(struct pico_dns_prefix *pre) { uint16_t id = 0; uint8_t retry = 32; do { id = (uint16_t)(pico_rand() & 0xFFFFU); dns_dbg("DNS: generated id %u\n", id); } while (retry-- && pico_dns_client_idcheck(id)); if (!retry) return -1; pre->id = short_be(id); pre->qr = PICO_DNS_QR_QUERY; pre->opcode = PICO_DNS_OPCODE_QUERY; pre->aa = PICO_DNS_AA_NO_AUTHORITY; pre->tc = PICO_DNS_TC_NO_TRUNCATION; pre->rd = PICO_DNS_RD_IS_DESIRED; pre->ra = PICO_DNS_RA_NO_SUPPORT; pre->z = 0; pre->rcode = PICO_DNS_RCODE_NO_ERROR; pre->qdcount = short_be(1); pre->ancount = short_be(0); pre->nscount = short_be(0); pre->arcount = short_be(0); return 0; }
static int pico_dns_client_check_qsuffix(struct pico_dns_query_suffix *suf, struct pico_dns_query *q) { if (short_be(suf->qtype) != q->qtype || short_be(suf->qclass) != q->qclass) { dns_dbg("DNS ERROR: received qtype (%u) or qclass (%u) incorrect\n", short_be(suf->qtype), short_be(suf->qclass)); return -1; } return 0; }
void app_tftp(char *arg) { struct command_t *commands; struct note_t *note; struct pico_tftp_session *session; int is_server_enabled = 0; int filesize; family = IPV6_MODE ? PICO_PROTO_IPV6 : PICO_PROTO_IPV4; commands = parse_arguments(arg); while (commands) { if (toupper(commands->operation) != 'S') note = transfer_prepare(&session, commands->operation, commands->filename, &commands->server_address, family); switch (commands->operation) { case 'S': case 's': if (!is_server_enabled) { pico_tftp_listen(PICO_PROTO_IPV4, (commands->operation == 'S') ? tftp_listen_cb_opt : tftp_listen_cb); is_server_enabled = 1; } break; case 'T': filesize = get_filesize(commands->filename); if (filesize < 0) { fprintf(stderr, "TFTP: unable to read size of file %s\n", commands->filename); exit(3); } pico_tftp_set_option(session, PICO_TFTP_OPTION_FILE, filesize); start_tx(session, commands->filename, short_be(PICO_TFTP_PORT), cb_tftp_tx_opt, note); break; case 't': start_tx(session, commands->filename, short_be(PICO_TFTP_PORT), cb_tftp_tx, note); break; case 'R': pico_tftp_set_option(session, PICO_TFTP_OPTION_FILE, 0); start_rx(session, commands->filename, short_be(PICO_TFTP_PORT), cb_tftp_rx_opt, note); break; case 'r': start_rx(session, commands->filename, short_be(PICO_TFTP_PORT), cb_tftp_rx, note); } commands = commands->next; } }
static struct pico_dhcp_server_negotiation *pico_dhcp_server_add_negotiation(struct pico_device *dev, struct pico_dhcp_hdr *hdr) { struct pico_dhcp_server_negotiation *dhcpn = NULL; struct pico_dhcp_server_setting test = { 0 }; if (pico_dhcp_server_find_negotiation(hdr->xid)) return NULL; dhcpn = PICO_ZALLOC(sizeof(struct pico_dhcp_server_negotiation)); if (!dhcpn) { pico_err = PICO_ERR_ENOMEM; return NULL; } dhcpn->xid = hdr->xid; dhcpn->state = PICO_DHCP_STATE_DISCOVER; dhcpn->bcast = ((short_be(hdr->flags) & PICO_DHCP_FLAG_BROADCAST) != 0) ? (1) : (0); memcpy(dhcpn->hwaddr.addr, hdr->hwaddr, PICO_SIZE_ETH); test.dev = dev; dhcpn->dhcps = pico_tree_findKey(&DHCPSettings, &test); if (!dhcpn->dhcps) { dhcps_dbg("DHCP server WARNING: received DHCP message on unconfigured link %s\n", dev->name); PICO_FREE(dhcpn); return NULL; } dhcp_negotiation_set_ciaddr(dhcpn); pico_tree_insert(&DHCPNegotiations, dhcpn); return dhcpn; }
static int pico_dns_client_send(struct pico_dns_query *q) { uint16_t *paramID = PICO_ZALLOC(sizeof(uint16_t)); if (!paramID) { pico_err = PICO_ERR_ENOMEM; return -1; } dns_dbg("DNS: sending query to %08X\n", q->q_ns.ns.addr); if (!q->s) goto failure; if (pico_socket_connect(q->s, &q->q_ns.ns, short_be(PICO_DNS_NS_PORT)) < 0) goto failure; pico_socket_send(q->s, q->query, q->len); *paramID = q->id; pico_timer_add(PICO_DNS_CLIENT_RETRANS, pico_dns_client_retransmission, paramID); return 0; failure: PICO_FREE(paramID); return -1; }
static char *pico_dns_client_seek_suffix(char *suf, struct pico_dns_header *pre, struct pico_dns_query *q) { struct pico_dns_answer_suffix *asuffix = NULL; uint16_t comp = 0, compression = 0; uint16_t i = 0; if (!suf) return NULL; while (i++ < short_be(pre->ancount)) { comp = short_from(suf); compression = short_be(comp); switch (compression >> 14) { case PICO_DNS_POINTER: while (compression >> 14 == PICO_DNS_POINTER) { dns_dbg("DNS: pointer\n"); suf += sizeof(uint16_t); comp = short_from(suf); compression = short_be(comp); } break; case PICO_DNS_LABEL: dns_dbg("DNS: label\n"); suf = pico_dns_client_seek(suf); break; default: dns_dbg("DNS ERROR: incorrect compression (%u) value\n", compression); return NULL; } asuffix = (struct pico_dns_answer_suffix *)suf; if (!asuffix) break; if (pico_dns_client_check_asuffix(asuffix, q) < 0) { suf += (sizeof(struct pico_dns_answer_suffix) + short_be(asuffix->rdlength)); continue; } return suf; } return NULL; }
END_TEST START_TEST(tc_pico_mld_process_in) { struct mld_parameters *p; struct pico_device *dev = pico_null_create("dummy3"); struct pico_ipv6_link *link; struct pico_tree *filter = PICO_ZALLOC(sizeof(struct pico_tree)); int i,j, _i,_j,result; struct pico_ipv6_mcast_group g; struct mldv2_report *report; //Building example frame p = PICO_ZALLOC(sizeof(struct mld_parameters)); pico_string_to_ipv6("AAAA::1", p->mcast_link.addr); pico_string_to_ipv6("FF00::e007:707", p->mcast_group.addr); //no link fail_if(pico_mld_generate_report(p) != -1); link = pico_ipv6_link_add(dev, p->mcast_link, p->mcast_link); pico_string_to_ipv6("AAAA::1", p->mcast_group.addr); fail_if(pico_mld_generate_report(p) != -1); pico_string_to_ipv6("FF00::e007:707", p->mcast_group.addr); link->mcast_compatibility = PICO_MLDV1; g.mcast_addr = p->mcast_group; g.MCASTSources.root = &LEAF; g.MCASTSources.compare = mcast_sources_cmp_ipv6; // No mcastsources tree link->mcast_compatibility = PICO_MLDV2; fail_if(pico_mld_generate_report(p) != -1); pico_tree_insert(link->MCASTGroups, &g); pico_tree_insert(&MLDParameters, p); link->mcast_compatibility = 99; fail_if(pico_mld_generate_report(p) != -1); link->mcast_compatibility = PICO_MLDV1; fail_if(pico_mld_generate_report(p) != 0); link->mcast_compatibility = PICO_MLDV2; for(_j =0; _j<3; _j++) { //FILTER (_j == 2) ? (result = -1) : (result = 0); for(_i=0; _i<3; _i++) { //FILTER if(_i == 2) result = -1; for(i = 0; i<3; i++) { //STATES for(j = 0; j<6; j++) { //EVENTS p->MCASTFilter = &_MCASTFilter; p->filter_mode = _i; g.filter_mode = _j; if(p->event == MLD_EVENT_DELETE_GROUP || p->event == MLD_EVENT_QUERY_RECV) p->event++; fail_if(pico_mld_generate_report(p) != result); p->state = i; p->event = j; if(result != -1 && p->f) {//in some combinations, no frame is created report = p->f->transport_hdr + MLD_ROUTER_ALERT_LEN; report->crc = short_be(pico_icmp6_checksum(p->f)); fail_if(pico_mld_process_in(p->f) != 0); } } } } } }
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; }
uint8_t pico_dhcp_opt_maxmsgsize(void *ptr, uint16_t size) { struct pico_dhcp_opt *opt = (struct pico_dhcp_opt *)ptr; /* option: maximum message size */ opt->code = PICO_DHCP_OPT_MAXMSGSIZE; opt->len = PICO_DHCP_OPTLEN_MAXMSGSIZE - PICO_DHCP_OPTLEN_HDR; opt->ext.max_msg_size.size = short_be(size); return PICO_DHCP_OPTLEN_MAXMSGSIZE; }
static int pico_dns_client_check_asuffix(struct pico_dns_answer_suffix *suf, struct pico_dns_query *q) { if (!suf) { pico_err = PICO_ERR_EINVAL; return -1; } if (short_be(suf->qtype) != q->qtype || short_be(suf->qclass) != q->qclass) { dns_dbg("DNS WARNING: received qtype (%u) or qclass (%u) incorrect\n", short_be(suf->qtype), short_be(suf->qclass)); return -1; } if (long_be(suf->ttl) > PICO_DNS_MAX_TTL) { dns_dbg("DNS WARNING: received TTL (%u) > MAX (%u)\n", short_be(suf->ttl), PICO_DNS_MAX_TTL); return -1; } return 0; }
static int pico_ipv4_checksum(struct pico_frame *f) { struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr; if (!hdr) return -1; hdr->crc = 0; hdr->crc = short_be(pico_checksum(hdr, f->net_len)); return 0; }
static uint8_t pico_icmp4_send_echo(struct pico_icmp4_ping_cookie *cookie) { struct pico_frame *echo = pico_proto_ipv4.alloc(&pico_proto_ipv4, (uint16_t)(PICO_ICMPHDR_UN_SIZE + cookie->size)); struct pico_icmp4_hdr *hdr; hdr = (struct pico_icmp4_hdr *) echo->transport_hdr; hdr->type = PICO_ICMP_ECHO; hdr->code = 0; hdr->hun.ih_idseq.idseq_id = short_be(cookie->id); hdr->hun.ih_idseq.idseq_seq = short_be(cookie->seq); echo->transport_len = (uint16_t)(PICO_ICMPHDR_UN_SIZE + cookie->size); echo->payload = echo->transport_hdr + PICO_ICMPHDR_UN_SIZE; echo->payload_len = cookie->size; /* XXX: Fill payload */ pico_icmp4_checksum(echo); pico_ipv4_frame_push(echo, &cookie->dst, PICO_PROTO_ICMP4); return 0; }
static int pico_icmp4_checksum(struct pico_frame *f) { struct pico_icmp4_hdr *hdr = (struct pico_icmp4_hdr *) f->transport_hdr; if (!hdr) { pico_err = PICO_ERR_EINVAL; return -1; } hdr->crc = 0; hdr->crc = short_be(pico_checksum(hdr, f->transport_len)); return 0; }
int pico_socket_sendto(struct pico_socket *s, const void *buf, const int len, void *dst, uint16_t remote_port) { const struct pico_tftp_hdr *h = (const struct pico_tftp_hdr *)buf; fail_if(s != &example_socket); fail_if(short_be(h->opcode) != expected_opcode); fail_if(len <= 0); (void)dst; (void)remote_port; called_sendto++; return 0; }
static int pico_dns_client_check_header(struct pico_dns_header *pre) { if (pre->qr != PICO_DNS_QR_RESPONSE || pre->opcode != PICO_DNS_OPCODE_QUERY || pre->rcode != PICO_DNS_RCODE_NO_ERROR) { dns_dbg("DNS ERROR: OPCODE %d | TC %d | RCODE %d\n", pre->opcode, pre->tc, pre->rcode); return -1; } if (short_be(pre->ancount) < 1) { dns_dbg("DNS ERROR: ancount < 1\n"); return -1; } return 0; }
static inline int pico_ipv4_crc_check(struct pico_frame *f) { uint16_t checksum_invalid = 1; struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr; checksum_invalid = short_be(pico_checksum(hdr, f->net_len)); if (checksum_invalid) { dbg("IP: checksum failed!\n"); pico_frame_discard(f); return 0; } return 1; }
/* * TCP code. For TCP, a socket is created and listens. * A callback occurs when the packet is received. The callback handles the different types of TCP events, * including the handshake protocol. * Based off the sample tcpecho app provided in the picotcp library. */ void cb_tcpecho(uint16_t ev, struct pico_socket *s) { int r = 0; ZF_LOGD("tcpecho> wakeup ev=%u\n", ev); if (ev & PICO_SOCK_EV_RD) { char buf[100]; r = pico_socket_read(s, buf, 100); pico_socket_write(s, buf, r); // Immediately echo back a response } if (ev & PICO_SOCK_EV_CONN) { uint32_t ka_val = 0; struct pico_socket *sock_peer; struct pico_ip4 orig = {0}; uint16_t port = 0; char peer[30] = {0}; int yes = 1; sock_peer = pico_socket_accept(s, &orig, &port); pico_ipv4_to_string(peer, orig.addr); ZF_LOGD("Connection established with %s:%d.\n", peer, short_be(port)); pico_socket_setoption(sock_peer, PICO_TCP_NODELAY, &yes); /* Set keepalive options - from picoTCP documentation */ ka_val = 5; pico_socket_setoption(sock_peer, PICO_SOCKET_OPT_KEEPCNT, &ka_val); ka_val = 30000; pico_socket_setoption(sock_peer, PICO_SOCKET_OPT_KEEPIDLE, &ka_val); ka_val = 5000; pico_socket_setoption(sock_peer, PICO_SOCKET_OPT_KEEPINTVL, &ka_val); } if (ev & PICO_SOCK_EV_FIN) { ZF_LOGD("Socket closed. Exit normally. \n"); } if (ev & PICO_SOCK_EV_ERR) { ZF_LOGD("Socket error received: %s. Bailing out.\n", strerror(pico_err)); } if (ev & PICO_SOCK_EV_CLOSE) { ZF_LOGD("Socket received close from peer.\n"); pico_socket_shutdown(s, PICO_SHUT_WR); } if (ev & PICO_SOCK_EV_WR) { ZF_LOGD("TCP Write ack\n"); } }
static void ping_recv_reply(struct pico_frame *f) { struct pico_icmp4_ping_cookie test, *cookie; struct pico_icmp4_hdr *hdr = (struct pico_icmp4_hdr *) f->transport_hdr; test.id = short_be(hdr->hun.ih_idseq.idseq_id ); test.seq = short_be(hdr->hun.ih_idseq.idseq_seq); cookie = pico_tree_findKey(&Pings, &test); if (cookie) { struct pico_icmp4_stats stats; cookie->err = PICO_PING_ERR_REPLIED; stats.dst = cookie->dst; stats.seq = cookie->seq; stats.size = cookie->size; stats.time = pico_tick - cookie->timestamp; stats.err = cookie->err; stats.ttl = ((struct pico_ipv4_hdr *)f->net_hdr)->ttl; if(cookie->cb != NULL) cookie->cb(&stats); } else { dbg("Reply for seq=%d, not found.\n", test.seq); } }
static inline void pico_dns_client_hdr_ntoh(struct dns_message_hdr *hdr) { hdr->id = short_be(hdr->id); hdr->flags = short_be(hdr->flags); hdr->qdcount = short_be(hdr->qdcount); hdr->ancount = short_be(hdr->ancount); hdr->nscount = short_be(hdr->nscount); hdr->arcount = short_be(hdr->arcount); }
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"); }
static int pico_dns_client_user_callback(struct pico_dns_answer_suffix *asuffix, struct pico_dns_query *q) { uint32_t ip = 0; char *str = NULL; char *rdata = (char *) asuffix + sizeof(struct pico_dns_answer_suffix); switch (q->qtype) { case PICO_DNS_TYPE_A: ip = long_from(rdata); str = PICO_ZALLOC(PICO_DNS_IPV4_ADDR_LEN); pico_ipv4_to_string(str, ip); break; #ifdef PICO_SUPPORT_IPV6 case PICO_DNS_TYPE_AAAA: { struct pico_ip6 ip6; memcpy(&ip6.addr, rdata, sizeof(struct pico_ip6)); str = PICO_ZALLOC(PICO_DNS_IPV6_ADDR_LEN); pico_ipv6_to_string(str, ip6.addr); break; } #endif case PICO_DNS_TYPE_PTR: pico_dns_client_answer_domain(rdata); str = PICO_ZALLOC((size_t)(asuffix->rdlength - PICO_DNS_LABEL_INITIAL)); if (!str) { pico_err = PICO_ERR_ENOMEM; return -1; } memcpy(str, rdata + PICO_DNS_LABEL_INITIAL, short_be(asuffix->rdlength) - PICO_DNS_LABEL_INITIAL); break; default: dns_dbg("DNS ERROR: incorrect qtype (%u)\n", q->qtype); break; } if (q->retrans) { q->callback(str, q->arg); q->retrans = 0; PICO_FREE(str); pico_dns_client_del_query(q->id); } return 0; }
void tftp_listen_cb(union pico_address *addr, uint16_t port, uint16_t opcode, char *filename, int32_t len) { struct note_t *note; struct pico_tftp_session *session; printf("TFTP listen callback (BASIC) from remote port %" PRIu16 ".\n", short_be(port)); if (opcode == PICO_TFTP_RRQ) { printf("Received TFTP get request for %s\n", filename); note = transfer_prepare(&session, 't', filename, addr, family); start_tx(session, filename, port, cb_tftp_tx, note); } else if (opcode == PICO_TFTP_WRQ) { printf("Received TFTP put request for %s\n", filename); note = transfer_prepare(&session, 'r', filename, addr, family); start_rx(session, filename, port, cb_tftp_rx, note); } }
static void pico_dns_client_callback(uint16_t ev, struct pico_socket *s) { struct pico_dns_header *header = NULL; char *domain; struct pico_dns_query_suffix *qsuffix = NULL; struct pico_dns_answer_suffix *asuffix = NULL; struct pico_dns_query *q = NULL; char *p_asuffix = NULL; char msg[PICO_DNS_MAX_RESPONSE_LEN] = { 0 }; if (ev == PICO_SOCK_EV_ERR) { dns_dbg("DNS: socket error received\n"); return; } if (ev & PICO_SOCK_EV_RD) { if (pico_socket_read(s, msg, PICO_DNS_MAX_RESPONSE_LEN) <= 0) return; } header = (struct pico_dns_header *)msg; domain = (char *)header + sizeof(struct pico_dns_header); qsuffix = (struct pico_dns_query_suffix *)pico_dns_client_seek(domain); /* valid asuffix is determined dynamically later on */ if (pico_dns_client_check_header(header) < 0) return; q = pico_dns_client_find_query(short_be(header->id)); if (!q) return; if (pico_dns_client_check_qsuffix(qsuffix, q) < 0) return; p_asuffix = (char *)qsuffix + sizeof(struct pico_dns_query_suffix); p_asuffix = pico_dns_client_seek_suffix(p_asuffix, header, q); if (!p_asuffix) return; asuffix = (struct pico_dns_answer_suffix *)p_asuffix; pico_dns_client_user_callback(asuffix, q); return; }
void tftp_listen_cb_opt(union pico_address *addr, uint16_t port, uint16_t opcode, char *filename, int32_t len) { struct note_t *note; struct pico_tftp_session *session; int options; uint8_t timeout; int32_t filesize; int ret; printf("TFTP listen callback (OPTIONS) from remote port %" PRIu16 ".\n", short_be(port)); /* declare the options we want to support */ ret = pico_tftp_parse_request_args(filename, len, &options, &timeout, &filesize); if (ret) pico_tftp_reject_request(addr, port, TFTP_ERR_EOPT, "Malformed request"); if (opcode == PICO_TFTP_RRQ) { printf("Received TFTP get request for %s\n", filename); note = transfer_prepare(&session, 'T', filename, addr, family); if (options & PICO_TFTP_OPTION_TIME) pico_tftp_set_option(session, PICO_TFTP_OPTION_TIME, timeout); if (options & PICO_TFTP_OPTION_FILE) { ret = get_filesize(filename); if (ret < 0) { pico_tftp_reject_request(addr, port, TFTP_ERR_ENOENT, "File not found"); return; } pico_tftp_set_option(session, PICO_TFTP_OPTION_FILE, ret); } start_tx(session, filename, port, cb_tftp_tx_opt, note); } else { /* opcode == PICO_TFTP_WRQ */ printf("Received TFTP put request for %s\n", filename); note = transfer_prepare(&session, 'R', filename, addr, family); if (options & PICO_TFTP_OPTION_TIME) pico_tftp_set_option(session, PICO_TFTP_OPTION_TIME, timeout); if (options & PICO_TFTP_OPTION_FILE) pico_tftp_set_option(session, PICO_TFTP_OPTION_FILE, filesize); start_rx(session, filename, port, cb_tftp_rx_opt, note); } }