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