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
;
68 int in_cksum (void *ptr
, int nbytes
);
70 int irdp_send_thread(struct thread
*t_advert
);
71 char *inet_2a(u_int32_t a
, char *b
);
72 void irdp_advert_off(struct interface
*ifp
);
75 char b1
[16], b2
[16], b3
[16], b4
[16]; /* For inet_2a */
77 static struct prefix
*
78 irdp_get_prefix(struct interface
*ifp
)
80 struct listnode
*node
;
81 struct connected
*ifc
;
84 for (ALL_LIST_ELEMENTS_RO (ifp
->connected
, node
, ifc
))
90 /* Join to the add/leave multicast group. */
92 if_group (struct interface
*ifp
,
104 bzero (&m
, 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
;
133 ret
= if_group (ifp
, irdp_sock
, INADDR_ALLRTRS_GROUP
, IP_ADD_MEMBERSHIP
);
138 if(irdp
->flags
& IF_DEBUG_MISC
)
139 zlog_debug("IRDP: Adding group %s for %s",
140 inet_2a(htonl(INADDR_ALLRTRS_GROUP
), b1
),
146 if_drop_group (struct interface
*ifp
)
148 struct zebra_if
*zi
= ifp
->info
;
149 struct irdp_interface
*irdp
= &zi
->irdp
;
152 ret
= if_group (ifp
, irdp_sock
, INADDR_ALLRTRS_GROUP
, IP_DROP_MEMBERSHIP
);
156 if(irdp
->flags
& IF_DEBUG_MISC
)
157 zlog_debug("IRDP: Leaving group %s for %s",
158 inet_2a(htonl(INADDR_ALLRTRS_GROUP
), b1
),
164 if_set_defaults(struct interface
*ifp
)
166 struct zebra_if
*zi
=ifp
->info
;
167 struct irdp_interface
*irdp
=&zi
->irdp
;
169 irdp
->MaxAdvertInterval
= IRDP_MAXADVERTINTERVAL
;
170 irdp
->MinAdvertInterval
= IRDP_MINADVERTINTERVAL
;
171 irdp
->Preference
= IRDP_PREFERENCE
;
172 irdp
->Lifetime
= IRDP_LIFETIME
;
176 struct Adv
*Adv_new (void)
179 new = XMALLOC (MTYPE_TMP
, sizeof (struct Adv
));
180 memset (new, 0, sizeof (struct Adv
));
185 Adv_free (struct Adv
*adv
)
187 XFREE (MTYPE_TMP
, adv
);
191 irdp_if_start(struct interface
*ifp
, int multicast
, int set_defaults
)
193 struct zebra_if
*zi
= ifp
->info
;
194 struct irdp_interface
*irdp
= &zi
->irdp
;
195 struct listnode
*node
;
196 struct connected
*ifc
;
197 u_int32_t timer
, seed
;
199 if (irdp
->flags
& IF_ACTIVE
) {
200 zlog_warn("IRDP: Interface is already active %s", ifp
->name
);
203 if ((irdp_sock
< 0) && ((irdp_sock
= irdp_sock_init()) < 0)) {
204 zlog_warn("IRDP: Cannot activate interface %s (cannot create "
205 "IRDP socket)", ifp
->name
);
208 irdp
->flags
|= IF_ACTIVE
;
211 irdp
->flags
|= IF_BROADCAST
;
215 if (! (ifp
->flags
& IFF_UP
)) {
216 zlog_warn("IRDP: Interface is down %s", ifp
->name
);
219 /* Shall we cancel if_start if if_add_group fails? */
224 if (! (ifp
->flags
& (IFF_MULTICAST
|IFF_ALLMULTI
))) {
225 zlog_warn("IRDP: Interface not multicast enabled %s", ifp
->name
);
230 if_set_defaults(ifp
);
234 /* The spec suggests this for randomness */
238 for (ALL_LIST_ELEMENTS_RO (ifp
->connected
, node
, ifc
))
240 seed
= ifc
->address
->u
.prefix4
.s_addr
;
245 timer
= (random () % IRDP_DEFAULT_INTERVAL
) + 1;
247 irdp
->AdvPrefList
= list_new();
248 irdp
->AdvPrefList
->del
= (void (*)(void *)) Adv_free
; /* Destructor */
251 /* And this for startup. Speed limit from 1991 :-). But it's OK*/
253 if(irdp
->irdp_sent
< MAX_INITIAL_ADVERTISEMENTS
&&
254 timer
> MAX_INITIAL_ADVERT_INTERVAL
)
255 timer
= MAX_INITIAL_ADVERT_INTERVAL
;
258 if(irdp
->flags
& IF_DEBUG_MISC
)
259 zlog_debug("IRDP: Init timer for %s set to %u",
263 irdp
->t_advertise
= thread_add_timer(zebrad
.master
,
270 irdp_if_stop(struct interface
*ifp
)
272 struct zebra_if
*zi
=ifp
->info
;
273 struct irdp_interface
*irdp
=&zi
->irdp
;
276 zlog_warn ("Interface %s structure is NULL", ifp
->name
);
280 if (! (irdp
->flags
& IF_ACTIVE
)) {
281 zlog_warn("Interface is not active %s", ifp
->name
);
285 if(! (irdp
->flags
& IF_BROADCAST
))
288 irdp_advert_off(ifp
);
290 list_delete(irdp
->AdvPrefList
);
291 irdp
->AdvPrefList
=NULL
;
298 irdp_if_shutdown(struct interface
*ifp
)
300 struct zebra_if
*zi
= ifp
->info
;
301 struct irdp_interface
*irdp
= &zi
->irdp
;
303 if (irdp
->flags
& IF_SHUTDOWN
) {
304 zlog_warn("IRDP: Interface is already shutdown %s", ifp
->name
);
308 irdp
->flags
|= IF_SHUTDOWN
;
309 irdp
->flags
&= ~IF_ACTIVE
;
311 if(! (irdp
->flags
& IF_BROADCAST
))
314 /* Tell the hosts we are out of service */
315 irdp_advert_off(ifp
);
319 irdp_if_no_shutdown(struct interface
*ifp
)
321 struct zebra_if
*zi
= ifp
->info
;
322 struct irdp_interface
*irdp
= &zi
->irdp
;
324 if (! (irdp
->flags
& IF_SHUTDOWN
)) {
325 zlog_warn("IRDP: Interface is not shutdown %s", ifp
->name
);
329 irdp
->flags
&= ~IF_SHUTDOWN
;
331 irdp_if_start(ifp
, irdp
->flags
& IF_BROADCAST
? FALSE
: TRUE
, FALSE
);
336 /* Write configuration to user */
338 void irdp_config_write (struct vty
*vty
, struct interface
*ifp
)
340 struct zebra_if
*zi
=ifp
->info
;
341 struct irdp_interface
*irdp
=&zi
->irdp
;
343 struct listnode
*node
;
345 if(irdp
->flags
& IF_ACTIVE
|| irdp
->flags
& IF_SHUTDOWN
) {
347 if( irdp
->flags
& IF_SHUTDOWN
)
348 vty_out (vty
, " ip irdp shutdown %s", VTY_NEWLINE
);
350 if( irdp
->flags
& IF_BROADCAST
)
351 vty_out (vty
, " ip irdp broadcast%s", VTY_NEWLINE
);
353 vty_out (vty
, " ip irdp multicast%s", VTY_NEWLINE
);
355 vty_out (vty
, " ip irdp preference %ld%s",
356 irdp
->Preference
, VTY_NEWLINE
);
358 for (ALL_LIST_ELEMENTS_RO (irdp
->AdvPrefList
, node
, adv
))
359 vty_out (vty
, " ip irdp address %s preference %d%s",
360 inet_2a(adv
->ip
.s_addr
, b1
),
364 vty_out (vty
, " ip irdp holdtime %d%s",
365 irdp
->Lifetime
, VTY_NEWLINE
);
367 vty_out (vty
, " ip irdp minadvertinterval %ld%s",
368 irdp
->MinAdvertInterval
, VTY_NEWLINE
);
370 vty_out (vty
, " ip irdp maxadvertinterval %ld%s",
371 irdp
->MaxAdvertInterval
, VTY_NEWLINE
);
377 DEFUN (ip_irdp_multicast
,
378 ip_irdp_multicast_cmd
,
381 "ICMP Router discovery on this interface using multicast\n")
383 struct interface
*ifp
;
385 ifp
= (struct interface
*) vty
->index
;
390 irdp_if_start(ifp
, TRUE
, TRUE
);
394 DEFUN (ip_irdp_broadcast
,
395 ip_irdp_broadcast_cmd
,
398 "ICMP Router discovery on this interface using broadcast\n")
400 struct interface
*ifp
;
402 ifp
= (struct interface
*) vty
->index
;
407 irdp_if_start(ifp
, FALSE
, TRUE
);
416 "Disable ICMP Router discovery on this interface\n")
418 struct interface
*ifp
;
420 ifp
= (struct interface
*) vty
->index
;
429 DEFUN (ip_irdp_shutdown
,
430 ip_irdp_shutdown_cmd
,
433 "ICMP Router discovery shutdown on this interface\n")
435 struct interface
*ifp
;
437 ifp
= (struct interface
*) vty
->index
;
442 irdp_if_shutdown(ifp
);
446 DEFUN (no_ip_irdp_shutdown
,
447 no_ip_irdp_shutdown_cmd
,
448 "no ip irdp shutdown",
451 "ICMP Router discovery no shutdown on this interface\n")
453 struct interface
*ifp
;
455 ifp
= (struct interface
*) vty
->index
;
460 irdp_if_no_shutdown(ifp
);
464 DEFUN (ip_irdp_holdtime
,
465 ip_irdp_holdtime_cmd
,
466 "ip irdp holdtime <0-9000>",
468 "ICMP Router discovery on this interface\n"
469 "Set holdtime value\n"
470 "Holdtime value in seconds. Default is 1800 seconds\n")
472 struct interface
*ifp
;
474 struct irdp_interface
*irdp
;
475 ifp
= (struct interface
*) vty
->index
;
483 irdp
->Lifetime
= atoi(argv
[0]);
487 DEFUN (ip_irdp_minadvertinterval
,
488 ip_irdp_minadvertinterval_cmd
,
489 "ip irdp minadvertinterval <3-1800>",
491 "ICMP Router discovery on this interface\n"
492 "Set minimum time between advertisement\n"
493 "Minimum advertisement interval in seconds\n")
495 struct interface
*ifp
;
497 struct irdp_interface
*irdp
;
498 ifp
= (struct interface
*) vty
->index
;
506 if( (unsigned) atoi(argv
[0]) <= irdp
->MaxAdvertInterval
) {
507 irdp
->MinAdvertInterval
= atoi(argv
[0]);
512 vty_out (vty
, "ICMP warning maxadvertinterval is greater or equal than minadvertinterval%s",
515 vty_out (vty
, "Please correct!%s",
520 DEFUN (ip_irdp_maxadvertinterval
,
521 ip_irdp_maxadvertinterval_cmd
,
522 "ip irdp maxadvertinterval <4-1800>",
524 "ICMP Router discovery on this interface\n"
525 "Set maximum time between advertisement\n"
526 "Maximum advertisement interval in seconds\n")
528 struct interface
*ifp
;
530 struct irdp_interface
*irdp
;
531 ifp
= (struct interface
*) vty
->index
;
540 if( irdp
->MinAdvertInterval
<= (unsigned) atoi(argv
[0]) ) {
541 irdp
->MaxAdvertInterval
= atoi(argv
[0]);
546 vty_out (vty
, "ICMP warning maxadvertinterval is greater or equal than minadvertinterval%s",
549 vty_out (vty
, "Please correct!%s",
554 /* DEFUN needs to be fixed for negative ranages...
555 * "ip irdp preference <-2147483648-2147483647>",
556 * Be positive for now. :-)
559 DEFUN (ip_irdp_preference
,
560 ip_irdp_preference_cmd
,
561 "ip irdp preference <0-2147483647>",
563 "ICMP Router discovery on this interface\n"
564 "Set default preference level for this interface\n"
565 "Preference level\n")
567 struct interface
*ifp
;
569 struct irdp_interface
*irdp
;
570 ifp
= (struct interface
*) vty
->index
;
578 irdp
->Preference
= atoi(argv
[0]);
582 DEFUN (ip_irdp_address_preference
,
583 ip_irdp_address_preference_cmd
,
584 "ip irdp address A.B.C.D preference <0-2147483647>",
586 "Alter ICMP Router discovery preference this interface\n"
587 "Specify IRDP non-default preference to advertise\n"
588 "Set IRDP address for advertise\n"
589 "Preference level\n")
591 struct listnode
*node
;
595 struct interface
*ifp
;
597 struct irdp_interface
*irdp
;
600 ifp
= (struct interface
*) vty
->index
;
608 ret
= inet_aton(argv
[0], &ip
);
609 if(!ret
) return CMD_WARNING
;
611 pref
= atoi(argv
[1]);
613 for (ALL_LIST_ELEMENTS_RO (irdp
->AdvPrefList
, node
, adv
))
614 if(adv
->ip
.s_addr
== ip
.s_addr
)
620 listnode_add(irdp
->AdvPrefList
, adv
);
626 DEFUN (no_ip_irdp_address_preference
,
627 no_ip_irdp_address_preference_cmd
,
628 "no ip irdp address A.B.C.D preference <0-2147483647>",
631 "Alter ICMP Router discovery preference this interface\n"
632 "Removes IRDP non-default preference\n"
633 "Select IRDP address\n"
634 "Old preference level\n")
636 struct listnode
*node
, *nnode
;
640 struct interface
*ifp
;
642 struct irdp_interface
*irdp
;
645 ifp
= (struct interface
*) vty
->index
;
653 ret
= inet_aton(argv
[0], &ip
);
657 pref
= atoi(argv
[1]);
659 for (ALL_LIST_ELEMENTS (irdp
->AdvPrefList
, node
, nnode
, adv
))
661 if(adv
->ip
.s_addr
== ip
.s_addr
)
663 listnode_delete(irdp
->AdvPrefList
, adv
);
671 DEFUN (ip_irdp_debug_messages
,
672 ip_irdp_debug_messages_cmd
,
673 "ip irdp debug messages",
675 "ICMP Router discovery debug Averts. and Solicits (short)\n")
677 struct interface
*ifp
;
679 struct irdp_interface
*irdp
;
680 ifp
= (struct interface
*) vty
->index
;
688 irdp
->flags
|= IF_DEBUG_MESSAGES
;
693 DEFUN (ip_irdp_debug_misc
,
694 ip_irdp_debug_misc_cmd
,
695 "ip irdp debug misc",
697 "ICMP Router discovery debug Averts. and Solicits (short)\n")
699 struct interface
*ifp
;
701 struct irdp_interface
*irdp
;
702 ifp
= (struct interface
*) vty
->index
;
710 irdp
->flags
|= IF_DEBUG_MISC
;
715 DEFUN (ip_irdp_debug_packet
,
716 ip_irdp_debug_packet_cmd
,
717 "ip irdp debug packet",
719 "ICMP Router discovery debug Averts. and Solicits (short)\n")
721 struct interface
*ifp
;
723 struct irdp_interface
*irdp
;
724 ifp
= (struct interface
*) vty
->index
;
732 irdp
->flags
|= IF_DEBUG_PACKET
;
738 DEFUN (ip_irdp_debug_disable
,
739 ip_irdp_debug_disable_cmd
,
740 "ip irdp debug disable",
742 "ICMP Router discovery debug Averts. and Solicits (short)\n")
744 struct interface
*ifp
;
746 struct irdp_interface
*irdp
;
747 ifp
= (struct interface
*) vty
->index
;
755 irdp
->flags
&= ~IF_DEBUG_PACKET
;
756 irdp
->flags
&= ~IF_DEBUG_MESSAGES
;
757 irdp
->flags
&= ~IF_DEBUG_MISC
;
765 install_element (INTERFACE_NODE
, &ip_irdp_broadcast_cmd
);
766 install_element (INTERFACE_NODE
, &ip_irdp_multicast_cmd
);
767 install_element (INTERFACE_NODE
, &no_ip_irdp_cmd
);
768 install_element (INTERFACE_NODE
, &ip_irdp_shutdown_cmd
);
769 install_element (INTERFACE_NODE
, &no_ip_irdp_shutdown_cmd
);
770 install_element (INTERFACE_NODE
, &ip_irdp_holdtime_cmd
);
771 install_element (INTERFACE_NODE
, &ip_irdp_maxadvertinterval_cmd
);
772 install_element (INTERFACE_NODE
, &ip_irdp_minadvertinterval_cmd
);
773 install_element (INTERFACE_NODE
, &ip_irdp_preference_cmd
);
774 install_element (INTERFACE_NODE
, &ip_irdp_address_preference_cmd
);
775 install_element (INTERFACE_NODE
, &no_ip_irdp_address_preference_cmd
);
777 install_element (INTERFACE_NODE
, &ip_irdp_debug_messages_cmd
);
778 install_element (INTERFACE_NODE
, &ip_irdp_debug_misc_cmd
);
779 install_element (INTERFACE_NODE
, &ip_irdp_debug_packet_cmd
);
780 install_element (INTERFACE_NODE
, &ip_irdp_debug_disable_cmd
);
783 #endif /* HAVE_IRDP */