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

自定义协议创建的C语言Socket绑定失败问题求助

AF_PACKET原始Socket调用bind失败问题排查

我用自定义协议RCP创建了AF_PACKET类型的Raw Socket,其他参数配置(比如sockaddr_ll的协议、硬件类型、接口索引等)都正常,但调用bind时出错。编译命令为gcc rcping.c -o rcping -lcap,相关代码如下:

#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 <linux/if_ether.h>
#include <libcap.h>
#include <string.h>
#define RCP             49152
#define ARPHRD_ETHER    1
#define PACKET_RX       2
#define sizepkt         512
typedef unsigned short ushort_t;
struct sockaddr_ll {
    ushort_t sll_family;      /* address family (AF_LINK) */
    ushort_t sll_protocol;    /* link-layer protocol (e.g., Ethernet) */
    int32_t sll_ifindex;      /* interface index */
    uint16_t sll_hatype;     /* ARP hardware type */
    uint8_t  sll_pkttype;    /* packet type */
    uint8_t  sll_halen;      /* hardware address length */
    uint8_t  sll_addr[8];   /* hardware address (e.g., MAC address) */
};

uint16_t srcport;
uint16_t extport;
uint16_t srcport1;
uint16_t extport2;
char payload[256];

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");
    }
    printf("test1\n");
    struct sockaddr_in *dst_addr = malloc((size_t)sizeof(struct sockaddr_in));
    printf("1\n");
    char buffer[sizepkt];
        printf("hi\n");
        dst_addr->sin_family = AF_INET;
        printf("test2\n");
        dst_addr->sin_port = htons(intextport);
        printf("test3\n");
        inet_pton(AF_INET, "127.0.0.1", &dst_addr->sin_addr);
        printf("test4\n");
        struct sockaddr_ll *src_addr = malloc((size_t)sizeof(struct sockaddr_ll));
        int error1 = src_addr->sll_family = AF_PACKET;
                if (error1 < 0) {
            printf("socket family couldn't be set\n");
            printf("%d\n", error1);
            return -1;
        }
        int error2 = src_addr->sll_protocol = RCP;
                if (error2 < 0) {
            printf("The Internet protocol(IP) couldn't be set up\n");
            printf("%d\n", error2);
            return -1;
        }
        printf("test5\n");
        int error3 = src_addr->sll_ifindex = if_nametoindex("wlan0");
                if (error3 < 0) {
            printf("local interface couldn't be set up\n");
            printf("%d\n", error3);
            return -1;
        }
        int error4 = src_addr->sll_pkttype = PACKET_RX;
                if (error4 < 0) {
            printf("package type couldn't be set\n");
            printf("%d\n", error4);
            return -1;
        }
        int error5 = src_addr->sll_halen = 6;
                        if (error5 < 0) {
            printf("package type couldn't be set\n");
            printf("%d\n", error5);
            return -1;
        }
        int error6 = src_addr->sll_hatype = ARPHRD_ETHER;
                        if (error6 < 0) {
            printf("package type couldn't be set\n");
            printf("%d\n", error6);
            return -1;
        }
        printf("test6\n");
        struct sockaddr *addr = (struct sockaddr *)&dst_addr;
        printf("1\n");
        struct sockaddr *interlcal = (struct sockaddr *)&src_addr;
     strcpy(payload, "This packet was sent using RCPing under the Really Crappy Protocol");
     extport = htons(intextport);
     srcport = htons(RCP);
     char chrsrcport[16];
     char chrextport[16];
     sprintf(chrsrcport, "%d", srcport);
     sprintf(chrextport, "%d", extport);
        memcpy(buffer, chrsrcport, sizeof(chrsrcport));
        printf("7\n");
            memcpy(buffer + sizeof(chrsrcport), chrextport, sizeof(chrextport));
            printf("8\n");
                memcpy(buffer + sizeof(chrsrcport) + sizeof(chrextport), payload, 8);
                printf("9\n");
        srcport1 = htons(RCP);
        extport2 = htons(intextport);
        int miku = bind(sockfd, interlcal, sizeof(interlcal));
        printf("10\n");
        if (miku < 0) {
            printf("client interface couldn't be set up\n");
            printf("%d\n", 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. bind参数错误
    你错误地将指针的地址(&src_addr)强转为sockaddr*,并且传入的长度是指针的大小(sizeof(interlcal)),而非sockaddr_ll结构体的实际大小。修正后代码:

    struct sockaddr *interlcal = (struct sockaddr *)src_addr;
    int miku = bind(sockfd, interlcal, sizeof(struct sockaddr_ll));
    
  2. sockaddr_ll地址族错误
    AF_PACKET类型Socket对应的地址族必须是AF_LINK,不是AF_PACKET,修改:

    src_addr->sll_family = AF_LINK;
    
  3. 权限未生效
    初始化cap后未将权限应用到进程,且原代码中capvl设为0会导致权限设置失败,修正后:

    cap_t caps = cap_init();
    cap_value_t capvl = CAP_NET_RAW;
    cap_set_flag(caps, CAP_EFFECTIVE, 1, &capvl, CAP_SET);
    cap_set_proc(caps);
    cap_free(caps);
    
  4. AF_PACKET不支持connect
    AF_PACKET是链路层原始Socket,不存在TCP/UDP的连接概念,需删除connect调用,发送数据时需自行构造以太网帧头部。

  5. 移除重复结构体定义
    系统头文件<linux/if_packet.h>已经定义了sockaddr_ll,自行定义可能导致内存布局不一致,删除自定义的struct sockaddr_ll,添加头文件包含:

    #include <linux/if_packet.h>
    
  6. 循环与send长度错误
    while(main)是无效循环,改为while(1);send时应传入实际要发送的字节数,而非整个buffer大小:

    size_t send_len = sizeof(chrsrcport) + sizeof(chrextport) + 8;
    ssize_t senresult = send(sockfd, buffer, send_len, 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:35:01