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"
37 #include "zebra_memory.h"
40 #include "connected.h"
44 #include "lib_errors.h"
45 #include "zebra/interface.h"
46 #include "zebra/rtadv.h"
47 #include "zebra/rib.h"
48 #include "zebra/zebra_router.h"
49 #include "zebra/redistribute.h"
50 #include "zebra/irdp.h"
51 #include "zebra/zebra_errors.h"
52 #include <netinet/ip_icmp.h>
54 #include "sockunion.h"
60 DEFINE_MTYPE_STATIC(ZEBRA
, IRDP_IF
, "IRDP interface data");
62 #define IRDP_CONFIGED \
66 "Please Configure IRDP before using this command\n"); \
67 return CMD_WARNING_CONFIG_FAILED; \
71 static struct irdp_interface
*irdp_if_get(struct interface
*ifp
)
73 struct zebra_if
*zi
= ifp
->info
;
79 zi
->irdp
= XCALLOC(MTYPE_IRDP_IF
, sizeof(*zi
->irdp
));
81 if (!zi
->irdp
->started
)
87 static int irdp_if_delete(struct interface
*ifp
)
89 struct zebra_if
*zi
= ifp
->info
;
92 XFREE(MTYPE_IRDP_IF
, zi
->irdp
);
96 static const char *inet_2a(uint32_t a
, char *b
, size_t b_len
)
98 snprintf(b
, b_len
, "%u.%u.%u.%u", (a
)&0xFF, (a
>> 8) & 0xFF,
99 (a
>> 16) & 0xFF, (a
>> 24) & 0xFF);
104 static struct prefix
*irdp_get_prefix(struct interface
*ifp
)
106 struct listnode
*node
;
107 struct connected
*ifc
;
110 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
))
116 /* Join to the add/leave multicast group. */
117 static int if_group(struct interface
*ifp
, int sock
, uint32_t group
,
123 char b1
[INET_ADDRSTRLEN
];
125 memset(&m
, 0, sizeof(m
));
126 m
.imr_multiaddr
.s_addr
= htonl(group
);
127 p
= irdp_get_prefix(ifp
);
130 flog_warn(EC_ZEBRA_NO_IFACE_ADDR
,
131 "IRDP: can't get address for %s", ifp
->name
);
135 m
.imr_interface
= p
->u
.prefix4
;
137 ret
= setsockopt(sock
, IPPROTO_IP
, add_leave
, (char *)&m
,
138 sizeof(struct ip_mreq
));
140 flog_err_sys(EC_LIB_SOCKET
, "IRDP: %s can't setsockopt %s: %s",
141 add_leave
== IP_ADD_MEMBERSHIP
? "join group"
143 inet_2a(group
, b1
, sizeof(b1
)),
144 safe_strerror(errno
));
149 static int if_add_group(struct interface
*ifp
)
151 struct zebra_if
*zi
= ifp
->info
;
152 struct irdp_interface
*irdp
= zi
->irdp
;
154 char b1
[INET_ADDRSTRLEN
];
159 ret
= if_group(ifp
, irdp_sock
, INADDR_ALLRTRS_GROUP
, IP_ADD_MEMBERSHIP
);
164 if (irdp
->flags
& IF_DEBUG_MISC
)
165 zlog_debug("IRDP: Adding group %s for %s",
166 inet_2a(htonl(INADDR_ALLRTRS_GROUP
), b1
, sizeof(b1
)),
171 static int if_drop_group(struct interface
*ifp
)
173 struct zebra_if
*zi
= ifp
->info
;
174 struct irdp_interface
*irdp
= zi
->irdp
;
176 char b1
[INET_ADDRSTRLEN
];
181 ret
= if_group(ifp
, irdp_sock
, INADDR_ALLRTRS_GROUP
,
186 if (irdp
->flags
& IF_DEBUG_MISC
)
187 zlog_debug("IRDP: Leaving group %s for %s",
188 inet_2a(htonl(INADDR_ALLRTRS_GROUP
), b1
, sizeof(b1
)),
193 static void if_set_defaults(struct irdp_interface
*irdp
)
195 irdp
->MaxAdvertInterval
= IRDP_MAXADVERTINTERVAL
;
196 irdp
->MinAdvertInterval
= IRDP_MINADVERTINTERVAL
;
197 irdp
->Preference
= IRDP_PREFERENCE
;
198 irdp
->Lifetime
= IRDP_LIFETIME
;
202 static struct Adv
*Adv_new(void)
204 return XCALLOC(MTYPE_TMP
, sizeof(struct Adv
));
207 static void Adv_free(struct Adv
*adv
)
209 XFREE(MTYPE_TMP
, adv
);
212 static void irdp_if_start(struct interface
*ifp
, int multicast
,
215 struct zebra_if
*zi
= ifp
->info
;
216 struct irdp_interface
*irdp
= zi
->irdp
;
217 struct listnode
*node
;
218 struct connected
*ifc
;
219 uint32_t timer
, seed
;
223 irdp
->started
= true;
224 if (irdp
->flags
& IF_ACTIVE
) {
225 zlog_debug("IRDP: Interface is already active %s", ifp
->name
);
228 if ((irdp_sock
< 0) && ((irdp_sock
= irdp_sock_init()) < 0)) {
229 flog_warn(EC_ZEBRA_IRDP_CANNOT_ACTIVATE_IFACE
,
230 "IRDP: Cannot activate interface %s (cannot create IRDP socket)",
234 irdp
->flags
|= IF_ACTIVE
;
237 irdp
->flags
|= IF_BROADCAST
;
241 if (!(ifp
->flags
& IFF_UP
)) {
242 flog_warn(EC_ZEBRA_IRDP_IFACE_DOWN
,
243 "IRDP: Interface is down %s", ifp
->name
);
246 /* Shall we cancel if_start if if_add_group fails? */
251 if (!(ifp
->flags
& (IFF_MULTICAST
| IFF_ALLMULTI
))) {
252 flog_warn(EC_ZEBRA_IRDP_IFACE_MCAST_DISABLED
,
253 "IRDP: Interface not multicast enabled %s",
259 if_set_defaults(irdp
);
263 /* The spec suggests this for randomness */
267 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
268 seed
= ifc
->address
->u
.prefix4
.s_addr
;
273 timer
= (frr_weak_random() % IRDP_DEFAULT_INTERVAL
) + 1;
275 irdp
->AdvPrefList
= list_new();
276 irdp
->AdvPrefList
->del
= (void (*)(void *))Adv_free
; /* Destructor */
279 /* And this for startup. Speed limit from 1991 :-). But it's OK*/
281 if (irdp
->irdp_sent
< MAX_INITIAL_ADVERTISEMENTS
282 && timer
> MAX_INITIAL_ADVERT_INTERVAL
)
283 timer
= MAX_INITIAL_ADVERT_INTERVAL
;
286 if (irdp
->flags
& IF_DEBUG_MISC
)
287 zlog_debug("IRDP: Init timer for %s set to %u", ifp
->name
,
290 irdp
->t_advertise
= NULL
;
291 thread_add_timer(zrouter
.master
, irdp_send_thread
, ifp
, timer
,
295 static void irdp_if_stop(struct interface
*ifp
)
297 struct zebra_if
*zi
= ifp
->info
;
298 struct irdp_interface
*irdp
= zi
->irdp
;
301 zlog_debug("Interface %s structure is NULL", ifp
->name
);
305 if (!(irdp
->flags
& IF_ACTIVE
)) {
306 zlog_debug("Interface is not active %s", ifp
->name
);
310 if (!(irdp
->flags
& IF_BROADCAST
))
313 irdp_advert_off(ifp
);
315 list_delete(&irdp
->AdvPrefList
);
321 static void irdp_if_shutdown(struct interface
*ifp
)
323 struct zebra_if
*zi
= ifp
->info
;
324 struct irdp_interface
*irdp
= zi
->irdp
;
329 if (irdp
->flags
& IF_SHUTDOWN
) {
330 zlog_debug("IRDP: Interface is already shutdown %s", ifp
->name
);
334 irdp
->flags
|= IF_SHUTDOWN
;
335 irdp
->flags
&= ~IF_ACTIVE
;
337 if (!(irdp
->flags
& IF_BROADCAST
))
340 /* Tell the hosts we are out of service */
341 irdp_advert_off(ifp
);
344 static void irdp_if_no_shutdown(struct interface
*ifp
)
346 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
351 if (!(irdp
->flags
& IF_SHUTDOWN
)) {
352 zlog_debug("IRDP: Interface is not shutdown %s", ifp
->name
);
356 irdp
->flags
&= ~IF_SHUTDOWN
;
358 irdp_if_start(ifp
, irdp
->flags
& IF_BROADCAST
? false : true, false);
362 /* Write configuration to user */
364 int irdp_config_write(struct vty
*vty
, struct interface
*ifp
)
366 struct zebra_if
*zi
= ifp
->info
;
367 struct irdp_interface
*irdp
= zi
->irdp
;
369 struct listnode
*node
;
370 char b1
[INET_ADDRSTRLEN
];
375 if (irdp
->flags
& IF_ACTIVE
|| irdp
->flags
& IF_SHUTDOWN
) {
377 if (irdp
->flags
& IF_SHUTDOWN
)
378 vty_out(vty
, " ip irdp shutdown \n");
380 if (irdp
->flags
& IF_BROADCAST
)
381 vty_out(vty
, " ip irdp broadcast\n");
383 vty_out(vty
, " ip irdp multicast\n");
385 vty_out(vty
, " ip irdp preference %ld\n", irdp
->Preference
);
387 for (ALL_LIST_ELEMENTS_RO(irdp
->AdvPrefList
, node
, adv
))
388 vty_out(vty
, " ip irdp address %s preference %d\n",
389 inet_2a(adv
->ip
.s_addr
, b1
, sizeof(b1
)),
392 vty_out(vty
, " ip irdp holdtime %d\n", irdp
->Lifetime
);
394 vty_out(vty
, " ip irdp minadvertinterval %ld\n",
395 irdp
->MinAdvertInterval
);
397 vty_out(vty
, " ip irdp maxadvertinterval %ld\n",
398 irdp
->MaxAdvertInterval
);
404 DEFUN (ip_irdp_multicast
,
405 ip_irdp_multicast_cmd
,
408 "ICMP Router discovery on this interface\n"
409 "Use multicast mode\n")
411 VTY_DECLVAR_CONTEXT(interface
, ifp
);
414 irdp_if_start(ifp
, true, true);
418 DEFUN (ip_irdp_broadcast
,
419 ip_irdp_broadcast_cmd
,
422 "ICMP Router discovery on this interface\n"
423 "Use broadcast mode\n")
425 VTY_DECLVAR_CONTEXT(interface
, ifp
);
428 irdp_if_start(ifp
, false, true);
437 "Disable ICMP Router discovery on this interface\n")
439 VTY_DECLVAR_CONTEXT(interface
, ifp
);
445 DEFUN (ip_irdp_shutdown
,
446 ip_irdp_shutdown_cmd
,
449 "ICMP Router discovery on this interface\n"
450 "ICMP Router discovery shutdown on this interface\n")
452 VTY_DECLVAR_CONTEXT(interface
, ifp
);
454 irdp_if_shutdown(ifp
);
458 DEFUN (no_ip_irdp_shutdown
,
459 no_ip_irdp_shutdown_cmd
,
460 "no ip irdp shutdown",
463 "ICMP Router discovery on this interface\n"
464 "ICMP Router discovery no shutdown on this interface\n")
466 VTY_DECLVAR_CONTEXT(interface
, ifp
);
468 irdp_if_no_shutdown(ifp
);
472 DEFUN (ip_irdp_holdtime
,
473 ip_irdp_holdtime_cmd
,
474 "ip irdp holdtime (0-9000)",
476 "ICMP Router discovery on this interface\n"
477 "Set holdtime value\n"
478 "Holdtime value in seconds. Default is 1800 seconds\n")
481 VTY_DECLVAR_CONTEXT(interface
, ifp
);
482 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
486 irdp
->Lifetime
= atoi(argv
[idx_number
]->arg
);
490 DEFUN (ip_irdp_minadvertinterval
,
491 ip_irdp_minadvertinterval_cmd
,
492 "ip irdp minadvertinterval (3-1800)",
494 "ICMP Router discovery on this interface\n"
495 "Set minimum time between advertisement\n"
496 "Minimum advertisement interval in seconds\n")
499 VTY_DECLVAR_CONTEXT(interface
, ifp
);
500 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
504 if ((unsigned)atoi(argv
[idx_number
]->arg
) <= irdp
->MaxAdvertInterval
) {
505 irdp
->MinAdvertInterval
= atoi(argv
[idx_number
]->arg
);
509 "%% MinAdvertInterval must be less than or equal to MaxAdvertInterval\n");
510 return CMD_WARNING_CONFIG_FAILED
;
514 DEFUN (ip_irdp_maxadvertinterval
,
515 ip_irdp_maxadvertinterval_cmd
,
516 "ip irdp maxadvertinterval (4-1800)",
518 "ICMP Router discovery on this interface\n"
519 "Set maximum time between advertisement\n"
520 "Maximum advertisement interval in seconds\n")
523 VTY_DECLVAR_CONTEXT(interface
, ifp
);
524 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
528 if (irdp
->MinAdvertInterval
<= (unsigned)atoi(argv
[idx_number
]->arg
)) {
529 irdp
->MaxAdvertInterval
= atoi(argv
[idx_number
]->arg
);
533 "%% MaxAdvertInterval must be greater than or equal to MinAdvertInterval\n");
534 return CMD_WARNING_CONFIG_FAILED
;
538 /* DEFUN needs to be fixed for negative ranages...
539 * "ip irdp preference <-2147483648-2147483647>",
540 * Be positive for now. :-)
543 DEFUN (ip_irdp_preference
,
544 ip_irdp_preference_cmd
,
545 "ip irdp preference (0-2147483647)",
547 "ICMP Router discovery on this interface\n"
548 "Set default preference level for this interface\n"
549 "Preference level\n")
552 VTY_DECLVAR_CONTEXT(interface
, ifp
);
553 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
557 irdp
->Preference
= atoi(argv
[idx_number
]->arg
);
561 DEFUN (ip_irdp_address_preference
,
562 ip_irdp_address_preference_cmd
,
563 "ip irdp address A.B.C.D preference (0-2147483647)",
565 "Alter ICMP Router discovery preference on this interface\n"
566 "Set IRDP address for advertise\n"
568 "Specify IRDP non-default preference to advertise\n"
569 "Preference level\n")
573 VTY_DECLVAR_CONTEXT(interface
, ifp
);
574 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
575 struct listnode
*node
;
583 ret
= inet_aton(argv
[idx_ipv4
]->arg
, &ip
);
585 return CMD_WARNING_CONFIG_FAILED
;
587 pref
= atoi(argv
[idx_number
]->arg
);
589 for (ALL_LIST_ELEMENTS_RO(irdp
->AdvPrefList
, node
, adv
))
590 if (adv
->ip
.s_addr
== ip
.s_addr
)
596 listnode_add(irdp
->AdvPrefList
, adv
);
601 DEFUN (no_ip_irdp_address_preference
,
602 no_ip_irdp_address_preference_cmd
,
603 "no ip irdp address A.B.C.D preference (0-2147483647)",
606 "Alter ICMP Router discovery preference on this interface\n"
607 "Select IRDP address\n"
609 "Reset ICMP Router discovery preference on this interface\n"
610 "Old preference level\n")
613 VTY_DECLVAR_CONTEXT(interface
, ifp
);
614 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
615 struct listnode
*node
, *nnode
;
622 ret
= inet_aton(argv
[idx_ipv4
]->arg
, &ip
);
624 return CMD_WARNING_CONFIG_FAILED
;
626 for (ALL_LIST_ELEMENTS(irdp
->AdvPrefList
, node
, nnode
, adv
)) {
627 if (adv
->ip
.s_addr
== ip
.s_addr
) {
628 listnode_delete(irdp
->AdvPrefList
, adv
);
636 DEFUN (ip_irdp_debug_messages
,
637 ip_irdp_debug_messages_cmd
,
638 "ip irdp debug messages",
640 "ICMP Router discovery debug Averts. and Solicits (short)\n"
641 "IRDP debugging options\n"
642 "Enable debugging for IRDP messages\n")
644 VTY_DECLVAR_CONTEXT(interface
, ifp
);
645 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
649 irdp
->flags
|= IF_DEBUG_MESSAGES
;
654 DEFUN (ip_irdp_debug_misc
,
655 ip_irdp_debug_misc_cmd
,
656 "ip irdp debug misc",
658 "ICMP Router discovery debug Averts. and Solicits (short)\n"
659 "IRDP debugging options\n"
660 "Enable debugging for miscellaneous IRDP events\n")
662 VTY_DECLVAR_CONTEXT(interface
, ifp
);
663 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
667 irdp
->flags
|= IF_DEBUG_MISC
;
672 DEFUN (ip_irdp_debug_packet
,
673 ip_irdp_debug_packet_cmd
,
674 "ip irdp debug packet",
676 "ICMP Router discovery debug Averts. and Solicits (short)\n"
677 "IRDP debugging options\n"
678 "Enable debugging for IRDP packets\n")
680 VTY_DECLVAR_CONTEXT(interface
, ifp
);
681 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
685 irdp
->flags
|= IF_DEBUG_PACKET
;
691 DEFUN (ip_irdp_debug_disable
,
692 ip_irdp_debug_disable_cmd
,
693 "ip irdp debug disable",
695 "ICMP Router discovery debug Averts. and Solicits (short)\n"
696 "IRDP debugging options\n"
697 "Disable debugging for all IRDP events\n")
699 VTY_DECLVAR_CONTEXT(interface
, ifp
);
700 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
704 irdp
->flags
&= ~IF_DEBUG_PACKET
;
705 irdp
->flags
&= ~IF_DEBUG_MESSAGES
;
706 irdp
->flags
&= ~IF_DEBUG_MISC
;
711 void irdp_if_init(void)
713 hook_register(zebra_if_config_wr
, irdp_config_write
);
714 hook_register(if_del
, irdp_if_delete
);
716 install_element(INTERFACE_NODE
, &ip_irdp_broadcast_cmd
);
717 install_element(INTERFACE_NODE
, &ip_irdp_multicast_cmd
);
718 install_element(INTERFACE_NODE
, &no_ip_irdp_cmd
);
719 install_element(INTERFACE_NODE
, &ip_irdp_shutdown_cmd
);
720 install_element(INTERFACE_NODE
, &no_ip_irdp_shutdown_cmd
);
721 install_element(INTERFACE_NODE
, &ip_irdp_holdtime_cmd
);
722 install_element(INTERFACE_NODE
, &ip_irdp_maxadvertinterval_cmd
);
723 install_element(INTERFACE_NODE
, &ip_irdp_minadvertinterval_cmd
);
724 install_element(INTERFACE_NODE
, &ip_irdp_preference_cmd
);
725 install_element(INTERFACE_NODE
, &ip_irdp_address_preference_cmd
);
726 install_element(INTERFACE_NODE
, &no_ip_irdp_address_preference_cmd
);
728 install_element(INTERFACE_NODE
, &ip_irdp_debug_messages_cmd
);
729 install_element(INTERFACE_NODE
, &ip_irdp_debug_misc_cmd
);
730 install_element(INTERFACE_NODE
, &ip_irdp_debug_packet_cmd
);
731 install_element(INTERFACE_NODE
, &ip_irdp_debug_disable_cmd
);