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