resolv.c
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 #include "net/tcpip.h"
00065 #include "net/resolv.h"
00066 #if UIP_UDP
00067
00068 #include <string.h>
00069
00070 #ifndef NULL
00071 #define NULL (void *)0
00072 #endif
00073
00074 #if UIP_CONF_IPV6
00075
00076
00077
00078
00079
00080
00081 process_event_t resolv_event_found;
00082
00083 PROCESS(resolv_process, "DNS resolver");
00084
00085 void resolv_conf(const uip_ipaddr_t *dnsserver) { }
00086 uip_ipaddr_t *resolv_getserver(void) { return NULL; }
00087 uip_ipaddr_t *resolv_lookup(const char *name) { return NULL; }
00088 void resolv_query(const char *name) { }
00089
00090 PROCESS_THREAD(resolv_process, ev, data)
00091 {
00092 PROCESS_BEGIN();
00093 resolv_event_found = process_alloc_event();
00094 PROCESS_END();
00095 }
00096
00097 #else
00098
00099
00100 #define MAX_RETRIES 8
00101
00102
00103 struct dns_hdr {
00104 u16_t id;
00105 u8_t flags1, flags2;
00106 #define DNS_FLAG1_RESPONSE 0x80
00107 #define DNS_FLAG1_OPCODE_STATUS 0x10
00108 #define DNS_FLAG1_OPCODE_INVERSE 0x08
00109 #define DNS_FLAG1_OPCODE_STANDARD 0x00
00110 #define DNS_FLAG1_AUTHORATIVE 0x04
00111 #define DNS_FLAG1_TRUNC 0x02
00112 #define DNS_FLAG1_RD 0x01
00113 #define DNS_FLAG2_RA 0x80
00114 #define DNS_FLAG2_ERR_MASK 0x0f
00115 #define DNS_FLAG2_ERR_NONE 0x00
00116 #define DNS_FLAG2_ERR_NAME 0x03
00117 u16_t numquestions;
00118 u16_t numanswers;
00119 u16_t numauthrr;
00120 u16_t numextrarr;
00121 };
00122
00123
00124 struct dns_answer {
00125
00126
00127 u16_t type;
00128 u16_t class;
00129 u16_t ttl[2];
00130 u16_t len;
00131 u8_t ipaddr[4];
00132 };
00133
00134 struct namemap {
00135 #define STATE_UNUSED 0
00136 #define STATE_NEW 1
00137 #define STATE_ASKING 2
00138 #define STATE_DONE 3
00139 #define STATE_ERROR 4
00140 u8_t state;
00141 u8_t tmr;
00142 u8_t retries;
00143 u8_t seqno;
00144 u8_t err;
00145 char name[32];
00146 uip_ipaddr_t ipaddr;
00147 };
00148
00149 #ifndef UIP_CONF_RESOLV_ENTRIES
00150 #define RESOLV_ENTRIES 4
00151 #else
00152 #define RESOLV_ENTRIES UIP_CONF_RESOLV_ENTRIES
00153 #endif
00154
00155
00156 static struct namemap names[RESOLV_ENTRIES];
00157
00158 static u8_t seqno;
00159
00160 static struct uip_udp_conn *resolv_conn = NULL;
00161
00162 static struct etimer retry;
00163
00164 process_event_t resolv_event_found;
00165
00166 PROCESS(resolv_process, "DNS resolver");
00167
00168 static void resolv_found(char *name, uip_ipaddr_t *ipaddr);
00169
00170 enum {
00171 EVENT_NEW_SERVER=0
00172 };
00173
00174
00175
00176
00177
00178
00179
00180
00181 static unsigned char *
00182 parse_name(unsigned char *query)
00183 {
00184 unsigned char n;
00185
00186 do {
00187 n = *query++;
00188
00189 while(n > 0) {
00190
00191 ++query;
00192 --n;
00193 };
00194
00195 } while(*query != 0);
00196
00197 return query + 1;
00198 }
00199
00200
00201
00202
00203
00204
00205 static void
00206 check_entries(void)
00207 {
00208 register struct dns_hdr *hdr;
00209 char *query, *nptr, *nameptr;
00210 uint8_t i;
00211 uint8_t n;
00212 register struct namemap *namemapptr;
00213
00214 for(i = 0; i < RESOLV_ENTRIES; ++i) {
00215 namemapptr = &names[i];
00216 if(namemapptr->state == STATE_NEW ||
00217 namemapptr->state == STATE_ASKING) {
00218 etimer_set(&retry, CLOCK_SECOND);
00219 if(namemapptr->state == STATE_ASKING) {
00220 if(--namemapptr->tmr == 0) {
00221 if(++namemapptr->retries == MAX_RETRIES) {
00222 namemapptr->state = STATE_ERROR;
00223 resolv_found(namemapptr->name, NULL);
00224 continue;
00225 }
00226 namemapptr->tmr = namemapptr->retries;
00227 } else {
00228
00229
00230
00231 continue;
00232 }
00233 } else {
00234 namemapptr->state = STATE_ASKING;
00235 namemapptr->tmr = 1;
00236 namemapptr->retries = 0;
00237 }
00238 hdr = (struct dns_hdr *)uip_appdata;
00239 memset(hdr, 0, sizeof(struct dns_hdr));
00240 hdr->id = uip_htons(i);
00241 hdr->flags1 = DNS_FLAG1_RD;
00242 hdr->numquestions = UIP_HTONS(1);
00243 query = (char *)uip_appdata + 12;
00244 nameptr = namemapptr->name;
00245 --nameptr;
00246
00247 do {
00248 ++nameptr;
00249 nptr = query;
00250 ++query;
00251 for(n = 0; *nameptr != '.' && *nameptr != 0; ++nameptr) {
00252 *query = *nameptr;
00253 ++query;
00254 ++n;
00255 }
00256 *nptr = n;
00257 } while(*nameptr != 0);
00258 {
00259 static unsigned char endquery[] =
00260 {0,0,1,0,1};
00261 memcpy(query, endquery, 5);
00262 }
00263 uip_udp_send((unsigned char)(query + 5 - (char *)uip_appdata));
00264 break;
00265 }
00266 }
00267 }
00268
00269
00270
00271
00272
00273 static void
00274 newdata(void)
00275 {
00276 unsigned char *nameptr;
00277 struct dns_answer *ans;
00278 struct dns_hdr *hdr;
00279 static u8_t nquestions, nanswers;
00280 static u8_t i;
00281 register struct namemap *namemapptr;
00282
00283 hdr = (struct dns_hdr *)uip_appdata;
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296 i = (u8_t)uip_htons(hdr->id);
00297 namemapptr = &names[i];
00298 if(i < RESOLV_ENTRIES &&
00299 namemapptr->state == STATE_ASKING) {
00300
00301
00302 namemapptr->state = STATE_DONE;
00303 namemapptr->err = hdr->flags2 & DNS_FLAG2_ERR_MASK;
00304
00305
00306 if(namemapptr->err != 0) {
00307 namemapptr->state = STATE_ERROR;
00308 resolv_found(namemapptr->name, NULL);
00309 return;
00310 }
00311
00312
00313
00314 nquestions = (u8_t)uip_htons(hdr->numquestions);
00315 nanswers = (u8_t)uip_htons(hdr->numanswers);
00316
00317
00318
00319
00320 nameptr = parse_name((uint8_t *)uip_appdata + 12) + 4;
00321
00322 while(nanswers > 0) {
00323
00324
00325 if(*nameptr & 0xc0) {
00326
00327 nameptr +=2;
00328
00329 } else {
00330
00331 nameptr = parse_name((uint8_t *)nameptr);
00332 }
00333
00334 ans = (struct dns_answer *)nameptr;
00335
00336
00337
00338
00339
00340
00341 if(ans->type == UIP_HTONS(1) &&
00342 ans->class == UIP_HTONS(1) &&
00343 ans->len == UIP_HTONS(4)) {
00344
00345
00346
00347
00348
00349
00350
00351 for(i = 0; i < 4; i++) {
00352 namemapptr->ipaddr.u8[i] = ans->ipaddr[i];
00353 }
00354
00355 resolv_found(namemapptr->name, &namemapptr->ipaddr);
00356 return;
00357 } else {
00358 nameptr = nameptr + 10 + uip_htons(ans->len);
00359 }
00360 --nanswers;
00361 }
00362 }
00363 }
00364
00365
00366
00367
00368
00369 PROCESS_THREAD(resolv_process, ev, data)
00370 {
00371 int i;
00372
00373 PROCESS_BEGIN();
00374
00375 for(i = 0; i < RESOLV_ENTRIES; ++i) {
00376 names[i].state = STATE_UNUSED;
00377 }
00378 resolv_conn = NULL;
00379 resolv_event_found = process_alloc_event();
00380
00381
00382 while(1) {
00383 PROCESS_WAIT_EVENT();
00384
00385 if(ev == PROCESS_EVENT_TIMER) {
00386 if(resolv_conn != NULL) {
00387 tcpip_poll_udp(resolv_conn);
00388 }
00389
00390 } else if(ev == EVENT_NEW_SERVER) {
00391 if(resolv_conn != NULL) {
00392 uip_udp_remove(resolv_conn);
00393 }
00394 resolv_conn = udp_new((uip_ipaddr_t *)data, UIP_HTONS(53), NULL);
00395
00396 } else if(ev == tcpip_event) {
00397 if(uip_udp_conn->rport == UIP_HTONS(53)) {
00398 if(uip_poll()) {
00399 check_entries();
00400 }
00401 if(uip_newdata()) {
00402 newdata();
00403 }
00404 }
00405 }
00406 }
00407
00408 PROCESS_END();
00409 }
00410
00411
00412
00413
00414
00415
00416
00417 void
00418 resolv_query(const char *name)
00419 {
00420 static u8_t i;
00421 static u8_t lseq, lseqi;
00422 register struct namemap *nameptr;
00423
00424 lseq = lseqi = 0;
00425 nameptr = 0;
00426
00427 for(i = 0; i < RESOLV_ENTRIES; ++i) {
00428 nameptr = &names[i];
00429 if(nameptr->state == STATE_UNUSED) {
00430 break;
00431 }
00432 if(seqno - nameptr->seqno > lseq) {
00433 lseq = seqno - nameptr->seqno;
00434 lseqi = i;
00435 }
00436 }
00437
00438 if(i == RESOLV_ENTRIES) {
00439 i = lseqi;
00440 nameptr = &names[i];
00441 }
00442
00443 strncpy(nameptr->name, name, sizeof(nameptr->name));
00444 nameptr->state = STATE_NEW;
00445 nameptr->seqno = seqno;
00446 ++seqno;
00447
00448 if(resolv_conn != NULL) {
00449 tcpip_poll_udp(resolv_conn);
00450 }
00451 }
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466 uip_ipaddr_t *
00467 resolv_lookup(const char *name)
00468 {
00469 static u8_t i;
00470 struct namemap *nameptr;
00471
00472
00473
00474 for(i = 0; i < RESOLV_ENTRIES; ++i) {
00475 nameptr = &names[i];
00476 if(nameptr->state == STATE_DONE &&
00477 strcmp(name, nameptr->name) == 0) {
00478 return &nameptr->ipaddr;
00479 }
00480 }
00481 return NULL;
00482 }
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492 uip_ipaddr_t *
00493 resolv_getserver(void)
00494 {
00495 if(resolv_conn == NULL) {
00496 return NULL;
00497 }
00498 return &resolv_conn->ripaddr;
00499 }
00500
00501
00502
00503
00504
00505
00506
00507
00508 void
00509 resolv_conf(const uip_ipaddr_t *dnsserver)
00510 {
00511 static uip_ipaddr_t server;
00512 uip_ipaddr_copy(&server, dnsserver);
00513 process_post(&resolv_process, EVENT_NEW_SERVER, &server);
00514
00515
00516
00517
00518
00519
00520 }
00521
00522
00523
00524
00525
00526
00527 static void
00528 resolv_found(char *name, uip_ipaddr_t *ipaddr)
00529 {
00530 process_post(PROCESS_BROADCAST, resolv_event_found, name);
00531 }
00532
00533 #endif
00534 #endif
00535
00536
00537