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