blob: 49fffcf5de8dade19ec021a17d6172d8ebb27be2 [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
190/* Wake up configured address if it is not in current kernel
191 address. */
paula1ac18c2005-06-28 17:17:12 +0000192static void
paul718e3742002-12-13 20:15:29 +0000193if_addr_wakeup (struct interface *ifp)
194{
paul1eb8ef22005-04-07 07:30:20 +0000195 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000196 struct connected *ifc;
197 struct prefix *p;
198 int ret;
199
paul1eb8ef22005-04-07 07:30:20 +0000200 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, ifc))
paul718e3742002-12-13 20:15:29 +0000201 {
paul718e3742002-12-13 20:15:29 +0000202 p = ifc->address;
203
204 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)
205 && ! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
206 {
207 /* Address check. */
208 if (p->family == AF_INET)
209 {
210 if (! if_is_up (ifp))
211 {
212 if_set_flags (ifp, IFF_UP | IFF_RUNNING);
213 if_refresh (ifp);
214 }
215
216 ret = if_set_prefix (ifp, ifc);
217 if (ret < 0)
218 {
219 zlog_warn ("Can't set interface's address: %s",
ajs6099b3b2004-11-20 02:06:59 +0000220 safe_strerror(errno));
paul718e3742002-12-13 20:15:29 +0000221 continue;
222 }
hassoeef1fe12004-10-03 18:46:08 +0000223
224 /* Add to subnet chain list. */
225 if_subnet_add (ifp, ifc);
226
paul718e3742002-12-13 20:15:29 +0000227 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
228
229 zebra_interface_address_add_update (ifp, ifc);
230
paul2e3b2e42002-12-13 21:03:13 +0000231 if (if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000232 connected_up_ipv4 (ifp, ifc);
233 }
234#ifdef HAVE_IPV6
235 if (p->family == AF_INET6)
236 {
237 if (! if_is_up (ifp))
238 {
239 if_set_flags (ifp, IFF_UP | IFF_RUNNING);
240 if_refresh (ifp);
241 }
242
243 ret = if_prefix_add_ipv6 (ifp, ifc);
244 if (ret < 0)
245 {
246 zlog_warn ("Can't set interface's address: %s",
ajs6099b3b2004-11-20 02:06:59 +0000247 safe_strerror(errno));
paul718e3742002-12-13 20:15:29 +0000248 continue;
249 }
250 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
251
252 zebra_interface_address_add_update (ifp, ifc);
253
paul2e3b2e42002-12-13 21:03:13 +0000254 if (if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000255 connected_up_ipv6 (ifp, ifc);
256 }
257#endif /* HAVE_IPV6 */
258 }
259 }
260}
261
262/* Handle interface addition */
263void
264if_add_update (struct interface *ifp)
265{
paul48b33aa2002-12-13 20:52:52 +0000266 struct zebra_if *if_data;
267
268 if_data = ifp->info;
269 if (if_data->multicast == IF_ZEBRA_MULTICAST_ON)
270 if_set_flags (ifp, IFF_MULTICAST);
271 else if (if_data->multicast == IF_ZEBRA_MULTICAST_OFF)
272 if_unset_flags (ifp, IFF_MULTICAST);
273
paul718e3742002-12-13 20:15:29 +0000274 zebra_interface_add_update (ifp);
275
276 if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
277 {
278 SET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE);
279
280 if_addr_wakeup (ifp);
281
282 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +0000283 zlog_debug ("interface %s index %d becomes active.",
284 ifp->name, ifp->ifindex);
paul718e3742002-12-13 20:15:29 +0000285 }
286 else
287 {
288 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +0000289 zlog_debug ("interface %s index %d is added.", ifp->name, ifp->ifindex);
paul718e3742002-12-13 20:15:29 +0000290 }
291}
292
paul6eb88272005-07-29 14:36:00 +0000293/* Handle an interface delete event */
paul718e3742002-12-13 20:15:29 +0000294void
295if_delete_update (struct interface *ifp)
296{
297 struct listnode *node;
298 struct listnode *next;
hassoeef1fe12004-10-03 18:46:08 +0000299 struct listnode *first;
300 struct listnode *last;
paul718e3742002-12-13 20:15:29 +0000301 struct connected *ifc;
302 struct prefix *p;
hassoeef1fe12004-10-03 18:46:08 +0000303 struct route_node *rn;
304 struct zebra_if *zebra_if;
305 struct list *addr_list;
306
307 zebra_if = ifp->info;
paul718e3742002-12-13 20:15:29 +0000308
309 if (if_is_up(ifp))
310 {
311 zlog_err ("interface %s index %d is still up while being deleted.",
312 ifp->name, ifp->ifindex);
313 return;
314 }
315
316 /* Mark interface as inactive */
317 UNSET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE);
318
319 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +0000320 zlog_debug ("interface %s index %d is now inactive.",
paul718e3742002-12-13 20:15:29 +0000321 ifp->name, ifp->ifindex);
322
323 /* Delete connected routes from the kernel. */
324 if (ifp->connected)
325 {
hassoeef1fe12004-10-03 18:46:08 +0000326 last = NULL;
327 while ((node = (last ? last->next : listhead (ifp->connected))))
paul718e3742002-12-13 20:15:29 +0000328 {
paul1eb8ef22005-04-07 07:30:20 +0000329 ifc = listgetdata (node);
paul718e3742002-12-13 20:15:29 +0000330 p = ifc->address;
hassoeef1fe12004-10-03 18:46:08 +0000331
paul718e3742002-12-13 20:15:29 +0000332 if (p->family == AF_INET)
hassoeef1fe12004-10-03 18:46:08 +0000333 {
334 rn = route_node_lookup (zebra_if->ipv4_subnets, p);
335 route_unlock_node (rn);
336 addr_list = (struct list *) rn->info;
337
338 /* Remove addresses, secondaries first. */
339 first = listhead (addr_list);
340 for (node = first->next; node || first; node = next)
341 {
342 if (! node)
343 {
344 node = first;
345 first = NULL;
346 }
347 next = node->next;
348
paul1eb8ef22005-04-07 07:30:20 +0000349 ifc = listgetdata (node);
hassoeef1fe12004-10-03 18:46:08 +0000350 p = ifc->address;
351
352 connected_down_ipv4 (ifp, ifc);
353
354 zebra_interface_address_delete_update (ifp, ifc);
355
356 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
357
358 /* Remove from subnet chain. */
359 list_delete_node (addr_list, node);
360 route_unlock_node (rn);
361
362 /* Remove from interface address list (unconditionally). */
363 listnode_delete (ifp->connected, ifc);
364 connected_free (ifc);
365 }
366
367 /* Free chain list and respective route node. */
368 list_delete (addr_list);
369 rn->info = NULL;
370 route_unlock_node (rn);
371 }
paul718e3742002-12-13 20:15:29 +0000372#ifdef HAVE_IPV6
373 else if (p->family == AF_INET6)
hassoeef1fe12004-10-03 18:46:08 +0000374 {
375 connected_down_ipv6 (ifp, ifc);
paul718e3742002-12-13 20:15:29 +0000376
hassoeef1fe12004-10-03 18:46:08 +0000377 zebra_interface_address_delete_update (ifp, ifc);
paul718e3742002-12-13 20:15:29 +0000378
hassoeef1fe12004-10-03 18:46:08 +0000379 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
380
381 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
382 last = node;
383 else
384 {
385 listnode_delete (ifp->connected, ifc);
386 connected_free (ifc);
387 }
paul718e3742002-12-13 20:15:29 +0000388 }
hassoeef1fe12004-10-03 18:46:08 +0000389#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +0000390 }
391 }
392 zebra_interface_delete_update (ifp);
ajsd2fc8892005-04-02 18:38:43 +0000393
394 /* Update ifindex after distributing the delete message. This is in
395 case any client needs to have the old value of ifindex available
396 while processing the deletion. Each client daemon is responsible
397 for setting ifindex to IFINDEX_INTERNAL after processing the
398 interface deletion message. */
399 ifp->ifindex = IFINDEX_INTERNAL;
paul718e3742002-12-13 20:15:29 +0000400}
401
402/* Interface is up. */
403void
404if_up (struct interface *ifp)
405{
hasso52dc7ee2004-09-23 19:18:23 +0000406 struct listnode *node;
407 struct listnode *next;
paul718e3742002-12-13 20:15:29 +0000408 struct connected *ifc;
409 struct prefix *p;
410
411 /* Notify the protocol daemons. */
412 zebra_interface_up_update (ifp);
413
414 /* Install connected routes to the kernel. */
415 if (ifp->connected)
416 {
paul1eb8ef22005-04-07 07:30:20 +0000417 for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc))
paul718e3742002-12-13 20:15:29 +0000418 {
paul718e3742002-12-13 20:15:29 +0000419 p = ifc->address;
420
421 if (p->family == AF_INET)
422 connected_up_ipv4 (ifp, ifc);
423#ifdef HAVE_IPV6
424 else if (p->family == AF_INET6)
425 connected_up_ipv6 (ifp, ifc);
426#endif /* HAVE_IPV6 */
427 }
428 }
429
430 /* Examine all static routes. */
431 rib_update ();
432}
433
434/* Interface goes down. We have to manage different behavior of based
435 OS. */
436void
437if_down (struct interface *ifp)
438{
hasso52dc7ee2004-09-23 19:18:23 +0000439 struct listnode *node;
440 struct listnode *next;
paul718e3742002-12-13 20:15:29 +0000441 struct connected *ifc;
442 struct prefix *p;
443
444 /* Notify to the protocol daemons. */
445 zebra_interface_down_update (ifp);
446
447 /* Delete connected routes from the kernel. */
448 if (ifp->connected)
449 {
paul1eb8ef22005-04-07 07:30:20 +0000450 for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc))
paul718e3742002-12-13 20:15:29 +0000451 {
paul718e3742002-12-13 20:15:29 +0000452 p = ifc->address;
453
454 if (p->family == AF_INET)
455 connected_down_ipv4 (ifp, ifc);
456#ifdef HAVE_IPV6
457 else if (p->family == AF_INET6)
458 connected_down_ipv6 (ifp, ifc);
459#endif /* HAVE_IPV6 */
460 }
461 }
462
463 /* Examine all static routes which direct to the interface. */
464 rib_update ();
465}
466
467void
468if_refresh (struct interface *ifp)
469{
paul2e3b2e42002-12-13 21:03:13 +0000470 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000471 {
472 if_get_flags (ifp);
paul2e3b2e42002-12-13 21:03:13 +0000473 if (! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000474 if_down (ifp);
475 }
476 else
477 {
478 if_get_flags (ifp);
paul2e3b2e42002-12-13 21:03:13 +0000479 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000480 if_up (ifp);
481 }
482}
483
484/* Printout flag information into vty */
paula1ac18c2005-06-28 17:17:12 +0000485static void
paul718e3742002-12-13 20:15:29 +0000486if_flag_dump_vty (struct vty *vty, unsigned long flag)
487{
488 int separator = 0;
489
490#define IFF_OUT_VTY(X, Y) \
491 if ((X) && (flag & (X))) \
492 { \
493 if (separator) \
494 vty_out (vty, ","); \
495 else \
496 separator = 1; \
497 vty_out (vty, Y); \
498 }
499
500 vty_out (vty, "<");
501 IFF_OUT_VTY (IFF_UP, "UP");
502 IFF_OUT_VTY (IFF_BROADCAST, "BROADCAST");
503 IFF_OUT_VTY (IFF_DEBUG, "DEBUG");
504 IFF_OUT_VTY (IFF_LOOPBACK, "LOOPBACK");
505 IFF_OUT_VTY (IFF_POINTOPOINT, "POINTOPOINT");
506 IFF_OUT_VTY (IFF_NOTRAILERS, "NOTRAILERS");
507 IFF_OUT_VTY (IFF_RUNNING, "RUNNING");
508 IFF_OUT_VTY (IFF_NOARP, "NOARP");
509 IFF_OUT_VTY (IFF_PROMISC, "PROMISC");
510 IFF_OUT_VTY (IFF_ALLMULTI, "ALLMULTI");
511 IFF_OUT_VTY (IFF_OACTIVE, "OACTIVE");
512 IFF_OUT_VTY (IFF_SIMPLEX, "SIMPLEX");
513 IFF_OUT_VTY (IFF_LINK0, "LINK0");
514 IFF_OUT_VTY (IFF_LINK1, "LINK1");
515 IFF_OUT_VTY (IFF_LINK2, "LINK2");
516 IFF_OUT_VTY (IFF_MULTICAST, "MULTICAST");
paul44145db2004-05-09 11:00:23 +0000517#ifdef SOLARIS_IPV6
518 IFF_OUT_VTY (IFF_IPV4, "IFF_IPv4");
519 IFF_OUT_VTY (IFF_IPV6, "IFF_IPv6");
520#endif /* SOLARIS_IPV6 */
paul718e3742002-12-13 20:15:29 +0000521 vty_out (vty, ">");
522}
523
524/* Output prefix string to vty. */
paula1ac18c2005-06-28 17:17:12 +0000525static int
paul718e3742002-12-13 20:15:29 +0000526prefix_vty_out (struct vty *vty, struct prefix *p)
527{
528 char str[INET6_ADDRSTRLEN];
529
530 inet_ntop (p->family, &p->u.prefix, str, sizeof (str));
531 vty_out (vty, "%s", str);
532 return strlen (str);
533}
534
535/* Dump if address information to vty. */
paula1ac18c2005-06-28 17:17:12 +0000536static void
paul718e3742002-12-13 20:15:29 +0000537connected_dump_vty (struct vty *vty, struct connected *connected)
538{
539 struct prefix *p;
540 struct interface *ifp;
541
542 /* Set interface pointer. */
543 ifp = connected->ifp;
544
545 /* Print interface address. */
546 p = connected->address;
547 vty_out (vty, " %s ", prefix_family_str (p));
548 prefix_vty_out (vty, p);
549 vty_out (vty, "/%d", p->prefixlen);
550
551 /* If there is destination address, print it. */
552 p = connected->destination;
553 if (p)
554 {
555 if (p->family == AF_INET)
556 if (ifp->flags & IFF_BROADCAST)
557 {
558 vty_out (vty, " broadcast ");
559 prefix_vty_out (vty, p);
560 }
561
562 if (ifp->flags & IFF_POINTOPOINT)
563 {
564 vty_out (vty, " pointopoint ");
565 prefix_vty_out (vty, p);
566 }
567 }
568
569 if (CHECK_FLAG (connected->flags, ZEBRA_IFA_SECONDARY))
570 vty_out (vty, " secondary");
571
572 if (connected->label)
573 vty_out (vty, " %s", connected->label);
574
575 vty_out (vty, "%s", VTY_NEWLINE);
576}
577
578#ifdef RTADV
579/* Dump interface ND information to vty. */
paula1ac18c2005-06-28 17:17:12 +0000580static void
paul718e3742002-12-13 20:15:29 +0000581nd_dump_vty (struct vty *vty, struct interface *ifp)
582{
583 struct zebra_if *zif;
584 struct rtadvconf *rtadv;
vincent7cee1bb2005-03-25 13:08:53 +0000585 int interval;
paul718e3742002-12-13 20:15:29 +0000586
587 zif = (struct zebra_if *) ifp->info;
588 rtadv = &zif->rtadv;
589
590 if (rtadv->AdvSendAdvertisements)
591 {
592 vty_out (vty, " ND advertised reachable time is %d milliseconds%s",
593 rtadv->AdvReachableTime, VTY_NEWLINE);
594 vty_out (vty, " ND advertised retransmit interval is %d milliseconds%s",
595 rtadv->AdvRetransTimer, VTY_NEWLINE);
vincent7cee1bb2005-03-25 13:08:53 +0000596 interval = rtadv->MaxRtrAdvInterval;
597 if (interval % 1000)
598 vty_out (vty, " ND router advertisements are sent every "
599 "%d milliseconds%s", interval,
600 VTY_NEWLINE);
601 else
602 vty_out (vty, " ND router advertisements are sent every "
603 "%d seconds%s", interval / 1000,
604 VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000605 vty_out (vty, " ND router advertisements live for %d seconds%s",
606 rtadv->AdvDefaultLifetime, VTY_NEWLINE);
607 if (rtadv->AdvManagedFlag)
608 vty_out (vty, " Hosts use DHCP to obtain routable addresses.%s",
609 VTY_NEWLINE);
610 else
611 vty_out (vty, " Hosts use stateless autoconfig for addresses.%s",
612 VTY_NEWLINE);
vincent7cee1bb2005-03-25 13:08:53 +0000613 if (rtadv->AdvHomeAgentFlag)
614 vty_out (vty, " ND router advertisements with "
615 "Home Agent flag bit set.%s",
616 VTY_NEWLINE);
617 if (rtadv->AdvIntervalOption)
618 vty_out (vty, " ND router advertisements with Adv. Interval option.%s",
619 VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000620 }
621}
622#endif /* RTADV */
623
624/* Interface's information print out to vty interface. */
paula1ac18c2005-06-28 17:17:12 +0000625static void
paul718e3742002-12-13 20:15:29 +0000626if_dump_vty (struct vty *vty, struct interface *ifp)
627{
628#ifdef HAVE_SOCKADDR_DL
629 struct sockaddr_dl *sdl;
630#endif /* HAVE_SOCKADDR_DL */
631 struct connected *connected;
hasso52dc7ee2004-09-23 19:18:23 +0000632 struct listnode *node;
hassoeef1fe12004-10-03 18:46:08 +0000633 struct route_node *rn;
634 struct zebra_if *zebra_if;
635
636 zebra_if = ifp->info;
paul718e3742002-12-13 20:15:29 +0000637
paul2e3b2e42002-12-13 21:03:13 +0000638 vty_out (vty, "Interface %s is ", ifp->name);
639 if (if_is_up(ifp)) {
640 vty_out (vty, "up, line protocol ");
641
642 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) {
643 if (if_is_running(ifp))
644 vty_out (vty, "is up%s", VTY_NEWLINE);
645 else
646 vty_out (vty, "is down%s", VTY_NEWLINE);
647 } else {
648 vty_out (vty, "detection is disabled%s", VTY_NEWLINE);
649 }
650 } else {
651 vty_out (vty, "down%s", VTY_NEWLINE);
652 }
653
paul718e3742002-12-13 20:15:29 +0000654 if (ifp->desc)
655 vty_out (vty, " Description: %s%s", ifp->desc,
656 VTY_NEWLINE);
ajsd2fc8892005-04-02 18:38:43 +0000657 if (ifp->ifindex == IFINDEX_INTERNAL)
paul718e3742002-12-13 20:15:29 +0000658 {
ajsd2fc8892005-04-02 18:38:43 +0000659 vty_out(vty, " pseudo interface%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000660 return;
661 }
662 else if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
663 {
664 vty_out(vty, " index %d inactive interface%s",
665 ifp->ifindex,
666 VTY_NEWLINE);
667 return;
668 }
669
670 vty_out (vty, " index %d metric %d mtu %d ",
671 ifp->ifindex, ifp->metric, ifp->mtu);
672 if_flag_dump_vty (vty, ifp->flags);
paul44145db2004-05-09 11:00:23 +0000673#ifdef HAVE_IPV6
674 if (ifp->mtu6 != ifp->mtu)
675 vty_out (vty, "mtu6 %d ", ifp->mtu6);
676#endif
677
paul718e3742002-12-13 20:15:29 +0000678 vty_out (vty, "%s", VTY_NEWLINE);
679
680 /* Hardware address. */
681#ifdef HAVE_SOCKADDR_DL
682 sdl = &ifp->sdl;
683 if (sdl != NULL && sdl->sdl_alen != 0)
684 {
685 int i;
686 u_char *ptr;
687
688 vty_out (vty, " HWaddr: ");
paul5b73a672004-07-23 15:26:14 +0000689 for (i = 0, ptr = (u_char *)LLADDR (sdl); i < sdl->sdl_alen; i++, ptr++)
690 vty_out (vty, "%s%02x", i == 0 ? "" : ":", *ptr);
paul718e3742002-12-13 20:15:29 +0000691 vty_out (vty, "%s", VTY_NEWLINE);
692 }
693#else
694 if (ifp->hw_addr_len != 0)
695 {
696 int i;
697
698 vty_out (vty, " HWaddr: ");
699 for (i = 0; i < ifp->hw_addr_len; i++)
700 vty_out (vty, "%s%02x", i == 0 ? "" : ":", ifp->hw_addr[i]);
701 vty_out (vty, "%s", VTY_NEWLINE);
702 }
703#endif /* HAVE_SOCKADDR_DL */
704
705 /* Bandwidth in kbps */
706 if (ifp->bandwidth != 0)
707 {
708 vty_out(vty, " bandwidth %u kbps", ifp->bandwidth);
709 vty_out(vty, "%s", VTY_NEWLINE);
710 }
711
hassoeef1fe12004-10-03 18:46:08 +0000712 for (rn = route_top (zebra_if->ipv4_subnets); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000713 {
hassoeef1fe12004-10-03 18:46:08 +0000714 if (! rn->info)
715 continue;
716
paul1eb8ef22005-04-07 07:30:20 +0000717 for (ALL_LIST_ELEMENTS_RO ((struct list *)rn->info, node, connected))
718 connected_dump_vty (vty, connected);
paul718e3742002-12-13 20:15:29 +0000719 }
720
paul1eb8ef22005-04-07 07:30:20 +0000721 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
hasso39db97e2004-10-12 20:50:58 +0000722 {
hasso39db97e2004-10-12 20:50:58 +0000723 if (CHECK_FLAG (connected->conf, ZEBRA_IFC_REAL) &&
724 (connected->address->family == AF_INET6))
725 connected_dump_vty (vty, connected);
726 }
727
paul718e3742002-12-13 20:15:29 +0000728#ifdef RTADV
729 nd_dump_vty (vty, ifp);
730#endif /* RTADV */
731
732#ifdef HAVE_PROC_NET_DEV
733 /* Statistics print out using proc file system. */
hasso6f2c27a2005-01-18 13:44:35 +0000734 vty_out (vty, " %lu input packets (%lu multicast), %lu bytes, "
735 "%lu dropped%s",
736 ifp->stats.rx_packets, ifp->stats.rx_multicast,
737 ifp->stats.rx_bytes, ifp->stats.rx_dropped, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000738
hasso6f2c27a2005-01-18 13:44:35 +0000739 vty_out (vty, " %lu input errors, %lu length, %lu overrun,"
hasso3452d472005-03-06 13:42:05 +0000740 " %lu CRC, %lu frame%s",
paul718e3742002-12-13 20:15:29 +0000741 ifp->stats.rx_errors, ifp->stats.rx_length_errors,
742 ifp->stats.rx_over_errors, ifp->stats.rx_crc_errors,
hasso6f2c27a2005-01-18 13:44:35 +0000743 ifp->stats.rx_frame_errors, VTY_NEWLINE);
744
745 vty_out (vty, " %lu fifo, %lu missed%s", ifp->stats.rx_fifo_errors,
paul718e3742002-12-13 20:15:29 +0000746 ifp->stats.rx_missed_errors, VTY_NEWLINE);
747
hasso6f2c27a2005-01-18 13:44:35 +0000748 vty_out (vty, " %lu output packets, %lu bytes, %lu dropped%s",
paul718e3742002-12-13 20:15:29 +0000749 ifp->stats.tx_packets, ifp->stats.tx_bytes,
750 ifp->stats.tx_dropped, VTY_NEWLINE);
751
hasso6f2c27a2005-01-18 13:44:35 +0000752 vty_out (vty, " %lu output errors, %lu aborted, %lu carrier,"
753 " %lu fifo, %lu heartbeat%s",
paul718e3742002-12-13 20:15:29 +0000754 ifp->stats.tx_errors, ifp->stats.tx_aborted_errors,
755 ifp->stats.tx_carrier_errors, ifp->stats.tx_fifo_errors,
hasso6f2c27a2005-01-18 13:44:35 +0000756 ifp->stats.tx_heartbeat_errors, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000757
hasso6f2c27a2005-01-18 13:44:35 +0000758 vty_out (vty, " %lu window, %lu collisions%s",
759 ifp->stats.tx_window_errors, ifp->stats.collisions, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000760#endif /* HAVE_PROC_NET_DEV */
761
762#ifdef HAVE_NET_RT_IFLIST
763#if defined (__bsdi__) || defined (__NetBSD__)
764 /* Statistics print out using sysctl (). */
765 vty_out (vty, " input packets %qu, bytes %qu, dropped %qu,"
766 " multicast packets %qu%s",
767 ifp->stats.ifi_ipackets, ifp->stats.ifi_ibytes,
768 ifp->stats.ifi_iqdrops, ifp->stats.ifi_imcasts,
769 VTY_NEWLINE);
770
771 vty_out (vty, " input errors %qu%s",
772 ifp->stats.ifi_ierrors, VTY_NEWLINE);
773
774 vty_out (vty, " output packets %qu, bytes %qu, multicast packets %qu%s",
775 ifp->stats.ifi_opackets, ifp->stats.ifi_obytes,
776 ifp->stats.ifi_omcasts, VTY_NEWLINE);
777
778 vty_out (vty, " output errors %qu%s",
779 ifp->stats.ifi_oerrors, VTY_NEWLINE);
780
781 vty_out (vty, " collisions %qu%s",
782 ifp->stats.ifi_collisions, VTY_NEWLINE);
783#else
784 /* Statistics print out using sysctl (). */
785 vty_out (vty, " input packets %lu, bytes %lu, dropped %lu,"
786 " multicast packets %lu%s",
787 ifp->stats.ifi_ipackets, ifp->stats.ifi_ibytes,
788 ifp->stats.ifi_iqdrops, ifp->stats.ifi_imcasts,
789 VTY_NEWLINE);
790
791 vty_out (vty, " input errors %lu%s",
792 ifp->stats.ifi_ierrors, VTY_NEWLINE);
793
794 vty_out (vty, " output packets %lu, bytes %lu, multicast packets %lu%s",
795 ifp->stats.ifi_opackets, ifp->stats.ifi_obytes,
796 ifp->stats.ifi_omcasts, VTY_NEWLINE);
797
798 vty_out (vty, " output errors %lu%s",
799 ifp->stats.ifi_oerrors, VTY_NEWLINE);
800
801 vty_out (vty, " collisions %lu%s",
802 ifp->stats.ifi_collisions, VTY_NEWLINE);
803#endif /* __bsdi__ || __NetBSD__ */
804#endif /* HAVE_NET_RT_IFLIST */
805}
806
807/* Check supported address family. */
paula1ac18c2005-06-28 17:17:12 +0000808static int
paul718e3742002-12-13 20:15:29 +0000809if_supported_family (int family)
810{
811 if (family == AF_INET)
812 return 1;
813#ifdef HAVE_IPV6
814 if (family == AF_INET6)
815 return 1;
816#endif /* HAVE_IPV6 */
817 return 0;
818}
819
820/* Wrapper hook point for zebra daemon so that ifindex can be set
821 * DEFUN macro not used as extract.pl HAS to ignore this
822 * See also interface_cmd in lib/if.c
823 */
824DEFUN_NOSH (zebra_interface,
825 zebra_interface_cmd,
826 "interface IFNAME",
827 "Select an interface to configure\n"
828 "Interface's name\n")
829{
830 int ret;
831 struct interface * ifp;
832
833 /* Call lib interface() */
ajsd2fc8892005-04-02 18:38:43 +0000834 if ((ret = interface_cmd.func (self, vty, argc, argv)) != CMD_SUCCESS)
835 return ret;
paul718e3742002-12-13 20:15:29 +0000836
837 ifp = vty->index;
838
ajsd2fc8892005-04-02 18:38:43 +0000839 if (ifp->ifindex == IFINDEX_INTERNAL)
840 /* Is this really necessary? Shouldn't status be initialized to 0
841 in that case? */
842 UNSET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE);
paul718e3742002-12-13 20:15:29 +0000843
844 return ret;
845}
846
paul718e3742002-12-13 20:15:29 +0000847struct cmd_node interface_node =
848{
849 INTERFACE_NODE,
850 "%s(config-if)# ",
851 1
852};
853
854/* Show all or specified interface to vty. */
855DEFUN (show_interface, show_interface_cmd,
856 "show interface [IFNAME]",
857 SHOW_STR
858 "Interface status and configuration\n"
859 "Inteface name\n")
860{
hasso52dc7ee2004-09-23 19:18:23 +0000861 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000862 struct interface *ifp;
863
864#ifdef HAVE_PROC_NET_DEV
865 /* If system has interface statistics via proc file system, update
866 statistics. */
867 ifstat_update_proc ();
868#endif /* HAVE_PROC_NET_DEV */
869#ifdef HAVE_NET_RT_IFLIST
870 ifstat_update_sysctl ();
871#endif /* HAVE_NET_RT_IFLIST */
872
873 /* Specified interface print. */
874 if (argc != 0)
875 {
876 ifp = if_lookup_by_name (argv[0]);
877 if (ifp == NULL)
878 {
879 vty_out (vty, "%% Can't find interface %s%s", argv[0],
880 VTY_NEWLINE);
881 return CMD_WARNING;
882 }
883 if_dump_vty (vty, ifp);
884 return CMD_SUCCESS;
885 }
886
887 /* All interface print. */
paul1eb8ef22005-04-07 07:30:20 +0000888 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
889 if_dump_vty (vty, ifp);
paul718e3742002-12-13 20:15:29 +0000890
891 return CMD_SUCCESS;
892}
893
hassoed9bb6d2005-03-13 19:17:21 +0000894DEFUN (show_interface_desc,
895 show_interface_desc_cmd,
896 "show interface description",
897 SHOW_STR
898 "Interface status and configuration\n"
899 "Interface description\n")
900{
901 struct listnode *node;
902 struct interface *ifp;
903
904 vty_out (vty, "Interface Status Protocol Description%s", VTY_NEWLINE);
paul1eb8ef22005-04-07 07:30:20 +0000905 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
hassoed9bb6d2005-03-13 19:17:21 +0000906 {
907 int len;
hassoed9bb6d2005-03-13 19:17:21 +0000908
909 len = vty_out (vty, "%s", ifp->name);
910 vty_out (vty, "%*s", (16 - len), " ");
911
912 if (if_is_up(ifp))
913 {
914 vty_out (vty, "up ");
915 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION))
916 {
917 if (if_is_running(ifp))
918 vty_out (vty, "up ");
919 else
920 vty_out (vty, "down ");
921 }
922 else
923 {
924 vty_out (vty, "unknown ");
925 }
926 }
927 else
928 {
929 vty_out (vty, "down down ");
930 }
931
932 if (ifp->desc)
933 vty_out (vty, "%s", ifp->desc);
934 vty_out (vty, "%s", VTY_NEWLINE);
935 }
936 return CMD_SUCCESS;
937}
938
paul718e3742002-12-13 20:15:29 +0000939DEFUN (multicast,
940 multicast_cmd,
941 "multicast",
942 "Set multicast flag to interface\n")
943{
944 int ret;
945 struct interface *ifp;
946 struct zebra_if *if_data;
947
948 ifp = (struct interface *) vty->index;
paul48b33aa2002-12-13 20:52:52 +0000949 if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
paul718e3742002-12-13 20:15:29 +0000950 {
paul48b33aa2002-12-13 20:52:52 +0000951 ret = if_set_flags (ifp, IFF_MULTICAST);
952 if (ret < 0)
953 {
954 vty_out (vty, "Can't set multicast flag%s", VTY_NEWLINE);
955 return CMD_WARNING;
956 }
957 if_refresh (ifp);
paul718e3742002-12-13 20:15:29 +0000958 }
paul718e3742002-12-13 20:15:29 +0000959 if_data = ifp->info;
960 if_data->multicast = IF_ZEBRA_MULTICAST_ON;
paul48b33aa2002-12-13 20:52:52 +0000961
paul718e3742002-12-13 20:15:29 +0000962 return CMD_SUCCESS;
963}
964
965DEFUN (no_multicast,
966 no_multicast_cmd,
967 "no multicast",
968 NO_STR
969 "Unset multicast flag to interface\n")
970{
971 int ret;
972 struct interface *ifp;
973 struct zebra_if *if_data;
974
975 ifp = (struct interface *) vty->index;
paul48b33aa2002-12-13 20:52:52 +0000976 if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
paul718e3742002-12-13 20:15:29 +0000977 {
paul48b33aa2002-12-13 20:52:52 +0000978 ret = if_unset_flags (ifp, IFF_MULTICAST);
979 if (ret < 0)
980 {
981 vty_out (vty, "Can't unset multicast flag%s", VTY_NEWLINE);
982 return CMD_WARNING;
983 }
984 if_refresh (ifp);
paul718e3742002-12-13 20:15:29 +0000985 }
paul718e3742002-12-13 20:15:29 +0000986 if_data = ifp->info;
987 if_data->multicast = IF_ZEBRA_MULTICAST_OFF;
988
989 return CMD_SUCCESS;
990}
991
paul2e3b2e42002-12-13 21:03:13 +0000992DEFUN (linkdetect,
993 linkdetect_cmd,
994 "link-detect",
995 "Enable link detection on interface\n")
996{
paul2e3b2e42002-12-13 21:03:13 +0000997 struct interface *ifp;
998 int if_was_operative;
999
1000 ifp = (struct interface *) vty->index;
1001 if_was_operative = if_is_operative(ifp);
1002 SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
1003
1004 /* When linkdetection is enabled, if might come down */
1005 if (!if_is_operative(ifp) && if_was_operative) if_down(ifp);
1006
1007 /* FIXME: Will defer status change forwarding if interface
1008 does not come down! */
1009
1010 return CMD_SUCCESS;
1011}
1012
1013
1014DEFUN (no_linkdetect,
1015 no_linkdetect_cmd,
1016 "no link-detect",
1017 NO_STR
1018 "Disable link detection on interface\n")
1019{
paul2e3b2e42002-12-13 21:03:13 +00001020 struct interface *ifp;
1021 int if_was_operative;
1022
1023 ifp = (struct interface *) vty->index;
1024 if_was_operative = if_is_operative(ifp);
1025 UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
1026
1027 /* Interface may come up after disabling link detection */
1028 if (if_is_operative(ifp) && !if_was_operative) if_up(ifp);
1029
1030 /* FIXME: see linkdetect_cmd */
1031
1032 return CMD_SUCCESS;
1033}
1034
paul718e3742002-12-13 20:15:29 +00001035DEFUN (shutdown_if,
1036 shutdown_if_cmd,
1037 "shutdown",
1038 "Shutdown the selected interface\n")
1039{
1040 int ret;
1041 struct interface *ifp;
1042 struct zebra_if *if_data;
1043
1044 ifp = (struct interface *) vty->index;
1045 ret = if_unset_flags (ifp, IFF_UP);
1046 if (ret < 0)
1047 {
1048 vty_out (vty, "Can't shutdown interface%s", VTY_NEWLINE);
1049 return CMD_WARNING;
1050 }
1051 if_refresh (ifp);
1052 if_data = ifp->info;
1053 if_data->shutdown = IF_ZEBRA_SHUTDOWN_ON;
1054
1055 return CMD_SUCCESS;
1056}
1057
1058DEFUN (no_shutdown_if,
1059 no_shutdown_if_cmd,
1060 "no shutdown",
1061 NO_STR
1062 "Shutdown the selected interface\n")
1063{
1064 int ret;
1065 struct interface *ifp;
1066 struct zebra_if *if_data;
1067
1068 ifp = (struct interface *) vty->index;
1069 ret = if_set_flags (ifp, IFF_UP | IFF_RUNNING);
1070 if (ret < 0)
1071 {
1072 vty_out (vty, "Can't up interface%s", VTY_NEWLINE);
1073 return CMD_WARNING;
1074 }
1075 if_refresh (ifp);
1076 if_data = ifp->info;
1077 if_data->shutdown = IF_ZEBRA_SHUTDOWN_OFF;
1078
1079 return CMD_SUCCESS;
1080}
1081
1082DEFUN (bandwidth_if,
1083 bandwidth_if_cmd,
1084 "bandwidth <1-10000000>",
1085 "Set bandwidth informational parameter\n"
1086 "Bandwidth in kilobits\n")
1087{
1088 struct interface *ifp;
1089 unsigned int bandwidth;
1090
1091 ifp = (struct interface *) vty->index;
1092 bandwidth = strtol(argv[0], NULL, 10);
1093
1094 /* bandwidth range is <1-10000000> */
1095 if (bandwidth < 1 || bandwidth > 10000000)
1096 {
1097 vty_out (vty, "Bandwidth is invalid%s", VTY_NEWLINE);
1098 return CMD_WARNING;
1099 }
1100
1101 ifp->bandwidth = bandwidth;
1102
1103 /* force protocols to recalculate routes due to cost change */
paul2e3b2e42002-12-13 21:03:13 +00001104 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00001105 zebra_interface_up_update (ifp);
1106
1107 return CMD_SUCCESS;
1108}
1109
1110DEFUN (no_bandwidth_if,
1111 no_bandwidth_if_cmd,
1112 "no bandwidth",
1113 NO_STR
1114 "Set bandwidth informational parameter\n")
1115{
1116 struct interface *ifp;
1117
1118 ifp = (struct interface *) vty->index;
1119
1120 ifp->bandwidth = 0;
1121
1122 /* force protocols to recalculate routes due to cost change */
paul2e3b2e42002-12-13 21:03:13 +00001123 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00001124 zebra_interface_up_update (ifp);
1125
1126 return CMD_SUCCESS;
1127}
1128
1129ALIAS (no_bandwidth_if,
1130 no_bandwidth_if_val_cmd,
1131 "no bandwidth <1-10000000>",
1132 NO_STR
1133 "Set bandwidth informational parameter\n"
1134 "Bandwidth in kilobits\n")
1135
paula1ac18c2005-06-28 17:17:12 +00001136static int
hasso39db97e2004-10-12 20:50:58 +00001137ip_address_install (struct vty *vty, struct interface *ifp,
1138 const char *addr_str, const char *peer_str,
1139 const char *label)
paul718e3742002-12-13 20:15:29 +00001140{
1141 struct prefix_ipv4 cp;
1142 struct connected *ifc;
1143 struct prefix_ipv4 *p;
paul718e3742002-12-13 20:15:29 +00001144 int ret;
1145
1146 ret = str2prefix_ipv4 (addr_str, &cp);
1147 if (ret <= 0)
1148 {
1149 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1150 return CMD_WARNING;
1151 }
1152
paulca162182005-09-12 16:58:52 +00001153 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001154 if (! ifc)
1155 {
1156 ifc = connected_new ();
1157 ifc->ifp = ifp;
1158
1159 /* Address. */
1160 p = prefix_ipv4_new ();
1161 *p = cp;
1162 ifc->address = (struct prefix *) p;
1163
1164 /* Broadcast. */
hasso3fb9cd62004-10-19 19:44:43 +00001165 if (p->prefixlen <= IPV4_MAX_PREFIXLEN-2)
paul718e3742002-12-13 20:15:29 +00001166 {
1167 p = prefix_ipv4_new ();
1168 *p = cp;
hasso3fb9cd62004-10-19 19:44:43 +00001169 p->prefix.s_addr = ipv4_broadcast_addr(p->prefix.s_addr,p->prefixlen);
paul718e3742002-12-13 20:15:29 +00001170 ifc->destination = (struct prefix *) p;
1171 }
1172
paul718e3742002-12-13 20:15:29 +00001173 /* Label. */
1174 if (label)
1175 ifc->label = strdup (label);
1176
1177 /* Add to linked list. */
1178 listnode_add (ifp->connected, ifc);
1179 }
1180
1181 /* This address is configured from zebra. */
1182 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1183 SET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED);
1184
1185 /* In case of this route need to install kernel. */
1186 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1187 && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1188 {
1189 /* Some system need to up the interface to set IP address. */
1190 if (! if_is_up (ifp))
1191 {
1192 if_set_flags (ifp, IFF_UP | IFF_RUNNING);
1193 if_refresh (ifp);
1194 }
1195
1196 ret = if_set_prefix (ifp, ifc);
1197 if (ret < 0)
1198 {
1199 vty_out (vty, "%% Can't set interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001200 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001201 return CMD_WARNING;
1202 }
1203
hassoeef1fe12004-10-03 18:46:08 +00001204 /* Add to subnet chain list (while marking secondary attribute). */
1205 if_subnet_add (ifp, ifc);
1206
paul718e3742002-12-13 20:15:29 +00001207 /* IP address propery set. */
1208 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
1209
1210 /* Update interface address information to protocol daemon. */
1211 zebra_interface_address_add_update (ifp, ifc);
1212
1213 /* If interface is up register connected route. */
paul2e3b2e42002-12-13 21:03:13 +00001214 if (if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001215 connected_up_ipv4 (ifp, ifc);
1216 }
1217
1218 return CMD_SUCCESS;
1219}
1220
paula1ac18c2005-06-28 17:17:12 +00001221static int
hasso39db97e2004-10-12 20:50:58 +00001222ip_address_uninstall (struct vty *vty, struct interface *ifp,
1223 const char *addr_str, const char *peer_str,
1224 const char *label)
paul718e3742002-12-13 20:15:29 +00001225{
1226 struct prefix_ipv4 cp;
1227 struct connected *ifc;
1228 int ret;
1229
1230 /* Convert to prefix structure. */
1231 ret = str2prefix_ipv4 (addr_str, &cp);
1232 if (ret <= 0)
1233 {
1234 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1235 return CMD_WARNING;
1236 }
1237
1238 /* Check current interface address. */
paulca162182005-09-12 16:58:52 +00001239 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001240 if (! ifc)
1241 {
1242 vty_out (vty, "%% Can't find address%s", VTY_NEWLINE);
1243 return CMD_WARNING;
1244 }
1245
1246 /* This is not configured address. */
1247 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1248 return CMD_WARNING;
1249
1250 /* This is not real address or interface is not active. */
1251 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1252 || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1253 {
1254 listnode_delete (ifp->connected, ifc);
1255 connected_free (ifc);
1256 return CMD_WARNING;
1257 }
1258
1259 /* This is real route. */
1260 ret = if_unset_prefix (ifp, ifc);
1261 if (ret < 0)
1262 {
1263 vty_out (vty, "%% Can't unset interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001264 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001265 return CMD_WARNING;
1266 }
1267
hassoeef1fe12004-10-03 18:46:08 +00001268#if 0
paul718e3742002-12-13 20:15:29 +00001269 /* Redistribute this information. */
1270 zebra_interface_address_delete_update (ifp, ifc);
1271
1272 /* Remove connected route. */
1273 connected_down_ipv4 (ifp, ifc);
1274
1275 /* Free address information. */
1276 listnode_delete (ifp->connected, ifc);
1277 connected_free (ifc);
hassoeef1fe12004-10-03 18:46:08 +00001278#endif
paul718e3742002-12-13 20:15:29 +00001279
1280 return CMD_SUCCESS;
1281}
1282
1283DEFUN (ip_address,
1284 ip_address_cmd,
1285 "ip address A.B.C.D/M",
1286 "Interface Internet Protocol config commands\n"
1287 "Set the IP address of an interface\n"
1288 "IP address (e.g. 10.0.0.1/8)\n")
1289{
hassoeef1fe12004-10-03 18:46:08 +00001290 return ip_address_install (vty, vty->index, argv[0], NULL, NULL);
paul718e3742002-12-13 20:15:29 +00001291}
1292
1293DEFUN (no_ip_address,
1294 no_ip_address_cmd,
1295 "no ip address A.B.C.D/M",
1296 NO_STR
1297 "Interface Internet Protocol config commands\n"
1298 "Set the IP address of an interface\n"
1299 "IP Address (e.g. 10.0.0.1/8)")
1300{
hassoeef1fe12004-10-03 18:46:08 +00001301 return ip_address_uninstall (vty, vty->index, argv[0], NULL, NULL);
paul718e3742002-12-13 20:15:29 +00001302}
1303
1304#ifdef HAVE_NETLINK
paul718e3742002-12-13 20:15:29 +00001305DEFUN (ip_address_label,
1306 ip_address_label_cmd,
1307 "ip address A.B.C.D/M label LINE",
1308 "Interface Internet Protocol config commands\n"
1309 "Set the IP address of an interface\n"
1310 "IP address (e.g. 10.0.0.1/8)\n"
1311 "Label of this address\n"
1312 "Label\n")
1313{
hassoeef1fe12004-10-03 18:46:08 +00001314 return ip_address_install (vty, vty->index, argv[0], NULL, argv[1]);
paul718e3742002-12-13 20:15:29 +00001315}
1316
1317DEFUN (no_ip_address_label,
1318 no_ip_address_label_cmd,
1319 "no ip address A.B.C.D/M label LINE",
1320 NO_STR
1321 "Interface Internet Protocol config commands\n"
1322 "Set the IP address of an interface\n"
1323 "IP address (e.g. 10.0.0.1/8)\n"
1324 "Label of this address\n"
1325 "Label\n")
1326{
hassoeef1fe12004-10-03 18:46:08 +00001327 return ip_address_uninstall (vty, vty->index, argv[0], NULL, argv[1]);
paul718e3742002-12-13 20:15:29 +00001328}
1329#endif /* HAVE_NETLINK */
1330
1331#ifdef HAVE_IPV6
paula1ac18c2005-06-28 17:17:12 +00001332static int
hasso39db97e2004-10-12 20:50:58 +00001333ipv6_address_install (struct vty *vty, struct interface *ifp,
1334 const char *addr_str, const char *peer_str,
1335 const char *label, int secondary)
paul718e3742002-12-13 20:15:29 +00001336{
1337 struct prefix_ipv6 cp;
1338 struct connected *ifc;
1339 struct prefix_ipv6 *p;
1340 int ret;
1341
1342 ret = str2prefix_ipv6 (addr_str, &cp);
1343 if (ret <= 0)
1344 {
1345 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1346 return CMD_WARNING;
1347 }
1348
paulca162182005-09-12 16:58:52 +00001349 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001350 if (! ifc)
1351 {
1352 ifc = connected_new ();
1353 ifc->ifp = ifp;
1354
1355 /* Address. */
1356 p = prefix_ipv6_new ();
1357 *p = cp;
1358 ifc->address = (struct prefix *) p;
1359
1360 /* Secondary. */
1361 if (secondary)
1362 SET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY);
1363
1364 /* Label. */
1365 if (label)
1366 ifc->label = strdup (label);
1367
1368 /* Add to linked list. */
1369 listnode_add (ifp->connected, ifc);
1370 }
1371
1372 /* This address is configured from zebra. */
1373 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1374 SET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED);
1375
1376 /* In case of this route need to install kernel. */
1377 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1378 && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1379 {
1380 /* Some system need to up the interface to set IP address. */
1381 if (! if_is_up (ifp))
1382 {
1383 if_set_flags (ifp, IFF_UP | IFF_RUNNING);
1384 if_refresh (ifp);
1385 }
1386
1387 ret = if_prefix_add_ipv6 (ifp, ifc);
1388
1389 if (ret < 0)
1390 {
1391 vty_out (vty, "%% Can't set interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001392 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001393 return CMD_WARNING;
1394 }
1395
1396 /* IP address propery set. */
1397 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
1398
1399 /* Update interface address information to protocol daemon. */
1400 zebra_interface_address_add_update (ifp, ifc);
1401
1402 /* If interface is up register connected route. */
paul2e3b2e42002-12-13 21:03:13 +00001403 if (if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001404 connected_up_ipv6 (ifp, ifc);
1405 }
1406
1407 return CMD_SUCCESS;
1408}
1409
paula1ac18c2005-06-28 17:17:12 +00001410static int
hasso39db97e2004-10-12 20:50:58 +00001411ipv6_address_uninstall (struct vty *vty, struct interface *ifp,
1412 const char *addr_str, const char *peer_str,
1413 const char *label, int secondry)
paul718e3742002-12-13 20:15:29 +00001414{
1415 struct prefix_ipv6 cp;
1416 struct connected *ifc;
1417 int ret;
1418
1419 /* Convert to prefix structure. */
1420 ret = str2prefix_ipv6 (addr_str, &cp);
1421 if (ret <= 0)
1422 {
1423 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1424 return CMD_WARNING;
1425 }
1426
1427 /* Check current interface address. */
paulca162182005-09-12 16:58:52 +00001428 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001429 if (! ifc)
1430 {
1431 vty_out (vty, "%% Can't find address%s", VTY_NEWLINE);
1432 return CMD_WARNING;
1433 }
1434
1435 /* This is not configured address. */
1436 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1437 return CMD_WARNING;
1438
1439 /* This is not real address or interface is not active. */
1440 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1441 || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1442 {
1443 listnode_delete (ifp->connected, ifc);
1444 connected_free (ifc);
1445 return CMD_WARNING;
1446 }
1447
1448 /* This is real route. */
1449 ret = if_prefix_delete_ipv6 (ifp, ifc);
1450 if (ret < 0)
1451 {
1452 vty_out (vty, "%% Can't unset interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001453 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001454 return CMD_WARNING;
1455 }
1456
1457 /* Redistribute this information. */
1458 zebra_interface_address_delete_update (ifp, ifc);
1459
1460 /* Remove connected route. */
1461 connected_down_ipv6 (ifp, ifc);
1462
1463 /* Free address information. */
1464 listnode_delete (ifp->connected, ifc);
1465 connected_free (ifc);
1466
1467 return CMD_SUCCESS;
1468}
1469
1470DEFUN (ipv6_address,
1471 ipv6_address_cmd,
1472 "ipv6 address X:X::X:X/M",
hassoe23949c2004-03-11 15:54:02 +00001473 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001474 "Set the IP address of an interface\n"
1475 "IPv6 address (e.g. 3ffe:506::1/48)\n")
1476{
1477 return ipv6_address_install (vty, vty->index, argv[0], NULL, NULL, 0);
1478}
1479
1480DEFUN (no_ipv6_address,
1481 no_ipv6_address_cmd,
1482 "no ipv6 address X:X::X:X/M",
1483 NO_STR
hassoe23949c2004-03-11 15:54:02 +00001484 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001485 "Set the IP address of an interface\n"
1486 "IPv6 address (e.g. 3ffe:506::1/48)\n")
1487{
1488 return ipv6_address_uninstall (vty, vty->index, argv[0], NULL, NULL, 0);
1489}
1490#endif /* HAVE_IPV6 */
1491
paula1ac18c2005-06-28 17:17:12 +00001492static int
paul718e3742002-12-13 20:15:29 +00001493if_config_write (struct vty *vty)
1494{
hasso52dc7ee2004-09-23 19:18:23 +00001495 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001496 struct interface *ifp;
1497 char buf[BUFSIZ];
1498
paul1eb8ef22005-04-07 07:30:20 +00001499 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00001500 {
1501 struct zebra_if *if_data;
hasso52dc7ee2004-09-23 19:18:23 +00001502 struct listnode *addrnode;
paul718e3742002-12-13 20:15:29 +00001503 struct connected *ifc;
1504 struct prefix *p;
1505
paul718e3742002-12-13 20:15:29 +00001506 if_data = ifp->info;
1507
1508 vty_out (vty, "interface %s%s", ifp->name,
1509 VTY_NEWLINE);
1510
1511 if (ifp->desc)
1512 vty_out (vty, " description %s%s", ifp->desc,
1513 VTY_NEWLINE);
1514
1515 /* Assign bandwidth here to avoid unnecessary interface flap
1516 while processing config script */
1517 if (ifp->bandwidth != 0)
1518 vty_out(vty, " bandwidth %u%s", ifp->bandwidth, VTY_NEWLINE);
1519
paul2e3b2e42002-12-13 21:03:13 +00001520 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION))
1521 vty_out(vty, " link-detect%s", VTY_NEWLINE);
1522
paul1eb8ef22005-04-07 07:30:20 +00001523 for (ALL_LIST_ELEMENTS_RO (ifp->connected, addrnode, ifc))
paul718e3742002-12-13 20:15:29 +00001524 {
paul718e3742002-12-13 20:15:29 +00001525 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1526 {
1527 p = ifc->address;
1528 vty_out (vty, " ip%s address %s/%d",
1529 p->family == AF_INET ? "" : "v6",
1530 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
1531 p->prefixlen);
1532
paul718e3742002-12-13 20:15:29 +00001533 if (ifc->label)
1534 vty_out (vty, " label %s", ifc->label);
1535
1536 vty_out (vty, "%s", VTY_NEWLINE);
1537 }
1538 }
1539
1540 if (if_data)
1541 {
1542 if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)
1543 vty_out (vty, " shutdown%s", VTY_NEWLINE);
1544
1545 if (if_data->multicast != IF_ZEBRA_MULTICAST_UNSPEC)
1546 vty_out (vty, " %smulticast%s",
1547 if_data->multicast == IF_ZEBRA_MULTICAST_ON ? "" : "no ",
1548 VTY_NEWLINE);
1549 }
1550
1551#ifdef RTADV
1552 rtadv_config_write (vty, ifp);
1553#endif /* RTADV */
1554
hassoca776982004-06-12 14:33:05 +00001555#ifdef HAVE_IRDP
1556 irdp_config_write (vty, ifp);
1557#endif /* IRDP */
1558
paul718e3742002-12-13 20:15:29 +00001559 vty_out (vty, "!%s", VTY_NEWLINE);
1560 }
1561 return 0;
1562}
1563
1564/* Allocate and initialize interface vector. */
1565void
paula1ac18c2005-06-28 17:17:12 +00001566zebra_if_init (void)
paul718e3742002-12-13 20:15:29 +00001567{
1568 /* Initialize interface and new hook. */
1569 if_init ();
1570 if_add_hook (IF_NEW_HOOK, if_zebra_new_hook);
1571 if_add_hook (IF_DELETE_HOOK, if_zebra_delete_hook);
1572
1573 /* Install configuration write function. */
1574 install_node (&interface_node, if_config_write);
1575
1576 install_element (VIEW_NODE, &show_interface_cmd);
1577 install_element (ENABLE_NODE, &show_interface_cmd);
hassoed9bb6d2005-03-13 19:17:21 +00001578 install_element (ENABLE_NODE, &show_interface_desc_cmd);
paul718e3742002-12-13 20:15:29 +00001579 install_element (CONFIG_NODE, &zebra_interface_cmd);
paulbfc13532003-05-24 06:40:04 +00001580 install_element (CONFIG_NODE, &no_interface_cmd);
paul718e3742002-12-13 20:15:29 +00001581 install_default (INTERFACE_NODE);
1582 install_element (INTERFACE_NODE, &interface_desc_cmd);
1583 install_element (INTERFACE_NODE, &no_interface_desc_cmd);
1584 install_element (INTERFACE_NODE, &multicast_cmd);
1585 install_element (INTERFACE_NODE, &no_multicast_cmd);
paul2e3b2e42002-12-13 21:03:13 +00001586 install_element (INTERFACE_NODE, &linkdetect_cmd);
1587 install_element (INTERFACE_NODE, &no_linkdetect_cmd);
paul718e3742002-12-13 20:15:29 +00001588 install_element (INTERFACE_NODE, &shutdown_if_cmd);
1589 install_element (INTERFACE_NODE, &no_shutdown_if_cmd);
1590 install_element (INTERFACE_NODE, &bandwidth_if_cmd);
1591 install_element (INTERFACE_NODE, &no_bandwidth_if_cmd);
1592 install_element (INTERFACE_NODE, &no_bandwidth_if_val_cmd);
1593 install_element (INTERFACE_NODE, &ip_address_cmd);
1594 install_element (INTERFACE_NODE, &no_ip_address_cmd);
1595#ifdef HAVE_IPV6
1596 install_element (INTERFACE_NODE, &ipv6_address_cmd);
1597 install_element (INTERFACE_NODE, &no_ipv6_address_cmd);
1598#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +00001599#ifdef HAVE_NETLINK
paul718e3742002-12-13 20:15:29 +00001600 install_element (INTERFACE_NODE, &ip_address_label_cmd);
paul718e3742002-12-13 20:15:29 +00001601 install_element (INTERFACE_NODE, &no_ip_address_label_cmd);
paul718e3742002-12-13 20:15:29 +00001602#endif /* HAVE_NETLINK */
1603}