3 * Copyright (C) 2000 Robert Olsson.
4 * Swedish University of Agricultural Sciences
6 * This file is part of GNU Zebra.
8 * GNU Zebra is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2, or (at your option) any
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.
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 Free
20 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * This work includes work with the following copywrite:
27 * Copyright (C) 1997, 2000 Kunihiro Ishiguro
32 * Thanks to Jens Låås at Swedish University of Agricultural Sciences
33 * for reviewing and tests.
43 #include "sockunion.h"
47 #include "zebra_memory.h"
50 #include "connected.h"
54 #include "zebra/interface.h"
55 #include "zebra/rtadv.h"
56 #include "zebra/rib.h"
57 #include "zebra/zserv.h"
58 #include "zebra/redistribute.h"
59 #include "zebra/irdp.h"
60 #include <netinet/ip_icmp.h>
62 #include "sockunion.h"
68 inet_2a(u_int32_t a
, char *b
)
70 sprintf(b
, "%u.%u.%u.%u",
79 static struct prefix
*
80 irdp_get_prefix(struct interface
*ifp
)
82 struct listnode
*node
;
83 struct connected
*ifc
;
86 for (ALL_LIST_ELEMENTS_RO (ifp
->connected
, node
, ifc
))
92 /* Join to the add/leave multicast group. */
94 if_group (struct interface
*ifp
,
102 char b1
[INET_ADDRSTRLEN
];
104 memset (&m
, 0, sizeof (m
));
105 m
.imr_multiaddr
.s_addr
= htonl (group
);
106 p
= irdp_get_prefix(ifp
);
109 zlog_warn ("IRDP: can't get address for %s", ifp
->name
);
113 m
.imr_interface
= p
->u
.prefix4
;
115 ret
= setsockopt (sock
, IPPROTO_IP
, add_leave
,
116 (char *) &m
, sizeof (struct ip_mreq
));
118 zlog_warn ("IRDP: %s can't setsockopt %s: %s",
119 add_leave
== IP_ADD_MEMBERSHIP
? "join group":"leave group",
121 safe_strerror (errno
));
127 if_add_group (struct interface
*ifp
)
129 struct zebra_if
*zi
= ifp
->info
;
130 struct irdp_interface
*irdp
= &zi
->irdp
;
132 char b1
[INET_ADDRSTRLEN
];
134 ret
= if_group (ifp
, irdp_sock
, INADDR_ALLRTRS_GROUP
, IP_ADD_MEMBERSHIP
);
139 if(irdp
->flags
& IF_DEBUG_MISC
)
140 zlog_debug("IRDP: Adding group %s for %s",
141 inet_2a(htonl(INADDR_ALLRTRS_GROUP
), b1
),
147 if_drop_group (struct interface
*ifp
)
149 struct zebra_if
*zi
= ifp
->info
;
150 struct irdp_interface
*irdp
= &zi
->irdp
;
152 char b1
[INET_ADDRSTRLEN
];
154 ret
= if_group (ifp
, irdp_sock
, INADDR_ALLRTRS_GROUP
, IP_DROP_MEMBERSHIP
);
158 if(irdp
->flags
& IF_DEBUG_MISC
)
159 zlog_debug("IRDP: Leaving group %s for %s",
160 inet_2a(htonl(INADDR_ALLRTRS_GROUP
), b1
),
166 if_set_defaults(struct interface
*ifp
)
168 struct zebra_if
*zi
=ifp
->info
;
169 struct irdp_interface
*irdp
=&zi
->irdp
;
171 irdp
->MaxAdvertInterval
= IRDP_MAXADVERTINTERVAL
;
172 irdp
->MinAdvertInterval
= IRDP_MINADVERTINTERVAL
;
173 irdp
->Preference
= IRDP_PREFERENCE
;
174 irdp
->Lifetime
= IRDP_LIFETIME
;
178 static struct Adv
*Adv_new (void)
180 return XCALLOC (MTYPE_TMP
, sizeof (struct Adv
));
184 Adv_free (struct Adv
*adv
)
186 XFREE (MTYPE_TMP
, adv
);
190 irdp_if_start(struct interface
*ifp
, int multicast
, int set_defaults
)
192 struct zebra_if
*zi
= ifp
->info
;
193 struct irdp_interface
*irdp
= &zi
->irdp
;
194 struct listnode
*node
;
195 struct connected
*ifc
;
196 u_int32_t timer
, seed
;
198 if (irdp
->flags
& IF_ACTIVE
) {
199 zlog_warn("IRDP: Interface is already active %s", ifp
->name
);
202 if ((irdp_sock
< 0) && ((irdp_sock
= irdp_sock_init()) < 0)) {
203 zlog_warn("IRDP: Cannot activate interface %s (cannot create "
204 "IRDP socket)", ifp
->name
);
207 irdp
->flags
|= IF_ACTIVE
;
210 irdp
->flags
|= IF_BROADCAST
;
214 if (! (ifp
->flags
& IFF_UP
)) {
215 zlog_warn("IRDP: Interface is down %s", ifp
->name
);
218 /* Shall we cancel if_start if if_add_group fails? */
223 if (! (ifp
->flags
& (IFF_MULTICAST
|IFF_ALLMULTI
))) {
224 zlog_warn("IRDP: Interface not multicast enabled %s", ifp
->name
);
229 if_set_defaults(ifp
);
233 /* The spec suggests this for randomness */
237 for (ALL_LIST_ELEMENTS_RO (ifp
->connected
, node
, ifc
))
239 seed
= ifc
->address
->u
.prefix4
.s_addr
;
244 timer
= (random () % IRDP_DEFAULT_INTERVAL
) + 1;
246 irdp
->AdvPrefList
= list_new();
247 irdp
->AdvPrefList
->del
= (void (*)(void *)) Adv_free
; /* Destructor */
250 /* And this for startup. Speed limit from 1991 :-). But it's OK*/
252 if(irdp
->irdp_sent
< MAX_INITIAL_ADVERTISEMENTS
&&
253 timer
> MAX_INITIAL_ADVERT_INTERVAL
)
254 timer
= MAX_INITIAL_ADVERT_INTERVAL
;
257 if(irdp
->flags
& IF_DEBUG_MISC
)
258 zlog_debug("IRDP: Init timer for %s set to %u",
262 irdp
->t_advertise
= NULL
;
263 thread_add_timer(zebrad
.master
, irdp_send_thread
, ifp
, timer
,
268 irdp_if_stop(struct interface
*ifp
)
270 struct zebra_if
*zi
=ifp
->info
;
271 struct irdp_interface
*irdp
=&zi
->irdp
;
274 zlog_warn ("Interface %s structure is NULL", ifp
->name
);
278 if (! (irdp
->flags
& IF_ACTIVE
)) {
279 zlog_warn("Interface is not active %s", ifp
->name
);
283 if(! (irdp
->flags
& IF_BROADCAST
))
286 irdp_advert_off(ifp
);
288 list_delete(irdp
->AdvPrefList
);
289 irdp
->AdvPrefList
=NULL
;
296 irdp_if_shutdown(struct interface
*ifp
)
298 struct zebra_if
*zi
= ifp
->info
;
299 struct irdp_interface
*irdp
= &zi
->irdp
;
301 if (irdp
->flags
& IF_SHUTDOWN
) {
302 zlog_warn("IRDP: Interface is already shutdown %s", ifp
->name
);
306 irdp
->flags
|= IF_SHUTDOWN
;
307 irdp
->flags
&= ~IF_ACTIVE
;
309 if(! (irdp
->flags
& IF_BROADCAST
))
312 /* Tell the hosts we are out of service */
313 irdp_advert_off(ifp
);
317 irdp_if_no_shutdown(struct interface
*ifp
)
319 struct zebra_if
*zi
= ifp
->info
;
320 struct irdp_interface
*irdp
= &zi
->irdp
;
322 if (! (irdp
->flags
& IF_SHUTDOWN
)) {
323 zlog_warn("IRDP: Interface is not shutdown %s", ifp
->name
);
327 irdp
->flags
&= ~IF_SHUTDOWN
;
329 irdp_if_start(ifp
, irdp
->flags
& IF_BROADCAST
? FALSE
: TRUE
, FALSE
);
334 /* Write configuration to user */
336 void irdp_config_write (struct vty
*vty
, struct interface
*ifp
)
338 struct zebra_if
*zi
=ifp
->info
;
339 struct irdp_interface
*irdp
=&zi
->irdp
;
341 struct listnode
*node
;
342 char b1
[INET_ADDRSTRLEN
];
344 if(irdp
->flags
& IF_ACTIVE
|| irdp
->flags
& IF_SHUTDOWN
) {
346 if( irdp
->flags
& IF_SHUTDOWN
)
347 vty_out (vty
, " ip irdp shutdown %s", VTY_NEWLINE
);
349 if( irdp
->flags
& IF_BROADCAST
)
350 vty_out (vty
, " ip irdp broadcast%s", VTY_NEWLINE
);
352 vty_out (vty
, " ip irdp multicast%s", VTY_NEWLINE
);
354 vty_out (vty
, " ip irdp preference %ld%s",
355 irdp
->Preference
, VTY_NEWLINE
);
357 for (ALL_LIST_ELEMENTS_RO (irdp
->AdvPrefList
, node
, adv
))
358 vty_out (vty
, " ip irdp address %s preference %d%s",
359 inet_2a(adv
->ip
.s_addr
, b1
),
363 vty_out (vty
, " ip irdp holdtime %d%s",
364 irdp
->Lifetime
, VTY_NEWLINE
);
366 vty_out (vty
, " ip irdp minadvertinterval %ld%s",
367 irdp
->MinAdvertInterval
, VTY_NEWLINE
);
369 vty_out (vty
, " ip irdp maxadvertinterval %ld%s",
370 irdp
->MaxAdvertInterval
, VTY_NEWLINE
);
376 DEFUN (ip_irdp_multicast
,
377 ip_irdp_multicast_cmd
,
380 "ICMP Router discovery on this interface\n"
381 "Use multicast mode\n")
383 VTY_DECLVAR_CONTEXT (interface
, ifp
);
385 irdp_if_start(ifp
, TRUE
, TRUE
);
389 DEFUN (ip_irdp_broadcast
,
390 ip_irdp_broadcast_cmd
,
393 "ICMP Router discovery on this interface\n"
394 "Use broadcast mode\n")
396 VTY_DECLVAR_CONTEXT (interface
, ifp
);
398 irdp_if_start(ifp
, FALSE
, TRUE
);
407 "Disable ICMP Router discovery on this interface\n")
409 VTY_DECLVAR_CONTEXT (interface
, ifp
);
415 DEFUN (ip_irdp_shutdown
,
416 ip_irdp_shutdown_cmd
,
419 "ICMP Router discovery on this interface\n"
420 "ICMP Router discovery shutdown on this interface\n")
422 VTY_DECLVAR_CONTEXT (interface
, ifp
);
424 irdp_if_shutdown(ifp
);
428 DEFUN (no_ip_irdp_shutdown
,
429 no_ip_irdp_shutdown_cmd
,
430 "no ip irdp shutdown",
433 "ICMP Router discovery on this interface\n"
434 "ICMP Router discovery no shutdown on this interface\n")
436 VTY_DECLVAR_CONTEXT (interface
, ifp
);
438 irdp_if_no_shutdown(ifp
);
442 DEFUN (ip_irdp_holdtime
,
443 ip_irdp_holdtime_cmd
,
444 "ip irdp holdtime (0-9000)",
446 "ICMP Router discovery on this interface\n"
447 "Set holdtime value\n"
448 "Holdtime value in seconds. Default is 1800 seconds\n")
451 VTY_DECLVAR_CONTEXT (interface
, ifp
);
453 struct irdp_interface
*irdp
;
458 irdp
->Lifetime
= atoi(argv
[idx_number
]->arg
);
462 DEFUN (ip_irdp_minadvertinterval
,
463 ip_irdp_minadvertinterval_cmd
,
464 "ip irdp minadvertinterval (3-1800)",
466 "ICMP Router discovery on this interface\n"
467 "Set minimum time between advertisement\n"
468 "Minimum advertisement interval in seconds\n")
471 VTY_DECLVAR_CONTEXT (interface
, ifp
);
473 struct irdp_interface
*irdp
;
478 if( (unsigned) atoi(argv
[idx_number
]->arg
) <= irdp
->MaxAdvertInterval
) {
479 irdp
->MinAdvertInterval
= atoi(argv
[idx_number
]->arg
);
484 vty_out (vty
, "ICMP warning maxadvertinterval is greater or equal than minadvertinterval%s",
487 vty_out (vty
, "Please correct!%s",
492 DEFUN (ip_irdp_maxadvertinterval
,
493 ip_irdp_maxadvertinterval_cmd
,
494 "ip irdp maxadvertinterval (4-1800)",
496 "ICMP Router discovery on this interface\n"
497 "Set maximum time between advertisement\n"
498 "Maximum advertisement interval in seconds\n")
501 VTY_DECLVAR_CONTEXT (interface
, ifp
);
503 struct irdp_interface
*irdp
;
509 if( irdp
->MinAdvertInterval
<= (unsigned) atoi(argv
[idx_number
]->arg
) ) {
510 irdp
->MaxAdvertInterval
= atoi(argv
[idx_number
]->arg
);
515 vty_out (vty
, "ICMP warning maxadvertinterval is greater or equal than minadvertinterval%s",
518 vty_out (vty
, "Please correct!%s",
523 /* DEFUN needs to be fixed for negative ranages...
524 * "ip irdp preference <-2147483648-2147483647>",
525 * Be positive for now. :-)
528 DEFUN (ip_irdp_preference
,
529 ip_irdp_preference_cmd
,
530 "ip irdp preference (0-2147483647)",
532 "ICMP Router discovery on this interface\n"
533 "Set default preference level for this interface\n"
534 "Preference level\n")
537 VTY_DECLVAR_CONTEXT (interface
, ifp
);
539 struct irdp_interface
*irdp
;
544 irdp
->Preference
= atoi(argv
[idx_number
]->arg
);
548 DEFUN (ip_irdp_address_preference
,
549 ip_irdp_address_preference_cmd
,
550 "ip irdp address A.B.C.D preference (0-2147483647)",
552 "Alter ICMP Router discovery preference on this interface\n"
553 "Set IRDP address for advertise\n"
555 "Specify IRDP non-default preference to advertise\n"
556 "Preference level\n")
560 VTY_DECLVAR_CONTEXT (interface
, ifp
);
561 struct listnode
*node
;
566 struct irdp_interface
*irdp
;
572 ret
= inet_aton(argv
[idx_ipv4
]->arg
, &ip
);
573 if(!ret
) return CMD_WARNING
;
575 pref
= atoi(argv
[idx_number
]->arg
);
577 for (ALL_LIST_ELEMENTS_RO (irdp
->AdvPrefList
, node
, adv
))
578 if(adv
->ip
.s_addr
== ip
.s_addr
)
584 listnode_add(irdp
->AdvPrefList
, adv
);
590 DEFUN (no_ip_irdp_address_preference
,
591 no_ip_irdp_address_preference_cmd
,
592 "no ip irdp address A.B.C.D preference (0-2147483647)",
595 "Alter ICMP Router discovery preference on this interface\n"
596 "Select IRDP address\n"
598 "Reset ICMP Router discovery preference on this interface\n"
599 "Old preference level\n")
602 VTY_DECLVAR_CONTEXT (interface
, ifp
);
603 struct listnode
*node
, *nnode
;
607 struct irdp_interface
*irdp
;
613 ret
= inet_aton(argv
[idx_ipv4
]->arg
, &ip
);
617 for (ALL_LIST_ELEMENTS (irdp
->AdvPrefList
, node
, nnode
, adv
))
619 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
);
639 struct irdp_interface
*irdp
;
644 irdp
->flags
|= IF_DEBUG_MESSAGES
;
649 DEFUN (ip_irdp_debug_misc
,
650 ip_irdp_debug_misc_cmd
,
651 "ip irdp debug misc",
653 "ICMP Router discovery debug Averts. and Solicits (short)\n"
654 "IRDP debugging options\n"
655 "Enable debugging for miscellaneous IRDP events\n")
657 VTY_DECLVAR_CONTEXT (interface
, ifp
);
659 struct irdp_interface
*irdp
;
664 irdp
->flags
|= IF_DEBUG_MISC
;
669 DEFUN (ip_irdp_debug_packet
,
670 ip_irdp_debug_packet_cmd
,
671 "ip irdp debug packet",
673 "ICMP Router discovery debug Averts. and Solicits (short)\n"
674 "IRDP debugging options\n"
675 "Enable debugging for IRDP packets\n")
677 VTY_DECLVAR_CONTEXT (interface
, ifp
);
679 struct irdp_interface
*irdp
;
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
);
700 struct irdp_interface
*irdp
;
705 irdp
->flags
&= ~IF_DEBUG_PACKET
;
706 irdp
->flags
&= ~IF_DEBUG_MESSAGES
;
707 irdp
->flags
&= ~IF_DEBUG_MISC
;
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
);
733 #endif /* HAVE_IRDP */