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