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"
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
)
97 sprintf(b
, "%u.%u.%u.%u", (a
)&0xFF, (a
>> 8) & 0xFF, (a
>> 16) & 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
), safe_strerror(errno
));
147 static int if_add_group(struct interface
*ifp
)
149 struct zebra_if
*zi
= ifp
->info
;
150 struct irdp_interface
*irdp
= zi
->irdp
;
152 char b1
[INET_ADDRSTRLEN
];
157 ret
= if_group(ifp
, irdp_sock
, INADDR_ALLRTRS_GROUP
, IP_ADD_MEMBERSHIP
);
162 if (irdp
->flags
& IF_DEBUG_MISC
)
163 zlog_debug("IRDP: Adding group %s for %s",
164 inet_2a(htonl(INADDR_ALLRTRS_GROUP
), b1
), ifp
->name
);
168 static int if_drop_group(struct interface
*ifp
)
170 struct zebra_if
*zi
= ifp
->info
;
171 struct irdp_interface
*irdp
= zi
->irdp
;
173 char b1
[INET_ADDRSTRLEN
];
178 ret
= if_group(ifp
, irdp_sock
, INADDR_ALLRTRS_GROUP
,
183 if (irdp
->flags
& IF_DEBUG_MISC
)
184 zlog_debug("IRDP: Leaving group %s for %s",
185 inet_2a(htonl(INADDR_ALLRTRS_GROUP
), b1
), ifp
->name
);
189 static void if_set_defaults(struct irdp_interface
*irdp
)
191 irdp
->MaxAdvertInterval
= IRDP_MAXADVERTINTERVAL
;
192 irdp
->MinAdvertInterval
= IRDP_MINADVERTINTERVAL
;
193 irdp
->Preference
= IRDP_PREFERENCE
;
194 irdp
->Lifetime
= IRDP_LIFETIME
;
198 static struct Adv
*Adv_new(void)
200 return XCALLOC(MTYPE_TMP
, sizeof(struct Adv
));
203 static void Adv_free(struct Adv
*adv
)
205 XFREE(MTYPE_TMP
, adv
);
208 static void irdp_if_start(struct interface
*ifp
, int multicast
,
211 struct zebra_if
*zi
= ifp
->info
;
212 struct irdp_interface
*irdp
= zi
->irdp
;
213 struct listnode
*node
;
214 struct connected
*ifc
;
215 uint32_t timer
, seed
;
219 irdp
->started
= true;
220 if (irdp
->flags
& IF_ACTIVE
) {
221 zlog_debug("IRDP: Interface is already active %s", ifp
->name
);
224 if ((irdp_sock
< 0) && ((irdp_sock
= irdp_sock_init()) < 0)) {
225 flog_warn(EC_ZEBRA_IRDP_CANNOT_ACTIVATE_IFACE
,
226 "IRDP: Cannot activate interface %s (cannot create "
231 irdp
->flags
|= IF_ACTIVE
;
234 irdp
->flags
|= IF_BROADCAST
;
238 if (!(ifp
->flags
& IFF_UP
)) {
239 flog_warn(EC_ZEBRA_IRDP_IFACE_DOWN
,
240 "IRDP: Interface is down %s", ifp
->name
);
243 /* Shall we cancel if_start if if_add_group fails? */
248 if (!(ifp
->flags
& (IFF_MULTICAST
| IFF_ALLMULTI
))) {
249 flog_warn(EC_ZEBRA_IRDP_IFACE_MCAST_DISABLED
,
250 "IRDP: Interface not multicast enabled %s",
256 if_set_defaults(irdp
);
260 /* The spec suggests this for randomness */
264 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
265 seed
= ifc
->address
->u
.prefix4
.s_addr
;
270 timer
= (random() % IRDP_DEFAULT_INTERVAL
) + 1;
272 irdp
->AdvPrefList
= list_new();
273 irdp
->AdvPrefList
->del
= (void (*)(void *))Adv_free
; /* Destructor */
276 /* And this for startup. Speed limit from 1991 :-). But it's OK*/
278 if (irdp
->irdp_sent
< MAX_INITIAL_ADVERTISEMENTS
279 && timer
> MAX_INITIAL_ADVERT_INTERVAL
)
280 timer
= MAX_INITIAL_ADVERT_INTERVAL
;
283 if (irdp
->flags
& IF_DEBUG_MISC
)
284 zlog_debug("IRDP: Init timer for %s set to %u", ifp
->name
,
287 irdp
->t_advertise
= NULL
;
288 thread_add_timer(zrouter
.master
, irdp_send_thread
, ifp
, timer
,
292 static void irdp_if_stop(struct interface
*ifp
)
294 struct zebra_if
*zi
= ifp
->info
;
295 struct irdp_interface
*irdp
= zi
->irdp
;
298 zlog_debug("Interface %s structure is NULL", ifp
->name
);
302 if (!(irdp
->flags
& IF_ACTIVE
)) {
303 zlog_debug("Interface is not active %s", ifp
->name
);
307 if (!(irdp
->flags
& IF_BROADCAST
))
310 irdp_advert_off(ifp
);
312 list_delete(&irdp
->AdvPrefList
);
318 static void irdp_if_shutdown(struct interface
*ifp
)
320 struct zebra_if
*zi
= ifp
->info
;
321 struct irdp_interface
*irdp
= zi
->irdp
;
326 if (irdp
->flags
& IF_SHUTDOWN
) {
327 zlog_debug("IRDP: Interface is already shutdown %s", ifp
->name
);
331 irdp
->flags
|= IF_SHUTDOWN
;
332 irdp
->flags
&= ~IF_ACTIVE
;
334 if (!(irdp
->flags
& IF_BROADCAST
))
337 /* Tell the hosts we are out of service */
338 irdp_advert_off(ifp
);
341 static void irdp_if_no_shutdown(struct interface
*ifp
)
343 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
348 if (!(irdp
->flags
& IF_SHUTDOWN
)) {
349 zlog_debug("IRDP: Interface is not shutdown %s", ifp
->name
);
353 irdp
->flags
&= ~IF_SHUTDOWN
;
355 irdp_if_start(ifp
, irdp
->flags
& IF_BROADCAST
? FALSE
: TRUE
, FALSE
);
359 /* Write configuration to user */
361 int irdp_config_write(struct vty
*vty
, struct interface
*ifp
)
363 struct zebra_if
*zi
= ifp
->info
;
364 struct irdp_interface
*irdp
= zi
->irdp
;
366 struct listnode
*node
;
367 char b1
[INET_ADDRSTRLEN
];
372 if (irdp
->flags
& IF_ACTIVE
|| irdp
->flags
& IF_SHUTDOWN
) {
374 if (irdp
->flags
& IF_SHUTDOWN
)
375 vty_out(vty
, " ip irdp shutdown \n");
377 if (irdp
->flags
& IF_BROADCAST
)
378 vty_out(vty
, " ip irdp broadcast\n");
380 vty_out(vty
, " ip irdp multicast\n");
382 vty_out(vty
, " ip irdp preference %ld\n", irdp
->Preference
);
384 for (ALL_LIST_ELEMENTS_RO(irdp
->AdvPrefList
, node
, adv
))
385 vty_out(vty
, " ip irdp address %s preference %d\n",
386 inet_2a(adv
->ip
.s_addr
, b1
), adv
->pref
);
388 vty_out(vty
, " ip irdp holdtime %d\n", irdp
->Lifetime
);
390 vty_out(vty
, " ip irdp minadvertinterval %ld\n",
391 irdp
->MinAdvertInterval
);
393 vty_out(vty
, " ip irdp maxadvertinterval %ld\n",
394 irdp
->MaxAdvertInterval
);
400 DEFUN (ip_irdp_multicast
,
401 ip_irdp_multicast_cmd
,
404 "ICMP Router discovery on this interface\n"
405 "Use multicast mode\n")
407 VTY_DECLVAR_CONTEXT(interface
, ifp
);
410 irdp_if_start(ifp
, TRUE
, TRUE
);
414 DEFUN (ip_irdp_broadcast
,
415 ip_irdp_broadcast_cmd
,
418 "ICMP Router discovery on this interface\n"
419 "Use broadcast mode\n")
421 VTY_DECLVAR_CONTEXT(interface
, ifp
);
424 irdp_if_start(ifp
, FALSE
, TRUE
);
433 "Disable ICMP Router discovery on this interface\n")
435 VTY_DECLVAR_CONTEXT(interface
, ifp
);
441 DEFUN (ip_irdp_shutdown
,
442 ip_irdp_shutdown_cmd
,
445 "ICMP Router discovery on this interface\n"
446 "ICMP Router discovery shutdown on this interface\n")
448 VTY_DECLVAR_CONTEXT(interface
, ifp
);
450 irdp_if_shutdown(ifp
);
454 DEFUN (no_ip_irdp_shutdown
,
455 no_ip_irdp_shutdown_cmd
,
456 "no ip irdp shutdown",
459 "ICMP Router discovery on this interface\n"
460 "ICMP Router discovery no shutdown on this interface\n")
462 VTY_DECLVAR_CONTEXT(interface
, ifp
);
464 irdp_if_no_shutdown(ifp
);
468 DEFUN (ip_irdp_holdtime
,
469 ip_irdp_holdtime_cmd
,
470 "ip irdp holdtime (0-9000)",
472 "ICMP Router discovery on this interface\n"
473 "Set holdtime value\n"
474 "Holdtime value in seconds. Default is 1800 seconds\n")
477 VTY_DECLVAR_CONTEXT(interface
, ifp
);
478 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
482 irdp
->Lifetime
= atoi(argv
[idx_number
]->arg
);
486 DEFUN (ip_irdp_minadvertinterval
,
487 ip_irdp_minadvertinterval_cmd
,
488 "ip irdp minadvertinterval (3-1800)",
490 "ICMP Router discovery on this interface\n"
491 "Set minimum time between advertisement\n"
492 "Minimum advertisement interval in seconds\n")
495 VTY_DECLVAR_CONTEXT(interface
, ifp
);
496 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
500 if ((unsigned)atoi(argv
[idx_number
]->arg
) <= irdp
->MaxAdvertInterval
) {
501 irdp
->MinAdvertInterval
= atoi(argv
[idx_number
]->arg
);
505 "%% MinAdvertInterval must be less than or equal to "
506 "MaxAdvertInterval\n");
507 return CMD_WARNING_CONFIG_FAILED
;
511 DEFUN (ip_irdp_maxadvertinterval
,
512 ip_irdp_maxadvertinterval_cmd
,
513 "ip irdp maxadvertinterval (4-1800)",
515 "ICMP Router discovery on this interface\n"
516 "Set maximum time between advertisement\n"
517 "Maximum advertisement interval in seconds\n")
520 VTY_DECLVAR_CONTEXT(interface
, ifp
);
521 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
525 if (irdp
->MinAdvertInterval
<= (unsigned)atoi(argv
[idx_number
]->arg
)) {
526 irdp
->MaxAdvertInterval
= atoi(argv
[idx_number
]->arg
);
530 "%% MaxAdvertInterval must be greater than or equal to "
531 "MinAdvertInterval\n");
532 return CMD_WARNING_CONFIG_FAILED
;
536 /* DEFUN needs to be fixed for negative ranages...
537 * "ip irdp preference <-2147483648-2147483647>",
538 * Be positive for now. :-)
541 DEFUN (ip_irdp_preference
,
542 ip_irdp_preference_cmd
,
543 "ip irdp preference (0-2147483647)",
545 "ICMP Router discovery on this interface\n"
546 "Set default preference level for this interface\n"
547 "Preference level\n")
550 VTY_DECLVAR_CONTEXT(interface
, ifp
);
551 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
555 irdp
->Preference
= atoi(argv
[idx_number
]->arg
);
559 DEFUN (ip_irdp_address_preference
,
560 ip_irdp_address_preference_cmd
,
561 "ip irdp address A.B.C.D preference (0-2147483647)",
563 "Alter ICMP Router discovery preference on this interface\n"
564 "Set IRDP address for advertise\n"
566 "Specify IRDP non-default preference to advertise\n"
567 "Preference level\n")
571 VTY_DECLVAR_CONTEXT(interface
, ifp
);
572 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
573 struct listnode
*node
;
581 ret
= inet_aton(argv
[idx_ipv4
]->arg
, &ip
);
583 return CMD_WARNING_CONFIG_FAILED
;
585 pref
= atoi(argv
[idx_number
]->arg
);
587 for (ALL_LIST_ELEMENTS_RO(irdp
->AdvPrefList
, node
, adv
))
588 if (adv
->ip
.s_addr
== ip
.s_addr
)
594 listnode_add(irdp
->AdvPrefList
, adv
);
599 DEFUN (no_ip_irdp_address_preference
,
600 no_ip_irdp_address_preference_cmd
,
601 "no ip irdp address A.B.C.D preference (0-2147483647)",
604 "Alter ICMP Router discovery preference on this interface\n"
605 "Select IRDP address\n"
607 "Reset ICMP Router discovery preference on this interface\n"
608 "Old preference level\n")
611 VTY_DECLVAR_CONTEXT(interface
, ifp
);
612 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
613 struct listnode
*node
, *nnode
;
620 ret
= inet_aton(argv
[idx_ipv4
]->arg
, &ip
);
622 return CMD_WARNING_CONFIG_FAILED
;
624 for (ALL_LIST_ELEMENTS(irdp
->AdvPrefList
, node
, nnode
, adv
)) {
625 if (adv
->ip
.s_addr
== ip
.s_addr
) {
626 listnode_delete(irdp
->AdvPrefList
, adv
);
634 DEFUN (ip_irdp_debug_messages
,
635 ip_irdp_debug_messages_cmd
,
636 "ip irdp debug messages",
638 "ICMP Router discovery debug Averts. and Solicits (short)\n"
639 "IRDP debugging options\n"
640 "Enable debugging for IRDP messages\n")
642 VTY_DECLVAR_CONTEXT(interface
, ifp
);
643 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
647 irdp
->flags
|= IF_DEBUG_MESSAGES
;
652 DEFUN (ip_irdp_debug_misc
,
653 ip_irdp_debug_misc_cmd
,
654 "ip irdp debug misc",
656 "ICMP Router discovery debug Averts. and Solicits (short)\n"
657 "IRDP debugging options\n"
658 "Enable debugging for miscellaneous IRDP events\n")
660 VTY_DECLVAR_CONTEXT(interface
, ifp
);
661 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
665 irdp
->flags
|= IF_DEBUG_MISC
;
670 DEFUN (ip_irdp_debug_packet
,
671 ip_irdp_debug_packet_cmd
,
672 "ip irdp debug packet",
674 "ICMP Router discovery debug Averts. and Solicits (short)\n"
675 "IRDP debugging options\n"
676 "Enable debugging for IRDP packets\n")
678 VTY_DECLVAR_CONTEXT(interface
, ifp
);
679 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
683 irdp
->flags
|= IF_DEBUG_PACKET
;
689 DEFUN (ip_irdp_debug_disable
,
690 ip_irdp_debug_disable_cmd
,
691 "ip irdp debug disable",
693 "ICMP Router discovery debug Averts. and Solicits (short)\n"
694 "IRDP debugging options\n"
695 "Disable debugging for all IRDP events\n")
697 VTY_DECLVAR_CONTEXT(interface
, ifp
);
698 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
702 irdp
->flags
&= ~IF_DEBUG_PACKET
;
703 irdp
->flags
&= ~IF_DEBUG_MESSAGES
;
704 irdp
->flags
&= ~IF_DEBUG_MISC
;
709 void irdp_if_init(void)
711 hook_register(zebra_if_config_wr
, irdp_config_write
);
712 hook_register(if_del
, irdp_if_delete
);
714 install_element(INTERFACE_NODE
, &ip_irdp_broadcast_cmd
);
715 install_element(INTERFACE_NODE
, &ip_irdp_multicast_cmd
);
716 install_element(INTERFACE_NODE
, &no_ip_irdp_cmd
);
717 install_element(INTERFACE_NODE
, &ip_irdp_shutdown_cmd
);
718 install_element(INTERFACE_NODE
, &no_ip_irdp_shutdown_cmd
);
719 install_element(INTERFACE_NODE
, &ip_irdp_holdtime_cmd
);
720 install_element(INTERFACE_NODE
, &ip_irdp_maxadvertinterval_cmd
);
721 install_element(INTERFACE_NODE
, &ip_irdp_minadvertinterval_cmd
);
722 install_element(INTERFACE_NODE
, &ip_irdp_preference_cmd
);
723 install_element(INTERFACE_NODE
, &ip_irdp_address_preference_cmd
);
724 install_element(INTERFACE_NODE
, &no_ip_irdp_address_preference_cmd
);
726 install_element(INTERFACE_NODE
, &ip_irdp_debug_messages_cmd
);
727 install_element(INTERFACE_NODE
, &ip_irdp_debug_misc_cmd
);
728 install_element(INTERFACE_NODE
, &ip_irdp_debug_packet_cmd
);
729 install_element(INTERFACE_NODE
, &ip_irdp_debug_disable_cmd
);