1#include <stdio.h>
2#include <string.h>
3#include <unistd.h>
4#include <signal.h>
5#include <sys/types.h>
6#include <sys/time.h>
7#include <sys/wait.h>
8#include <sys/socket.h>
9#include <netinet/in.h>
10#include <arpa/inet.h>
11#include <errno.h>
12#include <fcntl.h>
13#include <unistd.h>
14#include <arpa/inet.h>
15#include <net/if.h>
16#include <sys/ioctl.h>
17
18#include "dns.h"
19
20#define DNS_PORT 53
21#define SVR_PORT 4567
22
23static int
24waitsock(int sockfd, int sec, int usec)
25{
26	struct timeval tv;
27	fd_set 	fdvar;
28	int		res;
29
30	FD_ZERO(&fdvar);
31	FD_SET(sockfd, &fdvar);
32
33	tv.tv_sec = sec;
34	tv.tv_usec = usec;
35
36	res = select(sockfd + 1, &fdvar, NULL, NULL, &tv);
37
38	return res;
39}
40
41
42void dns_query(char *svrip, char *hostname, char qtype, char *ret)
43{
44    int                 sockfd;
45    struct sockaddr_in  svr, cli, from;
46    char dnsbuf[MAX_PACKET_SIZE];
47    int dnsbuflen;
48    dns_request_t m;
49    int i;
50    int retryCount;
51
52    if((sockfd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0 )
53    {
54        //perror("can't open datagram socket\n");
55        return;
56    }
57
58    bzero((char *)&svr, sizeof(svr));
59    svr.sin_family        = AF_INET;
60    svr.sin_addr.s_addr   = htonl(INADDR_ANY);
61    svr.sin_port          = htons(SVR_PORT);
62
63    if(bind(sockfd, (struct sockaddr *)&svr, sizeof(svr))<0)
64    {
65		//perror("can't bind datagram socket\n");
66	close(sockfd);
67	return;
68    }
69
70    bzero((char *)&cli, sizeof(cli));
71
72    cli.sin_family = AF_INET;
73    cli.sin_addr.s_addr = inet_addr(svrip);
74    cli.sin_port = htons(DNS_PORT);
75
76    dnsbuflen = 0;
77
78    dnsbuf[dnsbuflen++] = 0x00;	//Transaction ID
79    dnsbuf[dnsbuflen++] = 0x86;
80    dnsbuf[dnsbuflen++] = 0x01; //Flag: Standard query
81    dnsbuf[dnsbuflen++] = 0x00;
82    dnsbuf[dnsbuflen++] = 0x00; //Question
83    dnsbuf[dnsbuflen++] = 0x01;
84    memset(&dnsbuf[dnsbuflen], 0x00, 6);//Answer RRs, Authority RRs, Additional RRs
85    dnsbuflen+=6;
86    dnsbuflen+=dns_construct_name(hostname, &dnsbuf[dnsbuflen]);
87    if (qtype != 'M')
88    {
89      dnsbuf[dnsbuflen++] = 0x00; // Type a: host address
90      dnsbuf[dnsbuflen++] = 0x01;
91    }
92    else
93    {
94      dnsbuf[dnsbuflen++] = 0x00; // Type MX: Mail Exchanger
95      dnsbuf[dnsbuflen++] = 0x0f;
96    }
97    dnsbuf[dnsbuflen++] = 0x00; // Class : inet
98    dnsbuf[dnsbuflen++] = 0x01;
99
100    retryCount = 0;
101
102retry:
103    retryCount++;
104
105    if (retryCount==4) goto finish;
106
107    if(sendto(sockfd , dnsbuf, dnsbuflen , 0 ,(struct sockaddr *) &cli, sizeof(cli)) == -1)
108    {
109       //perror("sendto\n");
110       goto retry;
111    }
112
113    if (waitsock(sockfd, 3, 0) == 0)
114    {
115	//perror("timeout\n");
116 	goto retry;
117    }
118
119    if ((m.numread=recvfrom(sockfd, m.original_buf, sizeof(m.original_buf), 0, NULL, sizeof(from))) == -1)
120    {
121	//perror("recvfrom\n");
122	goto retry;
123    }
124
125    if (m.numread<sizeof(m.message.header))
126    {
127	//perror("invalid packet\n");
128	goto retry;
129    }
130
131    dns_decode_request(&m);
132
133    if (m.message.header.flags.f.rcode==0)
134    {
135    	if (qtype != 'M')
136	   sprintf(ret, "%s", m.ip);
137	else
138	   sprintf(ret, "%s", m.cname);
139#ifdef REMOVE_WL600
140	printf("Recv: \n");
141	for(i=0; i<m.numread; i++)
142	{
143		printf("%02x ", (unsigned char )m.original_buf[i]);
144		if (i%16==15) printf("\n");
145	}
146#endif
147    }
148    else goto retry;
149
150finish:
151    close(sockfd);
152    return;
153}
154
155int dns_construct_name(char *name, char *encoded_name)
156{
157  int i,j,k,n;
158
159  k = 0; /* k is the index to temp */
160  i = 0; /* i is the index to name */
161  while( name[i] ){
162
163	 /* find the dist to the next '.' or the end of the string and add it*/
164	 for( j = 0; name[i+j] && name[i+j] != '.'; j++);
165	 encoded_name[k++] = j;
166
167	 /* now copy the text till the next dot */
168	 for( n = 0; n < j; n++)
169		encoded_name[k++] = name[i+n];
170
171	 /* now move to the next dot */
172	 i += j + 1;
173
174	 /* check to see if last dot was not the end of the string */
175	 if(!name[i-1])break;
176  }
177  encoded_name[k++] = 0;
178  return k;
179}
180
181/* CVS edit 1 */
182