]> git.proxmox.com Git - mirror_frr.git/blame - lib/if.c
lib: register 'if_var_handlers' only once
[mirror_frr.git] / lib / if.c
CommitLineData
d62a17ae 1/*
718e3744 2 * Interface functions.
3 * Copyright (C) 1997, 98 Kunihiro Ishiguro
4 *
5 * This file is part of GNU Zebra.
896014f4 6 *
718e3744 7 * GNU Zebra is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation; either version 2, or (at your
10 * option) any 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 *
896014f4
DL
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
718e3744 20 */
21
22#include <zebra.h>
23
24#include "linklist.h"
25#include "vector.h"
26#include "vty.h"
27#include "command.h"
8736158a 28#include "vrf.h"
718e3744 29#include "if.h"
30#include "sockunion.h"
31#include "prefix.h"
718e3744 32#include "memory.h"
33#include "table.h"
34#include "buffer.h"
718e3744 35#include "log.h"
6b0655a2 36
d62a17ae 37DEFINE_MTYPE(LIB, IF, "Interface")
38DEFINE_MTYPE_STATIC(LIB, CONNECTED, "Connected")
39DEFINE_MTYPE_STATIC(LIB, NBR_CONNECTED, "Neighbor Connected")
40DEFINE_MTYPE(LIB, CONNECTED_LABEL, "Connected interface label")
41DEFINE_MTYPE_STATIC(LIB, IF_LINK_PARAMS, "Informational Link Parameters")
4a1ab8e4 42
e80e7cce
DL
43DEFINE_QOBJ_TYPE(interface)
44
ce19a04a
DL
45DEFINE_HOOK(if_add, (struct interface *ifp), (ifp))
46DEFINE_KOOH(if_del, (struct interface *ifp), (ifp))
47
8736158a 48/* List of interfaces in only the default VRF */
244c1cdc 49int ptm_enable = 0;
718e3744 50
3a0391a9 51/* Compare interface names, returning an integer greater than, equal to, or
52 * less than 0, (following the strcmp convention), according to the
53 * relationship between ifp1 and ifp2. Interface names consist of an
54 * alphabetic prefix and a numeric suffix. The primary sort key is
55 * lexicographic by name, and then numeric by number. No number sorts
56 * before all numbers. Examples: de0 < de1, de100 < fxp0 < xl0, devpty <
57 * devpty0, de0 < del0
d62a17ae 58 */
59int if_cmp_name_func(char *p1, char *p2)
106d2fd5 60{
d62a17ae 61 unsigned int l1, l2;
62 long int x1, x2;
63 int res;
64
65 while (*p1 && *p2) {
66 /* look up to any number */
67 l1 = strcspn(p1, "0123456789");
68 l2 = strcspn(p2, "0123456789");
69
70 /* name lengths are different -> compare names */
71 if (l1 != l2)
72 return (strcmp(p1, p2));
73
74 /* Note that this relies on all numbers being less than all
75 * letters, so
76 * that de0 < del0.
77 */
78 res = strncmp(p1, p2, l1);
79
80 /* names are different -> compare them */
81 if (res)
82 return res;
83
84 /* with identical name part, go to numeric part */
85 p1 += l1;
86 p2 += l1;
87
88 if (!*p1)
89 return -1;
90 if (!*p2)
91 return 1;
92
93 x1 = strtol(p1, &p1, 10);
94 x2 = strtol(p2, &p2, 10);
95
96 /* let's compare numbers now */
97 if (x1 < x2)
98 return -1;
99 if (x1 > x2)
100 return 1;
101
102 /* numbers were equal, lets do it again..
103 (it happens with name like "eth123.456:789") */
104 }
105 if (*p1)
106 return 1;
107 if (*p2)
108 return -1;
109 return 0;
106d2fd5 110}
111
d62a17ae 112static int if_cmp_func(struct interface *ifp1, struct interface *ifp2)
974fc9d2 113{
d62a17ae 114 return if_cmp_name_func(ifp1->name, ifp2->name);
974fc9d2
DS
115}
116
718e3744 117/* Create new interface structure. */
bcc24579 118struct interface *if_create(const char *name, vrf_id_t vrf_id)
718e3744 119{
d62a17ae 120 struct interface *ifp;
121 struct list *intf_list = vrf_iflist_get(vrf_id);
122
123 ifp = XCALLOC(MTYPE_IF, sizeof(struct interface));
124 ifp->ifindex = IFINDEX_INTERNAL;
125
126 assert(name);
bcc24579 127 strlcpy(ifp->name, name, sizeof(ifp->name));
d62a17ae 128 ifp->vrf_id = vrf_id;
129 if (if_lookup_by_name(ifp->name, vrf_id) == NULL)
130 listnode_add_sort(intf_list, ifp);
131 else
132 zlog_err(
133 "if_create(%s): corruption detected -- interface with this "
134 "name exists already in VRF %u!",
135 ifp->name, vrf_id);
136 ifp->connected = list_new();
137 ifp->connected->del = (void (*)(void *))connected_free;
138
139 ifp->nbr_connected = list_new();
140 ifp->nbr_connected->del = (void (*)(void *))nbr_connected_free;
141
142 /* Enable Link-detection by default */
143 SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
144
145 QOBJ_REG(ifp, interface);
ce19a04a 146 hook_call(if_add, ifp);
d62a17ae 147 return ifp;
718e3744 148}
149
f93e3f69 150/* Create new interface structure. */
d62a17ae 151void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id)
f93e3f69 152{
d62a17ae 153 struct list *intf_list = vrf_iflist_get(vrf_id);
154
155 /* remove interface from old master vrf list */
156 if (vrf_iflist(ifp->vrf_id))
157 listnode_delete(vrf_iflist(ifp->vrf_id), ifp);
158
159 ifp->vrf_id = vrf_id;
160 if (if_lookup_by_name(ifp->name, vrf_id) == NULL)
161 listnode_add_sort(intf_list, ifp);
162 else
163 zlog_err(
bcc24579
RW
164 "%s(%s): corruption detected -- interface with this "
165 "name exists already in VRF %u!", __func__,
d62a17ae 166 ifp->name, vrf_id);
167
168 return;
f93e3f69
DS
169}
170
171
d2fc8896 172/* Delete interface structure. */
d62a17ae 173void if_delete_retain(struct interface *ifp)
718e3744 174{
ce19a04a 175 hook_call(if_del, ifp);
d62a17ae 176 QOBJ_UNREG(ifp);
e80e7cce 177
d62a17ae 178 /* Free connected address list */
179 list_delete_all_node(ifp->connected);
a80beece 180
d62a17ae 181 /* Free connected nbr address list */
182 list_delete_all_node(ifp->nbr_connected);
d2fc8896 183}
184
185/* Delete and free interface structure. */
d62a17ae 186void if_delete(struct interface *ifp)
d2fc8896 187{
d62a17ae 188 listnode_delete(vrf_iflist(ifp->vrf_id), ifp);
d2fc8896 189
d62a17ae 190 if_delete_retain(ifp);
718e3744 191
acdf5e25
DS
192 list_delete_and_null(&ifp->connected);
193 list_delete_and_null(&ifp->nbr_connected);
2dd04c5d 194
d62a17ae 195 if_link_params_free(ifp);
16f1b9ee 196
d62a17ae 197 XFREE(MTYPE_IF, ifp);
718e3744 198}
199
718e3744 200/* Interface existance check by index. */
d62a17ae 201struct interface *if_lookup_by_index(ifindex_t ifindex, vrf_id_t vrf_id)
718e3744 202{
d62a17ae 203 struct listnode *node;
204 struct interface *ifp;
718e3744 205
d62a17ae 206 for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), node, ifp)) {
207 if (ifp->ifindex == ifindex)
208 return ifp;
209 }
210 return NULL;
718e3744 211}
212
d62a17ae 213const char *ifindex2ifname(ifindex_t ifindex, vrf_id_t vrf_id)
718e3744 214{
d62a17ae 215 struct interface *ifp;
718e3744 216
d62a17ae 217 return ((ifp = if_lookup_by_index(ifindex, vrf_id)) != NULL)
218 ? ifp->name
219 : "unknown";
d2fc8896 220}
221
d62a17ae 222ifindex_t ifname2ifindex(const char *name, vrf_id_t vrf_id)
d2fc8896 223{
d62a17ae 224 struct interface *ifp;
d2fc8896 225
d62a17ae 226 return ((ifp = if_lookup_by_name(name, vrf_id)) != NULL)
227 ? ifp->ifindex
228 : IFINDEX_INTERNAL;
718e3744 229}
230
231/* Interface existance check by interface name. */
d62a17ae 232struct interface *if_lookup_by_name(const char *name, vrf_id_t vrf_id)
718e3744 233{
d62a17ae 234 struct listnode *node;
235 struct interface *ifp;
236
bcc24579
RW
237 if (!name || strnlen(name, INTERFACE_NAMSIZ) == INTERFACE_NAMSIZ)
238 return NULL;
f8962871 239
bcc24579
RW
240 for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), node, ifp)) {
241 if (strcmp(name, ifp->name) == 0)
d62a17ae 242 return ifp;
243 }
f8962871 244
d62a17ae 245 return NULL;
f8962871
DS
246}
247
bcc24579 248struct interface *if_lookup_by_name_all_vrf(const char *name)
a349198f 249{
bcc24579 250 struct vrf *vrf;
d62a17ae 251 struct interface *ifp;
a349198f 252
bcc24579 253 if (!name || strnlen(name, INTERFACE_NAMSIZ) == INTERFACE_NAMSIZ)
d62a17ae 254 return NULL;
a349198f 255
bcc24579
RW
256 RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
257 ifp = if_lookup_by_name(name, vrf->vrf_id);
258 if (ifp)
d62a17ae 259 return ifp;
260 }
bcc24579 261
d62a17ae 262 return NULL;
a349198f 263}
264
718e3744 265/* Lookup interface by IPv4 address. */
d62a17ae 266struct interface *if_lookup_exact_address(void *src, int family,
267 vrf_id_t vrf_id)
718e3744 268{
d62a17ae 269 struct listnode *node;
270 struct listnode *cnode;
271 struct interface *ifp;
272 struct prefix *p;
273 struct connected *c;
274
275 for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), node, ifp)) {
276 for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
277 p = c->address;
278
279 if (p && (p->family == family)) {
280 if (family == AF_INET) {
281 if (IPV4_ADDR_SAME(
282 &p->u.prefix4,
283 (struct in_addr *)src))
284 return ifp;
285 } else if (family == AF_INET6) {
286 if (IPV6_ADDR_SAME(
287 &p->u.prefix6,
288 (struct in6_addr *)src))
289 return ifp;
290 }
291 }
0aabccc0 292 }
718e3744 293 }
d62a17ae 294 return NULL;
718e3744 295}
296
297/* Lookup interface by IPv4 address. */
d62a17ae 298struct connected *if_lookup_address(void *matchaddr, int family,
299 vrf_id_t vrf_id)
718e3744 300{
d62a17ae 301 struct listnode *node;
302 struct prefix addr;
303 int bestlen = 0;
304 struct listnode *cnode;
305 struct interface *ifp;
306 struct connected *c;
307 struct connected *match;
308
309 if (family == AF_INET) {
310 addr.family = AF_INET;
311 addr.u.prefix4 = *((struct in_addr *)matchaddr);
312 addr.prefixlen = IPV4_MAX_BITLEN;
313 } else if (family == AF_INET6) {
314 addr.family = AF_INET6;
315 addr.u.prefix6 = *((struct in6_addr *)matchaddr);
316 addr.prefixlen = IPV6_MAX_BITLEN;
317 }
718e3744 318
d62a17ae 319 match = NULL;
718e3744 320
d62a17ae 321 for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), node, ifp)) {
322 for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
323 if (c->address && (c->address->family == AF_INET)
324 && prefix_match(CONNECTED_PREFIX(c), &addr)
325 && (c->address->prefixlen > bestlen)) {
326 bestlen = c->address->prefixlen;
327 match = c;
328 }
329 }
718e3744 330 }
d62a17ae 331 return match;
718e3744 332}
333
b81e97a8 334/* Lookup interface by prefix */
d62a17ae 335struct interface *if_lookup_prefix(struct prefix *prefix, vrf_id_t vrf_id)
b81e97a8 336{
d62a17ae 337 struct listnode *node;
338 struct listnode *cnode;
339 struct interface *ifp;
340 struct connected *c;
341
342 for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), node, ifp)) {
343 for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
344 if (prefix_cmp(c->address, prefix) == 0) {
345 return ifp;
346 }
347 }
348 }
349 return NULL;
b81e97a8
DD
350}
351
718e3744 352/* Get interface by name if given name interface doesn't exist create
353 one. */
bcc24579 354struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id, int vty)
718e3744 355{
d62a17ae 356 struct interface *ifp;
718e3744 357
bcc24579
RW
358 ifp = if_lookup_by_name_all_vrf(name);
359 if (ifp) {
360 if (ifp->vrf_id == vrf_id)
361 return ifp;
a349198f 362
bcc24579
RW
363 /* Found a match on a different VRF. If the interface command
364 * was entered in vty without a VRF (passed as VRF_DEFAULT),
365 * accept the ifp we found. If a vrf was entered and there is
366 * a mismatch, reject it if from vty. If it came from the kernel
367 * or by way of zclient, believe it and update the ifp
368 * accordingly.
369 */
370 if (vty) {
371 if (vrf_id == VRF_DEFAULT)
372 return ifp;
373 return NULL;
374 } else {
375 if_update_to_new_vrf(ifp, vrf_id);
376 return ifp;
85f9da7f 377 }
85f9da7f 378 }
bcc24579
RW
379
380 return if_create(name, vrf_id);
8736158a
FL
381}
382
718e3744 383/* Does interface up ? */
d62a17ae 384int if_is_up(struct interface *ifp)
718e3744 385{
d62a17ae 386 return ifp->flags & IFF_UP;
718e3744 387}
388
2e3b2e47 389/* Is interface running? */
d62a17ae 390int if_is_running(struct interface *ifp)
2e3b2e47 391{
d62a17ae 392 return ifp->flags & IFF_RUNNING;
2e3b2e47 393}
394
395/* Is the interface operative, eg. either UP & RUNNING
244c1cdc
DS
396 or UP & !ZEBRA_INTERFACE_LINK_DETECTION and
397 if ptm checking is enabled, then ptm check has passed */
d62a17ae 398int if_is_operative(struct interface *ifp)
2e3b2e47 399{
d62a17ae 400 return ((ifp->flags & IFF_UP)
401 && (((ifp->flags & IFF_RUNNING)
402 && (ifp->ptm_status || !ifp->ptm_enable))
403 || !CHECK_FLAG(ifp->status,
404 ZEBRA_INTERFACE_LINKDETECTION)));
244c1cdc
DS
405}
406
407/* Is the interface operative, eg. either UP & RUNNING
408 or UP & !ZEBRA_INTERFACE_LINK_DETECTION, without PTM check */
d62a17ae 409int if_is_no_ptm_operative(struct interface *ifp)
244c1cdc 410{
d62a17ae 411 return ((ifp->flags & IFF_UP)
412 && ((ifp->flags & IFF_RUNNING)
413 || !CHECK_FLAG(ifp->status,
414 ZEBRA_INTERFACE_LINKDETECTION)));
2e3b2e47 415}
416
718e3744 417/* Is this loopback interface ? */
d62a17ae 418int if_is_loopback(struct interface *ifp)
718e3744 419{
d62a17ae 420 /* XXX: Do this better, eg what if IFF_WHATEVER means X on platform M
421 * but Y on platform N?
422 */
423 return (ifp->flags & (IFF_LOOPBACK | IFF_NOXMIT | IFF_VIRTUAL));
718e3744 424}
425
426/* Does this interface support broadcast ? */
d62a17ae 427int if_is_broadcast(struct interface *ifp)
718e3744 428{
d62a17ae 429 return ifp->flags & IFF_BROADCAST;
718e3744 430}
431
432/* Does this interface support broadcast ? */
d62a17ae 433int if_is_pointopoint(struct interface *ifp)
718e3744 434{
d62a17ae 435 return ifp->flags & IFF_POINTOPOINT;
718e3744 436}
437
438/* Does this interface support multicast ? */
d62a17ae 439int if_is_multicast(struct interface *ifp)
718e3744 440{
d62a17ae 441 return ifp->flags & IFF_MULTICAST;
718e3744 442}
443
444/* Printout flag information into log */
d62a17ae 445const char *if_flag_dump(unsigned long flag)
718e3744 446{
d62a17ae 447 int separator = 0;
448 static char logbuf[BUFSIZ];
449
450#define IFF_OUT_LOG(X, STR) \
451 if (flag & (X)) { \
452 if (separator) \
453 strlcat(logbuf, ",", BUFSIZ); \
454 else \
455 separator = 1; \
456 strlcat(logbuf, STR, BUFSIZ); \
457 }
718e3744 458
d62a17ae 459 strlcpy(logbuf, "<", BUFSIZ);
460 IFF_OUT_LOG(IFF_UP, "UP");
461 IFF_OUT_LOG(IFF_BROADCAST, "BROADCAST");
462 IFF_OUT_LOG(IFF_DEBUG, "DEBUG");
463 IFF_OUT_LOG(IFF_LOOPBACK, "LOOPBACK");
464 IFF_OUT_LOG(IFF_POINTOPOINT, "POINTOPOINT");
465 IFF_OUT_LOG(IFF_NOTRAILERS, "NOTRAILERS");
466 IFF_OUT_LOG(IFF_RUNNING, "RUNNING");
467 IFF_OUT_LOG(IFF_NOARP, "NOARP");
468 IFF_OUT_LOG(IFF_PROMISC, "PROMISC");
469 IFF_OUT_LOG(IFF_ALLMULTI, "ALLMULTI");
470 IFF_OUT_LOG(IFF_OACTIVE, "OACTIVE");
471 IFF_OUT_LOG(IFF_SIMPLEX, "SIMPLEX");
472 IFF_OUT_LOG(IFF_LINK0, "LINK0");
473 IFF_OUT_LOG(IFF_LINK1, "LINK1");
474 IFF_OUT_LOG(IFF_LINK2, "LINK2");
475 IFF_OUT_LOG(IFF_MULTICAST, "MULTICAST");
476 IFF_OUT_LOG(IFF_NOXMIT, "NOXMIT");
477 IFF_OUT_LOG(IFF_NORTEXCH, "NORTEXCH");
478 IFF_OUT_LOG(IFF_VIRTUAL, "VIRTUAL");
479 IFF_OUT_LOG(IFF_IPV4, "IPv4");
480 IFF_OUT_LOG(IFF_IPV6, "IPv6");
481
482 strlcat(logbuf, ">", BUFSIZ);
483
484 return logbuf;
630c97ce 485#undef IFF_OUT_LOG
718e3744 486}
487
488/* For debugging */
d62a17ae 489static void if_dump(const struct interface *ifp)
718e3744 490{
d62a17ae 491 struct listnode *node;
492 struct connected *c __attribute__((unused));
493
494 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, c))
495 zlog_info(
496 "Interface %s vrf %u index %d metric %d mtu %d "
497 "mtu6 %d %s",
498 ifp->name, ifp->vrf_id, ifp->ifindex, ifp->metric,
499 ifp->mtu, ifp->mtu6, if_flag_dump(ifp->flags));
718e3744 500}
501
502/* Interface printing for all interface. */
d62a17ae 503void if_dump_all(void)
718e3744 504{
d62a17ae 505 struct vrf *vrf;
506 struct listnode *node;
507 void *p;
508
a2addae8
RW
509 RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id)
510 if (vrf->iflist != NULL)
511 for (ALL_LIST_ELEMENTS_RO(vrf->iflist, node, p))
512 if_dump(p);
718e3744 513}
514
6147e2c6 515DEFUN (interface_desc,
718e3744 516 interface_desc_cmd,
fcbee690 517 "description LINE...",
718e3744 518 "Interface specific description\n"
519 "Characters describing this interface\n")
520{
d62a17ae 521 int idx_line = 1;
522 VTY_DECLVAR_CONTEXT(interface, ifp);
718e3744 523
d62a17ae 524 if (ifp->desc)
525 XFREE(MTYPE_TMP, ifp->desc);
526 ifp->desc = argv_concat(argv, argc, idx_line);
718e3744 527
d62a17ae 528 return CMD_SUCCESS;
718e3744 529}
530
6147e2c6 531DEFUN (no_interface_desc,
718e3744 532 no_interface_desc_cmd,
533 "no description",
534 NO_STR
535 "Interface specific description\n")
536{
d62a17ae 537 VTY_DECLVAR_CONTEXT(interface, ifp);
718e3744 538
d62a17ae 539 if (ifp->desc)
540 XFREE(MTYPE_TMP, ifp->desc);
541 ifp->desc = NULL;
718e3744 542
d62a17ae 543 return CMD_SUCCESS;
718e3744 544}
6b0655a2 545
98954844
PJ
546#ifdef SUNOS_5
547/* Need to handle upgrade from SUNWzebra to Quagga. SUNWzebra created
548 * a seperate struct interface for each logical interface, so config
549 * file may be full of 'interface fooX:Y'. Solaris however does not
550 * expose logical interfaces via PF_ROUTE, so trying to track logical
551 * interfaces can be fruitless, for that reason Quagga only tracks
552 * the primary IP interface.
553 *
554 * We try accomodate SUNWzebra by:
555 * - looking up the interface name, to see whether it exists, if so
556 * its useable
557 * - for protocol daemons, this could only because zebra told us of
558 * the interface
559 * - for zebra, only because it learnt from kernel
560 * - if not:
561 * - search the name to see if it contains a sub-ipif / logical interface
562 * seperator, the ':' char. If it does:
563 * - text up to that char must be the primary name - get that name.
564 * if not:
565 * - no idea, just get the name in its entirety.
566 */
bcc24579 567static struct interface *if_sunwzebra_get(char *name, vrf_id_t vrf_id)
98954844 568{
d62a17ae 569 struct interface *ifp;
bcc24579 570 char *cp;
d62a17ae 571
bcc24579 572 if ((ifp = if_lookup_by_name(name, vrf_id)) != NULL)
d62a17ae 573 return ifp;
574
575 /* hunt the primary interface name... */
bcc24579
RW
576 cp = strchr(name, ':');
577 if (cp)
578 *cp = '\0';
d62a17ae 579
bcc24579 580 return if_get_by_name(name, vrf_id, 1);
98954844
PJ
581}
582#endif /* SUNOS_5 */
6b0655a2 583
718e3744 584DEFUN (interface,
585 interface_cmd,
199d90a1 586 "interface IFNAME [vrf NAME]",
718e3744 587 "Select an interface to configure\n"
fcbee690
QY
588 "Interface's name\n"
589 VRF_CMD_HELP_STR)
718e3744 590{
d62a17ae 591 int idx_ifname = 1;
592 int idx_vrf = 3;
593 const char *ifname = argv[idx_ifname]->arg;
594 const char *vrfname = (argc > 2) ? argv[idx_vrf]->arg : NULL;
595
596 struct interface *ifp;
d62a17ae 597 vrf_id_t vrf_id = VRF_DEFAULT;
598
bcc24579 599 if (strlen(ifname) > INTERFACE_NAMSIZ) {
d62a17ae 600 vty_out(vty,
601 "%% Interface name %s is invalid: length exceeds "
602 "%d characters\n",
603 ifname, INTERFACE_NAMSIZ);
604 return CMD_WARNING_CONFIG_FAILED;
605 }
718e3744 606
d62a17ae 607 /*Pending: need proper vrf name based lookup/(possible creation of VRF)
608 Imagine forward reference of a vrf by name in this interface config */
609 if (vrfname)
610 VRF_GET_ID(vrf_id, vrfname);
cd2a8a42 611
98954844 612#ifdef SUNOS_5
bcc24579 613 ifp = if_sunwzebra_get(ifname, vrf_id);
98954844 614#else
bcc24579 615 ifp = if_get_by_name(ifname, vrf_id, 1);
98954844 616#endif /* SUNOS_5 */
718e3744 617
d62a17ae 618 if (!ifp) {
619 vty_out(vty, "%% interface %s not in %s\n", ifname, vrfname);
620 return CMD_WARNING_CONFIG_FAILED;
621 }
622 VTY_PUSH_CONTEXT(INTERFACE_NODE, ifp);
718e3744 623
d62a17ae 624 return CMD_SUCCESS;
718e3744 625}
626
32d2463c 627DEFUN_NOSH (no_interface,
628 no_interface_cmd,
199d90a1 629 "no interface IFNAME [vrf NAME]",
32d2463c 630 NO_STR
631 "Delete a pseudo interface's configuration\n"
fcbee690
QY
632 "Interface's name\n"
633 VRF_CMD_HELP_STR)
32d2463c 634{
d62a17ae 635 const char *ifname = argv[2]->arg;
636 const char *vrfname = (argc > 3) ? argv[3]->arg : NULL;
fcbee690 637
d62a17ae 638 // deleting interface
639 struct interface *ifp;
640 vrf_id_t vrf_id = VRF_DEFAULT;
32d2463c 641
d62a17ae 642 if (argc > 3)
643 VRF_GET_ID(vrf_id, vrfname);
cd2a8a42 644
d62a17ae 645 ifp = if_lookup_by_name(ifname, vrf_id);
32d2463c 646
d62a17ae 647 if (ifp == NULL) {
648 vty_out(vty, "%% Interface %s does not exist\n", ifname);
649 return CMD_WARNING_CONFIG_FAILED;
650 }
32d2463c 651
d62a17ae 652 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
653 vty_out(vty, "%% Only inactive interfaces can be deleted\n");
654 return CMD_WARNING_CONFIG_FAILED;
655 }
32d2463c 656
d62a17ae 657 if_delete(ifp);
32d2463c 658
d62a17ae 659 return CMD_SUCCESS;
32d2463c 660}
661
5d56066e
RW
662static void if_autocomplete(vector comps, struct cmd_token *token)
663{
664 struct interface *ifp;
665 struct vrf *vrf = NULL;
666
667 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
668 RB_FOREACH (ifp, if_name_head, &vrf->ifaces_by_name) {
669 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, ifp->name));
670 }
671 }
672}
673
674static const struct cmd_variable_handler if_var_handlers[] = {
675 {/* "interface NAME" */
676 .varname = "interface",
677 .completions = if_autocomplete},
678 {.tokenname = "IFNAME", .completions = if_autocomplete},
679 {.tokenname = "INTERFACE", .completions = if_autocomplete},
680 {.completions = NULL}};
681
d62a17ae 682void if_cmd_init(void)
0b84f294 683{
5d56066e
RW
684 cmd_variable_handler_register(if_var_handlers);
685
d62a17ae 686 install_element(CONFIG_NODE, &interface_cmd);
687 install_element(CONFIG_NODE, &no_interface_cmd);
0b84f294 688
d62a17ae 689 install_default(INTERFACE_NODE);
690 install_element(INTERFACE_NODE, &interface_desc_cmd);
691 install_element(INTERFACE_NODE, &no_interface_desc_cmd);
0b84f294
DL
692}
693
d7d73ffc 694#if 0
718e3744 695/* For debug purpose. */
696DEFUN (show_address,
697 show_address_cmd,
199d90a1 698 "show address [vrf NAME]",
718e3744 699 SHOW_STR
fcbee690
QY
700 "address\n"
701 VRF_CMD_HELP_STR)
718e3744 702{
abddf075 703 int idx_vrf = 3;
52dc7ee6 704 struct listnode *node;
705 struct listnode *node2;
718e3744 706 struct interface *ifp;
707 struct connected *ifc;
708 struct prefix *p;
8736158a 709 vrf_id_t vrf_id = VRF_DEFAULT;
718e3744 710
fcbee690 711 if (argc > 2)
58749582 712 VRF_GET_ID (vrf_id, argv[idx_vrf]->arg);
8736158a
FL
713
714 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
718e3744 715 {
1eb8ef25 716 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node2, ifc))
718e3744 717 {
718e3744 718 p = ifc->address;
719
720 if (p->family == AF_INET)
55f70b67 721 vty_out (vty, "%s/%d\n", inet_ntoa (p->u.prefix4), p->prefixlen);
718e3744 722 }
723 }
724 return CMD_SUCCESS;
725}
726
8736158a
FL
727DEFUN (show_address_vrf_all,
728 show_address_vrf_all_cmd,
9ccf14f7 729 "show address vrf all",
8736158a
FL
730 SHOW_STR
731 "address\n"
732 VRF_ALL_CMD_HELP_STR)
733{
1a1a7065 734 struct vrf *vrf;
8736158a
FL
735 struct listnode *node;
736 struct listnode *node2;
737 struct interface *ifp;
738 struct connected *ifc;
739 struct prefix *p;
8736158a 740
a62c4901 741 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
8736158a 742 {
1a1a7065 743 if (!vrf->iflist || !listcount (vrf->iflist))
8736158a
FL
744 continue;
745
55f70b67 746 vty_out (vty, "\nVRF %u\n\n", vrf->vrf_id);
8736158a 747
1a1a7065 748 for (ALL_LIST_ELEMENTS_RO (vrf->iflist, node, ifp))
8736158a
FL
749 {
750 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node2, ifc))
751 {
752 p = ifc->address;
753
754 if (p->family == AF_INET)
55f70b67 755 vty_out (vty, "%s/%d\n", inet_ntoa (p->u.prefix4), p->prefixlen);
8736158a
FL
756 }
757 }
758 }
759 return CMD_SUCCESS;
760}
d7d73ffc 761#endif
8736158a 762
718e3744 763/* Allocate connected structure. */
d62a17ae 764struct connected *connected_new(void)
718e3744 765{
d62a17ae 766 return XCALLOC(MTYPE_CONNECTED, sizeof(struct connected));
718e3744 767}
768
a80beece 769/* Allocate nbr connected structure. */
d62a17ae 770struct nbr_connected *nbr_connected_new(void)
a80beece 771{
d62a17ae 772 return XCALLOC(MTYPE_NBR_CONNECTED, sizeof(struct nbr_connected));
a80beece
DS
773}
774
718e3744 775/* Free connected structure. */
d62a17ae 776void connected_free(struct connected *connected)
718e3744 777{
d62a17ae 778 if (connected->address)
779 prefix_free(connected->address);
718e3744 780
d62a17ae 781 if (connected->destination)
782 prefix_free(connected->destination);
718e3744 783
d62a17ae 784 if (connected->label)
785 XFREE(MTYPE_CONNECTED_LABEL, connected->label);
718e3744 786
d62a17ae 787 XFREE(MTYPE_CONNECTED, connected);
718e3744 788}
789
a80beece 790/* Free nbr connected structure. */
d62a17ae 791void nbr_connected_free(struct nbr_connected *connected)
a80beece 792{
d62a17ae 793 if (connected->address)
794 prefix_free(connected->address);
a80beece 795
d62a17ae 796 XFREE(MTYPE_NBR_CONNECTED, connected);
a80beece
DS
797}
798
799/* If same interface nbr address already exists... */
d62a17ae 800struct nbr_connected *nbr_connected_check(struct interface *ifp,
801 struct prefix *p)
a80beece 802{
d62a17ae 803 struct nbr_connected *ifc;
804 struct listnode *node;
a80beece 805
d62a17ae 806 for (ALL_LIST_ELEMENTS_RO(ifp->nbr_connected, node, ifc))
807 if (prefix_same(ifc->address, p))
808 return ifc;
a80beece 809
d62a17ae 810 return NULL;
a80beece
DS
811}
812
718e3744 813/* Print if_addr structure. */
d62a17ae 814static void __attribute__((unused))
815connected_log(struct connected *connected, char *str)
718e3744 816{
d62a17ae 817 struct prefix *p;
818 struct interface *ifp;
819 char logbuf[BUFSIZ];
820 char buf[BUFSIZ];
821
822 ifp = connected->ifp;
823 p = connected->address;
824
825 snprintf(logbuf, BUFSIZ, "%s interface %s vrf %u %s %s/%d ", str,
826 ifp->name, ifp->vrf_id, prefix_family_str(p),
827 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ), p->prefixlen);
828
829 p = connected->destination;
830 if (p) {
831 strncat(logbuf, inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
832 BUFSIZ - strlen(logbuf));
833 }
834 zlog_info("%s", logbuf);
718e3744 835}
836
a80beece 837/* Print if_addr structure. */
d62a17ae 838static void __attribute__((unused))
839nbr_connected_log(struct nbr_connected *connected, char *str)
a80beece 840{
d62a17ae 841 struct prefix *p;
842 struct interface *ifp;
843 char logbuf[BUFSIZ];
844 char buf[BUFSIZ];
a80beece 845
d62a17ae 846 ifp = connected->ifp;
847 p = connected->address;
a80beece 848
d62a17ae 849 snprintf(logbuf, BUFSIZ, "%s interface %s %s %s/%d ", str, ifp->name,
850 prefix_family_str(p),
851 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ), p->prefixlen);
a80beece 852
d62a17ae 853 zlog_info("%s", logbuf);
a80beece
DS
854}
855
718e3744 856/* If two connected address has same prefix return 1. */
d62a17ae 857static int connected_same_prefix(struct prefix *p1, struct prefix *p2)
718e3744 858{
d62a17ae 859 if (p1->family == p2->family) {
860 if (p1->family == AF_INET
861 && IPV4_ADDR_SAME(&p1->u.prefix4, &p2->u.prefix4))
862 return 1;
863 if (p1->family == AF_INET6
864 && IPV6_ADDR_SAME(&p1->u.prefix6, &p2->u.prefix6))
865 return 1;
866 }
867 return 0;
718e3744 868}
869
d62a17ae 870struct connected *connected_lookup_prefix_exact(struct interface *ifp,
871 struct prefix *p)
38485402 872{
d62a17ae 873 struct listnode *node;
874 struct listnode *next;
875 struct connected *ifc;
38485402 876
d62a17ae 877 for (node = listhead(ifp->connected); node; node = next) {
878 ifc = listgetdata(node);
879 next = node->next;
38485402 880
d62a17ae 881 if (connected_same_prefix(ifc->address, p))
882 return ifc;
883 }
884 return NULL;
38485402
DS
885}
886
d62a17ae 887struct connected *connected_delete_by_prefix(struct interface *ifp,
888 struct prefix *p)
718e3744 889{
d62a17ae 890 struct listnode *node;
891 struct listnode *next;
892 struct connected *ifc;
893
894 /* In case of same prefix come, replace it with new one. */
895 for (node = listhead(ifp->connected); node; node = next) {
896 ifc = listgetdata(node);
897 next = node->next;
898
899 if (connected_same_prefix(ifc->address, p)) {
900 listnode_delete(ifp->connected, ifc);
901 return ifc;
902 }
718e3744 903 }
d62a17ae 904 return NULL;
718e3744 905}
906
bd40c341 907/* Find the address on our side that will be used when packets
727d104b 908 are sent to dst. */
d62a17ae 909struct connected *connected_lookup_prefix(struct interface *ifp,
910 struct prefix *addr)
727d104b 911{
d62a17ae 912 struct listnode *cnode;
913 struct connected *c;
914 struct connected *match;
915
916 match = NULL;
917
918 for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
919 if (c->address && (c->address->family == addr->family)
920 && prefix_match(CONNECTED_PREFIX(c), addr)
921 && (!match
922 || (c->address->prefixlen > match->address->prefixlen)))
923 match = c;
924 }
925 return match;
727d104b 926}
927
d62a17ae 928struct connected *connected_add_by_prefix(struct interface *ifp,
929 struct prefix *p,
930 struct prefix *destination)
4a7aac1b 931{
d62a17ae 932 struct connected *ifc;
4a7aac1b 933
d62a17ae 934 /* Allocate new connected address. */
935 ifc = connected_new();
936 ifc->ifp = ifp;
4a7aac1b 937
d62a17ae 938 /* Fetch interface address */
939 ifc->address = prefix_new();
940 memcpy(ifc->address, p, sizeof(struct prefix));
4a7aac1b 941
d62a17ae 942 /* Fetch dest address */
943 if (destination) {
944 ifc->destination = prefix_new();
945 memcpy(ifc->destination, destination, sizeof(struct prefix));
946 }
4a7aac1b 947
d62a17ae 948 /* Add connected address to the interface. */
949 listnode_add(ifp->connected, ifc);
950 return ifc;
4a7aac1b 951}
952
d62a17ae 953#if 0 /* this route_table of struct connected's is unused \
954 * however, it would be good to use a route_table rather than \
955 * a list.. \
956 */
718e3744 957/* Interface looking up by interface's address. */
718e3744 958/* Interface's IPv4 address reverse lookup table. */
959struct route_table *ifaddr_ipv4_table;
960/* struct route_table *ifaddr_ipv6_table; */
961
8cc4198f 962static void
718e3744 963ifaddr_ipv4_add (struct in_addr *ifaddr, struct interface *ifp)
964{
965 struct route_node *rn;
966 struct prefix_ipv4 p;
967
968 p.family = AF_INET;
969 p.prefixlen = IPV4_MAX_PREFIXLEN;
970 p.prefix = *ifaddr;
971
972 rn = route_node_get (ifaddr_ipv4_table, (struct prefix *) &p);
973 if (rn)
974 {
975 route_unlock_node (rn);
976 zlog_info ("ifaddr_ipv4_add(): address %s is already added",
977 inet_ntoa (*ifaddr));
978 return;
979 }
980 rn->info = ifp;
981}
982
8cc4198f 983static void
718e3744 984ifaddr_ipv4_delete (struct in_addr *ifaddr, struct interface *ifp)
985{
986 struct route_node *rn;
987 struct prefix_ipv4 p;
988
989 p.family = AF_INET;
990 p.prefixlen = IPV4_MAX_PREFIXLEN;
991 p.prefix = *ifaddr;
992
993 rn = route_node_lookup (ifaddr_ipv4_table, (struct prefix *) &p);
994 if (! rn)
995 {
996 zlog_info ("ifaddr_ipv4_delete(): can't find address %s",
997 inet_ntoa (*ifaddr));
998 return;
999 }
1000 rn->info = NULL;
1001 route_unlock_node (rn);
1002 route_unlock_node (rn);
1003}
1004
1005/* Lookup interface by interface's IP address or interface index. */
8cc4198f 1006static struct interface *
b892f1dd 1007ifaddr_ipv4_lookup (struct in_addr *addr, ifindex_t ifindex)
718e3744 1008{
1009 struct prefix_ipv4 p;
1010 struct route_node *rn;
1011 struct interface *ifp;
718e3744 1012
1013 if (addr)
1014 {
1015 p.family = AF_INET;
1016 p.prefixlen = IPV4_MAX_PREFIXLEN;
1017 p.prefix = *addr;
1018
1019 rn = route_node_lookup (ifaddr_ipv4_table, (struct prefix *) &p);
1020 if (! rn)
1021 return NULL;
1022
1023 ifp = rn->info;
1024 route_unlock_node (rn);
1025 return ifp;
1026 }
1027 else
7e2b7603 1028 return if_lookup_by_index(ifindex, VRF_DEFAULT);
718e3744 1029}
8cc4198f 1030#endif /* ifaddr_ipv4_table */
718e3744 1031
1032/* Initialize interface list. */
d62a17ae 1033void if_init(struct list **intf_list)
718e3744 1034{
d62a17ae 1035 *intf_list = list_new();
8cc4198f 1036#if 0
718e3744 1037 ifaddr_ipv4_table = route_table_init ();
8cc4198f 1038#endif /* ifaddr_ipv4_table */
718e3744 1039
d62a17ae 1040 (*intf_list)->cmp = (int (*)(void *, void *))if_cmp_func;
718e3744 1041}
4bd045d5 1042
d62a17ae 1043void if_terminate(struct list **intf_list)
4bd045d5 1044{
d62a17ae 1045 for (;;) {
1046 struct interface *ifp;
4bd045d5 1047
d62a17ae 1048 ifp = listnode_head(*intf_list);
1049 if (ifp == NULL)
1050 break;
4bd045d5 1051
d62a17ae 1052 if (ifp->node) {
1053 ifp->node->info = NULL;
1054 route_unlock_node(ifp->node);
1055 }
3f6d6a5d 1056
d62a17ae 1057 if_delete(ifp);
1058 }
4bd045d5 1059
affe9e99 1060 list_delete_and_null(intf_list);
4bd045d5 1061}
8ccc7e80 1062
d62a17ae 1063const char *if_link_type_str(enum zebra_link_type llt)
8ccc7e80 1064{
d62a17ae 1065 switch (llt) {
8ccc7e80 1066#define llts(T,S) case (T): return (S)
d62a17ae 1067 llts(ZEBRA_LLT_UNKNOWN, "Unknown");
1068 llts(ZEBRA_LLT_ETHER, "Ethernet");
1069 llts(ZEBRA_LLT_EETHER, "Experimental Ethernet");
1070 llts(ZEBRA_LLT_AX25, "AX.25 Level 2");
1071 llts(ZEBRA_LLT_PRONET, "PROnet token ring");
1072 llts(ZEBRA_LLT_IEEE802, "IEEE 802.2 Ethernet/TR/TB");
1073 llts(ZEBRA_LLT_ARCNET, "ARCnet");
1074 llts(ZEBRA_LLT_APPLETLK, "AppleTalk");
1075 llts(ZEBRA_LLT_DLCI, "Frame Relay DLCI");
1076 llts(ZEBRA_LLT_ATM, "ATM");
1077 llts(ZEBRA_LLT_METRICOM, "Metricom STRIP");
1078 llts(ZEBRA_LLT_IEEE1394, "IEEE 1394 IPv4");
1079 llts(ZEBRA_LLT_EUI64, "EUI-64");
1080 llts(ZEBRA_LLT_INFINIBAND, "InfiniBand");
1081 llts(ZEBRA_LLT_SLIP, "SLIP");
1082 llts(ZEBRA_LLT_CSLIP, "Compressed SLIP");
1083 llts(ZEBRA_LLT_SLIP6, "SLIPv6");
1084 llts(ZEBRA_LLT_CSLIP6, "Compressed SLIPv6");
1085 llts(ZEBRA_LLT_ROSE, "ROSE packet radio");
1086 llts(ZEBRA_LLT_X25, "CCITT X.25");
1087 llts(ZEBRA_LLT_PPP, "PPP");
1088 llts(ZEBRA_LLT_CHDLC, "Cisco HDLC");
1089 llts(ZEBRA_LLT_RAWHDLC, "Raw HDLC");
1090 llts(ZEBRA_LLT_LAPB, "LAPB");
1091 llts(ZEBRA_LLT_IPIP, "IPIP Tunnel");
1092 llts(ZEBRA_LLT_IPIP6, "IPIP6 Tunnel");
1093 llts(ZEBRA_LLT_FRAD, "FRAD");
1094 llts(ZEBRA_LLT_SKIP, "SKIP vif");
1095 llts(ZEBRA_LLT_LOOPBACK, "Loopback");
1096 llts(ZEBRA_LLT_LOCALTLK, "Localtalk");
1097 llts(ZEBRA_LLT_FDDI, "FDDI");
1098 llts(ZEBRA_LLT_SIT, "IPv6-in-IPv4 SIT");
1099 llts(ZEBRA_LLT_IPDDP, "IP-in-DDP tunnel");
1100 llts(ZEBRA_LLT_IPGRE, "GRE over IP");
1101 llts(ZEBRA_LLT_PIMREG, "PIMSM registration");
1102 llts(ZEBRA_LLT_HIPPI, "HiPPI");
1103 llts(ZEBRA_LLT_IRDA, "IrDA");
1104 llts(ZEBRA_LLT_FCPP, "Fibre-Channel PtP");
1105 llts(ZEBRA_LLT_FCAL, "Fibre-Channel Arbitrated Loop");
1106 llts(ZEBRA_LLT_FCPL, "Fibre-Channel Public Loop");
1107 llts(ZEBRA_LLT_FCFABRIC, "Fibre-Channel Fabric");
1108 llts(ZEBRA_LLT_IEEE802_TR, "IEEE 802.2 Token Ring");
1109 llts(ZEBRA_LLT_IEEE80211, "IEEE 802.11");
1110 llts(ZEBRA_LLT_IEEE80211_RADIOTAP, "IEEE 802.11 Radiotap");
1111 llts(ZEBRA_LLT_IEEE802154, "IEEE 802.15.4");
1112 llts(ZEBRA_LLT_IEEE802154_PHY, "IEEE 802.15.4 Phy");
1113 default:
1114 zlog_warn("Unknown value %d", llt);
1115 return "Unknown type!";
8ccc7e80 1116#undef llts
d62a17ae 1117 }
1118 return NULL;
8ccc7e80 1119}
16f1b9ee 1120
d62a17ae 1121struct if_link_params *if_link_params_get(struct interface *ifp)
16f1b9ee 1122{
d62a17ae 1123 int i;
16f1b9ee 1124
d62a17ae 1125 if (ifp->link_params != NULL)
1126 return ifp->link_params;
16f1b9ee 1127
d62a17ae 1128 struct if_link_params *iflp =
1129 XCALLOC(MTYPE_IF_LINK_PARAMS, sizeof(struct if_link_params));
1130 if (iflp == NULL)
1131 return NULL;
16f1b9ee 1132
d62a17ae 1133 /* Set TE metric equal to standard metric */
1134 iflp->te_metric = ifp->metric;
16f1b9ee 1135
d62a17ae 1136 /* Compute default bandwidth based on interface */
1137 iflp->default_bw =
1138 ((ifp->bandwidth ? ifp->bandwidth : DEFAULT_BANDWIDTH)
1139 * TE_KILO_BIT / TE_BYTE);
16f1b9ee 1140
d62a17ae 1141 /* Set Max, Reservable and Unreserved Bandwidth */
1142 iflp->max_bw = iflp->default_bw;
1143 iflp->max_rsv_bw = iflp->default_bw;
1144 for (i = 0; i < MAX_CLASS_TYPE; i++)
1145 iflp->unrsv_bw[i] = iflp->default_bw;
16f1b9ee 1146
d62a17ae 1147 /* Update Link parameters status */
1148 iflp->lp_status =
1149 LP_TE_METRIC | LP_MAX_BW | LP_MAX_RSV_BW | LP_UNRSV_BW;
16f1b9ee 1150
d62a17ae 1151 /* Finally attach newly created Link Parameters */
1152 ifp->link_params = iflp;
16f1b9ee 1153
d62a17ae 1154 return iflp;
16f1b9ee
OD
1155}
1156
d62a17ae 1157void if_link_params_free(struct interface *ifp)
16f1b9ee 1158{
d62a17ae 1159 if (ifp->link_params == NULL)
1160 return;
1161 XFREE(MTYPE_IF_LINK_PARAMS, ifp->link_params);
1162 ifp->link_params = NULL;
16f1b9ee 1163}