Использование epoll () с Raw Socket в C - PullRequest
1 голос
/ 30 апреля 2020

Меня мучает вопрос, как использовать epoll () с Raw Socket на языке C?

Я нашел несколько примеров, но все они для SOCK_DGRAM и SOCK_STREAM, а не SOCK_RAW.

Я попытался изменить этот пример, однако пакет не был получен и застрял в epoll_wait ().

Кто-нибудь знает, как решить эту проблему?

После C код - мой пробный код:

#include        <stdio.h>
#include        <stdlib.h>
#include        <string.h>
#include        <stddef.h>
#include        <sys/socket.h>
#include        <sys/types.h> 
#include        <netinet/in.h>
#include        <sys/epoll.h>
#include        <fcntl.h>
#include        <sys/ioctl.h>
#include        <net/if.h>
#include        <netpacket/packet.h>
#include        <linux/if_ether.h>
#include        <unistd.h>

struct ifreq            ethreq;
static struct sockaddr_ll   sll;
#define MAX_EVENTS 100
struct epoll_event ev;
int epollfd;
int fd;

int setnonblocking(int sockfd) {
    if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0) | O_NONBLOCK) == -1) {
        return -1;
    }

    return 0;
}

int SOCK_INIT(char *ifname) 
{
    if ((fd=socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) {
        perror("br raw socket");
        return -1;
    }

    /* Set the network card in promiscuous mode */
    strncpy(ethreq.ifr_name,ifname,IFNAMSIZ-1);
    if (ioctl(fd, SIOCGIFFLAGS, &ethreq)==-1) {
        perror("ioctl (SIOCGIFCONF) 1\n");
        close(fd);
        return -1;
    }

    ethreq.ifr_flags |= IFF_PROMISC;
    if (ioctl(fd, SIOCSIFFLAGS, &ethreq)==-1) {
        perror("ioctl (SIOCGIFCONF) 2\n");
        close(fd);
        return -1;
    }

    memset(&sll, 0, sizeof(sll));
    sll.sll_family = PF_PACKET;
    sll.sll_protocol = htons(ETH_P_ALL);
    sll.sll_halen = 6;

    ioctl(fd, SIOCGIFINDEX, &ethreq); //ifr_name must be set to "eth?" ahead
    sll.sll_ifindex = ethreq.ifr_ifindex;

    printf("ifindex=%d if name = %s\n",sll.sll_ifindex, ethreq.ifr_name);
    setnonblocking(fd);

    epollfd = epoll_create(100);
    ev.events = EPOLLIN | EPOLLET;
    ev.data.fd = fd;
    if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) < 0) {
        fprintf(stderr, "epoll set insertion error: fd=%d/n", fd);
        return -1;
    }
    else {
        printf("listen socket added in  epoll success /n");
    }

    return 0;
}

void sockd()
{
    int                 n,rxlen;
    struct epoll_event  events[MAX_EVENTS];
    int                 nfds;
    char                buf[1500];

    for (;;) {      
        nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
        if (nfds == -1) {
            perror("epoll_wait");
            exit(EXIT_FAILURE);
        }
        for (n = 0; n < nfds; ++n) {
             if(n == fd){
                  recvfrom(fd, buf, 1500, 0, NULL, NULL);
                  printf("%s\n", buf);
             }
        }
    }
}

int main(int argc, char **argv)
{

    SOCK_INIT("eth0");
    sockd();
}

Спасибо за ответ.

...