blob: 3ce59530f30e6ac910732a1f724da7c86f5daae3 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
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"
32
33#include "zebra/zserv.h"
34#include "zebra/redistribute.h"
hassoeef1fe12004-10-03 18:46:08 +000035#include "zebra/interface.h"
paul718e3742002-12-13 20:15:29 +000036
37/* If same interface address is already exist... */
38struct connected *
39connected_check_ipv4 (struct interface *ifp, struct prefix *p)
40{
41 struct connected *ifc;
hasso52dc7ee2004-09-23 19:18:23 +000042 struct listnode *node;
paul718e3742002-12-13 20:15:29 +000043
paul1eb8ef22005-04-07 07:30:20 +000044 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc))
45 if (prefix_same (ifc->address, p))
46 return ifc;
paul718e3742002-12-13 20:15:29 +000047
paul718e3742002-12-13 20:15:29 +000048 return NULL;
49}
50
51/* Called from if_up(). */
52void
53connected_up_ipv4 (struct interface *ifp, struct connected *ifc)
54{
55 struct prefix_ipv4 p;
56 struct prefix_ipv4 *addr;
57 struct prefix_ipv4 *dest;
58
59 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
60 return;
61
62 addr = (struct prefix_ipv4 *) ifc->address;
63 dest = (struct prefix_ipv4 *) ifc->destination;
64
65 memset (&p, 0, sizeof (struct prefix_ipv4));
66 p.family = AF_INET;
67 p.prefixlen = addr->prefixlen;
68
69 /* Point-to-point check. */
hasso3fb9cd62004-10-19 19:44:43 +000070 if (CONNECTED_POINTOPOINT_HOST(ifc))
paul718e3742002-12-13 20:15:29 +000071 p.prefix = dest->prefix;
72 else
73 p.prefix = addr->prefix;
74
75 /* Apply mask to the network. */
76 apply_mask_ipv4 (&p);
77
78 /* In case of connected address is 0.0.0.0/0 we treat it tunnel
79 address. */
80 if (prefix_ipv4_any (&p))
81 return;
82
83 rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, 0, 0);
84
85 rib_update ();
86}
87
88/* Add connected IPv4 route to the interface. */
89void
90connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
91 int prefixlen, struct in_addr *broad, char *label)
92{
93 struct prefix_ipv4 *p;
94 struct connected *ifc;
95 struct connected *current;
96
97 /* Make connected structure. */
98 ifc = connected_new ();
99 ifc->ifp = ifp;
100 ifc->flags = flags;
101
102 /* Allocate new connected address. */
103 p = prefix_ipv4_new ();
104 p->family = AF_INET;
105 p->prefix = *addr;
106 p->prefixlen = prefixlen;
107 ifc->address = (struct prefix *) p;
108
109 /* If there is broadcast or pointopoint address. */
110 if (broad)
111 {
112 p = prefix_ipv4_new ();
113 p->family = AF_INET;
114 p->prefix = *broad;
115 ifc->destination = (struct prefix *) p;
hasso3fb9cd62004-10-19 19:44:43 +0000116
117 /* validate the destination address */
118 if (ifp->flags & IFF_POINTOPOINT)
119 {
120 if (IPV4_ADDR_SAME(addr,broad))
121 zlog_warn("warning: PtP interface %s has same local and peer "
122 "address %s, routing protocols may malfunction",
123 ifp->name,inet_ntoa(*addr));
124 else if ((prefixlen != IPV4_MAX_PREFIXLEN) &&
125 (ipv4_network_addr(addr->s_addr,prefixlen) !=
126 ipv4_network_addr(broad->s_addr,prefixlen)))
127 {
128 char buf[2][INET_ADDRSTRLEN];
129 zlog_warn("warning: PtP interface %s network mismatch: local "
130 "%s/%d vs. peer %s, routing protocols may malfunction",
131 ifp->name,
132 inet_ntop (AF_INET, addr, buf[0], sizeof(buf[0])),
133 prefixlen,
134 inet_ntop (AF_INET, broad, buf[1], sizeof(buf[1])));
135 }
136 }
137 else
138 {
139 if (broad->s_addr != ipv4_broadcast_addr(addr->s_addr,prefixlen))
140 {
141 char buf[2][INET_ADDRSTRLEN];
142 struct in_addr bcalc;
143 bcalc.s_addr = ipv4_broadcast_addr(addr->s_addr,prefixlen);
144 zlog_warn("warning: interface %s broadcast addr %s/%d != "
145 "calculated %s, routing protocols may malfunction",
146 ifp->name,
147 inet_ntop (AF_INET, broad, buf[0], sizeof(buf[0])),
148 prefixlen,
149 inet_ntop (AF_INET, &bcalc, buf[1], sizeof(buf[1])));
150 }
151 }
152
paul718e3742002-12-13 20:15:29 +0000153 }
hasso3fb9cd62004-10-19 19:44:43 +0000154 else
155 /* no broadcast or destination address was supplied */
ajs341a8f12004-12-22 16:32:16 +0000156 if ((prefixlen == IPV4_MAX_PREFIXLEN) && if_is_pointopoint(ifp))
157 zlog_warn("warning: PtP interface %s with addr %s/%d needs a "
158 "peer address",ifp->name,inet_ntoa(*addr),prefixlen);
paul718e3742002-12-13 20:15:29 +0000159
160 /* Label of this address. */
161 if (label)
162 ifc->label = strdup (label);
163
164 /* Check same connected route. */
165 current = connected_check_ipv4 (ifp, (struct prefix *) ifc->address);
166 if (current)
167 {
168 connected_free (ifc);
169 ifc = current;
170 }
171 else
172 {
173 listnode_add (ifp->connected, ifc);
174 }
175
176 /* Update interface address information to protocol daemon. */
177 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
178 {
hassoeef1fe12004-10-03 18:46:08 +0000179 if_subnet_add (ifp, ifc);
180
paul718e3742002-12-13 20:15:29 +0000181 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
182
183 zebra_interface_address_add_update (ifp, ifc);
184
185 if (if_is_up(ifp))
186 connected_up_ipv4 (ifp, ifc);
187 }
188}
189
190void
191connected_down_ipv4 (struct interface *ifp, struct connected *ifc)
192{
193 struct prefix_ipv4 p;
194 struct prefix_ipv4 *addr;
195 struct prefix_ipv4 *dest;
196
197 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
198 return;
199
200 addr = (struct prefix_ipv4 *)ifc->address;
201 dest = (struct prefix_ipv4 *)ifc->destination;
202
203 memset (&p, 0, sizeof (struct prefix_ipv4));
204 p.family = AF_INET;
205 p.prefixlen = addr->prefixlen;
206
paul960182a2003-04-09 07:16:04 +0000207 /* Point-to-point check. */
hasso3fb9cd62004-10-19 19:44:43 +0000208 if (CONNECTED_POINTOPOINT_HOST(ifc))
paul718e3742002-12-13 20:15:29 +0000209 p.prefix = dest->prefix;
210 else
211 p.prefix = addr->prefix;
212
213 /* Apply mask to the network. */
214 apply_mask_ipv4 (&p);
215
216 /* In case of connected address is 0.0.0.0/0 we treat it tunnel
217 address. */
218 if (prefix_ipv4_any (&p))
219 return;
220
221 rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);
222
223 rib_update ();
224}
225
226/* Delete connected IPv4 route to the interface. */
227void
228connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
229 int prefixlen, struct in_addr *broad, char *label)
230{
231 struct prefix_ipv4 p;
232 struct connected *ifc;
233
234 memset (&p, 0, sizeof (struct prefix_ipv4));
235 p.family = AF_INET;
236 p.prefix = *addr;
237 p.prefixlen = prefixlen;
238
239 ifc = connected_check_ipv4 (ifp, (struct prefix *) &p);
240 if (! ifc)
241 return;
242
243 /* Update interface address information to protocol daemon. */
244 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
245 {
246 zebra_interface_address_delete_update (ifp, ifc);
247
hassoeef1fe12004-10-03 18:46:08 +0000248 if_subnet_delete (ifp, ifc);
249
paul718e3742002-12-13 20:15:29 +0000250 connected_down_ipv4 (ifp, ifc);
251
252 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
253 }
254
hassoeef1fe12004-10-03 18:46:08 +0000255 listnode_delete (ifp->connected, ifc);
256 connected_free (ifc);
paul718e3742002-12-13 20:15:29 +0000257}
258
259#ifdef HAVE_IPV6
260/* If same interface address is already exist... */
261struct connected *
262connected_check_ipv6 (struct interface *ifp, struct prefix *p)
263{
264 struct connected *ifc;
hasso52dc7ee2004-09-23 19:18:23 +0000265 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000266
paul1eb8ef22005-04-07 07:30:20 +0000267 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc))
268 if (prefix_same (ifc->address, p))
269 return ifc;
paul718e3742002-12-13 20:15:29 +0000270
paul718e3742002-12-13 20:15:29 +0000271 return 0;
272}
273
274void
275connected_up_ipv6 (struct interface *ifp, struct connected *ifc)
276{
277 struct prefix_ipv6 p;
278 struct prefix_ipv6 *addr;
279 struct prefix_ipv6 *dest;
280
281 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
282 return;
283
284 addr = (struct prefix_ipv6 *) ifc->address;
285 dest = (struct prefix_ipv6 *) ifc->destination;
286
287 memset (&p, 0, sizeof (struct prefix_ipv6));
288 p.family = AF_INET6;
289 p.prefixlen = addr->prefixlen;
290
paul31a476c2003-09-29 19:54:53 +0000291 if (if_is_pointopoint (ifp) && dest)
paul718e3742002-12-13 20:15:29 +0000292 {
293 if (IN6_IS_ADDR_UNSPECIFIED (&dest->prefix))
294 p.prefix = addr->prefix;
295 else
296 p.prefix = dest->prefix;
297 }
298 else
299 p.prefix = addr->prefix;
300
301 /* Apply mask to the network. */
302 apply_mask_ipv6 (&p);
303
hasso726f9b22003-05-25 21:04:54 +0000304#if ! defined (MUSICA) && ! defined (LINUX)
305 /* XXX: It is already done by rib_bogus_ipv6 within rib_add_ipv6 */
paul718e3742002-12-13 20:15:29 +0000306 if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
307 return;
hasso726f9b22003-05-25 21:04:54 +0000308#endif
paul718e3742002-12-13 20:15:29 +0000309
310 rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);
311
312 rib_update ();
313}
314
315/* Add connected IPv6 route to the interface. */
316void
317connected_add_ipv6 (struct interface *ifp, struct in6_addr *addr,
hassofce954f2004-10-07 20:29:24 +0000318 u_char prefixlen, struct in6_addr *broad)
paul718e3742002-12-13 20:15:29 +0000319{
320 struct prefix_ipv6 *p;
321 struct connected *ifc;
322 struct connected *current;
323
324 /* Make connected structure. */
325 ifc = connected_new ();
326 ifc->ifp = ifp;
327
328 /* Allocate new connected address. */
329 p = prefix_ipv6_new ();
330 p->family = AF_INET6;
331 IPV6_ADDR_COPY (&p->prefix, addr);
332 p->prefixlen = prefixlen;
333 ifc->address = (struct prefix *) p;
334
335 /* If there is broadcast or pointopoint address. */
336 if (broad)
337 {
338 p = prefix_ipv6_new ();
339 p->family = AF_INET6;
340 IPV6_ADDR_COPY (&p->prefix, broad);
341 ifc->destination = (struct prefix *) p;
342 }
343
344 current = connected_check_ipv6 (ifp, (struct prefix *) ifc->address);
345 if (current)
346 {
347 connected_free (ifc);
348 ifc = current;
349 }
350 else
351 {
352 listnode_add (ifp->connected, ifc);
353 }
354
355 /* Update interface address information to protocol daemon. */
356 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
357 {
358 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
359
360 zebra_interface_address_add_update (ifp, ifc);
361
362 if (if_is_up(ifp))
363 connected_up_ipv6 (ifp, ifc);
364 }
365}
366
367void
368connected_down_ipv6 (struct interface *ifp, struct connected *ifc)
369{
370 struct prefix_ipv6 p;
371 struct prefix_ipv6 *addr;
372 struct prefix_ipv6 *dest;
373
374 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
375 return;
376
377 addr = (struct prefix_ipv6 *) ifc->address;
378 dest = (struct prefix_ipv6 *) ifc->destination;
379
380 memset (&p, 0, sizeof (struct prefix_ipv6));
381 p.family = AF_INET6;
382 p.prefixlen = addr->prefixlen;
383
paul31a476c2003-09-29 19:54:53 +0000384 if (if_is_pointopoint (ifp) && dest)
paul718e3742002-12-13 20:15:29 +0000385 {
386 if (IN6_IS_ADDR_UNSPECIFIED (&dest->prefix))
387 p.prefix = addr->prefix;
388 else
389 p.prefix = dest->prefix;
390 }
391 else
392 p.prefix = addr->prefix;
393
394 apply_mask_ipv6 (&p);
395
396 if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
397 return;
398
399 rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);
400
401 rib_update ();
402}
403
404void
405connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address,
hassofce954f2004-10-07 20:29:24 +0000406 u_char prefixlen, struct in6_addr *broad)
paul718e3742002-12-13 20:15:29 +0000407{
408 struct prefix_ipv6 p;
409 struct connected *ifc;
410
411 memset (&p, 0, sizeof (struct prefix_ipv6));
412 p.family = AF_INET6;
413 memcpy (&p.prefix, address, sizeof (struct in6_addr));
414 p.prefixlen = prefixlen;
415
416 ifc = connected_check_ipv6 (ifp, (struct prefix *) &p);
417 if (! ifc)
418 return;
419
420 /* Update interface address information to protocol daemon. */
421 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
422 {
423 zebra_interface_address_delete_update (ifp, ifc);
424
425 connected_down_ipv6 (ifp, ifc);
426
427 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
428 }
429
hassoeef1fe12004-10-03 18:46:08 +0000430 listnode_delete (ifp->connected, ifc);
431 connected_free (ifc);
paul718e3742002-12-13 20:15:29 +0000432}
433#endif /* HAVE_IPV6 */