【问题标题】:socket file descriptor changes automatically套接字文件描述符自动更改
【发布时间】:2012-06-14 04:35:15
【问题描述】:

我尝试使用 RAW 套接字编程捕获所有接近我的 NIC 的 UDP 数据包。在这里,我遇到了一个奇怪的问题。当我的程序运行时,我的套接字描述符会自动更改。代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <netinet/tcp.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <arpa/inet.h>

int main () {

int sockfd = socket (PF_INET, SOCK_RAW, IPPROTO_UDP);
if (sockfd < 0) {
    perror ("socket failed");
    return -1;
}

char *buf = malloc (8192);
memset (buf, 0, 8192);
if (!buf) {
    perror ("calloc failed\n");
    return -1;
}

int ret_recv;
i:
while ((ret_recv = recv (sockfd, buf, 8192, 0)) > -1) {
    printf ("%d\n", ret_recv);
    struct iphdr *iph = (struct iphdr *) buf;
    //struct udphdr *udph = (struct udphdr *) (buf + sizeof (struct iphdr));
    struct tcphdr *tcph = (struct tcphdr *) (buf + sizeof (struct iphdr));
    char ip[4];
    printf ("source ip: %s\n", inet_ntop (AF_INET, &iph->saddr, ip, sizeof (struct sockaddr_in)));
    printf ("dest ip: %s\n", inet_ntop (AF_INET, &iph->daddr, ip, sizeof (struct sockaddr_in)));
    //printf ("port: %d\n", ntohs (udph->source));
    printf ("port: %d\n", ntohs (tcph->source));
}
perror ("recv failed");
//goto i;
return 0;
}

在我的输出中,不是无限循环的数据包信息打印,而是只打印一个信息包。所以我检查了gdb。我用display sockfd。 socket调用后,sockfd的值为7。然后在while循环中,执行dest ip的printf后,sockfd的值变为808988216。所以recv失败,出现“bad file descriptor”错误。我找不到实际出了什么问题。

提前致谢:-)

【问题讨论】:

  • 您是否使用 valgrind 运行您的程序?我的猜测是您正在破坏 while {} 内的堆栈。顺便说一句,将 char ip[4] 更改为 inet_ntop 为 ip[16] 或更好地更改为 ip[INET_ADDRSTRLEN]
  • 最好是内存损坏。检查你的指针算法。
  • 发布的代码是正确的。我怀疑这不是真正的代码(你可能忽略了一些想法“这不可能”)。
  • 你为什么要检查malloc()的结果你使用它?为什么在调用malloc() 而不是calloc() 时打印'calloc failed'?为什么在调用calloc() 时调用malloc()memset() 会同时完成这两个操作,并使您的调试打印输出正确?还有你为什么用struct tcphdr *来查看UDP数据包?
  • 我本可以猜到这一切。确实我做到了。提出这些问题的原因是为了改进您的代码,并让您思考它。

标签: c sockets networking file-descriptor


【解决方案1】:

这是一个缓冲区溢出:

char ip[4];
    printf ("source ip: %s\n", inet_ntop (AF_INET, &iph->saddr, ip, sizeof (struct sockaddr_in)));

缓冲区不够大,无法容纳 IP 地址的字符串形式。还有,第四个说法是在向inet_ntop()撒谎关于可用空间,应该是:

char ip[INET_ADDRSTRLEN];
printf ("source ip: %s\n", inet_ntop (AF_INET, &iph->saddr, ip, sizeof ip));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-02
    • 1970-01-01
    • 2014-04-25
    • 1970-01-01
    • 2011-03-31
    • 1970-01-01
    • 1970-01-01
    • 2011-02-09
    相关资源
    最近更新 更多