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 picotcp@tass.be
Date:
Thu Jan 16 14:46:07 2014 +0100
Revision:
134:cc4e6d2654d9
Parent:
131:4758606c9316
Child:
136:576dcbb16922
Update from masterbranch

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