3 * Copyright (C) 1997, 2000
5 * Swedish University of Agricultural Sciences
9 * Thanks to Jens Laas at Swedish University of Agricultural Sciences
10 * for reviewing and tests.
12 * This file is part of GNU Zebra.
14 * GNU Zebra is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2, or (at your option) any
19 * GNU Zebra is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
24 * You should have received a copy of the GNU General Public License along
25 * with this program; see the file COPYING; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33 #include "sockunion.h"
39 #include "connected.h"
43 #include "lib_errors.h"
44 #include "zebra/interface.h"
45 #include "zebra/rtadv.h"
46 #include "zebra/rib.h"
47 #include "zebra/zebra_router.h"
48 #include "zebra/redistribute.h"
49 #include "zebra/irdp.h"
50 #include "zebra/zebra_errors.h"
51 #include <netinet/ip_icmp.h>
53 #include "sockunion.h"
59 DEFINE_MTYPE_STATIC(ZEBRA
, IRDP_IF
, "IRDP interface data");
61 #define IRDP_CONFIGED \
65 "Please Configure IRDP before using this command\n"); \
66 return CMD_WARNING_CONFIG_FAILED; \
70 static struct irdp_interface
*irdp_if_get(struct interface
*ifp
)
72 struct zebra_if
*zi
= ifp
->info
;
78 zi
->irdp
= XCALLOC(MTYPE_IRDP_IF
, sizeof(*zi
->irdp
));
80 if (!zi
->irdp
->started
)
86 static int irdp_if_delete(struct interface
*ifp
)
88 struct zebra_if
*zi
= ifp
->info
;
91 XFREE(MTYPE_IRDP_IF
, zi
->irdp
);
95 static const char *inet_2a(uint32_t a
, char *b
, size_t b_len
)
97 snprintf(b
, b_len
, "%u.%u.%u.%u", (a
)&0xFF, (a
>> 8) & 0xFF,
98 (a
>> 16) & 0xFF, (a
>> 24) & 0xFF);
103 static struct prefix
*irdp_get_prefix(struct interface
*ifp
)
105 struct listnode
*node
;
106 struct connected
*ifc
;
109 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
))
115 /* Join to the add/leave multicast group. */
116 static int if_group(struct interface
*ifp
, int sock
, uint32_t group
,
122 char b1
[INET_ADDRSTRLEN
];
124 memset(&m
, 0, sizeof(m
));
125 m
.imr_multiaddr
.s_addr
= htonl(group
);
126 p
= irdp_get_prefix(ifp
);
129 flog_warn(EC_ZEBRA_NO_IFACE_ADDR
,
130 "IRDP: can't get address for %s", ifp
->name
);
134 m
.imr_interface
= p
->u
.prefix4
;
136 ret
= setsockopt(sock
, IPPROTO_IP
, add_leave
, (char *)&m
,
137 sizeof(struct ip_mreq
));
139 flog_err_sys(EC_LIB_SOCKET
, "IRDP: %s can't setsockopt %s: %s",
140 add_leave
== IP_ADD_MEMBERSHIP
? "join group"
142 inet_2a(group
, b1
, sizeof(b1
)),
143 safe_strerror(errno
));
148 static int if_add_group(struct interface
*ifp
)
150 struct zebra_if
*zi
= ifp
->info
;
151 struct irdp_interface
*irdp
= zi
->irdp
;
153 char b1
[INET_ADDRSTRLEN
];
158 ret
= if_group(ifp
, irdp_sock
, INADDR_ALLRTRS_GROUP
, IP_ADD_MEMBERSHIP
);
163 if (irdp
->flags
& IF_DEBUG_MISC
)
164 zlog_debug("IRDP: Adding group %s for %s",
165 inet_2a(htonl(INADDR_ALLRTRS_GROUP
), b1
, sizeof(b1
)),
170 static int if_drop_group(struct interface
*ifp
)
172 struct zebra_if
*zi
= ifp
->info
;
173 struct irdp_interface
*irdp
= zi
->irdp
;
175 char b1
[INET_ADDRSTRLEN
];
180 ret
= if_group(ifp
, irdp_sock
, INADDR_ALLRTRS_GROUP
,
185 if (irdp
->flags
& IF_DEBUG_MISC
)
186 zlog_debug("IRDP: Leaving group %s for %s",
187 inet_2a(htonl(INADDR_ALLRTRS_GROUP
), b1
, sizeof(b1
)),
192 static void if_set_defaults(struct irdp_interface
*irdp
)
194 irdp
->MaxAdvertInterval
= IRDP_MAXADVERTINTERVAL
;
195 irdp
->MinAdvertInterval
= IRDP_MINADVERTINTERVAL
;
196 irdp
->Preference
= IRDP_PREFERENCE
;
197 irdp
->Lifetime
= IRDP_LIFETIME
;
201 static struct Adv
*Adv_new(void)
203 return XCALLOC(MTYPE_IRDP_IF
, sizeof(struct Adv
));
206 static void Adv_free(struct Adv
*adv
)
208 XFREE(MTYPE_IRDP_IF
, adv
);
211 static void irdp_if_start(struct interface
*ifp
, int multicast
,
214 struct zebra_if
*zi
= ifp
->info
;
215 struct irdp_interface
*irdp
= zi
->irdp
;
216 struct listnode
*node
;
217 struct connected
*ifc
;
218 uint32_t timer
, seed
;
222 irdp
->started
= true;
223 if (irdp
->flags
& IF_ACTIVE
) {
224 zlog_debug("IRDP: Interface is already active %s", ifp
->name
);
227 if ((irdp_sock
< 0) && ((irdp_sock
= irdp_sock_init()) < 0)) {
228 flog_warn(EC_ZEBRA_IRDP_CANNOT_ACTIVATE_IFACE
,
229 "IRDP: Cannot activate interface %s (cannot create IRDP socket)",
233 irdp
->flags
|= IF_ACTIVE
;
236 irdp
->flags
|= IF_BROADCAST
;
240 if (!(ifp
->flags
& IFF_UP
)) {
241 flog_warn(EC_ZEBRA_IRDP_IFACE_DOWN
,
242 "IRDP: Interface is down %s", ifp
->name
);
245 /* Shall we cancel if_start if if_add_group fails? */
250 if (!(ifp
->flags
& (IFF_MULTICAST
| IFF_ALLMULTI
))) {
251 flog_warn(EC_ZEBRA_IRDP_IFACE_MCAST_DISABLED
,
252 "IRDP: Interface not multicast enabled %s",
258 if_set_defaults(irdp
);
262 /* The spec suggests this for randomness */
266 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
267 seed
= ifc
->address
->u
.prefix4
.s_addr
;
272 timer
= (frr_weak_random() % IRDP_DEFAULT_INTERVAL
) + 1;
274 irdp
->AdvPrefList
= list_new();
275 irdp
->AdvPrefList
->del
= (void (*)(void *))Adv_free
; /* Destructor */
278 /* And this for startup. Speed limit from 1991 :-). But it's OK*/
280 if (irdp
->irdp_sent
< MAX_INITIAL_ADVERTISEMENTS
281 && timer
> MAX_INITIAL_ADVERT_INTERVAL
)
282 timer
= MAX_INITIAL_ADVERT_INTERVAL
;
285 if (irdp
->flags
& IF_DEBUG_MISC
)
286 zlog_debug("IRDP: Init timer for %s set to %u", ifp
->name
,
289 irdp
->t_advertise
= NULL
;
290 thread_add_timer(zrouter
.master
, irdp_send_thread
, ifp
, timer
,
294 static void irdp_if_stop(struct interface
*ifp
)
296 struct zebra_if
*zi
= ifp
->info
;
297 struct irdp_interface
*irdp
= zi
->irdp
;
300 zlog_debug("Interface %s structure is NULL", ifp
->name
);
304 if (!(irdp
->flags
& IF_ACTIVE
)) {
305 zlog_debug("Interface is not active %s", ifp
->name
);
309 if (!(irdp
->flags
& IF_BROADCAST
))
312 irdp_advert_off(ifp
);
314 list_delete(&irdp
->AdvPrefList
);
320 static void irdp_if_shutdown(struct interface
*ifp
)
322 struct zebra_if
*zi
= ifp
->info
;
323 struct irdp_interface
*irdp
= zi
->irdp
;
328 if (irdp
->flags
& IF_SHUTDOWN
) {
329 zlog_debug("IRDP: Interface is already shutdown %s", ifp
->name
);
333 irdp
->flags
|= IF_SHUTDOWN
;
334 irdp
->flags
&= ~IF_ACTIVE
;
336 if (!(irdp
->flags
& IF_BROADCAST
))
339 /* Tell the hosts we are out of service */
340 irdp_advert_off(ifp
);
343 static void irdp_if_no_shutdown(struct interface
*ifp
)
345 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
350 if (!(irdp
->flags
& IF_SHUTDOWN
)) {
351 zlog_debug("IRDP: Interface is not shutdown %s", ifp
->name
);
355 irdp
->flags
&= ~IF_SHUTDOWN
;
357 irdp_if_start(ifp
, irdp
->flags
& IF_BROADCAST
? false : true, false);
361 /* Write configuration to user */
363 int irdp_config_write(struct vty
*vty
, struct interface
*ifp
)
365 struct zebra_if
*zi
= ifp
->info
;
366 struct irdp_interface
*irdp
= zi
->irdp
;
368 struct listnode
*node
;
369 char b1
[INET_ADDRSTRLEN
];
374 if (irdp
->flags
& IF_ACTIVE
|| irdp
->flags
& IF_SHUTDOWN
) {
376 if (irdp
->flags
& IF_SHUTDOWN
)
377 vty_out(vty
, " ip irdp shutdown \n");
379 if (irdp
->flags
& IF_BROADCAST
)
380 vty_out(vty
, " ip irdp broadcast\n");
382 vty_out(vty
, " ip irdp multicast\n");
384 vty_out(vty
, " ip irdp preference %ld\n", irdp
->Preference
);
386 for (ALL_LIST_ELEMENTS_RO(irdp
->AdvPrefList
, node
, adv
))
387 vty_out(vty
, " ip irdp address %s preference %d\n",
388 inet_2a(adv
->ip
.s_addr
, b1
, sizeof(b1
)),
391 vty_out(vty
, " ip irdp holdtime %d\n", irdp
->Lifetime
);
393 vty_out(vty
, " ip irdp minadvertinterval %ld\n",
394 irdp
->MinAdvertInterval
);
396 vty_out(vty
, " ip irdp maxadvertinterval %ld\n",
397 irdp
->MaxAdvertInterval
);
403 DEFUN (ip_irdp_multicast
,
404 ip_irdp_multicast_cmd
,
407 "ICMP Router discovery on this interface\n"
408 "Use multicast mode\n")
410 VTY_DECLVAR_CONTEXT(interface
, ifp
);
413 irdp_if_start(ifp
, true, true);
417 DEFUN (ip_irdp_broadcast
,
418 ip_irdp_broadcast_cmd
,
421 "ICMP Router discovery on this interface\n"
422 "Use broadcast mode\n")
424 VTY_DECLVAR_CONTEXT(interface
, ifp
);
427 irdp_if_start(ifp
, false, true);
436 "Disable ICMP Router discovery on this interface\n")
438 VTY_DECLVAR_CONTEXT(interface
, ifp
);
444 DEFUN (ip_irdp_shutdown
,
445 ip_irdp_shutdown_cmd
,
448 "ICMP Router discovery on this interface\n"
449 "ICMP Router discovery shutdown on this interface\n")
451 VTY_DECLVAR_CONTEXT(interface
, ifp
);
453 irdp_if_shutdown(ifp
);
457 DEFUN (no_ip_irdp_shutdown
,
458 no_ip_irdp_shutdown_cmd
,
459 "no ip irdp shutdown",
462 "ICMP Router discovery on this interface\n"
463 "ICMP Router discovery no shutdown on this interface\n")
465 VTY_DECLVAR_CONTEXT(interface
, ifp
);
467 irdp_if_no_shutdown(ifp
);
471 DEFUN (ip_irdp_holdtime
,
472 ip_irdp_holdtime_cmd
,
473 "ip irdp holdtime (0-9000)",
475 "ICMP Router discovery on this interface\n"
476 "Set holdtime value\n"
477 "Holdtime value in seconds. Default is 1800 seconds\n")
480 VTY_DECLVAR_CONTEXT(interface
, ifp
);
481 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
485 irdp
->Lifetime
= atoi(argv
[idx_number
]->arg
);
489 DEFUN (ip_irdp_minadvertinterval
,
490 ip_irdp_minadvertinterval_cmd
,
491 "ip irdp minadvertinterval (3-1800)",
493 "ICMP Router discovery on this interface\n"
494 "Set minimum time between advertisement\n"
495 "Minimum advertisement interval in seconds\n")
498 VTY_DECLVAR_CONTEXT(interface
, ifp
);
499 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
503 if ((unsigned)atoi(argv
[idx_number
]->arg
) <= irdp
->MaxAdvertInterval
) {
504 irdp
->MinAdvertInterval
= atoi(argv
[idx_number
]->arg
);
508 "%% MinAdvertInterval must be less than or equal to MaxAdvertInterval\n");
509 return CMD_WARNING_CONFIG_FAILED
;
513 DEFUN (ip_irdp_maxadvertinterval
,
514 ip_irdp_maxadvertinterval_cmd
,
515 "ip irdp maxadvertinterval (4-1800)",
517 "ICMP Router discovery on this interface\n"
518 "Set maximum time between advertisement\n"
519 "Maximum advertisement interval in seconds\n")
522 VTY_DECLVAR_CONTEXT(interface
, ifp
);
523 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
527 if (irdp
->MinAdvertInterval
<= (unsigned)atoi(argv
[idx_number
]->arg
)) {
528 irdp
->MaxAdvertInterval
= atoi(argv
[idx_number
]->arg
);
532 "%% MaxAdvertInterval must be greater than or equal to MinAdvertInterval\n");
533 return CMD_WARNING_CONFIG_FAILED
;
537 /* DEFUN needs to be fixed for negative ranages...
538 * "ip irdp preference <-2147483648-2147483647>",
539 * Be positive for now. :-)
542 DEFUN (ip_irdp_preference
,
543 ip_irdp_preference_cmd
,
544 "ip irdp preference (0-2147483647)",
546 "ICMP Router discovery on this interface\n"
547 "Set default preference level for this interface\n"
548 "Preference level\n")
551 VTY_DECLVAR_CONTEXT(interface
, ifp
);
552 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
556 irdp
->Preference
= atoi(argv
[idx_number
]->arg
);
560 DEFUN (ip_irdp_address_preference
,
561 ip_irdp_address_preference_cmd
,
562 "ip irdp address A.B.C.D preference (0-2147483647)",
564 "Alter ICMP Router discovery preference on this interface\n"
565 "Set IRDP address for advertise\n"
567 "Specify IRDP non-default preference to advertise\n"
568 "Preference level\n")
572 VTY_DECLVAR_CONTEXT(interface
, ifp
);
573 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
574 struct listnode
*node
;
582 ret
= inet_aton(argv
[idx_ipv4
]->arg
, &ip
);
584 return CMD_WARNING_CONFIG_FAILED
;
586 pref
= atoi(argv
[idx_number
]->arg
);
588 for (ALL_LIST_ELEMENTS_RO(irdp
->AdvPrefList
, node
, adv
))
589 if (adv
->ip
.s_addr
== ip
.s_addr
)
595 listnode_add(irdp
->AdvPrefList
, adv
);
600 DEFUN (no_ip_irdp_address_preference
,
601 no_ip_irdp_address_preference_cmd
,
602 "no ip irdp address A.B.C.D preference (0-2147483647)",
605 "Alter ICMP Router discovery preference on this interface\n"
606 "Select IRDP address\n"
608 "Reset ICMP Router discovery preference on this interface\n"
609 "Old preference level\n")
612 VTY_DECLVAR_CONTEXT(interface
, ifp
);
613 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
614 struct listnode
*node
, *nnode
;
621 ret
= inet_aton(argv
[idx_ipv4
]->arg
, &ip
);
623 return CMD_WARNING_CONFIG_FAILED
;
625 for (ALL_LIST_ELEMENTS(irdp
->AdvPrefList
, node
, nnode
, adv
)) {
626 if (adv
->ip
.s_addr
== ip
.s_addr
) {
627 listnode_delete(irdp
->AdvPrefList
, adv
);
635 DEFUN (ip_irdp_debug_messages
,
636 ip_irdp_debug_messages_cmd
,
637 "ip irdp debug messages",
639 "ICMP Router discovery debug Averts. and Solicits (short)\n"
640 "IRDP debugging options\n"
641 "Enable debugging for IRDP messages\n")
643 VTY_DECLVAR_CONTEXT(interface
, ifp
);
644 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
648 irdp
->flags
|= IF_DEBUG_MESSAGES
;
653 DEFUN (ip_irdp_debug_misc
,
654 ip_irdp_debug_misc_cmd
,
655 "ip irdp debug misc",
657 "ICMP Router discovery debug Averts. and Solicits (short)\n"
658 "IRDP debugging options\n"
659 "Enable debugging for miscellaneous IRDP events\n")
661 VTY_DECLVAR_CONTEXT(interface
, ifp
);
662 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
666 irdp
->flags
|= IF_DEBUG_MISC
;
671 DEFUN (ip_irdp_debug_packet
,
672 ip_irdp_debug_packet_cmd
,
673 "ip irdp debug packet",
675 "ICMP Router discovery debug Averts. and Solicits (short)\n"
676 "IRDP debugging options\n"
677 "Enable debugging for IRDP packets\n")
679 VTY_DECLVAR_CONTEXT(interface
, ifp
);
680 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
684 irdp
->flags
|= IF_DEBUG_PACKET
;
690 DEFUN (ip_irdp_debug_disable
,
691 ip_irdp_debug_disable_cmd
,
692 "ip irdp debug disable",
694 "ICMP Router discovery debug Averts. and Solicits (short)\n"
695 "IRDP debugging options\n"
696 "Disable debugging for all IRDP events\n")
698 VTY_DECLVAR_CONTEXT(interface
, ifp
);
699 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
703 irdp
->flags
&= ~IF_DEBUG_PACKET
;
704 irdp
->flags
&= ~IF_DEBUG_MESSAGES
;
705 irdp
->flags
&= ~IF_DEBUG_MISC
;
710 void irdp_if_init(void)
712 hook_register(zebra_if_config_wr
, irdp_config_write
);
713 hook_register(if_del
, irdp_if_delete
);
715 install_element(INTERFACE_NODE
, &ip_irdp_broadcast_cmd
);
716 install_element(INTERFACE_NODE
, &ip_irdp_multicast_cmd
);
717 install_element(INTERFACE_NODE
, &no_ip_irdp_cmd
);
718 install_element(INTERFACE_NODE
, &ip_irdp_shutdown_cmd
);
719 install_element(INTERFACE_NODE
, &no_ip_irdp_shutdown_cmd
);
720 install_element(INTERFACE_NODE
, &ip_irdp_holdtime_cmd
);
721 install_element(INTERFACE_NODE
, &ip_irdp_maxadvertinterval_cmd
);
722 install_element(INTERFACE_NODE
, &ip_irdp_minadvertinterval_cmd
);
723 install_element(INTERFACE_NODE
, &ip_irdp_preference_cmd
);
724 install_element(INTERFACE_NODE
, &ip_irdp_address_preference_cmd
);
725 install_element(INTERFACE_NODE
, &no_ip_irdp_address_preference_cmd
);
727 install_element(INTERFACE_NODE
, &ip_irdp_debug_messages_cmd
);
728 install_element(INTERFACE_NODE
, &ip_irdp_debug_misc_cmd
);
729 install_element(INTERFACE_NODE
, &ip_irdp_debug_packet_cmd
);
730 install_element(INTERFACE_NODE
, &ip_irdp_debug_disable_cmd
);