]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_network.c
Merge pull request #1369 from LabNConsulting/working/3.0/cherry-pick/minusS
[mirror_frr.git] / ospfd / ospf_network.c
CommitLineData
718e3744 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
18 * along with GNU Zebra; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25#include "thread.h"
26#include "linklist.h"
27#include "prefix.h"
28#include "if.h"
29#include "sockunion.h"
30#include "log.h"
31#include "sockopt.h"
edd7c245 32#include "privs.h"
33
34extern struct zebra_privs_t ospfd_privs;
718e3744 35
36#include "ospfd/ospfd.h"
37#include "ospfd/ospf_network.h"
38#include "ospfd/ospf_interface.h"
39#include "ospfd/ospf_asbr.h"
40#include "ospfd/ospf_lsa.h"
41#include "ospfd/ospf_lsdb.h"
42#include "ospfd/ospf_neighbor.h"
43#include "ospfd/ospf_packet.h"
44
edd7c245 45
718e3744 46/* Join to the OSPF ALL SPF ROUTERS multicast group. */
ac4d0be5 47int ospf_if_add_allspfrouters(struct ospf *top, struct prefix *p,
48 ifindex_t ifindex)
718e3744 49{
ac4d0be5 50 int ret;
51
52 ret = setsockopt_ipv4_multicast(top->fd, IP_ADD_MEMBERSHIP,
53 p->u.prefix4, htonl(OSPF_ALLSPFROUTERS),
54 ifindex);
55 if (ret < 0)
56 zlog_warn(
57 "can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, "
58 "ifindex %u, AllSPFRouters): %s; perhaps a kernel limit "
59 "on # of multicast group memberships has been exceeded?",
60 top->fd, inet_ntoa(p->u.prefix4), ifindex,
61 safe_strerror(errno));
62 else
63 zlog_debug(
64 "interface %s [%u] join AllSPFRouters Multicast group.",
65 inet_ntoa(p->u.prefix4), ifindex);
66
67 return ret;
718e3744 68}
69
ac4d0be5 70int ospf_if_drop_allspfrouters(struct ospf *top, struct prefix *p,
71 ifindex_t ifindex)
718e3744 72{
ac4d0be5 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 zlog_debug(
86 "interface %s [%u] leave AllSPFRouters Multicast group.",
87 inet_ntoa(p->u.prefix4), ifindex);
88
89 return ret;
718e3744 90}
91
92/* Join to the OSPF ALL Designated ROUTERS multicast group. */
ac4d0be5 93int ospf_if_add_alldrouters(struct ospf *top, struct prefix *p,
94 ifindex_t ifindex)
718e3744 95{
ac4d0be5 96 int ret;
97
98 ret = setsockopt_ipv4_multicast(top->fd, IP_ADD_MEMBERSHIP,
99 p->u.prefix4, htonl(OSPF_ALLDROUTERS),
100 ifindex);
101 if (ret < 0)
102 zlog_warn(
103 "can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, "
104 "ifindex %u, AllDRouters): %s; perhaps a kernel limit "
105 "on # of multicast group memberships has been exceeded?",
106 top->fd, inet_ntoa(p->u.prefix4), ifindex,
107 safe_strerror(errno));
108 else
109 zlog_debug(
110 "interface %s [%u] join AllDRouters Multicast group.",
111 inet_ntoa(p->u.prefix4), ifindex);
112
113 return ret;
718e3744 114}
115
ac4d0be5 116int ospf_if_drop_alldrouters(struct ospf *top, struct prefix *p,
117 ifindex_t ifindex)
718e3744 118{
ac4d0be5 119 int ret;
120
121 ret = setsockopt_ipv4_multicast(top->fd, IP_DROP_MEMBERSHIP,
122 p->u.prefix4, htonl(OSPF_ALLDROUTERS),
123 ifindex);
124 if (ret < 0)
125 zlog_warn(
126 "can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, "
127 "ifindex %u, AllDRouters): %s",
128 top->fd, inet_ntoa(p->u.prefix4), ifindex,
129 safe_strerror(errno));
130 else
131 zlog_debug(
132 "interface %s [%u] leave AllDRouters Multicast group.",
133 inet_ntoa(p->u.prefix4), ifindex);
134
135 return ret;
718e3744 136}
137
ac4d0be5 138int ospf_if_ipmulticast(struct ospf *top, struct prefix *p, ifindex_t ifindex)
718e3744 139{
ac4d0be5 140 u_char val;
141 int ret, len;
142
143 /* Prevent receiving self-origined multicast packets. */
144 ret = setsockopt_ipv4_multicast_loop(top->fd, 0);
145 if (ret < 0)
146 zlog_warn("can't setsockopt IP_MULTICAST_LOOP(0) for fd %d: %s",
147 top->fd, safe_strerror(errno));
148
149 /* Explicitly set multicast ttl to 1 -- endo. */
150 val = 1;
151 len = sizeof(val);
152 ret = setsockopt(top->fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&val,
153 len);
154 if (ret < 0)
155 zlog_warn("can't setsockopt IP_MULTICAST_TTL(1) for fd %d: %s",
156 top->fd, safe_strerror(errno));
157
158 ret = setsockopt_ipv4_multicast_if(top->fd, p->u.prefix4, ifindex);
159 if (ret < 0)
160 zlog_warn(
161 "can't setsockopt IP_MULTICAST_IF(fd %d, addr %s, "
162 "ifindex %u): %s",
163 top->fd, inet_ntoa(p->u.prefix4), ifindex,
164 safe_strerror(errno));
165
166 return ret;
718e3744 167}
168
ac4d0be5 169int ospf_sock_init(void)
718e3744 170{
ac4d0be5 171 int ospf_sock;
172 int ret, hincl = 1;
173 int bufsize = (8 * 1024 * 1024);
174
175 if (ospfd_privs.change(ZPRIVS_RAISE))
176 zlog_err("ospf_sock_init: could not raise privs, %s",
177 safe_strerror(errno));
178
179 ospf_sock = socket(AF_INET, SOCK_RAW, IPPROTO_OSPFIGP);
180 if (ospf_sock < 0) {
181 int save_errno = errno;
182 if (ospfd_privs.change(ZPRIVS_LOWER))
183 zlog_err("ospf_sock_init: could not lower privs, %s",
184 safe_strerror(errno));
185 zlog_err("ospf_read_sock_init: socket: %s",
186 safe_strerror(save_errno));
187 exit(1);
188 }
189
5bd4189c 190#ifdef IP_HDRINCL
ac4d0be5 191 /* we will include IP header with packet */
192 ret = setsockopt(ospf_sock, IPPROTO_IP, IP_HDRINCL, &hincl,
193 sizeof(hincl));
194 if (ret < 0) {
195 int save_errno = errno;
196 if (ospfd_privs.change(ZPRIVS_LOWER))
197 zlog_err("ospf_sock_init: could not lower privs, %s",
198 safe_strerror(errno));
199 zlog_warn("Can't set IP_HDRINCL option for fd %d: %s",
200 ospf_sock, safe_strerror(save_errno));
201 }
202#elif defined(IPTOS_PREC_INTERNETCONTROL)
5bd4189c 203#warning "IP_HDRINCL not available on this system"
204#warning "using IPTOS_PREC_INTERNETCONTROL"
ac4d0be5 205 ret = setsockopt_ipv4_tos(ospf_sock, IPTOS_PREC_INTERNETCONTROL);
206 if (ret < 0) {
207 int save_errno = errno;
208 if (ospfd_privs.change(ZPRIVS_LOWER))
209 zlog_err("ospf_sock_init: could not lower privs, %s",
210 safe_strerror(errno));
211 zlog_warn("can't set sockopt IP_TOS %d to socket %d: %s", tos,
212 ospf_sock, safe_strerror(save_errno));
213 close(ospf_sock); /* Prevent sd leak. */
214 return ret;
215 }
5bd4189c 216#else /* !IPTOS_PREC_INTERNETCONTROL */
217#warning "IP_HDRINCL not available, nor is IPTOS_PREC_INTERNETCONTROL"
ac4d0be5 218 zlog_warn("IP_HDRINCL option not available");
5bd4189c 219#endif /* IP_HDRINCL */
718e3744 220
ac4d0be5 221 ret = setsockopt_ifindex(AF_INET, ospf_sock, 1);
ac191232 222
ac4d0be5 223 if (ret < 0)
224 zlog_warn("Can't set pktinfo option for fd %d", ospf_sock);
edd7c245 225
ac4d0be5 226 if (ospfd_privs.change(ZPRIVS_LOWER)) {
227 zlog_err("ospf_sock_init: could not lower privs, %s",
228 safe_strerror(errno));
229 }
a78d75b0 230
ac4d0be5 231 setsockopt_so_sendbuf(ospf_sock, bufsize);
232 setsockopt_so_recvbuf(ospf_sock, bufsize);
a78d75b0 233
ac4d0be5 234 return ospf_sock;
718e3744 235}