back to topotato report
topotato coverage report
Current view: top level - ospf6d - ospf6_network.c (source / functions) Hit Total Coverage
Test: test_ospf6_vlink.py::VirtualLinkBasic Lines: 112 121 92.6 %
Date: 2023-02-16 02:06:43 Functions: 6 6 100.0 %

          Line data    Source code
       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 along
      17             :  * with this program; see the file COPYING; if not, write to the Free Software
      18             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : 
      21             : #include <zebra.h>
      22             : 
      23             : #include "log.h"
      24             : #include "memory.h"
      25             : #include "sockunion.h"
      26             : #include "sockopt.h"
      27             : #include "privs.h"
      28             : #include "lib_errors.h"
      29             : #include "vrf.h"
      30             : 
      31             : #include "libospf.h"
      32             : #include "ospf6_proto.h"
      33             : #include "ospf6_top.h"
      34             : #include "ospf6_network.h"
      35             : #include "ospf6d.h"
      36             : #include "ospf6_message.h"
      37             : 
      38             : struct in6_addr allspfrouters6;
      39             : struct in6_addr alldrouters6;
      40             : 
      41             : /* setsockopt MulticastLoop to off */
      42           8 : static void ospf6_reset_mcastloop(int ospf6_sock)
      43             : {
      44           8 :         unsigned int off = 0;
      45           8 :         if (setsockopt(ospf6_sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &off,
      46             :                        sizeof(unsigned int))
      47             :             < 0)
      48           0 :                 zlog_warn("Network: reset IPV6_MULTICAST_LOOP failed: %s",
      49             :                           safe_strerror(errno));
      50           8 : }
      51             : 
      52           8 : static void ospf6_set_pktinfo(int ospf6_sock)
      53             : {
      54           8 :         setsockopt_ipv6_pktinfo(ospf6_sock, 1);
      55             : }
      56             : 
      57           8 : static void ospf6_set_transport_class(int ospf6_sock)
      58             : {
      59             : #ifdef IPTOS_PREC_INTERNETCONTROL
      60           8 :         setsockopt_ipv6_tclass(ospf6_sock, IPTOS_PREC_INTERNETCONTROL);
      61             : #endif
      62             : }
      63             : 
      64           8 : void ospf6_serv_close(int *ospf6_sock)
      65             : {
      66           8 :         if (*ospf6_sock != -1) {
      67           8 :                 close(*ospf6_sock);
      68           8 :                 *ospf6_sock = -1;
      69           8 :                 return;
      70             :         }
      71             : }
      72             : 
      73             : /* Make ospf6d's server socket. */
      74           8 : int ospf6_serv_sock(struct ospf6 *ospf6)
      75             : {
      76           8 :         int ospf6_sock;
      77             : 
      78           8 :         if (ospf6->fd != -1)
      79             :                 return -1;
      80             : 
      81           8 :         if (ospf6->vrf_id == VRF_UNKNOWN)
      82             :                 return -1;
      83             : 
      84          16 :         frr_with_privs(&ospf6d_privs) {
      85             : 
      86          16 :                 ospf6_sock = vrf_socket(AF_INET6, SOCK_RAW, IPPROTO_OSPFIGP,
      87           8 :                                         ospf6->vrf_id, ospf6->name);
      88           8 :                 if (ospf6_sock < 0) {
      89           0 :                         zlog_warn("Network: can't create OSPF6 socket.");
      90           0 :                         return -1;
      91             :                 }
      92             :         }
      93             : 
      94             : /* set socket options */
      95             : #if 1
      96           8 :         sockopt_reuseaddr(ospf6_sock);
      97             : #else
      98             :         ospf6_set_reuseaddr();
      99             : #endif /*1*/
     100           8 :         ospf6_reset_mcastloop(ospf6_sock);
     101           8 :         ospf6_set_pktinfo(ospf6_sock);
     102           8 :         ospf6_set_transport_class(ospf6_sock);
     103             : 
     104           8 :         ospf6->fd = ospf6_sock;
     105             :         /* setup global in6_addr, allspf6 and alldr6 for later use */
     106           8 :         inet_pton(AF_INET6, ALLSPFROUTERS6, &allspfrouters6);
     107           8 :         inet_pton(AF_INET6, ALLDROUTERS6, &alldrouters6);
     108             : 
     109           8 :         return 0;
     110             : }
     111             : 
     112             : /* ospf6 set socket option */
     113          58 : int ospf6_sso(ifindex_t ifindex, struct in6_addr *group, int option, int sockfd)
     114             : {
     115          58 :         struct ipv6_mreq mreq6;
     116          58 :         int ret;
     117          58 :         int bufsize = (8 * 1024 * 1024);
     118             : 
     119          58 :         if (sockfd == -1)
     120             :                 return -1;
     121             : 
     122          58 :         assert(ifindex);
     123          58 :         mreq6.ipv6mr_interface = ifindex;
     124          58 :         memcpy(&mreq6.ipv6mr_multiaddr, group, sizeof(struct in6_addr));
     125             : 
     126          58 :         ret = setsockopt(sockfd, IPPROTO_IPV6, option, &mreq6, sizeof(mreq6));
     127          58 :         if (ret < 0) {
     128           0 :                 flog_err_sys(
     129             :                         EC_LIB_SOCKET,
     130             :                         "Network: setsockopt (%d) on ifindex %d failed: %s",
     131             :                         option, ifindex, safe_strerror(errno));
     132           0 :                 return ret;
     133             :         }
     134             : 
     135          58 :         setsockopt_so_sendbuf(sockfd, bufsize);
     136          58 :         setsockopt_so_recvbuf(sockfd, bufsize);
     137             : 
     138          58 :         return 0;
     139             : }
     140             : 
     141        1155 : static int iov_count(struct iovec *iov)
     142             : {
     143        1155 :         int i;
     144        2310 :         for (i = 0; iov[i].iov_base; i++)
     145             :                 ;
     146        1155 :         return i;
     147             : }
     148             : 
     149         418 : static int iov_totallen(struct iovec *iov)
     150             : {
     151             :         int i;
     152             :         int totallen = 0;
     153        1694 :         for (i = 0; iov[i].iov_base; i++)
     154         847 :                 totallen += iov[i].iov_len;
     155         847 :         return totallen;
     156             : }
     157             : 
     158         418 : int ospf6_sendmsg(struct in6_addr *src, struct in6_addr *dst,
     159             :                   ifindex_t ifindex, struct iovec *message, int ospf6_sock)
     160             : {
     161         418 :         int retval;
     162         418 :         struct msghdr smsghdr;
     163         418 :         struct cmsghdr *scmsgp;
     164         418 :         union {
     165             :                 struct cmsghdr hdr;
     166             :                 uint8_t buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
     167             :         } cmsgbuf;
     168         418 :         struct in6_pktinfo *pktinfo;
     169         418 :         struct sockaddr_in6 dst_sin6;
     170             : 
     171         418 :         assert(dst);
     172             : 
     173         418 :         memset(&cmsgbuf, 0, sizeof(cmsgbuf));
     174         418 :         scmsgp = (struct cmsghdr *)&cmsgbuf;
     175         418 :         pktinfo = (struct in6_pktinfo *)(CMSG_DATA(scmsgp));
     176         418 :         memset(&dst_sin6, 0, sizeof(dst_sin6));
     177             : 
     178             :         /* source address */
     179         418 :         pktinfo->ipi6_ifindex = ifindex;
     180         418 :         if (src)
     181         418 :                 memcpy(&pktinfo->ipi6_addr, src, sizeof(struct in6_addr));
     182             :         else
     183           0 :                 memset(&pktinfo->ipi6_addr, 0, sizeof(struct in6_addr));
     184             : 
     185             :         /* destination address */
     186         418 :         dst_sin6.sin6_family = AF_INET6;
     187             : #ifdef SIN6_LEN
     188             :         dst_sin6.sin6_len = sizeof(struct sockaddr_in6);
     189             : #endif /*SIN6_LEN*/
     190         418 :         memcpy(&dst_sin6.sin6_addr, dst, sizeof(struct in6_addr));
     191         418 :         dst_sin6.sin6_scope_id = ifindex;
     192             : 
     193             :         /* send control msg */
     194         418 :         scmsgp->cmsg_level = IPPROTO_IPV6;
     195         418 :         scmsgp->cmsg_type = IPV6_PKTINFO;
     196         418 :         scmsgp->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
     197             :         /* scmsgp = CMSG_NXTHDR (&smsghdr, scmsgp); */
     198             : 
     199             :         /* send msg hdr */
     200         418 :         memset(&smsghdr, 0, sizeof(smsghdr));
     201         418 :         smsghdr.msg_iov = message;
     202         418 :         smsghdr.msg_iovlen = iov_count(message);
     203         418 :         smsghdr.msg_name = (caddr_t)&dst_sin6;
     204         418 :         smsghdr.msg_namelen = sizeof(struct sockaddr_in6);
     205         418 :         smsghdr.msg_control = (caddr_t)&cmsgbuf.buf;
     206         418 :         smsghdr.msg_controllen = sizeof(cmsgbuf.buf);
     207             : 
     208         418 :         retval = sendmsg(ospf6_sock, &smsghdr, 0);
     209         836 :         if (retval != iov_totallen(message))
     210           0 :                 zlog_warn("sendmsg failed: source: %pI6 Dest: %pI6 ifindex: %d: %s (%d)",
     211             :                           src, dst, ifindex,
     212             :                           safe_strerror(errno), errno);
     213             : 
     214         418 :         return retval;
     215             : }
     216             : 
     217         737 : int ospf6_recvmsg(struct in6_addr *src, struct in6_addr *dst,
     218             :                   ifindex_t *ifindex, struct iovec *message, int ospf6_sock)
     219             : {
     220         737 :         int retval;
     221         737 :         struct msghdr rmsghdr;
     222         737 :         struct cmsghdr *rcmsgp;
     223         737 :         uint8_t cmsgbuf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
     224         737 :         struct in6_pktinfo *pktinfo;
     225         737 :         struct sockaddr_in6 src_sin6;
     226             : 
     227         737 :         rcmsgp = (struct cmsghdr *)cmsgbuf;
     228         737 :         pktinfo = (struct in6_pktinfo *)(CMSG_DATA(rcmsgp));
     229         737 :         memset(&src_sin6, 0, sizeof(src_sin6));
     230             : 
     231             :         /* receive control msg */
     232         737 :         rcmsgp->cmsg_level = IPPROTO_IPV6;
     233         737 :         rcmsgp->cmsg_type = IPV6_PKTINFO;
     234         737 :         rcmsgp->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
     235             :         /* rcmsgp = CMSG_NXTHDR (&rmsghdr, rcmsgp); */
     236             : 
     237             :         /* receive msg hdr */
     238         737 :         memset(&rmsghdr, 0, sizeof(rmsghdr));
     239         737 :         rmsghdr.msg_iov = message;
     240         737 :         rmsghdr.msg_iovlen = iov_count(message);
     241         737 :         rmsghdr.msg_name = (caddr_t)&src_sin6;
     242         737 :         rmsghdr.msg_namelen = sizeof(struct sockaddr_in6);
     243         737 :         rmsghdr.msg_control = (caddr_t)cmsgbuf;
     244         737 :         rmsghdr.msg_controllen = sizeof(cmsgbuf);
     245             : 
     246         737 :         retval = recvmsg(ospf6_sock, &rmsghdr, MSG_DONTWAIT);
     247         737 :         if (retval < 0) {
     248         308 :                 if (errno != EAGAIN && errno != EWOULDBLOCK)
     249           0 :                         zlog_warn("stream_recvmsg failed: %s",
     250             :                                   safe_strerror(errno));
     251         308 :                 return retval;
     252         429 :         } else if (retval == iov_totallen(message))
     253           0 :                 zlog_warn("recvmsg read full buffer size: %d", retval);
     254             : 
     255             :         /* source address */
     256         429 :         assert(src);
     257         429 :         memcpy(src, &src_sin6.sin6_addr, sizeof(struct in6_addr));
     258             : 
     259             :         /* destination address */
     260         429 :         if (ifindex)
     261         429 :                 *ifindex = pktinfo->ipi6_ifindex;
     262         429 :         if (dst)
     263         429 :                 memcpy(dst, &pktinfo->ipi6_addr, sizeof(struct in6_addr));
     264             : 
     265             :         return retval;
     266             : }

Generated by: LCOV version v1.16-topotato