LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1539|回复: 5

跪求使用netlink查询路由中返回信息处理的代码,写了一半了,帮忙补下吧!

[复制链接]
发表于 2006-11-2 18:07:21 | 显示全部楼层 |阅读模式
#include <netpacket/packet.h>
#include <net/ethernet.h>
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<sys/types.h>
#include<sys/ioctl.h>
#include<net/if.h>
#include<netinet/ip.h>
#include<err.h>
#include<netdb.h>
#include<fcntl.h>
#include<linux/netlink.h>
#include<linux/rtnetlink.h>
#include<net/route.h>

struct req {
          struct nlmsghdr nlmsg;
          struct rtmsg rtm;
          char buf[512];
};

int print_route(struct rtentry *rt);
int main(void)
{


        int fd;
        int n;
        char *c;
        char buff[BUFSIZ];
        char str[22];
        struct req req;
       
          struct nlmsghdr nlmsg, *nlp;
          struct rtmsg rtm;
        struct sockaddr so;
        struct sockaddr_nl nl;
        struct in_addr addr;

        fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
        if (fd < 0) {
                perror("open error");
                exit (1);
        }
        nl.nl_family = AF_NETLINK;
        nl.nl_pad = 0;
        nl.nl_pid = getpid();
        nl.nl_groups = 0;

        n = bind(fd, (struct sockaddr*)&nl, sizeof(nl));
        if (n < 0) {
                perror(" bind  error");
                exit (1);
        }

        memset(&nlmsg, 0, sizeof(struct nlmsghdr));
        req.nlmsg.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
        req.nlmsg.nlmsg_type = RTM_GETROUTE;
        req.nlmsg.nlmsg_flags = NLM_F_ROOT|NLM_F_REQUEST;
//        req.nlmsg.nlmsg_pid = nl.pid;  

        memset(&rtm, 0, sizeof(struct rtmsg));
        req.rtm.rtm_family = AF_NETLINK;
       
        /** we need change here **/
        req.rtm.rtm_dst_len = 4;
        req.rtm.rtm_src_len = 4;

        req.rtm.rtm_table = RT_TABLE_MAIN;
        req.rtm.rtm_protocol = RTPROT_BOOT;/* Route installed during boot                */
        req.rtm.rtm_scope = RT_SCOPE_LINK; /** located on directly LAN **/
        req.rtm.rtm_type = RTN_UNICAST;        /** Gateway or direct route **/

        n = send(fd, &req, sizeof(req), 0);
        if (n < 0)
        {
                perror("send error!");
                exit (-1);
        }
        else
                printf("%d bytes send!\n",n);

        n = recv(fd, buff, BUFSIZ, 0);
        if (n < 0)
                perror("received failed!");
        printf("%d bytes received!\n", n);
/**********************在这里开始加就好了**********************/

               
        }
}

这段代码烦了好几天了,有人说返回 nlmsghdr + route entry. route entry 又由几个
rtattr结构组成。可我还是没法理解。总是弄不出来。
哪个大哥帮添加一下吧,比如打印目的地址和网关。不愿意写,把详细的数据结构介绍下
也好,多谢了!
 楼主| 发表于 2006-11-6 11:14:22 | 显示全部楼层
自己的事情自己做!

不好意思,上面的代码有点乱。这是完整的代码。
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<string.h>
  4. #include<unistd.h>
  5. #include<sys/socket.h>
  6. #include<netinet/in.h>
  7. #include<sys/types.h>
  8. #include<linux/netlink.h>
  9. #include<linux/rtnetlink.h>
  10. struct req {
  11.           struct nlmsghdr nlmsg;
  12.           struct rtmsg rtm;
  13. };
  14. struct rtattr* get_gw_attr(struct nlmsghdr *nlmsghdr);
  15. int print_route(struct rtattr *rtp);
  16. int main(void)
  17. {
  18.         int fd;
  19.         int n;
  20.         char *c;
  21.         char buff[BUFSIZ];
  22.         char str[22];
  23.         struct req req;
  24.         struct rtattr *rtp;
  25.           struct nlmsghdr nlmsg, *nlp;
  26.           struct rtmsg rtm;
  27.         struct sockaddr so;
  28.         struct sockaddr_nl nl;
  29.         struct in_addr addr;
  30.         fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
  31.         if (fd < 0) {
  32.                 perror("open error");
  33.                 exit (1);
  34.         }
  35.         nl.nl_family = AF_NETLINK;
  36.         nl.nl_pad = 0;
  37.         nl.nl_pid = getpid();
  38.         nl.nl_groups = 0;
  39.         n = bind(fd, (struct sockaddr*)&nl, sizeof(nl));
  40.         if (n < 0) {
  41.                 perror(" bind  error");
  42.                 exit (1);
  43.         }
  44.         memset(&nlmsg, 0, sizeof(struct nlmsghdr));
  45.         req.nlmsg.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
  46.         req.nlmsg.nlmsg_type = RTM_GETROUTE;
  47.         /** In kernel header comments NLM_F_ROOT "specify tree root", but On somebooks
  48.           * said this means return the entire table not just one entry **/
  49.         req.nlmsg.nlmsg_flags = NLM_F_ROOT|NLM_F_REQUEST;
  50. //        req.nlmsg.nlmsg_pid = nl.pid;  /** this is not required! **/
  51.         memset(&rtm, 0, sizeof(struct rtmsg));
  52.         req.rtm.rtm_family = AF_NETLINK;
  53.        
  54.         /** we need change here **/
  55.         req.rtm.rtm_dst_len = 4;
  56.         req.rtm.rtm_src_len = 4;
  57.         req.rtm.rtm_table = RT_TABLE_MAIN;
  58.         req.rtm.rtm_protocol = RTPROT_BOOT;/** Route installed during boot **/
  59.         req.rtm.rtm_scope = RT_SCOPE_LINK; /** located on directly LAN **/
  60.         req.rtm.rtm_type = RTN_UNICAST;        /** Gateway or direct route **/
  61.         n = send(fd, &req, sizeof(req), 0);
  62.         if (n < 0)
  63.         {
  64.                 perror("send error!");
  65.                 exit (-1);
  66.         }
  67.         else
  68.                 printf("%d bytes send!\n",n);
  69.         n = recv(fd, buff, BUFSIZ, 0);
  70.         if (n < 0)
  71.                 perror("received failed!");
  72.         printf("%d bytes received!\n", n);
  73.         for (nlp = (struct nlmsghdr*)buff; \
  74.                 (nlp->nlmsg_type != NLMSG_DONE)&& NLMSG_OK(nlp, n); nlp = NLMSG_NEXT(nlp, n)) {
  75.                 rtp = get_gw_attr(nlp);
  76.                 if (rtp) {
  77.                         print_route(rtp);
  78.                         return;
  79.                 }
  80.         }
  81. }
  82. struct rtattr* get_gw_attr(struct nlmsghdr *nlmsghdr)
  83. {
  84.         struct rtattr *rta;
  85.         int len;
  86.         int gw;
  87.         char str[16];
  88.         len = nlmsghdr->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg));
  89.         /** NLMSG_DATA(nlmsghdr) return the rtmsg pointer following, and RTM_RTA return
  90.                 the rtattr pointer following the rtmsg.        **/
  91.         rta = RTM_RTA(NLMSG_DATA(nlmsghdr));
  92.         while (RTA_OK(rta, len)) {
  93.                 if (rta->rta_type >= RTA_MAX)
  94.                         break;
  95.                 /** We check if the address is INADDR_ANY.I don't know whethher this is needed **/
  96.                 if(rta->rta_type == RTA_GATEWAY && *(int *)RTA_DATA(rta) != INADDR_ANY)
  97.                                 return rta;
  98.                 rta = RTA_NEXT(rta, len);
  99.         }
  100.         return NULL;
  101. };
  102. int print_route(struct rtattr *rtp)
  103. {
  104.         char str[16];
  105.         char *c;
  106.         char buff[16];
  107.         c = inet_ntop (AF_INET, RTA_DATA(rtp), buff, INET_ADDRSTRLEN);
  108.         if (!c) {
  109.                 perror("inet_ntop failed !");
  110.                 exit (1);
  111.         }
  112.         printf("The gateway IP address is %s\n",c);
  113. }
复制代码
参考:
1. http://people.redhat.com/nhorman/papers/netlink.pdf
2. RFC3549:http://rfc.net/rfc3549.html

详细的过程我不想解释,因为上面的两个参考资料足够了。而我也正开始学习整理一份完整的NETLINK实现和编程的文章。
希望早日能出炉拿出来和大家分享。


说实话,我不知道是我问的方式不对,还是论坛里的高手不想回答,抑或是没有人知道。
回复 支持 反对

使用道具 举报

发表于 2006-11-7 00:41:17 | 显示全部楼层
楼主是个挺不错的guy,说真的,用linux内核接口NETLINK的人确实比较少。你的这篇文章也很有参考价值。
我为你加精,为你加油。
希望你能为GNU的事业再努力。
这里的很多老鸟相继的都退隐江湖了,好在现在的情况是新秀层出不穷。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-11-7 15:07:22 | 显示全部楼层
谢谢版主,这几天正忙毕业设计呢,想早点弄完,下半年就没事做了。那就有时间研究内核了。
回复 支持 反对

使用道具 举报

发表于 2007-4-18 15:23:56 | 显示全部楼层
楼主,我爱死你了!!!
回复 支持 反对

使用道具 举报

发表于 2007-4-19 10:56:47 | 显示全部楼层
可以在linuxjournal中搜一下netlink,有两篇文章专门讲这个,也写的很好.
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表