blob: d4266f59bf320793b92f31abd8dfa18a8f38ef15 [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
paul718e3742002-12-13 20:15:29 +0000410 if (p->family == AF_INET)
hassoeef1fe12004-10-03 18:46:08 +0000411 {
412 rn = route_node_lookup (zebra_if->ipv4_subnets, p);
413 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
551/* Printout flag information into vty */
paula1ac18c2005-06-28 17:17:12 +0000552static void
paul5c78b3d2006-01-25 04:31:40 +0000553if_flag_dump_vty (struct vty *vty, uint64_t flag)
paul718e3742002-12-13 20:15:29 +0000554{
555 int separator = 0;
556
557#define IFF_OUT_VTY(X, Y) \
558 if ((X) && (flag & (X))) \
559 { \
560 if (separator) \
561 vty_out (vty, ","); \
562 else \
563 separator = 1; \
564 vty_out (vty, Y); \
565 }
566
567 vty_out (vty, "<");
568 IFF_OUT_VTY (IFF_UP, "UP");
569 IFF_OUT_VTY (IFF_BROADCAST, "BROADCAST");
570 IFF_OUT_VTY (IFF_DEBUG, "DEBUG");
571 IFF_OUT_VTY (IFF_LOOPBACK, "LOOPBACK");
572 IFF_OUT_VTY (IFF_POINTOPOINT, "POINTOPOINT");
573 IFF_OUT_VTY (IFF_NOTRAILERS, "NOTRAILERS");
574 IFF_OUT_VTY (IFF_RUNNING, "RUNNING");
575 IFF_OUT_VTY (IFF_NOARP, "NOARP");
576 IFF_OUT_VTY (IFF_PROMISC, "PROMISC");
577 IFF_OUT_VTY (IFF_ALLMULTI, "ALLMULTI");
578 IFF_OUT_VTY (IFF_OACTIVE, "OACTIVE");
579 IFF_OUT_VTY (IFF_SIMPLEX, "SIMPLEX");
580 IFF_OUT_VTY (IFF_LINK0, "LINK0");
581 IFF_OUT_VTY (IFF_LINK1, "LINK1");
582 IFF_OUT_VTY (IFF_LINK2, "LINK2");
583 IFF_OUT_VTY (IFF_MULTICAST, "MULTICAST");
paul44145db2004-05-09 11:00:23 +0000584#ifdef SOLARIS_IPV6
paul5c78b3d2006-01-25 04:31:40 +0000585 IFF_OUT_VTY (IFF_VIRTUAL, "IFF_VIRTUAL");
586 IFF_OUT_VTY (IFF_NOXMIT, "IFF_NOXMIT");
paul44145db2004-05-09 11:00:23 +0000587#endif /* SOLARIS_IPV6 */
paul718e3742002-12-13 20:15:29 +0000588 vty_out (vty, ">");
589}
590
591/* Output prefix string to vty. */
paula1ac18c2005-06-28 17:17:12 +0000592static int
paul718e3742002-12-13 20:15:29 +0000593prefix_vty_out (struct vty *vty, struct prefix *p)
594{
595 char str[INET6_ADDRSTRLEN];
596
597 inet_ntop (p->family, &p->u.prefix, str, sizeof (str));
598 vty_out (vty, "%s", str);
599 return strlen (str);
600}
601
602/* Dump if address information to vty. */
paula1ac18c2005-06-28 17:17:12 +0000603static void
paul718e3742002-12-13 20:15:29 +0000604connected_dump_vty (struct vty *vty, struct connected *connected)
605{
606 struct prefix *p;
607 struct interface *ifp;
608
609 /* Set interface pointer. */
610 ifp = connected->ifp;
611
612 /* Print interface address. */
613 p = connected->address;
614 vty_out (vty, " %s ", prefix_family_str (p));
615 prefix_vty_out (vty, p);
616 vty_out (vty, "/%d", p->prefixlen);
617
618 /* If there is destination address, print it. */
619 p = connected->destination;
620 if (p)
621 {
622 if (p->family == AF_INET)
623 if (ifp->flags & IFF_BROADCAST)
624 {
625 vty_out (vty, " broadcast ");
626 prefix_vty_out (vty, p);
627 }
628
629 if (ifp->flags & IFF_POINTOPOINT)
630 {
631 vty_out (vty, " pointopoint ");
632 prefix_vty_out (vty, p);
633 }
634 }
635
636 if (CHECK_FLAG (connected->flags, ZEBRA_IFA_SECONDARY))
637 vty_out (vty, " secondary");
638
639 if (connected->label)
640 vty_out (vty, " %s", connected->label);
641
642 vty_out (vty, "%s", VTY_NEWLINE);
643}
644
645#ifdef RTADV
646/* Dump interface ND information to vty. */
paula1ac18c2005-06-28 17:17:12 +0000647static void
paul718e3742002-12-13 20:15:29 +0000648nd_dump_vty (struct vty *vty, struct interface *ifp)
649{
650 struct zebra_if *zif;
651 struct rtadvconf *rtadv;
vincent7cee1bb2005-03-25 13:08:53 +0000652 int interval;
paul718e3742002-12-13 20:15:29 +0000653
654 zif = (struct zebra_if *) ifp->info;
655 rtadv = &zif->rtadv;
656
657 if (rtadv->AdvSendAdvertisements)
658 {
659 vty_out (vty, " ND advertised reachable time is %d milliseconds%s",
660 rtadv->AdvReachableTime, VTY_NEWLINE);
661 vty_out (vty, " ND advertised retransmit interval is %d milliseconds%s",
662 rtadv->AdvRetransTimer, VTY_NEWLINE);
vincent7cee1bb2005-03-25 13:08:53 +0000663 interval = rtadv->MaxRtrAdvInterval;
664 if (interval % 1000)
665 vty_out (vty, " ND router advertisements are sent every "
666 "%d milliseconds%s", interval,
667 VTY_NEWLINE);
668 else
669 vty_out (vty, " ND router advertisements are sent every "
670 "%d seconds%s", interval / 1000,
671 VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000672 vty_out (vty, " ND router advertisements live for %d seconds%s",
673 rtadv->AdvDefaultLifetime, VTY_NEWLINE);
674 if (rtadv->AdvManagedFlag)
675 vty_out (vty, " Hosts use DHCP to obtain routable addresses.%s",
676 VTY_NEWLINE);
677 else
678 vty_out (vty, " Hosts use stateless autoconfig for addresses.%s",
679 VTY_NEWLINE);
vincent7cee1bb2005-03-25 13:08:53 +0000680 if (rtadv->AdvHomeAgentFlag)
681 vty_out (vty, " ND router advertisements with "
682 "Home Agent flag bit set.%s",
683 VTY_NEWLINE);
684 if (rtadv->AdvIntervalOption)
685 vty_out (vty, " ND router advertisements with Adv. Interval option.%s",
686 VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000687 }
688}
689#endif /* RTADV */
690
691/* Interface's information print out to vty interface. */
paula1ac18c2005-06-28 17:17:12 +0000692static void
paul718e3742002-12-13 20:15:29 +0000693if_dump_vty (struct vty *vty, struct interface *ifp)
694{
695#ifdef HAVE_SOCKADDR_DL
696 struct sockaddr_dl *sdl;
697#endif /* HAVE_SOCKADDR_DL */
698 struct connected *connected;
hasso52dc7ee2004-09-23 19:18:23 +0000699 struct listnode *node;
hassoeef1fe12004-10-03 18:46:08 +0000700 struct route_node *rn;
701 struct zebra_if *zebra_if;
702
703 zebra_if = ifp->info;
paul718e3742002-12-13 20:15:29 +0000704
paul2e3b2e42002-12-13 21:03:13 +0000705 vty_out (vty, "Interface %s is ", ifp->name);
706 if (if_is_up(ifp)) {
707 vty_out (vty, "up, line protocol ");
708
709 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) {
710 if (if_is_running(ifp))
711 vty_out (vty, "is up%s", VTY_NEWLINE);
712 else
713 vty_out (vty, "is down%s", VTY_NEWLINE);
714 } else {
715 vty_out (vty, "detection is disabled%s", VTY_NEWLINE);
716 }
717 } else {
718 vty_out (vty, "down%s", VTY_NEWLINE);
719 }
720
paul718e3742002-12-13 20:15:29 +0000721 if (ifp->desc)
722 vty_out (vty, " Description: %s%s", ifp->desc,
723 VTY_NEWLINE);
ajsd2fc8892005-04-02 18:38:43 +0000724 if (ifp->ifindex == IFINDEX_INTERNAL)
paul718e3742002-12-13 20:15:29 +0000725 {
ajsd2fc8892005-04-02 18:38:43 +0000726 vty_out(vty, " pseudo interface%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000727 return;
728 }
729 else if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
730 {
731 vty_out(vty, " index %d inactive interface%s",
732 ifp->ifindex,
733 VTY_NEWLINE);
734 return;
735 }
736
737 vty_out (vty, " index %d metric %d mtu %d ",
738 ifp->ifindex, ifp->metric, ifp->mtu);
739 if_flag_dump_vty (vty, ifp->flags);
paul44145db2004-05-09 11:00:23 +0000740#ifdef HAVE_IPV6
741 if (ifp->mtu6 != ifp->mtu)
742 vty_out (vty, "mtu6 %d ", ifp->mtu6);
743#endif
744
paul718e3742002-12-13 20:15:29 +0000745 vty_out (vty, "%s", VTY_NEWLINE);
746
747 /* Hardware address. */
748#ifdef HAVE_SOCKADDR_DL
749 sdl = &ifp->sdl;
750 if (sdl != NULL && sdl->sdl_alen != 0)
751 {
752 int i;
753 u_char *ptr;
754
755 vty_out (vty, " HWaddr: ");
paul5b73a672004-07-23 15:26:14 +0000756 for (i = 0, ptr = (u_char *)LLADDR (sdl); i < sdl->sdl_alen; i++, ptr++)
757 vty_out (vty, "%s%02x", i == 0 ? "" : ":", *ptr);
paul718e3742002-12-13 20:15:29 +0000758 vty_out (vty, "%s", VTY_NEWLINE);
759 }
760#else
761 if (ifp->hw_addr_len != 0)
762 {
763 int i;
764
765 vty_out (vty, " HWaddr: ");
766 for (i = 0; i < ifp->hw_addr_len; i++)
767 vty_out (vty, "%s%02x", i == 0 ? "" : ":", ifp->hw_addr[i]);
768 vty_out (vty, "%s", VTY_NEWLINE);
769 }
770#endif /* HAVE_SOCKADDR_DL */
771
772 /* Bandwidth in kbps */
773 if (ifp->bandwidth != 0)
774 {
775 vty_out(vty, " bandwidth %u kbps", ifp->bandwidth);
776 vty_out(vty, "%s", VTY_NEWLINE);
777 }
778
hassoeef1fe12004-10-03 18:46:08 +0000779 for (rn = route_top (zebra_if->ipv4_subnets); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000780 {
hassoeef1fe12004-10-03 18:46:08 +0000781 if (! rn->info)
782 continue;
783
paul1eb8ef22005-04-07 07:30:20 +0000784 for (ALL_LIST_ELEMENTS_RO ((struct list *)rn->info, node, connected))
785 connected_dump_vty (vty, connected);
paul718e3742002-12-13 20:15:29 +0000786 }
787
paul1eb8ef22005-04-07 07:30:20 +0000788 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
hasso39db97e2004-10-12 20:50:58 +0000789 {
hasso39db97e2004-10-12 20:50:58 +0000790 if (CHECK_FLAG (connected->conf, ZEBRA_IFC_REAL) &&
791 (connected->address->family == AF_INET6))
792 connected_dump_vty (vty, connected);
793 }
794
paul718e3742002-12-13 20:15:29 +0000795#ifdef RTADV
796 nd_dump_vty (vty, ifp);
797#endif /* RTADV */
798
799#ifdef HAVE_PROC_NET_DEV
800 /* Statistics print out using proc file system. */
hasso6f2c27a2005-01-18 13:44:35 +0000801 vty_out (vty, " %lu input packets (%lu multicast), %lu bytes, "
802 "%lu dropped%s",
803 ifp->stats.rx_packets, ifp->stats.rx_multicast,
804 ifp->stats.rx_bytes, ifp->stats.rx_dropped, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000805
hasso6f2c27a2005-01-18 13:44:35 +0000806 vty_out (vty, " %lu input errors, %lu length, %lu overrun,"
hasso3452d472005-03-06 13:42:05 +0000807 " %lu CRC, %lu frame%s",
paul718e3742002-12-13 20:15:29 +0000808 ifp->stats.rx_errors, ifp->stats.rx_length_errors,
809 ifp->stats.rx_over_errors, ifp->stats.rx_crc_errors,
hasso6f2c27a2005-01-18 13:44:35 +0000810 ifp->stats.rx_frame_errors, VTY_NEWLINE);
811
812 vty_out (vty, " %lu fifo, %lu missed%s", ifp->stats.rx_fifo_errors,
paul718e3742002-12-13 20:15:29 +0000813 ifp->stats.rx_missed_errors, VTY_NEWLINE);
814
hasso6f2c27a2005-01-18 13:44:35 +0000815 vty_out (vty, " %lu output packets, %lu bytes, %lu dropped%s",
paul718e3742002-12-13 20:15:29 +0000816 ifp->stats.tx_packets, ifp->stats.tx_bytes,
817 ifp->stats.tx_dropped, VTY_NEWLINE);
818
hasso6f2c27a2005-01-18 13:44:35 +0000819 vty_out (vty, " %lu output errors, %lu aborted, %lu carrier,"
820 " %lu fifo, %lu heartbeat%s",
paul718e3742002-12-13 20:15:29 +0000821 ifp->stats.tx_errors, ifp->stats.tx_aborted_errors,
822 ifp->stats.tx_carrier_errors, ifp->stats.tx_fifo_errors,
hasso6f2c27a2005-01-18 13:44:35 +0000823 ifp->stats.tx_heartbeat_errors, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000824
hasso6f2c27a2005-01-18 13:44:35 +0000825 vty_out (vty, " %lu window, %lu collisions%s",
826 ifp->stats.tx_window_errors, ifp->stats.collisions, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000827#endif /* HAVE_PROC_NET_DEV */
828
829#ifdef HAVE_NET_RT_IFLIST
830#if defined (__bsdi__) || defined (__NetBSD__)
831 /* Statistics print out using sysctl (). */
832 vty_out (vty, " input packets %qu, bytes %qu, dropped %qu,"
833 " multicast packets %qu%s",
834 ifp->stats.ifi_ipackets, ifp->stats.ifi_ibytes,
835 ifp->stats.ifi_iqdrops, ifp->stats.ifi_imcasts,
836 VTY_NEWLINE);
837
838 vty_out (vty, " input errors %qu%s",
839 ifp->stats.ifi_ierrors, VTY_NEWLINE);
840
841 vty_out (vty, " output packets %qu, bytes %qu, multicast packets %qu%s",
842 ifp->stats.ifi_opackets, ifp->stats.ifi_obytes,
843 ifp->stats.ifi_omcasts, VTY_NEWLINE);
844
845 vty_out (vty, " output errors %qu%s",
846 ifp->stats.ifi_oerrors, VTY_NEWLINE);
847
848 vty_out (vty, " collisions %qu%s",
849 ifp->stats.ifi_collisions, VTY_NEWLINE);
850#else
851 /* Statistics print out using sysctl (). */
852 vty_out (vty, " input packets %lu, bytes %lu, dropped %lu,"
853 " multicast packets %lu%s",
854 ifp->stats.ifi_ipackets, ifp->stats.ifi_ibytes,
855 ifp->stats.ifi_iqdrops, ifp->stats.ifi_imcasts,
856 VTY_NEWLINE);
857
858 vty_out (vty, " input errors %lu%s",
859 ifp->stats.ifi_ierrors, VTY_NEWLINE);
860
861 vty_out (vty, " output packets %lu, bytes %lu, multicast packets %lu%s",
862 ifp->stats.ifi_opackets, ifp->stats.ifi_obytes,
863 ifp->stats.ifi_omcasts, VTY_NEWLINE);
864
865 vty_out (vty, " output errors %lu%s",
866 ifp->stats.ifi_oerrors, VTY_NEWLINE);
867
868 vty_out (vty, " collisions %lu%s",
869 ifp->stats.ifi_collisions, VTY_NEWLINE);
870#endif /* __bsdi__ || __NetBSD__ */
871#endif /* HAVE_NET_RT_IFLIST */
872}
873
874/* Check supported address family. */
paula1ac18c2005-06-28 17:17:12 +0000875static int
paul718e3742002-12-13 20:15:29 +0000876if_supported_family (int family)
877{
878 if (family == AF_INET)
879 return 1;
880#ifdef HAVE_IPV6
881 if (family == AF_INET6)
882 return 1;
883#endif /* HAVE_IPV6 */
884 return 0;
885}
886
887/* Wrapper hook point for zebra daemon so that ifindex can be set
888 * DEFUN macro not used as extract.pl HAS to ignore this
889 * See also interface_cmd in lib/if.c
890 */
891DEFUN_NOSH (zebra_interface,
892 zebra_interface_cmd,
893 "interface IFNAME",
894 "Select an interface to configure\n"
895 "Interface's name\n")
896{
897 int ret;
898 struct interface * ifp;
899
900 /* Call lib interface() */
ajsd2fc8892005-04-02 18:38:43 +0000901 if ((ret = interface_cmd.func (self, vty, argc, argv)) != CMD_SUCCESS)
902 return ret;
paul718e3742002-12-13 20:15:29 +0000903
904 ifp = vty->index;
905
ajsd2fc8892005-04-02 18:38:43 +0000906 if (ifp->ifindex == IFINDEX_INTERNAL)
907 /* Is this really necessary? Shouldn't status be initialized to 0
908 in that case? */
909 UNSET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE);
paul718e3742002-12-13 20:15:29 +0000910
911 return ret;
912}
913
paul718e3742002-12-13 20:15:29 +0000914struct cmd_node interface_node =
915{
916 INTERFACE_NODE,
917 "%s(config-if)# ",
918 1
919};
920
921/* Show all or specified interface to vty. */
922DEFUN (show_interface, show_interface_cmd,
923 "show interface [IFNAME]",
924 SHOW_STR
925 "Interface status and configuration\n"
926 "Inteface name\n")
927{
hasso52dc7ee2004-09-23 19:18:23 +0000928 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000929 struct interface *ifp;
930
931#ifdef HAVE_PROC_NET_DEV
932 /* If system has interface statistics via proc file system, update
933 statistics. */
934 ifstat_update_proc ();
935#endif /* HAVE_PROC_NET_DEV */
936#ifdef HAVE_NET_RT_IFLIST
937 ifstat_update_sysctl ();
938#endif /* HAVE_NET_RT_IFLIST */
939
940 /* Specified interface print. */
941 if (argc != 0)
942 {
943 ifp = if_lookup_by_name (argv[0]);
944 if (ifp == NULL)
945 {
946 vty_out (vty, "%% Can't find interface %s%s", argv[0],
947 VTY_NEWLINE);
948 return CMD_WARNING;
949 }
950 if_dump_vty (vty, ifp);
951 return CMD_SUCCESS;
952 }
953
954 /* All interface print. */
paul1eb8ef22005-04-07 07:30:20 +0000955 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
956 if_dump_vty (vty, ifp);
paul718e3742002-12-13 20:15:29 +0000957
958 return CMD_SUCCESS;
959}
960
hassoed9bb6d2005-03-13 19:17:21 +0000961DEFUN (show_interface_desc,
962 show_interface_desc_cmd,
963 "show interface description",
964 SHOW_STR
965 "Interface status and configuration\n"
966 "Interface description\n")
967{
968 struct listnode *node;
969 struct interface *ifp;
970
971 vty_out (vty, "Interface Status Protocol Description%s", VTY_NEWLINE);
paul1eb8ef22005-04-07 07:30:20 +0000972 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
hassoed9bb6d2005-03-13 19:17:21 +0000973 {
974 int len;
hassoed9bb6d2005-03-13 19:17:21 +0000975
976 len = vty_out (vty, "%s", ifp->name);
977 vty_out (vty, "%*s", (16 - len), " ");
978
979 if (if_is_up(ifp))
980 {
981 vty_out (vty, "up ");
982 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION))
983 {
984 if (if_is_running(ifp))
985 vty_out (vty, "up ");
986 else
987 vty_out (vty, "down ");
988 }
989 else
990 {
991 vty_out (vty, "unknown ");
992 }
993 }
994 else
995 {
996 vty_out (vty, "down down ");
997 }
998
999 if (ifp->desc)
1000 vty_out (vty, "%s", ifp->desc);
1001 vty_out (vty, "%s", VTY_NEWLINE);
1002 }
1003 return CMD_SUCCESS;
1004}
1005
paul718e3742002-12-13 20:15:29 +00001006DEFUN (multicast,
1007 multicast_cmd,
1008 "multicast",
1009 "Set multicast flag to interface\n")
1010{
1011 int ret;
1012 struct interface *ifp;
1013 struct zebra_if *if_data;
1014
1015 ifp = (struct interface *) vty->index;
paul48b33aa2002-12-13 20:52:52 +00001016 if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
paul718e3742002-12-13 20:15:29 +00001017 {
paul48b33aa2002-12-13 20:52:52 +00001018 ret = if_set_flags (ifp, IFF_MULTICAST);
1019 if (ret < 0)
1020 {
1021 vty_out (vty, "Can't set multicast flag%s", VTY_NEWLINE);
1022 return CMD_WARNING;
1023 }
1024 if_refresh (ifp);
paul718e3742002-12-13 20:15:29 +00001025 }
paul718e3742002-12-13 20:15:29 +00001026 if_data = ifp->info;
1027 if_data->multicast = IF_ZEBRA_MULTICAST_ON;
paul48b33aa2002-12-13 20:52:52 +00001028
paul718e3742002-12-13 20:15:29 +00001029 return CMD_SUCCESS;
1030}
1031
1032DEFUN (no_multicast,
1033 no_multicast_cmd,
1034 "no multicast",
1035 NO_STR
1036 "Unset multicast flag to interface\n")
1037{
1038 int ret;
1039 struct interface *ifp;
1040 struct zebra_if *if_data;
1041
1042 ifp = (struct interface *) vty->index;
paul48b33aa2002-12-13 20:52:52 +00001043 if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
paul718e3742002-12-13 20:15:29 +00001044 {
paul48b33aa2002-12-13 20:52:52 +00001045 ret = if_unset_flags (ifp, IFF_MULTICAST);
1046 if (ret < 0)
1047 {
1048 vty_out (vty, "Can't unset multicast flag%s", VTY_NEWLINE);
1049 return CMD_WARNING;
1050 }
1051 if_refresh (ifp);
paul718e3742002-12-13 20:15:29 +00001052 }
paul718e3742002-12-13 20:15:29 +00001053 if_data = ifp->info;
1054 if_data->multicast = IF_ZEBRA_MULTICAST_OFF;
1055
1056 return CMD_SUCCESS;
1057}
1058
paul2e3b2e42002-12-13 21:03:13 +00001059DEFUN (linkdetect,
1060 linkdetect_cmd,
1061 "link-detect",
1062 "Enable link detection on interface\n")
1063{
paul2e3b2e42002-12-13 21:03:13 +00001064 struct interface *ifp;
1065 int if_was_operative;
1066
1067 ifp = (struct interface *) vty->index;
1068 if_was_operative = if_is_operative(ifp);
1069 SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
1070
1071 /* When linkdetection is enabled, if might come down */
1072 if (!if_is_operative(ifp) && if_was_operative) if_down(ifp);
1073
1074 /* FIXME: Will defer status change forwarding if interface
1075 does not come down! */
1076
1077 return CMD_SUCCESS;
1078}
1079
1080
1081DEFUN (no_linkdetect,
1082 no_linkdetect_cmd,
1083 "no link-detect",
1084 NO_STR
1085 "Disable link detection on interface\n")
1086{
paul2e3b2e42002-12-13 21:03:13 +00001087 struct interface *ifp;
1088 int if_was_operative;
1089
1090 ifp = (struct interface *) vty->index;
1091 if_was_operative = if_is_operative(ifp);
1092 UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
1093
1094 /* Interface may come up after disabling link detection */
1095 if (if_is_operative(ifp) && !if_was_operative) if_up(ifp);
1096
1097 /* FIXME: see linkdetect_cmd */
1098
1099 return CMD_SUCCESS;
1100}
1101
paul718e3742002-12-13 20:15:29 +00001102DEFUN (shutdown_if,
1103 shutdown_if_cmd,
1104 "shutdown",
1105 "Shutdown the selected interface\n")
1106{
1107 int ret;
1108 struct interface *ifp;
1109 struct zebra_if *if_data;
1110
1111 ifp = (struct interface *) vty->index;
1112 ret = if_unset_flags (ifp, IFF_UP);
1113 if (ret < 0)
1114 {
1115 vty_out (vty, "Can't shutdown interface%s", VTY_NEWLINE);
1116 return CMD_WARNING;
1117 }
1118 if_refresh (ifp);
1119 if_data = ifp->info;
1120 if_data->shutdown = IF_ZEBRA_SHUTDOWN_ON;
1121
1122 return CMD_SUCCESS;
1123}
1124
1125DEFUN (no_shutdown_if,
1126 no_shutdown_if_cmd,
1127 "no shutdown",
1128 NO_STR
1129 "Shutdown the selected interface\n")
1130{
1131 int ret;
1132 struct interface *ifp;
1133 struct zebra_if *if_data;
1134
1135 ifp = (struct interface *) vty->index;
1136 ret = if_set_flags (ifp, IFF_UP | IFF_RUNNING);
1137 if (ret < 0)
1138 {
1139 vty_out (vty, "Can't up interface%s", VTY_NEWLINE);
1140 return CMD_WARNING;
1141 }
1142 if_refresh (ifp);
1143 if_data = ifp->info;
1144 if_data->shutdown = IF_ZEBRA_SHUTDOWN_OFF;
1145
1146 return CMD_SUCCESS;
1147}
1148
1149DEFUN (bandwidth_if,
1150 bandwidth_if_cmd,
1151 "bandwidth <1-10000000>",
1152 "Set bandwidth informational parameter\n"
1153 "Bandwidth in kilobits\n")
1154{
1155 struct interface *ifp;
1156 unsigned int bandwidth;
1157
1158 ifp = (struct interface *) vty->index;
1159 bandwidth = strtol(argv[0], NULL, 10);
1160
1161 /* bandwidth range is <1-10000000> */
1162 if (bandwidth < 1 || bandwidth > 10000000)
1163 {
1164 vty_out (vty, "Bandwidth is invalid%s", VTY_NEWLINE);
1165 return CMD_WARNING;
1166 }
1167
1168 ifp->bandwidth = bandwidth;
1169
1170 /* force protocols to recalculate routes due to cost change */
paul2e3b2e42002-12-13 21:03:13 +00001171 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00001172 zebra_interface_up_update (ifp);
1173
1174 return CMD_SUCCESS;
1175}
1176
1177DEFUN (no_bandwidth_if,
1178 no_bandwidth_if_cmd,
1179 "no bandwidth",
1180 NO_STR
1181 "Set bandwidth informational parameter\n")
1182{
1183 struct interface *ifp;
1184
1185 ifp = (struct interface *) vty->index;
1186
1187 ifp->bandwidth = 0;
1188
1189 /* force protocols to recalculate routes due to cost change */
paul2e3b2e42002-12-13 21:03:13 +00001190 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00001191 zebra_interface_up_update (ifp);
1192
1193 return CMD_SUCCESS;
1194}
1195
1196ALIAS (no_bandwidth_if,
1197 no_bandwidth_if_val_cmd,
1198 "no bandwidth <1-10000000>",
1199 NO_STR
1200 "Set bandwidth informational parameter\n"
1201 "Bandwidth in kilobits\n")
1202
paula1ac18c2005-06-28 17:17:12 +00001203static int
hasso39db97e2004-10-12 20:50:58 +00001204ip_address_install (struct vty *vty, struct interface *ifp,
1205 const char *addr_str, const char *peer_str,
1206 const char *label)
paul718e3742002-12-13 20:15:29 +00001207{
1208 struct prefix_ipv4 cp;
1209 struct connected *ifc;
1210 struct prefix_ipv4 *p;
paul718e3742002-12-13 20:15:29 +00001211 int ret;
1212
1213 ret = str2prefix_ipv4 (addr_str, &cp);
1214 if (ret <= 0)
1215 {
1216 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1217 return CMD_WARNING;
1218 }
1219
paulca162182005-09-12 16:58:52 +00001220 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001221 if (! ifc)
1222 {
1223 ifc = connected_new ();
1224 ifc->ifp = ifp;
1225
1226 /* Address. */
1227 p = prefix_ipv4_new ();
1228 *p = cp;
1229 ifc->address = (struct prefix *) p;
1230
1231 /* Broadcast. */
hasso3fb9cd62004-10-19 19:44:43 +00001232 if (p->prefixlen <= IPV4_MAX_PREFIXLEN-2)
paul718e3742002-12-13 20:15:29 +00001233 {
1234 p = prefix_ipv4_new ();
1235 *p = cp;
hasso3fb9cd62004-10-19 19:44:43 +00001236 p->prefix.s_addr = ipv4_broadcast_addr(p->prefix.s_addr,p->prefixlen);
paul718e3742002-12-13 20:15:29 +00001237 ifc->destination = (struct prefix *) p;
1238 }
1239
paul718e3742002-12-13 20:15:29 +00001240 /* Label. */
1241 if (label)
paul0752ef02005-11-03 12:35:21 +00001242 ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
paul718e3742002-12-13 20:15:29 +00001243
1244 /* Add to linked list. */
1245 listnode_add (ifp->connected, ifc);
1246 }
1247
1248 /* This address is configured from zebra. */
1249 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1250 SET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED);
1251
1252 /* In case of this route need to install kernel. */
1253 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1254 && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1255 {
1256 /* Some system need to up the interface to set IP address. */
1257 if (! if_is_up (ifp))
1258 {
1259 if_set_flags (ifp, IFF_UP | IFF_RUNNING);
1260 if_refresh (ifp);
1261 }
1262
1263 ret = if_set_prefix (ifp, ifc);
1264 if (ret < 0)
1265 {
1266 vty_out (vty, "%% Can't set interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001267 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001268 return CMD_WARNING;
1269 }
1270
hassoeef1fe12004-10-03 18:46:08 +00001271 /* Add to subnet chain list (while marking secondary attribute). */
1272 if_subnet_add (ifp, ifc);
1273
paul718e3742002-12-13 20:15:29 +00001274 /* IP address propery set. */
1275 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
1276
1277 /* Update interface address information to protocol daemon. */
1278 zebra_interface_address_add_update (ifp, ifc);
1279
1280 /* If interface is up register connected route. */
paul2e3b2e42002-12-13 21:03:13 +00001281 if (if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001282 connected_up_ipv4 (ifp, ifc);
1283 }
1284
1285 return CMD_SUCCESS;
1286}
1287
paula1ac18c2005-06-28 17:17:12 +00001288static int
hasso39db97e2004-10-12 20:50:58 +00001289ip_address_uninstall (struct vty *vty, struct interface *ifp,
1290 const char *addr_str, const char *peer_str,
1291 const char *label)
paul718e3742002-12-13 20:15:29 +00001292{
1293 struct prefix_ipv4 cp;
1294 struct connected *ifc;
1295 int ret;
1296
1297 /* Convert to prefix structure. */
1298 ret = str2prefix_ipv4 (addr_str, &cp);
1299 if (ret <= 0)
1300 {
1301 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1302 return CMD_WARNING;
1303 }
1304
1305 /* Check current interface address. */
paulca162182005-09-12 16:58:52 +00001306 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001307 if (! ifc)
1308 {
1309 vty_out (vty, "%% Can't find address%s", VTY_NEWLINE);
1310 return CMD_WARNING;
1311 }
1312
1313 /* This is not configured address. */
1314 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1315 return CMD_WARNING;
1316
1317 /* This is not real address or interface is not active. */
1318 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1319 || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1320 {
1321 listnode_delete (ifp->connected, ifc);
1322 connected_free (ifc);
1323 return CMD_WARNING;
1324 }
1325
1326 /* This is real route. */
1327 ret = if_unset_prefix (ifp, ifc);
1328 if (ret < 0)
1329 {
1330 vty_out (vty, "%% Can't unset interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001331 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001332 return CMD_WARNING;
1333 }
1334
hassoeef1fe12004-10-03 18:46:08 +00001335#if 0
paul718e3742002-12-13 20:15:29 +00001336 /* Redistribute this information. */
1337 zebra_interface_address_delete_update (ifp, ifc);
1338
1339 /* Remove connected route. */
1340 connected_down_ipv4 (ifp, ifc);
1341
1342 /* Free address information. */
1343 listnode_delete (ifp->connected, ifc);
1344 connected_free (ifc);
hassoeef1fe12004-10-03 18:46:08 +00001345#endif
paul718e3742002-12-13 20:15:29 +00001346
1347 return CMD_SUCCESS;
1348}
1349
1350DEFUN (ip_address,
1351 ip_address_cmd,
1352 "ip address A.B.C.D/M",
1353 "Interface Internet Protocol config commands\n"
1354 "Set the IP address of an interface\n"
1355 "IP address (e.g. 10.0.0.1/8)\n")
1356{
hassoeef1fe12004-10-03 18:46:08 +00001357 return ip_address_install (vty, vty->index, argv[0], NULL, NULL);
paul718e3742002-12-13 20:15:29 +00001358}
1359
1360DEFUN (no_ip_address,
1361 no_ip_address_cmd,
1362 "no ip address A.B.C.D/M",
1363 NO_STR
1364 "Interface Internet Protocol config commands\n"
1365 "Set the IP address of an interface\n"
1366 "IP Address (e.g. 10.0.0.1/8)")
1367{
hassoeef1fe12004-10-03 18:46:08 +00001368 return ip_address_uninstall (vty, vty->index, argv[0], NULL, NULL);
paul718e3742002-12-13 20:15:29 +00001369}
1370
1371#ifdef HAVE_NETLINK
paul718e3742002-12-13 20:15:29 +00001372DEFUN (ip_address_label,
1373 ip_address_label_cmd,
1374 "ip address A.B.C.D/M label LINE",
1375 "Interface Internet Protocol config commands\n"
1376 "Set the IP address of an interface\n"
1377 "IP address (e.g. 10.0.0.1/8)\n"
1378 "Label of this address\n"
1379 "Label\n")
1380{
hassoeef1fe12004-10-03 18:46:08 +00001381 return ip_address_install (vty, vty->index, argv[0], NULL, argv[1]);
paul718e3742002-12-13 20:15:29 +00001382}
1383
1384DEFUN (no_ip_address_label,
1385 no_ip_address_label_cmd,
1386 "no ip address A.B.C.D/M label LINE",
1387 NO_STR
1388 "Interface Internet Protocol config commands\n"
1389 "Set the IP address of an interface\n"
1390 "IP address (e.g. 10.0.0.1/8)\n"
1391 "Label of this address\n"
1392 "Label\n")
1393{
hassoeef1fe12004-10-03 18:46:08 +00001394 return ip_address_uninstall (vty, vty->index, argv[0], NULL, argv[1]);
paul718e3742002-12-13 20:15:29 +00001395}
1396#endif /* HAVE_NETLINK */
1397
1398#ifdef HAVE_IPV6
paula1ac18c2005-06-28 17:17:12 +00001399static int
hasso39db97e2004-10-12 20:50:58 +00001400ipv6_address_install (struct vty *vty, struct interface *ifp,
1401 const char *addr_str, const char *peer_str,
1402 const char *label, int secondary)
paul718e3742002-12-13 20:15:29 +00001403{
1404 struct prefix_ipv6 cp;
1405 struct connected *ifc;
1406 struct prefix_ipv6 *p;
1407 int ret;
1408
1409 ret = str2prefix_ipv6 (addr_str, &cp);
1410 if (ret <= 0)
1411 {
1412 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1413 return CMD_WARNING;
1414 }
1415
paulca162182005-09-12 16:58:52 +00001416 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001417 if (! ifc)
1418 {
1419 ifc = connected_new ();
1420 ifc->ifp = ifp;
1421
1422 /* Address. */
1423 p = prefix_ipv6_new ();
1424 *p = cp;
1425 ifc->address = (struct prefix *) p;
1426
1427 /* Secondary. */
1428 if (secondary)
1429 SET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY);
1430
1431 /* Label. */
1432 if (label)
paul0752ef02005-11-03 12:35:21 +00001433 ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
paul718e3742002-12-13 20:15:29 +00001434
1435 /* Add to linked list. */
1436 listnode_add (ifp->connected, ifc);
1437 }
1438
1439 /* This address is configured from zebra. */
1440 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1441 SET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED);
1442
1443 /* In case of this route need to install kernel. */
1444 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1445 && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1446 {
1447 /* Some system need to up the interface to set IP address. */
1448 if (! if_is_up (ifp))
1449 {
1450 if_set_flags (ifp, IFF_UP | IFF_RUNNING);
1451 if_refresh (ifp);
1452 }
1453
1454 ret = if_prefix_add_ipv6 (ifp, ifc);
1455
1456 if (ret < 0)
1457 {
1458 vty_out (vty, "%% Can't set interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001459 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001460 return CMD_WARNING;
1461 }
1462
1463 /* IP address propery set. */
1464 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
1465
1466 /* Update interface address information to protocol daemon. */
1467 zebra_interface_address_add_update (ifp, ifc);
1468
1469 /* If interface is up register connected route. */
paul2e3b2e42002-12-13 21:03:13 +00001470 if (if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001471 connected_up_ipv6 (ifp, ifc);
1472 }
1473
1474 return CMD_SUCCESS;
1475}
1476
paula1ac18c2005-06-28 17:17:12 +00001477static int
hasso39db97e2004-10-12 20:50:58 +00001478ipv6_address_uninstall (struct vty *vty, struct interface *ifp,
1479 const char *addr_str, const char *peer_str,
1480 const char *label, int secondry)
paul718e3742002-12-13 20:15:29 +00001481{
1482 struct prefix_ipv6 cp;
1483 struct connected *ifc;
1484 int ret;
1485
1486 /* Convert to prefix structure. */
1487 ret = str2prefix_ipv6 (addr_str, &cp);
1488 if (ret <= 0)
1489 {
1490 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1491 return CMD_WARNING;
1492 }
1493
1494 /* Check current interface address. */
paulca162182005-09-12 16:58:52 +00001495 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001496 if (! ifc)
1497 {
1498 vty_out (vty, "%% Can't find address%s", VTY_NEWLINE);
1499 return CMD_WARNING;
1500 }
1501
1502 /* This is not configured address. */
1503 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1504 return CMD_WARNING;
1505
1506 /* This is not real address or interface is not active. */
1507 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1508 || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1509 {
1510 listnode_delete (ifp->connected, ifc);
1511 connected_free (ifc);
1512 return CMD_WARNING;
1513 }
1514
1515 /* This is real route. */
1516 ret = if_prefix_delete_ipv6 (ifp, ifc);
1517 if (ret < 0)
1518 {
1519 vty_out (vty, "%% Can't unset interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001520 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001521 return CMD_WARNING;
1522 }
1523
1524 /* Redistribute this information. */
1525 zebra_interface_address_delete_update (ifp, ifc);
1526
1527 /* Remove connected route. */
1528 connected_down_ipv6 (ifp, ifc);
1529
1530 /* Free address information. */
1531 listnode_delete (ifp->connected, ifc);
1532 connected_free (ifc);
1533
1534 return CMD_SUCCESS;
1535}
1536
1537DEFUN (ipv6_address,
1538 ipv6_address_cmd,
1539 "ipv6 address X:X::X:X/M",
hassoe23949c2004-03-11 15:54:02 +00001540 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001541 "Set the IP address of an interface\n"
1542 "IPv6 address (e.g. 3ffe:506::1/48)\n")
1543{
1544 return ipv6_address_install (vty, vty->index, argv[0], NULL, NULL, 0);
1545}
1546
1547DEFUN (no_ipv6_address,
1548 no_ipv6_address_cmd,
1549 "no ipv6 address X:X::X:X/M",
1550 NO_STR
hassoe23949c2004-03-11 15:54:02 +00001551 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001552 "Set the IP address of an interface\n"
1553 "IPv6 address (e.g. 3ffe:506::1/48)\n")
1554{
1555 return ipv6_address_uninstall (vty, vty->index, argv[0], NULL, NULL, 0);
1556}
1557#endif /* HAVE_IPV6 */
1558
paula1ac18c2005-06-28 17:17:12 +00001559static int
paul718e3742002-12-13 20:15:29 +00001560if_config_write (struct vty *vty)
1561{
hasso52dc7ee2004-09-23 19:18:23 +00001562 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001563 struct interface *ifp;
1564 char buf[BUFSIZ];
1565
paul1eb8ef22005-04-07 07:30:20 +00001566 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00001567 {
1568 struct zebra_if *if_data;
hasso52dc7ee2004-09-23 19:18:23 +00001569 struct listnode *addrnode;
paul718e3742002-12-13 20:15:29 +00001570 struct connected *ifc;
1571 struct prefix *p;
1572
paul718e3742002-12-13 20:15:29 +00001573 if_data = ifp->info;
1574
1575 vty_out (vty, "interface %s%s", ifp->name,
1576 VTY_NEWLINE);
1577
1578 if (ifp->desc)
1579 vty_out (vty, " description %s%s", ifp->desc,
1580 VTY_NEWLINE);
1581
1582 /* Assign bandwidth here to avoid unnecessary interface flap
1583 while processing config script */
1584 if (ifp->bandwidth != 0)
1585 vty_out(vty, " bandwidth %u%s", ifp->bandwidth, VTY_NEWLINE);
1586
paul2e3b2e42002-12-13 21:03:13 +00001587 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION))
1588 vty_out(vty, " link-detect%s", VTY_NEWLINE);
1589
paul1eb8ef22005-04-07 07:30:20 +00001590 for (ALL_LIST_ELEMENTS_RO (ifp->connected, addrnode, ifc))
paul718e3742002-12-13 20:15:29 +00001591 {
paul718e3742002-12-13 20:15:29 +00001592 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1593 {
1594 p = ifc->address;
1595 vty_out (vty, " ip%s address %s/%d",
1596 p->family == AF_INET ? "" : "v6",
1597 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
1598 p->prefixlen);
1599
paul718e3742002-12-13 20:15:29 +00001600 if (ifc->label)
1601 vty_out (vty, " label %s", ifc->label);
1602
1603 vty_out (vty, "%s", VTY_NEWLINE);
1604 }
1605 }
1606
1607 if (if_data)
1608 {
1609 if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)
1610 vty_out (vty, " shutdown%s", VTY_NEWLINE);
1611
1612 if (if_data->multicast != IF_ZEBRA_MULTICAST_UNSPEC)
1613 vty_out (vty, " %smulticast%s",
1614 if_data->multicast == IF_ZEBRA_MULTICAST_ON ? "" : "no ",
1615 VTY_NEWLINE);
1616 }
1617
1618#ifdef RTADV
1619 rtadv_config_write (vty, ifp);
1620#endif /* RTADV */
1621
hassoca776982004-06-12 14:33:05 +00001622#ifdef HAVE_IRDP
1623 irdp_config_write (vty, ifp);
1624#endif /* IRDP */
1625
paul718e3742002-12-13 20:15:29 +00001626 vty_out (vty, "!%s", VTY_NEWLINE);
1627 }
1628 return 0;
1629}
1630
1631/* Allocate and initialize interface vector. */
1632void
paula1ac18c2005-06-28 17:17:12 +00001633zebra_if_init (void)
paul718e3742002-12-13 20:15:29 +00001634{
1635 /* Initialize interface and new hook. */
1636 if_init ();
1637 if_add_hook (IF_NEW_HOOK, if_zebra_new_hook);
1638 if_add_hook (IF_DELETE_HOOK, if_zebra_delete_hook);
1639
1640 /* Install configuration write function. */
1641 install_node (&interface_node, if_config_write);
1642
1643 install_element (VIEW_NODE, &show_interface_cmd);
1644 install_element (ENABLE_NODE, &show_interface_cmd);
hassoed9bb6d2005-03-13 19:17:21 +00001645 install_element (ENABLE_NODE, &show_interface_desc_cmd);
paul718e3742002-12-13 20:15:29 +00001646 install_element (CONFIG_NODE, &zebra_interface_cmd);
paulbfc13532003-05-24 06:40:04 +00001647 install_element (CONFIG_NODE, &no_interface_cmd);
paul718e3742002-12-13 20:15:29 +00001648 install_default (INTERFACE_NODE);
1649 install_element (INTERFACE_NODE, &interface_desc_cmd);
1650 install_element (INTERFACE_NODE, &no_interface_desc_cmd);
1651 install_element (INTERFACE_NODE, &multicast_cmd);
1652 install_element (INTERFACE_NODE, &no_multicast_cmd);
paul2e3b2e42002-12-13 21:03:13 +00001653 install_element (INTERFACE_NODE, &linkdetect_cmd);
1654 install_element (INTERFACE_NODE, &no_linkdetect_cmd);
paul718e3742002-12-13 20:15:29 +00001655 install_element (INTERFACE_NODE, &shutdown_if_cmd);
1656 install_element (INTERFACE_NODE, &no_shutdown_if_cmd);
1657 install_element (INTERFACE_NODE, &bandwidth_if_cmd);
1658 install_element (INTERFACE_NODE, &no_bandwidth_if_cmd);
1659 install_element (INTERFACE_NODE, &no_bandwidth_if_val_cmd);
1660 install_element (INTERFACE_NODE, &ip_address_cmd);
1661 install_element (INTERFACE_NODE, &no_ip_address_cmd);
1662#ifdef HAVE_IPV6
1663 install_element (INTERFACE_NODE, &ipv6_address_cmd);
1664 install_element (INTERFACE_NODE, &no_ipv6_address_cmd);
1665#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +00001666#ifdef HAVE_NETLINK
paul718e3742002-12-13 20:15:29 +00001667 install_element (INTERFACE_NODE, &ip_address_label_cmd);
paul718e3742002-12-13 20:15:29 +00001668 install_element (INTERFACE_NODE, &no_ip_address_label_cmd);
paul718e3742002-12-13 20:15:29 +00001669#endif /* HAVE_NETLINK */
1670}