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"
49 #include "connected.h"
53 #include "zebra/interface.h"
54 #include "zebra/rtadv.h"
55 #include "zebra/rib.h"
56 #include "zebra/zserv.h"
57 #include "zebra/redistribute.h"
58 #include "zebra/irdp.h"
59 #include <netinet/ip_icmp.h>
61 #include "sockunion.h"
65 /* Master of threads. */
66 extern struct zebra_t zebrad
;
71 inet_2a(u_int32_t a
, char *b
)
73 sprintf(b
, "%u.%u.%u.%u",
82 static struct prefix
*
83 irdp_get_prefix(struct interface
*ifp
)
85 struct listnode
*node
;
86 struct connected
*ifc
;
89 for (ALL_LIST_ELEMENTS_RO (ifp
->connected
, node
, ifc
))
95 /* Join to the add/leave multicast group. */
97 if_group (struct interface
*ifp
,
105 char b1
[INET_ADDRSTRLEN
];
107 memset (&m
, 0, sizeof (m
));
108 m
.imr_multiaddr
.s_addr
= htonl (group
);
109 p
= irdp_get_prefix(ifp
);
112 zlog_warn ("IRDP: can't get address for %s", ifp
->name
);
116 m
.imr_interface
= p
->u
.prefix4
;
118 ret
= setsockopt (sock
, IPPROTO_IP
, add_leave
,
119 (char *) &m
, sizeof (struct ip_mreq
));
121 zlog_warn ("IRDP: %s can't setsockopt %s: %s",
122 add_leave
== IP_ADD_MEMBERSHIP
? "join group":"leave group",
124 safe_strerror (errno
));
130 if_add_group (struct interface
*ifp
)
132 struct zebra_if
*zi
= ifp
->info
;
133 struct irdp_interface
*irdp
= &zi
->irdp
;
135 char b1
[INET_ADDRSTRLEN
];
137 ret
= if_group (ifp
, irdp_sock
, INADDR_ALLRTRS_GROUP
, IP_ADD_MEMBERSHIP
);
142 if(irdp
->flags
& IF_DEBUG_MISC
)
143 zlog_debug("IRDP: Adding group %s for %s",
144 inet_2a(htonl(INADDR_ALLRTRS_GROUP
), b1
),
150 if_drop_group (struct interface
*ifp
)
152 struct zebra_if
*zi
= ifp
->info
;
153 struct irdp_interface
*irdp
= &zi
->irdp
;
155 char b1
[INET_ADDRSTRLEN
];
157 ret
= if_group (ifp
, irdp_sock
, INADDR_ALLRTRS_GROUP
, IP_DROP_MEMBERSHIP
);
161 if(irdp
->flags
& IF_DEBUG_MISC
)
162 zlog_debug("IRDP: Leaving group %s for %s",
163 inet_2a(htonl(INADDR_ALLRTRS_GROUP
), b1
),
169 if_set_defaults(struct interface
*ifp
)
171 struct zebra_if
*zi
=ifp
->info
;
172 struct irdp_interface
*irdp
=&zi
->irdp
;
174 irdp
->MaxAdvertInterval
= IRDP_MAXADVERTINTERVAL
;
175 irdp
->MinAdvertInterval
= IRDP_MINADVERTINTERVAL
;
176 irdp
->Preference
= IRDP_PREFERENCE
;
177 irdp
->Lifetime
= IRDP_LIFETIME
;
181 static struct Adv
*Adv_new (void)
183 return XCALLOC (MTYPE_TMP
, sizeof (struct Adv
));
187 Adv_free (struct Adv
*adv
)
189 XFREE (MTYPE_TMP
, adv
);
193 irdp_if_start(struct interface
*ifp
, int multicast
, int set_defaults
)
195 struct zebra_if
*zi
= ifp
->info
;
196 struct irdp_interface
*irdp
= &zi
->irdp
;
197 struct listnode
*node
;
198 struct connected
*ifc
;
199 u_int32_t timer
, seed
;
201 if (irdp
->flags
& IF_ACTIVE
) {
202 zlog_warn("IRDP: Interface is already active %s", ifp
->name
);
205 if ((irdp_sock
< 0) && ((irdp_sock
= irdp_sock_init()) < 0)) {
206 zlog_warn("IRDP: Cannot activate interface %s (cannot create "
207 "IRDP socket)", ifp
->name
);
210 irdp
->flags
|= IF_ACTIVE
;
213 irdp
->flags
|= IF_BROADCAST
;
217 if (! (ifp
->flags
& IFF_UP
)) {
218 zlog_warn("IRDP: Interface is down %s", ifp
->name
);
221 /* Shall we cancel if_start if if_add_group fails? */
226 if (! (ifp
->flags
& (IFF_MULTICAST
|IFF_ALLMULTI
))) {
227 zlog_warn("IRDP: Interface not multicast enabled %s", ifp
->name
);
232 if_set_defaults(ifp
);
236 /* The spec suggests this for randomness */
240 for (ALL_LIST_ELEMENTS_RO (ifp
->connected
, node
, ifc
))
242 seed
= ifc
->address
->u
.prefix4
.s_addr
;
247 timer
= (random () % IRDP_DEFAULT_INTERVAL
) + 1;
249 irdp
->AdvPrefList
= list_new();
250 irdp
->AdvPrefList
->del
= (void (*)(void *)) Adv_free
; /* Destructor */
253 /* And this for startup. Speed limit from 1991 :-). But it's OK*/
255 if(irdp
->irdp_sent
< MAX_INITIAL_ADVERTISEMENTS
&&
256 timer
> MAX_INITIAL_ADVERT_INTERVAL
)
257 timer
= MAX_INITIAL_ADVERT_INTERVAL
;
260 if(irdp
->flags
& IF_DEBUG_MISC
)
261 zlog_debug("IRDP: Init timer for %s set to %u",
265 irdp
->t_advertise
= thread_add_timer(zebrad
.master
,
272 irdp_if_stop(struct interface
*ifp
)
274 struct zebra_if
*zi
=ifp
->info
;
275 struct irdp_interface
*irdp
=&zi
->irdp
;
278 zlog_warn ("Interface %s structure is NULL", ifp
->name
);
282 if (! (irdp
->flags
& IF_ACTIVE
)) {
283 zlog_warn("Interface is not active %s", ifp
->name
);
287 if(! (irdp
->flags
& IF_BROADCAST
))
290 irdp_advert_off(ifp
);
292 list_delete(irdp
->AdvPrefList
);
293 irdp
->AdvPrefList
=NULL
;
300 irdp_if_shutdown(struct interface
*ifp
)
302 struct zebra_if
*zi
= ifp
->info
;
303 struct irdp_interface
*irdp
= &zi
->irdp
;
305 if (irdp
->flags
& IF_SHUTDOWN
) {
306 zlog_warn("IRDP: Interface is already shutdown %s", ifp
->name
);
310 irdp
->flags
|= IF_SHUTDOWN
;
311 irdp
->flags
&= ~IF_ACTIVE
;
313 if(! (irdp
->flags
& IF_BROADCAST
))
316 /* Tell the hosts we are out of service */
317 irdp_advert_off(ifp
);
321 irdp_if_no_shutdown(struct interface
*ifp
)
323 struct zebra_if
*zi
= ifp
->info
;
324 struct irdp_interface
*irdp
= &zi
->irdp
;
326 if (! (irdp
->flags
& IF_SHUTDOWN
)) {
327 zlog_warn("IRDP: Interface is not shutdown %s", ifp
->name
);
331 irdp
->flags
&= ~IF_SHUTDOWN
;
333 irdp_if_start(ifp
, irdp
->flags
& IF_BROADCAST
? FALSE
: TRUE
, FALSE
);
338 /* Write configuration to user */
340 void irdp_config_write (struct vty
*vty
, struct interface
*ifp
)
342 struct zebra_if
*zi
=ifp
->info
;
343 struct irdp_interface
*irdp
=&zi
->irdp
;
345 struct listnode
*node
;
346 char b1
[INET_ADDRSTRLEN
];
348 if(irdp
->flags
& IF_ACTIVE
|| irdp
->flags
& IF_SHUTDOWN
) {
350 if( irdp
->flags
& IF_SHUTDOWN
)
351 vty_out (vty
, " ip irdp shutdown %s", VTY_NEWLINE
);
353 if( irdp
->flags
& IF_BROADCAST
)
354 vty_out (vty
, " ip irdp broadcast%s", VTY_NEWLINE
);
356 vty_out (vty
, " ip irdp multicast%s", VTY_NEWLINE
);
358 vty_out (vty
, " ip irdp preference %ld%s",
359 irdp
->Preference
, VTY_NEWLINE
);
361 for (ALL_LIST_ELEMENTS_RO (irdp
->AdvPrefList
, node
, adv
))
362 vty_out (vty
, " ip irdp address %s preference %d%s",
363 inet_2a(adv
->ip
.s_addr
, b1
),
367 vty_out (vty
, " ip irdp holdtime %d%s",
368 irdp
->Lifetime
, VTY_NEWLINE
);
370 vty_out (vty
, " ip irdp minadvertinterval %ld%s",
371 irdp
->MinAdvertInterval
, VTY_NEWLINE
);
373 vty_out (vty
, " ip irdp maxadvertinterval %ld%s",
374 irdp
->MaxAdvertInterval
, VTY_NEWLINE
);
380 DEFUN (ip_irdp_multicast
,
381 ip_irdp_multicast_cmd
,
384 "ICMP Router discovery on this interface using multicast\n")
386 struct interface
*ifp
;
388 ifp
= (struct interface
*) vty
->index
;
393 irdp_if_start(ifp
, TRUE
, TRUE
);
397 DEFUN (ip_irdp_broadcast
,
398 ip_irdp_broadcast_cmd
,
401 "ICMP Router discovery on this interface using broadcast\n")
403 struct interface
*ifp
;
405 ifp
= (struct interface
*) vty
->index
;
410 irdp_if_start(ifp
, FALSE
, TRUE
);
419 "Disable ICMP Router discovery on this interface\n")
421 struct interface
*ifp
;
423 ifp
= (struct interface
*) vty
->index
;
432 DEFUN (ip_irdp_shutdown
,
433 ip_irdp_shutdown_cmd
,
436 "ICMP Router discovery shutdown on this interface\n")
438 struct interface
*ifp
;
440 ifp
= (struct interface
*) vty
->index
;
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 no shutdown on this interface\n")
456 struct interface
*ifp
;
458 ifp
= (struct interface
*) vty
->index
;
463 irdp_if_no_shutdown(ifp
);
467 DEFUN (ip_irdp_holdtime
,
468 ip_irdp_holdtime_cmd
,
469 "ip irdp holdtime <0-9000>",
471 "ICMP Router discovery on this interface\n"
472 "Set holdtime value\n"
473 "Holdtime value in seconds. Default is 1800 seconds\n")
475 struct interface
*ifp
;
477 struct irdp_interface
*irdp
;
478 ifp
= (struct interface
*) vty
->index
;
486 irdp
->Lifetime
= atoi(argv
[0]);
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")
498 struct interface
*ifp
;
500 struct irdp_interface
*irdp
;
501 ifp
= (struct interface
*) vty
->index
;
509 if( (unsigned) atoi(argv
[0]) <= irdp
->MaxAdvertInterval
) {
510 irdp
->MinAdvertInterval
= atoi(argv
[0]);
515 vty_out (vty
, "ICMP warning maxadvertinterval is greater or equal than minadvertinterval%s",
518 vty_out (vty
, "Please correct!%s",
523 DEFUN (ip_irdp_maxadvertinterval
,
524 ip_irdp_maxadvertinterval_cmd
,
525 "ip irdp maxadvertinterval <4-1800>",
527 "ICMP Router discovery on this interface\n"
528 "Set maximum time between advertisement\n"
529 "Maximum advertisement interval in seconds\n")
531 struct interface
*ifp
;
533 struct irdp_interface
*irdp
;
534 ifp
= (struct interface
*) vty
->index
;
543 if( irdp
->MinAdvertInterval
<= (unsigned) atoi(argv
[0]) ) {
544 irdp
->MaxAdvertInterval
= atoi(argv
[0]);
549 vty_out (vty
, "ICMP warning maxadvertinterval is greater or equal than minadvertinterval%s",
552 vty_out (vty
, "Please correct!%s",
557 /* DEFUN needs to be fixed for negative ranages...
558 * "ip irdp preference <-2147483648-2147483647>",
559 * Be positive for now. :-)
562 DEFUN (ip_irdp_preference
,
563 ip_irdp_preference_cmd
,
564 "ip irdp preference <0-2147483647>",
566 "ICMP Router discovery on this interface\n"
567 "Set default preference level for this interface\n"
568 "Preference level\n")
570 struct interface
*ifp
;
572 struct irdp_interface
*irdp
;
573 ifp
= (struct interface
*) vty
->index
;
581 irdp
->Preference
= atoi(argv
[0]);
585 DEFUN (ip_irdp_address_preference
,
586 ip_irdp_address_preference_cmd
,
587 "ip irdp address A.B.C.D preference <0-2147483647>",
589 "Alter ICMP Router discovery preference this interface\n"
590 "Specify IRDP non-default preference to advertise\n"
591 "Set IRDP address for advertise\n"
592 "Preference level\n")
594 struct listnode
*node
;
598 struct interface
*ifp
;
600 struct irdp_interface
*irdp
;
603 ifp
= (struct interface
*) vty
->index
;
611 ret
= inet_aton(argv
[0], &ip
);
612 if(!ret
) return CMD_WARNING
;
614 pref
= atoi(argv
[1]);
616 for (ALL_LIST_ELEMENTS_RO (irdp
->AdvPrefList
, node
, adv
))
617 if(adv
->ip
.s_addr
== ip
.s_addr
)
623 listnode_add(irdp
->AdvPrefList
, adv
);
629 DEFUN (no_ip_irdp_address_preference
,
630 no_ip_irdp_address_preference_cmd
,
631 "no ip irdp address A.B.C.D preference <0-2147483647>",
634 "Alter ICMP Router discovery preference this interface\n"
635 "Removes IRDP non-default preference\n"
636 "Select IRDP address\n"
637 "Old preference level\n")
639 struct listnode
*node
, *nnode
;
643 struct interface
*ifp
;
645 struct irdp_interface
*irdp
;
648 ifp
= (struct interface
*) vty
->index
;
656 ret
= inet_aton(argv
[0], &ip
);
660 pref
= atoi(argv
[1]);
662 for (ALL_LIST_ELEMENTS (irdp
->AdvPrefList
, node
, nnode
, adv
))
664 if(adv
->ip
.s_addr
== ip
.s_addr
)
666 listnode_delete(irdp
->AdvPrefList
, adv
);
674 DEFUN (ip_irdp_debug_messages
,
675 ip_irdp_debug_messages_cmd
,
676 "ip irdp debug messages",
678 "ICMP Router discovery debug Averts. and Solicits (short)\n")
680 struct interface
*ifp
;
682 struct irdp_interface
*irdp
;
683 ifp
= (struct interface
*) vty
->index
;
691 irdp
->flags
|= IF_DEBUG_MESSAGES
;
696 DEFUN (ip_irdp_debug_misc
,
697 ip_irdp_debug_misc_cmd
,
698 "ip irdp debug misc",
700 "ICMP Router discovery debug Averts. and Solicits (short)\n")
702 struct interface
*ifp
;
704 struct irdp_interface
*irdp
;
705 ifp
= (struct interface
*) vty
->index
;
713 irdp
->flags
|= IF_DEBUG_MISC
;
718 DEFUN (ip_irdp_debug_packet
,
719 ip_irdp_debug_packet_cmd
,
720 "ip irdp debug packet",
722 "ICMP Router discovery debug Averts. and Solicits (short)\n")
724 struct interface
*ifp
;
726 struct irdp_interface
*irdp
;
727 ifp
= (struct interface
*) vty
->index
;
735 irdp
->flags
|= IF_DEBUG_PACKET
;
741 DEFUN (ip_irdp_debug_disable
,
742 ip_irdp_debug_disable_cmd
,
743 "ip irdp debug disable",
745 "ICMP Router discovery debug Averts. and Solicits (short)\n")
747 struct interface
*ifp
;
749 struct irdp_interface
*irdp
;
750 ifp
= (struct interface
*) vty
->index
;
758 irdp
->flags
&= ~IF_DEBUG_PACKET
;
759 irdp
->flags
&= ~IF_DEBUG_MESSAGES
;
760 irdp
->flags
&= ~IF_DEBUG_MISC
;
768 install_element (INTERFACE_NODE
, &ip_irdp_broadcast_cmd
);
769 install_element (INTERFACE_NODE
, &ip_irdp_multicast_cmd
);
770 install_element (INTERFACE_NODE
, &no_ip_irdp_cmd
);
771 install_element (INTERFACE_NODE
, &ip_irdp_shutdown_cmd
);
772 install_element (INTERFACE_NODE
, &no_ip_irdp_shutdown_cmd
);
773 install_element (INTERFACE_NODE
, &ip_irdp_holdtime_cmd
);
774 install_element (INTERFACE_NODE
, &ip_irdp_maxadvertinterval_cmd
);
775 install_element (INTERFACE_NODE
, &ip_irdp_minadvertinterval_cmd
);
776 install_element (INTERFACE_NODE
, &ip_irdp_preference_cmd
);
777 install_element (INTERFACE_NODE
, &ip_irdp_address_preference_cmd
);
778 install_element (INTERFACE_NODE
, &no_ip_irdp_address_preference_cmd
);
780 install_element (INTERFACE_NODE
, &ip_irdp_debug_messages_cmd
);
781 install_element (INTERFACE_NODE
, &ip_irdp_debug_misc_cmd
);
782 install_element (INTERFACE_NODE
, &ip_irdp_debug_packet_cmd
);
783 install_element (INTERFACE_NODE
, &ip_irdp_debug_disable_cmd
);
786 #endif /* HAVE_IRDP */