Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 解析以太网帧和数据类型_C_Sockets_Typedef_Raw Sockets - Fatal编程技术网

C 解析以太网帧和数据类型

C 解析以太网帧和数据类型,c,sockets,typedef,raw-sockets,C,Sockets,Typedef,Raw Sockets,我有一个看似简单的任务,就是打印有关通过特定以太网接口的帧的基本信息。我有一个定义为 if ((sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) return __LINE__; strcpy(ifr.ifr_name, argv[1]); if (ioctl(sd, SIOCGIFFLAGS, &ifr) == -1) return __LINE__; ifr.ifr_flags |= IFF_PROMISC; if

我有一个看似简单的任务,就是打印有关通过特定以太网接口的帧的基本信息。我有一个定义为

if ((sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) return __LINE__;
strcpy(ifr.ifr_name, argv[1]);
if (ioctl(sd, SIOCGIFFLAGS, &ifr) == -1) return __LINE__;
ifr.ifr_flags |= IFF_PROMISC;
if (ioctl(sd, SIOCSIFFLAGS, &ifr) == -1) return __LINE__;
if (ioctl(sd, SIOCGIFINDEX, &ifr) == -1) return __LINE__;
我像这样循环输入

while (active) {
        FD_SET(sd, &fds);
        FD_SET(STDIN_FILENO, &fds);
        if ((rv = select(sd + 1, &fds, NULL, NULL, &tv)) < 0)
            active = 0;
        if (FD_ISSET(sd, &fds)) input(sd, buf);
并输出如下信息:

void input(int sd, char *buf) {
    int i;
    char *p = buf;
    struct ethheader *eth = (struct ethheader*)buf;
    int len = read(sd, buf, BUF_SIZ);
    if (len < sizeof(struct ethheader)) {
        printf("smaller than an ethernet frame\n");
        return;
    } else {
        char dst[18];
        char src[18];
        for (i = 0; i < 6; i++) {
            sprintf(dst + i * 3, "%02x:", eth->dsta[i]);
            sprintf(src + i * 3, "%02x:", eth->srca[i]);
        }
        dst[17] = '\0';
        src[17] = '\0';
        printf("dst: %s src: %s ", dst, src);
        switch (eth->type) {
        case 0x0800:
            printf("IPv4\n");
            break;
        case 0x0842:
            printf("ARP\n");
            break;
        case 0x86DD:
            printf("IPv6\n");
            break;
        default:
            printf("unknown\n");
            break;
        }
    }
}
我的第二个问题仍然是:如何更好地用更可移植的类型定义这些
struct
s;或者我可以使用
无符号字符吗?

如果您包含
,您将拥有
结构以太单元头

struct ether_header
{
  u_int8_t  ether_dhost[ETH_ALEN];      /* destination eth addr */
  u_int8_t  ether_shost[ETH_ALEN];      /* source ether addr    */
  u_int16_t ether_type;                 /* packet type ID field */
} __attribute__ ((__packed__));
您可能需要使用以下库函数:

   #include <netinet/ether.h>

   char *ether_ntoa(const struct ether_addr *addr);
#包括
字符*以太地址(常量结构以太地址*地址);
你考虑过使用吗?这真的让这些事情变得容易


(比如让一个tachikoma为你做这项工作:)

使用正确的序列化技术,而不是容易出错和不可移植的铸造。@Olaf,你能详细说明一下吗?对不起,不。使用搜索引擎确实是一项技能,现在可以假定。我已经给了你一个关键词了。@Olaf好的,谢谢。我已经在仔细阅读一些信息了。一个
struct
声明没有告诉您任何关于数据二进制格式的信息。它在最好的情况下是特定于实现的,在最坏的情况下是未定义的行为,在可移植代码中没有位置。照此,不能使用C
struct
声明来解组二进制数据。您必须显式地操作每个输入字节以提取所需的数据:是的,您确实需要读取单个字节以重新组合不同长度的字,等等。
struct ether_header
{
  u_int8_t  ether_dhost[ETH_ALEN];      /* destination eth addr */
  u_int8_t  ether_shost[ETH_ALEN];      /* source ether addr    */
  u_int16_t ether_type;                 /* packet type ID field */
} __attribute__ ((__packed__));
   #include <netinet/ether.h>

   char *ether_ntoa(const struct ether_addr *addr);