blob: 5aa82500e9176fd3f88ed12a9839a2a6939be3c9 [file] [log] [blame]
paul106d2fd2003-08-01 00:24:13 +00001
paul718e3742002-12-13 20:15:29 +00002/*
3 * Interface functions.
4 * Copyright (C) 1997, 98 Kunihiro Ishiguro
5 *
6 * This file is part of GNU Zebra.
7 *
8 * GNU Zebra is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published
10 * by the Free Software Foundation; either version 2, or (at your
11 * option) any later version.
12 *
13 * GNU Zebra is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with GNU Zebra; see the file COPYING. If not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
22 */
23
24#include <zebra.h>
25
26#include "linklist.h"
27#include "vector.h"
28#include "vty.h"
29#include "command.h"
Feng Lu5a5702f2015-05-22 11:39:59 +020030#include "vrf.h"
paul718e3742002-12-13 20:15:29 +000031#include "if.h"
32#include "sockunion.h"
33#include "prefix.h"
paul718e3742002-12-13 20:15:29 +000034#include "memory.h"
35#include "table.h"
36#include "buffer.h"
37#include "str.h"
38#include "log.h"
David Lamparter6b0655a2014-06-04 06:53:35 +020039
Feng Lu5a5702f2015-05-22 11:39:59 +020040/* List of interfaces in only the default VRF */
paul718e3742002-12-13 20:15:29 +000041struct list *iflist;
42
43/* One for each program. This structure is needed to store hooks. */
44struct if_master
45{
46 int (*if_new_hook) (struct interface *);
47 int (*if_delete_hook) (struct interface *);
Feng Lu5a5702f2015-05-22 11:39:59 +020048} if_master = {0,};
David Lamparter6b0655a2014-06-04 06:53:35 +020049
paul3a0391a2004-07-17 11:51:29 +000050/* Compare interface names, returning an integer greater than, equal to, or
51 * less than 0, (following the strcmp convention), according to the
52 * relationship between ifp1 and ifp2. Interface names consist of an
53 * alphabetic prefix and a numeric suffix. The primary sort key is
54 * lexicographic by name, and then numeric by number. No number sorts
55 * before all numbers. Examples: de0 < de1, de100 < fxp0 < xl0, devpty <
56 * devpty0, de0 < del0
57 */
paul106d2fd2003-08-01 00:24:13 +000058int
59if_cmp_func (struct interface *ifp1, struct interface *ifp2)
60{
61 unsigned int l1, l2;
62 long int x1, x2;
63 char *p1, *p2;
64 int res;
65
66 p1 = ifp1->name;
67 p2 = ifp2->name;
68
paul90578522003-09-23 23:46:01 +000069 while (*p1 && *p2) {
paul106d2fd2003-08-01 00:24:13 +000070 /* look up to any number */
71 l1 = strcspn(p1, "0123456789");
72 l2 = strcspn(p2, "0123456789");
73
74 /* name lengths are different -> compare names */
75 if (l1 != l2)
76 return (strcmp(p1, p2));
77
paul3a0391a2004-07-17 11:51:29 +000078 /* Note that this relies on all numbers being less than all letters, so
79 * that de0 < del0.
80 */
paul106d2fd2003-08-01 00:24:13 +000081 res = strncmp(p1, p2, l1);
82
83 /* names are different -> compare them */
84 if (res)
85 return res;
86
87 /* with identical name part, go to numeric part */
paul106d2fd2003-08-01 00:24:13 +000088 p1 += l1;
89 p2 += l1;
90
paulb06c14f2004-07-09 12:24:42 +000091 if (!*p1)
92 return -1;
93 if (!*p2)
94 return 1;
95
paul106d2fd2003-08-01 00:24:13 +000096 x1 = strtol(p1, &p1, 10);
97 x2 = strtol(p2, &p2, 10);
98
99 /* let's compare numbers now */
100 if (x1 < x2)
101 return -1;
102 if (x1 > x2)
103 return 1;
104
105 /* numbers were equal, lets do it again..
106 (it happens with name like "eth123.456:789") */
107 }
paul90578522003-09-23 23:46:01 +0000108 if (*p1)
109 return 1;
110 if (*p2)
111 return -1;
112 return 0;
paul106d2fd2003-08-01 00:24:13 +0000113}
114
paul718e3742002-12-13 20:15:29 +0000115/* Create new interface structure. */
116struct interface *
Feng Lu5a5702f2015-05-22 11:39:59 +0200117if_create_vrf (const char *name, int namelen, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000118{
119 struct interface *ifp;
Feng Lu5a5702f2015-05-22 11:39:59 +0200120 struct list *intf_list = vrf_iflist_get (vrf_id);
paul718e3742002-12-13 20:15:29 +0000121
ajsd2fc8892005-04-02 18:38:43 +0000122 ifp = XCALLOC (MTYPE_IF, sizeof (struct interface));
123 ifp->ifindex = IFINDEX_INTERNAL;
paul718e3742002-12-13 20:15:29 +0000124
paul106d2fd2003-08-01 00:24:13 +0000125 assert (name);
ajsd2fc8892005-04-02 18:38:43 +0000126 assert (namelen <= INTERFACE_NAMSIZ); /* Need space for '\0' at end. */
paul106d2fd2003-08-01 00:24:13 +0000127 strncpy (ifp->name, name, namelen);
ajsd2fc8892005-04-02 18:38:43 +0000128 ifp->name[namelen] = '\0';
Feng Lu5a5702f2015-05-22 11:39:59 +0200129 ifp->vrf_id = vrf_id;
130 if (if_lookup_by_name_vrf (ifp->name, vrf_id) == NULL)
131 listnode_add_sort (intf_list, ifp);
ajsd2fc8892005-04-02 18:38:43 +0000132 else
133 zlog_err("if_create(%s): corruption detected -- interface with this "
Feng Lu5a5702f2015-05-22 11:39:59 +0200134 "name exists already in VRF %u!", ifp->name, vrf_id);
paul718e3742002-12-13 20:15:29 +0000135 ifp->connected = list_new ();
136 ifp->connected->del = (void (*) (void *)) connected_free;
137
Dinesh G Dutta6d400c2015-09-18 08:32:56 -0400138 /* Enable Link-detection by default */
139 SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
140
paul718e3742002-12-13 20:15:29 +0000141 if (if_master.if_new_hook)
142 (*if_master.if_new_hook) (ifp);
143
144 return ifp;
145}
146
Feng Lu5a5702f2015-05-22 11:39:59 +0200147struct interface *
148if_create (const char *name, int namelen)
149{
150 return if_create_vrf (name, namelen, VRF_DEFAULT);
151}
152
ajsd2fc8892005-04-02 18:38:43 +0000153/* Delete interface structure. */
154void
155if_delete_retain (struct interface *ifp)
156{
157 if (if_master.if_delete_hook)
158 (*if_master.if_delete_hook) (ifp);
159
160 /* Free connected address list */
Josh Bailey2dd04c52012-03-21 10:37:03 -0700161 list_delete_all_node (ifp->connected);
ajsd2fc8892005-04-02 18:38:43 +0000162}
163
paul718e3742002-12-13 20:15:29 +0000164/* Delete and free interface structure. */
165void
166if_delete (struct interface *ifp)
167{
Feng Lu5a5702f2015-05-22 11:39:59 +0200168 listnode_delete (vrf_iflist (ifp->vrf_id), ifp);
paul718e3742002-12-13 20:15:29 +0000169
ajsd2fc8892005-04-02 18:38:43 +0000170 if_delete_retain(ifp);
paul718e3742002-12-13 20:15:29 +0000171
Josh Bailey2dd04c52012-03-21 10:37:03 -0700172 list_free (ifp->connected);
173
Olivier Dugeonae51c9d2016-04-19 16:21:46 +0200174 if_link_params_free (ifp);
175
paul718e3742002-12-13 20:15:29 +0000176 XFREE (MTYPE_IF, ifp);
177}
178
179/* Add hook to interface master. */
180void
181if_add_hook (int type, int (*func)(struct interface *ifp))
182{
183 switch (type) {
184 case IF_NEW_HOOK:
185 if_master.if_new_hook = func;
186 break;
187 case IF_DELETE_HOOK:
188 if_master.if_delete_hook = func;
189 break;
190 default:
191 break;
192 }
193}
194
195/* Interface existance check by index. */
196struct interface *
Paul Jakma9099f9b2016-01-18 10:12:10 +0000197if_lookup_by_index_vrf (ifindex_t ifindex, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000198{
hasso52dc7ee2004-09-23 19:18:23 +0000199 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000200 struct interface *ifp;
201
Feng Lu5a5702f2015-05-22 11:39:59 +0200202 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
paul718e3742002-12-13 20:15:29 +0000203 {
Paul Jakma9099f9b2016-01-18 10:12:10 +0000204 if (ifp->ifindex == ifindex)
paul718e3742002-12-13 20:15:29 +0000205 return ifp;
206 }
207 return NULL;
208}
209
Feng Lu5a5702f2015-05-22 11:39:59 +0200210struct interface *
Paul Jakma9099f9b2016-01-18 10:12:10 +0000211if_lookup_by_index (ifindex_t ifindex)
Feng Lu5a5702f2015-05-22 11:39:59 +0200212{
Paul Jakma9099f9b2016-01-18 10:12:10 +0000213 return if_lookup_by_index_vrf (ifindex, VRF_DEFAULT);
Feng Lu5a5702f2015-05-22 11:39:59 +0200214}
215
paul8cc41982005-05-06 21:25:49 +0000216const char *
Paul Jakma9099f9b2016-01-18 10:12:10 +0000217ifindex2ifname_vrf (ifindex_t ifindex, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000218{
paul718e3742002-12-13 20:15:29 +0000219 struct interface *ifp;
220
Paul Jakma9099f9b2016-01-18 10:12:10 +0000221 return ((ifp = if_lookup_by_index_vrf (ifindex, vrf_id)) != NULL) ?
paul8cc41982005-05-06 21:25:49 +0000222 ifp->name : "unknown";
ajsd2fc8892005-04-02 18:38:43 +0000223}
224
Feng Lu5a5702f2015-05-22 11:39:59 +0200225const char *
Paul Jakma9099f9b2016-01-18 10:12:10 +0000226ifindex2ifname (ifindex_t ifindex)
Feng Lu5a5702f2015-05-22 11:39:59 +0200227{
Paul Jakma9099f9b2016-01-18 10:12:10 +0000228 return ifindex2ifname_vrf (ifindex, VRF_DEFAULT);
Feng Lu5a5702f2015-05-22 11:39:59 +0200229}
230
Paul Jakma9099f9b2016-01-18 10:12:10 +0000231ifindex_t
Feng Lu5a5702f2015-05-22 11:39:59 +0200232ifname2ifindex_vrf (const char *name, vrf_id_t vrf_id)
233{
234 struct interface *ifp;
235
236 return ((ifp = if_lookup_by_name_vrf (name, vrf_id)) != NULL) ? ifp->ifindex
237 : IFINDEX_INTERNAL;
238}
239
Paul Jakma9099f9b2016-01-18 10:12:10 +0000240ifindex_t
ajsd2fc8892005-04-02 18:38:43 +0000241ifname2ifindex (const char *name)
242{
Feng Lu5a5702f2015-05-22 11:39:59 +0200243 return ifname2ifindex_vrf (name, VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +0000244}
245
246/* Interface existance check by interface name. */
247struct interface *
Feng Lu5a5702f2015-05-22 11:39:59 +0200248if_lookup_by_name_vrf (const char *name, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000249{
hasso52dc7ee2004-09-23 19:18:23 +0000250 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000251 struct interface *ifp;
Paul Jakma3e4ee952009-08-06 12:08:50 +0100252
253 if (name)
Feng Lu5a5702f2015-05-22 11:39:59 +0200254 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
Paul Jakma3e4ee952009-08-06 12:08:50 +0100255 {
256 if (strcmp(name, ifp->name) == 0)
257 return ifp;
258 }
paul718e3742002-12-13 20:15:29 +0000259 return NULL;
260}
261
ajsa3491982005-04-02 22:50:38 +0000262struct interface *
Feng Lu5a5702f2015-05-22 11:39:59 +0200263if_lookup_by_name (const char *name)
264{
265 return if_lookup_by_name_vrf (name, VRF_DEFAULT);
266}
267
268struct interface *
269if_lookup_by_name_len_vrf (const char *name, size_t namelen, vrf_id_t vrf_id)
ajsa3491982005-04-02 22:50:38 +0000270{
271 struct listnode *node;
paul1eb8ef22005-04-07 07:30:20 +0000272 struct interface *ifp;
ajsa3491982005-04-02 22:50:38 +0000273
274 if (namelen > INTERFACE_NAMSIZ)
275 return NULL;
276
Feng Lu5a5702f2015-05-22 11:39:59 +0200277 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
ajsa3491982005-04-02 22:50:38 +0000278 {
ajsa3491982005-04-02 22:50:38 +0000279 if (!memcmp(name, ifp->name, namelen) && (ifp->name[namelen] == '\0'))
280 return ifp;
281 }
282 return NULL;
283}
284
Feng Lu5a5702f2015-05-22 11:39:59 +0200285struct interface *
286if_lookup_by_name_len(const char *name, size_t namelen)
287{
288 return if_lookup_by_name_len_vrf (name, namelen, VRF_DEFAULT);
289}
290
paul718e3742002-12-13 20:15:29 +0000291/* Lookup interface by IPv4 address. */
292struct interface *
Feng Lu5a5702f2015-05-22 11:39:59 +0200293if_lookup_exact_address_vrf (struct in_addr src, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000294{
hasso52dc7ee2004-09-23 19:18:23 +0000295 struct listnode *node;
296 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000297 struct interface *ifp;
298 struct prefix *p;
299 struct connected *c;
300
Feng Lu5a5702f2015-05-22 11:39:59 +0200301 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
paul718e3742002-12-13 20:15:29 +0000302 {
paul1eb8ef22005-04-07 07:30:20 +0000303 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
paul718e3742002-12-13 20:15:29 +0000304 {
paul718e3742002-12-13 20:15:29 +0000305 p = c->address;
306
307 if (p && p->family == AF_INET)
308 {
309 if (IPV4_ADDR_SAME (&p->u.prefix4, &src))
310 return ifp;
311 }
312 }
313 }
314 return NULL;
315}
316
Feng Lu5a5702f2015-05-22 11:39:59 +0200317struct interface *
318if_lookup_exact_address (struct in_addr src)
319{
320 return if_lookup_exact_address_vrf (src, VRF_DEFAULT);
321}
322
paul718e3742002-12-13 20:15:29 +0000323/* Lookup interface by IPv4 address. */
324struct interface *
Feng Lu5a5702f2015-05-22 11:39:59 +0200325if_lookup_address_vrf (struct in_addr src, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000326{
hasso52dc7ee2004-09-23 19:18:23 +0000327 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000328 struct prefix addr;
hasso3fb9cd62004-10-19 19:44:43 +0000329 int bestlen = 0;
hasso52dc7ee2004-09-23 19:18:23 +0000330 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000331 struct interface *ifp;
paul718e3742002-12-13 20:15:29 +0000332 struct connected *c;
333 struct interface *match;
334
paul718e3742002-12-13 20:15:29 +0000335 addr.family = AF_INET;
336 addr.u.prefix4 = src;
337 addr.prefixlen = IPV4_MAX_BITLEN;
338
339 match = NULL;
340
Feng Lu5a5702f2015-05-22 11:39:59 +0200341 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
paul718e3742002-12-13 20:15:29 +0000342 {
paul1eb8ef22005-04-07 07:30:20 +0000343 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
paul718e3742002-12-13 20:15:29 +0000344 {
Andrew J. Schorre4529632006-12-12 19:18:21 +0000345 if (c->address && (c->address->family == AF_INET) &&
346 prefix_match(CONNECTED_PREFIX(c), &addr) &&
347 (c->address->prefixlen > bestlen))
paul718e3742002-12-13 20:15:29 +0000348 {
Andrew J. Schorre4529632006-12-12 19:18:21 +0000349 bestlen = c->address->prefixlen;
350 match = ifp;
paul718e3742002-12-13 20:15:29 +0000351 }
352 }
353 }
354 return match;
355}
356
Feng Lu5a5702f2015-05-22 11:39:59 +0200357struct interface *
358if_lookup_address (struct in_addr src)
359{
360 return if_lookup_address_vrf (src, VRF_DEFAULT);
361}
362
Dinesh Duttb81e97a2013-08-24 07:55:50 +0000363/* Lookup interface by prefix */
364struct interface *
Feng Lu5a5702f2015-05-22 11:39:59 +0200365if_lookup_prefix_vrf (struct prefix *prefix, vrf_id_t vrf_id)
Dinesh Duttb81e97a2013-08-24 07:55:50 +0000366{
367 struct listnode *node;
Dinesh Duttb81e97a2013-08-24 07:55:50 +0000368 struct listnode *cnode;
369 struct interface *ifp;
370 struct connected *c;
371
Feng Lu5a5702f2015-05-22 11:39:59 +0200372 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
Dinesh Duttb81e97a2013-08-24 07:55:50 +0000373 {
374 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
375 {
376 if (prefix_cmp(c->address, prefix) == 0)
377 {
378 return ifp;
379 }
380 }
381 }
382 return NULL;
383}
384
Feng Lu5a5702f2015-05-22 11:39:59 +0200385struct interface *
386if_lookup_prefix (struct prefix *prefix)
387{
388 return if_lookup_prefix_vrf (prefix, VRF_DEFAULT);
389}
390
paul718e3742002-12-13 20:15:29 +0000391/* Get interface by name if given name interface doesn't exist create
392 one. */
393struct interface *
Feng Lu5a5702f2015-05-22 11:39:59 +0200394if_get_by_name_vrf (const char *name, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000395{
396 struct interface *ifp;
397
Feng Lu5a5702f2015-05-22 11:39:59 +0200398 return ((ifp = if_lookup_by_name_vrf (name, vrf_id)) != NULL) ? ifp :
399 if_create_vrf (name, strlen(name), vrf_id);
ajsa3491982005-04-02 22:50:38 +0000400}
401
402struct interface *
Feng Lu5a5702f2015-05-22 11:39:59 +0200403if_get_by_name (const char *name)
404{
405 return if_get_by_name_vrf (name, VRF_DEFAULT);
406}
407
408struct interface *
409if_get_by_name_len_vrf (const char *name, size_t namelen, vrf_id_t vrf_id)
ajsa3491982005-04-02 22:50:38 +0000410{
411 struct interface *ifp;
412
Feng Lu5a5702f2015-05-22 11:39:59 +0200413 return ((ifp = if_lookup_by_name_len_vrf (name, namelen, vrf_id)) != NULL) ? \
414 ifp : if_create_vrf (name, namelen, vrf_id);
415}
416
417struct interface *
418if_get_by_name_len (const char *name, size_t namelen)
419{
420 return if_get_by_name_len_vrf (name, namelen, VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +0000421}
422
423/* Does interface up ? */
424int
425if_is_up (struct interface *ifp)
426{
427 return ifp->flags & IFF_UP;
428}
429
paul2e3b2e42002-12-13 21:03:13 +0000430/* Is interface running? */
431int
432if_is_running (struct interface *ifp)
433{
434 return ifp->flags & IFF_RUNNING;
435}
436
437/* Is the interface operative, eg. either UP & RUNNING
438 or UP & !ZEBRA_INTERFACE_LINK_DETECTION */
439int
440if_is_operative (struct interface *ifp)
441{
442 return ((ifp->flags & IFF_UP) &&
443 (ifp->flags & IFF_RUNNING || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)));
444}
445
paul718e3742002-12-13 20:15:29 +0000446/* Is this loopback interface ? */
447int
448if_is_loopback (struct interface *ifp)
449{
paul4ba9b922004-12-21 22:34:58 +0000450 /* XXX: Do this better, eg what if IFF_WHATEVER means X on platform M
451 * but Y on platform N?
452 */
453 return (ifp->flags & (IFF_LOOPBACK|IFF_NOXMIT|IFF_VIRTUAL));
paul718e3742002-12-13 20:15:29 +0000454}
455
456/* Does this interface support broadcast ? */
457int
458if_is_broadcast (struct interface *ifp)
459{
460 return ifp->flags & IFF_BROADCAST;
461}
462
463/* Does this interface support broadcast ? */
464int
465if_is_pointopoint (struct interface *ifp)
466{
467 return ifp->flags & IFF_POINTOPOINT;
468}
469
470/* Does this interface support multicast ? */
471int
472if_is_multicast (struct interface *ifp)
473{
474 return ifp->flags & IFF_MULTICAST;
475}
476
477/* Printout flag information into log */
478const char *
479if_flag_dump (unsigned long flag)
480{
481 int separator = 0;
482 static char logbuf[BUFSIZ];
483
484#define IFF_OUT_LOG(X,STR) \
paul4ba9b922004-12-21 22:34:58 +0000485 if (flag & (X)) \
paul718e3742002-12-13 20:15:29 +0000486 { \
487 if (separator) \
488 strlcat (logbuf, ",", BUFSIZ); \
489 else \
490 separator = 1; \
491 strlcat (logbuf, STR, BUFSIZ); \
492 }
493
Paul Jakma630c97c2006-06-15 12:48:17 +0000494 strlcpy (logbuf, "<", BUFSIZ);
paul718e3742002-12-13 20:15:29 +0000495 IFF_OUT_LOG (IFF_UP, "UP");
496 IFF_OUT_LOG (IFF_BROADCAST, "BROADCAST");
497 IFF_OUT_LOG (IFF_DEBUG, "DEBUG");
498 IFF_OUT_LOG (IFF_LOOPBACK, "LOOPBACK");
499 IFF_OUT_LOG (IFF_POINTOPOINT, "POINTOPOINT");
500 IFF_OUT_LOG (IFF_NOTRAILERS, "NOTRAILERS");
501 IFF_OUT_LOG (IFF_RUNNING, "RUNNING");
502 IFF_OUT_LOG (IFF_NOARP, "NOARP");
503 IFF_OUT_LOG (IFF_PROMISC, "PROMISC");
504 IFF_OUT_LOG (IFF_ALLMULTI, "ALLMULTI");
505 IFF_OUT_LOG (IFF_OACTIVE, "OACTIVE");
506 IFF_OUT_LOG (IFF_SIMPLEX, "SIMPLEX");
507 IFF_OUT_LOG (IFF_LINK0, "LINK0");
508 IFF_OUT_LOG (IFF_LINK1, "LINK1");
509 IFF_OUT_LOG (IFF_LINK2, "LINK2");
510 IFF_OUT_LOG (IFF_MULTICAST, "MULTICAST");
paul4ba9b922004-12-21 22:34:58 +0000511 IFF_OUT_LOG (IFF_NOXMIT, "NOXMIT");
512 IFF_OUT_LOG (IFF_NORTEXCH, "NORTEXCH");
513 IFF_OUT_LOG (IFF_VIRTUAL, "VIRTUAL");
514 IFF_OUT_LOG (IFF_IPV4, "IPv4");
515 IFF_OUT_LOG (IFF_IPV6, "IPv6");
paul718e3742002-12-13 20:15:29 +0000516
517 strlcat (logbuf, ">", BUFSIZ);
518
519 return logbuf;
Paul Jakma630c97c2006-06-15 12:48:17 +0000520#undef IFF_OUT_LOG
paul718e3742002-12-13 20:15:29 +0000521}
522
523/* For debugging */
paul8cc41982005-05-06 21:25:49 +0000524static void
Stephen Hemmingercedd7f22009-06-12 16:58:49 +0100525if_dump (const struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000526{
hasso52dc7ee2004-09-23 19:18:23 +0000527 struct listnode *node;
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100528 struct connected *c __attribute__((unused));
paul718e3742002-12-13 20:15:29 +0000529
paul1eb8ef22005-04-07 07:30:20 +0000530 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, c))
Feng Lu2fc97f62015-05-22 11:39:57 +0200531 zlog_info ("Interface %s vrf %u index %d metric %d mtu %d "
paul4a7aac12004-05-08 05:00:31 +0000532#ifdef HAVE_IPV6
Paul Jakma23be94e2012-01-06 16:07:39 +0000533 "mtu6 %d "
paul4a7aac12004-05-08 05:00:31 +0000534#endif /* HAVE_IPV6 */
Paul Jakma23be94e2012-01-06 16:07:39 +0000535 "%s",
Feng Lu2fc97f62015-05-22 11:39:57 +0200536 ifp->name, ifp->vrf_id, ifp->ifindex, ifp->metric, ifp->mtu,
paul4a7aac12004-05-08 05:00:31 +0000537#ifdef HAVE_IPV6
Paul Jakma23be94e2012-01-06 16:07:39 +0000538 ifp->mtu6,
paul4a7aac12004-05-08 05:00:31 +0000539#endif /* HAVE_IPV6 */
Paul Jakma23be94e2012-01-06 16:07:39 +0000540 if_flag_dump (ifp->flags));
paul718e3742002-12-13 20:15:29 +0000541}
542
543/* Interface printing for all interface. */
544void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -0800545if_dump_all (void)
paul718e3742002-12-13 20:15:29 +0000546{
Feng Lu5a5702f2015-05-22 11:39:59 +0200547 struct list *intf_list;
hasso52dc7ee2004-09-23 19:18:23 +0000548 struct listnode *node;
paul1eb8ef22005-04-07 07:30:20 +0000549 void *p;
Feng Lu5a5702f2015-05-22 11:39:59 +0200550 vrf_iter_t iter;
paul718e3742002-12-13 20:15:29 +0000551
Feng Lu5a5702f2015-05-22 11:39:59 +0200552 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
553 if ((intf_list = vrf_iter2iflist (iter)) != NULL)
554 for (ALL_LIST_ELEMENTS_RO (intf_list, node, p))
555 if_dump (p);
paul718e3742002-12-13 20:15:29 +0000556}
557
558DEFUN (interface_desc,
559 interface_desc_cmd,
560 "description .LINE",
561 "Interface specific description\n"
562 "Characters describing this interface\n")
563{
paul718e3742002-12-13 20:15:29 +0000564 struct interface *ifp;
paul718e3742002-12-13 20:15:29 +0000565
566 if (argc == 0)
567 return CMD_SUCCESS;
568
569 ifp = vty->index;
570 if (ifp->desc)
ajs3b8b1852005-01-29 18:19:13 +0000571 XFREE (MTYPE_TMP, ifp->desc);
572 ifp->desc = argv_concat(argv, argc, 0);
paul718e3742002-12-13 20:15:29 +0000573
574 return CMD_SUCCESS;
575}
576
577DEFUN (no_interface_desc,
578 no_interface_desc_cmd,
579 "no description",
580 NO_STR
581 "Interface specific description\n")
582{
583 struct interface *ifp;
584
585 ifp = vty->index;
586 if (ifp->desc)
paul02416842005-10-26 05:05:16 +0000587 XFREE (MTYPE_TMP, ifp->desc);
paul718e3742002-12-13 20:15:29 +0000588 ifp->desc = NULL;
589
590 return CMD_SUCCESS;
591}
David Lamparter6b0655a2014-06-04 06:53:35 +0200592
Paul Jakma98954842006-10-15 23:33:50 +0000593#ifdef SUNOS_5
594/* Need to handle upgrade from SUNWzebra to Quagga. SUNWzebra created
595 * a seperate struct interface for each logical interface, so config
596 * file may be full of 'interface fooX:Y'. Solaris however does not
597 * expose logical interfaces via PF_ROUTE, so trying to track logical
598 * interfaces can be fruitless, for that reason Quagga only tracks
599 * the primary IP interface.
600 *
601 * We try accomodate SUNWzebra by:
602 * - looking up the interface name, to see whether it exists, if so
603 * its useable
604 * - for protocol daemons, this could only because zebra told us of
605 * the interface
606 * - for zebra, only because it learnt from kernel
607 * - if not:
608 * - search the name to see if it contains a sub-ipif / logical interface
609 * seperator, the ':' char. If it does:
610 * - text up to that char must be the primary name - get that name.
611 * if not:
612 * - no idea, just get the name in its entirety.
613 */
614static struct interface *
Feng Lu5a5702f2015-05-22 11:39:59 +0200615if_sunwzebra_get (const char *name, size_t nlen, vrf_id_t vrf_id)
Paul Jakma98954842006-10-15 23:33:50 +0000616{
617 struct interface *ifp;
618 size_t seppos = 0;
paul718e3742002-12-13 20:15:29 +0000619
Feng Lu5a5702f2015-05-22 11:39:59 +0200620 if ( (ifp = if_lookup_by_name_len_vrf (name, nlen, vrf_id)) != NULL)
Paul Jakma98954842006-10-15 23:33:50 +0000621 return ifp;
622
623 /* hunt the primary interface name... */
624 while (seppos < nlen && name[seppos] != ':')
625 seppos++;
626
627 /* Wont catch seperator as last char, e.g. 'foo0:' but thats invalid */
628 if (seppos < nlen)
Feng Lu5a5702f2015-05-22 11:39:59 +0200629 return if_get_by_name_len_vrf (name, seppos, vrf_id);
Paul Jakma98954842006-10-15 23:33:50 +0000630 else
Feng Lu5a5702f2015-05-22 11:39:59 +0200631 return if_get_by_name_len_vrf (name, nlen, vrf_id);
Paul Jakma98954842006-10-15 23:33:50 +0000632}
633#endif /* SUNOS_5 */
David Lamparter6b0655a2014-06-04 06:53:35 +0200634
paul718e3742002-12-13 20:15:29 +0000635DEFUN (interface,
636 interface_cmd,
637 "interface IFNAME",
638 "Select an interface to configure\n"
639 "Interface's name\n")
640{
641 struct interface *ifp;
ajsd2fc8892005-04-02 18:38:43 +0000642 size_t sl;
Feng Lu5a5702f2015-05-22 11:39:59 +0200643 vrf_id_t vrf_id = VRF_DEFAULT;
ajsd2fc8892005-04-02 18:38:43 +0000644
645 if ((sl = strlen(argv[0])) > INTERFACE_NAMSIZ)
646 {
647 vty_out (vty, "%% Interface name %s is invalid: length exceeds "
648 "%d characters%s",
649 argv[0], INTERFACE_NAMSIZ, VTY_NEWLINE);
650 return CMD_WARNING;
651 }
paul718e3742002-12-13 20:15:29 +0000652
Feng Lu471ea392015-05-22 11:40:00 +0200653 if (argc > 1)
654 VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]);
655
Paul Jakma98954842006-10-15 23:33:50 +0000656#ifdef SUNOS_5
Feng Lu5a5702f2015-05-22 11:39:59 +0200657 ifp = if_sunwzebra_get (argv[0], sl, vrf_id);
Paul Jakma98954842006-10-15 23:33:50 +0000658#else
Feng Lu5a5702f2015-05-22 11:39:59 +0200659 ifp = if_get_by_name_len_vrf (argv[0], sl, vrf_id);
Paul Jakma98954842006-10-15 23:33:50 +0000660#endif /* SUNOS_5 */
paul718e3742002-12-13 20:15:29 +0000661
paul718e3742002-12-13 20:15:29 +0000662 vty->index = ifp;
663 vty->node = INTERFACE_NODE;
664
665 return CMD_SUCCESS;
666}
667
Feng Lu471ea392015-05-22 11:40:00 +0200668ALIAS (interface,
669 interface_vrf_cmd,
670 "interface IFNAME " VRF_CMD_STR,
671 "Select an interface to configure\n"
672 "Interface's name\n"
673 VRF_CMD_HELP_STR)
674
paul32d24632003-05-23 09:25:20 +0000675DEFUN_NOSH (no_interface,
676 no_interface_cmd,
677 "no interface IFNAME",
678 NO_STR
679 "Delete a pseudo interface's configuration\n"
680 "Interface's name\n")
681{
682 // deleting interface
683 struct interface *ifp;
Feng Lu5a5702f2015-05-22 11:39:59 +0200684 vrf_id_t vrf_id = VRF_DEFAULT;
paul32d24632003-05-23 09:25:20 +0000685
Feng Lu471ea392015-05-22 11:40:00 +0200686 if (argc > 1)
687 VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]);
688
Feng Lu5a5702f2015-05-22 11:39:59 +0200689 ifp = if_lookup_by_name_vrf (argv[0], vrf_id);
paul32d24632003-05-23 09:25:20 +0000690
691 if (ifp == NULL)
ajsd2fc8892005-04-02 18:38:43 +0000692 {
693 vty_out (vty, "%% Interface %s does not exist%s", argv[0], VTY_NEWLINE);
694 return CMD_WARNING;
695 }
paul32d24632003-05-23 09:25:20 +0000696
paulbfc13532003-05-24 06:40:04 +0000697 if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
ajsd2fc8892005-04-02 18:38:43 +0000698 {
699 vty_out (vty, "%% Only inactive interfaces can be deleted%s",
700 VTY_NEWLINE);
701 return CMD_WARNING;
702 }
paul32d24632003-05-23 09:25:20 +0000703
704 if_delete(ifp);
705
706 return CMD_SUCCESS;
707}
708
Feng Lu471ea392015-05-22 11:40:00 +0200709ALIAS (no_interface,
710 no_interface_vrf_cmd,
711 "no interface IFNAME " VRF_CMD_STR,
712 NO_STR
713 "Delete a pseudo interface's configuration\n"
714 "Interface's name\n"
715 VRF_CMD_HELP_STR)
716
paul718e3742002-12-13 20:15:29 +0000717/* For debug purpose. */
718DEFUN (show_address,
719 show_address_cmd,
720 "show address",
721 SHOW_STR
722 "address\n")
723{
hasso52dc7ee2004-09-23 19:18:23 +0000724 struct listnode *node;
725 struct listnode *node2;
paul718e3742002-12-13 20:15:29 +0000726 struct interface *ifp;
727 struct connected *ifc;
728 struct prefix *p;
Feng Lu5a5702f2015-05-22 11:39:59 +0200729 vrf_id_t vrf_id = VRF_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000730
Feng Lu5a5702f2015-05-22 11:39:59 +0200731 if (argc > 0)
732 VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]);
733
734 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
paul718e3742002-12-13 20:15:29 +0000735 {
paul1eb8ef22005-04-07 07:30:20 +0000736 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node2, ifc))
paul718e3742002-12-13 20:15:29 +0000737 {
paul718e3742002-12-13 20:15:29 +0000738 p = ifc->address;
739
740 if (p->family == AF_INET)
741 vty_out (vty, "%s/%d%s", inet_ntoa (p->u.prefix4), p->prefixlen,
742 VTY_NEWLINE);
743 }
744 }
745 return CMD_SUCCESS;
746}
747
Feng Lu5a5702f2015-05-22 11:39:59 +0200748ALIAS (show_address,
749 show_address_vrf_cmd,
750 "show address " VRF_CMD_STR,
751 SHOW_STR
752 "address\n"
753 VRF_CMD_HELP_STR)
754
755DEFUN (show_address_vrf_all,
756 show_address_vrf_all_cmd,
757 "show address " VRF_ALL_CMD_STR,
758 SHOW_STR
759 "address\n"
760 VRF_ALL_CMD_HELP_STR)
761{
762 struct list *intf_list;
763 struct listnode *node;
764 struct listnode *node2;
765 struct interface *ifp;
766 struct connected *ifc;
767 struct prefix *p;
768 vrf_iter_t iter;
769
770 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
771 {
772 intf_list = vrf_iter2iflist (iter);
773 if (!intf_list || !listcount (intf_list))
774 continue;
775
776 vty_out (vty, "%sVRF %u%s%s", VTY_NEWLINE, vrf_iter2id (iter),
777 VTY_NEWLINE, VTY_NEWLINE);
778
779 for (ALL_LIST_ELEMENTS_RO (intf_list, node, ifp))
780 {
781 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node2, ifc))
782 {
783 p = ifc->address;
784
785 if (p->family == AF_INET)
786 vty_out (vty, "%s/%d%s", inet_ntoa (p->u.prefix4), p->prefixlen,
787 VTY_NEWLINE);
788 }
789 }
790 }
791 return CMD_SUCCESS;
792}
793
paul718e3742002-12-13 20:15:29 +0000794/* Allocate connected structure. */
795struct connected *
paul8cc41982005-05-06 21:25:49 +0000796connected_new (void)
paul718e3742002-12-13 20:15:29 +0000797{
Stephen Hemminger393deb92008-08-18 14:13:29 -0700798 return XCALLOC (MTYPE_CONNECTED, sizeof (struct connected));
paul718e3742002-12-13 20:15:29 +0000799}
800
801/* Free connected structure. */
802void
803connected_free (struct connected *connected)
804{
805 if (connected->address)
806 prefix_free (connected->address);
807
808 if (connected->destination)
809 prefix_free (connected->destination);
810
811 if (connected->label)
paul9c4f1c62005-11-03 11:04:07 +0000812 XFREE (MTYPE_CONNECTED_LABEL, connected->label);
paul718e3742002-12-13 20:15:29 +0000813
814 XFREE (MTYPE_CONNECTED, connected);
815}
816
817/* Print if_addr structure. */
paul8cc41982005-05-06 21:25:49 +0000818static void __attribute__ ((unused))
paul718e3742002-12-13 20:15:29 +0000819connected_log (struct connected *connected, char *str)
820{
821 struct prefix *p;
822 struct interface *ifp;
823 char logbuf[BUFSIZ];
824 char buf[BUFSIZ];
825
826 ifp = connected->ifp;
827 p = connected->address;
828
Feng Lu2fc97f62015-05-22 11:39:57 +0200829 snprintf (logbuf, BUFSIZ, "%s interface %s vrf %u %s %s/%d ",
830 str, ifp->name, ifp->vrf_id, prefix_family_str (p),
paul718e3742002-12-13 20:15:29 +0000831 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
832 p->prefixlen);
833
834 p = connected->destination;
835 if (p)
836 {
837 strncat (logbuf, inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
838 BUFSIZ - strlen(logbuf));
839 }
Christian Hammersfc951862011-03-23 13:07:55 +0300840 zlog (NULL, LOG_INFO, "%s", logbuf);
paul718e3742002-12-13 20:15:29 +0000841}
842
843/* If two connected address has same prefix return 1. */
paul8cc41982005-05-06 21:25:49 +0000844static int
paul718e3742002-12-13 20:15:29 +0000845connected_same_prefix (struct prefix *p1, struct prefix *p2)
846{
847 if (p1->family == p2->family)
848 {
849 if (p1->family == AF_INET &&
850 IPV4_ADDR_SAME (&p1->u.prefix4, &p2->u.prefix4))
851 return 1;
852#ifdef HAVE_IPV6
853 if (p1->family == AF_INET6 &&
854 IPV6_ADDR_SAME (&p1->u.prefix6, &p2->u.prefix6))
855 return 1;
856#endif /* HAVE_IPV6 */
857 }
858 return 0;
859}
860
861struct connected *
862connected_delete_by_prefix (struct interface *ifp, struct prefix *p)
863{
864 struct listnode *node;
865 struct listnode *next;
866 struct connected *ifc;
867
868 /* In case of same prefix come, replace it with new one. */
869 for (node = listhead (ifp->connected); node; node = next)
870 {
paul1eb8ef22005-04-07 07:30:20 +0000871 ifc = listgetdata (node);
paul718e3742002-12-13 20:15:29 +0000872 next = node->next;
873
874 if (connected_same_prefix (ifc->address, p))
875 {
876 listnode_delete (ifp->connected, ifc);
877 return ifc;
878 }
879 }
880 return NULL;
881}
882
paul727d1042002-12-13 20:50:29 +0000883/* Find the IPv4 address on our side that will be used when packets
884 are sent to dst. */
885struct connected *
886connected_lookup_address (struct interface *ifp, struct in_addr dst)
887{
888 struct prefix addr;
hasso52dc7ee2004-09-23 19:18:23 +0000889 struct listnode *cnode;
paul727d1042002-12-13 20:50:29 +0000890 struct connected *c;
891 struct connected *match;
892
paul727d1042002-12-13 20:50:29 +0000893 addr.family = AF_INET;
894 addr.u.prefix4 = dst;
895 addr.prefixlen = IPV4_MAX_BITLEN;
896
897 match = NULL;
898
paul1eb8ef22005-04-07 07:30:20 +0000899 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
paul727d1042002-12-13 20:50:29 +0000900 {
Andrew J. Schorre4529632006-12-12 19:18:21 +0000901 if (c->address && (c->address->family == AF_INET) &&
902 prefix_match(CONNECTED_PREFIX(c), &addr) &&
903 (!match || (c->address->prefixlen > match->address->prefixlen)))
904 match = c;
paul727d1042002-12-13 20:50:29 +0000905 }
906 return match;
907}
908
paul4a7aac12004-05-08 05:00:31 +0000909struct connected *
910connected_add_by_prefix (struct interface *ifp, struct prefix *p,
911 struct prefix *destination)
912{
913 struct connected *ifc;
914
915 /* Allocate new connected address. */
916 ifc = connected_new ();
917 ifc->ifp = ifp;
918
919 /* Fetch interface address */
920 ifc->address = prefix_new();
921 memcpy (ifc->address, p, sizeof(struct prefix));
922
923 /* Fetch dest address */
hasso3fb9cd62004-10-19 19:44:43 +0000924 if (destination)
925 {
926 ifc->destination = prefix_new();
927 memcpy (ifc->destination, destination, sizeof(struct prefix));
928 }
paul4a7aac12004-05-08 05:00:31 +0000929
930 /* Add connected address to the interface. */
931 listnode_add (ifp->connected, ifc);
932 return ifc;
933}
934
paul718e3742002-12-13 20:15:29 +0000935#ifndef HAVE_IF_NAMETOINDEX
Paul Jakma9099f9b2016-01-18 10:12:10 +0000936ifindex_t
paul718e3742002-12-13 20:15:29 +0000937if_nametoindex (const char *name)
938{
paul718e3742002-12-13 20:15:29 +0000939 struct interface *ifp;
940
ajs018546e2005-04-02 23:05:56 +0000941 return ((ifp = if_lookup_by_name_len(name, strnlen(name, IFNAMSIZ))) != NULL)
942 ? ifp->ifindex : 0;
paul718e3742002-12-13 20:15:29 +0000943}
944#endif
945
946#ifndef HAVE_IF_INDEXTONAME
947char *
Paul Jakma9099f9b2016-01-18 10:12:10 +0000948if_indextoname (ifindex_t ifindex, char *name)
paul718e3742002-12-13 20:15:29 +0000949{
paul718e3742002-12-13 20:15:29 +0000950 struct interface *ifp;
951
ajsd2fc8892005-04-02 18:38:43 +0000952 if (!(ifp = if_lookup_by_index(ifindex)))
953 return NULL;
954 strncpy (name, ifp->name, IFNAMSIZ);
955 return ifp->name;
paul718e3742002-12-13 20:15:29 +0000956}
957#endif
David Lamparter6b0655a2014-06-04 06:53:35 +0200958
paul8cc41982005-05-06 21:25:49 +0000959#if 0 /* this route_table of struct connected's is unused
960 * however, it would be good to use a route_table rather than
961 * a list..
962 */
paul718e3742002-12-13 20:15:29 +0000963/* Interface looking up by interface's address. */
paul718e3742002-12-13 20:15:29 +0000964/* Interface's IPv4 address reverse lookup table. */
965struct route_table *ifaddr_ipv4_table;
966/* struct route_table *ifaddr_ipv6_table; */
967
paul8cc41982005-05-06 21:25:49 +0000968static void
paul718e3742002-12-13 20:15:29 +0000969ifaddr_ipv4_add (struct in_addr *ifaddr, struct interface *ifp)
970{
971 struct route_node *rn;
972 struct prefix_ipv4 p;
973
974 p.family = AF_INET;
975 p.prefixlen = IPV4_MAX_PREFIXLEN;
976 p.prefix = *ifaddr;
977
978 rn = route_node_get (ifaddr_ipv4_table, (struct prefix *) &p);
979 if (rn)
980 {
981 route_unlock_node (rn);
982 zlog_info ("ifaddr_ipv4_add(): address %s is already added",
983 inet_ntoa (*ifaddr));
984 return;
985 }
986 rn->info = ifp;
987}
988
paul8cc41982005-05-06 21:25:49 +0000989static void
paul718e3742002-12-13 20:15:29 +0000990ifaddr_ipv4_delete (struct in_addr *ifaddr, struct interface *ifp)
991{
992 struct route_node *rn;
993 struct prefix_ipv4 p;
994
995 p.family = AF_INET;
996 p.prefixlen = IPV4_MAX_PREFIXLEN;
997 p.prefix = *ifaddr;
998
999 rn = route_node_lookup (ifaddr_ipv4_table, (struct prefix *) &p);
1000 if (! rn)
1001 {
1002 zlog_info ("ifaddr_ipv4_delete(): can't find address %s",
1003 inet_ntoa (*ifaddr));
1004 return;
1005 }
1006 rn->info = NULL;
1007 route_unlock_node (rn);
1008 route_unlock_node (rn);
1009}
1010
1011/* Lookup interface by interface's IP address or interface index. */
paul8cc41982005-05-06 21:25:49 +00001012static struct interface *
Paul Jakma9099f9b2016-01-18 10:12:10 +00001013ifaddr_ipv4_lookup (struct in_addr *addr, ifindex_t ifindex)
paul718e3742002-12-13 20:15:29 +00001014{
1015 struct prefix_ipv4 p;
1016 struct route_node *rn;
1017 struct interface *ifp;
paul718e3742002-12-13 20:15:29 +00001018
1019 if (addr)
1020 {
1021 p.family = AF_INET;
1022 p.prefixlen = IPV4_MAX_PREFIXLEN;
1023 p.prefix = *addr;
1024
1025 rn = route_node_lookup (ifaddr_ipv4_table, (struct prefix *) &p);
1026 if (! rn)
1027 return NULL;
1028
1029 ifp = rn->info;
1030 route_unlock_node (rn);
1031 return ifp;
1032 }
1033 else
ajsd2fc8892005-04-02 18:38:43 +00001034 return if_lookup_by_index(ifindex);
paul718e3742002-12-13 20:15:29 +00001035}
paul8cc41982005-05-06 21:25:49 +00001036#endif /* ifaddr_ipv4_table */
paul718e3742002-12-13 20:15:29 +00001037
1038/* Initialize interface list. */
1039void
Feng Lu5a5702f2015-05-22 11:39:59 +02001040if_init (vrf_id_t vrf_id, struct list **intf_list)
paul718e3742002-12-13 20:15:29 +00001041{
Feng Lu5a5702f2015-05-22 11:39:59 +02001042 *intf_list = list_new ();
paul8cc41982005-05-06 21:25:49 +00001043#if 0
paul718e3742002-12-13 20:15:29 +00001044 ifaddr_ipv4_table = route_table_init ();
paul8cc41982005-05-06 21:25:49 +00001045#endif /* ifaddr_ipv4_table */
paul718e3742002-12-13 20:15:29 +00001046
Feng Lu5a5702f2015-05-22 11:39:59 +02001047 (*intf_list)->cmp = (int (*)(void *, void *))if_cmp_func;
paul718e3742002-12-13 20:15:29 +00001048
Feng Lu5a5702f2015-05-22 11:39:59 +02001049 if (vrf_id == VRF_DEFAULT)
1050 iflist = *intf_list;
paul718e3742002-12-13 20:15:29 +00001051}
Tom Goff4bd045d2010-11-10 13:00:54 -08001052
1053void
Feng Lu5a5702f2015-05-22 11:39:59 +02001054if_terminate (vrf_id_t vrf_id, struct list **intf_list)
Tom Goff4bd045d2010-11-10 13:00:54 -08001055{
1056 for (;;)
1057 {
1058 struct interface *ifp;
1059
Feng Lu5a5702f2015-05-22 11:39:59 +02001060 ifp = listnode_head (*intf_list);
Tom Goff4bd045d2010-11-10 13:00:54 -08001061 if (ifp == NULL)
1062 break;
1063
1064 if_delete (ifp);
1065 }
1066
Feng Lu5a5702f2015-05-22 11:39:59 +02001067 list_delete (*intf_list);
1068 *intf_list = NULL;
1069
1070 if (vrf_id == VRF_DEFAULT)
1071 iflist = NULL;
Tom Goff4bd045d2010-11-10 13:00:54 -08001072}
Timo Teräs954c7d62016-01-15 17:36:33 +02001073
1074const char *
1075if_link_type_str (enum zebra_link_type llt)
1076{
1077 switch (llt)
1078 {
1079#define llts(T,S) case (T): return (S)
1080 llts(ZEBRA_LLT_UNKNOWN, "Unknown");
1081 llts(ZEBRA_LLT_ETHER, "Ethernet");
1082 llts(ZEBRA_LLT_EETHER, "Experimental Ethernet");
1083 llts(ZEBRA_LLT_AX25, "AX.25 Level 2");
1084 llts(ZEBRA_LLT_PRONET, "PROnet token ring");
1085 llts(ZEBRA_LLT_IEEE802, "IEEE 802.2 Ethernet/TR/TB");
1086 llts(ZEBRA_LLT_ARCNET, "ARCnet");
1087 llts(ZEBRA_LLT_APPLETLK, "AppleTalk");
1088 llts(ZEBRA_LLT_DLCI, "Frame Relay DLCI");
1089 llts(ZEBRA_LLT_ATM, "ATM");
1090 llts(ZEBRA_LLT_METRICOM, "Metricom STRIP");
1091 llts(ZEBRA_LLT_IEEE1394, "IEEE 1394 IPv4");
1092 llts(ZEBRA_LLT_EUI64, "EUI-64");
1093 llts(ZEBRA_LLT_INFINIBAND, "InfiniBand");
1094 llts(ZEBRA_LLT_SLIP, "SLIP");
1095 llts(ZEBRA_LLT_CSLIP, "Compressed SLIP");
1096 llts(ZEBRA_LLT_SLIP6, "SLIPv6");
1097 llts(ZEBRA_LLT_CSLIP6, "Compressed SLIPv6");
1098 llts(ZEBRA_LLT_ROSE, "ROSE packet radio");
1099 llts(ZEBRA_LLT_X25, "CCITT X.25");
1100 llts(ZEBRA_LLT_PPP, "PPP");
1101 llts(ZEBRA_LLT_CHDLC, "Cisco HDLC");
1102 llts(ZEBRA_LLT_RAWHDLC, "Raw HDLC");
1103 llts(ZEBRA_LLT_LAPB, "LAPB");
1104 llts(ZEBRA_LLT_IPIP, "IPIP Tunnel");
1105 llts(ZEBRA_LLT_IPIP6, "IPIP6 Tunnel");
1106 llts(ZEBRA_LLT_FRAD, "FRAD");
1107 llts(ZEBRA_LLT_SKIP, "SKIP vif");
1108 llts(ZEBRA_LLT_LOOPBACK, "Loopback");
1109 llts(ZEBRA_LLT_LOCALTLK, "Localtalk");
1110 llts(ZEBRA_LLT_FDDI, "FDDI");
1111 llts(ZEBRA_LLT_SIT, "IPv6-in-IPv4 SIT");
1112 llts(ZEBRA_LLT_IPDDP, "IP-in-DDP tunnel");
1113 llts(ZEBRA_LLT_IPGRE, "GRE over IP");
1114 llts(ZEBRA_LLT_PIMREG, "PIMSM registration");
1115 llts(ZEBRA_LLT_HIPPI, "HiPPI");
1116 llts(ZEBRA_LLT_IRDA, "IrDA");
1117 llts(ZEBRA_LLT_FCPP, "Fibre-Channel PtP");
1118 llts(ZEBRA_LLT_FCAL, "Fibre-Channel Arbitrated Loop");
1119 llts(ZEBRA_LLT_FCPL, "Fibre-Channel Public Loop");
1120 llts(ZEBRA_LLT_FCFABRIC, "Fibre-Channel Fabric");
1121 llts(ZEBRA_LLT_IEEE802_TR, "IEEE 802.2 Token Ring");
1122 llts(ZEBRA_LLT_IEEE80211, "IEEE 802.11");
1123 llts(ZEBRA_LLT_IEEE80211_RADIOTAP, "IEEE 802.11 Radiotap");
1124 llts(ZEBRA_LLT_IEEE802154, "IEEE 802.15.4");
1125 llts(ZEBRA_LLT_IEEE802154_PHY, "IEEE 802.15.4 Phy");
1126 default:
1127 zlog_warn ("Unknown value %d", llt);
1128 return "Unknown type!";
1129#undef llts
1130 }
1131 return NULL;
1132}
Olivier Dugeonae51c9d2016-04-19 16:21:46 +02001133
1134struct if_link_params *
1135if_link_params_get (struct interface *ifp)
1136{
Paul Jakma3676cb02016-07-29 13:39:37 +01001137 int i;
1138
Olivier Dugeonae51c9d2016-04-19 16:21:46 +02001139 if (ifp->link_params != NULL)
1140 return ifp->link_params;
1141
1142 struct if_link_params *iflp = XCALLOC(MTYPE_IF_LINK_PARAMS,
1143 sizeof (struct if_link_params));
1144 if (iflp == NULL) return NULL;
1145
1146 /* Set TE metric == standard metric */
1147 iflp->te_metric = ifp->metric;
1148
1149 /* Compute default bandwidth based on interface */
1150 int bw = (float)((ifp->bandwidth ? ifp->bandwidth : DEFAULT_BANDWIDTH)
1151 * TE_KILO_BIT / TE_BYTE);
1152
1153 /* Set Max, Reservable and Unreserved Bandwidth */
1154 iflp->max_bw = bw;
1155 iflp->max_rsv_bw = bw;
Paul Jakma3676cb02016-07-29 13:39:37 +01001156 for (i = 0; i < MAX_CLASS_TYPE; i++)
Olivier Dugeonae51c9d2016-04-19 16:21:46 +02001157 iflp->unrsv_bw[i] = bw;
1158
1159 /* Update Link parameters status */
1160 iflp->lp_status = LP_TE | LP_MAX_BW | LP_MAX_RSV_BW | LP_UNRSV_BW;
1161
1162 /* Finally attach newly created Link Parameters */
1163 ifp->link_params = iflp;
1164
1165 return iflp;
1166}
1167
1168void
1169if_link_params_free (struct interface *ifp)
1170{
1171 if (ifp->link_params == NULL) return;
1172 XFREE(MTYPE_IF_LINK_PARAMS, ifp->link_params);
1173 ifp->link_params = NULL;
1174}