Chinaunix首页 | 论坛 | 博客
  • 博客访问: 818978
  • 博文数量: 264
  • 博客积分: 592
  • 博客等级: 中士
  • 技术积分: 1574
  • 用 户 组: 普通用户
  • 注册时间: 2011-10-24 22:02
文章分类

全部博文(264)

文章存档

2019年(2)

2018年(1)

2017年(1)

2016年(4)

2015年(14)

2014年(57)

2013年(88)

2012年(97)

分类: LINUX

2014-02-12 15:59:05

转:http://blog.csdn.net/nerdx/article/details/12841467
  1. //  路由子系统netlink控制块  
  2. //      在ip_rt_init->devinet_init中注册。  
  3. 1.1 static struct rtnetlink_link inet_rtnetlink_table[RTM_MAX - RTM_BASE + 1] = {  
  4.      [4] = { .doit   = inet_rtm_newaddr,  },  
  5.      [5] = { .doit   = inet_rtm_deladdr,  },  
  6.      [6] = { .dumpit = inet_dump_ifaddr,  },  
  7.      [8] = { .doit   = inet_rtm_newroute, },  
  8.      [9] = { .doit   = inet_rtm_delroute, },  
  9.     [10] = { .doit   = inet_rtm_getroute, .dumpit = inet_dump_fib, },  
  10. #ifdef CONFIG_IP_MULTIPLE_TABLES  
  11.     [16] = { .doit   = inet_rtm_newrule, },  
  12.     [17] = { .doit   = inet_rtm_delrule, },  
  13.     [18] = { .dumpit = inet_dump_rules,  },  
  14. #endif  
  15. };  
  16.   
  17. //  为设备配置ip地址  
  18. //  函数主要任务:  
  19. //      1.检查有效性  
  20. //          1.1 网络部分<=32,提供了ip地址  
  21. //      2.分配in_ifaddr并填充信息  
  22. //      3.将in_ifaddr插入到in_device中  
  23.   
  24. 1.2 static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)  
  25. {  
  26.     struct rtattr **rta = arg;  
  27.     struct net_device *dev;  
  28.     struct in_device *in_dev;  
  29.     struct ifaddrmsg *ifm = NLMSG_DATA(nlh);  
  30.     struct in_ifaddr *ifa;  
  31.     int rc = -EINVAL;  
  32.     // 有效性检查  
  33.     //  网路地址部分 <= 32  
  34.     if (ifm->ifa_prefixlen > 32 || !rta[IFA_LOCAL - 1])  
  35.         goto out;  
  36.   
  37.     rc = -ENODEV;  
  38.     //通过设备index获取设备描述符  
  39.     if ((dev = __dev_get_by_index(ifm->ifa_index)) == NULL)  
  40.         goto out;  
  41.   
  42.     rc = -ENOBUFS;  
  43.     //获取设备配置信息  
  44.     if ((in_dev = __in_dev_get(dev)) == NULL) {  
  45.         //第一次配置设备,则创建配置信息  
  46.         in_dev = inetdev_init(dev);  
  47.     }  
  48.     //分配ip地址  
  49.     if ((ifa = inet_alloc_ifa()) == NULL)  
  50.         goto out;  
  51.     //如果地址指派给隧道接口:  
  52.     //  ifa->ifa_local为隧道的本地地址,ifa->ifa_address为远程地址  
  53.     //否则:  
  54.     // ifa->ifa_local, ifa->ifa_address均为本地地址  
  55.     if (!rta[IFA_ADDRESS - 1])  
  56.         rta[IFA_ADDRESS - 1] = rta[IFA_LOCAL - 1];  
  57.     memcpy(&ifa->ifa_local, RTA_DATA(rta[IFA_LOCAL - 1]), 4);  
  58.     memcpy(&ifa->ifa_address, RTA_DATA(rta[IFA_ADDRESS - 1]), 4);  
  59.     //网络地址部分  
  60.     ifa->ifa_prefixlen = ifm->ifa_prefixlen;  
  61.     //掩码  
  62.     ifa->ifa_mask = inet_make_mask(ifm->ifa_prefixlen);  
  63.     //广播地址  
  64.     if (rta[IFA_BROADCAST - 1])  
  65.         memcpy(&ifa->ifa_broadcast,  
  66.                RTA_DATA(rta[IFA_BROADCAST - 1]), 4);  
  67.     //选播地址  
  68.     if (rta[IFA_ANYCAST - 1])  
  69.         memcpy(&ifa->ifa_anycast, RTA_DATA(rta[IFA_ANYCAST - 1]), 4);  
  70.     //ifa_flags标示主辅地址  
  71.     ifa->ifa_flags = ifm->ifa_flags;  
  72.     ifa->ifa_scope = ifm->ifa_scope;  
  73.     in_dev_hold(in_dev);  
  74.     ifa->ifa_dev   = in_dev;  
  75.     //设备别名  
  76.     if (rta[IFA_LABEL - 1])  
  77.         rtattr_strlcpy(ifa->ifa_label, rta[IFA_LABEL - 1], IFNAMSIZ);  
  78.     else  
  79.         memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);  
  80.     //将新地址插入到in_device中  
  81.     rc = inet_insert_ifa(ifa);  
  82. out:  
  83.     return rc;  
  84. }  
  85.   
  86. //  删除设备ip地址  
  87. //  函数主要任务:  
  88. //      1.获取设备的配置描述符in_device  
  89. //      2.从配置描述符中删除ip信息  
  90. 1.3 static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)  
  91. {  
  92.     struct rtattr **rta = arg;  
  93.     struct in_device *in_dev;  
  94.     struct ifaddrmsg *ifm = NLMSG_DATA(nlh);  
  95.     struct in_ifaddr *ifa, **ifap;  
  96.     //获取设备描述  
  97.     if ((in_dev = inetdev_by_index(ifm->ifa_index)) == NULL)  
  98.         goto out;  
  99.     __in_dev_put(in_dev);  
  100.   
  101.     for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;  
  102.          ifap = &ifa->ifa_next) {  
  103.         if ((rta[IFA_LOCAL - 1] &&  
  104.              memcmp(RTA_DATA(rta[IFA_LOCAL - 1]),  
  105.                 &ifa->ifa_local, 4)) ||  
  106.             (rta[IFA_LABEL - 1] &&  
  107.              rtattr_strcmp(rta[IFA_LABEL - 1], ifa->ifa_label)) ||  
  108.             (rta[IFA_ADDRESS - 1] &&  
  109.              (ifm->ifa_prefixlen != ifa->ifa_prefixlen ||  
  110.               !inet_ifa_match(*(u32*)RTA_DATA(rta[IFA_ADDRESS - 1]),  
  111.                           ifa))))  
  112.             continue;  
  113.         //从in_device 删除配置的ip地址  
  114.         inet_del_ifa(in_dev, ifap, 1);  
  115.         return 0;  
  116.     }  
  117. out:  
  118.     return -EADDRNOTAVAIL;  
  119. }  
  120.   
  121. //  添加路由  
  122. //      通过id选择路由表,通过特定于路由表的回调函数添加路由项  
  123. 1.4 int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)  
  124. {  
  125.     struct fib_table * tb;  
  126.     struct rtattr **rta = arg;  
  127.     struct rtmsg *r = NLMSG_DATA(nlh);  
  128.   
  129.     if (inet_check_attr(r, rta))  
  130.         return -EINVAL;  
  131.     //根据指定的id,选择路由表  
  132.     tb = fib_new_table(r->rtm_table);  
  133.     if (tb) //有路由表的回调函数添加一条新路由  
  134.         return tb->tb_insert(tb, r, (struct kern_rta*)rta, nlh, &NETLINK_CB(skb));  
  135.     return -ENOBUFS;  
  136. }  
  137.   
  138. //  获取路由信息  
  139. //  函数主要任务:  
  140. //      1.指定了入口设备,通过ip_route_input路由数据包,获取路由信息  
  141. //      2.否则通过出口路由,获取路由信息  
  142. //      3.将获取的路由信息通过netlink应答  
  143. 1.5 int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)  
  144. {  
  145.     struct rtattr **rta = arg;  
  146.     struct rtmsg *rtm = NLMSG_DATA(nlh);  
  147.     struct rtable *rt = NULL;  
  148.     u32 dst = 0;  
  149.     u32 src = 0;  
  150.     int iif = 0;  
  151.     int err = -ENOBUFS;  
  152.     struct sk_buff *skb;  
  153.   
  154.     skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);  
  155.     if (!skb)  
  156.         goto out;  
  157.   
  158.     skb->mac.raw = skb->data;  
  159.     skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr));  
  160.   
  161.     if (rta[RTA_SRC - 1])  
  162.         memcpy(&src, RTA_DATA(rta[RTA_SRC - 1]), 4);  
  163.     if (rta[RTA_DST - 1])  
  164.         memcpy(&dst, RTA_DATA(rta[RTA_DST - 1]), 4);  
  165.     if (rta[RTA_IIF - 1])  
  166.         memcpy(&iif, RTA_DATA(rta[RTA_IIF - 1]), sizeof(int));  
  167.     //入口路由  
  168.     if (iif) {  
  169.         struct net_device *dev = __dev_get_by_index(iif);  
  170.         err = -ENODEV;  
  171.         if (!dev)  
  172.             goto out_free;  
  173.         skb->protocol    = htons(ETH_P_IP);  
  174.         skb->dev = dev;  
  175.         local_bh_disable();  
  176.         //路由此skb,获取路由信息  
  177.         err = ip_route_input(skb, dst, src, rtm->rtm_tos, dev);  
  178.         local_bh_enable();  
  179.         rt = (struct rtable*)skb->dst;  
  180.         if (!err && rt->u.dst.error)  
  181.             err = -rt->u.dst.error;  
  182.     //出口路由  
  183.     } else {  
  184.         //构造查找关键字  
  185.         struct flowi fl = { .nl_u = { .ip4_u = { .daddr = dst,  
  186.                              .saddr = src,  
  187.                              .tos = rtm->rtm_tos } } };  
  188.         int oif = 0;  
  189.         //出口设备  
  190.         if (rta[RTA_OIF - 1])  
  191.             memcpy(&oif, RTA_DATA(rta[RTA_OIF - 1]), sizeof(int));  
  192.         fl.oif = oif;  
  193.         //出口路由  
  194.         err = ip_route_output_key(&rt, &fl);  
  195.     }  
  196.     if (err)  
  197.         goto out_free;  
  198.   
  199.     skb->dst = &rt->u.dst;  
  200.     if (rtm->rtm_flags & RTM_F_NOTIFY)  
  201.         rt->rt_flags |= RTCF_NOTIFY;  
  202.     //netlink控制块  
  203.     NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;  
  204.   
  205.     err = rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq,  
  206.                 RTM_NEWROUTE, 0);  
  207.     //通过netlink应答  
  208.     err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);  
  209.     if (err > 0)  
  210.         err = 0;  
  211. out:    return err;  
  212.   
  213. out_free:  
  214.     kfree_skb(skb);  
  215.     goto out;  
  216. }  
阅读(1106) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~