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 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
;
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)
178 return XCALLOC (MTYPE_TMP
, sizeof (struct Adv
));
182 Adv_free (struct Adv
*adv
)
184 XFREE (MTYPE_TMP
, adv
);
188 irdp_if_start(struct interface
*ifp
, int multicast
, int set_defaults
)
190 struct zebra_if
*zi
= ifp
->info
;
191 struct irdp_interface
*irdp
= &zi
->irdp
;
192 struct listnode
*node
;
193 struct connected
*ifc
;
194 u_int32_t timer
, seed
;
196 if (irdp
->flags
& IF_ACTIVE
) {
197 zlog_warn("IRDP: Interface is already active %s", ifp
->name
);
200 if ((irdp_sock
< 0) && ((irdp_sock
= irdp_sock_init()) < 0)) {
201 zlog_warn("IRDP: Cannot activate interface %s (cannot create "
202 "IRDP socket)", ifp
->name
);
205 irdp
->flags
|= IF_ACTIVE
;
208 irdp
->flags
|= IF_BROADCAST
;
212 if (! (ifp
->flags
& IFF_UP
)) {
213 zlog_warn("IRDP: Interface is down %s", ifp
->name
);
216 /* Shall we cancel if_start if if_add_group fails? */
221 if (! (ifp
->flags
& (IFF_MULTICAST
|IFF_ALLMULTI
))) {
222 zlog_warn("IRDP: Interface not multicast enabled %s", ifp
->name
);
227 if_set_defaults(ifp
);
231 /* The spec suggests this for randomness */
235 for (ALL_LIST_ELEMENTS_RO (ifp
->connected
, node
, ifc
))
237 seed
= ifc
->address
->u
.prefix4
.s_addr
;
242 timer
= (random () % IRDP_DEFAULT_INTERVAL
) + 1;
244 irdp
->AdvPrefList
= list_new();
245 irdp
->AdvPrefList
->del
= (void (*)(void *)) Adv_free
; /* Destructor */
248 /* And this for startup. Speed limit from 1991 :-). But it's OK*/
250 if(irdp
->irdp_sent
< MAX_INITIAL_ADVERTISEMENTS
&&
251 timer
> MAX_INITIAL_ADVERT_INTERVAL
)
252 timer
= MAX_INITIAL_ADVERT_INTERVAL
;
255 if(irdp
->flags
& IF_DEBUG_MISC
)
256 zlog_debug("IRDP: Init timer for %s set to %u",
260 irdp
->t_advertise
= thread_add_timer(zebrad
.master
,
267 irdp_if_stop(struct interface
*ifp
)
269 struct zebra_if
*zi
=ifp
->info
;
270 struct irdp_interface
*irdp
=&zi
->irdp
;
273 zlog_warn ("Interface %s structure is NULL", ifp
->name
);
277 if (! (irdp
->flags
& IF_ACTIVE
)) {
278 zlog_warn("Interface is not active %s", ifp
->name
);
282 if(! (irdp
->flags
& IF_BROADCAST
))
285 irdp_advert_off(ifp
);
287 list_delete(irdp
->AdvPrefList
);
288 irdp
->AdvPrefList
=NULL
;
295 irdp_if_shutdown(struct interface
*ifp
)
297 struct zebra_if
*zi
= ifp
->info
;
298 struct irdp_interface
*irdp
= &zi
->irdp
;
300 if (irdp
->flags
& IF_SHUTDOWN
) {
301 zlog_warn("IRDP: Interface is already shutdown %s", ifp
->name
);
305 irdp
->flags
|= IF_SHUTDOWN
;
306 irdp
->flags
&= ~IF_ACTIVE
;
308 if(! (irdp
->flags
& IF_BROADCAST
))
311 /* Tell the hosts we are out of service */
312 irdp_advert_off(ifp
);
316 irdp_if_no_shutdown(struct interface
*ifp
)
318 struct zebra_if
*zi
= ifp
->info
;
319 struct irdp_interface
*irdp
= &zi
->irdp
;
321 if (! (irdp
->flags
& IF_SHUTDOWN
)) {
322 zlog_warn("IRDP: Interface is not shutdown %s", ifp
->name
);
326 irdp
->flags
&= ~IF_SHUTDOWN
;
328 irdp_if_start(ifp
, irdp
->flags
& IF_BROADCAST
? FALSE
: TRUE
, FALSE
);
333 /* Write configuration to user */
335 void irdp_config_write (struct vty
*vty
, struct interface
*ifp
)
337 struct zebra_if
*zi
=ifp
->info
;
338 struct irdp_interface
*irdp
=&zi
->irdp
;
340 struct listnode
*node
;
342 if(irdp
->flags
& IF_ACTIVE
|| irdp
->flags
& IF_SHUTDOWN
) {
344 if( irdp
->flags
& IF_SHUTDOWN
)
345 vty_out (vty
, " ip irdp shutdown %s", VTY_NEWLINE
);
347 if( irdp
->flags
& IF_BROADCAST
)
348 vty_out (vty
, " ip irdp broadcast%s", VTY_NEWLINE
);
350 vty_out (vty
, " ip irdp multicast%s", VTY_NEWLINE
);
352 vty_out (vty
, " ip irdp preference %ld%s",
353 irdp
->Preference
, VTY_NEWLINE
);
355 for (ALL_LIST_ELEMENTS_RO (irdp
->AdvPrefList
, node
, adv
))
356 vty_out (vty
, " ip irdp address %s preference %d%s",
357 inet_2a(adv
->ip
.s_addr
, b1
),
361 vty_out (vty
, " ip irdp holdtime %d%s",
362 irdp
->Lifetime
, VTY_NEWLINE
);
364 vty_out (vty
, " ip irdp minadvertinterval %ld%s",
365 irdp
->MinAdvertInterval
, VTY_NEWLINE
);
367 vty_out (vty
, " ip irdp maxadvertinterval %ld%s",
368 irdp
->MaxAdvertInterval
, VTY_NEWLINE
);
374 DEFUN (ip_irdp_multicast
,
375 ip_irdp_multicast_cmd
,
378 "ICMP Router discovery on this interface using multicast\n")
380 struct interface
*ifp
;
382 ifp
= (struct interface
*) vty
->index
;
387 irdp_if_start(ifp
, TRUE
, TRUE
);
391 DEFUN (ip_irdp_broadcast
,
392 ip_irdp_broadcast_cmd
,
395 "ICMP Router discovery on this interface using broadcast\n")
397 struct interface
*ifp
;
399 ifp
= (struct interface
*) vty
->index
;
404 irdp_if_start(ifp
, FALSE
, TRUE
);
413 "Disable ICMP Router discovery on this interface\n")
415 struct interface
*ifp
;
417 ifp
= (struct interface
*) vty
->index
;
426 DEFUN (ip_irdp_shutdown
,
427 ip_irdp_shutdown_cmd
,
430 "ICMP Router discovery shutdown on this interface\n")
432 struct interface
*ifp
;
434 ifp
= (struct interface
*) vty
->index
;
439 irdp_if_shutdown(ifp
);
443 DEFUN (no_ip_irdp_shutdown
,
444 no_ip_irdp_shutdown_cmd
,
445 "no ip irdp shutdown",
448 "ICMP Router discovery no shutdown on this interface\n")
450 struct interface
*ifp
;
452 ifp
= (struct interface
*) vty
->index
;
457 irdp_if_no_shutdown(ifp
);
461 DEFUN (ip_irdp_holdtime
,
462 ip_irdp_holdtime_cmd
,
463 "ip irdp holdtime <0-9000>",
465 "ICMP Router discovery on this interface\n"
466 "Set holdtime value\n"
467 "Holdtime value in seconds. Default is 1800 seconds\n")
469 struct interface
*ifp
;
471 struct irdp_interface
*irdp
;
472 ifp
= (struct interface
*) vty
->index
;
480 irdp
->Lifetime
= atoi(argv
[0]);
484 DEFUN (ip_irdp_minadvertinterval
,
485 ip_irdp_minadvertinterval_cmd
,
486 "ip irdp minadvertinterval <3-1800>",
488 "ICMP Router discovery on this interface\n"
489 "Set minimum time between advertisement\n"
490 "Minimum advertisement interval in seconds\n")
492 struct interface
*ifp
;
494 struct irdp_interface
*irdp
;
495 ifp
= (struct interface
*) vty
->index
;
503 if( (unsigned) atoi(argv
[0]) <= irdp
->MaxAdvertInterval
) {
504 irdp
->MinAdvertInterval
= atoi(argv
[0]);
509 vty_out (vty
, "ICMP warning maxadvertinterval is greater or equal than minadvertinterval%s",
512 vty_out (vty
, "Please correct!%s",
517 DEFUN (ip_irdp_maxadvertinterval
,
518 ip_irdp_maxadvertinterval_cmd
,
519 "ip irdp maxadvertinterval <4-1800>",
521 "ICMP Router discovery on this interface\n"
522 "Set maximum time between advertisement\n"
523 "Maximum advertisement interval in seconds\n")
525 struct interface
*ifp
;
527 struct irdp_interface
*irdp
;
528 ifp
= (struct interface
*) vty
->index
;
537 if( irdp
->MinAdvertInterval
<= (unsigned) atoi(argv
[0]) ) {
538 irdp
->MaxAdvertInterval
= atoi(argv
[0]);
543 vty_out (vty
, "ICMP warning maxadvertinterval is greater or equal than minadvertinterval%s",
546 vty_out (vty
, "Please correct!%s",
551 /* DEFUN needs to be fixed for negative ranages...
552 * "ip irdp preference <-2147483648-2147483647>",
553 * Be positive for now. :-)
556 DEFUN (ip_irdp_preference
,
557 ip_irdp_preference_cmd
,
558 "ip irdp preference <0-2147483647>",
560 "ICMP Router discovery on this interface\n"
561 "Set default preference level for this interface\n"
562 "Preference level\n")
564 struct interface
*ifp
;
566 struct irdp_interface
*irdp
;
567 ifp
= (struct interface
*) vty
->index
;
575 irdp
->Preference
= atoi(argv
[0]);
579 DEFUN (ip_irdp_address_preference
,
580 ip_irdp_address_preference_cmd
,
581 "ip irdp address A.B.C.D preference <0-2147483647>",
583 "Alter ICMP Router discovery preference this interface\n"
584 "Specify IRDP non-default preference to advertise\n"
585 "Set IRDP address for advertise\n"
586 "Preference level\n")
588 struct listnode
*node
;
592 struct interface
*ifp
;
594 struct irdp_interface
*irdp
;
597 ifp
= (struct interface
*) vty
->index
;
605 ret
= inet_aton(argv
[0], &ip
);
606 if(!ret
) return CMD_WARNING
;
608 pref
= atoi(argv
[1]);
610 for (ALL_LIST_ELEMENTS_RO (irdp
->AdvPrefList
, node
, adv
))
611 if(adv
->ip
.s_addr
== ip
.s_addr
)
617 listnode_add(irdp
->AdvPrefList
, adv
);
623 DEFUN (no_ip_irdp_address_preference
,
624 no_ip_irdp_address_preference_cmd
,
625 "no ip irdp address A.B.C.D preference <0-2147483647>",
628 "Alter ICMP Router discovery preference this interface\n"
629 "Removes IRDP non-default preference\n"
630 "Select IRDP address\n"
631 "Old preference level\n")
633 struct listnode
*node
, *nnode
;
637 struct interface
*ifp
;
639 struct irdp_interface
*irdp
;
642 ifp
= (struct interface
*) vty
->index
;
650 ret
= inet_aton(argv
[0], &ip
);
654 pref
= atoi(argv
[1]);
656 for (ALL_LIST_ELEMENTS (irdp
->AdvPrefList
, node
, nnode
, adv
))
658 if(adv
->ip
.s_addr
== ip
.s_addr
)
660 listnode_delete(irdp
->AdvPrefList
, adv
);
668 DEFUN (ip_irdp_debug_messages
,
669 ip_irdp_debug_messages_cmd
,
670 "ip irdp debug messages",
672 "ICMP Router discovery debug Averts. and Solicits (short)\n")
674 struct interface
*ifp
;
676 struct irdp_interface
*irdp
;
677 ifp
= (struct interface
*) vty
->index
;
685 irdp
->flags
|= IF_DEBUG_MESSAGES
;
690 DEFUN (ip_irdp_debug_misc
,
691 ip_irdp_debug_misc_cmd
,
692 "ip irdp debug misc",
694 "ICMP Router discovery debug Averts. and Solicits (short)\n")
696 struct interface
*ifp
;
698 struct irdp_interface
*irdp
;
699 ifp
= (struct interface
*) vty
->index
;
707 irdp
->flags
|= IF_DEBUG_MISC
;
712 DEFUN (ip_irdp_debug_packet
,
713 ip_irdp_debug_packet_cmd
,
714 "ip irdp debug packet",
716 "ICMP Router discovery debug Averts. and Solicits (short)\n")
718 struct interface
*ifp
;
720 struct irdp_interface
*irdp
;
721 ifp
= (struct interface
*) vty
->index
;
729 irdp
->flags
|= IF_DEBUG_PACKET
;
735 DEFUN (ip_irdp_debug_disable
,
736 ip_irdp_debug_disable_cmd
,
737 "ip irdp debug disable",
739 "ICMP Router discovery debug Averts. and Solicits (short)\n")
741 struct interface
*ifp
;
743 struct irdp_interface
*irdp
;
744 ifp
= (struct interface
*) vty
->index
;
752 irdp
->flags
&= ~IF_DEBUG_PACKET
;
753 irdp
->flags
&= ~IF_DEBUG_MESSAGES
;
754 irdp
->flags
&= ~IF_DEBUG_MISC
;
762 install_element (INTERFACE_NODE
, &ip_irdp_broadcast_cmd
);
763 install_element (INTERFACE_NODE
, &ip_irdp_multicast_cmd
);
764 install_element (INTERFACE_NODE
, &no_ip_irdp_cmd
);
765 install_element (INTERFACE_NODE
, &ip_irdp_shutdown_cmd
);
766 install_element (INTERFACE_NODE
, &no_ip_irdp_shutdown_cmd
);
767 install_element (INTERFACE_NODE
, &ip_irdp_holdtime_cmd
);
768 install_element (INTERFACE_NODE
, &ip_irdp_maxadvertinterval_cmd
);
769 install_element (INTERFACE_NODE
, &ip_irdp_minadvertinterval_cmd
);
770 install_element (INTERFACE_NODE
, &ip_irdp_preference_cmd
);
771 install_element (INTERFACE_NODE
, &ip_irdp_address_preference_cmd
);
772 install_element (INTERFACE_NODE
, &no_ip_irdp_address_preference_cmd
);
774 install_element (INTERFACE_NODE
, &ip_irdp_debug_messages_cmd
);
775 install_element (INTERFACE_NODE
, &ip_irdp_debug_misc_cmd
);
776 install_element (INTERFACE_NODE
, &ip_irdp_debug_packet_cmd
);
777 install_element (INTERFACE_NODE
, &ip_irdp_debug_disable_cmd
);
780 #endif /* HAVE_IRDP */