blob: 259b84231ca4c01ed6d6dd51843afa40e1810db5 [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"
paul718e3742002-12-13 20:15:29 +000033#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
paul3a0391a2004-07-17 11:51:29 +000049/* Compare interface names, returning an integer greater than, equal to, or
50 * less than 0, (following the strcmp convention), according to the
51 * relationship between ifp1 and ifp2. Interface names consist of an
52 * alphabetic prefix and a numeric suffix. The primary sort key is
53 * lexicographic by name, and then numeric by number. No number sorts
54 * before all numbers. Examples: de0 < de1, de100 < fxp0 < xl0, devpty <
55 * devpty0, de0 < del0
56 */
paul106d2fd2003-08-01 00:24:13 +000057int
58if_cmp_func (struct interface *ifp1, struct interface *ifp2)
59{
60 unsigned int l1, l2;
61 long int x1, x2;
62 char *p1, *p2;
63 int res;
64
65 p1 = ifp1->name;
66 p2 = ifp2->name;
67
paul90578522003-09-23 23:46:01 +000068 while (*p1 && *p2) {
paul106d2fd2003-08-01 00:24:13 +000069 /* look up to any number */
70 l1 = strcspn(p1, "0123456789");
71 l2 = strcspn(p2, "0123456789");
72
73 /* name lengths are different -> compare names */
74 if (l1 != l2)
75 return (strcmp(p1, p2));
76
paul3a0391a2004-07-17 11:51:29 +000077 /* Note that this relies on all numbers being less than all letters, so
78 * that de0 < del0.
79 */
paul106d2fd2003-08-01 00:24:13 +000080 res = strncmp(p1, p2, l1);
81
82 /* names are different -> compare them */
83 if (res)
84 return res;
85
86 /* with identical name part, go to numeric part */
paul106d2fd2003-08-01 00:24:13 +000087 p1 += l1;
88 p2 += l1;
89
paulb06c14f2004-07-09 12:24:42 +000090 if (!*p1)
91 return -1;
92 if (!*p2)
93 return 1;
94
paul106d2fd2003-08-01 00:24:13 +000095 x1 = strtol(p1, &p1, 10);
96 x2 = strtol(p2, &p2, 10);
97
98 /* let's compare numbers now */
99 if (x1 < x2)
100 return -1;
101 if (x1 > x2)
102 return 1;
103
104 /* numbers were equal, lets do it again..
105 (it happens with name like "eth123.456:789") */
106 }
paul90578522003-09-23 23:46:01 +0000107 if (*p1)
108 return 1;
109 if (*p2)
110 return -1;
111 return 0;
paul106d2fd2003-08-01 00:24:13 +0000112}
113
paul718e3742002-12-13 20:15:29 +0000114/* Create new interface structure. */
115struct interface *
116if_new ()
117{
118 struct interface *ifp;
119
120 ifp = XMALLOC (MTYPE_IF, sizeof (struct interface));
121 memset (ifp, 0, sizeof (struct interface));
122 return ifp;
123}
124
125struct interface *
paul9035efa2004-10-10 11:56:56 +0000126if_create (const char *name, int namelen)
paul718e3742002-12-13 20:15:29 +0000127{
128 struct interface *ifp;
129
130 ifp = if_new ();
131
paul106d2fd2003-08-01 00:24:13 +0000132 assert (name);
133 assert (namelen <= (INTERFACE_NAMSIZ + 1));
134 strncpy (ifp->name, name, namelen);
135 ifp->name[INTERFACE_NAMSIZ] = '\0';
hassoe90fbab2003-12-21 09:51:42 +0000136 if (if_lookup_by_name(ifp->name) == NULL)
137 listnode_add_sort (iflist, ifp);
paul718e3742002-12-13 20:15:29 +0000138 ifp->connected = list_new ();
139 ifp->connected->del = (void (*) (void *)) connected_free;
140
141 if (if_master.if_new_hook)
142 (*if_master.if_new_hook) (ifp);
143
144 return ifp;
145}
146
147/* Delete and free interface structure. */
148void
149if_delete (struct interface *ifp)
150{
151 listnode_delete (iflist, ifp);
152
153 if (if_master.if_delete_hook)
154 (*if_master.if_delete_hook) (ifp);
155
156 /* Free connected address list */
157 list_delete (ifp->connected);
158
159 XFREE (MTYPE_IF, ifp);
160}
161
162/* Add hook to interface master. */
163void
164if_add_hook (int type, int (*func)(struct interface *ifp))
165{
166 switch (type) {
167 case IF_NEW_HOOK:
168 if_master.if_new_hook = func;
169 break;
170 case IF_DELETE_HOOK:
171 if_master.if_delete_hook = func;
172 break;
173 default:
174 break;
175 }
176}
177
178/* Interface existance check by index. */
179struct interface *
180if_lookup_by_index (unsigned int index)
181{
hasso52dc7ee2004-09-23 19:18:23 +0000182 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000183 struct interface *ifp;
184
185 for (node = listhead (iflist); node; nextnode (node))
186 {
187 ifp = getdata (node);
188 if (ifp->ifindex == index)
189 return ifp;
190 }
191 return NULL;
192}
193
194char *
195ifindex2ifname (unsigned int index)
196{
hasso52dc7ee2004-09-23 19:18:23 +0000197 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000198 struct interface *ifp;
199
200 for (node = listhead (iflist); node; nextnode (node))
201 {
202 ifp = getdata (node);
203 if (ifp->ifindex == index)
204 return ifp->name;
205 }
hasso8c328f12004-10-05 21:01:23 +0000206 return (char *) "unknown";
paul718e3742002-12-13 20:15:29 +0000207}
208
209/* Interface existance check by interface name. */
210struct interface *
paul9035efa2004-10-10 11:56:56 +0000211if_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +0000212{
hasso52dc7ee2004-09-23 19:18:23 +0000213 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000214 struct interface *ifp;
215
216 for (node = listhead (iflist); node; nextnode (node))
217 {
218 ifp = getdata (node);
219 if (strncmp (name, ifp->name, sizeof ifp->name) == 0)
220 return ifp;
221 }
222 return NULL;
223}
224
225/* Lookup interface by IPv4 address. */
226struct interface *
227if_lookup_exact_address (struct in_addr src)
228{
hasso52dc7ee2004-09-23 19:18:23 +0000229 struct listnode *node;
230 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000231 struct interface *ifp;
232 struct prefix *p;
233 struct connected *c;
234
235 for (node = listhead (iflist); node; nextnode (node))
236 {
237 ifp = getdata (node);
238
239 for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
240 {
241 c = getdata (cnode);
242
243 p = c->address;
244
245 if (p && p->family == AF_INET)
246 {
247 if (IPV4_ADDR_SAME (&p->u.prefix4, &src))
248 return ifp;
249 }
250 }
251 }
252 return NULL;
253}
254
255/* Lookup interface by IPv4 address. */
256struct interface *
257if_lookup_address (struct in_addr src)
258{
hasso52dc7ee2004-09-23 19:18:23 +0000259 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000260 struct prefix addr;
261 struct prefix best;
hasso52dc7ee2004-09-23 19:18:23 +0000262 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000263 struct interface *ifp;
264 struct prefix *p;
265 struct connected *c;
266 struct interface *match;
267
268 /* Zero structures - get rid of rubbish from stack */
269 memset(&addr, 0, sizeof(addr));
270 memset(&best, 0, sizeof(best));
271
272 addr.family = AF_INET;
273 addr.u.prefix4 = src;
274 addr.prefixlen = IPV4_MAX_BITLEN;
275
276 match = NULL;
277
278 for (node = listhead (iflist); node; nextnode (node))
279 {
280 ifp = getdata (node);
281
282 for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
283 {
284 c = getdata (cnode);
285
paul31a476c2003-09-29 19:54:53 +0000286 if (if_is_pointopoint (ifp))
paul718e3742002-12-13 20:15:29 +0000287 {
paul31a476c2003-09-29 19:54:53 +0000288 p = c->address;
paul718e3742002-12-13 20:15:29 +0000289
paul31a476c2003-09-29 19:54:53 +0000290 if (p && p->family == AF_INET)
paul718e3742002-12-13 20:15:29 +0000291 {
paul31a476c2003-09-29 19:54:53 +0000292#ifdef OLD_RIB /* PTP links are conventionally identified
293 by the address of the far end - MAG */
294 if (IPV4_ADDR_SAME (&p->u.prefix4, &src))
295 return ifp;
296#endif
297 p = c->destination;
298 if (p && IPV4_ADDR_SAME (&p->u.prefix4, &src))
299 return ifp;
paul718e3742002-12-13 20:15:29 +0000300 }
paul31a476c2003-09-29 19:54:53 +0000301 }
302 else
303 {
304 p = c->address;
paul718e3742002-12-13 20:15:29 +0000305
paul31a476c2003-09-29 19:54:53 +0000306 if (p->family == AF_INET)
paul718e3742002-12-13 20:15:29 +0000307 {
paul31a476c2003-09-29 19:54:53 +0000308 if (prefix_match (p, &addr) && p->prefixlen > best.prefixlen)
309 {
310 best = *p;
311 match = ifp;
312 }
paul718e3742002-12-13 20:15:29 +0000313 }
314 }
315 }
316 }
317 return match;
318}
319
320/* Get interface by name if given name interface doesn't exist create
321 one. */
322struct interface *
paul9035efa2004-10-10 11:56:56 +0000323if_get_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +0000324{
325 struct interface *ifp;
326
327 ifp = if_lookup_by_name (name);
328 if (ifp == NULL)
paul106d2fd2003-08-01 00:24:13 +0000329 ifp = if_create (name, INTERFACE_NAMSIZ);
paul718e3742002-12-13 20:15:29 +0000330 return ifp;
331}
332
333/* Does interface up ? */
334int
335if_is_up (struct interface *ifp)
336{
337 return ifp->flags & IFF_UP;
338}
339
paul2e3b2e42002-12-13 21:03:13 +0000340/* Is interface running? */
341int
342if_is_running (struct interface *ifp)
343{
344 return ifp->flags & IFF_RUNNING;
345}
346
347/* Is the interface operative, eg. either UP & RUNNING
348 or UP & !ZEBRA_INTERFACE_LINK_DETECTION */
349int
350if_is_operative (struct interface *ifp)
351{
352 return ((ifp->flags & IFF_UP) &&
353 (ifp->flags & IFF_RUNNING || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)));
354}
355
paul718e3742002-12-13 20:15:29 +0000356/* Is this loopback interface ? */
357int
358if_is_loopback (struct interface *ifp)
359{
360 return ifp->flags & IFF_LOOPBACK;
361}
362
363/* Does this interface support broadcast ? */
364int
365if_is_broadcast (struct interface *ifp)
366{
367 return ifp->flags & IFF_BROADCAST;
368}
369
370/* Does this interface support broadcast ? */
371int
372if_is_pointopoint (struct interface *ifp)
373{
374 return ifp->flags & IFF_POINTOPOINT;
375}
376
377/* Does this interface support multicast ? */
378int
379if_is_multicast (struct interface *ifp)
380{
381 return ifp->flags & IFF_MULTICAST;
382}
383
384/* Printout flag information into log */
385const char *
386if_flag_dump (unsigned long flag)
387{
388 int separator = 0;
389 static char logbuf[BUFSIZ];
390
391#define IFF_OUT_LOG(X,STR) \
392 if ((X) && (flag & (X))) \
393 { \
394 if (separator) \
395 strlcat (logbuf, ",", BUFSIZ); \
396 else \
397 separator = 1; \
398 strlcat (logbuf, STR, BUFSIZ); \
399 }
400
401 strlcpy (logbuf, " <", BUFSIZ);
402 IFF_OUT_LOG (IFF_UP, "UP");
403 IFF_OUT_LOG (IFF_BROADCAST, "BROADCAST");
404 IFF_OUT_LOG (IFF_DEBUG, "DEBUG");
405 IFF_OUT_LOG (IFF_LOOPBACK, "LOOPBACK");
406 IFF_OUT_LOG (IFF_POINTOPOINT, "POINTOPOINT");
407 IFF_OUT_LOG (IFF_NOTRAILERS, "NOTRAILERS");
408 IFF_OUT_LOG (IFF_RUNNING, "RUNNING");
409 IFF_OUT_LOG (IFF_NOARP, "NOARP");
410 IFF_OUT_LOG (IFF_PROMISC, "PROMISC");
411 IFF_OUT_LOG (IFF_ALLMULTI, "ALLMULTI");
412 IFF_OUT_LOG (IFF_OACTIVE, "OACTIVE");
413 IFF_OUT_LOG (IFF_SIMPLEX, "SIMPLEX");
414 IFF_OUT_LOG (IFF_LINK0, "LINK0");
415 IFF_OUT_LOG (IFF_LINK1, "LINK1");
416 IFF_OUT_LOG (IFF_LINK2, "LINK2");
417 IFF_OUT_LOG (IFF_MULTICAST, "MULTICAST");
paul4a7aac12004-05-08 05:00:31 +0000418#ifdef SOLARIS_IPV6
419 IFF_OUT_LOG (IFF_IPV4, "IFF_IPv4");
420 IFF_OUT_LOG (IFF_IPV6, "IFF_IPv6");
421#endif /* SOLARIS_IPV6 */
paul718e3742002-12-13 20:15:29 +0000422
423 strlcat (logbuf, ">", BUFSIZ);
424
425 return logbuf;
426}
427
428/* For debugging */
429void
430if_dump (struct interface *ifp)
431{
hasso52dc7ee2004-09-23 19:18:23 +0000432 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000433
paul4a7aac12004-05-08 05:00:31 +0000434 zlog_info ("Interface %s index %d metric %d mtu %d "
435#ifdef HAVE_IPV6
436 "mtu6 %d "
437#endif /* HAVE_IPV6 */
438 "%s",
paul718e3742002-12-13 20:15:29 +0000439 ifp->name, ifp->ifindex, ifp->metric, ifp->mtu,
paul4a7aac12004-05-08 05:00:31 +0000440#ifdef HAVE_IPV6
441 ifp->mtu6,
442#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +0000443 if_flag_dump (ifp->flags));
444
445 for (node = listhead (ifp->connected); node; nextnode (node))
446 ;
447}
448
449/* Interface printing for all interface. */
450void
451if_dump_all ()
452{
hasso52dc7ee2004-09-23 19:18:23 +0000453 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000454
455 for (node = listhead (iflist); node; nextnode (node))
456 if_dump (getdata (node));
457}
458
459DEFUN (interface_desc,
460 interface_desc_cmd,
461 "description .LINE",
462 "Interface specific description\n"
463 "Characters describing this interface\n")
464{
465 int i;
466 struct interface *ifp;
467 struct buffer *b;
468
469 if (argc == 0)
470 return CMD_SUCCESS;
471
472 ifp = vty->index;
473 if (ifp->desc)
474 XFREE (0, ifp->desc);
475
476 b = buffer_new (1024);
477 for (i = 0; i < argc; i++)
478 {
paul02ff83c2004-06-11 11:27:03 +0000479 buffer_putstr (b, argv[i]);
paul718e3742002-12-13 20:15:29 +0000480 buffer_putc (b, ' ');
481 }
482 buffer_putc (b, '\0');
483
484 ifp->desc = buffer_getstr (b);
485 buffer_free (b);
486
487 return CMD_SUCCESS;
488}
489
490DEFUN (no_interface_desc,
491 no_interface_desc_cmd,
492 "no description",
493 NO_STR
494 "Interface specific description\n")
495{
496 struct interface *ifp;
497
498 ifp = vty->index;
499 if (ifp->desc)
500 XFREE (0, ifp->desc);
501 ifp->desc = NULL;
502
503 return CMD_SUCCESS;
504}
505
506
507/* See also wrapper function zebra_interface() in zebra/interface.c */
508DEFUN (interface,
509 interface_cmd,
510 "interface IFNAME",
511 "Select an interface to configure\n"
512 "Interface's name\n")
513{
514 struct interface *ifp;
515
516 ifp = if_lookup_by_name (argv[0]);
517
518 if (ifp == NULL)
paul106d2fd2003-08-01 00:24:13 +0000519 ifp = if_create (argv[0], INTERFACE_NAMSIZ);
paul718e3742002-12-13 20:15:29 +0000520 vty->index = ifp;
521 vty->node = INTERFACE_NODE;
522
523 return CMD_SUCCESS;
524}
525
paul32d24632003-05-23 09:25:20 +0000526DEFUN_NOSH (no_interface,
527 no_interface_cmd,
528 "no interface IFNAME",
529 NO_STR
530 "Delete a pseudo interface's configuration\n"
531 "Interface's name\n")
532{
533 // deleting interface
534 struct interface *ifp;
535
536 ifp = if_lookup_by_name (argv[0]);
537
538 if (ifp == NULL)
paulbfc13532003-05-24 06:40:04 +0000539 {
540 vty_out (vty, "%% Inteface %s does not exist%s", argv[0], VTY_NEWLINE);
541 return CMD_WARNING;
542 }
paul32d24632003-05-23 09:25:20 +0000543
paulbfc13532003-05-24 06:40:04 +0000544 if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
545 {
paul32d24632003-05-23 09:25:20 +0000546 vty_out (vty, "%% Only inactive interfaces can be deleted%s",
547 VTY_NEWLINE);
548 return CMD_WARNING;
549 }
550
551 if_delete(ifp);
552
553 return CMD_SUCCESS;
554}
555
paul718e3742002-12-13 20:15:29 +0000556/* For debug purpose. */
557DEFUN (show_address,
558 show_address_cmd,
559 "show address",
560 SHOW_STR
561 "address\n")
562{
hasso52dc7ee2004-09-23 19:18:23 +0000563 struct listnode *node;
564 struct listnode *node2;
paul718e3742002-12-13 20:15:29 +0000565 struct interface *ifp;
566 struct connected *ifc;
567 struct prefix *p;
568
569 for (node = listhead (iflist); node; nextnode (node))
570 {
571 ifp = getdata (node);
572
573 for (node2 = listhead (ifp->connected); node2; nextnode (node2))
574 {
575 ifc = getdata (node2);
576 p = ifc->address;
577
578 if (p->family == AF_INET)
579 vty_out (vty, "%s/%d%s", inet_ntoa (p->u.prefix4), p->prefixlen,
580 VTY_NEWLINE);
581 }
582 }
583 return CMD_SUCCESS;
584}
585
586/* Allocate connected structure. */
587struct connected *
588connected_new ()
589{
590 struct connected *new = XMALLOC (MTYPE_CONNECTED, sizeof (struct connected));
591 memset (new, 0, sizeof (struct connected));
592 return new;
593}
594
595/* Free connected structure. */
596void
597connected_free (struct connected *connected)
598{
599 if (connected->address)
600 prefix_free (connected->address);
601
602 if (connected->destination)
603 prefix_free (connected->destination);
604
605 if (connected->label)
606 free (connected->label);
607
608 XFREE (MTYPE_CONNECTED, connected);
609}
610
611/* Print if_addr structure. */
612void
613connected_log (struct connected *connected, char *str)
614{
615 struct prefix *p;
616 struct interface *ifp;
617 char logbuf[BUFSIZ];
618 char buf[BUFSIZ];
619
620 ifp = connected->ifp;
621 p = connected->address;
622
623 snprintf (logbuf, BUFSIZ, "%s interface %s %s %s/%d ",
624 str, ifp->name, prefix_family_str (p),
625 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
626 p->prefixlen);
627
628 p = connected->destination;
629 if (p)
630 {
631 strncat (logbuf, inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
632 BUFSIZ - strlen(logbuf));
633 }
634 zlog (NULL, LOG_INFO, logbuf);
635}
636
637/* If two connected address has same prefix return 1. */
638int
639connected_same_prefix (struct prefix *p1, struct prefix *p2)
640{
641 if (p1->family == p2->family)
642 {
643 if (p1->family == AF_INET &&
644 IPV4_ADDR_SAME (&p1->u.prefix4, &p2->u.prefix4))
645 return 1;
646#ifdef HAVE_IPV6
647 if (p1->family == AF_INET6 &&
648 IPV6_ADDR_SAME (&p1->u.prefix6, &p2->u.prefix6))
649 return 1;
650#endif /* HAVE_IPV6 */
651 }
652 return 0;
653}
654
655struct connected *
656connected_delete_by_prefix (struct interface *ifp, struct prefix *p)
657{
658 struct listnode *node;
659 struct listnode *next;
660 struct connected *ifc;
661
662 /* In case of same prefix come, replace it with new one. */
663 for (node = listhead (ifp->connected); node; node = next)
664 {
665 ifc = getdata (node);
666 next = node->next;
667
668 if (connected_same_prefix (ifc->address, p))
669 {
670 listnode_delete (ifp->connected, ifc);
671 return ifc;
672 }
673 }
674 return NULL;
675}
676
paul727d1042002-12-13 20:50:29 +0000677/* Find the IPv4 address on our side that will be used when packets
678 are sent to dst. */
679struct connected *
680connected_lookup_address (struct interface *ifp, struct in_addr dst)
681{
682 struct prefix addr;
683 struct prefix best;
hasso52dc7ee2004-09-23 19:18:23 +0000684 struct listnode *cnode;
paul727d1042002-12-13 20:50:29 +0000685 struct prefix *p;
686 struct connected *c;
687 struct connected *match;
688
689 /* Zero structures - get rid of rubbish from stack */
690 memset(&addr, 0, sizeof(addr));
691 memset(&best, 0, sizeof(best));
692
693 addr.family = AF_INET;
694 addr.u.prefix4 = dst;
695 addr.prefixlen = IPV4_MAX_BITLEN;
696
697 match = NULL;
698
699 for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
700 {
701 c = getdata (cnode);
702
703 if (if_is_pointopoint (ifp))
704 {
705 p = c->address;
706
707 if (p && p->family == AF_INET)
708 {
709#ifdef OLD_RIB /* PTP links are conventionally identified
710 by the address of the far end - MAG */
711 if (IPV4_ADDR_SAME (&p->u.prefix4, &dst))
712 return c;
713#endif
714 p = c->destination;
715 if (p && IPV4_ADDR_SAME (&p->u.prefix4, &dst))
716 return c;
717 }
718 }
719 else
720 {
721 p = c->address;
722
723 if (p->family == AF_INET)
724 {
725 if (prefix_match (p, &addr) && p->prefixlen > best.prefixlen)
726 {
727 best = *p;
728 match = c;
729 }
730 }
731 }
732 }
733 return match;
734}
735
paul4a7aac12004-05-08 05:00:31 +0000736struct connected *
737connected_add_by_prefix (struct interface *ifp, struct prefix *p,
738 struct prefix *destination)
739{
740 struct connected *ifc;
741
742 /* Allocate new connected address. */
743 ifc = connected_new ();
744 ifc->ifp = ifp;
745
746 /* Fetch interface address */
747 ifc->address = prefix_new();
748 memcpy (ifc->address, p, sizeof(struct prefix));
749
750 /* Fetch dest address */
751 ifc->destination = prefix_new();
752 memcpy (ifc->destination, destination, sizeof(struct prefix));
753
754 /* Add connected address to the interface. */
755 listnode_add (ifp->connected, ifc);
756 return ifc;
757}
758
paul718e3742002-12-13 20:15:29 +0000759#ifndef HAVE_IF_NAMETOINDEX
760unsigned int
761if_nametoindex (const char *name)
762{
hasso52dc7ee2004-09-23 19:18:23 +0000763 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000764 struct interface *ifp;
765
766 for (node = listhead (iflist); node; nextnode (node))
767 {
768 ifp = getdata (node);
769 if (strcmp (ifp->name, name) == 0)
770 return ifp->ifindex;
771 }
772 return 0;
773}
774#endif
775
776#ifndef HAVE_IF_INDEXTONAME
777char *
778if_indextoname (unsigned int ifindex, char *name)
779{
hasso52dc7ee2004-09-23 19:18:23 +0000780 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000781 struct interface *ifp;
782
783 for (node = listhead (iflist); node; nextnode (node))
784 {
785 ifp = getdata (node);
786 if (ifp->ifindex == ifindex)
787 {
788 memcpy (name, ifp->name, IFNAMSIZ);
789 return ifp->name;
790 }
791 }
792 return NULL;
793}
794#endif
795
796/* Interface looking up by interface's address. */
797
798/* Interface's IPv4 address reverse lookup table. */
799struct route_table *ifaddr_ipv4_table;
800/* struct route_table *ifaddr_ipv6_table; */
801
802void
803ifaddr_ipv4_add (struct in_addr *ifaddr, struct interface *ifp)
804{
805 struct route_node *rn;
806 struct prefix_ipv4 p;
807
808 p.family = AF_INET;
809 p.prefixlen = IPV4_MAX_PREFIXLEN;
810 p.prefix = *ifaddr;
811
812 rn = route_node_get (ifaddr_ipv4_table, (struct prefix *) &p);
813 if (rn)
814 {
815 route_unlock_node (rn);
816 zlog_info ("ifaddr_ipv4_add(): address %s is already added",
817 inet_ntoa (*ifaddr));
818 return;
819 }
820 rn->info = ifp;
821}
822
823void
824ifaddr_ipv4_delete (struct in_addr *ifaddr, struct interface *ifp)
825{
826 struct route_node *rn;
827 struct prefix_ipv4 p;
828
829 p.family = AF_INET;
830 p.prefixlen = IPV4_MAX_PREFIXLEN;
831 p.prefix = *ifaddr;
832
833 rn = route_node_lookup (ifaddr_ipv4_table, (struct prefix *) &p);
834 if (! rn)
835 {
836 zlog_info ("ifaddr_ipv4_delete(): can't find address %s",
837 inet_ntoa (*ifaddr));
838 return;
839 }
840 rn->info = NULL;
841 route_unlock_node (rn);
842 route_unlock_node (rn);
843}
844
845/* Lookup interface by interface's IP address or interface index. */
846struct interface *
847ifaddr_ipv4_lookup (struct in_addr *addr, unsigned int ifindex)
848{
849 struct prefix_ipv4 p;
850 struct route_node *rn;
851 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +0000852 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000853
854 if (addr)
855 {
856 p.family = AF_INET;
857 p.prefixlen = IPV4_MAX_PREFIXLEN;
858 p.prefix = *addr;
859
860 rn = route_node_lookup (ifaddr_ipv4_table, (struct prefix *) &p);
861 if (! rn)
862 return NULL;
863
864 ifp = rn->info;
865 route_unlock_node (rn);
866 return ifp;
867 }
868 else
869 {
870 for (node = listhead (iflist); node; nextnode (node))
871 {
872 ifp = getdata (node);
873
874 if (ifp->ifindex == ifindex)
875 return ifp;
876 }
877 }
878 return NULL;
879}
880
881/* Initialize interface list. */
882void
883if_init ()
884{
885 iflist = list_new ();
886 ifaddr_ipv4_table = route_table_init ();
887
paul106d2fd2003-08-01 00:24:13 +0000888 if (iflist) {
889 iflist->cmp = (int (*)(void *, void *))if_cmp_func;
paul718e3742002-12-13 20:15:29 +0000890 return;
paul106d2fd2003-08-01 00:24:13 +0000891 }
paul718e3742002-12-13 20:15:29 +0000892
893 memset (&if_master, 0, sizeof if_master);
894}