Line data Source code
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"
30 : #include "if.h"
31 : #include "sockunion.h"
32 : #include "prefix.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. */
40 : struct list *iflist;
41 :
42 : /* One for each program. This structure is needed to store hooks. */
43 : struct if_master
44 : {
45 : int (*if_new_hook) (struct interface *);
46 : int (*if_delete_hook) (struct interface *);
47 : } if_master;
48 :
49 : /* 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 : */
57 : int
58 139 : if_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 139 : p1 = ifp1->name;
66 139 : p2 = ifp2->name;
67 :
68 278 : while (*p1 && *p2) {
69 : /* look up to any number */
70 139 : l1 = strcspn(p1, "0123456789");
71 139 : l2 = strcspn(p2, "0123456789");
72 :
73 : /* name lengths are different -> compare names */
74 139 : if (l1 != l2)
75 89 : return (strcmp(p1, p2));
76 :
77 : /* Note that this relies on all numbers being less than all letters, so
78 : * that de0 < del0.
79 : */
80 50 : res = strncmp(p1, p2, l1);
81 :
82 : /* names are different -> compare them */
83 50 : if (res)
84 0 : return res;
85 :
86 : /* with identical name part, go to numeric part */
87 50 : p1 += l1;
88 50 : p2 += l1;
89 :
90 50 : if (!*p1)
91 0 : return -1;
92 50 : if (!*p2)
93 0 : return 1;
94 :
95 50 : x1 = strtol(p1, &p1, 10);
96 50 : x2 = strtol(p2, &p2, 10);
97 :
98 : /* let's compare numbers now */
99 50 : if (x1 < x2)
100 0 : return -1;
101 50 : if (x1 > x2)
102 50 : return 1;
103 :
104 : /* numbers were equal, lets do it again..
105 : (it happens with name like "eth123.456:789") */
106 : }
107 0 : if (*p1)
108 0 : return 1;
109 0 : if (*p2)
110 0 : return -1;
111 0 : return 0;
112 : }
113 :
114 : /* Create new interface structure. */
115 : struct interface *
116 134 : if_create (const char *name, int namelen)
117 : {
118 : struct interface *ifp;
119 :
120 134 : ifp = XCALLOC (MTYPE_IF, sizeof (struct interface));
121 134 : ifp->ifindex = IFINDEX_INTERNAL;
122 :
123 134 : assert (name);
124 134 : assert (namelen <= INTERFACE_NAMSIZ); /* Need space for '\0' at end. */
125 134 : strncpy (ifp->name, name, namelen);
126 134 : ifp->name[namelen] = '\0';
127 134 : if (if_lookup_by_name(ifp->name) == NULL)
128 134 : listnode_add_sort (iflist, ifp);
129 : else
130 0 : zlog_err("if_create(%s): corruption detected -- interface with this "
131 0 : "name exists already!", ifp->name);
132 134 : ifp->connected = list_new ();
133 134 : ifp->connected->del = (void (*) (void *)) connected_free;
134 :
135 134 : if (if_master.if_new_hook)
136 134 : (*if_master.if_new_hook) (ifp);
137 :
138 134 : return ifp;
139 : }
140 :
141 : /* Delete interface structure. */
142 : void
143 0 : if_delete_retain (struct interface *ifp)
144 : {
145 0 : if (if_master.if_delete_hook)
146 0 : (*if_master.if_delete_hook) (ifp);
147 :
148 : /* Free connected address list */
149 0 : list_delete_all_node (ifp->connected);
150 0 : }
151 :
152 : /* Delete and free interface structure. */
153 : void
154 0 : if_delete (struct interface *ifp)
155 : {
156 0 : listnode_delete (iflist, ifp);
157 :
158 0 : if_delete_retain(ifp);
159 :
160 0 : list_free (ifp->connected);
161 :
162 0 : XFREE (MTYPE_IF, ifp);
163 0 : }
164 :
165 : /* Add hook to interface master. */
166 : void
167 90 : if_add_hook (int type, int (*func)(struct interface *ifp))
168 : {
169 90 : switch (type) {
170 : case IF_NEW_HOOK:
171 45 : if_master.if_new_hook = func;
172 45 : break;
173 : case IF_DELETE_HOOK:
174 45 : if_master.if_delete_hook = func;
175 45 : break;
176 : default:
177 0 : break;
178 : }
179 90 : }
180 :
181 : /* Interface existance check by index. */
182 : struct interface *
183 2006 : if_lookup_by_index (unsigned int index)
184 : {
185 : struct listnode *node;
186 : struct interface *ifp;
187 :
188 4206 : for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp))
189 : {
190 4072 : if (ifp->ifindex == index)
191 1872 : return ifp;
192 : }
193 134 : return NULL;
194 : }
195 :
196 : const char *
197 668 : ifindex2ifname (unsigned int index)
198 : {
199 : struct interface *ifp;
200 :
201 668 : return ((ifp = if_lookup_by_index(index)) != NULL) ?
202 668 : ifp->name : "unknown";
203 : }
204 :
205 : unsigned int
206 10 : ifname2ifindex (const char *name)
207 : {
208 : struct interface *ifp;
209 :
210 10 : return ((ifp = if_lookup_by_name(name)) != NULL) ? ifp->ifindex
211 10 : : IFINDEX_INTERNAL;
212 : }
213 :
214 : /* Interface existance check by interface name. */
215 : struct interface *
216 291 : if_lookup_by_name (const char *name)
217 : {
218 : struct listnode *node;
219 : struct interface *ifp;
220 :
221 291 : if (name)
222 592 : for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
223 : {
224 324 : if (strcmp(name, ifp->name) == 0)
225 23 : return ifp;
226 : }
227 268 : return NULL;
228 : }
229 :
230 : struct interface *
231 1 : if_lookup_by_name_len(const char *name, size_t namelen)
232 : {
233 : struct listnode *node;
234 : struct interface *ifp;
235 :
236 1 : if (namelen > INTERFACE_NAMSIZ)
237 0 : return NULL;
238 :
239 2 : for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
240 : {
241 2 : if (!memcmp(name, ifp->name, namelen) && (ifp->name[namelen] == '\0'))
242 1 : return ifp;
243 : }
244 0 : return NULL;
245 : }
246 :
247 : /* Lookup interface by IPv4 address. */
248 : struct interface *
249 6 : if_lookup_exact_address (struct in_addr src)
250 : {
251 : struct listnode *node;
252 : struct listnode *cnode;
253 : struct interface *ifp;
254 : struct prefix *p;
255 : struct connected *c;
256 :
257 24 : for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
258 : {
259 60 : for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
260 : {
261 42 : p = c->address;
262 :
263 42 : if (p && p->family == AF_INET)
264 : {
265 24 : if (IPV4_ADDR_SAME (&p->u.prefix4, &src))
266 6 : return ifp;
267 : }
268 : }
269 : }
270 0 : return NULL;
271 : }
272 :
273 : /* Lookup interface by IPv4 address. */
274 : struct interface *
275 0 : if_lookup_address (struct in_addr src)
276 : {
277 : struct listnode *node;
278 : struct prefix addr;
279 0 : int bestlen = 0;
280 : struct listnode *cnode;
281 : struct interface *ifp;
282 : struct connected *c;
283 : struct interface *match;
284 :
285 0 : addr.family = AF_INET;
286 0 : addr.u.prefix4 = src;
287 0 : addr.prefixlen = IPV4_MAX_BITLEN;
288 :
289 0 : match = NULL;
290 :
291 0 : for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
292 : {
293 0 : for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
294 : {
295 0 : if (c->address && (c->address->family == AF_INET) &&
296 0 : prefix_match(CONNECTED_PREFIX(c), &addr) &&
297 0 : (c->address->prefixlen > bestlen))
298 : {
299 0 : bestlen = c->address->prefixlen;
300 0 : match = ifp;
301 : }
302 : }
303 : }
304 0 : return match;
305 : }
306 :
307 : /* Lookup interface by prefix */
308 : struct interface *
309 0 : if_lookup_prefix (struct prefix *prefix)
310 : {
311 : struct listnode *node;
312 : struct prefix addr;
313 0 : int bestlen = 0;
314 : struct listnode *cnode;
315 : struct interface *ifp;
316 : struct connected *c;
317 :
318 0 : for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
319 : {
320 0 : for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
321 : {
322 0 : if (prefix_cmp(c->address, prefix) == 0)
323 : {
324 0 : return ifp;
325 : }
326 : }
327 : }
328 0 : return NULL;
329 : }
330 :
331 : /* Get interface by name if given name interface doesn't exist create
332 : one. */
333 : struct interface *
334 134 : if_get_by_name (const char *name)
335 : {
336 : struct interface *ifp;
337 :
338 268 : return ((ifp = if_lookup_by_name(name)) != NULL) ? ifp :
339 134 : if_create(name, strlen(name));
340 : }
341 :
342 : struct interface *
343 1 : if_get_by_name_len(const char *name, size_t namelen)
344 : {
345 : struct interface *ifp;
346 :
347 1 : return ((ifp = if_lookup_by_name_len(name, namelen)) != NULL) ? ifp :
348 0 : if_create(name, namelen);
349 : }
350 :
351 : /* Does interface up ? */
352 : int
353 8 : if_is_up (struct interface *ifp)
354 : {
355 8 : return ifp->flags & IFF_UP;
356 : }
357 :
358 : /* Is interface running? */
359 : int
360 0 : if_is_running (struct interface *ifp)
361 : {
362 0 : return ifp->flags & IFF_RUNNING;
363 : }
364 :
365 : /* Is the interface operative, eg. either UP & RUNNING
366 : or UP & !ZEBRA_INTERFACE_LINK_DETECTION */
367 : int
368 1203 : if_is_operative (struct interface *ifp)
369 : {
370 3579 : return ((ifp->flags & IFF_UP) &&
371 1188 : (ifp->flags & IFF_RUNNING || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)));
372 : }
373 :
374 : /* Is this loopback interface ? */
375 : int
376 0 : if_is_loopback (struct interface *ifp)
377 : {
378 : /* XXX: Do this better, eg what if IFF_WHATEVER means X on platform M
379 : * but Y on platform N?
380 : */
381 0 : return (ifp->flags & (IFF_LOOPBACK|IFF_NOXMIT|IFF_VIRTUAL));
382 : }
383 :
384 : /* Does this interface support broadcast ? */
385 : int
386 0 : if_is_broadcast (struct interface *ifp)
387 : {
388 0 : return ifp->flags & IFF_BROADCAST;
389 : }
390 :
391 : /* Does this interface support broadcast ? */
392 : int
393 6 : if_is_pointopoint (struct interface *ifp)
394 : {
395 6 : return ifp->flags & IFF_POINTOPOINT;
396 : }
397 :
398 : /* Does this interface support multicast ? */
399 : int
400 0 : if_is_multicast (struct interface *ifp)
401 : {
402 0 : return ifp->flags & IFF_MULTICAST;
403 : }
404 :
405 : /* Printout flag information into log */
406 : const char *
407 6 : if_flag_dump (unsigned long flag)
408 : {
409 6 : int separator = 0;
410 : static char logbuf[BUFSIZ];
411 :
412 : #define IFF_OUT_LOG(X,STR) \
413 : if (flag & (X)) \
414 : { \
415 : if (separator) \
416 : strlcat (logbuf, ",", BUFSIZ); \
417 : else \
418 : separator = 1; \
419 : strlcat (logbuf, STR, BUFSIZ); \
420 : }
421 :
422 6 : strlcpy (logbuf, "<", BUFSIZ);
423 6 : IFF_OUT_LOG (IFF_UP, "UP");
424 6 : IFF_OUT_LOG (IFF_BROADCAST, "BROADCAST");
425 6 : IFF_OUT_LOG (IFF_DEBUG, "DEBUG");
426 6 : IFF_OUT_LOG (IFF_LOOPBACK, "LOOPBACK");
427 6 : IFF_OUT_LOG (IFF_POINTOPOINT, "POINTOPOINT");
428 6 : IFF_OUT_LOG (IFF_NOTRAILERS, "NOTRAILERS");
429 6 : IFF_OUT_LOG (IFF_RUNNING, "RUNNING");
430 6 : IFF_OUT_LOG (IFF_NOARP, "NOARP");
431 6 : IFF_OUT_LOG (IFF_PROMISC, "PROMISC");
432 6 : IFF_OUT_LOG (IFF_ALLMULTI, "ALLMULTI");
433 : IFF_OUT_LOG (IFF_OACTIVE, "OACTIVE");
434 : IFF_OUT_LOG (IFF_SIMPLEX, "SIMPLEX");
435 : IFF_OUT_LOG (IFF_LINK0, "LINK0");
436 : IFF_OUT_LOG (IFF_LINK1, "LINK1");
437 : IFF_OUT_LOG (IFF_LINK2, "LINK2");
438 6 : IFF_OUT_LOG (IFF_MULTICAST, "MULTICAST");
439 : IFF_OUT_LOG (IFF_NOXMIT, "NOXMIT");
440 : IFF_OUT_LOG (IFF_NORTEXCH, "NORTEXCH");
441 : IFF_OUT_LOG (IFF_VIRTUAL, "VIRTUAL");
442 : IFF_OUT_LOG (IFF_IPV4, "IPv4");
443 : IFF_OUT_LOG (IFF_IPV6, "IPv6");
444 :
445 6 : strlcat (logbuf, ">", BUFSIZ);
446 :
447 6 : return logbuf;
448 : #undef IFF_OUT_LOG
449 : }
450 :
451 : /* For debugging */
452 : static void
453 0 : if_dump (const struct interface *ifp)
454 : {
455 : struct listnode *node;
456 : struct connected *c;
457 :
458 0 : for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, c))
459 0 : zlog_info ("Interface %s index %d metric %d mtu %d "
460 : #ifdef HAVE_IPV6
461 : "mtu6 %d "
462 : #endif /* HAVE_IPV6 */
463 : "%s",
464 0 : ifp->name, ifp->ifindex, ifp->metric, ifp->mtu,
465 : #ifdef HAVE_IPV6
466 : ifp->mtu6,
467 : #endif /* HAVE_IPV6 */
468 : if_flag_dump (ifp->flags));
469 0 : }
470 :
471 : /* Interface printing for all interface. */
472 : void
473 0 : if_dump_all (void)
474 : {
475 : struct listnode *node;
476 : void *p;
477 :
478 0 : for (ALL_LIST_ELEMENTS_RO (iflist, node, p))
479 0 : if_dump (p);
480 0 : }
481 :
482 0 : DEFUN (interface_desc,
483 : interface_desc_cmd,
484 : "description .LINE",
485 : "Interface specific description\n"
486 : "Characters describing this interface\n")
487 : {
488 : struct interface *ifp;
489 :
490 0 : if (argc == 0)
491 0 : return CMD_SUCCESS;
492 :
493 0 : ifp = vty->index;
494 0 : if (ifp->desc)
495 0 : XFREE (MTYPE_TMP, ifp->desc);
496 0 : ifp->desc = argv_concat(argv, argc, 0);
497 :
498 0 : return CMD_SUCCESS;
499 : }
500 :
501 0 : DEFUN (no_interface_desc,
502 : no_interface_desc_cmd,
503 : "no description",
504 : NO_STR
505 : "Interface specific description\n")
506 : {
507 : struct interface *ifp;
508 :
509 0 : ifp = vty->index;
510 0 : if (ifp->desc)
511 0 : XFREE (MTYPE_TMP, ifp->desc);
512 0 : ifp->desc = NULL;
513 :
514 0 : return CMD_SUCCESS;
515 : }
516 :
517 : #ifdef SUNOS_5
518 : /* Need to handle upgrade from SUNWzebra to Quagga. SUNWzebra created
519 : * a seperate struct interface for each logical interface, so config
520 : * file may be full of 'interface fooX:Y'. Solaris however does not
521 : * expose logical interfaces via PF_ROUTE, so trying to track logical
522 : * interfaces can be fruitless, for that reason Quagga only tracks
523 : * the primary IP interface.
524 : *
525 : * We try accomodate SUNWzebra by:
526 : * - looking up the interface name, to see whether it exists, if so
527 : * its useable
528 : * - for protocol daemons, this could only because zebra told us of
529 : * the interface
530 : * - for zebra, only because it learnt from kernel
531 : * - if not:
532 : * - search the name to see if it contains a sub-ipif / logical interface
533 : * seperator, the ':' char. If it does:
534 : * - text up to that char must be the primary name - get that name.
535 : * if not:
536 : * - no idea, just get the name in its entirety.
537 : */
538 : static struct interface *
539 : if_sunwzebra_get (const char *name, size_t nlen)
540 : {
541 : struct interface *ifp;
542 : size_t seppos = 0;
543 :
544 : if ( (ifp = if_lookup_by_name_len(name, nlen)) != NULL)
545 : return ifp;
546 :
547 : /* hunt the primary interface name... */
548 : while (seppos < nlen && name[seppos] != ':')
549 : seppos++;
550 :
551 : /* Wont catch seperator as last char, e.g. 'foo0:' but thats invalid */
552 : if (seppos < nlen)
553 : return if_get_by_name_len (name, seppos);
554 : else
555 : return if_get_by_name_len (name, nlen);
556 : }
557 : #endif /* SUNOS_5 */
558 :
559 1 : DEFUN (interface,
560 : interface_cmd,
561 : "interface IFNAME",
562 : "Select an interface to configure\n"
563 : "Interface's name\n")
564 : {
565 : struct interface *ifp;
566 : size_t sl;
567 :
568 1 : if ((sl = strlen(argv[0])) > INTERFACE_NAMSIZ)
569 : {
570 0 : vty_out (vty, "%% Interface name %s is invalid: length exceeds "
571 : "%d characters%s",
572 0 : argv[0], INTERFACE_NAMSIZ, VTY_NEWLINE);
573 0 : return CMD_WARNING;
574 : }
575 :
576 : #ifdef SUNOS_5
577 : ifp = if_sunwzebra_get (argv[0], sl);
578 : #else
579 1 : ifp = if_get_by_name_len(argv[0], sl);
580 : #endif /* SUNOS_5 */
581 :
582 1 : vty->index = ifp;
583 1 : vty->node = INTERFACE_NODE;
584 :
585 1 : return CMD_SUCCESS;
586 : }
587 :
588 0 : DEFUN_NOSH (no_interface,
589 : no_interface_cmd,
590 : "no interface IFNAME",
591 : NO_STR
592 : "Delete a pseudo interface's configuration\n"
593 : "Interface's name\n")
594 : {
595 : // deleting interface
596 : struct interface *ifp;
597 :
598 0 : ifp = if_lookup_by_name (argv[0]);
599 :
600 0 : if (ifp == NULL)
601 : {
602 0 : vty_out (vty, "%% Interface %s does not exist%s", argv[0], VTY_NEWLINE);
603 0 : return CMD_WARNING;
604 : }
605 :
606 0 : if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
607 : {
608 0 : vty_out (vty, "%% Only inactive interfaces can be deleted%s",
609 0 : VTY_NEWLINE);
610 0 : return CMD_WARNING;
611 : }
612 :
613 0 : if_delete(ifp);
614 :
615 0 : return CMD_SUCCESS;
616 : }
617 :
618 : /* For debug purpose. */
619 0 : DEFUN (show_address,
620 : show_address_cmd,
621 : "show address",
622 : SHOW_STR
623 : "address\n")
624 : {
625 : struct listnode *node;
626 : struct listnode *node2;
627 : struct interface *ifp;
628 : struct connected *ifc;
629 : struct prefix *p;
630 :
631 0 : for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
632 : {
633 0 : for (ALL_LIST_ELEMENTS_RO (ifp->connected, node2, ifc))
634 : {
635 0 : p = ifc->address;
636 :
637 0 : if (p->family == AF_INET)
638 0 : vty_out (vty, "%s/%d%s", inet_ntoa (p->u.prefix4), p->prefixlen,
639 0 : VTY_NEWLINE);
640 : }
641 : }
642 0 : return CMD_SUCCESS;
643 : }
644 :
645 : /* Allocate connected structure. */
646 : struct connected *
647 281 : connected_new (void)
648 : {
649 281 : return XCALLOC (MTYPE_CONNECTED, sizeof (struct connected));
650 : }
651 :
652 : /* Free connected structure. */
653 : void
654 9 : connected_free (struct connected *connected)
655 : {
656 9 : if (connected->address)
657 9 : prefix_free (connected->address);
658 :
659 9 : if (connected->destination)
660 1 : prefix_free (connected->destination);
661 :
662 9 : if (connected->label)
663 0 : XFREE (MTYPE_CONNECTED_LABEL, connected->label);
664 :
665 9 : XFREE (MTYPE_CONNECTED, connected);
666 9 : }
667 :
668 : /* Print if_addr structure. */
669 : static void __attribute__ ((unused))
670 0 : connected_log (struct connected *connected, char *str)
671 : {
672 : struct prefix *p;
673 : struct interface *ifp;
674 : char logbuf[BUFSIZ];
675 : char buf[BUFSIZ];
676 :
677 0 : ifp = connected->ifp;
678 0 : p = connected->address;
679 :
680 0 : snprintf (logbuf, BUFSIZ, "%s interface %s %s %s/%d ",
681 0 : str, ifp->name, prefix_family_str (p),
682 0 : inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
683 0 : p->prefixlen);
684 :
685 0 : p = connected->destination;
686 0 : if (p)
687 : {
688 0 : strncat (logbuf, inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
689 0 : BUFSIZ - strlen(logbuf));
690 : }
691 0 : zlog (NULL, LOG_INFO, "%s", logbuf);
692 0 : }
693 :
694 : /* If two connected address has same prefix return 1. */
695 : static int
696 0 : connected_same_prefix (struct prefix *p1, struct prefix *p2)
697 : {
698 0 : if (p1->family == p2->family)
699 : {
700 0 : if (p1->family == AF_INET &&
701 0 : IPV4_ADDR_SAME (&p1->u.prefix4, &p2->u.prefix4))
702 0 : return 1;
703 : #ifdef HAVE_IPV6
704 0 : if (p1->family == AF_INET6 &&
705 0 : IPV6_ADDR_SAME (&p1->u.prefix6, &p2->u.prefix6))
706 0 : return 1;
707 : #endif /* HAVE_IPV6 */
708 : }
709 0 : return 0;
710 : }
711 :
712 : struct connected *
713 0 : connected_delete_by_prefix (struct interface *ifp, struct prefix *p)
714 : {
715 : struct listnode *node;
716 : struct listnode *next;
717 : struct connected *ifc;
718 :
719 : /* In case of same prefix come, replace it with new one. */
720 0 : for (node = listhead (ifp->connected); node; node = next)
721 : {
722 0 : ifc = listgetdata (node);
723 0 : next = node->next;
724 :
725 0 : if (connected_same_prefix (ifc->address, p))
726 : {
727 0 : listnode_delete (ifp->connected, ifc);
728 0 : return ifc;
729 : }
730 : }
731 0 : return NULL;
732 : }
733 :
734 : /* Find the IPv4 address on our side that will be used when packets
735 : are sent to dst. */
736 : struct connected *
737 0 : connected_lookup_address (struct interface *ifp, struct in_addr dst)
738 : {
739 : struct prefix addr;
740 : struct listnode *cnode;
741 : struct connected *c;
742 : struct connected *match;
743 :
744 0 : addr.family = AF_INET;
745 0 : addr.u.prefix4 = dst;
746 0 : addr.prefixlen = IPV4_MAX_BITLEN;
747 :
748 0 : match = NULL;
749 :
750 0 : for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
751 : {
752 0 : if (c->address && (c->address->family == AF_INET) &&
753 0 : prefix_match(CONNECTED_PREFIX(c), &addr) &&
754 0 : (!match || (c->address->prefixlen > match->address->prefixlen)))
755 0 : match = c;
756 : }
757 0 : return match;
758 : }
759 :
760 : struct connected *
761 0 : connected_add_by_prefix (struct interface *ifp, struct prefix *p,
762 : struct prefix *destination)
763 : {
764 : struct connected *ifc;
765 :
766 : /* Allocate new connected address. */
767 0 : ifc = connected_new ();
768 0 : ifc->ifp = ifp;
769 :
770 : /* Fetch interface address */
771 0 : ifc->address = prefix_new();
772 0 : memcpy (ifc->address, p, sizeof(struct prefix));
773 :
774 : /* Fetch dest address */
775 0 : if (destination)
776 : {
777 0 : ifc->destination = prefix_new();
778 0 : memcpy (ifc->destination, destination, sizeof(struct prefix));
779 : }
780 :
781 : /* Add connected address to the interface. */
782 0 : listnode_add (ifp->connected, ifc);
783 0 : return ifc;
784 : }
785 :
786 : #ifndef HAVE_IF_NAMETOINDEX
787 : unsigned int
788 : if_nametoindex (const char *name)
789 : {
790 : struct interface *ifp;
791 :
792 : return ((ifp = if_lookup_by_name_len(name, strnlen(name, IFNAMSIZ))) != NULL)
793 : ? ifp->ifindex : 0;
794 : }
795 : #endif
796 :
797 : #ifndef HAVE_IF_INDEXTONAME
798 : char *
799 : if_indextoname (unsigned int ifindex, char *name)
800 : {
801 : struct interface *ifp;
802 :
803 : if (!(ifp = if_lookup_by_index(ifindex)))
804 : return NULL;
805 : strncpy (name, ifp->name, IFNAMSIZ);
806 : return ifp->name;
807 : }
808 : #endif
809 :
810 : #if 0 /* this route_table of struct connected's is unused
811 : * however, it would be good to use a route_table rather than
812 : * a list..
813 : */
814 : /* Interface looking up by interface's address. */
815 : /* Interface's IPv4 address reverse lookup table. */
816 : struct route_table *ifaddr_ipv4_table;
817 : /* struct route_table *ifaddr_ipv6_table; */
818 :
819 : static void
820 : ifaddr_ipv4_add (struct in_addr *ifaddr, struct interface *ifp)
821 : {
822 : struct route_node *rn;
823 : struct prefix_ipv4 p;
824 :
825 : p.family = AF_INET;
826 : p.prefixlen = IPV4_MAX_PREFIXLEN;
827 : p.prefix = *ifaddr;
828 :
829 : rn = route_node_get (ifaddr_ipv4_table, (struct prefix *) &p);
830 : if (rn)
831 : {
832 : route_unlock_node (rn);
833 : zlog_info ("ifaddr_ipv4_add(): address %s is already added",
834 : inet_ntoa (*ifaddr));
835 : return;
836 : }
837 : rn->info = ifp;
838 : }
839 :
840 : static void
841 : ifaddr_ipv4_delete (struct in_addr *ifaddr, struct interface *ifp)
842 : {
843 : struct route_node *rn;
844 : struct prefix_ipv4 p;
845 :
846 : p.family = AF_INET;
847 : p.prefixlen = IPV4_MAX_PREFIXLEN;
848 : p.prefix = *ifaddr;
849 :
850 : rn = route_node_lookup (ifaddr_ipv4_table, (struct prefix *) &p);
851 : if (! rn)
852 : {
853 : zlog_info ("ifaddr_ipv4_delete(): can't find address %s",
854 : inet_ntoa (*ifaddr));
855 : return;
856 : }
857 : rn->info = NULL;
858 : route_unlock_node (rn);
859 : route_unlock_node (rn);
860 : }
861 :
862 : /* Lookup interface by interface's IP address or interface index. */
863 : static struct interface *
864 : ifaddr_ipv4_lookup (struct in_addr *addr, unsigned int ifindex)
865 : {
866 : struct prefix_ipv4 p;
867 : struct route_node *rn;
868 : struct interface *ifp;
869 :
870 : if (addr)
871 : {
872 : p.family = AF_INET;
873 : p.prefixlen = IPV4_MAX_PREFIXLEN;
874 : p.prefix = *addr;
875 :
876 : rn = route_node_lookup (ifaddr_ipv4_table, (struct prefix *) &p);
877 : if (! rn)
878 : return NULL;
879 :
880 : ifp = rn->info;
881 : route_unlock_node (rn);
882 : return ifp;
883 : }
884 : else
885 : return if_lookup_by_index(ifindex);
886 : }
887 : #endif /* ifaddr_ipv4_table */
888 :
889 : /* Initialize interface list. */
890 : void
891 45 : if_init (void)
892 : {
893 45 : iflist = list_new ();
894 : #if 0
895 : ifaddr_ipv4_table = route_table_init ();
896 : #endif /* ifaddr_ipv4_table */
897 :
898 45 : if (iflist) {
899 45 : iflist->cmp = (int (*)(void *, void *))if_cmp_func;
900 45 : return;
901 : }
902 :
903 0 : memset (&if_master, 0, sizeof if_master);
904 : }
905 :
906 : void
907 0 : if_terminate (void)
908 : {
909 : for (;;)
910 : {
911 : struct interface *ifp;
912 :
913 0 : ifp = listnode_head (iflist);
914 0 : if (ifp == NULL)
915 0 : break;
916 :
917 0 : if_delete (ifp);
918 0 : }
919 :
920 0 : list_delete (iflist);
921 0 : iflist = NULL;
922 0 : }
|