blob: cb2d086e8cad1a315915853ac0f23d1b8c728596 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
2 * Interface functions.
3 * Copyright (C) 1997, 98 Kunihiro Ishiguro
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify
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 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING. If not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25#include "linklist.h"
26#include "vector.h"
27#include "vty.h"
28#include "command.h"
29#include "if.h"
30#include "sockunion.h"
31#include "prefix.h"
32#include "zebra/connected.h"
33#include "memory.h"
34#include "table.h"
35#include "buffer.h"
36#include "str.h"
37#include "log.h"
38
39/* Master list of interfaces. */
40struct list *iflist;
41
42/* One for each program. This structure is needed to store hooks. */
43struct if_master
44{
45 int (*if_new_hook) (struct interface *);
46 int (*if_delete_hook) (struct interface *);
47} if_master;
48
hassoa9395142003-06-05 17:50:01 +000049/* Compare interface names */
50int
51if_cmp_func (struct interface *ifp1, struct interface *ifp2)
52{
53 unsigned int l1, l2;
54 long int x1, x2;
55 char *p1, *p2;
56 int res;
57
58 p1 = ifp1->name;
59 p2 = ifp2->name;
60
61 while (1) {
62 /* look up to any number */
63 l1 = strcspn(p1, "0123456789");
64 l2 = strcspn(p2, "0123456789");
65
66 /* name lengths are different -> compare names */
67 if (l1 != l2)
68 return (strcmp(p1, p2));
69
70 res = strncmp(p1, p2, l1);
71
72 /* names are different -> compare them */
73 if (res)
74 return res;
75
76 /* with identical name part, go to numeric part */
77
78 p1 += l1;
79 p2 += l1;
80
81 x1 = strtol(p1, &p1, 10);
82 x2 = strtol(p2, &p2, 10);
83
84 /* let's compare numbers now */
85 if (x1 < x2)
86 return -1;
87 if (x1 > x2)
88 return 1;
89
90 /* numbers were equal, lets do it again..
91 (it happens with name like "eth123.456:789") */
92 }
93}
94
paul718e3742002-12-13 20:15:29 +000095/* Create new interface structure. */
96struct interface *
97if_new ()
98{
99 struct interface *ifp;
100
101 ifp = XMALLOC (MTYPE_IF, sizeof (struct interface));
102 memset (ifp, 0, sizeof (struct interface));
103 return ifp;
104}
105
106struct interface *
hassoa9395142003-06-05 17:50:01 +0000107if_create (char *name, int namelen)
paul718e3742002-12-13 20:15:29 +0000108{
109 struct interface *ifp;
110
111 ifp = if_new ();
112
hassoa9395142003-06-05 17:50:01 +0000113 if (name) {
114 strncpy (ifp->name, name, namelen);
115 listnode_add_sort (iflist, ifp);
116 } else {
117 listnode_add (iflist, ifp);
118 }
paul718e3742002-12-13 20:15:29 +0000119 ifp->connected = list_new ();
120 ifp->connected->del = (void (*) (void *)) connected_free;
121
122 if (if_master.if_new_hook)
123 (*if_master.if_new_hook) (ifp);
124
125 return ifp;
126}
127
128/* Delete and free interface structure. */
129void
130if_delete (struct interface *ifp)
131{
132 listnode_delete (iflist, ifp);
133
134 if (if_master.if_delete_hook)
135 (*if_master.if_delete_hook) (ifp);
136
137 /* Free connected address list */
138 list_delete (ifp->connected);
139
140 XFREE (MTYPE_IF, ifp);
141}
142
143/* Add hook to interface master. */
144void
145if_add_hook (int type, int (*func)(struct interface *ifp))
146{
147 switch (type) {
148 case IF_NEW_HOOK:
149 if_master.if_new_hook = func;
150 break;
151 case IF_DELETE_HOOK:
152 if_master.if_delete_hook = func;
153 break;
154 default:
155 break;
156 }
157}
158
159/* Interface existance check by index. */
160struct interface *
161if_lookup_by_index (unsigned int index)
162{
163 listnode node;
164 struct interface *ifp;
165
166 for (node = listhead (iflist); node; nextnode (node))
167 {
168 ifp = getdata (node);
169 if (ifp->ifindex == index)
170 return ifp;
171 }
172 return NULL;
173}
174
175char *
176ifindex2ifname (unsigned int index)
177{
178 listnode node;
179 struct interface *ifp;
180
181 for (node = listhead (iflist); node; nextnode (node))
182 {
183 ifp = getdata (node);
184 if (ifp->ifindex == index)
185 return ifp->name;
186 }
187 return "unknown";
188}
189
190/* Interface existance check by interface name. */
191struct interface *
192if_lookup_by_name (char *name)
193{
194 listnode node;
195 struct interface *ifp;
196
197 for (node = listhead (iflist); node; nextnode (node))
198 {
199 ifp = getdata (node);
200 if (strncmp (name, ifp->name, sizeof ifp->name) == 0)
201 return ifp;
202 }
203 return NULL;
204}
205
206/* Lookup interface by IPv4 address. */
207struct interface *
208if_lookup_exact_address (struct in_addr src)
209{
210 listnode node;
211 listnode cnode;
212 struct interface *ifp;
213 struct prefix *p;
214 struct connected *c;
215
216 for (node = listhead (iflist); node; nextnode (node))
217 {
218 ifp = getdata (node);
219
220 for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
221 {
222 c = getdata (cnode);
223
224 p = c->address;
225
226 if (p && p->family == AF_INET)
227 {
228 if (IPV4_ADDR_SAME (&p->u.prefix4, &src))
229 return ifp;
230 }
231 }
232 }
233 return NULL;
234}
235
236/* Lookup interface by IPv4 address. */
237struct interface *
238if_lookup_address (struct in_addr src)
239{
240 listnode node;
241 struct prefix addr;
242 struct prefix best;
paul00df0c12002-12-13 21:07:36 +0000243 struct prefix peer;
paul718e3742002-12-13 20:15:29 +0000244 listnode cnode;
245 struct interface *ifp;
246 struct prefix *p;
247 struct connected *c;
248 struct interface *match;
paul00df0c12002-12-13 21:07:36 +0000249 int prefixlen;
paul718e3742002-12-13 20:15:29 +0000250
251 /* Zero structures - get rid of rubbish from stack */
252 memset(&addr, 0, sizeof(addr));
253 memset(&best, 0, sizeof(best));
254
255 addr.family = AF_INET;
256 addr.u.prefix4 = src;
257 addr.prefixlen = IPV4_MAX_BITLEN;
258
259 match = NULL;
260
261 for (node = listhead (iflist); node; nextnode (node))
262 {
263 ifp = getdata (node);
264
265 for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
266 {
267 c = getdata (cnode);
paul00df0c12002-12-13 21:07:36 +0000268 p = c->address;
paul718e3742002-12-13 20:15:29 +0000269
paul00df0c12002-12-13 21:07:36 +0000270 if (p->family == AF_INET)
paul718e3742002-12-13 20:15:29 +0000271 {
paul00df0c12002-12-13 21:07:36 +0000272 prefixlen = p->prefixlen;
paul718e3742002-12-13 20:15:29 +0000273
paul00df0c12002-12-13 21:07:36 +0000274 if (if_is_pointopoint (ifp) ||
275 prefixlen >= IPV4_MAX_PREFIXLEN - 1)
paul718e3742002-12-13 20:15:29 +0000276 {
paul00df0c12002-12-13 21:07:36 +0000277 peer = *c->destination;
278 peer.prefixlen = prefixlen;
279 p = &peer;
paul718e3742002-12-13 20:15:29 +0000280 }
paul718e3742002-12-13 20:15:29 +0000281
paul00df0c12002-12-13 21:07:36 +0000282 if (prefix_match (p, &addr) && prefixlen > best.prefixlen)
paul718e3742002-12-13 20:15:29 +0000283 {
paul00df0c12002-12-13 21:07:36 +0000284 best = *p;
285 match = ifp;
paul718e3742002-12-13 20:15:29 +0000286 }
287 }
288 }
289 }
290 return match;
291}
292
293/* Get interface by name if given name interface doesn't exist create
294 one. */
295struct interface *
296if_get_by_name (char *name)
297{
298 struct interface *ifp;
299
300 ifp = if_lookup_by_name (name);
301 if (ifp == NULL)
hassoa9395142003-06-05 17:50:01 +0000302 ifp = if_create (name, IFNAMSIZ);
paul718e3742002-12-13 20:15:29 +0000303 return ifp;
304}
305
306/* Does interface up ? */
307int
308if_is_up (struct interface *ifp)
309{
310 return ifp->flags & IFF_UP;
311}
312
paul2e3b2e42002-12-13 21:03:13 +0000313/* Is interface running? */
314int
315if_is_running (struct interface *ifp)
316{
317 return ifp->flags & IFF_RUNNING;
318}
319
320/* Is the interface operative, eg. either UP & RUNNING
321 or UP & !ZEBRA_INTERFACE_LINK_DETECTION */
322int
323if_is_operative (struct interface *ifp)
324{
325 return ((ifp->flags & IFF_UP) &&
326 (ifp->flags & IFF_RUNNING || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)));
327}
328
paul718e3742002-12-13 20:15:29 +0000329/* Is this loopback interface ? */
330int
331if_is_loopback (struct interface *ifp)
332{
333 return ifp->flags & IFF_LOOPBACK;
334}
335
336/* Does this interface support broadcast ? */
337int
338if_is_broadcast (struct interface *ifp)
339{
340 return ifp->flags & IFF_BROADCAST;
341}
342
343/* Does this interface support broadcast ? */
344int
345if_is_pointopoint (struct interface *ifp)
346{
347 return ifp->flags & IFF_POINTOPOINT;
348}
349
350/* Does this interface support multicast ? */
351int
352if_is_multicast (struct interface *ifp)
353{
354 return ifp->flags & IFF_MULTICAST;
355}
356
357/* Printout flag information into log */
358const char *
359if_flag_dump (unsigned long flag)
360{
361 int separator = 0;
362 static char logbuf[BUFSIZ];
363
364#define IFF_OUT_LOG(X,STR) \
365 if ((X) && (flag & (X))) \
366 { \
367 if (separator) \
368 strlcat (logbuf, ",", BUFSIZ); \
369 else \
370 separator = 1; \
371 strlcat (logbuf, STR, BUFSIZ); \
372 }
373
374 strlcpy (logbuf, " <", BUFSIZ);
375 IFF_OUT_LOG (IFF_UP, "UP");
376 IFF_OUT_LOG (IFF_BROADCAST, "BROADCAST");
377 IFF_OUT_LOG (IFF_DEBUG, "DEBUG");
378 IFF_OUT_LOG (IFF_LOOPBACK, "LOOPBACK");
379 IFF_OUT_LOG (IFF_POINTOPOINT, "POINTOPOINT");
380 IFF_OUT_LOG (IFF_NOTRAILERS, "NOTRAILERS");
381 IFF_OUT_LOG (IFF_RUNNING, "RUNNING");
382 IFF_OUT_LOG (IFF_NOARP, "NOARP");
383 IFF_OUT_LOG (IFF_PROMISC, "PROMISC");
384 IFF_OUT_LOG (IFF_ALLMULTI, "ALLMULTI");
385 IFF_OUT_LOG (IFF_OACTIVE, "OACTIVE");
386 IFF_OUT_LOG (IFF_SIMPLEX, "SIMPLEX");
387 IFF_OUT_LOG (IFF_LINK0, "LINK0");
388 IFF_OUT_LOG (IFF_LINK1, "LINK1");
389 IFF_OUT_LOG (IFF_LINK2, "LINK2");
390 IFF_OUT_LOG (IFF_MULTICAST, "MULTICAST");
391
392 strlcat (logbuf, ">", BUFSIZ);
393
394 return logbuf;
395}
396
397/* For debugging */
398void
399if_dump (struct interface *ifp)
400{
401 listnode node;
402
403 zlog_info ("Interface %s index %d metric %d mtu %d %s",
404 ifp->name, ifp->ifindex, ifp->metric, ifp->mtu,
405 if_flag_dump (ifp->flags));
406
407 for (node = listhead (ifp->connected); node; nextnode (node))
408 ;
409}
410
411/* Interface printing for all interface. */
412void
413if_dump_all ()
414{
415 listnode node;
416
417 for (node = listhead (iflist); node; nextnode (node))
418 if_dump (getdata (node));
419}
420
421DEFUN (interface_desc,
422 interface_desc_cmd,
423 "description .LINE",
424 "Interface specific description\n"
425 "Characters describing this interface\n")
426{
427 int i;
428 struct interface *ifp;
429 struct buffer *b;
430
431 if (argc == 0)
432 return CMD_SUCCESS;
433
434 ifp = vty->index;
435 if (ifp->desc)
436 XFREE (0, ifp->desc);
437
438 b = buffer_new (1024);
439 for (i = 0; i < argc; i++)
440 {
441 buffer_putstr (b, (u_char *)argv[i]);
442 buffer_putc (b, ' ');
443 }
444 buffer_putc (b, '\0');
445
446 ifp->desc = buffer_getstr (b);
447 buffer_free (b);
448
449 return CMD_SUCCESS;
450}
451
452DEFUN (no_interface_desc,
453 no_interface_desc_cmd,
454 "no description",
455 NO_STR
456 "Interface specific description\n")
457{
458 struct interface *ifp;
459
460 ifp = vty->index;
461 if (ifp->desc)
462 XFREE (0, ifp->desc);
463 ifp->desc = NULL;
464
465 return CMD_SUCCESS;
466}
467
468
469/* See also wrapper function zebra_interface() in zebra/interface.c */
470DEFUN (interface,
471 interface_cmd,
472 "interface IFNAME",
473 "Select an interface to configure\n"
474 "Interface's name\n")
475{
476 struct interface *ifp;
477
478 ifp = if_lookup_by_name (argv[0]);
479
480 if (ifp == NULL)
hassoa9395142003-06-05 17:50:01 +0000481 ifp = if_create (argv[0], INTERFACE_NAMSIZ);
paul718e3742002-12-13 20:15:29 +0000482 vty->index = ifp;
483 vty->node = INTERFACE_NODE;
484
485 return CMD_SUCCESS;
486}
487
paul32d24632003-05-23 09:25:20 +0000488DEFUN_NOSH (no_interface,
489 no_interface_cmd,
490 "no interface IFNAME",
491 NO_STR
492 "Delete a pseudo interface's configuration\n"
493 "Interface's name\n")
494{
495 // deleting interface
496 struct interface *ifp;
497
498 ifp = if_lookup_by_name (argv[0]);
499
500 if (ifp == NULL)
paulbfc13532003-05-24 06:40:04 +0000501 {
502 vty_out (vty, "%% Inteface %s does not exist%s", argv[0], VTY_NEWLINE);
503 return CMD_WARNING;
504 }
paul32d24632003-05-23 09:25:20 +0000505
paulbfc13532003-05-24 06:40:04 +0000506 if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
507 {
paul32d24632003-05-23 09:25:20 +0000508 vty_out (vty, "%% Only inactive interfaces can be deleted%s",
509 VTY_NEWLINE);
510 return CMD_WARNING;
511 }
512
513 if_delete(ifp);
514
515 return CMD_SUCCESS;
516}
517
paul718e3742002-12-13 20:15:29 +0000518/* For debug purpose. */
519DEFUN (show_address,
520 show_address_cmd,
521 "show address",
522 SHOW_STR
523 "address\n")
524{
525 listnode node;
526 listnode node2;
527 struct interface *ifp;
528 struct connected *ifc;
529 struct prefix *p;
530
531 for (node = listhead (iflist); node; nextnode (node))
532 {
533 ifp = getdata (node);
534
535 for (node2 = listhead (ifp->connected); node2; nextnode (node2))
536 {
537 ifc = getdata (node2);
538 p = ifc->address;
539
540 if (p->family == AF_INET)
541 vty_out (vty, "%s/%d%s", inet_ntoa (p->u.prefix4), p->prefixlen,
542 VTY_NEWLINE);
543 }
544 }
545 return CMD_SUCCESS;
546}
547
548/* Allocate connected structure. */
549struct connected *
550connected_new ()
551{
552 struct connected *new = XMALLOC (MTYPE_CONNECTED, sizeof (struct connected));
553 memset (new, 0, sizeof (struct connected));
554 return new;
555}
556
557/* Free connected structure. */
558void
559connected_free (struct connected *connected)
560{
561 if (connected->address)
562 prefix_free (connected->address);
563
564 if (connected->destination)
565 prefix_free (connected->destination);
566
567 if (connected->label)
568 free (connected->label);
569
570 XFREE (MTYPE_CONNECTED, connected);
571}
572
573/* Print if_addr structure. */
574void
575connected_log (struct connected *connected, char *str)
576{
577 struct prefix *p;
578 struct interface *ifp;
579 char logbuf[BUFSIZ];
580 char buf[BUFSIZ];
581
582 ifp = connected->ifp;
583 p = connected->address;
584
585 snprintf (logbuf, BUFSIZ, "%s interface %s %s %s/%d ",
586 str, ifp->name, prefix_family_str (p),
587 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
588 p->prefixlen);
589
590 p = connected->destination;
591 if (p)
592 {
593 strncat (logbuf, inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
594 BUFSIZ - strlen(logbuf));
595 }
596 zlog (NULL, LOG_INFO, logbuf);
597}
598
599/* If two connected address has same prefix return 1. */
600int
601connected_same_prefix (struct prefix *p1, struct prefix *p2)
602{
603 if (p1->family == p2->family)
604 {
605 if (p1->family == AF_INET &&
606 IPV4_ADDR_SAME (&p1->u.prefix4, &p2->u.prefix4))
607 return 1;
608#ifdef HAVE_IPV6
609 if (p1->family == AF_INET6 &&
610 IPV6_ADDR_SAME (&p1->u.prefix6, &p2->u.prefix6))
611 return 1;
612#endif /* HAVE_IPV6 */
613 }
614 return 0;
615}
616
617struct connected *
618connected_delete_by_prefix (struct interface *ifp, struct prefix *p)
619{
620 struct listnode *node;
621 struct listnode *next;
622 struct connected *ifc;
623
624 /* In case of same prefix come, replace it with new one. */
625 for (node = listhead (ifp->connected); node; node = next)
626 {
627 ifc = getdata (node);
628 next = node->next;
629
630 if (connected_same_prefix (ifc->address, p))
631 {
632 listnode_delete (ifp->connected, ifc);
633 return ifc;
634 }
635 }
636 return NULL;
637}
638
paul727d1042002-12-13 20:50:29 +0000639/* Find the IPv4 address on our side that will be used when packets
640 are sent to dst. */
641struct connected *
642connected_lookup_address (struct interface *ifp, struct in_addr dst)
643{
644 struct prefix addr;
645 struct prefix best;
646 listnode cnode;
647 struct prefix *p;
648 struct connected *c;
649 struct connected *match;
650
651 /* Zero structures - get rid of rubbish from stack */
652 memset(&addr, 0, sizeof(addr));
653 memset(&best, 0, sizeof(best));
654
655 addr.family = AF_INET;
656 addr.u.prefix4 = dst;
657 addr.prefixlen = IPV4_MAX_BITLEN;
658
659 match = NULL;
660
661 for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
662 {
663 c = getdata (cnode);
664
665 if (if_is_pointopoint (ifp))
666 {
667 p = c->address;
668
669 if (p && p->family == AF_INET)
670 {
671#ifdef OLD_RIB /* PTP links are conventionally identified
672 by the address of the far end - MAG */
673 if (IPV4_ADDR_SAME (&p->u.prefix4, &dst))
674 return c;
675#endif
676 p = c->destination;
677 if (p && IPV4_ADDR_SAME (&p->u.prefix4, &dst))
678 return c;
679 }
680 }
681 else
682 {
683 p = c->address;
684
685 if (p->family == AF_INET)
686 {
687 if (prefix_match (p, &addr) && p->prefixlen > best.prefixlen)
688 {
689 best = *p;
690 match = c;
691 }
692 }
693 }
694 }
695 return match;
696}
697
paul718e3742002-12-13 20:15:29 +0000698/* Check the connected information is PtP style or not. */
699int
700ifc_pointopoint (struct connected *ifc)
701{
702 struct prefix *p;
703 int ptp = 0;
704
705 /* When interface has PtP flag. */
706 if (if_is_pointopoint (ifc->ifp))
707 return 1;
708
709 /* RFC3021 PtP check. */
710 p = ifc->address;
711
712 if (p->family == AF_INET)
713 ptp = (p->prefixlen >= IPV4_MAX_PREFIXLEN - 1);
714#ifdef HAVE_IPV6
715 if (p->family == AF_INET6)
716 ptp = (p->prefixlen >= IPV6_MAX_PREFIXLEN - 1);
717#endif /* HAVE_IPV6 */
718
719 return ptp;
720}
721
722#ifndef HAVE_IF_NAMETOINDEX
723unsigned int
724if_nametoindex (const char *name)
725{
726 listnode node;
727 struct interface *ifp;
728
729 for (node = listhead (iflist); node; nextnode (node))
730 {
731 ifp = getdata (node);
732 if (strcmp (ifp->name, name) == 0)
733 return ifp->ifindex;
734 }
735 return 0;
736}
737#endif
738
739#ifndef HAVE_IF_INDEXTONAME
740char *
741if_indextoname (unsigned int ifindex, char *name)
742{
743 listnode node;
744 struct interface *ifp;
745
746 for (node = listhead (iflist); node; nextnode (node))
747 {
748 ifp = getdata (node);
749 if (ifp->ifindex == ifindex)
750 {
751 memcpy (name, ifp->name, IFNAMSIZ);
752 return ifp->name;
753 }
754 }
755 return NULL;
756}
757#endif
758
759/* Interface looking up by interface's address. */
760
761/* Interface's IPv4 address reverse lookup table. */
762struct route_table *ifaddr_ipv4_table;
763/* struct route_table *ifaddr_ipv6_table; */
764
765void
766ifaddr_ipv4_add (struct in_addr *ifaddr, struct interface *ifp)
767{
768 struct route_node *rn;
769 struct prefix_ipv4 p;
770
771 p.family = AF_INET;
772 p.prefixlen = IPV4_MAX_PREFIXLEN;
773 p.prefix = *ifaddr;
774
775 rn = route_node_get (ifaddr_ipv4_table, (struct prefix *) &p);
776 if (rn)
777 {
778 route_unlock_node (rn);
779 zlog_info ("ifaddr_ipv4_add(): address %s is already added",
780 inet_ntoa (*ifaddr));
781 return;
782 }
783 rn->info = ifp;
784}
785
786void
787ifaddr_ipv4_delete (struct in_addr *ifaddr, struct interface *ifp)
788{
789 struct route_node *rn;
790 struct prefix_ipv4 p;
791
792 p.family = AF_INET;
793 p.prefixlen = IPV4_MAX_PREFIXLEN;
794 p.prefix = *ifaddr;
795
796 rn = route_node_lookup (ifaddr_ipv4_table, (struct prefix *) &p);
797 if (! rn)
798 {
799 zlog_info ("ifaddr_ipv4_delete(): can't find address %s",
800 inet_ntoa (*ifaddr));
801 return;
802 }
803 rn->info = NULL;
804 route_unlock_node (rn);
805 route_unlock_node (rn);
806}
807
808/* Lookup interface by interface's IP address or interface index. */
809struct interface *
810ifaddr_ipv4_lookup (struct in_addr *addr, unsigned int ifindex)
811{
812 struct prefix_ipv4 p;
813 struct route_node *rn;
814 struct interface *ifp;
815 listnode node;
816
817 if (addr)
818 {
819 p.family = AF_INET;
820 p.prefixlen = IPV4_MAX_PREFIXLEN;
821 p.prefix = *addr;
822
823 rn = route_node_lookup (ifaddr_ipv4_table, (struct prefix *) &p);
824 if (! rn)
825 return NULL;
826
827 ifp = rn->info;
828 route_unlock_node (rn);
829 return ifp;
830 }
831 else
832 {
833 for (node = listhead (iflist); node; nextnode (node))
834 {
835 ifp = getdata (node);
836
837 if (ifp->ifindex == ifindex)
838 return ifp;
839 }
840 }
841 return NULL;
842}
843
844/* Initialize interface list. */
845void
846if_init ()
847{
848 iflist = list_new ();
849 ifaddr_ipv4_table = route_table_init ();
850
hassoa9395142003-06-05 17:50:01 +0000851 if (iflist) {
852 iflist->cmp = (int (*)(void *, void *))if_cmp_func;
paul718e3742002-12-13 20:15:29 +0000853 return;
hassoa9395142003-06-05 17:50:01 +0000854 }
paul718e3742002-12-13 20:15:29 +0000855
856 memset (&if_master, 0, sizeof if_master);
857}