rt_socket.c
上传用户:xiaozhuqw
上传日期:2009-11-15
资源大小:1338k
文件大小:11k
源码类别:

网络

开发平台:

Unix_Linux

  1. /*
  2.  * Kernel routing table updates by routing socket.
  3.  * Copyright (C) 1997, 98 Kunihiro Ishiguro
  4.  *
  5.  * This file is part of GNU Zebra.
  6.  *
  7.  * GNU Zebra is free software; you can redistribute it and/or modify it
  8.  * under the terms of the GNU General Public License as published by the
  9.  * Free Software Foundation; either version 2, or (at your option) any
  10.  * later version.
  11.  *
  12.  * GNU Zebra is distributed in the hope that it will be useful, but
  13.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU General Public License
  18.  * along with GNU Zebra; see the file COPYING.  If not, write to the Free
  19.  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  20.  * 02111-1307, USA.  
  21.  */
  22. #include <zebra.h>
  23. #include "if.h"
  24. #include "prefix.h"
  25. #include "sockunion.h"
  26. #include "log.h"
  27. #include "str.h"
  28. #include "zebra/debug.h"
  29. #include "zebra/rib.h"
  30. int
  31. rtm_write (int message,
  32.    union sockunion *dest,
  33.    union sockunion *mask,
  34.    union sockunion *gate,
  35.    unsigned int index,
  36.    int zebra_flags,
  37.    int metric);
  38. /* Adjust netmask socket length. Return value is a adjusted sin_len
  39.    value. */
  40. int
  41. sin_masklen (struct in_addr mask)
  42. {
  43.   char *p, *lim;
  44.   int len;
  45.   struct sockaddr_in sin;
  46.   if (mask.s_addr == 0) 
  47.     return sizeof (long);
  48.   sin.sin_addr = mask;
  49.   len = sizeof (struct sockaddr_in);
  50.   lim = (char *) &sin.sin_addr;
  51.   p = lim + sizeof (sin.sin_addr);
  52.   while (*--p == 0 && p >= lim) 
  53.     len--;
  54.   return len;
  55. }
  56. /* Interface between zebra message and rtm message. */
  57. int
  58. kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib *rib, int family)
  59. {
  60.   struct sockaddr_in *mask = NULL;
  61.   struct sockaddr_in sin_dest, sin_mask, sin_gate;
  62.   struct nexthop *nexthop;
  63.   int nexthop_num = 0;
  64.   unsigned int ifindex = 0;
  65.   int gate = 0;
  66.   int error;
  67.   memset (&sin_dest, 0, sizeof (struct sockaddr_in));
  68.   sin_dest.sin_family = AF_INET;
  69. #ifdef HAVE_SIN_LEN
  70.   sin_dest.sin_len = sizeof (struct sockaddr_in);
  71. #endif /* HAVE_SIN_LEN */
  72.   sin_dest.sin_addr = p->u.prefix4;
  73.   memset (&sin_mask, 0, sizeof (struct sockaddr_in));
  74.   memset (&sin_gate, 0, sizeof (struct sockaddr_in));
  75.   sin_gate.sin_family = AF_INET;
  76. #ifdef HAVE_SIN_LEN
  77.   sin_gate.sin_len = sizeof (struct sockaddr_in);
  78. #endif /* HAVE_SIN_LEN */
  79.   /* Make gateway. */
  80.   for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
  81.     {
  82.       gate = 0;
  83.       if ((cmd == RTM_ADD
  84.    && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
  85.   || (cmd == RTM_DELETE
  86. #if 0
  87.       && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
  88. #endif
  89.       ))
  90. {
  91.   if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
  92.     {
  93.       if (nexthop->rtype == NEXTHOP_TYPE_IPV4 ||
  94.   nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)
  95. {
  96.   sin_gate.sin_addr = nexthop->rgate.ipv4;
  97.   gate = 1;
  98. }
  99.       if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX
  100.   || nexthop->rtype == NEXTHOP_TYPE_IFNAME
  101.   || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)
  102. ifindex = nexthop->rifindex;
  103.     }
  104.   else
  105.     {
  106.       if (nexthop->type == NEXTHOP_TYPE_IPV4 ||
  107.   nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
  108. {
  109.   sin_gate.sin_addr = nexthop->gate.ipv4;
  110.   gate = 1;
  111. }
  112.       if (nexthop->type == NEXTHOP_TYPE_IFINDEX
  113.   || nexthop->type == NEXTHOP_TYPE_IFNAME
  114.   || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
  115. ifindex = nexthop->ifindex;
  116.       if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
  117. {
  118.   struct in_addr loopback;
  119.   loopback.s_addr = htonl (INADDR_LOOPBACK);
  120.   sin_gate.sin_addr = loopback;
  121.   gate = 1;
  122. }
  123.     }
  124.   if (cmd == RTM_ADD)
  125.     SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
  126.   if (gate && p->prefixlen == 32)
  127.     mask = NULL;
  128.   else
  129.     {
  130.       masklen2ip (p->prefixlen, &sin_mask.sin_addr);
  131.       sin_mask.sin_family = AF_UNSPEC;
  132. #ifdef HAVE_SIN_LEN
  133.       sin_mask.sin_len = sin_masklen (sin_mask.sin_addr);
  134. #endif /* HAVE_SIN_LEN */
  135.       mask = &sin_mask;
  136.     }
  137. }
  138.       error = rtm_write (cmd,
  139. (union sockunion *)&sin_dest, 
  140. (union sockunion *)mask, 
  141. gate ? (union sockunion *)&sin_gate : NULL,
  142. ifindex,
  143. rib->flags,
  144. rib->metric);
  145. #if 0
  146.       if (error)
  147. {
  148.   zlog_info ("kernel_rtm_ipv4(): nexthop %d add error=%d.",
  149.     nexthop_num, error);
  150. }
  151. #endif
  152.       nexthop_num++;
  153.     }
  154.   /* If there is no useful nexthop then return. */
  155.   if (nexthop_num == 0)
  156.     {
  157.       if (IS_ZEBRA_DEBUG_KERNEL)
  158. zlog_info ("kernel_rtm_ipv4(): No useful nexthop.");
  159.       return 0;
  160.     }
  161.   return 0; /*XXX*/
  162. }
  163. int
  164. kernel_add_ipv4 (struct prefix *p, struct rib *rib)
  165. {
  166.   return kernel_rtm_ipv4 (RTM_ADD, p, rib, AF_INET);
  167. }
  168. int
  169. kernel_delete_ipv4 (struct prefix *p, struct rib *rib)
  170. {
  171.   return kernel_rtm_ipv4 (RTM_DELETE, p, rib, AF_INET);
  172. }
  173. #ifdef HAVE_IPV6
  174. /* Calculate sin6_len value for netmask socket value. */
  175. int
  176. sin6_masklen (struct in6_addr mask)
  177. {
  178.   struct sockaddr_in6 sin6;
  179.   char *p, *lim;
  180.   int len;
  181. #if defined (INRIA)
  182.   if (IN_ANYADDR6 (mask)) 
  183.     return sizeof (long);
  184. #else /* ! INRIA */
  185.   if (IN6_IS_ADDR_UNSPECIFIED (&mask)) 
  186.     return sizeof (long);
  187. #endif /* ! INRIA */
  188.   sin6.sin6_addr = mask;
  189.   len = sizeof (struct sockaddr_in6);
  190.   lim = (char *) & sin6.sin6_addr;
  191.   p = lim + sizeof (sin6.sin6_addr);
  192.   while (*--p == 0 && p >= lim) 
  193.     len--;
  194.   return len;
  195. }
  196. /* Interface between zebra message and rtm message. */
  197. int
  198. kernel_rtm_ipv6 (int message, struct prefix_ipv6 *dest,
  199.  struct in6_addr *gate, int index, int flags)
  200. {
  201.   struct sockaddr_in6 *mask;
  202.   struct sockaddr_in6 sin_dest, sin_mask, sin_gate;
  203.   memset (&sin_dest, 0, sizeof (struct sockaddr_in6));
  204.   sin_dest.sin6_family = AF_INET6;
  205. #ifdef SIN6_LEN
  206.   sin_dest.sin6_len = sizeof (struct sockaddr_in6);
  207. #endif /* SIN6_LEN */
  208.   memset (&sin_mask, 0, sizeof (struct sockaddr_in6));
  209.   memset (&sin_gate, 0, sizeof (struct sockaddr_in6));
  210.   sin_gate.sin6_family = AF_INET6;
  211. #ifdef SIN6_LEN
  212.   sin_gate.sin6_len = sizeof (struct sockaddr_in6);
  213. #endif /* SIN6_LEN */
  214.   sin_dest.sin6_addr = dest->prefix;
  215.   if (gate)
  216.     memcpy (&sin_gate.sin6_addr, gate, sizeof (struct in6_addr));
  217.   /* Under kame set interface index to link local address. */
  218. #ifdef KAME
  219. #define SET_IN6_LINKLOCAL_IFINDEX(a, i) 
  220.   do { 
  221.     (a).s6_addr[2] = ((i) >> 8) & 0xff; 
  222.     (a).s6_addr[3] = (i) & 0xff; 
  223.   } while (0)
  224.   if (gate && IN6_IS_ADDR_LINKLOCAL(gate))
  225.     SET_IN6_LINKLOCAL_IFINDEX (sin_gate.sin6_addr, index);
  226. #endif /* KAME */
  227.   if (gate && dest->prefixlen == 128)
  228.     mask = NULL;
  229.   else
  230.     {
  231.       masklen2ip6 (dest->prefixlen, &sin_mask.sin6_addr);
  232.       sin_mask.sin6_family = AF_UNSPEC;
  233. #ifdef SIN6_LEN
  234.       sin_mask.sin6_len = sin6_masklen (sin_mask.sin6_addr);
  235. #endif /* SIN6_LEN */
  236.       mask = &sin_mask;
  237.     }
  238.   return rtm_write (message, 
  239.     (union sockunion *) &sin_dest,
  240.     (union sockunion *) mask,
  241.     gate ? (union sockunion *)&sin_gate : NULL,
  242.     index,
  243.     flags,
  244.     0);
  245. }
  246. /* Interface between zebra message and rtm message. */
  247. int
  248. kernel_rtm_ipv6_multipath (int cmd, struct prefix *p, struct rib *rib,
  249.    int family)
  250. {
  251.   struct sockaddr_in6 *mask;
  252.   struct sockaddr_in6 sin_dest, sin_mask, sin_gate;
  253.   struct nexthop *nexthop;
  254.   int nexthop_num = 0;
  255.   unsigned int ifindex = 0;
  256.   int gate = 0;
  257.   int error;
  258.   memset (&sin_dest, 0, sizeof (struct sockaddr_in6));
  259.   sin_dest.sin6_family = AF_INET6;
  260. #ifdef SIN6_LEN
  261.   sin_dest.sin6_len = sizeof (struct sockaddr_in6);
  262. #endif /* SIN6_LEN */
  263.   sin_dest.sin6_addr = p->u.prefix6;
  264.   memset (&sin_mask, 0, sizeof (struct sockaddr_in6));
  265.   memset (&sin_gate, 0, sizeof (struct sockaddr_in6));
  266.   sin_gate.sin6_family = AF_INET6;
  267. #ifdef HAVE_SIN_LEN
  268.   sin_gate.sin6_len = sizeof (struct sockaddr_in6);
  269. #endif /* HAVE_SIN_LEN */
  270.   /* Make gateway. */
  271.   for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
  272.     {
  273.       gate = 0;
  274.       if ((cmd == RTM_ADD
  275.    && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
  276.   || (cmd == RTM_DELETE
  277. #if 0
  278.       && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
  279. #endif
  280.       ))
  281. {
  282.   if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
  283.     {
  284.       if (nexthop->rtype == NEXTHOP_TYPE_IPV6
  285.   || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME
  286.   || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX)
  287. {
  288.   sin_gate.sin6_addr = nexthop->rgate.ipv6;
  289.   gate = 1;
  290. }
  291.       if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX
  292.   || nexthop->rtype == NEXTHOP_TYPE_IFNAME
  293.   || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME
  294.   || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX)
  295. ifindex = nexthop->rifindex;
  296.     }
  297.   else
  298.     {
  299.       if (nexthop->type == NEXTHOP_TYPE_IPV6
  300.   || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
  301.   || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
  302. {
  303.   sin_gate.sin6_addr = nexthop->gate.ipv6;
  304.   gate = 1;
  305. }
  306.       if (nexthop->type == NEXTHOP_TYPE_IFINDEX
  307.   || nexthop->type == NEXTHOP_TYPE_IFNAME
  308.   || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
  309.   || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
  310. ifindex = nexthop->ifindex;
  311.       if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
  312. {
  313. #ifdef HAVE_IN6ADDR_GLOBAL
  314.   sin_gate.sin6_addr = in6addr_loopback;
  315. #else /*HAVE_IN6ADDR_GLOBAL*/
  316.   inet_pton (AF_INET6, "::1", &sin_gate.sin6_addr);
  317. #endif /*HAVE_IN6ADDR_GLOBAL*/
  318.   gate = 1;
  319. }
  320.     }
  321.   if (cmd == RTM_ADD)
  322.     SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
  323. }
  324.       /* Under kame set interface index to link local address. */
  325. #ifdef KAME
  326. #define SET_IN6_LINKLOCAL_IFINDEX(a, i) 
  327.       do { 
  328. (a).s6_addr[2] = ((i) >> 8) & 0xff; 
  329. (a).s6_addr[3] = (i) & 0xff; 
  330.       } while (0)
  331.       if (gate && IN6_IS_ADDR_LINKLOCAL(&sin_gate.sin6_addr))
  332. SET_IN6_LINKLOCAL_IFINDEX (sin_gate.sin6_addr, ifindex);
  333. #endif /* KAME */
  334.       if (gate && p->prefixlen == 128)
  335. mask = NULL;
  336.       else
  337. {
  338.   masklen2ip6 (p->prefixlen, &sin_mask.sin6_addr);
  339.   sin_mask.sin6_family = AF_UNSPEC;
  340. #ifdef SIN6_LEN
  341.   sin_mask.sin6_len = sin6_masklen (sin_mask.sin6_addr);
  342. #endif /* SIN6_LEN */
  343.   mask = &sin_mask;
  344. }
  345.       error = rtm_write (cmd,
  346. (union sockunion *) &sin_dest,
  347. (union sockunion *) mask,
  348. gate ? (union sockunion *)&sin_gate : NULL,
  349. ifindex,
  350. rib->flags,
  351. rib->metric);
  352. #if 0
  353.       if (error)
  354. {
  355.   zlog_info ("kernel_rtm_ipv6_multipath(): nexthop %d add error=%d.",
  356.     nexthop_num, error);
  357. }
  358. #endif
  359.       nexthop_num++;
  360.     }
  361.   /* If there is no useful nexthop then return. */
  362.   if (nexthop_num == 0)
  363.     {
  364.       if (IS_ZEBRA_DEBUG_KERNEL)
  365. zlog_info ("kernel_rtm_ipv6_multipath(): No useful nexthop.");
  366.       return 0;
  367.     }
  368.   return 0; /*XXX*/
  369. }
  370. int
  371. kernel_add_ipv6 (struct prefix *p, struct rib *rib)
  372. {
  373.   return kernel_rtm_ipv6_multipath (RTM_ADD, p, rib, AF_INET6);
  374. }
  375. int
  376. kernel_delete_ipv6 (struct prefix *p, struct rib *rib)
  377. {
  378.   return kernel_rtm_ipv6_multipath (RTM_DELETE, p, rib, AF_INET6);
  379. }
  380. /* Delete IPv6 route from the kernel. */
  381. int
  382. kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate,
  383.     int index, int flags, int table)
  384. {
  385.   return kernel_rtm_ipv6 (RTM_DELETE, dest, gate, index, flags);
  386. }
  387. #endif /* HAVE_IPV6 */