]> git.proxmox.com Git - mirror_frr.git/blame - zebra/connected.c
[build] Set default CFLAGS for SunPro, rationalise CFLAGS defaults.
[mirror_frr.git] / zebra / connected.c
CommitLineData
718e3744 1/*
2 * Address linked list routine.
3 * Copyright (C) 1997, 98 Kunihiro Ishiguro
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 "prefix.h"
26#include "linklist.h"
27#include "if.h"
28#include "table.h"
29#include "rib.h"
30#include "table.h"
31#include "log.h"
0752ef0b 32#include "memory.h"
718e3744 33
34#include "zebra/zserv.h"
35#include "zebra/redistribute.h"
eef1fe11 36#include "zebra/interface.h"
a1ac18c4 37#include "zebra/connected.h"
718e3744 38\f
ca16218d 39/* withdraw a connected address */
40static void
41connected_withdraw (struct connected *ifc)
42{
43 if (! ifc)
44 return;
45
46 /* Update interface address information to protocol daemon. */
47 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
48 {
49 zebra_interface_address_delete_update (ifc->ifp, ifc);
50
51 if_subnet_delete (ifc->ifp, ifc);
52
53 if (ifc->address->family == AF_INET)
54 connected_down_ipv4 (ifc->ifp, ifc);
aa2e32be 55#ifdef HAVE_IPV6
ca16218d 56 else
57 connected_down_ipv6 (ifc->ifp, ifc);
aa2e32be 58#endif
ca16218d 59
60 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
61 }
62
63 listnode_delete (ifc->ifp->connected, ifc);
64 connected_free (ifc);
65}
66
67static void
68connected_announce (struct interface *ifp, struct connected *ifc)
69{
70 if (!ifc)
71 return;
72
73 listnode_add (ifp->connected, ifc);
74
75 /* Update interface address information to protocol daemon. */
76 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
77 {
78 if (ifc->address->family == AF_INET)
79 if_subnet_add (ifp, ifc);
80
81 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
82
83 zebra_interface_address_add_update (ifp, ifc);
84
85 if (if_is_up(ifp))
86 {
87 if (ifc->address->family == AF_INET)
88 connected_up_ipv4 (ifp, ifc);
aa2e32be 89#ifdef HAVE_IPV6
ca16218d 90 else
91 connected_up_ipv6 (ifp, ifc);
aa2e32be 92#endif
ca16218d 93 }
94 }
95}
96\f
718e3744 97/* If same interface address is already exist... */
98struct connected *
ca16218d 99connected_check (struct interface *ifp, struct prefix *p)
718e3744 100{
101 struct connected *ifc;
52dc7ee6 102 struct listnode *node;
718e3744 103
1eb8ef25 104 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc))
105 if (prefix_same (ifc->address, p))
106 return ifc;
718e3744 107
718e3744 108 return NULL;
109}
110
111/* Called from if_up(). */
112void
113connected_up_ipv4 (struct interface *ifp, struct connected *ifc)
114{
115 struct prefix_ipv4 p;
116 struct prefix_ipv4 *addr;
117 struct prefix_ipv4 *dest;
118
119 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
120 return;
121
122 addr = (struct prefix_ipv4 *) ifc->address;
123 dest = (struct prefix_ipv4 *) ifc->destination;
124
125 memset (&p, 0, sizeof (struct prefix_ipv4));
126 p.family = AF_INET;
127 p.prefixlen = addr->prefixlen;
128
129 /* Point-to-point check. */
3fb9cd6e 130 if (CONNECTED_POINTOPOINT_HOST(ifc))
718e3744 131 p.prefix = dest->prefix;
132 else
133 p.prefix = addr->prefix;
134
135 /* Apply mask to the network. */
136 apply_mask_ipv4 (&p);
137
138 /* In case of connected address is 0.0.0.0/0 we treat it tunnel
139 address. */
140 if (prefix_ipv4_any (&p))
141 return;
142
143 rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, 0, 0);
144
145 rib_update ();
146}
147
148/* Add connected IPv4 route to the interface. */
149void
150connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
d06b2a64 151 u_char prefixlen, struct in_addr *broad,
152 const char *label)
718e3744 153{
154 struct prefix_ipv4 *p;
155 struct connected *ifc;
156 struct connected *current;
157
158 /* Make connected structure. */
159 ifc = connected_new ();
160 ifc->ifp = ifp;
161 ifc->flags = flags;
162
163 /* Allocate new connected address. */
164 p = prefix_ipv4_new ();
165 p->family = AF_INET;
166 p->prefix = *addr;
167 p->prefixlen = prefixlen;
168 ifc->address = (struct prefix *) p;
ca16218d 169
718e3744 170 /* If there is broadcast or pointopoint address. */
171 if (broad)
172 {
173 p = prefix_ipv4_new ();
174 p->family = AF_INET;
175 p->prefix = *broad;
176 ifc->destination = (struct prefix *) p;
3fb9cd6e 177
178 /* validate the destination address */
179 if (ifp->flags & IFF_POINTOPOINT)
180 {
181 if (IPV4_ADDR_SAME(addr,broad))
182 zlog_warn("warning: PtP interface %s has same local and peer "
183 "address %s, routing protocols may malfunction",
184 ifp->name,inet_ntoa(*addr));
185 else if ((prefixlen != IPV4_MAX_PREFIXLEN) &&
186 (ipv4_network_addr(addr->s_addr,prefixlen) !=
187 ipv4_network_addr(broad->s_addr,prefixlen)))
188 {
189 char buf[2][INET_ADDRSTRLEN];
190 zlog_warn("warning: PtP interface %s network mismatch: local "
191 "%s/%d vs. peer %s, routing protocols may malfunction",
192 ifp->name,
193 inet_ntop (AF_INET, addr, buf[0], sizeof(buf[0])),
194 prefixlen,
195 inet_ntop (AF_INET, broad, buf[1], sizeof(buf[1])));
196 }
197 }
198 else
199 {
200 if (broad->s_addr != ipv4_broadcast_addr(addr->s_addr,prefixlen))
201 {
202 char buf[2][INET_ADDRSTRLEN];
203 struct in_addr bcalc;
204 bcalc.s_addr = ipv4_broadcast_addr(addr->s_addr,prefixlen);
205 zlog_warn("warning: interface %s broadcast addr %s/%d != "
206 "calculated %s, routing protocols may malfunction",
207 ifp->name,
208 inet_ntop (AF_INET, broad, buf[0], sizeof(buf[0])),
209 prefixlen,
210 inet_ntop (AF_INET, &bcalc, buf[1], sizeof(buf[1])));
211 }
212 }
213
718e3744 214 }
3fb9cd6e 215 else
216 /* no broadcast or destination address was supplied */
341a8f1a 217 if ((prefixlen == IPV4_MAX_PREFIXLEN) && if_is_pointopoint(ifp))
218 zlog_warn("warning: PtP interface %s with addr %s/%d needs a "
219 "peer address",ifp->name,inet_ntoa(*addr),prefixlen);
718e3744 220
221 /* Label of this address. */
222 if (label)
0752ef0b 223 ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
718e3744 224
225 /* Check same connected route. */
ca16218d 226 if ((current = connected_check (ifp, (struct prefix *) ifc->address)))
227 connected_withdraw (current); /* implicit withdraw - freebsd does this */
228
229 connected_announce (ifp, ifc);
718e3744 230}
231
232void
233connected_down_ipv4 (struct interface *ifp, struct connected *ifc)
234{
235 struct prefix_ipv4 p;
236 struct prefix_ipv4 *addr;
237 struct prefix_ipv4 *dest;
238
239 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
240 return;
241
242 addr = (struct prefix_ipv4 *)ifc->address;
243 dest = (struct prefix_ipv4 *)ifc->destination;
244
245 memset (&p, 0, sizeof (struct prefix_ipv4));
246 p.family = AF_INET;
247 p.prefixlen = addr->prefixlen;
248
960182aa 249 /* Point-to-point check. */
3fb9cd6e 250 if (CONNECTED_POINTOPOINT_HOST(ifc))
718e3744 251 p.prefix = dest->prefix;
252 else
253 p.prefix = addr->prefix;
254
255 /* Apply mask to the network. */
256 apply_mask_ipv4 (&p);
257
258 /* In case of connected address is 0.0.0.0/0 we treat it tunnel
259 address. */
260 if (prefix_ipv4_any (&p))
261 return;
262
263 rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);
264
265 rib_update ();
266}
267
268/* Delete connected IPv4 route to the interface. */
269void
270connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
0752ef0b 271 u_char prefixlen, struct in_addr *broad)
718e3744 272{
273 struct prefix_ipv4 p;
274 struct connected *ifc;
275
276 memset (&p, 0, sizeof (struct prefix_ipv4));
277 p.family = AF_INET;
278 p.prefix = *addr;
279 p.prefixlen = prefixlen;
280
ca16218d 281 ifc = connected_check (ifp, (struct prefix *) &p);
718e3744 282 if (! ifc)
283 return;
ca16218d 284
285 connected_withdraw (ifc);
718e3744 286}
287
288#ifdef HAVE_IPV6
718e3744 289void
290connected_up_ipv6 (struct interface *ifp, struct connected *ifc)
291{
292 struct prefix_ipv6 p;
293 struct prefix_ipv6 *addr;
294 struct prefix_ipv6 *dest;
295
296 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
297 return;
298
299 addr = (struct prefix_ipv6 *) ifc->address;
300 dest = (struct prefix_ipv6 *) ifc->destination;
301
302 memset (&p, 0, sizeof (struct prefix_ipv6));
303 p.family = AF_INET6;
304 p.prefixlen = addr->prefixlen;
305
31a476c7 306 if (if_is_pointopoint (ifp) && dest)
718e3744 307 {
308 if (IN6_IS_ADDR_UNSPECIFIED (&dest->prefix))
309 p.prefix = addr->prefix;
310 else
311 p.prefix = dest->prefix;
312 }
313 else
314 p.prefix = addr->prefix;
315
316 /* Apply mask to the network. */
317 apply_mask_ipv6 (&p);
318
726f9b2b 319#if ! defined (MUSICA) && ! defined (LINUX)
320 /* XXX: It is already done by rib_bogus_ipv6 within rib_add_ipv6 */
718e3744 321 if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
322 return;
726f9b2b 323#endif
718e3744 324
be61c4eb 325 rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, 0, 0);
718e3744 326
327 rib_update ();
328}
329
330/* Add connected IPv6 route to the interface. */
331void
332connected_add_ipv6 (struct interface *ifp, struct in6_addr *addr,
0752ef0b 333 u_char prefixlen, struct in6_addr *broad, char *label)
718e3744 334{
335 struct prefix_ipv6 *p;
336 struct connected *ifc;
337 struct connected *current;
338
339 /* Make connected structure. */
340 ifc = connected_new ();
341 ifc->ifp = ifp;
342
343 /* Allocate new connected address. */
344 p = prefix_ipv6_new ();
345 p->family = AF_INET6;
346 IPV6_ADDR_COPY (&p->prefix, addr);
347 p->prefixlen = prefixlen;
348 ifc->address = (struct prefix *) p;
349
350 /* If there is broadcast or pointopoint address. */
351 if (broad)
352 {
353 p = prefix_ipv6_new ();
354 p->family = AF_INET6;
355 IPV6_ADDR_COPY (&p->prefix, broad);
356 ifc->destination = (struct prefix *) p;
357 }
358
0752ef0b 359 /* Label of this address. */
360 if (label)
361 ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
362
ca16218d 363 if ((current = connected_check (ifp, (struct prefix *) ifc->address)))
364 connected_withdraw (current); /* implicit update of existing address */
365
366 connected_announce (ifp, ifc);
718e3744 367}
368
369void
370connected_down_ipv6 (struct interface *ifp, struct connected *ifc)
371{
372 struct prefix_ipv6 p;
373 struct prefix_ipv6 *addr;
374 struct prefix_ipv6 *dest;
375
376 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
377 return;
378
379 addr = (struct prefix_ipv6 *) ifc->address;
380 dest = (struct prefix_ipv6 *) ifc->destination;
381
382 memset (&p, 0, sizeof (struct prefix_ipv6));
383 p.family = AF_INET6;
384 p.prefixlen = addr->prefixlen;
385
31a476c7 386 if (if_is_pointopoint (ifp) && dest)
718e3744 387 {
388 if (IN6_IS_ADDR_UNSPECIFIED (&dest->prefix))
389 p.prefix = addr->prefix;
390 else
391 p.prefix = dest->prefix;
392 }
393 else
394 p.prefix = addr->prefix;
395
396 apply_mask_ipv6 (&p);
397
398 if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
399 return;
400
401 rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);
402
403 rib_update ();
404}
405
406void
407connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address,
fce954f8 408 u_char prefixlen, struct in6_addr *broad)
718e3744 409{
410 struct prefix_ipv6 p;
411 struct connected *ifc;
412
413 memset (&p, 0, sizeof (struct prefix_ipv6));
414 p.family = AF_INET6;
415 memcpy (&p.prefix, address, sizeof (struct in6_addr));
416 p.prefixlen = prefixlen;
417
ca16218d 418 ifc = connected_check (ifp, (struct prefix *) &p);
718e3744 419 if (! ifc)
420 return;
421
ca16218d 422 connected_withdraw (ifc);
718e3744 423}
424#endif /* HAVE_IPV6 */