簡體   English   中英

recvfrom掛在某些地址C上

[英]recvfrom hangs on certain addresses C

我正在使用C中的套接字編程來創建跟蹤路由的實現,該實現只是使用遞增的TTL字段創建新請求。 下面顯示的代碼相對運行良好,但是,例如,當嘗試與Google聯系時,recvfrom函數會掛起某些地址,而掛起其他地址,從而使算法無法完成,並使程序無限運行。 這是我到目前為止的內容:

int traceroute(char *srcaddress) {
int exists = 0;
int sendsock, recvsock, portno, portno2, *ttl, i = 1;
portno = 33434;
portno2 = 33435;
struct sockaddr_in recvaddr, sendaddr, curraddr, target;
char *currAddr = myaddress;
char message[512];
char *probemessage = "hello";
target.sin_addr.s_addr = inet_addr(srcaddress);
target.sin_family = AF_INET;
target.sin_port = 33436;
ttl = &i;
recvaddr.sin_family = AF_INET;
recvaddr.sin_port = portno;
recvaddr.sin_addr.s_addr = INADDR_ANY;
sendaddr.sin_family = AF_INET;
sendaddr.sin_port = portno2;
sendaddr.sin_addr.s_addr = INADDR_ANY;
while (i <= 30) {

    sendsock = socket(AF_INET, SOCK_DGRAM, 0);
    recvsock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
    if (sendsock < 0) {
        exists = 1;

        fprintf(stderr, "could not create sending socket");
    }
    if (recvsock < 0) {
        fprintf(stderr, "could not create receiving socket");
    }
    setsockopt(sendsock, IPPROTO_IP, IP_TTL, ttl, sizeof(ttl));

    struct timeval tv;

    tv.tv_sec = 1;  /* 30 Secs Timeout */
    tv.tv_usec = 0;  // Not init'ing this can cause strange errors

    setsockopt(recvsock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval));


    int len = sizeof(curraddr);

    if (bind(recvsock, (struct sockaddr *) &recvaddr, sizeof(recvaddr))
            < 0) {
        fprintf(stderr, "could not bind");
    }
    if (sendto(sendsock, probemessage, strlen(probemessage), 0,
            (struct sockaddr*) &target, sizeof(target)) < 0) {
        puts("did not send[100] data");
    }
    if (recvfrom(recvsock, message, sizeof(message), 0,
            (struct sockaddr*) &curraddr, (socklen_t*) &len) < 0) {
        puts("no data receievd");
    }
    currAddr = strdup(inet_ntoa(curraddr.sin_addr));
    if (strcmp(currAddr, srcaddress) == 0) {
        break;
    }
    close(sendsock);
    close(recvsock);

    printf("hops: %d address %s \n", i, currAddr);

    i++;
}
if (*ttl == 30 && currAddr != srcaddress) {
    exists = 0;
} else {
    exists = 1;
}
return exists;

}

在google示例中,當當前地址為62.72.134.198時,它將掛起

更新

我現在實現了一個超時,但是該算法仍然無法通過這些地址,並且似乎無法檢測到中間節點。 我已經參考了現有的Linux跟蹤路由實現,即使跳數等於到達目標地址所需的跳數,它似乎也無法接收任何數據。

這是二進制文件的痕跡:

execve("./a.out", ["./a.out"], [/* 18 vars */]) = 0
brk(0)                                  = 0x9b1c000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7797000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=95669, ...}) = 0
mmap2(NULL, 95669, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb777f000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/i386-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\1\1\1\3\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\220\210\1\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1807496, ...}) = 0
mmap2(NULL, 1814236, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb75c4000
mmap2(0xb7778000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b3000) = 0xb7778000
mmap2(0xb777d000, 7900, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb777d000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb75c3000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb75c3940, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
mprotect(0xb7778000, 12288, PROT_READ)  = 0
mprotect(0x8049000, 4096, PROT_READ)    = 0
mprotect(0xb77be000, 4096, PROT_READ)   = 0
munmap(0xb777f000, 95669)               = 0
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 3
socket(PF_INET, SOCK_RAW, IPPROTO_ICMP) = 4
setsockopt(3, SOL_IP, IP_TTL, [1], 4)   = 0
setsockopt(4, SOL_SOCKET, SO_RCVTIMEO, "\1\0\0\0\0\0\0\0", 8) = 0
bind(4, {sa_family=AF_INET, sin_port=htons(39554), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
sendto(3, "hello", 5, 0, {sa_family=AF_INET, sin_port=htons(40066), sin_addr=inet_addr("192.168.1.244")}, 16) = 5
recvfrom(4, "E\300\0=+_\0\0@\1\311h\300\250\1\364\300\250\1\364\3\3\16Q\0\0\0\0E\0\0!"..., 512, 0, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("192.168.1.244")}, [16]) = 61
brk(0)                                  = 0x9b1c000
brk(0x9b3d000)                          = 0x9b3d000
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 3), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7796000
write(1, "TEST PASSED\n", 12)           = 12
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 5
socket(PF_INET, SOCK_RAW, IPPROTO_ICMP) = 6
setsockopt(5, SOL_IP, IP_TTL, [1], 4)   = 0
setsockopt(6, SOL_SOCKET, SO_RCVTIMEO, "\1\0\0\0\0\0\0\0", 8) = 0
bind(6, {sa_family=AF_INET, sin_port=htons(39554), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
sendto(5, "hello", 5, 0, {sa_family=AF_INET, sin_port=htons(40066), sin_addr=inet_addr("204.79.197.200")}, 16) = 5
recvfrom(6, "E\300\0=\234A\0\0@\1Yy\300\250\1\1\300\250\1\364\v\0I\323\0\0\0\0E\0\0!"..., 512, 0, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("192.168.1.1")}, [16]) = 61
close(5)                                = 0
close(6)                                = 0
write(1, "hops: 1 address 192.168.1.1 \n", 29) = 29
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 5
socket(PF_INET, SOCK_RAW, IPPROTO_ICMP) = 6
setsockopt(5, SOL_IP, IP_TTL, [2], 4)   = 0
setsockopt(6, SOL_SOCKET, SO_RCVTIMEO, "\1\0\0\0\0\0\0\0", 8) = 0
bind(6, {sa_family=AF_INET, sin_port=htons(39554), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
sendto(5, "hello", 5, 0, {sa_family=AF_INET, sin_port=htons(40066), sin_addr=inet_addr("204.79.197.200")}, 16) = 5
recvfrom(6, "E\0\0008\0\0\0\0\376\0013\264>H\210,\300\250\1\364\v\0\215\245\0\0\0\0E\0\0!"..., 512, 0, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("62.72.136.44")}, [16]) = 56
close(5)                                = 0
close(6)                                = 0
write(1, "hops: 2 address 62.72.136.44 \n", 30) = 30
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 5
socket(PF_INET, SOCK_RAW, IPPROTO_ICMP) = 6
setsockopt(5, SOL_IP, IP_TTL, [3], 4)   = 0
setsockopt(6, SOL_SOCKET, SO_RCVTIMEO, "\1\0\0\0\0\0\0\0", 8) = 0
bind(6, {sa_family=AF_INET, sin_port=htons(39554), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
sendto(5, "hello", 5, 0, {sa_family=AF_INET, sin_port=htons(40066), sin_addr=inet_addr("204.79.197.200")}, 16) = 5
recvfrom(6, "E\0\0`{\n\0\0\374\1\271@>H\211m\300\250\1\364\v\0B/?\363\307\260E\0\0!"..., 512, 0, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("62.72.137.109")}, [16]) = 96
close(5)                                = 0
close(6)                                = 0
write(1, "hops: 3 address 62.72.137.109 \n", 31) = 31
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 5
socket(PF_INET, SOCK_RAW, IPPROTO_ICMP) = 6
setsockopt(5, SOL_IP, IP_TTL, [4], 4)   = 0
setsockopt(6, SOL_SOCKET, SO_RCVTIMEO, "\1\0\0\0\0\0\0\0", 8) = 0
bind(6, {sa_family=AF_INET, sin_port=htons(39554), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
sendto(5, "hello", 5, 0, {sa_family=AF_INET, sin_port=htons(40066), sin_addr=inet_addr("204.79.197.200")}, 16) = 5
recvfrom(6, "E\0\0`{\v\0\0\374\1\271?>H\211m\300\250\1\364\v\0B/?\363\307\260E\0\0!"..., 512, 0, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("62.72.137.109")}, [16]) = 96
close(5)                                = 0
close(6)                                = 0
write(1, "hops: 4 address 62.72.137.109 \n", 31) = 31
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 5
socket(PF_INET, SOCK_RAW, IPPROTO_ICMP) = 6
setsockopt(5, SOL_IP, IP_TTL, [5], 4)   = 0
setsockopt(6, SOL_SOCKET, SO_RCVTIMEO, "\1\0\0\0\0\0\0\0", 8) = 0
bind(6, {sa_family=AF_INET, sin_port=htons(39554), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
sendto(5, "hello", 5, 0, {sa_family=AF_INET, sin_port=htons(40066), sin_addr=inet_addr("204.79.197.200")}, 16) = 5
recvfrom(6, "E\0\0`\2263\0\0\374\1\240\276>H\206\306\300\250\1\364\v\0I\302\0\21\0\0E\0\0!"..., 512, 0, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("62.72.134.198")}, [16]) = 96
close(5)                                = 0
close(6)                                = 0
write(1, "hops: 5 address 62.72.134.198 \n", 31) = 31
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 5
socket(PF_INET, SOCK_RAW, IPPROTO_ICMP) = 6
setsockopt(5, SOL_IP, IP_TTL, [6], 4)   = 0
setsockopt(6, SOL_SOCKET, SO_RCVTIMEO, "\1\0\0\0\0\0\0\0", 8) = 0
bind(6, {sa_family=AF_INET, sin_port=htons(39554), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
sendto(5, "hello", 5, 0, {sa_family=AF_INET, sin_port=htons(40066), sin_addr=inet_addr("204.79.197.200")}, 16) = 5
recvfrom(6, "E\0\0008\0\0\0\0\373\1YY\303B\340\214\300\250\1\364\v\0\215\245\0\0\0\0E\0\0!"..., 512, 0, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("195.66.224.140")}, [16]) = 56
close(5)                                = 0
close(6)                                = 0
write(1, "hops: 6 address 195.66.224.140 \n", 32) = 32
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 5
socket(PF_INET, SOCK_RAW, IPPROTO_ICMP) = 6
setsockopt(5, SOL_IP, IP_TTL, [7], 4)   = 0
setsockopt(6, SOL_SOCKET, SO_RCVTIMEO, "\1\0\0\0\0\0\0\0", 8) = 0
bind(6, {sa_family=AF_INET, sin_port=htons(39554), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
sendto(5, "hello", 5, 0, {sa_family=AF_INET, sin_port=htons(40066), sin_addr=inet_addr("204.79.197.200")}, 16) = 5
recvfrom(6, "E\0\0008\376j@\0\371\0016\271\203\375\6\7\300\250\1\364\v\0\215\245\0\0\0\0E\0\0!"..., 512, 0, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("131.253.6.7")}, [16]) = 56
close(5)                                = 0
close(6)                                = 0
write(1, "hops: 7 address 131.253.6.7 \n", 29) = 29
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 5
socket(PF_INET, SOCK_RAW, IPPROTO_ICMP) = 6
setsockopt(5, SOL_IP, IP_TTL, [8], 4)   = 0
setsockopt(6, SOL_SOCKET, SO_RCVTIMEO, "\1\0\0\0\0\0\0\0", 8) = 0
bind(6, {sa_family=AF_INET, sin_port=htons(39554), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
sendto(5, "hello", 5, 0, {sa_family=AF_INET, sin_port=htons(40066), sin_addr=inet_addr("204.79.197.200")}, 16) = 5
recvfrom(6, 0xbff3ab4c, 512, 0, 0xbff3ab2c, 0xbff3aae0) = -1 EAGAIN (Resource temporarily unavailable)
write(1, "no data receievd\n", 17)      = 17
close(5)                                = 0
close(6)                                = 0
write(1, "hops: 8 address 131.253.6.7 \n", 29) = 29

它反復進行,並從此處重復最后一個recv。

所討論的躍點很可能不會生成ICMP_TIMXCEED消息。

發生這種情況的原因有幾個:

  • 跳數限制的速率
  • 行政失能
  • 過濾路徑中的其他位置

您需要在原始套接字處理程序中實現“讀取超時”,以最方便地使用setsockopt(recvsock, SO_TIMEOUT, ...)來檢測該超時setsockopt(recvsock, SO_TIMEOUT, ...)

不能保證躍點發送不可達的ICMP消息,某些躍點根本不發送,有些躍點具有嚴格的速率限制以生成此類消息。

此外,目標可能會丟棄探測數據包而不進行答復,因此您不知道何時到達目標(即ttl>跳數)。

因此,如果一跳已超時,則必須使用select()(e)poll()實現超時以繼續發送探測。

除此之外,更好的方法是在套接字上設置IP_RECVERR ,使用recvmsg()進行讀取,並從套接字的錯誤隊列中獲取icmp錯誤。 這甚至應該在沒有root特權的情況下運行,因為您只需要UDP-,而無需原始套接字。 但是您仍然必須實現讀取超時。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM