`
helloyesyes
  • 浏览: 1323154 次
  • 性别: Icon_minigender_2
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

Linux下构造UDP原始数据报-DNS报文示例C语言实现

阅读更多

这几天构造一个DNS报文,查了好些资料,好象许多朋友对UDP报文的校验和老是出问题,自己试了一些例子代码,也有问题。所以花了一些时间,做了一个成功的例子,在Linux下GCC通过并验证成功。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/udp.h>


unsigned short checksum(unsigned short *buffer, int size)
{
unsigned long cksum=0;

while (size > 1)
{
cksum += *buffer++;
size -= sizeof(unsigned short);
}
if (size)
{
cksum += *(unsigned char *)buffer;
}
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >>16);

return (unsigned short)(~cksum);
}

void CalculateCheckSum(
void *iphdr,
struct udphdr *udphdr,
char *payload,
int payloadlen)
{
struct iphdr *v4hdr=NULL;
unsigned long zero=0;
char buf[1000],
*ptr=NULL;
int chksumlen=0,
i;

ptr = buf;

v4hdr = (struct iphdr *)iphdr;

// Include the source and destination IP addresses
memcpy(ptr, &v4hdr->saddr, sizeof(v4hdr->saddr));
ptr += sizeof(v4hdr->saddr);
chksumlen += sizeof(v4hdr->saddr);

memcpy(ptr, &v4hdr->daddr, sizeof(v4hdr->daddr));
ptr += sizeof(v4hdr->daddr);
chksumlen += sizeof(v4hdr->daddr);

// Include the 8 bit zero field
memcpy(ptr, &zero, 1);
ptr++;
chksumlen += 1;

// Protocol
memcpy(ptr, &v4hdr->protocol, sizeof(v4hdr->protocol));
ptr += sizeof(v4hdr->protocol);
chksumlen += sizeof(v4hdr->protocol);

// UDP length
memcpy(ptr, &udphdr->len, sizeof(udphdr->len));
ptr += sizeof(udphdr->len);
chksumlen += sizeof(udphdr->len);

// UDP source port
memcpy(ptr, &udphdr->source, sizeof(udphdr->source));
ptr += sizeof(udphdr->source);
chksumlen += sizeof(udphdr->source);

// UDP destination port
memcpy(ptr, &udphdr->dest, sizeof(udphdr->dest));
ptr += sizeof(udphdr->dest);
chksumlen += sizeof(udphdr->dest);

// UDP length again
memcpy(ptr, &udphdr->len, sizeof(udphdr->len));
ptr += sizeof(udphdr->len);
chksumlen += sizeof(udphdr->len);

// 16-bit UDP checksum, zero
memcpy(ptr, &zero, sizeof(unsigned short));
ptr += sizeof(unsigned short);
chksumlen += sizeof(unsigned short);

// payload
memcpy(ptr, payload, payloadlen);
ptr += payloadlen;
chksumlen += payloadlen;

// pad to next 16-bit boundary
for(i=0 ; i < payloadlen%2 ; i++, ptr++)
{
printf("pad one byte\n");
*ptr = 0;
ptr++;
chksumlen++;
}

// Compute the checksum and put it in the UDP header
udphdr->check = checksum((unsigned short *)buf, chksumlen);

return;
}


void main()
{

int sock;
unsigned int buffer_size = sizeof(struct iphdr) + sizeof(struct udphdr);

char DNS_Data[] = "\x71\x79\x81\x80\x00\x01"
"\x00\x02\x00\x04\x00\x04\x03\x77\x77\x77\x03\x61\x62\x63\x03\x63"
"\x6f\x6d\x00\x00\x01\x00\x01\xc0\x0c\x00\x05\x00\x01\x00\x00\x02"
"\xe8\x00\x02\xc0\x10\xc0\x10\x00\x01\x00\x01\x00\x00\x02\xe9\x00"
"\x04\x0a\xb5\x84\xfa\xc0\x10\x00\x02\x00\x01\x00\x00\xda\xeb\x00"
"\x0d\x06\x73\x65\x6e\x73\x30\x31\x03\x64\x69\x67\xc0\x14\xc0\x10"
"\x00\x02\x00\x01\x00\x00\xda\xeb\x00\x09\x06\x73\x65\x6e\x73\x30"
"\x32\xc0\x4e\xc0\x10\x00\x02\x00\x01\x00\x00\xda\xeb\x00\x09\x06"
"\x6f\x72\x6e\x73\x30\x31\xc0\x4e\xc0\x10\x00\x02\x00\x01\x00\x00"
"\xda\xeb\x00\x09\x06\x6f\x72\x6e\x73\x30\x32\xc0\x4e\xc0\x75\x00"
"\x01\x00\x01\x00\x00\x7a\x36\x00\x04\x0a\xbb\xbd\x2c\xc0\x8a\x00"
"\x01\x00\x01\x00\x00\x1b\x96\x00\x04\x0a\xbb\xbe\x2c\xc0\x47\x00"
"\x01\x00\x01\x00\x00\x92\xb1\x00\x04\x0a\xb5\x86\x10\xc0\x60\x00"
"\x01\x00\x01\x00\x00\x92\xb1\x00\x04\x0a\xb5\x87\xc7";

buffer_size += sizeof(DNS_Data);

unsigned char buffer[buffer_size];
memset (buffer, 0, buffer_size);

struct iphdr *ip = (struct iphdr *)buffer;
struct udphdr *udp = (struct udphdr *)(buffer + sizeof(struct iphdr));

if ((sock = socket(AF_INET,SOCK_RAW,IPPROTO_UDP)) == -1) {

perror("socket()");
exit(EXIT_FAILURE);
}

int o = 1;
if (setsockopt(sock,IPPROTO_IP,IP_HDRINCL,&o,sizeof(o)) == -1) {

perror("setsockopt()");
exit(EXIT_FAILURE);
}

ip->version = 4;
ip->ihl = 5;
ip->id = htonl(random());
ip->saddr = inet_addr("1.0.0.1");
ip->daddr = inet_addr("10.0.0.63");
ip->ttl = 255;
ip->protocol = IPPROTO_UDP;
ip->tot_len = buffer_size;
ip->check = 0;

udp->source = htons(53);
udp->dest = htons(1234);
udp->len = htons(buffer_size - sizeof(struct iphdr));
udp->check = 0;


struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = udp->source;
addr.sin_addr.s_addr = ip->saddr;

memcpy(buffer+sizeof(struct iphdr) + sizeof(struct udphdr),DNS_Data,sizeof(DNS_Data));
CalculateCheckSum(ip,udp,DNS_Data,sizeof(DNS_Data));

if ((sendto(sock, buffer, buffer_size, 0, (struct sockaddr*)&addr,
sizeof(struct sockaddr_in))) == -1) {

perror("send()");
exit(1);
}
else
printf("OK\n");
}

上面代码构造了一个DNS应答报文。用抓包程序抓下来验证正确。

分享到:
评论

相关推荐

    Internet协议分析-TFTP报文分析-DNS 报文分析

    通过分析,可以发现TFTP报文的结构和传输过程,以及如何通过TFTP报文实现文件的上传和下载。 实验报告还包含了对DNS递归查询和迭代查询的讨论。在递归查询中,DNS服务器会在客户端请求时直接给出结果,或者如果它...

    C语言实现基于wpcap的IP,TCP,UDP,ICMP报文发送

    本主题聚焦于利用C语言结合wpcap库实现IP、TCP、UDP和ICMP报文的发送,并涉及这些协议的校验和计算。下面我们将深入探讨这些知识点。 首先,wpcap是一个开源的网络数据包捕获库,它是libpcap的Windows版本。它提供...

    dns-c.rar_C语言实现 DNS

    分析此代码可以深入了解DNS协议的C语言实现细节,例如如何构造DNS报文,如何处理网络通信等。而"zxs.txt"可能是注释、日志文件或其他辅助文档,可以帮助理解代码的编写思路。 总结,通过C语言实现DNS协议涉及对DNS...

    dns请求响应,最原始的组包拆包DNS包

    在"**DnsParse1**"这个文件中,很可能包含了实现以上步骤的C++代码示例,可能包括了定义DNS报文结构、组装和拆包的函数,以及与Winsock交互的网络操作。通过分析这个文件,可以学习到如何在实际项目中实现DNS查询。 ...

    dns.rar_C语言DNS_DNS C语言_dns c语言实现_dns解析_springfog

    C语言DNS解析器通常包含以下几个关键部分: 1. **解析DNS报文**:DNS通信基于UDP协议,数据封装在DNS报文中。C程序需要能解析这些报文,包括报文头(标识符、标志、问题数量、回答数量、授权记录数量、附加记录数量...

    C语言开发----c语言实现如果cmd中的ping.rar

    在本主题中,我们将深入探讨如何使用C语言来实现类似于Windows命令行工具`ping`的功能。`ping`是一个网络诊断工具,它通过发送Internet控制消息协议(ICMP)回显请求来检查网络连接的可用性。以下是C语言实现这一...

    C语言开发----c语言UDP传输系统源码.rar

    本项目“C语言开发----c语言UDP传输系统源码”将深入探讨如何利用C语言实现用户数据报协议(UDP)的传输系统。UDP是互联网协议族中的一个无连接、不可靠的传输协议,常用于需要快速传输但不要求顺序到达或数据完整性...

    udp.rar_linux c语言 udp_udp 多线程_udp c语言 linux_udp linux

    2. Linux下的网络编程:在Linux中,C语言通常用于编写系统级程序,包括网络编程。主要通过套接字API(socket API)来实现,其中包括socket()函数创建套接字,bind()函数绑定本地端口,connect()或sendto()函数发送...

    dns.rar_DNS C语言_dns c语言实现

    本文将深入探讨使用C语言在ARM架构的硬件平台上实现DNS解析功能的相关知识点。 首先,我们要理解DNS的基本工作流程。当用户在浏览器中输入一个域名时,DNS客户端会发起一个查询请求,这个请求包含待解析的域名。DNS...

    c语言实现UDP广播

    基于win下的c语言UDP实现广播技术

    原始套接字发送完整UDP数据包(c语言实现)

    使用C语言实现原始套接字从数据链路层到应用层的操作,Linux系统

    UDP-circle-server-program.rar_UDP C语言_circle server_udp server

    总结起来,这个"UDP-circle-server-program"是一个基于C语言的UDP服务器实现,它在Linux环境下运行,利用UDP协议的特性实现了数据的循环发送。理解和掌握这个程序,有助于深入理解网络编程,特别是UDP服务端的设计与...

    LWIP-udp-DHCP-DNS

    【LWIP-UDP-DHCP-DNS】是网络通信中的关键组件,它们在嵌入式系统和物联网(IoT)设备中尤为重要。LWIP(Lightweight TCP/IP stack)是一个开源、轻量级的TCP/IP协议栈,适用于资源有限的微控制器。UDP(User Datagram...

    net-snmp-trap发送(c语言)

    在C语言中,实现SNMP trap通常涉及以下步骤: 1. **初始化环境**:首先,需要设置SNMP库的环境,包括初始化配置,指定社区字符串(如"public"或"private"),以及管理站的IP地址。 2. **创建PDU**:PDU(Protocol ...

    UDP.rar_C语言udp组播_linux UDP_udp linux _udp组播c语言

    本文将深入探讨标题“UDP.rar_C语言udp组播_linux UDP_udp linux _udp组播c语言”所涉及的知识点,主要集中在C语言实现UDP组播在Linux环境下的操作。 首先,让我们理解UDP(User Datagram Protocol)是什么。UDP是...

    使用Wireshark分析-以太网帧与ARP协议-IP协议-ICMP-UDP协议-TCP协议-协议HTTP-DNS协议_wireshark以太网帧分析-CSDN博客.html

    使用Wireshark分析-以太网帧与ARP协议-IP协议-ICMP-UDP协议-TCP协议-协议HTTP-DNS协议_wireshark以太网帧分析-CSDN博客.html

    UDP-本地通信(C语言)server client代码

    在这个“UDP-本地通信(C语言)server client代码”中,我们将深入探讨如何使用C语言实现UDP的本地通信。 在C语言中,我们通常使用socket编程接口来实现网络通信。对于UDP通信,我们需要创建一个UDP类型的socket,...

    udp 多播 c语言实现

    这个简单的示例展示了如何在C语言中实现UDP多播的基本功能。在实际应用中,你可能还需要处理错误,添加多线程或异步I/O来提高性能,以及使用更复杂的多播选项,比如设定多播TTL(Time To Live)来控制多播数据的传播...

    头歌UDP Ping程序实现-客户端创建UDP套接字

    头歌UDP Ping程序实现-客户端创建UDP套接字头歌UDP Ping程序实现-客户端创建UDP套接字头歌UDP Ping程序实现-客户端创建UDP套接字头歌UDP Ping程序实现-客户端创建UDP套接字头歌UDP Ping程序实现-客户端创建UDP套接...

    DNS报文格式说明及服务器端示例程序

    在压缩包中可能包含一个DNS服务器端的示例程序,这可能是一个简单的实现,演示如何接收DNS请求,解析报文,查找相应的记录,并返回响应。通常,这样的程序会涉及网络编程,使用UDP协议与客户端交互,因为DNS主要基于...

Global site tag (gtag.js) - Google Analytics