简体   繁体   English

如何同时使用2个套接字PF_INET和PF_PACKET?

[英]How to use 2 sockets PF_INET and PF_PACKET at the same time?

I have the following 2 functions 我有以下两个功能

int listen_socket(unsigned int ip, int port, char *inf)
{
    struct ifreq interface;
    int fd;
    struct sockaddr_in addr;
    int n = 1;

    DEBUG(LOG_INFO, "Opening listen socket on 0x%08x:%d %s\n", ip, port, inf);
    if ((fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
        DEBUG(LOG_ERR, "socket call failed: %s", strerror(errno));
        return -1;
    }

    fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);

    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = ip;

    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &n, sizeof(n)) == -1) {
        close(fd);
        return -1;
    }
    if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char *) &n, sizeof(n)) == -1) {
        close(fd);
        return -1;
    }

    strncpy(interface.ifr_ifrn.ifrn_name, inf, IFNAMSIZ);
    if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,(char *)&interface, sizeof(interface)) < 0) {
        close(fd);
        return -1;
    }

    if (bind(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) {
        close(fd);
        return -1;
    }

    return fd;
}


int raw_socket(int ifindex)
{
    int fd;
    struct sockaddr_ll sock;

    DEBUG(LOG_INFO, "Opening raw socket on ifindex %d\n", ifindex);
    if ((fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0) {
        DEBUG(LOG_ERR, "socket call failed: %s", strerror(errno));
        return -1;
    }

    fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);

    sock.sll_family = AF_PACKET;
    sock.sll_protocol = htons(ETH_P_IP);
    sock.sll_ifindex = ifindex;
    if (bind(fd, (struct sockaddr *) &sock, sizeof(sock)) < 0) {
        DEBUG(LOG_ERR, "bind call failed: %s", strerror(errno));
        close(fd);
        return -1;
    }

    return fd;
}

Both are socket listener functions. 两者都是套接字侦听器功能。

I used these functions in my application in this way 我以这种方式在我的应用程序中使用了这些功能

fd = listen_socket(INADDR_ANY, 67, client_config.interface);
fd2 = raw_socket(client_config.ifindex);

Now if I send packet to my application (with destination = ip of the interface and port=67). 现在,如果我将数据包发送到我的应用程序(目标地址为接口的ip,端口为67)。 What socket should catch my packet? 什么插座可以接住我的包? is it fd2 or fd or both? fd2还是fd或两者皆有?

And if I send a packet to my application (with destination = broacast:255.255.255.0 and port=67). 如果我向我的应用程序发送了一个数据包(目的地= broacast:255.255.255.0和port = 67)。 What socket should catch my packet? 什么插座可以接住我的包? is it fd2 or fd or both? fd2还是fd或两者皆有?

Both sockets will receive that packet. 两个套接字都将接收该数据包。 As each packet arrives from the network driver to the kernel, it is duplicated and sent to all PF_PACKET (layer 2) sockets. 当每个数据包从网络驱动程序到达内核时,它都会被复制并发送到所有PF_PACKET(第2层)套接字。 The packet is also sent to the layer 3 (IP/TCP) kernel code and from there, to the addressed socket. 数据包还发送到第3层(IP / TCP)内核代码,然后从那里发送到寻址的套接字。

If this didn't happen, running a separate program doing raw packet captures (eg wireshark) would prevent any other communications over the network. 如果没有发生,运行单独的程序进行原始数据包捕获(例如,wireshark)将阻止网络上的任何其他通信。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM