#c #linux #netlink
Вопрос:
У меня есть эти 3 функции для обработки событий netlink интерфейса вверх/вниз (init, receive_msg и handle_msg) Когда я делаю ifconfig eth0 вниз/вверх, я вижу, что флаг IFF_RUNNING установлен/снят правильно ifconfig eth0 вниз: событие IFF_BROADCAST IFF_MULTICAST Ссылка 16 ifindex 2 флага 4098 (ifi->ifi_flags amp; IFF_RUNNING)=0
ifconifg eth0 вверх: IFF_UP IFF_BROADCAST IFF_RUNNING Событие IFF_MULTICAST Ссылка 16 ifindex 2 флага 69699 (ifi->ifi_flags и IFF_RUNNING)=64 Но при запуске tcpdump-i eth0 я также получаю эти сообщения дважды (когда запускается tcpdump и когда он закрывается)
tcpdump -i eth0: Событие IFF_BROADCAST IFF_RUNNING IFF_MULTICAST Ссылка 16 флагов ifindex 2 69699 (ifi->ifi_flags и IFF_RUNNING)=64
Есть идеи, почему ? Могу ли я отфильтровать его ?
Спасибо!
int init()
{
struct sockaddr_nl snl;
netlink_socket = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (netlink_socket < 0) {
return -1;
}
memset((void *)amp;snl, 0, sizeof(snl));
snl.nl_family = AF_NETLINK;
snl.nl_pid = getpid();
snl.nl_groups = RTMGRP_LINK;
if (bind(netlink_socket, (struct sockaddr *)amp;snl, sizeof(snl)) < 0) {
return -1;
}
return 0;
}
int receive_msg()
{
int cc;
char buf[4096];
struct iovec iov = {.iov_base = buf, .iov_len = sizeof buf};
struct sockaddr_nl snl;
struct msghdr msg;
struct nlmsghdr *h;
msg.msg_name = (void*)amp;snl;
msg.msg_namelen = sizeof(snl);
msg.msg_control = 0;
msg.msg_iov = amp;iov;
msg.msg_iovlen = 1;
msg.msg_flags = 0;
cc = recvmsg(sock, amp;msg, MSG_DONTWAIT);
if (cc < 0) {
return -1;
}
/* We need to handle more than one message per 'recvmsg' */
for (h = (struct nlmsghdr *)buf; NLMSG_OK(h, cc); h = NLMSG_NEXT(h, cc)) {
/* Finish reading */
if (h->nlmsg_type == NLMSG_DONE) {
return 0;
}
/* Message is some kind of error */
if (h->nlmsg_type == NLMSG_ERROR) {
struct nlmsgerr err = (struct nlmsgerr)(NLMSG_DATA(h));
return -1;
}
/* Call message handler */
handle_msg(h);
}
return 0;
}
int handle_msg()
{
struct ifinfomsg ifi = (struct ifinfomsg)NLMSG_DATA(msg);
switch (msg->nlmsg_type) {
case RTM_NEWLINK:
case RTM_DELLINK:
int is_up = (ifi->ifi_flags amp; IFF_RUNNING);
printf("Link event %d ifindex %u flags %d link %d", _FUNCTION_, msg->nlmsg_type,
ifi->ifi_index, ifi->ifi_flags, is_up);
break;
default:
break;
}
}
Комментарии:
1. Вы уверены, что получаете ссылку на событие RTM_DELLINK? можете ли вы добавить разрыв в случае RTM_NEWLINK и попробовать?
2. Я удалил RTM_DELLINK. Это не тип сообщения для событий tcpdump или ссылок. Тот же результат только для RTM_NEWLINK.
3. Происходит, когда tcpdump переводит интерфейс в беспорядочный режим (не воспроизводится с помощью tcpdump-pi eth0)