DNS 协议运行在 UDP 协议上面,是一个 UDP 的“回显”程序,使用 53 号端口
#include /* See NOTES */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int sock;
struct sockaddr_in sa;
/*
generate_question:解析域名数据
*/
void generate_question(char*dns_name,char*buf,int*len)
{
char*pos = dns_name;//指向域名当前位置
char*ptr = buf;
int n = 0;
*len = 0;
while(1)
{
n = strlen(pos) - (strstr(pos , ".") ? strlen(strstr(pos , ".")) : 0);//在 pos 中查找"."子串
//返回"."在 pos 中第一次出现的地址,若没有找到返回 NULL
printf("%d\n", n);
*ptr++ = (unsigned char)n;
memcpy(ptr,pos,n);
printf("%lu\n",strlen(ptr));
printf("%s\n", ptr);
*len += n + 1;
ptr += n;
if(!strstr(pos , "."))
{
*ptr = (unsigned char)0;
ptr ++;
*len += 1;
break;
}
pos += n + 1;
printf("%s\n", pos);
}
}
/*
send_dns_request:解析域名数据,并发送数据包
*/
void send_dns_request(char * dns_name)
{
unsigned char request[256] = {0}; //保存整个请求报文
unsigned char *ptr = request;
unsigned char question[128];//存储域名解析数据
int question_len;
//产生请求(把字符串表示的域名转换成 DNS 要求的格式)
generate_question(dns_name , question ,&question_len);
printf("%s\n", question);
printf("%d\n", question_len);
*((unsigned short*)ptr) = 1; //会话标识 ID
ptr += 2;
*((unsigned short*)ptr) = htons(0x0100); //flags
ptr += 2;
*((unsigned short*)ptr) = htons(1); //Quetions 问题数,通常为 1
ptr += 2;
*((unsigned short*)ptr) = 0;
ptr += 2;
*((unsigned short*)ptr) = 0;
ptr += 2;
*((unsigned short*)ptr) = 0;
ptr += 2;
//把域名(www.baidu.com)装换为相应的问题格式保存在此处,以\0 结尾
memcpy(ptr , question , question_len);
ptr += question_len;
*((unsigned short*)ptr) = htons(1); //获取 IPV4 地址,查询类型
ptr += 2;
*((unsigned short*)ptr) = htons(1); //指互联网地址,查询类,一般为 1,表明是 Internet 数据
int re = sendto(sock, request,question_len+16 ,0, (structsockaddr*)&sa, sizeof(sa));
printf("re = %d\n",re);
int i;
for(i=0;i 0)//收到大于 0 的数据
{
int i;
for(i=r-4;i\n",argv[0]);
return -1;
}
//step 1: 创建一个套接字
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == -1)
{
perror("socket error:");
return -1;
}
//step 2: 绑定一个地址(ip+端口号)
memset(&sa, 0,sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons(53); //按"网络字节序"来保存一个整数
sa.sin_addr.s_addr = inet_addr("114.114.114.114");
//发送解析请求
send_dns_request(argv[1]);
//接收分析结果
recv_dns_response();
close(sock);
return 0;
}
#include
#include
extern int h_errno;
struct hostent *gethostbyname(const char *name);
struct hostent
{
char *h_name; /* 主机正式名称 */
char **h_aliases; /* 别名列表。 */
int h_addrtype; /* 主机地址类型。*/
int h_length; /* 地址的长度。 */
char **h_addr_list; /*来自名称服务器的地址列表。 */
#ifdef __USE_MISC
# define h_addr h_addr_list[0] /* 地址,用于向后兼容。*/
#endif
};
#include
#include
#include
#include
extern int h_errno;
int main(int argc, char **argv)
{
if (argc != 2) {
printf("Use example: %s www.google.com\n", *argv);
return -1;
}
char *name = argv[1];
struct hostent *hptr;
hptr = gethostbyname(name);
if (hptr == NULL) {
printf("gethostbyname error for host: %s: %s\n", name,
hstrerror(h_errno));
return -1;
}
//输出主机的规范名
printf("\tofficial: %s\n", hptr->h_name);
//输出主机的别名
char **pptr;
char str[INET_ADDRSTRLEN];
for (pptr=hptr->h_aliases; *pptr!=NULL; pptr++) {
printf("\ttalias: %s\n", *pptr);
}
//输出 ip 地址
switch (hptr->h_addrtype) {
case AF_INET:
pptr = hptr->h_addr_list;
for (; *pptr!=NULL; pptr++) {
printf("\taddress: %s\n",inet_ntop(hptr->h_addrtype, hptr->h_addr, str, sizeof(str)));
}
break;
default:
printf("unknown address type\n");
break;
}
return 0;
}
#include
int gethostname(char *name, size_t len);
char buf[256] = {0};
int t = gethostname(buf,256);
if(t == 0)
{
printf("%s\n",buf);
}
#include
int sethostname(const char *name, size_t len);
sethostname ( "jiuyue" , 6 );