]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_network.c
Merge pull request #13183 from Pdoijode/pdoijode/pim-json-changes
[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
24a58196 9#include "frrevent.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));
6e6e1020 114 else if (IS_DEBUG_OSPF_EVENT)
d62a17ae 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;
d62a17ae 162
3c0eb8fa
PG
163 /* silently ignore. already done */
164 if (ospf->fd > 0)
165 return -1;
166
167 if (ospf->vrf_id == VRF_UNKNOWN) {
168 /* silently return since VRF is not ready */
169 return -1;
170 }
0cf6db21 171 frr_with_privs(&ospfd_privs) {
6bb30c2c
DL
172 ospf_sock = vrf_socket(AF_INET, SOCK_RAW, IPPROTO_OSPFIGP,
173 ospf->vrf_id, ospf->name);
174 if (ospf_sock < 0) {
450971aa 175 flog_err(EC_LIB_SOCKET,
abcc171c 176 "ospf_read_sock_init: socket: %s",
6bb30c2c 177 safe_strerror(errno));
95d7a42a 178 return -1;
6bb30c2c 179 }
d62a17ae 180
5bd4189c 181#ifdef IP_HDRINCL
6bb30c2c
DL
182 /* we will include IP header with packet */
183 ret = setsockopt(ospf_sock, IPPROTO_IP, IP_HDRINCL, &hincl,
184 sizeof(hincl));
185 if (ret < 0) {
450971aa 186 flog_err(EC_LIB_SOCKET,
abcc171c
DS
187 "Can't set IP_HDRINCL option for fd %d: %s",
188 ospf_sock, safe_strerror(errno));
6bb30c2c
DL
189 break;
190 }
d62a17ae 191#elif defined(IPTOS_PREC_INTERNETCONTROL)
5bd4189c 192#warning "IP_HDRINCL not available on this system"
193#warning "using IPTOS_PREC_INTERNETCONTROL"
6bb30c2c
DL
194 ret = setsockopt_ipv4_tos(ospf_sock,
195 IPTOS_PREC_INTERNETCONTROL);
196 if (ret < 0) {
450971aa 197 flog_err(EC_LIB_SOCKET,
abcc171c
DS
198 "can't set sockopt IP_TOS %d to socket %d: %s",
199 tos, ospf_sock, safe_strerror(errno));
6bb30c2c
DL
200 break;
201 }
5bd4189c 202#else /* !IPTOS_PREC_INTERNETCONTROL */
203#warning "IP_HDRINCL not available, nor is IPTOS_PREC_INTERNETCONTROL"
1c50c1c0 204 flog_err(EC_LIB_UNAVAILABLE, "IP_HDRINCL option not available");
5bd4189c 205#endif /* IP_HDRINCL */
718e3744 206
6bb30c2c 207 ret = setsockopt_ifindex(AF_INET, ospf_sock, 1);
ac191232 208
6bb30c2c 209 if (ret < 0)
450971aa 210 flog_err(EC_LIB_SOCKET,
abcc171c
DS
211 "Can't set pktinfo option for fd %d",
212 ospf_sock);
6bb30c2c 213 }
e7503eab 214
6e6e1020
MS
215 /* Update socket buffer sizes */
216 ospf_sock_bufsize_update(ospf, ospf_sock, OSPF_SOCK_BOTH);
338b8e91 217
e7503eab 218 ospf->fd = ospf_sock;
e7503eab 219 return ret;
718e3744 220}
6e6e1020
MS
221
222/*
223 * Update a socket bufsize(s), based on its ospf instance
224 */
225void ospf_sock_bufsize_update(const struct ospf *ospf, int sock,
226 enum ospf_sock_type_e type)
227{
228 int bufsize;
229
230 if (type == OSPF_SOCK_BOTH || type == OSPF_SOCK_RECV) {
231 bufsize = ospf->recv_sock_bufsize;
232 setsockopt_so_recvbuf(sock, bufsize);
233 }
234
235 if (type == OSPF_SOCK_BOTH || type == OSPF_SOCK_SEND) {
236 bufsize = ospf->send_sock_bufsize;
237 setsockopt_so_sendbuf(sock, bufsize);
238 }
239}