back to topotato report
topotato coverage report
Current view: top level - ospf6d - ospf6_network.c (source / functions) Hit Total Coverage
Test: test_ospf6_p2xp.py::PtMPBasic Lines: 112 121 92.6 %
Date: 2023-02-24 18:38:14 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           4 : static void ospf6_reset_mcastloop(int ospf6_sock)
      43             : {
      44           4 :         unsigned int off = 0;
      45           4 :         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           4 : }
      51             : 
      52           4 : static void ospf6_set_pktinfo(int ospf6_sock)
      53             : {
      54           4 :         setsockopt_ipv6_pktinfo(ospf6_sock, 1);
      55             : }
      56             : 
      57           4 : static void ospf6_set_transport_class(int ospf6_sock)
      58             : {
      59             : #ifdef IPTOS_PREC_INTERNETCONTROL
      60           4 :         setsockopt_ipv6_tclass(ospf6_sock, IPTOS_PREC_INTERNETCONTROL);
      61             : #endif
      62             : }
      63             : 
      64           4 : void ospf6_serv_close(int *ospf6_sock)
      65             : {
      66           4 :         if (*ospf6_sock != -1) {
      67           4 :                 close(*ospf6_sock);
      68           4 :                 *ospf6_sock = -1;
      69           4 :                 return;
      70             :         }
      71             : }
      72             : 
      73             : /* Make ospf6d's server socket. */
      74           4 : int ospf6_serv_sock(struct ospf6 *ospf6)
      75             : {
      76           4 :         int ospf6_sock;
      77             : 
      78           4 :         if (ospf6->fd != -1)
      79             :                 return -1;
      80             : 
      81           4 :         if (ospf6->vrf_id == VRF_UNKNOWN)
      82             :                 return -1;
      83             : 
      84           8 :         frr_with_privs(&ospf6d_privs) {
      85             : 
      86           8 :                 ospf6_sock = vrf_socket(AF_INET6, SOCK_RAW, IPPROTO_OSPFIGP,
      87           4 :                                         ospf6->vrf_id, ospf6->name);
      88           4 :                 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           4 :         sockopt_reuseaddr(ospf6_sock);
      97             : #else
      98             :         ospf6_set_reuseaddr();
      99             : #endif /*1*/
     100           4 :         ospf6_reset_mcastloop(ospf6_sock);
     101           4 :         ospf6_set_pktinfo(ospf6_sock);
     102           4 :         ospf6_set_transport_class(ospf6_sock);
     103             : 
     104           4 :         ospf6->fd = ospf6_sock;
     105             :         /* setup global in6_addr, allspf6 and alldr6 for later use */
     106           4 :         inet_pton(AF_INET6, ALLSPFROUTERS6, &allspfrouters6);
     107           4 :         inet_pton(AF_INET6, ALLDROUTERS6, &alldrouters6);
     108             : 
     109           4 :         return 0;
     110             : }
     111             : 
     112             : /* ospf6 set socket option */
     113          14 : int ospf6_sso(ifindex_t ifindex, struct in6_addr *group, int option, int sockfd)
     114             : {
     115          14 :         struct ipv6_mreq mreq6;
     116          14 :         int ret;
     117          14 :         int bufsize = (8 * 1024 * 1024);
     118             : 
     119          14 :         if (sockfd == -1)
     120             :                 return -1;
     121             : 
     122          14 :         assert(ifindex);
     123          14 :         mreq6.ipv6mr_interface = ifindex;
     124          14 :         memcpy(&mreq6.ipv6mr_multiaddr, group, sizeof(struct in6_addr));
     125             : 
     126          14 :         ret = setsockopt(sockfd, IPPROTO_IPV6, option, &mreq6, sizeof(mreq6));
     127          14 :         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          14 :         setsockopt_so_sendbuf(sockfd, bufsize);
     136          14 :         setsockopt_so_recvbuf(sockfd, bufsize);
     137             : 
     138          14 :         return 0;
     139             : }
     140             : 
     141         628 : static int iov_count(struct iovec *iov)
     142             : {
     143         628 :         int i;
     144        1256 :         for (i = 0; iov[i].iov_base; i++)
     145             :                 ;
     146         628 :         return i;
     147             : }
     148             : 
     149         219 : static int iov_totallen(struct iovec *iov)
     150             : {
     151             :         int i;
     152             :         int totallen = 0;
     153         898 :         for (i = 0; iov[i].iov_base; i++)
     154         449 :                 totallen += iov[i].iov_len;
     155         449 :         return totallen;
     156             : }
     157             : 
     158         219 : int ospf6_sendmsg(struct in6_addr *src, struct in6_addr *dst,
     159             :                   ifindex_t ifindex, struct iovec *message, int ospf6_sock)
     160             : {
     161         219 :         int retval;
     162         219 :         struct msghdr smsghdr;
     163         219 :         struct cmsghdr *scmsgp;
     164         219 :         union {
     165             :                 struct cmsghdr hdr;
     166             :                 uint8_t buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
     167             :         } cmsgbuf;
     168         219 :         struct in6_pktinfo *pktinfo;
     169         219 :         struct sockaddr_in6 dst_sin6;
     170             : 
     171         219 :         assert(dst);
     172             : 
     173         219 :         memset(&cmsgbuf, 0, sizeof(cmsgbuf));
     174         219 :         scmsgp = (struct cmsghdr *)&cmsgbuf;
     175         219 :         pktinfo = (struct in6_pktinfo *)(CMSG_DATA(scmsgp));
     176         219 :         memset(&dst_sin6, 0, sizeof(dst_sin6));
     177             : 
     178             :         /* source address */
     179         219 :         pktinfo->ipi6_ifindex = ifindex;
     180         219 :         if (src)
     181         219 :                 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         219 :         dst_sin6.sin6_family = AF_INET6;
     187             : #ifdef SIN6_LEN
     188             :         dst_sin6.sin6_len = sizeof(struct sockaddr_in6);
     189             : #endif /*SIN6_LEN*/
     190         219 :         memcpy(&dst_sin6.sin6_addr, dst, sizeof(struct in6_addr));
     191         219 :         dst_sin6.sin6_scope_id = ifindex;
     192             : 
     193             :         /* send control msg */
     194         219 :         scmsgp->cmsg_level = IPPROTO_IPV6;
     195         219 :         scmsgp->cmsg_type = IPV6_PKTINFO;
     196         219 :         scmsgp->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
     197             :         /* scmsgp = CMSG_NXTHDR (&smsghdr, scmsgp); */
     198             : 
     199             :         /* send msg hdr */
     200         219 :         memset(&smsghdr, 0, sizeof(smsghdr));
     201         219 :         smsghdr.msg_iov = message;
     202         219 :         smsghdr.msg_iovlen = iov_count(message);
     203         219 :         smsghdr.msg_name = (caddr_t)&dst_sin6;
     204         219 :         smsghdr.msg_namelen = sizeof(struct sockaddr_in6);
     205         219 :         smsghdr.msg_control = (caddr_t)&cmsgbuf.buf;
     206         219 :         smsghdr.msg_controllen = sizeof(cmsgbuf.buf);
     207             : 
     208         219 :         retval = sendmsg(ospf6_sock, &smsghdr, 0);
     209         438 :         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         219 :         return retval;
     215             : }
     216             : 
     217         409 : int ospf6_recvmsg(struct in6_addr *src, struct in6_addr *dst,
     218             :                   ifindex_t *ifindex, struct iovec *message, int ospf6_sock)
     219             : {
     220         409 :         int retval;
     221         409 :         struct msghdr rmsghdr;
     222         409 :         struct cmsghdr *rcmsgp;
     223         409 :         uint8_t cmsgbuf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
     224         409 :         struct in6_pktinfo *pktinfo;
     225         409 :         struct sockaddr_in6 src_sin6;
     226             : 
     227         409 :         rcmsgp = (struct cmsghdr *)cmsgbuf;
     228         409 :         pktinfo = (struct in6_pktinfo *)(CMSG_DATA(rcmsgp));
     229         409 :         memset(&src_sin6, 0, sizeof(src_sin6));
     230             : 
     231             :         /* receive control msg */
     232         409 :         rcmsgp->cmsg_level = IPPROTO_IPV6;
     233         409 :         rcmsgp->cmsg_type = IPV6_PKTINFO;
     234         409 :         rcmsgp->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
     235             :         /* rcmsgp = CMSG_NXTHDR (&rmsghdr, rcmsgp); */
     236             : 
     237             :         /* receive msg hdr */
     238         409 :         memset(&rmsghdr, 0, sizeof(rmsghdr));
     239         409 :         rmsghdr.msg_iov = message;
     240         409 :         rmsghdr.msg_iovlen = iov_count(message);
     241         409 :         rmsghdr.msg_name = (caddr_t)&src_sin6;
     242         409 :         rmsghdr.msg_namelen = sizeof(struct sockaddr_in6);
     243         409 :         rmsghdr.msg_control = (caddr_t)cmsgbuf;
     244         409 :         rmsghdr.msg_controllen = sizeof(cmsgbuf);
     245             : 
     246         409 :         retval = recvmsg(ospf6_sock, &rmsghdr, MSG_DONTWAIT);
     247         409 :         if (retval < 0) {
     248         179 :                 if (errno != EAGAIN && errno != EWOULDBLOCK)
     249           0 :                         zlog_warn("stream_recvmsg failed: %s",
     250             :                                   safe_strerror(errno));
     251         179 :                 return retval;
     252         230 :         } else if (retval == iov_totallen(message))
     253           0 :                 zlog_warn("recvmsg read full buffer size: %d", retval);
     254             : 
     255             :         /* source address */
     256         230 :         assert(src);
     257         230 :         memcpy(src, &src_sin6.sin6_addr, sizeof(struct in6_addr));
     258             : 
     259             :         /* destination address */
     260         230 :         if (ifindex)
     261         230 :                 *ifindex = pktinfo->ipi6_ifindex;
     262         230 :         if (dst)
     263         230 :                 memcpy(dst, &pktinfo->ipi6_addr, sizeof(struct in6_addr));
     264             : 
     265             :         return retval;
     266             : }

Generated by: LCOV version v1.16-topotato