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

网络

开发平台:

Unix_Linux

  1. /* Router advertisement
  2.  * Copyright (C) 1999 Kunihiro Ishiguro
  3.  *
  4.  * This file is part of GNU Zebra.
  5.  *
  6.  * GNU Zebra is free software; you can redistribute it and/or modify it
  7.  * under the terms of the GNU General Public License as published by the
  8.  * Free Software Foundation; either version 2, or (at your option) any
  9.  * later version.
  10.  *
  11.  * GNU Zebra is distributed in the hope that it will be useful, but
  12.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  * General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with GNU Zebra; see the file COPYING.  If not, write to the Free
  18.  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  19.  * 02111-1307, USA.  
  20.  */
  21. #include <zebra.h>
  22. #include "memory.h"
  23. #include "sockopt.h"
  24. #include "thread.h"
  25. #include "if.h"
  26. #include "log.h"
  27. #include "prefix.h"
  28. #include "linklist.h"
  29. #include "command.h"
  30. #include "zebra/interface.h"
  31. #include "zebra/rtadv.h"
  32. #include "zebra/debug.h"
  33. #if defined (HAVE_IPV6) && defined (RTADV)
  34. /* If RFC2133 definition is used. */
  35. #ifndef IPV6_JOIN_GROUP
  36. #define IPV6_JOIN_GROUP  IPV6_ADD_MEMBERSHIP 
  37. #endif
  38. #ifndef IPV6_LEAVE_GROUP
  39. #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP 
  40. #endif
  41. #define ALLNODE   "ff02::1"
  42. #define ALLROUTER "ff02::2"
  43. enum rtadv_event {RTADV_START, RTADV_STOP, RTADV_TIMER, RTADV_READ};
  44. void rtadv_event (enum rtadv_event, int);
  45. int if_join_all_router (int, struct interface *);
  46. int if_leave_all_router (int, struct interface *);
  47. /* Structure which hold status of router advertisement. */
  48. struct rtadv
  49. {
  50.   int sock;
  51.   int adv_if_count;
  52.   struct thread *ra_read;
  53.   struct thread *ra_timer;
  54. };
  55. struct rtadv *rtadv = NULL;
  56. struct rtadv *
  57. rtadv_new ()
  58. {
  59.   struct rtadv *new;
  60.   new = XMALLOC (MTYPE_TMP, sizeof (struct rtadv));
  61.   memset (new, 0, sizeof (struct rtadv));
  62.   return new;
  63. }
  64. void
  65. rtadv_free (struct rtadv *rtadv)
  66. {
  67.   XFREE (MTYPE_TMP, rtadv);
  68. }
  69. int
  70. rtadv_recv_packet (int sock, u_char *buf, int buflen,
  71.    struct sockaddr_in6 *from, unsigned int *ifindex,
  72.    int *hoplimit)
  73. {
  74.   int ret;
  75.   struct msghdr msg;
  76.   struct iovec iov;
  77.   struct cmsghdr  *cmsgptr;
  78.   struct in6_addr dst;
  79.   char adata[1024];
  80.   /* Fill in message and iovec. */
  81.   msg.msg_name = (void *) from;
  82.   msg.msg_namelen = sizeof (struct sockaddr_in6);
  83.   msg.msg_iov = &iov;
  84.   msg.msg_iovlen = 1;
  85.   msg.msg_control = (void *) adata;
  86.   msg.msg_controllen = sizeof adata;
  87.   iov.iov_base = buf;
  88.   iov.iov_len = buflen;
  89.   /* If recvmsg fail return minus value. */
  90.   ret = recvmsg (sock, &msg, 0);
  91.   if (ret < 0)
  92.     return ret;
  93.   for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
  94.        cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) 
  95.     {
  96.       /* I want interface index which this packet comes from. */
  97.       if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
  98.   cmsgptr->cmsg_type == IPV6_PKTINFO) 
  99. {
  100.   struct in6_pktinfo *ptr;
  101.   
  102.   ptr = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
  103.   *ifindex = ptr->ipi6_ifindex;
  104.   memcpy(&dst, &ptr->ipi6_addr, sizeof(ptr->ipi6_addr));
  105.         }
  106.       /* Incoming packet's hop limit. */
  107.       if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
  108.   cmsgptr->cmsg_type == IPV6_HOPLIMIT)
  109. *hoplimit = *((int *) CMSG_DATA (cmsgptr));
  110.     }
  111.   return ret;
  112. }
  113. #define RTADV_MSG_SIZE 4096
  114. /* Send router advertisement packet. */
  115. void
  116. rtadv_send_packet (int sock, struct interface *ifp)
  117. {
  118.   struct msghdr msg;
  119.   struct iovec iov;
  120.   struct cmsghdr  *cmsgptr;
  121.   struct in6_pktinfo *pkt;
  122.   struct sockaddr_in6 addr;
  123. #ifdef HAVE_SOCKADDR_DL
  124.   struct sockaddr_dl *sdl;
  125. #endif /* HAVE_SOCKADDR_DL */
  126.   char adata [sizeof (struct cmsghdr) + sizeof (struct in6_pktinfo)];
  127.   unsigned char buf[RTADV_MSG_SIZE];
  128.   struct nd_router_advert *rtadv;
  129.   int ret;
  130.   int len = 0;
  131.   struct zebra_if *zif;
  132.   u_char all_nodes_addr[] = {0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
  133.   listnode node;
  134.   /* Logging of packet. */
  135.   if (IS_ZEBRA_DEBUG_PACKET)
  136.     zlog_info ("Router advertisement send to %s", ifp->name);
  137.   /* Fill in sockaddr_in6. */
  138.   memset (&addr, 0, sizeof (struct sockaddr_in6));
  139.   addr.sin6_family = AF_INET6;
  140. #ifdef SIN6_LEN
  141.   addr.sin6_len = sizeof (struct sockaddr_in6);
  142. #endif /* SIN6_LEN */
  143.   addr.sin6_port = htons (IPPROTO_ICMPV6);
  144.   memcpy (&addr.sin6_addr, all_nodes_addr, sizeof (struct in6_addr));
  145.   /* Fetch interface information. */
  146.   zif = ifp->info;
  147.   /* Make router advertisement message. */
  148.   rtadv = (struct nd_router_advert *) buf;
  149.   rtadv->nd_ra_type = ND_ROUTER_ADVERT;
  150.   rtadv->nd_ra_code = 0;
  151.   rtadv->nd_ra_cksum = 0;
  152.   rtadv->nd_ra_curhoplimit = 64;
  153.   rtadv->nd_ra_flags_reserved = 0;
  154.   if (zif->rtadv.AdvManagedFlag)
  155.     rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
  156.   if (zif->rtadv.AdvOtherConfigFlag)
  157.     rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
  158.   rtadv->nd_ra_router_lifetime = htons (zif->rtadv.AdvDefaultLifetime);
  159.   rtadv->nd_ra_reachable = htonl (zif->rtadv.AdvReachableTime);
  160.   rtadv->nd_ra_retransmit = htonl (0);
  161.   len = sizeof (struct nd_router_advert);
  162.   /* Fill in prefix. */
  163.   for (node = listhead (zif->rtadv.AdvPrefixList); node; node = nextnode (node))
  164.     {
  165.       struct nd_opt_prefix_info *pinfo;
  166.       struct rtadv_prefix *rprefix;
  167.       rprefix = getdata (node);
  168.       pinfo = (struct nd_opt_prefix_info *) (buf + len);
  169.       pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
  170.       pinfo->nd_opt_pi_len = 4;
  171.       pinfo->nd_opt_pi_prefix_len = rprefix->prefix.prefixlen;
  172.       pinfo->nd_opt_pi_flags_reserved = 0;
  173.       if (rprefix->AdvOnLinkFlag)
  174. pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_ONLINK;
  175.       if (rprefix->AdvAutonomousFlag)
  176. pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO;
  177.       pinfo->nd_opt_pi_valid_time = htonl (rprefix->AdvValidLifetime);
  178.       pinfo->nd_opt_pi_preferred_time = htonl (rprefix->AdvPreferredLifetime);
  179.       pinfo->nd_opt_pi_reserved2 = 0;
  180.       memcpy (&pinfo->nd_opt_pi_prefix, &rprefix->prefix.u.prefix6,
  181.       sizeof (struct in6_addr));
  182. #ifdef DEBUG
  183.       {
  184. u_char buf[INET6_ADDRSTRLEN];
  185. zlog_info ("DEBUG %s", inet_ntop (AF_INET6, &pinfo->nd_opt_pi_prefix, buf, INET6_ADDRSTRLEN));
  186.       }
  187. #endif /* DEBUG */
  188.       len += sizeof (struct nd_opt_prefix_info);
  189.     }
  190.   /* Hardware address. */
  191. #ifdef HAVE_SOCKADDR_DL
  192.   sdl = &ifp->sdl;
  193.   if (sdl != NULL && sdl->sdl_alen != 0)
  194.     {
  195.       buf[len++] = ND_OPT_SOURCE_LINKADDR;
  196.       buf[len++] = (sdl->sdl_alen + 2) >> 3;
  197.       memcpy (buf + len, LLADDR (sdl), sdl->sdl_alen);
  198.       len += sdl->sdl_alen;
  199.     }
  200. #else
  201.   if (ifp->hw_addr_len != 0)
  202.     {
  203.       buf[len++] = ND_OPT_SOURCE_LINKADDR;
  204.       buf[len++] = (ifp->hw_addr_len + 2) >> 3;
  205.       memcpy (buf + len, ifp->hw_addr, ifp->hw_addr_len);
  206.       len += ifp->hw_addr_len;
  207.     }
  208. #endif /* HAVE_SOCKADDR_DL */
  209.   msg.msg_name = (void *) &addr;
  210.   msg.msg_namelen = sizeof (struct sockaddr_in6);
  211.   msg.msg_iov = &iov;
  212.   msg.msg_iovlen = 1;
  213.   msg.msg_control = (void *) adata;
  214.   msg.msg_controllen = sizeof adata;
  215.   iov.iov_base = buf;
  216.   iov.iov_len = len;
  217.   cmsgptr = (struct cmsghdr *)adata;
  218.   cmsgptr->cmsg_len = sizeof adata;
  219.   cmsgptr->cmsg_level = IPPROTO_IPV6;
  220.   cmsgptr->cmsg_type = IPV6_PKTINFO;
  221.   pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
  222.   memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr));
  223.   pkt->ipi6_ifindex = ifp->ifindex;
  224.   ret = sendmsg (sock, &msg, 0);
  225.   if (ret <0)
  226.     perror ("sendmsg");
  227. }
  228. int
  229. rtadv_timer (struct thread *thread)
  230. {
  231.   listnode node;
  232.   struct interface *ifp;
  233.   struct zebra_if *zif;
  234.   rtadv->ra_timer = NULL;
  235.   rtadv_event (RTADV_TIMER, 1);
  236.   for (node = listhead (iflist); node; nextnode (node))
  237.     {
  238.       ifp = getdata (node);
  239.       if (if_is_loopback (ifp))
  240. continue;
  241.       zif = ifp->info;
  242.       if (zif->rtadv.AdvSendAdvertisements)
  243. if (--zif->rtadv.AdvIntervalTimer <= 0)
  244.   {
  245.     zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
  246.     rtadv_send_packet (rtadv->sock, ifp);
  247.   }
  248.     }
  249.   return 0;
  250. }
  251. void
  252. rtadv_process_solicit (struct interface *ifp)
  253. {
  254.   zlog_info ("Router solicitation received on %s", ifp->name);
  255.   rtadv_send_packet (rtadv->sock, ifp);
  256. }
  257. void
  258. rtadv_process_advert ()
  259. {
  260.   zlog_info ("Router advertisement received");
  261. }
  262. void
  263. rtadv_process_packet (u_char *buf, int len, unsigned int ifindex, int hoplimit)
  264. {
  265.   struct icmp6_hdr *icmph;
  266.   struct interface *ifp;
  267.   struct zebra_if *zif;
  268.   /* Interface search. */
  269.   ifp = if_lookup_by_index (ifindex);
  270.   if (ifp == NULL)
  271.     {
  272.       zlog_warn ("Unknown interface index: %d", ifindex);
  273.       return;
  274.     }
  275.   if (if_is_loopback (ifp))
  276.     return;
  277.   /* Check interface configuration. */
  278.   zif = ifp->info;
  279.   if (! zif->rtadv.AdvSendAdvertisements)
  280.     return;
  281.   /* ICMP message length check. */
  282.   if (len < sizeof (struct icmp6_hdr))
  283.     {
  284.       zlog_warn ("Invalid ICMPV6 packet length: %d", len);
  285.       return;
  286.     }
  287.   icmph = (struct icmp6_hdr *) buf;
  288.   /* ICMP message type check. */
  289.   if (icmph->icmp6_type != ND_ROUTER_SOLICIT &&
  290.       icmph->icmp6_type != ND_ROUTER_ADVERT)
  291.     {
  292.       zlog_warn ("Unwanted ICMPV6 message type: %d", icmph->icmp6_type);
  293.       return;
  294.     }
  295.   /* Hoplimit check. */
  296.   if (hoplimit >= 0 && hoplimit != 255)
  297.     {
  298.       zlog_warn ("Invalid hoplimit %d for router advertisement ICMP packet",
  299.  hoplimit);
  300.       return;
  301.     }
  302.   /* Check ICMP message type. */
  303.   if (icmph->icmp6_type == ND_ROUTER_SOLICIT)
  304.     rtadv_process_solicit (ifp);
  305.   else if (icmph->icmp6_type == ND_ROUTER_ADVERT)
  306.     rtadv_process_advert ();
  307.   return;
  308. }
  309. int
  310. rtadv_read (struct thread *thread)
  311. {
  312.   int sock;
  313.   int len;
  314.   u_char buf[RTADV_MSG_SIZE];
  315.   struct sockaddr_in6 from;
  316.   unsigned int ifindex;
  317.   int hoplimit = -1;
  318.   sock = THREAD_FD (thread);
  319.   rtadv->ra_read = NULL;
  320.   /* Register myself. */
  321.   rtadv_event (RTADV_READ, sock);
  322.   len = rtadv_recv_packet (sock, buf, BUFSIZ, &from, &ifindex, &hoplimit);
  323.   if (len < 0) 
  324.     {
  325.       zlog_warn ("router solicitation recv failed: %s.", strerror (errno));
  326.       return len;
  327.     }
  328.   rtadv_process_packet (buf, len, ifindex, hoplimit);
  329.   return 0;
  330. }
  331. int
  332. rtadv_make_socket (void)
  333. {
  334.   int sock;
  335.   int ret;
  336.   struct icmp6_filter filter;
  337.   sock = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
  338.   /* When we can't make ICMPV6 socket simply back.  Router
  339.      advertisement feature will not be supported. */
  340.   if (sock < 0)
  341.     return -1;
  342.   ret = setsockopt_ipv6_pktinfo (sock, 1);
  343.   if (ret < 0)
  344.     return ret;
  345.   ret = setsockopt_ipv6_checksum (sock, 2);
  346.   if (ret < 0)
  347.     return ret;
  348.   ret = setsockopt_ipv6_multicast_loop (sock, 0);
  349.   if (ret < 0)
  350.     return ret;
  351.   ret = setsockopt_ipv6_unicast_hops (sock, 255);
  352.   if (ret < 0)
  353.     return ret;
  354.   ret = setsockopt_ipv6_multicast_hops (sock, 255);
  355.   if (ret < 0)
  356.     return ret;
  357.   ret = setsockopt_ipv6_hoplimit (sock, 1);
  358.   if (ret < 0)
  359.     return ret;
  360.   ICMP6_FILTER_SETBLOCKALL(&filter);
  361.   ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT, &filter);
  362.   ICMP6_FILTER_SETPASS (ND_ROUTER_ADVERT, &filter);
  363.   ret = setsockopt (sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
  364.     sizeof (struct icmp6_filter));
  365.   if (ret < 0)
  366.     {
  367.       zlog_info ("ICMP6_FILTER set fail: %s", strerror (errno));
  368.       return ret;
  369.     }
  370.   return sock;
  371. }
  372. struct rtadv_prefix *
  373. rtadv_prefix_new ()
  374. {
  375.   struct rtadv_prefix *new;
  376.   new = XMALLOC (MTYPE_RTADV_PREFIX, sizeof (struct rtadv_prefix));
  377.   memset (new, 0, sizeof (struct rtadv_prefix));
  378.   return new;
  379. }
  380. void
  381. rtadv_prefix_free (struct rtadv_prefix *rtadv_prefix)
  382. {
  383.   XFREE (MTYPE_RTADV_PREFIX, rtadv_prefix);
  384. }
  385. struct rtadv_prefix *
  386. rtadv_prefix_lookup (list rplist, struct prefix *p)
  387. {
  388.   listnode node;
  389.   struct rtadv_prefix *rprefix;
  390.   for (node = listhead (rplist); node; node = nextnode (node))
  391.     {
  392.       rprefix = getdata (node);
  393.       if (prefix_same (&rprefix->prefix, p))
  394. return rprefix;
  395.     }
  396.   return NULL;
  397. }
  398. struct rtadv_prefix *
  399. rtadv_prefix_get (list rplist, struct prefix *p)
  400. {
  401.   struct rtadv_prefix *rprefix;
  402.   
  403.   rprefix = rtadv_prefix_lookup (rplist, p);
  404.   if (rprefix)
  405.     return rprefix;
  406.   rprefix = rtadv_prefix_new ();
  407.   memcpy (&rprefix->prefix, p, sizeof (struct prefix));
  408.   listnode_add (rplist, rprefix);
  409.   return rprefix;
  410. }
  411. void
  412. rtadv_prefix_set (struct zebra_if *zif, struct rtadv_prefix *rp)
  413. {
  414.   struct rtadv_prefix *rprefix;
  415.   
  416.   rprefix = rtadv_prefix_get (zif->rtadv.AdvPrefixList, &rp->prefix);
  417.   /* Set parameters. */
  418.   rprefix->AdvValidLifetime = rp->AdvValidLifetime;
  419.   rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime;
  420.   rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag;
  421.   rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag;
  422. }
  423. int
  424. rtadv_prefix_reset (struct zebra_if *zif, struct rtadv_prefix *rp)
  425. {
  426.   struct rtadv_prefix *rprefix;
  427.   
  428.   rprefix = rtadv_prefix_lookup (zif->rtadv.AdvPrefixList, &rp->prefix);
  429.   if (rprefix != NULL)
  430.     {
  431.       listnode_delete (zif->rtadv.AdvPrefixList, (void *) rprefix);
  432.       rtadv_prefix_free (rprefix);
  433.       return 1;
  434.     }
  435.   else
  436.     return 0;
  437. }
  438. DEFUN (ipv6_nd_suppress_ra,
  439.        ipv6_nd_suppress_ra_cmd,
  440.        "ipv6 nd suppress-ra",
  441.        IP_STR
  442.        "Neighbor discoveryn"
  443.        "Suppress Router Advertisementn")
  444. {
  445.   struct interface *ifp;
  446.   struct zebra_if *zif;
  447.   ifp = vty->index;
  448.   zif = ifp->info;
  449.   if (if_is_loopback (ifp))
  450.     {
  451.       vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
  452.       return CMD_WARNING;
  453.     }
  454.   if (zif->rtadv.AdvSendAdvertisements)
  455.     {
  456.       zif->rtadv.AdvSendAdvertisements = 0;
  457.       zif->rtadv.AdvIntervalTimer = 0;
  458.       rtadv->adv_if_count--;
  459.       if_leave_all_router (rtadv->sock, ifp);
  460.       if (rtadv->adv_if_count == 0)
  461. rtadv_event (RTADV_STOP, 0);
  462.     }
  463.   return CMD_SUCCESS;
  464. }
  465. ALIAS (ipv6_nd_suppress_ra,
  466.        no_ipv6_nd_send_ra_cmd,
  467.        "no ipv6 nd send-ra",
  468.        NO_STR
  469.        IP_STR
  470.        "Neighbor discoveryn"
  471.        "Send Router Advertisementn");
  472. DEFUN (no_ipv6_nd_suppress_ra,
  473.        no_ipv6_nd_suppress_ra_cmd,
  474.        "no ipv6 nd suppress-ra",
  475.        NO_STR
  476.        IP_STR
  477.        "Neighbor discoveryn"
  478.        "Suppress Router Advertisementn")
  479. {
  480.   struct interface *ifp;
  481.   struct zebra_if *zif;
  482.   ifp = vty->index;
  483.   zif = ifp->info;
  484.   if (if_is_loopback (ifp))
  485.     {
  486.       vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
  487.       return CMD_WARNING;
  488.     }
  489.   if (! zif->rtadv.AdvSendAdvertisements)
  490.     {
  491.       zif->rtadv.AdvSendAdvertisements = 1;
  492.       zif->rtadv.AdvIntervalTimer = 0;
  493.       rtadv->adv_if_count++;
  494.       if_join_all_router (rtadv->sock, ifp);
  495.       if (rtadv->adv_if_count == 1)
  496. rtadv_event (RTADV_START, rtadv->sock);
  497.     }
  498.   return CMD_SUCCESS;
  499. }
  500. ALIAS (no_ipv6_nd_suppress_ra,
  501.        ipv6_nd_send_ra_cmd,
  502.        "ipv6 nd send-ra",
  503.        IP_STR
  504.        "Neighbor discoveryn"
  505.        "Send Router Advertisementn");
  506. DEFUN (ipv6_nd_ra_interval,
  507.        ipv6_nd_ra_interval_cmd,
  508.        "ipv6 nd ra-interval SECONDS",
  509.        IP_STR
  510.        "Neighbor discoveryn"
  511.        "Router Advertisement intervaln"
  512.        "Router Advertisement interval in secondsn")
  513. {
  514.   int interval;
  515.   struct interface *ifp;
  516.   struct zebra_if *zif;
  517.   ifp = (struct interface *) vty->index;
  518.   zif = ifp->info;
  519.   interval = atoi (argv[0]);
  520.   if (interval < 0)
  521.     {
  522.       vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);
  523.       return CMD_WARNING;
  524.     }
  525.   zif->rtadv.MaxRtrAdvInterval = interval;
  526.   zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
  527.   zif->rtadv.AdvIntervalTimer = 0;
  528.   return CMD_SUCCESS;
  529. }
  530. DEFUN (no_ipv6_nd_ra_interval,
  531.        no_ipv6_nd_ra_interval_cmd,
  532.        "no ipv6 nd ra-interval",
  533.        NO_STR
  534.        IP_STR
  535.        "Neighbor discoveryn"
  536.        "Router Advertisement intervaln")
  537. {
  538.   struct interface *ifp;
  539.   struct zebra_if *zif;
  540.   ifp = (struct interface *) vty->index;
  541.   zif = ifp->info;
  542.   zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
  543.   zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
  544.   zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
  545.   return CMD_SUCCESS;
  546. }
  547. DEFUN (ipv6_nd_ra_lifetime,
  548.        ipv6_nd_ra_lifetime_cmd,
  549.        "ipv6 nd ra-lifetime SECONDS",
  550.        IP_STR
  551.        "Neighbor discoveryn"
  552.        "Router lifetimen"
  553.        "Router lifetime in secondsn")
  554. {
  555.   int lifetime;
  556.   struct interface *ifp;
  557.   struct zebra_if *zif;
  558.   ifp = (struct interface *) vty->index;
  559.   zif = ifp->info;
  560.   lifetime = atoi (argv[0]);
  561.   if (lifetime < 0 || lifetime > 0xffff)
  562.     {
  563.       vty_out (vty, "Invalid Router Lifetime%s", VTY_NEWLINE);
  564.       return CMD_WARNING;
  565.     }
  566.   zif->rtadv.AdvDefaultLifetime = lifetime;
  567.   return CMD_SUCCESS;
  568. }
  569. DEFUN (no_ipv6_nd_ra_lifetime,
  570.        no_ipv6_nd_ra_lifetime_cmd,
  571.        "no ipv6 nd ra-lifetime",
  572.        NO_STR
  573.        IP_STR
  574.        "Neighbor discoveryn"
  575.        "Router lifetimen")
  576. {
  577.   struct interface *ifp;
  578.   struct zebra_if *zif;
  579.   ifp = (struct interface *) vty->index;
  580.   zif = ifp->info;
  581.   zif->rtadv.AdvDefaultLifetime = RTADV_ADV_DEFAULT_LIFETIME;
  582.   return CMD_SUCCESS;
  583. }
  584. DEFUN (ipv6_nd_reachable_time,
  585.        ipv6_nd_reachable_time_cmd,
  586.        "ipv6 nd reachable-time MILLISECONDS",
  587.        IP_STR
  588.        "Neighbor discoveryn"
  589.        "Reachable timen"
  590.        "Reachable time in millisecondsn")
  591. {
  592.   u_int32_t rtime;
  593.   struct interface *ifp;
  594.   struct zebra_if *zif;
  595.   ifp = (struct interface *) vty->index;
  596.   zif = ifp->info;
  597.   rtime = (u_int32_t) atol (argv[0]);
  598.   if (rtime > RTADV_MAX_REACHABLE_TIME)
  599.     {
  600.       vty_out (vty, "Invalid Reachable time%s", VTY_NEWLINE);
  601.       return CMD_WARNING;
  602.     }
  603.   zif->rtadv.AdvReachableTime = rtime;
  604.   return CMD_SUCCESS;
  605. }
  606. DEFUN (no_ipv6_nd_reachable_time,
  607.        no_ipv6_nd_reachable_time_cmd,
  608.        "no ipv6 nd reachable-time",
  609.        NO_STR
  610.        IP_STR
  611.        "Neighbor discoveryn"
  612.        "Reachable timen")
  613. {
  614.   struct interface *ifp;
  615.   struct zebra_if *zif;
  616.   ifp = (struct interface *) vty->index;
  617.   zif = ifp->info;
  618.   zif->rtadv.AdvReachableTime = 0;
  619.   return CMD_SUCCESS;
  620. }
  621. DEFUN (ipv6_nd_managed_config_flag,
  622.        ipv6_nd_managed_config_flag_cmd,
  623.        "ipv6 nd managed-config-flag",
  624.        IP_STR
  625.        "Neighbor discoveryn"
  626.        "Managed address configuration flagn")
  627. {
  628.   struct interface *ifp;
  629.   struct zebra_if *zif;
  630.   ifp = (struct interface *) vty->index;
  631.   zif = ifp->info;
  632.   zif->rtadv.AdvManagedFlag = 1;
  633.   return CMD_SUCCESS;
  634. }
  635. DEFUN (no_ipv6_nd_managed_config_flag,
  636.        no_ipv6_nd_managed_config_flag_cmd,
  637.        "no ipv6 nd managed-config-flag",
  638.        NO_STR
  639.        IP_STR
  640.        "Neighbor discoveryn"
  641.        "Managed address configuration flagn")
  642. {
  643.   struct interface *ifp;
  644.   struct zebra_if *zif;
  645.   ifp = (struct interface *) vty->index;
  646.   zif = ifp->info;
  647.   zif->rtadv.AdvManagedFlag = 0;
  648.   return CMD_SUCCESS;
  649. }
  650. DEFUN (ipv6_nd_other_config_flag,
  651.        ipv6_nd_other_config_flag_cmd,
  652.        "ipv6 nd other-config-flag",
  653.        IP_STR
  654.        "Neighbor discoveryn"
  655.        "Other statefull configuration flagn")
  656. {
  657.   struct interface *ifp;
  658.   struct zebra_if *zif;
  659.   ifp = (struct interface *) vty->index;
  660.   zif = ifp->info;
  661.   zif->rtadv.AdvOtherConfigFlag = 1;
  662.   return CMD_SUCCESS;
  663. }
  664. DEFUN (no_ipv6_nd_other_config_flag,
  665.        no_ipv6_nd_other_config_flag_cmd,
  666.        "no ipv6 nd other-config-flag",
  667.        NO_STR
  668.        IP_STR
  669.        "Neighbor discoveryn"
  670.        "Other statefull configuration flagn")
  671. {
  672.   struct interface *ifp;
  673.   struct zebra_if *zif;
  674.   ifp = (struct interface *) vty->index;
  675.   zif = ifp->info;
  676.   zif->rtadv.AdvOtherConfigFlag = 0;
  677.   return CMD_SUCCESS;
  678. }
  679. DEFUN (ipv6_nd_prefix_advertisement,
  680.        ipv6_nd_prefix_advertisement_cmd,
  681.        "ipv6 nd prefix-advertisement IPV6PREFIX VALID PREFERRED [onlink] [autoconfig]",
  682.        IP_STR
  683.        "Neighbor discoveryn"
  684.        "Prefix informationn"
  685.        "IPv6 prefixn"
  686.        "Valid lifetime in secondsn"
  687.        "Preferred lifetime in secondsn"
  688.        "On link flagn"
  689.        "Autonomous address-configuration flagn")
  690. {
  691.   int i;
  692.   int ret;
  693.   struct interface *ifp;
  694.   struct zebra_if *zebra_if;
  695.   struct rtadv_prefix rp;
  696.   ifp = (struct interface *) vty->index;
  697.   zebra_if = ifp->info;
  698.   ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
  699.   if (!ret)
  700.     {
  701.       vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
  702.       return CMD_WARNING;
  703.     }
  704.   if (argc == 1)
  705.     {
  706.       rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
  707.       rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
  708.       rp.AdvOnLinkFlag = 1;
  709.       rp.AdvAutonomousFlag = 1;
  710.     }
  711.   else
  712.     {
  713.       rp.AdvValidLifetime = (u_int32_t) atol (argv[1]);
  714.       rp.AdvPreferredLifetime = (u_int32_t) atol (argv[2]);
  715.       if (rp.AdvPreferredLifetime > rp.AdvValidLifetime)
  716. {
  717.   vty_out (vty, "Invalid preferred lifetime%s", VTY_NEWLINE);
  718.   return CMD_WARNING;
  719. }
  720.       rp.AdvOnLinkFlag = 0;
  721.       rp.AdvAutonomousFlag = 0;
  722.       for (i = 3; i < argc; i++)
  723. {
  724.   if (! strcmp (argv[i], "onlink"))
  725.     rp.AdvOnLinkFlag = 1;
  726.   else if (! strcmp (argv[i], "autoconfig"))
  727.     rp.AdvAutonomousFlag = 1;
  728. }
  729.     }
  730.   rtadv_prefix_set (zebra_if, &rp);
  731.   return CMD_SUCCESS;
  732. }
  733. ALIAS (ipv6_nd_prefix_advertisement,
  734.        ipv6_nd_prefix_advertisement_no_val_cmd,
  735.        "ipv6 nd prefix-advertisement IPV6PREFIX",
  736.        IP_STR
  737.        "Neighbor discoveryn"
  738.        "Prefix informationn"
  739.        "IPv6 prefixn");
  740. DEFUN (no_ipv6_nd_prefix_advertisement,
  741.        no_ipv6_nd_prefix_advertisement_cmd,
  742.        "no ipv6 nd prefix-advertisement IPV6PREFIX",
  743.        NO_STR
  744.        IP_STR
  745.        "Neighbor discoveryn"
  746.        "Prefix informationn"
  747.        "IPv6 prefixn")
  748. {
  749.   int ret;
  750.   struct interface *ifp;
  751.   struct zebra_if *zebra_if;
  752.   struct rtadv_prefix rp;
  753.   ifp = (struct interface *) vty->index;
  754.   zebra_if = ifp->info;
  755.   ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
  756.   if (!ret)
  757.     {
  758.       vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
  759.       return CMD_WARNING;
  760.     }
  761.   ret = rtadv_prefix_reset (zebra_if, &rp);
  762.   if (!ret)
  763.     {
  764.       vty_out (vty, "Non-exist IPv6 prefix%s", VTY_NEWLINE);
  765.       return CMD_WARNING;
  766.     }
  767.   return CMD_SUCCESS;
  768. }
  769. /* Write configuration about router advertisement. */
  770. void
  771. rtadv_config_write (struct vty *vty, struct interface *ifp)
  772. {
  773.   struct zebra_if *zif;
  774.   listnode node;
  775.   struct rtadv_prefix *rprefix;
  776.   u_char buf[INET6_ADDRSTRLEN];
  777.   if (! rtadv)
  778.     return;
  779.   zif = ifp->info;
  780.   if (! if_is_loopback (ifp))
  781.     {
  782.       if (zif->rtadv.AdvSendAdvertisements)
  783. vty_out (vty, " no ipv6 nd suppress-ra%s", VTY_NEWLINE);
  784.       else
  785. vty_out (vty, " ipv6 nd suppress-ra%s", VTY_NEWLINE);
  786.     }
  787.   if (zif->rtadv.MaxRtrAdvInterval != RTADV_MAX_RTR_ADV_INTERVAL)
  788.     vty_out (vty, " ipv6 nd ra-interval %d%s", zif->rtadv.MaxRtrAdvInterval,
  789.      VTY_NEWLINE);
  790.   if (zif->rtadv.AdvDefaultLifetime != RTADV_ADV_DEFAULT_LIFETIME)
  791.     vty_out (vty, " ipv6 nd ra-lifetime %d%s", zif->rtadv.AdvDefaultLifetime,
  792.      VTY_NEWLINE);
  793.   if (zif->rtadv.AdvReachableTime)
  794.     vty_out (vty, " ipv6 nd reachable-time %d%s", zif->rtadv.AdvReachableTime,
  795.      VTY_NEWLINE);
  796.   if (zif->rtadv.AdvManagedFlag)
  797.     vty_out (vty, " ipv6 nd managed-config-flag%s", VTY_NEWLINE);
  798.   if (zif->rtadv.AdvOtherConfigFlag)
  799.     vty_out (vty, " ipv6 nd other-config-flag%s", VTY_NEWLINE);
  800.   for (node = listhead(zif->rtadv.AdvPrefixList); node; node = nextnode (node))
  801.     {
  802.       rprefix = getdata (node);
  803.       vty_out (vty, " ipv6 nd prefix-advertisement %s/%d %d %d",
  804.        inet_ntop (AF_INET6, &rprefix->prefix.u.prefix6, 
  805.   buf, INET6_ADDRSTRLEN),
  806.        rprefix->prefix.prefixlen,
  807.        rprefix->AdvValidLifetime,
  808.        rprefix->AdvPreferredLifetime);
  809.       if (rprefix->AdvOnLinkFlag)
  810. vty_out (vty, " onlink");
  811.       if (rprefix->AdvAutonomousFlag)
  812. vty_out (vty, " autoconfig");
  813.       vty_out (vty, "%s", VTY_NEWLINE);
  814.     }
  815. }
  816. extern struct thread_master *master;
  817. void
  818. rtadv_event (enum rtadv_event event, int val)
  819. {
  820.   switch (event)
  821.     {
  822.     case RTADV_START:
  823.       if (! rtadv->ra_read)
  824. rtadv->ra_read = thread_add_read (master, rtadv_read, NULL, val);
  825.       if (! rtadv->ra_timer)
  826. rtadv->ra_timer = thread_add_event (master, rtadv_timer, NULL, 0);
  827.       break;
  828.     case RTADV_STOP:
  829.       if (rtadv->ra_timer)
  830. {
  831.   thread_cancel (rtadv->ra_timer);
  832.   rtadv->ra_timer = NULL;
  833. }
  834.       if (rtadv->ra_read)
  835. {
  836.   thread_cancel (rtadv->ra_read);
  837.   rtadv->ra_read = NULL;
  838. }
  839.       break;
  840.     case RTADV_TIMER:
  841.       if (! rtadv->ra_timer)
  842. rtadv->ra_timer = thread_add_timer (master, rtadv_timer, NULL, val);
  843.       break;
  844.     case RTADV_READ:
  845.       if (! rtadv->ra_read)
  846. rtadv->ra_read = thread_add_read (master, rtadv_read, NULL, val);
  847.       break;
  848.     default:
  849.       break;
  850.     }
  851.   return;
  852. }
  853. void
  854. rtadv_init ()
  855. {
  856.   int sock;
  857.   sock = rtadv_make_socket ();
  858.   if (sock < 0)
  859.     return;
  860.   rtadv = rtadv_new ();
  861.   rtadv->sock = sock;
  862.   install_element (INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
  863.   install_element (INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
  864.   install_element (INTERFACE_NODE, &ipv6_nd_send_ra_cmd);
  865.   install_element (INTERFACE_NODE, &no_ipv6_nd_send_ra_cmd);
  866.   install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
  867.   install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
  868.   install_element (INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
  869.   install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
  870.   install_element (INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
  871.   install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
  872.   install_element (INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
  873.   install_element (INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);
  874.   install_element (INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
  875.   install_element (INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd);
  876.   install_element (INTERFACE_NODE, &ipv6_nd_prefix_advertisement_cmd);
  877.   install_element (INTERFACE_NODE, &ipv6_nd_prefix_advertisement_no_val_cmd);
  878.   install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_advertisement_cmd);
  879. }
  880. int
  881. if_join_all_router (int sock, struct interface *ifp)
  882. {
  883.   int ret;
  884.   struct ipv6_mreq mreq;
  885.   memset (&mreq, 0, sizeof (struct ipv6_mreq));
  886.   inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
  887.   mreq.ipv6mr_interface = ifp->ifindex;
  888.   ret = setsockopt (sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, 
  889.     (char *) &mreq, sizeof mreq);
  890.   if (ret < 0)
  891.     zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", strerror (errno));
  892.   zlog_info ("rtadv: %s join to all-routers multicast group", ifp->name);
  893.   return 0;
  894. }
  895. int
  896. if_leave_all_router (int sock, struct interface *ifp)
  897. {
  898.   int ret;
  899.   struct ipv6_mreq mreq;
  900.   memset (&mreq, 0, sizeof (struct ipv6_mreq));
  901.   inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
  902.   mreq.ipv6mr_interface = ifp->ifindex;
  903.   ret = setsockopt (sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, 
  904.     (char *) &mreq, sizeof mreq);
  905.   if (ret < 0)
  906.     zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s", strerror (errno));
  907.   zlog_info ("rtadv: %s leave from all-routers multicast group", ifp->name);
  908.   return 0;
  909. }
  910. #else
  911. void
  912. rtadv_init ()
  913. {
  914.   /* Empty.*/;
  915. }
  916. #endif /* RTADV && HAVE_IPV6 */