我正在尝试从端口6343捕获UDP sflow数据。我正在尝试捕获提供源端口,目标端口,UDP标头长度和校验和的UDP标头信息。我能够看到端口捕获,但UDP和校验和字段分别为0和1,这意味着不计算UDP长度,也不计算校验和。我在这里遗漏了UDP报头长度和校验和计算的内容吗? 以下是我使用的代码:
#include<stdio.h> //For standard things
#include<stdlib.h> //malloc
#include<string.h> //memset
#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<sys/socket.h>
#include<arpa/inet.h>
#define PORT 6343
#define PCKT_LEN 65536
void handlepacket(unsigned char *, int);
int sockt;
int i,j;
struct sockaddr_in source,dest;
int main()
{
int saddr_size,data_size;
struct sockaddr_in daddr;
struct sockaddr_in saddr;
//struct in_addr in;
unsigned char *buffer = (unsigned char *)malloc(65536); // Its Big ! Malloc allocates a block of size bytes of memory,returning a pointer to the begining of the block
struct udphdr *udph = (struct udphdr*)(buffer + sizeof(struct iphdr));
printf("Starting...\n");
//Create a raw socket that shall sniff
sockt = socket(AF_INET ,SOCK_DGRAM ,0);
if(sockt < 0)
{
printf("Socket Error\n");
return 1;
}
memset((char *)&daddr,0,sizeof(daddr));
//prepare the sockaddr_in structure
daddr.sin_family = AF_INET;
daddr.sin_addr.s_addr = INADDR_ANY;
daddr.sin_port = htons(PORT);
//Bind
if(bind(sockt,(struct sockaddr *)&daddr, sizeof(daddr))<0)
{
printf("bind failed");
return 1;
}
printf("bind done");
while(1)
{
saddr_size = sizeof saddr;
printf("waiting for data...");
//Receive a packet
data_size = recvfrom(sockt , buffer ,65536 , 0 , (struct sockaddr*) &saddr , (socklen_t*)&saddr_size);
if(data_size <0)
{
printf("Packets not recieved \n");
return 1;
}
//Now process the packet
handlepacket(buffer , data_size);
printf("Packets arrived from %d \n",ntohs(daddr.sin_port));
printf("Source Port : %d , Destination Port : %d \n", ntohs(udph->source), ntohs(udph->dest));
}
close(sockt);
printf("Finished");
return 0;
}
void handlepacket(unsigned char *buffer, int data_size)
{
//IP header length
struct iphdr *iph = (struct iphdr *)buffer;
unsigned short iphdrlen = iph->ihl*4;
// UDP header length
struct udphdr *udph = (struct udphdr*)(buffer + iphdrlen);
memset(&source,0,sizeof(source));
source.sin_addr.s_addr = iph ->saddr;
memset(&dest,0,sizeof(dest));
dest.sin_addr.s_addr = iph->daddr;
printf("UDP Length : %d , UDP checksum : %d \n",ntohs(udph->len), ntohs(udph->check));
}
答案 0 :(得分:0)
当使用创建类型为AF_INET
/ SOCK_DGRAM
的套接字时,操作系统会处理IP和UDP标头,并在将它们传递给您之前将其删除。您在buffer
中看到的是紧跟在UDP标头之后的内容。
您通过第五个参数将源IP和端口传递回recvfrom
函数,并将有效负载长度作为返回值传回。如果UDP校验和存在问题,操作系统将丢弃该数据包,您的应用程序代码将永远不会看到它,因此在应用程序级别上通常不需要担心这一点。