blob: ba4cf25f7cefd881b0e7b229c57a23b0375d6eba [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
Chris Caputob60668d2009-05-03 04:40:57 +000044#ifdef RTADV
45/* Order is intentional. Matches RFC4191. This array is also used for
46 command matching, so only modify with care. */
47const char *rtadv_pref_strs[] = { "medium", "high", "INVALID", "low", 0 };
48#endif /* RTADV */
paul718e3742002-12-13 20:15:29 +000049
50/* Called when new interface is added. */
paula1ac18c2005-06-28 17:17:12 +000051static int
paul718e3742002-12-13 20:15:29 +000052if_zebra_new_hook (struct interface *ifp)
53{
54 struct zebra_if *zebra_if;
55
Stephen Hemminger393deb92008-08-18 14:13:29 -070056 zebra_if = XCALLOC (MTYPE_TMP, sizeof (struct zebra_if));
paul718e3742002-12-13 20:15:29 +000057
58 zebra_if->multicast = IF_ZEBRA_MULTICAST_UNSPEC;
59 zebra_if->shutdown = IF_ZEBRA_SHUTDOWN_UNSPEC;
60
61#ifdef RTADV
62 {
63 /* Set default router advertise values. */
64 struct rtadvconf *rtadv;
65
66 rtadv = &zebra_if->rtadv;
67
68 rtadv->AdvSendAdvertisements = 0;
69 rtadv->MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
70 rtadv->MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
71 rtadv->AdvIntervalTimer = 0;
72 rtadv->AdvManagedFlag = 0;
73 rtadv->AdvOtherConfigFlag = 0;
vincent7cee1bb2005-03-25 13:08:53 +000074 rtadv->AdvHomeAgentFlag = 0;
paul718e3742002-12-13 20:15:29 +000075 rtadv->AdvLinkMTU = 0;
76 rtadv->AdvReachableTime = 0;
77 rtadv->AdvRetransTimer = 0;
78 rtadv->AdvCurHopLimit = 0;
79 rtadv->AdvDefaultLifetime = RTADV_ADV_DEFAULT_LIFETIME;
vincent7cee1bb2005-03-25 13:08:53 +000080 rtadv->HomeAgentPreference = 0;
81 rtadv->HomeAgentLifetime = RTADV_ADV_DEFAULT_LIFETIME;
82 rtadv->AdvIntervalOption = 0;
Chris Caputob60668d2009-05-03 04:40:57 +000083 rtadv->DefaultPreference = RTADV_PREF_MEDIUM;
paul718e3742002-12-13 20:15:29 +000084
85 rtadv->AdvPrefixList = list_new ();
86 }
87#endif /* RTADV */
88
hassoeef1fe12004-10-03 18:46:08 +000089 /* Initialize installed address chains tree. */
90 zebra_if->ipv4_subnets = route_table_init ();
91
paul718e3742002-12-13 20:15:29 +000092 ifp->info = zebra_if;
93 return 0;
94}
95
96/* Called when interface is deleted. */
paula1ac18c2005-06-28 17:17:12 +000097static int
paul718e3742002-12-13 20:15:29 +000098if_zebra_delete_hook (struct interface *ifp)
99{
hassoeef1fe12004-10-03 18:46:08 +0000100 struct zebra_if *zebra_if;
101
paul718e3742002-12-13 20:15:29 +0000102 if (ifp->info)
hassoeef1fe12004-10-03 18:46:08 +0000103 {
104 zebra_if = ifp->info;
105
106 /* Free installed address chains tree. */
107 if (zebra_if->ipv4_subnets)
108 route_table_finish (zebra_if->ipv4_subnets);
109
110 XFREE (MTYPE_TMP, zebra_if);
111 }
112
113 return 0;
114}
115
116/* Tie an interface address to its derived subnet list of addresses. */
117int
118if_subnet_add (struct interface *ifp, struct connected *ifc)
119{
120 struct route_node *rn;
121 struct zebra_if *zebra_if;
122 struct prefix cp;
123 struct list *addr_list;
124
125 assert (ifp && ifp->info && ifc);
126 zebra_if = ifp->info;
127
128 /* Get address derived subnet node and associated address list, while marking
129 address secondary attribute appropriately. */
130 cp = *ifc->address;
131 apply_mask (&cp);
132 rn = route_node_get (zebra_if->ipv4_subnets, &cp);
133
134 if ((addr_list = rn->info))
135 SET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY);
136 else
137 {
138 UNSET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY);
139 rn->info = addr_list = list_new ();
140 route_lock_node (rn);
141 }
142
143 /* Tie address at the tail of address list. */
144 listnode_add (addr_list, ifc);
145
146 /* Return list element count. */
147 return (addr_list->count);
148}
149
150/* Untie an interface address from its derived subnet list of addresses. */
151int
152if_subnet_delete (struct interface *ifp, struct connected *ifc)
153{
154 struct route_node *rn;
155 struct zebra_if *zebra_if;
156 struct list *addr_list;
157
158 assert (ifp && ifp->info && ifc);
159 zebra_if = ifp->info;
160
161 /* Get address derived subnet node. */
162 rn = route_node_lookup (zebra_if->ipv4_subnets, ifc->address);
163 if (! (rn && rn->info))
164 return -1;
165 route_unlock_node (rn);
166
167 /* Untie address from subnet's address list. */
168 addr_list = rn->info;
169 listnode_delete (addr_list, ifc);
170 route_unlock_node (rn);
171
172 /* Return list element count, if not empty. */
173 if (addr_list->count)
174 {
175 /* If deleted address is primary, mark subsequent one as such and distribute. */
176 if (! CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY))
177 {
paul1eb8ef22005-04-07 07:30:20 +0000178 ifc = listgetdata (listhead (addr_list));
hassoeef1fe12004-10-03 18:46:08 +0000179 zebra_interface_address_delete_update (ifp, ifc);
180 UNSET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY);
181 zebra_interface_address_add_update (ifp, ifc);
182 }
183
184 return addr_list->count;
185 }
186
187 /* Otherwise, free list and route node. */
188 list_free (addr_list);
189 rn->info = NULL;
190 route_unlock_node (rn);
191
paul718e3742002-12-13 20:15:29 +0000192 return 0;
193}
194
paul5c78b3d2006-01-25 04:31:40 +0000195/* if_flags_mangle: A place for hacks that require mangling
196 * or tweaking the interface flags.
197 *
198 * ******************** Solaris flags hacks **************************
199 *
200 * Solaris IFF_UP flag reflects only the primary interface as the
201 * routing socket only sends IFINFO for the primary interface. Hence
202 * ~IFF_UP does not per se imply all the logical interfaces are also
203 * down - which we only know of as addresses. Instead we must determine
204 * whether the interface really is up or not according to how many
205 * addresses are still attached. (Solaris always sends RTM_DELADDR if
206 * an interface, logical or not, goes ~IFF_UP).
207 *
208 * Ie, we mangle IFF_UP to *additionally* reflect whether or not there
209 * are addresses left in struct connected, not just the actual underlying
210 * IFF_UP flag.
211 *
212 * We must hence remember the real state of IFF_UP, which we do in
213 * struct zebra_if.primary_state.
214 *
215 * Setting IFF_UP within zebra to administratively shutdown the
216 * interface will affect only the primary interface/address on Solaris.
217 ************************End Solaris flags hacks ***********************
218 */
219static inline void
220if_flags_mangle (struct interface *ifp, uint64_t *newflags)
221{
222#ifdef SUNOS_5
223 struct zebra_if *zif = ifp->info;
224
225 zif->primary_state = *newflags & (IFF_UP & 0xff);
226
227 if (CHECK_FLAG (zif->primary_state, IFF_UP)
228 || listcount(ifp->connected) > 0)
229 SET_FLAG (*newflags, IFF_UP);
230 else
231 UNSET_FLAG (*newflags, IFF_UP);
232#endif /* SUNOS_5 */
233}
234
235/* Update the flags field of the ifp with the new flag set provided.
236 * Take whatever actions are required for any changes in flags we care
237 * about.
238 *
239 * newflags should be the raw value, as obtained from the OS.
240 */
241void
242if_flags_update (struct interface *ifp, uint64_t newflags)
243{
244 if_flags_mangle (ifp, &newflags);
245
246 if (if_is_operative (ifp))
247 {
248 /* operative -> inoperative? */
249 ifp->flags = newflags;
250 if (!if_is_operative (ifp))
251 if_down (ifp);
252 }
253 else
254 {
255 /* inoperative -> operative? */
256 ifp->flags = newflags;
257 if (if_is_operative (ifp))
258 if_up (ifp);
259 }
260}
261
paul718e3742002-12-13 20:15:29 +0000262/* Wake up configured address if it is not in current kernel
263 address. */
paula1ac18c2005-06-28 17:17:12 +0000264static void
paul718e3742002-12-13 20:15:29 +0000265if_addr_wakeup (struct interface *ifp)
266{
paul1eb8ef22005-04-07 07:30:20 +0000267 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000268 struct connected *ifc;
269 struct prefix *p;
270 int ret;
271
paul1eb8ef22005-04-07 07:30:20 +0000272 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, ifc))
paul718e3742002-12-13 20:15:29 +0000273 {
paul718e3742002-12-13 20:15:29 +0000274 p = ifc->address;
275
276 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)
277 && ! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
278 {
279 /* Address check. */
280 if (p->family == AF_INET)
281 {
282 if (! if_is_up (ifp))
283 {
paul0752ef02005-11-03 12:35:21 +0000284 /* XXX: WTF is it trying to set flags here?
285 * caller has just gotten a new interface, has been
286 * handed the flags already. This code has no business
287 * trying to override administrative status of the interface.
288 * The only call path to here which doesn't originate from
289 * kernel event is irdp - what on earth is it trying to do?
290 *
291 * further RUNNING is not a settable flag on any system
292 * I (paulj) am aware of.
293 */
paul718e3742002-12-13 20:15:29 +0000294 if_set_flags (ifp, IFF_UP | IFF_RUNNING);
295 if_refresh (ifp);
296 }
297
298 ret = if_set_prefix (ifp, ifc);
299 if (ret < 0)
300 {
301 zlog_warn ("Can't set interface's address: %s",
ajs6099b3b2004-11-20 02:06:59 +0000302 safe_strerror(errno));
paul718e3742002-12-13 20:15:29 +0000303 continue;
304 }
hassoeef1fe12004-10-03 18:46:08 +0000305
306 /* Add to subnet chain list. */
307 if_subnet_add (ifp, ifc);
308
paul718e3742002-12-13 20:15:29 +0000309 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
310
311 zebra_interface_address_add_update (ifp, ifc);
312
paul2e3b2e42002-12-13 21:03:13 +0000313 if (if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000314 connected_up_ipv4 (ifp, ifc);
315 }
316#ifdef HAVE_IPV6
317 if (p->family == AF_INET6)
318 {
319 if (! if_is_up (ifp))
320 {
paul0752ef02005-11-03 12:35:21 +0000321 /* XXX: See long comment above */
paul718e3742002-12-13 20:15:29 +0000322 if_set_flags (ifp, IFF_UP | IFF_RUNNING);
323 if_refresh (ifp);
324 }
325
326 ret = if_prefix_add_ipv6 (ifp, ifc);
327 if (ret < 0)
328 {
329 zlog_warn ("Can't set interface's address: %s",
ajs6099b3b2004-11-20 02:06:59 +0000330 safe_strerror(errno));
paul718e3742002-12-13 20:15:29 +0000331 continue;
332 }
333 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
334
335 zebra_interface_address_add_update (ifp, ifc);
336
paul2e3b2e42002-12-13 21:03:13 +0000337 if (if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000338 connected_up_ipv6 (ifp, ifc);
339 }
340#endif /* HAVE_IPV6 */
341 }
342 }
343}
344
345/* Handle interface addition */
346void
347if_add_update (struct interface *ifp)
348{
paul48b33aa2002-12-13 20:52:52 +0000349 struct zebra_if *if_data;
350
351 if_data = ifp->info;
352 if (if_data->multicast == IF_ZEBRA_MULTICAST_ON)
353 if_set_flags (ifp, IFF_MULTICAST);
354 else if (if_data->multicast == IF_ZEBRA_MULTICAST_OFF)
355 if_unset_flags (ifp, IFF_MULTICAST);
356
paul718e3742002-12-13 20:15:29 +0000357 zebra_interface_add_update (ifp);
358
359 if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
360 {
361 SET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE);
362
363 if_addr_wakeup (ifp);
364
365 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +0000366 zlog_debug ("interface %s index %d becomes active.",
367 ifp->name, ifp->ifindex);
paul718e3742002-12-13 20:15:29 +0000368 }
369 else
370 {
371 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +0000372 zlog_debug ("interface %s index %d is added.", ifp->name, ifp->ifindex);
paul718e3742002-12-13 20:15:29 +0000373 }
374}
375
paul6eb88272005-07-29 14:36:00 +0000376/* Handle an interface delete event */
paul718e3742002-12-13 20:15:29 +0000377void
378if_delete_update (struct interface *ifp)
379{
paul718e3742002-12-13 20:15:29 +0000380 struct connected *ifc;
381 struct prefix *p;
hassoeef1fe12004-10-03 18:46:08 +0000382 struct route_node *rn;
383 struct zebra_if *zebra_if;
hassoeef1fe12004-10-03 18:46:08 +0000384
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 {
Paul Jakmad9a18f12007-04-10 19:30:20 +0000404 struct listnode *node;
405 struct listnode *last = NULL;
406
hassoeef1fe12004-10-03 18:46:08 +0000407 while ((node = (last ? last->next : listhead (ifp->connected))))
paul718e3742002-12-13 20:15:29 +0000408 {
paul1eb8ef22005-04-07 07:30:20 +0000409 ifc = listgetdata (node);
paul718e3742002-12-13 20:15:29 +0000410 p = ifc->address;
hassoeef1fe12004-10-03 18:46:08 +0000411
Paul Jakmabeb56332006-05-11 13:28:05 +0000412 if (p->family == AF_INET
413 && (rn = route_node_lookup (zebra_if->ipv4_subnets, p)))
hassoeef1fe12004-10-03 18:46:08 +0000414 {
Paul Jakmad9a18f12007-04-10 19:30:20 +0000415 struct listnode *anode;
416 struct listnode *next;
417 struct listnode *first;
418 struct list *addr_list;
419
hassoeef1fe12004-10-03 18:46:08 +0000420 route_unlock_node (rn);
421 addr_list = (struct list *) rn->info;
422
423 /* Remove addresses, secondaries first. */
424 first = listhead (addr_list);
Paul Jakmad9a18f12007-04-10 19:30:20 +0000425 for (anode = first->next; anode || first; anode = next)
hassoeef1fe12004-10-03 18:46:08 +0000426 {
Paul Jakmad9a18f12007-04-10 19:30:20 +0000427 if (!anode)
hassoeef1fe12004-10-03 18:46:08 +0000428 {
Paul Jakmad9a18f12007-04-10 19:30:20 +0000429 anode = first;
hassoeef1fe12004-10-03 18:46:08 +0000430 first = NULL;
431 }
Paul Jakmad9a18f12007-04-10 19:30:20 +0000432 next = anode->next;
hassoeef1fe12004-10-03 18:46:08 +0000433
Paul Jakmad9a18f12007-04-10 19:30:20 +0000434 ifc = listgetdata (anode);
hassoeef1fe12004-10-03 18:46:08 +0000435 p = ifc->address;
436
437 connected_down_ipv4 (ifp, ifc);
438
439 zebra_interface_address_delete_update (ifp, ifc);
440
441 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
442
443 /* Remove from subnet chain. */
Paul Jakmad9a18f12007-04-10 19:30:20 +0000444 list_delete_node (addr_list, anode);
hassoeef1fe12004-10-03 18:46:08 +0000445 route_unlock_node (rn);
446
447 /* Remove from interface address list (unconditionally). */
Paul Jakmad9a18f12007-04-10 19:30:20 +0000448 if (!CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
449 {
450 listnode_delete (ifp->connected, ifc);
451 connected_free (ifc);
452 }
453 else
454 last = node;
hassoeef1fe12004-10-03 18:46:08 +0000455 }
456
457 /* Free chain list and respective route node. */
458 list_delete (addr_list);
459 rn->info = NULL;
460 route_unlock_node (rn);
461 }
paul718e3742002-12-13 20:15:29 +0000462#ifdef HAVE_IPV6
463 else if (p->family == AF_INET6)
hassoeef1fe12004-10-03 18:46:08 +0000464 {
465 connected_down_ipv6 (ifp, ifc);
paul718e3742002-12-13 20:15:29 +0000466
hassoeef1fe12004-10-03 18:46:08 +0000467 zebra_interface_address_delete_update (ifp, ifc);
paul718e3742002-12-13 20:15:29 +0000468
hassoeef1fe12004-10-03 18:46:08 +0000469 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
470
471 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
472 last = node;
473 else
474 {
475 listnode_delete (ifp->connected, ifc);
476 connected_free (ifc);
477 }
paul718e3742002-12-13 20:15:29 +0000478 }
hassoeef1fe12004-10-03 18:46:08 +0000479#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +0000480 }
481 }
482 zebra_interface_delete_update (ifp);
ajsd2fc8892005-04-02 18:38:43 +0000483
484 /* Update ifindex after distributing the delete message. This is in
485 case any client needs to have the old value of ifindex available
486 while processing the deletion. Each client daemon is responsible
487 for setting ifindex to IFINDEX_INTERNAL after processing the
488 interface deletion message. */
489 ifp->ifindex = IFINDEX_INTERNAL;
paul718e3742002-12-13 20:15:29 +0000490}
491
492/* Interface is up. */
493void
494if_up (struct interface *ifp)
495{
hasso52dc7ee2004-09-23 19:18:23 +0000496 struct listnode *node;
497 struct listnode *next;
paul718e3742002-12-13 20:15:29 +0000498 struct connected *ifc;
499 struct prefix *p;
500
501 /* Notify the protocol daemons. */
502 zebra_interface_up_update (ifp);
503
504 /* Install connected routes to the kernel. */
505 if (ifp->connected)
506 {
paul1eb8ef22005-04-07 07:30:20 +0000507 for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc))
paul718e3742002-12-13 20:15:29 +0000508 {
paul718e3742002-12-13 20:15:29 +0000509 p = ifc->address;
510
511 if (p->family == AF_INET)
512 connected_up_ipv4 (ifp, ifc);
513#ifdef HAVE_IPV6
514 else if (p->family == AF_INET6)
515 connected_up_ipv6 (ifp, ifc);
516#endif /* HAVE_IPV6 */
517 }
518 }
519
520 /* Examine all static routes. */
521 rib_update ();
522}
523
524/* Interface goes down. We have to manage different behavior of based
525 OS. */
526void
527if_down (struct interface *ifp)
528{
hasso52dc7ee2004-09-23 19:18:23 +0000529 struct listnode *node;
530 struct listnode *next;
paul718e3742002-12-13 20:15:29 +0000531 struct connected *ifc;
532 struct prefix *p;
533
534 /* Notify to the protocol daemons. */
535 zebra_interface_down_update (ifp);
536
537 /* Delete connected routes from the kernel. */
538 if (ifp->connected)
539 {
paul1eb8ef22005-04-07 07:30:20 +0000540 for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc))
paul718e3742002-12-13 20:15:29 +0000541 {
paul718e3742002-12-13 20:15:29 +0000542 p = ifc->address;
543
544 if (p->family == AF_INET)
545 connected_down_ipv4 (ifp, ifc);
546#ifdef HAVE_IPV6
547 else if (p->family == AF_INET6)
548 connected_down_ipv6 (ifp, ifc);
549#endif /* HAVE_IPV6 */
550 }
551 }
552
553 /* Examine all static routes which direct to the interface. */
554 rib_update ();
555}
556
557void
558if_refresh (struct interface *ifp)
559{
paul5c78b3d2006-01-25 04:31:40 +0000560 if_get_flags (ifp);
paul718e3742002-12-13 20:15:29 +0000561}
562
paul718e3742002-12-13 20:15:29 +0000563/* Output prefix string to vty. */
paula1ac18c2005-06-28 17:17:12 +0000564static int
paul718e3742002-12-13 20:15:29 +0000565prefix_vty_out (struct vty *vty, struct prefix *p)
566{
567 char str[INET6_ADDRSTRLEN];
568
569 inet_ntop (p->family, &p->u.prefix, str, sizeof (str));
570 vty_out (vty, "%s", str);
571 return strlen (str);
572}
573
574/* Dump if address information to vty. */
paula1ac18c2005-06-28 17:17:12 +0000575static void
paul718e3742002-12-13 20:15:29 +0000576connected_dump_vty (struct vty *vty, struct connected *connected)
577{
578 struct prefix *p;
paul718e3742002-12-13 20:15:29 +0000579
580 /* Print interface address. */
581 p = connected->address;
582 vty_out (vty, " %s ", prefix_family_str (p));
583 prefix_vty_out (vty, p);
584 vty_out (vty, "/%d", p->prefixlen);
585
586 /* If there is destination address, print it. */
Andrew J. Schorre4529632006-12-12 19:18:21 +0000587 if (connected->destination)
paul718e3742002-12-13 20:15:29 +0000588 {
Andrew J. Schorre4529632006-12-12 19:18:21 +0000589 vty_out (vty, (CONNECTED_PEER(connected) ? " peer " : " broadcast "));
590 prefix_vty_out (vty, connected->destination);
paul718e3742002-12-13 20:15:29 +0000591 }
592
593 if (CHECK_FLAG (connected->flags, ZEBRA_IFA_SECONDARY))
594 vty_out (vty, " secondary");
595
596 if (connected->label)
597 vty_out (vty, " %s", connected->label);
598
599 vty_out (vty, "%s", VTY_NEWLINE);
600}
601
602#ifdef RTADV
603/* Dump interface ND information to vty. */
paula1ac18c2005-06-28 17:17:12 +0000604static void
paul718e3742002-12-13 20:15:29 +0000605nd_dump_vty (struct vty *vty, struct interface *ifp)
606{
607 struct zebra_if *zif;
608 struct rtadvconf *rtadv;
vincent7cee1bb2005-03-25 13:08:53 +0000609 int interval;
paul718e3742002-12-13 20:15:29 +0000610
611 zif = (struct zebra_if *) ifp->info;
612 rtadv = &zif->rtadv;
613
614 if (rtadv->AdvSendAdvertisements)
615 {
616 vty_out (vty, " ND advertised reachable time is %d milliseconds%s",
617 rtadv->AdvReachableTime, VTY_NEWLINE);
618 vty_out (vty, " ND advertised retransmit interval is %d milliseconds%s",
619 rtadv->AdvRetransTimer, VTY_NEWLINE);
vincent7cee1bb2005-03-25 13:08:53 +0000620 interval = rtadv->MaxRtrAdvInterval;
621 if (interval % 1000)
622 vty_out (vty, " ND router advertisements are sent every "
623 "%d milliseconds%s", interval,
624 VTY_NEWLINE);
625 else
626 vty_out (vty, " ND router advertisements are sent every "
627 "%d seconds%s", interval / 1000,
628 VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000629 vty_out (vty, " ND router advertisements live for %d seconds%s",
630 rtadv->AdvDefaultLifetime, VTY_NEWLINE);
Chris Caputob60668d2009-05-03 04:40:57 +0000631 vty_out (vty, " ND router advertisement default router preference is "
632 "%s%s", rtadv_pref_strs[rtadv->DefaultPreference],
633 VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000634 if (rtadv->AdvManagedFlag)
635 vty_out (vty, " Hosts use DHCP to obtain routable addresses.%s",
636 VTY_NEWLINE);
637 else
638 vty_out (vty, " Hosts use stateless autoconfig for addresses.%s",
639 VTY_NEWLINE);
vincent7cee1bb2005-03-25 13:08:53 +0000640 if (rtadv->AdvHomeAgentFlag)
641 vty_out (vty, " ND router advertisements with "
642 "Home Agent flag bit set.%s",
643 VTY_NEWLINE);
644 if (rtadv->AdvIntervalOption)
645 vty_out (vty, " ND router advertisements with Adv. Interval option.%s",
646 VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000647 }
648}
649#endif /* RTADV */
650
651/* Interface's information print out to vty interface. */
paula1ac18c2005-06-28 17:17:12 +0000652static void
paul718e3742002-12-13 20:15:29 +0000653if_dump_vty (struct vty *vty, struct interface *ifp)
654{
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000655#ifdef HAVE_STRUCT_SOCKADDR_DL
paul718e3742002-12-13 20:15:29 +0000656 struct sockaddr_dl *sdl;
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000657#endif /* HAVE_STRUCT_SOCKADDR_DL */
paul718e3742002-12-13 20:15:29 +0000658 struct connected *connected;
hasso52dc7ee2004-09-23 19:18:23 +0000659 struct listnode *node;
hassoeef1fe12004-10-03 18:46:08 +0000660 struct route_node *rn;
661 struct zebra_if *zebra_if;
662
663 zebra_if = ifp->info;
paul718e3742002-12-13 20:15:29 +0000664
paul2e3b2e42002-12-13 21:03:13 +0000665 vty_out (vty, "Interface %s is ", ifp->name);
666 if (if_is_up(ifp)) {
667 vty_out (vty, "up, line protocol ");
668
669 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) {
670 if (if_is_running(ifp))
671 vty_out (vty, "is up%s", VTY_NEWLINE);
672 else
673 vty_out (vty, "is down%s", VTY_NEWLINE);
674 } else {
675 vty_out (vty, "detection is disabled%s", VTY_NEWLINE);
676 }
677 } else {
678 vty_out (vty, "down%s", VTY_NEWLINE);
679 }
680
paul718e3742002-12-13 20:15:29 +0000681 if (ifp->desc)
682 vty_out (vty, " Description: %s%s", ifp->desc,
683 VTY_NEWLINE);
ajsd2fc8892005-04-02 18:38:43 +0000684 if (ifp->ifindex == IFINDEX_INTERNAL)
paul718e3742002-12-13 20:15:29 +0000685 {
ajsd2fc8892005-04-02 18:38:43 +0000686 vty_out(vty, " pseudo interface%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000687 return;
688 }
689 else if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
690 {
691 vty_out(vty, " index %d inactive interface%s",
692 ifp->ifindex,
693 VTY_NEWLINE);
694 return;
695 }
696
697 vty_out (vty, " index %d metric %d mtu %d ",
698 ifp->ifindex, ifp->metric, ifp->mtu);
paul44145db2004-05-09 11:00:23 +0000699#ifdef HAVE_IPV6
700 if (ifp->mtu6 != ifp->mtu)
701 vty_out (vty, "mtu6 %d ", ifp->mtu6);
702#endif
Paul Jakma630c97c2006-06-15 12:48:17 +0000703 vty_out (vty, "%s flags: %s%s", VTY_NEWLINE,
704 if_flag_dump (ifp->flags), VTY_NEWLINE);
paul3a570c82006-02-02 17:27:13 +0000705
paul718e3742002-12-13 20:15:29 +0000706 /* Hardware address. */
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000707#ifdef HAVE_STRUCT_SOCKADDR_DL
paul718e3742002-12-13 20:15:29 +0000708 sdl = &ifp->sdl;
709 if (sdl != NULL && sdl->sdl_alen != 0)
710 {
711 int i;
712 u_char *ptr;
713
714 vty_out (vty, " HWaddr: ");
paul5b73a672004-07-23 15:26:14 +0000715 for (i = 0, ptr = (u_char *)LLADDR (sdl); i < sdl->sdl_alen; i++, ptr++)
716 vty_out (vty, "%s%02x", i == 0 ? "" : ":", *ptr);
paul718e3742002-12-13 20:15:29 +0000717 vty_out (vty, "%s", VTY_NEWLINE);
718 }
719#else
720 if (ifp->hw_addr_len != 0)
721 {
722 int i;
723
724 vty_out (vty, " HWaddr: ");
725 for (i = 0; i < ifp->hw_addr_len; i++)
726 vty_out (vty, "%s%02x", i == 0 ? "" : ":", ifp->hw_addr[i]);
727 vty_out (vty, "%s", VTY_NEWLINE);
728 }
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000729#endif /* HAVE_STRUCT_SOCKADDR_DL */
paul718e3742002-12-13 20:15:29 +0000730
731 /* Bandwidth in kbps */
732 if (ifp->bandwidth != 0)
733 {
734 vty_out(vty, " bandwidth %u kbps", ifp->bandwidth);
735 vty_out(vty, "%s", VTY_NEWLINE);
736 }
737
hassoeef1fe12004-10-03 18:46:08 +0000738 for (rn = route_top (zebra_if->ipv4_subnets); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000739 {
hassoeef1fe12004-10-03 18:46:08 +0000740 if (! rn->info)
741 continue;
742
paul1eb8ef22005-04-07 07:30:20 +0000743 for (ALL_LIST_ELEMENTS_RO ((struct list *)rn->info, node, connected))
744 connected_dump_vty (vty, connected);
paul718e3742002-12-13 20:15:29 +0000745 }
746
paul1eb8ef22005-04-07 07:30:20 +0000747 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
hasso39db97e2004-10-12 20:50:58 +0000748 {
hasso39db97e2004-10-12 20:50:58 +0000749 if (CHECK_FLAG (connected->conf, ZEBRA_IFC_REAL) &&
750 (connected->address->family == AF_INET6))
751 connected_dump_vty (vty, connected);
752 }
753
paul718e3742002-12-13 20:15:29 +0000754#ifdef RTADV
755 nd_dump_vty (vty, ifp);
756#endif /* RTADV */
757
758#ifdef HAVE_PROC_NET_DEV
759 /* Statistics print out using proc file system. */
hasso6f2c27a2005-01-18 13:44:35 +0000760 vty_out (vty, " %lu input packets (%lu multicast), %lu bytes, "
761 "%lu dropped%s",
762 ifp->stats.rx_packets, ifp->stats.rx_multicast,
763 ifp->stats.rx_bytes, ifp->stats.rx_dropped, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000764
hasso6f2c27a2005-01-18 13:44:35 +0000765 vty_out (vty, " %lu input errors, %lu length, %lu overrun,"
hasso3452d472005-03-06 13:42:05 +0000766 " %lu CRC, %lu frame%s",
paul718e3742002-12-13 20:15:29 +0000767 ifp->stats.rx_errors, ifp->stats.rx_length_errors,
768 ifp->stats.rx_over_errors, ifp->stats.rx_crc_errors,
hasso6f2c27a2005-01-18 13:44:35 +0000769 ifp->stats.rx_frame_errors, VTY_NEWLINE);
770
771 vty_out (vty, " %lu fifo, %lu missed%s", ifp->stats.rx_fifo_errors,
paul718e3742002-12-13 20:15:29 +0000772 ifp->stats.rx_missed_errors, VTY_NEWLINE);
773
hasso6f2c27a2005-01-18 13:44:35 +0000774 vty_out (vty, " %lu output packets, %lu bytes, %lu dropped%s",
paul718e3742002-12-13 20:15:29 +0000775 ifp->stats.tx_packets, ifp->stats.tx_bytes,
776 ifp->stats.tx_dropped, VTY_NEWLINE);
777
hasso6f2c27a2005-01-18 13:44:35 +0000778 vty_out (vty, " %lu output errors, %lu aborted, %lu carrier,"
779 " %lu fifo, %lu heartbeat%s",
paul718e3742002-12-13 20:15:29 +0000780 ifp->stats.tx_errors, ifp->stats.tx_aborted_errors,
781 ifp->stats.tx_carrier_errors, ifp->stats.tx_fifo_errors,
hasso6f2c27a2005-01-18 13:44:35 +0000782 ifp->stats.tx_heartbeat_errors, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000783
hasso6f2c27a2005-01-18 13:44:35 +0000784 vty_out (vty, " %lu window, %lu collisions%s",
785 ifp->stats.tx_window_errors, ifp->stats.collisions, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000786#endif /* HAVE_PROC_NET_DEV */
787
788#ifdef HAVE_NET_RT_IFLIST
789#if defined (__bsdi__) || defined (__NetBSD__)
790 /* Statistics print out using sysctl (). */
791 vty_out (vty, " input packets %qu, bytes %qu, dropped %qu,"
792 " multicast packets %qu%s",
793 ifp->stats.ifi_ipackets, ifp->stats.ifi_ibytes,
794 ifp->stats.ifi_iqdrops, ifp->stats.ifi_imcasts,
795 VTY_NEWLINE);
796
797 vty_out (vty, " input errors %qu%s",
798 ifp->stats.ifi_ierrors, VTY_NEWLINE);
799
800 vty_out (vty, " output packets %qu, bytes %qu, multicast packets %qu%s",
801 ifp->stats.ifi_opackets, ifp->stats.ifi_obytes,
802 ifp->stats.ifi_omcasts, VTY_NEWLINE);
803
804 vty_out (vty, " output errors %qu%s",
805 ifp->stats.ifi_oerrors, VTY_NEWLINE);
806
807 vty_out (vty, " collisions %qu%s",
808 ifp->stats.ifi_collisions, VTY_NEWLINE);
809#else
810 /* Statistics print out using sysctl (). */
811 vty_out (vty, " input packets %lu, bytes %lu, dropped %lu,"
812 " multicast packets %lu%s",
813 ifp->stats.ifi_ipackets, ifp->stats.ifi_ibytes,
814 ifp->stats.ifi_iqdrops, ifp->stats.ifi_imcasts,
815 VTY_NEWLINE);
816
817 vty_out (vty, " input errors %lu%s",
818 ifp->stats.ifi_ierrors, VTY_NEWLINE);
819
820 vty_out (vty, " output packets %lu, bytes %lu, multicast packets %lu%s",
821 ifp->stats.ifi_opackets, ifp->stats.ifi_obytes,
822 ifp->stats.ifi_omcasts, VTY_NEWLINE);
823
824 vty_out (vty, " output errors %lu%s",
825 ifp->stats.ifi_oerrors, VTY_NEWLINE);
826
827 vty_out (vty, " collisions %lu%s",
828 ifp->stats.ifi_collisions, VTY_NEWLINE);
829#endif /* __bsdi__ || __NetBSD__ */
830#endif /* HAVE_NET_RT_IFLIST */
831}
832
paul718e3742002-12-13 20:15:29 +0000833/* Wrapper hook point for zebra daemon so that ifindex can be set
834 * DEFUN macro not used as extract.pl HAS to ignore this
835 * See also interface_cmd in lib/if.c
836 */
837DEFUN_NOSH (zebra_interface,
838 zebra_interface_cmd,
839 "interface IFNAME",
840 "Select an interface to configure\n"
841 "Interface's name\n")
842{
843 int ret;
844 struct interface * ifp;
845
846 /* Call lib interface() */
ajsd2fc8892005-04-02 18:38:43 +0000847 if ((ret = interface_cmd.func (self, vty, argc, argv)) != CMD_SUCCESS)
848 return ret;
paul718e3742002-12-13 20:15:29 +0000849
850 ifp = vty->index;
851
ajsd2fc8892005-04-02 18:38:43 +0000852 if (ifp->ifindex == IFINDEX_INTERNAL)
853 /* Is this really necessary? Shouldn't status be initialized to 0
854 in that case? */
855 UNSET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE);
paul718e3742002-12-13 20:15:29 +0000856
857 return ret;
858}
859
paul718e3742002-12-13 20:15:29 +0000860struct cmd_node interface_node =
861{
862 INTERFACE_NODE,
863 "%s(config-if)# ",
864 1
865};
866
867/* Show all or specified interface to vty. */
868DEFUN (show_interface, show_interface_cmd,
869 "show interface [IFNAME]",
870 SHOW_STR
871 "Interface status and configuration\n"
872 "Inteface name\n")
873{
hasso52dc7ee2004-09-23 19:18:23 +0000874 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000875 struct interface *ifp;
876
877#ifdef HAVE_PROC_NET_DEV
878 /* If system has interface statistics via proc file system, update
879 statistics. */
880 ifstat_update_proc ();
881#endif /* HAVE_PROC_NET_DEV */
882#ifdef HAVE_NET_RT_IFLIST
883 ifstat_update_sysctl ();
884#endif /* HAVE_NET_RT_IFLIST */
885
886 /* Specified interface print. */
887 if (argc != 0)
888 {
889 ifp = if_lookup_by_name (argv[0]);
890 if (ifp == NULL)
891 {
892 vty_out (vty, "%% Can't find interface %s%s", argv[0],
893 VTY_NEWLINE);
894 return CMD_WARNING;
895 }
896 if_dump_vty (vty, ifp);
897 return CMD_SUCCESS;
898 }
899
900 /* All interface print. */
paul1eb8ef22005-04-07 07:30:20 +0000901 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
902 if_dump_vty (vty, ifp);
paul718e3742002-12-13 20:15:29 +0000903
904 return CMD_SUCCESS;
905}
906
hassoed9bb6d2005-03-13 19:17:21 +0000907DEFUN (show_interface_desc,
908 show_interface_desc_cmd,
909 "show interface description",
910 SHOW_STR
911 "Interface status and configuration\n"
912 "Interface description\n")
913{
914 struct listnode *node;
915 struct interface *ifp;
916
917 vty_out (vty, "Interface Status Protocol Description%s", VTY_NEWLINE);
paul1eb8ef22005-04-07 07:30:20 +0000918 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
hassoed9bb6d2005-03-13 19:17:21 +0000919 {
920 int len;
hassoed9bb6d2005-03-13 19:17:21 +0000921
922 len = vty_out (vty, "%s", ifp->name);
923 vty_out (vty, "%*s", (16 - len), " ");
924
925 if (if_is_up(ifp))
926 {
927 vty_out (vty, "up ");
928 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION))
929 {
930 if (if_is_running(ifp))
931 vty_out (vty, "up ");
932 else
933 vty_out (vty, "down ");
934 }
935 else
936 {
937 vty_out (vty, "unknown ");
938 }
939 }
940 else
941 {
942 vty_out (vty, "down down ");
943 }
944
945 if (ifp->desc)
946 vty_out (vty, "%s", ifp->desc);
947 vty_out (vty, "%s", VTY_NEWLINE);
948 }
949 return CMD_SUCCESS;
950}
951
paul718e3742002-12-13 20:15:29 +0000952DEFUN (multicast,
953 multicast_cmd,
954 "multicast",
955 "Set multicast flag to interface\n")
956{
957 int ret;
958 struct interface *ifp;
959 struct zebra_if *if_data;
960
961 ifp = (struct interface *) vty->index;
paul48b33aa2002-12-13 20:52:52 +0000962 if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
paul718e3742002-12-13 20:15:29 +0000963 {
paul48b33aa2002-12-13 20:52:52 +0000964 ret = if_set_flags (ifp, IFF_MULTICAST);
965 if (ret < 0)
966 {
967 vty_out (vty, "Can't set multicast flag%s", VTY_NEWLINE);
968 return CMD_WARNING;
969 }
970 if_refresh (ifp);
paul718e3742002-12-13 20:15:29 +0000971 }
paul718e3742002-12-13 20:15:29 +0000972 if_data = ifp->info;
973 if_data->multicast = IF_ZEBRA_MULTICAST_ON;
paul48b33aa2002-12-13 20:52:52 +0000974
paul718e3742002-12-13 20:15:29 +0000975 return CMD_SUCCESS;
976}
977
978DEFUN (no_multicast,
979 no_multicast_cmd,
980 "no multicast",
981 NO_STR
982 "Unset multicast flag to interface\n")
983{
984 int ret;
985 struct interface *ifp;
986 struct zebra_if *if_data;
987
988 ifp = (struct interface *) vty->index;
paul48b33aa2002-12-13 20:52:52 +0000989 if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
paul718e3742002-12-13 20:15:29 +0000990 {
paul48b33aa2002-12-13 20:52:52 +0000991 ret = if_unset_flags (ifp, IFF_MULTICAST);
992 if (ret < 0)
993 {
994 vty_out (vty, "Can't unset multicast flag%s", VTY_NEWLINE);
995 return CMD_WARNING;
996 }
997 if_refresh (ifp);
paul718e3742002-12-13 20:15:29 +0000998 }
paul718e3742002-12-13 20:15:29 +0000999 if_data = ifp->info;
1000 if_data->multicast = IF_ZEBRA_MULTICAST_OFF;
1001
1002 return CMD_SUCCESS;
1003}
1004
paul2e3b2e42002-12-13 21:03:13 +00001005DEFUN (linkdetect,
1006 linkdetect_cmd,
1007 "link-detect",
1008 "Enable link detection on interface\n")
1009{
paul2e3b2e42002-12-13 21:03:13 +00001010 struct interface *ifp;
1011 int if_was_operative;
1012
1013 ifp = (struct interface *) vty->index;
1014 if_was_operative = if_is_operative(ifp);
1015 SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
1016
1017 /* When linkdetection is enabled, if might come down */
1018 if (!if_is_operative(ifp) && if_was_operative) if_down(ifp);
1019
1020 /* FIXME: Will defer status change forwarding if interface
1021 does not come down! */
1022
1023 return CMD_SUCCESS;
1024}
1025
1026
1027DEFUN (no_linkdetect,
1028 no_linkdetect_cmd,
1029 "no link-detect",
1030 NO_STR
1031 "Disable link detection on interface\n")
1032{
paul2e3b2e42002-12-13 21:03:13 +00001033 struct interface *ifp;
1034 int if_was_operative;
1035
1036 ifp = (struct interface *) vty->index;
1037 if_was_operative = if_is_operative(ifp);
1038 UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
1039
1040 /* Interface may come up after disabling link detection */
1041 if (if_is_operative(ifp) && !if_was_operative) if_up(ifp);
1042
1043 /* FIXME: see linkdetect_cmd */
1044
1045 return CMD_SUCCESS;
1046}
1047
paul718e3742002-12-13 20:15:29 +00001048DEFUN (shutdown_if,
1049 shutdown_if_cmd,
1050 "shutdown",
1051 "Shutdown the selected interface\n")
1052{
1053 int ret;
1054 struct interface *ifp;
1055 struct zebra_if *if_data;
1056
1057 ifp = (struct interface *) vty->index;
1058 ret = if_unset_flags (ifp, IFF_UP);
1059 if (ret < 0)
1060 {
1061 vty_out (vty, "Can't shutdown interface%s", VTY_NEWLINE);
1062 return CMD_WARNING;
1063 }
1064 if_refresh (ifp);
1065 if_data = ifp->info;
1066 if_data->shutdown = IF_ZEBRA_SHUTDOWN_ON;
1067
1068 return CMD_SUCCESS;
1069}
1070
1071DEFUN (no_shutdown_if,
1072 no_shutdown_if_cmd,
1073 "no shutdown",
1074 NO_STR
1075 "Shutdown the selected interface\n")
1076{
1077 int ret;
1078 struct interface *ifp;
1079 struct zebra_if *if_data;
1080
1081 ifp = (struct interface *) vty->index;
1082 ret = if_set_flags (ifp, IFF_UP | IFF_RUNNING);
1083 if (ret < 0)
1084 {
1085 vty_out (vty, "Can't up interface%s", VTY_NEWLINE);
1086 return CMD_WARNING;
1087 }
1088 if_refresh (ifp);
1089 if_data = ifp->info;
1090 if_data->shutdown = IF_ZEBRA_SHUTDOWN_OFF;
1091
1092 return CMD_SUCCESS;
1093}
1094
1095DEFUN (bandwidth_if,
1096 bandwidth_if_cmd,
1097 "bandwidth <1-10000000>",
1098 "Set bandwidth informational parameter\n"
1099 "Bandwidth in kilobits\n")
1100{
1101 struct interface *ifp;
1102 unsigned int bandwidth;
1103
1104 ifp = (struct interface *) vty->index;
1105 bandwidth = strtol(argv[0], NULL, 10);
1106
1107 /* bandwidth range is <1-10000000> */
1108 if (bandwidth < 1 || bandwidth > 10000000)
1109 {
1110 vty_out (vty, "Bandwidth is invalid%s", VTY_NEWLINE);
1111 return CMD_WARNING;
1112 }
1113
1114 ifp->bandwidth = bandwidth;
1115
1116 /* force protocols to recalculate routes due to cost change */
paul2e3b2e42002-12-13 21:03:13 +00001117 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00001118 zebra_interface_up_update (ifp);
1119
1120 return CMD_SUCCESS;
1121}
1122
1123DEFUN (no_bandwidth_if,
1124 no_bandwidth_if_cmd,
1125 "no bandwidth",
1126 NO_STR
1127 "Set bandwidth informational parameter\n")
1128{
1129 struct interface *ifp;
1130
1131 ifp = (struct interface *) vty->index;
1132
1133 ifp->bandwidth = 0;
1134
1135 /* force protocols to recalculate routes due to cost change */
paul2e3b2e42002-12-13 21:03:13 +00001136 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00001137 zebra_interface_up_update (ifp);
1138
1139 return CMD_SUCCESS;
1140}
1141
1142ALIAS (no_bandwidth_if,
1143 no_bandwidth_if_val_cmd,
1144 "no bandwidth <1-10000000>",
1145 NO_STR
1146 "Set bandwidth informational parameter\n"
1147 "Bandwidth in kilobits\n")
1148
paula1ac18c2005-06-28 17:17:12 +00001149static int
hasso39db97e2004-10-12 20:50:58 +00001150ip_address_install (struct vty *vty, struct interface *ifp,
1151 const char *addr_str, const char *peer_str,
1152 const char *label)
paul718e3742002-12-13 20:15:29 +00001153{
1154 struct prefix_ipv4 cp;
1155 struct connected *ifc;
1156 struct prefix_ipv4 *p;
paul718e3742002-12-13 20:15:29 +00001157 int ret;
1158
1159 ret = str2prefix_ipv4 (addr_str, &cp);
1160 if (ret <= 0)
1161 {
1162 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1163 return CMD_WARNING;
1164 }
1165
paulca162182005-09-12 16:58:52 +00001166 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001167 if (! ifc)
1168 {
1169 ifc = connected_new ();
1170 ifc->ifp = ifp;
1171
1172 /* Address. */
1173 p = prefix_ipv4_new ();
1174 *p = cp;
1175 ifc->address = (struct prefix *) p;
1176
1177 /* Broadcast. */
hasso3fb9cd62004-10-19 19:44:43 +00001178 if (p->prefixlen <= IPV4_MAX_PREFIXLEN-2)
paul718e3742002-12-13 20:15:29 +00001179 {
1180 p = prefix_ipv4_new ();
1181 *p = cp;
hasso3fb9cd62004-10-19 19:44:43 +00001182 p->prefix.s_addr = ipv4_broadcast_addr(p->prefix.s_addr,p->prefixlen);
paul718e3742002-12-13 20:15:29 +00001183 ifc->destination = (struct prefix *) p;
1184 }
1185
paul718e3742002-12-13 20:15:29 +00001186 /* Label. */
1187 if (label)
paul0752ef02005-11-03 12:35:21 +00001188 ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
paul718e3742002-12-13 20:15:29 +00001189
1190 /* Add to linked list. */
1191 listnode_add (ifp->connected, ifc);
1192 }
1193
1194 /* This address is configured from zebra. */
1195 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1196 SET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED);
1197
1198 /* In case of this route need to install kernel. */
1199 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1200 && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1201 {
1202 /* Some system need to up the interface to set IP address. */
1203 if (! if_is_up (ifp))
1204 {
1205 if_set_flags (ifp, IFF_UP | IFF_RUNNING);
1206 if_refresh (ifp);
1207 }
1208
1209 ret = if_set_prefix (ifp, ifc);
1210 if (ret < 0)
1211 {
1212 vty_out (vty, "%% Can't set interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001213 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001214 return CMD_WARNING;
1215 }
1216
hassoeef1fe12004-10-03 18:46:08 +00001217 /* Add to subnet chain list (while marking secondary attribute). */
1218 if_subnet_add (ifp, ifc);
1219
paul718e3742002-12-13 20:15:29 +00001220 /* IP address propery set. */
1221 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
1222
1223 /* Update interface address information to protocol daemon. */
1224 zebra_interface_address_add_update (ifp, ifc);
1225
1226 /* If interface is up register connected route. */
paul2e3b2e42002-12-13 21:03:13 +00001227 if (if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001228 connected_up_ipv4 (ifp, ifc);
1229 }
1230
1231 return CMD_SUCCESS;
1232}
1233
paula1ac18c2005-06-28 17:17:12 +00001234static int
hasso39db97e2004-10-12 20:50:58 +00001235ip_address_uninstall (struct vty *vty, struct interface *ifp,
1236 const char *addr_str, const char *peer_str,
1237 const char *label)
paul718e3742002-12-13 20:15:29 +00001238{
1239 struct prefix_ipv4 cp;
1240 struct connected *ifc;
1241 int ret;
1242
1243 /* Convert to prefix structure. */
1244 ret = str2prefix_ipv4 (addr_str, &cp);
1245 if (ret <= 0)
1246 {
1247 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1248 return CMD_WARNING;
1249 }
1250
1251 /* Check current interface address. */
paulca162182005-09-12 16:58:52 +00001252 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001253 if (! ifc)
1254 {
1255 vty_out (vty, "%% Can't find address%s", VTY_NEWLINE);
1256 return CMD_WARNING;
1257 }
1258
1259 /* This is not configured address. */
1260 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1261 return CMD_WARNING;
1262
Paul Jakma74ecdc92006-06-15 18:10:47 +00001263 UNSET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED);
1264
paul718e3742002-12-13 20:15:29 +00001265 /* This is not real address or interface is not active. */
1266 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1267 || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1268 {
1269 listnode_delete (ifp->connected, ifc);
1270 connected_free (ifc);
1271 return CMD_WARNING;
1272 }
1273
1274 /* This is real route. */
1275 ret = if_unset_prefix (ifp, ifc);
1276 if (ret < 0)
1277 {
1278 vty_out (vty, "%% Can't unset interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001279 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001280 return CMD_WARNING;
1281 }
1282
hassoeef1fe12004-10-03 18:46:08 +00001283#if 0
paul718e3742002-12-13 20:15:29 +00001284 /* Redistribute this information. */
1285 zebra_interface_address_delete_update (ifp, ifc);
1286
1287 /* Remove connected route. */
1288 connected_down_ipv4 (ifp, ifc);
1289
1290 /* Free address information. */
1291 listnode_delete (ifp->connected, ifc);
1292 connected_free (ifc);
hassoeef1fe12004-10-03 18:46:08 +00001293#endif
paul718e3742002-12-13 20:15:29 +00001294
1295 return CMD_SUCCESS;
1296}
1297
1298DEFUN (ip_address,
1299 ip_address_cmd,
1300 "ip address A.B.C.D/M",
1301 "Interface Internet Protocol config commands\n"
1302 "Set the IP address of an interface\n"
1303 "IP address (e.g. 10.0.0.1/8)\n")
1304{
hassoeef1fe12004-10-03 18:46:08 +00001305 return ip_address_install (vty, vty->index, argv[0], NULL, NULL);
paul718e3742002-12-13 20:15:29 +00001306}
1307
1308DEFUN (no_ip_address,
1309 no_ip_address_cmd,
1310 "no ip address A.B.C.D/M",
1311 NO_STR
1312 "Interface Internet Protocol config commands\n"
1313 "Set the IP address of an interface\n"
1314 "IP Address (e.g. 10.0.0.1/8)")
1315{
hassoeef1fe12004-10-03 18:46:08 +00001316 return ip_address_uninstall (vty, vty->index, argv[0], NULL, NULL);
paul718e3742002-12-13 20:15:29 +00001317}
1318
1319#ifdef HAVE_NETLINK
paul718e3742002-12-13 20:15:29 +00001320DEFUN (ip_address_label,
1321 ip_address_label_cmd,
1322 "ip address A.B.C.D/M label LINE",
1323 "Interface Internet Protocol config commands\n"
1324 "Set the IP address of an interface\n"
1325 "IP address (e.g. 10.0.0.1/8)\n"
1326 "Label of this address\n"
1327 "Label\n")
1328{
hassoeef1fe12004-10-03 18:46:08 +00001329 return ip_address_install (vty, vty->index, argv[0], NULL, argv[1]);
paul718e3742002-12-13 20:15:29 +00001330}
1331
1332DEFUN (no_ip_address_label,
1333 no_ip_address_label_cmd,
1334 "no ip address A.B.C.D/M label LINE",
1335 NO_STR
1336 "Interface Internet Protocol config commands\n"
1337 "Set the IP address of an interface\n"
1338 "IP address (e.g. 10.0.0.1/8)\n"
1339 "Label of this address\n"
1340 "Label\n")
1341{
hassoeef1fe12004-10-03 18:46:08 +00001342 return ip_address_uninstall (vty, vty->index, argv[0], NULL, argv[1]);
paul718e3742002-12-13 20:15:29 +00001343}
1344#endif /* HAVE_NETLINK */
1345
1346#ifdef HAVE_IPV6
paula1ac18c2005-06-28 17:17:12 +00001347static int
hasso39db97e2004-10-12 20:50:58 +00001348ipv6_address_install (struct vty *vty, struct interface *ifp,
1349 const char *addr_str, const char *peer_str,
1350 const char *label, int secondary)
paul718e3742002-12-13 20:15:29 +00001351{
1352 struct prefix_ipv6 cp;
1353 struct connected *ifc;
1354 struct prefix_ipv6 *p;
1355 int ret;
1356
1357 ret = str2prefix_ipv6 (addr_str, &cp);
1358 if (ret <= 0)
1359 {
1360 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1361 return CMD_WARNING;
1362 }
1363
paulca162182005-09-12 16:58:52 +00001364 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001365 if (! ifc)
1366 {
1367 ifc = connected_new ();
1368 ifc->ifp = ifp;
1369
1370 /* Address. */
1371 p = prefix_ipv6_new ();
1372 *p = cp;
1373 ifc->address = (struct prefix *) p;
1374
1375 /* Secondary. */
1376 if (secondary)
1377 SET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY);
1378
1379 /* Label. */
1380 if (label)
paul0752ef02005-11-03 12:35:21 +00001381 ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
paul718e3742002-12-13 20:15:29 +00001382
1383 /* Add to linked list. */
1384 listnode_add (ifp->connected, ifc);
1385 }
1386
1387 /* This address is configured from zebra. */
1388 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1389 SET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED);
1390
1391 /* In case of this route need to install kernel. */
1392 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1393 && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1394 {
1395 /* Some system need to up the interface to set IP address. */
1396 if (! if_is_up (ifp))
1397 {
1398 if_set_flags (ifp, IFF_UP | IFF_RUNNING);
1399 if_refresh (ifp);
1400 }
1401
1402 ret = if_prefix_add_ipv6 (ifp, ifc);
1403
1404 if (ret < 0)
1405 {
1406 vty_out (vty, "%% Can't set interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001407 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001408 return CMD_WARNING;
1409 }
1410
1411 /* IP address propery set. */
1412 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
1413
1414 /* Update interface address information to protocol daemon. */
1415 zebra_interface_address_add_update (ifp, ifc);
1416
1417 /* If interface is up register connected route. */
paul2e3b2e42002-12-13 21:03:13 +00001418 if (if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001419 connected_up_ipv6 (ifp, ifc);
1420 }
1421
1422 return CMD_SUCCESS;
1423}
1424
paula1ac18c2005-06-28 17:17:12 +00001425static int
hasso39db97e2004-10-12 20:50:58 +00001426ipv6_address_uninstall (struct vty *vty, struct interface *ifp,
1427 const char *addr_str, const char *peer_str,
1428 const char *label, int secondry)
paul718e3742002-12-13 20:15:29 +00001429{
1430 struct prefix_ipv6 cp;
1431 struct connected *ifc;
1432 int ret;
1433
1434 /* Convert to prefix structure. */
1435 ret = str2prefix_ipv6 (addr_str, &cp);
1436 if (ret <= 0)
1437 {
1438 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1439 return CMD_WARNING;
1440 }
1441
1442 /* Check current interface address. */
paulca162182005-09-12 16:58:52 +00001443 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001444 if (! ifc)
1445 {
1446 vty_out (vty, "%% Can't find address%s", VTY_NEWLINE);
1447 return CMD_WARNING;
1448 }
1449
1450 /* This is not configured address. */
1451 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1452 return CMD_WARNING;
1453
1454 /* This is not real address or interface is not active. */
1455 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1456 || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1457 {
1458 listnode_delete (ifp->connected, ifc);
1459 connected_free (ifc);
1460 return CMD_WARNING;
1461 }
1462
1463 /* This is real route. */
1464 ret = if_prefix_delete_ipv6 (ifp, ifc);
1465 if (ret < 0)
1466 {
1467 vty_out (vty, "%% Can't unset interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001468 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001469 return CMD_WARNING;
1470 }
1471
1472 /* Redistribute this information. */
1473 zebra_interface_address_delete_update (ifp, ifc);
1474
1475 /* Remove connected route. */
1476 connected_down_ipv6 (ifp, ifc);
1477
1478 /* Free address information. */
1479 listnode_delete (ifp->connected, ifc);
1480 connected_free (ifc);
1481
1482 return CMD_SUCCESS;
1483}
1484
1485DEFUN (ipv6_address,
1486 ipv6_address_cmd,
1487 "ipv6 address X:X::X:X/M",
hassoe23949c2004-03-11 15:54:02 +00001488 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001489 "Set the IP address of an interface\n"
1490 "IPv6 address (e.g. 3ffe:506::1/48)\n")
1491{
1492 return ipv6_address_install (vty, vty->index, argv[0], NULL, NULL, 0);
1493}
1494
1495DEFUN (no_ipv6_address,
1496 no_ipv6_address_cmd,
1497 "no ipv6 address X:X::X:X/M",
1498 NO_STR
hassoe23949c2004-03-11 15:54:02 +00001499 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001500 "Set the IP address of an interface\n"
1501 "IPv6 address (e.g. 3ffe:506::1/48)\n")
1502{
1503 return ipv6_address_uninstall (vty, vty->index, argv[0], NULL, NULL, 0);
1504}
1505#endif /* HAVE_IPV6 */
1506
paula1ac18c2005-06-28 17:17:12 +00001507static int
paul718e3742002-12-13 20:15:29 +00001508if_config_write (struct vty *vty)
1509{
hasso52dc7ee2004-09-23 19:18:23 +00001510 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001511 struct interface *ifp;
paul718e3742002-12-13 20:15:29 +00001512
paul1eb8ef22005-04-07 07:30:20 +00001513 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00001514 {
1515 struct zebra_if *if_data;
hasso52dc7ee2004-09-23 19:18:23 +00001516 struct listnode *addrnode;
paul718e3742002-12-13 20:15:29 +00001517 struct connected *ifc;
1518 struct prefix *p;
1519
paul718e3742002-12-13 20:15:29 +00001520 if_data = ifp->info;
1521
1522 vty_out (vty, "interface %s%s", ifp->name,
1523 VTY_NEWLINE);
1524
1525 if (ifp->desc)
1526 vty_out (vty, " description %s%s", ifp->desc,
1527 VTY_NEWLINE);
1528
1529 /* Assign bandwidth here to avoid unnecessary interface flap
1530 while processing config script */
1531 if (ifp->bandwidth != 0)
1532 vty_out(vty, " bandwidth %u%s", ifp->bandwidth, VTY_NEWLINE);
1533
paul2e3b2e42002-12-13 21:03:13 +00001534 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION))
1535 vty_out(vty, " link-detect%s", VTY_NEWLINE);
1536
paul1eb8ef22005-04-07 07:30:20 +00001537 for (ALL_LIST_ELEMENTS_RO (ifp->connected, addrnode, ifc))
paul718e3742002-12-13 20:15:29 +00001538 {
paul718e3742002-12-13 20:15:29 +00001539 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1540 {
Stephen Hemminger81cce012009-04-28 14:28:00 -07001541 char buf[INET6_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00001542 p = ifc->address;
1543 vty_out (vty, " ip%s address %s/%d",
1544 p->family == AF_INET ? "" : "v6",
Stephen Hemminger81cce012009-04-28 14:28:00 -07001545 inet_ntop (p->family, &p->u.prefix, buf, sizeof(buf)),
paul718e3742002-12-13 20:15:29 +00001546 p->prefixlen);
1547
paul718e3742002-12-13 20:15:29 +00001548 if (ifc->label)
1549 vty_out (vty, " label %s", ifc->label);
1550
1551 vty_out (vty, "%s", VTY_NEWLINE);
1552 }
1553 }
1554
1555 if (if_data)
1556 {
1557 if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)
1558 vty_out (vty, " shutdown%s", VTY_NEWLINE);
1559
1560 if (if_data->multicast != IF_ZEBRA_MULTICAST_UNSPEC)
1561 vty_out (vty, " %smulticast%s",
1562 if_data->multicast == IF_ZEBRA_MULTICAST_ON ? "" : "no ",
1563 VTY_NEWLINE);
1564 }
1565
1566#ifdef RTADV
1567 rtadv_config_write (vty, ifp);
1568#endif /* RTADV */
1569
hassoca776982004-06-12 14:33:05 +00001570#ifdef HAVE_IRDP
1571 irdp_config_write (vty, ifp);
1572#endif /* IRDP */
1573
paul718e3742002-12-13 20:15:29 +00001574 vty_out (vty, "!%s", VTY_NEWLINE);
1575 }
1576 return 0;
1577}
1578
1579/* Allocate and initialize interface vector. */
1580void
paula1ac18c2005-06-28 17:17:12 +00001581zebra_if_init (void)
paul718e3742002-12-13 20:15:29 +00001582{
1583 /* Initialize interface and new hook. */
1584 if_init ();
1585 if_add_hook (IF_NEW_HOOK, if_zebra_new_hook);
1586 if_add_hook (IF_DELETE_HOOK, if_zebra_delete_hook);
1587
1588 /* Install configuration write function. */
1589 install_node (&interface_node, if_config_write);
1590
1591 install_element (VIEW_NODE, &show_interface_cmd);
1592 install_element (ENABLE_NODE, &show_interface_cmd);
hassoed9bb6d2005-03-13 19:17:21 +00001593 install_element (ENABLE_NODE, &show_interface_desc_cmd);
paul718e3742002-12-13 20:15:29 +00001594 install_element (CONFIG_NODE, &zebra_interface_cmd);
paulbfc13532003-05-24 06:40:04 +00001595 install_element (CONFIG_NODE, &no_interface_cmd);
paul718e3742002-12-13 20:15:29 +00001596 install_default (INTERFACE_NODE);
1597 install_element (INTERFACE_NODE, &interface_desc_cmd);
1598 install_element (INTERFACE_NODE, &no_interface_desc_cmd);
1599 install_element (INTERFACE_NODE, &multicast_cmd);
1600 install_element (INTERFACE_NODE, &no_multicast_cmd);
paul2e3b2e42002-12-13 21:03:13 +00001601 install_element (INTERFACE_NODE, &linkdetect_cmd);
1602 install_element (INTERFACE_NODE, &no_linkdetect_cmd);
paul718e3742002-12-13 20:15:29 +00001603 install_element (INTERFACE_NODE, &shutdown_if_cmd);
1604 install_element (INTERFACE_NODE, &no_shutdown_if_cmd);
1605 install_element (INTERFACE_NODE, &bandwidth_if_cmd);
1606 install_element (INTERFACE_NODE, &no_bandwidth_if_cmd);
1607 install_element (INTERFACE_NODE, &no_bandwidth_if_val_cmd);
1608 install_element (INTERFACE_NODE, &ip_address_cmd);
1609 install_element (INTERFACE_NODE, &no_ip_address_cmd);
1610#ifdef HAVE_IPV6
1611 install_element (INTERFACE_NODE, &ipv6_address_cmd);
1612 install_element (INTERFACE_NODE, &no_ipv6_address_cmd);
1613#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +00001614#ifdef HAVE_NETLINK
paul718e3742002-12-13 20:15:29 +00001615 install_element (INTERFACE_NODE, &ip_address_label_cmd);
paul718e3742002-12-13 20:15:29 +00001616 install_element (INTERFACE_NODE, &no_ip_address_label_cmd);
paul718e3742002-12-13 20:15:29 +00001617#endif /* HAVE_NETLINK */
1618}