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

网络

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright (C) 2003 Yasuhiro Ohara
  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 
  18.  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 
  19.  * Boston, MA 02111-1307, USA.  
  20.  */
  21. #include <zebra.h>
  22. #include "log.h"
  23. #include "memory.h"
  24. #include "sockunion.h"
  25. #include "ospf6_proto.h"
  26. #include "ospf6_network.h"
  27. int  ospf6_sock;
  28. struct in6_addr allspfrouters6;
  29. struct in6_addr alldrouters6;
  30. /* setsockopt ReUseAddr to on */
  31. void
  32. ospf6_set_reuseaddr ()
  33. {
  34.   u_int on = 0;
  35.   if (setsockopt (ospf6_sock, SOL_SOCKET, SO_REUSEADDR, &on,
  36.                   sizeof (u_int)) < 0)
  37.     zlog_warn ("Network: set SO_REUSEADDR failed: %s", strerror (errno));
  38. }
  39. /* setsockopt MulticastLoop to off */
  40. void
  41. ospf6_reset_mcastloop ()
  42. {
  43.   u_int off = 0;
  44.   if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
  45.                   &off, sizeof (u_int)) < 0)
  46.     zlog_warn ("Network: reset IPV6_MULTICAST_LOOP failed: %s",
  47.                strerror (errno));
  48. }
  49. void
  50. ospf6_set_pktinfo ()
  51. {
  52.   u_int on = 1;
  53. #ifdef IPV6_RECVPKTINFO /*2292bis-01*/
  54.   if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_RECVPKTINFO,
  55.                   &on, sizeof (u_int)) < 0)
  56.     zlog_warn ("Network: set IPV6_RECVPKTINFO failed: %s", strerror (errno));
  57. #else /*RFC2292*/
  58.   if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_PKTINFO,
  59.                   &on, sizeof (u_int)) < 0)
  60.     zlog_warn ("Network: set IPV6_PKTINFO failed: %s", strerror (errno));
  61. #endif
  62. }
  63. void
  64. ospf6_set_checksum ()
  65. {
  66.   int offset = 12;
  67. #ifndef DISABLE_IPV6_CHECKSUM
  68.   if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_CHECKSUM,
  69.                   &offset, sizeof (offset)) < 0)
  70.     zlog_warn ("Network: set IPV6_CHECKSUM failed: %s", strerror (errno));
  71. #else
  72.   zlog_warn ("Network: Don't set IPV6_CHECKSUM");
  73. #endif /* DISABLE_IPV6_CHECKSUM */
  74. }
  75. /* Make ospf6d's server socket. */
  76. int
  77. ospf6_serv_sock ()
  78. {
  79.   ospf6_sock = socket (AF_INET6, SOCK_RAW, IPPROTO_OSPFIGP);
  80.   if (ospf6_sock < 0)
  81.     {
  82.       zlog_warn ("Network: can't create OSPF6 socket.");
  83.       return -1;
  84.     }
  85.   /* set socket options */
  86. #if 1
  87.   sockopt_reuseaddr (ospf6_sock);
  88. #else
  89.   ospf6_set_reuseaddr ();
  90. #endif /*1*/
  91.   ospf6_reset_mcastloop ();
  92.   ospf6_set_pktinfo ();
  93.   ospf6_set_checksum ();
  94.   /* setup global in6_addr, allspf6 and alldr6 for later use */
  95.   inet_pton (AF_INET6, ALLSPFROUTERS6, &allspfrouters6);
  96.   inet_pton (AF_INET6, ALLDROUTERS6, &alldrouters6);
  97.   return 0;
  98. }
  99. void
  100. ospf6_join_allspfrouters (u_int ifindex)
  101. {
  102.   struct ipv6_mreq mreq6;
  103.   int retval;
  104.   assert (ifindex);
  105.   mreq6.ipv6mr_interface = ifindex;
  106.   memcpy (&mreq6.ipv6mr_multiaddr, &allspfrouters6,
  107.           sizeof (struct in6_addr));
  108.   retval = setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
  109.                        &mreq6, sizeof (mreq6));
  110.   if (retval < 0)
  111.     zlog_err ("Network: Join AllSPFRouters on ifindex %d failed: %s",
  112.               ifindex, strerror (errno));
  113. #if 0
  114.   else
  115.     zlog_info ("Network: Join AllSPFRouters on ifindex %d", ifindex);
  116. #endif
  117. }
  118. void
  119. ospf6_leave_allspfrouters (u_int ifindex)
  120. {
  121.   struct ipv6_mreq mreq6;
  122.   assert (ifindex);
  123.   mreq6.ipv6mr_interface = ifindex;
  124.   memcpy (&mreq6.ipv6mr_multiaddr, &allspfrouters6,
  125.           sizeof (struct in6_addr));
  126.   if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
  127.                   &mreq6, sizeof (mreq6)) < 0)
  128.     zlog_warn ("Network: Leave AllSPFRouters on ifindex %d Failed: %s",
  129.                ifindex, strerror (errno));
  130. #if 0
  131.   else
  132.     zlog_info ("Network: Leave AllSPFRouters on ifindex %d", ifindex);
  133. #endif
  134. }
  135. void
  136. ospf6_join_alldrouters (u_int ifindex)
  137. {
  138.   struct ipv6_mreq mreq6;
  139.   assert (ifindex);
  140.   mreq6.ipv6mr_interface = ifindex;
  141.   memcpy (&mreq6.ipv6mr_multiaddr, &alldrouters6,
  142.           sizeof (struct in6_addr));
  143.   if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
  144.                   &mreq6, sizeof (mreq6)) < 0)
  145.     zlog_warn ("Network: Join AllDRouters on ifindex %d Failed: %s",
  146.                ifindex, strerror (errno));
  147. #if 0
  148.   else
  149.     zlog_info ("Network: Join AllDRouters on ifindex %d", ifindex);
  150. #endif
  151. }
  152. void
  153. ospf6_leave_alldrouters (u_int ifindex)
  154. {
  155.   struct ipv6_mreq mreq6;
  156.   assert (ifindex);
  157.   mreq6.ipv6mr_interface = ifindex;
  158.   memcpy (&mreq6.ipv6mr_multiaddr, &alldrouters6,
  159.           sizeof (struct in6_addr));
  160.   if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
  161.                   &mreq6, sizeof (mreq6)) < 0)
  162.     zlog_warn ("Network: Leave AllDRouters on ifindex %d Failed", ifindex);
  163. #if 0
  164.   else
  165.     zlog_info ("Network: Leave AllDRouters on ifindex %d", ifindex);
  166. #endif
  167. }
  168. int
  169. iov_count (struct iovec *iov)
  170. {
  171.   int i;
  172.   for (i = 0; iov[i].iov_base; i++)
  173.     ;
  174.   return i;
  175. }
  176. int
  177. iov_totallen (struct iovec *iov)
  178. {
  179.   int i;
  180.   int totallen = 0;
  181.   for (i = 0; iov[i].iov_base; i++)
  182.     totallen += iov[i].iov_len;
  183.   return totallen;
  184. }
  185. int
  186. ospf6_sendmsg (struct in6_addr *src, struct in6_addr *dst,
  187.                unsigned int *ifindex, struct iovec *message)
  188. {
  189.   int retval;
  190.   struct msghdr smsghdr;
  191.   struct cmsghdr *scmsgp;
  192.   u_char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];
  193.   struct in6_pktinfo *pktinfo;
  194.   struct sockaddr_in6 dst_sin6;
  195.   assert (dst);
  196.   assert (*ifindex);
  197.   scmsgp = (struct cmsghdr *)cmsgbuf;
  198.   pktinfo = (struct in6_pktinfo *)(CMSG_DATA(scmsgp));
  199.   memset (&dst_sin6, 0, sizeof (struct sockaddr_in6));
  200.   /* source address */
  201.   pktinfo->ipi6_ifindex = *ifindex;
  202.   if (src)
  203.     memcpy (&pktinfo->ipi6_addr, src, sizeof (struct in6_addr));
  204.   else
  205.     memset (&pktinfo->ipi6_addr, 0, sizeof (struct in6_addr));
  206.   /* destination address */
  207.   dst_sin6.sin6_family = AF_INET6;
  208. #ifdef SIN6_LEN
  209.   dst_sin6.sin6_len = sizeof (struct sockaddr_in6);
  210. #endif /*SIN6_LEN*/
  211.   memcpy (&dst_sin6.sin6_addr, dst, sizeof (struct in6_addr));
  212. #ifdef HAVE_SIN6_SCOPE_ID
  213.   dst_sin6.sin6_scope_id = *ifindex;
  214. #endif
  215.   /* send control msg */
  216.   scmsgp->cmsg_level = IPPROTO_IPV6;
  217.   scmsgp->cmsg_type = IPV6_PKTINFO;
  218.   scmsgp->cmsg_len = CMSG_LEN (sizeof (struct in6_pktinfo));
  219.   /* scmsgp = CMSG_NXTHDR (&smsghdr, scmsgp); */
  220.   /* send msg hdr */
  221.   smsghdr.msg_iov = message;
  222.   smsghdr.msg_iovlen = iov_count (message);
  223.   smsghdr.msg_name = (caddr_t) &dst_sin6;
  224.   smsghdr.msg_namelen = sizeof (struct sockaddr_in6);
  225.   smsghdr.msg_control = (caddr_t) cmsgbuf;
  226.   smsghdr.msg_controllen = sizeof (cmsgbuf);
  227.   retval = sendmsg (ospf6_sock, &smsghdr, 0);
  228.   if (retval != iov_totallen (message))
  229.     zlog_warn ("sendmsg failed: ifindex: %d: %s (%d)",
  230.                *ifindex, strerror (errno), errno);
  231.   return retval;
  232. }
  233. int
  234. ospf6_recvmsg (struct in6_addr *src, struct in6_addr *dst,
  235.                unsigned int *ifindex, struct iovec *message)
  236. {
  237.   int retval;
  238.   struct msghdr rmsghdr;
  239.   struct cmsghdr *rcmsgp;
  240.   u_char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];
  241.   struct in6_pktinfo *pktinfo;
  242.   struct sockaddr_in6 src_sin6;
  243.   rcmsgp = (struct cmsghdr *)cmsgbuf;
  244.   pktinfo = (struct in6_pktinfo *)(CMSG_DATA(rcmsgp));
  245.   memset (&src_sin6, 0, sizeof (struct sockaddr_in6));
  246.   /* receive control msg */
  247.   rcmsgp->cmsg_level = IPPROTO_IPV6;
  248.   rcmsgp->cmsg_type = IPV6_PKTINFO;
  249.   rcmsgp->cmsg_len = CMSG_LEN (sizeof (struct in6_pktinfo));
  250.   /* rcmsgp = CMSG_NXTHDR (&rmsghdr, rcmsgp); */
  251.   /* receive msg hdr */
  252.   rmsghdr.msg_iov = message;
  253.   rmsghdr.msg_iovlen = iov_count (message);
  254.   rmsghdr.msg_name = (caddr_t) &src_sin6;
  255.   rmsghdr.msg_namelen = sizeof (struct sockaddr_in6);
  256.   rmsghdr.msg_control = (caddr_t) cmsgbuf;
  257.   rmsghdr.msg_controllen = sizeof (cmsgbuf);
  258.   retval = recvmsg (ospf6_sock, &rmsghdr, 0);
  259.   if (retval < 0)
  260.     zlog_warn ("recvmsg failed: %s", strerror (errno));
  261.   else if (retval == iov_totallen (message))
  262.     zlog_warn ("recvmsg read full buffer size: %d", retval);
  263.   /* source address */
  264.   assert (src);
  265.   memcpy (src, &src_sin6.sin6_addr, sizeof (struct in6_addr));
  266.   /* destination address */
  267.   if (ifindex)
  268.     *ifindex = pktinfo->ipi6_ifindex;
  269.   if (dst)
  270.     memcpy (dst, &pktinfo->ipi6_addr, sizeof (struct in6_addr));
  271.   return retval;
  272. }