]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_network.c
*: Convert `struct event_master` to `struct event_loop`
[mirror_frr.git] / ospfd / ospf_network.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
718e3744 2/*
3 * OSPF network related functions
4 * Copyright (C) 1999 Toshiaki Takada
718e3744 5 */
6
7#include <zebra.h>
8
cb37cb33 9#include "event.h"
718e3744 10#include "linklist.h"
11#include "prefix.h"
12#include "if.h"
13#include "sockunion.h"
14#include "log.h"
15#include "sockopt.h"
edd7c245 16#include "privs.h"
313d7993 17#include "lib_errors.h"
edd7c245 18
718e3744 19#include "ospfd/ospfd.h"
20#include "ospfd/ospf_network.h"
21#include "ospfd/ospf_interface.h"
22#include "ospfd/ospf_asbr.h"
23#include "ospfd/ospf_lsa.h"
24#include "ospfd/ospf_lsdb.h"
25#include "ospfd/ospf_neighbor.h"
26#include "ospfd/ospf_packet.h"
05ba78e4 27#include "ospfd/ospf_dump.h"
edd7c245 28
718e3744 29/* Join to the OSPF ALL SPF ROUTERS multicast group. */
d62a17ae 30int ospf_if_add_allspfrouters(struct ospf *top, struct prefix *p,
31 ifindex_t ifindex)
718e3744 32{
d62a17ae 33 int ret;
34
35 ret = setsockopt_ipv4_multicast(top->fd, IP_ADD_MEMBERSHIP,
36 p->u.prefix4, htonl(OSPF_ALLSPFROUTERS),
37 ifindex);
38 if (ret < 0)
ade6974d 39 flog_err(
450971aa 40 EC_LIB_SOCKET,
96b663a3
MS
41 "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?",
42 top->fd, &p->u.prefix4, ifindex,
ade6974d 43 safe_strerror(errno));
05ba78e4
CS
44 else {
45 if (IS_DEBUG_OSPF_EVENT)
996c9314 46 zlog_debug(
96b663a3
MS
47 "interface %pI4 [%u] join AllSPFRouters Multicast group.",
48 &p->u.prefix4, ifindex);
05ba78e4 49 }
d62a17ae 50
51 return ret;
718e3744 52}
53
d62a17ae 54int ospf_if_drop_allspfrouters(struct ospf *top, struct prefix *p,
55 ifindex_t ifindex)
718e3744 56{
d62a17ae 57 int ret;
58
59 ret = setsockopt_ipv4_multicast(top->fd, IP_DROP_MEMBERSHIP,
60 p->u.prefix4, htonl(OSPF_ALLSPFROUTERS),
61 ifindex);
62 if (ret < 0)
450971aa 63 flog_err(EC_LIB_SOCKET,
96b663a3
MS
64 "can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %pI4, ifindex %u, AllSPFRouters): %s",
65 top->fd, &p->u.prefix4, ifindex,
abcc171c 66 safe_strerror(errno));
05ba78e4
CS
67 else {
68 if (IS_DEBUG_OSPF_EVENT)
996c9314 69 zlog_debug(
96b663a3
MS
70 "interface %pI4 [%u] leave AllSPFRouters Multicast group.",
71 &p->u.prefix4, ifindex);
05ba78e4 72 }
d62a17ae 73
74 return ret;
718e3744 75}
76
77/* Join to the OSPF ALL Designated ROUTERS multicast group. */
d62a17ae 78int ospf_if_add_alldrouters(struct ospf *top, struct prefix *p,
79 ifindex_t ifindex)
718e3744 80{
d62a17ae 81 int ret;
82
83 ret = setsockopt_ipv4_multicast(top->fd, IP_ADD_MEMBERSHIP,
84 p->u.prefix4, htonl(OSPF_ALLDROUTERS),
85 ifindex);
86 if (ret < 0)
ade6974d 87 flog_err(
450971aa 88 EC_LIB_SOCKET,
96b663a3
MS
89 "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?",
90 top->fd, &p->u.prefix4, ifindex,
ade6974d 91 safe_strerror(errno));
15e78e64
DS
92 else {
93 if (IS_DEBUG_OSPF_EVENT)
94 zlog_debug(
95 "interface %pI4 [%u] join AllDRouters Multicast group.",
96 &p->u.prefix4, ifindex);
97 }
d62a17ae 98 return ret;
718e3744 99}
100
d62a17ae 101int ospf_if_drop_alldrouters(struct ospf *top, struct prefix *p,
102 ifindex_t ifindex)
718e3744 103{
d62a17ae 104 int ret;
105
106 ret = setsockopt_ipv4_multicast(top->fd, IP_DROP_MEMBERSHIP,
107 p->u.prefix4, htonl(OSPF_ALLDROUTERS),
108 ifindex);
109 if (ret < 0)
450971aa 110 flog_err(EC_LIB_SOCKET,
96b663a3
MS
111 "can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %pI4, ifindex %u, AllDRouters): %s",
112 top->fd, &p->u.prefix4, ifindex,
abcc171c 113 safe_strerror(errno));
d62a17ae 114 else
115 zlog_debug(
96b663a3
MS
116 "interface %pI4 [%u] leave AllDRouters Multicast group.",
117 &p->u.prefix4, ifindex);
d62a17ae 118
119 return ret;
718e3744 120}
121
d62a17ae 122int ospf_if_ipmulticast(struct ospf *top, struct prefix *p, ifindex_t ifindex)
718e3744 123{
d7c0a89a 124 uint8_t val;
d62a17ae 125 int ret, len;
126
127 /* Prevent receiving self-origined multicast packets. */
128 ret = setsockopt_ipv4_multicast_loop(top->fd, 0);
129 if (ret < 0)
450971aa 130 flog_err(EC_LIB_SOCKET,
abcc171c
DS
131 "can't setsockopt IP_MULTICAST_LOOP(0) for fd %d: %s",
132 top->fd, safe_strerror(errno));
d62a17ae 133
134 /* Explicitly set multicast ttl to 1 -- endo. */
135 val = 1;
136 len = sizeof(val);
137 ret = setsockopt(top->fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&val,
138 len);
139 if (ret < 0)
450971aa 140 flog_err(EC_LIB_SOCKET,
abcc171c
DS
141 "can't setsockopt IP_MULTICAST_TTL(1) for fd %d: %s",
142 top->fd, safe_strerror(errno));
e1b18df1
CS
143#ifndef GNU_LINUX
144 /* For GNU LINUX ospf_write uses IP_PKTINFO, in_pktinfo to send
145 * packet out of ifindex. Below would be used Non Linux system.
146 */
147 ret = setsockopt_ipv4_multicast_if(top->fd, p->u.prefix4, ifindex);
148 if (ret < 0)
450971aa 149 flog_err(EC_LIB_SOCKET,
96b663a3
MS
150 "can't setsockopt IP_MULTICAST_IF(fd %d, addr %pI4, ifindex %u): %s",
151 top->fd, &p->u.prefix4, ifindex,
abcc171c 152 safe_strerror(errno));
e1b18df1 153#endif
d62a17ae 154
e7503eab
CS
155 return ret;
156}
157
e7503eab 158int ospf_sock_init(struct ospf *ospf)
718e3744 159{
d62a17ae 160 int ospf_sock;
161 int ret, hincl = 1;
162 int bufsize = (8 * 1024 * 1024);
163
3c0eb8fa
PG
164 /* silently ignore. already done */
165 if (ospf->fd > 0)
166 return -1;
167
168 if (ospf->vrf_id == VRF_UNKNOWN) {
169 /* silently return since VRF is not ready */
170 return -1;
171 }
0cf6db21 172 frr_with_privs(&ospfd_privs) {
6bb30c2c
DL
173 ospf_sock = vrf_socket(AF_INET, SOCK_RAW, IPPROTO_OSPFIGP,
174 ospf->vrf_id, ospf->name);
175 if (ospf_sock < 0) {
450971aa 176 flog_err(EC_LIB_SOCKET,
abcc171c 177 "ospf_read_sock_init: socket: %s",
6bb30c2c 178 safe_strerror(errno));
95d7a42a 179 return -1;
6bb30c2c 180 }
d62a17ae 181
5bd4189c 182#ifdef IP_HDRINCL
6bb30c2c
DL
183 /* we will include IP header with packet */
184 ret = setsockopt(ospf_sock, IPPROTO_IP, IP_HDRINCL, &hincl,
185 sizeof(hincl));
186 if (ret < 0) {
450971aa 187 flog_err(EC_LIB_SOCKET,
abcc171c
DS
188 "Can't set IP_HDRINCL option for fd %d: %s",
189 ospf_sock, safe_strerror(errno));
6bb30c2c
DL
190 break;
191 }
d62a17ae 192#elif defined(IPTOS_PREC_INTERNETCONTROL)
5bd4189c 193#warning "IP_HDRINCL not available on this system"
194#warning "using IPTOS_PREC_INTERNETCONTROL"
6bb30c2c
DL
195 ret = setsockopt_ipv4_tos(ospf_sock,
196 IPTOS_PREC_INTERNETCONTROL);
197 if (ret < 0) {
450971aa 198 flog_err(EC_LIB_SOCKET,
abcc171c
DS
199 "can't set sockopt IP_TOS %d to socket %d: %s",
200 tos, ospf_sock, safe_strerror(errno));
6bb30c2c
DL
201 break;
202 }
5bd4189c 203#else /* !IPTOS_PREC_INTERNETCONTROL */
204#warning "IP_HDRINCL not available, nor is IPTOS_PREC_INTERNETCONTROL"
1c50c1c0 205 flog_err(EC_LIB_UNAVAILABLE, "IP_HDRINCL option not available");
5bd4189c 206#endif /* IP_HDRINCL */
718e3744 207
6bb30c2c 208 ret = setsockopt_ifindex(AF_INET, ospf_sock, 1);
ac191232 209
6bb30c2c 210 if (ret < 0)
450971aa 211 flog_err(EC_LIB_SOCKET,
abcc171c
DS
212 "Can't set pktinfo option for fd %d",
213 ospf_sock);
6bb30c2c 214 }
e7503eab 215
338b8e91
RW
216 setsockopt_so_sendbuf(ospf_sock, bufsize);
217 setsockopt_so_recvbuf(ospf_sock, bufsize);
218
e7503eab 219 ospf->fd = ospf_sock;
e7503eab 220 return ret;
718e3744 221}