blob: 03e7ff71386695f20702ac297c6031fc0ac0542b [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
Chris Caputob60668d2009-05-03 04:40:57 +000044#ifdef RTADV
45/* Order is intentional. Matches RFC4191. This array is also used for
46 command matching, so only modify with care. */
47const char *rtadv_pref_strs[] = { "medium", "high", "INVALID", "low", 0 };
48#endif /* RTADV */
paul718e3742002-12-13 20:15:29 +000049
50/* Called when new interface is added. */
paula1ac18c2005-06-28 17:17:12 +000051static int
paul718e3742002-12-13 20:15:29 +000052if_zebra_new_hook (struct interface *ifp)
53{
54 struct zebra_if *zebra_if;
55
Stephen Hemminger393deb92008-08-18 14:13:29 -070056 zebra_if = XCALLOC (MTYPE_TMP, sizeof (struct zebra_if));
paul718e3742002-12-13 20:15:29 +000057
58 zebra_if->multicast = IF_ZEBRA_MULTICAST_UNSPEC;
59 zebra_if->shutdown = IF_ZEBRA_SHUTDOWN_UNSPEC;
60
61#ifdef RTADV
62 {
63 /* Set default router advertise values. */
64 struct rtadvconf *rtadv;
65
66 rtadv = &zebra_if->rtadv;
67
68 rtadv->AdvSendAdvertisements = 0;
69 rtadv->MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
70 rtadv->MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
71 rtadv->AdvIntervalTimer = 0;
72 rtadv->AdvManagedFlag = 0;
73 rtadv->AdvOtherConfigFlag = 0;
vincent7cee1bb2005-03-25 13:08:53 +000074 rtadv->AdvHomeAgentFlag = 0;
paul718e3742002-12-13 20:15:29 +000075 rtadv->AdvLinkMTU = 0;
76 rtadv->AdvReachableTime = 0;
77 rtadv->AdvRetransTimer = 0;
78 rtadv->AdvCurHopLimit = 0;
79 rtadv->AdvDefaultLifetime = RTADV_ADV_DEFAULT_LIFETIME;
vincent7cee1bb2005-03-25 13:08:53 +000080 rtadv->HomeAgentPreference = 0;
81 rtadv->HomeAgentLifetime = RTADV_ADV_DEFAULT_LIFETIME;
82 rtadv->AdvIntervalOption = 0;
Chris Caputob60668d2009-05-03 04:40:57 +000083 rtadv->DefaultPreference = RTADV_PREF_MEDIUM;
paul718e3742002-12-13 20:15:29 +000084
85 rtadv->AdvPrefixList = list_new ();
86 }
87#endif /* RTADV */
88
hassoeef1fe12004-10-03 18:46:08 +000089 /* Initialize installed address chains tree. */
90 zebra_if->ipv4_subnets = route_table_init ();
91
paul718e3742002-12-13 20:15:29 +000092 ifp->info = zebra_if;
93 return 0;
94}
95
96/* Called when interface is deleted. */
paula1ac18c2005-06-28 17:17:12 +000097static int
paul718e3742002-12-13 20:15:29 +000098if_zebra_delete_hook (struct interface *ifp)
99{
hassoeef1fe12004-10-03 18:46:08 +0000100 struct zebra_if *zebra_if;
101
paul718e3742002-12-13 20:15:29 +0000102 if (ifp->info)
hassoeef1fe12004-10-03 18:46:08 +0000103 {
104 zebra_if = ifp->info;
105
106 /* Free installed address chains tree. */
107 if (zebra_if->ipv4_subnets)
108 route_table_finish (zebra_if->ipv4_subnets);
109
110 XFREE (MTYPE_TMP, zebra_if);
111 }
112
113 return 0;
114}
115
116/* Tie an interface address to its derived subnet list of addresses. */
117int
118if_subnet_add (struct interface *ifp, struct connected *ifc)
119{
120 struct route_node *rn;
121 struct zebra_if *zebra_if;
122 struct prefix cp;
123 struct list *addr_list;
124
125 assert (ifp && ifp->info && ifc);
126 zebra_if = ifp->info;
127
128 /* Get address derived subnet node and associated address list, while marking
129 address secondary attribute appropriately. */
130 cp = *ifc->address;
131 apply_mask (&cp);
132 rn = route_node_get (zebra_if->ipv4_subnets, &cp);
133
134 if ((addr_list = rn->info))
135 SET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY);
136 else
137 {
138 UNSET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY);
139 rn->info = addr_list = list_new ();
140 route_lock_node (rn);
141 }
142
143 /* Tie address at the tail of address list. */
144 listnode_add (addr_list, ifc);
145
146 /* Return list element count. */
147 return (addr_list->count);
148}
149
150/* Untie an interface address from its derived subnet list of addresses. */
151int
152if_subnet_delete (struct interface *ifp, struct connected *ifc)
153{
154 struct route_node *rn;
155 struct zebra_if *zebra_if;
156 struct list *addr_list;
157
158 assert (ifp && ifp->info && ifc);
159 zebra_if = ifp->info;
160
161 /* Get address derived subnet node. */
162 rn = route_node_lookup (zebra_if->ipv4_subnets, ifc->address);
163 if (! (rn && rn->info))
164 return -1;
165 route_unlock_node (rn);
166
167 /* Untie address from subnet's address list. */
168 addr_list = rn->info;
169 listnode_delete (addr_list, ifc);
170 route_unlock_node (rn);
171
172 /* Return list element count, if not empty. */
173 if (addr_list->count)
174 {
175 /* If deleted address is primary, mark subsequent one as such and distribute. */
176 if (! CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY))
177 {
paul1eb8ef22005-04-07 07:30:20 +0000178 ifc = listgetdata (listhead (addr_list));
hassoeef1fe12004-10-03 18:46:08 +0000179 zebra_interface_address_delete_update (ifp, ifc);
180 UNSET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY);
181 zebra_interface_address_add_update (ifp, ifc);
182 }
183
184 return addr_list->count;
185 }
186
187 /* Otherwise, free list and route node. */
188 list_free (addr_list);
189 rn->info = NULL;
190 route_unlock_node (rn);
191
paul718e3742002-12-13 20:15:29 +0000192 return 0;
193}
194
paul5c78b3d2006-01-25 04:31:40 +0000195/* if_flags_mangle: A place for hacks that require mangling
196 * or tweaking the interface flags.
197 *
198 * ******************** Solaris flags hacks **************************
199 *
200 * Solaris IFF_UP flag reflects only the primary interface as the
201 * routing socket only sends IFINFO for the primary interface. Hence
202 * ~IFF_UP does not per se imply all the logical interfaces are also
203 * down - which we only know of as addresses. Instead we must determine
204 * whether the interface really is up or not according to how many
205 * addresses are still attached. (Solaris always sends RTM_DELADDR if
206 * an interface, logical or not, goes ~IFF_UP).
207 *
208 * Ie, we mangle IFF_UP to *additionally* reflect whether or not there
209 * are addresses left in struct connected, not just the actual underlying
210 * IFF_UP flag.
211 *
212 * We must hence remember the real state of IFF_UP, which we do in
213 * struct zebra_if.primary_state.
214 *
215 * Setting IFF_UP within zebra to administratively shutdown the
216 * interface will affect only the primary interface/address on Solaris.
217 ************************End Solaris flags hacks ***********************
218 */
219static inline void
220if_flags_mangle (struct interface *ifp, uint64_t *newflags)
221{
222#ifdef SUNOS_5
223 struct zebra_if *zif = ifp->info;
224
225 zif->primary_state = *newflags & (IFF_UP & 0xff);
226
227 if (CHECK_FLAG (zif->primary_state, IFF_UP)
228 || listcount(ifp->connected) > 0)
229 SET_FLAG (*newflags, IFF_UP);
230 else
231 UNSET_FLAG (*newflags, IFF_UP);
232#endif /* SUNOS_5 */
233}
234
235/* Update the flags field of the ifp with the new flag set provided.
236 * Take whatever actions are required for any changes in flags we care
237 * about.
238 *
239 * newflags should be the raw value, as obtained from the OS.
240 */
241void
242if_flags_update (struct interface *ifp, uint64_t newflags)
243{
244 if_flags_mangle (ifp, &newflags);
245
246 if (if_is_operative (ifp))
247 {
248 /* operative -> inoperative? */
249 ifp->flags = newflags;
250 if (!if_is_operative (ifp))
251 if_down (ifp);
252 }
253 else
254 {
255 /* inoperative -> operative? */
256 ifp->flags = newflags;
257 if (if_is_operative (ifp))
258 if_up (ifp);
259 }
260}
261
paul718e3742002-12-13 20:15:29 +0000262/* Wake up configured address if it is not in current kernel
263 address. */
paula1ac18c2005-06-28 17:17:12 +0000264static void
paul718e3742002-12-13 20:15:29 +0000265if_addr_wakeup (struct interface *ifp)
266{
paul1eb8ef22005-04-07 07:30:20 +0000267 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000268 struct connected *ifc;
269 struct prefix *p;
270 int ret;
271
paul1eb8ef22005-04-07 07:30:20 +0000272 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, ifc))
paul718e3742002-12-13 20:15:29 +0000273 {
paul718e3742002-12-13 20:15:29 +0000274 p = ifc->address;
275
276 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)
277 && ! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
278 {
279 /* Address check. */
280 if (p->family == AF_INET)
281 {
282 if (! if_is_up (ifp))
283 {
paul0752ef02005-11-03 12:35:21 +0000284 /* XXX: WTF is it trying to set flags here?
285 * caller has just gotten a new interface, has been
286 * handed the flags already. This code has no business
287 * trying to override administrative status of the interface.
288 * The only call path to here which doesn't originate from
289 * kernel event is irdp - what on earth is it trying to do?
290 *
291 * further RUNNING is not a settable flag on any system
292 * I (paulj) am aware of.
293 */
paul718e3742002-12-13 20:15:29 +0000294 if_set_flags (ifp, IFF_UP | IFF_RUNNING);
295 if_refresh (ifp);
296 }
297
298 ret = if_set_prefix (ifp, ifc);
299 if (ret < 0)
300 {
301 zlog_warn ("Can't set interface's address: %s",
ajs6099b3b2004-11-20 02:06:59 +0000302 safe_strerror(errno));
paul718e3742002-12-13 20:15:29 +0000303 continue;
304 }
hassoeef1fe12004-10-03 18:46:08 +0000305
306 /* Add to subnet chain list. */
307 if_subnet_add (ifp, ifc);
308
paul718e3742002-12-13 20:15:29 +0000309 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
310
311 zebra_interface_address_add_update (ifp, ifc);
312
paul2e3b2e42002-12-13 21:03:13 +0000313 if (if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000314 connected_up_ipv4 (ifp, ifc);
315 }
316#ifdef HAVE_IPV6
317 if (p->family == AF_INET6)
318 {
319 if (! if_is_up (ifp))
320 {
paul0752ef02005-11-03 12:35:21 +0000321 /* XXX: See long comment above */
paul718e3742002-12-13 20:15:29 +0000322 if_set_flags (ifp, IFF_UP | IFF_RUNNING);
323 if_refresh (ifp);
324 }
325
326 ret = if_prefix_add_ipv6 (ifp, ifc);
327 if (ret < 0)
328 {
329 zlog_warn ("Can't set interface's address: %s",
ajs6099b3b2004-11-20 02:06:59 +0000330 safe_strerror(errno));
paul718e3742002-12-13 20:15:29 +0000331 continue;
332 }
333 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
334
335 zebra_interface_address_add_update (ifp, ifc);
336
paul2e3b2e42002-12-13 21:03:13 +0000337 if (if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +0000338 connected_up_ipv6 (ifp, ifc);
339 }
340#endif /* HAVE_IPV6 */
341 }
342 }
343}
344
345/* Handle interface addition */
346void
347if_add_update (struct interface *ifp)
348{
paul48b33aa2002-12-13 20:52:52 +0000349 struct zebra_if *if_data;
350
351 if_data = ifp->info;
352 if (if_data->multicast == IF_ZEBRA_MULTICAST_ON)
353 if_set_flags (ifp, IFF_MULTICAST);
354 else if (if_data->multicast == IF_ZEBRA_MULTICAST_OFF)
355 if_unset_flags (ifp, IFF_MULTICAST);
356
paul718e3742002-12-13 20:15:29 +0000357 zebra_interface_add_update (ifp);
358
359 if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
360 {
361 SET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE);
362
363 if_addr_wakeup (ifp);
364
365 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +0000366 zlog_debug ("interface %s index %d becomes active.",
367 ifp->name, ifp->ifindex);
paul718e3742002-12-13 20:15:29 +0000368 }
369 else
370 {
371 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +0000372 zlog_debug ("interface %s index %d is added.", ifp->name, ifp->ifindex);
paul718e3742002-12-13 20:15:29 +0000373 }
374}
375
paul6eb88272005-07-29 14:36:00 +0000376/* Handle an interface delete event */
paul718e3742002-12-13 20:15:29 +0000377void
378if_delete_update (struct interface *ifp)
379{
paul718e3742002-12-13 20:15:29 +0000380 struct connected *ifc;
381 struct prefix *p;
hassoeef1fe12004-10-03 18:46:08 +0000382 struct route_node *rn;
383 struct zebra_if *zebra_if;
hassoeef1fe12004-10-03 18:46:08 +0000384
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 {
Paul Jakmad9a18f12007-04-10 19:30:20 +0000404 struct listnode *node;
405 struct listnode *last = NULL;
406
hassoeef1fe12004-10-03 18:46:08 +0000407 while ((node = (last ? last->next : listhead (ifp->connected))))
paul718e3742002-12-13 20:15:29 +0000408 {
paul1eb8ef22005-04-07 07:30:20 +0000409 ifc = listgetdata (node);
paul718e3742002-12-13 20:15:29 +0000410 p = ifc->address;
hassoeef1fe12004-10-03 18:46:08 +0000411
Paul Jakmabeb56332006-05-11 13:28:05 +0000412 if (p->family == AF_INET
413 && (rn = route_node_lookup (zebra_if->ipv4_subnets, p)))
hassoeef1fe12004-10-03 18:46:08 +0000414 {
Paul Jakmad9a18f12007-04-10 19:30:20 +0000415 struct listnode *anode;
416 struct listnode *next;
417 struct listnode *first;
418 struct list *addr_list;
419
hassoeef1fe12004-10-03 18:46:08 +0000420 route_unlock_node (rn);
421 addr_list = (struct list *) rn->info;
422
423 /* Remove addresses, secondaries first. */
424 first = listhead (addr_list);
Paul Jakmad9a18f12007-04-10 19:30:20 +0000425 for (anode = first->next; anode || first; anode = next)
hassoeef1fe12004-10-03 18:46:08 +0000426 {
Paul Jakmad9a18f12007-04-10 19:30:20 +0000427 if (!anode)
hassoeef1fe12004-10-03 18:46:08 +0000428 {
Paul Jakmad9a18f12007-04-10 19:30:20 +0000429 anode = first;
hassoeef1fe12004-10-03 18:46:08 +0000430 first = NULL;
431 }
Paul Jakmad9a18f12007-04-10 19:30:20 +0000432 next = anode->next;
hassoeef1fe12004-10-03 18:46:08 +0000433
Paul Jakmad9a18f12007-04-10 19:30:20 +0000434 ifc = listgetdata (anode);
hassoeef1fe12004-10-03 18:46:08 +0000435 p = ifc->address;
436
437 connected_down_ipv4 (ifp, ifc);
438
439 zebra_interface_address_delete_update (ifp, ifc);
440
441 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
442
443 /* Remove from subnet chain. */
Paul Jakmad9a18f12007-04-10 19:30:20 +0000444 list_delete_node (addr_list, anode);
hassoeef1fe12004-10-03 18:46:08 +0000445 route_unlock_node (rn);
446
447 /* Remove from interface address list (unconditionally). */
Paul Jakmad9a18f12007-04-10 19:30:20 +0000448 if (!CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
449 {
450 listnode_delete (ifp->connected, ifc);
451 connected_free (ifc);
452 }
453 else
454 last = node;
hassoeef1fe12004-10-03 18:46:08 +0000455 }
456
457 /* Free chain list and respective route node. */
458 list_delete (addr_list);
459 rn->info = NULL;
460 route_unlock_node (rn);
461 }
paul718e3742002-12-13 20:15:29 +0000462#ifdef HAVE_IPV6
463 else if (p->family == AF_INET6)
hassoeef1fe12004-10-03 18:46:08 +0000464 {
465 connected_down_ipv6 (ifp, ifc);
paul718e3742002-12-13 20:15:29 +0000466
hassoeef1fe12004-10-03 18:46:08 +0000467 zebra_interface_address_delete_update (ifp, ifc);
paul718e3742002-12-13 20:15:29 +0000468
hassoeef1fe12004-10-03 18:46:08 +0000469 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
470
471 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
472 last = node;
473 else
474 {
475 listnode_delete (ifp->connected, ifc);
476 connected_free (ifc);
477 }
paul718e3742002-12-13 20:15:29 +0000478 }
hassoeef1fe12004-10-03 18:46:08 +0000479#endif /* HAVE_IPV6 */
Roman Hoog Antinke26873f2010-05-05 16:00:50 +0200480 else
481 {
482 last = node;
483 }
paul718e3742002-12-13 20:15:29 +0000484 }
485 }
486 zebra_interface_delete_update (ifp);
ajsd2fc8892005-04-02 18:38:43 +0000487
488 /* Update ifindex after distributing the delete message. This is in
489 case any client needs to have the old value of ifindex available
490 while processing the deletion. Each client daemon is responsible
491 for setting ifindex to IFINDEX_INTERNAL after processing the
492 interface deletion message. */
493 ifp->ifindex = IFINDEX_INTERNAL;
paul718e3742002-12-13 20:15:29 +0000494}
495
496/* Interface is up. */
497void
498if_up (struct interface *ifp)
499{
hasso52dc7ee2004-09-23 19:18:23 +0000500 struct listnode *node;
501 struct listnode *next;
paul718e3742002-12-13 20:15:29 +0000502 struct connected *ifc;
503 struct prefix *p;
504
505 /* Notify the protocol daemons. */
506 zebra_interface_up_update (ifp);
507
508 /* Install connected routes to the kernel. */
509 if (ifp->connected)
510 {
paul1eb8ef22005-04-07 07:30:20 +0000511 for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc))
paul718e3742002-12-13 20:15:29 +0000512 {
paul718e3742002-12-13 20:15:29 +0000513 p = ifc->address;
514
515 if (p->family == AF_INET)
516 connected_up_ipv4 (ifp, ifc);
517#ifdef HAVE_IPV6
518 else if (p->family == AF_INET6)
519 connected_up_ipv6 (ifp, ifc);
520#endif /* HAVE_IPV6 */
521 }
522 }
523
524 /* Examine all static routes. */
525 rib_update ();
526}
527
528/* Interface goes down. We have to manage different behavior of based
529 OS. */
530void
531if_down (struct interface *ifp)
532{
hasso52dc7ee2004-09-23 19:18:23 +0000533 struct listnode *node;
534 struct listnode *next;
paul718e3742002-12-13 20:15:29 +0000535 struct connected *ifc;
536 struct prefix *p;
537
538 /* Notify to the protocol daemons. */
539 zebra_interface_down_update (ifp);
540
541 /* Delete connected routes from the kernel. */
542 if (ifp->connected)
543 {
paul1eb8ef22005-04-07 07:30:20 +0000544 for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc))
paul718e3742002-12-13 20:15:29 +0000545 {
paul718e3742002-12-13 20:15:29 +0000546 p = ifc->address;
547
548 if (p->family == AF_INET)
549 connected_down_ipv4 (ifp, ifc);
550#ifdef HAVE_IPV6
551 else if (p->family == AF_INET6)
552 connected_down_ipv6 (ifp, ifc);
553#endif /* HAVE_IPV6 */
554 }
555 }
556
557 /* Examine all static routes which direct to the interface. */
558 rib_update ();
559}
560
561void
562if_refresh (struct interface *ifp)
563{
paul5c78b3d2006-01-25 04:31:40 +0000564 if_get_flags (ifp);
paul718e3742002-12-13 20:15:29 +0000565}
566
paul718e3742002-12-13 20:15:29 +0000567/* Output prefix string to vty. */
paula1ac18c2005-06-28 17:17:12 +0000568static int
paul718e3742002-12-13 20:15:29 +0000569prefix_vty_out (struct vty *vty, struct prefix *p)
570{
571 char str[INET6_ADDRSTRLEN];
572
573 inet_ntop (p->family, &p->u.prefix, str, sizeof (str));
574 vty_out (vty, "%s", str);
575 return strlen (str);
576}
577
578/* Dump if address information to vty. */
paula1ac18c2005-06-28 17:17:12 +0000579static void
paul718e3742002-12-13 20:15:29 +0000580connected_dump_vty (struct vty *vty, struct connected *connected)
581{
582 struct prefix *p;
paul718e3742002-12-13 20:15:29 +0000583
584 /* Print interface address. */
585 p = connected->address;
586 vty_out (vty, " %s ", prefix_family_str (p));
587 prefix_vty_out (vty, p);
588 vty_out (vty, "/%d", p->prefixlen);
589
590 /* If there is destination address, print it. */
Andrew J. Schorre4529632006-12-12 19:18:21 +0000591 if (connected->destination)
paul718e3742002-12-13 20:15:29 +0000592 {
Andrew J. Schorre4529632006-12-12 19:18:21 +0000593 vty_out (vty, (CONNECTED_PEER(connected) ? " peer " : " broadcast "));
594 prefix_vty_out (vty, connected->destination);
paul718e3742002-12-13 20:15:29 +0000595 }
596
597 if (CHECK_FLAG (connected->flags, ZEBRA_IFA_SECONDARY))
598 vty_out (vty, " secondary");
599
600 if (connected->label)
601 vty_out (vty, " %s", connected->label);
602
603 vty_out (vty, "%s", VTY_NEWLINE);
604}
605
606#ifdef RTADV
607/* Dump interface ND information to vty. */
paula1ac18c2005-06-28 17:17:12 +0000608static void
paul718e3742002-12-13 20:15:29 +0000609nd_dump_vty (struct vty *vty, struct interface *ifp)
610{
611 struct zebra_if *zif;
612 struct rtadvconf *rtadv;
vincent7cee1bb2005-03-25 13:08:53 +0000613 int interval;
paul718e3742002-12-13 20:15:29 +0000614
615 zif = (struct zebra_if *) ifp->info;
616 rtadv = &zif->rtadv;
617
618 if (rtadv->AdvSendAdvertisements)
619 {
620 vty_out (vty, " ND advertised reachable time is %d milliseconds%s",
621 rtadv->AdvReachableTime, VTY_NEWLINE);
622 vty_out (vty, " ND advertised retransmit interval is %d milliseconds%s",
623 rtadv->AdvRetransTimer, VTY_NEWLINE);
vincent7cee1bb2005-03-25 13:08:53 +0000624 interval = rtadv->MaxRtrAdvInterval;
625 if (interval % 1000)
626 vty_out (vty, " ND router advertisements are sent every "
627 "%d milliseconds%s", interval,
628 VTY_NEWLINE);
629 else
630 vty_out (vty, " ND router advertisements are sent every "
631 "%d seconds%s", interval / 1000,
632 VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000633 vty_out (vty, " ND router advertisements live for %d seconds%s",
634 rtadv->AdvDefaultLifetime, VTY_NEWLINE);
Chris Caputob60668d2009-05-03 04:40:57 +0000635 vty_out (vty, " ND router advertisement default router preference is "
636 "%s%s", rtadv_pref_strs[rtadv->DefaultPreference],
637 VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000638 if (rtadv->AdvManagedFlag)
639 vty_out (vty, " Hosts use DHCP to obtain routable addresses.%s",
640 VTY_NEWLINE);
641 else
642 vty_out (vty, " Hosts use stateless autoconfig for addresses.%s",
643 VTY_NEWLINE);
vincent7cee1bb2005-03-25 13:08:53 +0000644 if (rtadv->AdvHomeAgentFlag)
645 vty_out (vty, " ND router advertisements with "
646 "Home Agent flag bit set.%s",
647 VTY_NEWLINE);
648 if (rtadv->AdvIntervalOption)
649 vty_out (vty, " ND router advertisements with Adv. Interval option.%s",
650 VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000651 }
652}
653#endif /* RTADV */
654
655/* Interface's information print out to vty interface. */
paula1ac18c2005-06-28 17:17:12 +0000656static void
paul718e3742002-12-13 20:15:29 +0000657if_dump_vty (struct vty *vty, struct interface *ifp)
658{
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000659#ifdef HAVE_STRUCT_SOCKADDR_DL
paul718e3742002-12-13 20:15:29 +0000660 struct sockaddr_dl *sdl;
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000661#endif /* HAVE_STRUCT_SOCKADDR_DL */
paul718e3742002-12-13 20:15:29 +0000662 struct connected *connected;
hasso52dc7ee2004-09-23 19:18:23 +0000663 struct listnode *node;
hassoeef1fe12004-10-03 18:46:08 +0000664 struct route_node *rn;
665 struct zebra_if *zebra_if;
666
667 zebra_if = ifp->info;
paul718e3742002-12-13 20:15:29 +0000668
paul2e3b2e42002-12-13 21:03:13 +0000669 vty_out (vty, "Interface %s is ", ifp->name);
670 if (if_is_up(ifp)) {
671 vty_out (vty, "up, line protocol ");
672
673 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) {
674 if (if_is_running(ifp))
675 vty_out (vty, "is up%s", VTY_NEWLINE);
676 else
677 vty_out (vty, "is down%s", VTY_NEWLINE);
678 } else {
679 vty_out (vty, "detection is disabled%s", VTY_NEWLINE);
680 }
681 } else {
682 vty_out (vty, "down%s", VTY_NEWLINE);
683 }
684
paul718e3742002-12-13 20:15:29 +0000685 if (ifp->desc)
686 vty_out (vty, " Description: %s%s", ifp->desc,
687 VTY_NEWLINE);
ajsd2fc8892005-04-02 18:38:43 +0000688 if (ifp->ifindex == IFINDEX_INTERNAL)
paul718e3742002-12-13 20:15:29 +0000689 {
ajsd2fc8892005-04-02 18:38:43 +0000690 vty_out(vty, " pseudo interface%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000691 return;
692 }
693 else if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
694 {
695 vty_out(vty, " index %d inactive interface%s",
696 ifp->ifindex,
697 VTY_NEWLINE);
698 return;
699 }
700
701 vty_out (vty, " index %d metric %d mtu %d ",
702 ifp->ifindex, ifp->metric, ifp->mtu);
paul44145db2004-05-09 11:00:23 +0000703#ifdef HAVE_IPV6
704 if (ifp->mtu6 != ifp->mtu)
705 vty_out (vty, "mtu6 %d ", ifp->mtu6);
706#endif
Paul Jakma630c97c2006-06-15 12:48:17 +0000707 vty_out (vty, "%s flags: %s%s", VTY_NEWLINE,
708 if_flag_dump (ifp->flags), VTY_NEWLINE);
paul3a570c82006-02-02 17:27:13 +0000709
paul718e3742002-12-13 20:15:29 +0000710 /* Hardware address. */
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000711#ifdef HAVE_STRUCT_SOCKADDR_DL
paul718e3742002-12-13 20:15:29 +0000712 sdl = &ifp->sdl;
713 if (sdl != NULL && sdl->sdl_alen != 0)
714 {
715 int i;
716 u_char *ptr;
717
718 vty_out (vty, " HWaddr: ");
paul5b73a672004-07-23 15:26:14 +0000719 for (i = 0, ptr = (u_char *)LLADDR (sdl); i < sdl->sdl_alen; i++, ptr++)
720 vty_out (vty, "%s%02x", i == 0 ? "" : ":", *ptr);
paul718e3742002-12-13 20:15:29 +0000721 vty_out (vty, "%s", VTY_NEWLINE);
722 }
723#else
724 if (ifp->hw_addr_len != 0)
725 {
726 int i;
727
728 vty_out (vty, " HWaddr: ");
729 for (i = 0; i < ifp->hw_addr_len; i++)
730 vty_out (vty, "%s%02x", i == 0 ? "" : ":", ifp->hw_addr[i]);
731 vty_out (vty, "%s", VTY_NEWLINE);
732 }
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000733#endif /* HAVE_STRUCT_SOCKADDR_DL */
paul718e3742002-12-13 20:15:29 +0000734
735 /* Bandwidth in kbps */
736 if (ifp->bandwidth != 0)
737 {
738 vty_out(vty, " bandwidth %u kbps", ifp->bandwidth);
739 vty_out(vty, "%s", VTY_NEWLINE);
740 }
741
hassoeef1fe12004-10-03 18:46:08 +0000742 for (rn = route_top (zebra_if->ipv4_subnets); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000743 {
hassoeef1fe12004-10-03 18:46:08 +0000744 if (! rn->info)
745 continue;
746
paul1eb8ef22005-04-07 07:30:20 +0000747 for (ALL_LIST_ELEMENTS_RO ((struct list *)rn->info, node, connected))
748 connected_dump_vty (vty, connected);
paul718e3742002-12-13 20:15:29 +0000749 }
750
paul1eb8ef22005-04-07 07:30:20 +0000751 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
hasso39db97e2004-10-12 20:50:58 +0000752 {
hasso39db97e2004-10-12 20:50:58 +0000753 if (CHECK_FLAG (connected->conf, ZEBRA_IFC_REAL) &&
754 (connected->address->family == AF_INET6))
755 connected_dump_vty (vty, connected);
756 }
757
paul718e3742002-12-13 20:15:29 +0000758#ifdef RTADV
759 nd_dump_vty (vty, ifp);
760#endif /* RTADV */
761
762#ifdef HAVE_PROC_NET_DEV
763 /* Statistics print out using proc file system. */
hasso6f2c27a2005-01-18 13:44:35 +0000764 vty_out (vty, " %lu input packets (%lu multicast), %lu bytes, "
765 "%lu dropped%s",
766 ifp->stats.rx_packets, ifp->stats.rx_multicast,
767 ifp->stats.rx_bytes, ifp->stats.rx_dropped, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000768
hasso6f2c27a2005-01-18 13:44:35 +0000769 vty_out (vty, " %lu input errors, %lu length, %lu overrun,"
hasso3452d472005-03-06 13:42:05 +0000770 " %lu CRC, %lu frame%s",
paul718e3742002-12-13 20:15:29 +0000771 ifp->stats.rx_errors, ifp->stats.rx_length_errors,
772 ifp->stats.rx_over_errors, ifp->stats.rx_crc_errors,
hasso6f2c27a2005-01-18 13:44:35 +0000773 ifp->stats.rx_frame_errors, VTY_NEWLINE);
774
775 vty_out (vty, " %lu fifo, %lu missed%s", ifp->stats.rx_fifo_errors,
paul718e3742002-12-13 20:15:29 +0000776 ifp->stats.rx_missed_errors, VTY_NEWLINE);
777
hasso6f2c27a2005-01-18 13:44:35 +0000778 vty_out (vty, " %lu output packets, %lu bytes, %lu dropped%s",
paul718e3742002-12-13 20:15:29 +0000779 ifp->stats.tx_packets, ifp->stats.tx_bytes,
780 ifp->stats.tx_dropped, VTY_NEWLINE);
781
hasso6f2c27a2005-01-18 13:44:35 +0000782 vty_out (vty, " %lu output errors, %lu aborted, %lu carrier,"
783 " %lu fifo, %lu heartbeat%s",
paul718e3742002-12-13 20:15:29 +0000784 ifp->stats.tx_errors, ifp->stats.tx_aborted_errors,
785 ifp->stats.tx_carrier_errors, ifp->stats.tx_fifo_errors,
hasso6f2c27a2005-01-18 13:44:35 +0000786 ifp->stats.tx_heartbeat_errors, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000787
hasso6f2c27a2005-01-18 13:44:35 +0000788 vty_out (vty, " %lu window, %lu collisions%s",
789 ifp->stats.tx_window_errors, ifp->stats.collisions, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000790#endif /* HAVE_PROC_NET_DEV */
791
792#ifdef HAVE_NET_RT_IFLIST
793#if defined (__bsdi__) || defined (__NetBSD__)
794 /* Statistics print out using sysctl (). */
795 vty_out (vty, " input packets %qu, bytes %qu, dropped %qu,"
796 " multicast packets %qu%s",
797 ifp->stats.ifi_ipackets, ifp->stats.ifi_ibytes,
798 ifp->stats.ifi_iqdrops, ifp->stats.ifi_imcasts,
799 VTY_NEWLINE);
800
801 vty_out (vty, " input errors %qu%s",
802 ifp->stats.ifi_ierrors, VTY_NEWLINE);
803
804 vty_out (vty, " output packets %qu, bytes %qu, multicast packets %qu%s",
805 ifp->stats.ifi_opackets, ifp->stats.ifi_obytes,
806 ifp->stats.ifi_omcasts, VTY_NEWLINE);
807
808 vty_out (vty, " output errors %qu%s",
809 ifp->stats.ifi_oerrors, VTY_NEWLINE);
810
811 vty_out (vty, " collisions %qu%s",
812 ifp->stats.ifi_collisions, VTY_NEWLINE);
813#else
814 /* Statistics print out using sysctl (). */
815 vty_out (vty, " input packets %lu, bytes %lu, dropped %lu,"
816 " multicast packets %lu%s",
817 ifp->stats.ifi_ipackets, ifp->stats.ifi_ibytes,
818 ifp->stats.ifi_iqdrops, ifp->stats.ifi_imcasts,
819 VTY_NEWLINE);
820
821 vty_out (vty, " input errors %lu%s",
822 ifp->stats.ifi_ierrors, VTY_NEWLINE);
823
824 vty_out (vty, " output packets %lu, bytes %lu, multicast packets %lu%s",
825 ifp->stats.ifi_opackets, ifp->stats.ifi_obytes,
826 ifp->stats.ifi_omcasts, VTY_NEWLINE);
827
828 vty_out (vty, " output errors %lu%s",
829 ifp->stats.ifi_oerrors, VTY_NEWLINE);
830
831 vty_out (vty, " collisions %lu%s",
832 ifp->stats.ifi_collisions, VTY_NEWLINE);
833#endif /* __bsdi__ || __NetBSD__ */
834#endif /* HAVE_NET_RT_IFLIST */
835}
836
paul718e3742002-12-13 20:15:29 +0000837/* Wrapper hook point for zebra daemon so that ifindex can be set
838 * DEFUN macro not used as extract.pl HAS to ignore this
839 * See also interface_cmd in lib/if.c
840 */
841DEFUN_NOSH (zebra_interface,
842 zebra_interface_cmd,
843 "interface IFNAME",
844 "Select an interface to configure\n"
845 "Interface's name\n")
846{
847 int ret;
848 struct interface * ifp;
849
850 /* Call lib interface() */
ajsd2fc8892005-04-02 18:38:43 +0000851 if ((ret = interface_cmd.func (self, vty, argc, argv)) != CMD_SUCCESS)
852 return ret;
paul718e3742002-12-13 20:15:29 +0000853
854 ifp = vty->index;
855
ajsd2fc8892005-04-02 18:38:43 +0000856 if (ifp->ifindex == IFINDEX_INTERNAL)
857 /* Is this really necessary? Shouldn't status be initialized to 0
858 in that case? */
859 UNSET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE);
paul718e3742002-12-13 20:15:29 +0000860
861 return ret;
862}
863
paul718e3742002-12-13 20:15:29 +0000864struct cmd_node interface_node =
865{
866 INTERFACE_NODE,
867 "%s(config-if)# ",
868 1
869};
870
871/* Show all or specified interface to vty. */
872DEFUN (show_interface, show_interface_cmd,
873 "show interface [IFNAME]",
874 SHOW_STR
875 "Interface status and configuration\n"
876 "Inteface name\n")
877{
hasso52dc7ee2004-09-23 19:18:23 +0000878 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000879 struct interface *ifp;
880
881#ifdef HAVE_PROC_NET_DEV
882 /* If system has interface statistics via proc file system, update
883 statistics. */
884 ifstat_update_proc ();
885#endif /* HAVE_PROC_NET_DEV */
886#ifdef HAVE_NET_RT_IFLIST
887 ifstat_update_sysctl ();
888#endif /* HAVE_NET_RT_IFLIST */
889
890 /* Specified interface print. */
891 if (argc != 0)
892 {
893 ifp = if_lookup_by_name (argv[0]);
894 if (ifp == NULL)
895 {
896 vty_out (vty, "%% Can't find interface %s%s", argv[0],
897 VTY_NEWLINE);
898 return CMD_WARNING;
899 }
900 if_dump_vty (vty, ifp);
901 return CMD_SUCCESS;
902 }
903
904 /* All interface print. */
paul1eb8ef22005-04-07 07:30:20 +0000905 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
906 if_dump_vty (vty, ifp);
paul718e3742002-12-13 20:15:29 +0000907
908 return CMD_SUCCESS;
909}
910
hassoed9bb6d2005-03-13 19:17:21 +0000911DEFUN (show_interface_desc,
912 show_interface_desc_cmd,
913 "show interface description",
914 SHOW_STR
915 "Interface status and configuration\n"
916 "Interface description\n")
917{
918 struct listnode *node;
919 struct interface *ifp;
920
921 vty_out (vty, "Interface Status Protocol Description%s", VTY_NEWLINE);
paul1eb8ef22005-04-07 07:30:20 +0000922 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
hassoed9bb6d2005-03-13 19:17:21 +0000923 {
924 int len;
hassoed9bb6d2005-03-13 19:17:21 +0000925
926 len = vty_out (vty, "%s", ifp->name);
927 vty_out (vty, "%*s", (16 - len), " ");
928
929 if (if_is_up(ifp))
930 {
931 vty_out (vty, "up ");
932 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION))
933 {
934 if (if_is_running(ifp))
935 vty_out (vty, "up ");
936 else
937 vty_out (vty, "down ");
938 }
939 else
940 {
941 vty_out (vty, "unknown ");
942 }
943 }
944 else
945 {
946 vty_out (vty, "down down ");
947 }
948
949 if (ifp->desc)
950 vty_out (vty, "%s", ifp->desc);
951 vty_out (vty, "%s", VTY_NEWLINE);
952 }
953 return CMD_SUCCESS;
954}
955
paul718e3742002-12-13 20:15:29 +0000956DEFUN (multicast,
957 multicast_cmd,
958 "multicast",
959 "Set multicast flag to interface\n")
960{
961 int ret;
962 struct interface *ifp;
963 struct zebra_if *if_data;
964
965 ifp = (struct interface *) vty->index;
paul48b33aa2002-12-13 20:52:52 +0000966 if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
paul718e3742002-12-13 20:15:29 +0000967 {
paul48b33aa2002-12-13 20:52:52 +0000968 ret = if_set_flags (ifp, IFF_MULTICAST);
969 if (ret < 0)
970 {
971 vty_out (vty, "Can't set multicast flag%s", VTY_NEWLINE);
972 return CMD_WARNING;
973 }
974 if_refresh (ifp);
paul718e3742002-12-13 20:15:29 +0000975 }
paul718e3742002-12-13 20:15:29 +0000976 if_data = ifp->info;
977 if_data->multicast = IF_ZEBRA_MULTICAST_ON;
paul48b33aa2002-12-13 20:52:52 +0000978
paul718e3742002-12-13 20:15:29 +0000979 return CMD_SUCCESS;
980}
981
982DEFUN (no_multicast,
983 no_multicast_cmd,
984 "no multicast",
985 NO_STR
986 "Unset multicast flag to interface\n")
987{
988 int ret;
989 struct interface *ifp;
990 struct zebra_if *if_data;
991
992 ifp = (struct interface *) vty->index;
paul48b33aa2002-12-13 20:52:52 +0000993 if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
paul718e3742002-12-13 20:15:29 +0000994 {
paul48b33aa2002-12-13 20:52:52 +0000995 ret = if_unset_flags (ifp, IFF_MULTICAST);
996 if (ret < 0)
997 {
998 vty_out (vty, "Can't unset multicast flag%s", VTY_NEWLINE);
999 return CMD_WARNING;
1000 }
1001 if_refresh (ifp);
paul718e3742002-12-13 20:15:29 +00001002 }
paul718e3742002-12-13 20:15:29 +00001003 if_data = ifp->info;
1004 if_data->multicast = IF_ZEBRA_MULTICAST_OFF;
1005
1006 return CMD_SUCCESS;
1007}
1008
paul2e3b2e42002-12-13 21:03:13 +00001009DEFUN (linkdetect,
1010 linkdetect_cmd,
1011 "link-detect",
1012 "Enable link detection on interface\n")
1013{
paul2e3b2e42002-12-13 21:03:13 +00001014 struct interface *ifp;
1015 int if_was_operative;
1016
1017 ifp = (struct interface *) vty->index;
1018 if_was_operative = if_is_operative(ifp);
1019 SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
1020
1021 /* When linkdetection is enabled, if might come down */
1022 if (!if_is_operative(ifp) && if_was_operative) if_down(ifp);
1023
1024 /* FIXME: Will defer status change forwarding if interface
1025 does not come down! */
1026
1027 return CMD_SUCCESS;
1028}
1029
1030
1031DEFUN (no_linkdetect,
1032 no_linkdetect_cmd,
1033 "no link-detect",
1034 NO_STR
1035 "Disable link detection on interface\n")
1036{
paul2e3b2e42002-12-13 21:03:13 +00001037 struct interface *ifp;
1038 int if_was_operative;
1039
1040 ifp = (struct interface *) vty->index;
1041 if_was_operative = if_is_operative(ifp);
1042 UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
1043
1044 /* Interface may come up after disabling link detection */
1045 if (if_is_operative(ifp) && !if_was_operative) if_up(ifp);
1046
1047 /* FIXME: see linkdetect_cmd */
1048
1049 return CMD_SUCCESS;
1050}
1051
paul718e3742002-12-13 20:15:29 +00001052DEFUN (shutdown_if,
1053 shutdown_if_cmd,
1054 "shutdown",
1055 "Shutdown the selected interface\n")
1056{
1057 int ret;
1058 struct interface *ifp;
1059 struct zebra_if *if_data;
1060
1061 ifp = (struct interface *) vty->index;
1062 ret = if_unset_flags (ifp, IFF_UP);
1063 if (ret < 0)
1064 {
1065 vty_out (vty, "Can't shutdown interface%s", VTY_NEWLINE);
1066 return CMD_WARNING;
1067 }
1068 if_refresh (ifp);
1069 if_data = ifp->info;
1070 if_data->shutdown = IF_ZEBRA_SHUTDOWN_ON;
1071
1072 return CMD_SUCCESS;
1073}
1074
1075DEFUN (no_shutdown_if,
1076 no_shutdown_if_cmd,
1077 "no shutdown",
1078 NO_STR
1079 "Shutdown the selected interface\n")
1080{
1081 int ret;
1082 struct interface *ifp;
1083 struct zebra_if *if_data;
1084
1085 ifp = (struct interface *) vty->index;
1086 ret = if_set_flags (ifp, IFF_UP | IFF_RUNNING);
1087 if (ret < 0)
1088 {
1089 vty_out (vty, "Can't up interface%s", VTY_NEWLINE);
1090 return CMD_WARNING;
1091 }
1092 if_refresh (ifp);
1093 if_data = ifp->info;
1094 if_data->shutdown = IF_ZEBRA_SHUTDOWN_OFF;
1095
1096 return CMD_SUCCESS;
1097}
1098
1099DEFUN (bandwidth_if,
1100 bandwidth_if_cmd,
1101 "bandwidth <1-10000000>",
1102 "Set bandwidth informational parameter\n"
1103 "Bandwidth in kilobits\n")
1104{
1105 struct interface *ifp;
1106 unsigned int bandwidth;
1107
1108 ifp = (struct interface *) vty->index;
1109 bandwidth = strtol(argv[0], NULL, 10);
1110
1111 /* bandwidth range is <1-10000000> */
1112 if (bandwidth < 1 || bandwidth > 10000000)
1113 {
1114 vty_out (vty, "Bandwidth is invalid%s", VTY_NEWLINE);
1115 return CMD_WARNING;
1116 }
1117
1118 ifp->bandwidth = bandwidth;
1119
1120 /* force protocols to recalculate routes due to cost change */
paul2e3b2e42002-12-13 21:03:13 +00001121 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00001122 zebra_interface_up_update (ifp);
1123
1124 return CMD_SUCCESS;
1125}
1126
1127DEFUN (no_bandwidth_if,
1128 no_bandwidth_if_cmd,
1129 "no bandwidth",
1130 NO_STR
1131 "Set bandwidth informational parameter\n")
1132{
1133 struct interface *ifp;
1134
1135 ifp = (struct interface *) vty->index;
1136
1137 ifp->bandwidth = 0;
1138
1139 /* force protocols to recalculate routes due to cost change */
paul2e3b2e42002-12-13 21:03:13 +00001140 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00001141 zebra_interface_up_update (ifp);
1142
1143 return CMD_SUCCESS;
1144}
1145
1146ALIAS (no_bandwidth_if,
1147 no_bandwidth_if_val_cmd,
1148 "no bandwidth <1-10000000>",
1149 NO_STR
1150 "Set bandwidth informational parameter\n"
1151 "Bandwidth in kilobits\n")
1152
paula1ac18c2005-06-28 17:17:12 +00001153static int
hasso39db97e2004-10-12 20:50:58 +00001154ip_address_install (struct vty *vty, struct interface *ifp,
1155 const char *addr_str, const char *peer_str,
1156 const char *label)
paul718e3742002-12-13 20:15:29 +00001157{
1158 struct prefix_ipv4 cp;
1159 struct connected *ifc;
1160 struct prefix_ipv4 *p;
paul718e3742002-12-13 20:15:29 +00001161 int ret;
1162
1163 ret = str2prefix_ipv4 (addr_str, &cp);
1164 if (ret <= 0)
1165 {
1166 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1167 return CMD_WARNING;
1168 }
1169
paulca162182005-09-12 16:58:52 +00001170 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001171 if (! ifc)
1172 {
1173 ifc = connected_new ();
1174 ifc->ifp = ifp;
1175
1176 /* Address. */
1177 p = prefix_ipv4_new ();
1178 *p = cp;
1179 ifc->address = (struct prefix *) p;
1180
1181 /* Broadcast. */
hasso3fb9cd62004-10-19 19:44:43 +00001182 if (p->prefixlen <= IPV4_MAX_PREFIXLEN-2)
paul718e3742002-12-13 20:15:29 +00001183 {
1184 p = prefix_ipv4_new ();
1185 *p = cp;
hasso3fb9cd62004-10-19 19:44:43 +00001186 p->prefix.s_addr = ipv4_broadcast_addr(p->prefix.s_addr,p->prefixlen);
paul718e3742002-12-13 20:15:29 +00001187 ifc->destination = (struct prefix *) p;
1188 }
1189
paul718e3742002-12-13 20:15:29 +00001190 /* Label. */
1191 if (label)
paul0752ef02005-11-03 12:35:21 +00001192 ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
paul718e3742002-12-13 20:15:29 +00001193
1194 /* Add to linked list. */
1195 listnode_add (ifp->connected, ifc);
1196 }
1197
1198 /* This address is configured from zebra. */
1199 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1200 SET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED);
1201
1202 /* In case of this route need to install kernel. */
1203 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1204 && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1205 {
1206 /* Some system need to up the interface to set IP address. */
1207 if (! if_is_up (ifp))
1208 {
1209 if_set_flags (ifp, IFF_UP | IFF_RUNNING);
1210 if_refresh (ifp);
1211 }
1212
1213 ret = if_set_prefix (ifp, ifc);
1214 if (ret < 0)
1215 {
1216 vty_out (vty, "%% Can't set interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001217 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001218 return CMD_WARNING;
1219 }
1220
hassoeef1fe12004-10-03 18:46:08 +00001221 /* Add to subnet chain list (while marking secondary attribute). */
1222 if_subnet_add (ifp, ifc);
1223
paul718e3742002-12-13 20:15:29 +00001224 /* IP address propery set. */
1225 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
1226
1227 /* Update interface address information to protocol daemon. */
1228 zebra_interface_address_add_update (ifp, ifc);
1229
1230 /* If interface is up register connected route. */
paul2e3b2e42002-12-13 21:03:13 +00001231 if (if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001232 connected_up_ipv4 (ifp, ifc);
1233 }
1234
1235 return CMD_SUCCESS;
1236}
1237
paula1ac18c2005-06-28 17:17:12 +00001238static int
hasso39db97e2004-10-12 20:50:58 +00001239ip_address_uninstall (struct vty *vty, struct interface *ifp,
1240 const char *addr_str, const char *peer_str,
1241 const char *label)
paul718e3742002-12-13 20:15:29 +00001242{
1243 struct prefix_ipv4 cp;
1244 struct connected *ifc;
1245 int ret;
1246
1247 /* Convert to prefix structure. */
1248 ret = str2prefix_ipv4 (addr_str, &cp);
1249 if (ret <= 0)
1250 {
1251 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1252 return CMD_WARNING;
1253 }
1254
1255 /* Check current interface address. */
paulca162182005-09-12 16:58:52 +00001256 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001257 if (! ifc)
1258 {
1259 vty_out (vty, "%% Can't find address%s", VTY_NEWLINE);
1260 return CMD_WARNING;
1261 }
1262
1263 /* This is not configured address. */
1264 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1265 return CMD_WARNING;
1266
Paul Jakma74ecdc92006-06-15 18:10:47 +00001267 UNSET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED);
1268
paul718e3742002-12-13 20:15:29 +00001269 /* This is not real address or interface is not active. */
1270 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1271 || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1272 {
1273 listnode_delete (ifp->connected, ifc);
1274 connected_free (ifc);
1275 return CMD_WARNING;
1276 }
1277
1278 /* This is real route. */
1279 ret = if_unset_prefix (ifp, ifc);
1280 if (ret < 0)
1281 {
1282 vty_out (vty, "%% Can't unset interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001283 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001284 return CMD_WARNING;
1285 }
1286
hassoeef1fe12004-10-03 18:46:08 +00001287#if 0
paul718e3742002-12-13 20:15:29 +00001288 /* Redistribute this information. */
1289 zebra_interface_address_delete_update (ifp, ifc);
1290
1291 /* Remove connected route. */
1292 connected_down_ipv4 (ifp, ifc);
1293
1294 /* Free address information. */
1295 listnode_delete (ifp->connected, ifc);
1296 connected_free (ifc);
hassoeef1fe12004-10-03 18:46:08 +00001297#endif
paul718e3742002-12-13 20:15:29 +00001298
1299 return CMD_SUCCESS;
1300}
1301
1302DEFUN (ip_address,
1303 ip_address_cmd,
1304 "ip address A.B.C.D/M",
1305 "Interface Internet Protocol config commands\n"
1306 "Set the IP address of an interface\n"
1307 "IP address (e.g. 10.0.0.1/8)\n")
1308{
hassoeef1fe12004-10-03 18:46:08 +00001309 return ip_address_install (vty, vty->index, argv[0], NULL, NULL);
paul718e3742002-12-13 20:15:29 +00001310}
1311
1312DEFUN (no_ip_address,
1313 no_ip_address_cmd,
1314 "no ip address A.B.C.D/M",
1315 NO_STR
1316 "Interface Internet Protocol config commands\n"
1317 "Set the IP address of an interface\n"
1318 "IP Address (e.g. 10.0.0.1/8)")
1319{
hassoeef1fe12004-10-03 18:46:08 +00001320 return ip_address_uninstall (vty, vty->index, argv[0], NULL, NULL);
paul718e3742002-12-13 20:15:29 +00001321}
1322
1323#ifdef HAVE_NETLINK
paul718e3742002-12-13 20:15:29 +00001324DEFUN (ip_address_label,
1325 ip_address_label_cmd,
1326 "ip address A.B.C.D/M label LINE",
1327 "Interface Internet Protocol config commands\n"
1328 "Set the IP address of an interface\n"
1329 "IP address (e.g. 10.0.0.1/8)\n"
1330 "Label of this address\n"
1331 "Label\n")
1332{
hassoeef1fe12004-10-03 18:46:08 +00001333 return ip_address_install (vty, vty->index, argv[0], NULL, argv[1]);
paul718e3742002-12-13 20:15:29 +00001334}
1335
1336DEFUN (no_ip_address_label,
1337 no_ip_address_label_cmd,
1338 "no ip address A.B.C.D/M label LINE",
1339 NO_STR
1340 "Interface Internet Protocol config commands\n"
1341 "Set the IP address of an interface\n"
1342 "IP address (e.g. 10.0.0.1/8)\n"
1343 "Label of this address\n"
1344 "Label\n")
1345{
hassoeef1fe12004-10-03 18:46:08 +00001346 return ip_address_uninstall (vty, vty->index, argv[0], NULL, argv[1]);
paul718e3742002-12-13 20:15:29 +00001347}
1348#endif /* HAVE_NETLINK */
1349
1350#ifdef HAVE_IPV6
paula1ac18c2005-06-28 17:17:12 +00001351static int
hasso39db97e2004-10-12 20:50:58 +00001352ipv6_address_install (struct vty *vty, struct interface *ifp,
1353 const char *addr_str, const char *peer_str,
1354 const char *label, int secondary)
paul718e3742002-12-13 20:15:29 +00001355{
1356 struct prefix_ipv6 cp;
1357 struct connected *ifc;
1358 struct prefix_ipv6 *p;
1359 int ret;
1360
1361 ret = str2prefix_ipv6 (addr_str, &cp);
1362 if (ret <= 0)
1363 {
1364 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1365 return CMD_WARNING;
1366 }
1367
paulca162182005-09-12 16:58:52 +00001368 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001369 if (! ifc)
1370 {
1371 ifc = connected_new ();
1372 ifc->ifp = ifp;
1373
1374 /* Address. */
1375 p = prefix_ipv6_new ();
1376 *p = cp;
1377 ifc->address = (struct prefix *) p;
1378
1379 /* Secondary. */
1380 if (secondary)
1381 SET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY);
1382
1383 /* Label. */
1384 if (label)
paul0752ef02005-11-03 12:35:21 +00001385 ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
paul718e3742002-12-13 20:15:29 +00001386
1387 /* Add to linked list. */
1388 listnode_add (ifp->connected, ifc);
1389 }
1390
1391 /* This address is configured from zebra. */
1392 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1393 SET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED);
1394
1395 /* In case of this route need to install kernel. */
1396 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1397 && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1398 {
1399 /* Some system need to up the interface to set IP address. */
1400 if (! if_is_up (ifp))
1401 {
1402 if_set_flags (ifp, IFF_UP | IFF_RUNNING);
1403 if_refresh (ifp);
1404 }
1405
1406 ret = if_prefix_add_ipv6 (ifp, ifc);
1407
1408 if (ret < 0)
1409 {
1410 vty_out (vty, "%% Can't set interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001411 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001412 return CMD_WARNING;
1413 }
1414
1415 /* IP address propery set. */
1416 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
1417
1418 /* Update interface address information to protocol daemon. */
1419 zebra_interface_address_add_update (ifp, ifc);
1420
1421 /* If interface is up register connected route. */
paul2e3b2e42002-12-13 21:03:13 +00001422 if (if_is_operative(ifp))
paul718e3742002-12-13 20:15:29 +00001423 connected_up_ipv6 (ifp, ifc);
1424 }
1425
1426 return CMD_SUCCESS;
1427}
1428
paula1ac18c2005-06-28 17:17:12 +00001429static int
hasso39db97e2004-10-12 20:50:58 +00001430ipv6_address_uninstall (struct vty *vty, struct interface *ifp,
1431 const char *addr_str, const char *peer_str,
1432 const char *label, int secondry)
paul718e3742002-12-13 20:15:29 +00001433{
1434 struct prefix_ipv6 cp;
1435 struct connected *ifc;
1436 int ret;
1437
1438 /* Convert to prefix structure. */
1439 ret = str2prefix_ipv6 (addr_str, &cp);
1440 if (ret <= 0)
1441 {
1442 vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
1443 return CMD_WARNING;
1444 }
1445
1446 /* Check current interface address. */
paulca162182005-09-12 16:58:52 +00001447 ifc = connected_check (ifp, (struct prefix *) &cp);
paul718e3742002-12-13 20:15:29 +00001448 if (! ifc)
1449 {
1450 vty_out (vty, "%% Can't find address%s", VTY_NEWLINE);
1451 return CMD_WARNING;
1452 }
1453
1454 /* This is not configured address. */
1455 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1456 return CMD_WARNING;
1457
1458 /* This is not real address or interface is not active. */
1459 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
1460 || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1461 {
1462 listnode_delete (ifp->connected, ifc);
1463 connected_free (ifc);
1464 return CMD_WARNING;
1465 }
1466
1467 /* This is real route. */
1468 ret = if_prefix_delete_ipv6 (ifp, ifc);
1469 if (ret < 0)
1470 {
1471 vty_out (vty, "%% Can't unset interface IP address: %s.%s",
ajs6099b3b2004-11-20 02:06:59 +00001472 safe_strerror(errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001473 return CMD_WARNING;
1474 }
1475
1476 /* Redistribute this information. */
1477 zebra_interface_address_delete_update (ifp, ifc);
1478
1479 /* Remove connected route. */
1480 connected_down_ipv6 (ifp, ifc);
1481
1482 /* Free address information. */
1483 listnode_delete (ifp->connected, ifc);
1484 connected_free (ifc);
1485
1486 return CMD_SUCCESS;
1487}
1488
1489DEFUN (ipv6_address,
1490 ipv6_address_cmd,
1491 "ipv6 address X:X::X:X/M",
hassoe23949c2004-03-11 15:54:02 +00001492 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001493 "Set the IP address of an interface\n"
1494 "IPv6 address (e.g. 3ffe:506::1/48)\n")
1495{
1496 return ipv6_address_install (vty, vty->index, argv[0], NULL, NULL, 0);
1497}
1498
1499DEFUN (no_ipv6_address,
1500 no_ipv6_address_cmd,
1501 "no ipv6 address X:X::X:X/M",
1502 NO_STR
hassoe23949c2004-03-11 15:54:02 +00001503 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001504 "Set the IP address of an interface\n"
1505 "IPv6 address (e.g. 3ffe:506::1/48)\n")
1506{
1507 return ipv6_address_uninstall (vty, vty->index, argv[0], NULL, NULL, 0);
1508}
1509#endif /* HAVE_IPV6 */
1510
paula1ac18c2005-06-28 17:17:12 +00001511static int
paul718e3742002-12-13 20:15:29 +00001512if_config_write (struct vty *vty)
1513{
hasso52dc7ee2004-09-23 19:18:23 +00001514 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001515 struct interface *ifp;
paul718e3742002-12-13 20:15:29 +00001516
paul1eb8ef22005-04-07 07:30:20 +00001517 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00001518 {
1519 struct zebra_if *if_data;
hasso52dc7ee2004-09-23 19:18:23 +00001520 struct listnode *addrnode;
paul718e3742002-12-13 20:15:29 +00001521 struct connected *ifc;
1522 struct prefix *p;
1523
paul718e3742002-12-13 20:15:29 +00001524 if_data = ifp->info;
1525
1526 vty_out (vty, "interface %s%s", ifp->name,
1527 VTY_NEWLINE);
1528
1529 if (ifp->desc)
1530 vty_out (vty, " description %s%s", ifp->desc,
1531 VTY_NEWLINE);
1532
1533 /* Assign bandwidth here to avoid unnecessary interface flap
1534 while processing config script */
1535 if (ifp->bandwidth != 0)
1536 vty_out(vty, " bandwidth %u%s", ifp->bandwidth, VTY_NEWLINE);
1537
paul2e3b2e42002-12-13 21:03:13 +00001538 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION))
1539 vty_out(vty, " link-detect%s", VTY_NEWLINE);
1540
paul1eb8ef22005-04-07 07:30:20 +00001541 for (ALL_LIST_ELEMENTS_RO (ifp->connected, addrnode, ifc))
paul718e3742002-12-13 20:15:29 +00001542 {
paul718e3742002-12-13 20:15:29 +00001543 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
1544 {
Stephen Hemminger81cce012009-04-28 14:28:00 -07001545 char buf[INET6_ADDRSTRLEN];
paul718e3742002-12-13 20:15:29 +00001546 p = ifc->address;
1547 vty_out (vty, " ip%s address %s/%d",
1548 p->family == AF_INET ? "" : "v6",
Stephen Hemminger81cce012009-04-28 14:28:00 -07001549 inet_ntop (p->family, &p->u.prefix, buf, sizeof(buf)),
paul718e3742002-12-13 20:15:29 +00001550 p->prefixlen);
1551
paul718e3742002-12-13 20:15:29 +00001552 if (ifc->label)
1553 vty_out (vty, " label %s", ifc->label);
1554
1555 vty_out (vty, "%s", VTY_NEWLINE);
1556 }
1557 }
1558
1559 if (if_data)
1560 {
1561 if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)
1562 vty_out (vty, " shutdown%s", VTY_NEWLINE);
1563
1564 if (if_data->multicast != IF_ZEBRA_MULTICAST_UNSPEC)
1565 vty_out (vty, " %smulticast%s",
1566 if_data->multicast == IF_ZEBRA_MULTICAST_ON ? "" : "no ",
1567 VTY_NEWLINE);
1568 }
1569
1570#ifdef RTADV
1571 rtadv_config_write (vty, ifp);
1572#endif /* RTADV */
1573
hassoca776982004-06-12 14:33:05 +00001574#ifdef HAVE_IRDP
1575 irdp_config_write (vty, ifp);
1576#endif /* IRDP */
1577
paul718e3742002-12-13 20:15:29 +00001578 vty_out (vty, "!%s", VTY_NEWLINE);
1579 }
1580 return 0;
1581}
1582
1583/* Allocate and initialize interface vector. */
1584void
paula1ac18c2005-06-28 17:17:12 +00001585zebra_if_init (void)
paul718e3742002-12-13 20:15:29 +00001586{
1587 /* Initialize interface and new hook. */
1588 if_init ();
1589 if_add_hook (IF_NEW_HOOK, if_zebra_new_hook);
1590 if_add_hook (IF_DELETE_HOOK, if_zebra_delete_hook);
1591
1592 /* Install configuration write function. */
1593 install_node (&interface_node, if_config_write);
1594
1595 install_element (VIEW_NODE, &show_interface_cmd);
1596 install_element (ENABLE_NODE, &show_interface_cmd);
hassoed9bb6d2005-03-13 19:17:21 +00001597 install_element (ENABLE_NODE, &show_interface_desc_cmd);
paul718e3742002-12-13 20:15:29 +00001598 install_element (CONFIG_NODE, &zebra_interface_cmd);
paulbfc13532003-05-24 06:40:04 +00001599 install_element (CONFIG_NODE, &no_interface_cmd);
paul718e3742002-12-13 20:15:29 +00001600 install_default (INTERFACE_NODE);
1601 install_element (INTERFACE_NODE, &interface_desc_cmd);
1602 install_element (INTERFACE_NODE, &no_interface_desc_cmd);
1603 install_element (INTERFACE_NODE, &multicast_cmd);
1604 install_element (INTERFACE_NODE, &no_multicast_cmd);
paul2e3b2e42002-12-13 21:03:13 +00001605 install_element (INTERFACE_NODE, &linkdetect_cmd);
1606 install_element (INTERFACE_NODE, &no_linkdetect_cmd);
paul718e3742002-12-13 20:15:29 +00001607 install_element (INTERFACE_NODE, &shutdown_if_cmd);
1608 install_element (INTERFACE_NODE, &no_shutdown_if_cmd);
1609 install_element (INTERFACE_NODE, &bandwidth_if_cmd);
1610 install_element (INTERFACE_NODE, &no_bandwidth_if_cmd);
1611 install_element (INTERFACE_NODE, &no_bandwidth_if_val_cmd);
1612 install_element (INTERFACE_NODE, &ip_address_cmd);
1613 install_element (INTERFACE_NODE, &no_ip_address_cmd);
1614#ifdef HAVE_IPV6
1615 install_element (INTERFACE_NODE, &ipv6_address_cmd);
1616 install_element (INTERFACE_NODE, &no_ipv6_address_cmd);
1617#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +00001618#ifdef HAVE_NETLINK
paul718e3742002-12-13 20:15:29 +00001619 install_element (INTERFACE_NODE, &ip_address_label_cmd);
paul718e3742002-12-13 20:15:29 +00001620 install_element (INTERFACE_NODE, &no_ip_address_label_cmd);
paul718e3742002-12-13 20:15:29 +00001621#endif /* HAVE_NETLINK */
1622}