CDC/ECM driver for mbed, based on USBDevice by mbed-official. Uses PicoTCP to access Ethernet USB device. License: GPLv2
Fork of USB_Ethernet by
pico_dns_client.c
00001 /********************************************************************* 00002 PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved. 00003 See LICENSE and COPYING for usage. 00004 00005 . 00006 00007 Authors: Kristof Roelants 00008 *********************************************************************/ 00009 #include "pico_config.h" 00010 #include "pico_stack.h" 00011 #include "pico_addressing.h" 00012 #include "pico_socket.h" 00013 #include "pico_ipv4.h" 00014 #include "pico_dns_client.h" 00015 #include "pico_tree.h" 00016 00017 #ifdef PICO_SUPPORT_DNS_CLIENT 00018 00019 #define dns_dbg(...) do{}while(0) 00020 //#define dns_dbg dbg 00021 00022 /* DNS response length */ 00023 #define PICO_DNS_MAX_RESPONSE_LEN 256 00024 00025 /* DNS client retransmission time (msec) + frequency */ 00026 #define PICO_DNS_CLIENT_RETRANS 4000 00027 #define PICO_DNS_CLIENT_MAX_RETRANS 3 00028 00029 /* Default nameservers */ 00030 #define PICO_DNS_NS_GOOGLE "8.8.8.8" 00031 00032 /* Nameserver port */ 00033 #define PICO_DNS_NS_PORT 53 00034 00035 /* FLAG values */ 00036 #define PICO_DNS_QR_QUERY 0 00037 #define PICO_DNS_QR_RESPONSE 1 00038 #define PICO_DNS_OPCODE_QUERY 0 00039 #define PICO_DNS_OPCODE_IQUERY 1 00040 #define PICO_DNS_OPCODE_STATUS 2 00041 #define PICO_DNS_AA_NO_AUTHORITY 0 00042 #define PICO_DNS_AA_IS_AUTHORITY 1 00043 #define PICO_DNS_TC_NO_TRUNCATION 0 00044 #define PICO_DNS_TC_IS_TRUNCATED 1 00045 #define PICO_DNS_RD_NO_DESIRE 0 00046 #define PICO_DNS_RD_IS_DESIRED 1 00047 #define PICO_DNS_RA_NO_SUPPORT 0 00048 #define PICO_DNS_RA_IS_SUPPORTED 1 00049 #define PICO_DNS_RCODE_NO_ERROR 0 00050 #define PICO_DNS_RCODE_EFORMAT 1 00051 #define PICO_DNS_RCODE_ESERVER 2 00052 #define PICO_DNS_RCODE_ENAME 3 00053 #define PICO_DNS_RCODE_ENOIMP 4 00054 #define PICO_DNS_RCODE_EREFUSED 5 00055 00056 /* QTYPE values */ 00057 #define PICO_DNS_TYPE_A 1 00058 #define PICO_DNS_TYPE_PTR 12 00059 00060 /* QCLASS values */ 00061 #define PICO_DNS_CLASS_IN 1 00062 00063 /* Compression values */ 00064 #define PICO_DNS_LABEL 0 00065 #define PICO_DNS_POINTER 3 00066 00067 /* TTL values */ 00068 #define PICO_DNS_MAX_TTL 604800 /* one week */ 00069 00070 /* Header flags */ 00071 #define FLAG_QR(hdr, x) ((hdr)->flags = ((hdr)->flags & ~(0x1 << 15)) | (x << 15)) 00072 #define FLAG_OPCODE(hdr, x) ((hdr)->flags = ((hdr)->flags & ~(0xF << 11)) | (x << 11)) 00073 #define FLAG_AA(hdr, x) ((hdr)->flags = ((hdr)->flags & ~(0x1 << 10)) | (x << 10)) 00074 #define FLAG_TC(hdr, x) ((hdr)->flags = ((hdr)->flags & ~(0x1 << 9)) | (x << 9)) 00075 #define FLAG_RD(hdr, x) ((hdr)->flags = ((hdr)->flags & ~(0x1 << 8)) | (x << 8)) 00076 #define FLAG_RA(hdr, x) ((hdr)->flags = ((hdr)->flags & ~(0x1 << 7)) | (x << 7)) 00077 #define FLAG_Z(hdr, x) ((hdr)->flags = ((hdr)->flags & ~(0x7 << 4)) | (x << 4)) 00078 #define FLAG_RCODE(hdr, x) ((hdr)->flags = ((hdr)->flags & ~(0xF)) | x) 00079 00080 #define GET_FLAG_QR(hdr) ((((hdr)->flags) & (1 << 15)) != 0) 00081 #define GET_FLAG_OPCODE(hdr) ((((hdr)->flags) & (0xF << 11)) >> 11) 00082 #define GET_FLAG_AA(hdr) ((((hdr)->flags) & (1 << 10)) != 0) 00083 #define GET_FLAG_TC(hdr) ((((hdr)->flags) & (1 << 9)) != 0) 00084 #define GET_FLAG_RD(hdr) ((((hdr)->flags) & (1 << 8)) != 0) 00085 #define GET_FLAG_RA(hdr) ((((hdr)->flags) & (1 << 7)) != 0) 00086 #define GET_FLAG_Z(hdr) ((((hdr)->flags) & (0x7 << 4)) >> 4) 00087 #define GET_FLAG_RCODE(hdr) (((hdr)->flags) & (0x0F)) 00088 00089 /* RFC 1025 section 4. MESSAGES */ 00090 struct __attribute__((packed)) dns_message_hdr 00091 { 00092 uint16_t id; 00093 uint16_t flags; 00094 uint16_t qdcount; 00095 uint16_t ancount; 00096 uint16_t nscount; 00097 uint16_t arcount; 00098 }; 00099 00100 struct __attribute__((packed)) dns_query_suffix 00101 { 00102 /* NAME - domain name to which this resource record pertains */ 00103 uint16_t qtype; 00104 uint16_t qclass; 00105 }; 00106 00107 struct __attribute__((packed)) dns_answer_suffix 00108 { 00109 /* NAME - domain name to which this resource record pertains */ 00110 uint16_t qtype; 00111 uint16_t qclass; 00112 uint32_t ttl; 00113 uint16_t rdlength; 00114 /* RDATA - variable length string of octets that describes the resource */ 00115 }; 00116 00117 struct pico_dns_ns 00118 { 00119 struct pico_ip4 ns; /* Nameserver */ 00120 }; 00121 00122 static int dns_ns_cmp(void *ka, void *kb) 00123 { 00124 struct pico_dns_ns *a = ka, *b = kb; 00125 if (a->ns.addr < b->ns.addr) 00126 return -1; 00127 else if (a->ns.addr > b->ns.addr) 00128 return 1; 00129 else 00130 return 0; 00131 } 00132 00133 PICO_TREE_DECLARE(NSTable,dns_ns_cmp); 00134 00135 int pico_dns_client_nameserver(struct pico_ip4 *ns, uint8_t flag) 00136 { 00137 struct pico_dns_ns test, *key = NULL; 00138 00139 if (!ns) { 00140 pico_err = PICO_ERR_EINVAL; 00141 return -1; 00142 } 00143 00144 switch (flag) 00145 { 00146 case PICO_DNS_NS_ADD: 00147 key = pico_zalloc(sizeof(struct pico_dns_ns)); 00148 if (!key) { 00149 pico_err = PICO_ERR_ENOMEM; 00150 return -1; 00151 } 00152 key->ns = *ns; 00153 00154 if(pico_tree_insert(&NSTable,key)){ 00155 dns_dbg("DNS WARNING: nameserver %08X already added\n",ns->addr); 00156 pico_err = PICO_ERR_EINVAL; 00157 pico_free(key); 00158 return -1; /* Element key already exists */ 00159 } 00160 dns_dbg("DNS: nameserver %08X added\n", ns->addr); 00161 /* If default NS found, remove it */ 00162 pico_string_to_ipv4(PICO_DNS_NS_GOOGLE, &test.ns.addr); 00163 if (ns->addr != test.ns.addr) { 00164 00165 key = pico_tree_findKey(&NSTable,&test); 00166 if (key) { 00167 if(pico_tree_delete(&NSTable,key)) { 00168 dns_dbg("DNS: default nameserver %08X removed\n", test.ns.addr); 00169 pico_free(key); 00170 } else { 00171 pico_err = PICO_ERR_EAGAIN; 00172 return -1; 00173 } 00174 } 00175 } 00176 break; 00177 00178 case PICO_DNS_NS_DEL: 00179 test.ns = *ns; 00180 00181 key = pico_tree_findKey(&NSTable,&test); 00182 if (!key) { 00183 dns_dbg("DNS WARNING: nameserver %08X not found\n", ns->addr); 00184 pico_err = PICO_ERR_EINVAL; 00185 return -1; 00186 } 00187 /* RB_REMOVE returns pointer to removed element, NULL to indicate error */ 00188 00189 if(pico_tree_delete(&NSTable,key)) { 00190 dns_dbg("DNS: nameserver %08X removed\n",key->ns.addr); 00191 pico_free(key); 00192 } else { 00193 pico_err = PICO_ERR_EAGAIN; 00194 return -1; 00195 } 00196 /* If no NS left, add default NS */ 00197 if(pico_tree_first(&NSTable) == NULL){ 00198 dns_dbg("DNS: add default nameserver\n"); 00199 return pico_dns_client_init(); 00200 } 00201 break; 00202 00203 default: 00204 pico_err = PICO_ERR_EINVAL; 00205 return -1; 00206 } 00207 return 0; 00208 } 00209 00210 int pico_dns_client_init() 00211 { 00212 struct pico_ip4 default_ns; 00213 if (pico_string_to_ipv4(PICO_DNS_NS_GOOGLE, &default_ns.addr) != 0) { 00214 pico_err = PICO_ERR_EINVAL; 00215 return -1; 00216 } 00217 return pico_dns_client_nameserver(&default_ns, PICO_DNS_NS_ADD); 00218 } 00219 00220 struct pico_dns_key 00221 { 00222 char *q_hdr; 00223 uint16_t len; 00224 uint16_t id; 00225 uint16_t qtype; 00226 uint16_t qclass; 00227 uint8_t retrans; 00228 struct pico_dns_ns q_ns; 00229 struct pico_socket *s; 00230 void (*callback)(char *, void *); 00231 void *arg; 00232 }; 00233 00234 static int dns_cmp(void *ka, void *kb) 00235 { 00236 struct pico_dns_key *a = ka,*b = kb; 00237 if (a->id < b->id) 00238 return -1; 00239 else if (a->id > b->id) 00240 return 1; 00241 else 00242 return 0; 00243 } 00244 00245 PICO_TREE_DECLARE(DNSTable,dns_cmp); 00246 00247 static int pico_dns_client_strlen(const char *url) 00248 { 00249 uint16_t len = 0; 00250 int p; 00251 00252 if (!url) 00253 return -1; 00254 00255 while ((p = *url++) != 0) { 00256 len++; 00257 } 00258 return len; 00259 } 00260 00261 /* Replace '.' by the label length */ 00262 static int pico_dns_client_label(char *ptr) 00263 { 00264 char *l; 00265 uint8_t lbl_len = 0; 00266 int p; 00267 00268 if (!ptr) 00269 return -1; 00270 00271 l = ptr++; 00272 while ((p = *ptr++) != 0){ 00273 if (p == '.') { 00274 *l = lbl_len; 00275 l = ptr - 1; 00276 lbl_len = 0; 00277 } else { 00278 lbl_len++; 00279 } 00280 } 00281 *l = lbl_len; 00282 return 0; 00283 } 00284 00285 /* Replace the label length by '.' */ 00286 static int pico_dns_client_reverse_label(char *ptr) 00287 { 00288 char *l; 00289 int p; 00290 00291 if(!ptr) 00292 return -1; 00293 00294 l = ptr; 00295 while ((p = *ptr++) != 0){ 00296 ptr += p; 00297 *l = '.'; 00298 l = ptr; 00299 } 00300 return 0; 00301 } 00302 00303 /* Seek the end of a string */ 00304 static char *pico_dns_client_seek(char *ptr) 00305 { 00306 int p; 00307 00308 if (!ptr) 00309 return NULL; 00310 00311 while ((p = *ptr++) != 0); 00312 00313 return ptr++; 00314 } 00315 00316 static inline void pico_dns_client_construct_hdr(struct dns_message_hdr *hdr, uint16_t id) 00317 { 00318 hdr->id = short_be(id); 00319 FLAG_QR(hdr, PICO_DNS_QR_QUERY); 00320 FLAG_OPCODE(hdr, PICO_DNS_OPCODE_QUERY); 00321 FLAG_AA(hdr, PICO_DNS_AA_NO_AUTHORITY); 00322 FLAG_TC(hdr, PICO_DNS_TC_NO_TRUNCATION); 00323 FLAG_RD(hdr, PICO_DNS_RD_IS_DESIRED); 00324 FLAG_RA(hdr, PICO_DNS_RA_NO_SUPPORT); 00325 FLAG_Z(hdr, 0); 00326 FLAG_RCODE(hdr, PICO_DNS_RCODE_NO_ERROR); 00327 hdr->flags = short_be(hdr->flags); 00328 hdr->qdcount = short_be(1); 00329 hdr->ancount = short_be(0); 00330 hdr->nscount = short_be(0); 00331 hdr->arcount = short_be(0); 00332 } 00333 00334 static inline void pico_dns_client_hdr_ntoh(struct dns_message_hdr *hdr) 00335 { 00336 hdr->id = short_be(hdr->id); 00337 hdr->flags = short_be(hdr->flags); 00338 hdr->qdcount = short_be(hdr->qdcount); 00339 hdr->ancount = short_be(hdr->ancount); 00340 hdr->nscount = short_be(hdr->nscount); 00341 hdr->arcount = short_be(hdr->arcount); 00342 } 00343 00344 00345 static int pico_dns_client_mirror(char *ptr) 00346 { 00347 unsigned char buf[4] = {0}; 00348 char *m; 00349 int cnt = 0; 00350 int p, i; 00351 00352 if (!ptr) 00353 return -1; 00354 00355 m = ptr; 00356 while ((p = *ptr++) != 0) 00357 { 00358 if (pico_is_digit(p)) { 00359 buf[cnt] = (10 * buf[cnt]) + (p - '0'); 00360 } else if (p == '.') { 00361 cnt++; 00362 } else { 00363 return -1; 00364 } 00365 } 00366 00367 /* Handle short notation */ 00368 if(cnt == 1){ 00369 buf[3] = buf[1]; 00370 buf[1] = 0; 00371 buf[2] = 0; 00372 }else if (cnt == 2){ 00373 buf[3] = buf[2]; 00374 buf[2] = 0; 00375 }else if(cnt != 3){ 00376 /* String could not be parsed, return error */ 00377 return -1; 00378 } 00379 00380 ptr = m; 00381 for(i = 3; i >= 0; i--) 00382 { 00383 if(buf[i] > 99){ 00384 *ptr++ = '0' + (buf[i] / 100); 00385 *ptr++ = '0' + ((buf[i] % 100) / 10); 00386 *ptr++ = '0' + ((buf[i] % 100) % 10); 00387 }else if(buf[i] > 9){ 00388 *ptr++ = '0' + (buf[i] / 10); 00389 *ptr++ = '0' + (buf[i] % 10); 00390 }else{ 00391 *ptr++ = '0' + buf[i]; 00392 } 00393 if(i > 0) 00394 *ptr++ = '.'; 00395 } 00396 00397 return 0; 00398 } 00399 00400 static struct pico_dns_key *pico_dns_client_idcheck(uint16_t id) 00401 { 00402 struct pico_dns_key test; 00403 00404 test.id = id; 00405 return pico_tree_findKey(&DNSTable,&test); 00406 } 00407 00408 static void pico_dns_client_callback(uint16_t ev, struct pico_socket *s); 00409 00410 static int pico_dns_client_send(struct pico_dns_key *key) 00411 { 00412 struct pico_socket *s; 00413 int w = 0; 00414 00415 dns_dbg("DNS: sending query to %08X\n", key->q_ns.ns.addr); 00416 s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, &pico_dns_client_callback); 00417 if (!s) 00418 return -1; 00419 key->s = s; 00420 if (pico_socket_connect(s, &key->q_ns.ns, short_be(PICO_DNS_NS_PORT)) != 0) 00421 return -1; 00422 w = pico_socket_send(s, key->q_hdr, key->len); 00423 if (w <= 0) 00424 return -1; 00425 00426 return 0; 00427 } 00428 00429 static void pico_dns_client_retransmission(unsigned long now, void *arg) 00430 { 00431 struct pico_dns_key *key = (struct pico_dns_key *)arg; 00432 struct pico_dns_ns *q_ns = NULL; 00433 00434 if (!key->retrans) { 00435 dns_dbg("DNS: no retransmission!\n"); 00436 pico_free(key->q_hdr); 00437 00438 if(pico_tree_delete(&DNSTable,key)) 00439 pico_free(key); 00440 } 00441 else if (key->retrans <= PICO_DNS_CLIENT_MAX_RETRANS) { 00442 key->retrans++; 00443 dns_dbg("DNS: retransmission! (%u attempts)\n", key->retrans); 00444 // ugly hack 00445 q_ns = pico_tree_next(pico_tree_findNode(&NSTable,&key->q_ns))->keyValue; 00446 if (q_ns) 00447 key->q_ns = *q_ns; 00448 else 00449 key->q_ns = *((struct pico_dns_ns *)pico_tree_first(&NSTable)); 00450 pico_dns_client_send(key); 00451 pico_timer_add(PICO_DNS_CLIENT_RETRANS, pico_dns_client_retransmission, key); 00452 } else { 00453 dns_dbg("DNS ERROR: no reply from nameservers! (%u attempts)\n", key->retrans); 00454 pico_socket_close(key->s); 00455 pico_err = PICO_ERR_EIO; 00456 key->callback(NULL, key->arg); 00457 pico_free(key->q_hdr); 00458 /* RB_REMOVE returns pointer to removed element, NULL to indicate error */ 00459 00460 if(pico_tree_delete(&DNSTable,key)) 00461 pico_free(key); 00462 } 00463 } 00464 00465 static void pico_dns_client_callback(uint16_t ev, struct pico_socket *s) 00466 { 00467 char *q_qname, *q_suf, *a_hdr, *a_qname, *a_suf, *a_rdata; 00468 struct dns_message_hdr *hdr; 00469 struct dns_query_suffix query_suf; 00470 struct dns_answer_suffix answer_suf; 00471 struct pico_dns_key test, *key; 00472 char *answer; 00473 char dns_answer[PICO_DNS_MAX_RESPONSE_LEN] = {0}; 00474 uint8_t valid_suffix = 0; 00475 uint16_t compression = 0; 00476 int i = 0, r = 0; 00477 00478 if (ev & PICO_SOCK_EV_RD) { 00479 r = pico_socket_read(s, dns_answer, PICO_DNS_MAX_RESPONSE_LEN); 00480 pico_socket_close(s); 00481 if (r == PICO_DNS_MAX_RESPONSE_LEN || r < (int)sizeof(struct dns_message_hdr)) { 00482 dns_dbg("DNS ERROR: received incorrect number(%d) of bytes\n", r); 00483 return; 00484 } 00485 00486 /* Check header validity */ 00487 a_hdr = dns_answer; 00488 hdr = (struct dns_message_hdr *) a_hdr; 00489 pico_dns_client_hdr_ntoh(hdr); 00490 if (GET_FLAG_QR(hdr) != PICO_DNS_QR_RESPONSE || GET_FLAG_OPCODE(hdr) != PICO_DNS_OPCODE_QUERY 00491 || GET_FLAG_TC(hdr) == PICO_DNS_TC_IS_TRUNCATED || GET_FLAG_RCODE(hdr) != PICO_DNS_RCODE_NO_ERROR) { 00492 dns_dbg("DNS ERROR: OPCODE %d | TC %d | RCODE %d\n", GET_FLAG_OPCODE(hdr), GET_FLAG_TC(hdr), GET_FLAG_RCODE(hdr)); 00493 return; 00494 } 00495 00496 if (hdr->ancount < 1 || r < (int)(sizeof(struct dns_message_hdr) + hdr->qdcount * sizeof(struct dns_query_suffix) 00497 + hdr->ancount * sizeof(struct dns_answer_suffix))) { 00498 dns_dbg("DNS ERROR: ancount < 1 OR received number(%d) of bytes too low\n", r); 00499 return; 00500 } 00501 00502 /* Find DNS key */ 00503 test.id = hdr->id; 00504 00505 key = pico_tree_findKey(&DNSTable,&test); 00506 if (!key) { 00507 dns_dbg("DNS WARNING: key with id %u not found\n", hdr->id); 00508 return; 00509 } 00510 key->retrans = 0; 00511 00512 /* Check query suffix validity */ 00513 q_qname = a_hdr + sizeof(struct dns_message_hdr); 00514 q_suf = pico_dns_client_seek(q_qname); 00515 query_suf = *(struct dns_query_suffix *) q_suf; 00516 if (short_be(query_suf.qtype) != key->qtype || short_be(query_suf.qclass) != key->qclass) { 00517 dns_dbg("DNS ERROR: received qtype (%u) or qclass (%u) incorrect\n", short_be(query_suf.qtype), short_be(query_suf.qclass)); 00518 return; 00519 } 00520 00521 /* Seek answer suffix */ 00522 a_qname = q_suf + sizeof(struct dns_query_suffix); 00523 a_suf = a_qname; 00524 while(i++ < hdr->ancount) { 00525 uint16_t comp_h = short_from(a_suf); 00526 compression = short_be(comp_h); 00527 switch (compression >> 14) 00528 { 00529 case PICO_DNS_POINTER: 00530 while (compression >> 14 == PICO_DNS_POINTER) { 00531 dns_dbg("DNS: pointer\n"); 00532 a_suf += sizeof(uint16_t); 00533 comp_h = short_from(a_suf); 00534 compression = short_be(comp_h); 00535 } 00536 break; 00537 00538 case PICO_DNS_LABEL: 00539 dns_dbg("DNS: label\n"); 00540 a_suf = pico_dns_client_seek(a_qname); 00541 break; 00542 00543 default: 00544 dns_dbg("DNS ERROR: incorrect compression (%u) value\n", compression); 00545 return; 00546 } 00547 00548 /* Check answer suffix validity */ 00549 answer_suf = *(struct dns_answer_suffix *)a_suf; 00550 if (short_be(answer_suf.qtype) != key->qtype || short_be(answer_suf.qclass) != key->qclass) { 00551 dns_dbg("DNS WARNING: received qtype (%u) or qclass (%u) incorrect\n", short_be(answer_suf.qtype), short_be(answer_suf.qclass)); 00552 a_suf = a_suf + sizeof(struct dns_answer_suffix) + short_be(answer_suf.rdlength); 00553 continue; 00554 } 00555 00556 if (short_be(answer_suf.ttl) > PICO_DNS_MAX_TTL) { 00557 dns_dbg("DNS WARNING: received TTL (%u) > MAX (%u)\n", short_be(answer_suf.ttl), PICO_DNS_MAX_TTL); 00558 a_suf = a_suf + sizeof(struct dns_answer_suffix) + short_be(answer_suf.rdlength); 00559 continue; 00560 } 00561 00562 valid_suffix = 1; 00563 break; 00564 } 00565 00566 if (!valid_suffix) { 00567 dns_dbg("DNS ERROR: invalid dns answer suffix\n"); 00568 return; 00569 } 00570 00571 a_rdata = a_suf + sizeof(struct dns_answer_suffix); 00572 if (key->qtype == PICO_DNS_TYPE_A) { 00573 uint32_t ip_h = long_from(a_rdata); 00574 dns_dbg("DNS: length %u | ip %08X\n", short_be(answer_suf.rdlength), long_be(ip_h)); 00575 answer = pico_zalloc(16); 00576 pico_ipv4_to_string(answer, ip_h); 00577 key->callback(answer, key->arg); 00578 } else if (key->qtype == PICO_DNS_TYPE_PTR) { 00579 pico_dns_client_reverse_label((char *) a_rdata); 00580 dns_dbg("DNS: length %u | name %s\n", short_be(answer_suf.rdlength), (char *)a_rdata + 1); 00581 answer = pico_zalloc(answer_suf.rdlength - 1); 00582 memcpy(answer, (char *)a_rdata + 1, short_be(answer_suf.rdlength) - 1); 00583 key->callback(answer, key->arg); 00584 } else { 00585 dns_dbg("DNS ERROR: incorrect qtype (%u)\n", key->qtype); 00586 return; 00587 } 00588 } 00589 00590 if (ev == PICO_SOCK_EV_ERR) { 00591 dns_dbg("DNS: socket error received\n"); 00592 } 00593 } 00594 00595 int pico_dns_client_getaddr(const char *url, void (*callback)(char *, void *), void *arg) 00596 { 00597 char *q_hdr, *q_qname, *q_suf; 00598 struct dns_message_hdr *hdr; 00599 struct dns_query_suffix query_suf; 00600 struct pico_dns_key *key; 00601 uint16_t url_len = 0; 00602 uint16_t id = 0; 00603 00604 if (!url || !callback) { 00605 dns_dbg("DNS ERROR: NULL parameters\n"); 00606 pico_err = PICO_ERR_EINVAL; 00607 return -1; 00608 } 00609 00610 url_len = pico_dns_client_strlen(url); 00611 /* 2 extra bytes for url_len to account for 2 extra label length octets */ 00612 q_hdr = pico_zalloc(sizeof(struct dns_message_hdr) + (1 + url_len + 1) + sizeof(struct dns_query_suffix)); 00613 if (!q_hdr) { 00614 pico_err = PICO_ERR_ENOMEM; 00615 return -1; 00616 } 00617 q_qname = q_hdr + sizeof(struct dns_message_hdr); 00618 q_suf = q_qname + (1 + url_len + 1); 00619 00620 /* Construct query header */ 00621 hdr = (struct dns_message_hdr *) q_hdr; 00622 do { 00623 id = (uint16_t) (pico_rand() & 0xFFFFU); 00624 dns_dbg("DNS: generated id %u\n", id); 00625 } while (pico_dns_client_idcheck(id)); 00626 pico_dns_client_construct_hdr(hdr, id); 00627 /* Add and manipulate domain name */ 00628 memcpy(q_qname + 1, url, url_len + 1); 00629 pico_dns_client_label(q_qname); 00630 /* Add type and class of query */ 00631 query_suf.qtype = short_be(PICO_DNS_TYPE_A); 00632 query_suf.qclass = short_be(PICO_DNS_CLASS_IN); 00633 memcpy(q_suf, &query_suf, sizeof(struct dns_query_suffix)); 00634 /* Create RB entry */ 00635 key = pico_zalloc(sizeof(struct pico_dns_key)); 00636 if (!key) { 00637 pico_free(q_hdr); 00638 pico_err = PICO_ERR_ENOMEM; 00639 return -1; 00640 } 00641 key->q_hdr = q_hdr; 00642 key->len = sizeof(struct dns_message_hdr) + (1 + url_len + 1) + sizeof(struct dns_query_suffix); 00643 key->id = id; 00644 key->qtype = PICO_DNS_TYPE_A; 00645 key->qclass = PICO_DNS_CLASS_IN; 00646 key->retrans = 1; 00647 00648 key->q_ns = *((struct pico_dns_ns *)pico_tree_first(&NSTable)); 00649 key->s = NULL; 00650 key->callback = callback; 00651 key->arg = arg; 00652 /* Send query */ 00653 if (pico_dns_client_send(key) < 0) { 00654 pico_free(q_hdr); 00655 if (key->s) 00656 pico_socket_close(key->s); 00657 pico_free(key); 00658 pico_err = PICO_ERR_EAGAIN; 00659 return -1; 00660 } 00661 /* Insert RB entry */ 00662 00663 if(pico_tree_insert(&DNSTable,key)) { 00664 pico_free(q_hdr); 00665 pico_free(key); 00666 pico_err = PICO_ERR_EAGAIN; 00667 return -1; /* Element key already exists */ 00668 } 00669 00670 pico_timer_add(PICO_DNS_CLIENT_RETRANS, pico_dns_client_retransmission, key); 00671 return 0; 00672 } 00673 00674 int pico_dns_client_getname(const char *ip, void (*callback)(char *, void *), void *arg) 00675 { 00676 char *q_hdr, *q_qname, *q_suf; 00677 struct dns_message_hdr *hdr; 00678 struct dns_query_suffix query_suf; 00679 struct pico_dns_key *key; 00680 uint16_t ip_len = 0; 00681 uint16_t arpa_len = 0; 00682 uint16_t id = 0; 00683 00684 if (!ip || !callback) { 00685 dns_dbg("DNS ERROR: NULL parameters\n"); 00686 pico_err = PICO_ERR_EINVAL; 00687 return -1; 00688 } 00689 00690 ip_len = pico_dns_client_strlen(ip); 00691 arpa_len = pico_dns_client_strlen(".in-addr.arpa"); 00692 /* 2 extra bytes for ip_len and arpa_len to account for 2 extra length octets */ 00693 q_hdr = pico_zalloc(sizeof(struct dns_message_hdr) + (1 + ip_len + arpa_len + 1) + sizeof(struct dns_query_suffix)); 00694 if (!q_hdr) { 00695 pico_err = PICO_ERR_ENOMEM; 00696 return -1; 00697 } 00698 q_qname = q_hdr + sizeof(struct dns_message_hdr); 00699 q_suf = q_qname + (1 + ip_len + arpa_len + 1); 00700 00701 /* Construct query header */ 00702 hdr = (struct dns_message_hdr *)q_hdr; 00703 do { 00704 id = (uint16_t) (pico_rand() & 0xFFFFU); 00705 dns_dbg("DNS: generated id %u\n", id); 00706 } while (pico_dns_client_idcheck(id)); 00707 pico_dns_client_construct_hdr(hdr, id); 00708 /* Add and manipulate domain name */ 00709 memcpy(q_qname + 1, ip, ip_len + 1); 00710 pico_dns_client_mirror(q_qname + 1); 00711 memcpy(q_qname + 1 + ip_len, ".in-addr.arpa", arpa_len); 00712 pico_dns_client_label(q_qname); 00713 /* Add type and class of query */ 00714 query_suf.qtype = short_be(PICO_DNS_TYPE_PTR); 00715 query_suf.qclass = short_be(PICO_DNS_CLASS_IN); 00716 memcpy(q_suf, &query_suf, sizeof(struct dns_query_suffix)); 00717 /* Create RB entry */ 00718 key = pico_zalloc(sizeof(struct pico_dns_key)); 00719 if (!key) { 00720 pico_free(q_hdr); 00721 pico_err = PICO_ERR_ENOMEM; 00722 return -1; 00723 } 00724 key->q_hdr = q_hdr; 00725 key->len = sizeof(struct dns_message_hdr) + (1 + ip_len + arpa_len + 1) + sizeof(struct dns_query_suffix); 00726 key->id = id; 00727 key->qtype = PICO_DNS_TYPE_PTR; 00728 key->qclass = PICO_DNS_CLASS_IN; 00729 key->retrans = 1; 00730 key->q_ns = *((struct pico_dns_ns *)pico_tree_first(&NSTable)); 00731 key->s = NULL; 00732 key->callback = callback; 00733 key->arg = arg; 00734 /* Send query */ 00735 if (pico_dns_client_send(key) < 0) { 00736 pico_free(q_hdr); 00737 if (key->s) 00738 pico_socket_close(key->s); 00739 pico_free(key); 00740 pico_err = PICO_ERR_EAGAIN; 00741 return -1; 00742 } 00743 /* Insert RB entry */ 00744 00745 if(pico_tree_insert(&DNSTable,key)) { 00746 pico_free(q_hdr); 00747 pico_free(key); 00748 pico_err = PICO_ERR_EAGAIN; 00749 return -1; /* Element key already exists */ 00750 } 00751 00752 pico_timer_add(PICO_DNS_CLIENT_RETRANS, pico_dns_client_retransmission, key); 00753 return 0; 00754 } 00755 00756 #ifdef PICO_DNS_CLIENT_MAIN 00757 int main(int argc, char *argv[]) 00758 { 00759 dns_dbg(">>>>> DNS GET ADDR\n"); 00760 pico_dns_client_getaddr("www.google.be"); 00761 dns_dbg(">>>>> DNS GET NAME\n"); 00762 pico_dns_client_getname("173.194.67.94"); 00763 00764 return 0; 00765 } 00766 #endif /* PICO_DNS_CLIENT_MAIN */ 00767 #endif /* PICO_SUPPORT_DNS_CLIENT */
Generated on Wed Jul 13 2022 02:20:45 by 1.7.2