使用udp发送域名请求

#include <sys/socket.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <netinet/in.h>
#include <string.h>
#pragma pack(push)
#pragma pack(1)
typedef struct dns_query_header
{
  unsigned short transid;
  unsigned short flags;
  unsigned short questions;
  unsigned short answer;
  unsigned short authority;
  unsigned short additional;
}dns_query_header, *pdns_query_header;

typedef struct dns_query_body
{
  unsigned char body[100];
}dns_query_body;

typedef struct dns_answer_body
{
	unsigned char body[100];
	//name
	//type
	//closs
	//ttl
	//length
	//addr
}dns_answer_body;
#pragma pack(pop)
int main(int argc, const char* argv[])
{

	if(argc != 3)
	{
		printf("%s domain dnsserverip\n", argv[0]);
		return 0;
	}
	const char * domain = argv[1];
	const char * dns_sever = argv[2];
  int sock = socket(AF_INET, SOCK_DGRAM, 0);
  struct sockaddr_in dnsaddr;

  dnsaddr.sin_family = AF_INET;
  dnsaddr.sin_addr.s_addr = inet_addr(dns_sever);
  dnsaddr.sin_port = htons(53);

  dns_query_header dqh;
  dqh.transid = 0x1234;
  dqh.flags = htons(0x0100);
  dqh.questions = htons(0x1);
  dqh.answer = 0;
  dqh.authority = 0;
  dqh.additional = 0;
  
  int cursor = 0;
  dns_query_body dqb;
  memset((void *)dqb.body, 0x00, sizeof(dqb.body));
	int i = 0;
  // dqb.body[cursor++] = 3;
  // int i = 0;
  // for(i = 0; i < 3; i++)
    // {
      // dqb.body[cursor++] = 'w';
    // }
  // dqb.body[cursor++] = 6;
  // dqb.body[cursor++] = 'g';
  // dqb.body[cursor++] = 'o';
  // dqb.body[cursor++] = 'o';
  // dqb.body[cursor++] = 'g';
  // dqb.body[cursor++] = 'l';
  // dqb.body[cursor++] = 'e';
  // dqb.body[cursor++] = 3;
  // dqb.body[cursor++] = 'c';
  // dqb.body[cursor++] = 'o';
  // dqb.body[cursor++] = 'm';
  // dqb.body[cursor++] = '\0';
  // dqb.body[cursor++] = 3;
  // dqb.body[cursor++] = 'k';
  // dqb.body[cursor++] = 's';
  // dqb.body[cursor++] = 'u';
  // dqb.body[cursor++] = 3;
  // dqb.body[cursor++] = 'e';
  // dqb.body[cursor++] = 'd';
  // dqb.body[cursor++] = 'u';
  // dqb.body[cursor++] = '\0';
  unsigned char tcount = 0;
  cursor++; //blank for count
  for(i = 0; i < strlen(domain); i++)
  {
	if(domain[i] != '.')
	{
		tcount++;
		dqb.body[cursor++] = domain[i];
	}
	else
	{
		dqb.body[cursor-tcount-1] = tcount;
		tcount = 0;
		cursor++;
	}
  }
  dqb.body[cursor-tcount-1] = tcount;
  tcount = 0;
  dqb.body[cursor++] = '\0';
  dqb.body[cursor++] = 0x00;
  dqb.body[cursor++] = 0x01;//qtype
  dqb.body[cursor++] = 0x00;
  dqb.body[cursor++] = 0x01;//qclass

  char buf[500];
  memset((void *)buf, 0x00, sizeof(buf));
  memcpy((void *)buf, (void *)&dqh, sizeof(dqh));
  memcpy((void *)buf+sizeof(dqh), (void *)&dqb.body, cursor);

  if(sendto(sock, buf, sizeof(dqh)+cursor, 0, (struct sockaddr *)&dnsaddr, sizeof(dnsaddr)) < 0)
  {
	printf("send error\n");
	return 1;
  }
  unsigned char recvbuf[2048] = {""};//may be not enough, just for test
  if(recvfrom(sock, recvbuf, sizeof(recvbuf), 0, 0, 0) < 0)
  {
	printf("recv error\n");
	return 1;
  }
  unsigned short answer = ntohs(((dns_query_header *)&recvbuf)->answer);
  unsigned char *panswerbody = &recvbuf[sizeof(dns_query_header)+cursor];
  int anscursor = 0;
  unsigned short datalength = 0;
  if(answer > 0)
  {
	for(; answer > 0; answer--)
	{
		//while(panswerbody[anscursor++] != 0);// skip name
		//type = panswerbody[anscursor++]
		anscursor += 2;						// skip name
		anscursor += 2;						// skip type;
		anscursor += 2;						// skip class;
		anscursor += 4;						// skip ttl
		datalength = ntohs(*(unsigned short *)&panswerbody[anscursor]);
		anscursor += 2;						// skip data length
		if(datalength == 4)
		{
			//only decode ipv4
			printf("%d.%d.%d.%d\n", panswerbody[anscursor], panswerbody[anscursor+1], panswerbody[anscursor+2], panswerbody[anscursor+3]);
		}
		anscursor += datalength;
	}
  }
  else
  {
	printf("not find the domain\n");
	return 0;
  }
  return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值