blob: bd31fb40eb1733f46f21a1fed236e2038bb36df1 [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. */
46int
47if_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. */
92int
93if_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. */
192void
193if_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
paul44145db2004-05-09 11:00:23 +0000293
294/* Handle an interface delete event
295 *
296 * This function is only called when support for
297 * RTM_IFANNOUNCE or AF_NETLINK sockets (RTM_DELLINK message)
298 * is available. It is not called on, eg, Solaris.
299 */
300#if (defined(RTM_IFANNOUNCE) || defined(HAVE_NETLINK))
paul718e3742002-12-13 20:15:29 +0000301void
302if_delete_update (struct interface *ifp)
303{
304 struct listnode *node;
305 struct listnode *next;
hassoeef1fe12004-10-03 18:46:08 +0000306 struct listnode *first;
307 struct listnode *last;
paul718e3742002-12-13 20:15:29 +0000308 struct connected *ifc;
309 struct prefix *p;
hassoeef1fe12004-10-03 18:46:08 +0000310 struct route_node *rn;
311 struct zebra_if *zebra_if;
312 struct list *addr_list;
313
314 zebra_if = ifp->info;
paul718e3742002-12-13 20:15:29 +0000315
316 if (if_is_up(ifp))
317 {
318 zlog_err ("interface %s index %d is still up while being deleted.",
319 ifp->name, ifp->ifindex);
320 return;
321 }
322
323 /* Mark interface as inactive */
324 UNSET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE);
325
326 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +0000327 zlog_debug ("interface %s index %d is now inactive.",
paul718e3742002-12-13 20:15:29 +0000328 ifp->name, ifp->ifindex);
329
330 /* Delete connected routes from the kernel. */
331 if (ifp->connected)
332 {
hassoeef1fe12004-10-03 18:46:08 +0000333 last = NULL;
334 while ((node = (last ? last->next : listhead (ifp->connected))))
paul718e3742002-12-13 20:15:29 +0000335 {
paul1eb8ef22005-04-07 07:30:20 +0000336 ifc = listgetdata (node);
paul718e3742002-12-13 20:15:29 +0000337 p = ifc->address;
hassoeef1fe12004-10-03 18:46:08 +0000338
paul718e3742002-12-13 20:15:29 +0000339 if (p->family == AF_INET)
hassoeef1fe12004-10-03 18:46:08 +0000340 {
341 rn = route_node_lookup (zebra_if->ipv4_subnets, p);
342 route_unlock_node (rn);
343 addr_list = (struct list *) rn->info;
344
345 /* Remove addresses, secondaries first. */
346 first = listhead (addr_list);
347 for (node = first->next; node || first; node = next)
348 {
349 if (! node)
350 {
351 node = first;
352 first = NULL;
353 }
354 next = node->next;
355
paul1eb8ef22005-04-07 07:30:20 +0000356 ifc = listgetdata (node);
hassoeef1fe12004-10-03 18:46:08 +0000357 p = ifc->address;
358
359 connected_down_ipv4 (ifp, ifc);
360
361 zebra_interface_address_delete_update (ifp, ifc);
362
363 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
364
365 /* Remove from subnet chain. */
366 list_delete_node (addr_list, node);
367 route_unlock_node (rn);
368
369 /* Remove from interface address list (unconditionally). */
370 listnode_delete (ifp->connected, ifc);
371 connected_free (ifc);
372 }
373
374 /* Free chain list and respective route node. */
375 list_delete (addr_list);
376 rn->info = NULL;
377 route_unlock_node (rn);
378 }
paul718e3742002-12-13 20:15:29 +0000379#ifdef HAVE_IPV6
380 else if (p->family == AF_INET6)
hassoeef1fe12004-10-03 18:46:08 +0000381 {
382 connected_down_ipv6 (ifp, ifc);
paul718e3742002-12-13 20:15:29 +0000383
hassoeef1fe12004-10-03 18:46:08 +0000384 zebra_interface_address_delete_update (ifp, ifc);
paul718e3742002-12-13 20:15:29 +0000385
hassoeef1fe12004-10-03 18:46:08 +0000386 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
387
388 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
389 last = node;
390 else
391 {
392 listnode_delete (ifp->connected, ifc);
393 connected_free (ifc);
394 }
paul718e3742002-12-13 20:15:29 +0000395 }
hassoeef1fe12004-10-03 18:46:08 +0000396#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +0000397 }
398 }
399 zebra_interface_delete_update (ifp);
ajsd2fc8892005-04-02 18:38:43 +0000400
401 /* Update ifindex after distributing the delete message. This is in
402 case any client needs to have the old value of ifindex available
403 while processing the deletion. Each client daemon is responsible
404 for setting ifindex to IFINDEX_INTERNAL after processing the
405 interface deletion message. */
406 ifp->ifindex = IFINDEX_INTERNAL;
paul718e3742002-12-13 20:15:29 +0000407}
paul44145db2004-05-09 11:00:23 +0000408#endif /* (defined(RTM_IFANNOUNCE) || defined(HAVE_NETLINK) */
paul718e3742002-12-13 20:15:29 +0000409
410/* Interface is up. */
411void
412if_up (struct interface *ifp)
413{
hasso52dc7ee2004-09-23 19:18:23 +0000414 struct listnode *node;
415 struct listnode *next;
paul718e3742002-12-13 20:15:29 +0000416 struct connected *ifc;
417 struct prefix *p;
418
419 /* Notify the protocol daemons. */
420 zebra_interface_up_update (ifp);
421
422 /* Install connected routes to the kernel. */
423 if (ifp->connected)
424 {
paul1eb8ef22005-04-07 07:30:20 +0000425 for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc))
paul718e3742002-12-13 20:15:29 +0000426 {
paul718e3742002-12-13 20:15:29 +0000427 p = ifc->address;
428
429 if (p->family == AF_INET)
430 connected_up_ipv4 (ifp, ifc);
431#ifdef HAVE_IPV6
432 else if (p->family == AF_INET6)
433 connected_up_ipv6 (ifp, ifc);
434#endif /* HAVE_IPV6 */
435 }
436 }
437
438 /* Examine all static routes. */
439 rib_update ();
440}
441
442/* Interface goes down. We have to manage different behavior of based
443 OS. */
444void
445if_down (struct interface *ifp)
446{
hasso52dc7ee2004-09-23 19:18:23 +0000447 struct listnode *node;
448 struct listnode *next;
paul718e3742002-12-13 20:15:29 +0000449 struct connected *ifc;
450 struct prefix *p;
451
452 /* Notify to the protocol daemons. */
453 zebra_interface_down_update (ifp);
454
455 /* Delete connected routes from the kernel. */
456 if (ifp->connected)
457 {
paul1eb8ef22005-04-07 07:30:20 +0000458 for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc))
paul718e3742002-12-13 20:15:29 +0000459 {
paul718e3742002-12-13 20:15:29 +0000460 p = ifc->address;
461
462 if (p->family == AF_INET)
463 connected_down_ipv4 (ifp, ifc);
464#ifdef HAVE_IPV6
465 else if (p->family == AF_INET6)
466 connected_down_ipv6 (ifp, ifc);
467#endif /* HAVE_IPV6 */
468 }
469 }
470
471 /* Examine all static routes which direct to the interface. */
472 rib_update ();
473}
474
475void
476if_refresh (struct interface *ifp)
477{
paul2e3b2e42002-12-13 21:03:13 +0000478 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000479 {
480 if_get_flags (ifp);
paul2e3b2e42002-12-13 21:03:13 +0000481 if (! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000482 if_down (ifp);
483 }
484 else
485 {
486 if_get_flags (ifp);
paul2e3b2e42002-12-13 21:03:13 +0000487 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000488 if_up (ifp);
489 }
490}
491
492/* Printout flag information into vty */
493void
494if_flag_dump_vty (struct vty *vty, unsigned long flag)
495{
496 int separator = 0;
497
498#define IFF_OUT_VTY(X, Y) \
499 if ((X) && (flag & (X))) \
500 { \
501 if (separator) \
502 vty_out (vty, ","); \
503 else \
504 separator = 1; \
505 vty_out (vty, Y); \
506 }
507
508 vty_out (vty, "<");
509 IFF_OUT_VTY (IFF_UP, "UP");
510 IFF_OUT_VTY (IFF_BROADCAST, "BROADCAST");
511 IFF_OUT_VTY (IFF_DEBUG, "DEBUG");
512 IFF_OUT_VTY (IFF_LOOPBACK, "LOOPBACK");
513 IFF_OUT_VTY (IFF_POINTOPOINT, "POINTOPOINT");
514 IFF_OUT_VTY (IFF_NOTRAILERS, "NOTRAILERS");
515 IFF_OUT_VTY (IFF_RUNNING, "RUNNING");
516 IFF_OUT_VTY (IFF_NOARP, "NOARP");
517 IFF_OUT_VTY (IFF_PROMISC, "PROMISC");
518 IFF_OUT_VTY (IFF_ALLMULTI, "ALLMULTI");
519 IFF_OUT_VTY (IFF_OACTIVE, "OACTIVE");
520 IFF_OUT_VTY (IFF_SIMPLEX, "SIMPLEX");
521 IFF_OUT_VTY (IFF_LINK0, "LINK0");
522 IFF_OUT_VTY (IFF_LINK1, "LINK1");
523 IFF_OUT_VTY (IFF_LINK2, "LINK2");
524 IFF_OUT_VTY (IFF_MULTICAST, "MULTICAST");
paul44145db2004-05-09 11:00:23 +0000525#ifdef SOLARIS_IPV6
526 IFF_OUT_VTY (IFF_IPV4, "IFF_IPv4");
527 IFF_OUT_VTY (IFF_IPV6, "IFF_IPv6");
528#endif /* SOLARIS_IPV6 */
paul718e3742002-12-13 20:15:29 +0000529 vty_out (vty, ">");
530}
531
532/* Output prefix string to vty. */
533int
534prefix_vty_out (struct vty *vty, struct prefix *p)
535{
536 char str[INET6_ADDRSTRLEN];
537
538 inet_ntop (p->family, &p->u.prefix, str, sizeof (str));
539 vty_out (vty, "%s", str);
540 return strlen (str);
541}
542
543/* Dump if address information to vty. */
544void
545connected_dump_vty (struct vty *vty, struct connected *connected)
546{
547 struct prefix *p;
548 struct interface *ifp;
549
550 /* Set interface pointer. */
551 ifp = connected->ifp;
552
553 /* Print interface address. */
554 p = connected->address;
555 vty_out (vty, " %s ", prefix_family_str (p));
556 prefix_vty_out (vty, p);
557 vty_out (vty, "/%d", p->prefixlen);
558
559 /* If there is destination address, print it. */
560 p = connected->destination;
561 if (p)
562 {
563 if (p->family == AF_INET)
564 if (ifp->flags & IFF_BROADCAST)
565 {
566 vty_out (vty, " broadcast ");
567 prefix_vty_out (vty, p);
568 }
569
570 if (ifp->flags & IFF_POINTOPOINT)
571 {
572 vty_out (vty, " pointopoint ");
573 prefix_vty_out (vty, p);
574 }
575 }
576
577 if (CHECK_FLAG (connected->flags, ZEBRA_IFA_SECONDARY))
578 vty_out (vty, " secondary");
579
580 if (connected->label)
581 vty_out (vty, " %s", connected->label);
582
583 vty_out (vty, "%s", VTY_NEWLINE);
584}
585
586#ifdef RTADV
587/* Dump interface ND information to vty. */
588void
589nd_dump_vty (struct vty *vty, struct interface *ifp)
590{
591 struct zebra_if *zif;
592 struct rtadvconf *rtadv;
vincent7cee1bb2005-03-25 13:08:53 +0000593 int interval;
paul718e3742002-12-13 20:15:29 +0000594
595 zif = (struct zebra_if *) ifp->info;
596 rtadv = &zif->rtadv;
597
598 if (rtadv->AdvSendAdvertisements)
599 {
600 vty_out (vty, " ND advertised reachable time is %d milliseconds%s",
601 rtadv->AdvReachableTime, VTY_NEWLINE);
602 vty_out (vty, " ND advertised retransmit interval is %d milliseconds%s",
603 rtadv->AdvRetransTimer, VTY_NEWLINE);
vincent7cee1bb2005-03-25 13:08:53 +0000604 interval = rtadv->MaxRtrAdvInterval;
605 if (interval % 1000)
606 vty_out (vty, " ND router advertisements are sent every "
607 "%d milliseconds%s", interval,
608 VTY_NEWLINE);
609 else
610 vty_out (vty, " ND router advertisements are sent every "
611 "%d seconds%s", interval / 1000,
612 VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000613 vty_out (vty, " ND router advertisements live for %d seconds%s",
614 rtadv->AdvDefaultLifetime, VTY_NEWLINE);
615 if (rtadv->AdvManagedFlag)
616 vty_out (vty, " Hosts use DHCP to obtain routable addresses.%s",
617 VTY_NEWLINE);
618 else
619 vty_out (vty, " Hosts use stateless autoconfig for addresses.%s",
620 VTY_NEWLINE);
vincent7cee1bb2005-03-25 13:08:53 +0000621 if (rtadv->AdvHomeAgentFlag)
622 vty_out (vty, " ND router advertisements with "
623 "Home Agent flag bit set.%s",
624 VTY_NEWLINE);
625 if (rtadv->AdvIntervalOption)
626 vty_out (vty, " ND router advertisements with Adv. Interval option.%s",
627 VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000628 }
629}
630#endif /* RTADV */
631
632/* Interface's information print out to vty interface. */
633void
634if_dump_vty (struct vty *vty, struct interface *ifp)
635{
636#ifdef HAVE_SOCKADDR_DL
637 struct sockaddr_dl *sdl;
638#endif /* HAVE_SOCKADDR_DL */
639 struct connected *connected;
hasso52dc7ee2004-09-23 19:18:23 +0000640 struct listnode *node;
hassoeef1fe12004-10-03 18:46:08 +0000641 struct route_node *rn;
642 struct zebra_if *zebra_if;
643
644 zebra_if = ifp->info;
paul718e3742002-12-13 20:15:29 +0000645
paul2e3b2e42002-12-13 21:03:13 +0000646 vty_out (vty, "Interface %s is ", ifp->name);
647 if (if_is_up(ifp)) {
648 vty_out (vty, "up, line protocol ");
649
650 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) {
651 if (if_is_running(ifp))
652 vty_out (vty, "is up%s", VTY_NEWLINE);
653 else
654 vty_out (vty, "is down%s", VTY_NEWLINE);
655 } else {
656 vty_out (vty, "detection is disabled%s", VTY_NEWLINE);
657 }
658 } else {
659 vty_out (vty, "down%s", VTY_NEWLINE);
660 }
661
paul718e3742002-12-13 20:15:29 +0000662 if (ifp->desc)
663 vty_out (vty, " Description: %s%s", ifp->desc,
664 VTY_NEWLINE);
ajsd2fc8892005-04-02 18:38:43 +0000665 if (ifp->ifindex == IFINDEX_INTERNAL)
paul718e3742002-12-13 20:15:29 +0000666 {
ajsd2fc8892005-04-02 18:38:43 +0000667 vty_out(vty, " pseudo interface%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000668 return;
669 }
670 else if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
671 {
672 vty_out(vty, " index %d inactive interface%s",
673 ifp->ifindex,
674 VTY_NEWLINE);
675 return;
676 }
677
678 vty_out (vty, " index %d metric %d mtu %d ",
679 ifp->ifindex, ifp->metric, ifp->mtu);
680 if_flag_dump_vty (vty, ifp->flags);
paul44145db2004-05-09 11:00:23 +0000681#ifdef HAVE_IPV6
682 if (ifp->mtu6 != ifp->mtu)
683 vty_out (vty, "mtu6 %d ", ifp->mtu6);
684#endif
685
paul718e3742002-12-13 20:15:29 +0000686 vty_out (vty, "%s", VTY_NEWLINE);
687
688 /* Hardware address. */
689#ifdef HAVE_SOCKADDR_DL
690 sdl = &ifp->sdl;
691 if (sdl != NULL && sdl->sdl_alen != 0)
692 {
693 int i;
694 u_char *ptr;
695
696 vty_out (vty, " HWaddr: ");
paul5b73a672004-07-23 15:26:14 +0000697 for (i = 0, ptr = (u_char *)LLADDR (sdl); i < sdl->sdl_alen; i++, ptr++)
698 vty_out (vty, "%s%02x", i == 0 ? "" : ":", *ptr);
paul718e3742002-12-13 20:15:29 +0000699 vty_out (vty, "%s", VTY_NEWLINE);
700 }
701#else
702 if (ifp->hw_addr_len != 0)
703 {
704 int i;
705
706 vty_out (vty, " HWaddr: ");
707 for (i = 0; i < ifp->hw_addr_len; i++)
708 vty_out (vty, "%s%02x", i == 0 ? "" : ":", ifp->hw_addr[i]);
709 vty_out (vty, "%s", VTY_NEWLINE);
710 }
711#endif /* HAVE_SOCKADDR_DL */
712
713 /* Bandwidth in kbps */
714 if (ifp->bandwidth != 0)
715 {
716 vty_out(vty, " bandwidth %u kbps", ifp->bandwidth);
717 vty_out(vty, "%s", VTY_NEWLINE);
718 }
719
hassoeef1fe12004-10-03 18:46:08 +0000720 for (rn = route_top (zebra_if->ipv4_subnets); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000721 {
hassoeef1fe12004-10-03 18:46:08 +0000722 if (! rn->info)
723 continue;
724
paul1eb8ef22005-04-07 07:30:20 +0000725 for (ALL_LIST_ELEMENTS_RO ((struct list *)rn->info, node, connected))
726 connected_dump_vty (vty, connected);
paul718e3742002-12-13 20:15:29 +0000727 }
728
paul1eb8ef22005-04-07 07:30:20 +0000729 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
hasso39db97e2004-10-12 20:50:58 +0000730 {
hasso39db97e2004-10-12 20:50:58 +0000731 if (CHECK_FLAG (connected->conf, ZEBRA_IFC_REAL) &&
732 (connected->address->family == AF_INET6))
733 connected_dump_vty (vty, connected);
734 }
735
paul718e3742002-12-13 20:15:29 +0000736#ifdef RTADV
737 nd_dump_vty (vty, ifp);
738#endif /* RTADV */
739
740#ifdef HAVE_PROC_NET_DEV
741 /* Statistics print out using proc file system. */
hasso6f2c27a2005-01-18 13:44:35 +0000742 vty_out (vty, " %lu input packets (%lu multicast), %lu bytes, "
743 "%lu dropped%s",
744 ifp->stats.rx_packets, ifp->stats.rx_multicast,
745 ifp->stats.rx_bytes, ifp->stats.rx_dropped, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000746
hasso6f2c27a2005-01-18 13:44:35 +0000747 vty_out (vty, " %lu input errors, %lu length, %lu overrun,"
hasso3452d472005-03-06 13:42:05 +0000748 " %lu CRC, %lu frame%s",
paul718e3742002-12-13 20:15:29 +0000749 ifp->stats.rx_errors, ifp->stats.rx_length_errors,
750 ifp->stats.rx_over_errors, ifp->stats.rx_crc_errors,
hasso6f2c27a2005-01-18 13:44:35 +0000751 ifp->stats.rx_frame_errors, VTY_NEWLINE);
752
753 vty_out (vty, " %lu fifo, %lu missed%s", ifp->stats.rx_fifo_errors,
paul718e3742002-12-13 20:15:29 +0000754 ifp->stats.rx_missed_errors, VTY_NEWLINE);
755
hasso6f2c27a2005-01-18 13:44:35 +0000756 vty_out (vty, " %lu output packets, %lu bytes, %lu dropped%s",
paul718e3742002-12-13 20:15:29 +0000757 ifp->stats.tx_packets, ifp->stats.tx_bytes,
758 ifp->stats.tx_dropped, VTY_NEWLINE);
759
hasso6f2c27a2005-01-18 13:44:35 +0000760 vty_out (vty, " %lu output errors, %lu aborted, %lu carrier,"
761 " %lu fifo, %lu heartbeat%s",
paul718e3742002-12-13 20:15:29 +0000762 ifp->stats.tx_errors, ifp->stats.tx_aborted_errors,
763 ifp->stats.tx_carrier_errors, ifp->stats.tx_fifo_errors,
hasso6f2c27a2005-01-18 13:44:35 +0000764 ifp->stats.tx_heartbeat_errors, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000765
hasso6f2c27a2005-01-18 13:44:35 +0000766 vty_out (vty, " %lu window, %lu collisions%s",
767 ifp->stats.tx_window_errors, ifp->stats.collisions, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000768#endif /* HAVE_PROC_NET_DEV */
769
770#ifdef HAVE_NET_RT_IFLIST
771#if defined (__bsdi__) || defined (__NetBSD__)
772 /* Statistics print out using sysctl (). */
773 vty_out (vty, " input packets %qu, bytes %qu, dropped %qu,"
774 " multicast packets %qu%s",
775 ifp->stats.ifi_ipackets, ifp->stats.ifi_ibytes,
776 ifp->stats.ifi_iqdrops, ifp->stats.ifi_imcasts,
777 VTY_NEWLINE);
778
779 vty_out (vty, " input errors %qu%s",
780 ifp->stats.ifi_ierrors, VTY_NEWLINE);
781
782 vty_out (vty, " output packets %qu, bytes %qu, multicast packets %qu%s",
783 ifp->stats.ifi_opackets, ifp->stats.ifi_obytes,
784 ifp->stats.ifi_omcasts, VTY_NEWLINE);
785
786 vty_out (vty, " output errors %qu%s",
787 ifp->stats.ifi_oerrors, VTY_NEWLINE);
788
789 vty_out (vty, " collisions %qu%s",
790 ifp->stats.ifi_collisions, VTY_NEWLINE);
791#else
792 /* Statistics print out using sysctl (). */
793 vty_out (vty, " input packets %lu, bytes %lu, dropped %lu,"
794 " multicast packets %lu%s",
795 ifp->stats.ifi_ipackets, ifp->stats.ifi_ibytes,
796 ifp->stats.ifi_iqdrops, ifp->stats.ifi_imcasts,
797 VTY_NEWLINE);
798
799 vty_out (vty, " input errors %lu%s",
800 ifp->stats.ifi_ierrors, VTY_NEWLINE);
801
802 vty_out (vty, " output packets %lu, bytes %lu, multicast packets %lu%s",
803 ifp->stats.ifi_opackets, ifp->stats.ifi_obytes,
804 ifp->stats.ifi_omcasts, VTY_NEWLINE);
805
806 vty_out (vty, " output errors %lu%s",
807 ifp->stats.ifi_oerrors, VTY_NEWLINE);
808
809 vty_out (vty, " collisions %lu%s",
810 ifp->stats.ifi_collisions, VTY_NEWLINE);
811#endif /* __bsdi__ || __NetBSD__ */
812#endif /* HAVE_NET_RT_IFLIST */
813}
814
815/* Check supported address family. */
816int
817if_supported_family (int family)
818{
819 if (family == AF_INET)
820 return 1;
821#ifdef HAVE_IPV6
822 if (family == AF_INET6)
823 return 1;
824#endif /* HAVE_IPV6 */
825 return 0;
826}
827
828/* Wrapper hook point for zebra daemon so that ifindex can be set
829 * DEFUN macro not used as extract.pl HAS to ignore this
830 * See also interface_cmd in lib/if.c
831 */
832DEFUN_NOSH (zebra_interface,
833 zebra_interface_cmd,
834 "interface IFNAME",
835 "Select an interface to configure\n"
836 "Interface's name\n")
837{
838 int ret;
839 struct interface * ifp;
840
841 /* Call lib interface() */
ajsd2fc8892005-04-02 18:38:43 +0000842 if ((ret = interface_cmd.func (self, vty, argc, argv)) != CMD_SUCCESS)
843 return ret;
paul718e3742002-12-13 20:15:29 +0000844
845 ifp = vty->index;
846
ajsd2fc8892005-04-02 18:38:43 +0000847 if (ifp->ifindex == IFINDEX_INTERNAL)
848 /* Is this really necessary? Shouldn't status be initialized to 0
849 in that case? */
850 UNSET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE);
paul718e3742002-12-13 20:15:29 +0000851
852 return ret;
853}
854
paul718e3742002-12-13 20:15:29 +0000855struct cmd_node interface_node =
856{
857 INTERFACE_NODE,
858 "%s(config-if)# ",
859 1
860};
861
862/* Show all or specified interface to vty. */
863DEFUN (show_interface, show_interface_cmd,
864 "show interface [IFNAME]",
865 SHOW_STR
866 "Interface status and configuration\n"
867 "Inteface name\n")
868{
hasso52dc7ee2004-09-23 19:18:23 +0000869 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000870 struct interface *ifp;
871
872#ifdef HAVE_PROC_NET_DEV
873 /* If system has interface statistics via proc file system, update
874 statistics. */
875 ifstat_update_proc ();
876#endif /* HAVE_PROC_NET_DEV */
877#ifdef HAVE_NET_RT_IFLIST
878 ifstat_update_sysctl ();
879#endif /* HAVE_NET_RT_IFLIST */
880
881 /* Specified interface print. */
882 if (argc != 0)
883 {
884 ifp = if_lookup_by_name (argv[0]);
885 if (ifp == NULL)
886 {
887 vty_out (vty, "%% Can't find interface %s%s", argv[0],
888 VTY_NEWLINE);
889 return CMD_WARNING;
890 }
891 if_dump_vty (vty, ifp);
892 return CMD_SUCCESS;
893 }
894
895 /* All interface print. */
paul1eb8ef22005-04-07 07:30:20 +0000896 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
897 if_dump_vty (vty, ifp);
paul718e3742002-12-13 20:15:29 +0000898
899 return CMD_SUCCESS;
900}
901
hassoed9bb6d2005-03-13 19:17:21 +0000902DEFUN (show_interface_desc,
903 show_interface_desc_cmd,
904 "show interface description",
905 SHOW_STR
906 "Interface status and configuration\n"
907 "Interface description\n")
908{
909 struct listnode *node;
910 struct interface *ifp;
911
912 vty_out (vty, "Interface Status Protocol Description%s", VTY_NEWLINE);
paul1eb8ef22005-04-07 07:30:20 +0000913 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
hassoed9bb6d2005-03-13 19:17:21 +0000914 {
915 int len;
hassoed9bb6d2005-03-13 19:17:21 +0000916
917 len = vty_out (vty, "%s", ifp->name);
918 vty_out (vty, "%*s", (16 - len), " ");
919
920 if (if_is_up(ifp))
921 {
922 vty_out (vty, "up ");
923 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION))
924 {
925 if (if_is_running(ifp))
926 vty_out (vty, "up ");
927 else
928 vty_out (vty, "down ");
929 }
930 else
931 {
932 vty_out (vty, "unknown ");
933 }
934 }
935 else
936 {
937 vty_out (vty, "down down ");
938 }
939
940 if (ifp->desc)
941 vty_out (vty, "%s", ifp->desc);
942 vty_out (vty, "%s", VTY_NEWLINE);
943 }
944 return CMD_SUCCESS;
945}
946
paul718e3742002-12-13 20:15:29 +0000947DEFUN (multicast,
948 multicast_cmd,
949 "multicast",
950 "Set multicast flag to interface\n")
951{
952 int ret;
953 struct interface *ifp;
954 struct zebra_if *if_data;
955
956 ifp = (struct interface *) vty->index;
paul48b33aa2002-12-13 20:52:52 +0000957 if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
paul718e3742002-12-13 20:15:29 +0000958 {
paul48b33aa2002-12-13 20:52:52 +0000959 ret = if_set_flags (ifp, IFF_MULTICAST);
960 if (ret < 0)
961 {
962 vty_out (vty, "Can't set multicast flag%s", VTY_NEWLINE);
963 return CMD_WARNING;
964 }
965 if_refresh (ifp);
paul718e3742002-12-13 20:15:29 +0000966 }
paul718e3742002-12-13 20:15:29 +0000967 if_data = ifp->info;
968 if_data->multicast = IF_ZEBRA_MULTICAST_ON;
paul48b33aa2002-12-13 20:52:52 +0000969
paul718e3742002-12-13 20:15:29 +0000970 return CMD_SUCCESS;
971}
972
973DEFUN (no_multicast,
974 no_multicast_cmd,
975 "no multicast",
976 NO_STR
977 "Unset multicast flag to interface\n")
978{
979 int ret;
980 struct interface *ifp;
981 struct zebra_if *if_data;
982
983 ifp = (struct interface *) vty->index;
paul48b33aa2002-12-13 20:52:52 +0000984 if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
paul718e3742002-12-13 20:15:29 +0000985 {
paul48b33aa2002-12-13 20:52:52 +0000986 ret = if_unset_flags (ifp, IFF_MULTICAST);
987 if (ret < 0)
988 {
989 vty_out (vty, "Can't unset multicast flag%s", VTY_NEWLINE);
990 return CMD_WARNING;
991 }
992 if_refresh (ifp);
paul718e3742002-12-13 20:15:29 +0000993 }
paul718e3742002-12-13 20:15:29 +0000994 if_data = ifp->info;
995 if_data->multicast = IF_ZEBRA_MULTICAST_OFF;
996
997 return CMD_SUCCESS;
998}
999
paul2e3b2e42002-12-13 21:03:13 +00001000DEFUN (linkdetect,
1001 linkdetect_cmd,
1002 "link-detect",
1003 "Enable link detection on interface\n")
1004{
paul2e3b2e42002-12-13 21:03:13 +00001005 struct interface *ifp;
1006 int if_was_operative;
1007
1008 ifp = (struct interface *) vty->index;
1009 if_was_operative = if_is_operative(ifp);
1010 SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
1011
1012 /* When linkdetection is enabled, if might come down */
1013 if (!if_is_operative(ifp) && if_was_operative) if_down(ifp);
1014
1015 /* FIXME: Will defer status change forwarding if interface
1016 does not come down! */
1017
1018 return CMD_SUCCESS;
1019}
1020
1021
1022DEFUN (no_linkdetect,
1023 no_linkdetect_cmd,
1024 "no link-detect",
1025 NO_STR
1026 "Disable link detection on interface\n")
1027{
paul2e3b2e42002-12-13 21:03:13 +00001028 struct interface *ifp;
1029 int if_was_operative;
1030
1031 ifp = (struct interface *) vty->index;
1032 if_was_operative = if_is_operative(ifp);
1033 UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
1034
1035 /* Interface may come up after disabling link detection */
1036 if (if_is_operative(ifp) && !if_was_operative) if_up(ifp);
1037
1038 /* FIXME: see linkdetect_cmd */
1039
1040 return CMD_SUCCESS;
1041}
1042
paul718e3742002-12-13 20:15:29 +00001043DEFUN (shutdown_if,
1044 shutdown_if_cmd,
1045 "shutdown",
1046 "Shutdown the selected interface\n")
1047{
1048 int ret;
1049 struct interface *ifp;
1050 struct zebra_if *if_data;
1051
1052 ifp = (struct interface *) vty->index;
1053 ret = if_unset_flags (ifp, IFF_UP);
1054 if (ret < 0)
1055 {
1056 vty_out (vty, "Can't shutdown interface%s", VTY_NEWLINE);
1057 return CMD_WARNING;
1058 }
1059 if_refresh (ifp);
1060 if_data = ifp->info;
1061 if_data->shutdown = IF_ZEBRA_SHUTDOWN_ON;
1062
1063 return CMD_SUCCESS;
1064}
1065
1066DEFUN (no_shutdown_if,
1067 no_shutdown_if_cmd,
1068 "no shutdown",
1069 NO_STR
1070 "Shutdown the selected interface\n")
1071{
1072 int ret;
1073 struct interface *ifp;
1074 struct zebra_if *if_data;
1075
1076 ifp = (struct interface *) vty->index;
1077 ret = if_set_flags (ifp, IFF_UP | IFF_RUNNING);
1078 if (ret < 0)
1079 {
1080 vty_out (vty, "Can't up interface%s", VTY_NEWLINE);
1081 return CMD_WARNING;
1082 }
1083 if_refresh (ifp);
1084 if_data = ifp->info;
1085 if_data->shutdown = IF_ZEBRA_SHUTDOWN_OFF;
1086
1087 return CMD_SUCCESS;
1088}
1089
1090DEFUN (bandwidth_if,
1091 bandwidth_if_cmd,
1092 "bandwidth <1-10000000>",
1093 "Set bandwidth informational parameter\n"
1094 "Bandwidth in kilobits\n")
1095{
1096 struct interface *ifp;
1097 unsigned int bandwidth;
1098
1099 ifp = (struct interface *) vty->index;
1100 bandwidth = strtol(argv[0], NULL, 10);
1101
1102 /* bandwidth range is <1-10000000> */
1103 if (bandwidth < 1 || bandwidth > 10000000)
1104 {
1105 vty_out (vty, "Bandwidth is invalid%s", VTY_NEWLINE);
1106 return CMD_WARNING;
1107 }
1108
1109 ifp->bandwidth = bandwidth;
1110
1111 /* force protocols to recalculate routes due to cost change */
paul2e3b2e42002-12-13 21:03:13 +00001112 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00001113 zebra_interface_up_update (ifp);
1114
1115 return CMD_SUCCESS;
1116}
1117
1118DEFUN (no_bandwidth_if,
1119 no_bandwidth_if_cmd,
1120 "no bandwidth",
1121 NO_STR
1122 "Set bandwidth informational parameter\n")
1123{
1124 struct interface *ifp;
1125
1126 ifp = (struct interface *) vty->index;
1127
1128 ifp->bandwidth = 0;
1129
1130 /* force protocols to recalculate routes due to cost change */
paul2e3b2e42002-12-13 21:03:13 +00001131 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00001132 zebra_interface_up_update (ifp);
1133
1134 return CMD_SUCCESS;
1135}
1136
1137ALIAS (no_bandwidth_if,
1138 no_bandwidth_if_val_cmd,
1139 "no bandwidth <1-10000000>",
1140 NO_STR
1141 "Set bandwidth informational parameter\n"
1142 "Bandwidth in kilobits\n")
1143
1144int
hasso39db97e2004-10-12 20:50:58 +00001145ip_address_install (struct vty *vty, struct interface *ifp,
1146 const char *addr_str, const char *peer_str,
1147 const char *label)
paul718e3742002-12-13 20:15:29 +00001148{
1149 struct prefix_ipv4 cp;
1150 struct connected *ifc;
1151 struct prefix_ipv4 *p;
paul718e3742002-12-13 20:15:29 +00001152 int ret;
1153
1154 ret = str2prefix_ipv4 (addr_str, &cp);
1155 if (ret <= 0)
1156 {
1157 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1158 return CMD_WARNING;
1159 }
1160
1161 ifc = connected_check_ipv4 (ifp, (struct prefix *) &cp);
1162 if (! ifc)
1163 {
1164 ifc = connected_new ();
1165 ifc->ifp = ifp;
1166
1167 /* Address. */
1168 p = prefix_ipv4_new ();
1169 *p = cp;
1170 ifc->address = (struct prefix *) p;
1171
1172 /* Broadcast. */
hasso3fb9cd62004-10-19 19:44:43 +00001173 if (p->prefixlen <= IPV4_MAX_PREFIXLEN-2)
paul718e3742002-12-13 20:15:29 +00001174 {
1175 p = prefix_ipv4_new ();
1176 *p = cp;
hasso3fb9cd62004-10-19 19:44:43 +00001177 p->prefix.s_addr = ipv4_broadcast_addr(p->prefix.s_addr,p->prefixlen);
paul718e3742002-12-13 20:15:29 +00001178 ifc->destination = (struct prefix *) p;
1179 }
1180
paul718e3742002-12-13 20:15:29 +00001181 /* Label. */
1182 if (label)
1183 ifc->label = strdup (label);
1184
1185 /* Add to linked list. */
1186 listnode_add (ifp->connected, ifc);
1187 }
1188
1189 /* This address is configured from zebra. */
1190 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1191 SET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED);
1192
1193 /* In case of this route need to install kernel. */
1194 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1195 && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1196 {
1197 /* Some system need to up the interface to set IP address. */
1198 if (! if_is_up (ifp))
1199 {
1200 if_set_flags (ifp, IFF_UP | IFF_RUNNING);
1201 if_refresh (ifp);
1202 }
1203
1204 ret = if_set_prefix (ifp, ifc);
1205 if (ret < 0)
1206 {
1207 vty_out (vty, "%% Can't set interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001208 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001209 return CMD_WARNING;
1210 }
1211
hassoeef1fe12004-10-03 18:46:08 +00001212 /* Add to subnet chain list (while marking secondary attribute). */
1213 if_subnet_add (ifp, ifc);
1214
paul718e3742002-12-13 20:15:29 +00001215 /* IP address propery set. */
1216 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
1217
1218 /* Update interface address information to protocol daemon. */
1219 zebra_interface_address_add_update (ifp, ifc);
1220
1221 /* If interface is up register connected route. */
paul2e3b2e42002-12-13 21:03:13 +00001222 if (if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001223 connected_up_ipv4 (ifp, ifc);
1224 }
1225
1226 return CMD_SUCCESS;
1227}
1228
1229int
hasso39db97e2004-10-12 20:50:58 +00001230ip_address_uninstall (struct vty *vty, struct interface *ifp,
1231 const char *addr_str, const char *peer_str,
1232 const char *label)
paul718e3742002-12-13 20:15:29 +00001233{
1234 struct prefix_ipv4 cp;
1235 struct connected *ifc;
1236 int ret;
1237
1238 /* Convert to prefix structure. */
1239 ret = str2prefix_ipv4 (addr_str, &cp);
1240 if (ret <= 0)
1241 {
1242 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1243 return CMD_WARNING;
1244 }
1245
1246 /* Check current interface address. */
1247 ifc = connected_check_ipv4 (ifp, (struct prefix *) &cp);
1248 if (! ifc)
1249 {
1250 vty_out (vty, "%% Can't find address%s", VTY_NEWLINE);
1251 return CMD_WARNING;
1252 }
1253
1254 /* This is not configured address. */
1255 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1256 return CMD_WARNING;
1257
1258 /* This is not real address or interface is not active. */
1259 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1260 || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1261 {
1262 listnode_delete (ifp->connected, ifc);
1263 connected_free (ifc);
1264 return CMD_WARNING;
1265 }
1266
1267 /* This is real route. */
1268 ret = if_unset_prefix (ifp, ifc);
1269 if (ret < 0)
1270 {
1271 vty_out (vty, "%% Can't unset interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001272 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001273 return CMD_WARNING;
1274 }
1275
hassoeef1fe12004-10-03 18:46:08 +00001276#if 0
paul718e3742002-12-13 20:15:29 +00001277 /* Redistribute this information. */
1278 zebra_interface_address_delete_update (ifp, ifc);
1279
1280 /* Remove connected route. */
1281 connected_down_ipv4 (ifp, ifc);
1282
1283 /* Free address information. */
1284 listnode_delete (ifp->connected, ifc);
1285 connected_free (ifc);
hassoeef1fe12004-10-03 18:46:08 +00001286#endif
paul718e3742002-12-13 20:15:29 +00001287
1288 return CMD_SUCCESS;
1289}
1290
1291DEFUN (ip_address,
1292 ip_address_cmd,
1293 "ip address A.B.C.D/M",
1294 "Interface Internet Protocol config commands\n"
1295 "Set the IP address of an interface\n"
1296 "IP address (e.g. 10.0.0.1/8)\n")
1297{
hassoeef1fe12004-10-03 18:46:08 +00001298 return ip_address_install (vty, vty->index, argv[0], NULL, NULL);
paul718e3742002-12-13 20:15:29 +00001299}
1300
1301DEFUN (no_ip_address,
1302 no_ip_address_cmd,
1303 "no ip address A.B.C.D/M",
1304 NO_STR
1305 "Interface Internet Protocol config commands\n"
1306 "Set the IP address of an interface\n"
1307 "IP Address (e.g. 10.0.0.1/8)")
1308{
hassoeef1fe12004-10-03 18:46:08 +00001309 return ip_address_uninstall (vty, vty->index, argv[0], NULL, NULL);
paul718e3742002-12-13 20:15:29 +00001310}
1311
1312#ifdef HAVE_NETLINK
paul718e3742002-12-13 20:15:29 +00001313DEFUN (ip_address_label,
1314 ip_address_label_cmd,
1315 "ip address A.B.C.D/M label LINE",
1316 "Interface Internet Protocol config commands\n"
1317 "Set the IP address of an interface\n"
1318 "IP address (e.g. 10.0.0.1/8)\n"
1319 "Label of this address\n"
1320 "Label\n")
1321{
hassoeef1fe12004-10-03 18:46:08 +00001322 return ip_address_install (vty, vty->index, argv[0], NULL, argv[1]);
paul718e3742002-12-13 20:15:29 +00001323}
1324
1325DEFUN (no_ip_address_label,
1326 no_ip_address_label_cmd,
1327 "no ip address A.B.C.D/M label LINE",
1328 NO_STR
1329 "Interface Internet Protocol config commands\n"
1330 "Set the IP address of an interface\n"
1331 "IP address (e.g. 10.0.0.1/8)\n"
1332 "Label of this address\n"
1333 "Label\n")
1334{
hassoeef1fe12004-10-03 18:46:08 +00001335 return ip_address_uninstall (vty, vty->index, argv[0], NULL, argv[1]);
paul718e3742002-12-13 20:15:29 +00001336}
1337#endif /* HAVE_NETLINK */
1338
1339#ifdef HAVE_IPV6
1340int
hasso39db97e2004-10-12 20:50:58 +00001341ipv6_address_install (struct vty *vty, struct interface *ifp,
1342 const char *addr_str, const char *peer_str,
1343 const char *label, int secondary)
paul718e3742002-12-13 20:15:29 +00001344{
1345 struct prefix_ipv6 cp;
1346 struct connected *ifc;
1347 struct prefix_ipv6 *p;
1348 int ret;
1349
1350 ret = str2prefix_ipv6 (addr_str, &cp);
1351 if (ret <= 0)
1352 {
1353 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1354 return CMD_WARNING;
1355 }
1356
1357 ifc = connected_check_ipv6 (ifp, (struct prefix *) &cp);
1358 if (! ifc)
1359 {
1360 ifc = connected_new ();
1361 ifc->ifp = ifp;
1362
1363 /* Address. */
1364 p = prefix_ipv6_new ();
1365 *p = cp;
1366 ifc->address = (struct prefix *) p;
1367
1368 /* Secondary. */
1369 if (secondary)
1370 SET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY);
1371
1372 /* Label. */
1373 if (label)
1374 ifc->label = strdup (label);
1375
1376 /* Add to linked list. */
1377 listnode_add (ifp->connected, ifc);
1378 }
1379
1380 /* This address is configured from zebra. */
1381 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1382 SET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED);
1383
1384 /* In case of this route need to install kernel. */
1385 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1386 && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1387 {
1388 /* Some system need to up the interface to set IP address. */
1389 if (! if_is_up (ifp))
1390 {
1391 if_set_flags (ifp, IFF_UP | IFF_RUNNING);
1392 if_refresh (ifp);
1393 }
1394
1395 ret = if_prefix_add_ipv6 (ifp, ifc);
1396
1397 if (ret < 0)
1398 {
1399 vty_out (vty, "%% Can't set interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001400 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001401 return CMD_WARNING;
1402 }
1403
1404 /* IP address propery set. */
1405 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
1406
1407 /* Update interface address information to protocol daemon. */
1408 zebra_interface_address_add_update (ifp, ifc);
1409
1410 /* If interface is up register connected route. */
paul2e3b2e42002-12-13 21:03:13 +00001411 if (if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001412 connected_up_ipv6 (ifp, ifc);
1413 }
1414
1415 return CMD_SUCCESS;
1416}
1417
1418int
hasso39db97e2004-10-12 20:50:58 +00001419ipv6_address_uninstall (struct vty *vty, struct interface *ifp,
1420 const char *addr_str, const char *peer_str,
1421 const char *label, int secondry)
paul718e3742002-12-13 20:15:29 +00001422{
1423 struct prefix_ipv6 cp;
1424 struct connected *ifc;
1425 int ret;
1426
1427 /* Convert to prefix structure. */
1428 ret = str2prefix_ipv6 (addr_str, &cp);
1429 if (ret <= 0)
1430 {
1431 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1432 return CMD_WARNING;
1433 }
1434
1435 /* Check current interface address. */
1436 ifc = connected_check_ipv6 (ifp, (struct prefix *) &cp);
1437 if (! ifc)
1438 {
1439 vty_out (vty, "%% Can't find address%s", VTY_NEWLINE);
1440 return CMD_WARNING;
1441 }
1442
1443 /* This is not configured address. */
1444 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1445 return CMD_WARNING;
1446
1447 /* This is not real address or interface is not active. */
1448 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1449 || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1450 {
1451 listnode_delete (ifp->connected, ifc);
1452 connected_free (ifc);
1453 return CMD_WARNING;
1454 }
1455
1456 /* This is real route. */
1457 ret = if_prefix_delete_ipv6 (ifp, ifc);
1458 if (ret < 0)
1459 {
1460 vty_out (vty, "%% Can't unset interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001461 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001462 return CMD_WARNING;
1463 }
1464
1465 /* Redistribute this information. */
1466 zebra_interface_address_delete_update (ifp, ifc);
1467
1468 /* Remove connected route. */
1469 connected_down_ipv6 (ifp, ifc);
1470
1471 /* Free address information. */
1472 listnode_delete (ifp->connected, ifc);
1473 connected_free (ifc);
1474
1475 return CMD_SUCCESS;
1476}
1477
1478DEFUN (ipv6_address,
1479 ipv6_address_cmd,
1480 "ipv6 address X:X::X:X/M",
hassoe23949c2004-03-11 15:54:02 +00001481 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001482 "Set the IP address of an interface\n"
1483 "IPv6 address (e.g. 3ffe:506::1/48)\n")
1484{
1485 return ipv6_address_install (vty, vty->index, argv[0], NULL, NULL, 0);
1486}
1487
1488DEFUN (no_ipv6_address,
1489 no_ipv6_address_cmd,
1490 "no ipv6 address X:X::X:X/M",
1491 NO_STR
hassoe23949c2004-03-11 15:54:02 +00001492 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001493 "Set the IP address of an interface\n"
1494 "IPv6 address (e.g. 3ffe:506::1/48)\n")
1495{
1496 return ipv6_address_uninstall (vty, vty->index, argv[0], NULL, NULL, 0);
1497}
1498#endif /* HAVE_IPV6 */
1499
paul718e3742002-12-13 20:15:29 +00001500int
1501if_config_write (struct vty *vty)
1502{
hasso52dc7ee2004-09-23 19:18:23 +00001503 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001504 struct interface *ifp;
1505 char buf[BUFSIZ];
1506
paul1eb8ef22005-04-07 07:30:20 +00001507 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00001508 {
1509 struct zebra_if *if_data;
hasso52dc7ee2004-09-23 19:18:23 +00001510 struct listnode *addrnode;
paul718e3742002-12-13 20:15:29 +00001511 struct connected *ifc;
1512 struct prefix *p;
1513
paul718e3742002-12-13 20:15:29 +00001514 if_data = ifp->info;
1515
1516 vty_out (vty, "interface %s%s", ifp->name,
1517 VTY_NEWLINE);
1518
1519 if (ifp->desc)
1520 vty_out (vty, " description %s%s", ifp->desc,
1521 VTY_NEWLINE);
1522
1523 /* Assign bandwidth here to avoid unnecessary interface flap
1524 while processing config script */
1525 if (ifp->bandwidth != 0)
1526 vty_out(vty, " bandwidth %u%s", ifp->bandwidth, VTY_NEWLINE);
1527
paul2e3b2e42002-12-13 21:03:13 +00001528 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION))
1529 vty_out(vty, " link-detect%s", VTY_NEWLINE);
1530
paul1eb8ef22005-04-07 07:30:20 +00001531 for (ALL_LIST_ELEMENTS_RO (ifp->connected, addrnode, ifc))
paul718e3742002-12-13 20:15:29 +00001532 {
paul718e3742002-12-13 20:15:29 +00001533 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1534 {
1535 p = ifc->address;
1536 vty_out (vty, " ip%s address %s/%d",
1537 p->family == AF_INET ? "" : "v6",
1538 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
1539 p->prefixlen);
1540
paul718e3742002-12-13 20:15:29 +00001541 if (ifc->label)
1542 vty_out (vty, " label %s", ifc->label);
1543
1544 vty_out (vty, "%s", VTY_NEWLINE);
1545 }
1546 }
1547
1548 if (if_data)
1549 {
1550 if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)
1551 vty_out (vty, " shutdown%s", VTY_NEWLINE);
1552
1553 if (if_data->multicast != IF_ZEBRA_MULTICAST_UNSPEC)
1554 vty_out (vty, " %smulticast%s",
1555 if_data->multicast == IF_ZEBRA_MULTICAST_ON ? "" : "no ",
1556 VTY_NEWLINE);
1557 }
1558
1559#ifdef RTADV
1560 rtadv_config_write (vty, ifp);
1561#endif /* RTADV */
1562
hassoca776982004-06-12 14:33:05 +00001563#ifdef HAVE_IRDP
1564 irdp_config_write (vty, ifp);
1565#endif /* IRDP */
1566
paul718e3742002-12-13 20:15:29 +00001567 vty_out (vty, "!%s", VTY_NEWLINE);
1568 }
1569 return 0;
1570}
1571
1572/* Allocate and initialize interface vector. */
1573void
1574zebra_if_init ()
1575{
1576 /* Initialize interface and new hook. */
1577 if_init ();
1578 if_add_hook (IF_NEW_HOOK, if_zebra_new_hook);
1579 if_add_hook (IF_DELETE_HOOK, if_zebra_delete_hook);
1580
1581 /* Install configuration write function. */
1582 install_node (&interface_node, if_config_write);
1583
1584 install_element (VIEW_NODE, &show_interface_cmd);
1585 install_element (ENABLE_NODE, &show_interface_cmd);
hassoed9bb6d2005-03-13 19:17:21 +00001586 install_element (ENABLE_NODE, &show_interface_desc_cmd);
paul718e3742002-12-13 20:15:29 +00001587 install_element (CONFIG_NODE, &zebra_interface_cmd);
paulbfc13532003-05-24 06:40:04 +00001588 install_element (CONFIG_NODE, &no_interface_cmd);
paul718e3742002-12-13 20:15:29 +00001589 install_default (INTERFACE_NODE);
1590 install_element (INTERFACE_NODE, &interface_desc_cmd);
1591 install_element (INTERFACE_NODE, &no_interface_desc_cmd);
1592 install_element (INTERFACE_NODE, &multicast_cmd);
1593 install_element (INTERFACE_NODE, &no_multicast_cmd);
paul2e3b2e42002-12-13 21:03:13 +00001594 install_element (INTERFACE_NODE, &linkdetect_cmd);
1595 install_element (INTERFACE_NODE, &no_linkdetect_cmd);
paul718e3742002-12-13 20:15:29 +00001596 install_element (INTERFACE_NODE, &shutdown_if_cmd);
1597 install_element (INTERFACE_NODE, &no_shutdown_if_cmd);
1598 install_element (INTERFACE_NODE, &bandwidth_if_cmd);
1599 install_element (INTERFACE_NODE, &no_bandwidth_if_cmd);
1600 install_element (INTERFACE_NODE, &no_bandwidth_if_val_cmd);
1601 install_element (INTERFACE_NODE, &ip_address_cmd);
1602 install_element (INTERFACE_NODE, &no_ip_address_cmd);
1603#ifdef HAVE_IPV6
1604 install_element (INTERFACE_NODE, &ipv6_address_cmd);
1605 install_element (INTERFACE_NODE, &no_ipv6_address_cmd);
1606#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +00001607#ifdef HAVE_NETLINK
paul718e3742002-12-13 20:15:29 +00001608 install_element (INTERFACE_NODE, &ip_address_label_cmd);
paul718e3742002-12-13 20:15:29 +00001609 install_element (INTERFACE_NODE, &no_ip_address_label_cmd);
paul718e3742002-12-13 20:15:29 +00001610#endif /* HAVE_NETLINK */
1611}