Line data Source code
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 : #include "memory.h"
33 :
34 : #include "zebra/zserv.h"
35 : #include "zebra/redistribute.h"
36 : #include "zebra/interface.h"
37 : #include "zebra/connected.h"
38 : extern struct zebra_t zebrad;
39 :
40 : /* communicate the withdrawal of a connected address */
41 : static void
42 10 : connected_withdraw (struct connected *ifc)
43 : {
44 10 : if (! ifc)
45 0 : return;
46 :
47 : /* Update interface address information to protocol daemon. */
48 10 : if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
49 : {
50 8 : zebra_interface_address_delete_update (ifc->ifp, ifc);
51 :
52 8 : if (ifc->address->family == AF_INET)
53 2 : if_subnet_delete (ifc->ifp, ifc);
54 :
55 8 : if (ifc->address->family == AF_INET)
56 2 : connected_down_ipv4 (ifc->ifp, ifc);
57 : #ifdef HAVE_IPV6
58 : else
59 6 : connected_down_ipv6 (ifc->ifp, ifc);
60 : #endif
61 :
62 8 : UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
63 : }
64 :
65 : /* The address is not in the kernel anymore, so clear the flag */
66 10 : UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
67 :
68 10 : if (!CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
69 : {
70 9 : listnode_delete (ifc->ifp->connected, ifc);
71 9 : connected_free (ifc);
72 : }
73 : }
74 :
75 : static void
76 279 : connected_announce (struct interface *ifp, struct connected *ifc)
77 : {
78 279 : if (!ifc)
79 0 : return;
80 :
81 279 : listnode_add (ifp->connected, ifc);
82 :
83 : /* Update interface address information to protocol daemon. */
84 279 : if (ifc->address->family == AF_INET)
85 109 : if_subnet_add (ifp, ifc);
86 :
87 279 : zebra_interface_address_add_update (ifp, ifc);
88 :
89 279 : if (if_is_operative(ifp))
90 : {
91 279 : if (ifc->address->family == AF_INET)
92 109 : connected_up_ipv4 (ifp, ifc);
93 : #ifdef HAVE_IPV6
94 : else
95 170 : connected_up_ipv6 (ifp, ifc);
96 : #endif
97 : }
98 : }
99 :
100 : /* If same interface address is already exist... */
101 : struct connected *
102 289 : connected_check (struct interface *ifp, struct prefix *p)
103 : {
104 : struct connected *ifc;
105 : struct listnode *node;
106 :
107 448 : for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc))
108 169 : if (prefix_same (ifc->address, p))
109 10 : return ifc;
110 :
111 279 : return NULL;
112 : }
113 :
114 : /* Check if two ifc's describe the same address in the same state */
115 : static int
116 2 : connected_same (struct connected *ifc1, struct connected *ifc2)
117 : {
118 2 : if (ifc1->ifp != ifc2->ifp)
119 0 : return 0;
120 :
121 2 : if (ifc1->destination)
122 1 : if (!ifc2->destination)
123 0 : return 0;
124 2 : if (ifc2->destination)
125 1 : if (!ifc1->destination)
126 0 : return 0;
127 :
128 2 : if (ifc1->destination && ifc2->destination)
129 1 : if (!prefix_same (ifc1->destination, ifc2->destination))
130 0 : return 0;
131 :
132 2 : if (ifc1->flags != ifc2->flags)
133 0 : return 0;
134 :
135 2 : if (ifc1->conf != ifc2->conf)
136 2 : return 0;
137 :
138 0 : return 1;
139 : }
140 :
141 : /* Handle changes to addresses and send the neccesary announcements
142 : * to clients. */
143 : static void
144 279 : connected_update(struct interface *ifp, struct connected *ifc)
145 : {
146 : struct connected *current;
147 :
148 : /* Check same connected route. */
149 279 : if ((current = connected_check (ifp, (struct prefix *) ifc->address)))
150 : {
151 2 : if (CHECK_FLAG(current->conf, ZEBRA_IFC_CONFIGURED))
152 2 : SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
153 :
154 : /* Avoid spurious withdraws, this might be just the kernel 'reflecting'
155 : * back an address we have already added.
156 : */
157 2 : if (connected_same (current, ifc))
158 : {
159 : /* nothing to do */
160 0 : connected_free (ifc);
161 0 : return;
162 : }
163 :
164 : /* Clear the configured flag on the old ifc, so it will be freed by
165 : * connected withdraw. */
166 2 : UNSET_FLAG(current->conf, ZEBRA_IFC_CONFIGURED);
167 2 : connected_withdraw (current); /* implicit withdraw - freebsd does this */
168 : }
169 :
170 : /* If the connected is new or has changed, announce it, if it is usable */
171 279 : if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
172 279 : connected_announce(ifp, ifc);
173 : }
174 :
175 : /* Called from if_up(). */
176 : void
177 111 : connected_up_ipv4 (struct interface *ifp, struct connected *ifc)
178 : {
179 : struct prefix_ipv4 p;
180 :
181 111 : if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
182 0 : return;
183 :
184 111 : PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
185 :
186 : /* Apply mask to the network. */
187 111 : apply_mask_ipv4 (&p);
188 :
189 : /* In case of connected address is 0.0.0.0/0 we treat it tunnel
190 : address. */
191 111 : if (prefix_ipv4_any (&p))
192 0 : return;
193 :
194 111 : rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex,
195 111 : RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST);
196 :
197 111 : rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex,
198 111 : RT_TABLE_MAIN, ifp->metric, 0, SAFI_MULTICAST);
199 :
200 111 : rib_update ();
201 : }
202 :
203 : /* Add connected IPv4 route to the interface. */
204 : void
205 109 : connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
206 : u_char prefixlen, struct in_addr *broad,
207 : const char *label)
208 : {
209 : struct prefix_ipv4 *p;
210 : struct connected *ifc;
211 :
212 : /* Make connected structure. */
213 109 : ifc = connected_new ();
214 109 : ifc->ifp = ifp;
215 109 : ifc->flags = flags;
216 : /* If we get a notification from the kernel,
217 : * we can safely assume the address is known to the kernel */
218 109 : SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
219 :
220 : /* Allocate new connected address. */
221 109 : p = prefix_ipv4_new ();
222 109 : p->family = AF_INET;
223 109 : p->prefix = *addr;
224 109 : p->prefixlen = prefixlen;
225 109 : ifc->address = (struct prefix *) p;
226 :
227 : /* If there is broadcast or peer address. */
228 109 : if (broad)
229 : {
230 1 : p = prefix_ipv4_new ();
231 1 : p->family = AF_INET;
232 1 : p->prefix = *broad;
233 1 : p->prefixlen = prefixlen;
234 1 : ifc->destination = (struct prefix *) p;
235 :
236 : /* validate the destination address */
237 1 : if (CONNECTED_PEER(ifc))
238 : {
239 0 : if (IPV4_ADDR_SAME(addr,broad))
240 0 : zlog_warn("warning: interface %s has same local and peer "
241 : "address %s, routing protocols may malfunction",
242 0 : ifp->name,inet_ntoa(*addr));
243 : }
244 : else
245 : {
246 1 : if (broad->s_addr != ipv4_broadcast_addr(addr->s_addr,prefixlen))
247 : {
248 : char buf[2][INET_ADDRSTRLEN];
249 : struct in_addr bcalc;
250 0 : bcalc.s_addr = ipv4_broadcast_addr(addr->s_addr,prefixlen);
251 0 : zlog_warn("warning: interface %s broadcast addr %s/%d != "
252 : "calculated %s, routing protocols may malfunction",
253 0 : ifp->name,
254 : inet_ntop (AF_INET, broad, buf[0], sizeof(buf[0])),
255 : prefixlen,
256 : inet_ntop (AF_INET, &bcalc, buf[1], sizeof(buf[1])));
257 : }
258 : }
259 :
260 : }
261 : else
262 : {
263 108 : if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER))
264 : {
265 0 : zlog_warn("warning: %s called for interface %s "
266 : "with peer flag set, but no peer address supplied",
267 0 : __func__, ifp->name);
268 0 : UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
269 : }
270 :
271 : /* no broadcast or destination address was supplied */
272 108 : if ((prefixlen == IPV4_MAX_PREFIXLEN) && if_is_pointopoint(ifp))
273 0 : zlog_warn("warning: PtP interface %s with addr %s/%d needs a "
274 0 : "peer address",ifp->name,inet_ntoa(*addr),prefixlen);
275 : }
276 :
277 : /* Label of this address. */
278 109 : if (label)
279 0 : ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
280 :
281 : /* For all that I know an IPv4 address is always ready when we receive
282 : * the notification. So it should be safe to set the REAL flag here. */
283 109 : SET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
284 :
285 109 : connected_update(ifp, ifc);
286 109 : }
287 :
288 : void
289 4 : connected_down_ipv4 (struct interface *ifp, struct connected *ifc)
290 : {
291 : struct prefix_ipv4 p;
292 :
293 4 : if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
294 0 : return;
295 :
296 4 : PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
297 :
298 : /* Apply mask to the network. */
299 4 : apply_mask_ipv4 (&p);
300 :
301 : /* In case of connected address is 0.0.0.0/0 we treat it tunnel
302 : address. */
303 4 : if (prefix_ipv4_any (&p))
304 0 : return;
305 :
306 : /* Same logic as for connected_up_ipv4(): push the changes into the head. */
307 4 : rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, SAFI_UNICAST);
308 :
309 4 : rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, SAFI_MULTICAST);
310 :
311 4 : rib_update ();
312 : }
313 :
314 : /* Delete connected IPv4 route to the interface. */
315 : void
316 2 : connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
317 : u_char prefixlen, struct in_addr *broad)
318 : {
319 : struct prefix_ipv4 p;
320 : struct connected *ifc;
321 :
322 2 : memset (&p, 0, sizeof (struct prefix_ipv4));
323 2 : p.family = AF_INET;
324 2 : p.prefix = *addr;
325 2 : p.prefixlen = prefixlen;
326 :
327 2 : ifc = connected_check (ifp, (struct prefix *) &p);
328 2 : if (! ifc)
329 0 : return;
330 :
331 2 : connected_withdraw (ifc);
332 :
333 2 : rib_update();
334 : }
335 :
336 : #ifdef HAVE_IPV6
337 : void
338 171 : connected_up_ipv6 (struct interface *ifp, struct connected *ifc)
339 : {
340 : struct prefix_ipv6 p;
341 :
342 171 : if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
343 2 : return;
344 :
345 170 : PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
346 :
347 : /* Apply mask to the network. */
348 170 : apply_mask_ipv6 (&p);
349 :
350 : #if ! defined (MUSICA) && ! defined (LINUX)
351 : /* XXX: It is already done by rib_bogus_ipv6 within rib_add_ipv6 */
352 170 : if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
353 0 : return;
354 : #endif
355 :
356 170 : rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex,
357 170 : RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST);
358 :
359 170 : rib_update ();
360 : }
361 :
362 : /* Add connected IPv6 route to the interface. */
363 : void
364 170 : connected_add_ipv6 (struct interface *ifp, int flags, struct in6_addr *addr,
365 : u_char prefixlen, struct in6_addr *broad,
366 : const char *label)
367 : {
368 : struct prefix_ipv6 *p;
369 : struct connected *ifc;
370 :
371 : /* Make connected structure. */
372 170 : ifc = connected_new ();
373 170 : ifc->ifp = ifp;
374 170 : ifc->flags = flags;
375 : /* If we get a notification from the kernel,
376 : * we can safely assume the address is known to the kernel */
377 170 : SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
378 :
379 : /* Allocate new connected address. */
380 170 : p = prefix_ipv6_new ();
381 170 : p->family = AF_INET6;
382 170 : IPV6_ADDR_COPY (&p->prefix, addr);
383 170 : p->prefixlen = prefixlen;
384 170 : ifc->address = (struct prefix *) p;
385 :
386 : /* If there is broadcast or peer address. */
387 170 : if (broad)
388 : {
389 0 : if (IN6_IS_ADDR_UNSPECIFIED(broad))
390 0 : zlog_warn("warning: %s called for interface %s with unspecified "
391 0 : "destination address; ignoring!", __func__, ifp->name);
392 : else
393 : {
394 0 : p = prefix_ipv6_new ();
395 0 : p->family = AF_INET6;
396 0 : IPV6_ADDR_COPY (&p->prefix, broad);
397 0 : p->prefixlen = prefixlen;
398 0 : ifc->destination = (struct prefix *) p;
399 : }
400 : }
401 170 : if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER) && !ifc->destination)
402 : {
403 0 : zlog_warn("warning: %s called for interface %s "
404 : "with peer flag set, but no peer address supplied",
405 0 : __func__, ifp->name);
406 0 : UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
407 : }
408 :
409 : /* Label of this address. */
410 170 : if (label)
411 0 : ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
412 :
413 : /* On Linux, we only get here when DAD is complete, therefore we can set
414 : * ZEBRA_IFC_REAL.
415 : *
416 : * On BSD, there currently doesn't seem to be a way to check for completion of
417 : * DAD, so we replicate the old behaviour and set ZEBRA_IFC_REAL, although DAD
418 : * might still be running.
419 : */
420 170 : SET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
421 170 : connected_update(ifp, ifc);
422 170 : }
423 :
424 : void
425 10 : connected_down_ipv6 (struct interface *ifp, struct connected *ifc)
426 : {
427 : struct prefix_ipv6 p;
428 :
429 10 : if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
430 0 : return;
431 :
432 10 : PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
433 :
434 10 : apply_mask_ipv6 (&p);
435 :
436 10 : if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
437 0 : return;
438 :
439 10 : rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex, 0,
440 : SAFI_UNICAST);
441 :
442 10 : rib_update ();
443 : }
444 :
445 : void
446 6 : connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address,
447 : u_char prefixlen, struct in6_addr *broad)
448 : {
449 : struct prefix_ipv6 p;
450 : struct connected *ifc;
451 :
452 6 : memset (&p, 0, sizeof (struct prefix_ipv6));
453 6 : p.family = AF_INET6;
454 6 : memcpy (&p.prefix, address, sizeof (struct in6_addr));
455 6 : p.prefixlen = prefixlen;
456 :
457 6 : ifc = connected_check (ifp, (struct prefix *) &p);
458 6 : if (! ifc)
459 0 : return;
460 :
461 6 : connected_withdraw (ifc);
462 :
463 6 : rib_update();
464 : }
465 : #endif /* HAVE_IPV6 */
|