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

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

PicoTCP. Copyright (c) 2013 TASS Belgium NV.

Released under the GNU General Public License, version 2.

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

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

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

Development steps:

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

Demo application (measuring TCP sender performance):

Import programlpc1768-picotcp-demo

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

Committer:
tass
Date:
Thu Sep 19 13:06:00 2013 +0000
Revision:
66:71a2ef45a035
Parent:
63:97f481e33cb2
Parent:
65:8cdaaa1df01d
Merged branches.

Who changed what in which revision?

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