2017-02-16 19 views
0

私はnetlinkを使ってカーネルから割り込み番号を受け取ります。ユーザー空間のアプリケーションは、libeventを使用してTCP/IP要求を処理し、netlinkメッセージを処理します。 libevent Linux netlinkソケット?簡単な例がわかります。libeventはnetlinkソケットをサポートしています

答えて

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 */ 
} 
関連する問題