blob: 69124b3de8996b9f28c7a1b740c8208df155156f [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
2 * Interface function.
3 * Copyright (C) 1997, 1999 Kunihiro Ishiguro
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25#include "if.h"
26#include "vty.h"
27#include "sockunion.h"
28#include "prefix.h"
29#include "command.h"
30#include "memory.h"
31#include "ioctl.h"
32#include "connected.h"
33#include "log.h"
34#include "zclient.h"
35
36#include "zebra/interface.h"
37#include "zebra/rtadv.h"
38#include "zebra/rib.h"
39#include "zebra/zserv.h"
40#include "zebra/redistribute.h"
41#include "zebra/debug.h"
hassoca776982004-06-12 14:33:05 +000042#include "zebra/irdp.h"
paul718e3742002-12-13 20:15:29 +000043
paul718e3742002-12-13 20:15:29 +000044
45/* Called when new interface is added. */
paula1ac18c2005-06-28 17:17:12 +000046static int
paul718e3742002-12-13 20:15:29 +000047if_zebra_new_hook (struct interface *ifp)
48{
49 struct zebra_if *zebra_if;
50
51 zebra_if = XMALLOC (MTYPE_TMP, sizeof (struct zebra_if));
52 memset (zebra_if, 0, sizeof (struct zebra_if));
53
54 zebra_if->multicast = IF_ZEBRA_MULTICAST_UNSPEC;
55 zebra_if->shutdown = IF_ZEBRA_SHUTDOWN_UNSPEC;
56
57#ifdef RTADV
58 {
59 /* Set default router advertise values. */
60 struct rtadvconf *rtadv;
61
62 rtadv = &zebra_if->rtadv;
63
64 rtadv->AdvSendAdvertisements = 0;
65 rtadv->MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
66 rtadv->MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
67 rtadv->AdvIntervalTimer = 0;
68 rtadv->AdvManagedFlag = 0;
69 rtadv->AdvOtherConfigFlag = 0;
vincent7cee1bb2005-03-25 13:08:53 +000070 rtadv->AdvHomeAgentFlag = 0;
paul718e3742002-12-13 20:15:29 +000071 rtadv->AdvLinkMTU = 0;
72 rtadv->AdvReachableTime = 0;
73 rtadv->AdvRetransTimer = 0;
74 rtadv->AdvCurHopLimit = 0;
75 rtadv->AdvDefaultLifetime = RTADV_ADV_DEFAULT_LIFETIME;
vincent7cee1bb2005-03-25 13:08:53 +000076 rtadv->HomeAgentPreference = 0;
77 rtadv->HomeAgentLifetime = RTADV_ADV_DEFAULT_LIFETIME;
78 rtadv->AdvIntervalOption = 0;
paul718e3742002-12-13 20:15:29 +000079
80 rtadv->AdvPrefixList = list_new ();
81 }
82#endif /* RTADV */
83
hassoeef1fe12004-10-03 18:46:08 +000084 /* Initialize installed address chains tree. */
85 zebra_if->ipv4_subnets = route_table_init ();
86
paul718e3742002-12-13 20:15:29 +000087 ifp->info = zebra_if;
88 return 0;
89}
90
91/* Called when interface is deleted. */
paula1ac18c2005-06-28 17:17:12 +000092static int
paul718e3742002-12-13 20:15:29 +000093if_zebra_delete_hook (struct interface *ifp)
94{
hassoeef1fe12004-10-03 18:46:08 +000095 struct zebra_if *zebra_if;
96
paul718e3742002-12-13 20:15:29 +000097 if (ifp->info)
hassoeef1fe12004-10-03 18:46:08 +000098 {
99 zebra_if = ifp->info;
100
101 /* Free installed address chains tree. */
102 if (zebra_if->ipv4_subnets)
103 route_table_finish (zebra_if->ipv4_subnets);
104
105 XFREE (MTYPE_TMP, zebra_if);
106 }
107
108 return 0;
109}
110
111/* Tie an interface address to its derived subnet list of addresses. */
112int
113if_subnet_add (struct interface *ifp, struct connected *ifc)
114{
115 struct route_node *rn;
116 struct zebra_if *zebra_if;
117 struct prefix cp;
118 struct list *addr_list;
119
120 assert (ifp && ifp->info && ifc);
121 zebra_if = ifp->info;
122
123 /* Get address derived subnet node and associated address list, while marking
124 address secondary attribute appropriately. */
125 cp = *ifc->address;
126 apply_mask (&cp);
127 rn = route_node_get (zebra_if->ipv4_subnets, &cp);
128
129 if ((addr_list = rn->info))
130 SET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY);
131 else
132 {
133 UNSET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY);
134 rn->info = addr_list = list_new ();
135 route_lock_node (rn);
136 }
137
138 /* Tie address at the tail of address list. */
139 listnode_add (addr_list, ifc);
140
141 /* Return list element count. */
142 return (addr_list->count);
143}
144
145/* Untie an interface address from its derived subnet list of addresses. */
146int
147if_subnet_delete (struct interface *ifp, struct connected *ifc)
148{
149 struct route_node *rn;
150 struct zebra_if *zebra_if;
151 struct list *addr_list;
152
153 assert (ifp && ifp->info && ifc);
154 zebra_if = ifp->info;
155
156 /* Get address derived subnet node. */
157 rn = route_node_lookup (zebra_if->ipv4_subnets, ifc->address);
158 if (! (rn && rn->info))
159 return -1;
160 route_unlock_node (rn);
161
162 /* Untie address from subnet's address list. */
163 addr_list = rn->info;
164 listnode_delete (addr_list, ifc);
165 route_unlock_node (rn);
166
167 /* Return list element count, if not empty. */
168 if (addr_list->count)
169 {
170 /* If deleted address is primary, mark subsequent one as such and distribute. */
171 if (! CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY))
172 {
paul1eb8ef22005-04-07 07:30:20 +0000173 ifc = listgetdata (listhead (addr_list));
hassoeef1fe12004-10-03 18:46:08 +0000174 zebra_interface_address_delete_update (ifp, ifc);
175 UNSET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY);
176 zebra_interface_address_add_update (ifp, ifc);
177 }
178
179 return addr_list->count;
180 }
181
182 /* Otherwise, free list and route node. */
183 list_free (addr_list);
184 rn->info = NULL;
185 route_unlock_node (rn);
186
paul718e3742002-12-13 20:15:29 +0000187 return 0;
188}
189
paul5c78b3d2006-01-25 04:31:40 +0000190/* if_flags_mangle: A place for hacks that require mangling
191 * or tweaking the interface flags.
192 *
193 * ******************** Solaris flags hacks **************************
194 *
195 * Solaris IFF_UP flag reflects only the primary interface as the
196 * routing socket only sends IFINFO for the primary interface. Hence
197 * ~IFF_UP does not per se imply all the logical interfaces are also
198 * down - which we only know of as addresses. Instead we must determine
199 * whether the interface really is up or not according to how many
200 * addresses are still attached. (Solaris always sends RTM_DELADDR if
201 * an interface, logical or not, goes ~IFF_UP).
202 *
203 * Ie, we mangle IFF_UP to *additionally* reflect whether or not there
204 * are addresses left in struct connected, not just the actual underlying
205 * IFF_UP flag.
206 *
207 * We must hence remember the real state of IFF_UP, which we do in
208 * struct zebra_if.primary_state.
209 *
210 * Setting IFF_UP within zebra to administratively shutdown the
211 * interface will affect only the primary interface/address on Solaris.
212 ************************End Solaris flags hacks ***********************
213 */
214static inline void
215if_flags_mangle (struct interface *ifp, uint64_t *newflags)
216{
217#ifdef SUNOS_5
218 struct zebra_if *zif = ifp->info;
219
220 zif->primary_state = *newflags & (IFF_UP & 0xff);
221
222 if (CHECK_FLAG (zif->primary_state, IFF_UP)
223 || listcount(ifp->connected) > 0)
224 SET_FLAG (*newflags, IFF_UP);
225 else
226 UNSET_FLAG (*newflags, IFF_UP);
227#endif /* SUNOS_5 */
228}
229
230/* Update the flags field of the ifp with the new flag set provided.
231 * Take whatever actions are required for any changes in flags we care
232 * about.
233 *
234 * newflags should be the raw value, as obtained from the OS.
235 */
236void
237if_flags_update (struct interface *ifp, uint64_t newflags)
238{
239 if_flags_mangle (ifp, &newflags);
240
241 if (if_is_operative (ifp))
242 {
243 /* operative -> inoperative? */
244 ifp->flags = newflags;
245 if (!if_is_operative (ifp))
246 if_down (ifp);
247 }
248 else
249 {
250 /* inoperative -> operative? */
251 ifp->flags = newflags;
252 if (if_is_operative (ifp))
253 if_up (ifp);
254 }
255}
256
paul718e3742002-12-13 20:15:29 +0000257/* Wake up configured address if it is not in current kernel
258 address. */
paula1ac18c2005-06-28 17:17:12 +0000259static void
paul718e3742002-12-13 20:15:29 +0000260if_addr_wakeup (struct interface *ifp)
261{
paul1eb8ef22005-04-07 07:30:20 +0000262 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000263 struct connected *ifc;
264 struct prefix *p;
265 int ret;
266
paul1eb8ef22005-04-07 07:30:20 +0000267 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, ifc))
paul718e3742002-12-13 20:15:29 +0000268 {
paul718e3742002-12-13 20:15:29 +0000269 p = ifc->address;
270
271 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)
272 && ! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
273 {
274 /* Address check. */
275 if (p->family == AF_INET)
276 {
277 if (! if_is_up (ifp))
278 {
paul0752ef02005-11-03 12:35:21 +0000279 /* XXX: WTF is it trying to set flags here?
280 * caller has just gotten a new interface, has been
281 * handed the flags already. This code has no business
282 * trying to override administrative status of the interface.
283 * The only call path to here which doesn't originate from
284 * kernel event is irdp - what on earth is it trying to do?
285 *
286 * further RUNNING is not a settable flag on any system
287 * I (paulj) am aware of.
288 */
paul718e3742002-12-13 20:15:29 +0000289 if_set_flags (ifp, IFF_UP | IFF_RUNNING);
290 if_refresh (ifp);
291 }
292
293 ret = if_set_prefix (ifp, ifc);
294 if (ret < 0)
295 {
296 zlog_warn ("Can't set interface's address: %s",
ajs6099b3b2004-11-20 02:06:59 +0000297 safe_strerror(errno));
paul718e3742002-12-13 20:15:29 +0000298 continue;
299 }
hassoeef1fe12004-10-03 18:46:08 +0000300
301 /* Add to subnet chain list. */
302 if_subnet_add (ifp, ifc);
303
paul718e3742002-12-13 20:15:29 +0000304 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
305
306 zebra_interface_address_add_update (ifp, ifc);
307
paul2e3b2e42002-12-13 21:03:13 +0000308 if (if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000309 connected_up_ipv4 (ifp, ifc);
310 }
311#ifdef HAVE_IPV6
312 if (p->family == AF_INET6)
313 {
314 if (! if_is_up (ifp))
315 {
paul0752ef02005-11-03 12:35:21 +0000316 /* XXX: See long comment above */
paul718e3742002-12-13 20:15:29 +0000317 if_set_flags (ifp, IFF_UP | IFF_RUNNING);
318 if_refresh (ifp);
319 }
320
321 ret = if_prefix_add_ipv6 (ifp, ifc);
322 if (ret < 0)
323 {
324 zlog_warn ("Can't set interface's address: %s",
ajs6099b3b2004-11-20 02:06:59 +0000325 safe_strerror(errno));
paul718e3742002-12-13 20:15:29 +0000326 continue;
327 }
328 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
329
330 zebra_interface_address_add_update (ifp, ifc);
331
paul2e3b2e42002-12-13 21:03:13 +0000332 if (if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000333 connected_up_ipv6 (ifp, ifc);
334 }
335#endif /* HAVE_IPV6 */
336 }
337 }
338}
339
340/* Handle interface addition */
341void
342if_add_update (struct interface *ifp)
343{
paul48b33aa2002-12-13 20:52:52 +0000344 struct zebra_if *if_data;
345
346 if_data = ifp->info;
347 if (if_data->multicast == IF_ZEBRA_MULTICAST_ON)
348 if_set_flags (ifp, IFF_MULTICAST);
349 else if (if_data->multicast == IF_ZEBRA_MULTICAST_OFF)
350 if_unset_flags (ifp, IFF_MULTICAST);
351
paul718e3742002-12-13 20:15:29 +0000352 zebra_interface_add_update (ifp);
353
354 if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
355 {
356 SET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE);
357
358 if_addr_wakeup (ifp);
359
360 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +0000361 zlog_debug ("interface %s index %d becomes active.",
362 ifp->name, ifp->ifindex);
paul718e3742002-12-13 20:15:29 +0000363 }
364 else
365 {
366 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +0000367 zlog_debug ("interface %s index %d is added.", ifp->name, ifp->ifindex);
paul718e3742002-12-13 20:15:29 +0000368 }
369}
370
paul6eb88272005-07-29 14:36:00 +0000371/* Handle an interface delete event */
paul718e3742002-12-13 20:15:29 +0000372void
373if_delete_update (struct interface *ifp)
374{
375 struct listnode *node;
376 struct listnode *next;
hassoeef1fe12004-10-03 18:46:08 +0000377 struct listnode *first;
378 struct listnode *last;
paul718e3742002-12-13 20:15:29 +0000379 struct connected *ifc;
380 struct prefix *p;
hassoeef1fe12004-10-03 18:46:08 +0000381 struct route_node *rn;
382 struct zebra_if *zebra_if;
383 struct list *addr_list;
384
385 zebra_if = ifp->info;
paul718e3742002-12-13 20:15:29 +0000386
387 if (if_is_up(ifp))
388 {
389 zlog_err ("interface %s index %d is still up while being deleted.",
390 ifp->name, ifp->ifindex);
391 return;
392 }
393
394 /* Mark interface as inactive */
395 UNSET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE);
396
397 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +0000398 zlog_debug ("interface %s index %d is now inactive.",
paul718e3742002-12-13 20:15:29 +0000399 ifp->name, ifp->ifindex);
400
401 /* Delete connected routes from the kernel. */
402 if (ifp->connected)
403 {
hassoeef1fe12004-10-03 18:46:08 +0000404 last = NULL;
405 while ((node = (last ? last->next : listhead (ifp->connected))))
paul718e3742002-12-13 20:15:29 +0000406 {
paul1eb8ef22005-04-07 07:30:20 +0000407 ifc = listgetdata (node);
paul718e3742002-12-13 20:15:29 +0000408 p = ifc->address;
hassoeef1fe12004-10-03 18:46:08 +0000409
Paul Jakmabeb56332006-05-11 13:28:05 +0000410 if (p->family == AF_INET
411 && (rn = route_node_lookup (zebra_if->ipv4_subnets, p)))
hassoeef1fe12004-10-03 18:46:08 +0000412 {
hassoeef1fe12004-10-03 18:46:08 +0000413 route_unlock_node (rn);
414 addr_list = (struct list *) rn->info;
415
416 /* Remove addresses, secondaries first. */
417 first = listhead (addr_list);
418 for (node = first->next; node || first; node = next)
419 {
420 if (! node)
421 {
422 node = first;
423 first = NULL;
424 }
425 next = node->next;
426
paul1eb8ef22005-04-07 07:30:20 +0000427 ifc = listgetdata (node);
hassoeef1fe12004-10-03 18:46:08 +0000428 p = ifc->address;
429
430 connected_down_ipv4 (ifp, ifc);
431
432 zebra_interface_address_delete_update (ifp, ifc);
433
434 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
435
436 /* Remove from subnet chain. */
437 list_delete_node (addr_list, node);
438 route_unlock_node (rn);
439
440 /* Remove from interface address list (unconditionally). */
441 listnode_delete (ifp->connected, ifc);
442 connected_free (ifc);
443 }
444
445 /* Free chain list and respective route node. */
446 list_delete (addr_list);
447 rn->info = NULL;
448 route_unlock_node (rn);
449 }
paul718e3742002-12-13 20:15:29 +0000450#ifdef HAVE_IPV6
451 else if (p->family == AF_INET6)
hassoeef1fe12004-10-03 18:46:08 +0000452 {
453 connected_down_ipv6 (ifp, ifc);
paul718e3742002-12-13 20:15:29 +0000454
hassoeef1fe12004-10-03 18:46:08 +0000455 zebra_interface_address_delete_update (ifp, ifc);
paul718e3742002-12-13 20:15:29 +0000456
hassoeef1fe12004-10-03 18:46:08 +0000457 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
458
459 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
460 last = node;
461 else
462 {
463 listnode_delete (ifp->connected, ifc);
464 connected_free (ifc);
465 }
paul718e3742002-12-13 20:15:29 +0000466 }
hassoeef1fe12004-10-03 18:46:08 +0000467#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +0000468 }
469 }
470 zebra_interface_delete_update (ifp);
ajsd2fc8892005-04-02 18:38:43 +0000471
472 /* Update ifindex after distributing the delete message. This is in
473 case any client needs to have the old value of ifindex available
474 while processing the deletion. Each client daemon is responsible
475 for setting ifindex to IFINDEX_INTERNAL after processing the
476 interface deletion message. */
477 ifp->ifindex = IFINDEX_INTERNAL;
paul718e3742002-12-13 20:15:29 +0000478}
479
480/* Interface is up. */
481void
482if_up (struct interface *ifp)
483{
hasso52dc7ee2004-09-23 19:18:23 +0000484 struct listnode *node;
485 struct listnode *next;
paul718e3742002-12-13 20:15:29 +0000486 struct connected *ifc;
487 struct prefix *p;
488
489 /* Notify the protocol daemons. */
490 zebra_interface_up_update (ifp);
491
492 /* Install connected routes to the kernel. */
493 if (ifp->connected)
494 {
paul1eb8ef22005-04-07 07:30:20 +0000495 for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc))
paul718e3742002-12-13 20:15:29 +0000496 {
paul718e3742002-12-13 20:15:29 +0000497 p = ifc->address;
498
499 if (p->family == AF_INET)
500 connected_up_ipv4 (ifp, ifc);
501#ifdef HAVE_IPV6
502 else if (p->family == AF_INET6)
503 connected_up_ipv6 (ifp, ifc);
504#endif /* HAVE_IPV6 */
505 }
506 }
507
508 /* Examine all static routes. */
509 rib_update ();
510}
511
512/* Interface goes down. We have to manage different behavior of based
513 OS. */
514void
515if_down (struct interface *ifp)
516{
hasso52dc7ee2004-09-23 19:18:23 +0000517 struct listnode *node;
518 struct listnode *next;
paul718e3742002-12-13 20:15:29 +0000519 struct connected *ifc;
520 struct prefix *p;
521
522 /* Notify to the protocol daemons. */
523 zebra_interface_down_update (ifp);
524
525 /* Delete connected routes from the kernel. */
526 if (ifp->connected)
527 {
paul1eb8ef22005-04-07 07:30:20 +0000528 for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc))
paul718e3742002-12-13 20:15:29 +0000529 {
paul718e3742002-12-13 20:15:29 +0000530 p = ifc->address;
531
532 if (p->family == AF_INET)
533 connected_down_ipv4 (ifp, ifc);
534#ifdef HAVE_IPV6
535 else if (p->family == AF_INET6)
536 connected_down_ipv6 (ifp, ifc);
537#endif /* HAVE_IPV6 */
538 }
539 }
540
541 /* Examine all static routes which direct to the interface. */
542 rib_update ();
543}
544
545void
546if_refresh (struct interface *ifp)
547{
paul5c78b3d2006-01-25 04:31:40 +0000548 if_get_flags (ifp);
paul718e3742002-12-13 20:15:29 +0000549}
550
paul718e3742002-12-13 20:15:29 +0000551/* Output prefix string to vty. */
paula1ac18c2005-06-28 17:17:12 +0000552static int
paul718e3742002-12-13 20:15:29 +0000553prefix_vty_out (struct vty *vty, struct prefix *p)
554{
555 char str[INET6_ADDRSTRLEN];
556
557 inet_ntop (p->family, &p->u.prefix, str, sizeof (str));
558 vty_out (vty, "%s", str);
559 return strlen (str);
560}
561
562/* Dump if address information to vty. */
paula1ac18c2005-06-28 17:17:12 +0000563static void
paul718e3742002-12-13 20:15:29 +0000564connected_dump_vty (struct vty *vty, struct connected *connected)
565{
566 struct prefix *p;
567 struct interface *ifp;
568
569 /* Set interface pointer. */
570 ifp = connected->ifp;
571
572 /* Print interface address. */
573 p = connected->address;
574 vty_out (vty, " %s ", prefix_family_str (p));
575 prefix_vty_out (vty, p);
576 vty_out (vty, "/%d", p->prefixlen);
577
578 /* If there is destination address, print it. */
579 p = connected->destination;
580 if (p)
581 {
582 if (p->family == AF_INET)
583 if (ifp->flags & IFF_BROADCAST)
584 {
585 vty_out (vty, " broadcast ");
586 prefix_vty_out (vty, p);
587 }
588
589 if (ifp->flags & IFF_POINTOPOINT)
590 {
591 vty_out (vty, " pointopoint ");
592 prefix_vty_out (vty, p);
593 }
594 }
595
596 if (CHECK_FLAG (connected->flags, ZEBRA_IFA_SECONDARY))
597 vty_out (vty, " secondary");
598
599 if (connected->label)
600 vty_out (vty, " %s", connected->label);
601
602 vty_out (vty, "%s", VTY_NEWLINE);
603}
604
605#ifdef RTADV
606/* Dump interface ND information to vty. */
paula1ac18c2005-06-28 17:17:12 +0000607static void
paul718e3742002-12-13 20:15:29 +0000608nd_dump_vty (struct vty *vty, struct interface *ifp)
609{
610 struct zebra_if *zif;
611 struct rtadvconf *rtadv;
vincent7cee1bb2005-03-25 13:08:53 +0000612 int interval;
paul718e3742002-12-13 20:15:29 +0000613
614 zif = (struct zebra_if *) ifp->info;
615 rtadv = &zif->rtadv;
616
617 if (rtadv->AdvSendAdvertisements)
618 {
619 vty_out (vty, " ND advertised reachable time is %d milliseconds%s",
620 rtadv->AdvReachableTime, VTY_NEWLINE);
621 vty_out (vty, " ND advertised retransmit interval is %d milliseconds%s",
622 rtadv->AdvRetransTimer, VTY_NEWLINE);
vincent7cee1bb2005-03-25 13:08:53 +0000623 interval = rtadv->MaxRtrAdvInterval;
624 if (interval % 1000)
625 vty_out (vty, " ND router advertisements are sent every "
626 "%d milliseconds%s", interval,
627 VTY_NEWLINE);
628 else
629 vty_out (vty, " ND router advertisements are sent every "
630 "%d seconds%s", interval / 1000,
631 VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000632 vty_out (vty, " ND router advertisements live for %d seconds%s",
633 rtadv->AdvDefaultLifetime, VTY_NEWLINE);
634 if (rtadv->AdvManagedFlag)
635 vty_out (vty, " Hosts use DHCP to obtain routable addresses.%s",
636 VTY_NEWLINE);
637 else
638 vty_out (vty, " Hosts use stateless autoconfig for addresses.%s",
639 VTY_NEWLINE);
vincent7cee1bb2005-03-25 13:08:53 +0000640 if (rtadv->AdvHomeAgentFlag)
641 vty_out (vty, " ND router advertisements with "
642 "Home Agent flag bit set.%s",
643 VTY_NEWLINE);
644 if (rtadv->AdvIntervalOption)
645 vty_out (vty, " ND router advertisements with Adv. Interval option.%s",
646 VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000647 }
648}
649#endif /* RTADV */
650
651/* Interface's information print out to vty interface. */
paula1ac18c2005-06-28 17:17:12 +0000652static void
paul718e3742002-12-13 20:15:29 +0000653if_dump_vty (struct vty *vty, struct interface *ifp)
654{
655#ifdef HAVE_SOCKADDR_DL
656 struct sockaddr_dl *sdl;
657#endif /* HAVE_SOCKADDR_DL */
658 struct connected *connected;
hasso52dc7ee2004-09-23 19:18:23 +0000659 struct listnode *node;
hassoeef1fe12004-10-03 18:46:08 +0000660 struct route_node *rn;
661 struct zebra_if *zebra_if;
662
663 zebra_if = ifp->info;
paul718e3742002-12-13 20:15:29 +0000664
paul2e3b2e42002-12-13 21:03:13 +0000665 vty_out (vty, "Interface %s is ", ifp->name);
666 if (if_is_up(ifp)) {
667 vty_out (vty, "up, line protocol ");
668
669 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) {
670 if (if_is_running(ifp))
671 vty_out (vty, "is up%s", VTY_NEWLINE);
672 else
673 vty_out (vty, "is down%s", VTY_NEWLINE);
674 } else {
675 vty_out (vty, "detection is disabled%s", VTY_NEWLINE);
676 }
677 } else {
678 vty_out (vty, "down%s", VTY_NEWLINE);
679 }
680
paul718e3742002-12-13 20:15:29 +0000681 if (ifp->desc)
682 vty_out (vty, " Description: %s%s", ifp->desc,
683 VTY_NEWLINE);
ajsd2fc8892005-04-02 18:38:43 +0000684 if (ifp->ifindex == IFINDEX_INTERNAL)
paul718e3742002-12-13 20:15:29 +0000685 {
ajsd2fc8892005-04-02 18:38:43 +0000686 vty_out(vty, " pseudo interface%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000687 return;
688 }
689 else if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
690 {
691 vty_out(vty, " index %d inactive interface%s",
692 ifp->ifindex,
693 VTY_NEWLINE);
694 return;
695 }
696
697 vty_out (vty, " index %d metric %d mtu %d ",
698 ifp->ifindex, ifp->metric, ifp->mtu);
paul44145db2004-05-09 11:00:23 +0000699#ifdef HAVE_IPV6
700 if (ifp->mtu6 != ifp->mtu)
701 vty_out (vty, "mtu6 %d ", ifp->mtu6);
702#endif
Paul Jakma630c97c2006-06-15 12:48:17 +0000703 vty_out (vty, "%s flags: %s%s", VTY_NEWLINE,
704 if_flag_dump (ifp->flags), VTY_NEWLINE);
paul3a570c82006-02-02 17:27:13 +0000705
paul718e3742002-12-13 20:15:29 +0000706 /* Hardware address. */
707#ifdef HAVE_SOCKADDR_DL
708 sdl = &ifp->sdl;
709 if (sdl != NULL && sdl->sdl_alen != 0)
710 {
711 int i;
712 u_char *ptr;
713
714 vty_out (vty, " HWaddr: ");
paul5b73a672004-07-23 15:26:14 +0000715 for (i = 0, ptr = (u_char *)LLADDR (sdl); i < sdl->sdl_alen; i++, ptr++)
716 vty_out (vty, "%s%02x", i == 0 ? "" : ":", *ptr);
paul718e3742002-12-13 20:15:29 +0000717 vty_out (vty, "%s", VTY_NEWLINE);
718 }
719#else
720 if (ifp->hw_addr_len != 0)
721 {
722 int i;
723
724 vty_out (vty, " HWaddr: ");
725 for (i = 0; i < ifp->hw_addr_len; i++)
726 vty_out (vty, "%s%02x", i == 0 ? "" : ":", ifp->hw_addr[i]);
727 vty_out (vty, "%s", VTY_NEWLINE);
728 }
729#endif /* HAVE_SOCKADDR_DL */
730
731 /* Bandwidth in kbps */
732 if (ifp->bandwidth != 0)
733 {
734 vty_out(vty, " bandwidth %u kbps", ifp->bandwidth);
735 vty_out(vty, "%s", VTY_NEWLINE);
736 }
737
hassoeef1fe12004-10-03 18:46:08 +0000738 for (rn = route_top (zebra_if->ipv4_subnets); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000739 {
hassoeef1fe12004-10-03 18:46:08 +0000740 if (! rn->info)
741 continue;
742
paul1eb8ef22005-04-07 07:30:20 +0000743 for (ALL_LIST_ELEMENTS_RO ((struct list *)rn->info, node, connected))
744 connected_dump_vty (vty, connected);
paul718e3742002-12-13 20:15:29 +0000745 }
746
paul1eb8ef22005-04-07 07:30:20 +0000747 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
hasso39db97e2004-10-12 20:50:58 +0000748 {
hasso39db97e2004-10-12 20:50:58 +0000749 if (CHECK_FLAG (connected->conf, ZEBRA_IFC_REAL) &&
750 (connected->address->family == AF_INET6))
751 connected_dump_vty (vty, connected);
752 }
753
paul718e3742002-12-13 20:15:29 +0000754#ifdef RTADV
755 nd_dump_vty (vty, ifp);
756#endif /* RTADV */
757
758#ifdef HAVE_PROC_NET_DEV
759 /* Statistics print out using proc file system. */
hasso6f2c27a2005-01-18 13:44:35 +0000760 vty_out (vty, " %lu input packets (%lu multicast), %lu bytes, "
761 "%lu dropped%s",
762 ifp->stats.rx_packets, ifp->stats.rx_multicast,
763 ifp->stats.rx_bytes, ifp->stats.rx_dropped, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000764
hasso6f2c27a2005-01-18 13:44:35 +0000765 vty_out (vty, " %lu input errors, %lu length, %lu overrun,"
hasso3452d472005-03-06 13:42:05 +0000766 " %lu CRC, %lu frame%s",
paul718e3742002-12-13 20:15:29 +0000767 ifp->stats.rx_errors, ifp->stats.rx_length_errors,
768 ifp->stats.rx_over_errors, ifp->stats.rx_crc_errors,
hasso6f2c27a2005-01-18 13:44:35 +0000769 ifp->stats.rx_frame_errors, VTY_NEWLINE);
770
771 vty_out (vty, " %lu fifo, %lu missed%s", ifp->stats.rx_fifo_errors,
paul718e3742002-12-13 20:15:29 +0000772 ifp->stats.rx_missed_errors, VTY_NEWLINE);
773
hasso6f2c27a2005-01-18 13:44:35 +0000774 vty_out (vty, " %lu output packets, %lu bytes, %lu dropped%s",
paul718e3742002-12-13 20:15:29 +0000775 ifp->stats.tx_packets, ifp->stats.tx_bytes,
776 ifp->stats.tx_dropped, VTY_NEWLINE);
777
hasso6f2c27a2005-01-18 13:44:35 +0000778 vty_out (vty, " %lu output errors, %lu aborted, %lu carrier,"
779 " %lu fifo, %lu heartbeat%s",
paul718e3742002-12-13 20:15:29 +0000780 ifp->stats.tx_errors, ifp->stats.tx_aborted_errors,
781 ifp->stats.tx_carrier_errors, ifp->stats.tx_fifo_errors,
hasso6f2c27a2005-01-18 13:44:35 +0000782 ifp->stats.tx_heartbeat_errors, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000783
hasso6f2c27a2005-01-18 13:44:35 +0000784 vty_out (vty, " %lu window, %lu collisions%s",
785 ifp->stats.tx_window_errors, ifp->stats.collisions, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000786#endif /* HAVE_PROC_NET_DEV */
787
788#ifdef HAVE_NET_RT_IFLIST
789#if defined (__bsdi__) || defined (__NetBSD__)
790 /* Statistics print out using sysctl (). */
791 vty_out (vty, " input packets %qu, bytes %qu, dropped %qu,"
792 " multicast packets %qu%s",
793 ifp->stats.ifi_ipackets, ifp->stats.ifi_ibytes,
794 ifp->stats.ifi_iqdrops, ifp->stats.ifi_imcasts,
795 VTY_NEWLINE);
796
797 vty_out (vty, " input errors %qu%s",
798 ifp->stats.ifi_ierrors, VTY_NEWLINE);
799
800 vty_out (vty, " output packets %qu, bytes %qu, multicast packets %qu%s",
801 ifp->stats.ifi_opackets, ifp->stats.ifi_obytes,
802 ifp->stats.ifi_omcasts, VTY_NEWLINE);
803
804 vty_out (vty, " output errors %qu%s",
805 ifp->stats.ifi_oerrors, VTY_NEWLINE);
806
807 vty_out (vty, " collisions %qu%s",
808 ifp->stats.ifi_collisions, VTY_NEWLINE);
809#else
810 /* Statistics print out using sysctl (). */
811 vty_out (vty, " input packets %lu, bytes %lu, dropped %lu,"
812 " multicast packets %lu%s",
813 ifp->stats.ifi_ipackets, ifp->stats.ifi_ibytes,
814 ifp->stats.ifi_iqdrops, ifp->stats.ifi_imcasts,
815 VTY_NEWLINE);
816
817 vty_out (vty, " input errors %lu%s",
818 ifp->stats.ifi_ierrors, VTY_NEWLINE);
819
820 vty_out (vty, " output packets %lu, bytes %lu, multicast packets %lu%s",
821 ifp->stats.ifi_opackets, ifp->stats.ifi_obytes,
822 ifp->stats.ifi_omcasts, VTY_NEWLINE);
823
824 vty_out (vty, " output errors %lu%s",
825 ifp->stats.ifi_oerrors, VTY_NEWLINE);
826
827 vty_out (vty, " collisions %lu%s",
828 ifp->stats.ifi_collisions, VTY_NEWLINE);
829#endif /* __bsdi__ || __NetBSD__ */
830#endif /* HAVE_NET_RT_IFLIST */
831}
832
833/* Check supported address family. */
paula1ac18c2005-06-28 17:17:12 +0000834static int
paul718e3742002-12-13 20:15:29 +0000835if_supported_family (int family)
836{
837 if (family == AF_INET)
838 return 1;
839#ifdef HAVE_IPV6
840 if (family == AF_INET6)
841 return 1;
842#endif /* HAVE_IPV6 */
843 return 0;
844}
845
846/* Wrapper hook point for zebra daemon so that ifindex can be set
847 * DEFUN macro not used as extract.pl HAS to ignore this
848 * See also interface_cmd in lib/if.c
849 */
850DEFUN_NOSH (zebra_interface,
851 zebra_interface_cmd,
852 "interface IFNAME",
853 "Select an interface to configure\n"
854 "Interface's name\n")
855{
856 int ret;
857 struct interface * ifp;
858
859 /* Call lib interface() */
ajsd2fc8892005-04-02 18:38:43 +0000860 if ((ret = interface_cmd.func (self, vty, argc, argv)) != CMD_SUCCESS)
861 return ret;
paul718e3742002-12-13 20:15:29 +0000862
863 ifp = vty->index;
864
ajsd2fc8892005-04-02 18:38:43 +0000865 if (ifp->ifindex == IFINDEX_INTERNAL)
866 /* Is this really necessary? Shouldn't status be initialized to 0
867 in that case? */
868 UNSET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE);
paul718e3742002-12-13 20:15:29 +0000869
870 return ret;
871}
872
paul718e3742002-12-13 20:15:29 +0000873struct cmd_node interface_node =
874{
875 INTERFACE_NODE,
876 "%s(config-if)# ",
877 1
878};
879
880/* Show all or specified interface to vty. */
881DEFUN (show_interface, show_interface_cmd,
882 "show interface [IFNAME]",
883 SHOW_STR
884 "Interface status and configuration\n"
885 "Inteface name\n")
886{
hasso52dc7ee2004-09-23 19:18:23 +0000887 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000888 struct interface *ifp;
889
890#ifdef HAVE_PROC_NET_DEV
891 /* If system has interface statistics via proc file system, update
892 statistics. */
893 ifstat_update_proc ();
894#endif /* HAVE_PROC_NET_DEV */
895#ifdef HAVE_NET_RT_IFLIST
896 ifstat_update_sysctl ();
897#endif /* HAVE_NET_RT_IFLIST */
898
899 /* Specified interface print. */
900 if (argc != 0)
901 {
902 ifp = if_lookup_by_name (argv[0]);
903 if (ifp == NULL)
904 {
905 vty_out (vty, "%% Can't find interface %s%s", argv[0],
906 VTY_NEWLINE);
907 return CMD_WARNING;
908 }
909 if_dump_vty (vty, ifp);
910 return CMD_SUCCESS;
911 }
912
913 /* All interface print. */
paul1eb8ef22005-04-07 07:30:20 +0000914 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
915 if_dump_vty (vty, ifp);
paul718e3742002-12-13 20:15:29 +0000916
917 return CMD_SUCCESS;
918}
919
hassoed9bb6d2005-03-13 19:17:21 +0000920DEFUN (show_interface_desc,
921 show_interface_desc_cmd,
922 "show interface description",
923 SHOW_STR
924 "Interface status and configuration\n"
925 "Interface description\n")
926{
927 struct listnode *node;
928 struct interface *ifp;
929
930 vty_out (vty, "Interface Status Protocol Description%s", VTY_NEWLINE);
paul1eb8ef22005-04-07 07:30:20 +0000931 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
hassoed9bb6d2005-03-13 19:17:21 +0000932 {
933 int len;
hassoed9bb6d2005-03-13 19:17:21 +0000934
935 len = vty_out (vty, "%s", ifp->name);
936 vty_out (vty, "%*s", (16 - len), " ");
937
938 if (if_is_up(ifp))
939 {
940 vty_out (vty, "up ");
941 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION))
942 {
943 if (if_is_running(ifp))
944 vty_out (vty, "up ");
945 else
946 vty_out (vty, "down ");
947 }
948 else
949 {
950 vty_out (vty, "unknown ");
951 }
952 }
953 else
954 {
955 vty_out (vty, "down down ");
956 }
957
958 if (ifp->desc)
959 vty_out (vty, "%s", ifp->desc);
960 vty_out (vty, "%s", VTY_NEWLINE);
961 }
962 return CMD_SUCCESS;
963}
964
paul718e3742002-12-13 20:15:29 +0000965DEFUN (multicast,
966 multicast_cmd,
967 "multicast",
968 "Set multicast flag to interface\n")
969{
970 int ret;
971 struct interface *ifp;
972 struct zebra_if *if_data;
973
974 ifp = (struct interface *) vty->index;
paul48b33aa2002-12-13 20:52:52 +0000975 if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
paul718e3742002-12-13 20:15:29 +0000976 {
paul48b33aa2002-12-13 20:52:52 +0000977 ret = if_set_flags (ifp, IFF_MULTICAST);
978 if (ret < 0)
979 {
980 vty_out (vty, "Can't set multicast flag%s", VTY_NEWLINE);
981 return CMD_WARNING;
982 }
983 if_refresh (ifp);
paul718e3742002-12-13 20:15:29 +0000984 }
paul718e3742002-12-13 20:15:29 +0000985 if_data = ifp->info;
986 if_data->multicast = IF_ZEBRA_MULTICAST_ON;
paul48b33aa2002-12-13 20:52:52 +0000987
paul718e3742002-12-13 20:15:29 +0000988 return CMD_SUCCESS;
989}
990
991DEFUN (no_multicast,
992 no_multicast_cmd,
993 "no multicast",
994 NO_STR
995 "Unset multicast flag to interface\n")
996{
997 int ret;
998 struct interface *ifp;
999 struct zebra_if *if_data;
1000
1001 ifp = (struct interface *) vty->index;
paul48b33aa2002-12-13 20:52:52 +00001002 if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
paul718e3742002-12-13 20:15:29 +00001003 {
paul48b33aa2002-12-13 20:52:52 +00001004 ret = if_unset_flags (ifp, IFF_MULTICAST);
1005 if (ret < 0)
1006 {
1007 vty_out (vty, "Can't unset multicast flag%s", VTY_NEWLINE);
1008 return CMD_WARNING;
1009 }
1010 if_refresh (ifp);
paul718e3742002-12-13 20:15:29 +00001011 }
paul718e3742002-12-13 20:15:29 +00001012 if_data = ifp->info;
1013 if_data->multicast = IF_ZEBRA_MULTICAST_OFF;
1014
1015 return CMD_SUCCESS;
1016}
1017
paul2e3b2e42002-12-13 21:03:13 +00001018DEFUN (linkdetect,
1019 linkdetect_cmd,
1020 "link-detect",
1021 "Enable link detection on interface\n")
1022{
paul2e3b2e42002-12-13 21:03:13 +00001023 struct interface *ifp;
1024 int if_was_operative;
1025
1026 ifp = (struct interface *) vty->index;
1027 if_was_operative = if_is_operative(ifp);
1028 SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
1029
1030 /* When linkdetection is enabled, if might come down */
1031 if (!if_is_operative(ifp) && if_was_operative) if_down(ifp);
1032
1033 /* FIXME: Will defer status change forwarding if interface
1034 does not come down! */
1035
1036 return CMD_SUCCESS;
1037}
1038
1039
1040DEFUN (no_linkdetect,
1041 no_linkdetect_cmd,
1042 "no link-detect",
1043 NO_STR
1044 "Disable link detection on interface\n")
1045{
paul2e3b2e42002-12-13 21:03:13 +00001046 struct interface *ifp;
1047 int if_was_operative;
1048
1049 ifp = (struct interface *) vty->index;
1050 if_was_operative = if_is_operative(ifp);
1051 UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
1052
1053 /* Interface may come up after disabling link detection */
1054 if (if_is_operative(ifp) && !if_was_operative) if_up(ifp);
1055
1056 /* FIXME: see linkdetect_cmd */
1057
1058 return CMD_SUCCESS;
1059}
1060
paul718e3742002-12-13 20:15:29 +00001061DEFUN (shutdown_if,
1062 shutdown_if_cmd,
1063 "shutdown",
1064 "Shutdown the selected interface\n")
1065{
1066 int ret;
1067 struct interface *ifp;
1068 struct zebra_if *if_data;
1069
1070 ifp = (struct interface *) vty->index;
1071 ret = if_unset_flags (ifp, IFF_UP);
1072 if (ret < 0)
1073 {
1074 vty_out (vty, "Can't shutdown interface%s", VTY_NEWLINE);
1075 return CMD_WARNING;
1076 }
1077 if_refresh (ifp);
1078 if_data = ifp->info;
1079 if_data->shutdown = IF_ZEBRA_SHUTDOWN_ON;
1080
1081 return CMD_SUCCESS;
1082}
1083
1084DEFUN (no_shutdown_if,
1085 no_shutdown_if_cmd,
1086 "no shutdown",
1087 NO_STR
1088 "Shutdown the selected interface\n")
1089{
1090 int ret;
1091 struct interface *ifp;
1092 struct zebra_if *if_data;
1093
1094 ifp = (struct interface *) vty->index;
1095 ret = if_set_flags (ifp, IFF_UP | IFF_RUNNING);
1096 if (ret < 0)
1097 {
1098 vty_out (vty, "Can't up interface%s", VTY_NEWLINE);
1099 return CMD_WARNING;
1100 }
1101 if_refresh (ifp);
1102 if_data = ifp->info;
1103 if_data->shutdown = IF_ZEBRA_SHUTDOWN_OFF;
1104
1105 return CMD_SUCCESS;
1106}
1107
1108DEFUN (bandwidth_if,
1109 bandwidth_if_cmd,
1110 "bandwidth <1-10000000>",
1111 "Set bandwidth informational parameter\n"
1112 "Bandwidth in kilobits\n")
1113{
1114 struct interface *ifp;
1115 unsigned int bandwidth;
1116
1117 ifp = (struct interface *) vty->index;
1118 bandwidth = strtol(argv[0], NULL, 10);
1119
1120 /* bandwidth range is <1-10000000> */
1121 if (bandwidth < 1 || bandwidth > 10000000)
1122 {
1123 vty_out (vty, "Bandwidth is invalid%s", VTY_NEWLINE);
1124 return CMD_WARNING;
1125 }
1126
1127 ifp->bandwidth = bandwidth;
1128
1129 /* force protocols to recalculate routes due to cost change */
paul2e3b2e42002-12-13 21:03:13 +00001130 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00001131 zebra_interface_up_update (ifp);
1132
1133 return CMD_SUCCESS;
1134}
1135
1136DEFUN (no_bandwidth_if,
1137 no_bandwidth_if_cmd,
1138 "no bandwidth",
1139 NO_STR
1140 "Set bandwidth informational parameter\n")
1141{
1142 struct interface *ifp;
1143
1144 ifp = (struct interface *) vty->index;
1145
1146 ifp->bandwidth = 0;
1147
1148 /* force protocols to recalculate routes due to cost change */
paul2e3b2e42002-12-13 21:03:13 +00001149 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00001150 zebra_interface_up_update (ifp);
1151
1152 return CMD_SUCCESS;
1153}
1154
1155ALIAS (no_bandwidth_if,
1156 no_bandwidth_if_val_cmd,
1157 "no bandwidth <1-10000000>",
1158 NO_STR
1159 "Set bandwidth informational parameter\n"
1160 "Bandwidth in kilobits\n")
1161
paula1ac18c2005-06-28 17:17:12 +00001162static int
hasso39db97e2004-10-12 20:50:58 +00001163ip_address_install (struct vty *vty, struct interface *ifp,
1164 const char *addr_str, const char *peer_str,
1165 const char *label)
paul718e3742002-12-13 20:15:29 +00001166{
1167 struct prefix_ipv4 cp;
1168 struct connected *ifc;
1169 struct prefix_ipv4 *p;
paul718e3742002-12-13 20:15:29 +00001170 int ret;
1171
1172 ret = str2prefix_ipv4 (addr_str, &cp);
1173 if (ret <= 0)
1174 {
1175 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1176 return CMD_WARNING;
1177 }
1178
paulca162182005-09-12 16:58:52 +00001179 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001180 if (! ifc)
1181 {
1182 ifc = connected_new ();
1183 ifc->ifp = ifp;
1184
1185 /* Address. */
1186 p = prefix_ipv4_new ();
1187 *p = cp;
1188 ifc->address = (struct prefix *) p;
1189
1190 /* Broadcast. */
hasso3fb9cd62004-10-19 19:44:43 +00001191 if (p->prefixlen <= IPV4_MAX_PREFIXLEN-2)
paul718e3742002-12-13 20:15:29 +00001192 {
1193 p = prefix_ipv4_new ();
1194 *p = cp;
hasso3fb9cd62004-10-19 19:44:43 +00001195 p->prefix.s_addr = ipv4_broadcast_addr(p->prefix.s_addr,p->prefixlen);
paul718e3742002-12-13 20:15:29 +00001196 ifc->destination = (struct prefix *) p;
1197 }
1198
paul718e3742002-12-13 20:15:29 +00001199 /* Label. */
1200 if (label)
paul0752ef02005-11-03 12:35:21 +00001201 ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
paul718e3742002-12-13 20:15:29 +00001202
1203 /* Add to linked list. */
1204 listnode_add (ifp->connected, ifc);
1205 }
1206
1207 /* This address is configured from zebra. */
1208 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1209 SET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED);
1210
1211 /* In case of this route need to install kernel. */
1212 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1213 && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1214 {
1215 /* Some system need to up the interface to set IP address. */
1216 if (! if_is_up (ifp))
1217 {
1218 if_set_flags (ifp, IFF_UP | IFF_RUNNING);
1219 if_refresh (ifp);
1220 }
1221
1222 ret = if_set_prefix (ifp, ifc);
1223 if (ret < 0)
1224 {
1225 vty_out (vty, "%% Can't set interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001226 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001227 return CMD_WARNING;
1228 }
1229
hassoeef1fe12004-10-03 18:46:08 +00001230 /* Add to subnet chain list (while marking secondary attribute). */
1231 if_subnet_add (ifp, ifc);
1232
paul718e3742002-12-13 20:15:29 +00001233 /* IP address propery set. */
1234 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
1235
1236 /* Update interface address information to protocol daemon. */
1237 zebra_interface_address_add_update (ifp, ifc);
1238
1239 /* If interface is up register connected route. */
paul2e3b2e42002-12-13 21:03:13 +00001240 if (if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001241 connected_up_ipv4 (ifp, ifc);
1242 }
1243
1244 return CMD_SUCCESS;
1245}
1246
paula1ac18c2005-06-28 17:17:12 +00001247static int
hasso39db97e2004-10-12 20:50:58 +00001248ip_address_uninstall (struct vty *vty, struct interface *ifp,
1249 const char *addr_str, const char *peer_str,
1250 const char *label)
paul718e3742002-12-13 20:15:29 +00001251{
1252 struct prefix_ipv4 cp;
1253 struct connected *ifc;
1254 int ret;
1255
1256 /* Convert to prefix structure. */
1257 ret = str2prefix_ipv4 (addr_str, &cp);
1258 if (ret <= 0)
1259 {
1260 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1261 return CMD_WARNING;
1262 }
1263
1264 /* Check current interface address. */
paulca162182005-09-12 16:58:52 +00001265 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001266 if (! ifc)
1267 {
1268 vty_out (vty, "%% Can't find address%s", VTY_NEWLINE);
1269 return CMD_WARNING;
1270 }
1271
1272 /* This is not configured address. */
1273 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1274 return CMD_WARNING;
1275
Paul Jakma74ecdc92006-06-15 18:10:47 +00001276 UNSET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED);
1277
paul718e3742002-12-13 20:15:29 +00001278 /* This is not real address or interface is not active. */
1279 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1280 || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1281 {
1282 listnode_delete (ifp->connected, ifc);
1283 connected_free (ifc);
1284 return CMD_WARNING;
1285 }
1286
1287 /* This is real route. */
1288 ret = if_unset_prefix (ifp, ifc);
1289 if (ret < 0)
1290 {
1291 vty_out (vty, "%% Can't unset interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001292 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001293 return CMD_WARNING;
1294 }
1295
hassoeef1fe12004-10-03 18:46:08 +00001296#if 0
paul718e3742002-12-13 20:15:29 +00001297 /* Redistribute this information. */
1298 zebra_interface_address_delete_update (ifp, ifc);
1299
1300 /* Remove connected route. */
1301 connected_down_ipv4 (ifp, ifc);
1302
1303 /* Free address information. */
1304 listnode_delete (ifp->connected, ifc);
1305 connected_free (ifc);
hassoeef1fe12004-10-03 18:46:08 +00001306#endif
paul718e3742002-12-13 20:15:29 +00001307
1308 return CMD_SUCCESS;
1309}
1310
1311DEFUN (ip_address,
1312 ip_address_cmd,
1313 "ip address A.B.C.D/M",
1314 "Interface Internet Protocol config commands\n"
1315 "Set the IP address of an interface\n"
1316 "IP address (e.g. 10.0.0.1/8)\n")
1317{
hassoeef1fe12004-10-03 18:46:08 +00001318 return ip_address_install (vty, vty->index, argv[0], NULL, NULL);
paul718e3742002-12-13 20:15:29 +00001319}
1320
1321DEFUN (no_ip_address,
1322 no_ip_address_cmd,
1323 "no ip address A.B.C.D/M",
1324 NO_STR
1325 "Interface Internet Protocol config commands\n"
1326 "Set the IP address of an interface\n"
1327 "IP Address (e.g. 10.0.0.1/8)")
1328{
hassoeef1fe12004-10-03 18:46:08 +00001329 return ip_address_uninstall (vty, vty->index, argv[0], NULL, NULL);
paul718e3742002-12-13 20:15:29 +00001330}
1331
1332#ifdef HAVE_NETLINK
paul718e3742002-12-13 20:15:29 +00001333DEFUN (ip_address_label,
1334 ip_address_label_cmd,
1335 "ip address A.B.C.D/M label LINE",
1336 "Interface Internet Protocol config commands\n"
1337 "Set the IP address of an interface\n"
1338 "IP address (e.g. 10.0.0.1/8)\n"
1339 "Label of this address\n"
1340 "Label\n")
1341{
hassoeef1fe12004-10-03 18:46:08 +00001342 return ip_address_install (vty, vty->index, argv[0], NULL, argv[1]);
paul718e3742002-12-13 20:15:29 +00001343}
1344
1345DEFUN (no_ip_address_label,
1346 no_ip_address_label_cmd,
1347 "no ip address A.B.C.D/M label LINE",
1348 NO_STR
1349 "Interface Internet Protocol config commands\n"
1350 "Set the IP address of an interface\n"
1351 "IP address (e.g. 10.0.0.1/8)\n"
1352 "Label of this address\n"
1353 "Label\n")
1354{
hassoeef1fe12004-10-03 18:46:08 +00001355 return ip_address_uninstall (vty, vty->index, argv[0], NULL, argv[1]);
paul718e3742002-12-13 20:15:29 +00001356}
1357#endif /* HAVE_NETLINK */
1358
1359#ifdef HAVE_IPV6
paula1ac18c2005-06-28 17:17:12 +00001360static int
hasso39db97e2004-10-12 20:50:58 +00001361ipv6_address_install (struct vty *vty, struct interface *ifp,
1362 const char *addr_str, const char *peer_str,
1363 const char *label, int secondary)
paul718e3742002-12-13 20:15:29 +00001364{
1365 struct prefix_ipv6 cp;
1366 struct connected *ifc;
1367 struct prefix_ipv6 *p;
1368 int ret;
1369
1370 ret = str2prefix_ipv6 (addr_str, &cp);
1371 if (ret <= 0)
1372 {
1373 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1374 return CMD_WARNING;
1375 }
1376
paulca162182005-09-12 16:58:52 +00001377 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001378 if (! ifc)
1379 {
1380 ifc = connected_new ();
1381 ifc->ifp = ifp;
1382
1383 /* Address. */
1384 p = prefix_ipv6_new ();
1385 *p = cp;
1386 ifc->address = (struct prefix *) p;
1387
1388 /* Secondary. */
1389 if (secondary)
1390 SET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY);
1391
1392 /* Label. */
1393 if (label)
paul0752ef02005-11-03 12:35:21 +00001394 ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
paul718e3742002-12-13 20:15:29 +00001395
1396 /* Add to linked list. */
1397 listnode_add (ifp->connected, ifc);
1398 }
1399
1400 /* This address is configured from zebra. */
1401 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1402 SET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED);
1403
1404 /* In case of this route need to install kernel. */
1405 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1406 && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1407 {
1408 /* Some system need to up the interface to set IP address. */
1409 if (! if_is_up (ifp))
1410 {
1411 if_set_flags (ifp, IFF_UP | IFF_RUNNING);
1412 if_refresh (ifp);
1413 }
1414
1415 ret = if_prefix_add_ipv6 (ifp, ifc);
1416
1417 if (ret < 0)
1418 {
1419 vty_out (vty, "%% Can't set interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001420 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001421 return CMD_WARNING;
1422 }
1423
1424 /* IP address propery set. */
1425 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
1426
1427 /* Update interface address information to protocol daemon. */
1428 zebra_interface_address_add_update (ifp, ifc);
1429
1430 /* If interface is up register connected route. */
paul2e3b2e42002-12-13 21:03:13 +00001431 if (if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001432 connected_up_ipv6 (ifp, ifc);
1433 }
1434
1435 return CMD_SUCCESS;
1436}
1437
paula1ac18c2005-06-28 17:17:12 +00001438static int
hasso39db97e2004-10-12 20:50:58 +00001439ipv6_address_uninstall (struct vty *vty, struct interface *ifp,
1440 const char *addr_str, const char *peer_str,
1441 const char *label, int secondry)
paul718e3742002-12-13 20:15:29 +00001442{
1443 struct prefix_ipv6 cp;
1444 struct connected *ifc;
1445 int ret;
1446
1447 /* Convert to prefix structure. */
1448 ret = str2prefix_ipv6 (addr_str, &cp);
1449 if (ret <= 0)
1450 {
1451 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1452 return CMD_WARNING;
1453 }
1454
1455 /* Check current interface address. */
paulca162182005-09-12 16:58:52 +00001456 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001457 if (! ifc)
1458 {
1459 vty_out (vty, "%% Can't find address%s", VTY_NEWLINE);
1460 return CMD_WARNING;
1461 }
1462
1463 /* This is not configured address. */
1464 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1465 return CMD_WARNING;
1466
1467 /* This is not real address or interface is not active. */
1468 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1469 || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1470 {
1471 listnode_delete (ifp->connected, ifc);
1472 connected_free (ifc);
1473 return CMD_WARNING;
1474 }
1475
1476 /* This is real route. */
1477 ret = if_prefix_delete_ipv6 (ifp, ifc);
1478 if (ret < 0)
1479 {
1480 vty_out (vty, "%% Can't unset interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001481 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001482 return CMD_WARNING;
1483 }
1484
1485 /* Redistribute this information. */
1486 zebra_interface_address_delete_update (ifp, ifc);
1487
1488 /* Remove connected route. */
1489 connected_down_ipv6 (ifp, ifc);
1490
1491 /* Free address information. */
1492 listnode_delete (ifp->connected, ifc);
1493 connected_free (ifc);
1494
1495 return CMD_SUCCESS;
1496}
1497
1498DEFUN (ipv6_address,
1499 ipv6_address_cmd,
1500 "ipv6 address X:X::X:X/M",
hassoe23949c2004-03-11 15:54:02 +00001501 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001502 "Set the IP address of an interface\n"
1503 "IPv6 address (e.g. 3ffe:506::1/48)\n")
1504{
1505 return ipv6_address_install (vty, vty->index, argv[0], NULL, NULL, 0);
1506}
1507
1508DEFUN (no_ipv6_address,
1509 no_ipv6_address_cmd,
1510 "no ipv6 address X:X::X:X/M",
1511 NO_STR
hassoe23949c2004-03-11 15:54:02 +00001512 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001513 "Set the IP address of an interface\n"
1514 "IPv6 address (e.g. 3ffe:506::1/48)\n")
1515{
1516 return ipv6_address_uninstall (vty, vty->index, argv[0], NULL, NULL, 0);
1517}
1518#endif /* HAVE_IPV6 */
1519
paula1ac18c2005-06-28 17:17:12 +00001520static int
paul718e3742002-12-13 20:15:29 +00001521if_config_write (struct vty *vty)
1522{
hasso52dc7ee2004-09-23 19:18:23 +00001523 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001524 struct interface *ifp;
1525 char buf[BUFSIZ];
1526
paul1eb8ef22005-04-07 07:30:20 +00001527 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00001528 {
1529 struct zebra_if *if_data;
hasso52dc7ee2004-09-23 19:18:23 +00001530 struct listnode *addrnode;
paul718e3742002-12-13 20:15:29 +00001531 struct connected *ifc;
1532 struct prefix *p;
1533
paul718e3742002-12-13 20:15:29 +00001534 if_data = ifp->info;
1535
1536 vty_out (vty, "interface %s%s", ifp->name,
1537 VTY_NEWLINE);
1538
1539 if (ifp->desc)
1540 vty_out (vty, " description %s%s", ifp->desc,
1541 VTY_NEWLINE);
1542
1543 /* Assign bandwidth here to avoid unnecessary interface flap
1544 while processing config script */
1545 if (ifp->bandwidth != 0)
1546 vty_out(vty, " bandwidth %u%s", ifp->bandwidth, VTY_NEWLINE);
1547
paul2e3b2e42002-12-13 21:03:13 +00001548 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION))
1549 vty_out(vty, " link-detect%s", VTY_NEWLINE);
1550
paul1eb8ef22005-04-07 07:30:20 +00001551 for (ALL_LIST_ELEMENTS_RO (ifp->connected, addrnode, ifc))
paul718e3742002-12-13 20:15:29 +00001552 {
paul718e3742002-12-13 20:15:29 +00001553 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1554 {
1555 p = ifc->address;
1556 vty_out (vty, " ip%s address %s/%d",
1557 p->family == AF_INET ? "" : "v6",
1558 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
1559 p->prefixlen);
1560
paul718e3742002-12-13 20:15:29 +00001561 if (ifc->label)
1562 vty_out (vty, " label %s", ifc->label);
1563
1564 vty_out (vty, "%s", VTY_NEWLINE);
1565 }
1566 }
1567
1568 if (if_data)
1569 {
1570 if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)
1571 vty_out (vty, " shutdown%s", VTY_NEWLINE);
1572
1573 if (if_data->multicast != IF_ZEBRA_MULTICAST_UNSPEC)
1574 vty_out (vty, " %smulticast%s",
1575 if_data->multicast == IF_ZEBRA_MULTICAST_ON ? "" : "no ",
1576 VTY_NEWLINE);
1577 }
1578
1579#ifdef RTADV
1580 rtadv_config_write (vty, ifp);
1581#endif /* RTADV */
1582
hassoca776982004-06-12 14:33:05 +00001583#ifdef HAVE_IRDP
1584 irdp_config_write (vty, ifp);
1585#endif /* IRDP */
1586
paul718e3742002-12-13 20:15:29 +00001587 vty_out (vty, "!%s", VTY_NEWLINE);
1588 }
1589 return 0;
1590}
1591
1592/* Allocate and initialize interface vector. */
1593void
paula1ac18c2005-06-28 17:17:12 +00001594zebra_if_init (void)
paul718e3742002-12-13 20:15:29 +00001595{
1596 /* Initialize interface and new hook. */
1597 if_init ();
1598 if_add_hook (IF_NEW_HOOK, if_zebra_new_hook);
1599 if_add_hook (IF_DELETE_HOOK, if_zebra_delete_hook);
1600
1601 /* Install configuration write function. */
1602 install_node (&interface_node, if_config_write);
1603
1604 install_element (VIEW_NODE, &show_interface_cmd);
1605 install_element (ENABLE_NODE, &show_interface_cmd);
hassoed9bb6d2005-03-13 19:17:21 +00001606 install_element (ENABLE_NODE, &show_interface_desc_cmd);
paul718e3742002-12-13 20:15:29 +00001607 install_element (CONFIG_NODE, &zebra_interface_cmd);
paulbfc13532003-05-24 06:40:04 +00001608 install_element (CONFIG_NODE, &no_interface_cmd);
paul718e3742002-12-13 20:15:29 +00001609 install_default (INTERFACE_NODE);
1610 install_element (INTERFACE_NODE, &interface_desc_cmd);
1611 install_element (INTERFACE_NODE, &no_interface_desc_cmd);
1612 install_element (INTERFACE_NODE, &multicast_cmd);
1613 install_element (INTERFACE_NODE, &no_multicast_cmd);
paul2e3b2e42002-12-13 21:03:13 +00001614 install_element (INTERFACE_NODE, &linkdetect_cmd);
1615 install_element (INTERFACE_NODE, &no_linkdetect_cmd);
paul718e3742002-12-13 20:15:29 +00001616 install_element (INTERFACE_NODE, &shutdown_if_cmd);
1617 install_element (INTERFACE_NODE, &no_shutdown_if_cmd);
1618 install_element (INTERFACE_NODE, &bandwidth_if_cmd);
1619 install_element (INTERFACE_NODE, &no_bandwidth_if_cmd);
1620 install_element (INTERFACE_NODE, &no_bandwidth_if_val_cmd);
1621 install_element (INTERFACE_NODE, &ip_address_cmd);
1622 install_element (INTERFACE_NODE, &no_ip_address_cmd);
1623#ifdef HAVE_IPV6
1624 install_element (INTERFACE_NODE, &ipv6_address_cmd);
1625 install_element (INTERFACE_NODE, &no_ipv6_address_cmd);
1626#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +00001627#ifdef HAVE_NETLINK
paul718e3742002-12-13 20:15:29 +00001628 install_element (INTERFACE_NODE, &ip_address_label_cmd);
paul718e3742002-12-13 20:15:29 +00001629 install_element (INTERFACE_NODE, &no_ip_address_label_cmd);
paul718e3742002-12-13 20:15:29 +00001630#endif /* HAVE_NETLINK */
1631}