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

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

PicoTCP. Copyright (c) 2013 TASS Belgium NV.

Released under the GNU General Public License, version 2.

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

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

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

Development steps:

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

Demo application (measuring TCP sender performance):

Import programlpc1768-picotcp-demo

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

Committer:
tass
Date:
Fri Sep 27 12:43:36 2013 +0000
Revision:
73:dfb737147f6e
Parent:
70:cd218dd180e5
Child:
74:c146c4e346c4
Import from master branch.

Who changed what in which revision?

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