我试图从UDP客户端 - 服务器通信中捕获数据包。我不允许使用libpcap或tcpdump。 我发现了一篇关于它的好文章here.
但是,我无法理解该计划。因为,给出的评论非常少。
有人可以指点我这样的信息来源吗? 或者更准确地说,我正在寻找一个关于在Linux中使用C进行数据包分析的来源。
提前致谢。
答案 0 :(得分:1)
这是类似于你想要的东西,你可以删除不必要的标题。我编辑了代码的来源(来自您的链接)以获得所需的功能。
基本上这个人使用RAW套接字。 RAW套接字可以接收包含所有标头的任何数据包。在普通的Socket中,您可以定义您期望的协议,从哪个端口和哪个IP Source。 Linux IP Stack处理标头,您只获得应用程序层数据。此外,您还可以获取源和目标IP地址(来自您的sockaddr_in类型结构)。
现在,在这种情况下,您可以获得所有标头,这意味着您可以接收界面上的所有数据包,并根据需要插入标题。如果需要,这些类型的套接字对于数据包嗅探和创建一些自定义协议非常有用。
在下面提供的代码中,我只根据您的要求嗅探UDP数据包
#include<netinet/in.h>
#include<errno.h>
#include<netdb.h>
#include<stdio.h> //For standard things
#include<stdlib.h> //malloc
#include<string.h> //strlen
#include<netinet/ip_icmp.h> //Provides declarations for icmp header
#include<netinet/udp.h> //Provides declarations for udp header
#include<netinet/tcp.h> //Provides declarations for tcp header
#include<netinet/ip.h> //Provides declarations for ip header
#include<netinet/if_ether.h> //For ETH_P_ALL
#include<net/ethernet.h> //For ether_header
#include<sys/socket.h>
#include<arpa/inet.h>
#include<sys/ioctl.h>
#include<sys/time.h>
#include<sys/types.h>
#include<unistd.h>
#include <net/if.h> // struct ifreq
//#include <fcntl.h>
#include <linux/if_packet.h>
void ProcessPacket(unsigned char* , int);
void print_ip_header(unsigned char* , int);
void print_udp_packet(unsigned char * , int );
struct sockaddr_in source_epc,dest_epc;
//uint32_t ipSrc;
//uint16_t portSrc;
int main()
{
//struct sockaddr_ll sll;
//struct ifreq ifr;
int saddr_size , data_size;
struct sockaddr saddr;
//int udp = 0, others = 0;
unsigned char *buffer = (unsigned char *) malloc(500); //Its Big!
int sock_raw = socket( AF_PACKET , SOCK_RAW , htons(ETH_P_ALL)) ;
if(sock_raw < 0)
{
//Print the error with proper message
perror("Socket Error");
return 1;
}
/////////////////setsockopt(sock_raw , SOL_SOCKET , SO_BINDTODEVICE , "eth1" , strlen("eth1")+ 1 );
//memset(&sll, 0, sizeof(sll));
//memset(&ifr, 0, sizeof(ifr));
//strncpy((char *)ifr.ifr_name, "eth1", IFNAMSIZ);
/*if((ioctl(sock_raw, SIOCGIFHWADDR, &ifr)) == -1)
{
printf("Error getting Interface hw address!\n");
exit(-1);
}*/
while(1)
{
saddr_size = sizeof saddr;
//Receive a packet
//setsockopt(sock_raw , SOL_SOCKET , SO_BINDTODEVICE , "eth0" , strlen("eth0")+ 1 );
data_size = recvfrom(sock_raw , buffer , 65536 , 0 , &saddr , (socklen_t*)&saddr_size);
if(data_size <0 )
{
printf("Recvfrom error , failed to get packets\n");
return 1;
}
//Now process the packet
ProcessPacket(buffer , data_size);
}
close(sock_raw);
printf("Finished");
return 0;
}
void ProcessPacket(unsigned char* buffer, int size)
{
//Get the IP Header part of this packet , excluding the ethernet header
struct iphdr *iph = (struct iphdr*)(buffer + sizeof(struct ethhdr));
//++total;
if ( iph->protocol == 17)
{
printf("UDP Packet received\n");
print_ip_header(buffer, size);
print_udp_packet(buffer , size);
}
else
{
printf("Packet received in not UDP\n");
return 1;
}
}
void print_ip_header(unsigned char* Buffer, int Size)
{
// print_ethernet_header(Buffer , Size);
unsigned short iphdrlen;
struct iphdr *iph = (struct iphdr *)(Buffer + sizeof(struct ethhdr) );
iphdrlen =iph->ihl*4;
memset(&source_epc, 0, sizeof(source_epc));
source_epc.sin_addr.s_addr = iph->saddr;
memset(&dest_epc, 0, sizeof(dest_epc));
dest_epc.sin_addr.s_addr = iph->daddr;
printf(" \n\n***********************IP HEADER*************************\n " );
printf(" |-IP Version : %d\n",(unsigned int)iph->version);
printf(" |-IP Header Length : %d DWORDS or %d Bytes\n",(unsigned int)iph->ihl,((unsigned int)(iph->ihl))*4);
printf(" |-Type Of Service : %d\n",(unsigned int)iph->tos);
printf(" |-IP Total Length : %d Bytes(Size of Packet)\n",ntohs(iph->tot_len));
printf(" |-Identification : %d\n",ntohs(iph->id));
//printf(" |-Reserved ZERO Field : %d\n",(unsigned int)iphdr->ip_reserved_zero);
//printf(" |-Dont Fragment Field : %d\n",(unsigned int)iphdr->ip_dont_fragment);
//printf(" |-More Fragment Field : %d\n",(unsigned int)iphdr->ip_more_fragment);
printf(" |-TTL : %d\n",(unsigned int)iph->ttl);
printf(" |-Protocol : %d\n",(unsigned int)iph->protocol);
printf(" |-Checksum : %d\n",ntohs(iph->check));
printf(" |-Source IP : %s\n",inet_ntoa(source_epc.sin_addr));
printf(" |-Destination IP : %s\n",inet_ntoa(dest_epc.sin_addr));
}
void print_udp_packet(unsigned char *Buffer , int Size)
{
unsigned short iphdrlen;
struct iphdr *iph = (struct iphdr *)(Buffer + sizeof(struct ethhdr));
iphdrlen = iph->ihl*4;
struct udphdr *udph = (struct udphdr*)(Buffer + iphdrlen + sizeof(struct ethhdr));
int header_size = sizeof(struct ethhdr) + iphdrlen + sizeof udph;
printf("\n\n***********************UDP Packet*************************\n");
//print_ip_header(Buffer,Size);
printf("\nUDP Header\n");
printf(" |-Source Port : %d\n" , ntohs(udph->source));
printf(" |-Destination Port : %d\n" , ntohs(udph->dest));
printf(" |-UDP Length : %d\n" , ntohs(udph->len));
printf(" |-UDP Checksum : %d\n" , ntohs(udph->check));
printf("\n");
//printf("IP Header\n");
//PrintData(Buffer , iphdrlen);
//printf("UDP Header\n");
//PrintData(Buffer+iphdrlen , sizeof udph);
//printf("Data Payload\n");
//Move the pointer ahead and reduce the size of string
//PrintData(Buffer + header_size , Size - header_size);
printf("\n###########################################################");
}