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 Jan 17 10:13:51 2014 +0100
Revision:
136:576dcbb16922
Parent:
134:cc4e6d2654d9
Child:
137:a1c8bfa9d691
Fixed broken DNS client

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