]> git.proxmox.com Git - mirror_frr.git/blob - ospfd/ospf_network.c
Merge pull request #2804 from kssoman/bgp_fix
[mirror_frr.git] / ospfd / ospf_network.c
1 /*
2 * OSPF network related functions
3 * Copyright (C) 1999 Toshiaki Takada
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include <zebra.h>
23
24 #include "thread.h"
25 #include "linklist.h"
26 #include "prefix.h"
27 #include "if.h"
28 #include "sockunion.h"
29 #include "log.h"
30 #include "sockopt.h"
31 #include "privs.h"
32 #include "lib_errors.h"
33
34 #include "ospfd/ospfd.h"
35 #include "ospfd/ospf_network.h"
36 #include "ospfd/ospf_interface.h"
37 #include "ospfd/ospf_asbr.h"
38 #include "ospfd/ospf_lsa.h"
39 #include "ospfd/ospf_lsdb.h"
40 #include "ospfd/ospf_neighbor.h"
41 #include "ospfd/ospf_packet.h"
42 #include "ospfd/ospf_dump.h"
43
44 /* Join to the OSPF ALL SPF ROUTERS multicast group. */
45 int ospf_if_add_allspfrouters(struct ospf *top, struct prefix *p,
46 ifindex_t ifindex)
47 {
48 int ret;
49
50 ret = setsockopt_ipv4_multicast(top->fd, IP_ADD_MEMBERSHIP,
51 p->u.prefix4, htonl(OSPF_ALLSPFROUTERS),
52 ifindex);
53 if (ret < 0)
54 zlog_warn(
55 "can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, "
56 "ifindex %u, AllSPFRouters): %s; perhaps a kernel limit "
57 "on # of multicast group memberships has been exceeded?",
58 top->fd, inet_ntoa(p->u.prefix4), ifindex,
59 safe_strerror(errno));
60 else {
61 if (IS_DEBUG_OSPF_EVENT)
62 zlog_debug(
63 "interface %s [%u] join AllSPFRouters Multicast group.",
64 inet_ntoa(p->u.prefix4), ifindex);
65 }
66
67 return ret;
68 }
69
70 int ospf_if_drop_allspfrouters(struct ospf *top, struct prefix *p,
71 ifindex_t ifindex)
72 {
73 int ret;
74
75 ret = setsockopt_ipv4_multicast(top->fd, IP_DROP_MEMBERSHIP,
76 p->u.prefix4, htonl(OSPF_ALLSPFROUTERS),
77 ifindex);
78 if (ret < 0)
79 zlog_warn(
80 "can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, "
81 "ifindex %u, AllSPFRouters): %s",
82 top->fd, inet_ntoa(p->u.prefix4), ifindex,
83 safe_strerror(errno));
84 else {
85 if (IS_DEBUG_OSPF_EVENT)
86 zlog_debug(
87 "interface %s [%u] leave AllSPFRouters Multicast group.",
88 inet_ntoa(p->u.prefix4), ifindex);
89 }
90
91 return ret;
92 }
93
94 /* Join to the OSPF ALL Designated ROUTERS multicast group. */
95 int ospf_if_add_alldrouters(struct ospf *top, struct prefix *p,
96 ifindex_t ifindex)
97 {
98 int ret;
99
100 ret = setsockopt_ipv4_multicast(top->fd, IP_ADD_MEMBERSHIP,
101 p->u.prefix4, htonl(OSPF_ALLDROUTERS),
102 ifindex);
103 if (ret < 0)
104 zlog_warn(
105 "can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, "
106 "ifindex %u, AllDRouters): %s; perhaps a kernel limit "
107 "on # of multicast group memberships has been exceeded?",
108 top->fd, inet_ntoa(p->u.prefix4), ifindex,
109 safe_strerror(errno));
110 else
111 zlog_debug(
112 "interface %s [%u] join AllDRouters Multicast group.",
113 inet_ntoa(p->u.prefix4), ifindex);
114
115 return ret;
116 }
117
118 int ospf_if_drop_alldrouters(struct ospf *top, struct prefix *p,
119 ifindex_t ifindex)
120 {
121 int ret;
122
123 ret = setsockopt_ipv4_multicast(top->fd, IP_DROP_MEMBERSHIP,
124 p->u.prefix4, htonl(OSPF_ALLDROUTERS),
125 ifindex);
126 if (ret < 0)
127 zlog_warn(
128 "can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, "
129 "ifindex %u, AllDRouters): %s",
130 top->fd, inet_ntoa(p->u.prefix4), ifindex,
131 safe_strerror(errno));
132 else
133 zlog_debug(
134 "interface %s [%u] leave AllDRouters Multicast group.",
135 inet_ntoa(p->u.prefix4), ifindex);
136
137 return ret;
138 }
139
140 int ospf_if_ipmulticast(struct ospf *top, struct prefix *p, ifindex_t ifindex)
141 {
142 uint8_t val;
143 int ret, len;
144
145 /* Prevent receiving self-origined multicast packets. */
146 ret = setsockopt_ipv4_multicast_loop(top->fd, 0);
147 if (ret < 0)
148 zlog_warn("can't setsockopt IP_MULTICAST_LOOP(0) for fd %d: %s",
149 top->fd, safe_strerror(errno));
150
151 /* Explicitly set multicast ttl to 1 -- endo. */
152 val = 1;
153 len = sizeof(val);
154 ret = setsockopt(top->fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&val,
155 len);
156 if (ret < 0)
157 zlog_warn("can't setsockopt IP_MULTICAST_TTL(1) for fd %d: %s",
158 top->fd, safe_strerror(errno));
159 #ifndef GNU_LINUX
160 /* For GNU LINUX ospf_write uses IP_PKTINFO, in_pktinfo to send
161 * packet out of ifindex. Below would be used Non Linux system.
162 */
163 ret = setsockopt_ipv4_multicast_if(top->fd, p->u.prefix4, ifindex);
164 if (ret < 0)
165 zlog_warn(
166 "can't setsockopt IP_MULTICAST_IF(fd %d, addr %s, "
167 "ifindex %u): %s",
168 top->fd, inet_ntoa(p->u.prefix4), ifindex,
169 safe_strerror(errno));
170 #endif
171
172 return ret;
173 }
174
175 int ospf_sock_init(struct ospf *ospf)
176 {
177 int ospf_sock;
178 int ret, hincl = 1;
179 int bufsize = (8 * 1024 * 1024);
180
181 /* silently ignore. already done */
182 if (ospf->fd > 0)
183 return -1;
184
185 if (ospf->vrf_id == VRF_UNKNOWN) {
186 /* silently return since VRF is not ready */
187 return -1;
188 }
189 frr_elevate_privs(&ospfd_privs) {
190 ospf_sock = vrf_socket(AF_INET, SOCK_RAW, IPPROTO_OSPFIGP,
191 ospf->vrf_id, ospf->name);
192 if (ospf_sock < 0) {
193 zlog_err("ospf_read_sock_init: socket: %s",
194 safe_strerror(errno));
195 exit(1);
196 }
197
198 #ifdef IP_HDRINCL
199 /* we will include IP header with packet */
200 ret = setsockopt(ospf_sock, IPPROTO_IP, IP_HDRINCL, &hincl,
201 sizeof(hincl));
202 if (ret < 0) {
203 zlog_warn("Can't set IP_HDRINCL option for fd %d: %s",
204 ospf_sock, safe_strerror(errno));
205 close(ospf_sock);
206 break;
207 }
208 #elif defined(IPTOS_PREC_INTERNETCONTROL)
209 #warning "IP_HDRINCL not available on this system"
210 #warning "using IPTOS_PREC_INTERNETCONTROL"
211 ret = setsockopt_ipv4_tos(ospf_sock,
212 IPTOS_PREC_INTERNETCONTROL);
213 if (ret < 0) {
214 zlog_warn("can't set sockopt IP_TOS %d to socket %d: %s",
215 tos, ospf_sock, safe_strerror(errno));
216 close(ospf_sock); /* Prevent sd leak. */
217 break;
218 }
219 #else /* !IPTOS_PREC_INTERNETCONTROL */
220 #warning "IP_HDRINCL not available, nor is IPTOS_PREC_INTERNETCONTROL"
221 zlog_warn("IP_HDRINCL option not available");
222 #endif /* IP_HDRINCL */
223
224 ret = setsockopt_ifindex(AF_INET, ospf_sock, 1);
225
226 if (ret < 0)
227 zlog_warn("Can't set pktinfo option for fd %d",
228 ospf_sock);
229
230 setsockopt_so_sendbuf(ospf_sock, bufsize);
231 setsockopt_so_recvbuf(ospf_sock, bufsize);
232 }
233
234 ospf->fd = ospf_sock;
235 return ret;
236 }