blob: 184b42a0a11ced8c340dd4541b1302fe21bb0981 [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{
paul718e3742002-12-13 20:15:29 +0000375 struct connected *ifc;
376 struct prefix *p;
hassoeef1fe12004-10-03 18:46:08 +0000377 struct route_node *rn;
378 struct zebra_if *zebra_if;
hassoeef1fe12004-10-03 18:46:08 +0000379
380 zebra_if = ifp->info;
paul718e3742002-12-13 20:15:29 +0000381
382 if (if_is_up(ifp))
383 {
384 zlog_err ("interface %s index %d is still up while being deleted.",
385 ifp->name, ifp->ifindex);
386 return;
387 }
388
389 /* Mark interface as inactive */
390 UNSET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE);
391
392 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +0000393 zlog_debug ("interface %s index %d is now inactive.",
paul718e3742002-12-13 20:15:29 +0000394 ifp->name, ifp->ifindex);
395
396 /* Delete connected routes from the kernel. */
397 if (ifp->connected)
398 {
Paul Jakmad9a18f12007-04-10 19:30:20 +0000399 struct listnode *node;
400 struct listnode *last = NULL;
401
hassoeef1fe12004-10-03 18:46:08 +0000402 while ((node = (last ? last->next : listhead (ifp->connected))))
paul718e3742002-12-13 20:15:29 +0000403 {
paul1eb8ef22005-04-07 07:30:20 +0000404 ifc = listgetdata (node);
paul718e3742002-12-13 20:15:29 +0000405 p = ifc->address;
hassoeef1fe12004-10-03 18:46:08 +0000406
Paul Jakmabeb56332006-05-11 13:28:05 +0000407 if (p->family == AF_INET
408 && (rn = route_node_lookup (zebra_if->ipv4_subnets, p)))
hassoeef1fe12004-10-03 18:46:08 +0000409 {
Paul Jakmad9a18f12007-04-10 19:30:20 +0000410 struct listnode *anode;
411 struct listnode *next;
412 struct listnode *first;
413 struct list *addr_list;
414
hassoeef1fe12004-10-03 18:46:08 +0000415 route_unlock_node (rn);
416 addr_list = (struct list *) rn->info;
417
418 /* Remove addresses, secondaries first. */
419 first = listhead (addr_list);
Paul Jakmad9a18f12007-04-10 19:30:20 +0000420 for (anode = first->next; anode || first; anode = next)
hassoeef1fe12004-10-03 18:46:08 +0000421 {
Paul Jakmad9a18f12007-04-10 19:30:20 +0000422 if (!anode)
hassoeef1fe12004-10-03 18:46:08 +0000423 {
Paul Jakmad9a18f12007-04-10 19:30:20 +0000424 anode = first;
hassoeef1fe12004-10-03 18:46:08 +0000425 first = NULL;
426 }
Paul Jakmad9a18f12007-04-10 19:30:20 +0000427 next = anode->next;
hassoeef1fe12004-10-03 18:46:08 +0000428
Paul Jakmad9a18f12007-04-10 19:30:20 +0000429 ifc = listgetdata (anode);
hassoeef1fe12004-10-03 18:46:08 +0000430 p = ifc->address;
431
432 connected_down_ipv4 (ifp, ifc);
433
434 zebra_interface_address_delete_update (ifp, ifc);
435
436 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
437
438 /* Remove from subnet chain. */
Paul Jakmad9a18f12007-04-10 19:30:20 +0000439 list_delete_node (addr_list, anode);
hassoeef1fe12004-10-03 18:46:08 +0000440 route_unlock_node (rn);
441
442 /* Remove from interface address list (unconditionally). */
Paul Jakmad9a18f12007-04-10 19:30:20 +0000443 if (!CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
444 {
445 listnode_delete (ifp->connected, ifc);
446 connected_free (ifc);
447 }
448 else
449 last = node;
hassoeef1fe12004-10-03 18:46:08 +0000450 }
451
452 /* Free chain list and respective route node. */
453 list_delete (addr_list);
454 rn->info = NULL;
455 route_unlock_node (rn);
456 }
paul718e3742002-12-13 20:15:29 +0000457#ifdef HAVE_IPV6
458 else if (p->family == AF_INET6)
hassoeef1fe12004-10-03 18:46:08 +0000459 {
460 connected_down_ipv6 (ifp, ifc);
paul718e3742002-12-13 20:15:29 +0000461
hassoeef1fe12004-10-03 18:46:08 +0000462 zebra_interface_address_delete_update (ifp, ifc);
paul718e3742002-12-13 20:15:29 +0000463
hassoeef1fe12004-10-03 18:46:08 +0000464 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
465
466 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
467 last = node;
468 else
469 {
470 listnode_delete (ifp->connected, ifc);
471 connected_free (ifc);
472 }
paul718e3742002-12-13 20:15:29 +0000473 }
hassoeef1fe12004-10-03 18:46:08 +0000474#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +0000475 }
476 }
477 zebra_interface_delete_update (ifp);
ajsd2fc8892005-04-02 18:38:43 +0000478
479 /* Update ifindex after distributing the delete message. This is in
480 case any client needs to have the old value of ifindex available
481 while processing the deletion. Each client daemon is responsible
482 for setting ifindex to IFINDEX_INTERNAL after processing the
483 interface deletion message. */
484 ifp->ifindex = IFINDEX_INTERNAL;
paul718e3742002-12-13 20:15:29 +0000485}
486
487/* Interface is up. */
488void
489if_up (struct interface *ifp)
490{
hasso52dc7ee2004-09-23 19:18:23 +0000491 struct listnode *node;
492 struct listnode *next;
paul718e3742002-12-13 20:15:29 +0000493 struct connected *ifc;
494 struct prefix *p;
495
496 /* Notify the protocol daemons. */
497 zebra_interface_up_update (ifp);
498
499 /* Install connected routes to the kernel. */
500 if (ifp->connected)
501 {
paul1eb8ef22005-04-07 07:30:20 +0000502 for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc))
paul718e3742002-12-13 20:15:29 +0000503 {
paul718e3742002-12-13 20:15:29 +0000504 p = ifc->address;
505
506 if (p->family == AF_INET)
507 connected_up_ipv4 (ifp, ifc);
508#ifdef HAVE_IPV6
509 else if (p->family == AF_INET6)
510 connected_up_ipv6 (ifp, ifc);
511#endif /* HAVE_IPV6 */
512 }
513 }
514
515 /* Examine all static routes. */
516 rib_update ();
517}
518
519/* Interface goes down. We have to manage different behavior of based
520 OS. */
521void
522if_down (struct interface *ifp)
523{
hasso52dc7ee2004-09-23 19:18:23 +0000524 struct listnode *node;
525 struct listnode *next;
paul718e3742002-12-13 20:15:29 +0000526 struct connected *ifc;
527 struct prefix *p;
528
529 /* Notify to the protocol daemons. */
530 zebra_interface_down_update (ifp);
531
532 /* Delete connected routes from the kernel. */
533 if (ifp->connected)
534 {
paul1eb8ef22005-04-07 07:30:20 +0000535 for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc))
paul718e3742002-12-13 20:15:29 +0000536 {
paul718e3742002-12-13 20:15:29 +0000537 p = ifc->address;
538
539 if (p->family == AF_INET)
540 connected_down_ipv4 (ifp, ifc);
541#ifdef HAVE_IPV6
542 else if (p->family == AF_INET6)
543 connected_down_ipv6 (ifp, ifc);
544#endif /* HAVE_IPV6 */
545 }
546 }
547
548 /* Examine all static routes which direct to the interface. */
549 rib_update ();
550}
551
552void
553if_refresh (struct interface *ifp)
554{
paul5c78b3d2006-01-25 04:31:40 +0000555 if_get_flags (ifp);
paul718e3742002-12-13 20:15:29 +0000556}
557
paul718e3742002-12-13 20:15:29 +0000558/* Output prefix string to vty. */
paula1ac18c2005-06-28 17:17:12 +0000559static int
paul718e3742002-12-13 20:15:29 +0000560prefix_vty_out (struct vty *vty, struct prefix *p)
561{
562 char str[INET6_ADDRSTRLEN];
563
564 inet_ntop (p->family, &p->u.prefix, str, sizeof (str));
565 vty_out (vty, "%s", str);
566 return strlen (str);
567}
568
569/* Dump if address information to vty. */
paula1ac18c2005-06-28 17:17:12 +0000570static void
paul718e3742002-12-13 20:15:29 +0000571connected_dump_vty (struct vty *vty, struct connected *connected)
572{
573 struct prefix *p;
paul718e3742002-12-13 20:15:29 +0000574
575 /* Print interface address. */
576 p = connected->address;
577 vty_out (vty, " %s ", prefix_family_str (p));
578 prefix_vty_out (vty, p);
579 vty_out (vty, "/%d", p->prefixlen);
580
581 /* If there is destination address, print it. */
Andrew J. Schorre4529632006-12-12 19:18:21 +0000582 if (connected->destination)
paul718e3742002-12-13 20:15:29 +0000583 {
Andrew J. Schorre4529632006-12-12 19:18:21 +0000584 vty_out (vty, (CONNECTED_PEER(connected) ? " peer " : " broadcast "));
585 prefix_vty_out (vty, connected->destination);
paul718e3742002-12-13 20:15:29 +0000586 }
587
588 if (CHECK_FLAG (connected->flags, ZEBRA_IFA_SECONDARY))
589 vty_out (vty, " secondary");
590
591 if (connected->label)
592 vty_out (vty, " %s", connected->label);
593
594 vty_out (vty, "%s", VTY_NEWLINE);
595}
596
597#ifdef RTADV
598/* Dump interface ND information to vty. */
paula1ac18c2005-06-28 17:17:12 +0000599static void
paul718e3742002-12-13 20:15:29 +0000600nd_dump_vty (struct vty *vty, struct interface *ifp)
601{
602 struct zebra_if *zif;
603 struct rtadvconf *rtadv;
vincent7cee1bb2005-03-25 13:08:53 +0000604 int interval;
paul718e3742002-12-13 20:15:29 +0000605
606 zif = (struct zebra_if *) ifp->info;
607 rtadv = &zif->rtadv;
608
609 if (rtadv->AdvSendAdvertisements)
610 {
611 vty_out (vty, " ND advertised reachable time is %d milliseconds%s",
612 rtadv->AdvReachableTime, VTY_NEWLINE);
613 vty_out (vty, " ND advertised retransmit interval is %d milliseconds%s",
614 rtadv->AdvRetransTimer, VTY_NEWLINE);
vincent7cee1bb2005-03-25 13:08:53 +0000615 interval = rtadv->MaxRtrAdvInterval;
616 if (interval % 1000)
617 vty_out (vty, " ND router advertisements are sent every "
618 "%d milliseconds%s", interval,
619 VTY_NEWLINE);
620 else
621 vty_out (vty, " ND router advertisements are sent every "
622 "%d seconds%s", interval / 1000,
623 VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000624 vty_out (vty, " ND router advertisements live for %d seconds%s",
625 rtadv->AdvDefaultLifetime, VTY_NEWLINE);
626 if (rtadv->AdvManagedFlag)
627 vty_out (vty, " Hosts use DHCP to obtain routable addresses.%s",
628 VTY_NEWLINE);
629 else
630 vty_out (vty, " Hosts use stateless autoconfig for addresses.%s",
631 VTY_NEWLINE);
vincent7cee1bb2005-03-25 13:08:53 +0000632 if (rtadv->AdvHomeAgentFlag)
633 vty_out (vty, " ND router advertisements with "
634 "Home Agent flag bit set.%s",
635 VTY_NEWLINE);
636 if (rtadv->AdvIntervalOption)
637 vty_out (vty, " ND router advertisements with Adv. Interval option.%s",
638 VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000639 }
640}
641#endif /* RTADV */
642
643/* Interface's information print out to vty interface. */
paula1ac18c2005-06-28 17:17:12 +0000644static void
paul718e3742002-12-13 20:15:29 +0000645if_dump_vty (struct vty *vty, struct interface *ifp)
646{
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000647#ifdef HAVE_STRUCT_SOCKADDR_DL
paul718e3742002-12-13 20:15:29 +0000648 struct sockaddr_dl *sdl;
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000649#endif /* HAVE_STRUCT_SOCKADDR_DL */
paul718e3742002-12-13 20:15:29 +0000650 struct connected *connected;
hasso52dc7ee2004-09-23 19:18:23 +0000651 struct listnode *node;
hassoeef1fe12004-10-03 18:46:08 +0000652 struct route_node *rn;
653 struct zebra_if *zebra_if;
654
655 zebra_if = ifp->info;
paul718e3742002-12-13 20:15:29 +0000656
paul2e3b2e42002-12-13 21:03:13 +0000657 vty_out (vty, "Interface %s is ", ifp->name);
658 if (if_is_up(ifp)) {
659 vty_out (vty, "up, line protocol ");
660
661 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) {
662 if (if_is_running(ifp))
663 vty_out (vty, "is up%s", VTY_NEWLINE);
664 else
665 vty_out (vty, "is down%s", VTY_NEWLINE);
666 } else {
667 vty_out (vty, "detection is disabled%s", VTY_NEWLINE);
668 }
669 } else {
670 vty_out (vty, "down%s", VTY_NEWLINE);
671 }
672
paul718e3742002-12-13 20:15:29 +0000673 if (ifp->desc)
674 vty_out (vty, " Description: %s%s", ifp->desc,
675 VTY_NEWLINE);
ajsd2fc8892005-04-02 18:38:43 +0000676 if (ifp->ifindex == IFINDEX_INTERNAL)
paul718e3742002-12-13 20:15:29 +0000677 {
ajsd2fc8892005-04-02 18:38:43 +0000678 vty_out(vty, " pseudo interface%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000679 return;
680 }
681 else if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
682 {
683 vty_out(vty, " index %d inactive interface%s",
684 ifp->ifindex,
685 VTY_NEWLINE);
686 return;
687 }
688
689 vty_out (vty, " index %d metric %d mtu %d ",
690 ifp->ifindex, ifp->metric, ifp->mtu);
paul44145db2004-05-09 11:00:23 +0000691#ifdef HAVE_IPV6
692 if (ifp->mtu6 != ifp->mtu)
693 vty_out (vty, "mtu6 %d ", ifp->mtu6);
694#endif
Paul Jakma630c97c2006-06-15 12:48:17 +0000695 vty_out (vty, "%s flags: %s%s", VTY_NEWLINE,
696 if_flag_dump (ifp->flags), VTY_NEWLINE);
paul3a570c82006-02-02 17:27:13 +0000697
paul718e3742002-12-13 20:15:29 +0000698 /* Hardware address. */
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000699#ifdef HAVE_STRUCT_SOCKADDR_DL
paul718e3742002-12-13 20:15:29 +0000700 sdl = &ifp->sdl;
701 if (sdl != NULL && sdl->sdl_alen != 0)
702 {
703 int i;
704 u_char *ptr;
705
706 vty_out (vty, " HWaddr: ");
paul5b73a672004-07-23 15:26:14 +0000707 for (i = 0, ptr = (u_char *)LLADDR (sdl); i < sdl->sdl_alen; i++, ptr++)
708 vty_out (vty, "%s%02x", i == 0 ? "" : ":", *ptr);
paul718e3742002-12-13 20:15:29 +0000709 vty_out (vty, "%s", VTY_NEWLINE);
710 }
711#else
712 if (ifp->hw_addr_len != 0)
713 {
714 int i;
715
716 vty_out (vty, " HWaddr: ");
717 for (i = 0; i < ifp->hw_addr_len; i++)
718 vty_out (vty, "%s%02x", i == 0 ? "" : ":", ifp->hw_addr[i]);
719 vty_out (vty, "%s", VTY_NEWLINE);
720 }
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000721#endif /* HAVE_STRUCT_SOCKADDR_DL */
paul718e3742002-12-13 20:15:29 +0000722
723 /* Bandwidth in kbps */
724 if (ifp->bandwidth != 0)
725 {
726 vty_out(vty, " bandwidth %u kbps", ifp->bandwidth);
727 vty_out(vty, "%s", VTY_NEWLINE);
728 }
729
hassoeef1fe12004-10-03 18:46:08 +0000730 for (rn = route_top (zebra_if->ipv4_subnets); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000731 {
hassoeef1fe12004-10-03 18:46:08 +0000732 if (! rn->info)
733 continue;
734
paul1eb8ef22005-04-07 07:30:20 +0000735 for (ALL_LIST_ELEMENTS_RO ((struct list *)rn->info, node, connected))
736 connected_dump_vty (vty, connected);
paul718e3742002-12-13 20:15:29 +0000737 }
738
paul1eb8ef22005-04-07 07:30:20 +0000739 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
hasso39db97e2004-10-12 20:50:58 +0000740 {
hasso39db97e2004-10-12 20:50:58 +0000741 if (CHECK_FLAG (connected->conf, ZEBRA_IFC_REAL) &&
742 (connected->address->family == AF_INET6))
743 connected_dump_vty (vty, connected);
744 }
745
paul718e3742002-12-13 20:15:29 +0000746#ifdef RTADV
747 nd_dump_vty (vty, ifp);
748#endif /* RTADV */
749
750#ifdef HAVE_PROC_NET_DEV
751 /* Statistics print out using proc file system. */
hasso6f2c27a2005-01-18 13:44:35 +0000752 vty_out (vty, " %lu input packets (%lu multicast), %lu bytes, "
753 "%lu dropped%s",
754 ifp->stats.rx_packets, ifp->stats.rx_multicast,
755 ifp->stats.rx_bytes, ifp->stats.rx_dropped, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000756
hasso6f2c27a2005-01-18 13:44:35 +0000757 vty_out (vty, " %lu input errors, %lu length, %lu overrun,"
hasso3452d472005-03-06 13:42:05 +0000758 " %lu CRC, %lu frame%s",
paul718e3742002-12-13 20:15:29 +0000759 ifp->stats.rx_errors, ifp->stats.rx_length_errors,
760 ifp->stats.rx_over_errors, ifp->stats.rx_crc_errors,
hasso6f2c27a2005-01-18 13:44:35 +0000761 ifp->stats.rx_frame_errors, VTY_NEWLINE);
762
763 vty_out (vty, " %lu fifo, %lu missed%s", ifp->stats.rx_fifo_errors,
paul718e3742002-12-13 20:15:29 +0000764 ifp->stats.rx_missed_errors, VTY_NEWLINE);
765
hasso6f2c27a2005-01-18 13:44:35 +0000766 vty_out (vty, " %lu output packets, %lu bytes, %lu dropped%s",
paul718e3742002-12-13 20:15:29 +0000767 ifp->stats.tx_packets, ifp->stats.tx_bytes,
768 ifp->stats.tx_dropped, VTY_NEWLINE);
769
hasso6f2c27a2005-01-18 13:44:35 +0000770 vty_out (vty, " %lu output errors, %lu aborted, %lu carrier,"
771 " %lu fifo, %lu heartbeat%s",
paul718e3742002-12-13 20:15:29 +0000772 ifp->stats.tx_errors, ifp->stats.tx_aborted_errors,
773 ifp->stats.tx_carrier_errors, ifp->stats.tx_fifo_errors,
hasso6f2c27a2005-01-18 13:44:35 +0000774 ifp->stats.tx_heartbeat_errors, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000775
hasso6f2c27a2005-01-18 13:44:35 +0000776 vty_out (vty, " %lu window, %lu collisions%s",
777 ifp->stats.tx_window_errors, ifp->stats.collisions, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000778#endif /* HAVE_PROC_NET_DEV */
779
780#ifdef HAVE_NET_RT_IFLIST
781#if defined (__bsdi__) || defined (__NetBSD__)
782 /* Statistics print out using sysctl (). */
783 vty_out (vty, " input packets %qu, bytes %qu, dropped %qu,"
784 " multicast packets %qu%s",
785 ifp->stats.ifi_ipackets, ifp->stats.ifi_ibytes,
786 ifp->stats.ifi_iqdrops, ifp->stats.ifi_imcasts,
787 VTY_NEWLINE);
788
789 vty_out (vty, " input errors %qu%s",
790 ifp->stats.ifi_ierrors, VTY_NEWLINE);
791
792 vty_out (vty, " output packets %qu, bytes %qu, multicast packets %qu%s",
793 ifp->stats.ifi_opackets, ifp->stats.ifi_obytes,
794 ifp->stats.ifi_omcasts, VTY_NEWLINE);
795
796 vty_out (vty, " output errors %qu%s",
797 ifp->stats.ifi_oerrors, VTY_NEWLINE);
798
799 vty_out (vty, " collisions %qu%s",
800 ifp->stats.ifi_collisions, VTY_NEWLINE);
801#else
802 /* Statistics print out using sysctl (). */
803 vty_out (vty, " input packets %lu, bytes %lu, dropped %lu,"
804 " multicast packets %lu%s",
805 ifp->stats.ifi_ipackets, ifp->stats.ifi_ibytes,
806 ifp->stats.ifi_iqdrops, ifp->stats.ifi_imcasts,
807 VTY_NEWLINE);
808
809 vty_out (vty, " input errors %lu%s",
810 ifp->stats.ifi_ierrors, VTY_NEWLINE);
811
812 vty_out (vty, " output packets %lu, bytes %lu, multicast packets %lu%s",
813 ifp->stats.ifi_opackets, ifp->stats.ifi_obytes,
814 ifp->stats.ifi_omcasts, VTY_NEWLINE);
815
816 vty_out (vty, " output errors %lu%s",
817 ifp->stats.ifi_oerrors, VTY_NEWLINE);
818
819 vty_out (vty, " collisions %lu%s",
820 ifp->stats.ifi_collisions, VTY_NEWLINE);
821#endif /* __bsdi__ || __NetBSD__ */
822#endif /* HAVE_NET_RT_IFLIST */
823}
824
825/* Check supported address family. */
paula1ac18c2005-06-28 17:17:12 +0000826static int
paul718e3742002-12-13 20:15:29 +0000827if_supported_family (int family)
828{
829 if (family == AF_INET)
830 return 1;
831#ifdef HAVE_IPV6
832 if (family == AF_INET6)
833 return 1;
834#endif /* HAVE_IPV6 */
835 return 0;
836}
837
838/* Wrapper hook point for zebra daemon so that ifindex can be set
839 * DEFUN macro not used as extract.pl HAS to ignore this
840 * See also interface_cmd in lib/if.c
841 */
842DEFUN_NOSH (zebra_interface,
843 zebra_interface_cmd,
844 "interface IFNAME",
845 "Select an interface to configure\n"
846 "Interface's name\n")
847{
848 int ret;
849 struct interface * ifp;
850
851 /* Call lib interface() */
ajsd2fc8892005-04-02 18:38:43 +0000852 if ((ret = interface_cmd.func (self, vty, argc, argv)) != CMD_SUCCESS)
853 return ret;
paul718e3742002-12-13 20:15:29 +0000854
855 ifp = vty->index;
856
ajsd2fc8892005-04-02 18:38:43 +0000857 if (ifp->ifindex == IFINDEX_INTERNAL)
858 /* Is this really necessary? Shouldn't status be initialized to 0
859 in that case? */
860 UNSET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE);
paul718e3742002-12-13 20:15:29 +0000861
862 return ret;
863}
864
paul718e3742002-12-13 20:15:29 +0000865struct cmd_node interface_node =
866{
867 INTERFACE_NODE,
868 "%s(config-if)# ",
869 1
870};
871
872/* Show all or specified interface to vty. */
873DEFUN (show_interface, show_interface_cmd,
874 "show interface [IFNAME]",
875 SHOW_STR
876 "Interface status and configuration\n"
877 "Inteface name\n")
878{
hasso52dc7ee2004-09-23 19:18:23 +0000879 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000880 struct interface *ifp;
881
882#ifdef HAVE_PROC_NET_DEV
883 /* If system has interface statistics via proc file system, update
884 statistics. */
885 ifstat_update_proc ();
886#endif /* HAVE_PROC_NET_DEV */
887#ifdef HAVE_NET_RT_IFLIST
888 ifstat_update_sysctl ();
889#endif /* HAVE_NET_RT_IFLIST */
890
891 /* Specified interface print. */
892 if (argc != 0)
893 {
894 ifp = if_lookup_by_name (argv[0]);
895 if (ifp == NULL)
896 {
897 vty_out (vty, "%% Can't find interface %s%s", argv[0],
898 VTY_NEWLINE);
899 return CMD_WARNING;
900 }
901 if_dump_vty (vty, ifp);
902 return CMD_SUCCESS;
903 }
904
905 /* All interface print. */
paul1eb8ef22005-04-07 07:30:20 +0000906 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
907 if_dump_vty (vty, ifp);
paul718e3742002-12-13 20:15:29 +0000908
909 return CMD_SUCCESS;
910}
911
hassoed9bb6d2005-03-13 19:17:21 +0000912DEFUN (show_interface_desc,
913 show_interface_desc_cmd,
914 "show interface description",
915 SHOW_STR
916 "Interface status and configuration\n"
917 "Interface description\n")
918{
919 struct listnode *node;
920 struct interface *ifp;
921
922 vty_out (vty, "Interface Status Protocol Description%s", VTY_NEWLINE);
paul1eb8ef22005-04-07 07:30:20 +0000923 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
hassoed9bb6d2005-03-13 19:17:21 +0000924 {
925 int len;
hassoed9bb6d2005-03-13 19:17:21 +0000926
927 len = vty_out (vty, "%s", ifp->name);
928 vty_out (vty, "%*s", (16 - len), " ");
929
930 if (if_is_up(ifp))
931 {
932 vty_out (vty, "up ");
933 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION))
934 {
935 if (if_is_running(ifp))
936 vty_out (vty, "up ");
937 else
938 vty_out (vty, "down ");
939 }
940 else
941 {
942 vty_out (vty, "unknown ");
943 }
944 }
945 else
946 {
947 vty_out (vty, "down down ");
948 }
949
950 if (ifp->desc)
951 vty_out (vty, "%s", ifp->desc);
952 vty_out (vty, "%s", VTY_NEWLINE);
953 }
954 return CMD_SUCCESS;
955}
956
paul718e3742002-12-13 20:15:29 +0000957DEFUN (multicast,
958 multicast_cmd,
959 "multicast",
960 "Set multicast flag to interface\n")
961{
962 int ret;
963 struct interface *ifp;
964 struct zebra_if *if_data;
965
966 ifp = (struct interface *) vty->index;
paul48b33aa2002-12-13 20:52:52 +0000967 if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
paul718e3742002-12-13 20:15:29 +0000968 {
paul48b33aa2002-12-13 20:52:52 +0000969 ret = if_set_flags (ifp, IFF_MULTICAST);
970 if (ret < 0)
971 {
972 vty_out (vty, "Can't set multicast flag%s", VTY_NEWLINE);
973 return CMD_WARNING;
974 }
975 if_refresh (ifp);
paul718e3742002-12-13 20:15:29 +0000976 }
paul718e3742002-12-13 20:15:29 +0000977 if_data = ifp->info;
978 if_data->multicast = IF_ZEBRA_MULTICAST_ON;
paul48b33aa2002-12-13 20:52:52 +0000979
paul718e3742002-12-13 20:15:29 +0000980 return CMD_SUCCESS;
981}
982
983DEFUN (no_multicast,
984 no_multicast_cmd,
985 "no multicast",
986 NO_STR
987 "Unset multicast flag to interface\n")
988{
989 int ret;
990 struct interface *ifp;
991 struct zebra_if *if_data;
992
993 ifp = (struct interface *) vty->index;
paul48b33aa2002-12-13 20:52:52 +0000994 if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
paul718e3742002-12-13 20:15:29 +0000995 {
paul48b33aa2002-12-13 20:52:52 +0000996 ret = if_unset_flags (ifp, IFF_MULTICAST);
997 if (ret < 0)
998 {
999 vty_out (vty, "Can't unset multicast flag%s", VTY_NEWLINE);
1000 return CMD_WARNING;
1001 }
1002 if_refresh (ifp);
paul718e3742002-12-13 20:15:29 +00001003 }
paul718e3742002-12-13 20:15:29 +00001004 if_data = ifp->info;
1005 if_data->multicast = IF_ZEBRA_MULTICAST_OFF;
1006
1007 return CMD_SUCCESS;
1008}
1009
paul2e3b2e42002-12-13 21:03:13 +00001010DEFUN (linkdetect,
1011 linkdetect_cmd,
1012 "link-detect",
1013 "Enable link detection on interface\n")
1014{
paul2e3b2e42002-12-13 21:03:13 +00001015 struct interface *ifp;
1016 int if_was_operative;
1017
1018 ifp = (struct interface *) vty->index;
1019 if_was_operative = if_is_operative(ifp);
1020 SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
1021
1022 /* When linkdetection is enabled, if might come down */
1023 if (!if_is_operative(ifp) && if_was_operative) if_down(ifp);
1024
1025 /* FIXME: Will defer status change forwarding if interface
1026 does not come down! */
1027
1028 return CMD_SUCCESS;
1029}
1030
1031
1032DEFUN (no_linkdetect,
1033 no_linkdetect_cmd,
1034 "no link-detect",
1035 NO_STR
1036 "Disable link detection on interface\n")
1037{
paul2e3b2e42002-12-13 21:03:13 +00001038 struct interface *ifp;
1039 int if_was_operative;
1040
1041 ifp = (struct interface *) vty->index;
1042 if_was_operative = if_is_operative(ifp);
1043 UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
1044
1045 /* Interface may come up after disabling link detection */
1046 if (if_is_operative(ifp) && !if_was_operative) if_up(ifp);
1047
1048 /* FIXME: see linkdetect_cmd */
1049
1050 return CMD_SUCCESS;
1051}
1052
paul718e3742002-12-13 20:15:29 +00001053DEFUN (shutdown_if,
1054 shutdown_if_cmd,
1055 "shutdown",
1056 "Shutdown the selected interface\n")
1057{
1058 int ret;
1059 struct interface *ifp;
1060 struct zebra_if *if_data;
1061
1062 ifp = (struct interface *) vty->index;
1063 ret = if_unset_flags (ifp, IFF_UP);
1064 if (ret < 0)
1065 {
1066 vty_out (vty, "Can't shutdown interface%s", VTY_NEWLINE);
1067 return CMD_WARNING;
1068 }
1069 if_refresh (ifp);
1070 if_data = ifp->info;
1071 if_data->shutdown = IF_ZEBRA_SHUTDOWN_ON;
1072
1073 return CMD_SUCCESS;
1074}
1075
1076DEFUN (no_shutdown_if,
1077 no_shutdown_if_cmd,
1078 "no shutdown",
1079 NO_STR
1080 "Shutdown the selected interface\n")
1081{
1082 int ret;
1083 struct interface *ifp;
1084 struct zebra_if *if_data;
1085
1086 ifp = (struct interface *) vty->index;
1087 ret = if_set_flags (ifp, IFF_UP | IFF_RUNNING);
1088 if (ret < 0)
1089 {
1090 vty_out (vty, "Can't up interface%s", VTY_NEWLINE);
1091 return CMD_WARNING;
1092 }
1093 if_refresh (ifp);
1094 if_data = ifp->info;
1095 if_data->shutdown = IF_ZEBRA_SHUTDOWN_OFF;
1096
1097 return CMD_SUCCESS;
1098}
1099
1100DEFUN (bandwidth_if,
1101 bandwidth_if_cmd,
1102 "bandwidth <1-10000000>",
1103 "Set bandwidth informational parameter\n"
1104 "Bandwidth in kilobits\n")
1105{
1106 struct interface *ifp;
1107 unsigned int bandwidth;
1108
1109 ifp = (struct interface *) vty->index;
1110 bandwidth = strtol(argv[0], NULL, 10);
1111
1112 /* bandwidth range is <1-10000000> */
1113 if (bandwidth < 1 || bandwidth > 10000000)
1114 {
1115 vty_out (vty, "Bandwidth is invalid%s", VTY_NEWLINE);
1116 return CMD_WARNING;
1117 }
1118
1119 ifp->bandwidth = bandwidth;
1120
1121 /* force protocols to recalculate routes due to cost change */
paul2e3b2e42002-12-13 21:03:13 +00001122 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00001123 zebra_interface_up_update (ifp);
1124
1125 return CMD_SUCCESS;
1126}
1127
1128DEFUN (no_bandwidth_if,
1129 no_bandwidth_if_cmd,
1130 "no bandwidth",
1131 NO_STR
1132 "Set bandwidth informational parameter\n")
1133{
1134 struct interface *ifp;
1135
1136 ifp = (struct interface *) vty->index;
1137
1138 ifp->bandwidth = 0;
1139
1140 /* force protocols to recalculate routes due to cost change */
paul2e3b2e42002-12-13 21:03:13 +00001141 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00001142 zebra_interface_up_update (ifp);
1143
1144 return CMD_SUCCESS;
1145}
1146
1147ALIAS (no_bandwidth_if,
1148 no_bandwidth_if_val_cmd,
1149 "no bandwidth <1-10000000>",
1150 NO_STR
1151 "Set bandwidth informational parameter\n"
1152 "Bandwidth in kilobits\n")
1153
paula1ac18c2005-06-28 17:17:12 +00001154static int
hasso39db97e2004-10-12 20:50:58 +00001155ip_address_install (struct vty *vty, struct interface *ifp,
1156 const char *addr_str, const char *peer_str,
1157 const char *label)
paul718e3742002-12-13 20:15:29 +00001158{
1159 struct prefix_ipv4 cp;
1160 struct connected *ifc;
1161 struct prefix_ipv4 *p;
paul718e3742002-12-13 20:15:29 +00001162 int ret;
1163
1164 ret = str2prefix_ipv4 (addr_str, &cp);
1165 if (ret <= 0)
1166 {
1167 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1168 return CMD_WARNING;
1169 }
1170
paulca162182005-09-12 16:58:52 +00001171 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001172 if (! ifc)
1173 {
1174 ifc = connected_new ();
1175 ifc->ifp = ifp;
1176
1177 /* Address. */
1178 p = prefix_ipv4_new ();
1179 *p = cp;
1180 ifc->address = (struct prefix *) p;
1181
1182 /* Broadcast. */
hasso3fb9cd62004-10-19 19:44:43 +00001183 if (p->prefixlen <= IPV4_MAX_PREFIXLEN-2)
paul718e3742002-12-13 20:15:29 +00001184 {
1185 p = prefix_ipv4_new ();
1186 *p = cp;
hasso3fb9cd62004-10-19 19:44:43 +00001187 p->prefix.s_addr = ipv4_broadcast_addr(p->prefix.s_addr,p->prefixlen);
paul718e3742002-12-13 20:15:29 +00001188 ifc->destination = (struct prefix *) p;
1189 }
1190
paul718e3742002-12-13 20:15:29 +00001191 /* Label. */
1192 if (label)
paul0752ef02005-11-03 12:35:21 +00001193 ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
paul718e3742002-12-13 20:15:29 +00001194
1195 /* Add to linked list. */
1196 listnode_add (ifp->connected, ifc);
1197 }
1198
1199 /* This address is configured from zebra. */
1200 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1201 SET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED);
1202
1203 /* In case of this route need to install kernel. */
1204 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1205 && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1206 {
1207 /* Some system need to up the interface to set IP address. */
1208 if (! if_is_up (ifp))
1209 {
1210 if_set_flags (ifp, IFF_UP | IFF_RUNNING);
1211 if_refresh (ifp);
1212 }
1213
1214 ret = if_set_prefix (ifp, ifc);
1215 if (ret < 0)
1216 {
1217 vty_out (vty, "%% Can't set interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001218 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001219 return CMD_WARNING;
1220 }
1221
hassoeef1fe12004-10-03 18:46:08 +00001222 /* Add to subnet chain list (while marking secondary attribute). */
1223 if_subnet_add (ifp, ifc);
1224
paul718e3742002-12-13 20:15:29 +00001225 /* IP address propery set. */
1226 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
1227
1228 /* Update interface address information to protocol daemon. */
1229 zebra_interface_address_add_update (ifp, ifc);
1230
1231 /* If interface is up register connected route. */
paul2e3b2e42002-12-13 21:03:13 +00001232 if (if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001233 connected_up_ipv4 (ifp, ifc);
1234 }
1235
1236 return CMD_SUCCESS;
1237}
1238
paula1ac18c2005-06-28 17:17:12 +00001239static int
hasso39db97e2004-10-12 20:50:58 +00001240ip_address_uninstall (struct vty *vty, struct interface *ifp,
1241 const char *addr_str, const char *peer_str,
1242 const char *label)
paul718e3742002-12-13 20:15:29 +00001243{
1244 struct prefix_ipv4 cp;
1245 struct connected *ifc;
1246 int ret;
1247
1248 /* Convert to prefix structure. */
1249 ret = str2prefix_ipv4 (addr_str, &cp);
1250 if (ret <= 0)
1251 {
1252 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1253 return CMD_WARNING;
1254 }
1255
1256 /* Check current interface address. */
paulca162182005-09-12 16:58:52 +00001257 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001258 if (! ifc)
1259 {
1260 vty_out (vty, "%% Can't find address%s", VTY_NEWLINE);
1261 return CMD_WARNING;
1262 }
1263
1264 /* This is not configured address. */
1265 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1266 return CMD_WARNING;
1267
Paul Jakma74ecdc92006-06-15 18:10:47 +00001268 UNSET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED);
1269
paul718e3742002-12-13 20:15:29 +00001270 /* This is not real address or interface is not active. */
1271 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1272 || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1273 {
1274 listnode_delete (ifp->connected, ifc);
1275 connected_free (ifc);
1276 return CMD_WARNING;
1277 }
1278
1279 /* This is real route. */
1280 ret = if_unset_prefix (ifp, ifc);
1281 if (ret < 0)
1282 {
1283 vty_out (vty, "%% Can't unset interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001284 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001285 return CMD_WARNING;
1286 }
1287
hassoeef1fe12004-10-03 18:46:08 +00001288#if 0
paul718e3742002-12-13 20:15:29 +00001289 /* Redistribute this information. */
1290 zebra_interface_address_delete_update (ifp, ifc);
1291
1292 /* Remove connected route. */
1293 connected_down_ipv4 (ifp, ifc);
1294
1295 /* Free address information. */
1296 listnode_delete (ifp->connected, ifc);
1297 connected_free (ifc);
hassoeef1fe12004-10-03 18:46:08 +00001298#endif
paul718e3742002-12-13 20:15:29 +00001299
1300 return CMD_SUCCESS;
1301}
1302
1303DEFUN (ip_address,
1304 ip_address_cmd,
1305 "ip address A.B.C.D/M",
1306 "Interface Internet Protocol config commands\n"
1307 "Set the IP address of an interface\n"
1308 "IP address (e.g. 10.0.0.1/8)\n")
1309{
hassoeef1fe12004-10-03 18:46:08 +00001310 return ip_address_install (vty, vty->index, argv[0], NULL, NULL);
paul718e3742002-12-13 20:15:29 +00001311}
1312
1313DEFUN (no_ip_address,
1314 no_ip_address_cmd,
1315 "no ip address A.B.C.D/M",
1316 NO_STR
1317 "Interface Internet Protocol config commands\n"
1318 "Set the IP address of an interface\n"
1319 "IP Address (e.g. 10.0.0.1/8)")
1320{
hassoeef1fe12004-10-03 18:46:08 +00001321 return ip_address_uninstall (vty, vty->index, argv[0], NULL, NULL);
paul718e3742002-12-13 20:15:29 +00001322}
1323
1324#ifdef HAVE_NETLINK
paul718e3742002-12-13 20:15:29 +00001325DEFUN (ip_address_label,
1326 ip_address_label_cmd,
1327 "ip address A.B.C.D/M label LINE",
1328 "Interface Internet Protocol config commands\n"
1329 "Set the IP address of an interface\n"
1330 "IP address (e.g. 10.0.0.1/8)\n"
1331 "Label of this address\n"
1332 "Label\n")
1333{
hassoeef1fe12004-10-03 18:46:08 +00001334 return ip_address_install (vty, vty->index, argv[0], NULL, argv[1]);
paul718e3742002-12-13 20:15:29 +00001335}
1336
1337DEFUN (no_ip_address_label,
1338 no_ip_address_label_cmd,
1339 "no ip address A.B.C.D/M label LINE",
1340 NO_STR
1341 "Interface Internet Protocol config commands\n"
1342 "Set the IP address of an interface\n"
1343 "IP address (e.g. 10.0.0.1/8)\n"
1344 "Label of this address\n"
1345 "Label\n")
1346{
hassoeef1fe12004-10-03 18:46:08 +00001347 return ip_address_uninstall (vty, vty->index, argv[0], NULL, argv[1]);
paul718e3742002-12-13 20:15:29 +00001348}
1349#endif /* HAVE_NETLINK */
1350
1351#ifdef HAVE_IPV6
paula1ac18c2005-06-28 17:17:12 +00001352static int
hasso39db97e2004-10-12 20:50:58 +00001353ipv6_address_install (struct vty *vty, struct interface *ifp,
1354 const char *addr_str, const char *peer_str,
1355 const char *label, int secondary)
paul718e3742002-12-13 20:15:29 +00001356{
1357 struct prefix_ipv6 cp;
1358 struct connected *ifc;
1359 struct prefix_ipv6 *p;
1360 int ret;
1361
1362 ret = str2prefix_ipv6 (addr_str, &cp);
1363 if (ret <= 0)
1364 {
1365 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1366 return CMD_WARNING;
1367 }
1368
paulca162182005-09-12 16:58:52 +00001369 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001370 if (! ifc)
1371 {
1372 ifc = connected_new ();
1373 ifc->ifp = ifp;
1374
1375 /* Address. */
1376 p = prefix_ipv6_new ();
1377 *p = cp;
1378 ifc->address = (struct prefix *) p;
1379
1380 /* Secondary. */
1381 if (secondary)
1382 SET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY);
1383
1384 /* Label. */
1385 if (label)
paul0752ef02005-11-03 12:35:21 +00001386 ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
paul718e3742002-12-13 20:15:29 +00001387
1388 /* Add to linked list. */
1389 listnode_add (ifp->connected, ifc);
1390 }
1391
1392 /* This address is configured from zebra. */
1393 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1394 SET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED);
1395
1396 /* In case of this route need to install kernel. */
1397 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1398 && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1399 {
1400 /* Some system need to up the interface to set IP address. */
1401 if (! if_is_up (ifp))
1402 {
1403 if_set_flags (ifp, IFF_UP | IFF_RUNNING);
1404 if_refresh (ifp);
1405 }
1406
1407 ret = if_prefix_add_ipv6 (ifp, ifc);
1408
1409 if (ret < 0)
1410 {
1411 vty_out (vty, "%% Can't set interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001412 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001413 return CMD_WARNING;
1414 }
1415
1416 /* IP address propery set. */
1417 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
1418
1419 /* Update interface address information to protocol daemon. */
1420 zebra_interface_address_add_update (ifp, ifc);
1421
1422 /* If interface is up register connected route. */
paul2e3b2e42002-12-13 21:03:13 +00001423 if (if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001424 connected_up_ipv6 (ifp, ifc);
1425 }
1426
1427 return CMD_SUCCESS;
1428}
1429
paula1ac18c2005-06-28 17:17:12 +00001430static int
hasso39db97e2004-10-12 20:50:58 +00001431ipv6_address_uninstall (struct vty *vty, struct interface *ifp,
1432 const char *addr_str, const char *peer_str,
1433 const char *label, int secondry)
paul718e3742002-12-13 20:15:29 +00001434{
1435 struct prefix_ipv6 cp;
1436 struct connected *ifc;
1437 int ret;
1438
1439 /* Convert to prefix structure. */
1440 ret = str2prefix_ipv6 (addr_str, &cp);
1441 if (ret <= 0)
1442 {
1443 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1444 return CMD_WARNING;
1445 }
1446
1447 /* Check current interface address. */
paulca162182005-09-12 16:58:52 +00001448 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001449 if (! ifc)
1450 {
1451 vty_out (vty, "%% Can't find address%s", VTY_NEWLINE);
1452 return CMD_WARNING;
1453 }
1454
1455 /* This is not configured address. */
1456 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1457 return CMD_WARNING;
1458
1459 /* This is not real address or interface is not active. */
1460 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1461 || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1462 {
1463 listnode_delete (ifp->connected, ifc);
1464 connected_free (ifc);
1465 return CMD_WARNING;
1466 }
1467
1468 /* This is real route. */
1469 ret = if_prefix_delete_ipv6 (ifp, ifc);
1470 if (ret < 0)
1471 {
1472 vty_out (vty, "%% Can't unset interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001473 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001474 return CMD_WARNING;
1475 }
1476
1477 /* Redistribute this information. */
1478 zebra_interface_address_delete_update (ifp, ifc);
1479
1480 /* Remove connected route. */
1481 connected_down_ipv6 (ifp, ifc);
1482
1483 /* Free address information. */
1484 listnode_delete (ifp->connected, ifc);
1485 connected_free (ifc);
1486
1487 return CMD_SUCCESS;
1488}
1489
1490DEFUN (ipv6_address,
1491 ipv6_address_cmd,
1492 "ipv6 address X:X::X:X/M",
hassoe23949c2004-03-11 15:54:02 +00001493 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001494 "Set the IP address of an interface\n"
1495 "IPv6 address (e.g. 3ffe:506::1/48)\n")
1496{
1497 return ipv6_address_install (vty, vty->index, argv[0], NULL, NULL, 0);
1498}
1499
1500DEFUN (no_ipv6_address,
1501 no_ipv6_address_cmd,
1502 "no ipv6 address X:X::X:X/M",
1503 NO_STR
hassoe23949c2004-03-11 15:54:02 +00001504 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001505 "Set the IP address of an interface\n"
1506 "IPv6 address (e.g. 3ffe:506::1/48)\n")
1507{
1508 return ipv6_address_uninstall (vty, vty->index, argv[0], NULL, NULL, 0);
1509}
1510#endif /* HAVE_IPV6 */
1511
paula1ac18c2005-06-28 17:17:12 +00001512static int
paul718e3742002-12-13 20:15:29 +00001513if_config_write (struct vty *vty)
1514{
hasso52dc7ee2004-09-23 19:18:23 +00001515 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001516 struct interface *ifp;
1517 char buf[BUFSIZ];
1518
paul1eb8ef22005-04-07 07:30:20 +00001519 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00001520 {
1521 struct zebra_if *if_data;
hasso52dc7ee2004-09-23 19:18:23 +00001522 struct listnode *addrnode;
paul718e3742002-12-13 20:15:29 +00001523 struct connected *ifc;
1524 struct prefix *p;
1525
paul718e3742002-12-13 20:15:29 +00001526 if_data = ifp->info;
1527
1528 vty_out (vty, "interface %s%s", ifp->name,
1529 VTY_NEWLINE);
1530
1531 if (ifp->desc)
1532 vty_out (vty, " description %s%s", ifp->desc,
1533 VTY_NEWLINE);
1534
1535 /* Assign bandwidth here to avoid unnecessary interface flap
1536 while processing config script */
1537 if (ifp->bandwidth != 0)
1538 vty_out(vty, " bandwidth %u%s", ifp->bandwidth, VTY_NEWLINE);
1539
paul2e3b2e42002-12-13 21:03:13 +00001540 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION))
1541 vty_out(vty, " link-detect%s", VTY_NEWLINE);
1542
paul1eb8ef22005-04-07 07:30:20 +00001543 for (ALL_LIST_ELEMENTS_RO (ifp->connected, addrnode, ifc))
paul718e3742002-12-13 20:15:29 +00001544 {
paul718e3742002-12-13 20:15:29 +00001545 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1546 {
1547 p = ifc->address;
1548 vty_out (vty, " ip%s address %s/%d",
1549 p->family == AF_INET ? "" : "v6",
1550 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
1551 p->prefixlen);
1552
paul718e3742002-12-13 20:15:29 +00001553 if (ifc->label)
1554 vty_out (vty, " label %s", ifc->label);
1555
1556 vty_out (vty, "%s", VTY_NEWLINE);
1557 }
1558 }
1559
1560 if (if_data)
1561 {
1562 if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)
1563 vty_out (vty, " shutdown%s", VTY_NEWLINE);
1564
1565 if (if_data->multicast != IF_ZEBRA_MULTICAST_UNSPEC)
1566 vty_out (vty, " %smulticast%s",
1567 if_data->multicast == IF_ZEBRA_MULTICAST_ON ? "" : "no ",
1568 VTY_NEWLINE);
1569 }
1570
1571#ifdef RTADV
1572 rtadv_config_write (vty, ifp);
1573#endif /* RTADV */
1574
hassoca776982004-06-12 14:33:05 +00001575#ifdef HAVE_IRDP
1576 irdp_config_write (vty, ifp);
1577#endif /* IRDP */
1578
paul718e3742002-12-13 20:15:29 +00001579 vty_out (vty, "!%s", VTY_NEWLINE);
1580 }
1581 return 0;
1582}
1583
1584/* Allocate and initialize interface vector. */
1585void
paula1ac18c2005-06-28 17:17:12 +00001586zebra_if_init (void)
paul718e3742002-12-13 20:15:29 +00001587{
1588 /* Initialize interface and new hook. */
1589 if_init ();
1590 if_add_hook (IF_NEW_HOOK, if_zebra_new_hook);
1591 if_add_hook (IF_DELETE_HOOK, if_zebra_delete_hook);
1592
1593 /* Install configuration write function. */
1594 install_node (&interface_node, if_config_write);
1595
1596 install_element (VIEW_NODE, &show_interface_cmd);
1597 install_element (ENABLE_NODE, &show_interface_cmd);
hassoed9bb6d2005-03-13 19:17:21 +00001598 install_element (ENABLE_NODE, &show_interface_desc_cmd);
paul718e3742002-12-13 20:15:29 +00001599 install_element (CONFIG_NODE, &zebra_interface_cmd);
paulbfc13532003-05-24 06:40:04 +00001600 install_element (CONFIG_NODE, &no_interface_cmd);
paul718e3742002-12-13 20:15:29 +00001601 install_default (INTERFACE_NODE);
1602 install_element (INTERFACE_NODE, &interface_desc_cmd);
1603 install_element (INTERFACE_NODE, &no_interface_desc_cmd);
1604 install_element (INTERFACE_NODE, &multicast_cmd);
1605 install_element (INTERFACE_NODE, &no_multicast_cmd);
paul2e3b2e42002-12-13 21:03:13 +00001606 install_element (INTERFACE_NODE, &linkdetect_cmd);
1607 install_element (INTERFACE_NODE, &no_linkdetect_cmd);
paul718e3742002-12-13 20:15:29 +00001608 install_element (INTERFACE_NODE, &shutdown_if_cmd);
1609 install_element (INTERFACE_NODE, &no_shutdown_if_cmd);
1610 install_element (INTERFACE_NODE, &bandwidth_if_cmd);
1611 install_element (INTERFACE_NODE, &no_bandwidth_if_cmd);
1612 install_element (INTERFACE_NODE, &no_bandwidth_if_val_cmd);
1613 install_element (INTERFACE_NODE, &ip_address_cmd);
1614 install_element (INTERFACE_NODE, &no_ip_address_cmd);
1615#ifdef HAVE_IPV6
1616 install_element (INTERFACE_NODE, &ipv6_address_cmd);
1617 install_element (INTERFACE_NODE, &no_ipv6_address_cmd);
1618#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +00001619#ifdef HAVE_NETLINK
paul718e3742002-12-13 20:15:29 +00001620 install_element (INTERFACE_NODE, &ip_address_label_cmd);
paul718e3742002-12-13 20:15:29 +00001621 install_element (INTERFACE_NODE, &no_ip_address_label_cmd);
paul718e3742002-12-13 20:15:29 +00001622#endif /* HAVE_NETLINK */
1623}