оповещение через rtnetlink

Модератор: Модераторы разделов

Ответить
xsx
Сообщения: 2

оповещение через rtnetlink

Сообщение xsx »

Привет всем.
В руководстве man 7 rtnetlink написано к rtm_flags

Код: Выделить всё

              RTM_F_NOTIFY     if the route changes, notify the  user  via rtnetlink

Сначала программа отправляет запрос, получает ответ. Узнаю адрес шлюза. Подключаюсь к другой сети, маршрут меняеться,
а программе не приходит никаких оповещений.
Вот код. Как правильней сделать, и есть ли об этом где нибудь почитать?

Код: Выделить всё

#include <stdio.h>
#include <asm/types.h>
#include <linux/netlink.h>
#include <linux/if_link.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <strings.h>
#include <string.h>
#include <arpa/inet.h>

struct
{
    struct nlmsghdr nh;
    struct rtmsg rtmsg;
    char buf[8192];
}req;

int main(int argc, char *argv[])
{
    int rtnetlink_socket;

    if((rtnetlink_socket = socket(AF_NETLINK,SOCK_DGRAM,NETLINK_ROUTE)) == -1)
    {
        perror("socket");
        exit(-1);
    }

    memset(&req,0,sizeof(req));

    req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
    req.nh.nlmsg_type = RTM_GETROUTE;
    req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;

    req.rtmsg.rtm_dst_len = 0;
    req.rtmsg.rtm_src_len = 0;
    req.rtmsg.rtm_tos = 0;
    req.rtmsg.rtm_family = AF_INET;
    req.rtmsg.rtm_type = 0;
    req.rtmsg.rtm_protocol = RTPROT_STATIC;
    req.rtmsg.rtm_scope = 0;
    req.rtmsg.rtm_flags = RTM_F_NOTIFY;
    req.rtmsg.rtm_table = RT_TABLE_DEFAULT;
    unsigned int intaddr = 0;
    struct rtattr *rta;
    rta = (struct rtattr *)(((char *) &req) + NLMSG_ALIGN(req.nh.nlmsg_len));
    rta->rta_type =  RTA_GATEWAY;
    rta->rta_len = RTA_LENGTH(sizeof(unsigned int));
    req.nh.nlmsg_len = NLMSG_ALIGN(req.nh.nlmsg_len) + RTA_LENGTH(sizeof(intaddr));

    memcpy(RTA_DATA(rta), &intaddr, sizeof(intaddr));

    if(send(rtnetlink_socket,&req,req.nh.nlmsg_len,0) == -1)
    {
        perror("send");
        close(rtnetlink_socket);
        exit(-1);
    }

    int recvlen = 0;
    int counter = 8192;
    char buffer[counter];

    struct nlmsghdr *nl;
    int replylen = 0;
    int i = 0;

  struct sockaddr_nl sa;
  bzero(&sa,sizeof(sa));
  sa.nl_family = AF_NETLINK;

    i = sizeof(struct sockaddr_nl *);

    for(;;)
    {
        recvlen = recv(rtnetlink_socket,&buffer,1500,0);
        printf("recvlen = %d\n",recvlen);
        if(recvlen < 0)
        {
            printf("recvlen < 0\n");
            break;
        }

        if(recvlen == 0)
            printf("eof in netlink\n");

        int nll;
        struct rtmsg *rtp;
        nl = (struct nlmsghdr *)&buffer[replylen];
        rtp = (struct rtmsg *) NLMSG_DATA(nl);

        if(rtp->rtm_table != RT_TABLE_MAIN)
        {
            printf("non table main %d\n",rtp->rtm_table);
            continue;
        }
        char gws[24];
        struct rtattr *rtap;
        rtap = (struct rtattr *) RTM_RTA(rtp);
        int rtl = 0;
        rtl = RTM_PAYLOAD(nl);
        for(; RTA_OK(rtap,rtl);rtap=RTA_NEXT(rtap,rtl))
        {
            switch(rtap->rta_type)
            {
                case RTA_GATEWAY:
                    inet_ntop(AF_INET, RTA_DATA(rtap),gws,24);
                    printf("%s\n",gws);
            //        return 0;
                    break;
            }
        }

        if(nl->nlmsg_type == NLMSG_DONE)
        {
            printf("nlmsg done\n");
            break;
        }

        if(nl->nlmsg_type == NLMSG_ERROR)
        {
            printf("error in nl\n");
            exit(-1);
        }
        if(nl->nlmsg_type == NLMSG_NOOP)
        {
            printf("nothing.\n");
            exit(-1);
        }
        if(nl->nlmsg_type == NLMSG_OVERRUN)
        {
            printf("data lost\n");
            exit(-1);
        }
        if(nl->nlmsg_type == NLMSG_MIN_TYPE)
        {
            printf("reserved control message\n");
            exit(-1);
        }
        replylen += recvlen;
        counter -= recvlen;

    }
        close(rtnetlink_socket);
}
Спасибо сказали:
Ответить