숙제로했던..dig..

신승한의 이미지

한번씩들봐주세요~
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: 
첨부파일 크기
Binary Data ass2.tar.gz7.24 KB
Forums: 
ed.netdiver의 이미지

얌냠...근데 mydig.h는 어디있나요?

좀 긴데, 파일첨부해주심 더 죠케떠엽~^^;

--------------------------------------------------------------------------------
\(´∇`)ノ \(´∇`)ノ \(´∇`)ノ \(´∇`)ノ
def ed():neTdiVeR in range(thEeArTh)

신승한의 이미지

#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;
고맙습니다~
댓글 첨부 파일: 
첨부파일 크기
Binary Data 0바이트
cppig1995의 이미지

더 깊이 파서 주석도~~ (퍽)

500m 파셨는데 10km 파시는 거야 뭐 힘들겠습니까? (퍼버벅)

Real programmers /* don't */ comment their code.
If it was hard to write, it should be /* hard to */ read.

익명 사용자의 이미지

cppig1995 wrote:
더 깊이 파서 주석도~~ (퍽)

500m 파셨는데 10km 파시는 거야 뭐 힘들겠습니까? (퍼버벅)

주석 잘달려 있사와요~ :roll:

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.