blob: dcb0b875e54c2d22ed413b89192fdc572d37603e [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;
41 listnode node;
42
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. */
paulf2c80652002-12-13 21:44:27 +000072 if (ifc_pointopoint (ifc) && 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
paul00df0c12002-12-13 21:07:36 +0000165 if (ifc_pointopoint (ifc))
paul718e3742002-12-13 20:15:29 +0000166 p.prefix = dest->prefix;
167 else
168 p.prefix = addr->prefix;
169
170 /* Apply mask to the network. */
171 apply_mask_ipv4 (&p);
172
173 /* In case of connected address is 0.0.0.0/0 we treat it tunnel
174 address. */
175 if (prefix_ipv4_any (&p))
176 return;
177
178 rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);
179
180 rib_update ();
181}
182
183/* Delete connected IPv4 route to the interface. */
184void
185connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
186 int prefixlen, struct in_addr *broad, char *label)
187{
188 struct prefix_ipv4 p;
189 struct connected *ifc;
190
191 memset (&p, 0, sizeof (struct prefix_ipv4));
192 p.family = AF_INET;
193 p.prefix = *addr;
194 p.prefixlen = prefixlen;
195
196 ifc = connected_check_ipv4 (ifp, (struct prefix *) &p);
197 if (! ifc)
198 return;
199
200 /* Update interface address information to protocol daemon. */
201 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
202 {
203 zebra_interface_address_delete_update (ifp, ifc);
204
205 connected_down_ipv4 (ifp, ifc);
206
207 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
208 }
209
210 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
211 {
212 listnode_delete (ifp->connected, ifc);
213 connected_free (ifc);
214 }
215}
216
217#ifdef HAVE_IPV6
218/* If same interface address is already exist... */
219struct connected *
220connected_check_ipv6 (struct interface *ifp, struct prefix *p)
221{
222 struct connected *ifc;
223 listnode node;
224
225 for (node = listhead (ifp->connected); node; node = nextnode (node))
226 {
227 ifc = getdata (node);
228
229 if (prefix_same (ifc->address, p))
230 return ifc;
231 }
232 return 0;
233}
234
235void
236connected_up_ipv6 (struct interface *ifp, struct connected *ifc)
237{
238 struct prefix_ipv6 p;
239 struct prefix_ipv6 *addr;
240 struct prefix_ipv6 *dest;
241
242 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
243 return;
244
245 addr = (struct prefix_ipv6 *) ifc->address;
246 dest = (struct prefix_ipv6 *) ifc->destination;
247
248 memset (&p, 0, sizeof (struct prefix_ipv6));
249 p.family = AF_INET6;
250 p.prefixlen = addr->prefixlen;
251
paul00df0c12002-12-13 21:07:36 +0000252 if (ifc_pointopoint (ifc) && dest)
paul718e3742002-12-13 20:15:29 +0000253 {
254 if (IN6_IS_ADDR_UNSPECIFIED (&dest->prefix))
255 p.prefix = addr->prefix;
256 else
257 p.prefix = dest->prefix;
258 }
259 else
260 p.prefix = addr->prefix;
261
262 /* Apply mask to the network. */
263 apply_mask_ipv6 (&p);
264
265 if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
266 return;
267
268 rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);
269
270 rib_update ();
271}
272
273/* Add connected IPv6 route to the interface. */
274void
275connected_add_ipv6 (struct interface *ifp, struct in6_addr *addr,
276 int prefixlen, struct in6_addr *broad)
277{
278 struct prefix_ipv6 *p;
279 struct connected *ifc;
280 struct connected *current;
281
282 /* Make connected structure. */
283 ifc = connected_new ();
284 ifc->ifp = ifp;
285
286 /* Allocate new connected address. */
287 p = prefix_ipv6_new ();
288 p->family = AF_INET6;
289 IPV6_ADDR_COPY (&p->prefix, addr);
290 p->prefixlen = prefixlen;
291 ifc->address = (struct prefix *) p;
292
293 /* If there is broadcast or pointopoint address. */
294 if (broad)
295 {
296 p = prefix_ipv6_new ();
297 p->family = AF_INET6;
298 IPV6_ADDR_COPY (&p->prefix, broad);
299 ifc->destination = (struct prefix *) p;
300 }
301
302 current = connected_check_ipv6 (ifp, (struct prefix *) ifc->address);
303 if (current)
304 {
305 connected_free (ifc);
306 ifc = current;
307 }
308 else
309 {
310 listnode_add (ifp->connected, ifc);
311 }
312
313 /* Update interface address information to protocol daemon. */
314 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
315 {
316 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
317
318 zebra_interface_address_add_update (ifp, ifc);
319
320 if (if_is_up(ifp))
321 connected_up_ipv6 (ifp, ifc);
322 }
323}
324
325void
326connected_down_ipv6 (struct interface *ifp, struct connected *ifc)
327{
328 struct prefix_ipv6 p;
329 struct prefix_ipv6 *addr;
330 struct prefix_ipv6 *dest;
331
332 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
333 return;
334
335 addr = (struct prefix_ipv6 *) ifc->address;
336 dest = (struct prefix_ipv6 *) ifc->destination;
337
338 memset (&p, 0, sizeof (struct prefix_ipv6));
339 p.family = AF_INET6;
340 p.prefixlen = addr->prefixlen;
341
paul00df0c12002-12-13 21:07:36 +0000342 if (ifc_pointopoint (ifc) && dest)
paul718e3742002-12-13 20:15:29 +0000343 {
344 if (IN6_IS_ADDR_UNSPECIFIED (&dest->prefix))
345 p.prefix = addr->prefix;
346 else
347 p.prefix = dest->prefix;
348 }
349 else
350 p.prefix = addr->prefix;
351
352 apply_mask_ipv6 (&p);
353
354 if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
355 return;
356
357 rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);
358
359 rib_update ();
360}
361
362void
363connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address,
364 int prefixlen, struct in6_addr *broad)
365{
366 struct prefix_ipv6 p;
367 struct connected *ifc;
368
369 memset (&p, 0, sizeof (struct prefix_ipv6));
370 p.family = AF_INET6;
371 memcpy (&p.prefix, address, sizeof (struct in6_addr));
372 p.prefixlen = prefixlen;
373
374 ifc = connected_check_ipv6 (ifp, (struct prefix *) &p);
375 if (! ifc)
376 return;
377
378 /* Update interface address information to protocol daemon. */
379 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
380 {
381 zebra_interface_address_delete_update (ifp, ifc);
382
383 connected_down_ipv6 (ifp, ifc);
384
385 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
386 }
387
388 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
389 {
390 listnode_delete (ifp->connected, ifc);
391 connected_free (ifc);
392 }
393}
394#endif /* HAVE_IPV6 */