Free (GPLv2) TCP/IP stack developed by TASS Belgium

Dependents:   lpc1768-picotcp-demo ZeroMQ_PicoTCP_Publisher_demo TCPSocket_HelloWorld_PicoTCP Pico_TCP_UDP_Test ... more

PicoTCP. Copyright (c) 2013 TASS Belgium NV.

Released under the GNU General Public License, version 2.

Different licensing models may exist, at the sole discretion of the Copyright holders.

Official homepage: http://www.picotcp.com

Bug tracker: https://github.com/tass-belgium/picotcp/issues

Development steps:

  • initial integration with mbed RTOS
  • generic mbed Ethernet driver
  • high performance NXP LPC1768 specific Ethernet driver
  • Multi-threading support for mbed RTOS
  • Berkeley sockets and integration with the New Socket API
  • Fork of the apps running on top of the New Socket API
  • Scheduling optimizations
  • Debugging/benchmarking/testing

Demo application (measuring TCP sender performance):

Import programlpc1768-picotcp-demo

A PicoTCP demo app testing the ethernet throughput on the lpc1768 mbed board.

Committer:
tass
Date:
Thu Jan 28 15:12:00 2016 +0100
Revision:
155:a70f34550c34
Parent:
152:a3d286bf94e5
Adding TCP flag for FIN.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tass 68:0847e35d08a6 1 /*********************************************************************
TASS Belgium NV 131:4758606c9316 2 PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved.
TASS Belgium NV 131:4758606c9316 3 See LICENSE and COPYING for usage.
TASS Belgium NV 131:4758606c9316 4 .
TASS Belgium NV 131:4758606c9316 5 Authors: Kristof Roelants
TASS Belgium NV 131:4758606c9316 6 *********************************************************************/
tass 68:0847e35d08a6 7 #include "pico_config.h"
tass 68:0847e35d08a6 8 #include "pico_stack.h"
tass 68:0847e35d08a6 9 #include "pico_addressing.h"
tass 68:0847e35d08a6 10 #include "pico_socket.h"
tass 68:0847e35d08a6 11 #include "pico_ipv4.h"
tass picotcp@tass.be 149:5f4cb161cec3 12 #include "pico_ipv6.h"
tass 68:0847e35d08a6 13 #include "pico_dns_client.h"
tass 152:a3d286bf94e5 14 #include "pico_dns_common.h"
tass 68:0847e35d08a6 15 #include "pico_tree.h"
tass 68:0847e35d08a6 16
tass 68:0847e35d08a6 17 #ifdef PICO_SUPPORT_DNS_CLIENT
tass 68:0847e35d08a6 18
tass 152:a3d286bf94e5 19 #ifdef PICO_SUPPORT_IPV4
tass 152:a3d286bf94e5 20
TASS Belgium NV 131:4758606c9316 21 #define dns_dbg(...) do {} while(0)
TASS Belgium NV 131:4758606c9316 22 /* #define dns_dbg dbg */
tass 68:0847e35d08a6 23
tass 68:0847e35d08a6 24 /* DNS response length */
tass 152:a3d286bf94e5 25 #define PICO_DNS_MAX_QUERY_LEN 255
tass 152:a3d286bf94e5 26 #define PICO_DNS_MAX_QUERY_LABEL_LEN 63
tass 68:0847e35d08a6 27
tass 68:0847e35d08a6 28 /* DNS client retransmission time (msec) + frequency */
tass 68:0847e35d08a6 29 #define PICO_DNS_CLIENT_RETRANS 4000
tass 68:0847e35d08a6 30 #define PICO_DNS_CLIENT_MAX_RETRANS 3
tass 68:0847e35d08a6 31
tass 68:0847e35d08a6 32 static void pico_dns_client_callback(uint16_t ev, struct pico_socket *s);
tass 128:ae39e6e81531 33 static void pico_dns_client_retransmission(pico_time now, void *arg);
tass 152:a3d286bf94e5 34 static int pico_dns_client_getaddr_init(const char *url, uint16_t proto, void (*callback)(char *, void *), void *arg);
tass 68:0847e35d08a6 35
tass 68:0847e35d08a6 36 struct pico_dns_ns
tass 68:0847e35d08a6 37 {
TASS Belgium NV 131:4758606c9316 38 struct pico_ip4 ns; /* nameserver */
tass 68:0847e35d08a6 39 };
tass 68:0847e35d08a6 40
tass 68:0847e35d08a6 41 static int dns_ns_cmp(void *ka, void *kb)
tass 68:0847e35d08a6 42 {
TASS Belgium NV 131:4758606c9316 43 struct pico_dns_ns *a = ka, *b = kb;
tass 152:a3d286bf94e5 44 return pico_ipv4_compare(&a->ns, &b->ns);
TASS Belgium NV 131:4758606c9316 45 }
tass 68:0847e35d08a6 46 PICO_TREE_DECLARE(NSTable, dns_ns_cmp);
TASS Belgium NV 131:4758606c9316 47
tass 68:0847e35d08a6 48 struct pico_dns_query
tass 68:0847e35d08a6 49 {
TASS Belgium NV 131:4758606c9316 50 char *query;
TASS Belgium NV 131:4758606c9316 51 uint16_t len;
TASS Belgium NV 131:4758606c9316 52 uint16_t id;
TASS Belgium NV 131:4758606c9316 53 uint16_t qtype;
TASS Belgium NV 131:4758606c9316 54 uint16_t qclass;
TASS Belgium NV 131:4758606c9316 55 uint8_t retrans;
TASS Belgium NV 131:4758606c9316 56 struct pico_dns_ns q_ns;
TASS Belgium NV 131:4758606c9316 57 struct pico_socket *s;
TASS Belgium NV 131:4758606c9316 58 void (*callback)(char *, void *);
TASS Belgium NV 131:4758606c9316 59 void *arg;
tass 68:0847e35d08a6 60 };
tass 68:0847e35d08a6 61
tass 68:0847e35d08a6 62 static int dns_query_cmp(void *ka, void *kb)
tass 68:0847e35d08a6 63 {
TASS Belgium NV 131:4758606c9316 64 struct pico_dns_query *a = ka, *b = kb;
TASS Belgium NV 131:4758606c9316 65 if (a->id == b->id)
TASS Belgium NV 131:4758606c9316 66 return 0;
TASS Belgium NV 131:4758606c9316 67
tass picotcp@tass.be 149:5f4cb161cec3 68 return (a->id < b->id) ? (-1) : (1);
TASS Belgium NV 131:4758606c9316 69 }
tass 68:0847e35d08a6 70 PICO_TREE_DECLARE(DNSTable, dns_query_cmp);
tass 68:0847e35d08a6 71
tass 68:0847e35d08a6 72 static int pico_dns_client_del_ns(struct pico_ip4 *ns_addr)
tass 68:0847e35d08a6 73 {
TASS Belgium NV 131:4758606c9316 74 struct pico_dns_ns test = {{0}}, *found = NULL;
tass 68:0847e35d08a6 75
TASS Belgium NV 131:4758606c9316 76 test.ns = *ns_addr;
TASS Belgium NV 131:4758606c9316 77 found = pico_tree_findKey(&NSTable, &test);
TASS Belgium NV 131:4758606c9316 78 if (!found)
TASS Belgium NV 131:4758606c9316 79 return -1;
tass 68:0847e35d08a6 80
TASS Belgium NV 131:4758606c9316 81 pico_tree_delete(&NSTable, found);
tass picotcp@tass.be 149:5f4cb161cec3 82 PICO_FREE(found);
tass 68:0847e35d08a6 83
TASS Belgium NV 131:4758606c9316 84 /* no NS left, add default NS */
TASS Belgium NV 131:4758606c9316 85 if (pico_tree_empty(&NSTable))
TASS Belgium NV 131:4758606c9316 86 pico_dns_client_init();
tass 68:0847e35d08a6 87
TASS Belgium NV 131:4758606c9316 88 return 0;
tass 68:0847e35d08a6 89 }
tass 68:0847e35d08a6 90
tass 68:0847e35d08a6 91 static struct pico_dns_ns *pico_dns_client_add_ns(struct pico_ip4 *ns_addr)
tass 68:0847e35d08a6 92 {
TASS Belgium NV 131:4758606c9316 93 struct pico_dns_ns *dns = NULL, *found = NULL, test = {{0}};
TASS Belgium NV 131:4758606c9316 94
tass picotcp@tass.be 149:5f4cb161cec3 95 dns = PICO_ZALLOC(sizeof(struct pico_dns_ns));
TASS Belgium NV 131:4758606c9316 96 if (!dns) {
TASS Belgium NV 131:4758606c9316 97 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 98 return NULL;
TASS Belgium NV 131:4758606c9316 99 }
TASS Belgium NV 131:4758606c9316 100
TASS Belgium NV 131:4758606c9316 101 dns->ns = *ns_addr;
tass 68:0847e35d08a6 102
TASS Belgium NV 131:4758606c9316 103 found = pico_tree_insert(&NSTable, dns);
TASS Belgium NV 131:4758606c9316 104 if (found) { /* nameserver already present */
tass picotcp@tass.be 149:5f4cb161cec3 105 PICO_FREE(dns);
TASS Belgium NV 131:4758606c9316 106 return found;
TASS Belgium NV 131:4758606c9316 107 }
tass 68:0847e35d08a6 108
TASS Belgium NV 131:4758606c9316 109 /* default NS found, remove it */
tass picotcp@tass.be 149:5f4cb161cec3 110 pico_string_to_ipv4(PICO_DNS_NS_DEFAULT, (uint32_t *)&test.ns.addr);
TASS Belgium NV 131:4758606c9316 111 found = pico_tree_findKey(&NSTable, &test);
TASS Belgium NV 131:4758606c9316 112 if (found && (found->ns.addr != ns_addr->addr))
TASS Belgium NV 131:4758606c9316 113 pico_dns_client_del_ns(&found->ns);
tass 68:0847e35d08a6 114
TASS Belgium NV 131:4758606c9316 115 return dns;
tass 68:0847e35d08a6 116 }
tass 68:0847e35d08a6 117
tass 68:0847e35d08a6 118 static struct pico_dns_ns pico_dns_client_next_ns(struct pico_ip4 *ns_addr)
tass 68:0847e35d08a6 119 {
TASS Belgium NV 131:4758606c9316 120 struct pico_dns_ns dns = {{0}}, *nxtdns = NULL;
TASS Belgium NV 131:4758606c9316 121 struct pico_tree_node *node = NULL, *nxtnode = NULL;
tass 68:0847e35d08a6 122
TASS Belgium NV 131:4758606c9316 123 dns.ns = *ns_addr;
TASS Belgium NV 131:4758606c9316 124 node = pico_tree_findNode(&NSTable, &dns);
TASS Belgium NV 131:4758606c9316 125 if (!node)
TASS Belgium NV 131:4758606c9316 126 return dns; /* keep using current NS */
tass 68:0847e35d08a6 127
TASS Belgium NV 131:4758606c9316 128 nxtnode = pico_tree_next(node);
TASS Belgium NV 131:4758606c9316 129 nxtdns = nxtnode->keyValue;
TASS Belgium NV 131:4758606c9316 130 if (!nxtdns)
TASS Belgium NV 131:4758606c9316 131 nxtdns = (struct pico_dns_ns *)pico_tree_first(&NSTable);
TASS Belgium NV 131:4758606c9316 132
TASS Belgium NV 131:4758606c9316 133 return *nxtdns;
tass 68:0847e35d08a6 134 }
tass 68:0847e35d08a6 135
tass 152:a3d286bf94e5 136 static struct pico_dns_query *pico_dns_client_add_query(struct pico_dns_header *hdr, uint16_t len, struct pico_dns_question_suffix *suffix,
tass 68:0847e35d08a6 137 void (*callback)(char *, void *), void *arg)
tass 68:0847e35d08a6 138 {
TASS Belgium NV 131:4758606c9316 139 struct pico_dns_query *q = NULL, *found = NULL;
tass 68:0847e35d08a6 140
tass picotcp@tass.be 149:5f4cb161cec3 141 q = PICO_ZALLOC(sizeof(struct pico_dns_query));
TASS Belgium NV 131:4758606c9316 142 if (!q)
TASS Belgium NV 131:4758606c9316 143 return NULL;
tass 68:0847e35d08a6 144
TASS Belgium NV 131:4758606c9316 145 q->query = (char *)hdr;
TASS Belgium NV 131:4758606c9316 146 q->len = len;
TASS Belgium NV 131:4758606c9316 147 q->id = short_be(hdr->id);
TASS Belgium NV 131:4758606c9316 148 q->qtype = short_be(suffix->qtype);
TASS Belgium NV 131:4758606c9316 149 q->qclass = short_be(suffix->qclass);
TASS Belgium NV 131:4758606c9316 150 q->retrans = 1;
TASS Belgium NV 131:4758606c9316 151 q->q_ns = *((struct pico_dns_ns *)pico_tree_first(&NSTable));
TASS Belgium NV 131:4758606c9316 152 q->callback = callback;
TASS Belgium NV 131:4758606c9316 153 q->arg = arg;
TASS Belgium NV 131:4758606c9316 154 q->s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, &pico_dns_client_callback);
TASS Belgium NV 131:4758606c9316 155 if (!q->s) {
tass picotcp@tass.be 149:5f4cb161cec3 156 PICO_FREE(q);
TASS Belgium NV 131:4758606c9316 157 return NULL;
TASS Belgium NV 131:4758606c9316 158 }
tass 68:0847e35d08a6 159
TASS Belgium NV 131:4758606c9316 160 found = pico_tree_insert(&DNSTable, q);
TASS Belgium NV 131:4758606c9316 161 if (found) {
TASS Belgium NV 131:4758606c9316 162 pico_err = PICO_ERR_EAGAIN;
TASS Belgium NV 131:4758606c9316 163 pico_socket_close(q->s);
tass picotcp@tass.be 149:5f4cb161cec3 164 PICO_FREE(q);
TASS Belgium NV 131:4758606c9316 165 return NULL;
TASS Belgium NV 131:4758606c9316 166 }
tass 68:0847e35d08a6 167
TASS Belgium NV 131:4758606c9316 168 return q;
tass 68:0847e35d08a6 169 }
tass 68:0847e35d08a6 170
tass 68:0847e35d08a6 171 static int pico_dns_client_del_query(uint16_t id)
tass 68:0847e35d08a6 172 {
TASS Belgium NV 131:4758606c9316 173 struct pico_dns_query test = {
TASS Belgium NV 131:4758606c9316 174 0
TASS Belgium NV 131:4758606c9316 175 }, *found = NULL;
tass 68:0847e35d08a6 176
TASS Belgium NV 131:4758606c9316 177 test.id = id;
TASS Belgium NV 131:4758606c9316 178 found = pico_tree_findKey(&DNSTable, &test);
TASS Belgium NV 131:4758606c9316 179 if (!found)
TASS Belgium NV 131:4758606c9316 180 return -1;
tass 68:0847e35d08a6 181
tass picotcp@tass.be 149:5f4cb161cec3 182 PICO_FREE(found->query);
TASS Belgium NV 131:4758606c9316 183 pico_socket_close(found->s);
TASS Belgium NV 131:4758606c9316 184 pico_tree_delete(&DNSTable, found);
tass picotcp@tass.be 149:5f4cb161cec3 185 PICO_FREE(found);
TASS Belgium NV 131:4758606c9316 186 return 0;
tass 68:0847e35d08a6 187 }
tass 68:0847e35d08a6 188
tass 68:0847e35d08a6 189 static struct pico_dns_query *pico_dns_client_find_query(uint16_t id)
tass 68:0847e35d08a6 190 {
TASS Belgium NV 131:4758606c9316 191 struct pico_dns_query test = {
TASS Belgium NV 131:4758606c9316 192 0
TASS Belgium NV 131:4758606c9316 193 }, *found = NULL;
tass 68:0847e35d08a6 194
TASS Belgium NV 131:4758606c9316 195 test.id = id;
TASS Belgium NV 131:4758606c9316 196 found = pico_tree_findKey(&DNSTable, &test);
TASS Belgium NV 131:4758606c9316 197 if (found)
TASS Belgium NV 131:4758606c9316 198 return found;
TASS Belgium NV 131:4758606c9316 199 else
TASS Belgium NV 131:4758606c9316 200 return NULL;
tass 68:0847e35d08a6 201 }
tass 68:0847e35d08a6 202
tass 68:0847e35d08a6 203 /* seek end of string */
tass 68:0847e35d08a6 204 static char *pico_dns_client_seek(char *ptr)
tass 68:0847e35d08a6 205 {
TASS Belgium NV 131:4758606c9316 206 if (!ptr)
TASS Belgium NV 131:4758606c9316 207 return NULL;
tass 68:0847e35d08a6 208
tass picotcp@tass.be 134:cc4e6d2654d9 209 while (*ptr != 0)
tass picotcp@tass.be 134:cc4e6d2654d9 210 ptr++;
tass picotcp@tass.be 136:576dcbb16922 211 return ptr + 1;
tass 68:0847e35d08a6 212 }
tass 68:0847e35d08a6 213
tass 68:0847e35d08a6 214 static struct pico_dns_query *pico_dns_client_idcheck(uint16_t id)
tass 68:0847e35d08a6 215 {
TASS Belgium NV 131:4758606c9316 216 struct pico_dns_query test = {
TASS Belgium NV 131:4758606c9316 217 0
TASS Belgium NV 131:4758606c9316 218 };
tass 68:0847e35d08a6 219
TASS Belgium NV 131:4758606c9316 220 test.id = id;
TASS Belgium NV 131:4758606c9316 221 return pico_tree_findKey(&DNSTable, &test);
tass 68:0847e35d08a6 222 }
tass 68:0847e35d08a6 223
tass 152:a3d286bf94e5 224 static int pico_dns_client_query_header(struct pico_dns_header *hdr)
tass 68:0847e35d08a6 225 {
TASS Belgium NV 131:4758606c9316 226 uint16_t id = 0;
TASS Belgium NV 131:4758606c9316 227 uint8_t retry = 32;
tass 68:0847e35d08a6 228
TASS Belgium NV 131:4758606c9316 229 do {
TASS Belgium NV 131:4758606c9316 230 id = (uint16_t)(pico_rand() & 0xFFFFU);
TASS Belgium NV 131:4758606c9316 231 dns_dbg("DNS: generated id %u\n", id);
TASS Belgium NV 131:4758606c9316 232 } while (retry-- && pico_dns_client_idcheck(id));
TASS Belgium NV 131:4758606c9316 233 if (!retry)
TASS Belgium NV 131:4758606c9316 234 return -1;
tass 68:0847e35d08a6 235
tass 152:a3d286bf94e5 236 hdr->id = short_be(id);
tass 152:a3d286bf94e5 237 pico_dns_fill_packet_header(hdr, 1, 0, 0, 0); /* 1 question, 0 answers */
tass 68:0847e35d08a6 238
TASS Belgium NV 131:4758606c9316 239 return 0;
tass 68:0847e35d08a6 240 }
tass 68:0847e35d08a6 241
tass 152:a3d286bf94e5 242 static int pico_dns_client_check_header(struct pico_dns_header *pre)
tass 68:0847e35d08a6 243 {
TASS Belgium NV 131:4758606c9316 244 if (pre->qr != PICO_DNS_QR_RESPONSE || pre->opcode != PICO_DNS_OPCODE_QUERY || pre->rcode != PICO_DNS_RCODE_NO_ERROR) {
TASS Belgium NV 131:4758606c9316 245 dns_dbg("DNS ERROR: OPCODE %d | TC %d | RCODE %d\n", pre->opcode, pre->tc, pre->rcode);
TASS Belgium NV 131:4758606c9316 246 return -1;
TASS Belgium NV 131:4758606c9316 247 }
TASS Belgium NV 131:4758606c9316 248
TASS Belgium NV 131:4758606c9316 249 if (short_be(pre->ancount) < 1) {
TASS Belgium NV 131:4758606c9316 250 dns_dbg("DNS ERROR: ancount < 1\n");
TASS Belgium NV 131:4758606c9316 251 return -1;
TASS Belgium NV 131:4758606c9316 252 }
TASS Belgium NV 131:4758606c9316 253
TASS Belgium NV 131:4758606c9316 254 return 0;
tass 68:0847e35d08a6 255 }
tass 68:0847e35d08a6 256
tass 152:a3d286bf94e5 257 static int pico_dns_client_check_qsuffix(struct pico_dns_question_suffix *suf, struct pico_dns_query *q)
tass 68:0847e35d08a6 258 {
tass 152:a3d286bf94e5 259 if (!suf)
tass 152:a3d286bf94e5 260 return -1;
tass 152:a3d286bf94e5 261
TASS Belgium NV 131:4758606c9316 262 if (short_be(suf->qtype) != q->qtype || short_be(suf->qclass) != q->qclass) {
TASS Belgium NV 131:4758606c9316 263 dns_dbg("DNS ERROR: received qtype (%u) or qclass (%u) incorrect\n", short_be(suf->qtype), short_be(suf->qclass));
TASS Belgium NV 131:4758606c9316 264 return -1;
TASS Belgium NV 131:4758606c9316 265 }
TASS Belgium NV 131:4758606c9316 266
TASS Belgium NV 131:4758606c9316 267 return 0;
tass 68:0847e35d08a6 268 }
tass 68:0847e35d08a6 269
tass 152:a3d286bf94e5 270 static int pico_dns_client_check_url(struct pico_dns_header *resp, struct pico_dns_query *q)
tass 152:a3d286bf94e5 271 {
tass 152:a3d286bf94e5 272 char *recv_name = (char*)(resp) + sizeof(struct pico_dns_header) + PICO_DNS_LABEL_INITIAL;
tass 152:a3d286bf94e5 273 char *exp_name = (char *)(q->query) + sizeof(struct pico_dns_header) + PICO_DNS_LABEL_INITIAL;
tass 152:a3d286bf94e5 274 if (strcasecmp(recv_name, exp_name) != 0)
tass 152:a3d286bf94e5 275 return -1;
tass 152:a3d286bf94e5 276
tass 152:a3d286bf94e5 277 return 0;
tass 152:a3d286bf94e5 278 }
tass 152:a3d286bf94e5 279
tass 152:a3d286bf94e5 280 static int pico_dns_client_check_asuffix(struct pico_dns_record_suffix *suf, struct pico_dns_query *q)
tass 68:0847e35d08a6 281 {
tass picotcp@tass.be 149:5f4cb161cec3 282 if (!suf) {
tass picotcp@tass.be 149:5f4cb161cec3 283 pico_err = PICO_ERR_EINVAL;
tass picotcp@tass.be 149:5f4cb161cec3 284 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 285 }
tass picotcp@tass.be 149:5f4cb161cec3 286
tass 152:a3d286bf94e5 287 if (short_be(suf->rtype) != q->qtype || short_be(suf->rclass) != q->qclass) {
tass 152:a3d286bf94e5 288 dns_dbg("DNS WARNING: received qtype (%u) or qclass (%u) incorrect\n", short_be(suf->rtype), short_be(suf->rclass));
TASS Belgium NV 131:4758606c9316 289 return -1;
TASS Belgium NV 131:4758606c9316 290 }
TASS Belgium NV 131:4758606c9316 291
tass 152:a3d286bf94e5 292 if (long_be(suf->rttl) > PICO_DNS_MAX_TTL) {
tass 152:a3d286bf94e5 293 dns_dbg("DNS WARNING: received TTL (%u) > MAX (%u)\n", short_be(suf->rttl), PICO_DNS_MAX_TTL);
TASS Belgium NV 131:4758606c9316 294 return -1;
TASS Belgium NV 131:4758606c9316 295 }
TASS Belgium NV 131:4758606c9316 296
TASS Belgium NV 131:4758606c9316 297 return 0;
tass 68:0847e35d08a6 298 }
tass 68:0847e35d08a6 299
tass 152:a3d286bf94e5 300 static char *pico_dns_client_seek_suffix(char *suf, struct pico_dns_header *pre, struct pico_dns_query *q)
tass 68:0847e35d08a6 301 {
tass 152:a3d286bf94e5 302 struct pico_dns_record_suffix *asuffix = NULL;
TASS Belgium NV 131:4758606c9316 303 uint16_t comp = 0, compression = 0;
TASS Belgium NV 131:4758606c9316 304 uint16_t i = 0;
tass 152:a3d286bf94e5 305
tass picotcp@tass.be 149:5f4cb161cec3 306 if (!suf)
tass picotcp@tass.be 149:5f4cb161cec3 307 return NULL;
tass 68:0847e35d08a6 308
TASS Belgium NV 131:4758606c9316 309 while (i++ < short_be(pre->ancount)) {
tass 152:a3d286bf94e5 310 comp = short_from(suf);
TASS Belgium NV 131:4758606c9316 311 compression = short_be(comp);
TASS Belgium NV 131:4758606c9316 312 switch (compression >> 14)
TASS Belgium NV 131:4758606c9316 313 {
TASS Belgium NV 131:4758606c9316 314 case PICO_DNS_POINTER:
TASS Belgium NV 131:4758606c9316 315 while (compression >> 14 == PICO_DNS_POINTER) {
TASS Belgium NV 131:4758606c9316 316 dns_dbg("DNS: pointer\n");
tass 152:a3d286bf94e5 317 suf += sizeof(uint16_t);
tass 152:a3d286bf94e5 318 comp = short_from(suf);
TASS Belgium NV 131:4758606c9316 319 compression = short_be(comp);
TASS Belgium NV 131:4758606c9316 320 }
TASS Belgium NV 131:4758606c9316 321 break;
tass 68:0847e35d08a6 322
TASS Belgium NV 131:4758606c9316 323 case PICO_DNS_LABEL:
TASS Belgium NV 131:4758606c9316 324 dns_dbg("DNS: label\n");
tass 152:a3d286bf94e5 325 suf = pico_dns_client_seek(suf);
TASS Belgium NV 131:4758606c9316 326 break;
tass 68:0847e35d08a6 327
TASS Belgium NV 131:4758606c9316 328 default:
TASS Belgium NV 131:4758606c9316 329 dns_dbg("DNS ERROR: incorrect compression (%u) value\n", compression);
TASS Belgium NV 131:4758606c9316 330 return NULL;
TASS Belgium NV 131:4758606c9316 331 }
TASS Belgium NV 131:4758606c9316 332
tass 152:a3d286bf94e5 333 asuffix = (struct pico_dns_record_suffix *)suf;
tass picotcp@tass.be 149:5f4cb161cec3 334 if (!asuffix)
tass picotcp@tass.be 149:5f4cb161cec3 335 break;
tass picotcp@tass.be 149:5f4cb161cec3 336
TASS Belgium NV 131:4758606c9316 337 if (pico_dns_client_check_asuffix(asuffix, q) < 0) {
tass 152:a3d286bf94e5 338 suf += (sizeof(struct pico_dns_record_suffix) + short_be(asuffix->rdlength));
TASS Belgium NV 131:4758606c9316 339 continue;
TASS Belgium NV 131:4758606c9316 340 }
TASS Belgium NV 131:4758606c9316 341
tass 152:a3d286bf94e5 342 return suf;
tass 68:0847e35d08a6 343 }
TASS Belgium NV 131:4758606c9316 344 return NULL;
tass 68:0847e35d08a6 345 }
tass 68:0847e35d08a6 346
tass 68:0847e35d08a6 347 static int pico_dns_client_send(struct pico_dns_query *q)
tass 68:0847e35d08a6 348 {
tass picotcp@tass.be 149:5f4cb161cec3 349 uint16_t *paramID = PICO_ZALLOC(sizeof(uint16_t));
tass picotcp@tass.be 149:5f4cb161cec3 350 if (!paramID) {
tass picotcp@tass.be 149:5f4cb161cec3 351 pico_err = PICO_ERR_ENOMEM;
tass picotcp@tass.be 149:5f4cb161cec3 352 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 353 }
tass picotcp@tass.be 149:5f4cb161cec3 354
TASS Belgium NV 131:4758606c9316 355 dns_dbg("DNS: sending query to %08X\n", q->q_ns.ns.addr);
TASS Belgium NV 131:4758606c9316 356 if (!q->s)
TASS Belgium NV 131:4758606c9316 357 goto failure;
tass 68:0847e35d08a6 358
TASS Belgium NV 131:4758606c9316 359 if (pico_socket_connect(q->s, &q->q_ns.ns, short_be(PICO_DNS_NS_PORT)) < 0)
TASS Belgium NV 131:4758606c9316 360 goto failure;
tass 68:0847e35d08a6 361
TASS Belgium NV 131:4758606c9316 362 pico_socket_send(q->s, q->query, q->len);
TASS Belgium NV 131:4758606c9316 363 *paramID = q->id;
TASS Belgium NV 131:4758606c9316 364 pico_timer_add(PICO_DNS_CLIENT_RETRANS, pico_dns_client_retransmission, paramID);
TASS Belgium NV 131:4758606c9316 365
TASS Belgium NV 131:4758606c9316 366 return 0;
tass 74:c146c4e346c4 367
tass 74:c146c4e346c4 368 failure:
tass picotcp@tass.be 149:5f4cb161cec3 369 PICO_FREE(paramID);
TASS Belgium NV 131:4758606c9316 370 return -1;
tass 68:0847e35d08a6 371 }
tass 68:0847e35d08a6 372
tass 128:ae39e6e81531 373 static void pico_dns_client_retransmission(pico_time now, void *arg)
tass 68:0847e35d08a6 374 {
TASS Belgium NV 131:4758606c9316 375 struct pico_dns_query *q = NULL;
TASS Belgium NV 131:4758606c9316 376 struct pico_dns_query dummy;
TASS Belgium NV 131:4758606c9316 377 IGNORE_PARAMETER(now);
tass 68:0847e35d08a6 378
TASS Belgium NV 131:4758606c9316 379 if(!arg)
TASS Belgium NV 131:4758606c9316 380 return;
TASS Belgium NV 131:4758606c9316 381
TASS Belgium NV 131:4758606c9316 382 /* search for the dns query and free used space */
TASS Belgium NV 131:4758606c9316 383 dummy.id = *(uint16_t *)arg;
TASS Belgium NV 131:4758606c9316 384 q = (struct pico_dns_query *)pico_tree_findKey(&DNSTable, &dummy);
tass picotcp@tass.be 149:5f4cb161cec3 385 PICO_FREE(arg);
tass 68:0847e35d08a6 386
TASS Belgium NV 131:4758606c9316 387 /* dns query successful? */
TASS Belgium NV 131:4758606c9316 388 if (!q) {
TASS Belgium NV 131:4758606c9316 389 return;
TASS Belgium NV 131:4758606c9316 390 }
tass 68:0847e35d08a6 391
tass 152:a3d286bf94e5 392 q->retrans++;
tass 152:a3d286bf94e5 393 if (q->retrans <= PICO_DNS_CLIENT_MAX_RETRANS) {
TASS Belgium NV 131:4758606c9316 394 q->q_ns = pico_dns_client_next_ns(&q->q_ns.ns);
TASS Belgium NV 131:4758606c9316 395 pico_dns_client_send(q);
TASS Belgium NV 131:4758606c9316 396 } else {
TASS Belgium NV 131:4758606c9316 397 pico_err = PICO_ERR_EIO;
TASS Belgium NV 131:4758606c9316 398 q->callback(NULL, q->arg);
TASS Belgium NV 131:4758606c9316 399 pico_dns_client_del_query(q->id);
TASS Belgium NV 131:4758606c9316 400 }
tass 68:0847e35d08a6 401 }
tass 68:0847e35d08a6 402
tass 152:a3d286bf94e5 403 static int pico_dns_client_user_callback(struct pico_dns_record_suffix *asuffix, struct pico_dns_query *q)
tass 68:0847e35d08a6 404 {
TASS Belgium NV 131:4758606c9316 405 uint32_t ip = 0;
TASS Belgium NV 131:4758606c9316 406 char *str = NULL;
tass 152:a3d286bf94e5 407 char *rdata = (char *) asuffix + sizeof(struct pico_dns_record_suffix);
TASS Belgium NV 131:4758606c9316 408
TASS Belgium NV 131:4758606c9316 409 switch (q->qtype)
TASS Belgium NV 131:4758606c9316 410 {
tass 68:0847e35d08a6 411 case PICO_DNS_TYPE_A:
tass 152:a3d286bf94e5 412 ip = long_from(rdata);
tass picotcp@tass.be 149:5f4cb161cec3 413 str = PICO_ZALLOC(PICO_DNS_IPV4_ADDR_LEN);
TASS Belgium NV 131:4758606c9316 414 pico_ipv4_to_string(str, ip);
TASS Belgium NV 131:4758606c9316 415 break;
tass picotcp@tass.be 149:5f4cb161cec3 416 #ifdef PICO_SUPPORT_IPV6
tass picotcp@tass.be 149:5f4cb161cec3 417 case PICO_DNS_TYPE_AAAA:
tass picotcp@tass.be 149:5f4cb161cec3 418 {
tass picotcp@tass.be 149:5f4cb161cec3 419 struct pico_ip6 ip6;
tass 152:a3d286bf94e5 420 memcpy(&ip6.addr, rdata, sizeof(struct pico_ip6));
tass picotcp@tass.be 149:5f4cb161cec3 421 str = PICO_ZALLOC(PICO_DNS_IPV6_ADDR_LEN);
tass picotcp@tass.be 149:5f4cb161cec3 422 pico_ipv6_to_string(str, ip6.addr);
tass picotcp@tass.be 149:5f4cb161cec3 423 break;
tass picotcp@tass.be 149:5f4cb161cec3 424 }
tass picotcp@tass.be 149:5f4cb161cec3 425 #endif
tass 68:0847e35d08a6 426 case PICO_DNS_TYPE_PTR:
tass 152:a3d286bf94e5 427 /* TODO: check for decompression / rdlength vs. decompressed length */
tass 152:a3d286bf94e5 428 pico_dns_notation_to_name(rdata, short_be(asuffix->rdlength));
tass 152:a3d286bf94e5 429 str = PICO_ZALLOC((size_t)(short_be(asuffix->rdlength) -
tass 152:a3d286bf94e5 430 PICO_DNS_LABEL_INITIAL));
tass picotcp@tass.be 149:5f4cb161cec3 431 if (!str) {
tass picotcp@tass.be 149:5f4cb161cec3 432 pico_err = PICO_ERR_ENOMEM;
tass picotcp@tass.be 149:5f4cb161cec3 433 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 434 }
tass picotcp@tass.be 149:5f4cb161cec3 435
tass 152:a3d286bf94e5 436 memcpy(str, rdata + PICO_DNS_LABEL_INITIAL, short_be(asuffix->rdlength) - PICO_DNS_LABEL_INITIAL);
TASS Belgium NV 131:4758606c9316 437 break;
tass 68:0847e35d08a6 438
tass 68:0847e35d08a6 439 default:
TASS Belgium NV 131:4758606c9316 440 dns_dbg("DNS ERROR: incorrect qtype (%u)\n", q->qtype);
TASS Belgium NV 131:4758606c9316 441 break;
TASS Belgium NV 131:4758606c9316 442 }
tass 68:0847e35d08a6 443
TASS Belgium NV 131:4758606c9316 444 if (q->retrans) {
TASS Belgium NV 131:4758606c9316 445 q->callback(str, q->arg);
TASS Belgium NV 131:4758606c9316 446 q->retrans = 0;
TASS Belgium NV 131:4758606c9316 447 pico_dns_client_del_query(q->id);
TASS Belgium NV 131:4758606c9316 448 }
TASS Belgium NV 131:4758606c9316 449
tass 152:a3d286bf94e5 450 if (str)
tass 152:a3d286bf94e5 451 PICO_FREE(str);
tass 152:a3d286bf94e5 452
TASS Belgium NV 131:4758606c9316 453 return 0;
tass 68:0847e35d08a6 454 }
tass 68:0847e35d08a6 455
tass 152:a3d286bf94e5 456 static char dns_response[PICO_IP_MRU] = {
tass 152:a3d286bf94e5 457 0
tass 152:a3d286bf94e5 458 };
tass 152:a3d286bf94e5 459
tass 152:a3d286bf94e5 460 static void pico_dns_try_fallback_cname(struct pico_dns_query *q, struct pico_dns_header *h, struct pico_dns_question_suffix *qsuffix)
tass 152:a3d286bf94e5 461 {
tass 152:a3d286bf94e5 462 uint16_t type = q->qtype;
tass 152:a3d286bf94e5 463 uint16_t proto = PICO_PROTO_IPV4;
tass 152:a3d286bf94e5 464 struct pico_dns_record_suffix *asuffix = NULL;
tass 152:a3d286bf94e5 465 char *p_asuffix = NULL;
tass 152:a3d286bf94e5 466 char *cname_orig = NULL;
tass 152:a3d286bf94e5 467 char *cname = NULL;
tass 152:a3d286bf94e5 468 uint16_t cname_len;
tass 152:a3d286bf94e5 469
tass 152:a3d286bf94e5 470 /* Try to use CNAME only if A or AAAA query is ongoing */
tass 152:a3d286bf94e5 471 if (type != PICO_DNS_TYPE_A && type != PICO_DNS_TYPE_AAAA)
tass 152:a3d286bf94e5 472 return;
tass 152:a3d286bf94e5 473
tass 152:a3d286bf94e5 474 if (type == PICO_DNS_TYPE_AAAA)
tass 152:a3d286bf94e5 475 proto = PICO_PROTO_IPV6;
tass 152:a3d286bf94e5 476
tass 152:a3d286bf94e5 477 q->qtype = PICO_DNS_TYPE_CNAME;
tass 152:a3d286bf94e5 478 p_asuffix = (char *)qsuffix + sizeof(struct pico_dns_question_suffix);
tass 152:a3d286bf94e5 479 p_asuffix = pico_dns_client_seek_suffix(p_asuffix, h, q);
tass 152:a3d286bf94e5 480 if (!p_asuffix) {
tass 152:a3d286bf94e5 481 return;
tass 152:a3d286bf94e5 482 }
tass 152:a3d286bf94e5 483
tass 152:a3d286bf94e5 484 /* Found CNAME response. Re-initiating query. */
tass 152:a3d286bf94e5 485 asuffix = (struct pico_dns_record_suffix *)p_asuffix;
tass 152:a3d286bf94e5 486 cname = pico_dns_decompress_name((char *)asuffix + sizeof(struct pico_dns_record_suffix), (pico_dns_packet *)h); /* allocates memory! */
tass 152:a3d286bf94e5 487 cname_orig = cname; /* to free later */
tass 152:a3d286bf94e5 488
tass 152:a3d286bf94e5 489 if (cname == NULL)
tass 152:a3d286bf94e5 490 return;
tass 152:a3d286bf94e5 491
tass 152:a3d286bf94e5 492 cname_len = (uint16_t)(pico_dns_strlen(cname) + 1);
tass 152:a3d286bf94e5 493
tass 152:a3d286bf94e5 494 pico_dns_notation_to_name(cname, cname_len);
tass 152:a3d286bf94e5 495 if (cname[0] == '.')
tass 152:a3d286bf94e5 496 cname++;
tass 152:a3d286bf94e5 497
tass 152:a3d286bf94e5 498 dns_dbg("Restarting query for name '%s'\n", cname);
tass 152:a3d286bf94e5 499 pico_dns_client_getaddr_init(cname, proto, q->callback, q->arg);
tass 152:a3d286bf94e5 500 PICO_FREE(cname_orig);
tass 152:a3d286bf94e5 501 pico_dns_client_del_query(q->id);
tass 152:a3d286bf94e5 502 }
tass 152:a3d286bf94e5 503
tass 68:0847e35d08a6 504 static void pico_dns_client_callback(uint16_t ev, struct pico_socket *s)
tass 68:0847e35d08a6 505 {
tass 152:a3d286bf94e5 506 struct pico_dns_header *header = NULL;
tass 152:a3d286bf94e5 507 char *domain;
tass 152:a3d286bf94e5 508 struct pico_dns_question_suffix *qsuffix = NULL;
tass 152:a3d286bf94e5 509 struct pico_dns_record_suffix *asuffix = NULL;
TASS Belgium NV 131:4758606c9316 510 struct pico_dns_query *q = NULL;
TASS Belgium NV 131:4758606c9316 511 char *p_asuffix = NULL;
tass 68:0847e35d08a6 512
TASS Belgium NV 131:4758606c9316 513 if (ev == PICO_SOCK_EV_ERR) {
TASS Belgium NV 131:4758606c9316 514 dns_dbg("DNS: socket error received\n");
TASS Belgium NV 131:4758606c9316 515 return;
TASS Belgium NV 131:4758606c9316 516 }
tass 68:0847e35d08a6 517
TASS Belgium NV 131:4758606c9316 518 if (ev & PICO_SOCK_EV_RD) {
tass 152:a3d286bf94e5 519 if (pico_socket_read(s, dns_response, PICO_IP_MRU) < 0)
TASS Belgium NV 131:4758606c9316 520 return;
TASS Belgium NV 131:4758606c9316 521 }
tass 68:0847e35d08a6 522
tass 152:a3d286bf94e5 523 header = (struct pico_dns_header *)dns_response;
tass 152:a3d286bf94e5 524 domain = (char *)header + sizeof(struct pico_dns_header);
tass 152:a3d286bf94e5 525 qsuffix = (struct pico_dns_question_suffix *)pico_dns_client_seek(domain);
TASS Belgium NV 131:4758606c9316 526 /* valid asuffix is determined dynamically later on */
TASS Belgium NV 131:4758606c9316 527
tass 152:a3d286bf94e5 528 if (pico_dns_client_check_header(header) < 0)
TASS Belgium NV 131:4758606c9316 529 return;
TASS Belgium NV 131:4758606c9316 530
tass 152:a3d286bf94e5 531 q = pico_dns_client_find_query(short_be(header->id));
TASS Belgium NV 131:4758606c9316 532 if (!q)
TASS Belgium NV 131:4758606c9316 533 return;
tass 68:0847e35d08a6 534
TASS Belgium NV 131:4758606c9316 535 if (pico_dns_client_check_qsuffix(qsuffix, q) < 0)
TASS Belgium NV 131:4758606c9316 536 return;
TASS Belgium NV 131:4758606c9316 537
tass 152:a3d286bf94e5 538 if (pico_dns_client_check_url(header, q) < 0)
TASS Belgium NV 131:4758606c9316 539 return;
TASS Belgium NV 131:4758606c9316 540
tass 152:a3d286bf94e5 541 p_asuffix = (char *)qsuffix + sizeof(struct pico_dns_question_suffix);
tass 152:a3d286bf94e5 542 p_asuffix = pico_dns_client_seek_suffix(p_asuffix, header, q);
tass 152:a3d286bf94e5 543 if (!p_asuffix) {
tass 152:a3d286bf94e5 544 pico_dns_try_fallback_cname(q, header, qsuffix);
tass 152:a3d286bf94e5 545 return;
tass 152:a3d286bf94e5 546 }
tass 152:a3d286bf94e5 547
tass 152:a3d286bf94e5 548 asuffix = (struct pico_dns_record_suffix *)p_asuffix;
TASS Belgium NV 131:4758606c9316 549 pico_dns_client_user_callback(asuffix, q);
TASS Belgium NV 131:4758606c9316 550
tass 68:0847e35d08a6 551 return;
tass 68:0847e35d08a6 552 }
tass 68:0847e35d08a6 553
tass 152:a3d286bf94e5 554 static int pico_dns_create_message(struct pico_dns_header **header, struct pico_dns_question_suffix **qsuffix, enum pico_dns_arpa arpa, const char *url, uint16_t *urlen, uint16_t *hdrlen)
tass 68:0847e35d08a6 555 {
tass 152:a3d286bf94e5 556 char *domain;
tass 152:a3d286bf94e5 557 char inaddr_arpa[14];
tass 152:a3d286bf94e5 558 uint16_t strlen = 0, arpalen = 0;
tass 152:a3d286bf94e5 559
tass 152:a3d286bf94e5 560 if (!url) {
tass 152:a3d286bf94e5 561 pico_err = PICO_ERR_EINVAL;
tass 152:a3d286bf94e5 562 return -1;
tass 152:a3d286bf94e5 563 }
tass 152:a3d286bf94e5 564
tass 152:a3d286bf94e5 565 if(arpa == PICO_DNS_ARPA4) {
tass 152:a3d286bf94e5 566 strcpy(inaddr_arpa, ".in-addr.arpa");
tass 152:a3d286bf94e5 567 strlen = pico_dns_strlen(url);
tass 152:a3d286bf94e5 568 }
tass 152:a3d286bf94e5 569
tass 152:a3d286bf94e5 570 #ifdef PICO_SUPPORT_IPV6
tass 152:a3d286bf94e5 571 else if (arpa == PICO_DNS_ARPA6) {
tass 152:a3d286bf94e5 572 strcpy(inaddr_arpa, ".IP6.ARPA");
tass 152:a3d286bf94e5 573 strlen = STRLEN_PTR_IP6;
tass 152:a3d286bf94e5 574 }
tass 152:a3d286bf94e5 575 #endif
tass 152:a3d286bf94e5 576 else {
tass 152:a3d286bf94e5 577 strcpy(inaddr_arpa, "");
tass 152:a3d286bf94e5 578 strlen = pico_dns_strlen(url);
tass 152:a3d286bf94e5 579 }
tass 152:a3d286bf94e5 580
tass 152:a3d286bf94e5 581 arpalen = pico_dns_strlen(inaddr_arpa);
tass 152:a3d286bf94e5 582 *urlen = (uint16_t)(PICO_DNS_LABEL_INITIAL + strlen + arpalen + PICO_DNS_LABEL_ROOT);
tass 152:a3d286bf94e5 583 *hdrlen = (uint16_t)(sizeof(struct pico_dns_header) + *urlen + sizeof(struct pico_dns_question_suffix));
tass 152:a3d286bf94e5 584 *header = PICO_ZALLOC(*hdrlen);
tass 152:a3d286bf94e5 585 if (!*header) {
tass 152:a3d286bf94e5 586 pico_err = PICO_ERR_ENOMEM;
tass 152:a3d286bf94e5 587 return -1;
tass 152:a3d286bf94e5 588 }
tass 152:a3d286bf94e5 589
tass 152:a3d286bf94e5 590 *header = (struct pico_dns_header *)*header;
tass 152:a3d286bf94e5 591 domain = (char *) *header + sizeof(struct pico_dns_header);
tass 152:a3d286bf94e5 592 *qsuffix = (struct pico_dns_question_suffix *)(domain + *urlen);
tass 152:a3d286bf94e5 593
tass 152:a3d286bf94e5 594 if(arpa == PICO_DNS_ARPA4) {
tass 152:a3d286bf94e5 595 memcpy(domain + PICO_DNS_LABEL_INITIAL, url, strlen);
tass 152:a3d286bf94e5 596 pico_dns_mirror_addr(domain + PICO_DNS_LABEL_INITIAL);
tass 152:a3d286bf94e5 597 memcpy(domain + PICO_DNS_LABEL_INITIAL + strlen, inaddr_arpa, arpalen);
tass 152:a3d286bf94e5 598 }
tass 68:0847e35d08a6 599
tass 152:a3d286bf94e5 600 #ifdef PICO_SUPPORT_IPV6
tass 152:a3d286bf94e5 601 else if (arpa == PICO_DNS_ARPA6) {
tass 152:a3d286bf94e5 602 pico_dns_ipv6_set_ptr(url, domain + PICO_DNS_LABEL_INITIAL);
tass 152:a3d286bf94e5 603 memcpy(domain + PICO_DNS_LABEL_INITIAL + STRLEN_PTR_IP6, inaddr_arpa, arpalen);
tass 152:a3d286bf94e5 604 }
tass 152:a3d286bf94e5 605 #endif
tass 152:a3d286bf94e5 606 else {
tass 152:a3d286bf94e5 607 memcpy(domain + PICO_DNS_LABEL_INITIAL, url, strlen);
tass 152:a3d286bf94e5 608 }
tass 152:a3d286bf94e5 609
tass 152:a3d286bf94e5 610 /* assemble dns message */
tass 152:a3d286bf94e5 611 pico_dns_client_query_header(*header);
tass 152:a3d286bf94e5 612 pico_dns_name_to_dns_notation(domain, strlen);
tass 152:a3d286bf94e5 613
tass 152:a3d286bf94e5 614 return 0;
tass 152:a3d286bf94e5 615 }
tass 152:a3d286bf94e5 616
tass 152:a3d286bf94e5 617 static int pico_dns_client_addr_label_check_len(const char *url)
tass 152:a3d286bf94e5 618 {
tass 152:a3d286bf94e5 619 const char *p, *label;
tass 152:a3d286bf94e5 620 int count;
tass 152:a3d286bf94e5 621 label = url;
tass 152:a3d286bf94e5 622 p = label;
tass 152:a3d286bf94e5 623
tass 152:a3d286bf94e5 624 while(*p != (char) 0) {
tass 152:a3d286bf94e5 625 count = 0;
tass 152:a3d286bf94e5 626 while((*p != (char)0)) {
tass 152:a3d286bf94e5 627 if (*p == '.') {
tass 152:a3d286bf94e5 628 label = ++p;
tass 152:a3d286bf94e5 629 break;
tass 152:a3d286bf94e5 630 }
tass 152:a3d286bf94e5 631
tass 152:a3d286bf94e5 632 count++;
tass 152:a3d286bf94e5 633 p++;
tass 152:a3d286bf94e5 634 if (count > PICO_DNS_MAX_QUERY_LABEL_LEN)
tass 152:a3d286bf94e5 635 return -1;
tass 152:a3d286bf94e5 636 }
tass 152:a3d286bf94e5 637 }
tass 152:a3d286bf94e5 638 return 0;
tass 152:a3d286bf94e5 639 }
tass 152:a3d286bf94e5 640
tass 152:a3d286bf94e5 641 static int pico_dns_client_getaddr_check(const char *url, void (*callback)(char *, void *))
tass 152:a3d286bf94e5 642 {
TASS Belgium NV 131:4758606c9316 643 if (!url || !callback) {
TASS Belgium NV 131:4758606c9316 644 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 645 return -1;
TASS Belgium NV 131:4758606c9316 646 }
TASS Belgium NV 131:4758606c9316 647
tass 152:a3d286bf94e5 648 if (strlen(url) > PICO_DNS_MAX_QUERY_LEN) {
tass 152:a3d286bf94e5 649 pico_err = PICO_ERR_EINVAL;
tass 152:a3d286bf94e5 650 return -1;
tass 152:a3d286bf94e5 651 }
tass 152:a3d286bf94e5 652
tass 152:a3d286bf94e5 653 if (pico_dns_client_addr_label_check_len(url) < 0) {
tass 152:a3d286bf94e5 654 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 655 return -1;
TASS Belgium NV 131:4758606c9316 656 }
tass 68:0847e35d08a6 657
tass 152:a3d286bf94e5 658 return 0;
tass 152:a3d286bf94e5 659 }
TASS Belgium NV 131:4758606c9316 660
tass 152:a3d286bf94e5 661 static int pico_dns_client_getaddr_init(const char *url, uint16_t proto, void (*callback)(char *, void *), void *arg)
tass 152:a3d286bf94e5 662 {
tass 152:a3d286bf94e5 663 struct pico_dns_header *header = NULL;
tass 152:a3d286bf94e5 664 struct pico_dns_question_suffix *qsuffix = NULL;
tass 152:a3d286bf94e5 665 struct pico_dns_query *q = NULL;
tass 152:a3d286bf94e5 666 uint16_t len = 0, lblen = 0;
tass 152:a3d286bf94e5 667 (void)proto;
tass 152:a3d286bf94e5 668
tass 152:a3d286bf94e5 669 if (pico_dns_client_getaddr_check(url, callback) < 0)
tass 152:a3d286bf94e5 670 return -1;
tass 152:a3d286bf94e5 671
tass 152:a3d286bf94e5 672 if(pico_dns_create_message(&header, &qsuffix, PICO_DNS_NO_ARPA, url, &lblen, &len) != 0)
tass 152:a3d286bf94e5 673 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 674
tass picotcp@tass.be 149:5f4cb161cec3 675 #ifdef PICO_SUPPORT_IPV6
tass picotcp@tass.be 149:5f4cb161cec3 676 if (proto == PICO_PROTO_IPV6) {
tass 152:a3d286bf94e5 677 pico_dns_question_fill_suffix(qsuffix, PICO_DNS_TYPE_AAAA, PICO_DNS_CLASS_IN);
tass picotcp@tass.be 149:5f4cb161cec3 678 } else
tass picotcp@tass.be 149:5f4cb161cec3 679 #endif
tass 152:a3d286bf94e5 680 pico_dns_question_fill_suffix(qsuffix, PICO_DNS_TYPE_A, PICO_DNS_CLASS_IN);
tass 68:0847e35d08a6 681
tass 152:a3d286bf94e5 682 q = pico_dns_client_add_query(header, len, qsuffix, callback, arg);
TASS Belgium NV 131:4758606c9316 683 if (!q) {
tass 152:a3d286bf94e5 684 PICO_FREE(header);
TASS Belgium NV 131:4758606c9316 685 return -1;
TASS Belgium NV 131:4758606c9316 686 }
tass 68:0847e35d08a6 687
TASS Belgium NV 131:4758606c9316 688 if (pico_dns_client_send(q) < 0) {
TASS Belgium NV 131:4758606c9316 689 pico_dns_client_del_query(q->id); /* frees msg */
TASS Belgium NV 131:4758606c9316 690 return -1;
TASS Belgium NV 131:4758606c9316 691 }
tass 68:0847e35d08a6 692
TASS Belgium NV 131:4758606c9316 693 return 0;
tass 68:0847e35d08a6 694 }
tass 68:0847e35d08a6 695
tass picotcp@tass.be 149:5f4cb161cec3 696 int pico_dns_client_getaddr(const char *url, void (*callback)(char *, void *), void *arg)
tass picotcp@tass.be 149:5f4cb161cec3 697 {
tass picotcp@tass.be 149:5f4cb161cec3 698 return pico_dns_client_getaddr_init(url, PICO_PROTO_IPV4, callback, arg);
tass picotcp@tass.be 149:5f4cb161cec3 699 }
tass picotcp@tass.be 149:5f4cb161cec3 700
tass picotcp@tass.be 149:5f4cb161cec3 701 int pico_dns_client_getaddr6(const char *url, void (*callback)(char *, void *), void *arg)
tass picotcp@tass.be 149:5f4cb161cec3 702 {
tass picotcp@tass.be 149:5f4cb161cec3 703 return pico_dns_client_getaddr_init(url, PICO_PROTO_IPV6, callback, arg);
tass picotcp@tass.be 149:5f4cb161cec3 704 }
tass picotcp@tass.be 149:5f4cb161cec3 705
tass 152:a3d286bf94e5 706 static int pico_dns_getname_univ(const char *ip, void (*callback)(char *, void *), void *arg, enum pico_dns_arpa arpa)
tass 68:0847e35d08a6 707 {
tass 152:a3d286bf94e5 708 struct pico_dns_header *header = NULL;
tass 152:a3d286bf94e5 709 struct pico_dns_question_suffix *qsuffix = NULL;
TASS Belgium NV 131:4758606c9316 710 struct pico_dns_query *q = NULL;
tass 152:a3d286bf94e5 711 uint16_t len = 0, lblen = 0;
tass 68:0847e35d08a6 712
TASS Belgium NV 131:4758606c9316 713 if (!ip || !callback) {
TASS Belgium NV 131:4758606c9316 714 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 715 return -1;
TASS Belgium NV 131:4758606c9316 716 }
TASS Belgium NV 131:4758606c9316 717
tass 152:a3d286bf94e5 718 if(pico_dns_create_message(&header, &qsuffix, arpa, ip, &lblen, &len) != 0)
TASS Belgium NV 131:4758606c9316 719 return -1;
tass 68:0847e35d08a6 720
tass 152:a3d286bf94e5 721 pico_dns_question_fill_suffix(qsuffix, PICO_DNS_TYPE_PTR, PICO_DNS_CLASS_IN);
tass 152:a3d286bf94e5 722 q = pico_dns_client_add_query(header, len, qsuffix, callback, arg);
TASS Belgium NV 131:4758606c9316 723 if (!q) {
tass 152:a3d286bf94e5 724 PICO_FREE(header);
TASS Belgium NV 131:4758606c9316 725 return -1;
TASS Belgium NV 131:4758606c9316 726 }
tass 68:0847e35d08a6 727
TASS Belgium NV 131:4758606c9316 728 if (pico_dns_client_send(q) < 0) {
tass 152:a3d286bf94e5 729 pico_dns_client_del_query(q->id); /* frees header */
TASS Belgium NV 131:4758606c9316 730 return -1;
TASS Belgium NV 131:4758606c9316 731 }
tass 68:0847e35d08a6 732
TASS Belgium NV 131:4758606c9316 733 return 0;
tass 68:0847e35d08a6 734 }
tass 68:0847e35d08a6 735
tass 152:a3d286bf94e5 736 int pico_dns_client_getname(const char *ip, void (*callback)(char *, void *), void *arg)
tass picotcp@tass.be 149:5f4cb161cec3 737 {
tass 152:a3d286bf94e5 738 return pico_dns_getname_univ(ip, callback, arg, PICO_DNS_ARPA4);
tass picotcp@tass.be 149:5f4cb161cec3 739 }
tass picotcp@tass.be 149:5f4cb161cec3 740
tass picotcp@tass.be 149:5f4cb161cec3 741
tass picotcp@tass.be 149:5f4cb161cec3 742 int pico_dns_client_getname6(const char *ip, void (*callback)(char *, void *), void *arg)
tass picotcp@tass.be 149:5f4cb161cec3 743 {
tass 152:a3d286bf94e5 744 return pico_dns_getname_univ(ip, callback, arg, PICO_DNS_ARPA6);
tass picotcp@tass.be 149:5f4cb161cec3 745 }
tass picotcp@tass.be 149:5f4cb161cec3 746
tass 68:0847e35d08a6 747 int pico_dns_client_nameserver(struct pico_ip4 *ns, uint8_t flag)
tass 68:0847e35d08a6 748 {
TASS Belgium NV 131:4758606c9316 749 if (!ns) {
TASS Belgium NV 131:4758606c9316 750 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 751 return -1;
TASS Belgium NV 131:4758606c9316 752 }
tass 68:0847e35d08a6 753
TASS Belgium NV 131:4758606c9316 754 switch (flag)
TASS Belgium NV 131:4758606c9316 755 {
tass 68:0847e35d08a6 756 case PICO_DNS_NS_ADD:
TASS Belgium NV 131:4758606c9316 757 if (!pico_dns_client_add_ns(ns))
TASS Belgium NV 131:4758606c9316 758 return -1;
TASS Belgium NV 131:4758606c9316 759
TASS Belgium NV 131:4758606c9316 760 break;
tass 68:0847e35d08a6 761
tass 68:0847e35d08a6 762 case PICO_DNS_NS_DEL:
TASS Belgium NV 131:4758606c9316 763 if (pico_dns_client_del_ns(ns) < 0) {
TASS Belgium NV 131:4758606c9316 764 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 765 return -1;
TASS Belgium NV 131:4758606c9316 766 }
TASS Belgium NV 131:4758606c9316 767
TASS Belgium NV 131:4758606c9316 768 break;
TASS Belgium NV 131:4758606c9316 769
TASS Belgium NV 131:4758606c9316 770 default:
tass 68:0847e35d08a6 771 pico_err = PICO_ERR_EINVAL;
tass 68:0847e35d08a6 772 return -1;
TASS Belgium NV 131:4758606c9316 773 }
TASS Belgium NV 131:4758606c9316 774 return 0;
tass 68:0847e35d08a6 775 }
tass 68:0847e35d08a6 776
tass picotcp@tass.be 134:cc4e6d2654d9 777 int pico_dns_client_init(void)
tass 68:0847e35d08a6 778 {
TASS Belgium NV 131:4758606c9316 779 struct pico_ip4 default_ns = {
TASS Belgium NV 131:4758606c9316 780 0
TASS Belgium NV 131:4758606c9316 781 };
tass 68:0847e35d08a6 782
tass picotcp@tass.be 149:5f4cb161cec3 783 if (pico_string_to_ipv4(PICO_DNS_NS_DEFAULT, (uint32_t *)&default_ns.addr) < 0)
TASS Belgium NV 131:4758606c9316 784 return -1;
tass 68:0847e35d08a6 785
TASS Belgium NV 131:4758606c9316 786 return pico_dns_client_nameserver(&default_ns, PICO_DNS_NS_ADD);
tass 68:0847e35d08a6 787 }
tass 68:0847e35d08a6 788
tass 152:a3d286bf94e5 789 #else
tass 152:a3d286bf94e5 790
tass 152:a3d286bf94e5 791 int pico_dns_client_init(void)
tass 152:a3d286bf94e5 792 {
tass 152:a3d286bf94e5 793 dbg("ERROR Trying to initialize DNS module: IPv4 not supported in this build.\n");
tass 152:a3d286bf94e5 794 return -1;
tass 152:a3d286bf94e5 795 }
tass 152:a3d286bf94e5 796 #endif /* PICO_SUPPORT_IPV4 */
tass 152:a3d286bf94e5 797
tass 152:a3d286bf94e5 798
tass 68:0847e35d08a6 799 #endif /* PICO_SUPPORT_DNS_CLIENT */
tass 152:a3d286bf94e5 800