samples/net: DNS client application
This sample code shows how to write a DNS client application. Only client functionality is implemented in this sample. The code is self-documented. Read the README file for more information about the network setup. See https://tools.ietf.org/html/rfc1035 for more information about the DNS protocol. Origin: Original Jira: ZEP-500 Jira: ZEP-501 Change-Id: Ibcfa4e392143fdc2258971304d5296d70c1c9423 Signed-off-by: Flavio Santes <flavio.santes@intel.com>
This commit is contained in:
parent
58f88179ef
commit
e240f84c75
13 changed files with 1570 additions and 0 deletions
21
samples/net/dns_client/Makefile
Normal file
21
samples/net/dns_client/Makefile
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016 Intel Corporation
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
KERNEL_TYPE = nano
|
||||||
|
BOARD = galileo
|
||||||
|
CONF_FILE = prj_galileo.conf
|
||||||
|
|
||||||
|
include $(ZEPHYR_BASE)/Makefile.inc
|
102
samples/net/dns_client/README
Normal file
102
samples/net/dns_client/README
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
DNS Client Application
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
------------
|
||||||
|
|
||||||
|
* Ethernet LAN for testing purposes.
|
||||||
|
|
||||||
|
* Galileo Gen 2 Development Board.
|
||||||
|
|
||||||
|
* USB-UART cable: CH340, FTDI 6-pin or equivalent for debugging.
|
||||||
|
|
||||||
|
* dnsmasq application. The dnsmasq version used in this sample is:
|
||||||
|
|
||||||
|
dnsmasq -v
|
||||||
|
Dnsmasq version 2.75 Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
|
Building instructions
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
* Read src/main.c, change the IP addresses according to the LAN
|
||||||
|
environment.
|
||||||
|
|
||||||
|
* make pristine && make are enough to build this sample.
|
||||||
|
|
||||||
|
* Follow the steps indicated here:
|
||||||
|
|
||||||
|
https://www.zephyrproject.org/doc/board/galileo.html
|
||||||
|
|
||||||
|
to load the binary into the Galileo Dev Board.
|
||||||
|
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----
|
||||||
|
|
||||||
|
* Open a terminal window and type:
|
||||||
|
|
||||||
|
dnsmasq -d
|
||||||
|
|
||||||
|
* Connect the USB-UART cable to the Galileo. Open a terminal and run:
|
||||||
|
|
||||||
|
screen /dev/ttyUSB0 115200
|
||||||
|
|
||||||
|
* Connect Galileo to the LAN, Turn on the board.
|
||||||
|
|
||||||
|
* The screen terminal window will show:
|
||||||
|
|
||||||
|
WARNING: no console will be available to OS
|
||||||
|
error: no suitable video mode found.
|
||||||
|
|
||||||
|
-----------------------------------------
|
||||||
|
Domain name: not_a_real_domain_name
|
||||||
|
[fiber:82] DNS Create Query: 0, ID: 1
|
||||||
|
[fiber:85] TX: 0
|
||||||
|
[fiber:88] RX: -5
|
||||||
|
|
||||||
|
-----------------------------------------
|
||||||
|
Domain name: oops!
|
||||||
|
[fiber:82] DNS Create Query: 0, ID: 2
|
||||||
|
[fiber:85] TX: 0
|
||||||
|
[fiber:88] RX: 0
|
||||||
|
[fiber:95] DNS response: 2
|
||||||
|
|
||||||
|
-----------------------------------------
|
||||||
|
Domain name: zephyrproject.org
|
||||||
|
[fiber:82] DNS Create Query: 0, ID: 3
|
||||||
|
[fiber:85] TX: 0
|
||||||
|
[fiber:88] RX: 0
|
||||||
|
|
||||||
|
****** DNS ANSWER: 0 ******
|
||||||
|
Response: IP address Size: 4: 140 211 169 8
|
||||||
|
[fiber:95] DNS response: 0
|
||||||
|
|
||||||
|
-----------------------------------------
|
||||||
|
Domain name: www.google.com
|
||||||
|
[fiber:82] DNS Create Query: 0, ID: 4
|
||||||
|
[fiber:85] TX: 0
|
||||||
|
[fiber:88] RX: 0
|
||||||
|
|
||||||
|
****** DNS ANSWER: 0 ******
|
||||||
|
Response: IP address Size: 4: 216 58 192 4
|
||||||
|
[fiber:95] DNS response: 0
|
||||||
|
|
||||||
|
-----------------------------------------
|
||||||
|
Domain name: mail.yahoo.com
|
||||||
|
[fiber:82] DNS Create Query: 0, ID: 5
|
||||||
|
[fiber:85] TX: 0
|
||||||
|
[fiber:88] RX: 0
|
||||||
|
|
||||||
|
****** DNS ANSWER: 0 ******
|
||||||
|
Response: CNAME NO IP address Size: 8: 5 108 111 103 105 110 192 17
|
||||||
|
CNAME: login.yahoo.com
|
||||||
|
|
||||||
|
****** DNS ANSWER: 1 ******
|
||||||
|
Response: CNAME NO IP address Size: 35: 9 102 111 45 100 115 45 97 116 115 6 109 101 109 98 101 114 3 103 48 50 8 121 97 104 111 111 100 110 115 3 110 101 116 0
|
||||||
|
CNAME: fo-ds-ats.member.g02.yahoodns.net
|
||||||
|
|
||||||
|
****** DNS ANSWER: 2 ******
|
||||||
|
Response: IP address Size: 4: 98 136 189 41
|
||||||
|
[fiber:95] DNS response: 0
|
||||||
|
|
||||||
|
-----------------------------------------
|
||||||
|
Bye!
|
17
samples/net/dns_client/prj_galileo.conf
Normal file
17
samples/net/dns_client/prj_galileo.conf
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
CONFIG_STDOUT_CONSOLE=y
|
||||||
|
|
||||||
|
CONFIG_NETWORKING=y
|
||||||
|
CONFIG_ETHERNET=y
|
||||||
|
CONFIG_ETH_DW=y
|
||||||
|
|
||||||
|
CONFIG_NANO_TIMEOUTS=y
|
||||||
|
CONFIG_NETWORKING_WITH_TCP=y
|
||||||
|
CONFIG_NETWORKING_WITH_IPV4=y
|
||||||
|
CONFIG_NETWORKING_IPV6_NO_ND=y
|
||||||
|
|
||||||
|
CONFIG_IP_BUF_RX_SIZE=4
|
||||||
|
CONFIG_IP_BUF_TX_SIZE=4
|
||||||
|
|
||||||
|
#CONFIG_NETWORKING_WITH_LOGGING=y
|
||||||
|
#CONFIG_NETWORK_IP_STACK_DEBUG_NET_BUF=y
|
||||||
|
#CONFIG_NET_BUF_DEBUG=y
|
25
samples/net/dns_client/src/Makefile
Normal file
25
samples/net/dns_client/src/Makefile
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016 Intel Corporation
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
ccflags-y +=-I${ZEPHYR_BASE}/net/ip/contiki
|
||||||
|
ccflags-y +=-I${ZEPHYR_BASE}/net/ip/contiki/os/lib
|
||||||
|
ccflags-y +=-I${ZEPHYR_BASE}/net/ip/contiki/os
|
||||||
|
ccflags-y +=-I${ZEPHYR_BASE}/net/ip
|
||||||
|
|
||||||
|
obj-y += dns_pack.o
|
||||||
|
obj-y += netz.o
|
||||||
|
obj-y += dns_utils.o
|
||||||
|
obj-y += main.o
|
19
samples/net/dns_client/src/app_buf.h
Normal file
19
samples/net/dns_client/src/app_buf.h
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef _APP_BUF_H_
|
||||||
|
#define _APP_BUF_H_
|
||||||
|
|
||||||
|
#include <zephyr.h> /* for __deprecated */
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
struct __deprecated app_buf_t;
|
||||||
|
|
||||||
|
struct app_buf_t {
|
||||||
|
uint8_t *buf;
|
||||||
|
size_t size;
|
||||||
|
size_t length;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define APP_BUF_INIT(_buf, _size, _length) {.buf = _buf, .size = _size,\
|
||||||
|
.length = _length}
|
||||||
|
|
||||||
|
#endif
|
280
samples/net/dns_client/src/dns_pack.c
Normal file
280
samples/net/dns_client/src/dns_pack.c
Normal file
|
@ -0,0 +1,280 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Intel Corporation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dns_pack.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int dns_msg_pack_qname(int *len, uint8_t *buf, int size, char *domain_name)
|
||||||
|
{
|
||||||
|
int lb_index;
|
||||||
|
int lb_start;
|
||||||
|
int lb_size;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
lb_start = 0;
|
||||||
|
lb_index = 1;
|
||||||
|
lb_size = 0;
|
||||||
|
|
||||||
|
/* traverse the domain name str, including the null-terminator :) */
|
||||||
|
for (i = 0; i < strlen(domain_name) + 1; i++) {
|
||||||
|
if (lb_index >= size) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (domain_name[i]) {
|
||||||
|
default:
|
||||||
|
buf[lb_index] = domain_name[i];
|
||||||
|
lb_size += 1;
|
||||||
|
break;
|
||||||
|
case '.':
|
||||||
|
buf[lb_start] = lb_size;
|
||||||
|
lb_size = 0;
|
||||||
|
lb_start = lb_index;
|
||||||
|
break;
|
||||||
|
case '\0':
|
||||||
|
buf[lb_start] = lb_size;
|
||||||
|
buf[lb_index] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lb_index += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*len = lb_index;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dns_unpack_answer(struct dns_msg_t *dns_msg, int dname_ptr)
|
||||||
|
{
|
||||||
|
uint8_t *answer;
|
||||||
|
int buf_size;
|
||||||
|
int ptr;
|
||||||
|
|
||||||
|
answer = dns_msg->msg + dns_msg->answer_offset;
|
||||||
|
|
||||||
|
/* See RFC-1035 to find out why 63 */
|
||||||
|
if (answer[0] < 63) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Recovery of the pointer value */
|
||||||
|
ptr = (((answer[0] & 63) << 8) + answer[1]);
|
||||||
|
if (ptr != dname_ptr) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need to be sure this buffer has enough space
|
||||||
|
* to parse the answer.
|
||||||
|
*
|
||||||
|
* size: dname_size + type + class + ttl + rdlength + rdata
|
||||||
|
* 2 + 2 + 2 + 4 + 2 + ?
|
||||||
|
*
|
||||||
|
* So, answer size >= 12
|
||||||
|
*
|
||||||
|
* See RFC-1035 4.1.3. Resource record format
|
||||||
|
*/
|
||||||
|
buf_size = dns_msg->msg_size - dns_msg->answer_offset;
|
||||||
|
if (buf_size < 12) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only answers of type Internet.
|
||||||
|
* Here we use 2 as an offset because a ptr uses only 2 bytes.
|
||||||
|
*/
|
||||||
|
if (dns_answer_class(2, answer) != DNS_CLASS_IN) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (dns_response_type(2, answer)) {
|
||||||
|
case DNS_RR_TYPE_A:
|
||||||
|
case DNS_RR_TYPE_AAAA:
|
||||||
|
dns_msg->response_type = DNS_RESPONSE_IP;
|
||||||
|
dns_msg->response_position = dns_msg->answer_offset + 12;
|
||||||
|
dns_msg->response_length = dns_answer_rdlength(2, answer);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case DNS_RR_TYPE_CNAME:
|
||||||
|
|
||||||
|
dns_msg->response_type = DNS_RESPONSE_CNAME_NO_IP;
|
||||||
|
dns_msg->response_position = dns_msg->answer_offset + 12;
|
||||||
|
dns_msg->response_length = dns_answer_rdlength(2, answer);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* malformed dns answer */
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dns_unpack_response_header(struct dns_msg_t *msg, int src_id)
|
||||||
|
{
|
||||||
|
uint8_t *dns_header;
|
||||||
|
int size;
|
||||||
|
int qdcount;
|
||||||
|
int ancount;
|
||||||
|
|
||||||
|
dns_header = msg->msg;
|
||||||
|
size = msg->msg_size;
|
||||||
|
|
||||||
|
if (size < DNS_MSG_HEADER_SIZE) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dns_header_id(dns_header) != src_id) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dns_header_qr(dns_header) != DNS_RESPONSE) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dns_header_opcode(dns_header) != DNS_QUERY) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dns_header_z(dns_header) != 0) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (dns_header_rcode(dns_header)) {
|
||||||
|
case DNS_HEADER_NOERROR:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return dns_header_rcode(dns_header);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
qdcount = dns_header_qdcount(dns_header);
|
||||||
|
ancount = dns_header_ancount(dns_header);
|
||||||
|
if (qdcount < 1 || ancount < 1) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dns_msg_pack_query_header(uint8_t *buf, int size, uint16_t id)
|
||||||
|
{
|
||||||
|
if (size < DNS_MSG_HEADER_SIZE) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(uint16_t *)(buf + 0) = z_swap2(id);
|
||||||
|
|
||||||
|
/* RD = 1, TC = 0, AA = 0, Opcode = 0, QR = 0 <-> 0x01 (1B)
|
||||||
|
* RCode = 0, Z = 0, RA = 0 <-> 0x00 (1B)
|
||||||
|
*
|
||||||
|
* QDCOUNT = 1 <-> 0x0001 (2B)
|
||||||
|
*/
|
||||||
|
|
||||||
|
*(uint32_t *)(buf + 2) = 0x01000001;
|
||||||
|
*(uint32_t *)(buf + 6) = 0;
|
||||||
|
*(uint16_t *)(buf + 10) = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dns_msg_pack_query(struct app_buf_t *buf, char *domain_name,
|
||||||
|
uint16_t id, enum dns_rr_type qtype)
|
||||||
|
{
|
||||||
|
int qname_len;
|
||||||
|
int offset;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = dns_msg_pack_query_header(buf->buf, buf->size, id);
|
||||||
|
if (rc != 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = DNS_MSG_HEADER_SIZE;
|
||||||
|
|
||||||
|
rc = dns_msg_pack_qname(&qname_len, buf->buf + offset,
|
||||||
|
buf->size - offset, domain_name);
|
||||||
|
if (rc != 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset += qname_len;
|
||||||
|
|
||||||
|
/* 4Bytes required: QType: (2B), QClass (2B) */
|
||||||
|
if (offset + 4 > buf->size) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
/* QType */
|
||||||
|
*(uint16_t *)(buf->buf + offset + 0) = z_swap2(qtype);
|
||||||
|
/* QClass */
|
||||||
|
*(uint16_t *)(buf->buf + offset + 2) = z_swap2(DNS_CLASS_IN);
|
||||||
|
|
||||||
|
buf->length = offset + 4;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dns_find_null(int *qname_size, uint8_t *buf, int size)
|
||||||
|
{
|
||||||
|
*qname_size = 0;
|
||||||
|
while (*qname_size < size) {
|
||||||
|
if (buf[(*qname_size)++] == 0x00) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dns_unpack_response_query(struct dns_msg_t *dns_msg)
|
||||||
|
{
|
||||||
|
uint8_t *dns_query;
|
||||||
|
int remaining_size;
|
||||||
|
int qname_size;
|
||||||
|
int offset;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
dns_msg->query_offset = DNS_MSG_HEADER_SIZE;
|
||||||
|
dns_query = dns_msg->msg + dns_msg->query_offset;
|
||||||
|
remaining_size = dns_msg->msg_size - dns_msg->query_offset;
|
||||||
|
|
||||||
|
rc = dns_find_null(&qname_size, dns_query, remaining_size);
|
||||||
|
if (rc != 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* header already parsed + qname size */
|
||||||
|
offset = dns_msg->query_offset + qname_size;
|
||||||
|
/* 4 bytes more for qtype and qclass */
|
||||||
|
offset += 4;
|
||||||
|
if (offset > dns_msg->msg_size) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dns_query_qtype(dns_query + qname_size) != DNS_RR_TYPE_A &&
|
||||||
|
dns_query_qtype(dns_query + qname_size) != DNS_RR_TYPE_AAAA) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dns_query_qclass(dns_query + qname_size) != DNS_CLASS_IN) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dns_msg->answer_offset = dns_msg->query_offset + qname_size + 4;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
332
samples/net/dns_client/src/dns_pack.h
Normal file
332
samples/net/dns_client/src/dns_pack.h
Normal file
|
@ -0,0 +1,332 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Intel Corporation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _DNS_PACK_H_
|
||||||
|
#define _DNS_PACK_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <app_buf.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief dns_msg_t
|
||||||
|
*
|
||||||
|
* @details Structure that points to the buffer containing the
|
||||||
|
* DNS message. It also contains some decodified
|
||||||
|
* message's properties that can not be recovered easily:
|
||||||
|
*
|
||||||
|
* - cname_offset
|
||||||
|
*
|
||||||
|
* - query_offset
|
||||||
|
*
|
||||||
|
* - answer_offset:
|
||||||
|
*
|
||||||
|
* - response_type
|
||||||
|
* It indicates the response's content type. It could be
|
||||||
|
* an IP address, a CNAME with IP (two answers), a CNAME
|
||||||
|
* with no IP address. See enum dns_response_type for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* - response_position: this is an offset. It holds the
|
||||||
|
* starting byte of the field containing the desired
|
||||||
|
* info. For example an IPv4 address.
|
||||||
|
*
|
||||||
|
* - response_length: this is an offset. It holds the
|
||||||
|
* response's length.
|
||||||
|
*/
|
||||||
|
struct dns_msg_t {
|
||||||
|
uint8_t *msg;
|
||||||
|
size_t msg_size;
|
||||||
|
|
||||||
|
int response_type;
|
||||||
|
int response_position;
|
||||||
|
int response_length;
|
||||||
|
|
||||||
|
int cname_offset;
|
||||||
|
int query_offset;
|
||||||
|
int answer_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DNS_MSG_INIT(b, s) {.msg = b, .msg_size = s, \
|
||||||
|
.response_type = -EINVAL}
|
||||||
|
|
||||||
|
|
||||||
|
enum dns_rr_type {
|
||||||
|
DNS_RR_TYPE_INVALID = 0,
|
||||||
|
DNS_RR_TYPE_A = 1, /* IPv4 */
|
||||||
|
DNS_RR_TYPE_CNAME = 5, /* CNAME */
|
||||||
|
DNS_RR_TYPE_AAAA = 28 /* IPv6 */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum dns_response_type {
|
||||||
|
DNS_RESPONSE_INVALID = -EINVAL,
|
||||||
|
DNS_RESPONSE_IP,
|
||||||
|
DNS_RESPONSE_CNAME_WITH_IP,
|
||||||
|
DNS_RESPONSE_CNAME_NO_IP
|
||||||
|
};
|
||||||
|
|
||||||
|
enum dns_class {
|
||||||
|
DNS_CLASS_INVALID = 0,
|
||||||
|
DNS_CLASS_IN,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum dns_msg_type {
|
||||||
|
DNS_QUERY = 0,
|
||||||
|
DNS_RESPONSE
|
||||||
|
};
|
||||||
|
|
||||||
|
enum dns_header_rcode {
|
||||||
|
DNS_HEADER_NOERROR = 0,
|
||||||
|
DNS_HEADER_FORMATERROR,
|
||||||
|
DNS_HEADER_SERVERFAILURE,
|
||||||
|
DNS_HEADER_NAMEERROR,
|
||||||
|
DNS_HEADER_NOTIMPLEMENTED,
|
||||||
|
DNS_HEADER_REFUSED
|
||||||
|
};
|
||||||
|
|
||||||
|
/* See 4.1.1 Header section format
|
||||||
|
* DNS Message Header is always 12 bytes
|
||||||
|
*/
|
||||||
|
#define DNS_MSG_HEADER_SIZE 12
|
||||||
|
|
||||||
|
static inline uint32_t z_swap4(uint32_t n)
|
||||||
|
{
|
||||||
|
return ((n&0x000000FF)<<24) + ((n&0x0000FF00)<<8)
|
||||||
|
+ ((n&0x00FF0000)>>8) + ((n&0xFF000000)>>24);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint16_t z_swap2(uint16_t n)
|
||||||
|
{
|
||||||
|
return (n>>8) + ((n & 0x00FF) << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** It returns the ID field in the DNS msg header */
|
||||||
|
static inline int dns_header_id(uint8_t *header)
|
||||||
|
{
|
||||||
|
return z_swap2(*(uint16_t *)header);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** It returns the QR field in the DNS msg header */
|
||||||
|
static inline int dns_header_qr(uint8_t *header)
|
||||||
|
{
|
||||||
|
return ((*(header + 2)) & 0x80) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** It returns the OPCODE field in the DNS msg header */
|
||||||
|
static inline int dns_header_opcode(uint8_t *header)
|
||||||
|
{
|
||||||
|
return ((*(header + 2)) & 0x70) >> 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** It returns the AA field in the DNS msg header */
|
||||||
|
static inline int dns_header_aa(uint8_t *header)
|
||||||
|
{
|
||||||
|
return ((*(header + 2)) & 0x04) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** It returns the TC field in the DNS msg header */
|
||||||
|
static inline int dns_header_tc(uint8_t *header)
|
||||||
|
{
|
||||||
|
return ((*(header + 2)) & 0x02) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** It returns the RD field in the DNS msg header */
|
||||||
|
static inline int dns_header_rd(uint8_t *header)
|
||||||
|
{
|
||||||
|
return ((*(header + 2)) & 0x01) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** It returns the RA field in the DNS msg header */
|
||||||
|
static inline int dns_header_ra(uint8_t *header)
|
||||||
|
{
|
||||||
|
return ((*(header + 3)) & 0x80) >> 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** It returns the Z field in the DNS msg header */
|
||||||
|
static inline int dns_header_z(uint8_t *header)
|
||||||
|
{
|
||||||
|
return ((*(header + 3)) & 0x70) >> 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** It returns the RCODE field in the DNS msg header */
|
||||||
|
static inline int dns_header_rcode(uint8_t *header)
|
||||||
|
{
|
||||||
|
return ((*(header + 3)) & 0x0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** It returns the QDCOUNT field in the DNS msg header */
|
||||||
|
static inline int dns_header_qdcount(uint8_t *header)
|
||||||
|
{
|
||||||
|
return z_swap2(*(uint16_t *)(header + 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** It returns the ANCOUNT field in the DNS msg header */
|
||||||
|
static inline int dns_header_ancount(uint8_t *header)
|
||||||
|
{
|
||||||
|
return z_swap2(*(uint16_t *)(header + 6));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** It returns the NSCOUNT field in the DNS msg header */
|
||||||
|
static inline int dns_header_nscount(uint8_t *header)
|
||||||
|
{
|
||||||
|
return z_swap2(*(uint16_t *)(header + 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** It returns the ARCOUNT field in the DNS msg header */
|
||||||
|
static inline int dns_header_arcount(uint8_t *header)
|
||||||
|
{
|
||||||
|
return z_swap2(*(uint16_t *)(header + 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int dns_query_qtype(uint8_t *question)
|
||||||
|
{
|
||||||
|
return z_swap2(*((uint16_t *)(question + 0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int dns_query_qclass(uint8_t *question)
|
||||||
|
{
|
||||||
|
return z_swap2(*((uint16_t *)(question + 2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int dns_response_type(int dname_size, uint8_t *answer)
|
||||||
|
{
|
||||||
|
/** Future versions must consider byte 0
|
||||||
|
* *(answer + dname_size + 0);
|
||||||
|
*/
|
||||||
|
return *(answer + dname_size + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int dns_answer_class(int dname_size, uint8_t *answer)
|
||||||
|
{
|
||||||
|
/** Future versions must consider byte 2
|
||||||
|
* *(answer + dname_size + 2);
|
||||||
|
*/
|
||||||
|
return *(answer + dname_size + 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int dns_answer_ttl(int dname_size, uint8_t *answer)
|
||||||
|
{
|
||||||
|
return z_swap4(*(uint32_t *)(answer + dname_size + 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int dns_answer_rdlength(int dname_size, uint8_t *answer)
|
||||||
|
{
|
||||||
|
return z_swap2(*(uint16_t *)(answer + dname_size + 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief dns_msg_pack_qname Packs a QNAME
|
||||||
|
* @param len Bytes used by this function
|
||||||
|
* @param buf Buffer
|
||||||
|
* @param sizeof Buffer's size
|
||||||
|
* @param domain_name Something like www.example.com
|
||||||
|
* @return 0 on success
|
||||||
|
* @return -ENOMEM if there is no enough space to store
|
||||||
|
* the resultant QNAME
|
||||||
|
*/
|
||||||
|
int dns_msg_pack_qname(int *len, uint8_t *buf, int size, char *domain_name);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief dns_unpack_answer Unpacks an answer message
|
||||||
|
* @param dns_msg Structure
|
||||||
|
* @param dname_ptr An index to the previous CNAME. For example
|
||||||
|
* for the first answer, ptr must be 0x0c, the
|
||||||
|
* DNAME at the question.
|
||||||
|
* @return 0 on success
|
||||||
|
* @return -ENOMEM on error
|
||||||
|
*/
|
||||||
|
int dns_unpack_answer(struct dns_msg_t *dns_msg, int dname_ptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief dns_unpack_response_header
|
||||||
|
*
|
||||||
|
* @details Unpacks the header's response.
|
||||||
|
*
|
||||||
|
* @param msg Structure containing the response.
|
||||||
|
*
|
||||||
|
* @param src_id Transaction id, it must match the id
|
||||||
|
* used in the query datagram sent to the
|
||||||
|
* DNS server.
|
||||||
|
* @return 0 on success
|
||||||
|
*
|
||||||
|
* @return -ENOMEM if the buffer in msg has no
|
||||||
|
* enough space to store the header.
|
||||||
|
* The header is always 12 bytes length.
|
||||||
|
*
|
||||||
|
* @return -EINVAL:
|
||||||
|
* * if the src_id does not match the
|
||||||
|
* header's id.
|
||||||
|
* * if the header's QR value is
|
||||||
|
* not DNS_RESPONSE.
|
||||||
|
* * if the header's OPCODE value is not
|
||||||
|
* DNS_QUERY.
|
||||||
|
* * if the header's Z value is not 0.
|
||||||
|
* * if the question counter is not 1 or
|
||||||
|
* the answer counter is less than 1.
|
||||||
|
*
|
||||||
|
* RFC 1035 RCODEs (> 0):
|
||||||
|
*
|
||||||
|
* 1 Format error
|
||||||
|
* 2 Server failure
|
||||||
|
* 3 Name Error
|
||||||
|
* 4 Not Implemented
|
||||||
|
* 5 Refused
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int dns_unpack_response_header(struct dns_msg_t *msg, int src_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief dns_msg_pack_query Packs the query message
|
||||||
|
* @param buf Buffer that will contain the resultant query
|
||||||
|
* @param domain_name Something like: www.example.com
|
||||||
|
* @param id Transaction Identifier
|
||||||
|
* @param qtype Query type: AA, AAAA. See enum dns_rr_type
|
||||||
|
* @return 0 on success
|
||||||
|
* @return On error, a negative value is returned. See:
|
||||||
|
* - dns_msg_pack_query_header
|
||||||
|
* - dns_msg_pack_qname
|
||||||
|
*/
|
||||||
|
int dns_msg_pack_query(struct app_buf_t *buf, char *domain_name,
|
||||||
|
uint16_t id, enum dns_rr_type qtype);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief dns_unpack_response_query
|
||||||
|
*
|
||||||
|
* @details Unpacks the response's query. RFC 1035 states that the
|
||||||
|
* response's query comes after the first 12 bytes,
|
||||||
|
* i.e. afther the message's header.
|
||||||
|
*
|
||||||
|
* This function computes the answer_offset field.
|
||||||
|
*
|
||||||
|
* @param dns_msg Structure containing the message.
|
||||||
|
*
|
||||||
|
* @return 0 on success
|
||||||
|
* @return -ENOMEM:
|
||||||
|
* * if the null label is not found after
|
||||||
|
* traversing the buffer.
|
||||||
|
* * if QCLASS and QTYPE are not found.
|
||||||
|
* @return -EINVAL:
|
||||||
|
* * if QTYPE is not "A" (IPv4) or "AAAA" (IPv6).
|
||||||
|
* * if QCLASS is not "IN".
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int dns_unpack_response_query(struct dns_msg_t *dns_msg);
|
||||||
|
|
||||||
|
#endif
|
162
samples/net/dns_client/src/dns_utils.c
Normal file
162
samples/net/dns_client/src/dns_utils.c
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Intel Corporation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dns_pack.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
int dns_print_msg_header(uint8_t *header, int size)
|
||||||
|
{
|
||||||
|
if (size < DNS_MSG_HEADER_SIZE) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nHeader\n");
|
||||||
|
printf("\tFlags\n");
|
||||||
|
printf("\t\tTransaction ID:\t\t%d\n", dns_header_id(header));
|
||||||
|
printf("\t\tMessage type:\t\t%d (%s)\n", dns_header_qr(header),
|
||||||
|
(dns_header_qr(header) == DNS_QUERY ? "query" : "response"));
|
||||||
|
printf("\t\tOperation code:\t\t%d (%s)\n", dns_header_opcode(header),
|
||||||
|
(dns_header_opcode(header) == DNS_QUERY ? "query" : "other"));
|
||||||
|
printf("\t\tAuthoritative:\t\t%d (%s)\n", dns_header_aa(header),
|
||||||
|
(dns_header_aa(header) ? "true" : "false"));
|
||||||
|
printf("\t\tTruncated:\t\t%d (%s)\n", dns_header_tc(header),
|
||||||
|
(dns_header_tc(header) ? "true" : "false"));
|
||||||
|
printf("\t\tRecursion desired:\t%d (%s)\n", dns_header_rd(header),
|
||||||
|
(dns_header_rd(header) ? "true" : "false"));
|
||||||
|
printf("\t\tRecursion avaialable:\t%d (%s)\n", dns_header_ra(header),
|
||||||
|
(dns_header_ra(header) ? "true" : "false"));
|
||||||
|
printf("\t\tZ:\t\t\t%d\n", dns_header_z(header));
|
||||||
|
printf("\t\tResponse code:\t\t%d (%s)\n", dns_header_rcode(header),
|
||||||
|
(dns_header_rcode(header) == 0 ? "no error" : "error"));
|
||||||
|
printf("\tQuestion counter:\t%d\n", dns_header_qdcount(header));
|
||||||
|
printf("\tAnswer counter:\t\t%d\n", dns_header_ancount(header));
|
||||||
|
printf("\tNServer counter:\t%d\n", dns_header_nscount(header));
|
||||||
|
printf("\tAdditional counter:\t%d\n", dns_header_arcount(header));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dns_print_label(uint8_t *label, int size)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while (i < size) {
|
||||||
|
n = label[i];
|
||||||
|
if (n == 0) {
|
||||||
|
break;
|
||||||
|
} else if (n > 63) {
|
||||||
|
break;
|
||||||
|
} else if (i + n <= size) {
|
||||||
|
|
||||||
|
if (i) {
|
||||||
|
printf(".");
|
||||||
|
}
|
||||||
|
int j = i + 1; /* next char */
|
||||||
|
|
||||||
|
while (j < i + 1 + n) {
|
||||||
|
printf("%c", label[j]);
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
i += n + 1; /* content + octect size */
|
||||||
|
} else {
|
||||||
|
i = 0; /* no memory! */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dns_print_msg_query(uint8_t *qname, int qname_size, int qtype, int qclass)
|
||||||
|
{
|
||||||
|
printf("\nQuery\n");
|
||||||
|
printf("\tQuery name\n\t\tLabel size:\t%d\n\t\tDomain name:\t",
|
||||||
|
qname_size);
|
||||||
|
dns_print_label(qname, qname_size);
|
||||||
|
printf("\n");
|
||||||
|
printf("\tQuery type:\t\t%d\n", qtype);
|
||||||
|
printf("\tQuery class:\t\t%d\n", qclass);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dns_print_readable_msg_label(int offset, uint8_t *buf, int size)
|
||||||
|
{
|
||||||
|
int next;
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
for (i = offset; i < size;) {
|
||||||
|
if (buf[i] <= 63) {
|
||||||
|
/* +1 because the null label or a pointer */
|
||||||
|
if (i + buf[i] + 1 >= size) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 1; j <= buf[i]; j++) {
|
||||||
|
printf("%c", buf[i + j]);
|
||||||
|
}
|
||||||
|
i += buf[i] + 1;
|
||||||
|
if (buf[i] == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf(".");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (i + 1 >= size) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
next = ((buf[i] & 0x3F) << 8) + buf[i + 1];
|
||||||
|
if (next >= size) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
i = next;
|
||||||
|
offset = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int print_buf(uint8_t *buf, size_t size)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < size; i++) {
|
||||||
|
printf("%d ", buf[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int print_app_buf(struct app_buf_t *buf)
|
||||||
|
{
|
||||||
|
print_buf(buf->buf, buf->length);
|
||||||
|
return 0;
|
||||||
|
}
|
30
samples/net/dns_client/src/dns_utils.h
Normal file
30
samples/net/dns_client/src/dns_utils.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Intel Corporation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _DNS_UTILS_H_
|
||||||
|
#define _DNS_UTILS_H_
|
||||||
|
|
||||||
|
#include <app_buf.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
int dns_print_msg_header(uint8_t *header, int size);
|
||||||
|
int dns_print_msg_query(uint8_t *qname, int qname_size, int qtype, int qclass);
|
||||||
|
int dns_print_label(uint8_t *label, int size);
|
||||||
|
int dns_print_readable_msg_label(int offset, uint8_t *buf, int size);
|
||||||
|
int print_buf(uint8_t *buf, size_t size);
|
||||||
|
int print_app_buf(struct app_buf_t *buf);
|
||||||
|
|
||||||
|
#endif
|
191
samples/net/dns_client/src/main.c
Normal file
191
samples/net/dns_client/src/main.c
Normal file
|
@ -0,0 +1,191 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Intel Corporation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zephyr.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "dns_pack.h"
|
||||||
|
#include "dns_utils.h"
|
||||||
|
#include "netz.h"
|
||||||
|
|
||||||
|
#define STACK_SIZE 1024
|
||||||
|
uint8_t stack[STACK_SIZE];
|
||||||
|
|
||||||
|
#define BUF_SIZE 1024
|
||||||
|
|
||||||
|
uint8_t tx_raw_buf[BUF_SIZE];
|
||||||
|
uint8_t rx_raw_buf[BUF_SIZE];
|
||||||
|
|
||||||
|
#define SLEEP_TIME 10
|
||||||
|
|
||||||
|
char *domains[] = {"not_a_real_domain_name", "oops!",
|
||||||
|
"zephyrproject.org", "www.google.com",
|
||||||
|
"mail.yahoo.com", NULL};
|
||||||
|
|
||||||
|
int dns_query(struct app_buf_t *buf, char *str, uint16_t id,
|
||||||
|
enum dns_rr_type qtype);
|
||||||
|
|
||||||
|
int dns_response(struct app_buf_t *_buf, int *response_type, int src_id);
|
||||||
|
|
||||||
|
void fiber(void)
|
||||||
|
{
|
||||||
|
struct app_buf_t tx_buf = APP_BUF_INIT(tx_raw_buf,
|
||||||
|
sizeof(tx_raw_buf), 0);
|
||||||
|
|
||||||
|
struct app_buf_t rx_buf = APP_BUF_INIT(rx_raw_buf,
|
||||||
|
sizeof(rx_raw_buf), 0);
|
||||||
|
|
||||||
|
struct netz_ctx_t netz_ctx = NETZ_CTX_INIT;
|
||||||
|
|
||||||
|
int response_type;
|
||||||
|
int counter;
|
||||||
|
char *name;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
netz_host_ipv4(&netz_ctx, 192, 168, 1, 101);
|
||||||
|
netz_remote_ipv4(&netz_ctx, 192, 168, 1, 10, 5353);
|
||||||
|
netz_netmask_ipv4(&netz_ctx, 255, 255, 255, 0);
|
||||||
|
netz_udp(&netz_ctx);
|
||||||
|
|
||||||
|
counter = 0;
|
||||||
|
do {
|
||||||
|
fiber_sleep(300);
|
||||||
|
|
||||||
|
printf("\n-----------------------------------------\n");
|
||||||
|
|
||||||
|
name = domains[counter];
|
||||||
|
if (name == NULL) {
|
||||||
|
counter = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
counter += 1;
|
||||||
|
|
||||||
|
printf("Domain name: %s\n", name);
|
||||||
|
|
||||||
|
rc = dns_query(&tx_buf, name, counter, DNS_RR_TYPE_A);
|
||||||
|
printf("[%s:%d] DNS Create Query: %d, ID: %d\n",
|
||||||
|
__func__, __LINE__, rc, counter);
|
||||||
|
|
||||||
|
rc = netz_tx(&netz_ctx, &tx_buf);
|
||||||
|
printf("[%s:%d] TX: %d\n", __func__, __LINE__, rc);
|
||||||
|
|
||||||
|
rc = netz_rx(&netz_ctx, &rx_buf);
|
||||||
|
printf("[%s:%d] RX: %d\n", __func__, __LINE__, rc);
|
||||||
|
|
||||||
|
if (rc != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = dns_response(&rx_buf, &response_type, counter);
|
||||||
|
printf("[%s:%d] DNS response: %d\n", __func__, __LINE__, rc);
|
||||||
|
|
||||||
|
|
||||||
|
} while (1);
|
||||||
|
|
||||||
|
printf("Bye!\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
net_init();
|
||||||
|
|
||||||
|
task_fiber_start(stack, STACK_SIZE, (nano_fiber_entry_t)fiber,
|
||||||
|
0, 0, 7, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int dns_query(struct app_buf_t *buf, char *str, uint16_t id,
|
||||||
|
enum dns_rr_type qtype)
|
||||||
|
{
|
||||||
|
return dns_msg_pack_query(buf, str, id, qtype);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dns_response(struct app_buf_t *_buf, int *response_type, int src_id)
|
||||||
|
{
|
||||||
|
struct dns_msg_t dns_msg = DNS_MSG_INIT(_buf->buf, _buf->size);
|
||||||
|
int ptr;
|
||||||
|
int rc;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
rc = dns_unpack_response_header(&dns_msg, src_id);
|
||||||
|
if (rc != 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dns_header_qdcount(dns_msg.msg) != 1) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = dns_unpack_response_query(&dns_msg);
|
||||||
|
if (rc != 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
/* the first dname is at 0x0c bytes */
|
||||||
|
ptr = 0x0c;
|
||||||
|
while (i < dns_header_ancount(dns_msg.msg)) {
|
||||||
|
|
||||||
|
printf("\n****** DNS ANSWER: %d ******\n", i);
|
||||||
|
|
||||||
|
rc = dns_unpack_answer(&dns_msg, ptr);
|
||||||
|
if (rc != 0) {
|
||||||
|
printf("[%s:%d]\n", __func__, __LINE__);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (dns_msg.response_type) {
|
||||||
|
case DNS_RESPONSE_IP:
|
||||||
|
printf("Response: IP address\t\tSize: %d:\t",
|
||||||
|
dns_msg.response_length);
|
||||||
|
print_buf(dns_msg.msg + dns_msg.response_position,
|
||||||
|
dns_msg.response_length);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DNS_RESPONSE_CNAME_NO_IP:
|
||||||
|
printf("Response: CNAME NO IP address\t\tSize: %d:\t",
|
||||||
|
dns_msg.response_length);
|
||||||
|
print_buf(dns_msg.msg + dns_msg.response_position,
|
||||||
|
dns_msg.response_length);
|
||||||
|
printf("CNAME: ");
|
||||||
|
dns_print_readable_msg_label(dns_msg.response_position,
|
||||||
|
dns_msg.msg,
|
||||||
|
dns_msg.msg_size);
|
||||||
|
|
||||||
|
ptr = dns_msg.response_position;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DNS_RESPONSE_CNAME_WITH_IP:
|
||||||
|
printf("Response: CNAME WITH IP addr\t\tSize: %d:\t",
|
||||||
|
dns_msg.response_length);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dns_msg.answer_offset = dns_msg.answer_offset + 12
|
||||||
|
+ dns_msg.response_length;
|
||||||
|
|
||||||
|
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
*response_type = dns_msg.response_type;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
223
samples/net/dns_client/src/netz.c
Normal file
223
samples/net/dns_client/src/netz.c
Normal file
|
@ -0,0 +1,223 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Intel Corporation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <netz.h>
|
||||||
|
|
||||||
|
#include <net/net_core.h>
|
||||||
|
#include <net/net_socket.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
void netz_host(struct netz_ctx_t *ctx, struct net_addr *host)
|
||||||
|
{
|
||||||
|
return netz_host_ipv4(ctx, host->in_addr.in4_u.u4_addr8[0],
|
||||||
|
host->in_addr.in4_u.u4_addr8[1],
|
||||||
|
host->in_addr.in4_u.u4_addr8[2],
|
||||||
|
host->in_addr.in4_u.u4_addr8[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void netz_host_ipv4(struct netz_ctx_t *ctx, uint8_t a1, uint8_t a2,
|
||||||
|
uint8_t a3, uint8_t a4)
|
||||||
|
{
|
||||||
|
uip_ipaddr_t host_addr;
|
||||||
|
|
||||||
|
uip_ipaddr(&host_addr, a1, a2, a3, a4);
|
||||||
|
uip_sethostaddr(&host_addr);
|
||||||
|
|
||||||
|
ctx->host.in_addr.in4_u.u4_addr8[0] = a1;
|
||||||
|
ctx->host.in_addr.in4_u.u4_addr8[1] = a2;
|
||||||
|
ctx->host.in_addr.in4_u.u4_addr8[2] = a3;
|
||||||
|
ctx->host.in_addr.in4_u.u4_addr8[3] = a4;
|
||||||
|
ctx->host.family = AF_INET;
|
||||||
|
}
|
||||||
|
|
||||||
|
void netz_netmask(struct netz_ctx_t *ctx, struct net_addr *netmask)
|
||||||
|
{
|
||||||
|
return netz_netmask_ipv4(ctx, netmask->in_addr.in4_u.u4_addr8[0],
|
||||||
|
netmask->in_addr.in4_u.u4_addr8[1],
|
||||||
|
netmask->in_addr.in4_u.u4_addr8[2],
|
||||||
|
netmask->in_addr.in4_u.u4_addr8[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void netz_netmask_ipv4(struct netz_ctx_t *ctx, uint8_t n1, uint8_t n2,
|
||||||
|
uint8_t n3, uint8_t n4)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(ctx);
|
||||||
|
|
||||||
|
uip_ipaddr_t netmask;
|
||||||
|
|
||||||
|
uip_ipaddr(&netmask, n1, n2, n3, n4);
|
||||||
|
uip_setnetmask(&netmask);
|
||||||
|
}
|
||||||
|
|
||||||
|
void netz_remote(struct netz_ctx_t *ctx, struct net_addr *remote, int port)
|
||||||
|
{
|
||||||
|
return netz_remote_ipv4(ctx, remote->in_addr.in4_u.u4_addr8[0],
|
||||||
|
remote->in_addr.in4_u.u4_addr8[1],
|
||||||
|
remote->in_addr.in4_u.u4_addr8[2],
|
||||||
|
remote->in_addr.in4_u.u4_addr8[3], port);
|
||||||
|
}
|
||||||
|
|
||||||
|
void netz_remote_ipv4(struct netz_ctx_t *ctx, uint8_t a1, uint8_t a2,
|
||||||
|
uint8_t a3, uint8_t a4, int port)
|
||||||
|
{
|
||||||
|
ctx->remote.in_addr.in4_u.u4_addr8[0] = a1;
|
||||||
|
ctx->remote.in_addr.in4_u.u4_addr8[1] = a2;
|
||||||
|
ctx->remote.in_addr.in4_u.u4_addr8[2] = a3;
|
||||||
|
ctx->remote.in_addr.in4_u.u4_addr8[3] = a4;
|
||||||
|
ctx->remote.family = AF_INET;
|
||||||
|
|
||||||
|
ctx->remote_port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int netz_prepare(struct netz_ctx_t *ctx, enum ip_protocol proto)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_NETWORKING_WITH_TCP
|
||||||
|
struct app_buf_t buf = APP_BUF_INIT(NULL, 0, 0);
|
||||||
|
int rc;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ctx->connected = 0;
|
||||||
|
ctx->proto = proto;
|
||||||
|
|
||||||
|
ctx->net_ctx = net_context_get(ctx->proto,
|
||||||
|
&ctx->remote, ctx->remote_port,
|
||||||
|
&ctx->host, 0);
|
||||||
|
if (ctx->net_ctx == NULL) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_NETWORKING_WITH_TCP
|
||||||
|
/* workaround to activate the IP stack */
|
||||||
|
rc = netz_tx(ctx, &buf);
|
||||||
|
if (rc != 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
ctx->connected = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int netz_tcp(struct netz_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
return netz_prepare(ctx, IPPROTO_TCP);
|
||||||
|
}
|
||||||
|
|
||||||
|
int netz_udp(struct netz_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
return netz_prepare(ctx, IPPROTO_UDP);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void netz_sleep(int sleep_ticks)
|
||||||
|
{
|
||||||
|
struct nano_timer timer;
|
||||||
|
|
||||||
|
nano_timer_init(&timer, NULL);
|
||||||
|
nano_fiber_timer_start(&timer, sleep_ticks);
|
||||||
|
nano_fiber_timer_test(&timer, TICKS_UNLIMITED);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tcp_tx(struct net_context *ctx, uint8_t *buf, size_t size,
|
||||||
|
int tx_retry_timeout)
|
||||||
|
{
|
||||||
|
struct net_buf *nbuf;
|
||||||
|
uint8_t *ptr;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
nbuf = ip_buf_get_tx(ctx);
|
||||||
|
if (nbuf == NULL) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = net_buf_add(nbuf, size);
|
||||||
|
memcpy(ptr, buf, size);
|
||||||
|
ip_buf_appdatalen(nbuf) = size;
|
||||||
|
|
||||||
|
do {
|
||||||
|
rc = net_send(nbuf);
|
||||||
|
|
||||||
|
if (rc >= 0) {
|
||||||
|
ip_buf_unref(nbuf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
switch (rc) {
|
||||||
|
case -EINPROGRESS:
|
||||||
|
netz_sleep(tx_retry_timeout);
|
||||||
|
break;
|
||||||
|
case -EAGAIN:
|
||||||
|
case -ECONNRESET:
|
||||||
|
netz_sleep(tx_retry_timeout);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ip_buf_unref(nbuf);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
} while (1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tcp_rx(struct net_context *ctx, uint8_t *buf, size_t *read_bytes,
|
||||||
|
size_t size, int rx_timeout)
|
||||||
|
{
|
||||||
|
struct net_buf *nbuf;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
nbuf = net_receive(ctx, rx_timeout);
|
||||||
|
if (nbuf == NULL) {
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
*read_bytes = ip_buf_appdatalen(nbuf);
|
||||||
|
if (*read_bytes > size) {
|
||||||
|
*read_bytes = size;
|
||||||
|
rc = -ENOMEM;
|
||||||
|
} else {
|
||||||
|
rc = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buf, ip_buf_appdata(nbuf), *read_bytes);
|
||||||
|
ip_buf_unref(nbuf);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int netz_tx(struct netz_ctx_t *ctx, struct app_buf_t *buf)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* We don't evaluate if we are connected. */
|
||||||
|
|
||||||
|
rc = tcp_tx(ctx->net_ctx, buf->buf, buf->length,
|
||||||
|
ctx->tx_retry_timeout);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int netz_rx(struct netz_ctx_t *ctx, struct app_buf_t *buf)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (ctx->connected != 1) {
|
||||||
|
return -ENOTCONN;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = tcp_rx(ctx->net_ctx, buf->buf, &buf->length, buf->size,
|
||||||
|
ctx->rx_timeout);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
163
samples/net/dns_client/src/netz.h
Normal file
163
samples/net/dns_client/src/netz.h
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Intel Corporation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _NETZ_H_
|
||||||
|
#define _NETZ_H_
|
||||||
|
|
||||||
|
#include <net/ip_buf.h>
|
||||||
|
#include <net/net_core.h>
|
||||||
|
|
||||||
|
#include "app_buf.h"
|
||||||
|
|
||||||
|
struct __deprecated netz_ctx_t;
|
||||||
|
|
||||||
|
struct netz_ctx_t {
|
||||||
|
struct net_context *net_ctx;
|
||||||
|
int connected;
|
||||||
|
|
||||||
|
int rx_timeout;
|
||||||
|
int tx_retry_timeout;
|
||||||
|
|
||||||
|
struct net_addr host;
|
||||||
|
int host_port;
|
||||||
|
|
||||||
|
struct net_addr remote;
|
||||||
|
int remote_port;
|
||||||
|
|
||||||
|
enum ip_protocol proto;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TCP_COMMON_TIMEOUT 20
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief NETZ_CTX_INIT Initializes a netz context with default values
|
||||||
|
*/
|
||||||
|
#define NETZ_CTX_INIT { .rx_timeout = TCP_COMMON_TIMEOUT, \
|
||||||
|
.tx_retry_timeout = TCP_COMMON_TIMEOUT, \
|
||||||
|
.net_ctx = NULL, \
|
||||||
|
.connected = 0, \
|
||||||
|
.proto = IPPROTO_UDP, \
|
||||||
|
.host_port = 0, \
|
||||||
|
.remote_port = 0}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief NET_ADDR_IPV4_INIT Initializes a net_addr structure with
|
||||||
|
* an IPv4 address specified by a1, a2, a3 and a4
|
||||||
|
*/
|
||||||
|
#define NET_ADDR_IPV4_INIT(a1, a2, a3, a4) {.in_addr.in4_u.u4_addr8[0] = (a1),\
|
||||||
|
.in_addr.in4_u.u4_addr8[1] = (a2),\
|
||||||
|
.in_addr.in4_u.u4_addr8[2] = (a3),\
|
||||||
|
.in_addr.in4_u.u4_addr8[3] = (a4),\
|
||||||
|
.family = AF_INET}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief netz_host Sets the host IPv4 address (no IPv6 support)
|
||||||
|
* @param ctx netz context structure
|
||||||
|
* @param host Network address
|
||||||
|
*/
|
||||||
|
void __deprecated netz_host(struct netz_ctx_t *ctx, struct net_addr *host);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief netz_host_ipv4 Sets the host IPv4 address (no IPv6 support)
|
||||||
|
* @param ctx netz context structure
|
||||||
|
* @param a1 Byte 0 of the IPv4 address
|
||||||
|
* @param a2 Byte 1 of the IPv4 address
|
||||||
|
* @param a3 Byte 2 of the IPv4 address
|
||||||
|
* @param a4 Byte 3 of the IPv4 address
|
||||||
|
*/
|
||||||
|
void __deprecated netz_host_ipv4(struct netz_ctx_t *ctx, uint8_t a1,
|
||||||
|
uint8_t a2, uint8_t a3, uint8_t a4);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief netz_netmask Sets the host's netmask address
|
||||||
|
* @param ctx netz context structure
|
||||||
|
* @param netmask Network address to be used as netmask
|
||||||
|
*/
|
||||||
|
void __deprecated netz_netmask(struct netz_ctx_t *ctx,
|
||||||
|
struct net_addr *netmask);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief netz_netmask_ipv4 Sets the host's netmask IPv4 address
|
||||||
|
* @param ctx netz context structure
|
||||||
|
* @param n1 Byte 0 of the IPv4 address
|
||||||
|
* @param n2 Byte 1 of the IPv4 address
|
||||||
|
* @param n3 Byte 2 of the IPv4 address
|
||||||
|
* @param n4 Byte 3 of the IPv4 address
|
||||||
|
*/
|
||||||
|
void __deprecated netz_netmask_ipv4(struct netz_ctx_t *ctx, uint8_t n1,
|
||||||
|
uint8_t n2, uint8_t n3, uint8_t n4);
|
||||||
|
/**
|
||||||
|
* @brief netz_remote Sets the address of the remote peer
|
||||||
|
* @param ctx netz context structure
|
||||||
|
* @param remote Network address of the remote peer
|
||||||
|
* @param port Port number of the remote peer
|
||||||
|
*/
|
||||||
|
void __deprecated netz_remote(struct netz_ctx_t *ctx, struct net_addr *remote,
|
||||||
|
int port);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief netz_remote_ipv4 Sets the IPv4 address of the remote peer
|
||||||
|
* @param ctx netz context structure
|
||||||
|
* @param a1 Byte 0 of the IPv4 address
|
||||||
|
* @param a2 Byte 1 of the IPv4 address
|
||||||
|
* @param a3 Byte 2 of the IPv4 address
|
||||||
|
* @param a4 Byte 3 of the IPv4 address
|
||||||
|
*/
|
||||||
|
|
||||||
|
void __deprecated netz_remote_ipv4(struct netz_ctx_t *ctx, uint8_t a1,
|
||||||
|
uint8_t a2, uint8_t a3, uint8_t a4,
|
||||||
|
int port);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief netz_tcp Initializes the netz context & connects
|
||||||
|
* to the remote peer
|
||||||
|
* @param ctx netz context structure
|
||||||
|
* @return 0 on success
|
||||||
|
* @return -EINVAL if a null context was obtained
|
||||||
|
* @return Read netz_tx return codes
|
||||||
|
*/
|
||||||
|
int __deprecated netz_tcp(struct netz_ctx_t *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief netz_udp Initializes the context for UDP transfers
|
||||||
|
* @param ctx netz context structure
|
||||||
|
* @return 0 on success
|
||||||
|
* @return -EINVAL if a null context was obtained
|
||||||
|
*/
|
||||||
|
int __deprecated netz_udp(struct netz_ctx_t *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief netz_tx TCP/UDP data transmission
|
||||||
|
* @param ctx netz context structure
|
||||||
|
* @param buf Buffer that contains the data to be sent
|
||||||
|
* @return 0 on success
|
||||||
|
* @return -EINVAL if no network buffer is available
|
||||||
|
* @return -EIO if a TCP error was detected
|
||||||
|
*/
|
||||||
|
int __deprecated netz_tx(struct netz_ctx_t *ctx, struct app_buf_t *buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief netz_rx TCP/UDP data reception
|
||||||
|
* @param ctx netz context structure
|
||||||
|
* @param buf Buffer that contains the received data
|
||||||
|
* @return 0 on success
|
||||||
|
* @return -EIO on TCP or network buffer error
|
||||||
|
* @return -ENOMEM if the space in buf is not enough
|
||||||
|
* to store the received data
|
||||||
|
*/
|
||||||
|
int __deprecated netz_rx(struct netz_ctx_t *ctx, struct app_buf_t *buf);
|
||||||
|
|
||||||
|
#endif
|
5
samples/net/dns_client/testcase.ini
Normal file
5
samples/net/dns_client/testcase.ini
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
[test]
|
||||||
|
tags = net
|
||||||
|
build_only = true
|
||||||
|
arch_whitelist = x86
|
||||||
|
platform_whitelist = galileo
|
Loading…
Add table
Add a link
Reference in a new issue