我正在构建一个ping函数,该函数根据目标和最大跳数尝试到达目标并报告响应的统计信息。
但是我似乎在解码接收到的数据包并提取ttl,icmp-type和icmp-code以及识别内部ip-packet方面遇到了一些困难。我还希望能够设置传输数据包的标识,读取内部udp数据包的源端口或其他方法来识别此功能的数据包。
TL; DR 我很勉强,需要帮助:
来源:
#define SOCKET_ERROR -1
#include <cstdlib> //EXIT_SUCCES & EXIT_FAILURE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/ip.h> //iphdr
#include <netinet/ip_icmp.h> //icmphdr
#include <netinet/in.h> //sockaddr, sockaddr_in
#include <sys/socket.h>
#include <unistd.h>
//Additional network headers (taken from boost 1.53.0)
#include "../includes/icmp_header.hpp"
#include "../includes/ipv4_header.hpp"
int perform_ping(const char *destination, int max_hops) {
int msg_size = 32;
int transmission_socket;
if ((transmission_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == SOCKET_ERROR) {
printf("Failed to setup transmission socket.\n");
return EXIT_FAILURE;
}
int receiver_socket;
if ((receiver_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP)) == SOCKET_ERROR) { //Non-Priviledged
printf("Failed to setup receiver socket.\n");
return EXIT_FAILURE;
}
struct timeval timeout;
timeout.tv_sec = 3;
timeout.tv_usec = 0;
if (setsockopt(receiver_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) == SOCKET_ERROR) {
printf("Failed to setup receiver socket with timeout: %ld.%06d\n", timeout.tv_sec, timeout.tv_usec);
return EXIT_FAILURE;
}
struct sockaddr_in destination_address;
destination_address.sin_addr.s_addr = inet_addr(destination);
destination_address.sin_family = AF_INET;
destination_address.sin_port = htons(33434);
if (setsockopt(transmission_socket, IPPROTO_IP, IP_TTL, (char *)&max_hops, sizeof(max_hops)) == SOCKET_ERROR) {
printf("Failed to setup transmission socket with max_hops: %d\n", max_hops);
return EXIT_FAILURE;
}
char *transmission_buffer = NULL;
transmission_buffer = new char [sizeof (icmp) + msg_size];
int bytes_send = sendto(transmission_socket, transmission_buffer, sizeof(icmp) + msg_size, 0, (struct sockaddr *)&destination_address, sizeof(struct sockaddr_in));
if (bytes_send == SOCKET_ERROR) {
printf("An error has occured while sending: %s.", strerror(errno));
delete transmission_buffer;
return EXIT_FAILURE;
}
char *response_buffer;
if ((response_buffer = (char *)malloc(sizeof(struct ip) + sizeof(struct icmp))) == NULL) {
fprintf(stderr, "Could not allocate memory for packet\n");
return EXIT_FAILURE;
}
struct sockaddr remoteAddr;
socklen_t remoteAddrLen = sizeof(remoteAddr);
int bytes_received = recvfrom(receiver_socket, response_buffer, sizeof(ip) + sizeof(icmp), 0, &remoteAddr, &remoteAddrLen);
if (bytes_received != SOCKET_ERROR) {
printf("%s (%d)\n", inet_ntoa(((struct sockaddr_in *)&remoteAddr)->sin_addr), max_hops);
struct ip *ipheader = (struct ip *)response_buffer;
struct icmp *icmpheader = (struct icmp *)(response_buffer + sizeof(struct ip));
std::cout << "ip_ttl : " << std::dec << ipheader->ip_ttl << std::endl;
std::cout << "ip_ttl(hex): " << std::hex << ipheader->ip_ttl << std::endl;
std::cout << "ip_id : " << std::dec << ntohs(ipheader->ip_id) << std::endl;
std::cout << "ip_id(hex): " << std::hex << ntohs(ipheader->ip_id) << std::endl;
std::cout << "icmp_id : " << std::dec << ntohs(icmpheader->icmp_hun.ih_idseq.icd_id) << std::endl;
std::cout << "icmp_id(hex): " << std::hex << icmpheader->icmp_hun.ih_idseq.icd_id << std::endl;
std::cout << "icmp_type : " << std::dec << icmpheader->icmp_type << std::endl;
std::cout << "icmp_type(hex): " << std::hex << icmpheader->icmp_type << std::endl;
std::cout << "icmp_code : " << std::dec << icmpheader->icmp_code << std::endl;
std::cout << "icmp_code(hex): " << std::hex << icmpheader->icmp_code << std::endl;
} else {
printf("Socket error\n");
free(response_buffer);
return EXIT_FAILURE;
}
delete transmission_buffer;
free(response_buffer);
return EXIT_SUCCESS;
}
收到信息包
ip (
identification: 0xe0ab (57515),
time to live: 250
),
icmp (
type: 11
code: 0
ip:(
identification: 0x7ec7 (32455),
time to live: 1
),
udp:(
source port: 56086
)
)
预期输出
90.145.29.174 (5)
ip_ttl : 250
ip_id : 32455
ip_id(hex): 7ec7
icmp_type: 11
icmp_code: 0
实际输出
90.145.29.174 (5)
ip_ttl : ? (actual question mark)
ip_ttl(hex): ? (action question mark)
ip_id : 57515
ip_id(hex): e0ab
icmp_type :
(newline)
icmp_type(hex):
(newline)
icmp_code :
icmp_code(hex):
PS:这是我的第一篇文章,请原谅任何错误:)