blob: e69cf43ed8d4d3f6990adabc7dd6319f85dd8ea6 [file] [log] [blame]
/*
* 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 50
#define RC_STR(rc) (rc == 0 ? "OK" : "ERROR")
char *domains[] = {"not_a_real_domain_name",
"linuxfoundation.org", "www.linuxfoundation.org",
"gnu.org", "www.gnu.org",
"npr.org", "www.npr.org",
"wikipedia.org", "www.wikipedia.org",
"zephyrproject.org", "www.zephyrproject.org",
NULL};
/* this function creates the DNS query */
int dns_query(struct app_buf_t *buf, char *str, uint16_t id,
enum dns_rr_type qtype);
/* this function parses the DNS server response */
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);
/* If the network is a bit slow, increase rx_timeout and
* tx_retry_timeout in struct netz_ctx_t
*/
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 {
printf("\n-----------------------------------------\n");
name = domains[counter];
if (name == NULL) {
counter = 0;
continue;
}
printf("Domain name: %s\n", name);
rc = dns_query(&tx_buf, name, counter, DNS_RR_TYPE_A);
printf("[%s:%d] DNS Query: %s, ID: %d\n",
__func__, __LINE__, RC_STR(rc), counter);
rc = netz_tx(&netz_ctx, &tx_buf);
printf("[%s:%d] TX: %s\n", __func__, __LINE__, RC_STR(rc));
fiber_sleep(SLEEP_TIME);
rc = netz_rx(&netz_ctx, &rx_buf);
printf("[%s:%d] RX: %s\n", __func__, __LINE__, RC_STR(rc));
if (rc == 0) {
rc = dns_response(&rx_buf, &response_type, counter);
printf("[%s:%d] DNS Response: %s %s\n",
__func__, __LINE__, RC_STR(rc),
(rc != 0 && counter == 0 ? "<- :)" : ""));
}
counter += 1;
fiber_sleep(SLEEP_TIME);
} while (1);
}
void main(void)
{
net_init();
task_fiber_start(stack, STACK_SIZE, (nano_fiber_entry_t)fiber,
0, 0, 7, 0);
}
/* Next versions must handle the transaction id internally */
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);
}
/* See dns_unpack_answer, and also see:
* https://tools.ietf.org/html/rfc1035#section-4.1.2
*/
#define DNS_QUERY_POS 0x0c
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 -EINVAL;
}
if (dns_header_qdcount(dns_msg.msg) != 1) {
return -EINVAL;
}
rc = dns_unpack_response_query(&dns_msg);
if (rc != 0) {
return -EINVAL;
}
i = 0;
ptr = DNS_QUERY_POS;
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) {
return -EINVAL;
}
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);
printf("\n");
break;
case DNS_RESPONSE_CNAME_NO_IP:
printf("Response: CNAME NO IP address");
printf("\nCNAME: ");
dns_print_readable_msg_label(dns_msg.response_position,
dns_msg.msg,
dns_msg.msg_size);
printf("\n");
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;
}