mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-16 00:25:01 +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>
|
## Copyright (c) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
|
||||||
## Portions Copyright (c) 2003 Paul Jakma <paul@dishone.st>
|
## 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_PREREQ(2.53)
|
||||||
|
|
||||||
AC_INIT(quagga, 0.96.5, [http://bugzilla.quagga.net])
|
AC_INIT(quagga, 0.96.5, [http://bugzilla.quagga.net])
|
||||||
@ -125,6 +125,8 @@ AC_ARG_ENABLE(logfile_mask,
|
|||||||
|
|
||||||
AC_ARG_ENABLE(rtadv,
|
AC_ARG_ENABLE(rtadv,
|
||||||
[ --disable-rtadv disable IPV6 router advertisement feature])
|
[ --disable-rtadv disable IPV6 router advertisement feature])
|
||||||
|
AC_ARG_ENABLE(irdp,
|
||||||
|
[ --enable-irdp enable IRDP server support in zebra])
|
||||||
AC_ARG_ENABLE(capabilities,
|
AC_ARG_ENABLE(capabilities,
|
||||||
[ --disable-capabilities disable using POSIX capabilities])
|
[ --disable-capabilities disable using POSIX capabilities])
|
||||||
|
|
||||||
@ -163,6 +165,10 @@ else
|
|||||||
AC_MSG_RESULT(no)
|
AC_MSG_RESULT(no)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test "${enable_irdp}" = "yes"; then
|
||||||
|
AC_DEFINE(HAVE_IRDP,, IRDP )
|
||||||
|
fi
|
||||||
|
|
||||||
if test "${enable_user}" = "yes" || test x"${enable_user}" = x""; then
|
if test "${enable_user}" = "yes" || test x"${enable_user}" = x""; then
|
||||||
enable_user="quagga"
|
enable_user="quagga"
|
||||||
elif test "${enable_user}" = "no"; then
|
elif test "${enable_user}" = "no"; then
|
||||||
|
@ -38,6 +38,7 @@ enum
|
|||||||
MTYPE_VTY_HIST,
|
MTYPE_VTY_HIST,
|
||||||
MTYPE_VTY_OUT_BUF,
|
MTYPE_VTY_OUT_BUF,
|
||||||
MTYPE_IF,
|
MTYPE_IF,
|
||||||
|
MTYPE_IF_IRDP,
|
||||||
MTYPE_CONNECTED,
|
MTYPE_CONNECTED,
|
||||||
MTYPE_AS_SEG,
|
MTYPE_AS_SEG,
|
||||||
MTYPE_AS_STR,
|
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>
|
2004-05-18 Hasso Tepper <hasso@estpak.ee>
|
||||||
|
|
||||||
* rtadv.c: Removed "[no] ipv6 nd send-ra" command. Replaced "ipv6 nd
|
* rtadv.c: Removed "[no] ipv6 nd send-ra" command. Replaced "ipv6 nd
|
||||||
|
@ -23,11 +23,12 @@ sbin_PROGRAMS = zebra
|
|||||||
|
|
||||||
zebra_SOURCES = \
|
zebra_SOURCES = \
|
||||||
zserv.c main.c interface.c connected.c zebra_rib.c \
|
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 = \
|
noinst_HEADERS = \
|
||||||
connected.h ioctl.h rib.h rt.h zserv.h redistribute.h debug.h rtadv.h \
|
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)
|
zebra_LDADD = ../lib/libzebra.a $(otherobj) $(LIBCAP) $(LIB_IPV6)
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include "zebra/zserv.h"
|
#include "zebra/zserv.h"
|
||||||
#include "zebra/redistribute.h"
|
#include "zebra/redistribute.h"
|
||||||
#include "zebra/debug.h"
|
#include "zebra/debug.h"
|
||||||
|
#include "zebra/irdp.h"
|
||||||
|
|
||||||
/* Allocate a new internal interface index
|
/* Allocate a new internal interface index
|
||||||
* This works done from the top so that %d macros
|
* 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);
|
rtadv_config_write (vty, ifp);
|
||||||
#endif /* RTADV */
|
#endif /* RTADV */
|
||||||
|
|
||||||
|
#ifdef HAVE_IRDP
|
||||||
|
irdp_config_write (vty, ifp);
|
||||||
|
#endif /* IRDP */
|
||||||
|
|
||||||
vty_out (vty, "!%s", VTY_NEWLINE);
|
vty_out (vty, "!%s", VTY_NEWLINE);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -19,6 +19,10 @@
|
|||||||
* 02111-1307, USA.
|
* 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_IRDP
|
||||||
|
#include "zebra/irdp.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/* For interface multicast configuration. */
|
/* For interface multicast configuration. */
|
||||||
#define IF_ZEBRA_MULTICAST_UNSPEC 0
|
#define IF_ZEBRA_MULTICAST_UNSPEC 0
|
||||||
#define IF_ZEBRA_MULTICAST_ON 1
|
#define IF_ZEBRA_MULTICAST_ON 1
|
||||||
@ -153,6 +157,11 @@ struct zebra_if
|
|||||||
#ifdef RTADV
|
#ifdef RTADV
|
||||||
struct rtadvconf rtadv;
|
struct rtadvconf rtadv;
|
||||||
#endif /* RTADV */
|
#endif /* RTADV */
|
||||||
|
|
||||||
|
#ifdef HAVE_IRDP
|
||||||
|
struct irdp_interface irdp;
|
||||||
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void if_delete_update (struct interface *ifp);
|
void if_delete_update (struct interface *ifp);
|
||||||
|
151
zebra/irdp.h
151
zebra/irdp.h
@ -19,6 +19,19 @@
|
|||||||
* 02111-1307, USA.
|
* 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 */
|
/* ICMP Messages */
|
||||||
#ifndef ICMP_ROUTERADVERT
|
#ifndef ICMP_ROUTERADVERT
|
||||||
#define ICMP_ROUTERADVERT 9
|
#define ICMP_ROUTERADVERT 9
|
||||||
@ -30,17 +43,36 @@
|
|||||||
|
|
||||||
/* Multicast groups */
|
/* Multicast groups */
|
||||||
#ifndef INADDR_ALLHOSTS_GROUP
|
#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 */
|
#endif /* INADDR_ALLHOSTS_GROUP */
|
||||||
|
|
||||||
#ifndef INADDR_ALLRTRS_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 */
|
#endif /* INADDR_ALLRTRS_GROUP */
|
||||||
|
|
||||||
/* Comments comes from RFC1256 ICMP Router Discovery Messages. */
|
/* Default irdp packet interval */
|
||||||
struct irdp_router_interface
|
#define IRDP_DEFAULT_INTERVAL 300
|
||||||
{
|
|
||||||
/* The IP destination address to be used for multicast Router
|
/* 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
|
Advertisements sent from the interface. The only permissible
|
||||||
values are the all-systems multicast address, 224.0.0.1, or the
|
values are the all-systems multicast address, 224.0.0.1, or the
|
||||||
limited-broadcast address, 255.255.255.255. (The all-systems
|
limited-broadcast address, 255.255.255.255. (The all-systems
|
||||||
@ -48,101 +80,74 @@ struct irdp_router_interface
|
|||||||
all listening hosts support IP multicast.)
|
all listening hosts support IP multicast.)
|
||||||
|
|
||||||
Default: 224.0.0.1 if the router supports IP multicast on the
|
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
|
Advertisements from the interface, in seconds. Must be no less
|
||||||
than 4 seconds and no greater than 1800 seconds.
|
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
|
Router Advertisements from the interface, in seconds. Must be no
|
||||||
less than 3 seconds and no greater than MaxAdvertisementInterval.
|
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
|
Advertisements sent from the interface, in seconds. Must be no
|
||||||
less than MaxAdvertisementInterval and no greater than 9000
|
less than MaxAdvertisementInterval and no greater than 9000
|
||||||
seconds.
|
seconds.
|
||||||
|
|
||||||
Default: 3 * MaxAdvertisementInterval */
|
Default: 3 * MaxAdvertisementInterval
|
||||||
|
|
||||||
unsigned long AdvertisementLifetime;
|
The preferability of the address as a default router address,
|
||||||
|
|
||||||
/* 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,
|
|
||||||
relative to other router addresses on the same subnet. A 32-bit,
|
relative to other router addresses on the same subnet. A 32-bit,
|
||||||
signed, twos-complement integer, with higher values meaning more
|
signed, twos-complement integer, with higher values meaning more
|
||||||
preferable. The minimum value (hex 80000000) is used to indicate
|
preferable. The minimum value (hex 80000000) is used to indicate
|
||||||
that the address, even though it may be advertised, is not to be
|
that the address, even though it may be advertised, is not to be
|
||||||
used by neighboring hosts as a default router address.
|
used by neighboring hosts as a default router address.
|
||||||
|
|
||||||
Default: 0 */
|
Default: 0
|
||||||
|
*/
|
||||||
|
|
||||||
unsigned long PreferenceLevel;
|
struct irdp_interface
|
||||||
};
|
|
||||||
|
|
||||||
struct irdp_host_interface
|
|
||||||
{
|
{
|
||||||
/* A flag indicating whether or not the host is to perform ICMP router
|
unsigned long MaxAdvertInterval;
|
||||||
discovery on the interface. */
|
unsigned long MinAdvertInterval;
|
||||||
int PerformRouerDiscovery;
|
unsigned long Preference;
|
||||||
|
|
||||||
/* The IP destination address to be used for sending Router
|
u_int32_t flags;
|
||||||
Solicitations from the interface. The only permissible values
|
|
||||||
are the all-routers multicast address, 224.0.0.2, or the
|
#define IF_ACTIVE (1<<0) /* ICMP Active */
|
||||||
limited-broadcast address, 255.255.255.255. (The all-routers
|
#define IF_BROADCAST (1<<1) /* 255.255.255.255 */
|
||||||
address is preferred wherever possible, i.e., on any link where
|
#define IF_SOLICIT (1<<2) /* Solicit active */
|
||||||
all advertising routers support IP multicast.) */
|
#define IF_DEBUG_MESSAGES (1<<3)
|
||||||
unsigned long SolicitationAddress;
|
#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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Adv
|
||||||
/* Route preference structure */
|
|
||||||
struct irdp
|
|
||||||
{
|
{
|
||||||
struct in_addr prefix;
|
struct in_addr ip;
|
||||||
long pref; /* preference level */
|
int pref;
|
||||||
long timer; /* lifetime timer */
|
|
||||||
|
|
||||||
struct irdp *next; /* doubly linked list */
|
|
||||||
struct irdp *prev; /* doubly linked list */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Default irdp packet interval */
|
void irdp_init();
|
||||||
#define IRDP_DEFAULT_INTERVAL 300
|
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/zserv.h"
|
||||||
#include "zebra/debug.h"
|
#include "zebra/debug.h"
|
||||||
#include "zebra/rib.h"
|
#include "zebra/rib.h"
|
||||||
|
#include "zebra/irdp.h"
|
||||||
|
|
||||||
/* Zebra instance */
|
/* Zebra instance */
|
||||||
struct zebra_t zebrad =
|
struct zebra_t zebrad =
|
||||||
@ -151,6 +152,9 @@ sigint (void)
|
|||||||
|
|
||||||
if (!retain_mode)
|
if (!retain_mode)
|
||||||
rib_close ();
|
rib_close ();
|
||||||
|
#ifdef HAVE_IRDP
|
||||||
|
irdp_finish();
|
||||||
|
#endif
|
||||||
|
|
||||||
exit (0);
|
exit (0);
|
||||||
}
|
}
|
||||||
@ -289,6 +293,9 @@ main (int argc, char **argv)
|
|||||||
zebra_vty_init ();
|
zebra_vty_init ();
|
||||||
access_list_init ();
|
access_list_init ();
|
||||||
rtadv_init ();
|
rtadv_init ();
|
||||||
|
#ifdef HAVE_IRDP
|
||||||
|
irdp_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
/* For debug purpose. */
|
/* For debug purpose. */
|
||||||
/* SET_FLAG (zebra_debug_event, ZEBRA_DEBUG_EVENT); */
|
/* SET_FLAG (zebra_debug_event, ZEBRA_DEBUG_EVENT); */
|
||||||
|
Loading…
Reference in New Issue
Block a user