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