]> git.proxmox.com Git - mirror_frr.git/blob - zebra/connected.c
2005-04-07 Paul Jakma <paul.jakma@sun.com>
[mirror_frr.git] / zebra / connected.c
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"
32
33 #include "zebra/zserv.h"
34 #include "zebra/redistribute.h"
35 #include "zebra/interface.h"
36 \f
37 /* If same interface address is already exist... */
38 struct connected *
39 connected_check_ipv4 (struct interface *ifp, struct prefix *p)
40 {
41 struct connected *ifc;
42 struct listnode *node;
43
44 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc))
45 if (prefix_same (ifc->address, p))
46 return ifc;
47
48 return NULL;
49 }
50
51 /* Called from if_up(). */
52 void
53 connected_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. */
70 if (CONNECTED_POINTOPOINT_HOST(ifc))
71 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. */
89 void
90 connected_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;
116
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
153 }
154 else
155 /* no broadcast or destination address was supplied */
156 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);
159
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 {
179 if_subnet_add (ifp, ifc);
180
181 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
190 void
191 connected_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
207 /* Point-to-point check. */
208 if (CONNECTED_POINTOPOINT_HOST(ifc))
209 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. */
227 void
228 connected_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
248 if_subnet_delete (ifp, ifc);
249
250 connected_down_ipv4 (ifp, ifc);
251
252 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
253 }
254
255 listnode_delete (ifp->connected, ifc);
256 connected_free (ifc);
257 }
258
259 #ifdef HAVE_IPV6
260 /* If same interface address is already exist... */
261 struct connected *
262 connected_check_ipv6 (struct interface *ifp, struct prefix *p)
263 {
264 struct connected *ifc;
265 struct listnode *node;
266
267 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc))
268 if (prefix_same (ifc->address, p))
269 return ifc;
270
271 return 0;
272 }
273
274 void
275 connected_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
291 if (if_is_pointopoint (ifp) && dest)
292 {
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
304 #if ! defined (MUSICA) && ! defined (LINUX)
305 /* XXX: It is already done by rib_bogus_ipv6 within rib_add_ipv6 */
306 if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
307 return;
308 #endif
309
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. */
316 void
317 connected_add_ipv6 (struct interface *ifp, struct in6_addr *addr,
318 u_char prefixlen, struct in6_addr *broad)
319 {
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
367 void
368 connected_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
384 if (if_is_pointopoint (ifp) && dest)
385 {
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
404 void
405 connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address,
406 u_char prefixlen, struct in6_addr *broad)
407 {
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
430 listnode_delete (ifp->connected, ifc);
431 connected_free (ifc);
432 }
433 #endif /* HAVE_IPV6 */