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 */