【问题标题】:UDP header length field is zero always while capturing sflow data from port 6343从端口 6343 捕获 sflow 数据时,UDP 标头长度字段始终为零
【发布时间】:2015-07-27 12:38:28
【问题描述】:

我正在尝试从端口 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));


}

【问题讨论】:

    标签: c sockets udp


    【解决方案1】:

    当使用创建AF_INET / SOCK_DGRAM 类型的套接字时,操作系统会处理 IP 和 UDP 标头并在将它们传递给您之前将它们剥离。您在buffer 中看到的是紧跟在 UDP 标头之后的内容。

    您通过第五个参数将源 IP 和端口传回给recvfrom 函数,并且将有效负载长度作为返回值传回。如果 UDP 校验和有问题,操作系统会丢弃数据包,而您的应用程序代码将永远看不到它,因此您通常无需在应用程序级别担心。

    【讨论】:

    • 感谢您的评论。正如您提到的 AF_INET,我应该使用什么来避免剥离 UDP 标头信息?我应该使用 RAW 套接字类型来获取 UDP 标头吗?在那种情况下,我是否可以从指定端口获取数据,因为 RAW 套接字类型?
    • 我还应该使用任何函数来分别计算标题长度和校验和吗?我
    • 如果要获取完整的 UDP(和 IP)标头,则需要使用可以捕获完整数据包的库,例如 libpcap。我自己用的不多,所以你需要阅读它的手册页。然而问题是你为什么需要这些信息?你到底打算用它做什么?
    • 我实际上是在尝试从正在发送 UDP 数据的端口 6343 捕获 sflow 数据。我必须捕获这些数据包(如 src 端口、目标端口、数据包长度等信息)并创建此详细信息的图形表示。
    • 对于 UDP,您可以从recvfrom 获取除校验和之外的所有内容。如果校验和无效,则应丢弃数据包,因此我认为尝试捕获它没有多大价值。
    猜你喜欢
    • 2017-05-14
    • 2020-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-21
    • 1970-01-01
    • 2013-02-09
    • 2013-04-17
    相关资源
    最近更新 更多