linux raw socket 原始套接字

16 篇文章 1 订阅

TCP socket,UDP socket只能处理传输层数据,而
原始套接字raw socket绕过传输层直接获取网络链路层的数据包。我们平时用的tcpdump, libpcap都是基于raw socket实现的。
在这里插入图片描述
一般使用方法如下:

	// raw socket
    int rawsock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_IP));
    if (rawsock < 0)
    {
        perror("SOCK_RAW error");
        return rawsock;
    }

    // set the socket to non-blocking mode
    const int flags = fcntl(rawsock, F_GETFL, 0);
    if (flags < 0)
    {
        perror("fcntl F_GETFL error");
        return -1;
    }
    if (fcntl(rawsock, F_SETFL, flags | O_NONBLOCK) < 0)
    {
        perror("fcntl F_SETFL error");
        return -1;
    }

    // set recv buf len
    int       buflen = 0;
    socklen_t len = sizeof(int);
    if (getsockopt(rawsock, SOL_SOCKET, SO_RCVBUF, &buflen, &len) < 0)
    {
        perror("Error getsockopt SO_RCVBUF: %s", strerror(errno));
    }

    buflen = 10 * 1024 * 1024;
    if (setsockopt(rawsock, SOL_SOCKET, SO_RCVBUF, &buflen, sizeof(int)) < 0)
    {
        perror("Error setsockopt SO_RCVBUF: %s", strerror(errno));
    }

    if (getsockopt(rawsock, SOL_SOCKET, SO_RCVBUF, &buflen, &len) < 0)
    {
        perror("Error getsockopt SO_RCVBUF: %s", strerror(errno));
    }

    // get interface index
    struct ifreq ifr;
    bzero(&ifr, sizeof(struct ifreq));
    if (ifname.size() >= IFNAMSIZ)
    {
        perror("%s interface name is too long", ifname.c_str());
        return -1;
    }
    strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ);

    if (ioctl(rawsock, SIOCGIFINDEX, &ifr) < 0)
    {
        perror("ioctl SIOCGIFINDEX error");
        return -1;
    }

    // set promisc mode
    struct packet_mreq mreq;
    bzero(&mreq, sizeof(struct packet_mreq));
    mreq.mr_ifindex = ifr.ifr_ifindex;
    mreq.mr_type = PACKET_MR_PROMISC;
    if (setsockopt(rawsock, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
    {
        perror("setsockopt PACKET_ADD_MEMBERSHIP error");
        return -1;
    }

    // bind
    struct sockaddr_ll saddr;
    bzero(&saddr, sizeof(struct sockaddr_ll));
    saddr.sll_family = AF_PACKET;
    saddr.sll_protocol = htons(ETH_P_IP);
    saddr.sll_ifindex = ifr.ifr_ifindex;
    if (bind(rawsock, (struct sockaddr*)(&saddr), sizeof(saddr)) < 0)
    {
        perror("bind error");
        return -1;
    }

参考:
https://www.opensourceforu.com/2015/03/a-guide-to-using-raw-sockets/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值