blob: 21af3e9c155da6e7feb9b4fef98a48fa4a7f6ffb [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"
35
36/* If same interface address is already exist... */
37struct connected *
38connected_check_ipv4 (struct interface *ifp, struct prefix *p)
39{
40 struct connected *ifc;
hasso52dc7ee2004-09-23 19:18:23 +000041 struct listnode *node;
paul718e3742002-12-13 20:15:29 +000042
43 for (node = listhead (ifp->connected); node; node = nextnode (node))
44 {
45 ifc = getdata (node);
46
47 if (prefix_same (ifc->address, p))
48 return ifc;
49 }
50 return NULL;
51}
52
53/* Called from if_up(). */
54void
55connected_up_ipv4 (struct interface *ifp, struct connected *ifc)
56{
57 struct prefix_ipv4 p;
58 struct prefix_ipv4 *addr;
59 struct prefix_ipv4 *dest;
60
61 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
62 return;
63
64 addr = (struct prefix_ipv4 *) ifc->address;
65 dest = (struct prefix_ipv4 *) ifc->destination;
66
67 memset (&p, 0, sizeof (struct prefix_ipv4));
68 p.family = AF_INET;
69 p.prefixlen = addr->prefixlen;
70
71 /* Point-to-point check. */
paul2fe28bb2003-10-13 08:59:40 +000072 if (if_is_pointopoint (ifp) && dest)
paul718e3742002-12-13 20:15:29 +000073 p.prefix = dest->prefix;
74 else
75 p.prefix = addr->prefix;
76
77 /* Apply mask to the network. */
78 apply_mask_ipv4 (&p);
79
80 /* In case of connected address is 0.0.0.0/0 we treat it tunnel
81 address. */
82 if (prefix_ipv4_any (&p))
83 return;
84
85 rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, 0, 0);
86
87 rib_update ();
88}
89
90/* Add connected IPv4 route to the interface. */
91void
92connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
93 int prefixlen, struct in_addr *broad, char *label)
94{
95 struct prefix_ipv4 *p;
96 struct connected *ifc;
97 struct connected *current;
98
99 /* Make connected structure. */
100 ifc = connected_new ();
101 ifc->ifp = ifp;
102 ifc->flags = flags;
103
104 /* Allocate new connected address. */
105 p = prefix_ipv4_new ();
106 p->family = AF_INET;
107 p->prefix = *addr;
108 p->prefixlen = prefixlen;
109 ifc->address = (struct prefix *) p;
110
111 /* If there is broadcast or pointopoint address. */
112 if (broad)
113 {
114 p = prefix_ipv4_new ();
115 p->family = AF_INET;
116 p->prefix = *broad;
117 ifc->destination = (struct prefix *) p;
118 }
119
120 /* Label of this address. */
121 if (label)
122 ifc->label = strdup (label);
123
124 /* Check same connected route. */
125 current = connected_check_ipv4 (ifp, (struct prefix *) ifc->address);
126 if (current)
127 {
128 connected_free (ifc);
129 ifc = current;
130 }
131 else
132 {
133 listnode_add (ifp->connected, ifc);
134 }
135
136 /* Update interface address information to protocol daemon. */
137 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
138 {
139 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
140
141 zebra_interface_address_add_update (ifp, ifc);
142
143 if (if_is_up(ifp))
144 connected_up_ipv4 (ifp, ifc);
145 }
146}
147
148void
149connected_down_ipv4 (struct interface *ifp, struct connected *ifc)
150{
151 struct prefix_ipv4 p;
152 struct prefix_ipv4 *addr;
153 struct prefix_ipv4 *dest;
154
155 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
156 return;
157
158 addr = (struct prefix_ipv4 *)ifc->address;
159 dest = (struct prefix_ipv4 *)ifc->destination;
160
161 memset (&p, 0, sizeof (struct prefix_ipv4));
162 p.family = AF_INET;
163 p.prefixlen = addr->prefixlen;
164
paul960182a2003-04-09 07:16:04 +0000165 /* Point-to-point check. */
paul2fe28bb2003-10-13 08:59:40 +0000166 if (dest && if_is_pointopoint (ifp))
paul718e3742002-12-13 20:15:29 +0000167 p.prefix = dest->prefix;
168 else
169 p.prefix = addr->prefix;
170
171 /* Apply mask to the network. */
172 apply_mask_ipv4 (&p);
173
174 /* In case of connected address is 0.0.0.0/0 we treat it tunnel
175 address. */
176 if (prefix_ipv4_any (&p))
177 return;
178
179 rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);
180
181 rib_update ();
182}
183
184/* Delete connected IPv4 route to the interface. */
185void
186connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
187 int prefixlen, struct in_addr *broad, char *label)
188{
189 struct prefix_ipv4 p;
190 struct connected *ifc;
191
192 memset (&p, 0, sizeof (struct prefix_ipv4));
193 p.family = AF_INET;
194 p.prefix = *addr;
195 p.prefixlen = prefixlen;
196
197 ifc = connected_check_ipv4 (ifp, (struct prefix *) &p);
198 if (! ifc)
199 return;
200
201 /* Update interface address information to protocol daemon. */
202 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
203 {
204 zebra_interface_address_delete_update (ifp, ifc);
205
206 connected_down_ipv4 (ifp, ifc);
207
208 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
209 }
210
211 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
212 {
213 listnode_delete (ifp->connected, ifc);
214 connected_free (ifc);
215 }
216}
217
218#ifdef HAVE_IPV6
219/* If same interface address is already exist... */
220struct connected *
221connected_check_ipv6 (struct interface *ifp, struct prefix *p)
222{
223 struct connected *ifc;
hasso52dc7ee2004-09-23 19:18:23 +0000224 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000225
226 for (node = listhead (ifp->connected); node; node = nextnode (node))
227 {
228 ifc = getdata (node);
229
230 if (prefix_same (ifc->address, p))
231 return ifc;
232 }
233 return 0;
234}
235
236void
237connected_up_ipv6 (struct interface *ifp, struct connected *ifc)
238{
239 struct prefix_ipv6 p;
240 struct prefix_ipv6 *addr;
241 struct prefix_ipv6 *dest;
242
243 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
244 return;
245
246 addr = (struct prefix_ipv6 *) ifc->address;
247 dest = (struct prefix_ipv6 *) ifc->destination;
248
249 memset (&p, 0, sizeof (struct prefix_ipv6));
250 p.family = AF_INET6;
251 p.prefixlen = addr->prefixlen;
252
paul31a476c2003-09-29 19:54:53 +0000253 if (if_is_pointopoint (ifp) && dest)
paul718e3742002-12-13 20:15:29 +0000254 {
255 if (IN6_IS_ADDR_UNSPECIFIED (&dest->prefix))
256 p.prefix = addr->prefix;
257 else
258 p.prefix = dest->prefix;
259 }
260 else
261 p.prefix = addr->prefix;
262
263 /* Apply mask to the network. */
264 apply_mask_ipv6 (&p);
265
hasso726f9b22003-05-25 21:04:54 +0000266#if ! defined (MUSICA) && ! defined (LINUX)
267 /* XXX: It is already done by rib_bogus_ipv6 within rib_add_ipv6 */
paul718e3742002-12-13 20:15:29 +0000268 if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
269 return;
hasso726f9b22003-05-25 21:04:54 +0000270#endif
paul718e3742002-12-13 20:15:29 +0000271
272 rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);
273
274 rib_update ();
275}
276
277/* Add connected IPv6 route to the interface. */
278void
279connected_add_ipv6 (struct interface *ifp, struct in6_addr *addr,
280 int prefixlen, struct in6_addr *broad)
281{
282 struct prefix_ipv6 *p;
283 struct connected *ifc;
284 struct connected *current;
285
286 /* Make connected structure. */
287 ifc = connected_new ();
288 ifc->ifp = ifp;
289
290 /* Allocate new connected address. */
291 p = prefix_ipv6_new ();
292 p->family = AF_INET6;
293 IPV6_ADDR_COPY (&p->prefix, addr);
294 p->prefixlen = prefixlen;
295 ifc->address = (struct prefix *) p;
296
297 /* If there is broadcast or pointopoint address. */
298 if (broad)
299 {
300 p = prefix_ipv6_new ();
301 p->family = AF_INET6;
302 IPV6_ADDR_COPY (&p->prefix, broad);
303 ifc->destination = (struct prefix *) p;
304 }
305
306 current = connected_check_ipv6 (ifp, (struct prefix *) ifc->address);
307 if (current)
308 {
309 connected_free (ifc);
310 ifc = current;
311 }
312 else
313 {
314 listnode_add (ifp->connected, ifc);
315 }
316
317 /* Update interface address information to protocol daemon. */
318 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
319 {
320 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
321
322 zebra_interface_address_add_update (ifp, ifc);
323
324 if (if_is_up(ifp))
325 connected_up_ipv6 (ifp, ifc);
326 }
327}
328
329void
330connected_down_ipv6 (struct interface *ifp, struct connected *ifc)
331{
332 struct prefix_ipv6 p;
333 struct prefix_ipv6 *addr;
334 struct prefix_ipv6 *dest;
335
336 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
337 return;
338
339 addr = (struct prefix_ipv6 *) ifc->address;
340 dest = (struct prefix_ipv6 *) ifc->destination;
341
342 memset (&p, 0, sizeof (struct prefix_ipv6));
343 p.family = AF_INET6;
344 p.prefixlen = addr->prefixlen;
345
paul31a476c2003-09-29 19:54:53 +0000346 if (if_is_pointopoint (ifp) && dest)
paul718e3742002-12-13 20:15:29 +0000347 {
348 if (IN6_IS_ADDR_UNSPECIFIED (&dest->prefix))
349 p.prefix = addr->prefix;
350 else
351 p.prefix = dest->prefix;
352 }
353 else
354 p.prefix = addr->prefix;
355
356 apply_mask_ipv6 (&p);
357
358 if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
359 return;
360
361 rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);
362
363 rib_update ();
364}
365
366void
367connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address,
368 int prefixlen, struct in6_addr *broad)
369{
370 struct prefix_ipv6 p;
371 struct connected *ifc;
372
373 memset (&p, 0, sizeof (struct prefix_ipv6));
374 p.family = AF_INET6;
375 memcpy (&p.prefix, address, sizeof (struct in6_addr));
376 p.prefixlen = prefixlen;
377
378 ifc = connected_check_ipv6 (ifp, (struct prefix *) &p);
379 if (! ifc)
380 return;
381
382 /* Update interface address information to protocol daemon. */
383 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
384 {
385 zebra_interface_address_delete_update (ifp, ifc);
386
387 connected_down_ipv6 (ifp, ifc);
388
389 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
390 }
391
392 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
393 {
394 listnode_delete (ifp->connected, ifc);
395 connected_free (ifc);
396 }
397}
398#endif /* HAVE_IPV6 */