mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 02:53:55 +00:00
OK, here it is - irdp support. But don't expect me to fix any bugs in it.
This commit is contained in:
parent
02ff83c525
commit
ca7769881f
@ -5,7 +5,7 @@
|
||||
## Copyright (c) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
|
||||
## Portions Copyright (c) 2003 Paul Jakma <paul@dishone.st>
|
||||
##
|
||||
## $Id: configure.ac,v 1.51 2004/05/11 10:49:35 paul Exp $
|
||||
## $Id: configure.ac,v 1.52 2004/06/12 14:33:05 hasso Exp $
|
||||
AC_PREREQ(2.53)
|
||||
|
||||
AC_INIT(quagga, 0.96.5, [http://bugzilla.quagga.net])
|
||||
@ -125,6 +125,8 @@ AC_ARG_ENABLE(logfile_mask,
|
||||
|
||||
AC_ARG_ENABLE(rtadv,
|
||||
[ --disable-rtadv disable IPV6 router advertisement feature])
|
||||
AC_ARG_ENABLE(irdp,
|
||||
[ --enable-irdp enable IRDP server support in zebra])
|
||||
AC_ARG_ENABLE(capabilities,
|
||||
[ --disable-capabilities disable using POSIX capabilities])
|
||||
|
||||
@ -163,6 +165,10 @@ else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
if test "${enable_irdp}" = "yes"; then
|
||||
AC_DEFINE(HAVE_IRDP,, IRDP )
|
||||
fi
|
||||
|
||||
if test "${enable_user}" = "yes" || test x"${enable_user}" = x""; then
|
||||
enable_user="quagga"
|
||||
elif test "${enable_user}" = "no"; then
|
||||
|
@ -38,6 +38,7 @@ enum
|
||||
MTYPE_VTY_HIST,
|
||||
MTYPE_VTY_OUT_BUF,
|
||||
MTYPE_IF,
|
||||
MTYPE_IF_IRDP,
|
||||
MTYPE_CONNECTED,
|
||||
MTYPE_AS_SEG,
|
||||
MTYPE_AS_STR,
|
||||
|
@ -1,3 +1,7 @@
|
||||
2004-06-12 Robert Olsson <Robert.Olsson at data.slu.se>
|
||||
|
||||
* Added IRDP support.
|
||||
|
||||
2004-05-18 Hasso Tepper <hasso@estpak.ee>
|
||||
|
||||
* rtadv.c: Removed "[no] ipv6 nd send-ra" command. Replaced "ipv6 nd
|
||||
|
@ -23,11 +23,12 @@ sbin_PROGRAMS = zebra
|
||||
|
||||
zebra_SOURCES = \
|
||||
zserv.c main.c interface.c connected.c zebra_rib.c \
|
||||
redistribute.c debug.c rtadv.c zebra_snmp.c zebra_vty.c
|
||||
redistribute.c debug.c rtadv.c zebra_snmp.c zebra_vty.c \
|
||||
irdp_main.c irdp_interface.c irdp_packet.c
|
||||
|
||||
noinst_HEADERS = \
|
||||
connected.h ioctl.h rib.h rt.h zserv.h redistribute.h debug.h rtadv.h \
|
||||
interface.h ipforward.h
|
||||
interface.h ipforward.h irdp.h
|
||||
|
||||
zebra_LDADD = ../lib/libzebra.a $(otherobj) $(LIBCAP) $(LIB_IPV6)
|
||||
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "zebra/zserv.h"
|
||||
#include "zebra/redistribute.h"
|
||||
#include "zebra/debug.h"
|
||||
#include "zebra/irdp.h"
|
||||
|
||||
/* Allocate a new internal interface index
|
||||
* This works done from the top so that %d macros
|
||||
@ -1419,6 +1420,10 @@ if_config_write (struct vty *vty)
|
||||
rtadv_config_write (vty, ifp);
|
||||
#endif /* RTADV */
|
||||
|
||||
#ifdef HAVE_IRDP
|
||||
irdp_config_write (vty, ifp);
|
||||
#endif /* IRDP */
|
||||
|
||||
vty_out (vty, "!%s", VTY_NEWLINE);
|
||||
}
|
||||
return 0;
|
||||
|
@ -19,6 +19,10 @@
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_IRDP
|
||||
#include "zebra/irdp.h"
|
||||
#endif
|
||||
|
||||
/* For interface multicast configuration. */
|
||||
#define IF_ZEBRA_MULTICAST_UNSPEC 0
|
||||
#define IF_ZEBRA_MULTICAST_ON 1
|
||||
@ -153,6 +157,11 @@ struct zebra_if
|
||||
#ifdef RTADV
|
||||
struct rtadvconf rtadv;
|
||||
#endif /* RTADV */
|
||||
|
||||
#ifdef HAVE_IRDP
|
||||
struct irdp_interface irdp;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
void if_delete_update (struct interface *ifp);
|
||||
|
151
zebra/irdp.h
151
zebra/irdp.h
@ -19,6 +19,19 @@
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is modified and completed for the Zebra IRDP implementation
|
||||
* by Robert Olsson, Swedish University of Agricultural Sciences
|
||||
*/
|
||||
|
||||
#ifndef _IRDP_H
|
||||
#define _IRDP_H
|
||||
|
||||
#include "lib/vty.h"
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
/* ICMP Messages */
|
||||
#ifndef ICMP_ROUTERADVERT
|
||||
#define ICMP_ROUTERADVERT 9
|
||||
@ -30,17 +43,36 @@
|
||||
|
||||
/* Multicast groups */
|
||||
#ifndef INADDR_ALLHOSTS_GROUP
|
||||
#define INADDR_ALLHOSTS_GROUP 0xe0000001 /* 224.0.0.1 */
|
||||
#define INADDR_ALLHOSTS_GROUP 0xe0000001U /* 224.0.0.1 */
|
||||
#endif /* INADDR_ALLHOSTS_GROUP */
|
||||
|
||||
#ifndef INADDR_ALLRTRS_GROUP
|
||||
#define INADDR_ALLRTRS_GROUP 0xe0000002 /* 224.0.0.2 */
|
||||
#define INADDR_ALLRTRS_GROUP 0xe0000002U /* 224.0.0.2 */
|
||||
#endif /* INADDR_ALLRTRS_GROUP */
|
||||
|
||||
/* Comments comes from RFC1256 ICMP Router Discovery Messages. */
|
||||
struct irdp_router_interface
|
||||
{
|
||||
/* The IP destination address to be used for multicast Router
|
||||
/* Default irdp packet interval */
|
||||
#define IRDP_DEFAULT_INTERVAL 300
|
||||
|
||||
/* Router constants from RFC1256 */
|
||||
#define MAX_INITIAL_ADVERT_INTERVAL 16
|
||||
#define MAX_INITIAL_ADVERTISEMENTS 3
|
||||
#define MAX_RESPONSE_DELAY 2
|
||||
|
||||
#define IRDP_MAXADVERTINTERVAL 600
|
||||
#define IRDP_MINADVERTINTERVAL 450 /* 0.75*600 */
|
||||
#define IRDP_LIFETIME 1350 /* 3*450 */
|
||||
#define IRDP_PREFERENCE 0
|
||||
|
||||
#define ICMP_MINLEN 8
|
||||
|
||||
#define IRDP_LAST_ADVERT_MESSAGES 2 /* The last adverts with Holdtime 0 */
|
||||
|
||||
#define IRDP_RX_BUF 1500
|
||||
|
||||
/*
|
||||
Comments comes from RFC1256 ICMP Router Discovery Messages.
|
||||
|
||||
The IP destination address to be used for multicast Router
|
||||
Advertisements sent from the interface. The only permissible
|
||||
values are the all-systems multicast address, 224.0.0.1, or the
|
||||
limited-broadcast address, 255.255.255.255. (The all-systems
|
||||
@ -48,101 +80,74 @@ struct irdp_router_interface
|
||||
all listening hosts support IP multicast.)
|
||||
|
||||
Default: 224.0.0.1 if the router supports IP multicast on the
|
||||
interface, else 255.255.255.255 */
|
||||
interface, else 255.255.255.255
|
||||
|
||||
struct in_addr AdvertisementAddress;
|
||||
|
||||
/* The maximum time allowed between sending multicast Router
|
||||
The maximum time allowed between sending multicast Router
|
||||
Advertisements from the interface, in seconds. Must be no less
|
||||
than 4 seconds and no greater than 1800 seconds.
|
||||
|
||||
Default: 600 seconds */
|
||||
Default: 600 seconds
|
||||
|
||||
unsigned long MaxAdvertisementInterval;
|
||||
|
||||
/* The minimum time allowed between sending unsolicited multicast
|
||||
The minimum time allowed between sending unsolicited multicast
|
||||
Router Advertisements from the interface, in seconds. Must be no
|
||||
less than 3 seconds and no greater than MaxAdvertisementInterval.
|
||||
|
||||
Default: 0.75 * MaxAdvertisementInterval */
|
||||
Default: 0.75 * MaxAdvertisementInterval
|
||||
|
||||
unsigned long MinAdvertisementInterval;
|
||||
|
||||
|
||||
/* The value to be placed in the Lifetime field of Router
|
||||
The value to be placed in the Lifetime field of Router
|
||||
Advertisements sent from the interface, in seconds. Must be no
|
||||
less than MaxAdvertisementInterval and no greater than 9000
|
||||
seconds.
|
||||
|
||||
Default: 3 * MaxAdvertisementInterval */
|
||||
Default: 3 * MaxAdvertisementInterval
|
||||
|
||||
unsigned long AdvertisementLifetime;
|
||||
|
||||
/* A flag indicating whether or not the address is to be advertised.
|
||||
|
||||
Default: TRUE */
|
||||
|
||||
int Advertise;
|
||||
|
||||
|
||||
/* The preferability of the address as a default router address,
|
||||
The preferability of the address as a default router address,
|
||||
relative to other router addresses on the same subnet. A 32-bit,
|
||||
signed, twos-complement integer, with higher values meaning more
|
||||
preferable. The minimum value (hex 80000000) is used to indicate
|
||||
that the address, even though it may be advertised, is not to be
|
||||
used by neighboring hosts as a default router address.
|
||||
|
||||
Default: 0 */
|
||||
Default: 0
|
||||
*/
|
||||
|
||||
unsigned long PreferenceLevel;
|
||||
};
|
||||
|
||||
struct irdp_host_interface
|
||||
struct irdp_interface
|
||||
{
|
||||
/* A flag indicating whether or not the host is to perform ICMP router
|
||||
discovery on the interface. */
|
||||
int PerformRouerDiscovery;
|
||||
|
||||
/* The IP destination address to be used for sending Router
|
||||
Solicitations from the interface. The only permissible values
|
||||
are the all-routers multicast address, 224.0.0.2, or the
|
||||
limited-broadcast address, 255.255.255.255. (The all-routers
|
||||
address is preferred wherever possible, i.e., on any link where
|
||||
all advertising routers support IP multicast.) */
|
||||
unsigned long SolicitationAddress;
|
||||
unsigned long MaxAdvertInterval;
|
||||
unsigned long MinAdvertInterval;
|
||||
unsigned long Preference;
|
||||
|
||||
u_int32_t flags;
|
||||
|
||||
#define IF_ACTIVE (1<<0) /* ICMP Active */
|
||||
#define IF_BROADCAST (1<<1) /* 255.255.255.255 */
|
||||
#define IF_SOLICIT (1<<2) /* Solicit active */
|
||||
#define IF_DEBUG_MESSAGES (1<<3)
|
||||
#define IF_DEBUG_PACKET (1<<4)
|
||||
#define IF_DEBUG_MISC (1<<5)
|
||||
#define IF_SHUTDOWN (1<<6)
|
||||
|
||||
struct interface *ifp;
|
||||
struct thread *t_advertise;
|
||||
unsigned long irdp_sent;
|
||||
u_int16_t Lifetime;
|
||||
|
||||
list AdvPrefList;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/* Route preference structure */
|
||||
struct irdp
|
||||
struct Adv
|
||||
{
|
||||
struct in_addr prefix;
|
||||
long pref; /* preference level */
|
||||
long timer; /* lifetime timer */
|
||||
|
||||
struct irdp *next; /* doubly linked list */
|
||||
struct irdp *prev; /* doubly linked list */
|
||||
struct in_addr ip;
|
||||
int pref;
|
||||
};
|
||||
|
||||
/* Default irdp packet interval */
|
||||
#define IRDP_DEFAULT_INTERVAL 300
|
||||
void irdp_init();
|
||||
void irdp_finish();
|
||||
void irdp_config_write (struct vty *, struct interface *);
|
||||
#endif /* _IRDP_H */
|
||||
|
||||
|
||||
/* Router constants from RFC1256 */
|
||||
#define MAX_INITIAL_ADVERT_INTERVAL 16
|
||||
#define MAX_INITIAL_ADVERTISEMENTS 3
|
||||
#define MAX_RESPONSE_DELAY 2
|
||||
|
||||
/* Host constants from RFC1256 */
|
||||
#define MAX_SOLICITATION_DELAY 1
|
||||
#define SOLICITATION_INTERVAL 3
|
||||
#define MAX_SOLICITATIONS 3
|
||||
|
||||
enum
|
||||
{
|
||||
IRDP_NONE,
|
||||
IRDP_ROUTER,
|
||||
IRDP_HOST,
|
||||
};
|
||||
|
||||
/* default is host mode */
|
||||
extern int irdp_mode;
|
||||
|
784
zebra/irdp_interface.c
Normal file
784
zebra/irdp_interface.c
Normal file
@ -0,0 +1,784 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (C) 2000 Robert Olsson.
|
||||
* Swedish University of Agricultural Sciences
|
||||
*
|
||||
* This file is part of GNU Zebra.
|
||||
*
|
||||
* GNU Zebra is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* GNU Zebra is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Zebra; see the file COPYING. If not, write to the Free
|
||||
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This work includes work with the following copywrite:
|
||||
*
|
||||
* Copyright (C) 1997, 2000 Kunihiro Ishiguro
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Thanks to Jens Låås at Swedish University of Agricultural Sciences
|
||||
* for reviewing and tests.
|
||||
*/
|
||||
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#ifdef HAVE_IRDP
|
||||
|
||||
#include "if.h"
|
||||
#include "vty.h"
|
||||
#include "sockunion.h"
|
||||
#include "prefix.h"
|
||||
#include "command.h"
|
||||
#include "memory.h"
|
||||
#include "stream.h"
|
||||
#include "ioctl.h"
|
||||
#include "connected.h"
|
||||
#include "log.h"
|
||||
#include "zclient.h"
|
||||
#include "thread.h"
|
||||
#include "zebra/interface.h"
|
||||
#include "zebra/rtadv.h"
|
||||
#include "zebra/rib.h"
|
||||
#include "zebra/zserv.h"
|
||||
#include "zebra/redistribute.h"
|
||||
#include "zebra/irdp.h"
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include "if.h"
|
||||
#include "sockunion.h"
|
||||
#include "log.h"
|
||||
|
||||
|
||||
/* Master of threads. */
|
||||
extern struct zebra_t zebrad;
|
||||
|
||||
int in_cksum (void *ptr, int nbytes);
|
||||
extern int irdp_sock;
|
||||
int irdp_send_thread(struct thread *t_advert);
|
||||
char *inet_2a(u_int32_t a, char *b);
|
||||
void irdp_advert_off(struct interface *ifp);
|
||||
|
||||
|
||||
char b1[16], b2[16], b3[16], b4[16]; /* For inet_2a */
|
||||
|
||||
struct prefix *irdp_get_prefix(struct interface *ifp)
|
||||
{
|
||||
listnode node;
|
||||
struct connected *ifc;
|
||||
|
||||
if(ifp->connected)
|
||||
for (node = listhead (ifp->connected); node; nextnode (node)) {
|
||||
ifc = getdata (node);
|
||||
return ifc->address;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Join to the add/leave multicast group. */
|
||||
int if_group (struct interface *ifp,
|
||||
int sock,
|
||||
u_int32_t group,
|
||||
int add_leave)
|
||||
{
|
||||
struct zebra_if *zi;
|
||||
struct ip_mreq m;
|
||||
struct prefix *p;
|
||||
int ret;
|
||||
|
||||
zi = ifp->info;
|
||||
|
||||
bzero (&m, sizeof (m));
|
||||
m.imr_multiaddr.s_addr = htonl (group);
|
||||
p = irdp_get_prefix(ifp);
|
||||
|
||||
if(!p) {
|
||||
zlog_warn ("IRDP: can't get address for %s", ifp->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
m.imr_interface = p->u.prefix4;
|
||||
|
||||
ret = setsockopt (sock, IPPROTO_IP, add_leave,
|
||||
(char *) &m, sizeof (struct ip_mreq));
|
||||
if (ret < 0)
|
||||
zlog_warn ("IRDP: %s can't setsockopt %s: %s",
|
||||
add_leave == IP_ADD_MEMBERSHIP? "join group":"leave group",
|
||||
inet_2a(group, b1),
|
||||
strerror (errno));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int if_add_group (struct interface *ifp)
|
||||
{
|
||||
struct zebra_if *zi= ifp->info;
|
||||
struct irdp_interface *irdp = &zi->irdp;
|
||||
int ret;
|
||||
|
||||
ret = if_group (ifp, irdp_sock, INADDR_ALLRTRS_GROUP, IP_ADD_MEMBERSHIP);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if(irdp->flags & IF_DEBUG_MISC )
|
||||
zlog_warn("IRDP: Adding group %s for %s\n",
|
||||
inet_2a(htonl(INADDR_ALLRTRS_GROUP), b1),
|
||||
ifp->name);
|
||||
return 0;
|
||||
}
|
||||
int if_drop_group (struct interface *ifp)
|
||||
{
|
||||
struct zebra_if *zi= ifp->info;
|
||||
struct irdp_interface *irdp = &zi->irdp;
|
||||
int ret;
|
||||
|
||||
ret = if_group (ifp, irdp_sock, INADDR_ALLRTRS_GROUP, IP_DROP_MEMBERSHIP);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if(irdp->flags & IF_DEBUG_MISC)
|
||||
zlog_warn("IRDP: Leaving group %s for %s\n",
|
||||
inet_2a(htonl(INADDR_ALLRTRS_GROUP), b1),
|
||||
ifp->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct interface *get_iflist_ifp(int idx)
|
||||
{
|
||||
listnode node;
|
||||
struct interface *ifp;
|
||||
|
||||
for (node = listhead (iflist); node; nextnode (node)) {
|
||||
ifp = getdata (node);
|
||||
if(ifp->ifindex == idx) return ifp;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
if_set_defaults(struct interface *ifp)
|
||||
{
|
||||
struct zebra_if *zi=ifp->info;
|
||||
struct irdp_interface *irdp=&zi->irdp;
|
||||
|
||||
irdp->MaxAdvertInterval = IRDP_MAXADVERTINTERVAL;
|
||||
irdp->MinAdvertInterval = IRDP_MINADVERTINTERVAL;
|
||||
irdp->Preference = IRDP_PREFERENCE;
|
||||
irdp->Lifetime = IRDP_LIFETIME;
|
||||
}
|
||||
|
||||
|
||||
struct Adv *Adv_new ()
|
||||
{
|
||||
struct Adv *new;
|
||||
new = XMALLOC (MTYPE_TMP, sizeof (struct Adv));
|
||||
memset (new, 0, sizeof (struct Adv));
|
||||
return new;
|
||||
}
|
||||
|
||||
void Adv_free (struct Adv *adv)
|
||||
{
|
||||
XFREE (MTYPE_TMP, adv);
|
||||
}
|
||||
|
||||
void irdp_if_start(struct interface *ifp, int multicast, int set_defaults)
|
||||
{
|
||||
struct zebra_if *zi= ifp->info;
|
||||
struct irdp_interface *irdp = &zi->irdp;
|
||||
listnode node;
|
||||
u_int32_t timer, seed;
|
||||
|
||||
if (irdp->flags & IF_ACTIVE ) {
|
||||
zlog_warn("IRDP: Interface is already active %s\n", ifp->name);
|
||||
return;
|
||||
}
|
||||
irdp->flags |= IF_ACTIVE;
|
||||
|
||||
if(!multicast)
|
||||
irdp->flags |= IF_BROADCAST;
|
||||
|
||||
if_add_update(ifp);
|
||||
|
||||
if (! (ifp->flags & IFF_UP)) {
|
||||
zlog_warn("IRDP: Interface is down %s\n", ifp->name);
|
||||
}
|
||||
|
||||
/* Shall we cancel if_start if if_add_group fails? */
|
||||
|
||||
if( multicast) {
|
||||
if_add_group(ifp);
|
||||
|
||||
if (! (ifp->flags & (IFF_MULTICAST|IFF_ALLMULTI))) {
|
||||
zlog_warn("IRDP: Interface not multicast enabled %s\n", ifp->name);
|
||||
}
|
||||
}
|
||||
|
||||
if(set_defaults)
|
||||
if_set_defaults(ifp);
|
||||
|
||||
irdp->irdp_sent = 0;
|
||||
|
||||
/* The spec suggests this for randomness */
|
||||
|
||||
seed = 0;
|
||||
if( ifp->connected)
|
||||
for (node = listhead (ifp->connected); node; nextnode (node))
|
||||
{
|
||||
struct connected *ifc = getdata (node);
|
||||
seed = ifc->address->u.prefix4.s_addr;
|
||||
}
|
||||
|
||||
srandom(seed);
|
||||
timer = (random () % IRDP_DEFAULT_INTERVAL) + 1;
|
||||
|
||||
irdp->AdvPrefList = list_new();
|
||||
irdp->AdvPrefList->del = (void *) Adv_free; /* Destructor */
|
||||
|
||||
|
||||
/* And this for startup. Speed limit from 1991 :-). But it's OK*/
|
||||
|
||||
if(irdp->irdp_sent < MAX_INITIAL_ADVERTISEMENTS &&
|
||||
timer > MAX_INITIAL_ADVERT_INTERVAL )
|
||||
timer= MAX_INITIAL_ADVERT_INTERVAL;
|
||||
|
||||
|
||||
if(irdp->flags & IF_DEBUG_MISC)
|
||||
zlog_warn("IRDP: Init timer for %s set to %u\n",
|
||||
ifp->name,
|
||||
timer);
|
||||
|
||||
irdp->t_advertise = thread_add_timer(zebrad.master,
|
||||
irdp_send_thread,
|
||||
ifp,
|
||||
timer);
|
||||
}
|
||||
|
||||
void irdp_if_stop(struct interface *ifp)
|
||||
{
|
||||
struct zebra_if *zi=ifp->info;
|
||||
struct irdp_interface *irdp=&zi->irdp;
|
||||
|
||||
if (irdp == NULL) {
|
||||
zlog_warn ("Interface %s structure is NULL", ifp->name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (! (irdp->flags & IF_ACTIVE )) {
|
||||
zlog_warn("Interface is not active %s\n", ifp->name);
|
||||
return;
|
||||
}
|
||||
|
||||
if(! (irdp->flags & IF_BROADCAST))
|
||||
if_drop_group(ifp);
|
||||
|
||||
irdp_advert_off(ifp);
|
||||
|
||||
list_delete(irdp->AdvPrefList);
|
||||
irdp->AdvPrefList=NULL;
|
||||
|
||||
irdp->flags = 0;
|
||||
}
|
||||
|
||||
|
||||
void irdp_if_shutdown(struct interface *ifp)
|
||||
{
|
||||
struct zebra_if *zi= ifp->info;
|
||||
struct irdp_interface *irdp = &zi->irdp;
|
||||
|
||||
if (irdp->flags & IF_SHUTDOWN ) {
|
||||
zlog_warn("IRDP: Interface is already shutdown %s\n", ifp->name);
|
||||
return;
|
||||
}
|
||||
|
||||
irdp->flags |= IF_SHUTDOWN;
|
||||
irdp->flags &= ~IF_ACTIVE;
|
||||
|
||||
if(! (irdp->flags & IF_BROADCAST))
|
||||
if_drop_group(ifp);
|
||||
|
||||
/* Tell the hosts we are out of service */
|
||||
irdp_advert_off(ifp);
|
||||
}
|
||||
|
||||
void irdp_if_no_shutdown(struct interface *ifp)
|
||||
{
|
||||
struct zebra_if *zi= ifp->info;
|
||||
struct irdp_interface *irdp = &zi->irdp;
|
||||
|
||||
if (! (irdp->flags & IF_SHUTDOWN )) {
|
||||
zlog_warn("IRDP: Interface is not shutdown %s\n", ifp->name);
|
||||
return;
|
||||
}
|
||||
|
||||
irdp->flags &= ~IF_SHUTDOWN;
|
||||
|
||||
irdp_if_start(ifp, irdp->flags & IF_BROADCAST? FALSE : TRUE, FALSE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Write configuration to user */
|
||||
|
||||
void irdp_config_write (struct vty *vty, struct interface *ifp)
|
||||
{
|
||||
struct zebra_if *zi=ifp->info;
|
||||
struct irdp_interface *irdp=&zi->irdp;
|
||||
struct Adv *adv;
|
||||
listnode node;
|
||||
|
||||
if(irdp->flags & IF_ACTIVE || irdp->flags & IF_SHUTDOWN) {
|
||||
|
||||
if( irdp->flags & IF_SHUTDOWN)
|
||||
vty_out (vty, " ip irdp shutdown %s", VTY_NEWLINE);
|
||||
|
||||
if( irdp->flags & IF_BROADCAST)
|
||||
vty_out (vty, " ip irdp broadcast%s", VTY_NEWLINE);
|
||||
else
|
||||
vty_out (vty, " ip irdp multicast%s", VTY_NEWLINE);
|
||||
|
||||
vty_out (vty, " ip irdp preference %ld%s",
|
||||
irdp->Preference, VTY_NEWLINE);
|
||||
|
||||
for (node = listhead (irdp->AdvPrefList); node; nextnode (node)) {
|
||||
adv = getdata (node);
|
||||
vty_out (vty, " ip irdp address %s preference %d%s",
|
||||
inet_2a(adv->ip.s_addr, b1),
|
||||
adv->pref,
|
||||
VTY_NEWLINE);
|
||||
|
||||
}
|
||||
|
||||
vty_out (vty, " ip irdp holdtime %d%s",
|
||||
irdp->Lifetime, VTY_NEWLINE);
|
||||
|
||||
vty_out (vty, " ip irdp minadvertinterval %ld%s",
|
||||
irdp->MinAdvertInterval, VTY_NEWLINE);
|
||||
|
||||
vty_out (vty, " ip irdp maxadvertinterval %ld%s",
|
||||
irdp->MaxAdvertInterval, VTY_NEWLINE);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DEFUN (ip_irdp_multicast,
|
||||
ip_irdp_multicast_cmd,
|
||||
"ip irdp multicast",
|
||||
IP_STR
|
||||
"ICMP Router discovery on this interface using multicast\n")
|
||||
{
|
||||
struct interface *ifp;
|
||||
|
||||
ifp = (struct interface *) vty->index;
|
||||
if(!ifp) {
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
irdp_if_start(ifp, TRUE, TRUE);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (ip_irdp_broadcast,
|
||||
ip_irdp_broadcast_cmd,
|
||||
"ip irdp broadcast",
|
||||
IP_STR
|
||||
"ICMP Router discovery on this interface using broadcast\n")
|
||||
{
|
||||
struct interface *ifp;
|
||||
|
||||
ifp = (struct interface *) vty->index;
|
||||
if(!ifp) {
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
irdp_if_start(ifp, FALSE, TRUE);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (ip_irdp_no,
|
||||
ip_irdp_cmd_no,
|
||||
"no ip irdp",
|
||||
IP_STR
|
||||
"Disable ICMP Router discovery on this interface\n")
|
||||
{
|
||||
struct interface *ifp;
|
||||
|
||||
ifp = (struct interface *) vty->index;
|
||||
if(!ifp) {
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
irdp_if_stop(ifp);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (ip_irdp_shutdown,
|
||||
ip_irdp_shutdown_cmd,
|
||||
"ip irdp shutdown",
|
||||
IP_STR
|
||||
"ICMP Router discovery shutdown on this interface\n")
|
||||
{
|
||||
struct interface *ifp;
|
||||
|
||||
ifp = (struct interface *) vty->index;
|
||||
if(!ifp) {
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
irdp_if_shutdown(ifp);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (ip_irdp_no_shutdown,
|
||||
ip_irdp_no_shutdown_cmd,
|
||||
"no ip irdp shutdown",
|
||||
IP_STR
|
||||
"ICMP Router discovery no shutdown on this interface\n")
|
||||
{
|
||||
struct interface *ifp;
|
||||
|
||||
ifp = (struct interface *) vty->index;
|
||||
if(!ifp) {
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
irdp_if_no_shutdown(ifp);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (ip_irdp_holdtime,
|
||||
ip_irdp_holdtime_cmd,
|
||||
"ip irdp holdtime <0-9000>",
|
||||
IP_STR
|
||||
"ICMP Router discovery on this interface\n"
|
||||
"Set holdtime value\n"
|
||||
"Holdtime value in seconds. Default is 1800 seconds\n")
|
||||
{
|
||||
struct interface *ifp;
|
||||
struct zebra_if *zi;
|
||||
struct irdp_interface *irdp;
|
||||
ifp = (struct interface *) vty->index;
|
||||
if(!ifp) {
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
zi=ifp->info;
|
||||
irdp=&zi->irdp;
|
||||
|
||||
irdp->Lifetime = atoi(argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (ip_irdp_minadvertinterval,
|
||||
ip_irdp_minadvertinterval_cmd,
|
||||
"ip irdp minadvertinterval <3-1800>",
|
||||
IP_STR
|
||||
"ICMP Router discovery on this interface\n"
|
||||
"Set minimum time between advertisement\n"
|
||||
"Minimum advertisement interval in seconds\n")
|
||||
{
|
||||
struct interface *ifp;
|
||||
struct zebra_if *zi;
|
||||
struct irdp_interface *irdp;
|
||||
ifp = (struct interface *) vty->index;
|
||||
if(!ifp) {
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
zi=ifp->info;
|
||||
irdp=&zi->irdp;
|
||||
|
||||
if( atoi(argv[0]) <= irdp->MaxAdvertInterval) {
|
||||
irdp->MinAdvertInterval = atoi(argv[0]);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
vty_out (vty, "ICMP warning maxadvertinterval is greater or equal than minadvertinterval%s",
|
||||
VTY_NEWLINE);
|
||||
|
||||
vty_out (vty, "Please correct!%s",
|
||||
VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
DEFUN (ip_irdp_maxadvertinterval,
|
||||
ip_irdp_maxadvertinterval_cmd,
|
||||
"ip irdp maxadvertinterval <4-1800>",
|
||||
IP_STR
|
||||
"ICMP Router discovery on this interface\n"
|
||||
"Set maximum time between advertisement\n"
|
||||
"Maximum advertisement interval in seconds\n")
|
||||
{
|
||||
struct interface *ifp;
|
||||
struct zebra_if *zi;
|
||||
struct irdp_interface *irdp;
|
||||
ifp = (struct interface *) vty->index;
|
||||
if(!ifp) {
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
zi=ifp->info;
|
||||
irdp=&zi->irdp;
|
||||
|
||||
|
||||
if( irdp->MinAdvertInterval <= atoi(argv[0]) ) {
|
||||
irdp->MaxAdvertInterval = atoi(argv[0]);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
vty_out (vty, "ICMP warning maxadvertinterval is greater or equal than minadvertinterval%s",
|
||||
VTY_NEWLINE);
|
||||
|
||||
vty_out (vty, "Please correct!%s",
|
||||
VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
DEFUN (ip_irdp_preference,
|
||||
ip_irdp_preference_cmd,
|
||||
|
||||
/* DEFUN needs to be fixed for negative ranages...
|
||||
Be positive for now. :-)
|
||||
|
||||
"ip irdp preference <-2147483648-2147483647>",
|
||||
*/
|
||||
|
||||
|
||||
"ip irdp preference <0-2147483647>",
|
||||
IP_STR
|
||||
"ICMP Router discovery on this interface\n"
|
||||
"Set default preference level for this interface\n"
|
||||
"Preference level\n")
|
||||
{
|
||||
struct interface *ifp;
|
||||
struct zebra_if *zi;
|
||||
struct irdp_interface *irdp;
|
||||
ifp = (struct interface *) vty->index;
|
||||
if(!ifp) {
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
zi=ifp->info;
|
||||
irdp=&zi->irdp;
|
||||
|
||||
irdp->Preference = atoi(argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (ip_irdp_address_preference,
|
||||
ip_irdp_address_preference_cmd,
|
||||
"ip irdp address A.B.C.D preference <0-2147483647>",
|
||||
IP_STR
|
||||
"Alter ICMP Router discovery preference this interface\n"
|
||||
"Specify IRDP non-default preference to advertise\n"
|
||||
"Set IRDP address for advertise\n"
|
||||
"Preference level\n")
|
||||
{
|
||||
listnode node;
|
||||
struct in_addr ip;
|
||||
int pref;
|
||||
int ret;
|
||||
struct interface *ifp;
|
||||
struct zebra_if *zi;
|
||||
struct irdp_interface *irdp;
|
||||
struct Adv *adv;
|
||||
|
||||
ifp = (struct interface *) vty->index;
|
||||
if(!ifp) {
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
zi=ifp->info;
|
||||
irdp=&zi->irdp;
|
||||
|
||||
ret = inet_aton(argv[0], &ip);
|
||||
if(!ret) return CMD_WARNING;
|
||||
|
||||
pref = atoi(argv[1]);
|
||||
|
||||
for (node = listhead (irdp->AdvPrefList); node; nextnode (node)) {
|
||||
adv = getdata (node);
|
||||
if(adv->ip.s_addr == ip.s_addr) return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
adv = Adv_new();
|
||||
adv->ip = ip;
|
||||
adv->pref = pref;
|
||||
listnode_add(irdp->AdvPrefList, adv);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
DEFUN (ip_irdp_address_preference_no,
|
||||
ip_irdp_address_preference_cmd_no,
|
||||
"no ip irdp address A.B.C.D preference <0-2147483647>",
|
||||
IP_STR
|
||||
"Alter ICMP Router discovery preference this interface\n"
|
||||
"Removes IRDP non-default preference\n"
|
||||
"Select IRDP address\n"
|
||||
"Old preference level\n")
|
||||
{
|
||||
listnode node;
|
||||
struct in_addr ip;
|
||||
int pref;
|
||||
int ret;
|
||||
struct interface *ifp;
|
||||
struct zebra_if *zi;
|
||||
struct irdp_interface *irdp;
|
||||
struct Adv *adv;
|
||||
|
||||
ifp = (struct interface *) vty->index;
|
||||
if(!ifp) {
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
zi=ifp->info;
|
||||
irdp=&zi->irdp;
|
||||
|
||||
ret = inet_aton(argv[0], &ip);
|
||||
if(!ret) return CMD_WARNING;
|
||||
|
||||
pref = atoi(argv[1]);
|
||||
|
||||
for (node = listhead (irdp->AdvPrefList); node; nextnode (node)) {
|
||||
adv = getdata (node);
|
||||
if(adv->ip.s_addr == ip.s_addr ) {
|
||||
listnode_delete(irdp->AdvPrefList, adv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
|
||||
|
||||
}
|
||||
|
||||
DEFUN (ip_irdp_debug_messages,
|
||||
ip_irdp_debug_messages_cmd,
|
||||
"ip irdp debug messages",
|
||||
IP_STR
|
||||
"ICMP Router discovery debug Averts. and Solicits (short)\n")
|
||||
{
|
||||
struct interface *ifp;
|
||||
struct zebra_if *zi;
|
||||
struct irdp_interface *irdp;
|
||||
ifp = (struct interface *) vty->index;
|
||||
if(!ifp) {
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
zi=ifp->info;
|
||||
irdp=&zi->irdp;
|
||||
|
||||
irdp->flags |= IF_DEBUG_MESSAGES;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (ip_irdp_debug_misc,
|
||||
ip_irdp_debug_misc_cmd,
|
||||
"ip irdp debug misc",
|
||||
IP_STR
|
||||
"ICMP Router discovery debug Averts. and Solicits (short)\n")
|
||||
{
|
||||
struct interface *ifp;
|
||||
struct zebra_if *zi;
|
||||
struct irdp_interface *irdp;
|
||||
ifp = (struct interface *) vty->index;
|
||||
if(!ifp) {
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
zi=ifp->info;
|
||||
irdp=&zi->irdp;
|
||||
|
||||
irdp->flags |= IF_DEBUG_MISC;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (ip_irdp_debug_packet,
|
||||
ip_irdp_debug_packet_cmd,
|
||||
"ip irdp debug packet",
|
||||
IP_STR
|
||||
"ICMP Router discovery debug Averts. and Solicits (short)\n")
|
||||
{
|
||||
struct interface *ifp;
|
||||
struct zebra_if *zi;
|
||||
struct irdp_interface *irdp;
|
||||
ifp = (struct interface *) vty->index;
|
||||
if(!ifp) {
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
zi=ifp->info;
|
||||
irdp=&zi->irdp;
|
||||
|
||||
irdp->flags |= IF_DEBUG_PACKET;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
DEFUN (ip_irdp_debug_disable,
|
||||
ip_irdp_debug_disable_cmd,
|
||||
"ip irdp debug disable",
|
||||
IP_STR
|
||||
"ICMP Router discovery debug Averts. and Solicits (short)\n")
|
||||
{
|
||||
struct interface *ifp;
|
||||
struct zebra_if *zi;
|
||||
struct irdp_interface *irdp;
|
||||
ifp = (struct interface *) vty->index;
|
||||
if(!ifp) {
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
zi=ifp->info;
|
||||
irdp=&zi->irdp;
|
||||
|
||||
irdp->flags &= ~IF_DEBUG_PACKET;
|
||||
irdp->flags &= ~IF_DEBUG_MESSAGES;
|
||||
irdp->flags &= ~IF_DEBUG_MISC;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
irdp_if_init ()
|
||||
{
|
||||
install_element (INTERFACE_NODE, &ip_irdp_broadcast_cmd);
|
||||
install_element (INTERFACE_NODE, &ip_irdp_multicast_cmd);
|
||||
install_element (INTERFACE_NODE, &ip_irdp_cmd_no);
|
||||
install_element (INTERFACE_NODE, &ip_irdp_shutdown_cmd);
|
||||
install_element (INTERFACE_NODE, &ip_irdp_no_shutdown_cmd);
|
||||
install_element (INTERFACE_NODE, &ip_irdp_holdtime_cmd);
|
||||
install_element (INTERFACE_NODE, &ip_irdp_maxadvertinterval_cmd);
|
||||
install_element (INTERFACE_NODE, &ip_irdp_minadvertinterval_cmd);
|
||||
install_element (INTERFACE_NODE, &ip_irdp_preference_cmd);
|
||||
install_element (INTERFACE_NODE, &ip_irdp_address_preference_cmd);
|
||||
install_element (INTERFACE_NODE, &ip_irdp_address_preference_cmd_no);
|
||||
|
||||
install_element (INTERFACE_NODE, &ip_irdp_debug_messages_cmd);
|
||||
install_element (INTERFACE_NODE, &ip_irdp_debug_misc_cmd);
|
||||
install_element (INTERFACE_NODE, &ip_irdp_debug_packet_cmd);
|
||||
install_element (INTERFACE_NODE, &ip_irdp_debug_disable_cmd);
|
||||
}
|
||||
|
||||
#endif /* HAVE_IRDP */
|
347
zebra/irdp_main.c
Normal file
347
zebra/irdp_main.c
Normal file
@ -0,0 +1,347 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (C) 2000 Robert Olsson.
|
||||
* Swedish University of Agricultural Sciences
|
||||
*
|
||||
* This file is part of GNU Zebra.
|
||||
*
|
||||
* GNU Zebra is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* GNU Zebra is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Zebra; see the file COPYING. If not, write to the Free
|
||||
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This work includes work with the following copywrite:
|
||||
*
|
||||
* Copyright (C) 1997, 2000 Kunihiro Ishiguro
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Thanks to Jens Låås at Swedish University of Agricultural Sciences
|
||||
* for reviewing and tests.
|
||||
*/
|
||||
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#ifdef HAVE_IRDP
|
||||
|
||||
#include "if.h"
|
||||
#include "vty.h"
|
||||
#include "sockunion.h"
|
||||
#include "prefix.h"
|
||||
#include "command.h"
|
||||
#include "memory.h"
|
||||
#include "stream.h"
|
||||
#include "ioctl.h"
|
||||
#include "connected.h"
|
||||
#include "log.h"
|
||||
#include "zclient.h"
|
||||
#include "thread.h"
|
||||
#include "zebra/interface.h"
|
||||
#include "zebra/rtadv.h"
|
||||
#include "zebra/rib.h"
|
||||
#include "zebra/zserv.h"
|
||||
#include "zebra/redistribute.h"
|
||||
#include "zebra/irdp.h"
|
||||
#include <netinet/ip_icmp.h>
|
||||
|
||||
#include "if.h"
|
||||
#include "sockunion.h"
|
||||
#include "log.h"
|
||||
|
||||
/* GLOBAL VARS */
|
||||
|
||||
/* Master of threads. */
|
||||
extern struct zebra_t zebrad;
|
||||
struct thread *t_irdp_raw;
|
||||
|
||||
/* Timer interval of irdp. */
|
||||
int irdp_timer_interval = IRDP_DEFAULT_INTERVAL;
|
||||
|
||||
int irdp_read_raw(struct thread *r);
|
||||
int in_cksum (void *ptr, int nbytes);
|
||||
extern int irdp_sock;
|
||||
void send_packet(struct interface *ifp,
|
||||
struct stream *s,
|
||||
u_int32_t dst,
|
||||
struct prefix *p,
|
||||
u_int32_t ttl);
|
||||
|
||||
void irdp_if_init ();
|
||||
|
||||
char *
|
||||
inet_2a(u_int32_t a, char *b)
|
||||
{
|
||||
sprintf(b, "%u.%u.%u.%u",
|
||||
(a ) & 0xFF,
|
||||
(a>> 8) & 0xFF,
|
||||
(a>>16) & 0xFF,
|
||||
(a>>24) & 0xFF);
|
||||
return b;
|
||||
}
|
||||
|
||||
int
|
||||
irdp_sock_init (void)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
irdp_sock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);
|
||||
if (irdp_sock < 0) {
|
||||
zlog_warn ("IRDP: can't create irdp socket %s", strerror(errno));
|
||||
return irdp_sock;
|
||||
};
|
||||
|
||||
i = 1;
|
||||
ret = setsockopt (irdp_sock, IPPROTO_IP, IP_TTL,
|
||||
(void *) &i, sizeof (i));
|
||||
if (ret < 0) {
|
||||
zlog_warn ("IRDP: can't do irdp sockopt %s", strerror(errno));
|
||||
return ret;
|
||||
};
|
||||
|
||||
i = 1;
|
||||
ret = setsockopt (irdp_sock, IPPROTO_IP, IP_PKTINFO,
|
||||
(void *) &i, sizeof (i));
|
||||
if (ret < 0) {
|
||||
zlog_warn ("IRDP: can't do irdp sockopt %s", strerror(errno));
|
||||
return ret;
|
||||
};
|
||||
|
||||
t_irdp_raw = thread_add_read (zebrad.master, irdp_read_raw, NULL, irdp_sock);
|
||||
|
||||
return irdp_sock;
|
||||
}
|
||||
|
||||
|
||||
int get_pref(struct irdp_interface *irdp, struct prefix *p)
|
||||
{
|
||||
listnode node;
|
||||
struct Adv *adv;
|
||||
|
||||
/* Use default preference or use the override pref */
|
||||
|
||||
if( irdp->AdvPrefList == NULL ) return irdp->Preference;
|
||||
|
||||
for (node = listhead (irdp->AdvPrefList); node; nextnode (node)) {
|
||||
adv = getdata (node);
|
||||
if( p->u.prefix4.s_addr == adv->ip.s_addr )
|
||||
return adv->pref;
|
||||
}
|
||||
return irdp->Preference;
|
||||
}
|
||||
|
||||
/* Make ICMP Router Advertisement Message. */
|
||||
int make_advertisement_packet (struct interface *ifp,
|
||||
struct prefix *p,
|
||||
struct stream *s)
|
||||
{
|
||||
struct zebra_if *zi=ifp->info;
|
||||
struct irdp_interface *irdp=&zi->irdp;
|
||||
int size;
|
||||
int pref;
|
||||
u_int16_t checksum;
|
||||
|
||||
pref = get_pref(irdp, p);
|
||||
|
||||
stream_putc (s, ICMP_ROUTERADVERT); /* Type. */
|
||||
stream_putc (s, 0); /* Code. */
|
||||
stream_putw (s, 0); /* Checksum. */
|
||||
stream_putc (s, 1); /* Num address. */
|
||||
stream_putc (s, 2); /* Address Entry Size. */
|
||||
|
||||
if(irdp->flags & IF_SHUTDOWN)
|
||||
stream_putw (s, 0);
|
||||
else
|
||||
stream_putw (s, irdp->Lifetime);
|
||||
|
||||
stream_putl (s, htonl(p->u.prefix4.s_addr)); /* Router address. */
|
||||
stream_putl (s, pref);
|
||||
|
||||
/* in_cksum return network byte order value */
|
||||
size = 16;
|
||||
checksum = in_cksum (s->data, size);
|
||||
stream_putw_at (s, 2, htons(checksum));
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void irdp_send(struct interface *ifp,
|
||||
struct prefix *p,
|
||||
struct stream *s)
|
||||
{
|
||||
struct zebra_if *zi=ifp->info;
|
||||
struct irdp_interface *irdp=&zi->irdp;
|
||||
u_int32_t dst;
|
||||
u_int32_t ttl=1;
|
||||
|
||||
if (! (ifp->flags & IFF_UP)) return;
|
||||
|
||||
if (irdp->flags & IF_BROADCAST)
|
||||
dst =INADDR_BROADCAST ;
|
||||
else
|
||||
dst = htonl(INADDR_ALLHOSTS_GROUP);
|
||||
|
||||
if(irdp->flags & IF_DEBUG_MESSAGES)
|
||||
zlog_warn("IRDP: TX Advert on %s %s/%d Holdtime=%d Preference=%d",
|
||||
ifp->name,
|
||||
inet_ntoa(p->u.prefix4),
|
||||
p->prefixlen,
|
||||
irdp->flags & IF_SHUTDOWN? 0 : irdp->Lifetime,
|
||||
get_pref(irdp, p));
|
||||
|
||||
send_packet (ifp, s, dst, p, ttl);
|
||||
}
|
||||
|
||||
void irdp_advertisement (struct interface *ifp,
|
||||
struct prefix *p)
|
||||
{
|
||||
struct stream *s;
|
||||
s = stream_new (128);
|
||||
make_advertisement_packet (ifp, p, s);
|
||||
irdp_send(ifp, p, s);
|
||||
}
|
||||
|
||||
int irdp_send_thread(struct thread *t_advert)
|
||||
{
|
||||
u_int32_t timer, tmp;
|
||||
struct interface *ifp = THREAD_ARG (t_advert);
|
||||
struct zebra_if *zi=ifp->info;
|
||||
struct irdp_interface *irdp=&zi->irdp;
|
||||
struct prefix *p;
|
||||
listnode node;
|
||||
struct connected *ifc;
|
||||
|
||||
irdp->flags &= ~IF_SOLICIT;
|
||||
|
||||
if(ifp->connected)
|
||||
for (node = listhead (ifp->connected); node; nextnode (node)) {
|
||||
ifc = getdata (node);
|
||||
|
||||
p = ifc->address;
|
||||
|
||||
irdp_advertisement(ifp, p);
|
||||
irdp->irdp_sent++;
|
||||
|
||||
}
|
||||
|
||||
tmp = irdp->MaxAdvertInterval-irdp->MinAdvertInterval;
|
||||
timer = (random () % tmp ) + 1;
|
||||
timer = irdp->MinAdvertInterval + timer;
|
||||
|
||||
if(irdp->irdp_sent < MAX_INITIAL_ADVERTISEMENTS &&
|
||||
timer > MAX_INITIAL_ADVERT_INTERVAL )
|
||||
timer= MAX_INITIAL_ADVERT_INTERVAL;
|
||||
|
||||
if(irdp->flags & IF_DEBUG_MISC)
|
||||
zlog_warn("IRDP: New timer for %s set to %u\n", ifp->name, timer);
|
||||
|
||||
irdp->t_advertise = thread_add_timer(zebrad.master, irdp_send_thread, ifp, timer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void irdp_advert_off(struct interface *ifp)
|
||||
{
|
||||
struct zebra_if *zi=ifp->info;
|
||||
struct irdp_interface *irdp=&zi->irdp;
|
||||
listnode node;
|
||||
int i;
|
||||
struct connected *ifc;
|
||||
struct prefix *p;
|
||||
|
||||
if(irdp->t_advertise) thread_cancel(irdp->t_advertise);
|
||||
irdp->t_advertise = NULL;
|
||||
|
||||
if(ifp->connected)
|
||||
for (node = listhead (ifp->connected); node; nextnode (node)) {
|
||||
ifc = getdata (node);
|
||||
|
||||
p = ifc->address;
|
||||
|
||||
/* Output some packets with Lifetime 0
|
||||
we should add a wait...
|
||||
*/
|
||||
|
||||
for(i=0; i< IRDP_LAST_ADVERT_MESSAGES; i++) {
|
||||
|
||||
irdp->irdp_sent++;
|
||||
irdp_advertisement(ifp, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void process_solicit (struct interface *ifp)
|
||||
{
|
||||
struct zebra_if *zi=ifp->info;
|
||||
struct irdp_interface *irdp=&zi->irdp;
|
||||
u_int32_t timer;
|
||||
|
||||
/* When SOLICIT is active we reject further incoming solicits
|
||||
this keeps down the answering rate so we don't have think
|
||||
about DoS attacks here. */
|
||||
|
||||
if( irdp->flags & IF_SOLICIT) return;
|
||||
|
||||
irdp->flags |= IF_SOLICIT;
|
||||
if(irdp->t_advertise) thread_cancel(irdp->t_advertise);
|
||||
irdp->t_advertise = NULL;
|
||||
|
||||
timer = (random () % MAX_RESPONSE_DELAY) + 1;
|
||||
|
||||
irdp->t_advertise = thread_add_timer(zebrad.master,
|
||||
irdp_send_thread,
|
||||
ifp,
|
||||
timer);
|
||||
}
|
||||
|
||||
void irdp_finish()
|
||||
{
|
||||
|
||||
listnode node;
|
||||
struct interface *ifp;
|
||||
struct zebra_if *zi;
|
||||
struct irdp_interface *irdp;
|
||||
|
||||
zlog_warn("IRDP: Received shutdown notification.");
|
||||
|
||||
for (node = listhead (iflist); node; node = nextnode (node))
|
||||
{
|
||||
ifp = getdata(node);
|
||||
zi= ifp->info;
|
||||
if(! zi) continue;
|
||||
irdp = &zi->irdp;
|
||||
if(!irdp) continue;
|
||||
|
||||
if(irdp->flags & IF_ACTIVE ) {
|
||||
irdp->flags |= IF_SHUTDOWN;
|
||||
irdp_advert_off(ifp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void irdp_init()
|
||||
{
|
||||
irdp_sock_init();
|
||||
irdp_if_init ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* HAVE_IRDP */
|
||||
|
||||
|
||||
|
||||
|
364
zebra/irdp_packet.c
Normal file
364
zebra/irdp_packet.c
Normal file
@ -0,0 +1,364 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (C) 2000 Robert Olsson.
|
||||
* Swedish University of Agricultural Sciences
|
||||
*
|
||||
* This file is part of GNU Zebra.
|
||||
*
|
||||
* GNU Zebra is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* GNU Zebra is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Zebra; see the file COPYING. If not, write to the Free
|
||||
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This work includes work with the following copywrite:
|
||||
*
|
||||
* Copyright (C) 1997, 2000 Kunihiro Ishiguro
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Thanks to Jens Låås at Swedish University of Agricultural Sciences
|
||||
* for reviewing and tests.
|
||||
*/
|
||||
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
|
||||
#ifdef HAVE_IRDP
|
||||
|
||||
#include "if.h"
|
||||
#include "vty.h"
|
||||
#include "sockunion.h"
|
||||
#include "prefix.h"
|
||||
#include "command.h"
|
||||
#include "memory.h"
|
||||
#include "stream.h"
|
||||
#include "ioctl.h"
|
||||
#include "connected.h"
|
||||
#include "log.h"
|
||||
#include "zclient.h"
|
||||
#include "thread.h"
|
||||
#include "zebra/interface.h"
|
||||
#include "zebra/rtadv.h"
|
||||
#include "zebra/rib.h"
|
||||
#include "zebra/zserv.h"
|
||||
#include "zebra/redistribute.h"
|
||||
#include "zebra/irdp.h"
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include "if.h"
|
||||
#include "sockunion.h"
|
||||
#include "log.h"
|
||||
|
||||
|
||||
|
||||
/* GLOBAL VARS */
|
||||
|
||||
int irdp_sock;
|
||||
char b1[16], b2[16], b3[16], b4[16]; /* For inet_2a */
|
||||
|
||||
extern struct zebra_t zebrad;
|
||||
extern struct thread *t_irdp_raw;
|
||||
extern struct interface *get_iflist_ifp(int idx);
|
||||
int in_cksum (void *ptr, int nbytes);
|
||||
void process_solicit (struct interface *ifp);
|
||||
|
||||
void parse_irdp_packet(char *p,
|
||||
int len,
|
||||
struct interface *ifp)
|
||||
{
|
||||
struct ip *ip = (struct ip *)p ;
|
||||
struct icmphdr *icmp;
|
||||
struct in_addr src;
|
||||
int ip_hlen, ip_len;
|
||||
struct zebra_if *zi;
|
||||
struct irdp_interface *irdp;
|
||||
|
||||
zi = ifp->info;
|
||||
if(!zi) return;
|
||||
|
||||
irdp = &zi->irdp;
|
||||
if(!irdp) return;
|
||||
|
||||
ip_hlen = ip->ip_hl*4;
|
||||
ip_len = ntohs(ip->ip_len);
|
||||
len = len - ip_hlen;
|
||||
src = ip->ip_src;
|
||||
|
||||
if(ip_len < ICMP_MINLEN) {
|
||||
zlog_err ("IRDP: RX ICMP packet too short from %s\n",
|
||||
inet_ntoa (src));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check so we don't checksum packets longer than oure RX_BUF - (ethlen +
|
||||
len of IP-header) 14+20 */
|
||||
|
||||
if(ip_len > IRDP_RX_BUF-34) {
|
||||
zlog_err ("IRDP: RX ICMP packet too long from %s\n",
|
||||
inet_ntoa (src));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (in_cksum (ip, ip_len)) {
|
||||
zlog_warn ("IRDP: RX ICMP packet from %s. Bad checksum, silently ignored",
|
||||
inet_ntoa (src));
|
||||
return;
|
||||
}
|
||||
|
||||
icmp = (struct icmphdr *) (p+ip_hlen);
|
||||
|
||||
|
||||
/* Handle just only IRDP */
|
||||
|
||||
if( icmp->type == ICMP_ROUTERADVERT);
|
||||
else if( icmp->type == ICMP_ROUTERSOLICIT);
|
||||
else return;
|
||||
|
||||
|
||||
if (icmp->code != 0) {
|
||||
zlog_warn ("IRDP: RX packet type %d from %s. Bad ICMP type code, silently ignored",
|
||||
icmp->type,
|
||||
inet_ntoa (src));
|
||||
return;
|
||||
}
|
||||
|
||||
if(ip->ip_dst.s_addr == INADDR_BROADCAST &&
|
||||
irdp->flags & IF_BROADCAST);
|
||||
|
||||
else if ( ntohl(ip->ip_dst.s_addr) == INADDR_ALLRTRS_GROUP &&
|
||||
! (irdp->flags & IF_BROADCAST));
|
||||
|
||||
else { /* ERROR */
|
||||
|
||||
zlog_warn ("IRDP: RX illegal from %s to %s while %s operates in %s\n",
|
||||
inet_ntoa (src),
|
||||
ntohl(ip->ip_dst.s_addr) == INADDR_ALLRTRS_GROUP?
|
||||
"multicast" : inet_ntoa(ip->ip_dst),
|
||||
ifp->name,
|
||||
irdp->flags & IF_BROADCAST?
|
||||
"broadcast" : "multicast");
|
||||
|
||||
zlog_warn ("IRDP: Please correct settings\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (icmp->type)
|
||||
{
|
||||
case ICMP_ROUTERADVERT:
|
||||
break;
|
||||
|
||||
case ICMP_ROUTERSOLICIT:
|
||||
|
||||
if(irdp->flags & IF_DEBUG_MESSAGES)
|
||||
zlog_warn ("IRDP: RX Solicit on %s from %s\n",
|
||||
ifp->name,
|
||||
inet_ntoa (src));
|
||||
|
||||
process_solicit(ifp);
|
||||
break;
|
||||
|
||||
default:
|
||||
zlog_warn ("IRDP: RX type %d from %s. Bad ICMP type, silently ignored",
|
||||
icmp->type,
|
||||
inet_ntoa (src));
|
||||
}
|
||||
}
|
||||
|
||||
int irdp_recvmsg (int sock,
|
||||
u_char *buf,
|
||||
int size,
|
||||
int *ifindex)
|
||||
{
|
||||
struct msghdr msg;
|
||||
struct iovec iov;
|
||||
struct cmsghdr *ptr;
|
||||
char adata[1024];
|
||||
int ret;
|
||||
|
||||
msg.msg_name = (void *)0;
|
||||
msg.msg_namelen = 0;
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = (void *) adata;
|
||||
msg.msg_controllen = sizeof adata;
|
||||
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = size;
|
||||
|
||||
ret = recvmsg (sock, &msg, 0);
|
||||
if (ret < 0) {
|
||||
zlog_warn("IRDP: recvmsg: read error %s", strerror(errno));
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (msg.msg_flags & MSG_TRUNC) {
|
||||
zlog_warn("IRDP: recvmsg: truncated message");
|
||||
return ret;
|
||||
}
|
||||
if (msg.msg_flags & MSG_CTRUNC) {
|
||||
zlog_warn("IRDP: recvmsg: truncated control message");
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (ptr = CMSG_FIRSTHDR(&msg); ptr ; ptr = CMSG_NXTHDR(&msg, ptr))
|
||||
if (ptr->cmsg_level == SOL_IP && ptr->cmsg_type == IP_PKTINFO)
|
||||
{
|
||||
struct in_pktinfo *pktinfo;
|
||||
pktinfo = (struct in_pktinfo *) CMSG_DATA (ptr);
|
||||
*ifindex = pktinfo->ipi_ifindex;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int irdp_read_raw(struct thread *r)
|
||||
{
|
||||
struct interface *ifp;
|
||||
struct zebra_if *zi;
|
||||
struct irdp_interface *irdp;
|
||||
char buf[IRDP_RX_BUF];
|
||||
int ret, ifindex;
|
||||
|
||||
int irdp_sock = THREAD_FD (r);
|
||||
t_irdp_raw = thread_add_read (zebrad.master, irdp_read_raw, NULL, irdp_sock);
|
||||
|
||||
ret = irdp_recvmsg (irdp_sock, buf, IRDP_RX_BUF, &ifindex);
|
||||
|
||||
if (ret < 0) zlog_warn ("IRDP: RX Error length = %d", ret);
|
||||
|
||||
ifp = get_iflist_ifp(ifindex);
|
||||
if(! ifp ) return ret;
|
||||
|
||||
zi= ifp->info;
|
||||
if(! zi ) return ret;
|
||||
|
||||
irdp = &zi->irdp;
|
||||
if(! irdp ) return ret;
|
||||
|
||||
if(! (irdp->flags & IF_ACTIVE)) {
|
||||
|
||||
if(irdp->flags & IF_DEBUG_MISC)
|
||||
zlog_warn("IRDP: RX ICMP for disabled interface %s\n",
|
||||
ifp->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(irdp->flags & IF_DEBUG_PACKET) {
|
||||
int i;
|
||||
zlog_warn("IRDP: RX (idx %d) ", ifindex);
|
||||
for(i=0; i < ret; i++) zlog_warn( "IRDP: RX %x ", buf[i]&0xFF);
|
||||
}
|
||||
|
||||
parse_irdp_packet(buf, ret, ifp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void send_packet(struct interface *ifp,
|
||||
struct stream *s,
|
||||
u_int32_t dst,
|
||||
struct prefix *p,
|
||||
u_int32_t ttl)
|
||||
{
|
||||
static struct sockaddr_in sockdst = {AF_INET};
|
||||
struct ip *ip;
|
||||
struct icmphdr *icmp;
|
||||
struct msghdr *msg;
|
||||
struct cmsghdr *cmsg;
|
||||
struct iovec iovector;
|
||||
char msgbuf[256];
|
||||
char buf[256];
|
||||
struct in_pktinfo *pktinfo;
|
||||
u_long src;
|
||||
int on;
|
||||
|
||||
if (! (ifp->flags & IFF_UP)) return;
|
||||
|
||||
if(!p) src = ntohl(p->u.prefix4.s_addr);
|
||||
else src = 0; /* Is filled in */
|
||||
|
||||
ip = (struct ip *) buf;
|
||||
ip->ip_hl = sizeof(struct ip) >> 2;
|
||||
ip->ip_v = IPVERSION;
|
||||
ip->ip_tos = 0xC0;
|
||||
ip->ip_off = 0L;
|
||||
ip->ip_p = 1; /* IP_ICMP */
|
||||
ip->ip_ttl = ttl;
|
||||
ip->ip_src.s_addr = src;
|
||||
ip->ip_dst.s_addr = dst;
|
||||
icmp = (struct icmphdr *) (buf + 20);
|
||||
|
||||
/* Merge IP header with icmp packet */
|
||||
|
||||
stream_get(icmp, s, s->putp);
|
||||
|
||||
/* icmp->checksum is already calculated */
|
||||
ip->ip_len = sizeof(struct ip) + s->putp;
|
||||
stream_free(s);
|
||||
|
||||
on = 1;
|
||||
if (setsockopt(irdp_sock, IPPROTO_IP, IP_HDRINCL,
|
||||
(char *) &on, sizeof(on)) < 0)
|
||||
zlog_warn("sendto %s", strerror (errno));
|
||||
|
||||
|
||||
if(dst == INADDR_BROADCAST ) {
|
||||
on = 1;
|
||||
if (setsockopt(irdp_sock, SOL_SOCKET, SO_BROADCAST,
|
||||
(char *) &on, sizeof(on)) < 0)
|
||||
zlog_warn("sendto %s", strerror (errno));
|
||||
}
|
||||
|
||||
if(dst != INADDR_BROADCAST) {
|
||||
on = 0;
|
||||
if( setsockopt(irdp_sock,IPPROTO_IP, IP_MULTICAST_LOOP,
|
||||
(char *)&on,sizeof(on)) < 0)
|
||||
zlog_warn("sendto %s", strerror (errno));
|
||||
}
|
||||
|
||||
bzero(&sockdst,sizeof(sockdst));
|
||||
sockdst.sin_family=AF_INET;
|
||||
sockdst.sin_addr.s_addr = dst;
|
||||
|
||||
cmsg = (struct cmsghdr *) (msgbuf + sizeof(struct msghdr));
|
||||
cmsg->cmsg_len = sizeof(struct cmsghdr) + sizeof(struct in_pktinfo);
|
||||
cmsg->cmsg_level = SOL_IP;
|
||||
cmsg->cmsg_type = IP_PKTINFO;
|
||||
pktinfo = (struct in_pktinfo *) CMSG_DATA(cmsg);
|
||||
pktinfo->ipi_ifindex = ifp->ifindex;
|
||||
pktinfo->ipi_spec_dst.s_addr = src;
|
||||
pktinfo->ipi_addr.s_addr = src;
|
||||
|
||||
iovector.iov_base = (void *) buf;
|
||||
iovector.iov_len = ip->ip_len;
|
||||
msg = (struct msghdr *) msgbuf;
|
||||
msg->msg_name = &sockdst;
|
||||
msg->msg_namelen = sizeof(sockdst);
|
||||
msg->msg_iov = &iovector;
|
||||
msg->msg_iovlen = 1;
|
||||
msg->msg_control = cmsg;
|
||||
msg->msg_controllen = cmsg->cmsg_len;
|
||||
|
||||
if (sendmsg(irdp_sock, msg, 0) < 0) {
|
||||
zlog_warn("sendto %s", strerror (errno));
|
||||
}
|
||||
/* printf("TX on %s idx %d\n", ifp->name, ifp->ifindex); */
|
||||
}
|
||||
|
||||
|
||||
#endif /* HAVE_IRDP */
|
||||
|
||||
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "zebra/zserv.h"
|
||||
#include "zebra/debug.h"
|
||||
#include "zebra/rib.h"
|
||||
#include "zebra/irdp.h"
|
||||
|
||||
/* Zebra instance */
|
||||
struct zebra_t zebrad =
|
||||
@ -151,6 +152,9 @@ sigint (void)
|
||||
|
||||
if (!retain_mode)
|
||||
rib_close ();
|
||||
#ifdef HAVE_IRDP
|
||||
irdp_finish();
|
||||
#endif
|
||||
|
||||
exit (0);
|
||||
}
|
||||
@ -289,6 +293,9 @@ main (int argc, char **argv)
|
||||
zebra_vty_init ();
|
||||
access_list_init ();
|
||||
rtadv_init ();
|
||||
#ifdef HAVE_IRDP
|
||||
irdp_init();
|
||||
#endif
|
||||
|
||||
/* For debug purpose. */
|
||||
/* SET_FLAG (zebra_debug_event, ZEBRA_DEBUG_EVENT); */
|
||||
|
Loading…
Reference in New Issue
Block a user