blob: 5f9c7a234e40324134343d0ea96494ed8201d880 [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 {
paul0752ef02005-11-03 12:35:21 +0000212 /* XXX: WTF is it trying to set flags here?
213 * caller has just gotten a new interface, has been
214 * handed the flags already. This code has no business
215 * trying to override administrative status of the interface.
216 * The only call path to here which doesn't originate from
217 * kernel event is irdp - what on earth is it trying to do?
218 *
219 * further RUNNING is not a settable flag on any system
220 * I (paulj) am aware of.
221 */
paul718e3742002-12-13 20:15:29 +0000222 if_set_flags (ifp, IFF_UP | IFF_RUNNING);
223 if_refresh (ifp);
224 }
225
226 ret = if_set_prefix (ifp, ifc);
227 if (ret < 0)
228 {
229 zlog_warn ("Can't set interface's address: %s",
ajs6099b3b2004-11-20 02:06:59 +0000230 safe_strerror(errno));
paul718e3742002-12-13 20:15:29 +0000231 continue;
232 }
hassoeef1fe12004-10-03 18:46:08 +0000233
234 /* Add to subnet chain list. */
235 if_subnet_add (ifp, ifc);
236
paul718e3742002-12-13 20:15:29 +0000237 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
238
239 zebra_interface_address_add_update (ifp, ifc);
240
paul2e3b2e42002-12-13 21:03:13 +0000241 if (if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000242 connected_up_ipv4 (ifp, ifc);
243 }
244#ifdef HAVE_IPV6
245 if (p->family == AF_INET6)
246 {
247 if (! if_is_up (ifp))
248 {
paul0752ef02005-11-03 12:35:21 +0000249 /* XXX: See long comment above */
paul718e3742002-12-13 20:15:29 +0000250 if_set_flags (ifp, IFF_UP | IFF_RUNNING);
251 if_refresh (ifp);
252 }
253
254 ret = if_prefix_add_ipv6 (ifp, ifc);
255 if (ret < 0)
256 {
257 zlog_warn ("Can't set interface's address: %s",
ajs6099b3b2004-11-20 02:06:59 +0000258 safe_strerror(errno));
paul718e3742002-12-13 20:15:29 +0000259 continue;
260 }
261 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
262
263 zebra_interface_address_add_update (ifp, ifc);
264
paul2e3b2e42002-12-13 21:03:13 +0000265 if (if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000266 connected_up_ipv6 (ifp, ifc);
267 }
268#endif /* HAVE_IPV6 */
269 }
270 }
271}
272
273/* Handle interface addition */
274void
275if_add_update (struct interface *ifp)
276{
paul48b33aa2002-12-13 20:52:52 +0000277 struct zebra_if *if_data;
278
279 if_data = ifp->info;
280 if (if_data->multicast == IF_ZEBRA_MULTICAST_ON)
281 if_set_flags (ifp, IFF_MULTICAST);
282 else if (if_data->multicast == IF_ZEBRA_MULTICAST_OFF)
283 if_unset_flags (ifp, IFF_MULTICAST);
284
paul718e3742002-12-13 20:15:29 +0000285 zebra_interface_add_update (ifp);
286
287 if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
288 {
289 SET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE);
290
291 if_addr_wakeup (ifp);
292
293 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +0000294 zlog_debug ("interface %s index %d becomes active.",
295 ifp->name, ifp->ifindex);
paul718e3742002-12-13 20:15:29 +0000296 }
297 else
298 {
299 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +0000300 zlog_debug ("interface %s index %d is added.", ifp->name, ifp->ifindex);
paul718e3742002-12-13 20:15:29 +0000301 }
302}
303
paul6eb88272005-07-29 14:36:00 +0000304/* Handle an interface delete event */
paul718e3742002-12-13 20:15:29 +0000305void
306if_delete_update (struct interface *ifp)
307{
308 struct listnode *node;
309 struct listnode *next;
hassoeef1fe12004-10-03 18:46:08 +0000310 struct listnode *first;
311 struct listnode *last;
paul718e3742002-12-13 20:15:29 +0000312 struct connected *ifc;
313 struct prefix *p;
hassoeef1fe12004-10-03 18:46:08 +0000314 struct route_node *rn;
315 struct zebra_if *zebra_if;
316 struct list *addr_list;
317
318 zebra_if = ifp->info;
paul718e3742002-12-13 20:15:29 +0000319
320 if (if_is_up(ifp))
321 {
322 zlog_err ("interface %s index %d is still up while being deleted.",
323 ifp->name, ifp->ifindex);
324 return;
325 }
326
327 /* Mark interface as inactive */
328 UNSET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE);
329
330 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +0000331 zlog_debug ("interface %s index %d is now inactive.",
paul718e3742002-12-13 20:15:29 +0000332 ifp->name, ifp->ifindex);
333
334 /* Delete connected routes from the kernel. */
335 if (ifp->connected)
336 {
hassoeef1fe12004-10-03 18:46:08 +0000337 last = NULL;
338 while ((node = (last ? last->next : listhead (ifp->connected))))
paul718e3742002-12-13 20:15:29 +0000339 {
paul1eb8ef22005-04-07 07:30:20 +0000340 ifc = listgetdata (node);
paul718e3742002-12-13 20:15:29 +0000341 p = ifc->address;
hassoeef1fe12004-10-03 18:46:08 +0000342
paul718e3742002-12-13 20:15:29 +0000343 if (p->family == AF_INET)
hassoeef1fe12004-10-03 18:46:08 +0000344 {
345 rn = route_node_lookup (zebra_if->ipv4_subnets, p);
346 route_unlock_node (rn);
347 addr_list = (struct list *) rn->info;
348
349 /* Remove addresses, secondaries first. */
350 first = listhead (addr_list);
351 for (node = first->next; node || first; node = next)
352 {
353 if (! node)
354 {
355 node = first;
356 first = NULL;
357 }
358 next = node->next;
359
paul1eb8ef22005-04-07 07:30:20 +0000360 ifc = listgetdata (node);
hassoeef1fe12004-10-03 18:46:08 +0000361 p = ifc->address;
362
363 connected_down_ipv4 (ifp, ifc);
364
365 zebra_interface_address_delete_update (ifp, ifc);
366
367 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
368
369 /* Remove from subnet chain. */
370 list_delete_node (addr_list, node);
371 route_unlock_node (rn);
372
373 /* Remove from interface address list (unconditionally). */
374 listnode_delete (ifp->connected, ifc);
375 connected_free (ifc);
376 }
377
378 /* Free chain list and respective route node. */
379 list_delete (addr_list);
380 rn->info = NULL;
381 route_unlock_node (rn);
382 }
paul718e3742002-12-13 20:15:29 +0000383#ifdef HAVE_IPV6
384 else if (p->family == AF_INET6)
hassoeef1fe12004-10-03 18:46:08 +0000385 {
386 connected_down_ipv6 (ifp, ifc);
paul718e3742002-12-13 20:15:29 +0000387
hassoeef1fe12004-10-03 18:46:08 +0000388 zebra_interface_address_delete_update (ifp, ifc);
paul718e3742002-12-13 20:15:29 +0000389
hassoeef1fe12004-10-03 18:46:08 +0000390 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
391
392 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
393 last = node;
394 else
395 {
396 listnode_delete (ifp->connected, ifc);
397 connected_free (ifc);
398 }
paul718e3742002-12-13 20:15:29 +0000399 }
hassoeef1fe12004-10-03 18:46:08 +0000400#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +0000401 }
402 }
403 zebra_interface_delete_update (ifp);
ajsd2fc8892005-04-02 18:38:43 +0000404
405 /* Update ifindex after distributing the delete message. This is in
406 case any client needs to have the old value of ifindex available
407 while processing the deletion. Each client daemon is responsible
408 for setting ifindex to IFINDEX_INTERNAL after processing the
409 interface deletion message. */
410 ifp->ifindex = IFINDEX_INTERNAL;
paul718e3742002-12-13 20:15:29 +0000411}
412
413/* Interface is up. */
414void
415if_up (struct interface *ifp)
416{
hasso52dc7ee2004-09-23 19:18:23 +0000417 struct listnode *node;
418 struct listnode *next;
paul718e3742002-12-13 20:15:29 +0000419 struct connected *ifc;
420 struct prefix *p;
421
422 /* Notify the protocol daemons. */
423 zebra_interface_up_update (ifp);
424
425 /* Install connected routes to the kernel. */
426 if (ifp->connected)
427 {
paul1eb8ef22005-04-07 07:30:20 +0000428 for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc))
paul718e3742002-12-13 20:15:29 +0000429 {
paul718e3742002-12-13 20:15:29 +0000430 p = ifc->address;
431
432 if (p->family == AF_INET)
433 connected_up_ipv4 (ifp, ifc);
434#ifdef HAVE_IPV6
435 else if (p->family == AF_INET6)
436 connected_up_ipv6 (ifp, ifc);
437#endif /* HAVE_IPV6 */
438 }
439 }
440
441 /* Examine all static routes. */
442 rib_update ();
443}
444
445/* Interface goes down. We have to manage different behavior of based
446 OS. */
447void
448if_down (struct interface *ifp)
449{
hasso52dc7ee2004-09-23 19:18:23 +0000450 struct listnode *node;
451 struct listnode *next;
paul718e3742002-12-13 20:15:29 +0000452 struct connected *ifc;
453 struct prefix *p;
454
455 /* Notify to the protocol daemons. */
456 zebra_interface_down_update (ifp);
457
458 /* Delete connected routes from the kernel. */
459 if (ifp->connected)
460 {
paul1eb8ef22005-04-07 07:30:20 +0000461 for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc))
paul718e3742002-12-13 20:15:29 +0000462 {
paul718e3742002-12-13 20:15:29 +0000463 p = ifc->address;
464
465 if (p->family == AF_INET)
466 connected_down_ipv4 (ifp, ifc);
467#ifdef HAVE_IPV6
468 else if (p->family == AF_INET6)
469 connected_down_ipv6 (ifp, ifc);
470#endif /* HAVE_IPV6 */
471 }
472 }
473
474 /* Examine all static routes which direct to the interface. */
475 rib_update ();
476}
477
478void
479if_refresh (struct interface *ifp)
480{
paul2e3b2e42002-12-13 21:03:13 +0000481 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000482 {
483 if_get_flags (ifp);
paul2e3b2e42002-12-13 21:03:13 +0000484 if (! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000485 if_down (ifp);
486 }
487 else
488 {
489 if_get_flags (ifp);
paul2e3b2e42002-12-13 21:03:13 +0000490 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000491 if_up (ifp);
492 }
493}
494
495/* Printout flag information into vty */
paula1ac18c2005-06-28 17:17:12 +0000496static void
paul718e3742002-12-13 20:15:29 +0000497if_flag_dump_vty (struct vty *vty, unsigned long flag)
498{
499 int separator = 0;
500
501#define IFF_OUT_VTY(X, Y) \
502 if ((X) && (flag & (X))) \
503 { \
504 if (separator) \
505 vty_out (vty, ","); \
506 else \
507 separator = 1; \
508 vty_out (vty, Y); \
509 }
510
511 vty_out (vty, "<");
512 IFF_OUT_VTY (IFF_UP, "UP");
513 IFF_OUT_VTY (IFF_BROADCAST, "BROADCAST");
514 IFF_OUT_VTY (IFF_DEBUG, "DEBUG");
515 IFF_OUT_VTY (IFF_LOOPBACK, "LOOPBACK");
516 IFF_OUT_VTY (IFF_POINTOPOINT, "POINTOPOINT");
517 IFF_OUT_VTY (IFF_NOTRAILERS, "NOTRAILERS");
518 IFF_OUT_VTY (IFF_RUNNING, "RUNNING");
519 IFF_OUT_VTY (IFF_NOARP, "NOARP");
520 IFF_OUT_VTY (IFF_PROMISC, "PROMISC");
521 IFF_OUT_VTY (IFF_ALLMULTI, "ALLMULTI");
522 IFF_OUT_VTY (IFF_OACTIVE, "OACTIVE");
523 IFF_OUT_VTY (IFF_SIMPLEX, "SIMPLEX");
524 IFF_OUT_VTY (IFF_LINK0, "LINK0");
525 IFF_OUT_VTY (IFF_LINK1, "LINK1");
526 IFF_OUT_VTY (IFF_LINK2, "LINK2");
527 IFF_OUT_VTY (IFF_MULTICAST, "MULTICAST");
paul44145db2004-05-09 11:00:23 +0000528#ifdef SOLARIS_IPV6
529 IFF_OUT_VTY (IFF_IPV4, "IFF_IPv4");
530 IFF_OUT_VTY (IFF_IPV6, "IFF_IPv6");
531#endif /* SOLARIS_IPV6 */
paul718e3742002-12-13 20:15:29 +0000532 vty_out (vty, ">");
533}
534
535/* Output prefix string to vty. */
paula1ac18c2005-06-28 17:17:12 +0000536static int
paul718e3742002-12-13 20:15:29 +0000537prefix_vty_out (struct vty *vty, struct prefix *p)
538{
539 char str[INET6_ADDRSTRLEN];
540
541 inet_ntop (p->family, &p->u.prefix, str, sizeof (str));
542 vty_out (vty, "%s", str);
543 return strlen (str);
544}
545
546/* Dump if address information to vty. */
paula1ac18c2005-06-28 17:17:12 +0000547static void
paul718e3742002-12-13 20:15:29 +0000548connected_dump_vty (struct vty *vty, struct connected *connected)
549{
550 struct prefix *p;
551 struct interface *ifp;
552
553 /* Set interface pointer. */
554 ifp = connected->ifp;
555
556 /* Print interface address. */
557 p = connected->address;
558 vty_out (vty, " %s ", prefix_family_str (p));
559 prefix_vty_out (vty, p);
560 vty_out (vty, "/%d", p->prefixlen);
561
562 /* If there is destination address, print it. */
563 p = connected->destination;
564 if (p)
565 {
566 if (p->family == AF_INET)
567 if (ifp->flags & IFF_BROADCAST)
568 {
569 vty_out (vty, " broadcast ");
570 prefix_vty_out (vty, p);
571 }
572
573 if (ifp->flags & IFF_POINTOPOINT)
574 {
575 vty_out (vty, " pointopoint ");
576 prefix_vty_out (vty, p);
577 }
578 }
579
580 if (CHECK_FLAG (connected->flags, ZEBRA_IFA_SECONDARY))
581 vty_out (vty, " secondary");
582
583 if (connected->label)
584 vty_out (vty, " %s", connected->label);
585
586 vty_out (vty, "%s", VTY_NEWLINE);
587}
588
589#ifdef RTADV
590/* Dump interface ND information to vty. */
paula1ac18c2005-06-28 17:17:12 +0000591static void
paul718e3742002-12-13 20:15:29 +0000592nd_dump_vty (struct vty *vty, struct interface *ifp)
593{
594 struct zebra_if *zif;
595 struct rtadvconf *rtadv;
vincent7cee1bb2005-03-25 13:08:53 +0000596 int interval;
paul718e3742002-12-13 20:15:29 +0000597
598 zif = (struct zebra_if *) ifp->info;
599 rtadv = &zif->rtadv;
600
601 if (rtadv->AdvSendAdvertisements)
602 {
603 vty_out (vty, " ND advertised reachable time is %d milliseconds%s",
604 rtadv->AdvReachableTime, VTY_NEWLINE);
605 vty_out (vty, " ND advertised retransmit interval is %d milliseconds%s",
606 rtadv->AdvRetransTimer, VTY_NEWLINE);
vincent7cee1bb2005-03-25 13:08:53 +0000607 interval = rtadv->MaxRtrAdvInterval;
608 if (interval % 1000)
609 vty_out (vty, " ND router advertisements are sent every "
610 "%d milliseconds%s", interval,
611 VTY_NEWLINE);
612 else
613 vty_out (vty, " ND router advertisements are sent every "
614 "%d seconds%s", interval / 1000,
615 VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000616 vty_out (vty, " ND router advertisements live for %d seconds%s",
617 rtadv->AdvDefaultLifetime, VTY_NEWLINE);
618 if (rtadv->AdvManagedFlag)
619 vty_out (vty, " Hosts use DHCP to obtain routable addresses.%s",
620 VTY_NEWLINE);
621 else
622 vty_out (vty, " Hosts use stateless autoconfig for addresses.%s",
623 VTY_NEWLINE);
vincent7cee1bb2005-03-25 13:08:53 +0000624 if (rtadv->AdvHomeAgentFlag)
625 vty_out (vty, " ND router advertisements with "
626 "Home Agent flag bit set.%s",
627 VTY_NEWLINE);
628 if (rtadv->AdvIntervalOption)
629 vty_out (vty, " ND router advertisements with Adv. Interval option.%s",
630 VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000631 }
632}
633#endif /* RTADV */
634
635/* Interface's information print out to vty interface. */
paula1ac18c2005-06-28 17:17:12 +0000636static void
paul718e3742002-12-13 20:15:29 +0000637if_dump_vty (struct vty *vty, struct interface *ifp)
638{
639#ifdef HAVE_SOCKADDR_DL
640 struct sockaddr_dl *sdl;
641#endif /* HAVE_SOCKADDR_DL */
642 struct connected *connected;
hasso52dc7ee2004-09-23 19:18:23 +0000643 struct listnode *node;
hassoeef1fe12004-10-03 18:46:08 +0000644 struct route_node *rn;
645 struct zebra_if *zebra_if;
646
647 zebra_if = ifp->info;
paul718e3742002-12-13 20:15:29 +0000648
paul2e3b2e42002-12-13 21:03:13 +0000649 vty_out (vty, "Interface %s is ", ifp->name);
650 if (if_is_up(ifp)) {
651 vty_out (vty, "up, line protocol ");
652
653 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) {
654 if (if_is_running(ifp))
655 vty_out (vty, "is up%s", VTY_NEWLINE);
656 else
657 vty_out (vty, "is down%s", VTY_NEWLINE);
658 } else {
659 vty_out (vty, "detection is disabled%s", VTY_NEWLINE);
660 }
661 } else {
662 vty_out (vty, "down%s", VTY_NEWLINE);
663 }
664
paul718e3742002-12-13 20:15:29 +0000665 if (ifp->desc)
666 vty_out (vty, " Description: %s%s", ifp->desc,
667 VTY_NEWLINE);
ajsd2fc8892005-04-02 18:38:43 +0000668 if (ifp->ifindex == IFINDEX_INTERNAL)
paul718e3742002-12-13 20:15:29 +0000669 {
ajsd2fc8892005-04-02 18:38:43 +0000670 vty_out(vty, " pseudo interface%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000671 return;
672 }
673 else if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
674 {
675 vty_out(vty, " index %d inactive interface%s",
676 ifp->ifindex,
677 VTY_NEWLINE);
678 return;
679 }
680
681 vty_out (vty, " index %d metric %d mtu %d ",
682 ifp->ifindex, ifp->metric, ifp->mtu);
683 if_flag_dump_vty (vty, ifp->flags);
paul44145db2004-05-09 11:00:23 +0000684#ifdef HAVE_IPV6
685 if (ifp->mtu6 != ifp->mtu)
686 vty_out (vty, "mtu6 %d ", ifp->mtu6);
687#endif
688
paul718e3742002-12-13 20:15:29 +0000689 vty_out (vty, "%s", VTY_NEWLINE);
690
691 /* Hardware address. */
692#ifdef HAVE_SOCKADDR_DL
693 sdl = &ifp->sdl;
694 if (sdl != NULL && sdl->sdl_alen != 0)
695 {
696 int i;
697 u_char *ptr;
698
699 vty_out (vty, " HWaddr: ");
paul5b73a672004-07-23 15:26:14 +0000700 for (i = 0, ptr = (u_char *)LLADDR (sdl); i < sdl->sdl_alen; i++, ptr++)
701 vty_out (vty, "%s%02x", i == 0 ? "" : ":", *ptr);
paul718e3742002-12-13 20:15:29 +0000702 vty_out (vty, "%s", VTY_NEWLINE);
703 }
704#else
705 if (ifp->hw_addr_len != 0)
706 {
707 int i;
708
709 vty_out (vty, " HWaddr: ");
710 for (i = 0; i < ifp->hw_addr_len; i++)
711 vty_out (vty, "%s%02x", i == 0 ? "" : ":", ifp->hw_addr[i]);
712 vty_out (vty, "%s", VTY_NEWLINE);
713 }
714#endif /* HAVE_SOCKADDR_DL */
715
716 /* Bandwidth in kbps */
717 if (ifp->bandwidth != 0)
718 {
719 vty_out(vty, " bandwidth %u kbps", ifp->bandwidth);
720 vty_out(vty, "%s", VTY_NEWLINE);
721 }
722
hassoeef1fe12004-10-03 18:46:08 +0000723 for (rn = route_top (zebra_if->ipv4_subnets); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000724 {
hassoeef1fe12004-10-03 18:46:08 +0000725 if (! rn->info)
726 continue;
727
paul1eb8ef22005-04-07 07:30:20 +0000728 for (ALL_LIST_ELEMENTS_RO ((struct list *)rn->info, node, connected))
729 connected_dump_vty (vty, connected);
paul718e3742002-12-13 20:15:29 +0000730 }
731
paul1eb8ef22005-04-07 07:30:20 +0000732 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
hasso39db97e2004-10-12 20:50:58 +0000733 {
hasso39db97e2004-10-12 20:50:58 +0000734 if (CHECK_FLAG (connected->conf, ZEBRA_IFC_REAL) &&
735 (connected->address->family == AF_INET6))
736 connected_dump_vty (vty, connected);
737 }
738
paul718e3742002-12-13 20:15:29 +0000739#ifdef RTADV
740 nd_dump_vty (vty, ifp);
741#endif /* RTADV */
742
743#ifdef HAVE_PROC_NET_DEV
744 /* Statistics print out using proc file system. */
hasso6f2c27a2005-01-18 13:44:35 +0000745 vty_out (vty, " %lu input packets (%lu multicast), %lu bytes, "
746 "%lu dropped%s",
747 ifp->stats.rx_packets, ifp->stats.rx_multicast,
748 ifp->stats.rx_bytes, ifp->stats.rx_dropped, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000749
hasso6f2c27a2005-01-18 13:44:35 +0000750 vty_out (vty, " %lu input errors, %lu length, %lu overrun,"
hasso3452d472005-03-06 13:42:05 +0000751 " %lu CRC, %lu frame%s",
paul718e3742002-12-13 20:15:29 +0000752 ifp->stats.rx_errors, ifp->stats.rx_length_errors,
753 ifp->stats.rx_over_errors, ifp->stats.rx_crc_errors,
hasso6f2c27a2005-01-18 13:44:35 +0000754 ifp->stats.rx_frame_errors, VTY_NEWLINE);
755
756 vty_out (vty, " %lu fifo, %lu missed%s", ifp->stats.rx_fifo_errors,
paul718e3742002-12-13 20:15:29 +0000757 ifp->stats.rx_missed_errors, VTY_NEWLINE);
758
hasso6f2c27a2005-01-18 13:44:35 +0000759 vty_out (vty, " %lu output packets, %lu bytes, %lu dropped%s",
paul718e3742002-12-13 20:15:29 +0000760 ifp->stats.tx_packets, ifp->stats.tx_bytes,
761 ifp->stats.tx_dropped, VTY_NEWLINE);
762
hasso6f2c27a2005-01-18 13:44:35 +0000763 vty_out (vty, " %lu output errors, %lu aborted, %lu carrier,"
764 " %lu fifo, %lu heartbeat%s",
paul718e3742002-12-13 20:15:29 +0000765 ifp->stats.tx_errors, ifp->stats.tx_aborted_errors,
766 ifp->stats.tx_carrier_errors, ifp->stats.tx_fifo_errors,
hasso6f2c27a2005-01-18 13:44:35 +0000767 ifp->stats.tx_heartbeat_errors, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000768
hasso6f2c27a2005-01-18 13:44:35 +0000769 vty_out (vty, " %lu window, %lu collisions%s",
770 ifp->stats.tx_window_errors, ifp->stats.collisions, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000771#endif /* HAVE_PROC_NET_DEV */
772
773#ifdef HAVE_NET_RT_IFLIST
774#if defined (__bsdi__) || defined (__NetBSD__)
775 /* Statistics print out using sysctl (). */
776 vty_out (vty, " input packets %qu, bytes %qu, dropped %qu,"
777 " multicast packets %qu%s",
778 ifp->stats.ifi_ipackets, ifp->stats.ifi_ibytes,
779 ifp->stats.ifi_iqdrops, ifp->stats.ifi_imcasts,
780 VTY_NEWLINE);
781
782 vty_out (vty, " input errors %qu%s",
783 ifp->stats.ifi_ierrors, VTY_NEWLINE);
784
785 vty_out (vty, " output packets %qu, bytes %qu, multicast packets %qu%s",
786 ifp->stats.ifi_opackets, ifp->stats.ifi_obytes,
787 ifp->stats.ifi_omcasts, VTY_NEWLINE);
788
789 vty_out (vty, " output errors %qu%s",
790 ifp->stats.ifi_oerrors, VTY_NEWLINE);
791
792 vty_out (vty, " collisions %qu%s",
793 ifp->stats.ifi_collisions, VTY_NEWLINE);
794#else
795 /* Statistics print out using sysctl (). */
796 vty_out (vty, " input packets %lu, bytes %lu, dropped %lu,"
797 " multicast packets %lu%s",
798 ifp->stats.ifi_ipackets, ifp->stats.ifi_ibytes,
799 ifp->stats.ifi_iqdrops, ifp->stats.ifi_imcasts,
800 VTY_NEWLINE);
801
802 vty_out (vty, " input errors %lu%s",
803 ifp->stats.ifi_ierrors, VTY_NEWLINE);
804
805 vty_out (vty, " output packets %lu, bytes %lu, multicast packets %lu%s",
806 ifp->stats.ifi_opackets, ifp->stats.ifi_obytes,
807 ifp->stats.ifi_omcasts, VTY_NEWLINE);
808
809 vty_out (vty, " output errors %lu%s",
810 ifp->stats.ifi_oerrors, VTY_NEWLINE);
811
812 vty_out (vty, " collisions %lu%s",
813 ifp->stats.ifi_collisions, VTY_NEWLINE);
814#endif /* __bsdi__ || __NetBSD__ */
815#endif /* HAVE_NET_RT_IFLIST */
816}
817
818/* Check supported address family. */
paula1ac18c2005-06-28 17:17:12 +0000819static int
paul718e3742002-12-13 20:15:29 +0000820if_supported_family (int family)
821{
822 if (family == AF_INET)
823 return 1;
824#ifdef HAVE_IPV6
825 if (family == AF_INET6)
826 return 1;
827#endif /* HAVE_IPV6 */
828 return 0;
829}
830
831/* Wrapper hook point for zebra daemon so that ifindex can be set
832 * DEFUN macro not used as extract.pl HAS to ignore this
833 * See also interface_cmd in lib/if.c
834 */
835DEFUN_NOSH (zebra_interface,
836 zebra_interface_cmd,
837 "interface IFNAME",
838 "Select an interface to configure\n"
839 "Interface's name\n")
840{
841 int ret;
842 struct interface * ifp;
843
844 /* Call lib interface() */
ajsd2fc8892005-04-02 18:38:43 +0000845 if ((ret = interface_cmd.func (self, vty, argc, argv)) != CMD_SUCCESS)
846 return ret;
paul718e3742002-12-13 20:15:29 +0000847
848 ifp = vty->index;
849
ajsd2fc8892005-04-02 18:38:43 +0000850 if (ifp->ifindex == IFINDEX_INTERNAL)
851 /* Is this really necessary? Shouldn't status be initialized to 0
852 in that case? */
853 UNSET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE);
paul718e3742002-12-13 20:15:29 +0000854
855 return ret;
856}
857
paul718e3742002-12-13 20:15:29 +0000858struct cmd_node interface_node =
859{
860 INTERFACE_NODE,
861 "%s(config-if)# ",
862 1
863};
864
865/* Show all or specified interface to vty. */
866DEFUN (show_interface, show_interface_cmd,
867 "show interface [IFNAME]",
868 SHOW_STR
869 "Interface status and configuration\n"
870 "Inteface name\n")
871{
hasso52dc7ee2004-09-23 19:18:23 +0000872 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000873 struct interface *ifp;
874
875#ifdef HAVE_PROC_NET_DEV
876 /* If system has interface statistics via proc file system, update
877 statistics. */
878 ifstat_update_proc ();
879#endif /* HAVE_PROC_NET_DEV */
880#ifdef HAVE_NET_RT_IFLIST
881 ifstat_update_sysctl ();
882#endif /* HAVE_NET_RT_IFLIST */
883
884 /* Specified interface print. */
885 if (argc != 0)
886 {
887 ifp = if_lookup_by_name (argv[0]);
888 if (ifp == NULL)
889 {
890 vty_out (vty, "%% Can't find interface %s%s", argv[0],
891 VTY_NEWLINE);
892 return CMD_WARNING;
893 }
894 if_dump_vty (vty, ifp);
895 return CMD_SUCCESS;
896 }
897
898 /* All interface print. */
paul1eb8ef22005-04-07 07:30:20 +0000899 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
900 if_dump_vty (vty, ifp);
paul718e3742002-12-13 20:15:29 +0000901
902 return CMD_SUCCESS;
903}
904
hassoed9bb6d2005-03-13 19:17:21 +0000905DEFUN (show_interface_desc,
906 show_interface_desc_cmd,
907 "show interface description",
908 SHOW_STR
909 "Interface status and configuration\n"
910 "Interface description\n")
911{
912 struct listnode *node;
913 struct interface *ifp;
914
915 vty_out (vty, "Interface Status Protocol Description%s", VTY_NEWLINE);
paul1eb8ef22005-04-07 07:30:20 +0000916 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
hassoed9bb6d2005-03-13 19:17:21 +0000917 {
918 int len;
hassoed9bb6d2005-03-13 19:17:21 +0000919
920 len = vty_out (vty, "%s", ifp->name);
921 vty_out (vty, "%*s", (16 - len), " ");
922
923 if (if_is_up(ifp))
924 {
925 vty_out (vty, "up ");
926 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION))
927 {
928 if (if_is_running(ifp))
929 vty_out (vty, "up ");
930 else
931 vty_out (vty, "down ");
932 }
933 else
934 {
935 vty_out (vty, "unknown ");
936 }
937 }
938 else
939 {
940 vty_out (vty, "down down ");
941 }
942
943 if (ifp->desc)
944 vty_out (vty, "%s", ifp->desc);
945 vty_out (vty, "%s", VTY_NEWLINE);
946 }
947 return CMD_SUCCESS;
948}
949
paul718e3742002-12-13 20:15:29 +0000950DEFUN (multicast,
951 multicast_cmd,
952 "multicast",
953 "Set multicast flag to interface\n")
954{
955 int ret;
956 struct interface *ifp;
957 struct zebra_if *if_data;
958
959 ifp = (struct interface *) vty->index;
paul48b33aa2002-12-13 20:52:52 +0000960 if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
paul718e3742002-12-13 20:15:29 +0000961 {
paul48b33aa2002-12-13 20:52:52 +0000962 ret = if_set_flags (ifp, IFF_MULTICAST);
963 if (ret < 0)
964 {
965 vty_out (vty, "Can't set multicast flag%s", VTY_NEWLINE);
966 return CMD_WARNING;
967 }
968 if_refresh (ifp);
paul718e3742002-12-13 20:15:29 +0000969 }
paul718e3742002-12-13 20:15:29 +0000970 if_data = ifp->info;
971 if_data->multicast = IF_ZEBRA_MULTICAST_ON;
paul48b33aa2002-12-13 20:52:52 +0000972
paul718e3742002-12-13 20:15:29 +0000973 return CMD_SUCCESS;
974}
975
976DEFUN (no_multicast,
977 no_multicast_cmd,
978 "no multicast",
979 NO_STR
980 "Unset multicast flag to interface\n")
981{
982 int ret;
983 struct interface *ifp;
984 struct zebra_if *if_data;
985
986 ifp = (struct interface *) vty->index;
paul48b33aa2002-12-13 20:52:52 +0000987 if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
paul718e3742002-12-13 20:15:29 +0000988 {
paul48b33aa2002-12-13 20:52:52 +0000989 ret = if_unset_flags (ifp, IFF_MULTICAST);
990 if (ret < 0)
991 {
992 vty_out (vty, "Can't unset multicast flag%s", VTY_NEWLINE);
993 return CMD_WARNING;
994 }
995 if_refresh (ifp);
paul718e3742002-12-13 20:15:29 +0000996 }
paul718e3742002-12-13 20:15:29 +0000997 if_data = ifp->info;
998 if_data->multicast = IF_ZEBRA_MULTICAST_OFF;
999
1000 return CMD_SUCCESS;
1001}
1002
paul2e3b2e42002-12-13 21:03:13 +00001003DEFUN (linkdetect,
1004 linkdetect_cmd,
1005 "link-detect",
1006 "Enable link detection on interface\n")
1007{
paul2e3b2e42002-12-13 21:03:13 +00001008 struct interface *ifp;
1009 int if_was_operative;
1010
1011 ifp = (struct interface *) vty->index;
1012 if_was_operative = if_is_operative(ifp);
1013 SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
1014
1015 /* When linkdetection is enabled, if might come down */
1016 if (!if_is_operative(ifp) && if_was_operative) if_down(ifp);
1017
1018 /* FIXME: Will defer status change forwarding if interface
1019 does not come down! */
1020
1021 return CMD_SUCCESS;
1022}
1023
1024
1025DEFUN (no_linkdetect,
1026 no_linkdetect_cmd,
1027 "no link-detect",
1028 NO_STR
1029 "Disable link detection on interface\n")
1030{
paul2e3b2e42002-12-13 21:03:13 +00001031 struct interface *ifp;
1032 int if_was_operative;
1033
1034 ifp = (struct interface *) vty->index;
1035 if_was_operative = if_is_operative(ifp);
1036 UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
1037
1038 /* Interface may come up after disabling link detection */
1039 if (if_is_operative(ifp) && !if_was_operative) if_up(ifp);
1040
1041 /* FIXME: see linkdetect_cmd */
1042
1043 return CMD_SUCCESS;
1044}
1045
paul718e3742002-12-13 20:15:29 +00001046DEFUN (shutdown_if,
1047 shutdown_if_cmd,
1048 "shutdown",
1049 "Shutdown the selected interface\n")
1050{
1051 int ret;
1052 struct interface *ifp;
1053 struct zebra_if *if_data;
1054
1055 ifp = (struct interface *) vty->index;
1056 ret = if_unset_flags (ifp, IFF_UP);
1057 if (ret < 0)
1058 {
1059 vty_out (vty, "Can't shutdown interface%s", VTY_NEWLINE);
1060 return CMD_WARNING;
1061 }
1062 if_refresh (ifp);
1063 if_data = ifp->info;
1064 if_data->shutdown = IF_ZEBRA_SHUTDOWN_ON;
1065
1066 return CMD_SUCCESS;
1067}
1068
1069DEFUN (no_shutdown_if,
1070 no_shutdown_if_cmd,
1071 "no shutdown",
1072 NO_STR
1073 "Shutdown the selected interface\n")
1074{
1075 int ret;
1076 struct interface *ifp;
1077 struct zebra_if *if_data;
1078
1079 ifp = (struct interface *) vty->index;
1080 ret = if_set_flags (ifp, IFF_UP | IFF_RUNNING);
1081 if (ret < 0)
1082 {
1083 vty_out (vty, "Can't up interface%s", VTY_NEWLINE);
1084 return CMD_WARNING;
1085 }
1086 if_refresh (ifp);
1087 if_data = ifp->info;
1088 if_data->shutdown = IF_ZEBRA_SHUTDOWN_OFF;
1089
1090 return CMD_SUCCESS;
1091}
1092
1093DEFUN (bandwidth_if,
1094 bandwidth_if_cmd,
1095 "bandwidth <1-10000000>",
1096 "Set bandwidth informational parameter\n"
1097 "Bandwidth in kilobits\n")
1098{
1099 struct interface *ifp;
1100 unsigned int bandwidth;
1101
1102 ifp = (struct interface *) vty->index;
1103 bandwidth = strtol(argv[0], NULL, 10);
1104
1105 /* bandwidth range is <1-10000000> */
1106 if (bandwidth < 1 || bandwidth > 10000000)
1107 {
1108 vty_out (vty, "Bandwidth is invalid%s", VTY_NEWLINE);
1109 return CMD_WARNING;
1110 }
1111
1112 ifp->bandwidth = bandwidth;
1113
1114 /* force protocols to recalculate routes due to cost change */
paul2e3b2e42002-12-13 21:03:13 +00001115 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00001116 zebra_interface_up_update (ifp);
1117
1118 return CMD_SUCCESS;
1119}
1120
1121DEFUN (no_bandwidth_if,
1122 no_bandwidth_if_cmd,
1123 "no bandwidth",
1124 NO_STR
1125 "Set bandwidth informational parameter\n")
1126{
1127 struct interface *ifp;
1128
1129 ifp = (struct interface *) vty->index;
1130
1131 ifp->bandwidth = 0;
1132
1133 /* force protocols to recalculate routes due to cost change */
paul2e3b2e42002-12-13 21:03:13 +00001134 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00001135 zebra_interface_up_update (ifp);
1136
1137 return CMD_SUCCESS;
1138}
1139
1140ALIAS (no_bandwidth_if,
1141 no_bandwidth_if_val_cmd,
1142 "no bandwidth <1-10000000>",
1143 NO_STR
1144 "Set bandwidth informational parameter\n"
1145 "Bandwidth in kilobits\n")
1146
paula1ac18c2005-06-28 17:17:12 +00001147static int
hasso39db97e2004-10-12 20:50:58 +00001148ip_address_install (struct vty *vty, struct interface *ifp,
1149 const char *addr_str, const char *peer_str,
1150 const char *label)
paul718e3742002-12-13 20:15:29 +00001151{
1152 struct prefix_ipv4 cp;
1153 struct connected *ifc;
1154 struct prefix_ipv4 *p;
paul718e3742002-12-13 20:15:29 +00001155 int ret;
1156
1157 ret = str2prefix_ipv4 (addr_str, &cp);
1158 if (ret <= 0)
1159 {
1160 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1161 return CMD_WARNING;
1162 }
1163
paulca162182005-09-12 16:58:52 +00001164 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001165 if (! ifc)
1166 {
1167 ifc = connected_new ();
1168 ifc->ifp = ifp;
1169
1170 /* Address. */
1171 p = prefix_ipv4_new ();
1172 *p = cp;
1173 ifc->address = (struct prefix *) p;
1174
1175 /* Broadcast. */
hasso3fb9cd62004-10-19 19:44:43 +00001176 if (p->prefixlen <= IPV4_MAX_PREFIXLEN-2)
paul718e3742002-12-13 20:15:29 +00001177 {
1178 p = prefix_ipv4_new ();
1179 *p = cp;
hasso3fb9cd62004-10-19 19:44:43 +00001180 p->prefix.s_addr = ipv4_broadcast_addr(p->prefix.s_addr,p->prefixlen);
paul718e3742002-12-13 20:15:29 +00001181 ifc->destination = (struct prefix *) p;
1182 }
1183
paul718e3742002-12-13 20:15:29 +00001184 /* Label. */
1185 if (label)
paul0752ef02005-11-03 12:35:21 +00001186 ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
paul718e3742002-12-13 20:15:29 +00001187
1188 /* Add to linked list. */
1189 listnode_add (ifp->connected, ifc);
1190 }
1191
1192 /* This address is configured from zebra. */
1193 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1194 SET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED);
1195
1196 /* In case of this route need to install kernel. */
1197 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1198 && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1199 {
1200 /* Some system need to up the interface to set IP address. */
1201 if (! if_is_up (ifp))
1202 {
1203 if_set_flags (ifp, IFF_UP | IFF_RUNNING);
1204 if_refresh (ifp);
1205 }
1206
1207 ret = if_set_prefix (ifp, ifc);
1208 if (ret < 0)
1209 {
1210 vty_out (vty, "%% Can't set interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001211 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001212 return CMD_WARNING;
1213 }
1214
hassoeef1fe12004-10-03 18:46:08 +00001215 /* Add to subnet chain list (while marking secondary attribute). */
1216 if_subnet_add (ifp, ifc);
1217
paul718e3742002-12-13 20:15:29 +00001218 /* IP address propery set. */
1219 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
1220
1221 /* Update interface address information to protocol daemon. */
1222 zebra_interface_address_add_update (ifp, ifc);
1223
1224 /* If interface is up register connected route. */
paul2e3b2e42002-12-13 21:03:13 +00001225 if (if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001226 connected_up_ipv4 (ifp, ifc);
1227 }
1228
1229 return CMD_SUCCESS;
1230}
1231
paula1ac18c2005-06-28 17:17:12 +00001232static int
hasso39db97e2004-10-12 20:50:58 +00001233ip_address_uninstall (struct vty *vty, struct interface *ifp,
1234 const char *addr_str, const char *peer_str,
1235 const char *label)
paul718e3742002-12-13 20:15:29 +00001236{
1237 struct prefix_ipv4 cp;
1238 struct connected *ifc;
1239 int ret;
1240
1241 /* Convert to prefix structure. */
1242 ret = str2prefix_ipv4 (addr_str, &cp);
1243 if (ret <= 0)
1244 {
1245 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1246 return CMD_WARNING;
1247 }
1248
1249 /* Check current interface address. */
paulca162182005-09-12 16:58:52 +00001250 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001251 if (! ifc)
1252 {
1253 vty_out (vty, "%% Can't find address%s", VTY_NEWLINE);
1254 return CMD_WARNING;
1255 }
1256
1257 /* This is not configured address. */
1258 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1259 return CMD_WARNING;
1260
1261 /* This is not real address or interface is not active. */
1262 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1263 || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1264 {
1265 listnode_delete (ifp->connected, ifc);
1266 connected_free (ifc);
1267 return CMD_WARNING;
1268 }
1269
1270 /* This is real route. */
1271 ret = if_unset_prefix (ifp, ifc);
1272 if (ret < 0)
1273 {
1274 vty_out (vty, "%% Can't unset interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001275 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001276 return CMD_WARNING;
1277 }
1278
hassoeef1fe12004-10-03 18:46:08 +00001279#if 0
paul718e3742002-12-13 20:15:29 +00001280 /* Redistribute this information. */
1281 zebra_interface_address_delete_update (ifp, ifc);
1282
1283 /* Remove connected route. */
1284 connected_down_ipv4 (ifp, ifc);
1285
1286 /* Free address information. */
1287 listnode_delete (ifp->connected, ifc);
1288 connected_free (ifc);
hassoeef1fe12004-10-03 18:46:08 +00001289#endif
paul718e3742002-12-13 20:15:29 +00001290
1291 return CMD_SUCCESS;
1292}
1293
1294DEFUN (ip_address,
1295 ip_address_cmd,
1296 "ip address A.B.C.D/M",
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)\n")
1300{
hassoeef1fe12004-10-03 18:46:08 +00001301 return ip_address_install (vty, vty->index, argv[0], NULL, NULL);
paul718e3742002-12-13 20:15:29 +00001302}
1303
1304DEFUN (no_ip_address,
1305 no_ip_address_cmd,
1306 "no ip address A.B.C.D/M",
1307 NO_STR
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)")
1311{
hassoeef1fe12004-10-03 18:46:08 +00001312 return ip_address_uninstall (vty, vty->index, argv[0], NULL, NULL);
paul718e3742002-12-13 20:15:29 +00001313}
1314
1315#ifdef HAVE_NETLINK
paul718e3742002-12-13 20:15:29 +00001316DEFUN (ip_address_label,
1317 ip_address_label_cmd,
1318 "ip address A.B.C.D/M label LINE",
1319 "Interface Internet Protocol config commands\n"
1320 "Set the IP address of an interface\n"
1321 "IP address (e.g. 10.0.0.1/8)\n"
1322 "Label of this address\n"
1323 "Label\n")
1324{
hassoeef1fe12004-10-03 18:46:08 +00001325 return ip_address_install (vty, vty->index, argv[0], NULL, argv[1]);
paul718e3742002-12-13 20:15:29 +00001326}
1327
1328DEFUN (no_ip_address_label,
1329 no_ip_address_label_cmd,
1330 "no ip address A.B.C.D/M label LINE",
1331 NO_STR
1332 "Interface Internet Protocol config commands\n"
1333 "Set the IP address of an interface\n"
1334 "IP address (e.g. 10.0.0.1/8)\n"
1335 "Label of this address\n"
1336 "Label\n")
1337{
hassoeef1fe12004-10-03 18:46:08 +00001338 return ip_address_uninstall (vty, vty->index, argv[0], NULL, argv[1]);
paul718e3742002-12-13 20:15:29 +00001339}
1340#endif /* HAVE_NETLINK */
1341
1342#ifdef HAVE_IPV6
paula1ac18c2005-06-28 17:17:12 +00001343static int
hasso39db97e2004-10-12 20:50:58 +00001344ipv6_address_install (struct vty *vty, struct interface *ifp,
1345 const char *addr_str, const char *peer_str,
1346 const char *label, int secondary)
paul718e3742002-12-13 20:15:29 +00001347{
1348 struct prefix_ipv6 cp;
1349 struct connected *ifc;
1350 struct prefix_ipv6 *p;
1351 int ret;
1352
1353 ret = str2prefix_ipv6 (addr_str, &cp);
1354 if (ret <= 0)
1355 {
1356 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1357 return CMD_WARNING;
1358 }
1359
paulca162182005-09-12 16:58:52 +00001360 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001361 if (! ifc)
1362 {
1363 ifc = connected_new ();
1364 ifc->ifp = ifp;
1365
1366 /* Address. */
1367 p = prefix_ipv6_new ();
1368 *p = cp;
1369 ifc->address = (struct prefix *) p;
1370
1371 /* Secondary. */
1372 if (secondary)
1373 SET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY);
1374
1375 /* Label. */
1376 if (label)
paul0752ef02005-11-03 12:35:21 +00001377 ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
paul718e3742002-12-13 20:15:29 +00001378
1379 /* Add to linked list. */
1380 listnode_add (ifp->connected, ifc);
1381 }
1382
1383 /* This address is configured from zebra. */
1384 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1385 SET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED);
1386
1387 /* In case of this route need to install kernel. */
1388 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1389 && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1390 {
1391 /* Some system need to up the interface to set IP address. */
1392 if (! if_is_up (ifp))
1393 {
1394 if_set_flags (ifp, IFF_UP | IFF_RUNNING);
1395 if_refresh (ifp);
1396 }
1397
1398 ret = if_prefix_add_ipv6 (ifp, ifc);
1399
1400 if (ret < 0)
1401 {
1402 vty_out (vty, "%% Can't set interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001403 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001404 return CMD_WARNING;
1405 }
1406
1407 /* IP address propery set. */
1408 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
1409
1410 /* Update interface address information to protocol daemon. */
1411 zebra_interface_address_add_update (ifp, ifc);
1412
1413 /* If interface is up register connected route. */
paul2e3b2e42002-12-13 21:03:13 +00001414 if (if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001415 connected_up_ipv6 (ifp, ifc);
1416 }
1417
1418 return CMD_SUCCESS;
1419}
1420
paula1ac18c2005-06-28 17:17:12 +00001421static int
hasso39db97e2004-10-12 20:50:58 +00001422ipv6_address_uninstall (struct vty *vty, struct interface *ifp,
1423 const char *addr_str, const char *peer_str,
1424 const char *label, int secondry)
paul718e3742002-12-13 20:15:29 +00001425{
1426 struct prefix_ipv6 cp;
1427 struct connected *ifc;
1428 int ret;
1429
1430 /* Convert to prefix structure. */
1431 ret = str2prefix_ipv6 (addr_str, &cp);
1432 if (ret <= 0)
1433 {
1434 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1435 return CMD_WARNING;
1436 }
1437
1438 /* Check current interface address. */
paulca162182005-09-12 16:58:52 +00001439 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001440 if (! ifc)
1441 {
1442 vty_out (vty, "%% Can't find address%s", VTY_NEWLINE);
1443 return CMD_WARNING;
1444 }
1445
1446 /* This is not configured address. */
1447 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1448 return CMD_WARNING;
1449
1450 /* This is not real address or interface is not active. */
1451 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1452 || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1453 {
1454 listnode_delete (ifp->connected, ifc);
1455 connected_free (ifc);
1456 return CMD_WARNING;
1457 }
1458
1459 /* This is real route. */
1460 ret = if_prefix_delete_ipv6 (ifp, ifc);
1461 if (ret < 0)
1462 {
1463 vty_out (vty, "%% Can't unset interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001464 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001465 return CMD_WARNING;
1466 }
1467
1468 /* Redistribute this information. */
1469 zebra_interface_address_delete_update (ifp, ifc);
1470
1471 /* Remove connected route. */
1472 connected_down_ipv6 (ifp, ifc);
1473
1474 /* Free address information. */
1475 listnode_delete (ifp->connected, ifc);
1476 connected_free (ifc);
1477
1478 return CMD_SUCCESS;
1479}
1480
1481DEFUN (ipv6_address,
1482 ipv6_address_cmd,
1483 "ipv6 address X:X::X:X/M",
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_install (vty, vty->index, argv[0], NULL, NULL, 0);
1489}
1490
1491DEFUN (no_ipv6_address,
1492 no_ipv6_address_cmd,
1493 "no ipv6 address X:X::X:X/M",
1494 NO_STR
hassoe23949c2004-03-11 15:54:02 +00001495 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001496 "Set the IP address of an interface\n"
1497 "IPv6 address (e.g. 3ffe:506::1/48)\n")
1498{
1499 return ipv6_address_uninstall (vty, vty->index, argv[0], NULL, NULL, 0);
1500}
1501#endif /* HAVE_IPV6 */
1502
paula1ac18c2005-06-28 17:17:12 +00001503static int
paul718e3742002-12-13 20:15:29 +00001504if_config_write (struct vty *vty)
1505{
hasso52dc7ee2004-09-23 19:18:23 +00001506 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001507 struct interface *ifp;
1508 char buf[BUFSIZ];
1509
paul1eb8ef22005-04-07 07:30:20 +00001510 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00001511 {
1512 struct zebra_if *if_data;
hasso52dc7ee2004-09-23 19:18:23 +00001513 struct listnode *addrnode;
paul718e3742002-12-13 20:15:29 +00001514 struct connected *ifc;
1515 struct prefix *p;
1516
paul718e3742002-12-13 20:15:29 +00001517 if_data = ifp->info;
1518
1519 vty_out (vty, "interface %s%s", ifp->name,
1520 VTY_NEWLINE);
1521
1522 if (ifp->desc)
1523 vty_out (vty, " description %s%s", ifp->desc,
1524 VTY_NEWLINE);
1525
1526 /* Assign bandwidth here to avoid unnecessary interface flap
1527 while processing config script */
1528 if (ifp->bandwidth != 0)
1529 vty_out(vty, " bandwidth %u%s", ifp->bandwidth, VTY_NEWLINE);
1530
paul2e3b2e42002-12-13 21:03:13 +00001531 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION))
1532 vty_out(vty, " link-detect%s", VTY_NEWLINE);
1533
paul1eb8ef22005-04-07 07:30:20 +00001534 for (ALL_LIST_ELEMENTS_RO (ifp->connected, addrnode, ifc))
paul718e3742002-12-13 20:15:29 +00001535 {
paul718e3742002-12-13 20:15:29 +00001536 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1537 {
1538 p = ifc->address;
1539 vty_out (vty, " ip%s address %s/%d",
1540 p->family == AF_INET ? "" : "v6",
1541 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
1542 p->prefixlen);
1543
paul718e3742002-12-13 20:15:29 +00001544 if (ifc->label)
1545 vty_out (vty, " label %s", ifc->label);
1546
1547 vty_out (vty, "%s", VTY_NEWLINE);
1548 }
1549 }
1550
1551 if (if_data)
1552 {
1553 if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)
1554 vty_out (vty, " shutdown%s", VTY_NEWLINE);
1555
1556 if (if_data->multicast != IF_ZEBRA_MULTICAST_UNSPEC)
1557 vty_out (vty, " %smulticast%s",
1558 if_data->multicast == IF_ZEBRA_MULTICAST_ON ? "" : "no ",
1559 VTY_NEWLINE);
1560 }
1561
1562#ifdef RTADV
1563 rtadv_config_write (vty, ifp);
1564#endif /* RTADV */
1565
hassoca776982004-06-12 14:33:05 +00001566#ifdef HAVE_IRDP
1567 irdp_config_write (vty, ifp);
1568#endif /* IRDP */
1569
paul718e3742002-12-13 20:15:29 +00001570 vty_out (vty, "!%s", VTY_NEWLINE);
1571 }
1572 return 0;
1573}
1574
1575/* Allocate and initialize interface vector. */
1576void
paula1ac18c2005-06-28 17:17:12 +00001577zebra_if_init (void)
paul718e3742002-12-13 20:15:29 +00001578{
1579 /* Initialize interface and new hook. */
1580 if_init ();
1581 if_add_hook (IF_NEW_HOOK, if_zebra_new_hook);
1582 if_add_hook (IF_DELETE_HOOK, if_zebra_delete_hook);
1583
1584 /* Install configuration write function. */
1585 install_node (&interface_node, if_config_write);
1586
1587 install_element (VIEW_NODE, &show_interface_cmd);
1588 install_element (ENABLE_NODE, &show_interface_cmd);
hassoed9bb6d2005-03-13 19:17:21 +00001589 install_element (ENABLE_NODE, &show_interface_desc_cmd);
paul718e3742002-12-13 20:15:29 +00001590 install_element (CONFIG_NODE, &zebra_interface_cmd);
paulbfc13532003-05-24 06:40:04 +00001591 install_element (CONFIG_NODE, &no_interface_cmd);
paul718e3742002-12-13 20:15:29 +00001592 install_default (INTERFACE_NODE);
1593 install_element (INTERFACE_NODE, &interface_desc_cmd);
1594 install_element (INTERFACE_NODE, &no_interface_desc_cmd);
1595 install_element (INTERFACE_NODE, &multicast_cmd);
1596 install_element (INTERFACE_NODE, &no_multicast_cmd);
paul2e3b2e42002-12-13 21:03:13 +00001597 install_element (INTERFACE_NODE, &linkdetect_cmd);
1598 install_element (INTERFACE_NODE, &no_linkdetect_cmd);
paul718e3742002-12-13 20:15:29 +00001599 install_element (INTERFACE_NODE, &shutdown_if_cmd);
1600 install_element (INTERFACE_NODE, &no_shutdown_if_cmd);
1601 install_element (INTERFACE_NODE, &bandwidth_if_cmd);
1602 install_element (INTERFACE_NODE, &no_bandwidth_if_cmd);
1603 install_element (INTERFACE_NODE, &no_bandwidth_if_val_cmd);
1604 install_element (INTERFACE_NODE, &ip_address_cmd);
1605 install_element (INTERFACE_NODE, &no_ip_address_cmd);
1606#ifdef HAVE_IPV6
1607 install_element (INTERFACE_NODE, &ipv6_address_cmd);
1608 install_element (INTERFACE_NODE, &no_ipv6_address_cmd);
1609#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +00001610#ifdef HAVE_NETLINK
paul718e3742002-12-13 20:15:29 +00001611 install_element (INTERFACE_NODE, &ip_address_label_cmd);
paul718e3742002-12-13 20:15:29 +00001612 install_element (INTERFACE_NODE, &no_ip_address_label_cmd);
paul718e3742002-12-13 20:15:29 +00001613#endif /* HAVE_NETLINK */
1614}