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:
Fri Feb 07 11:21:12 2014 +0100
Revision:
137:a1c8bfa9d691
Parent:
136:576dcbb16922
Child:
149:5f4cb161cec3
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 136:576dcbb16922 294 if (!url)
tass picotcp@tass.be 136:576dcbb16922 295 return 0;
tass picotcp@tass.be 136:576dcbb16922 296
tass picotcp@tass.be 137:a1c8bfa9d691 297 for (len = 0; len < 0xFFFF; len++) {
tass picotcp@tass.be 134:cc4e6d2654d9 298 if (url[len] == 0)
tass picotcp@tass.be 134:cc4e6d2654d9 299 break;
TASS Belgium NV 131:4758606c9316 300 }
TASS Belgium NV 131:4758606c9316 301 return len;
tass 68:0847e35d08a6 302 }
tass 68:0847e35d08a6 303
tass 68:0847e35d08a6 304 /* seek end of string */
tass 68:0847e35d08a6 305 static char *pico_dns_client_seek(char *ptr)
tass 68:0847e35d08a6 306 {
TASS Belgium NV 131:4758606c9316 307 if (!ptr)
TASS Belgium NV 131:4758606c9316 308 return NULL;
tass 68:0847e35d08a6 309
tass picotcp@tass.be 134:cc4e6d2654d9 310 while (*ptr != 0)
tass picotcp@tass.be 134:cc4e6d2654d9 311 ptr++;
tass picotcp@tass.be 136:576dcbb16922 312 return ptr + 1;
tass 68:0847e35d08a6 313 }
tass 68:0847e35d08a6 314
tass 68:0847e35d08a6 315 /* mirror ip address numbers
tass 68:0847e35d08a6 316 * f.e. 192.168.0.1 => 1.0.168.192 */
tass 70:cd218dd180e5 317 static int8_t pico_dns_client_mirror(char *ptr)
tass 68:0847e35d08a6 318 {
TASS Belgium NV 131:4758606c9316 319 const unsigned char *addr = NULL;
TASS Belgium NV 131:4758606c9316 320 char *m = ptr;
TASS Belgium NV 131:4758606c9316 321 uint32_t ip = 0;
TASS Belgium NV 131:4758606c9316 322 int8_t i = 0;
tass 68:0847e35d08a6 323
TASS Belgium NV 131:4758606c9316 324 if (pico_string_to_ipv4(ptr, &ip) < 0)
TASS Belgium NV 131:4758606c9316 325 return -1;
tass 68:0847e35d08a6 326
TASS Belgium NV 131:4758606c9316 327 ptr = m;
TASS Belgium NV 131:4758606c9316 328 addr = (unsigned char *)&ip;
TASS Belgium NV 131:4758606c9316 329 for (i = 3; i >= 0; i--) {
TASS Belgium NV 131:4758606c9316 330 if (addr[i] > 99) {
TASS Belgium NV 131:4758606c9316 331 *ptr++ = (char)('0' + (addr[i] / 100));
TASS Belgium NV 131:4758606c9316 332 *ptr++ = (char)('0' + ((addr[i] % 100) / 10));
TASS Belgium NV 131:4758606c9316 333 *ptr++ = (char)('0' + ((addr[i] % 100) % 10));
TASS Belgium NV 131:4758606c9316 334 } else if(addr[i] > 9) {
TASS Belgium NV 131:4758606c9316 335 *ptr++ = (char)('0' + (addr[i] / 10));
TASS Belgium NV 131:4758606c9316 336 *ptr++ = (char)('0' + (addr[i] % 10));
TASS Belgium NV 131:4758606c9316 337 } else {
TASS Belgium NV 131:4758606c9316 338 *ptr++ = (char)('0' + addr[i]);
TASS Belgium NV 131:4758606c9316 339 }
TASS Belgium NV 131:4758606c9316 340
TASS Belgium NV 131:4758606c9316 341 if(i > 0)
TASS Belgium NV 131:4758606c9316 342 *ptr++ = '.';
tass 68:0847e35d08a6 343 }
TASS Belgium NV 131:4758606c9316 344 *ptr = '\0';
tass 68:0847e35d08a6 345
TASS Belgium NV 131:4758606c9316 346 return 0;
tass 68:0847e35d08a6 347 }
tass 68:0847e35d08a6 348
tass 68:0847e35d08a6 349 static struct pico_dns_query *pico_dns_client_idcheck(uint16_t id)
tass 68:0847e35d08a6 350 {
TASS Belgium NV 131:4758606c9316 351 struct pico_dns_query test = {
TASS Belgium NV 131:4758606c9316 352 0
TASS Belgium NV 131:4758606c9316 353 };
tass 68:0847e35d08a6 354
TASS Belgium NV 131:4758606c9316 355 test.id = id;
TASS Belgium NV 131:4758606c9316 356 return pico_tree_findKey(&DNSTable, &test);
tass 68:0847e35d08a6 357 }
tass 68:0847e35d08a6 358
tass 68:0847e35d08a6 359 static int pico_dns_client_query_prefix(struct pico_dns_prefix *pre)
tass 68:0847e35d08a6 360 {
TASS Belgium NV 131:4758606c9316 361 uint16_t id = 0;
TASS Belgium NV 131:4758606c9316 362 uint8_t retry = 32;
tass 68:0847e35d08a6 363
TASS Belgium NV 131:4758606c9316 364 do {
TASS Belgium NV 131:4758606c9316 365 id = (uint16_t)(pico_rand() & 0xFFFFU);
TASS Belgium NV 131:4758606c9316 366 dns_dbg("DNS: generated id %u\n", id);
TASS Belgium NV 131:4758606c9316 367 } while (retry-- && pico_dns_client_idcheck(id));
TASS Belgium NV 131:4758606c9316 368 if (!retry)
TASS Belgium NV 131:4758606c9316 369 return -1;
tass 68:0847e35d08a6 370
TASS Belgium NV 131:4758606c9316 371 pre->id = short_be(id);
TASS Belgium NV 131:4758606c9316 372 pre->qr = PICO_DNS_QR_QUERY;
TASS Belgium NV 131:4758606c9316 373 pre->opcode = PICO_DNS_OPCODE_QUERY;
TASS Belgium NV 131:4758606c9316 374 pre->aa = PICO_DNS_AA_NO_AUTHORITY;
TASS Belgium NV 131:4758606c9316 375 pre->tc = PICO_DNS_TC_NO_TRUNCATION;
TASS Belgium NV 131:4758606c9316 376 pre->rd = PICO_DNS_RD_IS_DESIRED;
TASS Belgium NV 131:4758606c9316 377 pre->ra = PICO_DNS_RA_NO_SUPPORT;
TASS Belgium NV 131:4758606c9316 378 pre->z = 0;
TASS Belgium NV 131:4758606c9316 379 pre->rcode = PICO_DNS_RCODE_NO_ERROR;
TASS Belgium NV 131:4758606c9316 380 pre->qdcount = short_be(1);
TASS Belgium NV 131:4758606c9316 381 pre->ancount = short_be(0);
TASS Belgium NV 131:4758606c9316 382 pre->nscount = short_be(0);
TASS Belgium NV 131:4758606c9316 383 pre->arcount = short_be(0);
tass 68:0847e35d08a6 384
TASS Belgium NV 131:4758606c9316 385 return 0;
tass 68:0847e35d08a6 386 }
tass 68:0847e35d08a6 387
tass 68:0847e35d08a6 388 static int pico_dns_client_query_suffix(struct pico_dns_query_suffix *suf, uint16_t type, uint16_t class)
tass 68:0847e35d08a6 389 {
TASS Belgium NV 131:4758606c9316 390 suf->qtype = short_be(type);
TASS Belgium NV 131:4758606c9316 391 suf->qclass = short_be(class);
TASS Belgium NV 131:4758606c9316 392 return 0;
tass 68:0847e35d08a6 393 }
tass 68:0847e35d08a6 394
TASS Belgium NV 131:4758606c9316 395 /* replace '.' in the domain name by the label length
tass 68:0847e35d08a6 396 * f.e. www.google.be => 3www6google2be0 */
tass 68:0847e35d08a6 397 static int pico_dns_client_query_domain(char *ptr)
tass 68:0847e35d08a6 398 {
TASS Belgium NV 131:4758606c9316 399 char p = 0, *label = NULL;
TASS Belgium NV 131:4758606c9316 400 uint8_t len = 0;
tass 68:0847e35d08a6 401
TASS Belgium NV 131:4758606c9316 402 if (!ptr)
TASS Belgium NV 131:4758606c9316 403 return -1;
tass 68:0847e35d08a6 404
TASS Belgium NV 131:4758606c9316 405 label = ptr++;
TASS Belgium NV 131:4758606c9316 406 while ((p = *ptr++) != 0) {
TASS Belgium NV 131:4758606c9316 407 if (p == '.') {
TASS Belgium NV 131:4758606c9316 408 *label = (char)len;
TASS Belgium NV 131:4758606c9316 409 label = ptr - 1;
TASS Belgium NV 131:4758606c9316 410 len = 0;
TASS Belgium NV 131:4758606c9316 411 } else {
TASS Belgium NV 131:4758606c9316 412 len++;
TASS Belgium NV 131:4758606c9316 413 }
tass 68:0847e35d08a6 414 }
TASS Belgium NV 131:4758606c9316 415 *label = (char)len;
TASS Belgium NV 131:4758606c9316 416 return 0;
tass 68:0847e35d08a6 417 }
tass 68:0847e35d08a6 418
TASS Belgium NV 131:4758606c9316 419 /* replace the label length in the domain name by '.'
tass 68:0847e35d08a6 420 * f.e. 3www6google2be0 => .www.google.be */
tass 68:0847e35d08a6 421 static int pico_dns_client_answer_domain(char *ptr)
tass 68:0847e35d08a6 422 {
TASS Belgium NV 131:4758606c9316 423 char p = 0, *label = NULL;
tass 68:0847e35d08a6 424
TASS Belgium NV 131:4758606c9316 425 if (!ptr)
TASS Belgium NV 131:4758606c9316 426 return -1;
tass 68:0847e35d08a6 427
tass 68:0847e35d08a6 428 label = ptr;
TASS Belgium NV 131:4758606c9316 429 while ((p = *ptr++) != 0) {
TASS Belgium NV 131:4758606c9316 430 ptr += p;
TASS Belgium NV 131:4758606c9316 431 *label = '.';
TASS Belgium NV 131:4758606c9316 432 label = ptr;
TASS Belgium NV 131:4758606c9316 433 }
TASS Belgium NV 131:4758606c9316 434 return 0;
tass 68:0847e35d08a6 435 }
tass 68:0847e35d08a6 436
tass 68:0847e35d08a6 437 static int pico_dns_client_check_prefix(struct pico_dns_prefix *pre)
tass 68:0847e35d08a6 438 {
TASS Belgium NV 131:4758606c9316 439 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 440 dns_dbg("DNS ERROR: OPCODE %d | TC %d | RCODE %d\n", pre->opcode, pre->tc, pre->rcode);
TASS Belgium NV 131:4758606c9316 441 return -1;
TASS Belgium NV 131:4758606c9316 442 }
TASS Belgium NV 131:4758606c9316 443
TASS Belgium NV 131:4758606c9316 444 if (short_be(pre->ancount) < 1) {
TASS Belgium NV 131:4758606c9316 445 dns_dbg("DNS ERROR: ancount < 1\n");
TASS Belgium NV 131:4758606c9316 446 return -1;
TASS Belgium NV 131:4758606c9316 447 }
TASS Belgium NV 131:4758606c9316 448
TASS Belgium NV 131:4758606c9316 449 return 0;
tass 68:0847e35d08a6 450 }
tass 68:0847e35d08a6 451
tass 68:0847e35d08a6 452 static int pico_dns_client_check_qsuffix(struct pico_dns_query_suffix *suf, struct pico_dns_query *q)
tass 68:0847e35d08a6 453 {
TASS Belgium NV 131:4758606c9316 454 if (short_be(suf->qtype) != q->qtype || short_be(suf->qclass) != q->qclass) {
TASS Belgium NV 131:4758606c9316 455 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 456 return -1;
TASS Belgium NV 131:4758606c9316 457 }
TASS Belgium NV 131:4758606c9316 458
TASS Belgium NV 131:4758606c9316 459 return 0;
tass 68:0847e35d08a6 460 }
tass 68:0847e35d08a6 461
tass 68:0847e35d08a6 462 static int pico_dns_client_check_asuffix(struct pico_dns_answer_suffix *suf, struct pico_dns_query *q)
tass 68:0847e35d08a6 463 {
TASS Belgium NV 131:4758606c9316 464 if (short_be(suf->qtype) != q->qtype || short_be(suf->qclass) != q->qclass) {
TASS Belgium NV 131:4758606c9316 465 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 466 return -1;
TASS Belgium NV 131:4758606c9316 467 }
TASS Belgium NV 131:4758606c9316 468
TASS Belgium NV 131:4758606c9316 469 if (long_be(suf->ttl) > PICO_DNS_MAX_TTL) {
TASS Belgium NV 131:4758606c9316 470 dns_dbg("DNS WARNING: received TTL (%u) > MAX (%u)\n", short_be(suf->ttl), PICO_DNS_MAX_TTL);
TASS Belgium NV 131:4758606c9316 471 return -1;
TASS Belgium NV 131:4758606c9316 472 }
TASS Belgium NV 131:4758606c9316 473
TASS Belgium NV 131:4758606c9316 474 return 0;
tass 68:0847e35d08a6 475 }
tass 68:0847e35d08a6 476
tass 68:0847e35d08a6 477 static char *pico_dns_client_seek_suffix(char *suf, struct pico_dns_prefix *pre, struct pico_dns_query *q)
tass 68:0847e35d08a6 478 {
TASS Belgium NV 131:4758606c9316 479 struct pico_dns_answer_suffix *asuffix = NULL;
TASS Belgium NV 131:4758606c9316 480 uint16_t comp = 0, compression = 0;
TASS Belgium NV 131:4758606c9316 481 uint16_t i = 0;
TASS Belgium NV 131:4758606c9316 482 char *psuffix = suf;
tass 68:0847e35d08a6 483
TASS Belgium NV 131:4758606c9316 484 while (i++ < short_be(pre->ancount)) {
TASS Belgium NV 131:4758606c9316 485 comp = short_from(psuffix);
TASS Belgium NV 131:4758606c9316 486 compression = short_be(comp);
TASS Belgium NV 131:4758606c9316 487 switch (compression >> 14)
TASS Belgium NV 131:4758606c9316 488 {
TASS Belgium NV 131:4758606c9316 489 case PICO_DNS_POINTER:
TASS Belgium NV 131:4758606c9316 490 while (compression >> 14 == PICO_DNS_POINTER) {
TASS Belgium NV 131:4758606c9316 491 dns_dbg("DNS: pointer\n");
TASS Belgium NV 131:4758606c9316 492 psuffix += sizeof(uint16_t);
TASS Belgium NV 131:4758606c9316 493 comp = short_from(psuffix);
TASS Belgium NV 131:4758606c9316 494 compression = short_be(comp);
TASS Belgium NV 131:4758606c9316 495 }
TASS Belgium NV 131:4758606c9316 496 break;
tass 68:0847e35d08a6 497
TASS Belgium NV 131:4758606c9316 498 case PICO_DNS_LABEL:
TASS Belgium NV 131:4758606c9316 499 dns_dbg("DNS: label\n");
TASS Belgium NV 131:4758606c9316 500 psuffix = pico_dns_client_seek(psuffix);
TASS Belgium NV 131:4758606c9316 501 break;
tass 68:0847e35d08a6 502
TASS Belgium NV 131:4758606c9316 503 default:
TASS Belgium NV 131:4758606c9316 504 dns_dbg("DNS ERROR: incorrect compression (%u) value\n", compression);
TASS Belgium NV 131:4758606c9316 505 return NULL;
TASS Belgium NV 131:4758606c9316 506 }
TASS Belgium NV 131:4758606c9316 507
TASS Belgium NV 131:4758606c9316 508 asuffix = (struct pico_dns_answer_suffix *)psuffix;
TASS Belgium NV 131:4758606c9316 509 if (pico_dns_client_check_asuffix(asuffix, q) < 0) {
TASS Belgium NV 131:4758606c9316 510 psuffix += (sizeof(struct pico_dns_answer_suffix) + short_be(asuffix->rdlength));
TASS Belgium NV 131:4758606c9316 511 continue;
TASS Belgium NV 131:4758606c9316 512 }
TASS Belgium NV 131:4758606c9316 513
TASS Belgium NV 131:4758606c9316 514 return psuffix;
tass 68:0847e35d08a6 515 }
TASS Belgium NV 131:4758606c9316 516 return NULL;
tass 68:0847e35d08a6 517 }
tass 68:0847e35d08a6 518
tass 68:0847e35d08a6 519 static int pico_dns_client_send(struct pico_dns_query *q)
tass 68:0847e35d08a6 520 {
TASS Belgium NV 131:4758606c9316 521 uint16_t *paramID = pico_zalloc(sizeof(uint16_t));
TASS Belgium NV 131:4758606c9316 522 dns_dbg("DNS: sending query to %08X\n", q->q_ns.ns.addr);
TASS Belgium NV 131:4758606c9316 523 if (!q->s)
TASS Belgium NV 131:4758606c9316 524 goto failure;
tass 68:0847e35d08a6 525
TASS Belgium NV 131:4758606c9316 526 if (pico_socket_connect(q->s, &q->q_ns.ns, short_be(PICO_DNS_NS_PORT)) < 0)
TASS Belgium NV 131:4758606c9316 527 goto failure;
tass 68:0847e35d08a6 528
TASS Belgium NV 131:4758606c9316 529 pico_socket_send(q->s, q->query, q->len);
TASS Belgium NV 131:4758606c9316 530 *paramID = q->id;
TASS Belgium NV 131:4758606c9316 531 pico_timer_add(PICO_DNS_CLIENT_RETRANS, pico_dns_client_retransmission, paramID);
TASS Belgium NV 131:4758606c9316 532
TASS Belgium NV 131:4758606c9316 533 return 0;
tass 74:c146c4e346c4 534
tass 74:c146c4e346c4 535 failure:
TASS Belgium NV 131:4758606c9316 536 pico_free(paramID);
TASS Belgium NV 131:4758606c9316 537 return -1;
tass 68:0847e35d08a6 538 }
tass 68:0847e35d08a6 539
tass 128:ae39e6e81531 540 static void pico_dns_client_retransmission(pico_time now, void *arg)
tass 68:0847e35d08a6 541 {
TASS Belgium NV 131:4758606c9316 542 struct pico_dns_query *q = NULL;
TASS Belgium NV 131:4758606c9316 543 struct pico_dns_query dummy;
TASS Belgium NV 131:4758606c9316 544 IGNORE_PARAMETER(now);
tass 68:0847e35d08a6 545
TASS Belgium NV 131:4758606c9316 546 if(!arg)
TASS Belgium NV 131:4758606c9316 547 return;
TASS Belgium NV 131:4758606c9316 548
TASS Belgium NV 131:4758606c9316 549 /* search for the dns query and free used space */
TASS Belgium NV 131:4758606c9316 550 dummy.id = *(uint16_t *)arg;
TASS Belgium NV 131:4758606c9316 551 q = (struct pico_dns_query *)pico_tree_findKey(&DNSTable, &dummy);
TASS Belgium NV 131:4758606c9316 552 pico_free(arg);
tass 68:0847e35d08a6 553
TASS Belgium NV 131:4758606c9316 554 /* dns query successful? */
TASS Belgium NV 131:4758606c9316 555 if (!q) {
TASS Belgium NV 131:4758606c9316 556 return;
TASS Belgium NV 131:4758606c9316 557 }
tass 68:0847e35d08a6 558
TASS Belgium NV 131:4758606c9316 559 if (q->retrans++ <= PICO_DNS_CLIENT_MAX_RETRANS) {
TASS Belgium NV 131:4758606c9316 560 q->q_ns = pico_dns_client_next_ns(&q->q_ns.ns);
TASS Belgium NV 131:4758606c9316 561 pico_dns_client_send(q);
TASS Belgium NV 131:4758606c9316 562 } else {
TASS Belgium NV 131:4758606c9316 563 pico_err = PICO_ERR_EIO;
TASS Belgium NV 131:4758606c9316 564 q->callback(NULL, q->arg);
TASS Belgium NV 131:4758606c9316 565 pico_dns_client_del_query(q->id);
TASS Belgium NV 131:4758606c9316 566 }
tass 68:0847e35d08a6 567 }
tass 68:0847e35d08a6 568
tass 68:0847e35d08a6 569 static int pico_dns_client_user_callback(struct pico_dns_answer_suffix *asuffix, struct pico_dns_query *q)
tass 68:0847e35d08a6 570 {
TASS Belgium NV 131:4758606c9316 571 uint32_t ip = 0;
TASS Belgium NV 131:4758606c9316 572 char *str = NULL;
TASS Belgium NV 131:4758606c9316 573
TASS Belgium NV 131:4758606c9316 574 switch (q->qtype)
TASS Belgium NV 131:4758606c9316 575 {
tass 68:0847e35d08a6 576 case PICO_DNS_TYPE_A:
TASS Belgium NV 131:4758606c9316 577 ip = long_from(asuffix->rdata);
TASS Belgium NV 131:4758606c9316 578 str = pico_zalloc(PICO_DNS_IPV4_ADDR_LEN);
TASS Belgium NV 131:4758606c9316 579 pico_ipv4_to_string(str, ip);
TASS Belgium NV 131:4758606c9316 580 break;
tass 68:0847e35d08a6 581
tass 68:0847e35d08a6 582 case PICO_DNS_TYPE_PTR:
TASS Belgium NV 131:4758606c9316 583 pico_dns_client_answer_domain((char *)asuffix->rdata);
TASS Belgium NV 131:4758606c9316 584 str = pico_zalloc((size_t)(asuffix->rdlength - PICO_DNS_LABEL_INITIAL));
TASS Belgium NV 131:4758606c9316 585 memcpy(str, asuffix->rdata + PICO_DNS_LABEL_INITIAL, short_be(asuffix->rdlength) - PICO_DNS_LABEL_INITIAL);
TASS Belgium NV 131:4758606c9316 586 break;
tass 68:0847e35d08a6 587
tass 68:0847e35d08a6 588 default:
TASS Belgium NV 131:4758606c9316 589 dns_dbg("DNS ERROR: incorrect qtype (%u)\n", q->qtype);
TASS Belgium NV 131:4758606c9316 590 break;
TASS Belgium NV 131:4758606c9316 591 }
tass 68:0847e35d08a6 592
TASS Belgium NV 131:4758606c9316 593 if (q->retrans) {
TASS Belgium NV 131:4758606c9316 594 q->callback(str, q->arg);
TASS Belgium NV 131:4758606c9316 595 q->retrans = 0;
TASS Belgium NV 131:4758606c9316 596 pico_dns_client_del_query(q->id);
TASS Belgium NV 131:4758606c9316 597 }
TASS Belgium NV 131:4758606c9316 598
TASS Belgium NV 131:4758606c9316 599 return 0;
tass 68:0847e35d08a6 600 }
tass 68:0847e35d08a6 601
tass 68:0847e35d08a6 602 static void pico_dns_client_callback(uint16_t ev, struct pico_socket *s)
tass 68:0847e35d08a6 603 {
TASS Belgium NV 131:4758606c9316 604 struct pico_dns_prefix *prefix = NULL;
TASS Belgium NV 131:4758606c9316 605 struct pico_dns_name *domain = NULL;
TASS Belgium NV 131:4758606c9316 606 struct pico_dns_query_suffix *qsuffix = NULL;
TASS Belgium NV 131:4758606c9316 607 struct pico_dns_answer_suffix *asuffix = NULL;
TASS Belgium NV 131:4758606c9316 608 struct pico_dns_query *q = NULL;
TASS Belgium NV 131:4758606c9316 609 char *p_asuffix = NULL;
TASS Belgium NV 131:4758606c9316 610 char msg[PICO_DNS_MAX_RESPONSE_LEN] = {
TASS Belgium NV 131:4758606c9316 611 0
TASS Belgium NV 131:4758606c9316 612 };
tass 68:0847e35d08a6 613
TASS Belgium NV 131:4758606c9316 614 if (ev == PICO_SOCK_EV_ERR) {
TASS Belgium NV 131:4758606c9316 615 dns_dbg("DNS: socket error received\n");
TASS Belgium NV 131:4758606c9316 616 return;
TASS Belgium NV 131:4758606c9316 617 }
tass 68:0847e35d08a6 618
TASS Belgium NV 131:4758606c9316 619 if (ev & PICO_SOCK_EV_RD) {
TASS Belgium NV 131:4758606c9316 620 if (pico_socket_read(s, msg, PICO_DNS_MAX_RESPONSE_LEN) <= 0)
TASS Belgium NV 131:4758606c9316 621 return;
TASS Belgium NV 131:4758606c9316 622 }
tass 68:0847e35d08a6 623
TASS Belgium NV 131:4758606c9316 624 prefix = (struct pico_dns_prefix *)msg;
TASS Belgium NV 131:4758606c9316 625 domain = &prefix->domain;
TASS Belgium NV 131:4758606c9316 626 qsuffix = (struct pico_dns_query_suffix *)pico_dns_client_seek(domain->name);
TASS Belgium NV 131:4758606c9316 627 /* valid asuffix is determined dynamically later on */
TASS Belgium NV 131:4758606c9316 628
TASS Belgium NV 131:4758606c9316 629 if (pico_dns_client_check_prefix(prefix) < 0)
TASS Belgium NV 131:4758606c9316 630 return;
TASS Belgium NV 131:4758606c9316 631
TASS Belgium NV 131:4758606c9316 632 q = pico_dns_client_find_query(short_be(prefix->id));
TASS Belgium NV 131:4758606c9316 633 if (!q)
TASS Belgium NV 131:4758606c9316 634 return;
tass 68:0847e35d08a6 635
TASS Belgium NV 131:4758606c9316 636 if (pico_dns_client_check_qsuffix(qsuffix, q) < 0)
TASS Belgium NV 131:4758606c9316 637 return;
TASS Belgium NV 131:4758606c9316 638
TASS Belgium NV 131:4758606c9316 639 p_asuffix = (char *)qsuffix + sizeof(struct pico_dns_query_suffix);
TASS Belgium NV 131:4758606c9316 640 p_asuffix = pico_dns_client_seek_suffix(p_asuffix, prefix, q);
TASS Belgium NV 131:4758606c9316 641 if (!p_asuffix)
TASS Belgium NV 131:4758606c9316 642 return;
TASS Belgium NV 131:4758606c9316 643
TASS Belgium NV 131:4758606c9316 644 asuffix = (struct pico_dns_answer_suffix *)p_asuffix;
TASS Belgium NV 131:4758606c9316 645 pico_dns_client_user_callback(asuffix, q);
TASS Belgium NV 131:4758606c9316 646
tass 68:0847e35d08a6 647 return;
tass 68:0847e35d08a6 648 }
tass 68:0847e35d08a6 649
tass 68:0847e35d08a6 650 int pico_dns_client_getaddr(const char *url, void (*callback)(char *, void *), void *arg)
tass 68:0847e35d08a6 651 {
TASS Belgium NV 131:4758606c9316 652 char *msg = NULL;
TASS Belgium NV 131:4758606c9316 653 struct pico_dns_prefix *prefix = NULL;
TASS Belgium NV 131:4758606c9316 654 struct pico_dns_name *domain = NULL;
TASS Belgium NV 131:4758606c9316 655 struct pico_dns_query_suffix *qsuffix = NULL;
TASS Belgium NV 131:4758606c9316 656 struct pico_dns_query *q = NULL;
TASS Belgium NV 131:4758606c9316 657 uint16_t len = 0, lblen = 0, strlen = 0;
tass 68:0847e35d08a6 658
TASS Belgium NV 131:4758606c9316 659 if (!url || !callback) {
TASS Belgium NV 131:4758606c9316 660 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 661 return -1;
TASS Belgium NV 131:4758606c9316 662 }
TASS Belgium NV 131:4758606c9316 663
TASS Belgium NV 131:4758606c9316 664 strlen = pico_dns_client_strlen(url);
TASS Belgium NV 131:4758606c9316 665 lblen = (uint16_t)(PICO_DNS_LABEL_INITIAL + strlen + PICO_DNS_LABEL_ROOT);
TASS Belgium NV 131:4758606c9316 666 len = (uint16_t)(sizeof(struct pico_dns_prefix) + lblen + sizeof(struct pico_dns_query_suffix));
TASS Belgium NV 131:4758606c9316 667 msg = pico_zalloc(len);
TASS Belgium NV 131:4758606c9316 668 if (!msg) {
TASS Belgium NV 131:4758606c9316 669 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 670 return -1;
TASS Belgium NV 131:4758606c9316 671 }
tass 68:0847e35d08a6 672
TASS Belgium NV 131:4758606c9316 673 prefix = (struct pico_dns_prefix *)msg;
TASS Belgium NV 131:4758606c9316 674 domain = &prefix->domain;
TASS Belgium NV 131:4758606c9316 675 qsuffix = (struct pico_dns_query_suffix *)(domain->name + lblen);
TASS Belgium NV 131:4758606c9316 676 memcpy(domain->name + PICO_DNS_LABEL_INITIAL, url, strlen);
TASS Belgium NV 131:4758606c9316 677
TASS Belgium NV 131:4758606c9316 678 /* assemble dns message */
TASS Belgium NV 131:4758606c9316 679 pico_dns_client_query_prefix(prefix);
TASS Belgium NV 131:4758606c9316 680 pico_dns_client_query_domain(domain->name);
TASS Belgium NV 131:4758606c9316 681 pico_dns_client_query_suffix(qsuffix, PICO_DNS_TYPE_A, PICO_DNS_CLASS_IN);
tass 68:0847e35d08a6 682
TASS Belgium NV 131:4758606c9316 683 q = pico_dns_client_add_query(prefix, len, qsuffix, callback, arg);
TASS Belgium NV 131:4758606c9316 684 if (!q) {
TASS Belgium NV 131:4758606c9316 685 pico_free(msg);
TASS Belgium NV 131:4758606c9316 686 return -1;
TASS Belgium NV 131:4758606c9316 687 }
tass 68:0847e35d08a6 688
TASS Belgium NV 131:4758606c9316 689 if (pico_dns_client_send(q) < 0) {
TASS Belgium NV 131:4758606c9316 690 pico_dns_client_del_query(q->id); /* frees msg */
TASS Belgium NV 131:4758606c9316 691 return -1;
TASS Belgium NV 131:4758606c9316 692 }
tass 68:0847e35d08a6 693
TASS Belgium NV 131:4758606c9316 694 return 0;
tass 68:0847e35d08a6 695 }
tass 68:0847e35d08a6 696
tass 68:0847e35d08a6 697 int pico_dns_client_getname(const char *ip, void (*callback)(char *, void *), void *arg)
tass 68:0847e35d08a6 698 {
TASS Belgium NV 131:4758606c9316 699 const char *inaddr_arpa = ".in-addr.arpa";
TASS Belgium NV 131:4758606c9316 700 char *msg = NULL;
TASS Belgium NV 131:4758606c9316 701 struct pico_dns_prefix *prefix = NULL;
TASS Belgium NV 131:4758606c9316 702 struct pico_dns_name *domain = NULL;
TASS Belgium NV 131:4758606c9316 703 struct pico_dns_query_suffix *qsuffix = NULL;
TASS Belgium NV 131:4758606c9316 704 struct pico_dns_query *q = NULL;
TASS Belgium NV 131:4758606c9316 705 uint16_t len = 0, lblen = 0, strlen = 0, arpalen = 0;
tass 68:0847e35d08a6 706
TASS Belgium NV 131:4758606c9316 707 if (!ip || !callback) {
TASS Belgium NV 131:4758606c9316 708 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 709 return -1;
TASS Belgium NV 131:4758606c9316 710 }
TASS Belgium NV 131:4758606c9316 711
TASS Belgium NV 131:4758606c9316 712 strlen = pico_dns_client_strlen(ip);
TASS Belgium NV 131:4758606c9316 713 arpalen = pico_dns_client_strlen(inaddr_arpa);
TASS Belgium NV 131:4758606c9316 714 lblen = (uint16_t)(PICO_DNS_LABEL_INITIAL + strlen + arpalen + PICO_DNS_LABEL_ROOT);
TASS Belgium NV 131:4758606c9316 715 len = (uint16_t)(sizeof(struct pico_dns_prefix) + lblen + sizeof(struct pico_dns_query_suffix));
TASS Belgium NV 131:4758606c9316 716 msg = pico_zalloc(len);
TASS Belgium NV 131:4758606c9316 717 if (!msg) {
TASS Belgium NV 131:4758606c9316 718 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 719 return -1;
TASS Belgium NV 131:4758606c9316 720 }
tass 68:0847e35d08a6 721
TASS Belgium NV 131:4758606c9316 722 prefix = (struct pico_dns_prefix *)msg;
TASS Belgium NV 131:4758606c9316 723 domain = &prefix->domain;
TASS Belgium NV 131:4758606c9316 724 qsuffix = (struct pico_dns_query_suffix *)(prefix->domain.name + lblen);
TASS Belgium NV 131:4758606c9316 725 memcpy(domain->name + PICO_DNS_LABEL_INITIAL, ip, strlen);
TASS Belgium NV 131:4758606c9316 726 pico_dns_client_mirror(domain->name + PICO_DNS_LABEL_INITIAL);
TASS Belgium NV 131:4758606c9316 727 memcpy(domain->name + PICO_DNS_LABEL_INITIAL + strlen, inaddr_arpa, arpalen);
TASS Belgium NV 131:4758606c9316 728
TASS Belgium NV 131:4758606c9316 729 /* assemble dns message */
TASS Belgium NV 131:4758606c9316 730 pico_dns_client_query_prefix(prefix);
TASS Belgium NV 131:4758606c9316 731 pico_dns_client_query_domain(domain->name);
TASS Belgium NV 131:4758606c9316 732 pico_dns_client_query_suffix(qsuffix, PICO_DNS_TYPE_PTR, PICO_DNS_CLASS_IN);
tass 68:0847e35d08a6 733
TASS Belgium NV 131:4758606c9316 734 q = pico_dns_client_add_query(prefix, len, qsuffix, callback, arg);
TASS Belgium NV 131:4758606c9316 735 if (!q) {
TASS Belgium NV 131:4758606c9316 736 pico_free(msg);
TASS Belgium NV 131:4758606c9316 737 return -1;
TASS Belgium NV 131:4758606c9316 738 }
tass 68:0847e35d08a6 739
TASS Belgium NV 131:4758606c9316 740 if (pico_dns_client_send(q) < 0) {
TASS Belgium NV 131:4758606c9316 741 pico_dns_client_del_query(q->id); /* frees msg */
TASS Belgium NV 131:4758606c9316 742 return -1;
TASS Belgium NV 131:4758606c9316 743 }
tass 68:0847e35d08a6 744
TASS Belgium NV 131:4758606c9316 745 return 0;
tass 68:0847e35d08a6 746 }
tass 68:0847e35d08a6 747
tass 68:0847e35d08a6 748 int pico_dns_client_nameserver(struct pico_ip4 *ns, uint8_t flag)
tass 68:0847e35d08a6 749 {
TASS Belgium NV 131:4758606c9316 750 if (!ns) {
TASS Belgium NV 131:4758606c9316 751 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 752 return -1;
TASS Belgium NV 131:4758606c9316 753 }
tass 68:0847e35d08a6 754
TASS Belgium NV 131:4758606c9316 755 switch (flag)
TASS Belgium NV 131:4758606c9316 756 {
tass 68:0847e35d08a6 757 case PICO_DNS_NS_ADD:
TASS Belgium NV 131:4758606c9316 758 if (!pico_dns_client_add_ns(ns))
TASS Belgium NV 131:4758606c9316 759 return -1;
TASS Belgium NV 131:4758606c9316 760
TASS Belgium NV 131:4758606c9316 761 break;
tass 68:0847e35d08a6 762
tass 68:0847e35d08a6 763 case PICO_DNS_NS_DEL:
TASS Belgium NV 131:4758606c9316 764 if (pico_dns_client_del_ns(ns) < 0) {
TASS Belgium NV 131:4758606c9316 765 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 766 return -1;
TASS Belgium NV 131:4758606c9316 767 }
TASS Belgium NV 131:4758606c9316 768
TASS Belgium NV 131:4758606c9316 769 break;
TASS Belgium NV 131:4758606c9316 770
TASS Belgium NV 131:4758606c9316 771 default:
tass 68:0847e35d08a6 772 pico_err = PICO_ERR_EINVAL;
tass 68:0847e35d08a6 773 return -1;
TASS Belgium NV 131:4758606c9316 774 }
TASS Belgium NV 131:4758606c9316 775 return 0;
tass 68:0847e35d08a6 776 }
tass 68:0847e35d08a6 777
tass picotcp@tass.be 134:cc4e6d2654d9 778 int pico_dns_client_init(void)
tass 68:0847e35d08a6 779 {
TASS Belgium NV 131:4758606c9316 780 struct pico_ip4 default_ns = {
TASS Belgium NV 131:4758606c9316 781 0
TASS Belgium NV 131:4758606c9316 782 };
tass 68:0847e35d08a6 783
TASS Belgium NV 131:4758606c9316 784 if (pico_string_to_ipv4(PICO_DNS_NS_GOOGLE, &default_ns.addr) < 0)
TASS Belgium NV 131:4758606c9316 785 return -1;
tass 68:0847e35d08a6 786
TASS Belgium NV 131:4758606c9316 787 return pico_dns_client_nameserver(&default_ns, PICO_DNS_NS_ADD);
tass 68:0847e35d08a6 788 }
tass 68:0847e35d08a6 789
tass 68:0847e35d08a6 790 #endif /* PICO_SUPPORT_DNS_CLIENT */