gpt4 book ai didi

c - 使用 C 编程将 sf​​low 数据从端口 6343 写入 Scientific Linux 中的 csv 文件

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:28:12 35 4
gpt4 key购买 nike

我正在尝试将来自端口 6343sflow 数据写入 csv 文件。代码编译但数据包未存储在文件中。以下代码是我使用的。我引用了 this code修改为仅捕获 UDP 数据包以及 IP header 和 UDP header 信息,并为特定端口创建 socket .

 #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<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/socket.h>
#include <sys/types.h>
#define PORT 6343

void ProcessPacket(unsigned char* , int);
void print_ip_header(unsigned char* , int);
void print_udp_packet(unsigned char * , int);
void PrintData (unsigned char* , int);

int sock;
FILE *logfile;
int udp=0,total=0,i,j;
struct sockaddr_in source,dest;

int main()
{
int saddr_size , data_size;
int yes=1;
struct sockaddr saddr;
struct in_addr in;
struct sockaddr_in myaddr;

unsigned char *buffer = (unsigned char *)malloc(65536); //Its Big!

logfile=fopen("log.csv","w");
if(logfile==NULL) printf("Unable to create file.");
printf("Starting...\n");

myaddr.sin_family=AF_INET;
myaddr.sin_addr.s_addr=INADDR_ANY;
myaddr.sin_port=htons(6343);

sock=socket(AF_INET,SOCK_DGRAM,0);
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1)
{
perror("setsockopt");
exit(1);
}
if(sock<0)
{
printf("failed to create socket");
return 1;
}

if(bind(sock,(struct sockaddr *)&myaddr,sizeof(myaddr))<0)
{
printf("binding failed");
return 1;
}

listen(sock,5);
while(1)
{
saddr_size = sizeof saddr;
//Receive a packet
data_size = recvfrom(sock , buffer , 65536 , 0 , &saddr , &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);
printf("Finished");
return 0;
}

void ProcessPacket(unsigned char* buffer, int size)
{
//Get the IP Header part of this packet
struct iphdr *iph = (struct iphdr*)buffer;
++total;
switch (iph->protocol) //Check the Protocol and do accordingly...
{

case 17: //UDP Protocol
++udp;
print_udp_packet(buffer , size);
break;
}

printf("UDP : %d Total : %d\r",udp,total);
}

void print_ip_header(unsigned char* Buffer, int Size)
{
unsigned short iphdrlen;

struct iphdr *iph = (struct iphdr *)Buffer;
iphdrlen =iph->ihl*4;

memset(&source, 0, sizeof(source));
source.sin_addr.s_addr = iph->saddr;

memset(&dest, 0, sizeof(dest));
dest.sin_addr.s_addr = iph->daddr;

fprintf(logfile,"\n");
fprintf(logfile,"IP Header\n");
fprintf(logfile," |-IP Version : %d\n",(unsigned int)iph->version);
fprintf(logfile," |-IP Header Length : %d DWORDS or %d Bytes\n",(unsigned int)iph->ihl,((unsigned int)(iph->ihl))*4);
fprintf(logfile," |-Type Of Service : %d\n",(unsigned int)iph->tos);
fprintf(logfile," |-IP Total Length : %d Bytes(Size of Packet)\n",ntohs(iph->tot_len));
fprintf(logfile," |-Identification : %d\n",ntohs(iph->id));
//fprintf(logfile," |-Reserved ZERO Field : %d\n",(unsigned int)iphdr->ip_reserved_zero);
//fprintf(logfile," |-Dont Fragment Field : %d\n",(unsigned int)iphdr->ip_dont_fragment);
//fprintf(logfile," |-More Fragment Field : %d\n",(unsigned int)iphdr->ip_more_fragment);
fprintf(logfile," |-TTL : %d\n",(unsigned int)iph->ttl);
fprintf(logfile," |-Protocol : %d\n",(unsigned int)iph->protocol);
fprintf(logfile," |-Checksum : %d\n",ntohs(iph->check));
fprintf(logfile," |-Source IP : %s\n",inet_ntoa(source.sin_addr));
fprintf(logfile," |-Destination IP : %s\n",inet_ntoa(dest.sin_addr));
}

void print_udp_packet(unsigned char *Buffer , int Size)
{

unsigned short iphdrlen;

struct iphdr *iph = (struct iphdr *)Buffer;
iphdrlen = iph->ihl*4;

struct udphdr *udph = (struct udphdr*)(Buffer + iphdrlen);

fprintf(logfile,"\n\n***********************UDP Packet*************************\n");

print_ip_header(Buffer,Size);

fprintf(logfile,"\nUDP Header\n");
fprintf(logfile," |-Source Port : %d\n" , ntohs(udph->source));
fprintf(logfile," |-Destination Port : %d\n" , ntohs(udph->dest));
fprintf(logfile," |-UDP Length : %d\n" , ntohs(udph->len));
fprintf(logfile," |-UDP Checksum : %d\n" , ntohs(udph->check));

fprintf(logfile,"\n");
fprintf(logfile,"IP Header\n");
PrintData(Buffer , iphdrlen);

fprintf(logfile,"UDP Header\n");
PrintData(Buffer+iphdrlen , sizeof udph);

fprintf(logfile,"Data Payload\n");
PrintData(Buffer + iphdrlen + sizeof udph ,( Size - sizeof udph - iph->ihl * 4 ));

fprintf(logfile,"\n###########################################################");
}

void PrintData (unsigned char* data , int Size)
{

for(i=0 ; i < Size ; i++)
{
if( i!=0 && i%16==0) //if one line of hex printing is complete...
{
fprintf(logfile," ");
for(j=i-16 ; j<i ; j++)
{
if(data[j]>=32 && data[j]<=128)
fprintf(logfile,"%c",(unsigned char)data[j]); //if its a number or alphabet

else fprintf(logfile,"."); //otherwise print a dot
}
fprintf(logfile,"\n");
}

if(i%16==0) fprintf(logfile," ");
fprintf(logfile," %02X",(unsigned int)data[i]);

if( i==Size-1) //print the last spaces
{
for(j=0;j<15-i%16;j++) fprintf(logfile," "); //extra spaces

fprintf(logfile," ");

for(j=i-i%16 ; j<=i ; j++)
{
if(data[j]>=32 && data[j]<=128) fprintf(logfile,"%c",(unsigned char)data[j]);
else fprintf(logfile,".");
}
fprintf(logfile,"\n");
}
}
}

你能告诉我代码中有什么问题吗?

最佳答案

原始数据包嗅探代码创建了一个原始套接字

sock_raw = socket(AF_INET , SOCK_RAW , IPPROTO_TCP);

原始套接字获取包括 IP header 在内的数据。但是你的程序创建了 UDP 套接字

sock=socket(AF_INET,SOCK_DGRAM,0);

UDP 套接字和 TCP 套接字提供没有 IP、UDP 和 TCP header 的数据。这意味着缓冲区仅包含数据。

编辑 - 解释细节:

是的,这是网络协议(protocol)栈设计的结果。每一层都有特定的任务。

简化的处理看起来像:

  • 在 IP 层接收并处理数据包。 IP 层移除 IP 报头并将数据包向上移动到 UDP 层。
  • UDP 层移除 UDP 报头并将数据复制到缓冲区。然后内核唤醒 recvfrom 调用。

当您使用 UDP 套接字时,您无法从 IP header 中获取信息,因为它已被删除。当您使用原始套接字时,您无法按端口过滤数据包,因为在 IP 和 UDP 层处理之前不知道端口。

你错过的功能乍一看似乎很合理,但你必须考虑什么时候该怎么做

  • 您的端口收到了一个非 IPv4 数据包。
  • 接收到属于您所需端口的数据包的 IPv4 片段。
  • UDP 数据包封装在 IPsec 或任何其他协议(protocol)中。
  • ...

所以你必须默认只有两个选项的事实。要么使用 UDP 套接字提供的便利,但您不会看到较低协议(protocol)的详细信息,要么使用原始套接字,然后做更多的工作并在您的应用程序中实现端口过滤。

关于c - 使用 C 编程将 sf​​low 数据从端口 6343 写入 Scientific Linux 中的 csv 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31265568/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com