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 "zebra/interface.h"
45 #include "zebra/rtadv.h"
46 #include "zebra/rib.h"
47 #include "zebra/zserv.h"
48 #include "zebra/redistribute.h"
49 #include "zebra/irdp.h"
50 #include <netinet/ip_icmp.h>
52 #include "sockunion.h"
57 DEFINE_MTYPE_STATIC(ZEBRA
, IRDP_IF
, "IRDP interface data")
59 #define IRDP_CONFIGED \
63 "Please Configure IRDP before using this command\n"); \
64 return CMD_WARNING_CONFIG_FAILED; \
68 static struct irdp_interface
*irdp_if_get(struct interface
*ifp
)
70 struct zebra_if
*zi
= ifp
->info
;
76 zi
->irdp
= XCALLOC(MTYPE_IRDP_IF
, sizeof(*zi
->irdp
));
78 if (!zi
->irdp
->started
)
84 static int irdp_if_delete(struct interface
*ifp
)
86 struct zebra_if
*zi
= ifp
->info
;
89 XFREE(MTYPE_IRDP_IF
, zi
->irdp
);
93 static const char *inet_2a(uint32_t a
, char *b
)
95 sprintf(b
, "%u.%u.%u.%u", (a
)&0xFF, (a
>> 8) & 0xFF, (a
>> 16) & 0xFF,
101 static struct prefix
*irdp_get_prefix(struct interface
*ifp
)
103 struct listnode
*node
;
104 struct connected
*ifc
;
107 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
))
113 /* Join to the add/leave multicast group. */
114 static int if_group(struct interface
*ifp
, int sock
, uint32_t group
,
120 char b1
[INET_ADDRSTRLEN
];
122 memset(&m
, 0, sizeof(m
));
123 m
.imr_multiaddr
.s_addr
= htonl(group
);
124 p
= irdp_get_prefix(ifp
);
127 zlog_warn("IRDP: can't get address for %s", ifp
->name
);
131 m
.imr_interface
= p
->u
.prefix4
;
133 ret
= setsockopt(sock
, IPPROTO_IP
, add_leave
, (char *)&m
,
134 sizeof(struct ip_mreq
));
136 zlog_warn("IRDP: %s can't setsockopt %s: %s",
137 add_leave
== IP_ADD_MEMBERSHIP
? "join group"
139 inet_2a(group
, b1
), safe_strerror(errno
));
144 static int if_add_group(struct interface
*ifp
)
146 struct zebra_if
*zi
= ifp
->info
;
147 struct irdp_interface
*irdp
= zi
->irdp
;
149 char b1
[INET_ADDRSTRLEN
];
154 ret
= if_group(ifp
, irdp_sock
, INADDR_ALLRTRS_GROUP
, IP_ADD_MEMBERSHIP
);
159 if (irdp
->flags
& IF_DEBUG_MISC
)
160 zlog_debug("IRDP: Adding group %s for %s",
161 inet_2a(htonl(INADDR_ALLRTRS_GROUP
), b1
), ifp
->name
);
165 static int if_drop_group(struct interface
*ifp
)
167 struct zebra_if
*zi
= ifp
->info
;
168 struct irdp_interface
*irdp
= zi
->irdp
;
170 char b1
[INET_ADDRSTRLEN
];
175 ret
= if_group(ifp
, irdp_sock
, INADDR_ALLRTRS_GROUP
,
180 if (irdp
->flags
& IF_DEBUG_MISC
)
181 zlog_debug("IRDP: Leaving group %s for %s",
182 inet_2a(htonl(INADDR_ALLRTRS_GROUP
), b1
), ifp
->name
);
186 static void if_set_defaults(struct irdp_interface
*irdp
)
188 irdp
->MaxAdvertInterval
= IRDP_MAXADVERTINTERVAL
;
189 irdp
->MinAdvertInterval
= IRDP_MINADVERTINTERVAL
;
190 irdp
->Preference
= IRDP_PREFERENCE
;
191 irdp
->Lifetime
= IRDP_LIFETIME
;
195 static struct Adv
*Adv_new(void)
197 return XCALLOC(MTYPE_TMP
, sizeof(struct Adv
));
200 static void Adv_free(struct Adv
*adv
)
202 XFREE(MTYPE_TMP
, adv
);
205 static void irdp_if_start(struct interface
*ifp
, int multicast
,
208 struct zebra_if
*zi
= ifp
->info
;
209 struct irdp_interface
*irdp
= zi
->irdp
;
210 struct listnode
*node
;
211 struct connected
*ifc
;
212 uint32_t timer
, seed
;
216 irdp
->started
= true;
217 if (irdp
->flags
& IF_ACTIVE
) {
218 zlog_warn("IRDP: Interface is already active %s", ifp
->name
);
221 if ((irdp_sock
< 0) && ((irdp_sock
= irdp_sock_init()) < 0)) {
223 "IRDP: Cannot activate interface %s (cannot create "
228 irdp
->flags
|= IF_ACTIVE
;
231 irdp
->flags
|= IF_BROADCAST
;
235 if (!(ifp
->flags
& IFF_UP
)) {
236 zlog_warn("IRDP: Interface is down %s", ifp
->name
);
239 /* Shall we cancel if_start if if_add_group fails? */
244 if (!(ifp
->flags
& (IFF_MULTICAST
| IFF_ALLMULTI
))) {
245 zlog_warn("IRDP: Interface not multicast enabled %s",
251 if_set_defaults(irdp
);
255 /* The spec suggests this for randomness */
259 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
260 seed
= ifc
->address
->u
.prefix4
.s_addr
;
265 timer
= (random() % IRDP_DEFAULT_INTERVAL
) + 1;
267 irdp
->AdvPrefList
= list_new();
268 irdp
->AdvPrefList
->del
= (void (*)(void *))Adv_free
; /* Destructor */
271 /* And this for startup. Speed limit from 1991 :-). But it's OK*/
273 if (irdp
->irdp_sent
< MAX_INITIAL_ADVERTISEMENTS
274 && timer
> MAX_INITIAL_ADVERT_INTERVAL
)
275 timer
= MAX_INITIAL_ADVERT_INTERVAL
;
278 if (irdp
->flags
& IF_DEBUG_MISC
)
279 zlog_debug("IRDP: Init timer for %s set to %u", ifp
->name
,
282 irdp
->t_advertise
= NULL
;
283 thread_add_timer(zebrad
.master
, irdp_send_thread
, ifp
, timer
,
287 static void irdp_if_stop(struct interface
*ifp
)
289 struct zebra_if
*zi
= ifp
->info
;
290 struct irdp_interface
*irdp
= zi
->irdp
;
293 zlog_warn("Interface %s structure is NULL", ifp
->name
);
297 if (!(irdp
->flags
& IF_ACTIVE
)) {
298 zlog_warn("Interface is not active %s", ifp
->name
);
302 if (!(irdp
->flags
& IF_BROADCAST
))
305 irdp_advert_off(ifp
);
307 list_delete_and_null(&irdp
->AdvPrefList
);
313 static void irdp_if_shutdown(struct interface
*ifp
)
315 struct zebra_if
*zi
= ifp
->info
;
316 struct irdp_interface
*irdp
= zi
->irdp
;
321 if (irdp
->flags
& IF_SHUTDOWN
) {
322 zlog_warn("IRDP: Interface is already shutdown %s", ifp
->name
);
326 irdp
->flags
|= IF_SHUTDOWN
;
327 irdp
->flags
&= ~IF_ACTIVE
;
329 if (!(irdp
->flags
& IF_BROADCAST
))
332 /* Tell the hosts we are out of service */
333 irdp_advert_off(ifp
);
336 static void irdp_if_no_shutdown(struct interface
*ifp
)
338 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
343 if (!(irdp
->flags
& IF_SHUTDOWN
)) {
344 zlog_warn("IRDP: Interface is not shutdown %s", ifp
->name
);
348 irdp
->flags
&= ~IF_SHUTDOWN
;
350 irdp_if_start(ifp
, irdp
->flags
& IF_BROADCAST
? FALSE
: TRUE
, FALSE
);
354 /* Write configuration to user */
356 int irdp_config_write(struct vty
*vty
, struct interface
*ifp
)
358 struct zebra_if
*zi
= ifp
->info
;
359 struct irdp_interface
*irdp
= zi
->irdp
;
361 struct listnode
*node
;
362 char b1
[INET_ADDRSTRLEN
];
367 if (irdp
->flags
& IF_ACTIVE
|| irdp
->flags
& IF_SHUTDOWN
) {
369 if (irdp
->flags
& IF_SHUTDOWN
)
370 vty_out(vty
, " ip irdp shutdown \n");
372 if (irdp
->flags
& IF_BROADCAST
)
373 vty_out(vty
, " ip irdp broadcast\n");
375 vty_out(vty
, " ip irdp multicast\n");
377 vty_out(vty
, " ip irdp preference %ld\n", irdp
->Preference
);
379 for (ALL_LIST_ELEMENTS_RO(irdp
->AdvPrefList
, node
, adv
))
380 vty_out(vty
, " ip irdp address %s preference %d\n",
381 inet_2a(adv
->ip
.s_addr
, b1
), adv
->pref
);
383 vty_out(vty
, " ip irdp holdtime %d\n", irdp
->Lifetime
);
385 vty_out(vty
, " ip irdp minadvertinterval %ld\n",
386 irdp
->MinAdvertInterval
);
388 vty_out(vty
, " ip irdp maxadvertinterval %ld\n",
389 irdp
->MaxAdvertInterval
);
395 DEFUN (ip_irdp_multicast
,
396 ip_irdp_multicast_cmd
,
399 "ICMP Router discovery on this interface\n"
400 "Use multicast mode\n")
402 VTY_DECLVAR_CONTEXT(interface
, ifp
);
405 irdp_if_start(ifp
, TRUE
, TRUE
);
409 DEFUN (ip_irdp_broadcast
,
410 ip_irdp_broadcast_cmd
,
413 "ICMP Router discovery on this interface\n"
414 "Use broadcast mode\n")
416 VTY_DECLVAR_CONTEXT(interface
, ifp
);
419 irdp_if_start(ifp
, FALSE
, TRUE
);
428 "Disable ICMP Router discovery on this interface\n")
430 VTY_DECLVAR_CONTEXT(interface
, ifp
);
436 DEFUN (ip_irdp_shutdown
,
437 ip_irdp_shutdown_cmd
,
440 "ICMP Router discovery on this interface\n"
441 "ICMP Router discovery shutdown on this interface\n")
443 VTY_DECLVAR_CONTEXT(interface
, ifp
);
445 irdp_if_shutdown(ifp
);
449 DEFUN (no_ip_irdp_shutdown
,
450 no_ip_irdp_shutdown_cmd
,
451 "no ip irdp shutdown",
454 "ICMP Router discovery on this interface\n"
455 "ICMP Router discovery no shutdown on this interface\n")
457 VTY_DECLVAR_CONTEXT(interface
, ifp
);
459 irdp_if_no_shutdown(ifp
);
463 DEFUN (ip_irdp_holdtime
,
464 ip_irdp_holdtime_cmd
,
465 "ip irdp holdtime (0-9000)",
467 "ICMP Router discovery on this interface\n"
468 "Set holdtime value\n"
469 "Holdtime value in seconds. Default is 1800 seconds\n")
472 VTY_DECLVAR_CONTEXT(interface
, ifp
);
473 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
477 irdp
->Lifetime
= atoi(argv
[idx_number
]->arg
);
481 DEFUN (ip_irdp_minadvertinterval
,
482 ip_irdp_minadvertinterval_cmd
,
483 "ip irdp minadvertinterval (3-1800)",
485 "ICMP Router discovery on this interface\n"
486 "Set minimum time between advertisement\n"
487 "Minimum advertisement interval in seconds\n")
490 VTY_DECLVAR_CONTEXT(interface
, ifp
);
491 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
495 if ((unsigned)atoi(argv
[idx_number
]->arg
) <= irdp
->MaxAdvertInterval
) {
496 irdp
->MinAdvertInterval
= atoi(argv
[idx_number
]->arg
);
500 "%% MinAdvertInterval must be less than or equal to "
501 "MaxAdvertInterval\n");
502 return CMD_WARNING_CONFIG_FAILED
;
506 DEFUN (ip_irdp_maxadvertinterval
,
507 ip_irdp_maxadvertinterval_cmd
,
508 "ip irdp maxadvertinterval (4-1800)",
510 "ICMP Router discovery on this interface\n"
511 "Set maximum time between advertisement\n"
512 "Maximum advertisement interval in seconds\n")
515 VTY_DECLVAR_CONTEXT(interface
, ifp
);
516 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
520 if (irdp
->MinAdvertInterval
<= (unsigned)atoi(argv
[idx_number
]->arg
)) {
521 irdp
->MaxAdvertInterval
= atoi(argv
[idx_number
]->arg
);
525 "%% MaxAdvertInterval must be greater than or equal to "
526 "MinAdvertInterval\n");
527 return CMD_WARNING_CONFIG_FAILED
;
531 /* DEFUN needs to be fixed for negative ranages...
532 * "ip irdp preference <-2147483648-2147483647>",
533 * Be positive for now. :-)
536 DEFUN (ip_irdp_preference
,
537 ip_irdp_preference_cmd
,
538 "ip irdp preference (0-2147483647)",
540 "ICMP Router discovery on this interface\n"
541 "Set default preference level for this interface\n"
542 "Preference level\n")
545 VTY_DECLVAR_CONTEXT(interface
, ifp
);
546 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
550 irdp
->Preference
= atoi(argv
[idx_number
]->arg
);
554 DEFUN (ip_irdp_address_preference
,
555 ip_irdp_address_preference_cmd
,
556 "ip irdp address A.B.C.D preference (0-2147483647)",
558 "Alter ICMP Router discovery preference on this interface\n"
559 "Set IRDP address for advertise\n"
561 "Specify IRDP non-default preference to advertise\n"
562 "Preference level\n")
566 VTY_DECLVAR_CONTEXT(interface
, ifp
);
567 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
568 struct listnode
*node
;
576 ret
= inet_aton(argv
[idx_ipv4
]->arg
, &ip
);
578 return CMD_WARNING_CONFIG_FAILED
;
580 pref
= atoi(argv
[idx_number
]->arg
);
582 for (ALL_LIST_ELEMENTS_RO(irdp
->AdvPrefList
, node
, adv
))
583 if (adv
->ip
.s_addr
== ip
.s_addr
)
589 listnode_add(irdp
->AdvPrefList
, adv
);
594 DEFUN (no_ip_irdp_address_preference
,
595 no_ip_irdp_address_preference_cmd
,
596 "no ip irdp address A.B.C.D preference (0-2147483647)",
599 "Alter ICMP Router discovery preference on this interface\n"
600 "Select IRDP address\n"
602 "Reset ICMP Router discovery preference on this interface\n"
603 "Old preference level\n")
606 VTY_DECLVAR_CONTEXT(interface
, ifp
);
607 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
608 struct listnode
*node
, *nnode
;
615 ret
= inet_aton(argv
[idx_ipv4
]->arg
, &ip
);
617 return CMD_WARNING_CONFIG_FAILED
;
619 for (ALL_LIST_ELEMENTS(irdp
->AdvPrefList
, node
, nnode
, adv
)) {
620 if (adv
->ip
.s_addr
== ip
.s_addr
) {
621 listnode_delete(irdp
->AdvPrefList
, adv
);
629 DEFUN (ip_irdp_debug_messages
,
630 ip_irdp_debug_messages_cmd
,
631 "ip irdp debug messages",
633 "ICMP Router discovery debug Averts. and Solicits (short)\n"
634 "IRDP debugging options\n"
635 "Enable debugging for IRDP messages\n")
637 VTY_DECLVAR_CONTEXT(interface
, ifp
);
638 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
642 irdp
->flags
|= IF_DEBUG_MESSAGES
;
647 DEFUN (ip_irdp_debug_misc
,
648 ip_irdp_debug_misc_cmd
,
649 "ip irdp debug misc",
651 "ICMP Router discovery debug Averts. and Solicits (short)\n"
652 "IRDP debugging options\n"
653 "Enable debugging for miscellaneous IRDP events\n")
655 VTY_DECLVAR_CONTEXT(interface
, ifp
);
656 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
660 irdp
->flags
|= IF_DEBUG_MISC
;
665 DEFUN (ip_irdp_debug_packet
,
666 ip_irdp_debug_packet_cmd
,
667 "ip irdp debug packet",
669 "ICMP Router discovery debug Averts. and Solicits (short)\n"
670 "IRDP debugging options\n"
671 "Enable debugging for IRDP packets\n")
673 VTY_DECLVAR_CONTEXT(interface
, ifp
);
674 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
678 irdp
->flags
|= IF_DEBUG_PACKET
;
684 DEFUN (ip_irdp_debug_disable
,
685 ip_irdp_debug_disable_cmd
,
686 "ip irdp debug disable",
688 "ICMP Router discovery debug Averts. and Solicits (short)\n"
689 "IRDP debugging options\n"
690 "Disable debugging for all IRDP events\n")
692 VTY_DECLVAR_CONTEXT(interface
, ifp
);
693 struct irdp_interface
*irdp
= irdp_if_get(ifp
);
697 irdp
->flags
&= ~IF_DEBUG_PACKET
;
698 irdp
->flags
&= ~IF_DEBUG_MESSAGES
;
699 irdp
->flags
&= ~IF_DEBUG_MISC
;
706 hook_register(zebra_if_config_wr
, irdp_config_write
);
707 hook_register(if_del
, irdp_if_delete
);
709 install_element(INTERFACE_NODE
, &ip_irdp_broadcast_cmd
);
710 install_element(INTERFACE_NODE
, &ip_irdp_multicast_cmd
);
711 install_element(INTERFACE_NODE
, &no_ip_irdp_cmd
);
712 install_element(INTERFACE_NODE
, &ip_irdp_shutdown_cmd
);
713 install_element(INTERFACE_NODE
, &no_ip_irdp_shutdown_cmd
);
714 install_element(INTERFACE_NODE
, &ip_irdp_holdtime_cmd
);
715 install_element(INTERFACE_NODE
, &ip_irdp_maxadvertinterval_cmd
);
716 install_element(INTERFACE_NODE
, &ip_irdp_minadvertinterval_cmd
);
717 install_element(INTERFACE_NODE
, &ip_irdp_preference_cmd
);
718 install_element(INTERFACE_NODE
, &ip_irdp_address_preference_cmd
);
719 install_element(INTERFACE_NODE
, &no_ip_irdp_address_preference_cmd
);
721 install_element(INTERFACE_NODE
, &ip_irdp_debug_messages_cmd
);
722 install_element(INTERFACE_NODE
, &ip_irdp_debug_misc_cmd
);
723 install_element(INTERFACE_NODE
, &ip_irdp_debug_packet_cmd
);
724 install_element(INTERFACE_NODE
, &ip_irdp_debug_disable_cmd
);