blob: ceee0e2b8dd05bc7df0d7364d1f9dab01f94917f [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
2 * Interface function.
3 * Copyright (C) 1997, 1999 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 "if.h"
26#include "vty.h"
27#include "sockunion.h"
28#include "prefix.h"
29#include "command.h"
30#include "memory.h"
31#include "ioctl.h"
32#include "connected.h"
33#include "log.h"
34#include "zclient.h"
35
36#include "zebra/interface.h"
37#include "zebra/rtadv.h"
38#include "zebra/rib.h"
39#include "zebra/zserv.h"
40#include "zebra/redistribute.h"
41#include "zebra/debug.h"
hassoca776982004-06-12 14:33:05 +000042#include "zebra/irdp.h"
paul718e3742002-12-13 20:15:29 +000043
paul718e3742002-12-13 20:15:29 +000044
45/* Called when new interface is added. */
paula1ac18c2005-06-28 17:17:12 +000046static int
paul718e3742002-12-13 20:15:29 +000047if_zebra_new_hook (struct interface *ifp)
48{
49 struct zebra_if *zebra_if;
50
51 zebra_if = XMALLOC (MTYPE_TMP, sizeof (struct zebra_if));
52 memset (zebra_if, 0, sizeof (struct zebra_if));
53
54 zebra_if->multicast = IF_ZEBRA_MULTICAST_UNSPEC;
55 zebra_if->shutdown = IF_ZEBRA_SHUTDOWN_UNSPEC;
56
57#ifdef RTADV
58 {
59 /* Set default router advertise values. */
60 struct rtadvconf *rtadv;
61
62 rtadv = &zebra_if->rtadv;
63
64 rtadv->AdvSendAdvertisements = 0;
65 rtadv->MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
66 rtadv->MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
67 rtadv->AdvIntervalTimer = 0;
68 rtadv->AdvManagedFlag = 0;
69 rtadv->AdvOtherConfigFlag = 0;
vincent7cee1bb2005-03-25 13:08:53 +000070 rtadv->AdvHomeAgentFlag = 0;
paul718e3742002-12-13 20:15:29 +000071 rtadv->AdvLinkMTU = 0;
72 rtadv->AdvReachableTime = 0;
73 rtadv->AdvRetransTimer = 0;
74 rtadv->AdvCurHopLimit = 0;
75 rtadv->AdvDefaultLifetime = RTADV_ADV_DEFAULT_LIFETIME;
vincent7cee1bb2005-03-25 13:08:53 +000076 rtadv->HomeAgentPreference = 0;
77 rtadv->HomeAgentLifetime = RTADV_ADV_DEFAULT_LIFETIME;
78 rtadv->AdvIntervalOption = 0;
paul718e3742002-12-13 20:15:29 +000079
80 rtadv->AdvPrefixList = list_new ();
81 }
82#endif /* RTADV */
83
hassoeef1fe12004-10-03 18:46:08 +000084 /* Initialize installed address chains tree. */
85 zebra_if->ipv4_subnets = route_table_init ();
86
paul718e3742002-12-13 20:15:29 +000087 ifp->info = zebra_if;
88 return 0;
89}
90
91/* Called when interface is deleted. */
paula1ac18c2005-06-28 17:17:12 +000092static int
paul718e3742002-12-13 20:15:29 +000093if_zebra_delete_hook (struct interface *ifp)
94{
hassoeef1fe12004-10-03 18:46:08 +000095 struct zebra_if *zebra_if;
96
paul718e3742002-12-13 20:15:29 +000097 if (ifp->info)
hassoeef1fe12004-10-03 18:46:08 +000098 {
99 zebra_if = ifp->info;
100
101 /* Free installed address chains tree. */
102 if (zebra_if->ipv4_subnets)
103 route_table_finish (zebra_if->ipv4_subnets);
104
105 XFREE (MTYPE_TMP, zebra_if);
106 }
107
108 return 0;
109}
110
111/* Tie an interface address to its derived subnet list of addresses. */
112int
113if_subnet_add (struct interface *ifp, struct connected *ifc)
114{
115 struct route_node *rn;
116 struct zebra_if *zebra_if;
117 struct prefix cp;
118 struct list *addr_list;
119
120 assert (ifp && ifp->info && ifc);
121 zebra_if = ifp->info;
122
123 /* Get address derived subnet node and associated address list, while marking
124 address secondary attribute appropriately. */
125 cp = *ifc->address;
126 apply_mask (&cp);
127 rn = route_node_get (zebra_if->ipv4_subnets, &cp);
128
129 if ((addr_list = rn->info))
130 SET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY);
131 else
132 {
133 UNSET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY);
134 rn->info = addr_list = list_new ();
135 route_lock_node (rn);
136 }
137
138 /* Tie address at the tail of address list. */
139 listnode_add (addr_list, ifc);
140
141 /* Return list element count. */
142 return (addr_list->count);
143}
144
145/* Untie an interface address from its derived subnet list of addresses. */
146int
147if_subnet_delete (struct interface *ifp, struct connected *ifc)
148{
149 struct route_node *rn;
150 struct zebra_if *zebra_if;
151 struct list *addr_list;
152
153 assert (ifp && ifp->info && ifc);
154 zebra_if = ifp->info;
155
156 /* Get address derived subnet node. */
157 rn = route_node_lookup (zebra_if->ipv4_subnets, ifc->address);
158 if (! (rn && rn->info))
159 return -1;
160 route_unlock_node (rn);
161
162 /* Untie address from subnet's address list. */
163 addr_list = rn->info;
164 listnode_delete (addr_list, ifc);
165 route_unlock_node (rn);
166
167 /* Return list element count, if not empty. */
168 if (addr_list->count)
169 {
170 /* If deleted address is primary, mark subsequent one as such and distribute. */
171 if (! CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY))
172 {
paul1eb8ef22005-04-07 07:30:20 +0000173 ifc = listgetdata (listhead (addr_list));
hassoeef1fe12004-10-03 18:46:08 +0000174 zebra_interface_address_delete_update (ifp, ifc);
175 UNSET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY);
176 zebra_interface_address_add_update (ifp, ifc);
177 }
178
179 return addr_list->count;
180 }
181
182 /* Otherwise, free list and route node. */
183 list_free (addr_list);
184 rn->info = NULL;
185 route_unlock_node (rn);
186
paul718e3742002-12-13 20:15:29 +0000187 return 0;
188}
189
paul5c78b3d2006-01-25 04:31:40 +0000190/* if_flags_mangle: A place for hacks that require mangling
191 * or tweaking the interface flags.
192 *
193 * ******************** Solaris flags hacks **************************
194 *
195 * Solaris IFF_UP flag reflects only the primary interface as the
196 * routing socket only sends IFINFO for the primary interface. Hence
197 * ~IFF_UP does not per se imply all the logical interfaces are also
198 * down - which we only know of as addresses. Instead we must determine
199 * whether the interface really is up or not according to how many
200 * addresses are still attached. (Solaris always sends RTM_DELADDR if
201 * an interface, logical or not, goes ~IFF_UP).
202 *
203 * Ie, we mangle IFF_UP to *additionally* reflect whether or not there
204 * are addresses left in struct connected, not just the actual underlying
205 * IFF_UP flag.
206 *
207 * We must hence remember the real state of IFF_UP, which we do in
208 * struct zebra_if.primary_state.
209 *
210 * Setting IFF_UP within zebra to administratively shutdown the
211 * interface will affect only the primary interface/address on Solaris.
212 ************************End Solaris flags hacks ***********************
213 */
214static inline void
215if_flags_mangle (struct interface *ifp, uint64_t *newflags)
216{
217#ifdef SUNOS_5
218 struct zebra_if *zif = ifp->info;
219
220 zif->primary_state = *newflags & (IFF_UP & 0xff);
221
222 if (CHECK_FLAG (zif->primary_state, IFF_UP)
223 || listcount(ifp->connected) > 0)
224 SET_FLAG (*newflags, IFF_UP);
225 else
226 UNSET_FLAG (*newflags, IFF_UP);
227#endif /* SUNOS_5 */
228}
229
230/* Update the flags field of the ifp with the new flag set provided.
231 * Take whatever actions are required for any changes in flags we care
232 * about.
233 *
234 * newflags should be the raw value, as obtained from the OS.
235 */
236void
237if_flags_update (struct interface *ifp, uint64_t newflags)
238{
239 if_flags_mangle (ifp, &newflags);
240
241 if (if_is_operative (ifp))
242 {
243 /* operative -> inoperative? */
244 ifp->flags = newflags;
245 if (!if_is_operative (ifp))
246 if_down (ifp);
247 }
248 else
249 {
250 /* inoperative -> operative? */
251 ifp->flags = newflags;
252 if (if_is_operative (ifp))
253 if_up (ifp);
254 }
255}
256
paul718e3742002-12-13 20:15:29 +0000257/* Wake up configured address if it is not in current kernel
258 address. */
paula1ac18c2005-06-28 17:17:12 +0000259static void
paul718e3742002-12-13 20:15:29 +0000260if_addr_wakeup (struct interface *ifp)
261{
paul1eb8ef22005-04-07 07:30:20 +0000262 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000263 struct connected *ifc;
264 struct prefix *p;
265 int ret;
266
paul1eb8ef22005-04-07 07:30:20 +0000267 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, ifc))
paul718e3742002-12-13 20:15:29 +0000268 {
paul718e3742002-12-13 20:15:29 +0000269 p = ifc->address;
270
271 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)
272 && ! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
273 {
274 /* Address check. */
275 if (p->family == AF_INET)
276 {
277 if (! if_is_up (ifp))
278 {
paul0752ef02005-11-03 12:35:21 +0000279 /* XXX: WTF is it trying to set flags here?
280 * caller has just gotten a new interface, has been
281 * handed the flags already. This code has no business
282 * trying to override administrative status of the interface.
283 * The only call path to here which doesn't originate from
284 * kernel event is irdp - what on earth is it trying to do?
285 *
286 * further RUNNING is not a settable flag on any system
287 * I (paulj) am aware of.
288 */
paul718e3742002-12-13 20:15:29 +0000289 if_set_flags (ifp, IFF_UP | IFF_RUNNING);
290 if_refresh (ifp);
291 }
292
293 ret = if_set_prefix (ifp, ifc);
294 if (ret < 0)
295 {
296 zlog_warn ("Can't set interface's address: %s",
ajs6099b3b2004-11-20 02:06:59 +0000297 safe_strerror(errno));
paul718e3742002-12-13 20:15:29 +0000298 continue;
299 }
hassoeef1fe12004-10-03 18:46:08 +0000300
301 /* Add to subnet chain list. */
302 if_subnet_add (ifp, ifc);
303
paul718e3742002-12-13 20:15:29 +0000304 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
305
306 zebra_interface_address_add_update (ifp, ifc);
307
paul2e3b2e42002-12-13 21:03:13 +0000308 if (if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000309 connected_up_ipv4 (ifp, ifc);
310 }
311#ifdef HAVE_IPV6
312 if (p->family == AF_INET6)
313 {
314 if (! if_is_up (ifp))
315 {
paul0752ef02005-11-03 12:35:21 +0000316 /* XXX: See long comment above */
paul718e3742002-12-13 20:15:29 +0000317 if_set_flags (ifp, IFF_UP | IFF_RUNNING);
318 if_refresh (ifp);
319 }
320
321 ret = if_prefix_add_ipv6 (ifp, ifc);
322 if (ret < 0)
323 {
324 zlog_warn ("Can't set interface's address: %s",
ajs6099b3b2004-11-20 02:06:59 +0000325 safe_strerror(errno));
paul718e3742002-12-13 20:15:29 +0000326 continue;
327 }
328 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
329
330 zebra_interface_address_add_update (ifp, ifc);
331
paul2e3b2e42002-12-13 21:03:13 +0000332 if (if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000333 connected_up_ipv6 (ifp, ifc);
334 }
335#endif /* HAVE_IPV6 */
336 }
337 }
338}
339
340/* Handle interface addition */
341void
342if_add_update (struct interface *ifp)
343{
paul48b33aa2002-12-13 20:52:52 +0000344 struct zebra_if *if_data;
345
346 if_data = ifp->info;
347 if (if_data->multicast == IF_ZEBRA_MULTICAST_ON)
348 if_set_flags (ifp, IFF_MULTICAST);
349 else if (if_data->multicast == IF_ZEBRA_MULTICAST_OFF)
350 if_unset_flags (ifp, IFF_MULTICAST);
351
paul718e3742002-12-13 20:15:29 +0000352 zebra_interface_add_update (ifp);
353
354 if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
355 {
356 SET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE);
357
358 if_addr_wakeup (ifp);
359
360 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +0000361 zlog_debug ("interface %s index %d becomes active.",
362 ifp->name, ifp->ifindex);
paul718e3742002-12-13 20:15:29 +0000363 }
364 else
365 {
366 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +0000367 zlog_debug ("interface %s index %d is added.", ifp->name, ifp->ifindex);
paul718e3742002-12-13 20:15:29 +0000368 }
369}
370
paul6eb88272005-07-29 14:36:00 +0000371/* Handle an interface delete event */
paul718e3742002-12-13 20:15:29 +0000372void
373if_delete_update (struct interface *ifp)
374{
375 struct listnode *node;
376 struct listnode *next;
hassoeef1fe12004-10-03 18:46:08 +0000377 struct listnode *first;
378 struct listnode *last;
paul718e3742002-12-13 20:15:29 +0000379 struct connected *ifc;
380 struct prefix *p;
hassoeef1fe12004-10-03 18:46:08 +0000381 struct route_node *rn;
382 struct zebra_if *zebra_if;
383 struct list *addr_list;
384
385 zebra_if = ifp->info;
paul718e3742002-12-13 20:15:29 +0000386
387 if (if_is_up(ifp))
388 {
389 zlog_err ("interface %s index %d is still up while being deleted.",
390 ifp->name, ifp->ifindex);
391 return;
392 }
393
394 /* Mark interface as inactive */
395 UNSET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE);
396
397 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +0000398 zlog_debug ("interface %s index %d is now inactive.",
paul718e3742002-12-13 20:15:29 +0000399 ifp->name, ifp->ifindex);
400
401 /* Delete connected routes from the kernel. */
402 if (ifp->connected)
403 {
hassoeef1fe12004-10-03 18:46:08 +0000404 last = NULL;
405 while ((node = (last ? last->next : listhead (ifp->connected))))
paul718e3742002-12-13 20:15:29 +0000406 {
paul1eb8ef22005-04-07 07:30:20 +0000407 ifc = listgetdata (node);
paul718e3742002-12-13 20:15:29 +0000408 p = ifc->address;
hassoeef1fe12004-10-03 18:46:08 +0000409
Paul Jakmabeb56332006-05-11 13:28:05 +0000410 if (p->family == AF_INET
411 && (rn = route_node_lookup (zebra_if->ipv4_subnets, p)))
hassoeef1fe12004-10-03 18:46:08 +0000412 {
hassoeef1fe12004-10-03 18:46:08 +0000413 route_unlock_node (rn);
414 addr_list = (struct list *) rn->info;
415
416 /* Remove addresses, secondaries first. */
417 first = listhead (addr_list);
418 for (node = first->next; node || first; node = next)
419 {
420 if (! node)
421 {
422 node = first;
423 first = NULL;
424 }
425 next = node->next;
426
paul1eb8ef22005-04-07 07:30:20 +0000427 ifc = listgetdata (node);
hassoeef1fe12004-10-03 18:46:08 +0000428 p = ifc->address;
429
430 connected_down_ipv4 (ifp, ifc);
431
432 zebra_interface_address_delete_update (ifp, ifc);
433
434 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
435
436 /* Remove from subnet chain. */
437 list_delete_node (addr_list, node);
438 route_unlock_node (rn);
439
440 /* Remove from interface address list (unconditionally). */
441 listnode_delete (ifp->connected, ifc);
442 connected_free (ifc);
443 }
444
445 /* Free chain list and respective route node. */
446 list_delete (addr_list);
447 rn->info = NULL;
448 route_unlock_node (rn);
449 }
paul718e3742002-12-13 20:15:29 +0000450#ifdef HAVE_IPV6
451 else if (p->family == AF_INET6)
hassoeef1fe12004-10-03 18:46:08 +0000452 {
453 connected_down_ipv6 (ifp, ifc);
paul718e3742002-12-13 20:15:29 +0000454
hassoeef1fe12004-10-03 18:46:08 +0000455 zebra_interface_address_delete_update (ifp, ifc);
paul718e3742002-12-13 20:15:29 +0000456
hassoeef1fe12004-10-03 18:46:08 +0000457 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
458
459 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
460 last = node;
461 else
462 {
463 listnode_delete (ifp->connected, ifc);
464 connected_free (ifc);
465 }
paul718e3742002-12-13 20:15:29 +0000466 }
hassoeef1fe12004-10-03 18:46:08 +0000467#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +0000468 }
469 }
470 zebra_interface_delete_update (ifp);
ajsd2fc8892005-04-02 18:38:43 +0000471
472 /* Update ifindex after distributing the delete message. This is in
473 case any client needs to have the old value of ifindex available
474 while processing the deletion. Each client daemon is responsible
475 for setting ifindex to IFINDEX_INTERNAL after processing the
476 interface deletion message. */
477 ifp->ifindex = IFINDEX_INTERNAL;
paul718e3742002-12-13 20:15:29 +0000478}
479
480/* Interface is up. */
481void
482if_up (struct interface *ifp)
483{
hasso52dc7ee2004-09-23 19:18:23 +0000484 struct listnode *node;
485 struct listnode *next;
paul718e3742002-12-13 20:15:29 +0000486 struct connected *ifc;
487 struct prefix *p;
488
489 /* Notify the protocol daemons. */
490 zebra_interface_up_update (ifp);
491
492 /* Install connected routes to the kernel. */
493 if (ifp->connected)
494 {
paul1eb8ef22005-04-07 07:30:20 +0000495 for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc))
paul718e3742002-12-13 20:15:29 +0000496 {
paul718e3742002-12-13 20:15:29 +0000497 p = ifc->address;
498
499 if (p->family == AF_INET)
500 connected_up_ipv4 (ifp, ifc);
501#ifdef HAVE_IPV6
502 else if (p->family == AF_INET6)
503 connected_up_ipv6 (ifp, ifc);
504#endif /* HAVE_IPV6 */
505 }
506 }
507
508 /* Examine all static routes. */
509 rib_update ();
510}
511
512/* Interface goes down. We have to manage different behavior of based
513 OS. */
514void
515if_down (struct interface *ifp)
516{
hasso52dc7ee2004-09-23 19:18:23 +0000517 struct listnode *node;
518 struct listnode *next;
paul718e3742002-12-13 20:15:29 +0000519 struct connected *ifc;
520 struct prefix *p;
521
522 /* Notify to the protocol daemons. */
523 zebra_interface_down_update (ifp);
524
525 /* Delete connected routes from the kernel. */
526 if (ifp->connected)
527 {
paul1eb8ef22005-04-07 07:30:20 +0000528 for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc))
paul718e3742002-12-13 20:15:29 +0000529 {
paul718e3742002-12-13 20:15:29 +0000530 p = ifc->address;
531
532 if (p->family == AF_INET)
533 connected_down_ipv4 (ifp, ifc);
534#ifdef HAVE_IPV6
535 else if (p->family == AF_INET6)
536 connected_down_ipv6 (ifp, ifc);
537#endif /* HAVE_IPV6 */
538 }
539 }
540
541 /* Examine all static routes which direct to the interface. */
542 rib_update ();
543}
544
545void
546if_refresh (struct interface *ifp)
547{
paul5c78b3d2006-01-25 04:31:40 +0000548 if_get_flags (ifp);
paul718e3742002-12-13 20:15:29 +0000549}
550
paul718e3742002-12-13 20:15:29 +0000551/* Output prefix string to vty. */
paula1ac18c2005-06-28 17:17:12 +0000552static int
paul718e3742002-12-13 20:15:29 +0000553prefix_vty_out (struct vty *vty, struct prefix *p)
554{
555 char str[INET6_ADDRSTRLEN];
556
557 inet_ntop (p->family, &p->u.prefix, str, sizeof (str));
558 vty_out (vty, "%s", str);
559 return strlen (str);
560}
561
562/* Dump if address information to vty. */
paula1ac18c2005-06-28 17:17:12 +0000563static void
paul718e3742002-12-13 20:15:29 +0000564connected_dump_vty (struct vty *vty, struct connected *connected)
565{
566 struct prefix *p;
paul718e3742002-12-13 20:15:29 +0000567
568 /* Print interface address. */
569 p = connected->address;
570 vty_out (vty, " %s ", prefix_family_str (p));
571 prefix_vty_out (vty, p);
572 vty_out (vty, "/%d", p->prefixlen);
573
574 /* If there is destination address, print it. */
Andrew J. Schorre4529632006-12-12 19:18:21 +0000575 if (connected->destination)
paul718e3742002-12-13 20:15:29 +0000576 {
Andrew J. Schorre4529632006-12-12 19:18:21 +0000577 vty_out (vty, (CONNECTED_PEER(connected) ? " peer " : " broadcast "));
578 prefix_vty_out (vty, connected->destination);
paul718e3742002-12-13 20:15:29 +0000579 }
580
581 if (CHECK_FLAG (connected->flags, ZEBRA_IFA_SECONDARY))
582 vty_out (vty, " secondary");
583
584 if (connected->label)
585 vty_out (vty, " %s", connected->label);
586
587 vty_out (vty, "%s", VTY_NEWLINE);
588}
589
590#ifdef RTADV
591/* Dump interface ND information to vty. */
paula1ac18c2005-06-28 17:17:12 +0000592static void
paul718e3742002-12-13 20:15:29 +0000593nd_dump_vty (struct vty *vty, struct interface *ifp)
594{
595 struct zebra_if *zif;
596 struct rtadvconf *rtadv;
vincent7cee1bb2005-03-25 13:08:53 +0000597 int interval;
paul718e3742002-12-13 20:15:29 +0000598
599 zif = (struct zebra_if *) ifp->info;
600 rtadv = &zif->rtadv;
601
602 if (rtadv->AdvSendAdvertisements)
603 {
604 vty_out (vty, " ND advertised reachable time is %d milliseconds%s",
605 rtadv->AdvReachableTime, VTY_NEWLINE);
606 vty_out (vty, " ND advertised retransmit interval is %d milliseconds%s",
607 rtadv->AdvRetransTimer, VTY_NEWLINE);
vincent7cee1bb2005-03-25 13:08:53 +0000608 interval = rtadv->MaxRtrAdvInterval;
609 if (interval % 1000)
610 vty_out (vty, " ND router advertisements are sent every "
611 "%d milliseconds%s", interval,
612 VTY_NEWLINE);
613 else
614 vty_out (vty, " ND router advertisements are sent every "
615 "%d seconds%s", interval / 1000,
616 VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000617 vty_out (vty, " ND router advertisements live for %d seconds%s",
618 rtadv->AdvDefaultLifetime, VTY_NEWLINE);
619 if (rtadv->AdvManagedFlag)
620 vty_out (vty, " Hosts use DHCP to obtain routable addresses.%s",
621 VTY_NEWLINE);
622 else
623 vty_out (vty, " Hosts use stateless autoconfig for addresses.%s",
624 VTY_NEWLINE);
vincent7cee1bb2005-03-25 13:08:53 +0000625 if (rtadv->AdvHomeAgentFlag)
626 vty_out (vty, " ND router advertisements with "
627 "Home Agent flag bit set.%s",
628 VTY_NEWLINE);
629 if (rtadv->AdvIntervalOption)
630 vty_out (vty, " ND router advertisements with Adv. Interval option.%s",
631 VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000632 }
633}
634#endif /* RTADV */
635
636/* Interface's information print out to vty interface. */
paula1ac18c2005-06-28 17:17:12 +0000637static void
paul718e3742002-12-13 20:15:29 +0000638if_dump_vty (struct vty *vty, struct interface *ifp)
639{
640#ifdef HAVE_SOCKADDR_DL
641 struct sockaddr_dl *sdl;
642#endif /* HAVE_SOCKADDR_DL */
643 struct connected *connected;
hasso52dc7ee2004-09-23 19:18:23 +0000644 struct listnode *node;
hassoeef1fe12004-10-03 18:46:08 +0000645 struct route_node *rn;
646 struct zebra_if *zebra_if;
647
648 zebra_if = ifp->info;
paul718e3742002-12-13 20:15:29 +0000649
paul2e3b2e42002-12-13 21:03:13 +0000650 vty_out (vty, "Interface %s is ", ifp->name);
651 if (if_is_up(ifp)) {
652 vty_out (vty, "up, line protocol ");
653
654 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) {
655 if (if_is_running(ifp))
656 vty_out (vty, "is up%s", VTY_NEWLINE);
657 else
658 vty_out (vty, "is down%s", VTY_NEWLINE);
659 } else {
660 vty_out (vty, "detection is disabled%s", VTY_NEWLINE);
661 }
662 } else {
663 vty_out (vty, "down%s", VTY_NEWLINE);
664 }
665
paul718e3742002-12-13 20:15:29 +0000666 if (ifp->desc)
667 vty_out (vty, " Description: %s%s", ifp->desc,
668 VTY_NEWLINE);
ajsd2fc8892005-04-02 18:38:43 +0000669 if (ifp->ifindex == IFINDEX_INTERNAL)
paul718e3742002-12-13 20:15:29 +0000670 {
ajsd2fc8892005-04-02 18:38:43 +0000671 vty_out(vty, " pseudo interface%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000672 return;
673 }
674 else if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
675 {
676 vty_out(vty, " index %d inactive interface%s",
677 ifp->ifindex,
678 VTY_NEWLINE);
679 return;
680 }
681
682 vty_out (vty, " index %d metric %d mtu %d ",
683 ifp->ifindex, ifp->metric, ifp->mtu);
paul44145db2004-05-09 11:00:23 +0000684#ifdef HAVE_IPV6
685 if (ifp->mtu6 != ifp->mtu)
686 vty_out (vty, "mtu6 %d ", ifp->mtu6);
687#endif
Paul Jakma630c97c2006-06-15 12:48:17 +0000688 vty_out (vty, "%s flags: %s%s", VTY_NEWLINE,
689 if_flag_dump (ifp->flags), VTY_NEWLINE);
paul3a570c82006-02-02 17:27:13 +0000690
paul718e3742002-12-13 20:15:29 +0000691 /* Hardware address. */
692#ifdef HAVE_SOCKADDR_DL
693 sdl = &ifp->sdl;
694 if (sdl != NULL && sdl->sdl_alen != 0)
695 {
696 int i;
697 u_char *ptr;
698
699 vty_out (vty, " HWaddr: ");
paul5b73a672004-07-23 15:26:14 +0000700 for (i = 0, ptr = (u_char *)LLADDR (sdl); i < sdl->sdl_alen; i++, ptr++)
701 vty_out (vty, "%s%02x", i == 0 ? "" : ":", *ptr);
paul718e3742002-12-13 20:15:29 +0000702 vty_out (vty, "%s", VTY_NEWLINE);
703 }
704#else
705 if (ifp->hw_addr_len != 0)
706 {
707 int i;
708
709 vty_out (vty, " HWaddr: ");
710 for (i = 0; i < ifp->hw_addr_len; i++)
711 vty_out (vty, "%s%02x", i == 0 ? "" : ":", ifp->hw_addr[i]);
712 vty_out (vty, "%s", VTY_NEWLINE);
713 }
714#endif /* HAVE_SOCKADDR_DL */
715
716 /* Bandwidth in kbps */
717 if (ifp->bandwidth != 0)
718 {
719 vty_out(vty, " bandwidth %u kbps", ifp->bandwidth);
720 vty_out(vty, "%s", VTY_NEWLINE);
721 }
722
hassoeef1fe12004-10-03 18:46:08 +0000723 for (rn = route_top (zebra_if->ipv4_subnets); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000724 {
hassoeef1fe12004-10-03 18:46:08 +0000725 if (! rn->info)
726 continue;
727
paul1eb8ef22005-04-07 07:30:20 +0000728 for (ALL_LIST_ELEMENTS_RO ((struct list *)rn->info, node, connected))
729 connected_dump_vty (vty, connected);
paul718e3742002-12-13 20:15:29 +0000730 }
731
paul1eb8ef22005-04-07 07:30:20 +0000732 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
hasso39db97e2004-10-12 20:50:58 +0000733 {
hasso39db97e2004-10-12 20:50:58 +0000734 if (CHECK_FLAG (connected->conf, ZEBRA_IFC_REAL) &&
735 (connected->address->family == AF_INET6))
736 connected_dump_vty (vty, connected);
737 }
738
paul718e3742002-12-13 20:15:29 +0000739#ifdef RTADV
740 nd_dump_vty (vty, ifp);
741#endif /* RTADV */
742
743#ifdef HAVE_PROC_NET_DEV
744 /* Statistics print out using proc file system. */
hasso6f2c27a2005-01-18 13:44:35 +0000745 vty_out (vty, " %lu input packets (%lu multicast), %lu bytes, "
746 "%lu dropped%s",
747 ifp->stats.rx_packets, ifp->stats.rx_multicast,
748 ifp->stats.rx_bytes, ifp->stats.rx_dropped, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000749
hasso6f2c27a2005-01-18 13:44:35 +0000750 vty_out (vty, " %lu input errors, %lu length, %lu overrun,"
hasso3452d472005-03-06 13:42:05 +0000751 " %lu CRC, %lu frame%s",
paul718e3742002-12-13 20:15:29 +0000752 ifp->stats.rx_errors, ifp->stats.rx_length_errors,
753 ifp->stats.rx_over_errors, ifp->stats.rx_crc_errors,
hasso6f2c27a2005-01-18 13:44:35 +0000754 ifp->stats.rx_frame_errors, VTY_NEWLINE);
755
756 vty_out (vty, " %lu fifo, %lu missed%s", ifp->stats.rx_fifo_errors,
paul718e3742002-12-13 20:15:29 +0000757 ifp->stats.rx_missed_errors, VTY_NEWLINE);
758
hasso6f2c27a2005-01-18 13:44:35 +0000759 vty_out (vty, " %lu output packets, %lu bytes, %lu dropped%s",
paul718e3742002-12-13 20:15:29 +0000760 ifp->stats.tx_packets, ifp->stats.tx_bytes,
761 ifp->stats.tx_dropped, VTY_NEWLINE);
762
hasso6f2c27a2005-01-18 13:44:35 +0000763 vty_out (vty, " %lu output errors, %lu aborted, %lu carrier,"
764 " %lu fifo, %lu heartbeat%s",
paul718e3742002-12-13 20:15:29 +0000765 ifp->stats.tx_errors, ifp->stats.tx_aborted_errors,
766 ifp->stats.tx_carrier_errors, ifp->stats.tx_fifo_errors,
hasso6f2c27a2005-01-18 13:44:35 +0000767 ifp->stats.tx_heartbeat_errors, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000768
hasso6f2c27a2005-01-18 13:44:35 +0000769 vty_out (vty, " %lu window, %lu collisions%s",
770 ifp->stats.tx_window_errors, ifp->stats.collisions, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000771#endif /* HAVE_PROC_NET_DEV */
772
773#ifdef HAVE_NET_RT_IFLIST
774#if defined (__bsdi__) || defined (__NetBSD__)
775 /* Statistics print out using sysctl (). */
776 vty_out (vty, " input packets %qu, bytes %qu, dropped %qu,"
777 " multicast packets %qu%s",
778 ifp->stats.ifi_ipackets, ifp->stats.ifi_ibytes,
779 ifp->stats.ifi_iqdrops, ifp->stats.ifi_imcasts,
780 VTY_NEWLINE);
781
782 vty_out (vty, " input errors %qu%s",
783 ifp->stats.ifi_ierrors, VTY_NEWLINE);
784
785 vty_out (vty, " output packets %qu, bytes %qu, multicast packets %qu%s",
786 ifp->stats.ifi_opackets, ifp->stats.ifi_obytes,
787 ifp->stats.ifi_omcasts, VTY_NEWLINE);
788
789 vty_out (vty, " output errors %qu%s",
790 ifp->stats.ifi_oerrors, VTY_NEWLINE);
791
792 vty_out (vty, " collisions %qu%s",
793 ifp->stats.ifi_collisions, VTY_NEWLINE);
794#else
795 /* Statistics print out using sysctl (). */
796 vty_out (vty, " input packets %lu, bytes %lu, dropped %lu,"
797 " multicast packets %lu%s",
798 ifp->stats.ifi_ipackets, ifp->stats.ifi_ibytes,
799 ifp->stats.ifi_iqdrops, ifp->stats.ifi_imcasts,
800 VTY_NEWLINE);
801
802 vty_out (vty, " input errors %lu%s",
803 ifp->stats.ifi_ierrors, VTY_NEWLINE);
804
805 vty_out (vty, " output packets %lu, bytes %lu, multicast packets %lu%s",
806 ifp->stats.ifi_opackets, ifp->stats.ifi_obytes,
807 ifp->stats.ifi_omcasts, VTY_NEWLINE);
808
809 vty_out (vty, " output errors %lu%s",
810 ifp->stats.ifi_oerrors, VTY_NEWLINE);
811
812 vty_out (vty, " collisions %lu%s",
813 ifp->stats.ifi_collisions, VTY_NEWLINE);
814#endif /* __bsdi__ || __NetBSD__ */
815#endif /* HAVE_NET_RT_IFLIST */
816}
817
818/* Check supported address family. */
paula1ac18c2005-06-28 17:17:12 +0000819static int
paul718e3742002-12-13 20:15:29 +0000820if_supported_family (int family)
821{
822 if (family == AF_INET)
823 return 1;
824#ifdef HAVE_IPV6
825 if (family == AF_INET6)
826 return 1;
827#endif /* HAVE_IPV6 */
828 return 0;
829}
830
831/* Wrapper hook point for zebra daemon so that ifindex can be set
832 * DEFUN macro not used as extract.pl HAS to ignore this
833 * See also interface_cmd in lib/if.c
834 */
835DEFUN_NOSH (zebra_interface,
836 zebra_interface_cmd,
837 "interface IFNAME",
838 "Select an interface to configure\n"
839 "Interface's name\n")
840{
841 int ret;
842 struct interface * ifp;
843
844 /* Call lib interface() */
ajsd2fc8892005-04-02 18:38:43 +0000845 if ((ret = interface_cmd.func (self, vty, argc, argv)) != CMD_SUCCESS)
846 return ret;
paul718e3742002-12-13 20:15:29 +0000847
848 ifp = vty->index;
849
ajsd2fc8892005-04-02 18:38:43 +0000850 if (ifp->ifindex == IFINDEX_INTERNAL)
851 /* Is this really necessary? Shouldn't status be initialized to 0
852 in that case? */
853 UNSET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE);
paul718e3742002-12-13 20:15:29 +0000854
855 return ret;
856}
857
paul718e3742002-12-13 20:15:29 +0000858struct cmd_node interface_node =
859{
860 INTERFACE_NODE,
861 "%s(config-if)# ",
862 1
863};
864
865/* Show all or specified interface to vty. */
866DEFUN (show_interface, show_interface_cmd,
867 "show interface [IFNAME]",
868 SHOW_STR
869 "Interface status and configuration\n"
870 "Inteface name\n")
871{
hasso52dc7ee2004-09-23 19:18:23 +0000872 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000873 struct interface *ifp;
874
875#ifdef HAVE_PROC_NET_DEV
876 /* If system has interface statistics via proc file system, update
877 statistics. */
878 ifstat_update_proc ();
879#endif /* HAVE_PROC_NET_DEV */
880#ifdef HAVE_NET_RT_IFLIST
881 ifstat_update_sysctl ();
882#endif /* HAVE_NET_RT_IFLIST */
883
884 /* Specified interface print. */
885 if (argc != 0)
886 {
887 ifp = if_lookup_by_name (argv[0]);
888 if (ifp == NULL)
889 {
890 vty_out (vty, "%% Can't find interface %s%s", argv[0],
891 VTY_NEWLINE);
892 return CMD_WARNING;
893 }
894 if_dump_vty (vty, ifp);
895 return CMD_SUCCESS;
896 }
897
898 /* All interface print. */
paul1eb8ef22005-04-07 07:30:20 +0000899 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
900 if_dump_vty (vty, ifp);
paul718e3742002-12-13 20:15:29 +0000901
902 return CMD_SUCCESS;
903}
904
hassoed9bb6d2005-03-13 19:17:21 +0000905DEFUN (show_interface_desc,
906 show_interface_desc_cmd,
907 "show interface description",
908 SHOW_STR
909 "Interface status and configuration\n"
910 "Interface description\n")
911{
912 struct listnode *node;
913 struct interface *ifp;
914
915 vty_out (vty, "Interface Status Protocol Description%s", VTY_NEWLINE);
paul1eb8ef22005-04-07 07:30:20 +0000916 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
hassoed9bb6d2005-03-13 19:17:21 +0000917 {
918 int len;
hassoed9bb6d2005-03-13 19:17:21 +0000919
920 len = vty_out (vty, "%s", ifp->name);
921 vty_out (vty, "%*s", (16 - len), " ");
922
923 if (if_is_up(ifp))
924 {
925 vty_out (vty, "up ");
926 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION))
927 {
928 if (if_is_running(ifp))
929 vty_out (vty, "up ");
930 else
931 vty_out (vty, "down ");
932 }
933 else
934 {
935 vty_out (vty, "unknown ");
936 }
937 }
938 else
939 {
940 vty_out (vty, "down down ");
941 }
942
943 if (ifp->desc)
944 vty_out (vty, "%s", ifp->desc);
945 vty_out (vty, "%s", VTY_NEWLINE);
946 }
947 return CMD_SUCCESS;
948}
949
paul718e3742002-12-13 20:15:29 +0000950DEFUN (multicast,
951 multicast_cmd,
952 "multicast",
953 "Set multicast flag to interface\n")
954{
955 int ret;
956 struct interface *ifp;
957 struct zebra_if *if_data;
958
959 ifp = (struct interface *) vty->index;
paul48b33aa2002-12-13 20:52:52 +0000960 if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
paul718e3742002-12-13 20:15:29 +0000961 {
paul48b33aa2002-12-13 20:52:52 +0000962 ret = if_set_flags (ifp, IFF_MULTICAST);
963 if (ret < 0)
964 {
965 vty_out (vty, "Can't set multicast flag%s", VTY_NEWLINE);
966 return CMD_WARNING;
967 }
968 if_refresh (ifp);
paul718e3742002-12-13 20:15:29 +0000969 }
paul718e3742002-12-13 20:15:29 +0000970 if_data = ifp->info;
971 if_data->multicast = IF_ZEBRA_MULTICAST_ON;
paul48b33aa2002-12-13 20:52:52 +0000972
paul718e3742002-12-13 20:15:29 +0000973 return CMD_SUCCESS;
974}
975
976DEFUN (no_multicast,
977 no_multicast_cmd,
978 "no multicast",
979 NO_STR
980 "Unset multicast flag to interface\n")
981{
982 int ret;
983 struct interface *ifp;
984 struct zebra_if *if_data;
985
986 ifp = (struct interface *) vty->index;
paul48b33aa2002-12-13 20:52:52 +0000987 if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
paul718e3742002-12-13 20:15:29 +0000988 {
paul48b33aa2002-12-13 20:52:52 +0000989 ret = if_unset_flags (ifp, IFF_MULTICAST);
990 if (ret < 0)
991 {
992 vty_out (vty, "Can't unset multicast flag%s", VTY_NEWLINE);
993 return CMD_WARNING;
994 }
995 if_refresh (ifp);
paul718e3742002-12-13 20:15:29 +0000996 }
paul718e3742002-12-13 20:15:29 +0000997 if_data = ifp->info;
998 if_data->multicast = IF_ZEBRA_MULTICAST_OFF;
999
1000 return CMD_SUCCESS;
1001}
1002
paul2e3b2e42002-12-13 21:03:13 +00001003DEFUN (linkdetect,
1004 linkdetect_cmd,
1005 "link-detect",
1006 "Enable link detection on interface\n")
1007{
paul2e3b2e42002-12-13 21:03:13 +00001008 struct interface *ifp;
1009 int if_was_operative;
1010
1011 ifp = (struct interface *) vty->index;
1012 if_was_operative = if_is_operative(ifp);
1013 SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
1014
1015 /* When linkdetection is enabled, if might come down */
1016 if (!if_is_operative(ifp) && if_was_operative) if_down(ifp);
1017
1018 /* FIXME: Will defer status change forwarding if interface
1019 does not come down! */
1020
1021 return CMD_SUCCESS;
1022}
1023
1024
1025DEFUN (no_linkdetect,
1026 no_linkdetect_cmd,
1027 "no link-detect",
1028 NO_STR
1029 "Disable link detection on interface\n")
1030{
paul2e3b2e42002-12-13 21:03:13 +00001031 struct interface *ifp;
1032 int if_was_operative;
1033
1034 ifp = (struct interface *) vty->index;
1035 if_was_operative = if_is_operative(ifp);
1036 UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
1037
1038 /* Interface may come up after disabling link detection */
1039 if (if_is_operative(ifp) && !if_was_operative) if_up(ifp);
1040
1041 /* FIXME: see linkdetect_cmd */
1042
1043 return CMD_SUCCESS;
1044}
1045
paul718e3742002-12-13 20:15:29 +00001046DEFUN (shutdown_if,
1047 shutdown_if_cmd,
1048 "shutdown",
1049 "Shutdown the selected interface\n")
1050{
1051 int ret;
1052 struct interface *ifp;
1053 struct zebra_if *if_data;
1054
1055 ifp = (struct interface *) vty->index;
1056 ret = if_unset_flags (ifp, IFF_UP);
1057 if (ret < 0)
1058 {
1059 vty_out (vty, "Can't shutdown interface%s", VTY_NEWLINE);
1060 return CMD_WARNING;
1061 }
1062 if_refresh (ifp);
1063 if_data = ifp->info;
1064 if_data->shutdown = IF_ZEBRA_SHUTDOWN_ON;
1065
1066 return CMD_SUCCESS;
1067}
1068
1069DEFUN (no_shutdown_if,
1070 no_shutdown_if_cmd,
1071 "no shutdown",
1072 NO_STR
1073 "Shutdown the selected interface\n")
1074{
1075 int ret;
1076 struct interface *ifp;
1077 struct zebra_if *if_data;
1078
1079 ifp = (struct interface *) vty->index;
1080 ret = if_set_flags (ifp, IFF_UP | IFF_RUNNING);
1081 if (ret < 0)
1082 {
1083 vty_out (vty, "Can't up interface%s", VTY_NEWLINE);
1084 return CMD_WARNING;
1085 }
1086 if_refresh (ifp);
1087 if_data = ifp->info;
1088 if_data->shutdown = IF_ZEBRA_SHUTDOWN_OFF;
1089
1090 return CMD_SUCCESS;
1091}
1092
1093DEFUN (bandwidth_if,
1094 bandwidth_if_cmd,
1095 "bandwidth <1-10000000>",
1096 "Set bandwidth informational parameter\n"
1097 "Bandwidth in kilobits\n")
1098{
1099 struct interface *ifp;
1100 unsigned int bandwidth;
1101
1102 ifp = (struct interface *) vty->index;
1103 bandwidth = strtol(argv[0], NULL, 10);
1104
1105 /* bandwidth range is <1-10000000> */
1106 if (bandwidth < 1 || bandwidth > 10000000)
1107 {
1108 vty_out (vty, "Bandwidth is invalid%s", VTY_NEWLINE);
1109 return CMD_WARNING;
1110 }
1111
1112 ifp->bandwidth = bandwidth;
1113
1114 /* force protocols to recalculate routes due to cost change */
paul2e3b2e42002-12-13 21:03:13 +00001115 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00001116 zebra_interface_up_update (ifp);
1117
1118 return CMD_SUCCESS;
1119}
1120
1121DEFUN (no_bandwidth_if,
1122 no_bandwidth_if_cmd,
1123 "no bandwidth",
1124 NO_STR
1125 "Set bandwidth informational parameter\n")
1126{
1127 struct interface *ifp;
1128
1129 ifp = (struct interface *) vty->index;
1130
1131 ifp->bandwidth = 0;
1132
1133 /* force protocols to recalculate routes due to cost change */
paul2e3b2e42002-12-13 21:03:13 +00001134 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00001135 zebra_interface_up_update (ifp);
1136
1137 return CMD_SUCCESS;
1138}
1139
1140ALIAS (no_bandwidth_if,
1141 no_bandwidth_if_val_cmd,
1142 "no bandwidth <1-10000000>",
1143 NO_STR
1144 "Set bandwidth informational parameter\n"
1145 "Bandwidth in kilobits\n")
1146
paula1ac18c2005-06-28 17:17:12 +00001147static int
hasso39db97e2004-10-12 20:50:58 +00001148ip_address_install (struct vty *vty, struct interface *ifp,
1149 const char *addr_str, const char *peer_str,
1150 const char *label)
paul718e3742002-12-13 20:15:29 +00001151{
1152 struct prefix_ipv4 cp;
1153 struct connected *ifc;
1154 struct prefix_ipv4 *p;
paul718e3742002-12-13 20:15:29 +00001155 int ret;
1156
1157 ret = str2prefix_ipv4 (addr_str, &cp);
1158 if (ret <= 0)
1159 {
1160 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1161 return CMD_WARNING;
1162 }
1163
paulca162182005-09-12 16:58:52 +00001164 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001165 if (! ifc)
1166 {
1167 ifc = connected_new ();
1168 ifc->ifp = ifp;
1169
1170 /* Address. */
1171 p = prefix_ipv4_new ();
1172 *p = cp;
1173 ifc->address = (struct prefix *) p;
1174
1175 /* Broadcast. */
hasso3fb9cd62004-10-19 19:44:43 +00001176 if (p->prefixlen <= IPV4_MAX_PREFIXLEN-2)
paul718e3742002-12-13 20:15:29 +00001177 {
1178 p = prefix_ipv4_new ();
1179 *p = cp;
hasso3fb9cd62004-10-19 19:44:43 +00001180 p->prefix.s_addr = ipv4_broadcast_addr(p->prefix.s_addr,p->prefixlen);
paul718e3742002-12-13 20:15:29 +00001181 ifc->destination = (struct prefix *) p;
1182 }
1183
paul718e3742002-12-13 20:15:29 +00001184 /* Label. */
1185 if (label)
paul0752ef02005-11-03 12:35:21 +00001186 ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
paul718e3742002-12-13 20:15:29 +00001187
1188 /* Add to linked list. */
1189 listnode_add (ifp->connected, ifc);
1190 }
1191
1192 /* This address is configured from zebra. */
1193 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1194 SET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED);
1195
1196 /* In case of this route need to install kernel. */
1197 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1198 && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1199 {
1200 /* Some system need to up the interface to set IP address. */
1201 if (! if_is_up (ifp))
1202 {
1203 if_set_flags (ifp, IFF_UP | IFF_RUNNING);
1204 if_refresh (ifp);
1205 }
1206
1207 ret = if_set_prefix (ifp, ifc);
1208 if (ret < 0)
1209 {
1210 vty_out (vty, "%% Can't set interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001211 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001212 return CMD_WARNING;
1213 }
1214
hassoeef1fe12004-10-03 18:46:08 +00001215 /* Add to subnet chain list (while marking secondary attribute). */
1216 if_subnet_add (ifp, ifc);
1217
paul718e3742002-12-13 20:15:29 +00001218 /* IP address propery set. */
1219 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
1220
1221 /* Update interface address information to protocol daemon. */
1222 zebra_interface_address_add_update (ifp, ifc);
1223
1224 /* If interface is up register connected route. */
paul2e3b2e42002-12-13 21:03:13 +00001225 if (if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001226 connected_up_ipv4 (ifp, ifc);
1227 }
1228
1229 return CMD_SUCCESS;
1230}
1231
paula1ac18c2005-06-28 17:17:12 +00001232static int
hasso39db97e2004-10-12 20:50:58 +00001233ip_address_uninstall (struct vty *vty, struct interface *ifp,
1234 const char *addr_str, const char *peer_str,
1235 const char *label)
paul718e3742002-12-13 20:15:29 +00001236{
1237 struct prefix_ipv4 cp;
1238 struct connected *ifc;
1239 int ret;
1240
1241 /* Convert to prefix structure. */
1242 ret = str2prefix_ipv4 (addr_str, &cp);
1243 if (ret <= 0)
1244 {
1245 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1246 return CMD_WARNING;
1247 }
1248
1249 /* Check current interface address. */
paulca162182005-09-12 16:58:52 +00001250 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001251 if (! ifc)
1252 {
1253 vty_out (vty, "%% Can't find address%s", VTY_NEWLINE);
1254 return CMD_WARNING;
1255 }
1256
1257 /* This is not configured address. */
1258 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1259 return CMD_WARNING;
1260
Paul Jakma74ecdc92006-06-15 18:10:47 +00001261 UNSET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED);
1262
paul718e3742002-12-13 20:15:29 +00001263 /* This is not real address or interface is not active. */
1264 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1265 || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1266 {
1267 listnode_delete (ifp->connected, ifc);
1268 connected_free (ifc);
1269 return CMD_WARNING;
1270 }
1271
1272 /* This is real route. */
1273 ret = if_unset_prefix (ifp, ifc);
1274 if (ret < 0)
1275 {
1276 vty_out (vty, "%% Can't unset interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001277 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001278 return CMD_WARNING;
1279 }
1280
hassoeef1fe12004-10-03 18:46:08 +00001281#if 0
paul718e3742002-12-13 20:15:29 +00001282 /* Redistribute this information. */
1283 zebra_interface_address_delete_update (ifp, ifc);
1284
1285 /* Remove connected route. */
1286 connected_down_ipv4 (ifp, ifc);
1287
1288 /* Free address information. */
1289 listnode_delete (ifp->connected, ifc);
1290 connected_free (ifc);
hassoeef1fe12004-10-03 18:46:08 +00001291#endif
paul718e3742002-12-13 20:15:29 +00001292
1293 return CMD_SUCCESS;
1294}
1295
1296DEFUN (ip_address,
1297 ip_address_cmd,
1298 "ip address A.B.C.D/M",
1299 "Interface Internet Protocol config commands\n"
1300 "Set the IP address of an interface\n"
1301 "IP address (e.g. 10.0.0.1/8)\n")
1302{
hassoeef1fe12004-10-03 18:46:08 +00001303 return ip_address_install (vty, vty->index, argv[0], NULL, NULL);
paul718e3742002-12-13 20:15:29 +00001304}
1305
1306DEFUN (no_ip_address,
1307 no_ip_address_cmd,
1308 "no ip address A.B.C.D/M",
1309 NO_STR
1310 "Interface Internet Protocol config commands\n"
1311 "Set the IP address of an interface\n"
1312 "IP Address (e.g. 10.0.0.1/8)")
1313{
hassoeef1fe12004-10-03 18:46:08 +00001314 return ip_address_uninstall (vty, vty->index, argv[0], NULL, NULL);
paul718e3742002-12-13 20:15:29 +00001315}
1316
1317#ifdef HAVE_NETLINK
paul718e3742002-12-13 20:15:29 +00001318DEFUN (ip_address_label,
1319 ip_address_label_cmd,
1320 "ip address A.B.C.D/M label LINE",
1321 "Interface Internet Protocol config commands\n"
1322 "Set the IP address of an interface\n"
1323 "IP address (e.g. 10.0.0.1/8)\n"
1324 "Label of this address\n"
1325 "Label\n")
1326{
hassoeef1fe12004-10-03 18:46:08 +00001327 return ip_address_install (vty, vty->index, argv[0], NULL, argv[1]);
paul718e3742002-12-13 20:15:29 +00001328}
1329
1330DEFUN (no_ip_address_label,
1331 no_ip_address_label_cmd,
1332 "no ip address A.B.C.D/M label LINE",
1333 NO_STR
1334 "Interface Internet Protocol config commands\n"
1335 "Set the IP address of an interface\n"
1336 "IP address (e.g. 10.0.0.1/8)\n"
1337 "Label of this address\n"
1338 "Label\n")
1339{
hassoeef1fe12004-10-03 18:46:08 +00001340 return ip_address_uninstall (vty, vty->index, argv[0], NULL, argv[1]);
paul718e3742002-12-13 20:15:29 +00001341}
1342#endif /* HAVE_NETLINK */
1343
1344#ifdef HAVE_IPV6
paula1ac18c2005-06-28 17:17:12 +00001345static int
hasso39db97e2004-10-12 20:50:58 +00001346ipv6_address_install (struct vty *vty, struct interface *ifp,
1347 const char *addr_str, const char *peer_str,
1348 const char *label, int secondary)
paul718e3742002-12-13 20:15:29 +00001349{
1350 struct prefix_ipv6 cp;
1351 struct connected *ifc;
1352 struct prefix_ipv6 *p;
1353 int ret;
1354
1355 ret = str2prefix_ipv6 (addr_str, &cp);
1356 if (ret <= 0)
1357 {
1358 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1359 return CMD_WARNING;
1360 }
1361
paulca162182005-09-12 16:58:52 +00001362 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001363 if (! ifc)
1364 {
1365 ifc = connected_new ();
1366 ifc->ifp = ifp;
1367
1368 /* Address. */
1369 p = prefix_ipv6_new ();
1370 *p = cp;
1371 ifc->address = (struct prefix *) p;
1372
1373 /* Secondary. */
1374 if (secondary)
1375 SET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY);
1376
1377 /* Label. */
1378 if (label)
paul0752ef02005-11-03 12:35:21 +00001379 ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
paul718e3742002-12-13 20:15:29 +00001380
1381 /* Add to linked list. */
1382 listnode_add (ifp->connected, ifc);
1383 }
1384
1385 /* This address is configured from zebra. */
1386 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1387 SET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED);
1388
1389 /* In case of this route need to install kernel. */
1390 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1391 && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1392 {
1393 /* Some system need to up the interface to set IP address. */
1394 if (! if_is_up (ifp))
1395 {
1396 if_set_flags (ifp, IFF_UP | IFF_RUNNING);
1397 if_refresh (ifp);
1398 }
1399
1400 ret = if_prefix_add_ipv6 (ifp, ifc);
1401
1402 if (ret < 0)
1403 {
1404 vty_out (vty, "%% Can't set interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001405 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001406 return CMD_WARNING;
1407 }
1408
1409 /* IP address propery set. */
1410 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
1411
1412 /* Update interface address information to protocol daemon. */
1413 zebra_interface_address_add_update (ifp, ifc);
1414
1415 /* If interface is up register connected route. */
paul2e3b2e42002-12-13 21:03:13 +00001416 if (if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001417 connected_up_ipv6 (ifp, ifc);
1418 }
1419
1420 return CMD_SUCCESS;
1421}
1422
paula1ac18c2005-06-28 17:17:12 +00001423static int
hasso39db97e2004-10-12 20:50:58 +00001424ipv6_address_uninstall (struct vty *vty, struct interface *ifp,
1425 const char *addr_str, const char *peer_str,
1426 const char *label, int secondry)
paul718e3742002-12-13 20:15:29 +00001427{
1428 struct prefix_ipv6 cp;
1429 struct connected *ifc;
1430 int ret;
1431
1432 /* Convert to prefix structure. */
1433 ret = str2prefix_ipv6 (addr_str, &cp);
1434 if (ret <= 0)
1435 {
1436 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1437 return CMD_WARNING;
1438 }
1439
1440 /* Check current interface address. */
paulca162182005-09-12 16:58:52 +00001441 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001442 if (! ifc)
1443 {
1444 vty_out (vty, "%% Can't find address%s", VTY_NEWLINE);
1445 return CMD_WARNING;
1446 }
1447
1448 /* This is not configured address. */
1449 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1450 return CMD_WARNING;
1451
1452 /* This is not real address or interface is not active. */
1453 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1454 || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1455 {
1456 listnode_delete (ifp->connected, ifc);
1457 connected_free (ifc);
1458 return CMD_WARNING;
1459 }
1460
1461 /* This is real route. */
1462 ret = if_prefix_delete_ipv6 (ifp, ifc);
1463 if (ret < 0)
1464 {
1465 vty_out (vty, "%% Can't unset interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001466 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001467 return CMD_WARNING;
1468 }
1469
1470 /* Redistribute this information. */
1471 zebra_interface_address_delete_update (ifp, ifc);
1472
1473 /* Remove connected route. */
1474 connected_down_ipv6 (ifp, ifc);
1475
1476 /* Free address information. */
1477 listnode_delete (ifp->connected, ifc);
1478 connected_free (ifc);
1479
1480 return CMD_SUCCESS;
1481}
1482
1483DEFUN (ipv6_address,
1484 ipv6_address_cmd,
1485 "ipv6 address X:X::X:X/M",
hassoe23949c2004-03-11 15:54:02 +00001486 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001487 "Set the IP address of an interface\n"
1488 "IPv6 address (e.g. 3ffe:506::1/48)\n")
1489{
1490 return ipv6_address_install (vty, vty->index, argv[0], NULL, NULL, 0);
1491}
1492
1493DEFUN (no_ipv6_address,
1494 no_ipv6_address_cmd,
1495 "no ipv6 address X:X::X:X/M",
1496 NO_STR
hassoe23949c2004-03-11 15:54:02 +00001497 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001498 "Set the IP address of an interface\n"
1499 "IPv6 address (e.g. 3ffe:506::1/48)\n")
1500{
1501 return ipv6_address_uninstall (vty, vty->index, argv[0], NULL, NULL, 0);
1502}
1503#endif /* HAVE_IPV6 */
1504
paula1ac18c2005-06-28 17:17:12 +00001505static int
paul718e3742002-12-13 20:15:29 +00001506if_config_write (struct vty *vty)
1507{
hasso52dc7ee2004-09-23 19:18:23 +00001508 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001509 struct interface *ifp;
1510 char buf[BUFSIZ];
1511
paul1eb8ef22005-04-07 07:30:20 +00001512 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00001513 {
1514 struct zebra_if *if_data;
hasso52dc7ee2004-09-23 19:18:23 +00001515 struct listnode *addrnode;
paul718e3742002-12-13 20:15:29 +00001516 struct connected *ifc;
1517 struct prefix *p;
1518
paul718e3742002-12-13 20:15:29 +00001519 if_data = ifp->info;
1520
1521 vty_out (vty, "interface %s%s", ifp->name,
1522 VTY_NEWLINE);
1523
1524 if (ifp->desc)
1525 vty_out (vty, " description %s%s", ifp->desc,
1526 VTY_NEWLINE);
1527
1528 /* Assign bandwidth here to avoid unnecessary interface flap
1529 while processing config script */
1530 if (ifp->bandwidth != 0)
1531 vty_out(vty, " bandwidth %u%s", ifp->bandwidth, VTY_NEWLINE);
1532
paul2e3b2e42002-12-13 21:03:13 +00001533 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION))
1534 vty_out(vty, " link-detect%s", VTY_NEWLINE);
1535
paul1eb8ef22005-04-07 07:30:20 +00001536 for (ALL_LIST_ELEMENTS_RO (ifp->connected, addrnode, ifc))
paul718e3742002-12-13 20:15:29 +00001537 {
paul718e3742002-12-13 20:15:29 +00001538 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1539 {
1540 p = ifc->address;
1541 vty_out (vty, " ip%s address %s/%d",
1542 p->family == AF_INET ? "" : "v6",
1543 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
1544 p->prefixlen);
1545
paul718e3742002-12-13 20:15:29 +00001546 if (ifc->label)
1547 vty_out (vty, " label %s", ifc->label);
1548
1549 vty_out (vty, "%s", VTY_NEWLINE);
1550 }
1551 }
1552
1553 if (if_data)
1554 {
1555 if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)
1556 vty_out (vty, " shutdown%s", VTY_NEWLINE);
1557
1558 if (if_data->multicast != IF_ZEBRA_MULTICAST_UNSPEC)
1559 vty_out (vty, " %smulticast%s",
1560 if_data->multicast == IF_ZEBRA_MULTICAST_ON ? "" : "no ",
1561 VTY_NEWLINE);
1562 }
1563
1564#ifdef RTADV
1565 rtadv_config_write (vty, ifp);
1566#endif /* RTADV */
1567
hassoca776982004-06-12 14:33:05 +00001568#ifdef HAVE_IRDP
1569 irdp_config_write (vty, ifp);
1570#endif /* IRDP */
1571
paul718e3742002-12-13 20:15:29 +00001572 vty_out (vty, "!%s", VTY_NEWLINE);
1573 }
1574 return 0;
1575}
1576
1577/* Allocate and initialize interface vector. */
1578void
paula1ac18c2005-06-28 17:17:12 +00001579zebra_if_init (void)
paul718e3742002-12-13 20:15:29 +00001580{
1581 /* Initialize interface and new hook. */
1582 if_init ();
1583 if_add_hook (IF_NEW_HOOK, if_zebra_new_hook);
1584 if_add_hook (IF_DELETE_HOOK, if_zebra_delete_hook);
1585
1586 /* Install configuration write function. */
1587 install_node (&interface_node, if_config_write);
1588
1589 install_element (VIEW_NODE, &show_interface_cmd);
1590 install_element (ENABLE_NODE, &show_interface_cmd);
hassoed9bb6d2005-03-13 19:17:21 +00001591 install_element (ENABLE_NODE, &show_interface_desc_cmd);
paul718e3742002-12-13 20:15:29 +00001592 install_element (CONFIG_NODE, &zebra_interface_cmd);
paulbfc13532003-05-24 06:40:04 +00001593 install_element (CONFIG_NODE, &no_interface_cmd);
paul718e3742002-12-13 20:15:29 +00001594 install_default (INTERFACE_NODE);
1595 install_element (INTERFACE_NODE, &interface_desc_cmd);
1596 install_element (INTERFACE_NODE, &no_interface_desc_cmd);
1597 install_element (INTERFACE_NODE, &multicast_cmd);
1598 install_element (INTERFACE_NODE, &no_multicast_cmd);
paul2e3b2e42002-12-13 21:03:13 +00001599 install_element (INTERFACE_NODE, &linkdetect_cmd);
1600 install_element (INTERFACE_NODE, &no_linkdetect_cmd);
paul718e3742002-12-13 20:15:29 +00001601 install_element (INTERFACE_NODE, &shutdown_if_cmd);
1602 install_element (INTERFACE_NODE, &no_shutdown_if_cmd);
1603 install_element (INTERFACE_NODE, &bandwidth_if_cmd);
1604 install_element (INTERFACE_NODE, &no_bandwidth_if_cmd);
1605 install_element (INTERFACE_NODE, &no_bandwidth_if_val_cmd);
1606 install_element (INTERFACE_NODE, &ip_address_cmd);
1607 install_element (INTERFACE_NODE, &no_ip_address_cmd);
1608#ifdef HAVE_IPV6
1609 install_element (INTERFACE_NODE, &ipv6_address_cmd);
1610 install_element (INTERFACE_NODE, &no_ipv6_address_cmd);
1611#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +00001612#ifdef HAVE_NETLINK
paul718e3742002-12-13 20:15:29 +00001613 install_element (INTERFACE_NODE, &ip_address_label_cmd);
paul718e3742002-12-13 20:15:29 +00001614 install_element (INTERFACE_NODE, &no_ip_address_label_cmd);
paul718e3742002-12-13 20:15:29 +00001615#endif /* HAVE_NETLINK */
1616}