解码接收(内部)数据包的困难

时间:2014-06-02 09:48:08

标签: c++ linux macos sockets

我正在构建一个ping函数,该函数根据目标和最大跳数尝试到达目标并报告响应的统计信息。

但是我似乎在解码接收到的数据包并提取ttl,icmp-type和icmp-code以及识别内部ip-packet方面遇到了一些困难。我还希望能够设置传输数据包的标识,读取内部udp数据包的源端口或其他方法来识别此功能的数据包。

TL; DR 我很勉强,需要帮助:

  • 从收到的数据包中提取ttl,icmp-type和icmp-code;
  • 从收到的内部数据包中提取标识;
  • 设置传输数据包的标识,读取内部udp数据包的源端口或其他方法来识别此功能的数据包。

来源:

#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:这是我的第一篇文章,请原谅任何错误:)

0 个答案:

没有答案