You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

编译程序时<linux/if_arp.h>出现重复声明错误求助

问题描述

编译用户空间程序时,<linux/if_arp.h>头文件引发重复声明错误,涉及IFF_UP、IFF_BROADCAST等枚举值,以及ifmap、ifreq、ifconf等结构体的重定义,导致无法编译。

编译错误信息

In file included from /usr/include/linux/netdevice.h:29,
                 from /usr/include/linux/if_arp.h:27,
                 from rcping.c:6:
/usr/include/net/if.h:44:5: error: redeclaration of enumerator 'IFF_UP'
   44 |     IFF_UP = 0x1,               /* Interface is up.  */
      |     ^~~~~~
/usr/include/linux/if.h:83:9: note: previous definition of 'IFF_UP' with type 'enum net_device_flags'
   83 |         IFF_UP                          = 1<<0,  /* sysfs */
      |         ^~~~~~
...(省略其余重复错误)
/usr/include/net/if.h:176:8: error: redefinition of 'struct ifconf'
  176 | struct ifconf
      |        ^~~~~~
/usr/include/linux/if.h:284:8: note: originally defined here
  284 | struct ifconf  {

待编译代码

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <linux/if_arp.h>
#include <net/if.h>
#include <asm/types.h>
#include <libcap.h>
#include <string.h>
#define RCP 49152
#define sizepkt 512
struct RCP_packet {
uint16_t srcport;
uint16_t extport;
char* payload;
};
int main(int argc, char* argv[]) {
int intextport = atoi(argv[1]);
    cap_t caps = cap_init();
        cap_value_t *capvl = 0;
            cap_set_flag(caps, CAP_NET_RAW, 1, capvl, CAP_SET);
int sockfd = socket(AF_PACKET, SOCK_RAW, RCP);
if (sockfd < 0) {
    printf("Socket not created\n");
    printf("%d\n", sockfd);
    return -1;
    } else {
        printf("Socket Created successfully\n");
    }
    struct sockaddr_in *dst_addr;
    char buffer[sizepkt];
        dst_addr->sin_family = AF_INET;
        dst_addr->sin_port = htons(intextport);
        inet_pton(AF_INET, "127.0.0.1", &dst_addr->sin_addr);
        struct sockaddr_ll *src_addr;
        src_addr->sll_family = AF_PACKET;
        src_addr->sll_protocol = htons(1560);
        src_addr->sll_ifindex = if_nametoindex("wlan0");
        struct sockaddr *addr = (struct sockaddr *)&dst_addr;
        struct sockaddr *interlcal = (struct sockaddr *)&src_addr;
     struct RCP_packet *packet;
     packet->srcport = htons(49152);
     packet->extport = htons(intextport);
     strcpy(packet->payload, "This packet was sent using RCPing under the Really Crappy Protocol");
        memcpy(buffer, &packet->srcport, sizeof(packet->srcport));
            memcpy(buffer + sizeof(packet->srcport), &packet->extport, sizeof(packet->extport));
                memcpy(buffer + sizeof(packet->srcport) + sizeof(packet->extport), packet->payload, 8);
                   struct RCP_packet *rcp;
        rcp->srcport = htons(1560);
        rcp->extport = htons(intextport);
        int miku = bind(sockfd, interlcal, sizeof(interlcal));
        if (miku < 0) {
            printf("Local interface couldn't be set up\n");
            printf("%d", miku);
            return -1;
        }

        int jumanji = connect(sockfd, addr, sizeof(addr));
    if (jumanji < 0) {
        printf("Couldn't establish a connection using RCP, unsurprisingly\n");
        printf("%d", jumanji);
        return -1;
    } else {
        while (main) {
            ssize_t senresult = send(sockfd, buffer, sizeof(buffer), 0);
            if (senresult < 0) {
                printf("Package wasn't sent");
            }
        }
    }
}
解决方案

1. 解决头文件冲突问题

错误根源是混合使用了内核头文件和用户空间标准头文件:

  • 手动包含的<net/if.h>是用户空间POSIX标准头文件,而<linux/if_arp.h>(内核头文件)会间接引入<linux/if.h>(内核版本的同名头文件),两者定义了完全重复的枚举和结构体,导致编译冲突。

修复方法:
将代码中的#include <linux/if_arp.h>替换为用户空间标准头文件#include <net/if_arp.h>,保留#include <net/if.h>即可。两个头文件属于同一标准体系,不会出现重复定义。

2. 修复代码中的其他致命问题

除头文件冲突外,代码还有多处会导致运行崩溃或逻辑错误的问题,需一并修复:

  • 未初始化指针问题:
    dst_addr、src_addr、packet、rcp均为未分配内存的野指针,直接访问其成员会触发段错误。改为声明结构体变量而非指针,或手动分配内存:

    // 示例:将指针改为栈变量
    struct sockaddr_in dst_addr;
    struct sockaddr_ll src_addr;
    struct RCP_packet packet;
    
  • CAP权限设置错误:
    cap_value_t *capvl = 0; 传入cap_set_flag会导致错误,需初始化包含目标权限的数组并将权限应用到进程:

    cap_value_t capvl[] = {CAP_NET_RAW};
    cap_set_flag(caps, CAP_EFFECTIVE, 1, capvl, CAP_SET);
    cap_set_flag(caps, CAP_PERMITTED, 1, capvl, CAP_SET);
    cap_set_proc(caps); // 将权限应用到当前进程
    
  • RCP_packet的payload未分配内存:
    payload是指针,直接strcpy会写入未知内存。改为固定大小数组:

    struct RCP_packet {
        uint16_t srcport;
        uint16_t extport;
        char payload[128]; // 改为固定大小数组
    };
    
  • while(main)逻辑错误:
    main是函数名,会被视为非零常量导致死循环,改为while(1)或添加终止条件。

  • AF_PACKET套接字不支持connect:
    AF_PACKET是链路层套接字,无法使用connect建立连接,应改用sendto并指定目标链路层地址。

  • sizeof(interlcal)和sizeof(addr)错误:
    这两个是指针,sizeof得到的是指针长度而非结构体长度,应改为sizeof(src_addr)和sizeof(dst_addr)。

修复后的示例代码片段(关键部分)

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if_arp.h>  // 替换为用户空间标准头文件
#include <net/if.h>
#include <asm/types.h>
#include <libcap.h>
#include <string.h>
#include <unistd.h>
#define RCP 49152
#define sizepkt 512

struct RCP_packet {
    uint16_t srcport;
    uint16_t extport;
    char payload[128]; // 改为固定大小数组
};

int main(int argc, char* argv[]) {
    if (argc < 2) {
        fprintf(stderr, "Usage: %s <port>\n", argv[0]);
        return 1;
    }
    int intextport = atoi(argv[1]);

    // 修复CAP权限设置
    cap_t caps = cap_init();
    cap_value_t capvl[] = {CAP_NET_RAW};
    cap_set_flag(caps, CAP_EFFECTIVE, 1, capvl, CAP_SET);
    cap_set_flag(caps, CAP_PERMITTED, 1, capvl, CAP_SET);
    if (cap_set_proc(caps) == -1) {
        perror("cap_set_proc failed");
        return 1;
    }
    cap_free(caps);

    int sockfd = socket(AF_PACKET, SOCK_RAW, htons(RCP)); // 协议号需用htons转换
    if (sockfd < 0) {
        perror("Socket not created");
        return -1;
    }
    printf("Socket Created successfully\n");

    // 改用栈变量,避免野指针
    struct sockaddr_ll src_addr = {0};
    src_addr.sll_family = AF_PACKET;
    src_addr.sll_protocol = htons(RCP);
    src_addr.sll_ifindex = if_nametoindex("wlan0");
    if (src_addr.sll_ifindex == 0) {
        perror("if_nametoindex failed");
        close(sockfd);
        return 1;
    }

    int miku = bind(sockfd, (struct sockaddr*)&src_addr, sizeof(src_addr));
    if (miku < 0) {
        perror("Local interface couldn't be set up");
        close(sockfd);
        return -1;
    }

    struct RCP_packet packet = {0};
    packet.srcport = htons(49152);
    packet.extport = htons(intextport);
    strncpy(packet.payload, "This packet was sent using RCPing under the Really Crappy Protocol", sizeof(packet.payload)-1);

    char buffer[sizepkt] = {0};
    size_t offset = 0;
    memcpy(buffer + offset, &packet.srcport, sizeof(packet.srcport));
    offset += sizeof(packet.srcport);
    memcpy(buffer + offset, &packet.extport, sizeof(packet.extport));
    offset += sizeof(packet.extport);
    memcpy(buffer + offset, packet.payload, strlen(packet.payload));
    offset += strlen(packet.payload);

    // AF_PACKET使用sendto发送,需设置目标链路层地址(示例用广播地址)
    struct sockaddr_ll dst_addr = {0};
    dst_addr.sll_family = AF_PACKET;
    dst_addr.sll_protocol = htons(RCP);
    dst_addr.sll_ifindex = src_addr.sll_ifindex;
    unsigned char broadcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
    memcpy(dst_addr.sll_addr, broadcast_mac, 6);
    dst_addr.sll_halen = 6;

    while (1) {
        ssize_t senresult = sendto(sockfd, buffer, offset, 0, (struct sockaddr*)&dst_addr, sizeof(dst_addr));
        if (senresult < 0) {
            perror("Package wasn't sent");
        } else {
            printf("Sent %zd bytes\n", senresult);
        }
        sleep(1); // 避免发送过快
    }

    close(sockfd);
    return 0;
}

内容的提问来源于stack exchange,提问作者The QNX girl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 18:00:53