从网络链路消息中提取当前路径,code附 [英] Extract current route from netlink message, code attached

查看:288
本文介绍了从网络链路消息中提取当前路径,code附的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想,以监测网络连接套接字路线的变化,但我应该怎么获取更新的路由地址?

code:

 的#include< SYS / socket.h中>
#包括LT&;&stdlib.h中GT;
#包括LT&;&stdio.h中GT;
#包括LT&;&string.h中GT;
#包括LT&; Linux的/ netlink.h>
#包括LT&; Linux的/ rtnetlink.h>
#定义ERR_RET(X)做{PERROR(X);返回EXIT_FAILURE; }而(0);无效循环(INT袜子)
{
    结构sockaddr_nl nladdr;
    结构指向msghdr味精;
    结构iovec的IOV [2];
    结构nlmsghdr NLH;
    字符缓冲区[65536]    IOV [0] = .iov_base(无效*)及北大屿山医院;
    IOV [0] = .iov_len的sizeof(NLH);
    IOV [1] .iov_base =(无效*)缓冲区;
    IOV [1] .iov_len = sizeof的(缓冲器);    msg.msg_name =(无效*)及(nladdr);
    msg.msg_namelen = sizeof的(nladdr);
    msg.msg_iov = IOV;
    msg.msg_iovlen = sizeof的(IOV)/的sizeof(结构iovec的);    如果(recvmsg(袜子,和放大器;味精,0))
    {
        如果(nlh.nlmsg_type == RTM_NEWROUTE)
        {
            的printf(新航线邮件\\ n);
        }
        否则,如果(nlh.nlmsg_type == RTM_DELROUTE)
        {
            的printf(德尔航线邮件\\ n);
        }
    }
}INT主(INT ARGC,CHAR *的argv [])
{
    INT袜子= -1;
    结构sockaddr_nl地址;
    bzero(安培;地址,的sizeof(地址));    如果((袜子=插座(AF_NETLINK,SOCK_RAW,NETLINK_ROUTE))小于0)
        ERR_RET(插座);    addr.nl_family = AF_NETLINK;
    addr.nl_groups = RTMGRP_IPV4_ROUTE;    如果(绑定(袜子,(结构sockaddr *)及地址,的sizeof(地址))小于0)
        ERR_RET(绑定);    而(1)
        环(袜子);
    返回0;
}


解决方案

我编辑你的code和增加两个结构(),路由表变化(code被注释掉)时,为了获得所需的信息。

  / *这项计划的目的是监控路由
 *表更改
 * /#包括LT&; SYS / socket.h中>
#包括LT&;&stdlib.h中GT;
#包括LT&;&stdio.h中GT;
#包括LT&;&string.h中GT;
#包括LT&; Linux的/ netlink.h>
#包括LT&; Linux的/ rtnetlink.h>
#包括LT&; ARPA / inet.h>
#包括LT&;&unistd.h中GT;#定义ERR_RET(X)做{PERROR(X);返回EXIT_FAILURE; }而(0);
的#define BUFFER_SIZE 4095INT回路(INT袜子,结构sockaddr_nl *地址)
{
    INT received_bytes = 0;
    结构nlmsghdr * NLH;
    焦炭目的地地址[32];
    焦炭gateway_address [32];
    结构rtmsg * route_entry; / *这个结构重新present的路由条目\\
                                    在路由表中* /
    结构rtattr * route_attribute; / *这个结构包含路径\\
                                            属性(路由类型)* /
    INT route_attribute_len = 0;
    字符缓冲区[BUFFER_SIZE];    bzero(目的地地址,的sizeof(目的地地址));
    bzero(gateway_address,sizeof的(gateway_address));
    bzero(缓冲液,的sizeof(缓冲液));    / *接收的网络连接套接字数据* /
    而(1)
    {
        received_bytes =的recv(袜子,缓冲器,的sizeof(缓冲液),0);
        如果(received_bytes℃,)
            ERR_RET(RECV);
        / *投接收缓冲区* /
        NLH =(结构nlmsghdr *)缓冲区;
        / *如果我们收到的所有数据--->打破* /
        如果(nlh-> nlmsg_type == NLMSG_DONE)
            打破;
        / *我们是路由信息只是intrested * /
        如果(addr-> nl_groups == RTMGRP_IPV4_ROUTE)
            打破;
    }    / *阅读的网络连接套接字数据* /
    / *通过所有条目循环* /
    / *有关的一些功能更多的信息:
     * http://www.kernel.org/doc/man-pages/online/pages/man3/netlink.3.html
     * http://www.kernel.org/doc/man-pages/online/pages/man7/rtnetlink.7.html
     * /    对于(; NLMSG_OK(北大屿山医院,received_bytes); \\
                    NLH = NLMSG_NEXT(北大屿山医院,received_bytes))
    {
        / *获取路线数据* /
        route_entry =(结构rtmsg *)NLMSG_DATA(NLH);        / *我们是在主路由表只是intrested * /
        如果(route_entry->!rtm_table = RT_TABLE_MAIN)
            继续;        / *获取route_entry属性* /
        route_attribute =(结构rtattr *)RTM_RTA(route_entry);        / *获取路线atttibutes len个* /
        route_attribute_len = RTM_PAYLOAD(NLH);
        / *遍历所有属性* /
        为(; RTA_OK(route_attribute,route_attribute_len); \\
            route_attribute = RTA_NEXT(route_attribute,route_attribute_len))
        {
            / *获取目的地址* /
            如果(route_attribute-> rta_type == RTA_DST)
            {
                inet_ntop(AF_INET,RTA_DATA(route_attribute),\\
                        目的地地址,sizeof的(目的地地址));
            }
            / *获取网关(下一跳)* /
            如果(route_attribute-> rta_type == RTA_GATEWAY)
            {
                inet_ntop(AF_INET,RTA_DATA(route_attribute),\\
                        gateway_address,sizeof的(gateway_address));
            }
        }        / *现在,我们可以转储路由属性* /
        如果(nlh-> nlmsg_type == RTM_DELROUTE)
            fprintf中(标准输出,删除路线的目的地 - >%s和网关%S \\ n,\\
                目的地地址,gateway_address);
        如果(nlh-> nlmsg_type == RTM_NEWROUTE)
            的printf(增加路线的目的地 - >%s和网关%S \\ n,\\
                            目的地地址,gateway_address);
    }    返回0;
}INT主(INT ARGC,字符** argv的)
{
    INT袜子= -1;
    结构sockaddr_nl地址;    / *归零地址* /
    bzero(安培;地址,的sizeof(地址));    如果((袜子=插座(AF_NETLINK,SOCK_RAW,NETLINK_ROUTE))小于0)
        ERR_RET(插座);    addr.nl_family = AF_NETLINK;
    addr.nl_groups = RTMGRP_IPV4_ROUTE;    如果(绑定(袜子,(结构sockaddr *)及地址,的sizeof(地址))小于0)
        ERR_RET(绑定);    而(1)
        环(袜子,&安培;地址);    / *关闭插座* /
    关闭(袜子);    返回0;
}

您可以测试这样为例(如根路由添加到路由表中):

 根@#UnixServer路由添加-host 10.113.0.0 GW bsdBox
根@#UnixServer德尔路线-host 10.113.0.0 GW bsdBox

在我的机器上我得到这样的输出:

  TOC @ UnixServer:〜$ / route_monitor
添加路线的目的地 - > 10.113.0.0和网关192.168.1.1
删除路线的目的地 - > 10.113.0.0和网关192.168.1.1
^ C

I'm trying to monitor route changes with netlink socket, but how should I get the updated route address ?

Code:

#include <sys/socket.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#define ERR_RET(x) do { perror(x); return EXIT_FAILURE; } while (0);

void loop (int sock)
{
    struct sockaddr_nl nladdr;
    struct msghdr msg;
    struct iovec iov[2];
    struct nlmsghdr nlh;
    char buffer[65536];

    iov[0].iov_base = (void *)&nlh;
    iov[0].iov_len = sizeof(nlh);
    iov[1].iov_base = (void *)buffer;
    iov[1].iov_len = sizeof(buffer);

    msg.msg_name = (void *)&(nladdr);
    msg.msg_namelen = sizeof(nladdr);
    msg.msg_iov = iov;
    msg.msg_iovlen = sizeof(iov)/sizeof(struct iovec);

    if ( recvmsg (sock, &msg, 0) )
    {
        if ( nlh.nlmsg_type == RTM_NEWROUTE )
        {
            printf ("New route message\n");
        }
        else if ( nlh.nlmsg_type == RTM_DELROUTE )
        {
            printf ("Del route message\n");
        }
    }
}

int main(int argc, char *argv[])
{
    int sock = -1;
    struct sockaddr_nl addr;
    bzero (&addr, sizeof(addr));

    if ( (sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE) ) < 0 )
        ERR_RET("socket");

    addr.nl_family = AF_NETLINK;
    addr.nl_groups = RTMGRP_IPV4_ROUTE;

    if (bind(sock,(struct sockaddr *)&addr,sizeof(addr))<0)
        ERR_RET("bind");

    while (1)
        loop (sock);
    return 0;
}

解决方案

I edited your code and add two structs (), to get the needed information when routing table change (the code is commented).

/* The purpose of this program is to monitor routing
 * table changes
 */

#include <sys/socket.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <arpa/inet.h>
#include <unistd.h>

#define ERR_RET(x) do { perror(x); return EXIT_FAILURE; } while (0);
#define BUFFER_SIZE 4095

int  loop (int sock, struct sockaddr_nl *addr)
{
    int     received_bytes = 0;
    struct  nlmsghdr *nlh;
    char    destination_address[32];
    char    gateway_address[32];
    struct  rtmsg *route_entry;  /* This struct represent a route entry \
                                    in the routing table */
    struct  rtattr *route_attribute; /* This struct contain route \
                                            attributes (route type) */
    int     route_attribute_len = 0;
    char    buffer[BUFFER_SIZE];

    bzero(destination_address, sizeof(destination_address));
    bzero(gateway_address, sizeof(gateway_address));
    bzero(buffer, sizeof(buffer));

    /* Receiving netlink socket data */
    while (1)
    {
        received_bytes = recv(sock, buffer, sizeof(buffer), 0);
        if (received_bytes < 0)
            ERR_RET("recv");
        /* cast the received buffer */
        nlh = (struct nlmsghdr *) buffer;
        /* If we received all data ---> break */
        if (nlh->nlmsg_type == NLMSG_DONE)
            break;
        /* We are just intrested in Routing information */
        if (addr->nl_groups == RTMGRP_IPV4_ROUTE)
            break;
    }

    /* Reading netlink socket data */
    /* Loop through all entries */
    /* For more informations on some functions :
     * http://www.kernel.org/doc/man-pages/online/pages/man3/netlink.3.html
     * http://www.kernel.org/doc/man-pages/online/pages/man7/rtnetlink.7.html
     */

    for ( ; NLMSG_OK(nlh, received_bytes); \
                    nlh = NLMSG_NEXT(nlh, received_bytes))
    {
        /* Get the route data */
        route_entry = (struct rtmsg *) NLMSG_DATA(nlh);

        /* We are just intrested in main routing table */
        if (route_entry->rtm_table != RT_TABLE_MAIN)
            continue;

        /* Get attributes of route_entry */
        route_attribute = (struct rtattr *) RTM_RTA(route_entry);

        /* Get the route atttibutes len */
        route_attribute_len = RTM_PAYLOAD(nlh);
        /* Loop through all attributes */
        for ( ; RTA_OK(route_attribute, route_attribute_len); \
            route_attribute = RTA_NEXT(route_attribute, route_attribute_len))
        {
            /* Get the destination address */
            if (route_attribute->rta_type == RTA_DST)
            {
                inet_ntop(AF_INET, RTA_DATA(route_attribute), \
                        destination_address, sizeof(destination_address));
            }
            /* Get the gateway (Next hop) */
            if (route_attribute->rta_type == RTA_GATEWAY)
            {
                inet_ntop(AF_INET, RTA_DATA(route_attribute), \
                        gateway_address, sizeof(gateway_address));
            }
        }

        /* Now we can dump the routing attributes */
        if (nlh->nlmsg_type == RTM_DELROUTE)
            fprintf(stdout, "Deleting route to destination --> %s and gateway %s\n", \
                destination_address, gateway_address);
        if (nlh->nlmsg_type == RTM_NEWROUTE)
            printf("Adding route to destination --> %s and gateway %s\n", \
                            destination_address, gateway_address);
    }

    return 0;
}

int main(int argc, char **argv)
{
    int sock = -1;
    struct sockaddr_nl addr;

    /* Zeroing addr */
    bzero (&addr, sizeof(addr));

    if ((sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0)
        ERR_RET("socket");

    addr.nl_family = AF_NETLINK;
    addr.nl_groups = RTMGRP_IPV4_ROUTE;

    if (bind(sock,(struct sockaddr *)&addr,sizeof(addr)) < 0)
        ERR_RET("bind");

    while (1)
        loop (sock, &addr);

    /* Close socket */
    close(sock);

    return 0;
}

You can test like this for example (as root to add routes to the routing table):

root@UnixServer# route add -host 10.113.0.0 gw bsdBox
root@UnixServer# route del -host 10.113.0.0 gw bsdBox

In my machine i got this output:

toc@UnixServer:~$./route_monitor 
Adding route to destination --> 10.113.0.0 and gateway 192.168.1.1
Deleting route to destination --> 10.113.0.0 and gateway 192.168.1.1
^C

这篇关于从网络链路消息中提取当前路径,code附的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆