File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / ospf6d / ospf6_network.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:26:12 2012 UTC (12 years, 4 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_20_1, v0_99_20, HEAD
quagga

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>