Linux recvfrom()不工作
我正在尝试在linux(ubuntu)中使用原始套接字实现Linux recvfrom()不工作,linux,sockets,Linux,Sockets,我正在尝试在linux(ubuntu)中使用原始套接字实现tracert,比如ICMP(echo)。我想我几乎实现了功能。但当我执行它时,它就不起作用了 通过测试,我发现“程序在recvfrom()停止” 我正在使用wireshark,我可以看到它正在发送和接收数据包。但是recvfrom()不起作用。它只是在等待一个包 我从wireshark上传屏幕截图 下面是我的代码 /* Copyright (C) 2011-2015 P.D. Buchan (pdbuchan@yahoo.com)
tracert
,比如ICMP
(echo)。我想我几乎实现了功能。但当我执行它时,它就不起作用了
通过测试,我发现“程序在recvfrom()停止”
我正在使用wireshark
,我可以看到它正在发送和接收数据包。但是recvfrom()
不起作用。它只是在等待一个包
我从wireshark
上传屏幕截图
下面是我的代码
/* Copyright (C) 2011-2015 P.D. Buchan (pdbuchan@yahoo.com)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Send an IPv4 ICMP packet via raw socket.
// Stack fills out layer 2 (data link) information (MAC addresses) for us.
// Values set for echo request packet, includes some ICMP data.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> // close()
#include <string.h> // strcpy, memset(), and memcpy()
#include <netdb.h> // struct addrinfo
#include <sys/types.h> // needed for socket(), uint8_t, uint16_t, uint32_t
#include <sys/socket.h> // needed for socket()
#include <netinet/in.h> // IPPROTO_RAW, IPPROTO_IP, IPPROTO_ICMP, INET_ADDRSTRLEN
#include <netinet/ip.h> // struct ip and IP_MAXPACKET (which is 65535)
#include <netinet/ip_icmp.h> // struct icmp, ICMP_ECHO
#include <arpa/inet.h> // inet_pton() and inet_ntop()
#include <sys/ioctl.h> // macro ioctl is defined
//#include <bits/ioctls.h> // defines values for argument "request" of ioctl.
#include <net/if.h> // struct ifreq
#include <errno.h> // errno, perror()
// Define some constants.
#define IP4_HDRLEN 20 // IPv4 header length
#define ICMP_HDRLEN 8 // ICMP header length for echo request, excludes data
// Function prototypes
uint16_t checksum (uint16_t *, int);
char *allocate_strmem (int);
uint8_t *allocate_ustrmem (int);
int *allocate_intmem (int);
int
main (int argc, char **argv)
{
int status, sd, *ip_flags; // status? ip_flags?
const int on = 1; // ?
//char *interface, *target, *src_ip, *dst_ip; // ????
struct ip iphdr;
struct icmp icmphdr;
uint8_t data[1000];
uint8_t packet[1000];
struct addrinfo hints, *res; // hints? res?
struct sockaddr_in *ipv4, serverAddr, routerAddr, clientAddr; // ipv4?
struct ifreq ifr; // ifr?
void *tmp; // tmp?
memset (&ifr, 0, sizeof (ifr));
// IP header
iphdr.ip_hl = 5;
iphdr.ip_v = 4;
iphdr.ip_tos = 0;
iphdr.ip_len = htons (IP4_HDRLEN + ICMP_HDRLEN);
iphdr.ip_id = htons (0);
iphdr.ip_off = 0;
iphdr.ip_ttl = 1;
iphdr.ip_p = IPPROTO_ICMP;
iphdr.ip_src.s_addr=inet_addr("192.168.81.128");
iphdr.ip_dst.s_addr=inet_addr(argv[1]);
iphdr.ip_sum = 0;
iphdr.ip_sum = checksum ((uint16_t *) &iphdr, IP4_HDRLEN);
// ICMP header
icmphdr.icmp_type = ICMP_ECHO;
icmphdr.icmp_code = 0;
icmphdr.icmp_id = htons (1000);
icmphdr.icmp_seq = htons (0);
icmphdr.icmp_cksum = 0;
icmphdr.icmp_cksum = checksum ((uint16_t *) &icmphdr, ICMP_HDRLEN);
// set IP packet(IP Header, ICMP Header, ICMP Data)
memcpy (packet, &iphdr, IP4_HDRLEN);
memcpy ((packet + IP4_HDRLEN), &icmphdr, ICMP_HDRLEN);
// set Destination address
memset (&serverAddr, 0, sizeof (struct sockaddr_in)); // about destination(server). use for bind
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = iphdr.ip_dst.s_addr;
// Submit request for a raw socket descriptor.
if ((sd = socket (AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
perror ("socket() failed ");
exit (EXIT_FAILURE);
}
// Set flag so socket expects us to provide IPv4 header.
if (setsockopt (sd, IPPROTO_IP, IP_HDRINCL, &on, sizeof (on)) < 0) {
perror ("setsockopt() failed to set IP_HDRINCL ");
exit (EXIT_FAILURE);
}
// Bind socket to interface index.
// send and receive
printf("send with ttl 1\n");
if (sendto (sd, packet, IP4_HDRLEN + ICMP_HDRLEN, 0, (struct sockaddr *) &serverAddr, sizeof (struct sockaddr)) < 0) {
perror ("sendto() failed ");
exit (EXIT_FAILURE);
}
printf("after send\n");
int addrSize = sizeof(routerAddr);
char buff[1000];
printf("before receive\n");
recvfrom(sd, buff, 1000, 0, (struct sockaddr*)&routerAddr, &addrSize);
printf("after receive\n");
printf("close(sd)!\n");
close (sd);
// Free allocated memory.
return (EXIT_SUCCESS);
}
uint16_t checksum (uint16_t *hdr, int hdrlen)
{
uint32_t sum = 0;
int n;
for(n=0; n<hdrlen/2; n++)
sum += hdr[n];
sum = (sum&0xFFFF) + (sum>>16);
sum = ~sum;
return sum;
}
多谢各位
另外,我正在使用vmware来使用ubuntu。我用的是NAT 您确实需要将套接字绑定到一个地址。使用SO_BINDTODEVICE套接字选项。这看起来像是在“将套接字绑定到接口索引”下,您当前什么都没有…链接显示错误,您没有访问此服务器“”的权限。参考#24.ccc1bbcb.1431016227.15a29dd1感谢您的回答!我从其他人的密码开始。因此,一些评论可能与我的课程目标不符。我知道sendto()函数是自动绑定的。(我从昨天开始学习socket编程。)我不太了解这一点,但我在其他网站上看到过。我也不能保证这是真的。)我正在查找SO_BINDTODEVICE,但我不能清楚地理解它。人们通过“setsockopt(sock,SOL_SOCKET,SO_BINDTODEVICE,device,sizeof(device));”来使用它,但我无法理解什么是设备(看起来像设备的名称“eth1”,但我不知道它是什么意思)和SOL_SOCKET是什么。这实际上是您正在测试的代码,是您的代码吗?上传代码只需将其粘贴到编辑框中即可。如果你实际上找不到你的代码,当你得到一个答案时,你可能会在修复它时遇到问题。
send with ttl 1
after send
before receive