]> git.proxmox.com Git - mirror_frr.git/blame - lib/if.c
zebra: display_vrf_name_on_interface
[mirror_frr.git] / lib / if.c
CommitLineData
106d2fd5 1
718e3744 2/*
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"
8736158a 30#include "vrf.h"
718e3744 31#include "if.h"
32#include "sockunion.h"
33#include "prefix.h"
718e3744 34#include "memory.h"
35#include "table.h"
36#include "buffer.h"
37#include "str.h"
38#include "log.h"
6b0655a2 39
8736158a 40/* List of interfaces in only the default VRF */
718e3744 41struct list *iflist;
244c1cdc 42int ptm_enable = 0;
718e3744 43
44/* One for each program. This structure is needed to store hooks. */
45struct if_master
46{
47 int (*if_new_hook) (struct interface *);
48 int (*if_delete_hook) (struct interface *);
8736158a 49} if_master = {0,};
6b0655a2 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
58 */
106d2fd5 59int
60if_cmp_func (struct interface *ifp1, struct interface *ifp2)
61{
62 unsigned int l1, l2;
63 long int x1, x2;
64 char *p1, *p2;
65 int res;
66
67 p1 = ifp1->name;
68 p2 = ifp2->name;
69
90578521 70 while (*p1 && *p2) {
106d2fd5 71 /* look up to any number */
72 l1 = strcspn(p1, "0123456789");
73 l2 = strcspn(p2, "0123456789");
74
75 /* name lengths are different -> compare names */
76 if (l1 != l2)
77 return (strcmp(p1, p2));
78
3a0391a9 79 /* Note that this relies on all numbers being less than all letters, so
80 * that de0 < del0.
81 */
106d2fd5 82 res = strncmp(p1, p2, l1);
83
84 /* names are different -> compare them */
85 if (res)
86 return res;
87
88 /* with identical name part, go to numeric part */
106d2fd5 89 p1 += l1;
90 p2 += l1;
91
b06c14f2 92 if (!*p1)
93 return -1;
94 if (!*p2)
95 return 1;
96
106d2fd5 97 x1 = strtol(p1, &p1, 10);
98 x2 = strtol(p2, &p2, 10);
99
100 /* let's compare numbers now */
101 if (x1 < x2)
102 return -1;
103 if (x1 > x2)
104 return 1;
105
106 /* numbers were equal, lets do it again..
107 (it happens with name like "eth123.456:789") */
108 }
90578521 109 if (*p1)
110 return 1;
111 if (*p2)
112 return -1;
113 return 0;
106d2fd5 114}
115
718e3744 116/* Create new interface structure. */
718e3744 117struct interface *
8736158a 118if_create_vrf (const char *name, int namelen, vrf_id_t vrf_id)
718e3744 119{
120 struct interface *ifp;
8736158a 121 struct list *intf_list = vrf_iflist_get (vrf_id);
718e3744 122
d2fc8896 123 ifp = XCALLOC (MTYPE_IF, sizeof (struct interface));
124 ifp->ifindex = IFINDEX_INTERNAL;
718e3744 125
106d2fd5 126 assert (name);
d2fc8896 127 assert (namelen <= INTERFACE_NAMSIZ); /* Need space for '\0' at end. */
106d2fd5 128 strncpy (ifp->name, name, namelen);
d2fc8896 129 ifp->name[namelen] = '\0';
8736158a
FL
130 ifp->vrf_id = vrf_id;
131 if (if_lookup_by_name_vrf (ifp->name, vrf_id) == NULL)
132 listnode_add_sort (intf_list, ifp);
d2fc8896 133 else
134 zlog_err("if_create(%s): corruption detected -- interface with this "
8736158a 135 "name exists already in VRF %u!", ifp->name, vrf_id);
718e3744 136 ifp->connected = list_new ();
137 ifp->connected->del = (void (*) (void *)) connected_free;
138
a80beece
DS
139 ifp->nbr_connected = list_new ();
140 ifp->nbr_connected->del = (void (*) (void *)) nbr_connected_free;
141
c9506a0a
DS
142 /* Enable Link-detection by default */
143 SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
144
718e3744 145 if (if_master.if_new_hook)
146 (*if_master.if_new_hook) (ifp);
147
148 return ifp;
149}
150
8736158a
FL
151struct interface *
152if_create (const char *name, int namelen)
153{
154 return if_create_vrf (name, namelen, VRF_DEFAULT);
155}
156
f93e3f69
DS
157/* Create new interface structure. */
158void
159if_update_vrf (struct interface *ifp, const char *name, int namelen, vrf_id_t vrf_id)
160{
161 struct list *intf_list = vrf_iflist_get (vrf_id);
162
163 /* remove interface from old master vrf list */
164 if (vrf_iflist (ifp->vrf_id))
165 listnode_delete (vrf_iflist (ifp->vrf_id), ifp);
166
167 assert (name);
168 assert (namelen <= INTERFACE_NAMSIZ); /* Need space for '\0' at end. */
169 strncpy (ifp->name, name, namelen);
170 ifp->name[namelen] = '\0';
171 ifp->vrf_id = vrf_id;
172 if (if_lookup_by_name_vrf (ifp->name, vrf_id) == NULL)
173 listnode_add_sort (intf_list, ifp);
174 else
175 zlog_err("if_create(%s): corruption detected -- interface with this "
176 "name exists already in VRF %u!", ifp->name, vrf_id);
177
178 return;
179}
180
181
d2fc8896 182/* Delete interface structure. */
718e3744 183void
d2fc8896 184if_delete_retain (struct interface *ifp)
718e3744 185{
718e3744 186 if (if_master.if_delete_hook)
187 (*if_master.if_delete_hook) (ifp);
188
189 /* Free connected address list */
2dd04c5d 190 list_delete_all_node (ifp->connected);
a80beece
DS
191
192 /* Free connected nbr address list */
193 list_delete_all_node (ifp->nbr_connected);
d2fc8896 194}
195
196/* Delete and free interface structure. */
197void
198if_delete (struct interface *ifp)
199{
8736158a 200 listnode_delete (vrf_iflist (ifp->vrf_id), ifp);
d2fc8896 201
202 if_delete_retain(ifp);
718e3744 203
2dd04c5d 204 list_free (ifp->connected);
a80beece 205 list_free (ifp->nbr_connected);
2dd04c5d 206
718e3744 207 XFREE (MTYPE_IF, ifp);
208}
209
210/* Add hook to interface master. */
211void
212if_add_hook (int type, int (*func)(struct interface *ifp))
213{
214 switch (type) {
215 case IF_NEW_HOOK:
216 if_master.if_new_hook = func;
217 break;
218 case IF_DELETE_HOOK:
219 if_master.if_delete_hook = func;
220 break;
221 default:
222 break;
223 }
224}
225
226/* Interface existance check by index. */
227struct interface *
8736158a 228if_lookup_by_index_vrf (unsigned int index, vrf_id_t vrf_id)
718e3744 229{
52dc7ee6 230 struct listnode *node;
718e3744 231 struct interface *ifp;
232
8736158a 233 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
718e3744 234 {
718e3744 235 if (ifp->ifindex == index)
236 return ifp;
237 }
238 return NULL;
239}
240
8736158a
FL
241struct interface *
242if_lookup_by_index (unsigned int index)
243{
244 return if_lookup_by_index_vrf (index, VRF_DEFAULT);
245}
246
8cc4198f 247const char *
8736158a 248ifindex2ifname_vrf (unsigned int index, vrf_id_t vrf_id)
718e3744 249{
718e3744 250 struct interface *ifp;
251
8736158a 252 return ((ifp = if_lookup_by_index_vrf (index, vrf_id)) != NULL) ?
8cc4198f 253 ifp->name : "unknown";
d2fc8896 254}
255
8736158a
FL
256const char *
257ifindex2ifname (unsigned int index)
258{
259 return ifindex2ifname_vrf (index, VRF_DEFAULT);
260}
261
d2fc8896 262unsigned int
8736158a 263ifname2ifindex_vrf (const char *name, vrf_id_t vrf_id)
d2fc8896 264{
265 struct interface *ifp;
266
8736158a 267 return ((ifp = if_lookup_by_name_vrf (name, vrf_id)) != NULL) ? ifp->ifindex
3e4ee959 268 : IFINDEX_INTERNAL;
718e3744 269}
270
8736158a
FL
271unsigned int
272ifname2ifindex (const char *name)
273{
274 return ifname2ifindex_vrf (name, VRF_DEFAULT);
275}
276
718e3744 277/* Interface existance check by interface name. */
278struct interface *
8736158a 279if_lookup_by_name_vrf (const char *name, vrf_id_t vrf_id)
718e3744 280{
52dc7ee6 281 struct listnode *node;
718e3744 282 struct interface *ifp;
3e4ee959
PJ
283
284 if (name)
8736158a 285 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
3e4ee959
PJ
286 {
287 if (strcmp(name, ifp->name) == 0)
288 return ifp;
289 }
718e3744 290 return NULL;
291}
292
a349198f 293struct interface *
8736158a
FL
294if_lookup_by_name (const char *name)
295{
296 return if_lookup_by_name_vrf (name, VRF_DEFAULT);
297}
298
299struct interface *
300if_lookup_by_name_len_vrf (const char *name, size_t namelen, vrf_id_t vrf_id)
a349198f 301{
302 struct listnode *node;
1eb8ef25 303 struct interface *ifp;
a349198f 304
305 if (namelen > INTERFACE_NAMSIZ)
306 return NULL;
307
8736158a 308 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
a349198f 309 {
a349198f 310 if (!memcmp(name, ifp->name, namelen) && (ifp->name[namelen] == '\0'))
311 return ifp;
312 }
313 return NULL;
314}
315
8736158a
FL
316struct interface *
317if_lookup_by_name_len(const char *name, size_t namelen)
318{
319 return if_lookup_by_name_len_vrf (name, namelen, VRF_DEFAULT);
320}
321
718e3744 322/* Lookup interface by IPv4 address. */
323struct interface *
8736158a 324if_lookup_exact_address_vrf (void *src, int family, vrf_id_t vrf_id)
718e3744 325{
52dc7ee6 326 struct listnode *node;
327 struct listnode *cnode;
718e3744 328 struct interface *ifp;
329 struct prefix *p;
330 struct connected *c;
331
8736158a 332 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
718e3744 333 {
1eb8ef25 334 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
718e3744 335 {
718e3744 336 p = c->address;
337
0aabccc0 338 if (p && (p->family == family))
718e3744 339 {
0aabccc0
DD
340 if (family == AF_INET)
341 {
342 if (IPV4_ADDR_SAME (&p->u.prefix4, (struct in_addr *)src))
343 return ifp;
344 }
345 else if (family == AF_INET6)
346 {
347 if (IPV6_ADDR_SAME (&p->u.prefix4, (struct in6_addr *)src))
348 return ifp;
349 }
350 }
718e3744 351 }
352 }
353 return NULL;
354}
355
8736158a
FL
356struct interface *
357if_lookup_exact_address (void *src, int family)
358{
359 return if_lookup_exact_address_vrf (src, family, VRF_DEFAULT);
360}
361
718e3744 362/* Lookup interface by IPv4 address. */
363struct interface *
8736158a 364if_lookup_address_vrf (void *matchaddr, int family, vrf_id_t vrf_id)
718e3744 365{
52dc7ee6 366 struct listnode *node;
718e3744 367 struct prefix addr;
3fb9cd6e 368 int bestlen = 0;
52dc7ee6 369 struct listnode *cnode;
718e3744 370 struct interface *ifp;
718e3744 371 struct connected *c;
372 struct interface *match;
373
0aabccc0
DD
374 if (family == AF_INET)
375 {
376 addr.family = AF_INET;
377 addr.u.prefix4 = *((struct in_addr *)matchaddr);
378 addr.prefixlen = IPV4_MAX_BITLEN;
379 }
380 else if (family == AF_INET6)
381 {
382 addr.family = AF_INET6;
383 addr.u.prefix6 = *((struct in6_addr *)matchaddr);
384 addr.prefixlen = IPV6_MAX_BITLEN;
385 }
718e3744 386
387 match = NULL;
388
8736158a 389 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
718e3744 390 {
1eb8ef25 391 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
718e3744 392 {
e4529636
AS
393 if (c->address && (c->address->family == AF_INET) &&
394 prefix_match(CONNECTED_PREFIX(c), &addr) &&
395 (c->address->prefixlen > bestlen))
718e3744 396 {
e4529636
AS
397 bestlen = c->address->prefixlen;
398 match = ifp;
718e3744 399 }
400 }
401 }
402 return match;
403}
404
8736158a
FL
405struct interface *
406if_lookup_address (void *matchaddr, int family)
407{
408 return if_lookup_address_vrf (matchaddr, family, VRF_DEFAULT);
409}
410
b81e97a8
DD
411/* Lookup interface by prefix */
412struct interface *
8736158a 413if_lookup_prefix_vrf (struct prefix *prefix, vrf_id_t vrf_id)
b81e97a8
DD
414{
415 struct listnode *node;
b81e97a8
DD
416 struct listnode *cnode;
417 struct interface *ifp;
418 struct connected *c;
419
8736158a 420 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
b81e97a8
DD
421 {
422 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
423 {
424 if (prefix_cmp(c->address, prefix) == 0)
425 {
426 return ifp;
427 }
428 }
429 }
430 return NULL;
431}
432
8736158a
FL
433struct interface *
434if_lookup_prefix (struct prefix *prefix)
435{
436 return if_lookup_prefix_vrf (prefix, VRF_DEFAULT);
437}
438
718e3744 439/* Get interface by name if given name interface doesn't exist create
440 one. */
441struct interface *
8736158a 442if_get_by_name_vrf (const char *name, vrf_id_t vrf_id)
718e3744 443{
444 struct interface *ifp;
445
8736158a
FL
446 return ((ifp = if_lookup_by_name_vrf (name, vrf_id)) != NULL) ? ifp :
447 if_create_vrf (name, strlen(name), vrf_id);
a349198f 448}
449
450struct interface *
8736158a
FL
451if_get_by_name (const char *name)
452{
453 return if_get_by_name_vrf (name, VRF_DEFAULT);
454}
455
456struct interface *
457if_get_by_name_len_vrf (const char *name, size_t namelen, vrf_id_t vrf_id)
a349198f 458{
459 struct interface *ifp;
460
8736158a
FL
461 return ((ifp = if_lookup_by_name_len_vrf (name, namelen, vrf_id)) != NULL) ? \
462 ifp : if_create_vrf (name, namelen, vrf_id);
463}
464
465struct interface *
466if_get_by_name_len (const char *name, size_t namelen)
467{
468 return if_get_by_name_len_vrf (name, namelen, VRF_DEFAULT);
718e3744 469}
470
471/* Does interface up ? */
472int
473if_is_up (struct interface *ifp)
474{
475 return ifp->flags & IFF_UP;
476}
477
2e3b2e47 478/* Is interface running? */
479int
480if_is_running (struct interface *ifp)
481{
482 return ifp->flags & IFF_RUNNING;
483}
484
485/* Is the interface operative, eg. either UP & RUNNING
244c1cdc
DS
486 or UP & !ZEBRA_INTERFACE_LINK_DETECTION and
487 if ptm checking is enabled, then ptm check has passed */
2e3b2e47 488int
489if_is_operative (struct interface *ifp)
490{
491 return ((ifp->flags & IFF_UP) &&
244c1cdc
DS
492 (((ifp->flags & IFF_RUNNING) &&
493 (ifp->ptm_status || !ifp->ptm_enable)) ||
494 !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)));
495}
496
497/* Is the interface operative, eg. either UP & RUNNING
498 or UP & !ZEBRA_INTERFACE_LINK_DETECTION, without PTM check */
499int
500if_is_no_ptm_operative (struct interface *ifp)
501{
502 return ((ifp->flags & IFF_UP) &&
503 ((ifp->flags & IFF_RUNNING) ||
504 !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)));
2e3b2e47 505}
506
718e3744 507/* Is this loopback interface ? */
508int
509if_is_loopback (struct interface *ifp)
510{
4ba9b924 511 /* XXX: Do this better, eg what if IFF_WHATEVER means X on platform M
512 * but Y on platform N?
513 */
514 return (ifp->flags & (IFF_LOOPBACK|IFF_NOXMIT|IFF_VIRTUAL));
718e3744 515}
516
517/* Does this interface support broadcast ? */
518int
519if_is_broadcast (struct interface *ifp)
520{
521 return ifp->flags & IFF_BROADCAST;
522}
523
524/* Does this interface support broadcast ? */
525int
526if_is_pointopoint (struct interface *ifp)
527{
528 return ifp->flags & IFF_POINTOPOINT;
529}
530
531/* Does this interface support multicast ? */
532int
533if_is_multicast (struct interface *ifp)
534{
535 return ifp->flags & IFF_MULTICAST;
536}
537
538/* Printout flag information into log */
539const char *
540if_flag_dump (unsigned long flag)
541{
542 int separator = 0;
543 static char logbuf[BUFSIZ];
544
545#define IFF_OUT_LOG(X,STR) \
4ba9b924 546 if (flag & (X)) \
718e3744 547 { \
548 if (separator) \
549 strlcat (logbuf, ",", BUFSIZ); \
550 else \
551 separator = 1; \
552 strlcat (logbuf, STR, BUFSIZ); \
553 }
554
630c97ce 555 strlcpy (logbuf, "<", BUFSIZ);
718e3744 556 IFF_OUT_LOG (IFF_UP, "UP");
557 IFF_OUT_LOG (IFF_BROADCAST, "BROADCAST");
558 IFF_OUT_LOG (IFF_DEBUG, "DEBUG");
559 IFF_OUT_LOG (IFF_LOOPBACK, "LOOPBACK");
560 IFF_OUT_LOG (IFF_POINTOPOINT, "POINTOPOINT");
561 IFF_OUT_LOG (IFF_NOTRAILERS, "NOTRAILERS");
562 IFF_OUT_LOG (IFF_RUNNING, "RUNNING");
563 IFF_OUT_LOG (IFF_NOARP, "NOARP");
564 IFF_OUT_LOG (IFF_PROMISC, "PROMISC");
565 IFF_OUT_LOG (IFF_ALLMULTI, "ALLMULTI");
566 IFF_OUT_LOG (IFF_OACTIVE, "OACTIVE");
567 IFF_OUT_LOG (IFF_SIMPLEX, "SIMPLEX");
568 IFF_OUT_LOG (IFF_LINK0, "LINK0");
569 IFF_OUT_LOG (IFF_LINK1, "LINK1");
570 IFF_OUT_LOG (IFF_LINK2, "LINK2");
571 IFF_OUT_LOG (IFF_MULTICAST, "MULTICAST");
4ba9b924 572 IFF_OUT_LOG (IFF_NOXMIT, "NOXMIT");
573 IFF_OUT_LOG (IFF_NORTEXCH, "NORTEXCH");
574 IFF_OUT_LOG (IFF_VIRTUAL, "VIRTUAL");
575 IFF_OUT_LOG (IFF_IPV4, "IPv4");
576 IFF_OUT_LOG (IFF_IPV6, "IPv6");
718e3744 577
578 strlcat (logbuf, ">", BUFSIZ);
579
580 return logbuf;
630c97ce 581#undef IFF_OUT_LOG
718e3744 582}
583
584/* For debugging */
8cc4198f 585static void
cedd7f2f 586if_dump (const struct interface *ifp)
718e3744 587{
3968dbf8 588 zlog_info ("Interface %s vrf %u index %d metric %d mtu %d "
4a7aac1b 589#ifdef HAVE_IPV6
23be94ea 590 "mtu6 %d "
4a7aac1b 591#endif /* HAVE_IPV6 */
23be94ea 592 "%s",
3968dbf8 593 ifp->name, ifp->vrf_id, ifp->ifindex, ifp->metric, ifp->mtu,
4a7aac1b 594#ifdef HAVE_IPV6
23be94ea 595 ifp->mtu6,
4a7aac1b 596#endif /* HAVE_IPV6 */
23be94ea 597 if_flag_dump (ifp->flags));
718e3744 598}
599
600/* Interface printing for all interface. */
601void
66e5cd87 602if_dump_all (void)
718e3744 603{
8736158a 604 struct list *intf_list;
52dc7ee6 605 struct listnode *node;
1eb8ef25 606 void *p;
8736158a 607 vrf_iter_t iter;
718e3744 608
8736158a
FL
609 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
610 if ((intf_list = vrf_iter2iflist (iter)) != NULL)
611 for (ALL_LIST_ELEMENTS_RO (intf_list, node, p))
612 if_dump (p);
718e3744 613}
614
615DEFUN (interface_desc,
616 interface_desc_cmd,
617 "description .LINE",
618 "Interface specific description\n"
619 "Characters describing this interface\n")
620{
718e3744 621 struct interface *ifp;
718e3744 622
623 if (argc == 0)
624 return CMD_SUCCESS;
625
626 ifp = vty->index;
627 if (ifp->desc)
3b8b1855 628 XFREE (MTYPE_TMP, ifp->desc);
629 ifp->desc = argv_concat(argv, argc, 0);
718e3744 630
631 return CMD_SUCCESS;
632}
633
634DEFUN (no_interface_desc,
635 no_interface_desc_cmd,
636 "no description",
637 NO_STR
638 "Interface specific description\n")
639{
640 struct interface *ifp;
641
642 ifp = vty->index;
643 if (ifp->desc)
0241684e 644 XFREE (MTYPE_TMP, ifp->desc);
718e3744 645 ifp->desc = NULL;
646
647 return CMD_SUCCESS;
648}
6b0655a2 649
98954844
PJ
650#ifdef SUNOS_5
651/* Need to handle upgrade from SUNWzebra to Quagga. SUNWzebra created
652 * a seperate struct interface for each logical interface, so config
653 * file may be full of 'interface fooX:Y'. Solaris however does not
654 * expose logical interfaces via PF_ROUTE, so trying to track logical
655 * interfaces can be fruitless, for that reason Quagga only tracks
656 * the primary IP interface.
657 *
658 * We try accomodate SUNWzebra by:
659 * - looking up the interface name, to see whether it exists, if so
660 * its useable
661 * - for protocol daemons, this could only because zebra told us of
662 * the interface
663 * - for zebra, only because it learnt from kernel
664 * - if not:
665 * - search the name to see if it contains a sub-ipif / logical interface
666 * seperator, the ':' char. If it does:
667 * - text up to that char must be the primary name - get that name.
668 * if not:
669 * - no idea, just get the name in its entirety.
670 */
671static struct interface *
8736158a 672if_sunwzebra_get (const char *name, size_t nlen, vrf_id_t vrf_id)
98954844
PJ
673{
674 struct interface *ifp;
675 size_t seppos = 0;
718e3744 676
8736158a 677 if ( (ifp = if_lookup_by_name_len_vrf (name, nlen, vrf_id)) != NULL)
98954844
PJ
678 return ifp;
679
680 /* hunt the primary interface name... */
681 while (seppos < nlen && name[seppos] != ':')
682 seppos++;
683
684 /* Wont catch seperator as last char, e.g. 'foo0:' but thats invalid */
685 if (seppos < nlen)
8736158a 686 return if_get_by_name_len_vrf (name, seppos, vrf_id);
98954844 687 else
8736158a 688 return if_get_by_name_len_vrf (name, nlen, vrf_id);
98954844
PJ
689}
690#endif /* SUNOS_5 */
6b0655a2 691
718e3744 692DEFUN (interface,
693 interface_cmd,
694 "interface IFNAME",
695 "Select an interface to configure\n"
696 "Interface's name\n")
697{
698 struct interface *ifp;
d2fc8896 699 size_t sl;
8736158a 700 vrf_id_t vrf_id = VRF_DEFAULT;
d2fc8896 701
702 if ((sl = strlen(argv[0])) > INTERFACE_NAMSIZ)
703 {
704 vty_out (vty, "%% Interface name %s is invalid: length exceeds "
705 "%d characters%s",
706 argv[0], INTERFACE_NAMSIZ, VTY_NEWLINE);
707 return CMD_WARNING;
708 }
718e3744 709
f93e3f69
DS
710/*Pending: need proper vrf name based lookup/(possible creation of VRF)
711 Imagine forward reference of a vrf by name in this interface config */
cd2a8a42 712 if (argc > 1)
f93e3f69 713 VRF_GET_ID (vrf_id, argv[1]);
cd2a8a42 714
98954844 715#ifdef SUNOS_5
8736158a 716 ifp = if_sunwzebra_get (argv[0], sl, vrf_id);
98954844 717#else
8736158a 718 ifp = if_get_by_name_len_vrf (argv[0], sl, vrf_id);
98954844 719#endif /* SUNOS_5 */
718e3744 720
718e3744 721 vty->index = ifp;
722 vty->node = INTERFACE_NODE;
723
724 return CMD_SUCCESS;
725}
726
cd2a8a42
FL
727ALIAS (interface,
728 interface_vrf_cmd,
729 "interface IFNAME " VRF_CMD_STR,
730 "Select an interface to configure\n"
731 "Interface's name\n"
732 VRF_CMD_HELP_STR)
733
32d2463c 734DEFUN_NOSH (no_interface,
735 no_interface_cmd,
736 "no interface IFNAME",
737 NO_STR
738 "Delete a pseudo interface's configuration\n"
739 "Interface's name\n")
740{
741 // deleting interface
742 struct interface *ifp;
8736158a 743 vrf_id_t vrf_id = VRF_DEFAULT;
32d2463c 744
cd2a8a42 745 if (argc > 1)
f93e3f69 746 VRF_GET_ID (vrf_id, argv[1]);
cd2a8a42 747
8736158a 748 ifp = if_lookup_by_name_vrf (argv[0], vrf_id);
32d2463c 749
750 if (ifp == NULL)
d2fc8896 751 {
752 vty_out (vty, "%% Interface %s does not exist%s", argv[0], VTY_NEWLINE);
753 return CMD_WARNING;
754 }
32d2463c 755
bfc13532 756 if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
d2fc8896 757 {
758 vty_out (vty, "%% Only inactive interfaces can be deleted%s",
759 VTY_NEWLINE);
760 return CMD_WARNING;
761 }
32d2463c 762
763 if_delete(ifp);
764
765 return CMD_SUCCESS;
766}
767
cd2a8a42
FL
768ALIAS (no_interface,
769 no_interface_vrf_cmd,
770 "no interface IFNAME " VRF_CMD_STR,
771 NO_STR
772 "Delete a pseudo interface's configuration\n"
773 "Interface's name\n"
774 VRF_CMD_HELP_STR)
775
f93e3f69
DS
776DEFUN (vrf,
777 vrf_cmd,
778 "vrf NAME",
779 "Select a VRF to configure\n"
780 "VRF's name\n")
781{
782 struct vrf *vrfp;
783 size_t sl;
784
785 if ((sl = strlen(argv[0])) > VRF_NAMSIZ)
786 {
787 vty_out (vty, "%% VRF name %s is invalid: length exceeds "
788 "%d characters%s",
789 argv[0], VRF_NAMSIZ, VTY_NEWLINE);
790 return CMD_WARNING;
791 }
792
793 vrfp = vrf_get_by_name_len (argv[0], sl);
794
795 vty->index = vrfp;
796 vty->node = VRF_NODE;
797
798 return CMD_SUCCESS;
799}
800
801DEFUN_NOSH (no_vrf,
802 no_vrf_cmd,
803 "no vrf NAME",
804 NO_STR
805 "Delete a pseudo VRF's configuration\n"
806 "VRF's name\n")
807{
808 struct vrf *vrfp;
809
810 vrfp = vrf_list_lookup_by_name (argv[0]);
811
812 if (vrfp == NULL)
813 {
814 vty_out (vty, "%% VRF %s does not exist%s", argv[0], VTY_NEWLINE);
815 return CMD_WARNING;
816 }
817
818 if (CHECK_FLAG (vrfp->status, ZEBRA_VRF_ACTIVE))
819 {
820 vty_out (vty, "%% Only inactive VRFs can be deleted%s",
821 VTY_NEWLINE);
822 return CMD_WARNING;
823 }
824
825 vrf_delete(vrfp);
826
827 return CMD_SUCCESS;
828}
829
830
718e3744 831/* For debug purpose. */
832DEFUN (show_address,
833 show_address_cmd,
834 "show address",
835 SHOW_STR
836 "address\n")
837{
52dc7ee6 838 struct listnode *node;
839 struct listnode *node2;
718e3744 840 struct interface *ifp;
841 struct connected *ifc;
842 struct prefix *p;
8736158a 843 vrf_id_t vrf_id = VRF_DEFAULT;
718e3744 844
8736158a 845 if (argc > 0)
f93e3f69 846 VRF_GET_ID (vrf_id, argv[0]);
8736158a
FL
847
848 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
718e3744 849 {
1eb8ef25 850 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node2, ifc))
718e3744 851 {
718e3744 852 p = ifc->address;
853
854 if (p->family == AF_INET)
855 vty_out (vty, "%s/%d%s", inet_ntoa (p->u.prefix4), p->prefixlen,
856 VTY_NEWLINE);
857 }
858 }
859 return CMD_SUCCESS;
860}
861
8736158a
FL
862ALIAS (show_address,
863 show_address_vrf_cmd,
864 "show address " VRF_CMD_STR,
865 SHOW_STR
866 "address\n"
867 VRF_CMD_HELP_STR)
868
869DEFUN (show_address_vrf_all,
870 show_address_vrf_all_cmd,
871 "show address " VRF_ALL_CMD_STR,
872 SHOW_STR
873 "address\n"
874 VRF_ALL_CMD_HELP_STR)
875{
876 struct list *intf_list;
877 struct listnode *node;
878 struct listnode *node2;
879 struct interface *ifp;
880 struct connected *ifc;
881 struct prefix *p;
882 vrf_iter_t iter;
883
884 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
885 {
886 intf_list = vrf_iter2iflist (iter);
887 if (!intf_list || !listcount (intf_list))
888 continue;
889
890 vty_out (vty, "%sVRF %u%s%s", VTY_NEWLINE, vrf_iter2id (iter),
891 VTY_NEWLINE, VTY_NEWLINE);
892
893 for (ALL_LIST_ELEMENTS_RO (intf_list, node, ifp))
894 {
895 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node2, ifc))
896 {
897 p = ifc->address;
898
899 if (p->family == AF_INET)
900 vty_out (vty, "%s/%d%s", inet_ntoa (p->u.prefix4), p->prefixlen,
901 VTY_NEWLINE);
902 }
903 }
904 }
905 return CMD_SUCCESS;
906}
907
718e3744 908/* Allocate connected structure. */
909struct connected *
8cc4198f 910connected_new (void)
718e3744 911{
393deb9b 912 return XCALLOC (MTYPE_CONNECTED, sizeof (struct connected));
718e3744 913}
914
a80beece
DS
915/* Allocate nbr connected structure. */
916struct nbr_connected *
917nbr_connected_new (void)
918{
919 return XCALLOC (MTYPE_NBR_CONNECTED, sizeof (struct nbr_connected));
920}
921
718e3744 922/* Free connected structure. */
923void
924connected_free (struct connected *connected)
925{
926 if (connected->address)
927 prefix_free (connected->address);
928
929 if (connected->destination)
930 prefix_free (connected->destination);
931
932 if (connected->label)
9c4f1c6f 933 XFREE (MTYPE_CONNECTED_LABEL, connected->label);
718e3744 934
935 XFREE (MTYPE_CONNECTED, connected);
936}
937
a80beece
DS
938/* Free nbr connected structure. */
939void
940nbr_connected_free (struct nbr_connected *connected)
941{
942 if (connected->address)
943 prefix_free (connected->address);
944
945 XFREE (MTYPE_NBR_CONNECTED, connected);
946}
947
948/* If same interface nbr address already exists... */
949struct nbr_connected *
950nbr_connected_check (struct interface *ifp, struct prefix *p)
951{
952 struct nbr_connected *ifc;
953 struct listnode *node;
954
955 for (ALL_LIST_ELEMENTS_RO (ifp->nbr_connected, node, ifc))
956 if (prefix_same (ifc->address, p))
957 return ifc;
958
959 return NULL;
960}
961
718e3744 962/* Print if_addr structure. */
8cc4198f 963static void __attribute__ ((unused))
718e3744 964connected_log (struct connected *connected, char *str)
965{
966 struct prefix *p;
967 struct interface *ifp;
968 char logbuf[BUFSIZ];
969 char buf[BUFSIZ];
970
971 ifp = connected->ifp;
972 p = connected->address;
973
3968dbf8
FL
974 snprintf (logbuf, BUFSIZ, "%s interface %s vrf %u %s %s/%d ",
975 str, ifp->name, ifp->vrf_id, prefix_family_str (p),
718e3744 976 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
977 p->prefixlen);
978
979 p = connected->destination;
980 if (p)
981 {
982 strncat (logbuf, inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
983 BUFSIZ - strlen(logbuf));
984 }
fc95186c 985 zlog (NULL, LOG_INFO, "%s", logbuf);
718e3744 986}
987
a80beece
DS
988/* Print if_addr structure. */
989static void __attribute__ ((unused))
990nbr_connected_log (struct nbr_connected *connected, char *str)
991{
992 struct prefix *p;
993 struct interface *ifp;
994 char logbuf[BUFSIZ];
995 char buf[BUFSIZ];
996
997 ifp = connected->ifp;
998 p = connected->address;
999
1000 snprintf (logbuf, BUFSIZ, "%s interface %s %s %s/%d ",
1001 str, ifp->name, prefix_family_str (p),
1002 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
1003 p->prefixlen);
1004
1005 zlog (NULL, LOG_INFO, "%s", logbuf);
1006}
1007
718e3744 1008/* If two connected address has same prefix return 1. */
8cc4198f 1009static int
718e3744 1010connected_same_prefix (struct prefix *p1, struct prefix *p2)
1011{
1012 if (p1->family == p2->family)
1013 {
1014 if (p1->family == AF_INET &&
1015 IPV4_ADDR_SAME (&p1->u.prefix4, &p2->u.prefix4))
1016 return 1;
1017#ifdef HAVE_IPV6
1018 if (p1->family == AF_INET6 &&
1019 IPV6_ADDR_SAME (&p1->u.prefix6, &p2->u.prefix6))
1020 return 1;
1021#endif /* HAVE_IPV6 */
1022 }
1023 return 0;
1024}
1025
1026struct connected *
1027connected_delete_by_prefix (struct interface *ifp, struct prefix *p)
1028{
1029 struct listnode *node;
1030 struct listnode *next;
1031 struct connected *ifc;
1032
1033 /* In case of same prefix come, replace it with new one. */
1034 for (node = listhead (ifp->connected); node; node = next)
1035 {
1eb8ef25 1036 ifc = listgetdata (node);
718e3744 1037 next = node->next;
1038
1039 if (connected_same_prefix (ifc->address, p))
1040 {
1041 listnode_delete (ifp->connected, ifc);
1042 return ifc;
1043 }
1044 }
1045 return NULL;
1046}
1047
727d104b 1048/* Find the IPv4 address on our side that will be used when packets
1049 are sent to dst. */
1050struct connected *
1051connected_lookup_address (struct interface *ifp, struct in_addr dst)
1052{
1053 struct prefix addr;
52dc7ee6 1054 struct listnode *cnode;
727d104b 1055 struct connected *c;
1056 struct connected *match;
1057
727d104b 1058 addr.family = AF_INET;
1059 addr.u.prefix4 = dst;
1060 addr.prefixlen = IPV4_MAX_BITLEN;
1061
1062 match = NULL;
1063
1eb8ef25 1064 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
727d104b 1065 {
e4529636
AS
1066 if (c->address && (c->address->family == AF_INET) &&
1067 prefix_match(CONNECTED_PREFIX(c), &addr) &&
1068 (!match || (c->address->prefixlen > match->address->prefixlen)))
1069 match = c;
727d104b 1070 }
1071 return match;
1072}
1073
4a7aac1b 1074struct connected *
1075connected_add_by_prefix (struct interface *ifp, struct prefix *p,
1076 struct prefix *destination)
1077{
1078 struct connected *ifc;
1079
1080 /* Allocate new connected address. */
1081 ifc = connected_new ();
1082 ifc->ifp = ifp;
1083
1084 /* Fetch interface address */
1085 ifc->address = prefix_new();
1086 memcpy (ifc->address, p, sizeof(struct prefix));
1087
1088 /* Fetch dest address */
3fb9cd6e 1089 if (destination)
1090 {
1091 ifc->destination = prefix_new();
1092 memcpy (ifc->destination, destination, sizeof(struct prefix));
1093 }
4a7aac1b 1094
1095 /* Add connected address to the interface. */
1096 listnode_add (ifp->connected, ifc);
1097 return ifc;
1098}
1099
718e3744 1100#ifndef HAVE_IF_NAMETOINDEX
1101unsigned int
1102if_nametoindex (const char *name)
1103{
718e3744 1104 struct interface *ifp;
1105
018546e9 1106 return ((ifp = if_lookup_by_name_len(name, strnlen(name, IFNAMSIZ))) != NULL)
1107 ? ifp->ifindex : 0;
718e3744 1108}
1109#endif
1110
1111#ifndef HAVE_IF_INDEXTONAME
1112char *
1113if_indextoname (unsigned int ifindex, char *name)
1114{
718e3744 1115 struct interface *ifp;
1116
d2fc8896 1117 if (!(ifp = if_lookup_by_index(ifindex)))
1118 return NULL;
1119 strncpy (name, ifp->name, IFNAMSIZ);
1120 return ifp->name;
718e3744 1121}
1122#endif
6b0655a2 1123
8cc4198f 1124#if 0 /* this route_table of struct connected's is unused
1125 * however, it would be good to use a route_table rather than
1126 * a list..
1127 */
718e3744 1128/* Interface looking up by interface's address. */
718e3744 1129/* Interface's IPv4 address reverse lookup table. */
1130struct route_table *ifaddr_ipv4_table;
1131/* struct route_table *ifaddr_ipv6_table; */
1132
8cc4198f 1133static void
718e3744 1134ifaddr_ipv4_add (struct in_addr *ifaddr, struct interface *ifp)
1135{
1136 struct route_node *rn;
1137 struct prefix_ipv4 p;
1138
1139 p.family = AF_INET;
1140 p.prefixlen = IPV4_MAX_PREFIXLEN;
1141 p.prefix = *ifaddr;
1142
1143 rn = route_node_get (ifaddr_ipv4_table, (struct prefix *) &p);
1144 if (rn)
1145 {
1146 route_unlock_node (rn);
1147 zlog_info ("ifaddr_ipv4_add(): address %s is already added",
1148 inet_ntoa (*ifaddr));
1149 return;
1150 }
1151 rn->info = ifp;
1152}
1153
8cc4198f 1154static void
718e3744 1155ifaddr_ipv4_delete (struct in_addr *ifaddr, struct interface *ifp)
1156{
1157 struct route_node *rn;
1158 struct prefix_ipv4 p;
1159
1160 p.family = AF_INET;
1161 p.prefixlen = IPV4_MAX_PREFIXLEN;
1162 p.prefix = *ifaddr;
1163
1164 rn = route_node_lookup (ifaddr_ipv4_table, (struct prefix *) &p);
1165 if (! rn)
1166 {
1167 zlog_info ("ifaddr_ipv4_delete(): can't find address %s",
1168 inet_ntoa (*ifaddr));
1169 return;
1170 }
1171 rn->info = NULL;
1172 route_unlock_node (rn);
1173 route_unlock_node (rn);
1174}
1175
1176/* Lookup interface by interface's IP address or interface index. */
8cc4198f 1177static struct interface *
718e3744 1178ifaddr_ipv4_lookup (struct in_addr *addr, unsigned int ifindex)
1179{
1180 struct prefix_ipv4 p;
1181 struct route_node *rn;
1182 struct interface *ifp;
718e3744 1183
1184 if (addr)
1185 {
1186 p.family = AF_INET;
1187 p.prefixlen = IPV4_MAX_PREFIXLEN;
1188 p.prefix = *addr;
1189
1190 rn = route_node_lookup (ifaddr_ipv4_table, (struct prefix *) &p);
1191 if (! rn)
1192 return NULL;
1193
1194 ifp = rn->info;
1195 route_unlock_node (rn);
1196 return ifp;
1197 }
1198 else
d2fc8896 1199 return if_lookup_by_index(ifindex);
718e3744 1200}
8cc4198f 1201#endif /* ifaddr_ipv4_table */
718e3744 1202
1203/* Initialize interface list. */
1204void
8736158a 1205if_init (vrf_id_t vrf_id, struct list **intf_list)
718e3744 1206{
8736158a 1207 *intf_list = list_new ();
8cc4198f 1208#if 0
718e3744 1209 ifaddr_ipv4_table = route_table_init ();
8cc4198f 1210#endif /* ifaddr_ipv4_table */
718e3744 1211
8736158a 1212 (*intf_list)->cmp = (int (*)(void *, void *))if_cmp_func;
718e3744 1213
8736158a
FL
1214 if (vrf_id == VRF_DEFAULT)
1215 iflist = *intf_list;
718e3744 1216}
4bd045d5
TG
1217
1218void
8736158a 1219if_terminate (vrf_id_t vrf_id, struct list **intf_list)
4bd045d5
TG
1220{
1221 for (;;)
1222 {
1223 struct interface *ifp;
1224
8736158a 1225 ifp = listnode_head (*intf_list);
4bd045d5
TG
1226 if (ifp == NULL)
1227 break;
1228
1229 if_delete (ifp);
1230 }
1231
8736158a
FL
1232 list_delete (*intf_list);
1233 *intf_list = NULL;
1234
1235 if (vrf_id == VRF_DEFAULT)
1236 iflist = NULL;
4bd045d5 1237}