숙제로했던..dig..
글쓴이: 신승한 / 작성시간: 금, 2005/03/11 - 2:49오후
한번씩들봐주세요~
RFC1305 참고했습니다.
클라이언트쪽만우선...
#include "mydig.h"
#define DEBUG 0 // debug flag
int main(int argc, char **argv)
{
u_char buf[1024]={0}; // data buffer
HEADER *hdr; // header structure pointer
QUESTION *qst; // question structure pointer
struct sockaddr_in sin; // socket address structure
int sd; // socket descriptor
short ret; // a variable for return value from sendto, recvfrom
int pklen=0; // packet length
u_char *p; // a pointer to data buffer
int i = 0;
char serverIP[15]; // Server's IP address
char sport[5]; // Server's Port
short Qtype = 0; // Query type value
char *qname; // Query name value
struct timeval tv, td; // timevalue structures
double etime = 0; // elapsed time variable
// command line argument parsing
// @server port name type
if(argc < 5 || (**++argv != '@')) usage(*argv);
// Socket stuff setting
bzero(&sin,sizeof(sin)); // structure initializing as 0
// Server address conversion
strncpy(serverIP, ++(*argv), sizeof(char)*15);
if(inet_pton(AF_INET, serverIP, &sin.sin_addr) <= 0)
{
fprintf(stderr,"Invalid server address\n");
exit(-1);
}
if(DEBUG) printf("\ns_addr: %s", inet_ntoa(sin.sin_addr));
// Service port conversion
strncpy(sport, *++argv, sizeof(char)*5);
if(atoi(sport) > 65535 || atoi(sport) < 53)
{
fprintf(stderr,"Invalid service port\n");
exit(-1);
}
sin.sin_port=htons(atoi(sport)); // Service port bit order conversion
sin.sin_family=AF_INET; // Internet address family
// Query type
Qtype = qType(*(argv+2));
// reverse query processing from input
if(Qtype == 12) {
// input format check
if(inet_addr(*(argv+1)) == -1)
{
fprintf(stderr,"Invalid query name for PTR\n");
exit(-1);
}
// we need space for reverse query format
qname = (char *)malloc(strlen(*++argv)+13);
// query format conversion
make_reverse_qname(qname, *argv);
} else qname = *++argv; // it's not a reverse query
if(DEBUG) printf("after F:%s\n", qname);
// mapping up as type of HEADER
hdr = (HEADER *)buf;
hdr->id=htons(rand () % 65535); // random ID
hdr->qr = 0; // This is a query
hdr->rd = 1; // Recursive query request
hdr->opcode = htons(QUERY); // standard query
hdr->qdcount = htons(1); // # of questions
pklen += sizeof(HEADER);
// Question setting
pklen += mkQname(qname, &buf[pklen]); //Query name
// mapping up as type of question
qst = (QUESTION *)&buf[pklen];
qst->qtype=htons(Qtype);
qst->qclass=htons(C_IN);
pklen += sizeof(short) * 2; // increase packet length
//create the socket, a UDP datagram socket
if((sd=socket(AF_INET,SOCK_DGRAM,0)) < 0)
{
fprintf(stderr,"Socket error!");
exit(-2);
}
if(DEBUG) printf("\nFinal pklen: %d\n",pklen);
// signal handler setting for timeout
if(signal(SIGALRM, sig_alarm) == SIG_ERR)
{
perror("Signal error");
exit(-1);
}
// take the start time of query
gettimeofday(&tv, NULL);
// send query
ret = sendto(sd, buf, pklen, 0, (SA *)&sin, sizeof(sin));
if (ret < 0)
{
fprintf(stderr,"error: sendto error\n") ;
exit(-1);
}
alarm(10); // set timeout 3 seconds
bzero(&buf,sizeof(buf)); // structure initializing as 0
if(Qtype == 12) free(qname);// release the memory we got for reverse query
// receive result
if ((ret = recvfrom(sd, buf, sizeof(buf), 0, NULL, NULL)) < 0)
{
fprintf(stderr,"error: recvfrom error\n") ;
exit(-1);
}
// take the end time of query
gettimeofday(&td, NULL);
// we got the answer, map as the HEADER structure
hdr = (HEADER *)buf;
// Header parsing and print out
printf(";; ->>HEADER<<- opcode: %d, status: %d, id: %d\n", ntohs(hdr->opcode),ntohs(hdr->rcode), ntohs(hdr->id));
printf(";; QUERY: %d, ANSWER: %d, AUTHORITY: %d, ADDITIONAL: %d\n",ntohs(hdr->qdcount), ntohs(hdr->ancount), ntohs(hdr->nscount), ntohs(hdr->arcount));
// is the data trucated?
if (hdr->tc) printf("data truncated!\n");
// forward on the size of HEADER
p = buf+sizeof(HEADER);
// question part parsing
printf("\n;; QUESTION SECTION:\n");
for (i=ntohs(hdr->qdcount); i>0; --i)
{
p = toChar(buf, p);
printf("\tIN\t%s\n", *(argv+1));
p += 4; // skip type(x2)/class(x2)
}
// answer part parsing
printf("\n;; ANSWER SECTION:\n");
for (i=ntohs(hdr->ancount); i>0; --i)
p = RR_parsing(buf, p);
// authority part parsing
printf("\n\n;; AUTHORITY SECTION:\n");
for (i=ntohs(hdr->nscount); i>0; --i)
p = RR_parsing(buf, p);
// additional part parsing
printf("\n\n;; ADDITIONAL SECTION:\n");
for (i=ntohs(hdr->arcount); i>0; --i)
p = RR_parsing(buf, p);
// elapse time print out
printf("\n\n;; Query time: %2.0f msec\n",df(tv,td));
printf(";; MSG SIZE rcvd: %d bytes\n", ret);
printf(";; SERVER: %s#%s(%s)\n\n", *(argv-2), *(argv-1), *(argv-2));
return 0;
}
#include "mydig.h"
// translate string type query name into proper format
int mkQname(char *host, unsigned char *qname)
{
char *dummy=(char *)malloc(strlen(host)+3); // temporary space for strtok
int i=0;
int pklen = 0; // qname index number
char *p; // pointer to chunks
strcpy(dummy,host); // copy the string to temp
p = (char *)strtok(dummy, "."); // split the string with dot(.)s
while (p != NULL) // loop til we got the end
{
qname[pklen++] = strlen(p); // set '\num' of characters
while (i < strlen(p)) {
qname[pklen++] = p[i++]; // copy the characters
}
i = 0 ; // need to reset this for subsequent tokens
p =(char *)strtok(NULL, "."); // chop again
}
qname[pklen++] = '\0'; // the end of format
free(dummy); // release the temp
return pklen; // need to return the length of data to add to total length of the buffer
}
// Resource Record parsing function
char* RR_parsing(char *buf, unsigned char *p)
{
unsigned int rttl; // for TTL
unsigned short rtype; // for Resouce Type
unsigned short mx_pri; // for MX priority
RR *rr; // RR structure pointer
// domain name variable converting from bit to chars
p = toChar(buf, p);
putchar('\t');
// Buf to RR mapping
rr = (RR *)p;
rtype = ntohs(rr->rtype); // rtype conversion
rttl = ntohl(rr->rttl); // rttl conversion
p += 10; // forward 10byte of RR
// print the parsing results for each resource type
switch (rtype)
{
case 1: // A (IPV4)
printf("%4u IN A\t",rttl);
printf("%s\n",(char *) inet_ntoa(*(SI *)p));
p+=4;
break;
case 2: // NS
printf("%8u IN NS\t",rttl);
p=toChar(buf, p);
putchar('\n');
break;
case 5: // CNAME : it is not requirement but, I need it for some records to display properly
printf("%4u IN CNAME\t",rttl);
p=toChar(buf, p);
putchar('\n');
break;
case 6: // SOA : again, not requirement but, UoC DNS server reply wierd sometime, so just in case
printf("%4u IN SOA\t",rttl);
p = toChar(buf, p); putchar(' '); // SOA domain name
p = toChar(buf, p); putchar(' '); // email address of the admin
p = dword(p); putchar(' '); // serial
p = dword(p); putchar(' '); // refresh
p = dword(p); putchar(' '); // retry
p = dword(p); putchar(' '); // expire
p = dword(p); // minimum
break;
case 12: // PTR
printf("%4u IN PTR\t",rttl);
p=toChar(buf, p);
putchar('\n');
break;
case 15: // MX
mx_pri = (*p++) << 8; // MX priority conversion
mx_pri |= (*p++); // two 8 bits into on short number
printf("MX%4u\t", mx_pri);
p = toChar(buf, p);
putchar('\n');
break;
default: // Why should I bother?
printf("Unimplemented type:%d\n",rtype);
}
return p; // return the position in the buffer atfer
}
// convert bits pattern into characters
char* toChar(unsigned char *base, unsigned char *p)
{
unsigned short size;
unsigned short z;
while ((size = *p++))
{
// is message compressed?
if ((size & 192) == 192) {
// get offset
z = (size & ~192) << 8;
z |= *p++;
// recursive call me
toChar(base, base + z);
return p; // return the pointer position
} else { // no, it's just bits
// then.. print out!
for (; size-- > 0; ++p) putchar(*p);
putchar('.'); // dot for get the DOT
}
}
return p; // return the pointer position
}
// for the type of SOA, serial, refresh, retry, expire, and minimum
unsigned char* dword(unsigned char *q)
{
unsigned long val;
int i;
// make 4 bytes into one value
for (val=0, i=0; i < 4; i++) {
val <<= 8;
val |= *q++;
}
printf("%lu", val); // print out
return q; // return the position after
}
// usage print function
void usage(char *argv)
{
printf("Usage : %s @server port name type\n \
\n \
@server - IP of the DNS server you want(def: localhost)\n \
port - Service port of the @server (def: 53)\n \
name - Resource record you want\n \
type - Query type you want\n\n", argv);
exit(0);
}
// query type converting function, from string to short
short qType(char *argv)
{
printf("\nQTYPE: %s\n", argv);
// this function convert query type from input into integer value
if(strcmp(argv, "A") == 0) return T_A;
else if(strcmp(argv, "MX") == 0) return T_MX;
else if(strcmp(argv, "NS") == 0) return T_NS;
else if(strcmp(argv, "PTR") == 0) return T_PTR;
else{
fprintf(stderr,"Not supported qtype\n");
exit(-1);
}
}
// function that makes inverse query format from IP string
void make_reverse_qname(char *qname, char *argv)
{
int i = 0;
char *idx[4],*p;
idx[4] = (char *)strtok(argv, "."); // chop argv into pieces
while(idx[4-i] != NULL)
{
i++;
idx[4-i] = (char *)strtok(NULL, "."); // save the pieces in reverse order
}
p = qname; // set pointer to the start of target
for(i = 1 ; i <= 4; i++)
{
sprintf(p,"%s.",idx[i]);// copy it in normal order, which is actually reverse
p += strlen(p); // forward pointer by the last token length
}
sprintf(p,"in-addr.arpa"); // attach the last chunk
}
// signal handler
void sig_alarm(int whocares)
{
fprintf(stderr,"error :timeout !!\n");
exit(-1);
}
// elapsed time calculating
double df(struct timeval t1, struct timeval t2)
{
long sec, usec; // holds second, microsecond differences
// compute the differences of seconds and microseconds (usec)
usec = t2.tv_usec - t1.tv_usec;
sec = t2.tv_sec - t1.tv_sec;
// normalize
if (usec < 0){
sec--;
usec += 1000000;
}
// combine the values into a double
//return(((double) sec) + ((double) usec)/1000000.0); seconds
return(((double) sec) + ((double) usec)); // micro seconds
}
[/code]File attachments:
| 첨부 | 파일 크기 |
|---|---|
| 7.24 KB |
Forums:


얌냠...근데 mydig.h는 어디있나요?좀 긴데, 파일첨부해주심
얌냠...근데 mydig.h는 어디있나요?
좀 긴데, 파일첨부해주심 더 죠케떠엽~^^;
--------------------------------------------------------------------------------
\(´∇`)ノ \(´∇`)ノ \(´∇`)ノ \(´∇`)ノ
def ed():neTdiVeR in range(thEeArTh)
[code:1]#include <arpa/nameser.h>
#include <arpa/nameser.h> #include <arpa/inet.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <strings.h> #include <string.h> #include <ctype.h> #include <signal.h> #include <errno.h> #define DNS "136.159.5.16" #define SI struct in_addr #define SA struct sockaddr /* type of query ============== A : 1 NS : 2 CNAME : 5 PTR : 12 HINFO : 13 MX : 15 ANY : 255 */ typedef struct { unsigned qtype :16; /* type of query */ unsigned qclass :16; /* query class, IN for internet */ } QUESTION; typedef struct { unsigned rtype :16; /* type of query */ unsigned rclass :16; /* query class, IN for internet */ unsigned rttl:32; /* Time to live */ unsigned dlen:16; /* data length */ } RR; // client function prototypes short qType(char *); void usage(char *); void make_reverse_qname(char *, char *); double df(struct timeval, struct timeval); unsigned char* dword(unsigned char *); char* toChar(unsigned char *base, unsigned char *p); int mkQname(char *host, unsigned char *qname); char* RR_parsing(char *buf, unsigned char *curptr); void word(unsigned char *p); void sig_alarm(int); // cache functions and stuff #define BSIZE 256 // hash bucket size unsigned char* get_qname(unsigned char *base, unsigned char *p); void add_cache(unsigned char*, int); int search_cache(unsigned char *packet); int gethash(char *s); typedef struct cache_data *cptr; typedef struct cache_data{ int size; // packet size short type; // query type char *qname; // question name unsigned char* data; // packet data cptr next; // ptr to next in hash table } cdata;고맙습니다~첨부!
더 깊이 파서 주석도~~ (퍽)
500m 파셨는데 10km 파시는 거야 뭐 힘들겠습니까? (퍼버벅)
Real programmers /* don't */ comment their code.
If it was hard to write, it should be /* hard to */ read.
Re: 첨부!
주석 잘달려 있사와요~ :roll:
댓글 달기