2023-02-08 13:17:09 +01:00
// SPDX-License-Identifier: GPL-2.0-or-later
2002-12-13 21:15:29 +01:00
/*
* OSPF network related functions
* Copyright ( C ) 1999 Toshiaki Takada
*/
# include <zebra.h>
2023-03-07 20:22:48 +01:00
# include "frrevent.h"
2002-12-13 21:15:29 +01:00
# include "linklist.h"
# include "prefix.h"
# include "if.h"
# include "sockunion.h"
# include "log.h"
# include "sockopt.h"
2003-06-04 15:59:38 +02:00
# include "privs.h"
2018-06-19 22:41:28 +02:00
# include "lib_errors.h"
2023-03-29 22:58:25 +02:00
# include "lib/table.h"
2003-06-04 15:59:38 +02:00
2002-12-13 21:15:29 +01:00
# include "ospfd/ospfd.h"
# include "ospfd/ospf_network.h"
# include "ospfd/ospf_interface.h"
# include "ospfd/ospf_asbr.h"
# include "ospfd/ospf_lsa.h"
# include "ospfd/ospf_lsdb.h"
# include "ospfd/ospf_neighbor.h"
# include "ospfd/ospf_packet.h"
2017-12-26 18:45:25 +01:00
# include "ospfd/ospf_dump.h"
2003-06-04 15:59:38 +02:00
2002-12-13 21:15:29 +01:00
/* Join to the OSPF ALL SPF ROUTERS multicast group. */
int ospf_if_add_allspfrouters ( struct ospf * top , struct prefix * p ,
2016-01-18 11:12:10 +01:00
ifindex_t ifindex )
2002-12-13 21:15:29 +01:00
{
int ret ;
2017-07-17 14:03:14 +02:00
2011-08-18 18:22:17 +02:00
ret = setsockopt_ipv4_multicast ( top - > fd , IP_ADD_MEMBERSHIP ,
2016-08-04 15:07:26 +02:00
p - > u . prefix4 , htonl ( OSPF_ALLSPFROUTERS ) ,
2002-12-13 21:15:29 +01:00
ifindex ) ;
if ( ret < 0 )
2018-08-24 18:26:43 +02:00
flog_err (
2018-09-13 21:34:28 +02:00
EC_LIB_SOCKET ,
2020-10-21 19:56:26 +02:00
" can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %pI4, ifindex %u, AllSPFRouters): %s; perhaps a kernel limit on # of multicast group memberships has been exceeded? " ,
top - > fd , & p - > u . prefix4 , ifindex ,
2018-08-24 18:26:43 +02:00
safe_strerror ( errno ) ) ;
2017-12-26 18:45:25 +01:00
else {
if ( IS_DEBUG_OSPF_EVENT )
zlog_debug (
2020-10-21 19:56:26 +02:00
" interface %pI4 [%u] join AllSPFRouters Multicast group. " ,
& p - > u . prefix4 , ifindex ) ;
2017-12-26 18:45:25 +01:00
}
2017-07-17 14:03:14 +02:00
2002-12-13 21:15:29 +01:00
return ret ;
}
int ospf_if_drop_allspfrouters ( struct ospf * top , struct prefix * p ,
2016-01-18 11:12:10 +01:00
ifindex_t ifindex )
2002-12-13 21:15:29 +01:00
{
int ret ;
2017-07-17 14:03:14 +02:00
2011-08-18 18:22:17 +02:00
ret = setsockopt_ipv4_multicast ( top - > fd , IP_DROP_MEMBERSHIP ,
2016-08-04 15:07:26 +02:00
p - > u . prefix4 , htonl ( OSPF_ALLSPFROUTERS ) ,
2002-12-13 21:15:29 +01:00
ifindex ) ;
if ( ret < 0 )
2018-09-13 21:34:28 +02:00
flog_err ( EC_LIB_SOCKET ,
2020-10-21 19:56:26 +02:00
" can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %pI4, ifindex %u, AllSPFRouters): %s " ,
top - > fd , & p - > u . prefix4 , ifindex ,
2018-08-20 20:14:23 +02:00
safe_strerror ( errno ) ) ;
2017-12-26 18:45:25 +01:00
else {
if ( IS_DEBUG_OSPF_EVENT )
zlog_debug (
2020-10-21 19:56:26 +02:00
" interface %pI4 [%u] leave AllSPFRouters Multicast group. " ,
& p - > u . prefix4 , ifindex ) ;
2017-12-26 18:45:25 +01:00
}
2017-07-17 14:03:14 +02:00
2002-12-13 21:15:29 +01:00
return ret ;
}
/* Join to the OSPF ALL Designated ROUTERS multicast group. */
2016-01-18 11:12:10 +01:00
int ospf_if_add_alldrouters ( struct ospf * top , struct prefix * p ,
ifindex_t ifindex )
2002-12-13 21:15:29 +01:00
{
int ret ;
2017-07-17 14:03:14 +02:00
2011-08-18 18:22:17 +02:00
ret = setsockopt_ipv4_multicast ( top - > fd , IP_ADD_MEMBERSHIP ,
2016-08-04 15:07:26 +02:00
p - > u . prefix4 , htonl ( OSPF_ALLDROUTERS ) ,
2002-12-13 21:15:29 +01:00
ifindex ) ;
if ( ret < 0 )
2018-08-24 18:26:43 +02:00
flog_err (
2018-09-13 21:34:28 +02:00
EC_LIB_SOCKET ,
2020-10-21 19:56:26 +02:00
" can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %pI4, ifindex %u, AllDRouters): %s; perhaps a kernel limit on # of multicast group memberships has been exceeded? " ,
top - > fd , & p - > u . prefix4 , ifindex ,
2018-08-24 18:26:43 +02:00
safe_strerror ( errno ) ) ;
2022-11-28 14:53:20 +01:00
else {
if ( IS_DEBUG_OSPF_EVENT )
zlog_debug (
" interface %pI4 [%u] join AllDRouters Multicast group. " ,
& p - > u . prefix4 , ifindex ) ;
}
2002-12-13 21:15:29 +01:00
return ret ;
}
2016-01-18 11:12:10 +01:00
int ospf_if_drop_alldrouters ( struct ospf * top , struct prefix * p ,
ifindex_t ifindex )
2002-12-13 21:15:29 +01:00
{
int ret ;
2017-07-17 14:03:14 +02:00
2011-08-18 18:22:17 +02:00
ret = setsockopt_ipv4_multicast ( top - > fd , IP_DROP_MEMBERSHIP ,
2016-08-04 15:07:26 +02:00
p - > u . prefix4 , htonl ( OSPF_ALLDROUTERS ) ,
2002-12-13 21:15:29 +01:00
ifindex ) ;
if ( ret < 0 )
2018-09-13 21:34:28 +02:00
flog_err ( EC_LIB_SOCKET ,
2020-10-21 19:56:26 +02:00
" can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %pI4, ifindex %u, AllDRouters): %s " ,
top - > fd , & p - > u . prefix4 , ifindex ,
2018-08-20 20:14:23 +02:00
safe_strerror ( errno ) ) ;
2023-04-06 19:40:23 +02:00
else if ( IS_DEBUG_OSPF_EVENT )
2010-12-06 13:21:52 +01:00
zlog_debug (
2020-10-21 19:56:26 +02:00
" interface %pI4 [%u] leave AllDRouters Multicast group. " ,
& p - > u . prefix4 , ifindex ) ;
2017-07-17 14:03:14 +02:00
2002-12-13 21:15:29 +01:00
return ret ;
}
2023-03-29 22:58:25 +02:00
int ospf_if_ipmulticast ( int fd , struct prefix * p , ifindex_t ifindex )
2002-12-13 21:15:29 +01:00
{
2018-03-27 21:13:34 +02:00
uint8_t val ;
2002-12-13 21:15:29 +01:00
int ret , len ;
2017-07-17 14:03:14 +02:00
2002-12-13 21:15:29 +01:00
/* Prevent receiving self-origined multicast packets. */
2023-03-29 22:58:25 +02:00
ret = setsockopt_ipv4_multicast_loop ( fd , 0 ) ;
2002-12-13 21:15:29 +01:00
if ( ret < 0 )
2018-09-13 21:34:28 +02:00
flog_err ( EC_LIB_SOCKET ,
2018-08-20 20:14:23 +02:00
" can't setsockopt IP_MULTICAST_LOOP(0) for fd %d: %s " ,
2023-03-29 22:58:25 +02:00
fd , safe_strerror ( errno ) ) ;
2017-07-17 14:03:14 +02:00
2002-12-13 21:15:29 +01:00
/* Explicitly set multicast ttl to 1 -- endo. */
val = 1 ;
2016-11-12 22:05:08 +01:00
len = sizeof ( val ) ;
2023-03-29 22:58:25 +02:00
ret = setsockopt ( fd , IPPROTO_IP , IP_MULTICAST_TTL , ( void * ) & val , len ) ;
2002-12-13 21:15:29 +01:00
if ( ret < 0 )
2018-09-13 21:34:28 +02:00
flog_err ( EC_LIB_SOCKET ,
2018-08-20 20:14:23 +02:00
" can't setsockopt IP_MULTICAST_TTL(1) for fd %d: %s " ,
2023-03-29 22:58:25 +02:00
fd , safe_strerror ( errno ) ) ;
2017-09-17 03:08:33 +02:00
# ifndef GNU_LINUX
/* For GNU LINUX ospf_write uses IP_PKTINFO, in_pktinfo to send
* packet out of ifindex . Below would be used Non Linux system .
*/
2023-03-29 22:58:25 +02:00
ret = setsockopt_ipv4_multicast_if ( fd , p - > u . prefix4 , ifindex ) ;
2017-09-17 03:08:33 +02:00
if ( ret < 0 )
2018-09-13 21:34:28 +02:00
flog_err ( EC_LIB_SOCKET ,
2020-10-21 19:56:26 +02:00
" can't setsockopt IP_MULTICAST_IF(fd %d, addr %pI4, ifindex %u): %s " ,
2023-03-29 22:58:25 +02:00
fd , & p - > u . prefix4 , ifindex ,
2018-08-20 20:14:23 +02:00
safe_strerror ( errno ) ) ;
2017-09-17 03:08:33 +02:00
# endif
2017-07-17 14:03:14 +02:00
2017-09-13 02:27:26 +02:00
return ret ;
}
2023-03-29 22:58:25 +02:00
/*
* Helper to open and set up a socket ; returns the new fd on success ,
* - 1 on error .
*/
2023-06-29 19:51:18 +02:00
static int sock_init_common ( vrf_id_t vrf_id , const char * name , int proto ,
int * pfd )
2002-12-13 21:15:29 +01:00
{
int ospf_sock ;
2008-08-14 18:59:25 +02:00
int ret , hincl = 1 ;
2017-07-17 14:03:14 +02:00
2023-03-29 22:58:25 +02:00
if ( vrf_id = = VRF_UNKNOWN ) {
2018-01-29 16:56:11 +01:00
/* silently return since VRF is not ready */
return - 1 ;
}
2023-03-29 22:58:25 +02:00
2019-08-13 15:47:23 +02:00
frr_with_privs ( & ospfd_privs ) {
2023-06-29 19:51:18 +02:00
ospf_sock = vrf_socket ( AF_INET , SOCK_RAW , proto , vrf_id , name ) ;
2018-08-10 18:46:07 +02:00
if ( ospf_sock < 0 ) {
2023-03-29 22:58:25 +02:00
flog_err ( EC_LIB_SOCKET , " %s: socket: %s " , __func__ ,
2018-08-10 18:46:07 +02:00
safe_strerror ( errno ) ) ;
2021-07-27 15:10:35 +02:00
return - 1 ;
2018-08-10 18:46:07 +02:00
}
2017-07-17 14:03:14 +02:00
2004-05-05 19:29:24 +02:00
# ifdef IP_HDRINCL
2018-08-10 18:46:07 +02:00
/* we will include IP header with packet */
ret = setsockopt ( ospf_sock , IPPROTO_IP , IP_HDRINCL , & hincl ,
sizeof ( hincl ) ) ;
if ( ret < 0 ) {
2018-09-13 21:34:28 +02:00
flog_err ( EC_LIB_SOCKET ,
2018-08-20 20:14:23 +02:00
" Can't set IP_HDRINCL option for fd %d: %s " ,
ospf_sock , safe_strerror ( errno ) ) ;
2018-08-10 18:46:07 +02:00
break ;
}
2004-05-05 19:29:24 +02:00
# elif defined(IPTOS_PREC_INTERNETCONTROL)
# warning "IP_HDRINCL not available on this system"
# warning "using IPTOS_PREC_INTERNETCONTROL"
2018-08-10 18:46:07 +02:00
ret = setsockopt_ipv4_tos ( ospf_sock ,
IPTOS_PREC_INTERNETCONTROL ) ;
if ( ret < 0 ) {
2018-09-13 21:34:28 +02:00
flog_err ( EC_LIB_SOCKET ,
2018-08-20 20:14:23 +02:00
" can't set sockopt IP_TOS %d to socket %d: %s " ,
tos , ospf_sock , safe_strerror ( errno ) ) ;
2018-08-10 18:46:07 +02:00
break ;
}
2004-05-05 19:29:24 +02:00
# else /* !IPTOS_PREC_INTERNETCONTROL */
# warning "IP_HDRINCL not available, nor is IPTOS_PREC_INTERNETCONTROL"
2018-09-13 21:38:57 +02:00
flog_err ( EC_LIB_UNAVAILABLE , " IP_HDRINCL option not available " ) ;
2004-05-05 19:29:24 +02:00
# endif /* IP_HDRINCL */
2002-12-13 21:15:29 +01:00
2018-08-10 18:46:07 +02:00
ret = setsockopt_ifindex ( AF_INET , ospf_sock , 1 ) ;
2004-10-22 14:05:17 +02:00
2018-08-10 18:46:07 +02:00
if ( ret < 0 )
2018-09-13 21:34:28 +02:00
flog_err ( EC_LIB_SOCKET ,
2018-08-20 20:14:23 +02:00
" Can't set pktinfo option for fd %d " ,
ospf_sock ) ;
2018-08-10 18:46:07 +02:00
}
2017-09-13 02:27:26 +02:00
2023-03-29 22:58:25 +02:00
* pfd = ospf_sock ;
2019-04-08 18:08:00 +02:00
2017-09-13 02:27:26 +02:00
return ret ;
2002-12-13 21:15:29 +01:00
}
2023-04-06 19:40:23 +02:00
/*
* Update a socket bufsize ( s ) , based on its ospf instance
*/
void ospf_sock_bufsize_update ( const struct ospf * ospf , int sock ,
enum ospf_sock_type_e type )
{
int bufsize ;
if ( type = = OSPF_SOCK_BOTH | | type = = OSPF_SOCK_RECV ) {
bufsize = ospf - > recv_sock_bufsize ;
setsockopt_so_recvbuf ( sock , bufsize ) ;
}
if ( type = = OSPF_SOCK_BOTH | | type = = OSPF_SOCK_SEND ) {
bufsize = ospf - > send_sock_bufsize ;
setsockopt_so_sendbuf ( sock , bufsize ) ;
}
}
2023-03-29 22:58:25 +02:00
int ospf_sock_init ( struct ospf * ospf )
{
int ret ;
/* silently ignore. already done */
if ( ospf - > fd > 0 )
return - 1 ;
2023-06-29 19:51:18 +02:00
ret = sock_init_common ( ospf - > vrf_id , ospf - > name , IPPROTO_OSPFIGP ,
& ( ospf - > fd ) ) ;
2023-03-29 22:58:25 +02:00
if ( ret > = 0 ) /* Update socket buffer sizes */
ospf_sock_bufsize_update ( ospf , ospf - > fd , OSPF_SOCK_BOTH ) ;
return ret ;
}
/*
* Open per - interface write socket
*/
int ospf_ifp_sock_init ( struct interface * ifp )
{
struct ospf_if_info * oii ;
2023-06-29 19:51:18 +02:00
struct ospf_interface * oi = NULL ;
struct ospf * ospf = NULL ;
2023-03-29 22:58:25 +02:00
struct route_node * rn ;
int ret ;
oii = IF_OSPF_IF_INFO ( ifp ) ;
if ( oii = = NULL )
return - 1 ;
if ( oii - > oii_fd > 0 )
return 0 ;
2023-06-29 19:51:18 +02:00
for ( rn = route_top ( IF_OIFS ( ifp ) ) ; rn ; rn = route_next ( rn ) ) {
if ( rn & & rn - > info ) {
oi = rn - > info ;
ospf = oi - > ospf ;
break ;
}
}
if ( ospf = = NULL )
2023-03-29 22:58:25 +02:00
return - 1 ;
2023-06-29 19:51:18 +02:00
ret = sock_init_common ( ifp - > vrf - > vrf_id , ifp - > name , IPPROTO_OSPFIGP ,
& oii - > oii_fd ) ;
2023-03-29 22:58:25 +02:00
2023-06-29 19:51:18 +02:00
if ( ret > = 0 ) { /* Update socket buffer sizes */
/* Write-only, so no recv buf */
setsockopt_so_recvbuf ( oii - > oii_fd , 0 ) ;
ospf_sock_bufsize_update ( ospf , oii - > oii_fd , OSPF_SOCK_SEND ) ;
}
2023-03-29 22:58:25 +02:00
if ( IS_DEBUG_OSPF_EVENT )
zlog_debug ( " %s: ifp %s, oii %p, fd %d " , __func__ , ifp - > name ,
oii , oii - > oii_fd ) ;
return ret ;
}
/*
* Close per - interface write socket
*/
int ospf_ifp_sock_close ( struct interface * ifp )
{
struct ospf_if_info * oii ;
oii = IF_OSPF_IF_INFO ( ifp ) ;
if ( oii = = NULL )
return 0 ;
if ( oii - > oii_fd > 0 ) {
if ( IS_DEBUG_OSPF_EVENT )
zlog_debug ( " %s: ifp %s, oii %p, fd %d " , __func__ ,
ifp - > name , oii , oii - > oii_fd ) ;
close ( oii - > oii_fd ) ;
oii - > oii_fd = - 1 ;
}
return 0 ;
}