【问题标题】:Receiving same address for Source and Destination IP address while capturing UDP data in Linux using C program使用 C 程序在 Linux 中捕获 UDP 数据时接收相同的源 IP 地址和目标 IP 地址
【发布时间】:2015-10-19 08:06:00
【问题描述】:

我试图在从端口 6343 捕获 UDP 数据时显示源 IP 地址和目标 IP 地址。我观察到我为两个字段显示相同的 IP 地址。以下是我运行的代码,

#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
int sockt;
int i,j;

struct sockaddr_in source,dest; 

int main()
{
    int saddr_size,data_size;
    struct sockaddr_in saddr;
    struct sockaddr_in daddr;

    //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));
    struct iphdr *iph = (struct iphdr *)buffer;
    memset(&source,0,sizeof(source));
    source.sin_addr.s_addr = iph ->saddr;
    memset(&dest,0,sizeof(dest));
    dest.sin_addr.s_addr = iph->daddr;
    unsigned short iphdrlen = iph->ihl*4;


    printf("Starting...\n");
    //Create a socket
    sockt = socket(AF_INET ,SOCK_DGRAM ,0);
    if(sockt < 0)
        {
            printf("Socket Error\n");
            return 1;
        }
    memset((char *)&saddr,0,sizeof(saddr));

    //prepare the sockaddr_in structure
    daddr.sin_family = AF_INET;
    daddr.sin_addr.s_addr = htonl(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;
                }

            printf("Packets arrived from %d \n",ntohs(daddr.sin_port));
            printf("\t Source Port : %d , Destination Port : %d, UDP Length : %d, Source IP  : %s, Destination IP  : %s, Protocol : %d, total length : %d \n", ntohs(udph->source), ntohs(udph->dest), ntohs(data_size), inet_ntoa(saddr.sin_addr),inet_ntoa(daddr.sin_addr), (unsigned int)iph->protocol, ntohs(iph->tot_len)); 
            ProcessPacket(buffer,data_size);
        }
    close(sockt);
    printf("Finished");
    return 0;
}

我收到的输出是:

源端口:55600,目标端口:9162,UDP 长度:7173,源 IP:147.188.195.6,目标 IP:147.188.195.6,协议:188,总长度:5

我在显示 IP 地址或未指向正确的位置获取地址时出错了吗?

【问题讨论】:

  • 那个IP是服务器的IP还是客户端的IP?
  • IP 看起来像来自本地机器(客户端)。我正在从端口捕获数据包,因此我期望发送数据包的 IP 地址不同。因此,源 IP 将是来自端口的 IP,目标将是我正在收集的本地计算机。
  • 没有。我在 Linux 机器上使用 C 编程。很抱歉没有提供完整的信息。我现在已经编辑了问题。
  • 除非你使用另一个问题中的技术,否则它只会说目标IP是0.0.0.0,因为套接字绑定到INADDR_ANY。套接字的地址不会根据接收到的数据包而改变。

标签: c udp ip-address


【解决方案1】:

inet_ntoa() 是一个不可重入函数。每次调用它都会返回一个指向同一个缓冲区的指针,所以当你在一个语句中调用它两次时,其中一个调用会覆盖另一个调用产生的缓冲区内容。

分几个步骤来做:

printf("\t Source Port : %d , Destination Port : %d, UDP Length :%d, ",
       ntohs(udph->source), ntohs(udph->dest), ntohs(data_size));  
printf("Source IP  : %s, ", inet_ntoa(saddr.sin_addr));
printf("Destination IP  : %s, ", inet_ntoa(daddr.sin_addr));
printf("Protocol : %d, total length : %d \n", 
      (unsigned int)iph->protocol, ntohs(iph->tot_len));

【讨论】:

  • 感谢您的cmets。
【解决方案2】:

如果你必须保存源IP地址和目的IP地址,最好使用strcpy函数。例如,

strcpy(src_ipaddr, inet_ntoa(saddr.sin_addr)); strcpy(dst_ipaddr, inet_ntoa(daddr.sin_addr));

其中 src_ipaddr 和 dst_ipaddr 是 char*。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-02
    • 1970-01-01
    • 2018-12-16
    • 2019-06-03
    • 2017-05-13
    • 2014-08-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多