Annotation of embedaddon/quagga/lib/if.c, revision 1.1.1.3
1.1 misho 1:
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"
1.1.1.3 ! misho 30: #include "vrf.h"
1.1 misho 31: #include "if.h"
32: #include "sockunion.h"
33: #include "prefix.h"
34: #include "memory.h"
35: #include "table.h"
36: #include "buffer.h"
37: #include "str.h"
38: #include "log.h"
1.1.1.3 ! misho 39:
! 40: /* List of interfaces in only the default VRF */
1.1 misho 41: struct list *iflist;
42:
43: /* One for each program. This structure is needed to store hooks. */
44: struct if_master
45: {
46: int (*if_new_hook) (struct interface *);
47: int (*if_delete_hook) (struct interface *);
1.1.1.3 ! misho 48: } if_master = {0,};
! 49:
1.1 misho 50: /* 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: */
58: int
59: if_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:
69: while (*p1 && *p2) {
70: /* 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:
78: /* Note that this relies on all numbers being less than all letters, so
79: * that de0 < del0.
80: */
81: 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 */
88: p1 += l1;
89: p2 += l1;
90:
91: if (!*p1)
92: return -1;
93: if (!*p2)
94: return 1;
95:
96: 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: }
108: if (*p1)
109: return 1;
110: if (*p2)
111: return -1;
112: return 0;
113: }
114:
115: /* Create new interface structure. */
116: struct interface *
1.1.1.3 ! misho 117: if_create_vrf (const char *name, int namelen, vrf_id_t vrf_id)
1.1 misho 118: {
119: struct interface *ifp;
1.1.1.3 ! misho 120: struct list *intf_list = vrf_iflist_get (vrf_id);
1.1 misho 121:
122: ifp = XCALLOC (MTYPE_IF, sizeof (struct interface));
123: ifp->ifindex = IFINDEX_INTERNAL;
124:
125: assert (name);
126: assert (namelen <= INTERFACE_NAMSIZ); /* Need space for '\0' at end. */
127: strncpy (ifp->name, name, namelen);
128: ifp->name[namelen] = '\0';
1.1.1.3 ! misho 129: ifp->vrf_id = vrf_id;
! 130: if (if_lookup_by_name_vrf (ifp->name, vrf_id) == NULL)
! 131: listnode_add_sort (intf_list, ifp);
1.1 misho 132: else
133: zlog_err("if_create(%s): corruption detected -- interface with this "
1.1.1.3 ! misho 134: "name exists already in VRF %u!", ifp->name, vrf_id);
1.1 misho 135: ifp->connected = list_new ();
136: ifp->connected->del = (void (*) (void *)) connected_free;
137:
138: if (if_master.if_new_hook)
139: (*if_master.if_new_hook) (ifp);
140:
141: return ifp;
142: }
143:
1.1.1.3 ! misho 144: struct interface *
! 145: if_create (const char *name, int namelen)
! 146: {
! 147: return if_create_vrf (name, namelen, VRF_DEFAULT);
! 148: }
! 149:
1.1 misho 150: /* Delete interface structure. */
151: void
152: if_delete_retain (struct interface *ifp)
153: {
154: if (if_master.if_delete_hook)
155: (*if_master.if_delete_hook) (ifp);
156:
157: /* Free connected address list */
1.1.1.2 misho 158: list_delete_all_node (ifp->connected);
1.1 misho 159: }
160:
161: /* Delete and free interface structure. */
162: void
163: if_delete (struct interface *ifp)
164: {
1.1.1.3 ! misho 165: listnode_delete (vrf_iflist (ifp->vrf_id), ifp);
1.1 misho 166:
167: if_delete_retain(ifp);
168:
1.1.1.2 misho 169: list_free (ifp->connected);
170:
1.1 misho 171: XFREE (MTYPE_IF, ifp);
172: }
173:
174: /* Add hook to interface master. */
175: void
176: if_add_hook (int type, int (*func)(struct interface *ifp))
177: {
178: switch (type) {
179: case IF_NEW_HOOK:
180: if_master.if_new_hook = func;
181: break;
182: case IF_DELETE_HOOK:
183: if_master.if_delete_hook = func;
184: break;
185: default:
186: break;
187: }
188: }
189:
190: /* Interface existance check by index. */
191: struct interface *
1.1.1.3 ! misho 192: if_lookup_by_index_vrf (ifindex_t ifindex, vrf_id_t vrf_id)
1.1 misho 193: {
194: struct listnode *node;
195: struct interface *ifp;
196:
1.1.1.3 ! misho 197: for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
1.1 misho 198: {
1.1.1.3 ! misho 199: if (ifp->ifindex == ifindex)
1.1 misho 200: return ifp;
201: }
202: return NULL;
203: }
204:
1.1.1.3 ! misho 205: struct interface *
! 206: if_lookup_by_index (ifindex_t ifindex)
! 207: {
! 208: return if_lookup_by_index_vrf (ifindex, VRF_DEFAULT);
! 209: }
! 210:
1.1 misho 211: const char *
1.1.1.3 ! misho 212: ifindex2ifname_vrf (ifindex_t ifindex, vrf_id_t vrf_id)
1.1 misho 213: {
214: struct interface *ifp;
215:
1.1.1.3 ! misho 216: return ((ifp = if_lookup_by_index_vrf (ifindex, vrf_id)) != NULL) ?
1.1 misho 217: ifp->name : "unknown";
218: }
219:
1.1.1.3 ! misho 220: const char *
! 221: ifindex2ifname (ifindex_t ifindex)
! 222: {
! 223: return ifindex2ifname_vrf (ifindex, VRF_DEFAULT);
! 224: }
! 225:
! 226: ifindex_t
! 227: ifname2ifindex_vrf (const char *name, vrf_id_t vrf_id)
1.1 misho 228: {
229: struct interface *ifp;
230:
1.1.1.3 ! misho 231: return ((ifp = if_lookup_by_name_vrf (name, vrf_id)) != NULL) ? ifp->ifindex
1.1 misho 232: : IFINDEX_INTERNAL;
233: }
234:
1.1.1.3 ! misho 235: ifindex_t
! 236: ifname2ifindex (const char *name)
! 237: {
! 238: return ifname2ifindex_vrf (name, VRF_DEFAULT);
! 239: }
! 240:
1.1 misho 241: /* Interface existance check by interface name. */
242: struct interface *
1.1.1.3 ! misho 243: if_lookup_by_name_vrf (const char *name, vrf_id_t vrf_id)
1.1 misho 244: {
245: struct listnode *node;
246: struct interface *ifp;
247:
248: if (name)
1.1.1.3 ! misho 249: for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
1.1 misho 250: {
251: if (strcmp(name, ifp->name) == 0)
252: return ifp;
253: }
254: return NULL;
255: }
256:
257: struct interface *
1.1.1.3 ! misho 258: if_lookup_by_name (const char *name)
! 259: {
! 260: return if_lookup_by_name_vrf (name, VRF_DEFAULT);
! 261: }
! 262:
! 263: struct interface *
! 264: if_lookup_by_name_len_vrf (const char *name, size_t namelen, vrf_id_t vrf_id)
1.1 misho 265: {
266: struct listnode *node;
267: struct interface *ifp;
268:
269: if (namelen > INTERFACE_NAMSIZ)
270: return NULL;
271:
1.1.1.3 ! misho 272: for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
1.1 misho 273: {
274: if (!memcmp(name, ifp->name, namelen) && (ifp->name[namelen] == '\0'))
275: return ifp;
276: }
277: return NULL;
278: }
279:
1.1.1.3 ! misho 280: struct interface *
! 281: if_lookup_by_name_len(const char *name, size_t namelen)
! 282: {
! 283: return if_lookup_by_name_len_vrf (name, namelen, VRF_DEFAULT);
! 284: }
! 285:
1.1 misho 286: /* Lookup interface by IPv4 address. */
287: struct interface *
1.1.1.3 ! misho 288: if_lookup_exact_address_vrf (struct in_addr src, vrf_id_t vrf_id)
1.1 misho 289: {
290: struct listnode *node;
291: struct listnode *cnode;
292: struct interface *ifp;
293: struct prefix *p;
294: struct connected *c;
295:
1.1.1.3 ! misho 296: for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
1.1 misho 297: {
298: for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
299: {
300: p = c->address;
301:
302: if (p && p->family == AF_INET)
303: {
304: if (IPV4_ADDR_SAME (&p->u.prefix4, &src))
305: return ifp;
306: }
307: }
308: }
309: return NULL;
310: }
311:
1.1.1.3 ! misho 312: struct interface *
! 313: if_lookup_exact_address (struct in_addr src)
! 314: {
! 315: return if_lookup_exact_address_vrf (src, VRF_DEFAULT);
! 316: }
! 317:
1.1 misho 318: /* Lookup interface by IPv4 address. */
319: struct interface *
1.1.1.3 ! misho 320: if_lookup_address_vrf (struct in_addr src, vrf_id_t vrf_id)
1.1 misho 321: {
322: struct listnode *node;
323: struct prefix addr;
324: int bestlen = 0;
325: struct listnode *cnode;
326: struct interface *ifp;
327: struct connected *c;
328: struct interface *match;
329:
330: addr.family = AF_INET;
331: addr.u.prefix4 = src;
332: addr.prefixlen = IPV4_MAX_BITLEN;
333:
334: match = NULL;
335:
1.1.1.3 ! misho 336: for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
1.1 misho 337: {
338: for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
339: {
340: if (c->address && (c->address->family == AF_INET) &&
341: prefix_match(CONNECTED_PREFIX(c), &addr) &&
342: (c->address->prefixlen > bestlen))
343: {
344: bestlen = c->address->prefixlen;
345: match = ifp;
346: }
347: }
348: }
349: return match;
350: }
351:
1.1.1.3 ! misho 352: struct interface *
! 353: if_lookup_address (struct in_addr src)
! 354: {
! 355: return if_lookup_address_vrf (src, VRF_DEFAULT);
! 356: }
! 357:
! 358: /* Lookup interface by prefix */
! 359: struct interface *
! 360: if_lookup_prefix_vrf (struct prefix *prefix, vrf_id_t vrf_id)
! 361: {
! 362: struct listnode *node;
! 363: struct listnode *cnode;
! 364: struct interface *ifp;
! 365: struct connected *c;
! 366:
! 367: for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
! 368: {
! 369: for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
! 370: {
! 371: if (prefix_cmp(c->address, prefix) == 0)
! 372: {
! 373: return ifp;
! 374: }
! 375: }
! 376: }
! 377: return NULL;
! 378: }
! 379:
! 380: struct interface *
! 381: if_lookup_prefix (struct prefix *prefix)
! 382: {
! 383: return if_lookup_prefix_vrf (prefix, VRF_DEFAULT);
! 384: }
! 385:
1.1 misho 386: /* Get interface by name if given name interface doesn't exist create
387: one. */
388: struct interface *
1.1.1.3 ! misho 389: if_get_by_name_vrf (const char *name, vrf_id_t vrf_id)
1.1 misho 390: {
391: struct interface *ifp;
392:
1.1.1.3 ! misho 393: return ((ifp = if_lookup_by_name_vrf (name, vrf_id)) != NULL) ? ifp :
! 394: if_create_vrf (name, strlen(name), vrf_id);
! 395: }
! 396:
! 397: struct interface *
! 398: if_get_by_name (const char *name)
! 399: {
! 400: return if_get_by_name_vrf (name, VRF_DEFAULT);
1.1 misho 401: }
402:
403: struct interface *
1.1.1.3 ! misho 404: if_get_by_name_len_vrf (const char *name, size_t namelen, vrf_id_t vrf_id)
1.1 misho 405: {
406: struct interface *ifp;
407:
1.1.1.3 ! misho 408: return ((ifp = if_lookup_by_name_len_vrf (name, namelen, vrf_id)) != NULL) ? \
! 409: ifp : if_create_vrf (name, namelen, vrf_id);
! 410: }
! 411:
! 412: struct interface *
! 413: if_get_by_name_len (const char *name, size_t namelen)
! 414: {
! 415: return if_get_by_name_len_vrf (name, namelen, VRF_DEFAULT);
1.1 misho 416: }
417:
418: /* Does interface up ? */
419: int
420: if_is_up (struct interface *ifp)
421: {
422: return ifp->flags & IFF_UP;
423: }
424:
425: /* Is interface running? */
426: int
427: if_is_running (struct interface *ifp)
428: {
429: return ifp->flags & IFF_RUNNING;
430: }
431:
432: /* Is the interface operative, eg. either UP & RUNNING
433: or UP & !ZEBRA_INTERFACE_LINK_DETECTION */
434: int
435: if_is_operative (struct interface *ifp)
436: {
437: return ((ifp->flags & IFF_UP) &&
438: (ifp->flags & IFF_RUNNING || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)));
439: }
440:
441: /* Is this loopback interface ? */
442: int
443: if_is_loopback (struct interface *ifp)
444: {
445: /* XXX: Do this better, eg what if IFF_WHATEVER means X on platform M
446: * but Y on platform N?
447: */
448: return (ifp->flags & (IFF_LOOPBACK|IFF_NOXMIT|IFF_VIRTUAL));
449: }
450:
451: /* Does this interface support broadcast ? */
452: int
453: if_is_broadcast (struct interface *ifp)
454: {
455: return ifp->flags & IFF_BROADCAST;
456: }
457:
458: /* Does this interface support broadcast ? */
459: int
460: if_is_pointopoint (struct interface *ifp)
461: {
462: return ifp->flags & IFF_POINTOPOINT;
463: }
464:
465: /* Does this interface support multicast ? */
466: int
467: if_is_multicast (struct interface *ifp)
468: {
469: return ifp->flags & IFF_MULTICAST;
470: }
471:
472: /* Printout flag information into log */
473: const char *
474: if_flag_dump (unsigned long flag)
475: {
476: int separator = 0;
477: static char logbuf[BUFSIZ];
478:
479: #define IFF_OUT_LOG(X,STR) \
480: if (flag & (X)) \
481: { \
482: if (separator) \
483: strlcat (logbuf, ",", BUFSIZ); \
484: else \
485: separator = 1; \
486: strlcat (logbuf, STR, BUFSIZ); \
487: }
488:
489: strlcpy (logbuf, "<", BUFSIZ);
490: IFF_OUT_LOG (IFF_UP, "UP");
491: IFF_OUT_LOG (IFF_BROADCAST, "BROADCAST");
492: IFF_OUT_LOG (IFF_DEBUG, "DEBUG");
493: IFF_OUT_LOG (IFF_LOOPBACK, "LOOPBACK");
494: IFF_OUT_LOG (IFF_POINTOPOINT, "POINTOPOINT");
495: IFF_OUT_LOG (IFF_NOTRAILERS, "NOTRAILERS");
496: IFF_OUT_LOG (IFF_RUNNING, "RUNNING");
497: IFF_OUT_LOG (IFF_NOARP, "NOARP");
498: IFF_OUT_LOG (IFF_PROMISC, "PROMISC");
499: IFF_OUT_LOG (IFF_ALLMULTI, "ALLMULTI");
500: IFF_OUT_LOG (IFF_OACTIVE, "OACTIVE");
501: IFF_OUT_LOG (IFF_SIMPLEX, "SIMPLEX");
502: IFF_OUT_LOG (IFF_LINK0, "LINK0");
503: IFF_OUT_LOG (IFF_LINK1, "LINK1");
504: IFF_OUT_LOG (IFF_LINK2, "LINK2");
505: IFF_OUT_LOG (IFF_MULTICAST, "MULTICAST");
506: IFF_OUT_LOG (IFF_NOXMIT, "NOXMIT");
507: IFF_OUT_LOG (IFF_NORTEXCH, "NORTEXCH");
508: IFF_OUT_LOG (IFF_VIRTUAL, "VIRTUAL");
509: IFF_OUT_LOG (IFF_IPV4, "IPv4");
510: IFF_OUT_LOG (IFF_IPV6, "IPv6");
511:
512: strlcat (logbuf, ">", BUFSIZ);
513:
514: return logbuf;
515: #undef IFF_OUT_LOG
516: }
517:
518: /* For debugging */
519: static void
520: if_dump (const struct interface *ifp)
521: {
522: struct listnode *node;
1.1.1.3 ! misho 523: struct connected *c __attribute__((unused));
1.1 misho 524:
1.1.1.2 misho 525: for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, c))
1.1.1.3 ! misho 526: zlog_info ("Interface %s vrf %u index %d metric %d mtu %d "
1.1 misho 527: #ifdef HAVE_IPV6
1.1.1.2 misho 528: "mtu6 %d "
1.1 misho 529: #endif /* HAVE_IPV6 */
1.1.1.2 misho 530: "%s",
1.1.1.3 ! misho 531: ifp->name, ifp->vrf_id, ifp->ifindex, ifp->metric, ifp->mtu,
1.1 misho 532: #ifdef HAVE_IPV6
1.1.1.2 misho 533: ifp->mtu6,
1.1 misho 534: #endif /* HAVE_IPV6 */
1.1.1.2 misho 535: if_flag_dump (ifp->flags));
1.1 misho 536: }
537:
538: /* Interface printing for all interface. */
539: void
540: if_dump_all (void)
541: {
1.1.1.3 ! misho 542: struct list *intf_list;
1.1 misho 543: struct listnode *node;
544: void *p;
1.1.1.3 ! misho 545: vrf_iter_t iter;
1.1 misho 546:
1.1.1.3 ! misho 547: for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
! 548: if ((intf_list = vrf_iter2iflist (iter)) != NULL)
! 549: for (ALL_LIST_ELEMENTS_RO (intf_list, node, p))
! 550: if_dump (p);
1.1 misho 551: }
552:
553: DEFUN (interface_desc,
554: interface_desc_cmd,
555: "description .LINE",
556: "Interface specific description\n"
557: "Characters describing this interface\n")
558: {
559: struct interface *ifp;
560:
561: if (argc == 0)
562: return CMD_SUCCESS;
563:
564: ifp = vty->index;
565: if (ifp->desc)
566: XFREE (MTYPE_TMP, ifp->desc);
567: ifp->desc = argv_concat(argv, argc, 0);
568:
569: return CMD_SUCCESS;
570: }
571:
572: DEFUN (no_interface_desc,
573: no_interface_desc_cmd,
574: "no description",
575: NO_STR
576: "Interface specific description\n")
577: {
578: struct interface *ifp;
579:
580: ifp = vty->index;
581: if (ifp->desc)
582: XFREE (MTYPE_TMP, ifp->desc);
583: ifp->desc = NULL;
584:
585: return CMD_SUCCESS;
586: }
1.1.1.3 ! misho 587:
1.1 misho 588: #ifdef SUNOS_5
589: /* Need to handle upgrade from SUNWzebra to Quagga. SUNWzebra created
590: * a seperate struct interface for each logical interface, so config
591: * file may be full of 'interface fooX:Y'. Solaris however does not
592: * expose logical interfaces via PF_ROUTE, so trying to track logical
593: * interfaces can be fruitless, for that reason Quagga only tracks
594: * the primary IP interface.
595: *
596: * We try accomodate SUNWzebra by:
597: * - looking up the interface name, to see whether it exists, if so
598: * its useable
599: * - for protocol daemons, this could only because zebra told us of
600: * the interface
601: * - for zebra, only because it learnt from kernel
602: * - if not:
603: * - search the name to see if it contains a sub-ipif / logical interface
604: * seperator, the ':' char. If it does:
605: * - text up to that char must be the primary name - get that name.
606: * if not:
607: * - no idea, just get the name in its entirety.
608: */
609: static struct interface *
1.1.1.3 ! misho 610: if_sunwzebra_get (const char *name, size_t nlen, vrf_id_t vrf_id)
1.1 misho 611: {
612: struct interface *ifp;
613: size_t seppos = 0;
614:
1.1.1.3 ! misho 615: if ( (ifp = if_lookup_by_name_len_vrf (name, nlen, vrf_id)) != NULL)
1.1 misho 616: return ifp;
617:
618: /* hunt the primary interface name... */
619: while (seppos < nlen && name[seppos] != ':')
620: seppos++;
621:
622: /* Wont catch seperator as last char, e.g. 'foo0:' but thats invalid */
623: if (seppos < nlen)
1.1.1.3 ! misho 624: return if_get_by_name_len_vrf (name, seppos, vrf_id);
1.1 misho 625: else
1.1.1.3 ! misho 626: return if_get_by_name_len_vrf (name, nlen, vrf_id);
1.1 misho 627: }
628: #endif /* SUNOS_5 */
1.1.1.3 ! misho 629:
1.1 misho 630: DEFUN (interface,
631: interface_cmd,
632: "interface IFNAME",
633: "Select an interface to configure\n"
634: "Interface's name\n")
635: {
636: struct interface *ifp;
637: size_t sl;
1.1.1.3 ! misho 638: vrf_id_t vrf_id = VRF_DEFAULT;
1.1 misho 639:
640: if ((sl = strlen(argv[0])) > INTERFACE_NAMSIZ)
641: {
642: vty_out (vty, "%% Interface name %s is invalid: length exceeds "
643: "%d characters%s",
644: argv[0], INTERFACE_NAMSIZ, VTY_NEWLINE);
645: return CMD_WARNING;
646: }
647:
1.1.1.3 ! misho 648: if (argc > 1)
! 649: VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]);
! 650:
1.1 misho 651: #ifdef SUNOS_5
1.1.1.3 ! misho 652: ifp = if_sunwzebra_get (argv[0], sl, vrf_id);
1.1 misho 653: #else
1.1.1.3 ! misho 654: ifp = if_get_by_name_len_vrf (argv[0], sl, vrf_id);
1.1 misho 655: #endif /* SUNOS_5 */
656:
657: vty->index = ifp;
658: vty->node = INTERFACE_NODE;
659:
660: return CMD_SUCCESS;
661: }
662:
1.1.1.3 ! misho 663: ALIAS (interface,
! 664: interface_vrf_cmd,
! 665: "interface IFNAME " VRF_CMD_STR,
! 666: "Select an interface to configure\n"
! 667: "Interface's name\n"
! 668: VRF_CMD_HELP_STR)
! 669:
1.1 misho 670: DEFUN_NOSH (no_interface,
671: no_interface_cmd,
672: "no interface IFNAME",
673: NO_STR
674: "Delete a pseudo interface's configuration\n"
675: "Interface's name\n")
676: {
677: // deleting interface
678: struct interface *ifp;
1.1.1.3 ! misho 679: vrf_id_t vrf_id = VRF_DEFAULT;
1.1 misho 680:
1.1.1.3 ! misho 681: if (argc > 1)
! 682: VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]);
! 683:
! 684: ifp = if_lookup_by_name_vrf (argv[0], vrf_id);
1.1 misho 685:
686: if (ifp == NULL)
687: {
688: vty_out (vty, "%% Interface %s does not exist%s", argv[0], VTY_NEWLINE);
689: return CMD_WARNING;
690: }
691:
692: if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
693: {
694: vty_out (vty, "%% Only inactive interfaces can be deleted%s",
695: VTY_NEWLINE);
696: return CMD_WARNING;
697: }
698:
699: if_delete(ifp);
700:
701: return CMD_SUCCESS;
702: }
703:
1.1.1.3 ! misho 704: ALIAS (no_interface,
! 705: no_interface_vrf_cmd,
! 706: "no interface IFNAME " VRF_CMD_STR,
! 707: NO_STR
! 708: "Delete a pseudo interface's configuration\n"
! 709: "Interface's name\n"
! 710: VRF_CMD_HELP_STR)
! 711:
1.1 misho 712: /* For debug purpose. */
713: DEFUN (show_address,
714: show_address_cmd,
715: "show address",
716: SHOW_STR
717: "address\n")
718: {
719: struct listnode *node;
720: struct listnode *node2;
721: struct interface *ifp;
722: struct connected *ifc;
723: struct prefix *p;
1.1.1.3 ! misho 724: vrf_id_t vrf_id = VRF_DEFAULT;
1.1 misho 725:
1.1.1.3 ! misho 726: if (argc > 0)
! 727: VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]);
! 728:
! 729: for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
1.1 misho 730: {
731: for (ALL_LIST_ELEMENTS_RO (ifp->connected, node2, ifc))
732: {
733: p = ifc->address;
734:
735: if (p->family == AF_INET)
736: vty_out (vty, "%s/%d%s", inet_ntoa (p->u.prefix4), p->prefixlen,
737: VTY_NEWLINE);
738: }
739: }
740: return CMD_SUCCESS;
741: }
742:
1.1.1.3 ! misho 743: ALIAS (show_address,
! 744: show_address_vrf_cmd,
! 745: "show address " VRF_CMD_STR,
! 746: SHOW_STR
! 747: "address\n"
! 748: VRF_CMD_HELP_STR)
! 749:
! 750: DEFUN (show_address_vrf_all,
! 751: show_address_vrf_all_cmd,
! 752: "show address " VRF_ALL_CMD_STR,
! 753: SHOW_STR
! 754: "address\n"
! 755: VRF_ALL_CMD_HELP_STR)
! 756: {
! 757: struct list *intf_list;
! 758: struct listnode *node;
! 759: struct listnode *node2;
! 760: struct interface *ifp;
! 761: struct connected *ifc;
! 762: struct prefix *p;
! 763: vrf_iter_t iter;
! 764:
! 765: for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
! 766: {
! 767: intf_list = vrf_iter2iflist (iter);
! 768: if (!intf_list || !listcount (intf_list))
! 769: continue;
! 770:
! 771: vty_out (vty, "%sVRF %u%s%s", VTY_NEWLINE, vrf_iter2id (iter),
! 772: VTY_NEWLINE, VTY_NEWLINE);
! 773:
! 774: for (ALL_LIST_ELEMENTS_RO (intf_list, node, ifp))
! 775: {
! 776: for (ALL_LIST_ELEMENTS_RO (ifp->connected, node2, ifc))
! 777: {
! 778: p = ifc->address;
! 779:
! 780: if (p->family == AF_INET)
! 781: vty_out (vty, "%s/%d%s", inet_ntoa (p->u.prefix4), p->prefixlen,
! 782: VTY_NEWLINE);
! 783: }
! 784: }
! 785: }
! 786: return CMD_SUCCESS;
! 787: }
! 788:
1.1 misho 789: /* Allocate connected structure. */
790: struct connected *
791: connected_new (void)
792: {
793: return XCALLOC (MTYPE_CONNECTED, sizeof (struct connected));
794: }
795:
796: /* Free connected structure. */
797: void
798: connected_free (struct connected *connected)
799: {
800: if (connected->address)
801: prefix_free (connected->address);
802:
803: if (connected->destination)
804: prefix_free (connected->destination);
805:
806: if (connected->label)
807: XFREE (MTYPE_CONNECTED_LABEL, connected->label);
808:
809: XFREE (MTYPE_CONNECTED, connected);
810: }
811:
812: /* Print if_addr structure. */
813: static void __attribute__ ((unused))
814: connected_log (struct connected *connected, char *str)
815: {
816: struct prefix *p;
817: struct interface *ifp;
818: char logbuf[BUFSIZ];
819: char buf[BUFSIZ];
820:
821: ifp = connected->ifp;
822: p = connected->address;
823:
1.1.1.3 ! misho 824: snprintf (logbuf, BUFSIZ, "%s interface %s vrf %u %s %s/%d ",
! 825: str, ifp->name, ifp->vrf_id, prefix_family_str (p),
1.1 misho 826: inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
827: p->prefixlen);
828:
829: p = connected->destination;
830: if (p)
831: {
832: strncat (logbuf, inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
833: BUFSIZ - strlen(logbuf));
834: }
835: zlog (NULL, LOG_INFO, "%s", logbuf);
836: }
837:
838: /* If two connected address has same prefix return 1. */
839: static int
840: connected_same_prefix (struct prefix *p1, struct prefix *p2)
841: {
842: if (p1->family == p2->family)
843: {
844: if (p1->family == AF_INET &&
845: IPV4_ADDR_SAME (&p1->u.prefix4, &p2->u.prefix4))
846: return 1;
847: #ifdef HAVE_IPV6
848: if (p1->family == AF_INET6 &&
849: IPV6_ADDR_SAME (&p1->u.prefix6, &p2->u.prefix6))
850: return 1;
851: #endif /* HAVE_IPV6 */
852: }
853: return 0;
854: }
855:
856: struct connected *
857: connected_delete_by_prefix (struct interface *ifp, struct prefix *p)
858: {
859: struct listnode *node;
860: struct listnode *next;
861: struct connected *ifc;
862:
863: /* In case of same prefix come, replace it with new one. */
864: for (node = listhead (ifp->connected); node; node = next)
865: {
866: ifc = listgetdata (node);
867: next = node->next;
868:
869: if (connected_same_prefix (ifc->address, p))
870: {
871: listnode_delete (ifp->connected, ifc);
872: return ifc;
873: }
874: }
875: return NULL;
876: }
877:
878: /* Find the IPv4 address on our side that will be used when packets
879: are sent to dst. */
880: struct connected *
881: connected_lookup_address (struct interface *ifp, struct in_addr dst)
882: {
883: struct prefix addr;
884: struct listnode *cnode;
885: struct connected *c;
886: struct connected *match;
887:
888: addr.family = AF_INET;
889: addr.u.prefix4 = dst;
890: addr.prefixlen = IPV4_MAX_BITLEN;
891:
892: match = NULL;
893:
894: for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
895: {
896: if (c->address && (c->address->family == AF_INET) &&
897: prefix_match(CONNECTED_PREFIX(c), &addr) &&
898: (!match || (c->address->prefixlen > match->address->prefixlen)))
899: match = c;
900: }
901: return match;
902: }
903:
904: struct connected *
905: connected_add_by_prefix (struct interface *ifp, struct prefix *p,
906: struct prefix *destination)
907: {
908: struct connected *ifc;
909:
910: /* Allocate new connected address. */
911: ifc = connected_new ();
912: ifc->ifp = ifp;
913:
914: /* Fetch interface address */
915: ifc->address = prefix_new();
916: memcpy (ifc->address, p, sizeof(struct prefix));
917:
918: /* Fetch dest address */
919: if (destination)
920: {
921: ifc->destination = prefix_new();
922: memcpy (ifc->destination, destination, sizeof(struct prefix));
923: }
924:
925: /* Add connected address to the interface. */
926: listnode_add (ifp->connected, ifc);
927: return ifc;
928: }
929:
930: #ifndef HAVE_IF_NAMETOINDEX
1.1.1.3 ! misho 931: ifindex_t
1.1 misho 932: if_nametoindex (const char *name)
933: {
934: struct interface *ifp;
935:
936: return ((ifp = if_lookup_by_name_len(name, strnlen(name, IFNAMSIZ))) != NULL)
937: ? ifp->ifindex : 0;
938: }
939: #endif
940:
941: #ifndef HAVE_IF_INDEXTONAME
942: char *
1.1.1.3 ! misho 943: if_indextoname (ifindex_t ifindex, char *name)
1.1 misho 944: {
945: struct interface *ifp;
946:
947: if (!(ifp = if_lookup_by_index(ifindex)))
948: return NULL;
949: strncpy (name, ifp->name, IFNAMSIZ);
950: return ifp->name;
951: }
952: #endif
1.1.1.3 ! misho 953:
1.1 misho 954: #if 0 /* this route_table of struct connected's is unused
955: * however, it would be good to use a route_table rather than
956: * a list..
957: */
958: /* Interface looking up by interface's address. */
959: /* Interface's IPv4 address reverse lookup table. */
960: struct route_table *ifaddr_ipv4_table;
961: /* struct route_table *ifaddr_ipv6_table; */
962:
963: static void
964: ifaddr_ipv4_add (struct in_addr *ifaddr, struct interface *ifp)
965: {
966: struct route_node *rn;
967: struct prefix_ipv4 p;
968:
969: p.family = AF_INET;
970: p.prefixlen = IPV4_MAX_PREFIXLEN;
971: p.prefix = *ifaddr;
972:
973: rn = route_node_get (ifaddr_ipv4_table, (struct prefix *) &p);
974: if (rn)
975: {
976: route_unlock_node (rn);
977: zlog_info ("ifaddr_ipv4_add(): address %s is already added",
978: inet_ntoa (*ifaddr));
979: return;
980: }
981: rn->info = ifp;
982: }
983:
984: static void
985: ifaddr_ipv4_delete (struct in_addr *ifaddr, struct interface *ifp)
986: {
987: struct route_node *rn;
988: struct prefix_ipv4 p;
989:
990: p.family = AF_INET;
991: p.prefixlen = IPV4_MAX_PREFIXLEN;
992: p.prefix = *ifaddr;
993:
994: rn = route_node_lookup (ifaddr_ipv4_table, (struct prefix *) &p);
995: if (! rn)
996: {
997: zlog_info ("ifaddr_ipv4_delete(): can't find address %s",
998: inet_ntoa (*ifaddr));
999: return;
1000: }
1001: rn->info = NULL;
1002: route_unlock_node (rn);
1003: route_unlock_node (rn);
1004: }
1005:
1006: /* Lookup interface by interface's IP address or interface index. */
1007: static struct interface *
1.1.1.3 ! misho 1008: ifaddr_ipv4_lookup (struct in_addr *addr, ifindex_t ifindex)
1.1 misho 1009: {
1010: struct prefix_ipv4 p;
1011: struct route_node *rn;
1012: struct interface *ifp;
1013:
1014: if (addr)
1015: {
1016: p.family = AF_INET;
1017: p.prefixlen = IPV4_MAX_PREFIXLEN;
1018: p.prefix = *addr;
1019:
1020: rn = route_node_lookup (ifaddr_ipv4_table, (struct prefix *) &p);
1021: if (! rn)
1022: return NULL;
1023:
1024: ifp = rn->info;
1025: route_unlock_node (rn);
1026: return ifp;
1027: }
1028: else
1029: return if_lookup_by_index(ifindex);
1030: }
1031: #endif /* ifaddr_ipv4_table */
1032:
1033: /* Initialize interface list. */
1034: void
1.1.1.3 ! misho 1035: if_init (vrf_id_t vrf_id, struct list **intf_list)
1.1 misho 1036: {
1.1.1.3 ! misho 1037: *intf_list = list_new ();
1.1 misho 1038: #if 0
1039: ifaddr_ipv4_table = route_table_init ();
1040: #endif /* ifaddr_ipv4_table */
1041:
1.1.1.3 ! misho 1042: (*intf_list)->cmp = (int (*)(void *, void *))if_cmp_func;
1.1 misho 1043:
1.1.1.3 ! misho 1044: if (vrf_id == VRF_DEFAULT)
! 1045: iflist = *intf_list;
1.1 misho 1046: }
1047:
1048: void
1.1.1.3 ! misho 1049: if_terminate (vrf_id_t vrf_id, struct list **intf_list)
1.1 misho 1050: {
1051: for (;;)
1052: {
1053: struct interface *ifp;
1054:
1.1.1.3 ! misho 1055: ifp = listnode_head (*intf_list);
1.1 misho 1056: if (ifp == NULL)
1057: break;
1058:
1059: if_delete (ifp);
1060: }
1061:
1.1.1.3 ! misho 1062: list_delete (*intf_list);
! 1063: *intf_list = NULL;
! 1064:
! 1065: if (vrf_id == VRF_DEFAULT)
! 1066: iflist = NULL;
! 1067: }
! 1068:
! 1069: const char *
! 1070: if_link_type_str (enum zebra_link_type llt)
! 1071: {
! 1072: switch (llt)
! 1073: {
! 1074: #define llts(T,S) case (T): return (S)
! 1075: llts(ZEBRA_LLT_UNKNOWN, "Unknown");
! 1076: llts(ZEBRA_LLT_ETHER, "Ethernet");
! 1077: llts(ZEBRA_LLT_EETHER, "Experimental Ethernet");
! 1078: llts(ZEBRA_LLT_AX25, "AX.25 Level 2");
! 1079: llts(ZEBRA_LLT_PRONET, "PROnet token ring");
! 1080: llts(ZEBRA_LLT_IEEE802, "IEEE 802.2 Ethernet/TR/TB");
! 1081: llts(ZEBRA_LLT_ARCNET, "ARCnet");
! 1082: llts(ZEBRA_LLT_APPLETLK, "AppleTalk");
! 1083: llts(ZEBRA_LLT_DLCI, "Frame Relay DLCI");
! 1084: llts(ZEBRA_LLT_ATM, "ATM");
! 1085: llts(ZEBRA_LLT_METRICOM, "Metricom STRIP");
! 1086: llts(ZEBRA_LLT_IEEE1394, "IEEE 1394 IPv4");
! 1087: llts(ZEBRA_LLT_EUI64, "EUI-64");
! 1088: llts(ZEBRA_LLT_INFINIBAND, "InfiniBand");
! 1089: llts(ZEBRA_LLT_SLIP, "SLIP");
! 1090: llts(ZEBRA_LLT_CSLIP, "Compressed SLIP");
! 1091: llts(ZEBRA_LLT_SLIP6, "SLIPv6");
! 1092: llts(ZEBRA_LLT_CSLIP6, "Compressed SLIPv6");
! 1093: llts(ZEBRA_LLT_ROSE, "ROSE packet radio");
! 1094: llts(ZEBRA_LLT_X25, "CCITT X.25");
! 1095: llts(ZEBRA_LLT_PPP, "PPP");
! 1096: llts(ZEBRA_LLT_CHDLC, "Cisco HDLC");
! 1097: llts(ZEBRA_LLT_RAWHDLC, "Raw HDLC");
! 1098: llts(ZEBRA_LLT_LAPB, "LAPB");
! 1099: llts(ZEBRA_LLT_IPIP, "IPIP Tunnel");
! 1100: llts(ZEBRA_LLT_IPIP6, "IPIP6 Tunnel");
! 1101: llts(ZEBRA_LLT_FRAD, "FRAD");
! 1102: llts(ZEBRA_LLT_SKIP, "SKIP vif");
! 1103: llts(ZEBRA_LLT_LOOPBACK, "Loopback");
! 1104: llts(ZEBRA_LLT_LOCALTLK, "Localtalk");
! 1105: llts(ZEBRA_LLT_FDDI, "FDDI");
! 1106: llts(ZEBRA_LLT_SIT, "IPv6-in-IPv4 SIT");
! 1107: llts(ZEBRA_LLT_IPDDP, "IP-in-DDP tunnel");
! 1108: llts(ZEBRA_LLT_IPGRE, "GRE over IP");
! 1109: llts(ZEBRA_LLT_PIMREG, "PIMSM registration");
! 1110: llts(ZEBRA_LLT_HIPPI, "HiPPI");
! 1111: llts(ZEBRA_LLT_IRDA, "IrDA");
! 1112: llts(ZEBRA_LLT_FCPP, "Fibre-Channel PtP");
! 1113: llts(ZEBRA_LLT_FCAL, "Fibre-Channel Arbitrated Loop");
! 1114: llts(ZEBRA_LLT_FCPL, "Fibre-Channel Public Loop");
! 1115: llts(ZEBRA_LLT_FCFABRIC, "Fibre-Channel Fabric");
! 1116: llts(ZEBRA_LLT_IEEE802_TR, "IEEE 802.2 Token Ring");
! 1117: llts(ZEBRA_LLT_IEEE80211, "IEEE 802.11");
! 1118: llts(ZEBRA_LLT_IEEE80211_RADIOTAP, "IEEE 802.11 Radiotap");
! 1119: llts(ZEBRA_LLT_IEEE802154, "IEEE 802.15.4");
! 1120: llts(ZEBRA_LLT_IEEE802154_PHY, "IEEE 802.15.4 Phy");
! 1121: default:
! 1122: zlog_warn ("Unknown value %d", llt);
! 1123: return "Unknown type!";
! 1124: #undef llts
! 1125: }
! 1126: return NULL;
1.1 misho 1127: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>