2017-02-16 214 views
0

我使用netlink从内核接收中断号码。用户空间中的应用程序使用libevent来处理TCP/IP请求和netlink消息。 libevent支持Linux netlink socket?我会欣赏一个简单的例子。是否libevent支持netlink socket

回答

1

是的,libevent支持netlink套接字。

还有https://github.com/libevent/libevent/blob/master/sample/hello-world.c,它在下面修改,以侦听netlink套接字。

基本示例监听Linux网络接口创建/删除,并可以使用sudo执行以获得所需的特权。它倾听与ip monitor link相同的事件。

另一个用libevent收听RAW套接字的例子是https://github.com/bodgit/libevent-natpmp/blob/master/natpmp.c

static void link_recvmsg(int fd, short event, void *arg) 
{ 
    char   buf[NLMSG_SPACE(BUF_SIZE)] = {0}; 
    socklen_t  socklen; 
    struct iovec iov = {.iov_base = buf, .iov_len = sizeof(buf)}; 
    struct sockaddr addr; 
    memset(&addr, 0, sizeof(struct sockaddr)); 

    if (!fd || -1 == fd) 
     return; 

    int status = getsockname(fd, &addr, &socklen); 
    if(-1 == status) 
     return; 

    struct msghdr mh = {.msg_name = NULL, .msg_namelen = 0, .msg_iov = &iov, .msg_iovlen = 1, 
     .msg_flags = 0, .msg_name = &addr, .msg_namelen = sizeof(struct sockaddr)}; 

    status = recvmsg(fd, &mh, 0); 
    if ((-1 == status) && ((EINTR == errno) || (EAGAIN == errno))) 
     return; 
    if(-1 == status) 
     return; 
    if ((mh.msg_flags & MSG_TRUNC) == MSG_TRUNC) 
     return; 
    if ((mh.msg_flags & MSG_CTRUNC) == MSG_CTRUNC) 
     return; 

    for (const struct nlmsghdr *h = (struct nlmsghdr *)buf; NLMSG_OK(h, status); h = NLMSG_NEXT(h, status)) { 
     switch (h->nlmsg_type) { 
      case RTM_NEWLINK: 
       fprintf(stderr, "got RTM_NEWLINK\n"); 
       break; 
      case RTM_DELLINK: 
       fprintf(stderr, "got RTM_DELLINK\n"); 
       break; 
      default: 
       fprintf(stderr, "unexpected case in swtch statement\n"); 
       break; 
     } 
    } 
} 
int main(int argc, char **argv) 
{ 
    /* some init code here */ 
    /* NETLINK socket */ 
    int status; 
    int buf_size = BUF_SIZE; 
    struct sockaddr_nl src_addr; 

    int socket_nl = socket(AF_NETLINK, SOCK_RAW | SOCK_NONBLOCK, NETLINK_ROUTE); 
    if(-1 == socket_nl) return -1; 

    memset(&src_addr, 0, sizeof(struct sockaddr_nl)); 
    src_addr.nl_family = AF_NETLINK; 
    src_addr.nl_pid = getpid(); 
    src_addr.nl_groups |= RTNLGRP_LINK; 

    status = setsockopt(socket_nl, SOL_SOCKET, SO_RCVBUF, 
      &buf_size, sizeof(buf_size)); 
    if(-1 == status) return -1; 

    status = bind(socket_nl, (struct sockaddr *)&src_addr, sizeof(struct sockaddr_nl)); 
    if(status < 0) return -1; 

    static struct event nl_ev; 
    event_set(&nl_ev, socket_nl, EV_READ|EV_PERSIST, link_recvmsg, 
      NULL); 
    if (base) { 
     event_base_set(base, &nl_ev); 
    } 
    event_add(&nl_ev, NULL); 
    /* some other code, dispatch event and deinit */ 
}