From c96d656001914b495f54e7a25d54079e41af86ce Mon Sep 17 00:00:00 2001 From: patacongo Date: Mon, 3 Sep 2007 20:34:44 +0000 Subject: Add send, sendto, rec, recvfrom git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@328 42af7a65-404d-4744-a932-0658087f49c3 --- nuttx/netutils/resolv/resolv.c | 399 +++++++++++++++-------------------------- 1 file changed, 142 insertions(+), 257 deletions(-) (limited to 'nuttx/netutils/resolv/resolv.c') diff --git a/nuttx/netutils/resolv/resolv.c b/nuttx/netutils/resolv/resolv.c index f149c6a80..512f1ac59 100644 --- a/nuttx/netutils/resolv/resolv.c +++ b/nuttx/netutils/resolv/resolv.c @@ -54,7 +54,7 @@ #include #include -#include +#include #include /**************************************************************************** @@ -87,11 +87,8 @@ #define DNS_FLAG2_ERR_NONE 0x00 #define DNS_FLAG2_ERR_NAME 0x03 -#define STATE_UNUSED 0 -#define STATE_NEW 1 -#define STATE_ASKING 2 -#define STATE_DONE 3 -#define STATE_ERROR 4 +#define SEND_BUFFER_SIZE 64 +#define RECV_BUFFER_SIZE 64 /**************************************************************************** * Private Types @@ -140,8 +137,13 @@ struct namemap ****************************************************************************/ static struct namemap names[RESOLV_ENTRIES]; -static uint8 seqno; -static struct uip_udp_conn *resolv_conn = NULL; +static uint8 gseqno; +static int g_sockfd = -1; +#ifdef CONFIG_NET_IPv6 +static struct sockaddr_in6 gdnsserver; +#else +static struct sockaddr_in gdnsserver; +#endif /**************************************************************************** * Private Functions @@ -171,90 +173,76 @@ static unsigned char *parse_name(unsigned char *query) * not yet been queried and, if so, sends out a query. */ -static void check_entries(void) +static int send_query(const char name) { register struct dns_hdr *hdr; - char *query, *nptr, *nameptr; + char *query; + char *nptr; + char **nameptr; static uint8 i; static uint8 n; - register struct namemap *namemapptr; + uint8 state = NEW_STATE; + uint8 seqno = gsegno++; + uint8 err; + static unsigned char endquery[] = {0,0,1,0,1}; + char buffer[SEND_BUFFER_SIZE]; - for(i = 0; i < RESOLV_ENTRIES; ++i) - { - namemapptr = &names[i]; - if (namemapptr->state == STATE_NEW || - namemapptr->state == STATE_ASKING) - { - if (namemapptr->state == STATE_ASKING) - { - if (--namemapptr->tmr == 0) - { - if (++namemapptr->retries == MAX_RETRIES) - { - namemapptr->state = STATE_ERROR; - resolv_found(namemapptr->name, NULL); - continue; - } - namemapptr->tmr = namemapptr->retries; - } - else - { - /* Its timer has not run out, so we move on to next entry. */ - continue; - } - } - else - { - namemapptr->state = STATE_ASKING; - namemapptr->tmr = 1; - namemapptr->retries = 0; - } - hdr = (struct dns_hdr *)uip_appdata; - memset(hdr, 0, sizeof(struct dns_hdr)); - hdr->id = htons(i); - hdr->flags1 = DNS_FLAG1_RD; - hdr->numquestions = HTONS(1); - query = (char *)uip_appdata + 12; - nameptr = namemapptr->name; - --nameptr; - - /* Convert hostname into suitable query format. */ - do - { - ++nameptr; - nptr = query; - ++query; - for (n = 0; *nameptr != '.' && *nameptr != 0; ++nameptr) - { - *query = *nameptr; - ++query; - ++n; - } - *nptr = n; - } - while(*nameptr != 0); - { - static unsigned char endquery[] = {0,0,1,0,1}; - memcpy(query, endquery, 5); - } - uip_udp_send((unsigned char)(query + 5 - (char *)uip_appdata)); - break; - } - } + hdr = (struct dns_hdr*)buffer; + memset(hdr, 0, sizeof(struct dns_hdr)); + hdr->id = htons(seqno); + hdr->flags1 = DNS_FLAG1_RD; + hdr->numquestions = HTONS(1); + query = buffer + 12; + + /* Convert hostname into suitable query format. */ + + nameptr = name - 1; + do + { + nameptr++; + nptr = query++; + for (n = 0; *nameptr != '.' && *nameptr != 0; ++nameptr) + { + *query = *nameptr; + ++query; + ++n; + } + *nptr = n; + } + while(*nameptr != 0); + + memcpy(query, endquery, 5); + return sendto(gsockfd, buffer, query + 5 - buffer); } /* Called when new UDP data arrives */ -static void newdata(void) +#ifdef CONFIG_NET_IPv6 +#error "Not implemented +#else +int recv_response(struct sockaddr_in *addr) +#endif + +hdr->flags2 & DNS_FLAG2_ERR_MASKstatic int (void) { unsigned char *nameptr; + char buffer[RECV_BUFFER_SIZE]; struct dns_answer *ans; struct dns_hdr *hdr; - static uint8 nquestions, nanswers; - static uint8 i; - register struct namemap *namemapptr; + uint8 nquestions; + uint8 nanswers; + uint8 i; + int ret; - hdr = (struct dns_hdr *)uip_appdata; + /* Receive the response */ + + ret = recv(g_sockfd, buffer, RECV_BUFFER_SIZE); + if (ret < 0) + { + return ret; + } + + hdr = (struct dns_hdr *)b dbg( "ID %d\n", htons(hdr->id)); dbg( "Query %d\n", hdr->flags1 & DNS_FLAG1_RESPONSE); @@ -263,226 +251,123 @@ static void newdata(void) htons(hdr->numquestions), htons(hdr->numanswers), htons(hdr->numauthrr), htons(hdr->numextrarr)); - /* The ID in the DNS header should be our entry into the name - * table. - */ + /* Check for error. If so, call callback to inform */ - i = htons(hdr->id); - namemapptr = &names[i]; - if (i < RESOLV_ENTRIES && namemapptr->state == STATE_ASKING) + if ((hdr->flags2 & DNS_FLAG2_ERR_MASK) != 0) { - /* This entry is now finished */ + return ERROR; + } - namemapptr->state = STATE_DONE; - namemapptr->err = hdr->flags2 & DNS_FLAG2_ERR_MASK; + /* We only care about the question(s) and the answers. The authrr + * and the extrarr are simply discarded. + */ - /* Check for error. If so, call callback to inform */ + nquestions = htons(hdr->numquestions); + nanswers = htons(hdr->numanswers); - if (namemapptr->err != 0) - { - namemapptr->state = STATE_ERROR; - resolv_found(namemapptr->name, NULL); - return; - } + /* Skip the name in the question. XXX: This should really be + * checked agains the name in the question, to be sure that they + * match. + */ - /* We only care about the question(s) and the answers. The authrr - * and the extrarr are simply discarded. - */ - - nquestions = htons(hdr->numquestions); - nanswers = htons(hdr->numanswers); + nameptr = parse_name((unsigned char *)buffer + 12) + 4; - /* Skip the name in the question. XXX: This should really be - * checked agains the name in the question, to be sure that they - * match. + for (; nanswers > 0; nanswers--) + { + /* The first byte in the answer resource record determines if it + * is a compressed record or a normal one. */ - nameptr = parse_name((unsigned char *)uip_appdata + 12) + 4; - - while(nanswers > 0) + if (*nameptr & 0xc0) { - /* The first byte in the answer resource record determines if it - * is a compressed record or a normal one. - */ - - if (*nameptr & 0xc0) - { - /* Compressed name. */ - - nameptr +=2; - dbg("Compressed anwser\n"); - } - else - { - /* Not compressed name. */ - nameptr = parse_name(nameptr); - } - - ans = (struct dns_answer *)nameptr; - dbg("Answer: type %x, class %x, ttl %x, length %x\n", - htons(ans->type), htons(ans->class), (htons(ans->ttl[0]) << 16) | htons(ans->ttl[1]), - htons(ans->len)); - - /* Check for IP address type and Internet class. Others are discarded. */ - - if (ans->type == HTONS(1) && ans->class == HTONS(1) && ans->len == HTONS(4)) - { - dbg("IP address %d.%d.%d.%d\n", - htons(ans->ipaddr[0]) >> 8, htons(ans->ipaddr[0]) & 0xff, - htons(ans->ipaddr[1]) >> 8, htons(ans->ipaddr[1]) & 0xff); - - /* XXX: we should really check that this IP address is the one - * we want. - */ - - namemapptr->ipaddr[0] = ans->ipaddr[0]; - namemapptr->ipaddr[1] = ans->ipaddr[1]; - - resolv_found(namemapptr->name, namemapptr->ipaddr); - return; - } - else - { - nameptr = nameptr + 10 + htons(ans->len); - } - --nanswers; - } - } -} + /* Compressed name. */ -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/* This function is called by the UIP interrupt handling logic whenevent an - * event of interest occurs. - */ - -void uip_interrupt_udp_event(void) -{ - if (uip_udp_conn->rport == HTONS(53)) - { - if (uip_poll()) - { - check_entries(); + nameptr +=2; + dbg("Compressed anwser\n"); } - if (uip_newdata()) + else { - newdata(); + /* Not compressed name. */ + nameptr = parse_name(nameptr); } - } -} - -/* Queues a name so that a question for the name will be sent out. */ -void resolv_query(char *name) -{ - static uint8 i; - static uint8 lseq, lseqi; - register struct namemap *nameptr; + ans = (struct dns_answer *)nameptr; + dbg("Answer: type %x, class %x, ttl %x, length %x\n", + htons(ans->type), htons(ans->class), (htons(ans->ttl[0]) << 16) | htons(ans->ttl[1]), + htons(ans->len)); - lseq = lseqi = 0; + /* Check for IP address type and Internet class. Others are discarded. */ - for(i = 0; i < RESOLV_ENTRIES; ++i) - { - nameptr = &names[i]; - if (nameptr->state == STATE_UNUSED) + if (ans->type == HTONS(1) && ans->class == HTONS(1) && ans->len == HTONS(4)) { - break; + dbg("IP address %d.%d.%d.%d\n", + htons(ans->ipaddr[0]) >> 8, htons(ans->ipaddr[0]) & 0xff, + htons(ans->ipaddr[1]) >> 8, htons(ans->ipaddr[1]) & 0xff); + + /* XXX: we should really check that this IP address is the one + * we want. + */ + + addr->sin_addr.s_addr = ((uint32)ans->ipaddr[0] << 16) | (uint32)ans->ipaddr[1]; + return OK; } - if (seqno - nameptr->seqno > lseq) + else { - lseq = seqno - nameptr->seqno; - lseqi = i; + nameptr = nameptr + 10 + htons(ans->len); } } - - if (i == RESOLV_ENTRIES) - { - i = lseqi; - nameptr = &names[i]; - } - - dbg("Using entry %d\n", i); - - strcpy(nameptr->name, name); - nameptr->state = STATE_NEW; - nameptr->seqno = seqno; - ++seqno; } -/* Look up a hostname in the array of known hostnames. - * - * Note: This function only looks in the internal array of known - * hostnames, it does not send out a query for the hostname if none - * was found. The function resolv_query() can be used to send a query - * for a hostname. - * - * Return A pointer to a 4-byte representation of the hostname's IP - * address, or NULL if the hostname was not found in the array of - * hostnames. - */ - -uint16 *resolv_lookup(char *name) -{ - static uint8 i; - struct namemap *nameptr; +/**************************************************************************** + * Public Functions + ****************************************************************************/ - /* Walk through the list to see if the name is in there. If it is - * not, we return NULL. - */ +/* Get the binding for name. */ - for(i = 0; i < RESOLV_ENTRIES; ++i) +#ifdef CONFIG_NET_IPv6 +int resolv_query(char *name, struct sockaddr_in6 *addr) +#else +int resolv_query(char *name, struct sockaddr_in *addr) +#endif +{ + int ret = send_query(name); + if (ret == 0) { - nameptr = &names[i]; - if (nameptr->state == STATE_DONE && strcmp(name, nameptr->name) == 0) - { - return nameptr->ipaddr; - } + ret = recv_response(addr); } - return NULL; + return ret; } -/* Obtain the currently configured DNS server. - * - * Return: A pointer to a 4-byte representation of the IP address of - * the currently configured DNS server or NULL if no DNS server has - * been configured. - */ +/* Obtain the currently configured DNS server. */ -uint16 *resolv_getserver(void) +#ifdef CONFIG_NET_IPv6 +void resolv_getserver(const struct sockaddr_in6 *dnsserver) +#else +void resolv_getserver(const struct sockaddr_in *dnsserver) +#endif { - if (resolv_conn == NULL) - { - return NULL; - } - return resolv_conn->ripaddr; + memcpy(dnsserver, gdnsserver, sizeof(gdnsserver)); } -/* Configure which DNS server to use for queries. - * - * dnsserver A pointer to a 4-byte representation of the IP - * address of the DNS server to be configured. - */ +/* Configure which DNS server to use for queries */ -void resolv_conf(uint16 *dnsserver) +#ifdef CONFIG_NET_IPv6 +void resolv_conf(const struct sockaddr_in6 *dnsserver) +#else +void resolv_conf(const struct sockaddr_in *dnsserver) +#endif { - if (resolv_conn != NULL) - { - uip_udp_remove(resolv_conn); - } - - resolv_conn = uip_udp_new(dnsserver, HTONS(53)); + memcpy(&gdnsserver, dnsserver, sizeof(gdnsserver)); } /* Initalize the resolver. */ -void resolv_init(void) +int resolv_init(void) { - static uint8 i; - - for(i = 0; i < RESOLV_ENTRIES; ++i) + g_sockfd = socket(PF_INET, SOCK_DGRAM, 0); + if (g_sockfd < 0) { - names[i].state = STATE_DONE; + return ERROR; } + return OK; } -- cgit v1.2.3