forked from Mirror/frr
eigrp: Initial Commit
Please Note, I will be redoing this commit message with more information. Additionally I will rework the lib/* changes into their own commits. Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
This commit is contained in:
parent
baf9c43622
commit
7f57883ee6
|
@ -2,13 +2,14 @@
|
|||
|
||||
SUBDIRS = lib qpb fpm @ZEBRA@ @LIBRFP@ @RFPTEST@ \
|
||||
@BGPD@ @RIPD@ @RIPNGD@ @OSPFD@ @OSPF6D@ @LDPD@ \
|
||||
@ISISD@ @PIMD@ @NHRPD@ \
|
||||
@ISISD@ @PIMD@ @NHRPD@ @EIGRPD@ \
|
||||
@WATCHFRR@ @VTYSH@ @OSPFCLIENT@ @DOC@ m4 @pkgsrcdir@ \
|
||||
redhat @SOLARIS@ tests tools cumulus snapcraft
|
||||
|
||||
DIST_SUBDIRS = lib qpb fpm zebra bgpd ripd ripngd ospfd ospf6d ldpd \
|
||||
isisd watchfrr vtysh ospfclient doc m4 pkgsrc redhat tests \
|
||||
solaris pimd nhrpd @LIBRFP@ @RFPTEST@ tools cumulus snapcraft
|
||||
solaris pimd nhrpd eigrpd @LIBRFP@ @RFPTEST@ tools cumulus \
|
||||
snapcraft
|
||||
|
||||
EXTRA_DIST = aclocal.m4 SERVICES REPORTING-BUGS \
|
||||
update-autotools \
|
||||
|
|
14
configure.ac
14
configure.ac
|
@ -217,6 +217,8 @@ AC_ARG_ENABLE(ldpd,
|
|||
AS_HELP_STRING([--enable-ldpd], [build ldpd]))
|
||||
AC_ARG_ENABLE(nhrpd,
|
||||
AS_HELP_STRING([--disable-nhrpd], [do not build nhrpd]))
|
||||
AC_ARG_ENABLE(eigrpd,
|
||||
AS_HELP_STRING([--disable-eigrpd], [do not build eigrpd]))
|
||||
AC_ARG_ENABLE(watchfrr,
|
||||
AS_HELP_STRING([--disable-watchfrr], [do not build watchfrr]))
|
||||
AC_ARG_ENABLE(isisd,
|
||||
|
@ -1200,6 +1202,13 @@ else
|
|||
fi
|
||||
AM_CONDITIONAL(NHRPD, test "x$NHRPD" = "xnhrpd")
|
||||
|
||||
if test "${enable_eigrpd}" = "no";then
|
||||
EIGRPD=""
|
||||
else
|
||||
EIGRPD="eigrpd"
|
||||
fi
|
||||
AM_CONDITIONAL(EIGRPD, test "x$EIGRPD" = "xeigrpd")
|
||||
|
||||
if test "${enable_watchfrr}" = "no";then
|
||||
WATCHFRR=""
|
||||
else
|
||||
|
@ -1281,6 +1290,7 @@ AC_SUBST(OSPFD)
|
|||
AC_SUBST(OSPF6D)
|
||||
AC_SUBST(LDPD)
|
||||
AC_SUBST(NHRPD)
|
||||
AC_SUBST(EIGRPD)
|
||||
AC_SUBST(WATCHFRR)
|
||||
AC_SUBST(ISISD)
|
||||
AC_SUBST(PIMD)
|
||||
|
@ -1671,6 +1681,7 @@ AC_CONFIG_FILES([Makefile lib/Makefile qpb/Makefile zebra/Makefile ripd/Makefile
|
|||
ospf6d/Makefile ldpd/Makefile isisd/Makefile vtysh/Makefile
|
||||
doc/Makefile ospfclient/Makefile tests/Makefile m4/Makefile
|
||||
pimd/Makefile
|
||||
eigrpd/Makefile
|
||||
nhrpd/Makefile
|
||||
redhat/Makefile
|
||||
tools/Makefile
|
||||
|
@ -1697,7 +1708,8 @@ AC_CONFIG_FILES([Makefile lib/Makefile qpb/Makefile zebra/Makefile ripd/Makefile
|
|||
doc/zebra.8
|
||||
doc/frr.1
|
||||
pkgsrc/bgpd.sh pkgsrc/ospf6d.sh pkgsrc/ospfd.sh
|
||||
pkgsrc/ripd.sh pkgsrc/ripngd.sh pkgsrc/zebra.sh])
|
||||
pkgsrc/ripd.sh pkgsrc/ripngd.sh pkgsrc/zebra.sh
|
||||
pkgsrc/eigrpd.sh])
|
||||
|
||||
if test "${enable_bgp_vnc}" != "no"; then
|
||||
if test "${with_rfp_path}" = "bgpd/rfp-example" ; then
|
||||
|
|
17
eigrpd/.gitignore
vendored
Normal file
17
eigrpd/.gitignore
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
Makefile
|
||||
Makefile.in
|
||||
*.o
|
||||
eigrpd
|
||||
eigrpd.conf
|
||||
tags
|
||||
TAGS
|
||||
.deps
|
||||
.nfs*
|
||||
*.lo
|
||||
*.la
|
||||
*.libs
|
||||
.arch-inventory
|
||||
.arch-ids
|
||||
*~
|
||||
*.loT
|
||||
|
1321
eigrpd/EIGRP-MIB.txt
Normal file
1321
eigrpd/EIGRP-MIB.txt
Normal file
File diff suppressed because it is too large
Load diff
45
eigrpd/Makefile.am
Normal file
45
eigrpd/Makefile.am
Normal file
|
@ -0,0 +1,45 @@
|
|||
## Process this file with automake to produce Makefile.in.
|
||||
|
||||
AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib
|
||||
DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\"
|
||||
INSTALL_SDATA=@INSTALL@ -m 600
|
||||
|
||||
AM_CFLAGS = $(WERROR)
|
||||
|
||||
noinst_LIBRARIES = libeigrp.a
|
||||
sbin_PROGRAMS = eigrpd
|
||||
|
||||
libeigrp_a_SOURCES = \
|
||||
eigrpd.c eigrp_zebra.c \
|
||||
eigrp_interface.c eigrp_neighbor.c \
|
||||
eigrp_dump.c eigrp_vty.c \
|
||||
eigrp_network.c eigrp_packet.c \
|
||||
eigrp_topology.c eigrp_fsm.c \
|
||||
eigrp_hello.c eigrp_update.c \
|
||||
eigrp_query.c eigrp_reply.c \
|
||||
eigrp_snmp.c eigrp_siaquery.c \
|
||||
eigrp_siareply.c eigrp_filter.c \
|
||||
eigrp_memory.c
|
||||
|
||||
|
||||
eigrpdheaderdir = $(pkgincludedir)/eigrpd
|
||||
|
||||
eigrpdheader_HEADERS = \
|
||||
eigrp_topology.h eigrp_dump.h eigrpd.h
|
||||
|
||||
noinst_HEADERS = \
|
||||
eigrp_const.h eigrp_structs.h \
|
||||
eigrp_macros.h eigrp_interface.h \
|
||||
eigrp_neighbor.h eigrp_network.h \
|
||||
eigrp_packet.h eigrp_memory.h \
|
||||
eigrp_zebra.h eigrp_vty.h \
|
||||
eigrp_snmp.h eigrp_filter.h
|
||||
|
||||
eigrpd_SOURCES = eigrp_main.c $(libeigrp_a_SOURCES)
|
||||
|
||||
eigrpd_LDADD = ../lib/libfrr.la @LIBCAP@
|
||||
|
||||
EXTRA_DIST = EIGRP-MIB.txt
|
||||
|
||||
examplesdir = $(exampledir)
|
||||
dist_examples_DATA = eigrpd.conf.sample
|
439
eigrpd/eigrp_const.h
Normal file
439
eigrpd/eigrp_const.h
Normal file
|
@ -0,0 +1,439 @@
|
|||
/*
|
||||
* EIGRP Definition of Constants.
|
||||
* Copyright (C) 2013-2016
|
||||
* Authors:
|
||||
* Donnie Savage
|
||||
* Jan Janovic
|
||||
* Matej Perina
|
||||
* Peter Orsag
|
||||
* Peter Paluch
|
||||
* Frantisek Gazo
|
||||
* Tomas Hvorkovy
|
||||
* Martin Kontsek
|
||||
* Lukas Koribsky
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _ZEBRA_EIGRP_CONST_H_
|
||||
#define _ZEBRA_EIGRP_CONST_H_
|
||||
|
||||
#define FALSE 0
|
||||
|
||||
#define EIGRP_NEIGHBOR_DOWN 0
|
||||
#define EIGRP_NEIGHBOR_PENDING 1
|
||||
#define EIGRP_NEIGHBOR_UP 2
|
||||
#define EIGRP_NEIGHBOR_STATE_MAX 3
|
||||
|
||||
/*Packet requiring ack will be retransmitted again after this time*/
|
||||
#define EIGRP_PACKET_RETRANS_TIME 2 /* in seconds */
|
||||
#define EIGRP_PACKET_RETRANS_MAX 16 /* number of retrans attempts */
|
||||
#define PLAINTEXT_LENGTH 81
|
||||
|
||||
/*Metric variance multiplier*/
|
||||
#define EIGRP_VARIANCE_DEFAULT 1
|
||||
#define EIGRP_MAX_PATHS_DEFAULT 4
|
||||
|
||||
|
||||
/* Return values of functions involved in packet verification */
|
||||
#define MSG_OK 0
|
||||
#define MSG_NG 1
|
||||
|
||||
#define EIGRP_HEADER_VERSION 2
|
||||
|
||||
/* Default protocol, port number. */
|
||||
#ifndef IPPROTO_EIGRPIGP
|
||||
#define IPPROTO_EIGRPIGP 88
|
||||
#endif /* IPPROTO_EIGRPIGP */
|
||||
|
||||
#define EIGRP_AUTH_MD5_TLV_SIZE 40
|
||||
#define EIGRP_AUTH_SHA256_TLV_SIZE 56
|
||||
|
||||
/*Cisco routers use only first 44 bytes of basic hello for their MD5 calculations*/
|
||||
#define EIGRP_MD5_BASIC_COMPUTE 44
|
||||
#define EIGRP_MD5_UPDATE_INIT_COMPUTE 40
|
||||
|
||||
|
||||
|
||||
#define EIGRP_AUTH_BASIC_HELLO_FLAG 0x01
|
||||
#define EIGRP_AUTH_TID_HELLO_FLAG 0x02
|
||||
#define EIGRP_AUTH_UPDATE_INIT_FLAG 0x04
|
||||
#define EIGRP_AUTH_UPDATE_FLAG 0x08
|
||||
#define EIGRP_AUTH_EXTRA_SALT_FLAG 0x10
|
||||
|
||||
#define EIGRP_NEXT_SEQUENCE_TLV_SIZE 8
|
||||
|
||||
/* IP TTL for EIGRP protocol. */
|
||||
#define EIGRP_IP_TTL 1
|
||||
|
||||
/* VTY port number. */
|
||||
#define EIGRP_VTY_PORT 2609
|
||||
|
||||
/* Default configuration file name for eigrp. */
|
||||
#define EIGRP_DEFAULT_CONFIG "eigrpd.conf"
|
||||
|
||||
#define EIGRP_HELLO_INTERVAL_DEFAULT 5
|
||||
#define EIGRP_HOLD_INTERVAL_DEFAULT 15
|
||||
#define EIGRP_BANDWIDTH_DEFAULT 10000000
|
||||
#define EIGRP_DELAY_DEFAULT 1000
|
||||
#define EIGRP_RELIABILITY_DEFAULT 255
|
||||
#define EIGRP_LOAD_DEFAULT 1
|
||||
|
||||
#define EIGRP_MULTICAST_ADDRESS 0xe000000A /*224.0.0.10*/
|
||||
|
||||
#define EIGRP_MAX_METRIC 0xffffffffU /*4294967295*/
|
||||
|
||||
#define DEFAULT_ROUTE ZEBRA_ROUTE_MAX
|
||||
#define DEFAULT_ROUTE_TYPE(T) ((T) == DEFAULT_ROUTE)
|
||||
|
||||
#define INTERFACE_DOWN_BY_ZEBRA 1
|
||||
#define INTERFACE_DOWN_BY_VTY 2
|
||||
|
||||
#define EIGRP_HELLO_NORMAL 0x00
|
||||
#define EIGRP_HELLO_GRACEFUL_SHUTDOWN 0x01
|
||||
#define EIGRP_HELLO_ADD_SEQUENCE 0x02
|
||||
#define EIGRP_HELLO_GRACEFUL_SHUTDOWN_NBR 0x04
|
||||
|
||||
/* EIGRP Network Type. */
|
||||
#define EIGRP_IFTYPE_NONE 0
|
||||
#define EIGRP_IFTYPE_POINTOPOINT 1
|
||||
#define EIGRP_IFTYPE_BROADCAST 2
|
||||
#define EIGRP_IFTYPE_NBMA 3
|
||||
#define EIGRP_IFTYPE_POINTOMULTIPOINT 4
|
||||
#define EIGRP_IFTYPE_LOOPBACK 5
|
||||
#define EIGRP_IFTYPE_MAX 6
|
||||
|
||||
#define EIGRP_IF_ACTIVE 0
|
||||
#define EIGRP_IF_PASSIVE 1
|
||||
|
||||
/* EIGRP TT destination type */
|
||||
#define EIGRP_TOPOLOGY_TYPE_CONNECTED 0 // Connected network
|
||||
#define EIGRP_TOPOLOGY_TYPE_REMOTE 1 // Remote internal network
|
||||
#define EIGRP_TOPOLOGY_TYPE_REMOTE_EXTERNAL 2 // Remote external network
|
||||
|
||||
/*EIGRP TT entry flags*/
|
||||
#define EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG 1
|
||||
#define EIGRP_NEIGHBOR_ENTRY_FSUCCESSOR_FLAG 2
|
||||
#define EIGRP_NEIGHBOR_ENTRY_INTABLE_FLAG 4
|
||||
#define EIGRP_NEIGHBOR_ENTRY_EXTERNAL_FLAG 8
|
||||
|
||||
/*EIGRP FSM state count, event count*/
|
||||
#define EIGRP_FSM_STATE_MAX 5
|
||||
#define EIGRP_FSM_EVENT_MAX 16
|
||||
|
||||
/*EGRP FSM states*/
|
||||
#define EIGRP_FSM_STATE_PASSIVE 0
|
||||
#define EIGRP_FSM_STATE_ACTIVE_0 1
|
||||
#define EIGRP_FSM_STATE_ACTIVE_1 2
|
||||
#define EIGRP_FSM_STATE_ACTIVE_2 3
|
||||
#define EIGRP_FSM_STATE_ACTIVE_3 4
|
||||
|
||||
/*EIGRP FSM events return values*/
|
||||
#define EIGRP_FSM_NEED_UPDATE 1
|
||||
#define EIGRP_FSM_NEED_QUERY 2
|
||||
|
||||
/*EIGRP FSM events*/
|
||||
#define EIGRP_FSM_EVENT_NQ_FCN 0 /*input event other than query from succ, FC not satisfied*/
|
||||
#define EIGRP_FSM_EVENT_LR 1 /*last reply, FD is reset*/
|
||||
#define EIGRP_FSM_EVENT_Q_FCN 2 /*query from succ, FC not satisfied*/
|
||||
#define EIGRP_FSM_EVENT_LR_FCS 3 /*last reply, FC satisfied with current value of FDij*/
|
||||
#define EIGRP_FSM_EVENT_DINC 4 /*distance increase while in active state*/
|
||||
#define EIGRP_FSM_EVENT_QACT 5 /*query from succ while in active state*/
|
||||
#define EIGRP_FSM_EVENT_LR_FCN 6 /*last reply, FC not satisfied with current value of FDij*/
|
||||
#define EIGRP_FSM_KEEP_STATE 7 /*state not changed, usually by receiving not last reply */
|
||||
|
||||
#define INT_TYPES_CMD_STR \
|
||||
"detail|fastethernet|loopback|static"
|
||||
|
||||
#define INT_TYPES_DESC \
|
||||
"Virtual Ethernet interface\n" \
|
||||
"FastEthernet IEEE 802.3\n" \
|
||||
"Loopback interface\n" \
|
||||
"Show static peer information\n"
|
||||
|
||||
/**
|
||||
* External routes originate from some other protocol - these are them
|
||||
*/
|
||||
#define NULL_PROTID 0 /*!< unknown protocol */
|
||||
#define IGRP_PROTID 1 /*!< IGRP.. whos your daddy! */
|
||||
#define EIGRP_PROTID 2 /*!< EIGRP - Just flat out the best */
|
||||
#define STATIC_PROTID 3 /*!< Staticly configured source */
|
||||
#define RIP_PROTID 4 /*!< Routing Information Protocol */
|
||||
#define HELLO_PROTID 5 /*!< Hello? RFC-891 you there? */
|
||||
#define OSPF_PROTID 6 /*!< OSPF - Open Shortest Path First */
|
||||
#define ISIS_PROTID 7 /*!< Intermediate System To Intermediate System */
|
||||
#define EGP_PROTID 8 /*!< Exterior Gateway Protocol */
|
||||
#define BGP_PROTID 9 /*!< Border Gateway Protocol */
|
||||
#define IDRP_PROTID 10 /*!< InterDomain Routing Protocol */
|
||||
#define CONN_PROTID 11 /*!< Connected source */
|
||||
|
||||
/*
|
||||
* metric k-value defaults
|
||||
*/
|
||||
#define EIGRP_K1_DEFAULT 1 //!< unweighed inverse bandwidth
|
||||
#define EIGRP_K2_DEFAULT 0 //!< no loading term
|
||||
#define EIGRP_K3_DEFAULT 1 //!< unweighted delay
|
||||
#define EIGRP_K4_DEFAULT 0 //!< no reliability term
|
||||
#define EIGRP_K5_DEFAULT 0 //!< no reliability term
|
||||
#define EIGRP_K6_DEFAULT 0 //!< do not add in extended metrics
|
||||
|
||||
|
||||
/*
|
||||
* EIGRP Fixed header
|
||||
*/
|
||||
#define EIGRP_HEADER_LEN 20U
|
||||
#define EIGRP_PACKET_MAX_LEN 65535U /* includes IP Header size. */
|
||||
|
||||
|
||||
#define EIGRP_TLV_HDR_LENGTH 4
|
||||
|
||||
/**
|
||||
* EIGRP Packet Opcodes
|
||||
*/
|
||||
#define EIGRP_OPC_UPDATE 1 /*!< packet containing routing information */
|
||||
#define EIGRP_OPC_REQUEST 2 /*!< sent to request one or more routes */
|
||||
#define EIGRP_OPC_QUERY 3 /*!< sent when a routing is in active start */
|
||||
#define EIGRP_OPC_REPLY 4 /*!< sent in response to a query */
|
||||
#define EIGRP_OPC_HELLO 5 /*!< sent to maintain a peering session */
|
||||
#define EIGRP_OPC_IPXSAP 6 /*!< IPX SAP information */
|
||||
#define EIGRP_OPC_PROBE 7 /*!< for test purposes */
|
||||
#define EIGRP_OPC_ACK 8 /*!< acknowledge */
|
||||
#define EIGRP_OPC_SIAQUERY 10 /*!< QUERY - with relaxed restrictions */
|
||||
#define EIGRP_OPC_SIAREPLY 11 /*!< REPLY - may contain old routing information */
|
||||
|
||||
/**
|
||||
* EIGRP TLV Range definitions
|
||||
* PDM TLV Range
|
||||
* General 0x0000
|
||||
* IPv4 0x0100 ** TLVs for one and all
|
||||
* ATALK 0x0200 ** legacy
|
||||
* IPX 0x0300 ** discontinued
|
||||
* IPv6 0x0400 ** legacy
|
||||
* Multiprotocol 0x0600 ** wide metrics
|
||||
* MultiTopology 0x00f0 ** deprecated
|
||||
*/
|
||||
#define EIGRP_TLV_RANGEMASK 0xfff0 /*!< should be 0xff00 - opps */
|
||||
#define EIGRP_TLV_GENERAL 0x0000
|
||||
|
||||
/**
|
||||
* 1.2 TLV Definitions ** legacy
|
||||
* These are considered legacyu and are only used for backward compability with
|
||||
* older Cisco Routers. They should not be your first choice for packet codings
|
||||
*/
|
||||
#define EIGRP_TLV_IPv4 0x0100 /*!< Classic IPv4 TLV encoding */
|
||||
#define EIGRP_TLV_ATALK 0x0200 /*!< Classic Appletalk TLV encoding*/
|
||||
#define EIGRP_TLV_IPX 0x0300 /*!< Classic IPX TLV encoding */
|
||||
#define EIGRP_TLV_IPv6 0x0400 /*!< Classic IPv6 TLV encoding */
|
||||
|
||||
/**
|
||||
* 2.0 Multi-Protocol TLV Definitions
|
||||
* These are the current packet formats and should be used for packets
|
||||
*/
|
||||
#define EIGRP_TLV_MP 0x0600 /*!< Non-PDM specific encoding */
|
||||
|
||||
/**
|
||||
* TLV type definitions. Generic (protocol-independent) TLV types are
|
||||
* defined here. Protocol-specific ones are defined elsewhere.
|
||||
*/
|
||||
#define EIGRP_TLV_PARAMETER (EIGRP_TLV_GENERAL | 0x0001) /*!< eigrp parameters */
|
||||
#define EIGRP_TLV_PARAMETER_LEN (12U)
|
||||
#define EIGRP_TLV_AUTH (EIGRP_TLV_GENERAL | 0x0002) /*!< authentication */
|
||||
#define EIGRP_TLV_SEQ (EIGRP_TLV_GENERAL | 0x0003) /*!< sequenced packet */
|
||||
#define EIGRP_TLV_SEQ_BASE_LEN (5U)
|
||||
#define EIGRP_TLV_SW_VERSION (EIGRP_TLV_GENERAL | 0x0004) /*!< software version */
|
||||
#define EIGRP_TLV_SW_VERSION_LEN (8U)
|
||||
#define EIGRP_TLV_NEXT_MCAST_SEQ (EIGRP_TLV_GENERAL | 0x0005) /*!< sequence number */
|
||||
#define EIGRP_TLV_PEER_TERMINATION (EIGRP_TLV_GENERAL | 0x0007) /*!< peer termination */
|
||||
#define EIGRP_TLV_PEER_TERMINATION_LEN (9U)
|
||||
#define EIGRP_TLV_PEER_TIDLIST (EIGRP_TLV_GENERAL | 0x0008) /*!< peer sub-topology list */
|
||||
|
||||
/* Older cisco routers send TIDLIST value wrong, adding for backwards compatabily */
|
||||
#define EIGRP_TLV_PEER_MTRLIST (EIGRP_TLV_GENERAL | 0x00f5)
|
||||
|
||||
/**
|
||||
* Route Based TLVs
|
||||
*/
|
||||
#define EIGRP_TLV_REQUEST 0x0001
|
||||
#define EIGRP_TLV_INTERNAL 0x0002
|
||||
#define EIGRP_TLV_EXTERNAL 0x0003
|
||||
#define EIGRP_TLV_COMMUNITY 0x0004
|
||||
#define EIGRP_TLV_TYPEMASK 0x000f
|
||||
|
||||
#define EIGRP_TLV_IPv4_REQ (EIGRP_TLV_IPv4 | EIGRP_TLV_REQUEST)
|
||||
#define EIGRP_TLV_IPv4_INT (EIGRP_TLV_IPv4 | EIGRP_TLV_INTERNAL)
|
||||
#define EIGRP_TLV_IPv4_EXT (EIGRP_TLV_IPv4 | EIGRP_TLV_EXTERNAL)
|
||||
#define EIGRP_TLV_IPv4_COM (EIGRP_TLV_IPv4 | EIGRP_TLV_COMMUNITY)
|
||||
|
||||
/* max number of TLV IPv4 prefixes in packet */
|
||||
#define EIGRP_TLV_MAX_IPv4 25
|
||||
|
||||
/**
|
||||
*
|
||||
* extdata flag field definitions
|
||||
*/
|
||||
#define EIGRP_OPAQUE_EXT 0x01 /*!< Route is external */
|
||||
#define EIGRP_OPAQUE_CD 0x02 /*!< Candidate default route */
|
||||
|
||||
/**
|
||||
* Address-Family types are taken from:
|
||||
* http://www.iana.org/assignments/address-family-numbers
|
||||
* to provide a standards based exchange of AFI information between
|
||||
* EIGRP routers.
|
||||
*/
|
||||
#define EIGRP_AF_IPv4 1 /*!< IPv4 (IP version 4) */
|
||||
#define EIGRP_AF_IPv6 2 /*!< IPv6 (IP version 6) */
|
||||
#define EIGRP_AF_IPX 11 /*!< IPX */
|
||||
#define EIGRP_AF_ATALK 12 /*!< Appletalk */
|
||||
#define EIGRP_SF_COMMON 16384 /*!< Cisco Service Family */
|
||||
#define EIGRP_SF_IPv4 16385 /*!< Cisco IPv4 Service Family */
|
||||
#define EIGRP_SF_IPv6 16386 /*!< Cisco IPv6 Service Family */
|
||||
|
||||
/**
|
||||
* Authentication types supported by EIGRP
|
||||
*/
|
||||
#define EIGRP_AUTH_TYPE_NONE 0
|
||||
#define EIGRP_AUTH_TYPE_TEXT 1
|
||||
#define EIGRP_AUTH_TYPE_MD5 2
|
||||
#define EIGRP_AUTH_TYPE_MD5_LEN 16
|
||||
#define EIGRP_AUTH_TYPE_SHA256 3
|
||||
#define EIGRP_AUTH_TYPE_SHA256_LEN 32
|
||||
|
||||
/**
|
||||
* opaque flag field definitions
|
||||
*/
|
||||
#define EIGRP_OPAQUE_SRCWD 0x01 /*!< Route Source Withdraw */
|
||||
#define EIGRP_OPAQUE_ACTIVE 0x04 /*!< Route is currently in active state */
|
||||
#define EIGRP_OPAQUE_REPL 0x08 /*!< Route is replicated from different tableid */
|
||||
|
||||
/**
|
||||
* pak flag bit field definitions - 0 (none)-7 source priority
|
||||
*/
|
||||
#define EIGRP_PRIV_DEFAULT 0x00 /* 0 (none)-7 source priority */
|
||||
#define EIGRP_PRIV_LOW 0x01
|
||||
#define EIGRP_PRIV_MEDIUM 0x04
|
||||
#define EIGRP_PRIV_HIGH 0x07
|
||||
|
||||
/*
|
||||
* Init bit definition. First unicast transmitted Update has this
|
||||
* bit set in the flags field of the fixed header. It tells the neighbor
|
||||
* to down-load his topology table.
|
||||
*/
|
||||
#define EIGRP_INIT_FLAG 0x01
|
||||
|
||||
/*
|
||||
* CR bit (Conditionally Received) definition in flags field on header. Any
|
||||
* packets with the CR-bit set can be accepted by an EIGRP speaker if and
|
||||
* only if a previous Hello was received with the SEQUENCE_TYPE TLV present.
|
||||
*
|
||||
* This allows multicasts to be transmitted in order and reliably at the
|
||||
* same time as unicasts are transmitted.
|
||||
*/
|
||||
#define EIGRP_CR_FLAG 0x02
|
||||
|
||||
/*
|
||||
* RS bit. The Restart flag is set in the hello and the init
|
||||
* update packets during the nsf signaling period. A nsf-aware
|
||||
* router looks at the RS flag to detect if a peer is restarting
|
||||
* and maintain the adjacency. A restarting router looks at
|
||||
* this flag to determine if the peer is helping out with the restart.
|
||||
*/
|
||||
#define EIGRP_RS_FLAG 0x04
|
||||
|
||||
/*
|
||||
* EOT bit. The End-of-Table flag marks the end of the start-up updates
|
||||
* sent to a new peer. A nsf restarting router looks at this flag to
|
||||
* determine if it has finished receiving the start-up updates from all
|
||||
* peers. A nsf-aware router waits for this flag before cleaning up
|
||||
* the stale routes from the restarting peer.
|
||||
*/
|
||||
#define EIGRP_EOT_FLAG 0x08
|
||||
|
||||
/**
|
||||
* EIGRP Virtual Router ID
|
||||
*
|
||||
* Define values to deal with EIGRP virtual router ids. Virtual
|
||||
* router IDs are stored in the upper short of the EIGRP fixed packet
|
||||
* header. The lower short of the packet header continues to be used
|
||||
* as asystem number.
|
||||
*
|
||||
* Virtual Router IDs are PDM-independent. All PDMs will use
|
||||
* VRID_BASE to indicate the 'base' or 'legacy' EIGRP instance.
|
||||
* All PDMs need to initialize their vrid to VRID_BASE for compatibility
|
||||
* with legacy routers.
|
||||
* Once IPv6 supports 'MTR Multicast', it will use the same VRID as
|
||||
* IPv4. No current plans to support VRIDs on IPX. :)
|
||||
* Initial usage of VRID is to signal usage of Multicast topology for
|
||||
* MTR.
|
||||
*
|
||||
* VRID_MCAST is a well known constant, other VRIDs will be determined
|
||||
* programmatic...
|
||||
*
|
||||
* With the addition of SAF the VRID space has been divided into two
|
||||
* segments 0x0000-0x7fff is for EIGRP and vNets, 0x8000-0xffff is
|
||||
* for saf and its associated vNets.
|
||||
*/
|
||||
#define EIGRP_VRID_MASK 0x8001
|
||||
#define EIGRP_VRID_AF_BASE 0x0000
|
||||
#define EIGRP_VRID_MCAST_BASE 0x0001
|
||||
#define EIGRP_VRID_SF_BASE 0x8000
|
||||
|
||||
/* Extended Attributes for a destination */
|
||||
#define EIGRP_ATTR_HDRLEN (2)
|
||||
#define EIGRP_ATTR_MAXDATA (512)
|
||||
|
||||
#define EIGRP_ATTR_NOOP 0 /*!< No-Op used as offset padding */
|
||||
#define EIGRP_ATTR_SCALED 1 /*!< Scaled metric values */
|
||||
#define EIGRP_ATTR_TAG 2 /*!< Tag assigned by Admin for dest */
|
||||
#define EIGRP_ATTR_COMM 3 /*!< Community attribute for dest */
|
||||
#define EIGRP_ATTR_JITTER 4 /*!< Variation in path delay */
|
||||
#define EIGRP_ATTR_QENERGY 5 /*!< Non-Active energy usage along path */
|
||||
#define EIGRP_ATTR_ENERGY 6 /*!< Active energy usage along path */
|
||||
|
||||
/*
|
||||
* Begin EIGRP-BGP interoperability communities
|
||||
*/
|
||||
#define EIGRP_EXTCOMM_SOO_ASFMT 0x0003 /* Site-of-Origin, BGP AS format */
|
||||
#define EIGRP_EXTCOMM_SOO_ADRFMT 0x0103 /* Site-of-Origin, BGP/EIGRP addr format */
|
||||
|
||||
/*
|
||||
* EIGRP Specific communities
|
||||
*/
|
||||
#define EIGRP_EXTCOMM_EIGRP 0x8800 /* EIGRP route information appended*/
|
||||
#define EIGRP_EXTCOMM_DAD 0x8801 /* EIGRP AS + Delay */
|
||||
#define EIGRP_EXTCOMM_VRHB 0x8802 /* EIGRP Vector: Reliability + Hop + BW */
|
||||
#define EIGRP_EXTCOMM_SRLM 0x8803 /* EIGRP System: Reserve +Load + MTU */
|
||||
#define EIGRP_EXTCOMM_SAR 0x8804 /* EIGRP System: Remote AS + Remote ID */
|
||||
#define EIGRP_EXTCOMM_RPM 0x8805 /* EIGRP Remote: Protocol + Metric */
|
||||
#define EIGRP_EXTCOMM_VRR 0x8806 /* EIGRP Vecmet: Rsvd + (internal) Routerid */
|
||||
|
||||
|
||||
/*
|
||||
* EIGRP Filter constants
|
||||
*/
|
||||
#define EIGRP_FILTER_IN 0
|
||||
#define EIGRP_FILTER_OUT 1
|
||||
#define EIGRP_FILTER_MAX 2
|
||||
|
||||
/*
|
||||
* EIGRP Filter constants
|
||||
*/
|
||||
#define EIGRP_HSROLE_DEFAULT EIGRP_HSROLE_SPOKE
|
||||
#define EIGRP_HSROLE_HUB 0x01
|
||||
#define EIGRP_HSROLE_SPOKE 0x02
|
||||
|
||||
#endif /* _ZEBRA_EIGRP_CONST_H_ */
|
768
eigrpd/eigrp_dump.c
Normal file
768
eigrpd/eigrp_dump.c
Normal file
|
@ -0,0 +1,768 @@
|
|||
/*
|
||||
* EIGRP Dump Functions and Debugging.
|
||||
* Copyright (C) 2013-2014
|
||||
* Authors:
|
||||
* Donnie Savage
|
||||
* Jan Janovic
|
||||
* Matej Perina
|
||||
* Peter Orsag
|
||||
* Peter Paluch
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#include "linklist.h"
|
||||
#include "thread.h"
|
||||
#include "prefix.h"
|
||||
#include "command.h"
|
||||
#include "stream.h"
|
||||
#include "log.h"
|
||||
#include "sockopt.h"
|
||||
#include "table.h"
|
||||
#include "keychain.h"
|
||||
|
||||
#include "eigrpd/eigrp_structs.h"
|
||||
#include "eigrpd/eigrpd.h"
|
||||
#include "eigrpd/eigrp_interface.h"
|
||||
#include "eigrpd/eigrp_neighbor.h"
|
||||
#include "eigrpd/eigrp_packet.h"
|
||||
#include "eigrpd/eigrp_zebra.h"
|
||||
#include "eigrpd/eigrp_vty.h"
|
||||
#include "eigrpd/eigrp_network.h"
|
||||
#include "eigrpd/eigrp_dump.h"
|
||||
#include "eigrpd/eigrp_topology.h"
|
||||
|
||||
/* Enable debug option variables -- valid only session. */
|
||||
unsigned long term_debug_eigrp = 0;
|
||||
unsigned long term_debug_eigrp_nei = 0;
|
||||
unsigned long term_debug_eigrp_packet[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
unsigned long term_debug_eigrp_zebra = 6;
|
||||
unsigned long term_debug_eigrp_transmit = 0;
|
||||
|
||||
/* Configuration debug option variables. */
|
||||
unsigned long conf_debug_eigrp = 0;
|
||||
unsigned long conf_debug_eigrp_nei = 0;
|
||||
unsigned long conf_debug_eigrp_packet[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
unsigned long conf_debug_eigrp_zebra = 0;
|
||||
unsigned long conf_debug_eigrp_transmit = 0;
|
||||
|
||||
|
||||
static int
|
||||
config_write_debug (struct vty *vty)
|
||||
{
|
||||
int write = 0;
|
||||
int i;
|
||||
|
||||
const char *type_str[] = {"update", "request", "query", "reply", "hello", "", "probe", "ack", "",
|
||||
"SIA query", "SIA reply", "stub", "all"};
|
||||
const char *detail_str[] = {"", " send", " recv", "", " detail",
|
||||
" send detail", " recv detail", " detail"};
|
||||
|
||||
|
||||
/* debug eigrp event. */
|
||||
// if (IS_CONF_DEBUG_EIGRP (event, EVENT) == EIGRP_DEBUG_EVENT)
|
||||
// {
|
||||
// vty_out (vty, "debug eigrp event%s", VTY_NEWLINE);
|
||||
// write = 1;
|
||||
// }
|
||||
|
||||
/* debug eigrp packet all detail. */
|
||||
// r = EIGRP_DEBUG_SEND_RECV|EIGRP_DEBUG_DETAIL;
|
||||
// for (i = 0; i < 11; i++)
|
||||
// r &= conf_debug_eigrp_packet[i] & (EIGRP_DEBUG_SEND_RECV|EIGRP_DEBUG_DETAIL);
|
||||
// if (r == (EIGRP_DEBUG_SEND_RECV|EIGRP_DEBUG_DETAIL))
|
||||
// {
|
||||
// vty_out (vty, "debug eigrp packet all detail%s", VTY_NEWLINE);
|
||||
//// return 1;
|
||||
// }
|
||||
//
|
||||
// /* debug eigrp packet all. */
|
||||
// r = EIGRP_DEBUG_SEND_RECV;
|
||||
// for (i = 0; i < 11; i++)
|
||||
// r &= conf_debug_eigrp_packet[i] & EIGRP_DEBUG_SEND_RECV;
|
||||
// if (r == EIGRP_DEBUG_SEND_RECV)
|
||||
// {
|
||||
// vty_out (vty, "debug eigrp packet all%s", VTY_NEWLINE);
|
||||
// for (i = 0; i < 11; i++)
|
||||
// if (conf_debug_eigrp_packet[i] & EIGRP_DEBUG_DETAIL)
|
||||
// vty_out (vty, "debug eigrp packet %s detail%s",
|
||||
// type_str[i],
|
||||
// VTY_NEWLINE);
|
||||
//// return 1;
|
||||
// }
|
||||
|
||||
/* debug eigrp packet */
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
if (conf_debug_eigrp_packet[i] == 0 && term_debug_eigrp_packet[i] == 0 )
|
||||
continue;
|
||||
|
||||
vty_out (vty, "debug eigrp packet %s%s%s",
|
||||
type_str[i], detail_str[conf_debug_eigrp_packet[i]],
|
||||
VTY_NEWLINE);
|
||||
write = 1;
|
||||
}
|
||||
|
||||
// int write = 0;
|
||||
// int i, r;
|
||||
//
|
||||
// const char *type_str[] = {"hello", "dd", "ls-request", "ls-update", "ls-ack"};
|
||||
// const char *detail_str[] = {"", " send", " recv", "", " detail",
|
||||
// " send detail", " recv detail", " detail"};
|
||||
//
|
||||
// /* debug ospf ism (status|events|timers). */
|
||||
// if (IS_CONF_DEBUG_OSPF (ism, ISM) == OSPF_DEBUG_ISM)
|
||||
// vty_out (vty, "debug ospf ism%s", VTY_NEWLINE);
|
||||
// else
|
||||
// {
|
||||
// if (IS_CONF_DEBUG_OSPF (ism, ISM_STATUS))
|
||||
// vty_out (vty, "debug ospf ism status%s", VTY_NEWLINE);
|
||||
// if (IS_CONF_DEBUG_OSPF (ism, ISM_EVENTS))
|
||||
// vty_out (vty, "debug ospf ism event%s", VTY_NEWLINE);
|
||||
// if (IS_CONF_DEBUG_OSPF (ism, ISM_TIMERS))
|
||||
// vty_out (vty, "debug ospf ism timer%s", VTY_NEWLINE);
|
||||
// }
|
||||
//
|
||||
// /* debug ospf nsm (status|events|timers). */
|
||||
// if (IS_CONF_DEBUG_OSPF (nsm, NSM) == OSPF_DEBUG_NSM)
|
||||
// vty_out (vty, "debug ospf nsm%s", VTY_NEWLINE);
|
||||
// else
|
||||
// {
|
||||
// if (IS_CONF_DEBUG_OSPF (nsm, NSM_STATUS))
|
||||
// vty_out (vty, "debug ospf nsm status%s", VTY_NEWLINE);
|
||||
// if (IS_CONF_DEBUG_OSPF (nsm, NSM_EVENTS))
|
||||
// vty_out (vty, "debug ospf nsm event%s", VTY_NEWLINE);
|
||||
// if (IS_CONF_DEBUG_OSPF (nsm, NSM_TIMERS))
|
||||
// vty_out (vty, "debug ospf nsm timer%s", VTY_NEWLINE);
|
||||
// }
|
||||
//
|
||||
// /* debug ospf lsa (generate|flooding|install|refresh). */
|
||||
// if (IS_CONF_DEBUG_OSPF (lsa, LSA) == OSPF_DEBUG_LSA)
|
||||
// vty_out (vty, "debug ospf lsa%s", VTY_NEWLINE);
|
||||
// else
|
||||
// {
|
||||
// if (IS_CONF_DEBUG_OSPF (lsa, LSA_GENERATE))
|
||||
// vty_out (vty, "debug ospf lsa generate%s", VTY_NEWLINE);
|
||||
// if (IS_CONF_DEBUG_OSPF (lsa, LSA_FLOODING))
|
||||
// vty_out (vty, "debug ospf lsa flooding%s", VTY_NEWLINE);
|
||||
// if (IS_CONF_DEBUG_OSPF (lsa, LSA_INSTALL))
|
||||
// vty_out (vty, "debug ospf lsa install%s", VTY_NEWLINE);
|
||||
// if (IS_CONF_DEBUG_OSPF (lsa, LSA_REFRESH))
|
||||
// vty_out (vty, "debug ospf lsa refresh%s", VTY_NEWLINE);
|
||||
//
|
||||
// write = 1;
|
||||
// }
|
||||
//
|
||||
// /* debug ospf zebra (interface|redistribute). */
|
||||
// if (IS_CONF_DEBUG_OSPF (zebra, ZEBRA) == OSPF_DEBUG_ZEBRA)
|
||||
// vty_out (vty, "debug ospf zebra%s", VTY_NEWLINE);
|
||||
// else
|
||||
// {
|
||||
// if (IS_CONF_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
|
||||
// vty_out (vty, "debug ospf zebra interface%s", VTY_NEWLINE);
|
||||
// if (IS_CONF_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
|
||||
// vty_out (vty, "debug ospf zebra redistribute%s", VTY_NEWLINE);
|
||||
//
|
||||
// write = 1;
|
||||
// }
|
||||
//
|
||||
// /* debug ospf event. */
|
||||
// if (IS_CONF_DEBUG_OSPF (event, EVENT) == OSPF_DEBUG_EVENT)
|
||||
// {
|
||||
// vty_out (vty, "debug ospf event%s", VTY_NEWLINE);
|
||||
// write = 1;
|
||||
// }
|
||||
//
|
||||
// /* debug ospf nssa. */
|
||||
// if (IS_CONF_DEBUG_OSPF (nssa, NSSA) == OSPF_DEBUG_NSSA)
|
||||
// {
|
||||
// vty_out (vty, "debug ospf nssa%s", VTY_NEWLINE);
|
||||
// write = 1;
|
||||
// }
|
||||
//
|
||||
// /* debug ospf packet all detail. */
|
||||
// r = OSPF_DEBUG_SEND_RECV|OSPF_DEBUG_DETAIL;
|
||||
// for (i = 0; i < 5; i++)
|
||||
// r &= conf_debug_ospf_packet[i] & (OSPF_DEBUG_SEND_RECV|OSPF_DEBUG_DETAIL);
|
||||
// if (r == (OSPF_DEBUG_SEND_RECV|OSPF_DEBUG_DETAIL))
|
||||
// {
|
||||
// vty_out (vty, "debug ospf packet all detail%s", VTY_NEWLINE);
|
||||
// return 1;
|
||||
// }
|
||||
//
|
||||
// /* debug ospf packet all. */
|
||||
// r = OSPF_DEBUG_SEND_RECV;
|
||||
// for (i = 0; i < 5; i++)
|
||||
// r &= conf_debug_ospf_packet[i] & OSPF_DEBUG_SEND_RECV;
|
||||
// if (r == OSPF_DEBUG_SEND_RECV)
|
||||
// {
|
||||
// vty_out (vty, "debug ospf packet all%s", VTY_NEWLINE);
|
||||
// for (i = 0; i < 5; i++)
|
||||
// if (conf_debug_ospf_packet[i] & OSPF_DEBUG_DETAIL)
|
||||
// vty_out (vty, "debug ospf packet %s detail%s",
|
||||
// type_str[i],
|
||||
// VTY_NEWLINE);
|
||||
// return 1;
|
||||
// }
|
||||
//
|
||||
// /* debug ospf packet (hello|dd|ls-request|ls-update|ls-ack)
|
||||
// (send|recv) (detail). */
|
||||
// for (i = 0; i < 5; i++)
|
||||
// {
|
||||
// if (conf_debug_ospf_packet[i] == 0)
|
||||
// continue;
|
||||
//
|
||||
// vty_out (vty, "debug ospf packet %s%s%s",
|
||||
// type_str[i], detail_str[conf_debug_ospf_packet[i]],
|
||||
// VTY_NEWLINE);
|
||||
// write = 1;
|
||||
// }
|
||||
|
||||
return write;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
eigrp_neighbor_packet_queue_sum (struct eigrp_interface *ei)
|
||||
{
|
||||
struct eigrp_neighbor *nbr;
|
||||
struct listnode *node, *nnode;
|
||||
int sum;
|
||||
sum = 0;
|
||||
|
||||
for (ALL_LIST_ELEMENTS (ei->nbrs, node, nnode, nbr))
|
||||
{
|
||||
sum += nbr->retrans_queue->count;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
/*
|
||||
* Expects header to be in host order
|
||||
*/
|
||||
void
|
||||
eigrp_ip_header_dump (struct ip *iph)
|
||||
{
|
||||
/* IP Header dump. */
|
||||
zlog_debug ("ip_v %u", iph->ip_v);
|
||||
zlog_debug ("ip_hl %u", iph->ip_hl);
|
||||
zlog_debug ("ip_tos %u", iph->ip_tos);
|
||||
zlog_debug ("ip_len %u", iph->ip_len);
|
||||
zlog_debug ("ip_id %u", (u_int32_t) iph->ip_id);
|
||||
zlog_debug ("ip_off %u", (u_int32_t) iph->ip_off);
|
||||
zlog_debug ("ip_ttl %u", iph->ip_ttl);
|
||||
zlog_debug ("ip_p %u", iph->ip_p);
|
||||
zlog_debug ("ip_sum 0x%x", (u_int32_t) iph->ip_sum);
|
||||
zlog_debug ("ip_src %s", inet_ntoa (iph->ip_src));
|
||||
zlog_debug ("ip_dst %s", inet_ntoa (iph->ip_dst));
|
||||
}
|
||||
|
||||
/*
|
||||
* Expects header to be in host order
|
||||
*/
|
||||
void
|
||||
eigrp_header_dump (struct eigrp_header *eigrph)
|
||||
{
|
||||
/* EIGRP Header dump. */
|
||||
zlog_debug ("eigrp_version %u", eigrph->version);
|
||||
zlog_debug ("eigrp_opcode %u", eigrph->opcode);
|
||||
zlog_debug ("eigrp_checksum 0x%x", ntohs(eigrph->checksum));
|
||||
zlog_debug ("eigrp_flags 0x%x", ntohl(eigrph->flags));
|
||||
zlog_debug ("eigrp_sequence %u", ntohl(eigrph->sequence));
|
||||
zlog_debug ("eigrp_ack %u", ntohl(eigrph->ack));
|
||||
zlog_debug ("eigrp_vrid %u" , ntohs(eigrph->vrid));
|
||||
zlog_debug ("eigrp_AS %u", ntohs(eigrph->ASNumber));
|
||||
}
|
||||
|
||||
const char *
|
||||
eigrp_if_name_string (struct eigrp_interface *ei)
|
||||
{
|
||||
static char buf[EIGRP_IF_STRING_MAXLEN] = "";
|
||||
|
||||
if (!ei)
|
||||
return "inactive";
|
||||
|
||||
snprintf (buf, EIGRP_IF_STRING_MAXLEN,
|
||||
"%s", ei->ifp->name);
|
||||
return buf;
|
||||
}
|
||||
|
||||
const char *
|
||||
eigrp_topology_ip_string (struct eigrp_prefix_entry *tn)
|
||||
{
|
||||
static char buf[EIGRP_IF_STRING_MAXLEN] = "";
|
||||
u_int32_t ifaddr;
|
||||
|
||||
ifaddr = ntohl (tn->destination_ipv4->prefix.s_addr);
|
||||
snprintf (buf, EIGRP_IF_STRING_MAXLEN,
|
||||
"%u.%u.%u.%u",
|
||||
(ifaddr >> 24) & 0xff, (ifaddr >> 16) & 0xff,
|
||||
(ifaddr >> 8) & 0xff, ifaddr & 0xff);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
eigrp_if_ip_string (struct eigrp_interface *ei)
|
||||
{
|
||||
static char buf[EIGRP_IF_STRING_MAXLEN] = "";
|
||||
u_int32_t ifaddr;
|
||||
|
||||
if (!ei)
|
||||
return "inactive";
|
||||
|
||||
ifaddr = ntohl (ei->address->u.prefix4.s_addr);
|
||||
snprintf (buf, EIGRP_IF_STRING_MAXLEN,
|
||||
"%u.%u.%u.%u",
|
||||
(ifaddr >> 24) & 0xff, (ifaddr >> 16) & 0xff,
|
||||
(ifaddr >> 8) & 0xff, ifaddr & 0xff);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
const char *
|
||||
eigrp_neigh_ip_string (struct eigrp_neighbor *nbr)
|
||||
{
|
||||
static char buf[EIGRP_IF_STRING_MAXLEN] = "";
|
||||
u_int32_t ifaddr;
|
||||
|
||||
ifaddr = ntohl (nbr->src.s_addr);
|
||||
snprintf (buf, EIGRP_IF_STRING_MAXLEN,
|
||||
"%u.%u.%u.%u",
|
||||
(ifaddr >> 24) & 0xff, (ifaddr >> 16) & 0xff,
|
||||
(ifaddr >> 8) & 0xff, ifaddr & 0xff);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void
|
||||
show_ip_eigrp_interface_header (struct vty *vty, struct eigrp *eigrp)
|
||||
{
|
||||
|
||||
vty_out (vty, "%s%s%d%s%s%s %-10s %-10s %-10s %-6s %-12s %-7s %-14s %-12s %-8s %-8s %-8s%s %-39s %-12s %-7s %-14s %-12s %-8s%s",
|
||||
VTY_NEWLINE,
|
||||
"EIGRP interfaces for AS(",eigrp->AS,")",VTY_NEWLINE,VTY_NEWLINE,
|
||||
"Interface", "Bandwidth", "Delay", "Peers", "Xmit Queue", "Mean",
|
||||
"Pacing Time", "Multicast", "Pending", "Hello", "Holdtime",
|
||||
VTY_NEWLINE,"","Un/Reliable","SRTT","Un/Reliable","Flow Timer","Routes",
|
||||
VTY_NEWLINE);
|
||||
}
|
||||
|
||||
void
|
||||
show_ip_eigrp_interface_sub (struct vty *vty, struct eigrp *eigrp,
|
||||
struct eigrp_interface *ei)
|
||||
{
|
||||
vty_out (vty, "%-11s ", eigrp_if_name_string (ei));
|
||||
vty_out (vty, "%-11u",IF_DEF_PARAMS (ei->ifp)->bandwidth);
|
||||
vty_out (vty, "%-11u",IF_DEF_PARAMS (ei->ifp)->delay);
|
||||
vty_out (vty, "%-7u", ei->nbrs->count);
|
||||
vty_out (vty, "%u %c %-10u",0,'/',eigrp_neighbor_packet_queue_sum (ei));
|
||||
vty_out (vty, "%-7u %-14u %-12u %-8u",0,0,0,0);
|
||||
vty_out (vty, "%-8u %-8u %s",IF_DEF_PARAMS (ei->ifp)->v_hello,IF_DEF_PARAMS (ei->ifp)->v_wait,VTY_NEWLINE);
|
||||
}
|
||||
|
||||
void
|
||||
show_ip_eigrp_interface_detail (struct vty *vty, struct eigrp *eigrp,
|
||||
struct eigrp_interface *ei)
|
||||
{
|
||||
vty_out (vty, "%-2s %s %d %-3s %s","","Hello interval is ",0," sec",VTY_NEWLINE);
|
||||
vty_out (vty, "%-2s %s %s %s","","Next xmit serial","<none>",VTY_NEWLINE);
|
||||
vty_out (vty, "%-2s %s %d %s %d %s %d %s %d %s","","Un/reliable mcasts: ",0,"/",0,"Un/reliable ucasts: ",0,"/",0,VTY_NEWLINE);
|
||||
vty_out (vty, "%-2s %s %d %s %d %s %d %s","","Mcast exceptions: ",0," CR packets: ",0," ACKs supressed: ",0,VTY_NEWLINE);
|
||||
vty_out (vty, "%-2s %s %d %s %d %s","","Retransmissions sent: ",0,"Out-of-sequence rcvd: ",0,VTY_NEWLINE);
|
||||
vty_out (vty, "%-2s %s %s %s %s","","Authentication mode is ","not","set",VTY_NEWLINE);
|
||||
vty_out (vty, "%-2s %s %s","","Use multicast",VTY_NEWLINE);
|
||||
}
|
||||
|
||||
void
|
||||
show_ip_eigrp_neighbor_header (struct vty *vty, struct eigrp *eigrp)
|
||||
{
|
||||
vty_out (vty, "%s%s%d%s%s%s%-3s %-17s %-20s %-6s %-8s %-6s %-5s %-5s %-5s%s %-41s %-6s %-8s %-6s %-4s %-6s %-5s %s",
|
||||
VTY_NEWLINE,
|
||||
"EIGRP neighbors for AS(",eigrp->AS,")",VTY_NEWLINE,VTY_NEWLINE,
|
||||
"H", "Address", "Interface", "Hold", "Uptime",
|
||||
"SRTT", "RTO", "Q", "Seq", VTY_NEWLINE
|
||||
,"","(sec)","","(ms)","","Cnt","Num", VTY_NEWLINE);
|
||||
}
|
||||
|
||||
void
|
||||
show_ip_eigrp_neighbor_sub (struct vty *vty, struct eigrp_neighbor *nbr,
|
||||
int detail)
|
||||
{
|
||||
|
||||
vty_out (vty, "%-3u %-17s %-21s",0,eigrp_neigh_ip_string (nbr),eigrp_if_name_string (nbr->ei));
|
||||
vty_out (vty,"%-7lu",thread_timer_remain_second (nbr->t_holddown));
|
||||
vty_out (vty,"%-8u %-6u %-5u",0,0,EIGRP_PACKET_RETRANS_TIME);
|
||||
vty_out (vty,"%-7lu",nbr->retrans_queue->count);
|
||||
vty_out (vty,"%u%s",nbr->recv_sequence_number,VTY_NEWLINE);
|
||||
|
||||
|
||||
if (detail)
|
||||
{
|
||||
vty_out(vty," Version %u.%u/%u.%u",
|
||||
nbr->os_rel_major, nbr->os_rel_minor,
|
||||
nbr->tlv_rel_major, nbr->tlv_rel_minor);
|
||||
vty_out(vty,", Retrans: %lu, Retries: %lu",
|
||||
nbr->retrans_queue->count, 0UL);
|
||||
vty_out(vty,", %s%s", eigrp_nbr_state_str(nbr), VTY_NEWLINE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print standard header for show EIGRP topology output
|
||||
*/
|
||||
void
|
||||
show_ip_eigrp_topology_header (struct vty *vty, struct eigrp *eigrp)
|
||||
{
|
||||
struct in_addr router_id;
|
||||
router_id.s_addr = htonl(eigrp->router_id);
|
||||
|
||||
vty_out (vty, "%s%s%d%s%s%s%s%s%s%s%s%s%s%s",
|
||||
VTY_NEWLINE,
|
||||
"EIGRP Topology Table for AS(", eigrp->AS, ")/ID(", inet_ntoa(router_id), ")", VTY_NEWLINE,VTY_NEWLINE,
|
||||
"Codes: P - Passive, A - Active, U - Update, Q - Query, "
|
||||
"R - Reply", VTY_NEWLINE ," ","r - reply Status, s - sia Status",VTY_NEWLINE,VTY_NEWLINE);
|
||||
}
|
||||
|
||||
void
|
||||
show_ip_eigrp_prefix_entry (struct vty *vty, struct eigrp_prefix_entry *tn)
|
||||
{
|
||||
vty_out (vty, "%-3c",(tn->state > 0) ? 'A' : 'P');
|
||||
vty_out (vty, "%s/%u, ",inet_ntoa (tn->destination_ipv4->prefix),tn->destination_ipv4->prefixlen);
|
||||
vty_out (vty, "%u successors, ",eigrp_topology_get_successor(tn)->count);
|
||||
vty_out (vty, "FD is %u, serno: %lu %s",tn->fdistance, tn->serno, VTY_NEWLINE);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
show_ip_eigrp_neighbor_entry (struct vty *vty, struct eigrp *eigrp, struct eigrp_neighbor_entry *te)
|
||||
{
|
||||
if (te->adv_router == eigrp->neighbor_self)
|
||||
vty_out (vty, "%-7s%s, %s%s"," ","via Connected",eigrp_if_name_string (te->ei), VTY_NEWLINE);
|
||||
else
|
||||
{
|
||||
vty_out (vty, "%-7s%s%s (%u/%u), %s%s"," ","via ",inet_ntoa (te->adv_router->src),te->distance, te->reported_distance, eigrp_if_name_string (te->ei), VTY_NEWLINE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DEFUN (show_debugging_eigrp,
|
||||
show_debugging_eigrp_cmd,
|
||||
"show debugging eigrp",
|
||||
SHOW_STR
|
||||
DEBUG_STR
|
||||
EIGRP_STR)
|
||||
{
|
||||
int i;
|
||||
|
||||
vty_out (vty, "EIGRP debugging status:%s", VTY_NEWLINE);
|
||||
|
||||
/* Show debug status for events. */
|
||||
if (IS_DEBUG_EIGRP(event,EVENT))
|
||||
vty_out (vty, " EIGRP event debugging is on%s", VTY_NEWLINE);
|
||||
|
||||
/* Show debug status for EIGRP Packets. */
|
||||
for (i = 0; i < 11 ; i++)
|
||||
{
|
||||
if (i == 8)
|
||||
continue;
|
||||
|
||||
if (IS_DEBUG_EIGRP_PACKET (i, SEND) && IS_DEBUG_EIGRP_PACKET (i, RECV))
|
||||
{
|
||||
vty_out (vty, " EIGRP packet %s%s debugging is on%s",
|
||||
LOOKUP (eigrp_packet_type_str, i + 1),
|
||||
IS_DEBUG_EIGRP_PACKET (i, PACKET_DETAIL) ? " detail" : "",
|
||||
VTY_NEWLINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IS_DEBUG_EIGRP_PACKET (i, SEND))
|
||||
vty_out (vty, " EIGRP packet %s send%s debugging is on%s",
|
||||
LOOKUP (eigrp_packet_type_str, i + 1),
|
||||
IS_DEBUG_EIGRP_PACKET (i, PACKET_DETAIL) ? " detail" : "",
|
||||
VTY_NEWLINE);
|
||||
if (IS_DEBUG_EIGRP_PACKET (i, RECV))
|
||||
vty_out (vty, " EIGRP packet %s receive%s debugging is on%s",
|
||||
LOOKUP (eigrp_packet_type_str, i + 1),
|
||||
IS_DEBUG_EIGRP_PACKET (i, PACKET_DETAIL) ? " detail" : "",
|
||||
VTY_NEWLINE);
|
||||
}
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
[no] debug eigrp packet (hello|dd|ls-request|ls-update|ls-ack|all)
|
||||
[send|recv [detail]]
|
||||
*/
|
||||
|
||||
DEFUN (debug_eigrp_transmit,
|
||||
debug_eigrp_transmit_cmd,
|
||||
"debug eigrp transmit <send|recv|all> [detail]",
|
||||
DEBUG_STR
|
||||
EIGRP_STR
|
||||
"EIGRP transmission events\n"
|
||||
"packet sent\n"
|
||||
"packet received\n"
|
||||
"all packets\n"
|
||||
"Detailed Information\n")
|
||||
{
|
||||
int flag = 0;
|
||||
int idx = 2;
|
||||
|
||||
/* send or recv. */
|
||||
if (argv_find (argv, argc, "send", &idx))
|
||||
flag = EIGRP_DEBUG_SEND;
|
||||
else if (argv_find (argv, argc, "recv", &idx))
|
||||
flag = EIGRP_DEBUG_RECV;
|
||||
else if (argv_find (argv, argc, "all", &idx) == 0)
|
||||
flag = EIGRP_DEBUG_SEND_RECV;
|
||||
|
||||
/* detail option */
|
||||
if (argv_find (argv, argc, "detail", &idx) == 0)
|
||||
flag = EIGRP_DEBUG_PACKET_DETAIL;
|
||||
|
||||
if (vty->node == CONFIG_NODE)
|
||||
DEBUG_TRANSMIT_ON (0, flag);
|
||||
else
|
||||
TERM_DEBUG_TRANSMIT_ON (0, flag);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_debug_eigrp_transmit,
|
||||
no_debug_eigrp_transmit_cmd,
|
||||
"no debug eigrp transmit <send|recv|all> [detail]",
|
||||
NO_STR
|
||||
UNDEBUG_STR
|
||||
EIGRP_STR
|
||||
"EIGRP transmission events\n"
|
||||
"packet sent\n"
|
||||
"packet received\n"
|
||||
"all packets\n"
|
||||
"Detailed Information\n")
|
||||
{
|
||||
int flag = 0;
|
||||
int idx = 3;
|
||||
|
||||
/* send or recv. */
|
||||
if (argv_find (argv, argc, "send", &idx) == 0)
|
||||
flag = EIGRP_DEBUG_SEND;
|
||||
else if (argv_find (argv, argc, "recv", &idx) == 0)
|
||||
flag = EIGRP_DEBUG_RECV;
|
||||
else if (argv_find (argv, argc, "all", &idx) == 0)
|
||||
flag = EIGRP_DEBUG_SEND_RECV;
|
||||
|
||||
/* detail option */
|
||||
if (argv_find (argv, argc, "detail", &idx) == 0)
|
||||
flag = EIGRP_DEBUG_PACKET_DETAIL;
|
||||
|
||||
if (vty->node == CONFIG_NODE)
|
||||
DEBUG_TRANSMIT_OFF (0, flag);
|
||||
else
|
||||
TERM_DEBUG_TRANSMIT_OFF (0, flag);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (debug_eigrp_packets,
|
||||
debug_eigrp_packets_all_cmd,
|
||||
"debug eigrp packets <siaquery|siareply|ack|hello|probe|query|reply|request|retry|stub|terse|update|all> [send|receive] [detail]",
|
||||
DEBUG_STR
|
||||
EIGRP_STR
|
||||
"EIGRP packets\n"
|
||||
"EIGRP SIA-Query packets\n"
|
||||
"EIGRP SIA-Reply packets\n"
|
||||
"EIGRP ack packets\n"
|
||||
"EIGRP hello packets\n"
|
||||
"EIGRP probe packets\n"
|
||||
"EIGRP query packets\n"
|
||||
"EIGRP reply packets\n"
|
||||
"EIGRP request packets\n"
|
||||
"EIGRP retransmissions\n"
|
||||
"EIGRP stub packets\n"
|
||||
"Display all EIGRP packets except Hellos\n"
|
||||
"EIGRP update packets\n"
|
||||
"Display all EIGRP packets\n"
|
||||
"Send Packets\n"
|
||||
"Receive Packets\n"
|
||||
"Detail Information\n")
|
||||
{
|
||||
int type = 0;
|
||||
int flag = 0;
|
||||
int i;
|
||||
int idx = 0;
|
||||
|
||||
/* Check packet type. */
|
||||
if (argv_find (argv, argc, "hello", &idx) == 0)
|
||||
type = EIGRP_DEBUG_HELLO;
|
||||
if (argv_find (argv, argc, "update", &idx) == 0)
|
||||
type = EIGRP_DEBUG_UPDATE;
|
||||
if (argv_find (argv, argc, "query", &idx) == 0)
|
||||
type = EIGRP_DEBUG_QUERY;
|
||||
if (argv_find (argv, argc, "ack", &idx) == 0)
|
||||
type = EIGRP_DEBUG_ACK;
|
||||
if (argv_find (argv, argc, "probe", &idx) == 0)
|
||||
type = EIGRP_DEBUG_PROBE;
|
||||
if (argv_find (argv, argc, "stub", &idx) == 0)
|
||||
type = EIGRP_DEBUG_STUB;
|
||||
if (argv_find (argv, argc, "reply", &idx) == 0)
|
||||
type = EIGRP_DEBUG_REPLY;
|
||||
if (argv_find (argv, argc, "request", &idx) == 0)
|
||||
type = EIGRP_DEBUG_REQUEST;
|
||||
if (argv_find (argv, argc, "siaquery", &idx) == 0)
|
||||
type = EIGRP_DEBUG_SIAQUERY;
|
||||
if (argv_find (argv, argc, "siareply", &idx) == 0)
|
||||
type = EIGRP_DEBUG_SIAREPLY;
|
||||
if (argv_find (argv, argc, "all", &idx) == 0)
|
||||
type = EIGRP_DEBUG_PACKETS_ALL;
|
||||
|
||||
|
||||
/* All packet types, both send and recv. */
|
||||
flag = EIGRP_DEBUG_SEND_RECV;
|
||||
|
||||
/* send or recv. */
|
||||
if (argv_find (argv, argc, "s", &idx) == 0)
|
||||
flag = EIGRP_DEBUG_SEND;
|
||||
else if (argv_find (argv, argc, "r", &idx) == 0)
|
||||
flag = EIGRP_DEBUG_RECV;
|
||||
|
||||
/* detail. */
|
||||
if (argv_find (argv, argc, "detail", &idx) == 0)
|
||||
flag |= EIGRP_DEBUG_PACKET_DETAIL;
|
||||
|
||||
for (i = 0; i < 11; i++)
|
||||
if (type & (0x01 << i))
|
||||
{
|
||||
if (vty->node == CONFIG_NODE)
|
||||
DEBUG_PACKET_ON (i, flag);
|
||||
else
|
||||
TERM_DEBUG_PACKET_ON (i, flag);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_debug_eigrp_packets,
|
||||
no_debug_eigrp_packets_all_cmd,
|
||||
"no debug eigrp packets <siaquery|siareply|ack|hello|probe|query|reply|request|retry|stub|terse|update|all> [send|receive] [detail]",
|
||||
NO_STR
|
||||
UNDEBUG_STR
|
||||
EIGRP_STR
|
||||
"EIGRP packets\n"
|
||||
"EIGRP SIA-Query packets\n"
|
||||
"EIGRP SIA-Reply packets\n"
|
||||
"EIGRP ack packets\n"
|
||||
"EIGRP hello packets\n"
|
||||
"EIGRP probe packets\n"
|
||||
"EIGRP query packets\n"
|
||||
"EIGRP reply packets\n"
|
||||
"EIGRP request packets\n"
|
||||
"EIGRP retransmissions\n"
|
||||
"EIGRP stub packets\n"
|
||||
"Display all EIGRP packets except Hellos\n"
|
||||
"EIGRP update packets\n"
|
||||
"Display all EIGRP packets\n"
|
||||
"Send Packets\n"
|
||||
"Receive Packets\n"
|
||||
"Detailed Information\n")
|
||||
{
|
||||
int type = 0;
|
||||
int flag = 0;
|
||||
int i;
|
||||
int idx = 0;
|
||||
|
||||
/* Check packet type. */
|
||||
if (argv_find (argv, argc, "hello", &idx) == 0)
|
||||
type = EIGRP_DEBUG_HELLO;
|
||||
if (argv_find (argv, argc, "update", &idx) == 0)
|
||||
type = EIGRP_DEBUG_UPDATE;
|
||||
if (argv_find (argv, argc, "query", &idx) == 0)
|
||||
type = EIGRP_DEBUG_QUERY;
|
||||
if (argv_find (argv, argc, "ack", &idx) == 0)
|
||||
type = EIGRP_DEBUG_ACK;
|
||||
if (argv_find (argv, argc, "probe", &idx) == 0)
|
||||
type = EIGRP_DEBUG_PROBE;
|
||||
if (argv_find (argv, argc, "stub", &idx) == 0)
|
||||
type = EIGRP_DEBUG_STUB;
|
||||
if (argv_find (argv, argc, "reply", &idx) == 0)
|
||||
type = EIGRP_DEBUG_REPLY;
|
||||
if (argv_find (argv, argc, "request", &idx) == 0)
|
||||
type = EIGRP_DEBUG_REQUEST;
|
||||
if (argv_find (argv, argc, "siaquery", &idx) == 0)
|
||||
type = EIGRP_DEBUG_SIAQUERY;
|
||||
if (argv_find (argv, argc, "siareply", &idx) == 0)
|
||||
type = EIGRP_DEBUG_SIAREPLY;
|
||||
|
||||
/* Default, both send and recv. */
|
||||
flag = EIGRP_DEBUG_SEND_RECV;
|
||||
|
||||
/* send or recv. */
|
||||
if (argv_find (argv, argc, "send", &idx) == 0)
|
||||
flag = EIGRP_DEBUG_SEND;
|
||||
else if (argv_find (argv, argc, "reply", &idx) == 0)
|
||||
flag = EIGRP_DEBUG_RECV;
|
||||
|
||||
/* detail. */
|
||||
if (argv_find (argv, argc, "detail", &idx) == 0)
|
||||
flag |= EIGRP_DEBUG_PACKET_DETAIL;
|
||||
|
||||
for (i = 0; i < 11; i++)
|
||||
if (type & (0x01 << i))
|
||||
{
|
||||
if (vty->node == CONFIG_NODE)
|
||||
DEBUG_PACKET_OFF (i, flag);
|
||||
else
|
||||
TERM_DEBUG_PACKET_OFF (i, flag);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/* Debug node. */
|
||||
static struct cmd_node eigrp_debug_node =
|
||||
{
|
||||
DEBUG_NODE,
|
||||
"",
|
||||
1 /* VTYSH */
|
||||
};
|
||||
|
||||
/* Initialize debug commands. */
|
||||
void
|
||||
eigrp_debug_init ()
|
||||
{
|
||||
install_node (&eigrp_debug_node, config_write_debug);
|
||||
|
||||
install_element (ENABLE_NODE, &show_debugging_eigrp_cmd);
|
||||
install_element (ENABLE_NODE, &debug_eigrp_packets_all_cmd);
|
||||
install_element (ENABLE_NODE, &no_debug_eigrp_packets_all_cmd);
|
||||
install_element (ENABLE_NODE, &debug_eigrp_transmit_cmd);
|
||||
install_element (ENABLE_NODE, &no_debug_eigrp_transmit_cmd);
|
||||
|
||||
install_element (CONFIG_NODE, &show_debugging_eigrp_cmd);
|
||||
install_element (CONFIG_NODE, &debug_eigrp_packets_all_cmd);
|
||||
install_element (CONFIG_NODE, &no_debug_eigrp_packets_all_cmd);
|
||||
install_element (CONFIG_NODE, &no_debug_eigrp_transmit_cmd);
|
||||
}
|
||||
|
||||
|
165
eigrpd/eigrp_dump.h
Normal file
165
eigrpd/eigrp_dump.h
Normal file
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* EIGRP Dump Functions and Debbuging.
|
||||
* Copyright (C) 2013-2014
|
||||
* Authors:
|
||||
* Donnie Savage
|
||||
* Jan Janovic
|
||||
* Matej Perina
|
||||
* Peter Orsag
|
||||
* Peter Paluch
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _ZEBRA_EIGRPD_DUMP_H_
|
||||
#define _ZEBRA_EIGRPD_DUMP_H_
|
||||
|
||||
#define EIGRP_TIME_DUMP_SIZE 16
|
||||
|
||||
/* general debug flags */
|
||||
extern unsigned long term_debug_eigrp;
|
||||
#define EIGRP_DEBUG_EVENT 0x01
|
||||
#define EIGRP_DEBUG_DETAIL 0x02
|
||||
#define EIGRP_DEBUG_TIMERS 0x04
|
||||
|
||||
/* neighbor debug flags */
|
||||
extern unsigned long term_debug_eigrp_nei;
|
||||
#define EIGRP_DEBUG_NEI 0x01
|
||||
|
||||
/* packet debug flags */
|
||||
extern unsigned long term_debug_eigrp_packet[];
|
||||
#define EIGRP_DEBUG_UPDATE 0x01
|
||||
#define EIGRP_DEBUG_REQUEST 0x02
|
||||
#define EIGRP_DEBUG_QUERY 0x04
|
||||
#define EIGRP_DEBUG_REPLY 0x08
|
||||
#define EIGRP_DEBUG_HELLO 0x10
|
||||
#define EIGRP_DEBUG_PROBE 0x40
|
||||
#define EIGRP_DEBUG_ACK 0x80
|
||||
#define EIGRP_DEBUG_SIAQUERY 0x200
|
||||
#define EIGRP_DEBUG_SIAREPLY 0x400
|
||||
#define EIGRP_DEBUG_STUB 0x800
|
||||
#define EIGRP_DEBUG_PACKETS_ALL 0xfff
|
||||
|
||||
extern unsigned long term_debug_eigrp_transmit;
|
||||
#define EIGRP_DEBUG_SEND 0x01
|
||||
#define EIGRP_DEBUG_RECV 0x02
|
||||
#define EIGRP_DEBUG_SEND_RECV 0x03
|
||||
#define EIGRP_DEBUG_PACKET_DETAIL 0x04
|
||||
|
||||
/* zebra debug flags */
|
||||
extern unsigned long term_debug_eigrp_zebra;
|
||||
#define EIGRP_DEBUG_ZEBRA_INTERFACE 0x01
|
||||
#define EIGRP_DEBUG_ZEBRA_REDISTRIBUTE 0x02
|
||||
#define EIGRP_DEBUG_ZEBRA 0x03
|
||||
|
||||
/* Macro for setting debug option. */
|
||||
#define CONF_DEBUG_NEI_ON(a, b) conf_debug_eigrp_nei[a] |= (b)
|
||||
#define CONF_DEBUG_NEI_OFF(a, b) conf_debug_eigrp_nei[a] &= ~(b)
|
||||
#define TERM_DEBUG_NEI_ON(a, b) term_debug_eigrp_nei[a] |= (b)
|
||||
#define TERM_DEBUG_NEI_OFF(a, b) term_debug_eigrp_nei[a] &= ~(b)
|
||||
#define DEBUG_NEI_ON(a, b) \
|
||||
do { \
|
||||
CONF_DEBUG_NEI_ON(a, b); \
|
||||
TERM_DEBUG_NEI_ON(a, b); \
|
||||
} while (0)
|
||||
#define DEBUG_NEI_OFF(a, b) \
|
||||
do { \
|
||||
CONF_DEBUG_NEI_OFF(a, b); \
|
||||
TERM_DEBUG_NEI_OFF(a, b); \
|
||||
} while (0)
|
||||
|
||||
#define CONF_DEBUG_PACKET_ON(a, b) conf_debug_eigrp_packet[a] |= (b)
|
||||
#define CONF_DEBUG_PACKET_OFF(a, b) conf_debug_eigrp_packet[a] &= ~(b)
|
||||
#define TERM_DEBUG_PACKET_ON(a, b) term_debug_eigrp_packet[a] |= (b)
|
||||
#define TERM_DEBUG_PACKET_OFF(a, b) term_debug_eigrp_packet[a] &= ~(b)
|
||||
#define DEBUG_PACKET_ON(a, b) \
|
||||
do { \
|
||||
CONF_DEBUG_PACKET_ON(a, b); \
|
||||
TERM_DEBUG_PACKET_ON(a, b); \
|
||||
} while (0)
|
||||
#define DEBUG_PACKET_OFF(a, b) \
|
||||
do { \
|
||||
CONF_DEBUG_PACKET_OFF(a, b); \
|
||||
TERM_DEBUG_PACKET_OFF(a, b); \
|
||||
} while (0)
|
||||
|
||||
#define CONF_DEBUG_TRANSMIT_ON(a, b) conf_debug_eigrp_transmit |= (b)
|
||||
#define CONF_DEBUG_TRANSMIT_OFF(a, b) conf_debug_eigrp_transmit &= ~(b)
|
||||
#define TERM_DEBUG_TRANSMIT_ON(a, b) term_debug_eigrp_transmit |= (b)
|
||||
#define TERM_DEBUG_TRANSMIT_OFF(a, b) term_debug_eigrp_transmit &= ~(b)
|
||||
#define DEBUG_TRANSMIT_ON(a, b) \
|
||||
do { \
|
||||
CONF_DEBUG_TRANSMIT_ON(a, b); \
|
||||
TERM_DEBUG_TRANSMIT_ON(a, b); \
|
||||
} while (0)
|
||||
#define DEBUG_TRANSMIT_OFF(a, b) \
|
||||
do { \
|
||||
CONF_DEBUG_TRANSMIT_OFF(a, b); \
|
||||
TERM_DEBUG_TRANSMIT_OFF(a, b); \
|
||||
} while (0)
|
||||
|
||||
#define CONF_DEBUG_ON(a, b) conf_debug_eigrp_ ## a |= (EIGRP_DEBUG_ ## b)
|
||||
#define CONF_DEBUG_OFF(a, b) conf_debug_eigrp_ ## a &= ~(EIGRP_DEBUG_ ## b)
|
||||
#define TERM_DEBUG_ON(a, b) term_debug_eigrp_ ## a |= (EIGRP_DEBUG_ ## b)
|
||||
#define TERM_DEBUG_OFF(a, b) term_debug_eigrp_ ## a &= ~(EIGRP_DEBUG_ ## b)
|
||||
#define DEBUG_ON(a, b) \
|
||||
do { \
|
||||
CONF_DEBUG_ON(a, b); \
|
||||
TERM_DEBUG_ON(a, b); \
|
||||
} while (0)
|
||||
#define DEBUG_OFF(a, b) \
|
||||
do { \
|
||||
CONF_DEBUG_OFF(a, b); \
|
||||
TERM_DEBUG_OFF(a, b); \
|
||||
} while (0)
|
||||
|
||||
/* Macro for checking debug option. */
|
||||
#define IS_DEBUG_EIGRP_PACKET(a, b) \
|
||||
(term_debug_eigrp_packet[a] & EIGRP_DEBUG_ ## b)
|
||||
#define IS_DEBUG_EIGRP_TRANSMIT(a, b) \
|
||||
(term_debug_eigrp_transmit & EIGRP_DEBUG_ ## b)
|
||||
#define IS_DEBUG_EIGRP_NEI(a, b) \
|
||||
(term_debug_eigrp_nei & EIGRP_DEBUG_ ## b)
|
||||
#define IS_DEBUG_EIGRP(a, b) \
|
||||
(term_debug_eigrp & EIGRP_DEBUG_ ## b)
|
||||
#define IS_DEBUG_EIGRP_EVENT IS_DEBUG_EIGRP(event, EVENT)
|
||||
|
||||
|
||||
/* Prototypes. */
|
||||
extern const char *eigrp_if_name_string (struct eigrp_interface *);
|
||||
extern const char *eigrp_if_ip_string (struct eigrp_interface *);
|
||||
extern const char *eigrp_neigh_ip_string (struct eigrp_neighbor *);
|
||||
extern const char *eigrp_topology_ip_string (struct eigrp_prefix_entry *);
|
||||
|
||||
extern void eigrp_ip_header_dump(struct ip *);
|
||||
extern void eigrp_header_dump(struct eigrp_header *);
|
||||
|
||||
extern void show_ip_eigrp_interface_header (struct vty *, struct eigrp *);
|
||||
extern void show_ip_eigrp_neighbor_header (struct vty *, struct eigrp *);
|
||||
extern void show_ip_eigrp_topology_header (struct vty *, struct eigrp *);
|
||||
extern void show_ip_eigrp_interface_detail (struct vty *, struct eigrp *,
|
||||
struct eigrp_interface *);
|
||||
extern void show_ip_eigrp_interface_sub (struct vty *, struct eigrp *,
|
||||
struct eigrp_interface *);
|
||||
extern void show_ip_eigrp_neighbor_sub (struct vty *, struct eigrp_neighbor *, int);
|
||||
extern void show_ip_eigrp_prefix_entry (struct vty *, struct eigrp_prefix_entry *);
|
||||
extern void show_ip_eigrp_neighbor_entry (struct vty *, struct eigrp *, struct eigrp_neighbor_entry *);
|
||||
|
||||
extern void eigrp_debug_init (void);
|
||||
|
||||
#endif /* _ZEBRA_EIGRPD_DUMP_H_ */
|
395
eigrpd/eigrp_filter.c
Normal file
395
eigrpd/eigrp_filter.c
Normal file
|
@ -0,0 +1,395 @@
|
|||
/*
|
||||
* EIGRP Filter Functions.
|
||||
* Copyright (C) 2013-2015
|
||||
* Authors:
|
||||
* Donnie Savage
|
||||
* Jan Janovic
|
||||
* Matej Perina
|
||||
* Peter Orsag
|
||||
* Peter Paluch
|
||||
* Frantisek Gazo
|
||||
* Tomas Hvorkovy
|
||||
* Martin Kontsek
|
||||
* Lukas Koribsky
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#include "if.h"
|
||||
#include "command.h"
|
||||
#include "prefix.h"
|
||||
#include "table.h"
|
||||
#include "thread.h"
|
||||
#include "memory.h"
|
||||
#include "log.h"
|
||||
#include "stream.h"
|
||||
#include "filter.h"
|
||||
#include "sockunion.h"
|
||||
#include "sockopt.h"
|
||||
#include "routemap.h"
|
||||
#include "if_rmap.h"
|
||||
#include "plist.h"
|
||||
#include "distribute.h"
|
||||
#include "md5.h"
|
||||
#include "keychain.h"
|
||||
#include "privs.h"
|
||||
#include "vrf.h"
|
||||
|
||||
#include "eigrpd/eigrp_structs.h"
|
||||
#include "eigrpd/eigrpd.h"
|
||||
#include "eigrpd/eigrp_const.h"
|
||||
#include "eigrpd/eigrp_filter.h"
|
||||
#include "eigrpd/eigrp_packet.h"
|
||||
#include "eigrpd/eigrp_memory.h"
|
||||
|
||||
/*
|
||||
* Distribute-list update functions.
|
||||
*/
|
||||
void
|
||||
eigrp_distribute_update (struct distribute *dist)
|
||||
{
|
||||
struct interface *ifp;
|
||||
struct eigrp_interface *ei = NULL;
|
||||
struct access_list *alist;
|
||||
struct prefix_list *plist;
|
||||
//struct route_map *routemap;
|
||||
struct eigrp *e;
|
||||
|
||||
/* if no interface address is present, set list to eigrp process struct */
|
||||
e = eigrp_lookup();
|
||||
|
||||
/* Check if distribute-list was set for process or interface */
|
||||
if (! dist->ifname)
|
||||
{
|
||||
/* access list IN for whole process */
|
||||
if (dist->list[DISTRIBUTE_V4_IN])
|
||||
{
|
||||
alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_V4_IN]);
|
||||
zlog_info("<DEBUG DISTRIBUTE ACL IN FOUND: %s",alist->name);
|
||||
if (alist)
|
||||
e->list[EIGRP_FILTER_IN] = alist;
|
||||
else
|
||||
e->list[EIGRP_FILTER_IN] = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
e->list[EIGRP_FILTER_IN] = NULL;
|
||||
}
|
||||
|
||||
/* access list OUT for whole process */
|
||||
if (dist->list[DISTRIBUTE_V4_OUT])
|
||||
{
|
||||
zlog_info("<DEBUG DISTRIBUTE ACL OUT FOUND: %s",dist->list[DISTRIBUTE_V4_OUT]);
|
||||
alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_V4_OUT]);
|
||||
if (alist)
|
||||
e->list[EIGRP_FILTER_OUT] = alist;
|
||||
else
|
||||
e->list[EIGRP_FILTER_OUT] = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
e->list[EIGRP_FILTER_OUT] = NULL;
|
||||
}
|
||||
|
||||
/* PREFIX_LIST IN for process */
|
||||
if (dist->prefix[DISTRIBUTE_V4_IN])
|
||||
{
|
||||
zlog_info("<DEBUG DISTRIBUTE PREFIX IN FOUND: %s",dist->prefix[DISTRIBUTE_V4_IN]);
|
||||
plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_V4_IN]);
|
||||
if (plist)
|
||||
{
|
||||
e->prefix[EIGRP_FILTER_IN] = plist;
|
||||
}
|
||||
else
|
||||
e->prefix[EIGRP_FILTER_IN] = NULL;
|
||||
} else
|
||||
e->prefix[EIGRP_FILTER_IN] = NULL;
|
||||
|
||||
/* PREFIX_LIST OUT for process */
|
||||
if (dist->prefix[DISTRIBUTE_V4_OUT])
|
||||
{
|
||||
zlog_info("<DEBUG DISTRIBUTE PREFIX OUT FOUND: %s",dist->prefix[DISTRIBUTE_V4_OUT]);
|
||||
plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_V4_OUT]);
|
||||
if (plist)
|
||||
{
|
||||
e->prefix[EIGRP_FILTER_OUT] = plist;
|
||||
|
||||
}
|
||||
else
|
||||
e->prefix[EIGRP_FILTER_OUT] = NULL;
|
||||
}
|
||||
else
|
||||
e->prefix[EIGRP_FILTER_OUT] = NULL;
|
||||
|
||||
//This is commented out, because the distribute.[ch] code
|
||||
//changes looked poorly written from first glance
|
||||
//commit was 133bdf2d
|
||||
//TODO: DBS
|
||||
#if 0
|
||||
/* route-map IN for whole process */
|
||||
if (dist->route[DISTRIBUTE_V4_IN])
|
||||
{
|
||||
routemap = route_map_lookup_by_name (dist->route[DISTRIBUTE_V4_IN]);
|
||||
if (routemap)
|
||||
e->routemap[EIGRP_FILTER_IN] = routemap;
|
||||
else
|
||||
e->routemap[EIGRP_FILTER_IN] = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
e->routemap[EIGRP_FILTER_IN] = NULL;
|
||||
}
|
||||
|
||||
/* route-map OUT for whole process */
|
||||
if (dist->route[DISTRIBUTE_V4_OUT])
|
||||
{
|
||||
routemap = route_map_lookup_by_name (dist->route[DISTRIBUTE_V4_OUT]);
|
||||
if (routemap)
|
||||
e->routemap[EIGRP_FILTER_OUT] = routemap;
|
||||
else
|
||||
e->routemap[EIGRP_FILTER_OUT] = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
e->routemap[EIGRP_FILTER_OUT] = NULL;
|
||||
}
|
||||
#endif
|
||||
//TODO: check Graceful restart after 10sec
|
||||
|
||||
/* check if there is already GR scheduled */
|
||||
if(e->t_distribute != NULL)
|
||||
{
|
||||
/* if is, cancel schedule */
|
||||
thread_cancel(e->t_distribute);
|
||||
}
|
||||
/* schedule Graceful restart for whole process in 10sec */
|
||||
e->t_distribute = thread_add_timer(master, eigrp_distribute_timer_process, e,(10));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ifp = if_lookup_by_name (dist->ifname);
|
||||
if (ifp == NULL)
|
||||
return;
|
||||
|
||||
zlog_info("<DEBUG ACL 2");
|
||||
|
||||
/*struct eigrp_if_info * info = ifp->info;
|
||||
ei = info->eigrp_interface;*/
|
||||
struct listnode *node, *nnode;
|
||||
struct eigrp_interface *ei2;
|
||||
/* Find proper interface */
|
||||
for (ALL_LIST_ELEMENTS (e->eiflist, node, nnode, ei2))
|
||||
{
|
||||
if(strcmp(ei2->ifp->name,ifp->name) == 0){
|
||||
ei = ei2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(ei == NULL)
|
||||
{
|
||||
zlog_info("Not Found eigrp interface %s",ifp->name);
|
||||
}
|
||||
|
||||
/* Access-list for interface in */
|
||||
if (dist->list[DISTRIBUTE_V4_IN])
|
||||
{
|
||||
zlog_info("<DEBUG ACL in");
|
||||
alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_V4_IN]);
|
||||
if (alist){
|
||||
ei->list[EIGRP_FILTER_IN] = alist;
|
||||
}
|
||||
else
|
||||
ei->list[EIGRP_FILTER_IN] = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
ei->list[EIGRP_FILTER_IN] = NULL;
|
||||
}
|
||||
|
||||
/* Access-list for interface in */
|
||||
if (dist->list[DISTRIBUTE_V4_OUT])
|
||||
{
|
||||
alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_V4_OUT]);
|
||||
if (alist)
|
||||
ei->list[EIGRP_FILTER_OUT] = alist;
|
||||
else
|
||||
ei->list[EIGRP_FILTER_OUT] = NULL;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ei->list[EIGRP_FILTER_OUT] = NULL;
|
||||
zlog_info("<DEBUG ACL out else");
|
||||
}
|
||||
|
||||
/* Prefix-list for interface in */
|
||||
if (dist->prefix[DISTRIBUTE_V4_IN])
|
||||
{
|
||||
plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_V4_IN]);
|
||||
if (plist)
|
||||
ei->prefix[EIGRP_FILTER_IN] = plist;
|
||||
else
|
||||
ei->prefix[EIGRP_FILTER_IN] = NULL;
|
||||
}
|
||||
else
|
||||
ei->prefix[EIGRP_FILTER_IN] = NULL;
|
||||
|
||||
/* Prefix-list for interface out */
|
||||
if (dist->prefix[DISTRIBUTE_V4_OUT])
|
||||
{
|
||||
plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_V4_OUT]);
|
||||
if (plist)
|
||||
ei->prefix[EIGRP_FILTER_OUT] = plist;
|
||||
else
|
||||
ei->prefix[EIGRP_FILTER_OUT] = NULL;
|
||||
}
|
||||
else
|
||||
ei->prefix[EIGRP_FILTER_OUT] = NULL;
|
||||
|
||||
#if 0
|
||||
/* route-map IN for whole process */
|
||||
if (dist->route[DISTRIBUTE_V4_IN])
|
||||
{
|
||||
zlog_info("<DEBUG ACL ALL in");
|
||||
routemap = route_map_lookup_by_name (dist->route[DISTRIBUTE_V4_IN]);
|
||||
if (routemap)
|
||||
ei->routemap[EIGRP_FILTER_IN] = routemap;
|
||||
else
|
||||
ei->routemap[EIGRP_FILTER_IN] = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
ei->routemap[EIGRP_FILTER_IN] = NULL;
|
||||
}
|
||||
|
||||
/* route-map OUT for whole process */
|
||||
if (dist->route[DISTRIBUTE_V4_OUT])
|
||||
{
|
||||
routemap = route_map_lookup_by_name (dist->route[DISTRIBUTE_V4_OUT]);
|
||||
if (routemap)
|
||||
ei->routemap[EIGRP_FILTER_OUT] = routemap;
|
||||
else
|
||||
ei->routemap[EIGRP_FILTER_OUT] = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
ei->routemap[EIGRP_FILTER_OUT] = NULL;
|
||||
}
|
||||
#endif
|
||||
//TODO: check Graceful restart after 10sec
|
||||
|
||||
/* check if there is already GR scheduled */
|
||||
if(ei->t_distribute != NULL)
|
||||
{
|
||||
/* if is, cancel schedule */
|
||||
thread_cancel(ei->t_distribute);
|
||||
}
|
||||
/* schedule Graceful restart for interface in 10sec */
|
||||
e->t_distribute = thread_add_timer(master, eigrp_distribute_timer_interface, ei,(10));
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Function called by prefix-list and access-list update
|
||||
*/
|
||||
void
|
||||
eigrp_distribute_update_interface (struct interface *ifp)
|
||||
{
|
||||
struct distribute *dist;
|
||||
|
||||
dist = distribute_lookup (ifp->name);
|
||||
if (dist)
|
||||
eigrp_distribute_update (dist);
|
||||
}
|
||||
|
||||
/* Update all interface's distribute list.
|
||||
* Function used in hook for prefix-list
|
||||
*/
|
||||
void
|
||||
eigrp_distribute_update_all (struct prefix_list *notused)
|
||||
{
|
||||
struct interface *ifp;
|
||||
struct listnode *node, *nnode;
|
||||
|
||||
for (ALL_LIST_ELEMENTS (vrf_iflist(VRF_DEFAULT), node, nnode, ifp))
|
||||
eigrp_distribute_update_interface (ifp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Function used in hook for acces-list
|
||||
*/
|
||||
void
|
||||
eigrp_distribute_update_all_wrapper(struct access_list *notused)
|
||||
{
|
||||
eigrp_distribute_update_all(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* @fn eigrp_distribute_timer_process
|
||||
*
|
||||
* @param[in] thread current execution thread timer is associated with
|
||||
*
|
||||
* @return int always returns 0
|
||||
*
|
||||
* @par
|
||||
* Called when 10sec waiting time expire and
|
||||
* executes Graceful restart for whole process
|
||||
*/
|
||||
int
|
||||
eigrp_distribute_timer_process (struct thread *thread)
|
||||
{
|
||||
struct eigrp *eigrp;
|
||||
|
||||
eigrp = THREAD_ARG(thread);
|
||||
eigrp->t_distribute = NULL;
|
||||
|
||||
/* execute GR for whole process */
|
||||
eigrp_update_send_process_GR(eigrp, EIGRP_GR_FILTER, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* @fn eigrp_distribute_timer_interface
|
||||
*
|
||||
* @param[in] thread current execution thread timer is associated with
|
||||
*
|
||||
* @return int always returns 0
|
||||
*
|
||||
* @par
|
||||
* Called when 10sec waiting time expire and
|
||||
* executes Graceful restart for interface
|
||||
*/
|
||||
int
|
||||
eigrp_distribute_timer_interface (struct thread *thread)
|
||||
{
|
||||
struct eigrp_interface *ei;
|
||||
|
||||
ei = THREAD_ARG(thread);
|
||||
ei->t_distribute = NULL;
|
||||
|
||||
/* execute GR for interface */
|
||||
eigrp_update_send_interface_GR(ei, EIGRP_GR_FILTER, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
44
eigrpd/eigrp_filter.h
Normal file
44
eigrpd/eigrp_filter.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* EIGRP Filter Functions.
|
||||
* Copyright (C) 2013-2016
|
||||
* Authors:
|
||||
* Donnie Savage
|
||||
* Jan Janovic
|
||||
* Matej Perina
|
||||
* Peter Orsag
|
||||
* Peter Paluch
|
||||
* Frantisek Gazo
|
||||
* Tomas Hvorkovy
|
||||
* Martin Kontsek
|
||||
* Lukas Koribsky
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef EIGRPD_EIGRP_FILTER_H_
|
||||
#define EIGRPD_EIGRP_FILTER_H_
|
||||
|
||||
extern void eigrp_distribute_update (struct distribute *);
|
||||
extern void eigrp_distribute_update_interface (struct interface *);
|
||||
extern void eigrp_distribute_update_all (struct prefix_list *);
|
||||
extern void eigrp_distribute_update_all_wrapper(struct access_list *);
|
||||
extern int eigrp_distribute_timer_process (struct thread *);
|
||||
extern int eigrp_distribute_timer_interface (struct thread *);
|
||||
|
||||
#endif /* EIGRPD_EIGRP_FILTER_H_ */
|
502
eigrpd/eigrp_fsm.c
Normal file
502
eigrpd/eigrp_fsm.c
Normal file
|
@ -0,0 +1,502 @@
|
|||
/*
|
||||
* EIGRPd Finite State Machine (DUAL).
|
||||
* Copyright (C) 2013-2014
|
||||
* Authors:
|
||||
* Donnie Savage
|
||||
* Jan Janovic
|
||||
* Matej Perina
|
||||
* Peter Orsag
|
||||
* Peter Paluch
|
||||
*
|
||||
* 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 file contains functions for executing logic of finite state machine
|
||||
*
|
||||
* +------------ +
|
||||
* | (7) |
|
||||
* | v
|
||||
* +=====================================+
|
||||
* | |
|
||||
* | Passive |
|
||||
* | |
|
||||
* +=====================================+
|
||||
* ^ | ^ ^ ^ |
|
||||
* (3)| | (1)| | (1)| |
|
||||
* | (0)| | (3)| | (2)|
|
||||
* | | | | | +---------------+
|
||||
* | | | | | \
|
||||
* +--------+ | | | +-----------------+ \
|
||||
* / / / | \ \
|
||||
* / / / +----+ \ \
|
||||
* | | | | | |
|
||||
* | v | | | v
|
||||
* +===========+ (6) +===========+ +===========+ (6) +===========+
|
||||
* | |------->| | (5) | |-------->| |
|
||||
* | | (4) | |------>| | (4) | |
|
||||
* | ACTIVE 0 |<-------| ACTIVE 1 | | ACTIVE 2 |<--------| ACTIVE 3 |
|
||||
* +--| | +--| | +--| | +--| |
|
||||
* | +===========+ | +===========+ | +===========+ | +===========+
|
||||
* | ^ |(5) | ^ | ^ ^ | ^
|
||||
* | | +---------|------|------------|----+ | | |
|
||||
* +-------+ +------+ +---------+ +---------+
|
||||
* (7) (7) (7) (7)
|
||||
*
|
||||
* 0- input event other than query from successor, FC not satisfied
|
||||
* 1- last reply, FD is reset
|
||||
* 2- query from successor, FC not satisfied
|
||||
* 3- last reply, FC satisfied with current value of FDij
|
||||
* 4- distance increase while in active state
|
||||
* 5- query from successor while in active state
|
||||
* 6- last reply, FC not satisfied with current value of FDij
|
||||
* 7- state not changed, usually by receiving not last reply
|
||||
*
|
||||
*/
|
||||
|
||||
#include <thread.h>
|
||||
#include <zebra.h>
|
||||
|
||||
#include "prefix.h"
|
||||
#include "table.h"
|
||||
#include "memory.h"
|
||||
#include "log.h"
|
||||
#include "linklist.h"
|
||||
#include "vty.h"
|
||||
|
||||
#include "eigrpd/eigrp_structs.h"
|
||||
#include "eigrpd/eigrpd.h"
|
||||
#include "eigrpd/eigrp_interface.h"
|
||||
#include "eigrpd/eigrp_neighbor.h"
|
||||
#include "eigrpd/eigrp_packet.h"
|
||||
#include "eigrpd/eigrp_zebra.h"
|
||||
#include "eigrpd/eigrp_vty.h"
|
||||
#include "eigrpd/eigrp_network.h"
|
||||
#include "eigrpd/eigrp_dump.h"
|
||||
#include "eigrpd/eigrp_topology.h"
|
||||
#include "eigrpd/eigrp_fsm.h"
|
||||
|
||||
/*
|
||||
* Prototypes
|
||||
*/
|
||||
int
|
||||
eigrp_fsm_event_keep_state(struct eigrp_fsm_action_message *);
|
||||
int
|
||||
eigrp_fsm_event_nq_fcn(struct eigrp_fsm_action_message *);
|
||||
int
|
||||
eigrp_fsm_event_q_fcn(struct eigrp_fsm_action_message *);
|
||||
int
|
||||
eigrp_fsm_event_lr(struct eigrp_fsm_action_message *);
|
||||
int
|
||||
eigrp_fsm_event_dinc(struct eigrp_fsm_action_message *);
|
||||
int
|
||||
eigrp_fsm_event_lr_fcs(struct eigrp_fsm_action_message *);
|
||||
int
|
||||
eigrp_fsm_event_lr_fcn(struct eigrp_fsm_action_message *);
|
||||
int
|
||||
eigrp_fsm_event_qact(struct eigrp_fsm_action_message *);
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* NSM - field of fields of struct containing one function each.
|
||||
* Which function is used depends on actual state of FSM and occurred
|
||||
* event(arrow in diagram). Usage:
|
||||
* NSM[actual/starting state][occurred event].func
|
||||
* Functions are should be executed within separate thread.
|
||||
*/
|
||||
struct {
|
||||
int
|
||||
(*func)(struct eigrp_fsm_action_message *);
|
||||
} NSM[EIGRP_FSM_STATE_MAX][EIGRP_FSM_EVENT_MAX] = { {
|
||||
//PASSIVE STATE
|
||||
{ eigrp_fsm_event_nq_fcn }, /* Event 0 */
|
||||
{ eigrp_fsm_event_keep_state }, /* Event 1 */
|
||||
{ eigrp_fsm_event_q_fcn }, /* Event 2 */
|
||||
{ eigrp_fsm_event_keep_state }, /* Event 3 */
|
||||
{ eigrp_fsm_event_keep_state }, /* Event 4 */
|
||||
{ eigrp_fsm_event_keep_state }, /* Event 5 */
|
||||
{ eigrp_fsm_event_keep_state }, /* Event 6 */
|
||||
{ eigrp_fsm_event_keep_state }, /* Event 7 */
|
||||
}, {
|
||||
//Active 0 state
|
||||
{ eigrp_fsm_event_keep_state }, /* Event 0 */
|
||||
{ eigrp_fsm_event_keep_state }, /* Event 1 */
|
||||
{ eigrp_fsm_event_keep_state }, /* Event 2 */
|
||||
{ eigrp_fsm_event_lr_fcs }, /* Event 3 */
|
||||
{ eigrp_fsm_event_keep_state }, /* Event 4 */
|
||||
{ eigrp_fsm_event_qact }, /* Event 5 */
|
||||
{ eigrp_fsm_event_lr_fcn }, /* Event 6 */
|
||||
{ eigrp_fsm_event_keep_state }, /* Event 7 */
|
||||
|
||||
}, {
|
||||
//Active 1 state
|
||||
{ eigrp_fsm_event_keep_state }, /* Event 0 */
|
||||
{ eigrp_fsm_event_lr }, /* Event 1 */
|
||||
{ eigrp_fsm_event_keep_state }, /* Event 2 */
|
||||
{ eigrp_fsm_event_keep_state }, /* Event 3 */
|
||||
{ eigrp_fsm_event_dinc }, /* Event 4 */
|
||||
{ eigrp_fsm_event_qact }, /* Event 5 */
|
||||
{ eigrp_fsm_event_keep_state }, /* Event 6 */
|
||||
{ eigrp_fsm_event_keep_state }, /* Event 7 */
|
||||
}, {
|
||||
//Active 2 state
|
||||
{ eigrp_fsm_event_keep_state }, /* Event 0 */
|
||||
{ eigrp_fsm_event_keep_state }, /* Event 1 */
|
||||
{ eigrp_fsm_event_keep_state }, /* Event 2 */
|
||||
{ eigrp_fsm_event_lr_fcs }, /* Event 3 */
|
||||
{ eigrp_fsm_event_keep_state }, /* Event 4 */
|
||||
{ eigrp_fsm_event_keep_state }, /* Event 5 */
|
||||
{ eigrp_fsm_event_lr_fcn }, /* Event 6 */
|
||||
{ eigrp_fsm_event_keep_state }, /* Event 7 */
|
||||
}, {
|
||||
//Active 3 state
|
||||
{ eigrp_fsm_event_keep_state }, /* Event 0 */
|
||||
{ eigrp_fsm_event_lr }, /* Event 1 */
|
||||
{ eigrp_fsm_event_keep_state }, /* Event 2 */
|
||||
{ eigrp_fsm_event_keep_state }, /* Event 3 */
|
||||
{ eigrp_fsm_event_dinc }, /* Event 4 */
|
||||
{ eigrp_fsm_event_keep_state }, /* Event 5 */
|
||||
{ eigrp_fsm_event_keep_state }, /* Event 6 */
|
||||
{ eigrp_fsm_event_keep_state }, /* Event 7 */
|
||||
}, };
|
||||
|
||||
/*
|
||||
* Main function in which are make decisions which event occurred.
|
||||
* msg - argument of type struct eigrp_fsm_action_message contain
|
||||
* details about what happen
|
||||
*
|
||||
* Return number of occurred event (arrow in diagram).
|
||||
*
|
||||
*/
|
||||
int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg) {
|
||||
// Loading base information from message
|
||||
//struct eigrp *eigrp = msg->eigrp;
|
||||
struct eigrp_prefix_entry *prefix = msg->prefix;
|
||||
struct eigrp_neighbor_entry *entry = msg->entry;
|
||||
u_char actual_state = prefix->state;
|
||||
|
||||
if (entry == NULL) {
|
||||
entry = eigrp_neighbor_entry_new();
|
||||
entry->adv_router = msg->adv_router;
|
||||
entry->ei = msg->adv_router->ei;
|
||||
entry->prefix = prefix;
|
||||
msg->entry = entry;
|
||||
}
|
||||
|
||||
// Dividing by actual state of prefix's FSM
|
||||
switch (actual_state) {
|
||||
case EIGRP_FSM_STATE_PASSIVE: {
|
||||
//Calculate resultant metrics and insert to correct position in entries list
|
||||
eigrp_topology_update_distance(msg);
|
||||
|
||||
struct eigrp_neighbor_entry * head =
|
||||
(struct eigrp_neighbor_entry *) entry->prefix->entries->head->data;
|
||||
//zlog_info ("flag: %d rdist: %u dist: %u pfdist: %u pdist: %u", head->flags, head->reported_distance, head->distance, prefix->fdistance, prefix->distance);
|
||||
if (head->reported_distance < prefix->fdistance) {
|
||||
return EIGRP_FSM_KEEP_STATE;
|
||||
}
|
||||
/*
|
||||
* if best entry doesn't satisfy feasibility condition it means move to active state
|
||||
* dependently if it was query from successor
|
||||
*/
|
||||
else {
|
||||
if (msg->packet_type == EIGRP_OPC_QUERY) {
|
||||
return EIGRP_FSM_EVENT_Q_FCN;
|
||||
} else {
|
||||
return EIGRP_FSM_EVENT_NQ_FCN;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case EIGRP_FSM_STATE_ACTIVE_0: {
|
||||
eigrp_topology_update_distance(msg);
|
||||
|
||||
if (msg->packet_type == EIGRP_OPC_REPLY) {
|
||||
listnode_delete(prefix->rij, entry->adv_router);
|
||||
if (prefix->rij->count) {
|
||||
return EIGRP_FSM_KEEP_STATE;
|
||||
} else {
|
||||
zlog_info("All reply received\n");
|
||||
if (((struct eigrp_neighbor_entry *) prefix->entries->head->data)->reported_distance
|
||||
< prefix->fdistance) {
|
||||
return EIGRP_FSM_EVENT_LR_FCS;
|
||||
}
|
||||
|
||||
return EIGRP_FSM_EVENT_LR_FCN;
|
||||
}
|
||||
} else if (msg->packet_type == EIGRP_OPC_QUERY
|
||||
&& (entry->flags & EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG)) {
|
||||
return EIGRP_FSM_EVENT_QACT;
|
||||
}
|
||||
|
||||
return EIGRP_FSM_KEEP_STATE;
|
||||
|
||||
break;
|
||||
}
|
||||
case EIGRP_FSM_STATE_ACTIVE_1: {
|
||||
int change = eigrp_topology_update_distance(msg);
|
||||
|
||||
if (msg->packet_type == EIGRP_OPC_QUERY
|
||||
&& (entry->flags & EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG)) {
|
||||
return EIGRP_FSM_EVENT_QACT;
|
||||
} else if (msg->packet_type == EIGRP_OPC_REPLY) {
|
||||
listnode_delete(prefix->rij, entry->adv_router);
|
||||
|
||||
if (change == 1
|
||||
&& (entry->flags & EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG)) {
|
||||
return EIGRP_FSM_EVENT_DINC;
|
||||
} else if (prefix->rij->count) {
|
||||
return EIGRP_FSM_KEEP_STATE;
|
||||
} else {
|
||||
zlog_info("All reply received\n");
|
||||
return EIGRP_FSM_EVENT_LR;
|
||||
}
|
||||
} else if (msg->packet_type == EIGRP_OPC_UPDATE && change == 1
|
||||
&& (entry->flags & EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG)) {
|
||||
return EIGRP_FSM_EVENT_DINC;
|
||||
}
|
||||
return EIGRP_FSM_KEEP_STATE;
|
||||
|
||||
break;
|
||||
}
|
||||
case EIGRP_FSM_STATE_ACTIVE_2: {
|
||||
|
||||
eigrp_topology_update_distance(msg);
|
||||
|
||||
if (msg->packet_type == EIGRP_OPC_REPLY) {
|
||||
listnode_delete(prefix->rij, entry->adv_router);
|
||||
if (prefix->rij->count) {
|
||||
return EIGRP_FSM_KEEP_STATE;
|
||||
} else {
|
||||
zlog_info("All reply received\n");
|
||||
if (((struct eigrp_neighbor_entry *) prefix->entries->head->data)->reported_distance
|
||||
< prefix->fdistance) {
|
||||
return EIGRP_FSM_EVENT_LR_FCS;
|
||||
}
|
||||
|
||||
return EIGRP_FSM_EVENT_LR_FCN;
|
||||
}
|
||||
}
|
||||
return EIGRP_FSM_KEEP_STATE;
|
||||
|
||||
break;
|
||||
}
|
||||
case EIGRP_FSM_STATE_ACTIVE_3: {
|
||||
|
||||
int change = eigrp_topology_update_distance(msg);
|
||||
|
||||
if (msg->packet_type == EIGRP_OPC_REPLY) {
|
||||
listnode_delete(prefix->rij, entry->adv_router);
|
||||
|
||||
if (change == 1
|
||||
&& (entry->flags & EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG)) {
|
||||
return EIGRP_FSM_EVENT_DINC;
|
||||
} else if (prefix->rij->count) {
|
||||
return EIGRP_FSM_KEEP_STATE;
|
||||
} else {
|
||||
zlog_info("All reply received\n");
|
||||
return EIGRP_FSM_EVENT_LR;
|
||||
}
|
||||
} else if (msg->packet_type == EIGRP_OPC_UPDATE && change == 1
|
||||
&& (entry->flags & EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG)) {
|
||||
return EIGRP_FSM_EVENT_DINC;
|
||||
}
|
||||
return EIGRP_FSM_KEEP_STATE;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return EIGRP_FSM_KEEP_STATE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function made to execute in separate thread.
|
||||
* Load argument from thread and execute proper NSM function
|
||||
*/
|
||||
int eigrp_fsm_event(struct eigrp_fsm_action_message *msg, int event) {
|
||||
|
||||
zlog_info("EIGRP AS: %d State: %d Event: %d Network: %s\n", msg->eigrp->AS,
|
||||
msg->prefix->state, event, eigrp_topology_ip_string(msg->prefix));
|
||||
(*(NSM[msg->prefix->state][event].func))(msg);
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
* Function of event 0.
|
||||
*
|
||||
*/
|
||||
int eigrp_fsm_event_nq_fcn(struct eigrp_fsm_action_message *msg) {
|
||||
struct eigrp *eigrp = msg->eigrp;
|
||||
struct eigrp_prefix_entry *prefix = msg->prefix;
|
||||
struct list *successors = eigrp_topology_get_successor(prefix);
|
||||
prefix->state = EIGRP_FSM_STATE_ACTIVE_1;
|
||||
prefix->rdistance = prefix->distance = prefix->fdistance =
|
||||
((struct eigrp_neighbor_entry *) successors->head->data)->distance;
|
||||
prefix->reported_metric =
|
||||
((struct eigrp_neighbor_entry *) successors->head->data)->total_metric;
|
||||
|
||||
if (eigrp_nbr_count_get()) {
|
||||
prefix->req_action |= EIGRP_FSM_NEED_QUERY;
|
||||
listnode_add(eigrp->topology_changes_internalIPV4,prefix);
|
||||
} else {
|
||||
eigrp_fsm_event_lr(msg); //in the case that there are no more neighbors left
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int eigrp_fsm_event_q_fcn(struct eigrp_fsm_action_message *msg) {
|
||||
struct eigrp *eigrp = msg->eigrp;
|
||||
struct eigrp_prefix_entry *prefix = msg->prefix;
|
||||
struct list *successors = eigrp_topology_get_successor(prefix);
|
||||
prefix->state = EIGRP_FSM_STATE_ACTIVE_3;
|
||||
prefix->rdistance = prefix->distance = prefix->fdistance =
|
||||
((struct eigrp_neighbor_entry *) successors->head->data)->distance;
|
||||
prefix->reported_metric =
|
||||
((struct eigrp_neighbor_entry *) successors->head->data)->total_metric;
|
||||
if (eigrp_nbr_count_get()) {
|
||||
prefix->req_action |= EIGRP_FSM_NEED_QUERY;
|
||||
listnode_add(eigrp->topology_changes_internalIPV4,prefix);
|
||||
} else {
|
||||
eigrp_fsm_event_lr(msg); //in the case that there are no more neighbors left
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int eigrp_fsm_event_keep_state(struct eigrp_fsm_action_message *msg) {
|
||||
|
||||
struct eigrp_prefix_entry *prefix = msg->prefix;
|
||||
|
||||
if (prefix->state == EIGRP_FSM_STATE_PASSIVE) {
|
||||
if (!eigrp_metrics_is_same(&prefix->reported_metric,
|
||||
&((struct eigrp_neighbor_entry *) prefix->entries->head->data)->total_metric)) {
|
||||
prefix->rdistance =
|
||||
prefix->fdistance =
|
||||
prefix->distance =
|
||||
((struct eigrp_neighbor_entry *) prefix->entries->head->data)->distance;
|
||||
prefix->reported_metric =
|
||||
((struct eigrp_neighbor_entry *) prefix->entries->head->data)->total_metric;
|
||||
if (msg->packet_type == EIGRP_OPC_QUERY)
|
||||
eigrp_send_reply(msg->adv_router, prefix);
|
||||
prefix->req_action |= EIGRP_FSM_NEED_UPDATE;
|
||||
listnode_add((eigrp_lookup())->topology_changes_internalIPV4,prefix);
|
||||
}
|
||||
eigrp_topology_update_node_flags(prefix);
|
||||
eigrp_update_routing_table(prefix);
|
||||
}
|
||||
|
||||
if (msg->packet_type == EIGRP_OPC_QUERY)
|
||||
eigrp_send_reply(msg->adv_router, prefix);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int eigrp_fsm_event_lr(struct eigrp_fsm_action_message *msg) {
|
||||
struct eigrp *eigrp = msg->eigrp;
|
||||
struct eigrp_prefix_entry *prefix = msg->prefix;
|
||||
prefix->fdistance =
|
||||
prefix->distance =
|
||||
prefix->rdistance =
|
||||
((struct eigrp_neighbor_entry *) (prefix->entries->head->data))->distance;
|
||||
prefix->reported_metric =
|
||||
((struct eigrp_neighbor_entry *) (prefix->entries->head->data))->total_metric;
|
||||
if (prefix->state == EIGRP_FSM_STATE_ACTIVE_3)
|
||||
eigrp_send_reply(
|
||||
((struct eigrp_neighbor_entry *) (eigrp_topology_get_successor(
|
||||
prefix)->head->data))->adv_router, prefix);
|
||||
prefix->state = EIGRP_FSM_STATE_PASSIVE;
|
||||
prefix->req_action |= EIGRP_FSM_NEED_UPDATE;
|
||||
listnode_add(eigrp->topology_changes_internalIPV4,prefix);
|
||||
eigrp_topology_update_node_flags(prefix);
|
||||
eigrp_update_routing_table(prefix);
|
||||
eigrp_update_topology_table_prefix(eigrp->topology_table, prefix);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int eigrp_fsm_event_dinc(struct eigrp_fsm_action_message *msg) {
|
||||
|
||||
msg->prefix->state =
|
||||
msg->prefix->state == EIGRP_FSM_STATE_ACTIVE_1 ?
|
||||
EIGRP_FSM_STATE_ACTIVE_0 : EIGRP_FSM_STATE_ACTIVE_2;
|
||||
msg->prefix->distance =
|
||||
((struct eigrp_neighbor_entry *) (eigrp_topology_get_successor(
|
||||
msg->prefix)->head->data))->distance;
|
||||
if (!msg->prefix->rij->count) {
|
||||
(*(NSM[msg->prefix->state][eigrp_get_fsm_event(msg)].func))(msg);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int eigrp_fsm_event_lr_fcs(struct eigrp_fsm_action_message *msg) {
|
||||
struct eigrp *eigrp = msg->eigrp;
|
||||
struct eigrp_prefix_entry *prefix = msg->prefix;
|
||||
prefix->state = EIGRP_FSM_STATE_PASSIVE;
|
||||
prefix->distance =
|
||||
prefix->rdistance =
|
||||
((struct eigrp_neighbor_entry *) (prefix->entries->head->data))->distance;
|
||||
prefix->reported_metric =
|
||||
((struct eigrp_neighbor_entry *) (prefix->entries->head->data))->total_metric;
|
||||
prefix->fdistance =
|
||||
prefix->fdistance > prefix->distance ?
|
||||
prefix->distance : prefix->fdistance;
|
||||
if (prefix->state == EIGRP_FSM_STATE_ACTIVE_2)
|
||||
eigrp_send_reply(
|
||||
((struct eigrp_neighbor_entry *) (eigrp_topology_get_successor(
|
||||
prefix)->head->data))->adv_router, prefix);
|
||||
prefix->req_action |= EIGRP_FSM_NEED_UPDATE;
|
||||
listnode_add(eigrp->topology_changes_internalIPV4,prefix);
|
||||
eigrp_topology_update_node_flags(prefix);
|
||||
eigrp_update_routing_table(prefix);
|
||||
eigrp_update_topology_table_prefix(eigrp->topology_table, prefix);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int eigrp_fsm_event_lr_fcn(struct eigrp_fsm_action_message *msg) {
|
||||
struct eigrp *eigrp = msg->eigrp;
|
||||
struct eigrp_prefix_entry *prefix = msg->prefix;
|
||||
prefix->state =
|
||||
prefix->state == EIGRP_FSM_STATE_ACTIVE_0 ?
|
||||
EIGRP_FSM_STATE_ACTIVE_1 : EIGRP_FSM_STATE_ACTIVE_3;
|
||||
struct eigrp_neighbor_entry *best_successor =
|
||||
((struct eigrp_neighbor_entry *) (eigrp_topology_get_successor(
|
||||
prefix)->head->data));
|
||||
prefix->rdistance = prefix->distance = best_successor->distance;
|
||||
prefix->reported_metric = best_successor->total_metric;
|
||||
if (eigrp_nbr_count_get()) {
|
||||
prefix->req_action |= EIGRP_FSM_NEED_QUERY;
|
||||
listnode_add(eigrp->topology_changes_internalIPV4,prefix);
|
||||
} else {
|
||||
eigrp_fsm_event_lr(msg); //in the case that there are no more neighbors left
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int eigrp_fsm_event_qact(struct eigrp_fsm_action_message *msg) {
|
||||
msg->prefix->state = EIGRP_FSM_STATE_ACTIVE_2;
|
||||
msg->prefix->distance =
|
||||
((struct eigrp_neighbor_entry *) (eigrp_topology_get_successor(
|
||||
msg->prefix)->head->data))->distance;
|
||||
return 1;
|
||||
}
|
37
eigrpd/eigrp_fsm.h
Normal file
37
eigrpd/eigrp_fsm.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* EIGRP Finite State Machine (DUAL).
|
||||
* Copyright (C) 2013-2014
|
||||
* Authors:
|
||||
* Donnie Savage
|
||||
* Jan Janovic
|
||||
* Matej Perina
|
||||
* Peter Orsag
|
||||
* Peter Paluch
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _ZEBRA_EIGRP_FSM_H
|
||||
#define _ZEBRA_EIGRP_FSM_H
|
||||
|
||||
|
||||
extern int eigrp_get_fsm_event (struct eigrp_fsm_action_message *);
|
||||
extern int eigrp_fsm_event (struct eigrp_fsm_action_message *, int);
|
||||
|
||||
|
||||
#endif /* _ZEBRA_EIGRP_DUAL_H */
|
774
eigrpd/eigrp_hello.c
Normal file
774
eigrpd/eigrp_hello.c
Normal file
|
@ -0,0 +1,774 @@
|
|||
/*
|
||||
* EIGRP Sending and Receiving EIGRP Hello Packets.
|
||||
* Copyright (C) 2013-2016
|
||||
* Authors:
|
||||
* Donnie Savage
|
||||
* Jan Janovic
|
||||
* Matej Perina
|
||||
* Peter Orsag
|
||||
* Peter Paluch
|
||||
* Frantisek Gazo
|
||||
* Tomas Hvorkovy
|
||||
* Martin Kontsek
|
||||
* Lukas Koribsky
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#include "thread.h"
|
||||
#include "memory.h"
|
||||
#include "linklist.h"
|
||||
#include "prefix.h"
|
||||
#include "if.h"
|
||||
#include "table.h"
|
||||
#include "sockunion.h"
|
||||
#include "stream.h"
|
||||
#include "log.h"
|
||||
#include "sockopt.h"
|
||||
#include "checksum.h"
|
||||
#include "vty.h"
|
||||
#include "md5.h"
|
||||
|
||||
#include "eigrpd/eigrp_structs.h"
|
||||
#include "eigrpd/eigrpd.h"
|
||||
#include "eigrpd/eigrp_interface.h"
|
||||
#include "eigrpd/eigrp_neighbor.h"
|
||||
#include "eigrpd/eigrp_packet.h"
|
||||
#include "eigrpd/eigrp_zebra.h"
|
||||
#include "eigrpd/eigrp_vty.h"
|
||||
#include "eigrpd/eigrp_dump.h"
|
||||
#include "eigrpd/eigrp_macros.h"
|
||||
|
||||
/* Packet Type String. */
|
||||
static const struct message eigrp_general_tlv_type_str[] =
|
||||
{
|
||||
{ EIGRP_TLV_PARAMETER, "PARAMETER" },
|
||||
{ EIGRP_TLV_AUTH, "AUTH" },
|
||||
{ EIGRP_TLV_SEQ, "SEQ" },
|
||||
{ EIGRP_TLV_SW_VERSION, "SW_VERSION" },
|
||||
{ EIGRP_TLV_NEXT_MCAST_SEQ, "NEXT_MCAST_SEQ" },
|
||||
{ EIGRP_TLV_PEER_TERMINATION, "PEER_TERMINATION" },
|
||||
{ EIGRP_TLV_PEER_MTRLIST, "PEER_MTRLIST" },
|
||||
{ EIGRP_TLV_PEER_TIDLIST, "PEER_TIDLIST" },
|
||||
};
|
||||
|
||||
static const size_t eigrp_general_tlv_type_str_max = sizeof(eigrp_general_tlv_type_str) /
|
||||
sizeof(eigrp_general_tlv_type_str[0]);
|
||||
|
||||
|
||||
/*
|
||||
* @fn eigrp_hello_timer
|
||||
*
|
||||
* @param[in] thread current execution thread timer is associated with
|
||||
*
|
||||
* @return int always returns 0
|
||||
*
|
||||
* @par
|
||||
* Called once per "hello" time interval, default 5 seconds
|
||||
* Sends hello packet via multicast for all interfaces eigrp
|
||||
* is configured for
|
||||
*/
|
||||
int
|
||||
eigrp_hello_timer (struct thread *thread)
|
||||
{
|
||||
struct eigrp_interface *ei;
|
||||
|
||||
ei = THREAD_ARG(thread);
|
||||
ei->t_hello = NULL;
|
||||
|
||||
if (IS_DEBUG_EIGRP(0, TIMERS))
|
||||
zlog (NULL, LOG_DEBUG, "Start Hello Timer (%s) Expire [%u]",
|
||||
IF_NAME(ei), EIGRP_IF_PARAM(ei, v_hello));
|
||||
|
||||
/* Sending hello packet. */
|
||||
eigrp_hello_send(ei, EIGRP_HELLO_NORMAL, NULL);
|
||||
|
||||
/* Hello timer set. */
|
||||
ei->t_hello = thread_add_timer(master, eigrp_hello_timer, ei,
|
||||
EIGRP_IF_PARAM(ei, v_hello));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn eigrp_hello_parameter_decode
|
||||
*
|
||||
* @param[in] nbr neighbor the ACK should be sent to
|
||||
* @param[in] param pointer packet TLV is stored to
|
||||
*
|
||||
* @return u_int16_t number of bytes added to packet stream
|
||||
*
|
||||
* @par
|
||||
* Encode Parameter TLV, used to convey metric weights and the hold time.
|
||||
*
|
||||
* @usage
|
||||
* Note the addition of K6 for the new extended metrics, and does not apply to
|
||||
* older TLV packet formats.
|
||||
*/
|
||||
static void
|
||||
eigrp_hello_parameter_decode (struct eigrp_neighbor *nbr,
|
||||
struct eigrp_tlv_hdr_type *tlv)
|
||||
{
|
||||
struct eigrp *eigrp = nbr->ei->eigrp;
|
||||
struct TLV_Parameter_Type *param = (struct TLV_Parameter_Type *)tlv;
|
||||
|
||||
/* copy over the values passed in by the neighbor */
|
||||
nbr->K1 = param->K1;
|
||||
nbr->K2 = param->K2;
|
||||
nbr->K3 = param->K3;
|
||||
nbr->K4 = param->K4;
|
||||
nbr->K5 = param->K5;
|
||||
nbr->K6 = param->K6;
|
||||
nbr->v_holddown = ntohs(param->hold_time);
|
||||
|
||||
/*
|
||||
* Check K1-K5 have the correct values to be able to become neighbors
|
||||
* K6 does not have to match
|
||||
*/
|
||||
if ((eigrp->k_values[0] == nbr->K1) &&
|
||||
(eigrp->k_values[1] == nbr->K2) &&
|
||||
(eigrp->k_values[2] == nbr->K3) &&
|
||||
(eigrp->k_values[3] == nbr->K4) &&
|
||||
(eigrp->k_values[4] == nbr->K5))
|
||||
{
|
||||
|
||||
if (eigrp_nbr_state_get(nbr) == EIGRP_NEIGHBOR_DOWN)
|
||||
{
|
||||
zlog_info("Neighbor %s (%s) is pending: new adjacency",
|
||||
inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex));
|
||||
|
||||
/* Expedited hello sent */
|
||||
eigrp_hello_send(nbr->ei, EIGRP_HELLO_NORMAL, NULL);
|
||||
|
||||
// if(ntohl(nbr->ei->address->u.prefix4.s_addr) > ntohl(nbr->src.s_addr))
|
||||
eigrp_update_send_init(nbr);
|
||||
|
||||
eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_PENDING);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (eigrp_nbr_state_get(nbr) != EIGRP_NEIGHBOR_DOWN)
|
||||
{
|
||||
if ((param->K1 & param->K2 & param->K3 & param->K4 & param->K5) == 255)
|
||||
{
|
||||
zlog_info ("Neighbor %s (%s) is down: Interface PEER-TERMINATION received",
|
||||
inet_ntoa (nbr->src),ifindex2ifname (nbr->ei->ifp->ifindex));
|
||||
eigrp_nbr_delete (nbr);
|
||||
}
|
||||
else
|
||||
{
|
||||
zlog_info ("Neighbor %s (%s) going down: Kvalue mismatch",
|
||||
inet_ntoa (nbr->src),ifindex2ifname (nbr->ei->ifp->ifindex));
|
||||
eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_DOWN);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static u_char
|
||||
eigrp_hello_authentication_decode(struct stream *s, struct eigrp_tlv_hdr_type *tlv_header, struct eigrp_neighbor *nbr)
|
||||
{
|
||||
|
||||
struct TLV_MD5_Authentication_Type *md5;
|
||||
|
||||
md5 = (struct TLV_MD5_Authentication_Type *) tlv_header;
|
||||
|
||||
if(md5->auth_type == EIGRP_AUTH_TYPE_MD5)
|
||||
return eigrp_check_md5_digest(s, md5, nbr, EIGRP_AUTH_BASIC_HELLO_FLAG);
|
||||
else if (md5->auth_type == EIGRP_AUTH_TYPE_SHA256)
|
||||
return eigrp_check_sha256_digest(s, (struct TLV_SHA256_Authentication_Type *) tlv_header, nbr, EIGRP_AUTH_BASIC_HELLO_FLAG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn eigrp_sw_version_decode
|
||||
*
|
||||
* @param[in] nbr neighbor the ACK shoudl be sent to
|
||||
* @param[in] param pointer to TLV software version information
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @par
|
||||
* Read the software version in the specified location.
|
||||
* This consists of two bytes of OS version, and two bytes of EIGRP
|
||||
* revision number.
|
||||
*/
|
||||
static void
|
||||
eigrp_sw_version_decode (struct eigrp_neighbor *nbr,
|
||||
struct eigrp_tlv_hdr_type *tlv)
|
||||
{
|
||||
struct TLV_Software_Type *version = (struct TLV_Software_Type *)tlv;
|
||||
|
||||
nbr->os_rel_major = version->vender_major;
|
||||
nbr->os_rel_minor = version->vender_minor;
|
||||
nbr->tlv_rel_major = version->eigrp_major;
|
||||
nbr->tlv_rel_minor = version->eigrp_minor;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn eigrp_peer_termination_decode
|
||||
*
|
||||
* @param[in] nbr neighbor the ACK shoudl be sent to
|
||||
* @param[in] tlv pointer to TLV software version information
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @par
|
||||
* Read the address in the TLV and match to out address. If
|
||||
* a match is found, move the sending neighbor to the down state. If
|
||||
* out address is not in the TLV, then ignore the peer termination
|
||||
*/
|
||||
static void
|
||||
eigrp_peer_termination_decode (struct eigrp_neighbor *nbr,
|
||||
struct eigrp_tlv_hdr_type *tlv)
|
||||
{
|
||||
struct TLV_Peer_Termination_type *param = (struct TLV_Peer_Termination_type *)tlv;
|
||||
|
||||
uint32_t my_ip = nbr->ei->address->u.prefix4.s_addr;
|
||||
uint32_t received_ip = param->neighbor_ip;
|
||||
|
||||
if(my_ip == received_ip)
|
||||
{
|
||||
zlog_info ("Neighbor %s (%s) is down: Peer Termination received",
|
||||
inet_ntoa (nbr->src),ifindex2ifname (nbr->ei->ifp->ifindex));
|
||||
/* set neighbor to DOWN */
|
||||
nbr->state = EIGRP_NEIGHBOR_DOWN;
|
||||
/* delete neighbor */
|
||||
eigrp_nbr_delete (nbr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn eigrp_peer_termination_encode
|
||||
*
|
||||
* @param[in,out] s packet stream TLV is stored to
|
||||
* @param[in] nbr_addr pointer to neighbor address for Peer Termination TLV
|
||||
*
|
||||
* @return u_int16_t number of bytes added to packet stream
|
||||
*
|
||||
* @par
|
||||
* Function used to encode Peer Termination TLV to Hello packet.
|
||||
*/
|
||||
static u_int16_t
|
||||
eigrp_peer_termination_encode (struct stream *s, struct in_addr *nbr_addr)
|
||||
{
|
||||
u_int16_t length = EIGRP_TLV_PEER_TERMINATION_LEN;
|
||||
|
||||
/* fill in type and length */
|
||||
stream_putw(s, EIGRP_TLV_PEER_TERMINATION);
|
||||
stream_putw(s, length);
|
||||
|
||||
/* fill in unknown field 0x04 */
|
||||
stream_putc(s, 0x04);
|
||||
|
||||
/* finally neighbor IP address */
|
||||
stream_put_ipv4(s, nbr_addr->s_addr);
|
||||
|
||||
return(length);
|
||||
}
|
||||
|
||||
/*
|
||||
* @fn eigrp_hello_receive
|
||||
*
|
||||
* @param[in] eigrp eigrp routing process
|
||||
* @param[in] iph pointer to ip header
|
||||
* @param[in] eigrph pointer to eigrp header
|
||||
* @param[in] s input ip stream
|
||||
* @param[in] ei eigrp interface packet arrived on
|
||||
* @param[in] size size of eigrp packet
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @par
|
||||
* This is the main worker function for processing hello packets. It
|
||||
* will validate the peer associated with the src ip address of the ip
|
||||
* header, and then decode each of the general TLVs which the packet
|
||||
* may contain.
|
||||
*
|
||||
* @usage
|
||||
* Not all TLVs are current decoder. This is a work in progress..
|
||||
*/
|
||||
void
|
||||
eigrp_hello_receive (struct eigrp *eigrp, struct ip *iph, struct eigrp_header *eigrph,
|
||||
struct stream *s, struct eigrp_interface *ei, int size)
|
||||
{
|
||||
struct eigrp_tlv_hdr_type *tlv_header;
|
||||
struct eigrp_neighbor *nbr;
|
||||
uint16_t type;
|
||||
uint16_t length;
|
||||
|
||||
/* get neighbor struct */
|
||||
nbr = eigrp_nbr_get(ei, eigrph, iph);
|
||||
|
||||
/* neighbor must be valid, eigrp_nbr_get creates if none existed */
|
||||
assert(nbr);
|
||||
|
||||
if (IS_DEBUG_EIGRP_PACKET(eigrph->opcode - 1, RECV))
|
||||
zlog_debug("Processing Hello size[%u] int(%s) nbr(%s)",
|
||||
size, ifindex2ifname(nbr->ei->ifp->ifindex),
|
||||
inet_ntoa(nbr->src));
|
||||
|
||||
size -= EIGRP_HEADER_LEN;
|
||||
if (size < 0)
|
||||
return;
|
||||
|
||||
tlv_header = (struct eigrp_tlv_hdr_type *)eigrph->tlv;
|
||||
|
||||
do {
|
||||
type = ntohs(tlv_header->type);
|
||||
length = ntohs(tlv_header->length);
|
||||
|
||||
if ((length > 0) && (length <= size))
|
||||
{
|
||||
if (IS_DEBUG_EIGRP_PACKET(0, RECV))
|
||||
zlog_debug(" General TLV(%s)", LOOKUP(eigrp_general_tlv_type_str, type));
|
||||
|
||||
// determine what General TLV is being processed
|
||||
switch (type)
|
||||
{
|
||||
case EIGRP_TLV_PARAMETER:
|
||||
eigrp_hello_parameter_decode(nbr, tlv_header);
|
||||
break;
|
||||
case EIGRP_TLV_AUTH:
|
||||
{
|
||||
if(eigrp_hello_authentication_decode(s,tlv_header,nbr) == 0)
|
||||
return;
|
||||
else
|
||||
break;
|
||||
break;
|
||||
}
|
||||
case EIGRP_TLV_SEQ:
|
||||
break;
|
||||
case EIGRP_TLV_SW_VERSION:
|
||||
eigrp_sw_version_decode(nbr, tlv_header);
|
||||
break;
|
||||
case EIGRP_TLV_NEXT_MCAST_SEQ:
|
||||
break;
|
||||
case EIGRP_TLV_PEER_TERMINATION:
|
||||
eigrp_peer_termination_decode(nbr, tlv_header);
|
||||
break;
|
||||
case EIGRP_TLV_PEER_MTRLIST:
|
||||
case EIGRP_TLV_PEER_TIDLIST:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
tlv_header = (struct eigrp_tlv_hdr_type *)(((char *)tlv_header) + length);
|
||||
size -= length;
|
||||
|
||||
} while (size > 0);
|
||||
|
||||
|
||||
/*If received packet is hello with Parameter TLV*/
|
||||
if (ntohl(eigrph->ack) == 0)
|
||||
{
|
||||
/* increment statistics. */
|
||||
ei->hello_in++;
|
||||
eigrp_nbr_state_update(nbr);
|
||||
|
||||
}
|
||||
|
||||
if (IS_DEBUG_EIGRP_PACKET(0, RECV))
|
||||
zlog_debug("Hello Packet received from %s", inet_ntoa(nbr->src));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn eigrp_sw_version_encode
|
||||
*
|
||||
* @param[in,out] s packet stream TLV is stored to
|
||||
*
|
||||
* @return u_int16_t number of bytes added to packet stream
|
||||
*
|
||||
* @par
|
||||
* Store the software version in the specified location.
|
||||
* This consists of two bytes of OS version, and two bytes of EIGRP
|
||||
* revision number.
|
||||
*/
|
||||
static u_int16_t
|
||||
eigrp_sw_version_encode (struct stream *s)
|
||||
{
|
||||
u_int16_t length = EIGRP_TLV_SW_VERSION_LEN;
|
||||
|
||||
// setup the tlv fields
|
||||
stream_putw(s, EIGRP_TLV_SW_VERSION);
|
||||
stream_putw(s, length);
|
||||
|
||||
// encode the version of quagga we're running
|
||||
// DVS: need to figure out a cleaner way to do this
|
||||
stream_putc(s, 0); //!< major os version
|
||||
stream_putc(s, 99); //!< minor os version
|
||||
|
||||
/* and the core eigrp version */
|
||||
stream_putc(s, EIGRP_MAJOR_VERSION);
|
||||
stream_putc(s, EIGRP_MINOR_VERSION);
|
||||
|
||||
return(length);
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn eigrp_tidlist_encode
|
||||
*
|
||||
* @param[in,out] s packet stream TLV is stored to
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @par
|
||||
* If doing mutli-topology, then store the supported TID list.
|
||||
* This is currently a place holder function
|
||||
*/
|
||||
static u_int16_t
|
||||
eigrp_tidlist_encode (struct stream *s)
|
||||
{
|
||||
//u_int16_t length = EIGRP_TLV_SW_VERSION_LEN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn eigrp_sequence_encode
|
||||
*
|
||||
* @param[in,out] s packet stream TLV is stored to
|
||||
*
|
||||
* @return u_int16_t number of bytes added to packet stream
|
||||
*
|
||||
* @par
|
||||
* Part of conditional receive process
|
||||
*
|
||||
*/
|
||||
static u_int16_t
|
||||
eigrp_sequence_encode (struct stream *s)
|
||||
{
|
||||
u_int16_t length = EIGRP_TLV_SEQ_BASE_LEN;
|
||||
struct eigrp *eigrp;
|
||||
struct eigrp_interface *ei;
|
||||
struct listnode *node, *node2, *nnode2;
|
||||
struct eigrp_neighbor *nbr;
|
||||
size_t backup_end, size_end;
|
||||
int found;
|
||||
|
||||
eigrp = eigrp_lookup ();
|
||||
if (eigrp == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// add in the parameters TLV
|
||||
backup_end = stream_get_endp(s);
|
||||
stream_putw(s, EIGRP_TLV_SEQ);
|
||||
size_end = s->endp;
|
||||
stream_putw(s, 0x0000);
|
||||
stream_putc(s, IPV4_MAX_BYTELEN);
|
||||
|
||||
found = 0;
|
||||
for (ALL_LIST_ELEMENTS_RO (eigrp->eiflist, node, ei))
|
||||
{
|
||||
for (ALL_LIST_ELEMENTS (ei->nbrs, node2, nnode2, nbr))
|
||||
{
|
||||
if(nbr->multicast_queue->count > 0)
|
||||
{
|
||||
length += (u_int16_t) stream_put_ipv4(s,nbr->src.s_addr);
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(found == 0)
|
||||
{
|
||||
stream_set_endp(s,backup_end);
|
||||
return 0;
|
||||
}
|
||||
|
||||
backup_end = stream_get_endp (s);
|
||||
stream_set_endp (s,size_end);
|
||||
stream_putw (s, length);
|
||||
stream_set_endp (s, backup_end);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn eigrp_sequence_encode
|
||||
*
|
||||
* @param[in,out] s packet stream TLV is stored to
|
||||
*
|
||||
* @return u_int16_t number of bytes added to packet stream
|
||||
*
|
||||
* @par
|
||||
* Part of conditional receive process
|
||||
*
|
||||
*/
|
||||
static u_int16_t
|
||||
eigrp_next_sequence_encode (struct stream *s)
|
||||
{
|
||||
u_int16_t length = EIGRP_NEXT_SEQUENCE_TLV_SIZE;
|
||||
struct eigrp *eigrp;
|
||||
|
||||
eigrp = eigrp_lookup ();
|
||||
if (eigrp == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// add in the parameters TLV
|
||||
stream_putw(s, EIGRP_TLV_NEXT_MCAST_SEQ);
|
||||
stream_putw(s, EIGRP_NEXT_SEQUENCE_TLV_SIZE);
|
||||
stream_putl(s,eigrp->sequence_number+1);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn eigrp_hello_parameter_encode
|
||||
*
|
||||
* @param[in] ei pointer to interface hello packet came in on
|
||||
* @param[in,out] s packet stream TLV is stored to
|
||||
*
|
||||
* @return u_int16_t number of bytes added to packet stream
|
||||
*
|
||||
* @par
|
||||
* Encode Parameter TLV, used to convey metric weights and the hold time.
|
||||
*
|
||||
* @usage
|
||||
* Note the addition of K6 for the new extended metrics, and does not apply to
|
||||
* older TLV packet formats.
|
||||
*/
|
||||
static u_int16_t
|
||||
eigrp_hello_parameter_encode (struct eigrp_interface *ei, struct stream *s, u_char flags)
|
||||
{
|
||||
u_int16_t length = EIGRP_TLV_PARAMETER_LEN;
|
||||
|
||||
// add in the parameters TLV
|
||||
stream_putw(s, EIGRP_TLV_PARAMETER);
|
||||
stream_putw(s, EIGRP_TLV_PARAMETER_LEN);
|
||||
|
||||
//if graceful shutdown is needed to be announced, send all 255 in K values
|
||||
if(flags & EIGRP_HELLO_GRACEFUL_SHUTDOWN)
|
||||
{
|
||||
stream_putc(s, 0xff); /* K1 */
|
||||
stream_putc(s, 0xff); /* K2 */
|
||||
stream_putc(s, 0xff); /* K3 */
|
||||
stream_putc(s, 0xff); /* K4 */
|
||||
stream_putc(s, 0xff); /* K5 */
|
||||
stream_putc(s, 0xff); /* K6 */
|
||||
}
|
||||
else // set k values
|
||||
{
|
||||
stream_putc(s, ei->eigrp->k_values[0]); /* K1 */
|
||||
stream_putc(s, ei->eigrp->k_values[1]); /* K2 */
|
||||
stream_putc(s, ei->eigrp->k_values[2]); /* K3 */
|
||||
stream_putc(s, ei->eigrp->k_values[3]); /* K4 */
|
||||
stream_putc(s, ei->eigrp->k_values[4]); /* K5 */
|
||||
stream_putc(s, ei->eigrp->k_values[5]); /* K6 */
|
||||
}
|
||||
|
||||
// and set hold time value..
|
||||
stream_putw(s, IF_DEF_PARAMS(ei->ifp)->v_wait);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn eigrp_hello_encode
|
||||
*
|
||||
* @param[in] ei pointer to interface hello packet came in on
|
||||
* @param[in] s packet stream TLV is stored to
|
||||
* @param[in] ack if non-zero, neigbors sequence packet to ack
|
||||
* @param[in] flags type of hello packet
|
||||
* @param[in] nbr_addr pointer to neighbor address for Peer Termination TLV
|
||||
*
|
||||
* @return eigrp_packet pointer initialize hello packet
|
||||
*
|
||||
* @par
|
||||
* Allocate an EIGRP hello packet, and add in the the approperate TLVs
|
||||
*
|
||||
*/
|
||||
static struct eigrp_packet *
|
||||
eigrp_hello_encode (struct eigrp_interface *ei, in_addr_t addr, u_int32_t ack, u_char flags, struct in_addr *nbr_addr)
|
||||
{
|
||||
struct eigrp_packet *ep;
|
||||
u_int16_t length = EIGRP_HEADER_LEN;
|
||||
|
||||
// allocate a new packet to be sent
|
||||
ep = eigrp_packet_new(ei->ifp->mtu);
|
||||
|
||||
if (ep)
|
||||
{
|
||||
// encode common header feilds
|
||||
eigrp_packet_header_init(EIGRP_OPC_HELLO, ei, ep->s, 0, 0, ack);
|
||||
|
||||
// encode Authentication TLV
|
||||
if((IF_DEF_PARAMS (ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (ei->ifp)->auth_keychain != NULL))
|
||||
{
|
||||
length += eigrp_add_authTLV_MD5_to_stream(ep->s,ei);
|
||||
}
|
||||
else if((IF_DEF_PARAMS (ei->ifp)->auth_type == EIGRP_AUTH_TYPE_SHA256) && (IF_DEF_PARAMS (ei->ifp)->auth_keychain != NULL))
|
||||
{
|
||||
length += eigrp_add_authTLV_SHA256_to_stream(ep->s,ei);
|
||||
}
|
||||
|
||||
/* encode appropriate parameters to Hello packet */
|
||||
if(flags & EIGRP_HELLO_GRACEFUL_SHUTDOWN)
|
||||
length += eigrp_hello_parameter_encode(ei, ep->s, EIGRP_HELLO_GRACEFUL_SHUTDOWN);
|
||||
else
|
||||
length += eigrp_hello_parameter_encode(ei, ep->s, EIGRP_HELLO_NORMAL);
|
||||
|
||||
// figure out the version of code we're running
|
||||
length += eigrp_sw_version_encode(ep->s);
|
||||
|
||||
if(flags & EIGRP_HELLO_ADD_SEQUENCE)
|
||||
{
|
||||
length += eigrp_sequence_encode(ep->s);
|
||||
length += eigrp_next_sequence_encode(ep->s);
|
||||
}
|
||||
|
||||
// add in the TID list if doing multi-topology
|
||||
length += eigrp_tidlist_encode(ep->s);
|
||||
|
||||
/* encode Peer Termination TLV if needed */
|
||||
if(flags & EIGRP_HELLO_GRACEFUL_SHUTDOWN_NBR)
|
||||
length += eigrp_peer_termination_encode(ep->s, nbr_addr);
|
||||
|
||||
// Set packet length
|
||||
ep->length = length;
|
||||
|
||||
// set soruce address for the hello packet
|
||||
ep->dst.s_addr = addr;
|
||||
|
||||
if((IF_DEF_PARAMS (ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (ei->ifp)->auth_keychain != NULL))
|
||||
{
|
||||
eigrp_make_md5_digest(ei,ep->s, EIGRP_AUTH_BASIC_HELLO_FLAG);
|
||||
}
|
||||
else if((IF_DEF_PARAMS (ei->ifp)->auth_type == EIGRP_AUTH_TYPE_SHA256) && (IF_DEF_PARAMS (ei->ifp)->auth_keychain != NULL))
|
||||
{
|
||||
eigrp_make_sha256_digest(ei,ep->s, EIGRP_AUTH_BASIC_HELLO_FLAG);
|
||||
}
|
||||
|
||||
// EIGRP Checksum
|
||||
eigrp_packet_checksum(ei, ep->s, length);
|
||||
}
|
||||
|
||||
return(ep);
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn eigrp_hello_send
|
||||
*
|
||||
* @param[in] nbr neighbor the ACK should be sent to
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @par
|
||||
* Send (unicast) a hello packet with the destination address
|
||||
* associated with the neighbor. The eigrp header ACK feild will be
|
||||
* updated to the neighbor's sequence number to acknolodge any
|
||||
* outstanding packets
|
||||
*/
|
||||
void
|
||||
eigrp_hello_send_ack (struct eigrp_neighbor *nbr)
|
||||
{
|
||||
struct eigrp_packet *ep;
|
||||
|
||||
/* if packet succesfully created, add it to the interface queue */
|
||||
ep = eigrp_hello_encode(nbr->ei, nbr->src.s_addr, nbr->recv_sequence_number, EIGRP_HELLO_NORMAL, NULL);
|
||||
|
||||
if (ep)
|
||||
{
|
||||
if (IS_DEBUG_EIGRP_PACKET(0, SEND))
|
||||
zlog_debug("Queueing [Hello] Ack Seq [%u] nbr [%s]",
|
||||
nbr->recv_sequence_number, inet_ntoa(nbr->src));
|
||||
|
||||
/* Add packet to the top of the interface output queue*/
|
||||
eigrp_fifo_push_head(nbr->ei->obuf, ep);
|
||||
|
||||
/* Hook thread to write packet. */
|
||||
if (nbr->ei->on_write_q == 0)
|
||||
{
|
||||
listnode_add(nbr->ei->eigrp->oi_write_q, nbr->ei);
|
||||
nbr->ei->on_write_q = 1;
|
||||
}
|
||||
if (nbr->ei->eigrp->t_write == NULL)
|
||||
nbr->ei->eigrp->t_write =
|
||||
thread_add_write(master, eigrp_write, nbr->ei->eigrp, nbr->ei->eigrp->fd);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn eigrp_hello_send
|
||||
*
|
||||
* @param[in] ei pointer to interface hello should be sent
|
||||
* @param[in] flags type of hello packet
|
||||
* @param[in] nbr_addr pointer to neighbor address for Peer Termination TLV
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @par
|
||||
* Build and enqueue a generic (multicast) periodic hello packet for
|
||||
* sending. If no packets are currently queues, the packet will be
|
||||
* sent immadiatly
|
||||
*/
|
||||
void
|
||||
eigrp_hello_send (struct eigrp_interface *ei, u_char flags, struct in_addr *nbr_addr)
|
||||
{
|
||||
struct eigrp_packet *ep = NULL;
|
||||
|
||||
/* If this is passive interface, do not send EIGRP Hello.
|
||||
if ((EIGRP_IF_PASSIVE_STATUS (ei) == EIGRP_IF_PASSIVE) ||
|
||||
(ei->type != EIGRP_IFTYPE_NBMA))
|
||||
return;
|
||||
*/
|
||||
|
||||
if (IS_DEBUG_EIGRP_PACKET(0, SEND))
|
||||
zlog_debug("Queueing [Hello] Interface(%s)", IF_NAME(ei));
|
||||
|
||||
/* if packet was succesfully created, then add it to the interface queue */
|
||||
ep = eigrp_hello_encode(ei, htonl(EIGRP_MULTICAST_ADDRESS), 0, flags, nbr_addr);
|
||||
|
||||
if (ep)
|
||||
{
|
||||
// Add packet to the top of the interface output queue
|
||||
eigrp_fifo_push_head(ei->obuf, ep);
|
||||
|
||||
/* Hook thread to write packet. */
|
||||
if (ei->on_write_q == 0)
|
||||
{
|
||||
listnode_add(ei->eigrp->oi_write_q, ei);
|
||||
ei->on_write_q = 1;
|
||||
}
|
||||
|
||||
if (ei->eigrp->t_write == NULL)
|
||||
{
|
||||
if(flags & EIGRP_HELLO_GRACEFUL_SHUTDOWN)
|
||||
{
|
||||
ei->eigrp->t_write =
|
||||
thread_execute(master, eigrp_write, ei->eigrp, ei->eigrp->fd);
|
||||
}
|
||||
else
|
||||
{
|
||||
ei->eigrp->t_write =
|
||||
thread_add_write(master, eigrp_write, ei->eigrp, ei->eigrp->fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
613
eigrpd/eigrp_interface.c
Normal file
613
eigrpd/eigrp_interface.c
Normal file
|
@ -0,0 +1,613 @@
|
|||
/*
|
||||
* EIGRP Interface Functions.
|
||||
* Copyright (C) 2013-2016
|
||||
* Authors:
|
||||
* Donnie Savage
|
||||
* Jan Janovic
|
||||
* Matej Perina
|
||||
* Peter Orsag
|
||||
* Peter Paluch
|
||||
* Frantisek Gazo
|
||||
* Tomas Hvorkovy
|
||||
* Martin Kontsek
|
||||
* Lukas Koribsky
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#include "thread.h"
|
||||
#include "linklist.h"
|
||||
#include "prefix.h"
|
||||
#include "if.h"
|
||||
#include "table.h"
|
||||
#include "memory.h"
|
||||
#include "command.h"
|
||||
#include "stream.h"
|
||||
#include "log.h"
|
||||
#include "keychain.h"
|
||||
#include "vrf.h"
|
||||
|
||||
#include "eigrpd/eigrp_structs.h"
|
||||
#include "eigrpd/eigrpd.h"
|
||||
#include "eigrpd/eigrp_interface.h"
|
||||
#include "eigrpd/eigrp_neighbor.h"
|
||||
#include "eigrpd/eigrp_packet.h"
|
||||
#include "eigrpd/eigrp_zebra.h"
|
||||
#include "eigrpd/eigrp_vty.h"
|
||||
#include "eigrpd/eigrp_network.h"
|
||||
#include "eigrpd/eigrp_topology.h"
|
||||
#include "eigrpd/eigrp_memory.h"
|
||||
|
||||
static void
|
||||
eigrp_delete_from_if (struct interface *, struct eigrp_interface *);
|
||||
|
||||
static void
|
||||
eigrp_add_to_if (struct interface *ifp, struct eigrp_interface *ei)
|
||||
{
|
||||
struct route_node *rn;
|
||||
struct prefix p;
|
||||
|
||||
p = *ei->address;
|
||||
p.prefixlen = IPV4_MAX_PREFIXLEN;
|
||||
|
||||
rn = route_node_get (IF_OIFS (ifp), &p);
|
||||
/* rn->info should either be NULL or equal to this ei
|
||||
* as route_node_get may return an existing node
|
||||
*/
|
||||
assert (!rn->info || rn->info == ei);
|
||||
rn->info = ei;
|
||||
}
|
||||
|
||||
struct eigrp_interface *
|
||||
eigrp_if_new (struct eigrp *eigrp, struct interface *ifp, struct prefix *p)
|
||||
{
|
||||
struct eigrp_interface *ei;
|
||||
int i;
|
||||
|
||||
if ((ei = eigrp_if_table_lookup (ifp, p)) == NULL)
|
||||
{
|
||||
ei = XCALLOC (MTYPE_EIGRP_IF, sizeof (struct eigrp_interface));
|
||||
memset (ei, 0, sizeof (struct eigrp_interface));
|
||||
}
|
||||
else
|
||||
return ei;
|
||||
|
||||
/* Set zebra interface pointer. */
|
||||
ei->ifp = ifp;
|
||||
ei->address = p;
|
||||
|
||||
eigrp_add_to_if (ifp, ei);
|
||||
listnode_add (eigrp->eiflist, ei);
|
||||
|
||||
ei->type = EIGRP_IFTYPE_BROADCAST;
|
||||
|
||||
/* Initialize neighbor list. */
|
||||
ei->nbrs = list_new ();
|
||||
|
||||
ei->crypt_seqnum = time (NULL);
|
||||
|
||||
/* Initialize lists */
|
||||
for (i = 0; i < EIGRP_FILTER_MAX; i++)
|
||||
{
|
||||
ei->list[i] = NULL;
|
||||
ei->prefix[i] = NULL;
|
||||
ei->routemap[i] = NULL;
|
||||
}
|
||||
|
||||
return ei;
|
||||
}
|
||||
|
||||
/* lookup ei for specified prefix/ifp */
|
||||
struct eigrp_interface *
|
||||
eigrp_if_table_lookup (struct interface *ifp, struct prefix *prefix)
|
||||
{
|
||||
struct prefix p;
|
||||
struct route_node *rn;
|
||||
struct eigrp_interface *rninfo = NULL;
|
||||
|
||||
p = *prefix;
|
||||
p.prefixlen = IPV4_MAX_PREFIXLEN;
|
||||
|
||||
/* route_node_get implicitly locks */
|
||||
if ((rn = route_node_lookup (IF_OIFS (ifp), &p)))
|
||||
{
|
||||
rninfo = (struct eigrp_interface *) rn->info;
|
||||
route_unlock_node (rn);
|
||||
}
|
||||
|
||||
return rninfo;
|
||||
}
|
||||
|
||||
int
|
||||
eigrp_if_delete_hook (struct interface *ifp)
|
||||
{
|
||||
|
||||
struct route_node *rn;
|
||||
|
||||
route_table_finish (IF_OIFS (ifp));
|
||||
|
||||
for (rn = route_top (IF_OIFS_PARAMS (ifp)); rn; rn = route_next (rn))
|
||||
if (rn->info)
|
||||
eigrp_del_if_params (rn->info);
|
||||
route_table_finish (IF_OIFS_PARAMS (ifp));
|
||||
|
||||
XFREE (MTYPE_EIGRP_IF_INFO, ifp->info);
|
||||
ifp->info = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct list *eigrp_iflist;
|
||||
|
||||
void
|
||||
eigrp_if_init ()
|
||||
{
|
||||
/* Initialize Zebra interface data structure. */
|
||||
if_add_hook (IF_NEW_HOOK, eigrp_if_new_hook);
|
||||
if_add_hook (IF_DELETE_HOOK, eigrp_if_delete_hook);
|
||||
}
|
||||
|
||||
int
|
||||
eigrp_if_new_hook (struct interface *ifp)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
ifp->info = XCALLOC (MTYPE_EIGRP_IF_INFO, sizeof (struct eigrp_if_info));
|
||||
|
||||
IF_OIFS (ifp) = route_table_init ();
|
||||
IF_OIFS_PARAMS (ifp) = route_table_init ();
|
||||
|
||||
IF_DEF_PARAMS (ifp) = eigrp_new_if_params ();
|
||||
|
||||
SET_IF_PARAM (IF_DEF_PARAMS (ifp), v_hello);
|
||||
IF_DEF_PARAMS (ifp)->v_hello = (u_int32_t) EIGRP_HELLO_INTERVAL_DEFAULT;
|
||||
|
||||
SET_IF_PARAM (IF_DEF_PARAMS (ifp), v_wait);
|
||||
IF_DEF_PARAMS (ifp)->v_wait = (u_int16_t) EIGRP_HOLD_INTERVAL_DEFAULT;
|
||||
|
||||
SET_IF_PARAM (IF_DEF_PARAMS (ifp), bandwidth);
|
||||
IF_DEF_PARAMS (ifp)->bandwidth = (u_int32_t) EIGRP_BANDWIDTH_DEFAULT;
|
||||
|
||||
SET_IF_PARAM (IF_DEF_PARAMS (ifp), delay);
|
||||
IF_DEF_PARAMS (ifp)->delay = (u_int32_t) EIGRP_DELAY_DEFAULT;
|
||||
|
||||
SET_IF_PARAM (IF_DEF_PARAMS (ifp), reliability);
|
||||
IF_DEF_PARAMS (ifp)->reliability = (u_char) EIGRP_RELIABILITY_DEFAULT;
|
||||
|
||||
SET_IF_PARAM (IF_DEF_PARAMS (ifp), load);
|
||||
IF_DEF_PARAMS (ifp)->load = (u_char) EIGRP_LOAD_DEFAULT;
|
||||
|
||||
SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_type);
|
||||
IF_DEF_PARAMS (ifp)->auth_type = EIGRP_AUTH_TYPE_NONE;
|
||||
|
||||
SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_keychain);
|
||||
IF_DEF_PARAMS (ifp)->auth_keychain= NULL;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
struct eigrp_if_params *
|
||||
eigrp_new_if_params (void)
|
||||
{
|
||||
struct eigrp_if_params *eip;
|
||||
|
||||
eip = XCALLOC (MTYPE_EIGRP_IF_PARAMS, sizeof (struct eigrp_if_params));
|
||||
if (!eip)
|
||||
return NULL;
|
||||
|
||||
UNSET_IF_PARAM (eip, passive_interface);
|
||||
UNSET_IF_PARAM (eip, v_hello);
|
||||
UNSET_IF_PARAM (eip, v_wait);
|
||||
UNSET_IF_PARAM (eip, bandwidth);
|
||||
UNSET_IF_PARAM (eip, delay);
|
||||
UNSET_IF_PARAM (eip, reliability);
|
||||
UNSET_IF_PARAM (eip, load);
|
||||
UNSET_IF_PARAM (eip, auth_keychain);
|
||||
UNSET_IF_PARAM (eip, auth_type);
|
||||
|
||||
|
||||
return eip;
|
||||
}
|
||||
|
||||
void
|
||||
eigrp_del_if_params (struct eigrp_if_params *eip)
|
||||
{
|
||||
if(eip->auth_keychain)
|
||||
free(eip->auth_keychain);
|
||||
|
||||
XFREE (MTYPE_EIGRP_IF_PARAMS, eip);
|
||||
}
|
||||
|
||||
struct eigrp_if_params *
|
||||
eigrp_lookup_if_params (struct interface *ifp, struct in_addr addr)
|
||||
{
|
||||
struct prefix_ipv4 p;
|
||||
struct route_node *rn;
|
||||
|
||||
p.family = AF_INET;
|
||||
p.prefixlen = IPV4_MAX_PREFIXLEN;
|
||||
p.prefix = addr;
|
||||
|
||||
rn = route_node_lookup (IF_OIFS_PARAMS (ifp), (struct prefix*) &p);
|
||||
|
||||
if (rn)
|
||||
{
|
||||
route_unlock_node (rn);
|
||||
return rn->info;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
eigrp_if_up (struct eigrp_interface *ei)
|
||||
{
|
||||
struct eigrp_prefix_entry *pe;
|
||||
struct eigrp_neighbor_entry *ne;
|
||||
struct eigrp_metrics metric;
|
||||
struct eigrp_interface *ei2;
|
||||
struct listnode *node, *nnode;
|
||||
struct eigrp *eigrp = eigrp_lookup ();
|
||||
|
||||
if (ei == NULL)
|
||||
return 0;
|
||||
|
||||
if (eigrp != NULL)
|
||||
eigrp_adjust_sndbuflen (eigrp, ei->ifp->mtu);
|
||||
else
|
||||
zlog_warn ("%s: eigrp_lookup () returned NULL", __func__);
|
||||
eigrp_if_stream_set (ei);
|
||||
|
||||
/* Set multicast memberships appropriately for new state. */
|
||||
eigrp_if_set_multicast (ei);
|
||||
|
||||
thread_add_event (master, eigrp_hello_timer, ei, (1));
|
||||
|
||||
/*Prepare metrics*/
|
||||
metric.bandwith = eigrp_bandwidth_to_scaled (EIGRP_IF_PARAM (ei,bandwidth));
|
||||
metric.delay = eigrp_delay_to_scaled (EIGRP_IF_PARAM (ei,delay));
|
||||
metric.load = EIGRP_IF_PARAM (ei,load);
|
||||
metric.reliability = EIGRP_IF_PARAM (ei,reliability);
|
||||
metric.mtu[0] = 0xDC;
|
||||
metric.mtu[1] = 0x05;
|
||||
metric.mtu[2] = 0x00;
|
||||
metric.hop_count = 0;
|
||||
metric.flags = 0;
|
||||
metric.tag = 0;
|
||||
|
||||
/*Add connected entry to topology table*/
|
||||
|
||||
struct prefix_ipv4 *dest_addr = prefix_ipv4_new ();
|
||||
|
||||
dest_addr->family = AF_INET;
|
||||
dest_addr->prefix = ei->connected->address->u.prefix4;
|
||||
dest_addr->prefixlen = ei->connected->address->prefixlen;
|
||||
apply_mask_ipv4 (dest_addr);
|
||||
pe = eigrp_topology_table_lookup_ipv4 (eigrp->topology_table, dest_addr);
|
||||
|
||||
if (pe == NULL)
|
||||
{
|
||||
pe = eigrp_prefix_entry_new ();
|
||||
pe->serno = eigrp->serno;
|
||||
pe->destination_ipv4 = dest_addr;
|
||||
pe->af = AF_INET;
|
||||
pe->nt = EIGRP_TOPOLOGY_TYPE_CONNECTED;
|
||||
|
||||
pe->state = EIGRP_FSM_STATE_PASSIVE;
|
||||
pe->fdistance = eigrp_calculate_metrics (eigrp, &metric);
|
||||
pe->req_action |= EIGRP_FSM_NEED_UPDATE;
|
||||
eigrp_prefix_entry_add (eigrp->topology_table, pe);
|
||||
listnode_add(eigrp->topology_changes_internalIPV4, pe);
|
||||
}
|
||||
ne = eigrp_neighbor_entry_new ();
|
||||
ne->ei = ei;
|
||||
ne->reported_metric = metric;
|
||||
ne->total_metric = metric;
|
||||
ne->distance = eigrp_calculate_metrics (eigrp, &metric);
|
||||
ne->reported_distance = 0;
|
||||
ne->prefix = pe;
|
||||
ne->adv_router = eigrp->neighbor_self;
|
||||
ne->flags = EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG;
|
||||
eigrp_neighbor_entry_add (pe, ne);
|
||||
|
||||
for (ALL_LIST_ELEMENTS (eigrp->eiflist, node, nnode, ei2))
|
||||
{
|
||||
if (ei2->nbrs->count != 0)
|
||||
{
|
||||
eigrp_update_send (ei2);
|
||||
}
|
||||
}
|
||||
|
||||
pe->req_action &= ~EIGRP_FSM_NEED_UPDATE;
|
||||
listnode_delete(eigrp->topology_changes_internalIPV4, pe);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
eigrp_if_down (struct eigrp_interface *ei)
|
||||
{
|
||||
struct listnode *node, *nnode;
|
||||
struct eigrp_neighbor *nbr;
|
||||
|
||||
if (ei == NULL)
|
||||
return 0;
|
||||
|
||||
/* Shutdown packet reception and sending */
|
||||
if(ei->t_hello)
|
||||
THREAD_OFF (ei->t_hello);
|
||||
|
||||
eigrp_if_stream_unset (ei);
|
||||
|
||||
/*Set infinite metrics to routes learned by this interface and start query process*/
|
||||
for (ALL_LIST_ELEMENTS (ei->nbrs, node, nnode, nbr))
|
||||
{
|
||||
eigrp_nbr_delete(nbr);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
eigrp_if_stream_set (struct eigrp_interface *ei)
|
||||
{
|
||||
/* set output fifo queue. */
|
||||
if (ei->obuf == NULL)
|
||||
ei->obuf = eigrp_fifo_new ();
|
||||
}
|
||||
|
||||
void
|
||||
eigrp_if_stream_unset (struct eigrp_interface *ei)
|
||||
{
|
||||
struct eigrp *eigrp = ei->eigrp;
|
||||
|
||||
if (ei->obuf)
|
||||
{
|
||||
eigrp_fifo_free (ei->obuf);
|
||||
ei->obuf = NULL;
|
||||
|
||||
if (ei->on_write_q)
|
||||
{
|
||||
listnode_delete (eigrp->oi_write_q, ei);
|
||||
if (list_isempty (eigrp->oi_write_q))
|
||||
thread_cancel (eigrp->t_write);
|
||||
ei->on_write_q = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
eigrp_if_set_multicast (struct eigrp_interface *ei)
|
||||
{
|
||||
if ((EIGRP_IF_PASSIVE_STATUS (ei) == EIGRP_IF_ACTIVE))
|
||||
{
|
||||
/* The interface should belong to the EIGRP-all-routers group. */
|
||||
if (!EI_MEMBER_CHECK (ei, MEMBER_ALLROUTERS)
|
||||
&& (eigrp_if_add_allspfrouters (ei->eigrp, ei->address,
|
||||
ei->ifp->ifindex) >= 0))
|
||||
/* Set the flag only if the system call to join succeeded. */
|
||||
EI_MEMBER_JOINED (ei, MEMBER_ALLROUTERS);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The interface should NOT belong to the EIGRP-all-routers group. */
|
||||
if (EI_MEMBER_CHECK (ei, MEMBER_ALLROUTERS))
|
||||
{
|
||||
/* Only actually drop if this is the last reference */
|
||||
if (EI_MEMBER_COUNT (ei, MEMBER_ALLROUTERS) == 1)
|
||||
eigrp_if_drop_allspfrouters (ei->eigrp, ei->address,
|
||||
ei->ifp->ifindex);
|
||||
/* Unset the flag regardless of whether the system call to leave
|
||||
the group succeeded, since it's much safer to assume that
|
||||
we are not a member. */
|
||||
EI_MEMBER_LEFT (ei, MEMBER_ALLROUTERS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u_char
|
||||
eigrp_default_iftype (struct interface *ifp)
|
||||
{
|
||||
if (if_is_pointopoint (ifp))
|
||||
return EIGRP_IFTYPE_POINTOPOINT;
|
||||
else if (if_is_loopback (ifp))
|
||||
return EIGRP_IFTYPE_LOOPBACK;
|
||||
else
|
||||
return EIGRP_IFTYPE_BROADCAST;
|
||||
}
|
||||
|
||||
void
|
||||
eigrp_if_free (struct eigrp_interface *ei, int source)
|
||||
{
|
||||
|
||||
if (source == INTERFACE_DOWN_BY_VTY)
|
||||
{
|
||||
THREAD_OFF (ei->t_hello);
|
||||
eigrp_hello_send(ei,EIGRP_HELLO_GRACEFUL_SHUTDOWN, NULL);
|
||||
}
|
||||
|
||||
eigrp_if_down (ei);
|
||||
|
||||
list_delete (ei->nbrs);
|
||||
eigrp_delete_from_if (ei->ifp, ei);
|
||||
listnode_delete (ei->eigrp->eiflist, ei);
|
||||
|
||||
thread_cancel_event (master, ei);
|
||||
|
||||
memset (ei, 0, sizeof (*ei));
|
||||
XFREE (MTYPE_EIGRP_IF, ei);
|
||||
}
|
||||
|
||||
static void
|
||||
eigrp_delete_from_if (struct interface *ifp, struct eigrp_interface *ei)
|
||||
{
|
||||
struct route_node *rn;
|
||||
struct prefix p;
|
||||
|
||||
p = *ei->address;
|
||||
p.prefixlen = IPV4_MAX_PREFIXLEN;
|
||||
|
||||
rn = route_node_lookup (IF_OIFS (ei->ifp), &p);
|
||||
assert (rn);
|
||||
assert (rn->info);
|
||||
rn->info = NULL;
|
||||
route_unlock_node (rn);
|
||||
route_unlock_node (rn);
|
||||
}
|
||||
|
||||
/* Simulate down/up on the interface. This is needed, for example, when
|
||||
the MTU changes. */
|
||||
void
|
||||
eigrp_if_reset (struct interface *ifp)
|
||||
{
|
||||
struct route_node *rn;
|
||||
|
||||
for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
|
||||
{
|
||||
struct eigrp_interface *ei;
|
||||
|
||||
if ((ei = rn->info) == NULL)
|
||||
continue;
|
||||
|
||||
eigrp_if_down (ei);
|
||||
eigrp_if_up (ei);
|
||||
}
|
||||
}
|
||||
|
||||
struct eigrp_interface *
|
||||
eigrp_if_lookup_by_local_addr (struct eigrp *eigrp, struct interface *ifp,
|
||||
struct in_addr address)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct eigrp_interface *ei;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO (eigrp->eiflist, node, ei))
|
||||
{
|
||||
if (ifp && ei->ifp != ifp)
|
||||
continue;
|
||||
|
||||
if (IPV4_ADDR_SAME (&address, &ei->address->u.prefix4))
|
||||
return ei;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn eigrp_if_lookup_by_name
|
||||
*
|
||||
* @param[in] eigrp EIGRP process
|
||||
* @param[in] if_name Name of the interface
|
||||
*
|
||||
* @return struct eigrp_interface *
|
||||
*
|
||||
* @par
|
||||
* Function is used for lookup interface by name.
|
||||
*/
|
||||
struct eigrp_interface *
|
||||
eigrp_if_lookup_by_name (struct eigrp *eigrp, const char *if_name)
|
||||
{
|
||||
struct eigrp_interface *ei;
|
||||
struct listnode *node;
|
||||
|
||||
/* iterate over all eigrp interfaces */
|
||||
for (ALL_LIST_ELEMENTS_RO (eigrp->eiflist, node, ei))
|
||||
{
|
||||
/* compare int name with eigrp interface's name */
|
||||
if(strcmp(ei->ifp->name, if_name) == 0)
|
||||
{
|
||||
return ei;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* determine receiving interface by ifp and source address */
|
||||
struct eigrp_interface *
|
||||
eigrp_if_lookup_recv_if (struct eigrp *eigrp, struct in_addr src,
|
||||
struct interface *ifp)
|
||||
{
|
||||
struct route_node *rn;
|
||||
struct prefix_ipv4 addr;
|
||||
struct eigrp_interface *ei, *match;
|
||||
|
||||
addr.family = AF_INET;
|
||||
addr.prefix = src;
|
||||
addr.prefixlen = IPV4_MAX_BITLEN;
|
||||
|
||||
match = NULL;
|
||||
|
||||
for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
|
||||
{
|
||||
ei = rn->info;
|
||||
|
||||
if (!ei) /* oi can be NULL for PtP aliases */
|
||||
continue;
|
||||
|
||||
if (if_is_loopback (ei->ifp))
|
||||
continue;
|
||||
|
||||
if (prefix_match (CONNECTED_PREFIX (ei->connected),
|
||||
(struct prefix *) &addr))
|
||||
{
|
||||
if ((match == NULL)
|
||||
|| (match->address->prefixlen < ei->address->prefixlen))
|
||||
match = ei;
|
||||
}
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
u_int32_t
|
||||
eigrp_bandwidth_to_scaled (u_int32_t bandwidth)
|
||||
{
|
||||
u_int64_t temp_bandwidth = (256ull * 10000000) / bandwidth;
|
||||
|
||||
temp_bandwidth =
|
||||
temp_bandwidth < EIGRP_MAX_METRIC ? temp_bandwidth : EIGRP_MAX_METRIC;
|
||||
|
||||
return (u_int32_t) temp_bandwidth;
|
||||
|
||||
}
|
||||
|
||||
u_int32_t
|
||||
eigrp_scaled_to_bandwidth (u_int32_t scaled)
|
||||
{
|
||||
u_int64_t temp_scaled = scaled * (256ull * 10000000);
|
||||
|
||||
temp_scaled =
|
||||
temp_scaled < EIGRP_MAX_METRIC ? temp_scaled : EIGRP_MAX_METRIC;
|
||||
|
||||
return (u_int32_t) temp_scaled;
|
||||
}
|
||||
|
||||
u_int32_t
|
||||
eigrp_delay_to_scaled (u_int32_t delay)
|
||||
{
|
||||
return delay * 256;
|
||||
}
|
||||
|
||||
u_int32_t
|
||||
eigrp_scaled_to_delay (u_int32_t scaled)
|
||||
{
|
||||
return scaled / 256;
|
||||
}
|
73
eigrpd/eigrp_interface.h
Normal file
73
eigrpd/eigrp_interface.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* EIGRP Interface Functions.
|
||||
* Copyright (C) 2013-2016
|
||||
* Authors:
|
||||
* Donnie Savage
|
||||
* Jan Janovic
|
||||
* Matej Perina
|
||||
* Peter Orsag
|
||||
* Peter Paluch
|
||||
* Frantisek Gazo
|
||||
* Tomas Hvorkovy
|
||||
* Martin Kontsek
|
||||
* Lukas Koribsky
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _ZEBRA_EIGRP_INTERFACE_H_
|
||||
#define _ZEBRA_EIGRP_INTERFACE_H_
|
||||
|
||||
/*Prototypes*/
|
||||
extern void eigrp_if_init (void);
|
||||
extern int eigrp_if_new_hook (struct interface *);
|
||||
extern int eigrp_if_delete_hook (struct interface *);
|
||||
|
||||
extern void eigrp_del_if_params (struct eigrp_if_params *);
|
||||
extern struct eigrp_if_params *eigrp_new_if_params (void);
|
||||
extern struct eigrp_interface * eigrp_if_new (struct eigrp *, struct interface *,
|
||||
struct prefix *);
|
||||
extern struct eigrp_interface * eigrp_if_table_lookup (struct interface *,
|
||||
struct prefix *);
|
||||
extern struct eigrp_if_params *eigrp_lookup_if_params (struct interface *,
|
||||
struct in_addr);
|
||||
extern int eigrp_if_up (struct eigrp_interface *);
|
||||
extern void eigrp_if_stream_set (struct eigrp_interface *);
|
||||
extern void eigrp_if_set_multicast (struct eigrp_interface *);
|
||||
extern u_char eigrp_default_iftype (struct interface *);
|
||||
extern void eigrp_if_free (struct eigrp_interface *, int);
|
||||
extern int eigrp_if_down (struct eigrp_interface *);
|
||||
extern void eigrp_if_stream_unset (struct eigrp_interface *);
|
||||
|
||||
extern struct eigrp_interface *eigrp_if_lookup_by_local_addr (struct eigrp *,
|
||||
struct interface *,
|
||||
struct in_addr);
|
||||
extern struct eigrp_interface *eigrp_if_lookup_by_name (struct eigrp *, const char *);
|
||||
struct eigrp_interface * eigrp_if_lookup_recv_if (struct eigrp *, struct in_addr,
|
||||
struct interface *);
|
||||
|
||||
/* Simulate down/up on the interface. */
|
||||
extern void eigrp_if_reset (struct interface *);
|
||||
|
||||
extern u_int32_t eigrp_bandwidth_to_scaled (u_int32_t);
|
||||
extern u_int32_t eigrp_scaled_to_bandwidth (u_int32_t);
|
||||
extern u_int32_t eigrp_delay_to_scaled (u_int32_t);
|
||||
extern u_int32_t eigrp_scaled_to_delay (u_int32_t);
|
||||
|
||||
|
||||
#endif /* ZEBRA_EIGRP_INTERFACE_H_ */
|
85
eigrpd/eigrp_macros.h
Normal file
85
eigrpd/eigrp_macros.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* EIGRP Macros Definition.
|
||||
* Copyright (C) 2013-2014
|
||||
* Authors:
|
||||
* Donnie Savage
|
||||
* Jan Janovic
|
||||
* Matej Perina
|
||||
* Peter Orsag
|
||||
* Peter Paluch
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _ZEBRA_EIGRP_MACROS_H_
|
||||
#define _ZEBRA_EIGRP_MACROS_H_
|
||||
|
||||
#define DECLARE_IF_PARAM(T, P) T P; u_char P##__config:1
|
||||
#define IF_EIGRP_IF_INFO(I) ((struct eigrp_if_info *)((I)->info))
|
||||
#define IF_OIFS(I) (IF_EIGRP_IF_INFO (I)->eifs)
|
||||
#define IF_OIFS_PARAMS(I) (IF_EIGRP_IF_INFO (I)->params)
|
||||
|
||||
#define SET_IF_PARAM(S, P) ((S)->P##__config) = 1
|
||||
#define IF_DEF_PARAMS(I) (IF_EIGRP_IF_INFO (I)->def_params)
|
||||
|
||||
#define UNSET_IF_PARAM(S, P) ((S)->P##__config) = 0
|
||||
|
||||
#define EIGRP_IF_PARAM_CONFIGURED(S, P) ((S) && (S)->P##__config)
|
||||
#define EIGRP_IF_PARAM(O, P) \
|
||||
(EIGRP_IF_PARAM_CONFIGURED ((O)->params, P)?\
|
||||
(O)->params->P:IF_DEF_PARAMS((O)->ifp)->P)
|
||||
|
||||
#define EIGRP_IF_PASSIVE_STATUS(O) \
|
||||
(EIGRP_IF_PARAM_CONFIGURED((O)->params, passive_interface) ? \
|
||||
(O)->params->passive_interface : \
|
||||
(EIGRP_IF_PARAM_CONFIGURED(IF_DEF_PARAMS((O)->ifp), passive_interface) ? \
|
||||
IF_DEF_PARAMS((O)->ifp)->passive_interface : \
|
||||
(O)->eigrp->passive_interface_default))
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#define EIGRP_IF_STRING_MAXLEN 40
|
||||
#define IF_NAME(I) eigrp_if_name_string ((I))
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/*Macros for EIGRP interface multicast membership*/
|
||||
#define EI_MEMBER_FLAG(M) (1 << (M))
|
||||
#define EI_MEMBER_COUNT(O,M) (IF_EIGRP_IF_INFO(ei->ifp)->membership_counts[(M)])
|
||||
#define EI_MEMBER_CHECK(O,M) \
|
||||
(CHECK_FLAG((O)->multicast_memberships, EI_MEMBER_FLAG(M)))
|
||||
#define EI_MEMBER_JOINED(O,M) \
|
||||
do { \
|
||||
SET_FLAG ((O)->multicast_memberships, EI_MEMBER_FLAG(M)); \
|
||||
IF_EIGRP_IF_INFO((O)->ifp)->membership_counts[(M)]++; \
|
||||
} while (0)
|
||||
#define EI_MEMBER_LEFT(O,M) \
|
||||
do { \
|
||||
UNSET_FLAG ((O)->multicast_memberships, EI_MEMBER_FLAG(M)); \
|
||||
IF_EIGRP_IF_INFO((O)->ifp)->membership_counts[(M)]--; \
|
||||
} while (0)
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------------------
|
||||
/* Topology Macros */
|
||||
|
||||
|
||||
/* FSM macros*/
|
||||
#define EIGRP_FSM_EVENT_SCHEDULE(I,E) \
|
||||
thread_add_event (master, eigrp_fsm_event, (I), (E))
|
||||
|
||||
#endif /* _ZEBRA_EIGRP_MACROS_H_ */
|
231
eigrpd/eigrp_main.c
Normal file
231
eigrpd/eigrp_main.c
Normal file
|
@ -0,0 +1,231 @@
|
|||
/*
|
||||
* EIGRP Main Routine.
|
||||
* Copyright (C) 2013-2015
|
||||
* Authors:
|
||||
* Donnie Savage
|
||||
* Jan Janovic
|
||||
* Matej Perina
|
||||
* Peter Orsag
|
||||
* Peter Paluch
|
||||
* Frantisek Gazo
|
||||
* Tomas Hvorkovy
|
||||
* Martin Kontsek
|
||||
* Lukas Koribsky
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#include <zebra.h>
|
||||
|
||||
#include <lib/version.h>
|
||||
#include "getopt.h"
|
||||
#include "thread.h"
|
||||
#include "prefix.h"
|
||||
#include "linklist.h"
|
||||
#include "if.h"
|
||||
#include "vector.h"
|
||||
#include "vty.h"
|
||||
#include "command.h"
|
||||
#include "filter.h"
|
||||
#include "plist.h"
|
||||
#include "stream.h"
|
||||
#include "log.h"
|
||||
#include "memory.h"
|
||||
#include "privs.h"
|
||||
#include "sigevent.h"
|
||||
#include "zclient.h"
|
||||
#include "keychain.h"
|
||||
#include "distribute.h"
|
||||
#include "libfrr.h"
|
||||
//#include "routemap.h"
|
||||
//#include "if_rmap.h"
|
||||
|
||||
#include "eigrpd/eigrp_structs.h"
|
||||
#include "eigrpd/eigrpd.h"
|
||||
#include "eigrpd/eigrp_dump.h"
|
||||
#include "eigrpd/eigrp_interface.h"
|
||||
#include "eigrpd/eigrp_neighbor.h"
|
||||
#include "eigrpd/eigrp_packet.h"
|
||||
#include "eigrpd/eigrp_vty.h"
|
||||
#include "eigrpd/eigrp_zebra.h"
|
||||
#include "eigrpd/eigrp_network.h"
|
||||
#include "eigrpd/eigrp_snmp.h"
|
||||
#include "eigrpd/eigrp_filter.h"
|
||||
//#include "eigrpd/eigrp_routemap.h"
|
||||
|
||||
/* eigprd privileges */
|
||||
zebra_capabilities_t _caps_p [] =
|
||||
{
|
||||
ZCAP_NET_RAW,
|
||||
ZCAP_BIND,
|
||||
ZCAP_NET_ADMIN,
|
||||
};
|
||||
|
||||
struct zebra_privs_t eigrpd_privs =
|
||||
{
|
||||
#if defined (FRR_USER) && defined (FRR_GROUP)
|
||||
.user = FRR_USER,
|
||||
.group = FRR_GROUP,
|
||||
#endif
|
||||
#if defined (VTY_GROUP)
|
||||
.vty_group = VTY_GROUP,
|
||||
#endif
|
||||
.caps_p = _caps_p,
|
||||
.cap_num_p = array_size (_caps_p),
|
||||
.cap_num_i = 0
|
||||
};
|
||||
|
||||
/* EIGRPd options. */
|
||||
struct option longopts[] =
|
||||
{
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
/* Master of threads. */
|
||||
struct thread_master *master;
|
||||
|
||||
/* SIGHUP handler. */
|
||||
static void
|
||||
sighup (void)
|
||||
{
|
||||
zlog_info ("SIGHUP received");
|
||||
}
|
||||
|
||||
/* SIGINT / SIGTERM handler. */
|
||||
static void
|
||||
sigint (void)
|
||||
{
|
||||
zlog_notice ("Terminating on signal");
|
||||
eigrp_terminate ();
|
||||
}
|
||||
|
||||
/* SIGUSR1 handler. */
|
||||
static void
|
||||
sigusr1 (void)
|
||||
{
|
||||
zlog_rotate ();
|
||||
}
|
||||
|
||||
struct quagga_signal_t eigrp_signals[] =
|
||||
{
|
||||
{
|
||||
.signal = SIGHUP,
|
||||
.handler = &sighup,
|
||||
},
|
||||
{
|
||||
.signal = SIGUSR1,
|
||||
.handler = &sigusr1,
|
||||
},
|
||||
{
|
||||
.signal = SIGINT,
|
||||
.handler = &sigint,
|
||||
},
|
||||
{
|
||||
.signal = SIGTERM,
|
||||
.handler = &sigint,
|
||||
},
|
||||
};
|
||||
|
||||
FRR_DAEMON_INFO(eigrpd, EIGRP,
|
||||
.vty_port = EIGRP_VTY_PORT,
|
||||
|
||||
.proghelp = "Implementation of the EIGRP routing protocol.",
|
||||
|
||||
.signals = eigrp_signals,
|
||||
.n_signals = array_size(eigrp_signals),
|
||||
|
||||
.privs = &eigrpd_privs,
|
||||
)
|
||||
|
||||
/* EIGRPd main routine. */
|
||||
int
|
||||
main (int argc, char **argv, char **envp)
|
||||
{
|
||||
frr_preinit (&eigrpd_di, argc, argv);
|
||||
frr_opt_add ("", longopts, "");
|
||||
|
||||
while (1)
|
||||
{
|
||||
int opt;
|
||||
|
||||
opt = frr_getopt (argc, argv, NULL);
|
||||
|
||||
if (opt == EOF)
|
||||
break;
|
||||
|
||||
switch (opt)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
frr_help_exit (1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* EIGRP master init. */
|
||||
eigrp_master_init ();
|
||||
eigrp_om->master = frr_init();
|
||||
master = eigrp_om->master;
|
||||
|
||||
vrf_init ();
|
||||
|
||||
/*EIGRPd init*/
|
||||
eigrp_if_init ();
|
||||
eigrp_zebra_init ();
|
||||
eigrp_debug_init ();
|
||||
|
||||
/* Get configuration file. */
|
||||
/* EIGRP VTY inits */
|
||||
eigrp_vty_init ();
|
||||
keychain_init();
|
||||
eigrp_vty_show_init ();
|
||||
eigrp_vty_if_init ();
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
eigrp_snmp_init ();
|
||||
#endif /* HAVE_SNMP */
|
||||
|
||||
/* Access list install. */
|
||||
access_list_init ();
|
||||
access_list_add_hook (eigrp_distribute_update_all_wrapper);
|
||||
access_list_delete_hook (eigrp_distribute_update_all_wrapper);
|
||||
|
||||
/* Prefix list initialize.*/
|
||||
prefix_list_init ();
|
||||
prefix_list_add_hook (eigrp_distribute_update_all);
|
||||
prefix_list_delete_hook (eigrp_distribute_update_all);
|
||||
|
||||
/*eigrp_route_map_init();
|
||||
route_map_add_hook (eigrp_rmap_update);
|
||||
route_map_delete_hook (eigrp_rmap_update);*/
|
||||
/*if_rmap_init (EIGRP_NODE);
|
||||
if_rmap_hook_add (eigrp_if_rmap_update);
|
||||
if_rmap_hook_delete (eigrp_if_rmap_update);*/
|
||||
|
||||
/* Distribute list install. */
|
||||
distribute_list_init (EIGRP_NODE);
|
||||
distribute_list_add_hook (eigrp_distribute_update);
|
||||
distribute_list_delete_hook (eigrp_distribute_update);
|
||||
|
||||
frr_config_fork ();
|
||||
frr_run(master);
|
||||
|
||||
/* Not reached. */
|
||||
return (0);
|
||||
|
||||
}
|
43
eigrpd/eigrp_memory.c
Normal file
43
eigrpd/eigrp_memory.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
/* eigrpd memory type definitions
|
||||
*
|
||||
* Copyright (C) 2017 Donald Sharp
|
||||
*
|
||||
* This file is part of FRR
|
||||
*
|
||||
* FRR 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.
|
||||
*
|
||||
* FRR 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 FRR; see the file COPYING. If not, write to the Free
|
||||
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "eigrp_memory.h"
|
||||
|
||||
DEFINE_MGROUP(EIGRPD, "eigrpd")
|
||||
DEFINE_MTYPE(EIGRPD, EIGRP_TOP, "EIGRP structure")
|
||||
DEFINE_MTYPE(EIGRPD, EIGRP_IF, "EIGRP interface")
|
||||
DEFINE_MTYPE(EIGRPD, EIGRP_NEIGHBOR, "EIGRP neighbor")
|
||||
DEFINE_MTYPE(EIGRPD, EIGRP_IF_PARAMS, "EIGRP Interface Parameters")
|
||||
DEFINE_MTYPE(EIGRPD, EIGRP_IF_INFO, "EIGRP Interface Information")
|
||||
DEFINE_MTYPE(EIGRPD, EIGRP_FIFO, "EIGRP FIFO")
|
||||
DEFINE_MTYPE(EIGRPD, EIGRP_PACKET, "EIGRP Packet")
|
||||
DEFINE_MTYPE(EIGRPD, EIGRP_IPV4_INT_TLV, "EIGRP IPv4 TLV")
|
||||
DEFINE_MTYPE(EIGRPD, EIGRP_SEQ_TLV, "EIGRP SEQ TLV")
|
||||
DEFINE_MTYPE(EIGRPD, EIGRP_AUTH_TLV, "EIGRP AUTH TLV")
|
||||
DEFINE_MTYPE(EIGRPD, EIGRP_AUTH_SHA256_TLV, "EIGRP SHA TLV")
|
||||
DEFINE_MTYPE(EIGRPD, EIGRP_PREFIX_ENTRY, "EIGRP Prefix")
|
||||
DEFINE_MTYPE(EIGRPD, EIGRP_NEIGHBOR_ENTRY, "EIGRP Neighbor Entry")
|
||||
DEFINE_MTYPE(EIGRPD, EIGRP_FSM_MSG, "EIGRP FSM Message")
|
44
eigrpd/eigrp_memory.h
Normal file
44
eigrpd/eigrp_memory.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/* eigrpd memory type declarations
|
||||
*
|
||||
* Copyright (C) 2017 Donald Sharp
|
||||
*
|
||||
* This file is part of FRR.
|
||||
*
|
||||
* FRR 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.
|
||||
*
|
||||
* FRR 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 FRR; see the file COPYING. If not, write to the Free
|
||||
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _FRR_EIGRP_MEMORY_H
|
||||
#define _FRR_EIGRP_MEMORY_H
|
||||
|
||||
#include "memory.h"
|
||||
|
||||
DECLARE_MGROUP(EIGRPD)
|
||||
DECLARE_MTYPE(EIGRP_TOP)
|
||||
DECLARE_MTYPE(EIGRP_IF)
|
||||
DECLARE_MTYPE(EIGRP_NEIGHBOR)
|
||||
DECLARE_MTYPE(EIGRP_IF_PARAMS)
|
||||
DECLARE_MTYPE(EIGRP_IF_INFO)
|
||||
DECLARE_MTYPE(EIGRP_FIFO)
|
||||
DECLARE_MTYPE(EIGRP_PACKET)
|
||||
DECLARE_MTYPE(EIGRP_IPV4_INT_TLV)
|
||||
DECLARE_MTYPE(EIGRP_SEQ_TLV)
|
||||
DECLARE_MTYPE(EIGRP_AUTH_TLV)
|
||||
DECLARE_MTYPE(EIGRP_AUTH_SHA256_TLV)
|
||||
DECLARE_MTYPE(EIGRP_PREFIX_ENTRY)
|
||||
DECLARE_MTYPE(EIGRP_NEIGHBOR_ENTRY)
|
||||
DECLARE_MTYPE(EIGRP_FSM_MSG)
|
||||
|
||||
#endif /* _FRR_EIGRP_MEMORY_H */
|
384
eigrpd/eigrp_neighbor.c
Normal file
384
eigrpd/eigrp_neighbor.c
Normal file
|
@ -0,0 +1,384 @@
|
|||
/*
|
||||
* EIGRP Neighbor Handling.
|
||||
* Copyright (C) 2013-2016
|
||||
* Authors:
|
||||
* Donnie Savage
|
||||
* Jan Janovic
|
||||
* Matej Perina
|
||||
* Peter Orsag
|
||||
* Peter Paluch
|
||||
* Frantisek Gazo
|
||||
* Tomas Hvorkovy
|
||||
* Martin Kontsek
|
||||
* Lukas Koribsky
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#include "linklist.h"
|
||||
#include "prefix.h"
|
||||
#include "memory.h"
|
||||
#include "command.h"
|
||||
#include "thread.h"
|
||||
#include "stream.h"
|
||||
#include "table.h"
|
||||
#include "log.h"
|
||||
#include "keychain.h"
|
||||
#include "vty.h"
|
||||
|
||||
#include "eigrpd/eigrp_structs.h"
|
||||
#include "eigrpd/eigrpd.h"
|
||||
#include "eigrpd/eigrp_interface.h"
|
||||
#include "eigrpd/eigrp_neighbor.h"
|
||||
#include "eigrpd/eigrp_dump.h"
|
||||
#include "eigrpd/eigrp_packet.h"
|
||||
#include "eigrpd/eigrp_zebra.h"
|
||||
#include "eigrpd/eigrp_vty.h"
|
||||
#include "eigrpd/eigrp_network.h"
|
||||
#include "eigrpd/eigrp_topology.h"
|
||||
#include "eigrpd/eigrp_memory.h"
|
||||
|
||||
struct eigrp_neighbor *
|
||||
eigrp_nbr_new (struct eigrp_interface *ei)
|
||||
{
|
||||
struct eigrp_neighbor *nbr;
|
||||
|
||||
/* Allcate new neighbor. */
|
||||
nbr = XCALLOC (MTYPE_EIGRP_NEIGHBOR, sizeof (struct eigrp_neighbor));
|
||||
|
||||
/* Relate neighbor to the interface. */
|
||||
nbr->ei = ei;
|
||||
|
||||
/* Set default values. */
|
||||
|
||||
eigrp_nbr_state_set (nbr, EIGRP_NEIGHBOR_DOWN);
|
||||
|
||||
return nbr;
|
||||
}
|
||||
|
||||
/**
|
||||
*@fn void dissect_eigrp_sw_version (tvbuff_t *tvb, proto_tree *tree,
|
||||
* proto_item *ti)
|
||||
*
|
||||
* @par
|
||||
* Create a new neighbor structure and initalize it.
|
||||
*/
|
||||
static struct eigrp_neighbor *
|
||||
eigrp_nbr_add (struct eigrp_interface *ei, struct eigrp_header *eigrph,
|
||||
struct ip *iph)
|
||||
{
|
||||
struct eigrp_neighbor *nbr;
|
||||
|
||||
nbr = eigrp_nbr_new (ei);
|
||||
nbr->src = iph->ip_src;
|
||||
|
||||
// if (IS_DEBUG_EIGRP_EVENT)
|
||||
// zlog_debug("NSM[%s:%s]: start", IF_NAME (nbr->oi),
|
||||
// inet_ntoa (nbr->router_id));
|
||||
|
||||
return nbr;
|
||||
}
|
||||
|
||||
struct eigrp_neighbor *
|
||||
eigrp_nbr_get (struct eigrp_interface *ei, struct eigrp_header *eigrph,
|
||||
struct ip *iph)
|
||||
{
|
||||
struct eigrp_neighbor *nbr;
|
||||
struct listnode *node, *nnode;
|
||||
|
||||
for (ALL_LIST_ELEMENTS (ei->nbrs, node, nnode, nbr))
|
||||
{
|
||||
if (iph->ip_src.s_addr == nbr->src.s_addr)
|
||||
{
|
||||
return nbr;
|
||||
}
|
||||
}
|
||||
|
||||
nbr = eigrp_nbr_add (ei, eigrph, iph);
|
||||
listnode_add (ei->nbrs, nbr);
|
||||
|
||||
return nbr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn eigrp_nbr_lookup_by_addr
|
||||
*
|
||||
* @param[in] ei EIGRP interface
|
||||
* @param[in] nbr_addr Address of neighbor
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @par
|
||||
* Function is used for neighbor lookup by address
|
||||
* in specified interface.
|
||||
*/
|
||||
struct eigrp_neighbor *
|
||||
eigrp_nbr_lookup_by_addr (struct eigrp_interface *ei, struct in_addr *addr)
|
||||
{
|
||||
struct eigrp_neighbor *nbr;
|
||||
struct listnode *node, *nnode;
|
||||
|
||||
for (ALL_LIST_ELEMENTS (ei->nbrs, node, nnode, nbr))
|
||||
{
|
||||
if (addr->s_addr == nbr->src.s_addr)
|
||||
{
|
||||
return nbr;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn eigrp_nbr_lookup_by_addr_process
|
||||
*
|
||||
* @param[in] eigrp EIGRP process
|
||||
* @param[in] nbr_addr Address of neighbor
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @par
|
||||
* Function is used for neighbor lookup by address
|
||||
* in whole EIGRP process.
|
||||
*/
|
||||
struct eigrp_neighbor *
|
||||
eigrp_nbr_lookup_by_addr_process (struct eigrp *eigrp, struct in_addr nbr_addr)
|
||||
{
|
||||
struct eigrp_interface *ei;
|
||||
struct listnode *node, *node2, *nnode2;
|
||||
struct eigrp_neighbor *nbr;
|
||||
|
||||
/* iterate over all eigrp interfaces */
|
||||
for (ALL_LIST_ELEMENTS_RO (eigrp->eiflist, node, ei))
|
||||
{
|
||||
/* iterate over all neighbors on eigrp interface */
|
||||
for (ALL_LIST_ELEMENTS (ei->nbrs, node2, nnode2, nbr))
|
||||
{
|
||||
/* compare if neighbor address is same as arg address */
|
||||
if (nbr->src.s_addr == nbr_addr.s_addr)
|
||||
{
|
||||
return nbr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Delete specified EIGRP neighbor from interface. */
|
||||
void
|
||||
eigrp_nbr_delete (struct eigrp_neighbor *nbr)
|
||||
{
|
||||
|
||||
eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_DOWN);
|
||||
eigrp_topology_neighbor_down(nbr->ei->eigrp, nbr);
|
||||
|
||||
/* Cancel all events. *//* Thread lookup cost would be negligible. */
|
||||
thread_cancel_event (master, nbr);
|
||||
eigrp_fifo_free (nbr->multicast_queue);
|
||||
eigrp_fifo_free (nbr->retrans_queue);
|
||||
THREAD_OFF (nbr->t_holddown);
|
||||
|
||||
listnode_delete (nbr->ei->nbrs,nbr);
|
||||
XFREE (MTYPE_EIGRP_NEIGHBOR, nbr);
|
||||
}
|
||||
|
||||
int
|
||||
holddown_timer_expired (struct thread *thread)
|
||||
{
|
||||
struct eigrp_neighbor *nbr;
|
||||
|
||||
nbr = THREAD_ARG (thread);
|
||||
|
||||
zlog_info ("Neighbor %s (%s) is down: holding time expired",
|
||||
inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex));
|
||||
nbr->state = EIGRP_NEIGHBOR_DOWN;
|
||||
eigrp_nbr_delete (nbr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u_char
|
||||
eigrp_nbr_state_get (struct eigrp_neighbor *nbr)
|
||||
{
|
||||
return(nbr->state);
|
||||
}
|
||||
|
||||
void
|
||||
eigrp_nbr_state_set (struct eigrp_neighbor *nbr, u_char state)
|
||||
{
|
||||
|
||||
nbr->state = state;
|
||||
|
||||
if (eigrp_nbr_state_get(nbr) == EIGRP_NEIGHBOR_DOWN)
|
||||
{
|
||||
// reset all the seq/ack counters
|
||||
nbr->recv_sequence_number = 0;
|
||||
nbr->init_sequence_number = 0;
|
||||
nbr->retrans_counter = 0;
|
||||
|
||||
// Kvalues
|
||||
nbr->K1 = EIGRP_K1_DEFAULT;
|
||||
nbr->K2 = EIGRP_K2_DEFAULT;
|
||||
nbr->K3 = EIGRP_K3_DEFAULT;
|
||||
nbr->K4 = EIGRP_K4_DEFAULT;
|
||||
nbr->K5 = EIGRP_K5_DEFAULT;
|
||||
nbr->K6 = EIGRP_K6_DEFAULT;
|
||||
|
||||
// hold time..
|
||||
nbr->v_holddown = EIGRP_HOLD_INTERVAL_DEFAULT;
|
||||
THREAD_OFF(nbr->t_holddown);
|
||||
|
||||
/* out with the old */
|
||||
if (nbr->multicast_queue)
|
||||
eigrp_fifo_free (nbr->multicast_queue);
|
||||
if (nbr->retrans_queue)
|
||||
eigrp_fifo_free (nbr->retrans_queue);
|
||||
|
||||
/* in with the new */
|
||||
nbr->retrans_queue = eigrp_fifo_new ();
|
||||
nbr->multicast_queue = eigrp_fifo_new ();
|
||||
|
||||
nbr->crypt_seqnum = 0;
|
||||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
eigrp_nbr_state_str (struct eigrp_neighbor *nbr)
|
||||
{
|
||||
const char *state;
|
||||
switch (nbr->state)
|
||||
{
|
||||
case EIGRP_NEIGHBOR_DOWN:
|
||||
state = "Down";
|
||||
break;
|
||||
case EIGRP_NEIGHBOR_PENDING:
|
||||
state = "Waiting for Init";
|
||||
break;
|
||||
case EIGRP_NEIGHBOR_UP:
|
||||
state = "Up";
|
||||
break;
|
||||
default:
|
||||
state = "Unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
void
|
||||
eigrp_nbr_state_update (struct eigrp_neighbor *nbr)
|
||||
{
|
||||
switch (nbr->state)
|
||||
{
|
||||
case EIGRP_NEIGHBOR_DOWN:
|
||||
{
|
||||
/*Start Hold Down Timer for neighbor*/
|
||||
// THREAD_OFF(nbr->t_holddown);
|
||||
// THREAD_TIMER_ON(master, nbr->t_holddown, holddown_timer_expired,
|
||||
// nbr, nbr->v_holddown);
|
||||
break;
|
||||
}
|
||||
case EIGRP_NEIGHBOR_PENDING:
|
||||
{
|
||||
/*Reset Hold Down Timer for neighbor*/
|
||||
THREAD_OFF(nbr->t_holddown);
|
||||
THREAD_TIMER_ON(master, nbr->t_holddown, holddown_timer_expired, nbr,
|
||||
nbr->v_holddown);
|
||||
break;
|
||||
}
|
||||
case EIGRP_NEIGHBOR_UP:
|
||||
{
|
||||
/*Reset Hold Down Timer for neighbor*/
|
||||
THREAD_OFF(nbr->t_holddown);
|
||||
THREAD_TIMER_ON(master, nbr->t_holddown, holddown_timer_expired, nbr,
|
||||
nbr->v_holddown);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int eigrp_nbr_count_get(void){
|
||||
|
||||
struct eigrp_interface *iface;
|
||||
struct listnode *node, *node2, *nnode2;
|
||||
struct eigrp_neighbor *nbr;
|
||||
struct eigrp *eigrp = eigrp_lookup();
|
||||
u_int32_t counter;
|
||||
|
||||
if (eigrp == NULL)
|
||||
{
|
||||
zlog_debug("EIGRP Routing Process not enabled");
|
||||
return 0;
|
||||
}
|
||||
|
||||
counter=0;
|
||||
for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, iface))
|
||||
{
|
||||
for (ALL_LIST_ELEMENTS(iface->nbrs, node2, nnode2, nbr))
|
||||
{
|
||||
if (nbr->state == EIGRP_NEIGHBOR_UP){
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return counter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn eigrp_nbr_hard_restart
|
||||
*
|
||||
* @param[in] nbr Neighbor who would receive hard restart
|
||||
* @param[in] vty Virtual terminal for log output
|
||||
* @return void
|
||||
*
|
||||
* @par
|
||||
* Function used for executing hard restart for neighbor:
|
||||
* Send Hello packet with Peer Termination TLV with
|
||||
* neighbor's address, set it's state to DOWN and delete the neighbor
|
||||
*/
|
||||
void eigrp_nbr_hard_restart(struct eigrp_neighbor *nbr, struct vty *vty)
|
||||
{
|
||||
if(nbr == NULL)
|
||||
{
|
||||
zlog_err("Nbr Hard restart: Neighbor not specified.");
|
||||
return;
|
||||
}
|
||||
|
||||
zlog_debug ("Neighbor %s (%s) is down: manually cleared",
|
||||
inet_ntoa (nbr->src),
|
||||
ifindex2ifname (nbr->ei->ifp->ifindex));
|
||||
if(vty != NULL)
|
||||
{
|
||||
vty_time_print (vty, 0);
|
||||
vty_out (vty, "Neighbor %s (%s) is down: manually cleared%s",
|
||||
inet_ntoa (nbr->src),
|
||||
ifindex2ifname (nbr->ei->ifp->ifindex),
|
||||
VTY_NEWLINE);
|
||||
}
|
||||
|
||||
/* send Hello with Peer Termination TLV */
|
||||
eigrp_hello_send(nbr->ei, EIGRP_HELLO_GRACEFUL_SHUTDOWN_NBR, &(nbr->src));
|
||||
/* set neighbor to DOWN */
|
||||
nbr->state = EIGRP_NEIGHBOR_DOWN;
|
||||
/* delete neighbor */
|
||||
eigrp_nbr_delete (nbr);
|
||||
}
|
55
eigrpd/eigrp_neighbor.h
Normal file
55
eigrpd/eigrp_neighbor.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* EIGRP Neighbor Handling.
|
||||
* Copyright (C) 2013-2016
|
||||
* Authors:
|
||||
* Donnie Savage
|
||||
* Jan Janovic
|
||||
* Matej Perina
|
||||
* Peter Orsag
|
||||
* Peter Paluch
|
||||
* Frantisek Gazo
|
||||
* Tomas Hvorkovy
|
||||
* Martin Kontsek
|
||||
* Lukas Koribsky
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _ZEBRA_EIGRP_NEIGHBOR_H
|
||||
#define _ZEBRA_EIGRP_NEIGHBOR_H
|
||||
|
||||
/* Prototypes */
|
||||
extern struct eigrp_neighbor *eigrp_nbr_get(struct eigrp_interface *,
|
||||
struct eigrp_header *,
|
||||
struct ip *);
|
||||
extern struct eigrp_neighbor *eigrp_nbr_new (struct eigrp_interface *);
|
||||
extern void eigrp_nbr_delete(struct eigrp_neighbor *);
|
||||
|
||||
extern int holddown_timer_expired(struct thread *);
|
||||
|
||||
extern int eigrp_neighborship_check(struct eigrp_neighbor *,struct TLV_Parameter_Type *);
|
||||
extern void eigrp_nbr_state_update(struct eigrp_neighbor *);
|
||||
extern void eigrp_nbr_state_set(struct eigrp_neighbor *, u_char state);
|
||||
extern u_char eigrp_nbr_state_get(struct eigrp_neighbor *);
|
||||
extern int eigrp_nbr_count_get(void);
|
||||
extern const char *eigrp_nbr_state_str(struct eigrp_neighbor *);
|
||||
extern struct eigrp_neighbor *eigrp_nbr_lookup_by_addr (struct eigrp_interface *, struct in_addr *);
|
||||
extern struct eigrp_neighbor *eigrp_nbr_lookup_by_addr_process (struct eigrp *, struct in_addr);
|
||||
extern void eigrp_nbr_hard_restart(struct eigrp_neighbor *nbr, struct vty *vty);
|
||||
|
||||
#endif /* _ZEBRA_EIGRP_NEIGHBOR_H */
|
463
eigrpd/eigrp_network.c
Normal file
463
eigrpd/eigrp_network.c
Normal file
|
@ -0,0 +1,463 @@
|
|||
/*
|
||||
* EIGRP Network Related Functions.
|
||||
* Copyright (C) 2013-2014
|
||||
* Authors:
|
||||
* Donnie Savage
|
||||
* Jan Janovic
|
||||
* Matej Perina
|
||||
* Peter Orsag
|
||||
* Peter Paluch
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#include "thread.h"
|
||||
#include "linklist.h"
|
||||
#include "prefix.h"
|
||||
#include "if.h"
|
||||
#include "sockunion.h"
|
||||
#include "log.h"
|
||||
#include "sockopt.h"
|
||||
#include "privs.h"
|
||||
#include "table.h"
|
||||
#include "vty.h"
|
||||
|
||||
extern struct zebra_privs_t eigrpd_privs;
|
||||
|
||||
#include "eigrpd/eigrp_structs.h"
|
||||
#include "eigrpd/eigrpd.h"
|
||||
#include "eigrpd/eigrp_interface.h"
|
||||
#include "eigrpd/eigrp_neighbor.h"
|
||||
#include "eigrpd/eigrp_packet.h"
|
||||
#include "eigrpd/eigrp_zebra.h"
|
||||
#include "eigrpd/eigrp_vty.h"
|
||||
#include "eigrpd/eigrp_network.h"
|
||||
|
||||
static int
|
||||
eigrp_network_match_iface(const struct connected *, const struct prefix *);
|
||||
static void
|
||||
eigrp_network_run_interface(struct eigrp *, struct prefix *, struct interface *);
|
||||
|
||||
int
|
||||
eigrp_sock_init(void)
|
||||
{
|
||||
int eigrp_sock;
|
||||
int ret, hincl = 1;
|
||||
|
||||
if (eigrpd_privs.change(ZPRIVS_RAISE))
|
||||
zlog_err("eigrp_sock_init: could not raise privs, %s",
|
||||
safe_strerror(errno));
|
||||
|
||||
eigrp_sock = socket(AF_INET, SOCK_RAW, IPPROTO_EIGRPIGP);
|
||||
if (eigrp_sock < 0)
|
||||
{
|
||||
int save_errno = errno;
|
||||
if (eigrpd_privs.change(ZPRIVS_LOWER))
|
||||
zlog_err("eigrp_sock_init: could not lower privs, %s",
|
||||
safe_strerror(errno));
|
||||
zlog_err("eigrp_read_sock_init: socket: %s", safe_strerror(save_errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef IP_HDRINCL
|
||||
/* we will include IP header with packet */
|
||||
ret = setsockopt(eigrp_sock, IPPROTO_IP, IP_HDRINCL, &hincl, sizeof(hincl));
|
||||
if (ret < 0)
|
||||
{
|
||||
int save_errno = errno;
|
||||
if (eigrpd_privs.change(ZPRIVS_LOWER))
|
||||
zlog_err("eigrp_sock_init: could not lower privs, %s",
|
||||
safe_strerror(errno));
|
||||
zlog_warn("Can't set IP_HDRINCL option for fd %d: %s", eigrp_sock,
|
||||
safe_strerror(save_errno));
|
||||
|
||||
}
|
||||
#elif defined (IPTOS_PREC_INTERNETCONTROL)
|
||||
#warning "IP_HDRINCL not available on this system"
|
||||
#warning "using IPTOS_PREC_INTERNETCONTROL"
|
||||
ret = setsockopt_ipv4_tos (eigrp_sock, IPTOS_PREC_INTERNETCONTROL);
|
||||
if (ret < 0)
|
||||
{
|
||||
int save_errno = errno;
|
||||
if ( eigrpd_privs.change (ZPRIVS_LOWER) )
|
||||
zlog_err ("eigrpd_sock_init: could not lower privs, %s",
|
||||
safe_strerror (errno) );
|
||||
zlog_warn ("can't set sockopt IP_TOS %d to socket %d: %s",
|
||||
tos, eigrp_sock, safe_strerror (save_errno));
|
||||
close (eigrp_sock); /* Prevent sd leak. */
|
||||
return ret;
|
||||
}
|
||||
#else /* !IPTOS_PREC_INTERNETCONTROL */
|
||||
#warning "IP_HDRINCL not available, nor is IPTOS_PREC_INTERNETCONTROL"
|
||||
zlog_warn ("IP_HDRINCL option not available");
|
||||
#endif /* IP_HDRINCL */
|
||||
|
||||
ret = setsockopt_ifindex(AF_INET, eigrp_sock, 1);
|
||||
|
||||
if (ret < 0)
|
||||
zlog_warn("Can't set pktinfo option for fd %d", eigrp_sock);
|
||||
|
||||
if (eigrpd_privs.change(ZPRIVS_LOWER))
|
||||
{
|
||||
zlog_err("eigrp_sock_init: could not lower privs, %s",
|
||||
safe_strerror(errno));
|
||||
}
|
||||
|
||||
return eigrp_sock;
|
||||
}
|
||||
|
||||
void
|
||||
eigrp_adjust_sndbuflen(struct eigrp * eigrp, unsigned int buflen)
|
||||
{
|
||||
int newbuflen;
|
||||
/* Check if any work has to be done at all. */
|
||||
if (eigrp->maxsndbuflen >= buflen)
|
||||
return;
|
||||
if (eigrpd_privs.change(ZPRIVS_RAISE))
|
||||
zlog_err("%s: could not raise privs, %s", __func__, safe_strerror(errno));
|
||||
/* Now we try to set SO_SNDBUF to what our caller has requested
|
||||
* (the MTU of a newly added interface). However, if the OS has
|
||||
* truncated the actual buffer size to somewhat less size, try
|
||||
* to detect it and update our records appropriately. The OS
|
||||
* may allocate more buffer space, than requested, this isn't
|
||||
* a error.
|
||||
*/
|
||||
setsockopt_so_sendbuf(eigrp->fd, buflen);
|
||||
newbuflen = getsockopt_so_sendbuf(eigrp->fd);
|
||||
if (newbuflen < 0 || newbuflen < (int) buflen)
|
||||
zlog_warn("%s: tried to set SO_SNDBUF to %u, but got %d", __func__, buflen,
|
||||
newbuflen);
|
||||
if (newbuflen >= 0)
|
||||
eigrp->maxsndbuflen = (unsigned int) newbuflen;
|
||||
else
|
||||
zlog_warn("%s: failed to get SO_SNDBUF", __func__);
|
||||
if (eigrpd_privs.change(ZPRIVS_LOWER))
|
||||
zlog_err("%s: could not lower privs, %s", __func__, safe_strerror(errno));
|
||||
}
|
||||
|
||||
int
|
||||
eigrp_if_ipmulticast(struct eigrp *top, struct prefix *p, unsigned int ifindex)
|
||||
{
|
||||
u_char val;
|
||||
int ret, len;
|
||||
|
||||
val = 0;
|
||||
len = sizeof(val);
|
||||
|
||||
/* Prevent receiving self-origined multicast packets. */
|
||||
ret = setsockopt(top->fd, IPPROTO_IP, IP_MULTICAST_LOOP, (void *) &val, len);
|
||||
if (ret < 0)
|
||||
zlog_warn("can't setsockopt IP_MULTICAST_LOOP (0) for fd %d: %s", top->fd,
|
||||
safe_strerror(errno));
|
||||
|
||||
/* Explicitly set multicast ttl to 1 -- endo. */
|
||||
val = 1;
|
||||
ret = setsockopt(top->fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *) &val, len);
|
||||
if (ret < 0)
|
||||
zlog_warn("can't setsockopt IP_MULTICAST_TTL (1) for fd %d: %s", top->fd,
|
||||
safe_strerror(errno));
|
||||
|
||||
ret = setsockopt_ipv4_multicast_if(top->fd, p->u.prefix4, ifindex);
|
||||
if (ret < 0)
|
||||
zlog_warn("can't setsockopt IP_MULTICAST_IF (fd %d, addr %s, "
|
||||
"ifindex %u): %s", top->fd, inet_ntoa(p->u.prefix4), ifindex,
|
||||
safe_strerror(errno));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Join to the EIGRP multicast group. */
|
||||
int
|
||||
eigrp_if_add_allspfrouters(struct eigrp *top, struct prefix *p,
|
||||
unsigned int ifindex)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = setsockopt_ipv4_multicast(top->fd, IP_ADD_MEMBERSHIP, p->u.prefix4,
|
||||
htonl(EIGRP_MULTICAST_ADDRESS), ifindex);
|
||||
if (ret < 0)
|
||||
zlog_warn("can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, "
|
||||
"ifindex %u, AllSPFRouters): %s; perhaps a kernel limit "
|
||||
"on # of multicast group memberships has been exceeded?", top->fd,
|
||||
inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno));
|
||||
else
|
||||
zlog_debug("interface %s [%u] join EIGRP Multicast group.",
|
||||
inet_ntoa(p->u.prefix4), ifindex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
eigrp_if_drop_allspfrouters(struct eigrp *top, struct prefix *p,
|
||||
unsigned int ifindex)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = setsockopt_ipv4_multicast(top->fd, IP_DROP_MEMBERSHIP, p->u.prefix4,
|
||||
htonl(EIGRP_MULTICAST_ADDRESS), ifindex);
|
||||
if (ret < 0)
|
||||
zlog_warn("can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, "
|
||||
"ifindex %u, AllSPFRouters): %s", top->fd, inet_ntoa(p->u.prefix4),
|
||||
ifindex, safe_strerror(errno));
|
||||
else
|
||||
zlog_debug("interface %s [%u] leave EIGRP Multicast group.",
|
||||
inet_ntoa(p->u.prefix4), ifindex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
eigrp_network_set(struct eigrp *eigrp, struct prefix_ipv4 *p)
|
||||
{
|
||||
struct route_node *rn;
|
||||
struct interface *ifp;
|
||||
struct listnode *node;
|
||||
|
||||
zlog_debug ("A");
|
||||
rn = route_node_get(eigrp->networks, (struct prefix *) p);
|
||||
if (rn->info)
|
||||
{
|
||||
/* There is already same network statement. */
|
||||
route_unlock_node(rn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct prefix_ipv4 *pref = prefix_ipv4_new();
|
||||
PREFIX_COPY_IPV4(pref,p);
|
||||
rn->info = (void *) pref;
|
||||
|
||||
zlog_debug ("B");
|
||||
/* Schedule Router ID Update. */
|
||||
// if (eigrp->router_id == 0)
|
||||
// eigrp_router_id_update(eigrp);
|
||||
/* Run network config now. */
|
||||
/* Get target interface. */
|
||||
for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp))
|
||||
{
|
||||
zlog_debug("Setting up %s", ifp->name);
|
||||
eigrp_network_run_interface(eigrp, (struct prefix *) p, ifp);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Check whether interface matches given network
|
||||
* returns: 1, true. 0, false
|
||||
*/
|
||||
static int
|
||||
eigrp_network_match_iface(const struct connected *co, const struct prefix *net)
|
||||
{
|
||||
/* new approach: more elegant and conceptually clean */
|
||||
return prefix_match(net, CONNECTED_PREFIX (co));
|
||||
}
|
||||
|
||||
static void
|
||||
eigrp_network_run_interface(struct eigrp *eigrp, struct prefix *p,
|
||||
struct interface *ifp)
|
||||
{
|
||||
struct listnode *cnode;
|
||||
struct connected *co;
|
||||
|
||||
/* if interface prefix is match specified prefix,
|
||||
then create socket and join multicast group. */
|
||||
for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, co))
|
||||
{
|
||||
|
||||
if (CHECK_FLAG (co->flags,ZEBRA_IFA_SECONDARY))
|
||||
continue;
|
||||
|
||||
if (p->family == co->address->family
|
||||
&& !eigrp_if_table_lookup(ifp, co->address)
|
||||
&& eigrp_network_match_iface(co, p))
|
||||
{
|
||||
struct eigrp_interface *ei;
|
||||
|
||||
ei = eigrp_if_new(eigrp, ifp, co->address);
|
||||
ei->connected = co;
|
||||
|
||||
ei->params = eigrp_lookup_if_params(ifp, ei->address->u.prefix4);
|
||||
|
||||
/* Relate eigrp interface to eigrp instance. */
|
||||
ei->eigrp = eigrp;
|
||||
|
||||
/* update network type as interface flag */
|
||||
/* If network type is specified previously,
|
||||
skip network type setting. */
|
||||
ei->type = IF_DEF_PARAMS (ifp)->type;
|
||||
|
||||
/* if router_id is not configured, dont bring up
|
||||
* interfaces.
|
||||
* eigrp_router_id_update() will call eigrp_if_update
|
||||
* whenever r-id is configured instead.
|
||||
*/
|
||||
if (if_is_operative(ifp))
|
||||
eigrp_if_up(ei);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
eigrp_if_update(struct interface *ifp)
|
||||
{
|
||||
struct listnode *node, *nnode;
|
||||
struct route_node *rn;
|
||||
struct eigrp *eigrp;
|
||||
|
||||
/*
|
||||
* In the event there are multiple eigrp autonymnous systems running,
|
||||
* we need to check eac one and add the interface as approperate
|
||||
*/
|
||||
for (ALL_LIST_ELEMENTS(eigrp_om->eigrp, node, nnode, eigrp))
|
||||
{
|
||||
/* EIGRP must be on and Router-ID must be configured. */
|
||||
if (!eigrp || eigrp->router_id == 0)
|
||||
continue;
|
||||
|
||||
/* Run each network for this interface. */
|
||||
for (rn = route_top(eigrp->networks); rn; rn = route_next(rn))
|
||||
if (rn->info != NULL)
|
||||
{
|
||||
eigrp_network_run_interface(eigrp, &rn->p, ifp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
eigrp_network_unset(struct eigrp *eigrp, struct prefix_ipv4 *p)
|
||||
{
|
||||
struct route_node *rn;
|
||||
struct listnode *node, *nnode;
|
||||
struct eigrp_interface *ei;
|
||||
struct prefix *pref;
|
||||
|
||||
rn = route_node_lookup(eigrp->networks, (struct prefix *) p);
|
||||
if (rn == NULL)
|
||||
return 0;
|
||||
|
||||
pref = rn->info;
|
||||
route_unlock_node (rn);
|
||||
|
||||
if (!IPV4_ADDR_SAME (&pref->u.prefix4, &p->prefix))
|
||||
return 0;
|
||||
|
||||
prefix_ipv4_free(rn->info);
|
||||
rn->info = NULL;
|
||||
route_unlock_node(rn); /* initial reference */
|
||||
|
||||
/* Find interfaces that not configured already. */
|
||||
for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, ei))
|
||||
{
|
||||
int found = 0;
|
||||
struct connected *co = ei->connected;
|
||||
|
||||
for (rn = route_top(eigrp->networks); rn; rn = route_next(rn))
|
||||
{
|
||||
if (rn->info == NULL)
|
||||
continue;
|
||||
|
||||
if (eigrp_network_match_iface(co, &rn->p))
|
||||
{
|
||||
zlog_debug("eigrp_network_unset()2");
|
||||
found = 1;
|
||||
route_unlock_node(rn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found == 0)
|
||||
{
|
||||
eigrp_if_free(ei, INTERFACE_DOWN_BY_VTY);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
u_int32_t
|
||||
eigrp_calculate_metrics(struct eigrp *eigrp, struct eigrp_metrics *metric)
|
||||
{
|
||||
u_int64_t temp_metric;
|
||||
temp_metric = 0;
|
||||
|
||||
if(metric->delay == EIGRP_MAX_METRIC)
|
||||
return EIGRP_MAX_METRIC;
|
||||
|
||||
// EIGRP Metric = {K1*BW+[(K2*BW)/(256-load)]+(K3*delay)}*{K5/(reliability+K4)}
|
||||
|
||||
if (eigrp->k_values[0])
|
||||
temp_metric += (eigrp->k_values[0] * metric->bandwith);
|
||||
if (eigrp->k_values[1])
|
||||
temp_metric += ((eigrp->k_values[1] * metric->bandwith)
|
||||
/ (256 - metric->load));
|
||||
if (eigrp->k_values[2])
|
||||
temp_metric += (eigrp->k_values[2] * metric->delay);
|
||||
if (eigrp->k_values[3] && !eigrp->k_values[4])
|
||||
temp_metric *= eigrp->k_values[3];
|
||||
if (!eigrp->k_values[3] && eigrp->k_values[4])
|
||||
temp_metric *= (eigrp->k_values[4] / metric->reliability);
|
||||
if (eigrp->k_values[3] && eigrp->k_values[4])
|
||||
temp_metric *= ((eigrp->k_values[4] / metric->reliability)
|
||||
+ eigrp->k_values[3]);
|
||||
|
||||
if (temp_metric <= EIGRP_MAX_METRIC)
|
||||
return (u_int32_t) temp_metric;
|
||||
else
|
||||
return EIGRP_MAX_METRIC;
|
||||
}
|
||||
|
||||
u_int32_t
|
||||
eigrp_calculate_total_metrics(struct eigrp *eigrp,
|
||||
struct eigrp_neighbor_entry *entry)
|
||||
{
|
||||
entry->total_metric = entry->reported_metric;
|
||||
u_int64_t temp_delay = (u_int64_t) entry->total_metric.delay
|
||||
+ (u_int64_t) EIGRP_IF_PARAM (entry->ei, delay);
|
||||
entry->total_metric.delay =
|
||||
temp_delay > EIGRP_MAX_METRIC ? EIGRP_MAX_METRIC : (u_int32_t) temp_delay;
|
||||
|
||||
u_int32_t bw = EIGRP_IF_PARAM (entry->ei,bandwidth);
|
||||
entry->total_metric.bandwith =
|
||||
entry->total_metric.bandwith > bw ? bw : entry->total_metric.bandwith;
|
||||
|
||||
return eigrp_calculate_metrics(eigrp, &entry->total_metric);
|
||||
}
|
||||
|
||||
u_char
|
||||
eigrp_metrics_is_same(struct eigrp_metrics *metric1,
|
||||
struct eigrp_metrics *metric2)
|
||||
{
|
||||
if ((metric1->bandwith == metric2->bandwith)
|
||||
&& (metric1->delay == metric2->delay)
|
||||
&& (metric1->hop_count == metric2->hop_count)
|
||||
&& (metric1->load == metric2->load)
|
||||
&& (metric1->reliability == metric2->reliability)
|
||||
&& (metric1->mtu[0] == metric2->mtu[0])
|
||||
&& (metric1->mtu[1] == metric2->mtu[1])
|
||||
&& (metric1->mtu[2] == metric2->mtu[2]))
|
||||
return 1;
|
||||
|
||||
return 0; // if different
|
||||
}
|
||||
void
|
||||
eigrp_external_routes_refresh (struct eigrp *eigrp, int type)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
52
eigrpd/eigrp_network.h
Normal file
52
eigrpd/eigrp_network.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* EIGRP Network Related Functions.
|
||||
* Copyright (C) 2013-2014
|
||||
* Authors:
|
||||
* Donnie Savage
|
||||
* Jan Janovic
|
||||
* Matej Perina
|
||||
* Peter Orsag
|
||||
* Peter Paluch
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _ZEBRA_EIGRP_NETWORK_H
|
||||
#define _ZEBRA_EIGRP_NETWORK_H
|
||||
|
||||
/* Prototypes */
|
||||
|
||||
extern int eigrp_sock_init (void);
|
||||
extern int eigrp_if_ipmulticast (struct eigrp *, struct prefix *, unsigned int);
|
||||
extern int eigrp_network_set (struct eigrp *, struct prefix_ipv4 *);
|
||||
extern int eigrp_network_unset (struct eigrp *eigrp, struct prefix_ipv4 *p);
|
||||
|
||||
extern int eigrp_hello_timer (struct thread *);
|
||||
extern void eigrp_if_update (struct interface *);
|
||||
extern int eigrp_if_add_allspfrouters (struct eigrp *, struct prefix *,
|
||||
unsigned int);
|
||||
extern int eigrp_if_drop_allspfrouters (struct eigrp *top, struct prefix *p,
|
||||
unsigned int ifindex);
|
||||
extern void eigrp_adjust_sndbuflen (struct eigrp *, unsigned int);
|
||||
|
||||
extern u_int32_t eigrp_calculate_metrics (struct eigrp *, struct eigrp_metrics *);
|
||||
extern u_int32_t eigrp_calculate_total_metrics (struct eigrp *, struct eigrp_neighbor_entry *);
|
||||
extern u_char eigrp_metrics_is_same(struct eigrp_metrics *,struct eigrp_metrics *);
|
||||
extern void eigrp_external_routes_refresh (struct eigrp *, int);
|
||||
|
||||
#endif /* EIGRP_NETWORK_H_ */
|
1441
eigrpd/eigrp_packet.c
Normal file
1441
eigrpd/eigrp_packet.c
Normal file
File diff suppressed because it is too large
Load diff
143
eigrpd/eigrp_packet.h
Normal file
143
eigrpd/eigrp_packet.h
Normal file
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* EIGRP General Sending and Receiving of EIGRP Packets.
|
||||
* Copyright (C) 2013-2016
|
||||
* Authors:
|
||||
* Donnie Savage
|
||||
* Jan Janovic
|
||||
* Matej Perina
|
||||
* Peter Orsag
|
||||
* Peter Paluch
|
||||
* Frantisek Gazo
|
||||
* Tomas Hvorkovy
|
||||
* Martin Kontsek
|
||||
* Lukas Koribsky
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _ZEBRA_EIGRP_PACKET_H
|
||||
#define _ZEBRA_EIGRP_PACKET_H
|
||||
|
||||
/*Prototypes*/
|
||||
extern int eigrp_read (struct thread *);
|
||||
extern int eigrp_write (struct thread *);
|
||||
|
||||
extern struct eigrp_packet *eigrp_packet_new (size_t);
|
||||
extern struct eigrp_packet *eigrp_packet_duplicate (struct eigrp_packet *, struct eigrp_neighbor *);
|
||||
extern void eigrp_packet_free (struct eigrp_packet *);
|
||||
extern void eigrp_packet_delete (struct eigrp_interface *);
|
||||
extern void eigrp_packet_header_init (int, struct eigrp_interface *, struct stream *,
|
||||
u_int32_t, u_int32_t, u_int32_t);
|
||||
extern void eigrp_packet_checksum (struct eigrp_interface *, struct stream *, u_int16_t);
|
||||
|
||||
extern struct eigrp_fifo *eigrp_fifo_new (void);
|
||||
extern struct eigrp_packet *eigrp_fifo_head (struct eigrp_fifo *);
|
||||
extern struct eigrp_packet *eigrp_fifo_tail (struct eigrp_fifo *);
|
||||
extern struct eigrp_packet *eigrp_fifo_pop (struct eigrp_fifo *);
|
||||
extern struct eigrp_packet *eigrp_fifo_pop_tail (struct eigrp_fifo *);
|
||||
extern void eigrp_fifo_push_head (struct eigrp_fifo *, struct eigrp_packet *);
|
||||
extern void eigrp_fifo_free (struct eigrp_fifo *);
|
||||
extern void eigrp_fifo_reset (struct eigrp_fifo *);
|
||||
|
||||
extern void eigrp_send_packet_reliably (struct eigrp_neighbor *);
|
||||
|
||||
extern struct TLV_IPv4_Internal_type *eigrp_read_ipv4_tlv (struct stream *);
|
||||
extern u_int16_t eigrp_add_internalTLV_to_stream (struct stream *, struct eigrp_prefix_entry *);
|
||||
extern u_int16_t eigrp_add_authTLV_MD5_to_stream (struct stream *, struct eigrp_interface *);
|
||||
extern u_int16_t eigrp_add_authTLV_SHA256_to_stream (struct stream *, struct eigrp_interface *);
|
||||
|
||||
extern int eigrp_unack_packet_retrans (struct thread *);
|
||||
extern int eigrp_unack_multicast_packet_retrans (struct thread *);
|
||||
|
||||
/*
|
||||
* untill there is reason to have their own header, these externs are found in
|
||||
* eigrp_hello.c
|
||||
*/
|
||||
extern void eigrp_hello_send (struct eigrp_interface *, u_char, struct in_addr *);
|
||||
extern void eigrp_hello_send_ack (struct eigrp_neighbor *);
|
||||
extern void eigrp_hello_receive (struct eigrp *, struct ip *, struct eigrp_header *,
|
||||
struct stream *, struct eigrp_interface *, int);
|
||||
extern int eigrp_hello_timer (struct thread *);
|
||||
|
||||
/*
|
||||
* These externs are found in eigrp_update.c
|
||||
*/
|
||||
extern void eigrp_update_send (struct eigrp_interface *);
|
||||
extern void eigrp_update_receive (struct eigrp *, struct ip *, struct eigrp_header *,
|
||||
struct stream *, struct eigrp_interface *, int);
|
||||
extern void eigrp_update_send_all (struct eigrp *, struct eigrp_interface *);
|
||||
extern void eigrp_update_send_init (struct eigrp_neighbor *);
|
||||
extern void eigrp_update_send_EOT (struct eigrp_neighbor *);
|
||||
extern int eigrp_update_send_GR_thread(struct thread *);
|
||||
extern void eigrp_update_send_GR (struct eigrp_neighbor *, enum GR_type, struct vty *);
|
||||
extern void eigrp_update_send_interface_GR (struct eigrp_interface *, enum GR_type, struct vty *);
|
||||
extern void eigrp_update_send_process_GR (struct eigrp *, enum GR_type, struct vty *);
|
||||
|
||||
/*
|
||||
* These externs are found in eigrp_query.c
|
||||
*/
|
||||
|
||||
extern void eigrp_send_query (struct eigrp_interface *);
|
||||
extern void eigrp_query_receive (struct eigrp *, struct ip *, struct eigrp_header *,
|
||||
struct stream *, struct eigrp_interface *, int);
|
||||
extern u_int32_t eigrp_query_send_all (struct eigrp *);
|
||||
|
||||
/*
|
||||
* These externs are found in eigrp_reply.c
|
||||
*/
|
||||
extern void eigrp_send_reply (struct eigrp_neighbor *, struct eigrp_prefix_entry *);
|
||||
extern void eigrp_reply_receive (struct eigrp *, struct ip *, struct eigrp_header *,
|
||||
struct stream *, struct eigrp_interface *, int);
|
||||
|
||||
/*
|
||||
* These externs are found in eigrp_siaquery.c
|
||||
*/
|
||||
extern void eigrp_send_siaquery (struct eigrp_neighbor *, struct eigrp_prefix_entry *);
|
||||
extern void eigrp_siaquery_receive (struct eigrp *, struct ip *, struct eigrp_header *,
|
||||
struct stream *, struct eigrp_interface *, int);
|
||||
|
||||
/*
|
||||
* These externs are found in eigrp_siareply.c
|
||||
*/
|
||||
extern void eigrp_send_siareply (struct eigrp_neighbor *, struct eigrp_prefix_entry *);
|
||||
extern void eigrp_siareply_receive (struct eigrp *, struct ip *, struct eigrp_header *,
|
||||
struct stream *, struct eigrp_interface *, int);
|
||||
|
||||
extern struct TLV_MD5_Authentication_Type *eigrp_authTLV_MD5_new (void);
|
||||
extern void eigrp_authTLV_MD5_free (struct TLV_MD5_Authentication_Type *);
|
||||
extern struct TLV_SHA256_Authentication_Type *eigrp_authTLV_SHA256_new (void);
|
||||
extern void eigrp_authTLV_SHA256_free (struct TLV_SHA256_Authentication_Type *);
|
||||
|
||||
extern int eigrp_make_md5_digest (struct eigrp_interface *, struct stream *,
|
||||
u_char);
|
||||
extern int eigrp_check_md5_digest (struct stream *, struct TLV_MD5_Authentication_Type *,
|
||||
struct eigrp_neighbor *, u_char);
|
||||
extern int eigrp_make_sha256_digest (struct eigrp_interface *, struct stream *, u_char);
|
||||
extern int eigrp_check_sha256_digest (struct stream *, struct TLV_SHA256_Authentication_Type *,
|
||||
struct eigrp_neighbor *, u_char );
|
||||
|
||||
|
||||
extern struct TLV_IPv4_Internal_type *eigrp_IPv4_InternalTLV_new (void);
|
||||
extern void eigrp_IPv4_InternalTLV_free (struct TLV_IPv4_Internal_type *);
|
||||
|
||||
extern struct TLV_Sequence_Type *eigrp_SequenceTLV_new (void);
|
||||
|
||||
extern const struct message eigrp_packet_type_str[];
|
||||
extern const size_t eigrp_packet_type_str_max;
|
||||
|
||||
#endif /* _ZEBRA_EIGRP_PACKET_H */
|
0
eigrpd/eigrp_pkt_tlv1.c
Normal file
0
eigrpd/eigrp_pkt_tlv1.c
Normal file
0
eigrpd/eigrp_pkt_tlv2.c
Normal file
0
eigrpd/eigrp_pkt_tlv2.c
Normal file
226
eigrpd/eigrp_query.c
Normal file
226
eigrpd/eigrp_query.c
Normal file
|
@ -0,0 +1,226 @@
|
|||
/*
|
||||
* EIGRP Sending and Receiving EIGRP Query Packets.
|
||||
* Copyright (C) 2013-2014
|
||||
* Authors:
|
||||
* Donnie Savage
|
||||
* Jan Janovic
|
||||
* Matej Perina
|
||||
* Peter Orsag
|
||||
* Peter Paluch
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#include "thread.h"
|
||||
#include "memory.h"
|
||||
#include "linklist.h"
|
||||
#include "prefix.h"
|
||||
#include "if.h"
|
||||
#include "table.h"
|
||||
#include "sockunion.h"
|
||||
#include "stream.h"
|
||||
#include "log.h"
|
||||
#include "sockopt.h"
|
||||
#include "checksum.h"
|
||||
#include "md5.h"
|
||||
#include "vty.h"
|
||||
|
||||
#include "eigrpd/eigrp_structs.h"
|
||||
#include "eigrpd/eigrpd.h"
|
||||
#include "eigrpd/eigrp_interface.h"
|
||||
#include "eigrpd/eigrp_neighbor.h"
|
||||
#include "eigrpd/eigrp_packet.h"
|
||||
#include "eigrpd/eigrp_zebra.h"
|
||||
#include "eigrpd/eigrp_vty.h"
|
||||
#include "eigrpd/eigrp_dump.h"
|
||||
#include "eigrpd/eigrp_macros.h"
|
||||
#include "eigrpd/eigrp_topology.h"
|
||||
#include "eigrpd/eigrp_fsm.h"
|
||||
#include "eigrpd/eigrp_memory.h"
|
||||
|
||||
u_int32_t
|
||||
eigrp_query_send_all (struct eigrp *eigrp)
|
||||
{
|
||||
struct eigrp_interface *iface;
|
||||
struct listnode *node, *node2, *nnode2;
|
||||
struct eigrp_prefix_entry *pe;
|
||||
u_int32_t counter;
|
||||
|
||||
if (eigrp == NULL)
|
||||
{
|
||||
zlog_debug("EIGRP Routing Process not enabled");
|
||||
return 0;
|
||||
}
|
||||
|
||||
counter=0;
|
||||
for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, iface))
|
||||
{
|
||||
eigrp_send_query(iface);
|
||||
counter++;
|
||||
}
|
||||
|
||||
for (ALL_LIST_ELEMENTS(eigrp->topology_changes_internalIPV4, node2, nnode2, pe))
|
||||
{
|
||||
if(pe->req_action & EIGRP_FSM_NEED_QUERY)
|
||||
{
|
||||
pe->req_action &= ~EIGRP_FSM_NEED_QUERY;
|
||||
listnode_delete(eigrp->topology_changes_internalIPV4, pe);
|
||||
}
|
||||
}
|
||||
|
||||
return counter;
|
||||
}
|
||||
|
||||
/*EIGRP QUERY read function*/
|
||||
void
|
||||
eigrp_query_receive (struct eigrp *eigrp, struct ip *iph, struct eigrp_header *eigrph,
|
||||
struct stream * s, struct eigrp_interface *ei, int size)
|
||||
{
|
||||
struct eigrp_neighbor *nbr;
|
||||
struct TLV_IPv4_Internal_type *tlv;
|
||||
|
||||
u_int16_t type;
|
||||
|
||||
/* increment statistics. */
|
||||
ei->query_in++;
|
||||
|
||||
/* get neighbor struct */
|
||||
nbr = eigrp_nbr_get(ei, eigrph, iph);
|
||||
|
||||
/* neighbor must be valid, eigrp_nbr_get creates if none existed */
|
||||
assert(nbr);
|
||||
|
||||
nbr->recv_sequence_number = ntohl(eigrph->sequence);
|
||||
|
||||
while (s->endp > s->getp)
|
||||
{
|
||||
type = stream_getw(s);
|
||||
if (type == EIGRP_TLV_IPv4_INT)
|
||||
{
|
||||
stream_set_getp(s, s->getp - sizeof(u_int16_t));
|
||||
|
||||
tlv = eigrp_read_ipv4_tlv(s);
|
||||
|
||||
struct prefix_ipv4 *dest_addr;
|
||||
dest_addr = prefix_ipv4_new();
|
||||
dest_addr->prefix = tlv->destination;
|
||||
dest_addr->prefixlen = tlv->prefix_length;
|
||||
struct eigrp_prefix_entry *dest = eigrp_topology_table_lookup_ipv4(
|
||||
eigrp->topology_table, dest_addr);
|
||||
|
||||
/* If the destination exists (it should, but one never know)*/
|
||||
if (dest != NULL)
|
||||
{
|
||||
struct eigrp_fsm_action_message *msg;
|
||||
msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
|
||||
sizeof(struct eigrp_fsm_action_message));
|
||||
struct eigrp_neighbor_entry *entry = eigrp_prefix_entry_lookup(
|
||||
dest->entries, nbr);
|
||||
msg->packet_type = EIGRP_OPC_QUERY;
|
||||
msg->eigrp = eigrp;
|
||||
msg->data_type = EIGRP_TLV_IPv4_INT;
|
||||
msg->adv_router = nbr;
|
||||
msg->data.ipv4_int_type = tlv;
|
||||
msg->entry = entry;
|
||||
msg->prefix = dest;
|
||||
int event = eigrp_get_fsm_event(msg);
|
||||
eigrp_fsm_event(msg, event);
|
||||
}
|
||||
eigrp_IPv4_InternalTLV_free (tlv);
|
||||
}
|
||||
}
|
||||
eigrp_hello_send_ack(nbr);
|
||||
eigrp_query_send_all(eigrp);
|
||||
eigrp_update_send_all(eigrp,nbr->ei);
|
||||
}
|
||||
|
||||
void
|
||||
eigrp_send_query (struct eigrp_interface *ei)
|
||||
{
|
||||
struct eigrp_packet *ep;
|
||||
u_int16_t length = EIGRP_HEADER_LEN;
|
||||
struct listnode *node, *nnode, *node2, *nnode2;
|
||||
struct eigrp_neighbor *nbr;
|
||||
struct eigrp_prefix_entry *pe;
|
||||
char has_tlv;
|
||||
|
||||
ep = eigrp_packet_new(ei->ifp->mtu);
|
||||
|
||||
/* Prepare EIGRP INIT UPDATE header */
|
||||
eigrp_packet_header_init(EIGRP_OPC_QUERY, ei, ep->s, 0,
|
||||
ei->eigrp->sequence_number, 0);
|
||||
|
||||
// encode Authentication TLV, if needed
|
||||
if((IF_DEF_PARAMS (ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (ei->ifp)->auth_keychain != NULL))
|
||||
{
|
||||
length += eigrp_add_authTLV_MD5_to_stream(ep->s,ei);
|
||||
}
|
||||
|
||||
has_tlv = 0;
|
||||
for (ALL_LIST_ELEMENTS(ei->eigrp->topology_changes_internalIPV4, node, nnode, pe))
|
||||
{
|
||||
if(pe->req_action & EIGRP_FSM_NEED_QUERY)
|
||||
{
|
||||
length += eigrp_add_internalTLV_to_stream(ep->s, pe);
|
||||
for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr))
|
||||
{
|
||||
if(nbr->state == EIGRP_NEIGHBOR_UP)
|
||||
{
|
||||
listnode_add(pe->rij, nbr);
|
||||
has_tlv = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!has_tlv)
|
||||
{
|
||||
eigrp_packet_free(ep);
|
||||
return;
|
||||
}
|
||||
|
||||
if((IF_DEF_PARAMS (ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (ei->ifp)->auth_keychain != NULL))
|
||||
{
|
||||
eigrp_make_md5_digest(ei,ep->s, EIGRP_AUTH_UPDATE_FLAG);
|
||||
}
|
||||
|
||||
/* EIGRP Checksum */
|
||||
eigrp_packet_checksum(ei, ep->s, length);
|
||||
|
||||
ep->length = length;
|
||||
ep->dst.s_addr = htonl(EIGRP_MULTICAST_ADDRESS);
|
||||
|
||||
/*This ack number we await from neighbor*/
|
||||
ep->sequence_number = ei->eigrp->sequence_number;
|
||||
|
||||
for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr))
|
||||
{
|
||||
if (nbr->state == EIGRP_NEIGHBOR_UP)
|
||||
{
|
||||
/*Put packet to retransmission queue*/
|
||||
eigrp_fifo_push_head(nbr->retrans_queue, ep);
|
||||
|
||||
if (nbr->retrans_queue->count == 1)
|
||||
{
|
||||
eigrp_send_packet_reliably(nbr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
249
eigrpd/eigrp_reply.c
Normal file
249
eigrpd/eigrp_reply.c
Normal file
|
@ -0,0 +1,249 @@
|
|||
/*
|
||||
* EIGRP Sending and Receiving EIGRP Reply Packets.
|
||||
* Copyright (C) 2013-2016
|
||||
* Authors:
|
||||
* Donnie Savage
|
||||
* Jan Janovic
|
||||
* Matej Perina
|
||||
* Peter Orsag
|
||||
* Peter Paluch
|
||||
* Frantisek Gazo
|
||||
* Tomas Hvorkovy
|
||||
* Martin Kontsek
|
||||
* Lukas Koribsky
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#include "thread.h"
|
||||
#include "memory.h"
|
||||
#include "linklist.h"
|
||||
#include "prefix.h"
|
||||
#include "if.h"
|
||||
#include "table.h"
|
||||
#include "sockunion.h"
|
||||
#include "stream.h"
|
||||
#include "log.h"
|
||||
#include "sockopt.h"
|
||||
#include "checksum.h"
|
||||
#include "md5.h"
|
||||
#include "vty.h"
|
||||
#include "keychain.h"
|
||||
#include "plist.h"
|
||||
|
||||
#include "eigrpd/eigrp_structs.h"
|
||||
#include "eigrpd/eigrpd.h"
|
||||
#include "eigrpd/eigrp_interface.h"
|
||||
#include "eigrpd/eigrp_neighbor.h"
|
||||
#include "eigrpd/eigrp_packet.h"
|
||||
#include "eigrpd/eigrp_zebra.h"
|
||||
#include "eigrpd/eigrp_vty.h"
|
||||
#include "eigrpd/eigrp_dump.h"
|
||||
#include "eigrpd/eigrp_macros.h"
|
||||
#include "eigrpd/eigrp_topology.h"
|
||||
#include "eigrpd/eigrp_fsm.h"
|
||||
#include "eigrpd/eigrp_memory.h"
|
||||
|
||||
void
|
||||
eigrp_send_reply (struct eigrp_neighbor *nbr, struct eigrp_prefix_entry *pe)
|
||||
{
|
||||
struct eigrp_packet *ep;
|
||||
u_int16_t length = EIGRP_HEADER_LEN;
|
||||
|
||||
struct access_list *alist;
|
||||
struct prefix_list *plist;
|
||||
struct access_list *alist_i;
|
||||
struct prefix_list *plist_i;
|
||||
struct eigrp *e;
|
||||
struct eigrp_prefix_entry *pe2;
|
||||
|
||||
//TODO: Work in progress
|
||||
/* Filtering */
|
||||
/* get list from eigrp process */
|
||||
e = eigrp_lookup();
|
||||
pe2 = XCALLOC(MTYPE_EIGRP_PREFIX_ENTRY, sizeof(struct eigrp_prefix_entry));
|
||||
memcpy(pe2,pe,sizeof(struct eigrp_prefix_entry));
|
||||
/* Get access-lists and prefix-lists from process and interface */
|
||||
alist = e->list[EIGRP_FILTER_OUT];
|
||||
plist = e->prefix[EIGRP_FILTER_OUT];
|
||||
alist_i = nbr->ei->list[EIGRP_FILTER_OUT];
|
||||
plist_i = nbr->ei->prefix[EIGRP_FILTER_OUT];
|
||||
zlog_info("REPLY Send: Filtering");
|
||||
|
||||
zlog_info("REPLY SEND Prefix: %s", inet_ntoa(nbr->src));
|
||||
/* Check if any list fits */
|
||||
if ((alist && access_list_apply (alist, (struct prefix *) pe2->destination_ipv4) == FILTER_DENY)||
|
||||
(plist && prefix_list_apply (plist, (struct prefix *) pe2->destination_ipv4) == FILTER_DENY)||
|
||||
(alist_i && access_list_apply (alist_i, (struct prefix *) pe2->destination_ipv4) == FILTER_DENY)||
|
||||
(plist_i && prefix_list_apply (plist_i, (struct prefix *) pe2->destination_ipv4) == FILTER_DENY))
|
||||
{
|
||||
zlog_info("REPLY SEND: Setting Metric to max");
|
||||
pe2->reported_metric.delay = EIGRP_MAX_METRIC;
|
||||
|
||||
} else {
|
||||
zlog_info("REPLY SEND: Not setting metric");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* End of filtering
|
||||
*/
|
||||
|
||||
ep = eigrp_packet_new(nbr->ei->ifp->mtu);
|
||||
|
||||
/* Prepare EIGRP INIT UPDATE header */
|
||||
eigrp_packet_header_init(EIGRP_OPC_REPLY, nbr->ei, ep->s, 0,
|
||||
nbr->ei->eigrp->sequence_number, 0);
|
||||
|
||||
// encode Authentication TLV, if needed
|
||||
if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL))
|
||||
{
|
||||
length += eigrp_add_authTLV_MD5_to_stream(ep->s,nbr->ei);
|
||||
}
|
||||
|
||||
|
||||
length += eigrp_add_internalTLV_to_stream(ep->s, pe2);
|
||||
|
||||
if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL))
|
||||
{
|
||||
eigrp_make_md5_digest(nbr->ei,ep->s, EIGRP_AUTH_UPDATE_FLAG);
|
||||
}
|
||||
|
||||
/* EIGRP Checksum */
|
||||
eigrp_packet_checksum(nbr->ei, ep->s, length);
|
||||
|
||||
ep->length = length;
|
||||
ep->dst.s_addr = nbr->src.s_addr;
|
||||
|
||||
/*This ack number we await from neighbor*/
|
||||
ep->sequence_number = nbr->ei->eigrp->sequence_number;
|
||||
|
||||
/*Put packet to retransmission queue*/
|
||||
eigrp_fifo_push_head(nbr->retrans_queue, ep);
|
||||
|
||||
if (nbr->retrans_queue->count == 1)
|
||||
{
|
||||
eigrp_send_packet_reliably(nbr);
|
||||
}
|
||||
}
|
||||
|
||||
/*EIGRP REPLY read function*/
|
||||
void
|
||||
eigrp_reply_receive (struct eigrp *eigrp, struct ip *iph, struct eigrp_header *eigrph,
|
||||
struct stream * s, struct eigrp_interface *ei, int size)
|
||||
{
|
||||
struct eigrp_neighbor *nbr;
|
||||
struct TLV_IPv4_Internal_type *tlv;
|
||||
|
||||
struct access_list *alist;
|
||||
struct prefix_list *plist;
|
||||
struct access_list *alist_i;
|
||||
struct prefix_list *plist_i;
|
||||
struct eigrp *e;
|
||||
|
||||
u_int16_t type;
|
||||
|
||||
/* increment statistics. */
|
||||
ei->reply_in++;
|
||||
|
||||
/* get neighbor struct */
|
||||
nbr = eigrp_nbr_get(ei, eigrph, iph);
|
||||
|
||||
/* neighbor must be valid, eigrp_nbr_get creates if none existed */
|
||||
assert(nbr);
|
||||
|
||||
nbr->recv_sequence_number = ntohl(eigrph->sequence);
|
||||
|
||||
while (s->endp > s->getp)
|
||||
{
|
||||
type = stream_getw(s);
|
||||
if (type == EIGRP_TLV_IPv4_INT)
|
||||
{
|
||||
stream_set_getp(s, s->getp - sizeof(u_int16_t));
|
||||
|
||||
tlv = eigrp_read_ipv4_tlv(s);
|
||||
|
||||
struct prefix_ipv4 *dest_addr;
|
||||
dest_addr = prefix_ipv4_new();
|
||||
dest_addr->prefix = tlv->destination;
|
||||
dest_addr->prefixlen = tlv->prefix_length;
|
||||
struct eigrp_prefix_entry *dest = eigrp_topology_table_lookup_ipv4(
|
||||
eigrp->topology_table, dest_addr);
|
||||
/*
|
||||
* Destination must exists
|
||||
*/
|
||||
assert(dest);
|
||||
|
||||
struct eigrp_fsm_action_message *msg;
|
||||
msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
|
||||
sizeof(struct eigrp_fsm_action_message));
|
||||
struct eigrp_neighbor_entry *entry = eigrp_prefix_entry_lookup(
|
||||
dest->entries, nbr);
|
||||
|
||||
/*
|
||||
* Filtering
|
||||
*/
|
||||
//TODO: Work in progress
|
||||
/* get list from eigrp process */
|
||||
e = eigrp_lookup();
|
||||
/* Get access-lists and prefix-lists from process and interface */
|
||||
alist = e->list[EIGRP_FILTER_IN];
|
||||
plist = e->prefix[EIGRP_FILTER_IN];
|
||||
alist_i = ei->list[EIGRP_FILTER_IN];
|
||||
plist_i = ei->prefix[EIGRP_FILTER_IN];
|
||||
zlog_info("REPLY Receive: Filtering");
|
||||
zlog_info("REPLY RECEIVE Prefix: %s", inet_ntoa(dest_addr->prefix));
|
||||
/* Check if any list fits */
|
||||
if ((alist && access_list_apply (alist,
|
||||
(struct prefix *) dest_addr) == FILTER_DENY)||
|
||||
(plist && prefix_list_apply (plist,
|
||||
(struct prefix *) dest_addr) == FILTER_DENY)||
|
||||
(alist_i && access_list_apply (alist_i,
|
||||
(struct prefix *) dest_addr) == FILTER_DENY)||
|
||||
(plist_i && prefix_list_apply (plist_i,
|
||||
(struct prefix *) dest_addr) == FILTER_DENY))
|
||||
{
|
||||
zlog_info("REPLY RECEIVE: Setting metric to max");
|
||||
tlv->metric.delay = EIGRP_MAX_METRIC;
|
||||
zlog_info("REPLY RECEIVE Prefix: %s", inet_ntoa(dest_addr->prefix));
|
||||
} else {
|
||||
zlog_info("REPLY RECEIVE: Not setting metric");
|
||||
}
|
||||
/*
|
||||
* End of filtering
|
||||
*/
|
||||
|
||||
msg->packet_type = EIGRP_OPC_REPLY;
|
||||
msg->eigrp = eigrp;
|
||||
msg->data_type = EIGRP_TLV_IPv4_INT;
|
||||
msg->adv_router = nbr;
|
||||
msg->data.ipv4_int_type = tlv;
|
||||
msg->entry = entry;
|
||||
msg->prefix = dest;
|
||||
int event = eigrp_get_fsm_event(msg);
|
||||
eigrp_fsm_event(msg, event);
|
||||
|
||||
|
||||
eigrp_IPv4_InternalTLV_free (tlv);
|
||||
}
|
||||
}
|
||||
eigrp_hello_send_ack(nbr);
|
||||
}
|
||||
|
1244
eigrpd/eigrp_routemap.c
Normal file
1244
eigrpd/eigrp_routemap.c
Normal file
File diff suppressed because it is too large
Load diff
18
eigrpd/eigrp_routemap.h
Normal file
18
eigrpd/eigrp_routemap.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* eigrp_routemap.h
|
||||
*
|
||||
* Created on: Nov 19, 2015
|
||||
* Author: root
|
||||
*/
|
||||
|
||||
#ifndef EIGRPD_EIGRP_ROUTEMAP_H_
|
||||
#define EIGRPD_EIGRP_ROUTEMAP_H_
|
||||
|
||||
extern void eigrp_route_map_update (const char *);
|
||||
extern void eigrp_route_map_init ();
|
||||
extern void eigrp_if_rmap_update (struct if_rmap *);
|
||||
extern void eigrp_if_rmap_update_interface (struct interface *);
|
||||
extern void eigrp_routemap_update_redistribute (void);
|
||||
extern void eigrp_rmap_update (const char *);
|
||||
|
||||
#endif /* EIGRPD_EIGRP_ROUTEMAP_H_ */
|
164
eigrpd/eigrp_siaquery.c
Normal file
164
eigrpd/eigrp_siaquery.c
Normal file
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
* EIGRP Sending and Receiving EIGRP SIA-Query Packets.
|
||||
* Copyright (C) 2013-2014
|
||||
* Authors:
|
||||
* Donnie Savage
|
||||
* Jan Janovic
|
||||
* Matej Perina
|
||||
* Peter Orsag
|
||||
* Peter Paluch
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#include "thread.h"
|
||||
#include "memory.h"
|
||||
#include "linklist.h"
|
||||
#include "prefix.h"
|
||||
#include "if.h"
|
||||
#include "table.h"
|
||||
#include "sockunion.h"
|
||||
#include "stream.h"
|
||||
#include "log.h"
|
||||
#include "sockopt.h"
|
||||
#include "checksum.h"
|
||||
#include "md5.h"
|
||||
#include "vty.h"
|
||||
|
||||
#include "eigrpd/eigrp_structs.h"
|
||||
#include "eigrpd/eigrpd.h"
|
||||
#include "eigrpd/eigrp_interface.h"
|
||||
#include "eigrpd/eigrp_neighbor.h"
|
||||
#include "eigrpd/eigrp_packet.h"
|
||||
#include "eigrpd/eigrp_zebra.h"
|
||||
#include "eigrpd/eigrp_vty.h"
|
||||
#include "eigrpd/eigrp_dump.h"
|
||||
#include "eigrpd/eigrp_macros.h"
|
||||
#include "eigrpd/eigrp_topology.h"
|
||||
#include "eigrpd/eigrp_fsm.h"
|
||||
#include "eigrpd/eigrp_memory.h"
|
||||
|
||||
/*EIGRP SIA-QUERY read function*/
|
||||
void
|
||||
eigrp_siaquery_receive (struct eigrp *eigrp, struct ip *iph, struct eigrp_header *eigrph,
|
||||
struct stream * s, struct eigrp_interface *ei, int size)
|
||||
{
|
||||
struct eigrp_neighbor *nbr;
|
||||
struct TLV_IPv4_Internal_type *tlv;
|
||||
|
||||
u_int16_t type;
|
||||
|
||||
/* increment statistics. */
|
||||
ei->siaQuery_in++;
|
||||
|
||||
/* get neighbor struct */
|
||||
nbr = eigrp_nbr_get(ei, eigrph, iph);
|
||||
|
||||
/* neighbor must be valid, eigrp_nbr_get creates if none existed */
|
||||
assert(nbr);
|
||||
|
||||
nbr->recv_sequence_number = ntohl(eigrph->sequence);
|
||||
|
||||
while (s->endp > s->getp)
|
||||
{
|
||||
type = stream_getw(s);
|
||||
if (type == EIGRP_TLV_IPv4_INT)
|
||||
{
|
||||
stream_set_getp(s, s->getp - sizeof(u_int16_t));
|
||||
|
||||
tlv = eigrp_read_ipv4_tlv(s);
|
||||
|
||||
struct prefix_ipv4 *dest_addr;
|
||||
dest_addr = prefix_ipv4_new();
|
||||
dest_addr->prefix = tlv->destination;
|
||||
dest_addr->prefixlen = tlv->prefix_length;
|
||||
struct eigrp_prefix_entry *dest = eigrp_topology_table_lookup_ipv4(
|
||||
eigrp->topology_table, dest_addr);
|
||||
|
||||
/* If the destination exists (it should, but one never know)*/
|
||||
if (dest != NULL)
|
||||
{
|
||||
struct eigrp_fsm_action_message *msg;
|
||||
msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
|
||||
sizeof(struct eigrp_fsm_action_message));
|
||||
struct eigrp_neighbor_entry *entry = eigrp_prefix_entry_lookup(
|
||||
dest->entries, nbr);
|
||||
msg->packet_type = EIGRP_OPC_SIAQUERY;
|
||||
msg->eigrp = eigrp;
|
||||
msg->data_type = EIGRP_TLV_IPv4_INT;
|
||||
msg->adv_router = nbr;
|
||||
msg->data.ipv4_int_type = tlv;
|
||||
msg->entry = entry;
|
||||
msg->prefix = dest;
|
||||
int event = eigrp_get_fsm_event(msg);
|
||||
eigrp_fsm_event(msg, event);
|
||||
}
|
||||
eigrp_IPv4_InternalTLV_free (tlv);
|
||||
}
|
||||
}
|
||||
eigrp_hello_send_ack(nbr);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
eigrp_send_siaquery (struct eigrp_neighbor *nbr, struct eigrp_prefix_entry *pe)
|
||||
{
|
||||
struct eigrp_packet *ep;
|
||||
u_int16_t length = EIGRP_HEADER_LEN;
|
||||
|
||||
ep = eigrp_packet_new(nbr->ei->ifp->mtu);
|
||||
|
||||
/* Prepare EIGRP INIT UPDATE header */
|
||||
eigrp_packet_header_init(EIGRP_OPC_SIAQUERY, nbr->ei, ep->s, 0,
|
||||
nbr->ei->eigrp->sequence_number, 0);
|
||||
|
||||
// encode Authentication TLV, if needed
|
||||
if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL))
|
||||
{
|
||||
length += eigrp_add_authTLV_MD5_to_stream(ep->s,nbr->ei);
|
||||
}
|
||||
|
||||
length += eigrp_add_internalTLV_to_stream(ep->s, pe);
|
||||
|
||||
if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL))
|
||||
{
|
||||
eigrp_make_md5_digest(nbr->ei,ep->s, EIGRP_AUTH_UPDATE_FLAG);
|
||||
}
|
||||
|
||||
/* EIGRP Checksum */
|
||||
eigrp_packet_checksum(nbr->ei, ep->s, length);
|
||||
|
||||
ep->length = length;
|
||||
ep->dst.s_addr = nbr->src.s_addr;
|
||||
|
||||
/*This ack number we await from neighbor*/
|
||||
ep->sequence_number = nbr->ei->eigrp->sequence_number;
|
||||
|
||||
if (nbr->state == EIGRP_NEIGHBOR_UP)
|
||||
{
|
||||
/*Put packet to retransmission queue*/
|
||||
eigrp_fifo_push_head(nbr->retrans_queue, ep);
|
||||
|
||||
if (nbr->retrans_queue->count == 1)
|
||||
{
|
||||
eigrp_send_packet_reliably(nbr);
|
||||
}
|
||||
}
|
||||
}
|
165
eigrpd/eigrp_siareply.c
Normal file
165
eigrpd/eigrp_siareply.c
Normal file
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* EIGRP Sending and Receiving EIGRP SIA-Reply Packets.
|
||||
* Copyright (C) 2013-2014
|
||||
* Authors:
|
||||
* Donnie Savage
|
||||
* Jan Janovic
|
||||
* Matej Perina
|
||||
* Peter Orsag
|
||||
* Peter Paluch
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#include "thread.h"
|
||||
#include "memory.h"
|
||||
#include "linklist.h"
|
||||
#include "prefix.h"
|
||||
#include "if.h"
|
||||
#include "table.h"
|
||||
#include "sockunion.h"
|
||||
#include "stream.h"
|
||||
#include "log.h"
|
||||
#include "sockopt.h"
|
||||
#include "checksum.h"
|
||||
#include "md5.h"
|
||||
#include "vty.h"
|
||||
|
||||
#include "eigrpd/eigrp_structs.h"
|
||||
#include "eigrpd/eigrpd.h"
|
||||
#include "eigrpd/eigrp_interface.h"
|
||||
#include "eigrpd/eigrp_neighbor.h"
|
||||
#include "eigrpd/eigrp_packet.h"
|
||||
#include "eigrpd/eigrp_zebra.h"
|
||||
#include "eigrpd/eigrp_vty.h"
|
||||
#include "eigrpd/eigrp_dump.h"
|
||||
#include "eigrpd/eigrp_macros.h"
|
||||
#include "eigrpd/eigrp_topology.h"
|
||||
#include "eigrpd/eigrp_fsm.h"
|
||||
#include "eigrpd/eigrp_memory.h"
|
||||
|
||||
/*EIGRP SIA-REPLY read function*/
|
||||
void
|
||||
eigrp_siareply_receive (struct eigrp *eigrp, struct ip *iph, struct eigrp_header *eigrph,
|
||||
struct stream * s, struct eigrp_interface *ei, int size)
|
||||
{
|
||||
struct eigrp_neighbor *nbr;
|
||||
struct TLV_IPv4_Internal_type *tlv;
|
||||
|
||||
u_int16_t type;
|
||||
|
||||
/* increment statistics. */
|
||||
ei->siaReply_in++;
|
||||
|
||||
/* get neighbor struct */
|
||||
nbr = eigrp_nbr_get(ei, eigrph, iph);
|
||||
|
||||
/* neighbor must be valid, eigrp_nbr_get creates if none existed */
|
||||
assert(nbr);
|
||||
|
||||
nbr->recv_sequence_number = ntohl(eigrph->sequence);
|
||||
|
||||
while (s->endp > s->getp)
|
||||
{
|
||||
type = stream_getw(s);
|
||||
if (type == EIGRP_TLV_IPv4_INT)
|
||||
{
|
||||
stream_set_getp(s, s->getp - sizeof(u_int16_t));
|
||||
|
||||
tlv = eigrp_read_ipv4_tlv(s);
|
||||
|
||||
struct prefix_ipv4 *dest_addr;
|
||||
dest_addr = prefix_ipv4_new();
|
||||
dest_addr->prefix = tlv->destination;
|
||||
dest_addr->prefixlen = tlv->prefix_length;
|
||||
struct eigrp_prefix_entry *dest = eigrp_topology_table_lookup_ipv4(
|
||||
eigrp->topology_table, dest_addr);
|
||||
|
||||
/* If the destination exists (it should, but one never know)*/
|
||||
if (dest != NULL)
|
||||
{
|
||||
struct eigrp_fsm_action_message *msg;
|
||||
msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
|
||||
sizeof(struct eigrp_fsm_action_message));
|
||||
struct eigrp_neighbor_entry *entry = eigrp_prefix_entry_lookup(
|
||||
dest->entries, nbr);
|
||||
msg->packet_type = EIGRP_OPC_SIAQUERY;
|
||||
msg->eigrp = eigrp;
|
||||
msg->data_type = EIGRP_TLV_IPv4_INT;
|
||||
msg->adv_router = nbr;
|
||||
msg->data.ipv4_int_type = tlv;
|
||||
msg->entry = entry;
|
||||
msg->prefix = dest;
|
||||
int event = eigrp_get_fsm_event(msg);
|
||||
eigrp_fsm_event(msg, event);
|
||||
}
|
||||
eigrp_IPv4_InternalTLV_free (tlv);
|
||||
}
|
||||
}
|
||||
eigrp_hello_send_ack(nbr);
|
||||
}
|
||||
|
||||
void
|
||||
eigrp_send_siareply (struct eigrp_neighbor *nbr, struct eigrp_prefix_entry *pe)
|
||||
{
|
||||
struct eigrp_packet *ep;
|
||||
u_int16_t length = EIGRP_HEADER_LEN;
|
||||
|
||||
ep = eigrp_packet_new(nbr->ei->ifp->mtu);
|
||||
|
||||
/* Prepare EIGRP INIT UPDATE header */
|
||||
eigrp_packet_header_init(EIGRP_OPC_SIAREPLY, nbr->ei, ep->s, 0,
|
||||
nbr->ei->eigrp->sequence_number, 0);
|
||||
|
||||
// encode Authentication TLV, if needed
|
||||
if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL))
|
||||
{
|
||||
length += eigrp_add_authTLV_MD5_to_stream(ep->s,nbr->ei);
|
||||
}
|
||||
|
||||
length += eigrp_add_internalTLV_to_stream(ep->s, pe);
|
||||
|
||||
if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL))
|
||||
{
|
||||
eigrp_make_md5_digest(nbr->ei,ep->s, EIGRP_AUTH_UPDATE_FLAG);
|
||||
}
|
||||
|
||||
/* EIGRP Checksum */
|
||||
eigrp_packet_checksum(nbr->ei, ep->s, length);
|
||||
|
||||
ep->length = length;
|
||||
ep->dst.s_addr = nbr->src.s_addr;
|
||||
|
||||
/*This ack number we await from neighbor*/
|
||||
ep->sequence_number = nbr->ei->eigrp->sequence_number;
|
||||
|
||||
if (nbr->state == EIGRP_NEIGHBOR_UP)
|
||||
{
|
||||
/*Put packet to retransmission queue*/
|
||||
eigrp_fifo_push_head(nbr->retrans_queue, ep);
|
||||
|
||||
if (nbr->retrans_queue->count == 1)
|
||||
{
|
||||
eigrp_send_packet_reliably(nbr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
1395
eigrpd/eigrp_snmp.c
Normal file
1395
eigrpd/eigrp_snmp.c
Normal file
File diff suppressed because it is too large
Load diff
36
eigrpd/eigrp_snmp.h
Normal file
36
eigrpd/eigrp_snmp.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* EIGRP SNMP Support.
|
||||
* Copyright (C) 2013-2014
|
||||
* Authors:
|
||||
* Donnie Savage
|
||||
* Jan Janovic
|
||||
* Matej Perina
|
||||
* Peter Orsag
|
||||
* Peter Paluch
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _ZEBRA_EIGRP_SNMP_H
|
||||
#define _ZEBRA_EIGRP_SNMP_H
|
||||
|
||||
extern void eigrp_snmp_init (void);
|
||||
|
||||
|
||||
#endif /* _ZEBRA_EIGRP_SNMP_H */
|
533
eigrpd/eigrp_structs.h
Normal file
533
eigrpd/eigrp_structs.h
Normal file
|
@ -0,0 +1,533 @@
|
|||
/*
|
||||
* EIGRP Definition of Data Structures.
|
||||
* Copyright (C) 2013-2016
|
||||
* Authors:
|
||||
* Donnie Savage
|
||||
* Jan Janovic
|
||||
* Matej Perina
|
||||
* Peter Orsag
|
||||
* Peter Paluch
|
||||
* Frantisek Gazo
|
||||
* Tomas Hvorkovy
|
||||
* Martin Kontsek
|
||||
* Lukas Koribsky
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _ZEBRA_EIGRP_STRUCTS_H_
|
||||
#define _ZEBRA_EIGRP_STRUCTS_H_
|
||||
|
||||
#include "filter.h"
|
||||
|
||||
#include "eigrpd/eigrp_const.h"
|
||||
#include "eigrpd/eigrp_macros.h"
|
||||
|
||||
/* EIGRP master for system wide configuration and variables. */
|
||||
struct eigrp_master
|
||||
{
|
||||
/* EIGRP instance. */
|
||||
struct list *eigrp;
|
||||
|
||||
/* EIGRP thread master. */
|
||||
struct thread_master *master;
|
||||
|
||||
/* Zebra interface list. */
|
||||
struct list *iflist;
|
||||
|
||||
/* EIGRP start time. */
|
||||
time_t start_time;
|
||||
|
||||
/* Various EIGRP global configuration. */
|
||||
u_char options;
|
||||
|
||||
#define EIGRP_MASTER_SHUTDOWN (1 << 0) /* deferred-shutdown */
|
||||
};
|
||||
|
||||
struct eigrp_metrics
|
||||
{
|
||||
u_int32_t delay;
|
||||
u_int32_t bandwith;
|
||||
unsigned char mtu[3];
|
||||
u_char hop_count;
|
||||
u_char reliability;
|
||||
u_char load;
|
||||
u_char tag;
|
||||
u_char flags;
|
||||
};
|
||||
|
||||
struct eigrp
|
||||
{
|
||||
u_int16_t AS; /* Autonomous system number */
|
||||
u_int16_t vrid; /* Virtual Router ID */
|
||||
u_char k_values[6]; /*Array for K values configuration*/
|
||||
u_char variance; /*Metric variance multiplier*/
|
||||
u_char max_paths; /*Maximum allowed paths for 1 prefix*/
|
||||
|
||||
/*Name of this EIGRP instance*/
|
||||
char *name;
|
||||
|
||||
/* EIGRP Router ID. */
|
||||
u_int32_t router_id; /* Configured automatically. */
|
||||
u_int32_t router_id_static; /* Configured manually. */
|
||||
|
||||
struct list *eiflist; /* eigrp interfaces */
|
||||
u_char passive_interface_default; /* passive-interface default */
|
||||
|
||||
unsigned int fd;
|
||||
unsigned int maxsndbuflen;
|
||||
|
||||
u_int32_t sequence_number; /*Global EIGRP sequence number*/
|
||||
|
||||
struct stream *ibuf;
|
||||
struct list *oi_write_q;
|
||||
|
||||
/*Threads*/
|
||||
struct thread *t_write;
|
||||
struct thread *t_read;
|
||||
struct thread *t_distribute; /* timer for distribute list */
|
||||
|
||||
struct route_table *networks; /* EIGRP config networks. */
|
||||
|
||||
struct list *topology_table;
|
||||
|
||||
u_int64_t serno; /* Global serial number counter for topology entry changes*/
|
||||
u_int64_t serno_last_update; /* Highest serial number of information send by last update*/
|
||||
struct list *topology_changes_internalIPV4;
|
||||
struct list *topology_changes_externalIPV4;
|
||||
|
||||
/*Neighbor self*/
|
||||
struct eigrp_neighbor *neighbor_self;
|
||||
|
||||
/*Configured metric for redistributed routes*/
|
||||
struct eigrp_metrics dmetric[ZEBRA_ROUTE_MAX + 1];
|
||||
int redistribute; /* Num of redistributed protocols. */
|
||||
|
||||
/* Access-list. */
|
||||
struct access_list *list[EIGRP_FILTER_MAX];
|
||||
/* Prefix-list. */
|
||||
struct prefix_list *prefix[EIGRP_FILTER_MAX];
|
||||
/* Route-map. */
|
||||
struct route_map *routemap[EIGRP_FILTER_MAX];
|
||||
|
||||
/* For redistribute route map. */
|
||||
struct
|
||||
{
|
||||
char *name;
|
||||
struct route_map *map;
|
||||
int metric_config;
|
||||
u_int32_t metric;
|
||||
} route_map[ZEBRA_ROUTE_MAX];
|
||||
|
||||
QOBJ_FIELDS
|
||||
};
|
||||
DECLARE_QOBJ_TYPE(eigrp)
|
||||
//------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/*EIGRP interface structure*/
|
||||
struct eigrp_interface
|
||||
{
|
||||
/* This interface's parent eigrp instance. */
|
||||
struct eigrp *eigrp;
|
||||
|
||||
/* Interface data from zebra. */
|
||||
struct interface *ifp;
|
||||
|
||||
/* Packet send buffer. */
|
||||
struct eigrp_fifo *obuf; /* Output queue */
|
||||
|
||||
/* To which multicast groups do we currently belong? */
|
||||
|
||||
/* Configured varables. */
|
||||
struct eigrp_if_params *params;
|
||||
|
||||
u_char multicast_memberships;
|
||||
|
||||
/* EIGRP Network Type. */
|
||||
u_char type;
|
||||
|
||||
struct prefix *address; /* Interface prefix */
|
||||
struct connected *connected; /* Pointer to connected */
|
||||
|
||||
/* Neighbor information. */
|
||||
struct list *nbrs; /* EIGRP Neighbor List */
|
||||
|
||||
/* Threads. */
|
||||
struct thread *t_hello; /* timer */
|
||||
struct thread *t_distribute; /* timer for distribute list */
|
||||
|
||||
int on_write_q;
|
||||
|
||||
/* Statistics fields. */
|
||||
u_int32_t hello_in; /* Hello message input count. */
|
||||
u_int32_t update_in; /* Update message input count. */
|
||||
u_int32_t query_in; /* Querry message input count. */
|
||||
u_int32_t reply_in; /* Reply message input count. */
|
||||
u_int32_t hello_out; /* Hello message output count. */
|
||||
u_int32_t update_out; /* Update message output count. */
|
||||
u_int32_t query_out; /* Query message output count. */
|
||||
u_int32_t reply_out; /* Reply message output count. */
|
||||
u_int32_t siaQuery_in;
|
||||
u_int32_t siaQuery_out;
|
||||
u_int32_t siaReply_in;
|
||||
u_int32_t siaReply_out;
|
||||
u_int32_t ack_out;
|
||||
u_int32_t ack_in;
|
||||
|
||||
u_int32_t crypt_seqnum; /* Cryptographic Sequence Number */
|
||||
|
||||
/* Access-list. */
|
||||
struct access_list *list[EIGRP_FILTER_MAX];
|
||||
/* Prefix-list. */
|
||||
struct prefix_list *prefix[EIGRP_FILTER_MAX];
|
||||
/* Route-map. */
|
||||
struct route_map *routemap[EIGRP_FILTER_MAX];
|
||||
};
|
||||
|
||||
struct eigrp_if_params
|
||||
{
|
||||
DECLARE_IF_PARAM (u_char, passive_interface); /* EIGRP Interface is passive: no sending or receiving (no need to join multicast groups) */
|
||||
DECLARE_IF_PARAM (u_int32_t, v_hello); /* Hello Interval */
|
||||
DECLARE_IF_PARAM (u_int16_t, v_wait); /* Router Hold Time Interval */
|
||||
DECLARE_IF_PARAM (u_char, type); /* type of interface */
|
||||
DECLARE_IF_PARAM (u_int32_t, bandwidth);
|
||||
DECLARE_IF_PARAM (u_int32_t, delay);
|
||||
DECLARE_IF_PARAM (u_char, reliability);
|
||||
DECLARE_IF_PARAM (u_char, load);
|
||||
|
||||
DECLARE_IF_PARAM (char *, auth_keychain ); /* Associated keychain with interface*/
|
||||
DECLARE_IF_PARAM (int, auth_type); /* EIGRP authentication type */
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
MEMBER_ALLROUTERS = 0, MEMBER_MAX,
|
||||
};
|
||||
|
||||
struct eigrp_if_info
|
||||
{
|
||||
struct eigrp_if_params *def_params;
|
||||
struct route_table *params;
|
||||
struct route_table *eifs;
|
||||
unsigned int membership_counts[MEMBER_MAX]; /* multicast group refcnts */
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/* Determines if it is first or last packet
|
||||
* when packet consists of multiple packet
|
||||
* chunks because of many route TLV
|
||||
* (all won't fit into one packet) */
|
||||
enum Packet_part_type
|
||||
{
|
||||
EIGRP_PACKET_PART_NA,
|
||||
EIGRP_PACKET_PART_FIRST,
|
||||
EIGRP_PACKET_PART_LAST
|
||||
};
|
||||
|
||||
/* Neighbor Data Structure */
|
||||
struct eigrp_neighbor
|
||||
{
|
||||
/* This neighbor's parent eigrp interface. */
|
||||
struct eigrp_interface *ei;
|
||||
|
||||
/* EIGRP neighbor Information */
|
||||
u_char state; /* neigbor status. */
|
||||
|
||||
u_int32_t recv_sequence_number; /* Last received sequence Number. */
|
||||
u_int32_t init_sequence_number;
|
||||
|
||||
/*If packet is unacknowledged, we try to send it again 16 times*/
|
||||
u_char retrans_counter;
|
||||
|
||||
struct in_addr src; /* Neighbor Src address. */
|
||||
|
||||
u_char os_rel_major; // system version - just for show
|
||||
u_char os_rel_minor; // system version - just for show
|
||||
u_char tlv_rel_major; // eigrp version - tells us what TLV format to use
|
||||
u_char tlv_rel_minor; // eigrp version - tells us what TLV format to use
|
||||
|
||||
u_char K1;
|
||||
u_char K2;
|
||||
u_char K3;
|
||||
u_char K4;
|
||||
u_char K5;
|
||||
u_char K6;
|
||||
|
||||
/* Timer values. */
|
||||
u_int16_t v_holddown;
|
||||
|
||||
/* Threads. */
|
||||
struct thread *t_holddown;
|
||||
struct thread *t_nbr_send_gr; /* thread for sending multiple GR packet chunks */
|
||||
|
||||
struct eigrp_fifo *retrans_queue;
|
||||
struct eigrp_fifo *multicast_queue;
|
||||
|
||||
u_int32_t crypt_seqnum; /* Cryptographic Sequence Number. */
|
||||
|
||||
/* prefixes not received from neighbor during Graceful restart */
|
||||
struct list *nbr_gr_prefixes;
|
||||
/* prefixes not yet send to neighbor during Graceful restart */
|
||||
struct list *nbr_gr_prefixes_send;
|
||||
/* if packet is first or last during Graceful restart */
|
||||
enum Packet_part_type nbr_gr_packet_type;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
struct eigrp_packet
|
||||
{
|
||||
struct eigrp_packet *next;
|
||||
struct eigrp_packet *previous;
|
||||
|
||||
/* Pointer to data stream. */
|
||||
struct stream *s;
|
||||
|
||||
/* IP destination address. */
|
||||
struct in_addr dst;
|
||||
|
||||
/*Packet retransmission thread*/
|
||||
struct thread *t_retrans_timer;
|
||||
|
||||
/*Packet retransmission counter*/
|
||||
u_char retrans_counter;
|
||||
|
||||
u_int32_t sequence_number;
|
||||
|
||||
/* EIGRP packet length. */
|
||||
u_int16_t length;
|
||||
};
|
||||
|
||||
struct eigrp_fifo
|
||||
{
|
||||
struct eigrp_packet *head;
|
||||
struct eigrp_packet *tail;
|
||||
|
||||
unsigned long count;
|
||||
};
|
||||
|
||||
struct eigrp_header
|
||||
{
|
||||
u_char version;
|
||||
u_char opcode;
|
||||
u_int16_t checksum;
|
||||
u_int32_t flags;
|
||||
u_int32_t sequence;
|
||||
u_int32_t ack;
|
||||
u_int16_t vrid;
|
||||
u_int16_t ASNumber;
|
||||
char *tlv[0];
|
||||
|
||||
}__attribute__((packed));
|
||||
|
||||
|
||||
/**
|
||||
* Generic TLV type used for packet decoding.
|
||||
*
|
||||
* +-----+------------------+
|
||||
* | | | |
|
||||
* | Type| Len | Vector |
|
||||
* | | | |
|
||||
* +-----+------------------+
|
||||
*/
|
||||
struct eigrp_tlv_hdr_type
|
||||
{
|
||||
u_int16_t type;
|
||||
u_int16_t length;
|
||||
uint8_t value[0];
|
||||
}__attribute__((packed));
|
||||
|
||||
struct TLV_Parameter_Type
|
||||
{
|
||||
u_int16_t type;
|
||||
u_int16_t length;
|
||||
u_char K1;
|
||||
u_char K2;
|
||||
u_char K3;
|
||||
u_char K4;
|
||||
u_char K5;
|
||||
u_char K6;
|
||||
u_int16_t hold_time;
|
||||
}__attribute__((packed));
|
||||
|
||||
struct TLV_MD5_Authentication_Type
|
||||
{
|
||||
u_int16_t type;
|
||||
u_int16_t length;
|
||||
u_int16_t auth_type;
|
||||
u_int16_t auth_length;
|
||||
u_int32_t key_id;
|
||||
u_int32_t key_sequence;
|
||||
u_char Nullpad[8];
|
||||
u_char digest[EIGRP_AUTH_TYPE_MD5_LEN];
|
||||
|
||||
}__attribute__((packed));
|
||||
|
||||
struct TLV_SHA256_Authentication_Type
|
||||
{
|
||||
u_int16_t type;
|
||||
u_int16_t length;
|
||||
u_int16_t auth_type;
|
||||
u_int16_t auth_length;
|
||||
u_int32_t key_id;
|
||||
u_int32_t key_sequence;
|
||||
u_char Nullpad[8];
|
||||
u_char digest[EIGRP_AUTH_TYPE_SHA256_LEN];
|
||||
|
||||
}__attribute__((packed));
|
||||
|
||||
struct TLV_Sequence_Type
|
||||
{
|
||||
u_int16_t type;
|
||||
u_int16_t length;
|
||||
u_char addr_length;
|
||||
struct in_addr *addresses;
|
||||
}__attribute__((packed));
|
||||
|
||||
struct TLV_Next_Multicast_Sequence
|
||||
{
|
||||
u_int16_t type;
|
||||
u_int16_t length;
|
||||
u_int32_t multicast_sequence;
|
||||
}__attribute__((packed));
|
||||
|
||||
struct TLV_Software_Type
|
||||
{
|
||||
u_int16_t type;
|
||||
u_int16_t length;
|
||||
u_char vender_major;
|
||||
u_char vender_minor;
|
||||
u_char eigrp_major;
|
||||
u_char eigrp_minor;
|
||||
}__attribute__((packed));
|
||||
|
||||
struct TLV_IPv4_Internal_type
|
||||
{
|
||||
u_int16_t type;
|
||||
u_int16_t length;
|
||||
struct in_addr forward;
|
||||
|
||||
/*Metrics*/
|
||||
struct eigrp_metrics metric;
|
||||
|
||||
u_char prefix_length;
|
||||
|
||||
unsigned char destination_part[4];
|
||||
struct in_addr destination;
|
||||
}__attribute__((packed));
|
||||
|
||||
struct TLV_IPv4_External_type
|
||||
{
|
||||
u_int16_t type;
|
||||
u_int16_t length;
|
||||
struct in_addr next_hop;
|
||||
struct in_addr originating_router;
|
||||
u_int32_t originating_as;
|
||||
u_int32_t administrative_tag;
|
||||
u_int32_t external_metric;
|
||||
u_int16_t reserved;
|
||||
u_char external_protocol;
|
||||
u_char external_flags;
|
||||
|
||||
/*Metrics*/
|
||||
struct eigrp_metrics metric;
|
||||
|
||||
u_char prefix_length;
|
||||
unsigned char destination_part[4];
|
||||
struct in_addr destination;
|
||||
}__attribute__((packed));
|
||||
|
||||
/* EIGRP Peer Termination TLV - used for hard restart */
|
||||
struct TLV_Peer_Termination_type
|
||||
{
|
||||
u_int16_t type;
|
||||
u_int16_t length;
|
||||
u_char unknown;
|
||||
u_int32_t neighbor_ip;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* Who executed Graceful restart */
|
||||
enum GR_type
|
||||
{
|
||||
EIGRP_GR_MANUAL,
|
||||
EIGRP_GR_FILTER
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/* EIGRP Topology table node structure */
|
||||
struct eigrp_prefix_entry
|
||||
{
|
||||
struct list *entries, *rij;
|
||||
u_int32_t fdistance; // FD
|
||||
u_int32_t rdistance; // RD
|
||||
u_int32_t distance; // D
|
||||
struct eigrp_metrics reported_metric; // RD for sending
|
||||
|
||||
u_char nt; //network type
|
||||
u_char state; //route fsm state
|
||||
u_char af; // address family
|
||||
u_char req_action; // required action
|
||||
|
||||
struct prefix_ipv4 *destination_ipv4; // pointer to struct with ipv4 address
|
||||
struct prefix_ipv6 *destination_ipv6; // pointer to struct with ipv6 address
|
||||
|
||||
//If network type is REMOTE_EXTERNAL, pointer will have reference to its external TLV
|
||||
struct TLV_IPv4_External_type *extTLV;
|
||||
|
||||
u_int64_t serno; /*Serial number for this entry. Increased with each change of entry*/
|
||||
};
|
||||
|
||||
/* EIGRP Topology table record structure */
|
||||
struct eigrp_neighbor_entry
|
||||
{
|
||||
struct eigrp_prefix_entry *prefix;
|
||||
u_int32_t reported_distance; //distance reported by neighbor
|
||||
u_int32_t distance; //sum of reported distance and link cost to advertised neighbor
|
||||
|
||||
struct eigrp_metrics reported_metric;
|
||||
struct eigrp_metrics total_metric;
|
||||
|
||||
struct eigrp_neighbor *adv_router; //ip address of advertising neighbor
|
||||
u_char flags; //used for marking successor and FS
|
||||
|
||||
struct eigrp_interface *ei; //pointer for case of connected entry
|
||||
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/* EIGRP Finite State Machine */
|
||||
|
||||
struct eigrp_fsm_action_message
|
||||
{
|
||||
u_char packet_type; //UPDATE, QUERY, SIAQUERY, SIAREPLY
|
||||
struct eigrp *eigrp; // which thread sent mesg
|
||||
struct eigrp_neighbor *adv_router; //advertising neighbor
|
||||
struct eigrp_neighbor_entry *entry;
|
||||
struct eigrp_prefix_entry *prefix;
|
||||
int data_type; // internal or external tlv type
|
||||
union{
|
||||
struct TLV_IPv4_External_type *ipv4_ext_data;
|
||||
struct TLV_IPv4_Internal_type *ipv4_int_type;
|
||||
}data;
|
||||
};
|
||||
|
||||
#endif /* _ZEBRA_EIGRP_STRUCTURES_H_ */
|
586
eigrpd/eigrp_topology.c
Normal file
586
eigrpd/eigrp_topology.c
Normal file
|
@ -0,0 +1,586 @@
|
|||
/*
|
||||
* EIGRP Topology Table.
|
||||
* Copyright (C) 2013-2016
|
||||
* Authors:
|
||||
* Donnie Savage
|
||||
* Jan Janovic
|
||||
* Matej Perina
|
||||
* Peter Orsag
|
||||
* Peter Paluch
|
||||
* Frantisek Gazo
|
||||
* Tomas Hvorkovy
|
||||
* Martin Kontsek
|
||||
* Lukas Koribsky
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#include "prefix.h"
|
||||
#include "table.h"
|
||||
#include "memory.h"
|
||||
#include "log.h"
|
||||
#include "linklist.h"
|
||||
#include "vty.h"
|
||||
|
||||
#include "eigrpd/eigrp_structs.h"
|
||||
#include "eigrpd/eigrpd.h"
|
||||
#include "eigrpd/eigrp_interface.h"
|
||||
#include "eigrpd/eigrp_neighbor.h"
|
||||
#include "eigrpd/eigrp_packet.h"
|
||||
#include "eigrpd/eigrp_zebra.h"
|
||||
#include "eigrpd/eigrp_vty.h"
|
||||
#include "eigrpd/eigrp_network.h"
|
||||
#include "eigrpd/eigrp_dump.h"
|
||||
#include "eigrpd/eigrp_topology.h"
|
||||
#include "eigrpd/eigrp_fsm.h"
|
||||
#include "eigrpd/eigrp_memory.h"
|
||||
|
||||
static int
|
||||
eigrp_prefix_entry_cmp(struct eigrp_prefix_entry *, struct eigrp_prefix_entry *);
|
||||
static void
|
||||
eigrp_prefix_entry_del(struct eigrp_prefix_entry *);
|
||||
static int
|
||||
eigrp_neighbor_entry_cmp(struct eigrp_neighbor_entry *,
|
||||
struct eigrp_neighbor_entry *);
|
||||
|
||||
/*
|
||||
* asdf;laksdjf;lajsdf;kasdjf;asdjf;
|
||||
* asdfaskdjfa;sdkjf;adlskj
|
||||
* Returns linkedlist used as topology table
|
||||
* cmp - assigned function for comparing topology nodes
|
||||
* del - assigned function executed before deleting topology node by list function
|
||||
*/
|
||||
struct list *
|
||||
eigrp_topology_new()
|
||||
{
|
||||
struct list* new = list_new();
|
||||
new->cmp = (int
|
||||
(*)(void *, void *)) eigrp_prefix_entry_cmp;
|
||||
new->del = (void
|
||||
(*)(void *)) eigrp_prefix_entry_del;
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
/*
|
||||
* Topology node comparison
|
||||
*/
|
||||
|
||||
static int
|
||||
eigrp_prefix_entry_cmp(struct eigrp_prefix_entry *node1,
|
||||
struct eigrp_prefix_entry *node2)
|
||||
{
|
||||
if (node1->af == AF_INET)
|
||||
{
|
||||
if (node2->af == AF_INET)
|
||||
{
|
||||
if (node1->destination_ipv4->prefix.s_addr
|
||||
< node2->destination_ipv4->prefix.s_addr)
|
||||
{
|
||||
return -1; // if it belong above node2
|
||||
}
|
||||
else
|
||||
{
|
||||
if (node1->destination_ipv4->prefix.s_addr
|
||||
> node2->destination_ipv4->prefix.s_addr)
|
||||
{
|
||||
return 1; //if it belongs under node2
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0; // same value... ERROR...in case of adding same prefix again
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // TODO check if the prefix dont exists
|
||||
return 1; // add to end
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Topology node delete
|
||||
*/
|
||||
|
||||
static void
|
||||
eigrp_prefix_entry_del(struct eigrp_prefix_entry *node)
|
||||
{
|
||||
list_delete_all_node(node->entries);
|
||||
list_free(node->entries);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns new created toplogy node
|
||||
* cmp - assigned function for comparing topology entry
|
||||
*/
|
||||
|
||||
struct eigrp_prefix_entry *
|
||||
eigrp_prefix_entry_new()
|
||||
{
|
||||
struct eigrp_prefix_entry *new;
|
||||
new = XCALLOC(MTYPE_EIGRP_PREFIX_ENTRY, sizeof(struct eigrp_prefix_entry));
|
||||
new->entries = list_new();
|
||||
new->rij = list_new();
|
||||
new->entries->cmp = (int
|
||||
(*)(void *, void *)) eigrp_neighbor_entry_cmp;
|
||||
new->distance = new->fdistance = new->rdistance = EIGRP_MAX_METRIC;
|
||||
new->destination_ipv4 = NULL;
|
||||
new->destination_ipv6 = NULL;
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
/*
|
||||
* Topology entry comparison
|
||||
*/
|
||||
|
||||
static int
|
||||
eigrp_neighbor_entry_cmp(struct eigrp_neighbor_entry *entry1,
|
||||
struct eigrp_neighbor_entry *entry2)
|
||||
{
|
||||
if (entry1->distance < entry2->distance) // parameter used in list_add_sort ()
|
||||
return -1; // actually set to sort by distance
|
||||
if (entry1->distance > entry2->distance)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns new topology entry
|
||||
*/
|
||||
|
||||
struct eigrp_neighbor_entry *
|
||||
eigrp_neighbor_entry_new()
|
||||
{
|
||||
struct eigrp_neighbor_entry *new;
|
||||
|
||||
new = XCALLOC(MTYPE_EIGRP_NEIGHBOR_ENTRY,
|
||||
sizeof(struct eigrp_neighbor_entry));
|
||||
new->reported_distance = EIGRP_MAX_METRIC;
|
||||
new->distance = EIGRP_MAX_METRIC;
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
/*
|
||||
* Freeing topology table list
|
||||
*/
|
||||
|
||||
void
|
||||
eigrp_topology_free(struct list *list)
|
||||
{
|
||||
list_free(list);
|
||||
}
|
||||
|
||||
/*
|
||||
* Deleting all topology nodes in table
|
||||
*/
|
||||
|
||||
void
|
||||
eigrp_topology_cleanup(struct list *topology)
|
||||
{
|
||||
assert(topology);
|
||||
|
||||
eigrp_topology_delete_all(topology);
|
||||
}
|
||||
|
||||
/*
|
||||
* Adding topology node to topology table
|
||||
*/
|
||||
|
||||
void
|
||||
eigrp_prefix_entry_add(struct list *topology, struct eigrp_prefix_entry *node)
|
||||
{
|
||||
if (listnode_lookup(topology, node) == NULL)
|
||||
{
|
||||
listnode_add_sort(topology, node);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Adding topology entry to topology node
|
||||
*/
|
||||
|
||||
void
|
||||
eigrp_neighbor_entry_add(struct eigrp_prefix_entry *node,
|
||||
struct eigrp_neighbor_entry *entry)
|
||||
{
|
||||
if (listnode_lookup(node->entries, entry) == NULL)
|
||||
{
|
||||
listnode_add_sort(node->entries, entry);
|
||||
entry->prefix = node;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Deleting topology node from topology table
|
||||
*/
|
||||
|
||||
void
|
||||
eigrp_prefix_entry_delete(struct list *topology,
|
||||
struct eigrp_prefix_entry *node)
|
||||
{
|
||||
if (listnode_lookup(topology, node) != NULL)
|
||||
{
|
||||
list_delete_all_node(node->entries);
|
||||
list_free(node->entries);
|
||||
list_free(node->rij);
|
||||
listnode_delete(topology, node);
|
||||
XFREE(MTYPE_EIGRP_PREFIX_ENTRY,node);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Deleting topology entry from topology node
|
||||
*/
|
||||
|
||||
void
|
||||
eigrp_neighbor_entry_delete(struct eigrp_prefix_entry *node,
|
||||
struct eigrp_neighbor_entry *entry)
|
||||
{
|
||||
if (listnode_lookup(node->entries, entry) != NULL)
|
||||
{
|
||||
listnode_delete(node->entries, entry);
|
||||
XFREE(MTYPE_EIGRP_NEIGHBOR_ENTRY,entry);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Deleting all nodes from topology table
|
||||
*/
|
||||
|
||||
void
|
||||
eigrp_topology_delete_all(struct list *topology)
|
||||
{
|
||||
list_delete_all_node(topology);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return 0 if topology is not empty
|
||||
* otherwise return 1
|
||||
*/
|
||||
|
||||
unsigned int
|
||||
eigrp_topology_table_isempty(struct list *topology)
|
||||
{
|
||||
if (topology->count)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct eigrp_prefix_entry *
|
||||
eigrp_topology_table_lookup_ipv4(struct list *topology_table,
|
||||
struct prefix_ipv4 * address)
|
||||
{
|
||||
struct eigrp_prefix_entry *data;
|
||||
struct listnode *node;
|
||||
for (ALL_LIST_ELEMENTS_RO(topology_table, node, data))
|
||||
{
|
||||
|
||||
if ((data->af == AF_INET)
|
||||
&& (data->destination_ipv4->prefix.s_addr == address->prefix.s_addr)
|
||||
&& (data->destination_ipv4->prefixlen == address->prefixlen))
|
||||
return data;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
/* TODO
|
||||
struct eigrp_prefix_entry *
|
||||
eigrp_topology_table_lookup_ipv6 (struct list *topology_table,
|
||||
struct prefix_ipv6 * address)
|
||||
{
|
||||
struct eigrp_prefix_entry *data;
|
||||
struct listnode *node, *nnode;
|
||||
for (ALL_LIST_ELEMENTS (topology_table, node, nnode, data))
|
||||
{
|
||||
|
||||
if (comparison)
|
||||
return data;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
*/
|
||||
struct list *
|
||||
eigrp_topology_get_successor(struct eigrp_prefix_entry *table_node)
|
||||
{
|
||||
struct list *successors = list_new();
|
||||
;
|
||||
struct eigrp_neighbor_entry *data;
|
||||
struct listnode *node1, *node2;
|
||||
for (ALL_LIST_ELEMENTS(table_node->entries, node1, node2, data))
|
||||
{
|
||||
if (data->flags & EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG)
|
||||
{
|
||||
listnode_add(successors, data);
|
||||
}
|
||||
}
|
||||
|
||||
return successors;
|
||||
}
|
||||
|
||||
/*extern struct eigrp_neighbor_entry *
|
||||
eigrp_topology_get_fsuccessor (struct eigrp_prefix_entry *table_node)
|
||||
{
|
||||
struct eigrp_neighbor_entry *data;
|
||||
struct listnode *node, *nnode;
|
||||
for (ALL_LIST_ELEMENTS (table_node->entries, node, nnode, data))
|
||||
{
|
||||
if ((data->flags & EIGRP_NEIGHBOR_ENTRY_FSUCCESSOR_FLAG) == 1)
|
||||
{
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}*/
|
||||
|
||||
struct eigrp_neighbor_entry *
|
||||
eigrp_prefix_entry_lookup(struct list *entries, struct eigrp_neighbor *nbr)
|
||||
{
|
||||
struct eigrp_neighbor_entry *data;
|
||||
struct listnode *node, *nnode;
|
||||
for (ALL_LIST_ELEMENTS(entries, node, nnode, data))
|
||||
{
|
||||
if (data->adv_router == nbr)
|
||||
{
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Lookup all prefixes from specified neighbor */
|
||||
struct list *
|
||||
eigrp_neighbor_prefixes_lookup(struct eigrp *eigrp, struct eigrp_neighbor *nbr)
|
||||
{
|
||||
struct listnode *node1, *node11, *node2, *node22;
|
||||
struct eigrp_prefix_entry *prefix;
|
||||
struct eigrp_neighbor_entry *entry;
|
||||
|
||||
/* create new empty list for prefixes storage */
|
||||
struct list *prefixes = list_new();
|
||||
|
||||
/* iterate over all prefixes in topology table */
|
||||
for (ALL_LIST_ELEMENTS(eigrp->topology_table, node1, node11, prefix))
|
||||
{
|
||||
/* iterate over all neighbor entry in prefix */
|
||||
for (ALL_LIST_ELEMENTS(prefix->entries, node2, node22, entry))
|
||||
{
|
||||
/* if entry is from specified neighbor, add to list */
|
||||
if (entry->adv_router == nbr)
|
||||
{
|
||||
listnode_add(prefixes, prefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* return list of prefixes from specified neighbor */
|
||||
return prefixes;
|
||||
}
|
||||
|
||||
int
|
||||
eigrp_topology_update_distance(struct eigrp_fsm_action_message *msg)
|
||||
{
|
||||
struct eigrp *eigrp = msg->eigrp;
|
||||
struct eigrp_prefix_entry *prefix = msg->prefix;
|
||||
struct eigrp_neighbor_entry *entry = msg->entry;
|
||||
int change = 0;
|
||||
assert(entry);
|
||||
|
||||
struct TLV_IPv4_External_type *ext_data = NULL;
|
||||
struct TLV_IPv4_Internal_type *int_data = NULL;
|
||||
if (msg->data_type == EIGRP_TLV_IPv4_INT)
|
||||
{
|
||||
int_data = msg->data.ipv4_int_type;
|
||||
if (eigrp_metrics_is_same(&int_data->metric,&entry->reported_metric))
|
||||
{
|
||||
return 0; // No change
|
||||
}
|
||||
change =
|
||||
entry->reported_distance
|
||||
< eigrp_calculate_metrics(eigrp, &int_data->metric) ? 1 :
|
||||
entry->reported_distance
|
||||
> eigrp_calculate_metrics(eigrp, &int_data->metric) ? 2 : 3; // Increase : Decrease : No change
|
||||
entry->reported_metric = int_data->metric;
|
||||
entry->reported_distance = eigrp_calculate_metrics(eigrp,
|
||||
&int_data->metric);
|
||||
entry->distance = eigrp_calculate_total_metrics(eigrp, entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
ext_data = msg->data.ipv4_ext_data;
|
||||
if (eigrp_metrics_is_same (&ext_data->metric, &entry->reported_metric))
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Move to correct position in list according to new distance
|
||||
*/
|
||||
listnode_delete(prefix->entries, entry);
|
||||
listnode_add_sort(prefix->entries, entry);
|
||||
|
||||
return change;
|
||||
}
|
||||
|
||||
void
|
||||
eigrp_topology_update_all_node_flags(struct eigrp *eigrp)
|
||||
{
|
||||
struct list *table = eigrp->topology_table;
|
||||
struct eigrp_prefix_entry *data;
|
||||
struct listnode *node, *nnode;
|
||||
for (ALL_LIST_ELEMENTS(table, node, nnode, data))
|
||||
{
|
||||
eigrp_topology_update_node_flags(data);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
eigrp_topology_update_node_flags(struct eigrp_prefix_entry *dest)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct eigrp_neighbor_entry *entry;
|
||||
struct eigrp * eigrp = eigrp_lookup();
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(dest->entries, node, entry))
|
||||
{
|
||||
if ((entry->distance <= (u_int64_t)(dest->distance*eigrp->variance)) && entry->distance != EIGRP_MAX_METRIC) // is successor
|
||||
{
|
||||
entry->flags |= EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG;
|
||||
entry->flags &= 0xfd; // 1111 1101 set fs flag to zero
|
||||
}
|
||||
else if (entry->reported_distance < dest->fdistance) // is feasible successor
|
||||
{
|
||||
entry->flags |= EIGRP_NEIGHBOR_ENTRY_FSUCCESSOR_FLAG;
|
||||
entry->flags &= 0xfe; // 1111 1110 set successor flag to zero
|
||||
}
|
||||
else
|
||||
{
|
||||
entry->flags &= 0xfc; // 1111 1100 set successor and fs flag to zero
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
eigrp_update_routing_table(struct eigrp_prefix_entry * prefix)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct eigrp_neighbor_entry *entry;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(prefix->entries, node, entry))
|
||||
{
|
||||
if (entry->flags & EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG)
|
||||
{
|
||||
if (!(entry->flags & EIGRP_NEIGHBOR_ENTRY_INTABLE_FLAG))
|
||||
{
|
||||
eigrp_zebra_route_add(prefix->destination_ipv4, entry);
|
||||
entry->flags += EIGRP_NEIGHBOR_ENTRY_INTABLE_FLAG;
|
||||
}
|
||||
}
|
||||
else if (entry->flags & EIGRP_NEIGHBOR_ENTRY_INTABLE_FLAG)
|
||||
{
|
||||
eigrp_zebra_route_delete(prefix->destination_ipv4, entry);
|
||||
entry->flags -= EIGRP_NEIGHBOR_ENTRY_INTABLE_FLAG;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
eigrp_topology_neighbor_down(struct eigrp *eigrp, struct eigrp_neighbor * nbr)
|
||||
{
|
||||
struct listnode *node1, *node11, *node2, *node22;
|
||||
struct eigrp_prefix_entry *prefix;
|
||||
struct eigrp_neighbor_entry *entry;
|
||||
|
||||
for (ALL_LIST_ELEMENTS(eigrp->topology_table, node1, node11, prefix))
|
||||
{
|
||||
for (ALL_LIST_ELEMENTS(prefix->entries, node2, node22, entry))
|
||||
{
|
||||
if (entry->adv_router == nbr)
|
||||
{
|
||||
struct eigrp_fsm_action_message *msg;
|
||||
msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
|
||||
sizeof(struct eigrp_fsm_action_message));
|
||||
struct TLV_IPv4_Internal_type * tlv = eigrp_IPv4_InternalTLV_new();
|
||||
tlv->metric.delay = EIGRP_MAX_METRIC;
|
||||
msg->packet_type = EIGRP_OPC_UPDATE;
|
||||
msg->eigrp = eigrp;
|
||||
msg->data_type = EIGRP_TLV_IPv4_INT;
|
||||
msg->adv_router = nbr;
|
||||
msg->data.ipv4_int_type = tlv;
|
||||
msg->entry = entry;
|
||||
msg->prefix = prefix;
|
||||
int event = eigrp_get_fsm_event(msg);
|
||||
eigrp_fsm_event(msg, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eigrp_query_send_all(eigrp);
|
||||
eigrp_update_send_all(eigrp,nbr->ei);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
eigrp_update_topology_table_prefix(struct list * table, struct eigrp_prefix_entry * prefix)
|
||||
{
|
||||
struct listnode *node1, *node2;
|
||||
|
||||
struct eigrp_neighbor_entry *entry;
|
||||
for (ALL_LIST_ELEMENTS(prefix->entries, node1, node2, entry))
|
||||
{
|
||||
if(entry->distance == EIGRP_MAX_METRIC)
|
||||
{
|
||||
eigrp_neighbor_entry_delete(prefix,entry);
|
||||
}
|
||||
}
|
||||
if(prefix->distance == EIGRP_MAX_METRIC && prefix->nt != EIGRP_TOPOLOGY_TYPE_CONNECTED)
|
||||
{
|
||||
eigrp_prefix_entry_delete(table,prefix);
|
||||
}
|
||||
}
|
||||
/*int
|
||||
eigrp_topology_get_successor_count (struct eigrp_prefix_entry *prefix)
|
||||
{
|
||||
|
||||
struct listnode *node;
|
||||
struct eigrp_neighbor_entry *entry;
|
||||
|
||||
int count = 0;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO (prefix->entries,node,entry))
|
||||
{
|
||||
if ((entry->flags & EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG) == EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG)
|
||||
{
|
||||
count ++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
*/
|
75
eigrpd/eigrp_topology.h
Normal file
75
eigrpd/eigrp_topology.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* EIGRP Topology Table.
|
||||
* Copyright (C) 2013-2016
|
||||
* Authors:
|
||||
* Donnie Savage
|
||||
* Jan Janovic
|
||||
* Matej Perina
|
||||
* Peter Orsag
|
||||
* Peter Paluch
|
||||
* Frantisek Gazo
|
||||
* Tomas Hvorkovy
|
||||
* Martin Kontsek
|
||||
* Lukas Koribsky
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _ZEBRA_EIGRP_TOPOLOGY_H
|
||||
#define _ZEBRA_EIGRP_TOPOLOGY_H
|
||||
|
||||
|
||||
/* EIGRP Topology table related functions. */
|
||||
extern struct list *eigrp_topology_new (void);
|
||||
extern void eigrp_topology_init (struct list*);
|
||||
extern struct eigrp_prefix_entry *eigrp_prefix_entry_new (void);
|
||||
extern struct eigrp_neighbor_entry *eigrp_neighbor_entry_new (void);
|
||||
extern void eigrp_topology_free (struct list *);
|
||||
extern void eigrp_topology_cleanup (struct list *);
|
||||
extern void eigrp_prefix_entry_add (struct list *, struct eigrp_prefix_entry *);
|
||||
extern void eigrp_neighbor_entry_add (struct eigrp_prefix_entry *, struct eigrp_neighbor_entry *);
|
||||
extern void eigrp_prefix_entry_delete (struct list *, struct eigrp_prefix_entry *);
|
||||
extern void eigrp_neighbor_entry_delete (struct eigrp_prefix_entry *, struct eigrp_neighbor_entry *);
|
||||
extern void eigrp_topology_delete_all (struct list *);
|
||||
extern unsigned int eigrp_topology_table_isempty (struct list *);
|
||||
extern struct eigrp_prefix_entry *eigrp_topology_table_lookup_ipv4 (struct list *, struct prefix_ipv4 *);
|
||||
extern struct list *eigrp_topology_get_successor (struct eigrp_prefix_entry *);
|
||||
//extern struct eigrp_neighbor_entry *eigrp_topology_get_fsuccessor (struct eigrp_prefix_entry *);
|
||||
extern struct eigrp_neighbor_entry *eigrp_prefix_entry_lookup (struct list *, struct eigrp_neighbor *);
|
||||
extern struct list *eigrp_neighbor_prefixes_lookup(struct eigrp *, struct eigrp_neighbor *);
|
||||
extern void eigrp_topology_update_all_node_flags (struct eigrp *);
|
||||
extern void eigrp_topology_update_node_flags (struct eigrp_prefix_entry *);
|
||||
extern int eigrp_topology_update_distance ( struct eigrp_fsm_action_message *);
|
||||
extern void eigrp_update_routing_table(struct eigrp_prefix_entry *);
|
||||
extern void eigrp_topology_neighbor_down(struct eigrp *, struct eigrp_neighbor *);
|
||||
extern void eigrp_update_topology_table_prefix(struct list *, struct eigrp_prefix_entry * );
|
||||
//extern int eigrp_topology_get_successor_count (struct eigrp_prefix_entry *);
|
||||
/* Set all stats to -1 (LSA_SPF_NOT_EXPLORED). */
|
||||
/*extern void eigrp_lsdb_clean_stat (struct eigrp_lsdb *lsdb);
|
||||
extern struct eigrp_lsa *eigrp_lsdb_lookup_by_id (struct eigrp_lsdb *, u_char,
|
||||
struct in_addr, struct in_addr);
|
||||
extern struct eigrp_lsa *eigrp_lsdb_lookup_by_id_next (struct eigrp_lsdb *, u_char,
|
||||
struct in_addr, struct in_addr,
|
||||
int);
|
||||
extern unsigned long eigrp_lsdb_count_all (struct eigrp_lsdb *);
|
||||
extern unsigned long eigrp_lsdb_count (struct eigrp_lsdb *, int);
|
||||
extern unsigned long eigrp_lsdb_count_self (struct eigrp_lsdb *, int);
|
||||
extern unsigned int eigrp_lsdb_checksum (struct eigrp_lsdb *, int);
|
||||
extern unsigned long eigrp_lsdb_isempty (struct eigrp_lsdb *);
|
||||
*/
|
||||
#endif
|
1159
eigrpd/eigrp_update.c
Normal file
1159
eigrpd/eigrp_update.c
Normal file
File diff suppressed because it is too large
Load diff
1584
eigrpd/eigrp_vty.c
Normal file
1584
eigrpd/eigrp_vty.c
Normal file
File diff suppressed because it is too large
Load diff
42
eigrpd/eigrp_vty.h
Normal file
42
eigrpd/eigrp_vty.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* EIGRP VTY Interface.
|
||||
* Copyright (C) 2013-2016
|
||||
* Authors:
|
||||
* Donnie Savage
|
||||
* Jan Janovic
|
||||
* Matej Perina
|
||||
* Peter Orsag
|
||||
* Peter Paluch
|
||||
* Frantisek Gazo
|
||||
* Tomas Hvorkovy
|
||||
* Martin Kontsek
|
||||
* Lukas Koribsky
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _QUAGGA_EIGRP_VTY_H
|
||||
#define _QUAGGA_EIGRP_VTY_H
|
||||
|
||||
|
||||
/* Prototypes. */
|
||||
extern void eigrp_vty_init (void);
|
||||
extern void eigrp_vty_show_init (void);
|
||||
extern void eigrp_vty_if_init (void);
|
||||
|
||||
#endif /* _Quagga_EIGRP_VTY_H_ */
|
579
eigrpd/eigrp_zebra.c
Normal file
579
eigrpd/eigrp_zebra.c
Normal file
|
@ -0,0 +1,579 @@
|
|||
/*
|
||||
* Zebra connect library for EIGRP.
|
||||
* Copyright (C) 2013-2014
|
||||
* Authors:
|
||||
* Donnie Savage
|
||||
* Jan Janovic
|
||||
* Matej Perina
|
||||
* Peter Orsag
|
||||
* Peter Paluch
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#include "thread.h"
|
||||
#include "command.h"
|
||||
#include "network.h"
|
||||
#include "prefix.h"
|
||||
#include "routemap.h"
|
||||
#include "table.h"
|
||||
#include "stream.h"
|
||||
#include "memory.h"
|
||||
#include "zclient.h"
|
||||
#include "filter.h"
|
||||
#include "plist.h"
|
||||
#include "log.h"
|
||||
#include "nexthop.h"
|
||||
|
||||
#include "eigrpd/eigrp_structs.h"
|
||||
#include "eigrpd/eigrpd.h"
|
||||
#include "eigrpd/eigrp_interface.h"
|
||||
#include "eigrpd/eigrp_neighbor.h"
|
||||
#include "eigrpd/eigrp_packet.h"
|
||||
#include "eigrpd/eigrp_zebra.h"
|
||||
#include "eigrpd/eigrp_vty.h"
|
||||
#include "eigrpd/eigrp_dump.h"
|
||||
#include "eigrpd/eigrp_network.h"
|
||||
#include "eigrpd/eigrp_topology.h"
|
||||
#include "eigrpd/eigrp_fsm.h"
|
||||
|
||||
static int eigrp_interface_add (int , struct zclient *, zebra_size_t, vrf_id_t);
|
||||
static int eigrp_interface_delete (int , struct zclient *,
|
||||
zebra_size_t, vrf_id_t);
|
||||
static int eigrp_interface_address_add (int, struct zclient *,
|
||||
zebra_size_t, vrf_id_t vrf_id);
|
||||
static int eigrp_interface_address_delete (int, struct zclient *,
|
||||
zebra_size_t, vrf_id_t vrf_id);
|
||||
static int eigrp_interface_state_up (int, struct zclient *,
|
||||
zebra_size_t, vrf_id_t vrf_id);
|
||||
static int eigrp_interface_state_down (int, struct zclient *,
|
||||
zebra_size_t, vrf_id_t vrf_id);
|
||||
static struct interface * zebra_interface_if_lookup (struct stream *);
|
||||
|
||||
static int eigrp_zebra_read_ipv4 (int , struct zclient *,
|
||||
zebra_size_t, vrf_id_t vrf_id);
|
||||
|
||||
/* Zebra structure to hold current status. */
|
||||
struct zclient *zclient = NULL;
|
||||
|
||||
/* For registering threads. */
|
||||
extern struct thread_master *master;
|
||||
struct in_addr router_id_zebra;
|
||||
|
||||
/* Router-id update message from zebra. */
|
||||
static int
|
||||
eigrp_router_id_update_zebra (int command, struct zclient *zclient,
|
||||
zebra_size_t length, vrf_id_t vrf_id)
|
||||
{
|
||||
struct eigrp *eigrp;
|
||||
struct prefix router_id;
|
||||
zebra_router_id_update_read (zclient->ibuf,&router_id);
|
||||
|
||||
router_id_zebra = router_id.u.prefix4;
|
||||
|
||||
eigrp = eigrp_lookup ();
|
||||
|
||||
if (eigrp != NULL)
|
||||
eigrp_router_id_update (eigrp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
eigrp_zebra_init (void)
|
||||
{
|
||||
zclient = zclient_new (master);
|
||||
|
||||
zclient_init (zclient, ZEBRA_ROUTE_EIGRP, 0);
|
||||
zclient->router_id_update = eigrp_router_id_update_zebra;
|
||||
zclient->interface_add = eigrp_interface_add;
|
||||
zclient->interface_delete = eigrp_interface_delete;
|
||||
zclient->interface_up = eigrp_interface_state_up;
|
||||
zclient->interface_down = eigrp_interface_state_down;
|
||||
zclient->interface_address_add = eigrp_interface_address_add;
|
||||
zclient->interface_address_delete = eigrp_interface_address_delete;
|
||||
zclient->redistribute_route_ipv4_add = eigrp_zebra_read_ipv4;
|
||||
zclient->redistribute_route_ipv4_del = eigrp_zebra_read_ipv4;
|
||||
}
|
||||
|
||||
|
||||
/* Zebra route add and delete treatment. */
|
||||
static int
|
||||
eigrp_zebra_read_ipv4 (int command, struct zclient *zclient,
|
||||
zebra_size_t length, vrf_id_t vrf_id)
|
||||
{
|
||||
struct stream *s;
|
||||
struct zapi_ipv4 api;
|
||||
struct prefix_ipv4 p;
|
||||
struct eigrp *eigrp;
|
||||
|
||||
s = zclient->ibuf;
|
||||
|
||||
/* Type, flags, message. */
|
||||
api.type = stream_getc (s);
|
||||
api.instance = stream_getw (s);
|
||||
api.flags = stream_getc (s);
|
||||
api.message = stream_getc (s);
|
||||
|
||||
/* IPv4 prefix. */
|
||||
memset (&p, 0, sizeof (struct prefix_ipv4));
|
||||
p.family = AF_INET;
|
||||
p.prefixlen = stream_getc (s);
|
||||
stream_get (&p.prefix, s, PSIZE (p.prefixlen));
|
||||
|
||||
if (IPV4_NET127(ntohl(p.prefix.s_addr)))
|
||||
return 0;
|
||||
|
||||
/* Nexthop, ifindex, distance, metric. */
|
||||
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
|
||||
{
|
||||
api.nexthop_num = stream_getc (s);
|
||||
stream_get_ipv4 (s);
|
||||
}
|
||||
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
|
||||
{
|
||||
api.ifindex_num = stream_getc (s);
|
||||
/* XXX assert(api.ifindex_num == 1); */
|
||||
stream_getl (s); /* ifindex, unused */
|
||||
}
|
||||
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
|
||||
api.distance = stream_getc (s);
|
||||
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
|
||||
api.metric = stream_getl (s);
|
||||
|
||||
eigrp = eigrp_lookup ();
|
||||
if (eigrp == NULL)
|
||||
return 0;
|
||||
|
||||
if (command == ZEBRA_IPV4_ROUTE_ADD)
|
||||
{
|
||||
|
||||
}
|
||||
else /* if (command == ZEBRA_IPV4_ROUTE_DELETE) */
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Inteface addition message from zebra. */
|
||||
static int
|
||||
eigrp_interface_add (int command, struct zclient *zclient, zebra_size_t length,
|
||||
vrf_id_t vrf_id)
|
||||
{
|
||||
struct interface *ifp;
|
||||
|
||||
ifp = zebra_interface_add_read (zclient->ibuf, vrf_id);
|
||||
|
||||
assert (ifp->info);
|
||||
|
||||
if (!EIGRP_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (ifp), type))
|
||||
{
|
||||
SET_IF_PARAM (IF_DEF_PARAMS (ifp), type);
|
||||
IF_DEF_PARAMS (ifp)->type = eigrp_default_iftype (ifp);
|
||||
}
|
||||
|
||||
eigrp_if_update (ifp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
eigrp_interface_delete (int command, struct zclient *zclient,
|
||||
zebra_size_t length, vrf_id_t vrf_id)
|
||||
{
|
||||
struct interface *ifp;
|
||||
struct stream *s;
|
||||
struct route_node *rn;
|
||||
|
||||
s = zclient->ibuf;
|
||||
/* zebra_interface_state_read () updates interface structure in iflist */
|
||||
ifp = zebra_interface_state_read (s, vrf_id);
|
||||
|
||||
if (ifp == NULL)
|
||||
return 0;
|
||||
|
||||
if (if_is_up (ifp))
|
||||
zlog_warn ("Zebra: got delete of %s, but interface is still up",
|
||||
ifp->name);
|
||||
|
||||
if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE))
|
||||
zlog_debug("Zebra: interface delete %s index %d flags %llx metric %d mtu %d",
|
||||
ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
|
||||
|
||||
for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
|
||||
if (rn->info)
|
||||
eigrp_if_free ((struct eigrp_interface *) rn->info, INTERFACE_DOWN_BY_ZEBRA);
|
||||
|
||||
ifp->ifindex = IFINDEX_INTERNAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
eigrp_interface_address_add (int command, struct zclient *zclient,
|
||||
zebra_size_t length, vrf_id_t vrf_id)
|
||||
{
|
||||
struct connected *c;
|
||||
|
||||
c = zebra_interface_address_read (command, zclient->ibuf, vrf_id);
|
||||
|
||||
if (c == NULL)
|
||||
return 0;
|
||||
|
||||
if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE))
|
||||
{
|
||||
char buf[128];
|
||||
prefix2str (c->address, buf, sizeof (buf));
|
||||
zlog_debug ("Zebra: interface %s address add %s", c->ifp->name, buf);
|
||||
}
|
||||
|
||||
eigrp_if_update (c->ifp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
eigrp_interface_address_delete (int command, struct zclient *zclient,
|
||||
zebra_size_t length, vrf_id_t vrf_id)
|
||||
{
|
||||
struct connected *c;
|
||||
struct interface *ifp;
|
||||
struct eigrp_interface *ei;
|
||||
struct route_node *rn;
|
||||
struct prefix p;
|
||||
|
||||
c = zebra_interface_address_read (command, zclient->ibuf, vrf_id);
|
||||
|
||||
if (c == NULL)
|
||||
return 0;
|
||||
|
||||
if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE))
|
||||
{
|
||||
char buf[128];
|
||||
prefix2str (c->address, buf, sizeof (buf));
|
||||
zlog_debug ("Zebra: interface %s address delete %s", c->ifp->name, buf);
|
||||
}
|
||||
|
||||
ifp = c->ifp;
|
||||
p = *c->address;
|
||||
p.prefixlen = IPV4_MAX_PREFIXLEN;
|
||||
|
||||
rn = route_node_lookup (IF_OIFS (ifp), &p);
|
||||
if (!rn)
|
||||
{
|
||||
connected_free (c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert (rn->info);
|
||||
ei = rn->info;
|
||||
|
||||
/* Call interface hook functions to clean up */
|
||||
eigrp_if_free (ei, INTERFACE_DOWN_BY_ZEBRA);
|
||||
|
||||
connected_free (c);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
eigrp_interface_state_up (int command, struct zclient *zclient,
|
||||
zebra_size_t length, vrf_id_t vrf_id)
|
||||
{
|
||||
struct interface *ifp;
|
||||
struct eigrp_interface *ei;
|
||||
struct route_node *rn;
|
||||
|
||||
ifp = zebra_interface_if_lookup (zclient->ibuf);
|
||||
|
||||
if (ifp == NULL)
|
||||
return 0;
|
||||
|
||||
/* Interface is already up. */
|
||||
if (if_is_operative (ifp))
|
||||
{
|
||||
/* Temporarily keep ifp values. */
|
||||
struct interface if_tmp;
|
||||
memcpy (&if_tmp, ifp, sizeof (struct interface));
|
||||
|
||||
zebra_interface_if_set_value (zclient->ibuf, ifp);
|
||||
|
||||
if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE))
|
||||
zlog_debug ("Zebra: Interface[%s] state update.", ifp->name);
|
||||
|
||||
if (if_tmp.bandwidth != ifp->bandwidth)
|
||||
{
|
||||
if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE))
|
||||
zlog_debug ("Zebra: Interface[%s] bandwidth change %d -> %d.",
|
||||
ifp->name, if_tmp.bandwidth, ifp->bandwidth);
|
||||
|
||||
// eigrp_if_recalculate_output_cost (ifp);
|
||||
}
|
||||
|
||||
if (if_tmp.mtu != ifp->mtu)
|
||||
{
|
||||
if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE))
|
||||
zlog_debug ("Zebra: Interface[%s] MTU change %u -> %u.",
|
||||
ifp->name, if_tmp.mtu, ifp->mtu);
|
||||
|
||||
/* Must reset the interface (simulate down/up) when MTU changes. */
|
||||
eigrp_if_reset (ifp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
zebra_interface_if_set_value (zclient->ibuf, ifp);
|
||||
|
||||
if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE))
|
||||
zlog_debug ("Zebra: Interface[%s] state change to up.", ifp->name);
|
||||
|
||||
for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
|
||||
{
|
||||
if ((ei = rn->info) == NULL)
|
||||
continue;
|
||||
|
||||
eigrp_if_up (ei);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
eigrp_interface_state_down (int command, struct zclient *zclient,
|
||||
zebra_size_t length, vrf_id_t vrf_id)
|
||||
{
|
||||
struct interface *ifp;
|
||||
struct eigrp_interface *ei;
|
||||
struct route_node *node;
|
||||
|
||||
ifp = zebra_interface_state_read (zclient->ibuf, vrf_id);
|
||||
|
||||
if (ifp == NULL)
|
||||
return 0;
|
||||
|
||||
if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE))
|
||||
zlog_debug ("Zebra: Interface[%s] state change to down.", ifp->name);
|
||||
|
||||
for (node = route_top (IF_OIFS (ifp)); node; node = route_next (node))
|
||||
{
|
||||
if ((ei = node->info) == NULL)
|
||||
continue;
|
||||
eigrp_if_down (ei);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct interface *
|
||||
zebra_interface_if_lookup (struct stream *s)
|
||||
{
|
||||
char ifname_tmp[INTERFACE_NAMSIZ];
|
||||
|
||||
/* Read interface name. */
|
||||
stream_get (ifname_tmp, s, INTERFACE_NAMSIZ);
|
||||
|
||||
/* And look it up. */
|
||||
return if_lookup_by_name_len (ifname_tmp,
|
||||
strnlen (ifname_tmp, INTERFACE_NAMSIZ));
|
||||
}
|
||||
|
||||
void
|
||||
eigrp_zebra_route_add (struct prefix_ipv4 *p, struct eigrp_neighbor_entry *te)
|
||||
{
|
||||
u_char message;
|
||||
u_char flags;
|
||||
int psize;
|
||||
struct stream *s;
|
||||
|
||||
if (zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP])
|
||||
{
|
||||
message = 0;
|
||||
flags = 0;
|
||||
|
||||
/* EIGRP pass nexthop and metric */
|
||||
SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP);
|
||||
SET_FLAG (message, ZAPI_MESSAGE_METRIC);
|
||||
|
||||
/* Distance value. */
|
||||
// distance = eigrp_distance_apply (p, er);
|
||||
// if (distance)
|
||||
// SET_FLAG (message, ZAPI_MESSAGE_DISTANCE);
|
||||
|
||||
/* Make packet. */
|
||||
s = zclient->obuf;
|
||||
stream_reset (s);
|
||||
|
||||
/* Put command, type, flags, message. */
|
||||
zclient_create_header (s, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT);
|
||||
stream_putc (s, ZEBRA_ROUTE_EIGRP);
|
||||
stream_putc (s, flags);
|
||||
stream_putc (s, message);
|
||||
stream_putw (s, SAFI_UNICAST);
|
||||
|
||||
/* Put prefix information. */
|
||||
psize = PSIZE (p->prefixlen);
|
||||
stream_putc (s, p->prefixlen);
|
||||
stream_write (s, (u_char *) & p->prefix, psize);
|
||||
|
||||
/* Nexthop count. */
|
||||
stream_putc (s, 1);
|
||||
|
||||
/* Nexthop, ifindex, distance and metric information. */
|
||||
stream_putc (s, NEXTHOP_TYPE_IPV4_IFINDEX);
|
||||
stream_put_in_addr (s, &te->adv_router->src);
|
||||
stream_putl (s, te->ei->ifp->ifindex);
|
||||
|
||||
if (IS_DEBUG_EIGRP (zebra, ZEBRA_REDISTRIBUTE))
|
||||
{
|
||||
char buf[2][INET_ADDRSTRLEN];
|
||||
zlog_debug ("Zebra: Route add %s/%d nexthop %s",
|
||||
inet_ntop(AF_INET, &p->prefix, buf[0], sizeof (buf[0])),
|
||||
p->prefixlen,
|
||||
inet_ntop(AF_INET, 0 /*&p->nexthop*/, buf[1], sizeof (buf[1])));
|
||||
}
|
||||
|
||||
stream_putl (s, te->distance);
|
||||
stream_putw_at (s, 0, stream_get_endp (s));
|
||||
|
||||
zclient_send_message (zclient);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
eigrp_zebra_route_delete (struct prefix_ipv4 *p, struct eigrp_neighbor_entry *te)
|
||||
{
|
||||
u_char message;
|
||||
u_char flags;
|
||||
int psize;
|
||||
struct stream *s;
|
||||
|
||||
if (zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP])
|
||||
{
|
||||
message = 0;
|
||||
flags = 0;
|
||||
/* Make packet. */
|
||||
s = zclient->obuf;
|
||||
stream_reset (s);
|
||||
|
||||
/* Put command, type, flags, message. */
|
||||
zclient_create_header (s, ZEBRA_IPV4_ROUTE_DELETE, VRF_DEFAULT);
|
||||
stream_putc (s, ZEBRA_ROUTE_EIGRP);
|
||||
stream_putc (s, flags);
|
||||
stream_putc (s, message);
|
||||
stream_putw (s, SAFI_UNICAST);
|
||||
|
||||
/* Put prefix information. */
|
||||
psize = PSIZE (p->prefixlen);
|
||||
stream_putc (s, p->prefixlen);
|
||||
stream_write (s, (u_char *) & p->prefix, psize);
|
||||
|
||||
/* Nexthop count. */
|
||||
stream_putc (s, 1);
|
||||
|
||||
/* Nexthop, ifindex, distance and metric information. */
|
||||
stream_putc (s, NEXTHOP_TYPE_IPV4_IFINDEX);
|
||||
stream_put_in_addr (s, &te->adv_router->src);
|
||||
stream_putl (s, te->ei->ifp->ifindex);
|
||||
|
||||
if (IS_DEBUG_EIGRP (zebra, ZEBRA_REDISTRIBUTE))
|
||||
{
|
||||
char buf[2][INET_ADDRSTRLEN];
|
||||
zlog_debug ("Zebra: Route del %s/%d nexthop %s",
|
||||
inet_ntop (AF_INET, &p->prefix, buf[0], sizeof (buf[0])),
|
||||
p->prefixlen,
|
||||
inet_ntop (AF_INET, 0 /*&p->nexthop*/, buf[1], sizeof (buf[1])));
|
||||
}
|
||||
|
||||
|
||||
if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
|
||||
{
|
||||
stream_putl (s, te->distance);
|
||||
}
|
||||
|
||||
stream_putw_at (s, 0, stream_get_endp (s));
|
||||
|
||||
zclient_send_message (zclient);
|
||||
}
|
||||
}
|
||||
|
||||
vrf_bitmap_t
|
||||
eigrp_is_type_redistributed (int type)
|
||||
{
|
||||
return (DEFAULT_ROUTE_TYPE (type)) ?
|
||||
zclient->default_information : zclient->redist[AFI_IP][type];
|
||||
}
|
||||
|
||||
int
|
||||
eigrp_redistribute_set (struct eigrp *eigrp, int type, struct eigrp_metrics metric)
|
||||
{
|
||||
|
||||
if (eigrp_is_type_redistributed (type))
|
||||
{
|
||||
if (eigrp_metrics_is_same(&metric, &eigrp->dmetric[type]))
|
||||
{
|
||||
eigrp->dmetric[type] = metric;
|
||||
}
|
||||
|
||||
eigrp_external_routes_refresh (eigrp, type);
|
||||
|
||||
// if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE))
|
||||
// zlog_debug ("Redistribute[%s]: Refresh Type[%d], Metric[%d]",
|
||||
// eigrp_redist_string(type),
|
||||
// metric_type (eigrp, type), metric_value (eigrp, type));
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
eigrp->dmetric[type] = metric;
|
||||
|
||||
zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient,
|
||||
AFI_IP, type, 0, VRF_DEFAULT);
|
||||
|
||||
// if (IS_DEBUG_EIGRP (zebra, ZEBRA_REDISTRIBUTE))
|
||||
// zlog_debug ("Redistribute[%s]: Start Type[%d], Metric[%d]",
|
||||
// ospf_redist_string(type),
|
||||
// metric_type (ospf, type), metric_value (ospf, type));
|
||||
|
||||
++eigrp->redistribute;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
eigrp_redistribute_unset (struct eigrp *eigrp, int type)
|
||||
{
|
||||
|
||||
if (eigrp_is_type_redistributed (type))
|
||||
{
|
||||
memset(&eigrp->dmetric[type], 0, sizeof(struct eigrp_metrics));
|
||||
zclient_redistribute (ZEBRA_REDISTRIBUTE_DELETE, zclient,
|
||||
AFI_IP, type, 0, VRF_DEFAULT);
|
||||
--eigrp->redistribute;
|
||||
}
|
||||
|
||||
// if (IS_DEBUG_EIGRP (zebra, ZEBRA_REDISTRIBUTE))
|
||||
// zlog_debug ("Redistribute[%s]: Start Type[%d], Metric[%d]",
|
||||
// ospf_redist_string(type),
|
||||
// metric_type (ospf, type), metric_value (ospf, type));
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
43
eigrpd/eigrp_zebra.h
Normal file
43
eigrpd/eigrp_zebra.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Zebra connect library for EIGRP.
|
||||
* Copyright (C) 2013-2014
|
||||
* Authors:
|
||||
* Donnie Savage
|
||||
* Jan Janovic
|
||||
* Matej Perina
|
||||
* Peter Orsag
|
||||
* Peter Paluch
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _ZEBRA_EIGRP_ZEBRA_H_
|
||||
#define _ZEBRA_EIGRP_ZEBRA_H_
|
||||
|
||||
#include "vty.h"
|
||||
#include "vrf.h"
|
||||
|
||||
extern void eigrp_zebra_init (void);
|
||||
|
||||
extern void eigrp_zebra_route_add (struct prefix_ipv4 *, struct eigrp_neighbor_entry *);
|
||||
extern void eigrp_zebra_route_delete (struct prefix_ipv4 *, struct eigrp_neighbor_entry *);
|
||||
extern int eigrp_redistribute_set (struct eigrp *, int, struct eigrp_metrics);
|
||||
extern int eigrp_redistribute_unset (struct eigrp *, int);
|
||||
extern vrf_bitmap_t eigrp_is_type_redistributed (int);
|
||||
|
||||
#endif /* _ZEBRA_EIGRP_ZEBRA_H_ */
|
310
eigrpd/eigrpd.c
Normal file
310
eigrpd/eigrpd.c
Normal file
|
@ -0,0 +1,310 @@
|
|||
/*
|
||||
* EIGRP Daemon Program.
|
||||
* Copyright (C) 2013-2014
|
||||
* Authors:
|
||||
* Donnie Savage
|
||||
* Jan Janovic
|
||||
* Matej Perina
|
||||
* Peter Orsag
|
||||
* Peter Paluch
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#include "thread.h"
|
||||
#include "vty.h"
|
||||
#include "command.h"
|
||||
#include "linklist.h"
|
||||
#include "prefix.h"
|
||||
#include "table.h"
|
||||
#include "if.h"
|
||||
#include "memory.h"
|
||||
#include "stream.h"
|
||||
#include "log.h"
|
||||
#include "sockunion.h" /* for inet_aton () */
|
||||
#include "zclient.h"
|
||||
#include "plist.h"
|
||||
#include "sockopt.h"
|
||||
#include "keychain.h"
|
||||
|
||||
#include "eigrpd/eigrp_structs.h"
|
||||
#include "eigrpd/eigrpd.h"
|
||||
#include "eigrpd/eigrp_interface.h"
|
||||
#include "eigrpd/eigrp_zebra.h"
|
||||
#include "eigrpd/eigrp_vty.h"
|
||||
#include "eigrpd/eigrp_neighbor.h"
|
||||
#include "eigrpd/eigrp_packet.h"
|
||||
#include "eigrpd/eigrp_network.h"
|
||||
#include "eigrpd/eigrp_topology.h"
|
||||
#include "eigrpd/eigrp_memory.h"
|
||||
|
||||
DEFINE_QOBJ_TYPE(eigrp)
|
||||
|
||||
static struct eigrp_master eigrp_master;
|
||||
|
||||
struct eigrp_master *eigrp_om;
|
||||
|
||||
static void eigrp_finish_final(struct eigrp *);
|
||||
static void eigrp_delete(struct eigrp *);
|
||||
static struct eigrp *eigrp_new(const char *);
|
||||
static void eigrp_add(struct eigrp *);
|
||||
|
||||
extern struct zclient *zclient;
|
||||
extern struct in_addr router_id_zebra;
|
||||
|
||||
|
||||
/*
|
||||
* void eigrp_router_id_update(struct eigrp *eigrp)
|
||||
*
|
||||
* Description:
|
||||
* update routerid associated with this instance of EIGRP.
|
||||
* If the id changes, then call if_update for each interface
|
||||
* to resync the topology database with all neighbors
|
||||
*
|
||||
* Select the router ID based on these priorities:
|
||||
* 1. Statically assigned router ID is always the first choice.
|
||||
* 2. If there is no statically assigned router ID, then try to stick
|
||||
* with the most recent value, since changing router ID's is very
|
||||
* disruptive.
|
||||
* 3. Last choice: just go with whatever the zebra daemon recommends.
|
||||
*
|
||||
* Note:
|
||||
* router id for EIGRP is really just a 32 bit number. Cisco historically
|
||||
* displays it in dotted decimal notation, and will pickup an IP address
|
||||
* from an interface so it can be 'auto-configed" to a uniqe value
|
||||
*
|
||||
* This does not work for IPv6, and to make the code simpler, its
|
||||
* stored and processed internerall as a 32bit number
|
||||
*/
|
||||
void
|
||||
eigrp_router_id_update (struct eigrp *eigrp)
|
||||
{
|
||||
struct interface *ifp;
|
||||
struct listnode *node;
|
||||
u_int32_t router_id, router_id_old;
|
||||
|
||||
router_id_old = eigrp->router_id;
|
||||
|
||||
if (eigrp->router_id_static != 0)
|
||||
router_id = eigrp->router_id_static;
|
||||
|
||||
else if (eigrp->router_id != 0)
|
||||
router_id = eigrp->router_id;
|
||||
|
||||
else
|
||||
router_id = router_id_zebra.s_addr;
|
||||
|
||||
eigrp->router_id = router_id;
|
||||
if (router_id_old != router_id)
|
||||
{
|
||||
// if (IS_DEBUG_EIGRP_EVENT)
|
||||
// zlog_debug("Router-ID[NEW:%s]: Update", inet_ntoa(eigrp->router_id));
|
||||
|
||||
/* update eigrp_interface's */
|
||||
for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp))
|
||||
eigrp_if_update(ifp);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
eigrp_master_init ()
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
memset(&eigrp_master, 0, sizeof(struct eigrp_master));
|
||||
|
||||
eigrp_om = &eigrp_master;
|
||||
eigrp_om->eigrp = list_new();
|
||||
|
||||
monotime(&tv);
|
||||
eigrp_om->start_time = tv.tv_sec;
|
||||
}
|
||||
|
||||
|
||||
/* Allocate new eigrp structure. */
|
||||
static struct eigrp *
|
||||
eigrp_new (const char *AS)
|
||||
{
|
||||
struct eigrp *eigrp = XCALLOC(MTYPE_EIGRP_TOP, sizeof (struct eigrp));
|
||||
int eigrp_socket;
|
||||
|
||||
/* init information relevant to peers */
|
||||
eigrp->vrid = 0;
|
||||
eigrp->AS = atoi(AS);
|
||||
eigrp->router_id = 0L;
|
||||
eigrp->router_id_static = 0L;
|
||||
eigrp->sequence_number = 1;
|
||||
|
||||
/*Configure default K Values for EIGRP Process*/
|
||||
eigrp->k_values[0] = EIGRP_K1_DEFAULT;
|
||||
eigrp->k_values[1] = EIGRP_K2_DEFAULT;
|
||||
eigrp->k_values[2] = EIGRP_K3_DEFAULT;
|
||||
eigrp->k_values[3] = EIGRP_K4_DEFAULT;
|
||||
eigrp->k_values[4] = EIGRP_K5_DEFAULT;
|
||||
eigrp->k_values[5] = EIGRP_K6_DEFAULT;
|
||||
|
||||
/* init internal data structures */
|
||||
eigrp->eiflist = list_new();
|
||||
eigrp->passive_interface_default = EIGRP_IF_ACTIVE;
|
||||
eigrp->networks = route_table_init();
|
||||
|
||||
if ((eigrp_socket = eigrp_sock_init()) < 0)
|
||||
{
|
||||
zlog_err("eigrp_new: fatal error: eigrp_sock_init was unable to open "
|
||||
"a socket");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
eigrp->fd = eigrp_socket;
|
||||
eigrp->maxsndbuflen = getsockopt_so_sendbuf(eigrp->fd);
|
||||
|
||||
if ((eigrp->ibuf = stream_new(EIGRP_PACKET_MAX_LEN+1)) == NULL)
|
||||
{
|
||||
zlog_err("eigrp_new: fatal error: stream_new (%u) failed allocating ibuf",
|
||||
EIGRP_PACKET_MAX_LEN+1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
eigrp->t_read = thread_add_read(master, eigrp_read, eigrp, eigrp->fd);
|
||||
eigrp->oi_write_q = list_new();
|
||||
|
||||
eigrp->topology_table = eigrp_topology_new();
|
||||
|
||||
eigrp->neighbor_self = eigrp_nbr_new(NULL);
|
||||
inet_aton("127.0.0.1", &eigrp->neighbor_self->src);
|
||||
|
||||
eigrp->variance = EIGRP_VARIANCE_DEFAULT;
|
||||
eigrp->max_paths = EIGRP_MAX_PATHS_DEFAULT;
|
||||
|
||||
eigrp->serno = 0;
|
||||
eigrp->serno_last_update = 0;
|
||||
eigrp->topology_changes_externalIPV4 = list_new ();
|
||||
eigrp->topology_changes_internalIPV4 = list_new ();
|
||||
|
||||
eigrp->list[EIGRP_FILTER_IN] = NULL;
|
||||
eigrp->list[EIGRP_FILTER_OUT] = NULL;
|
||||
|
||||
eigrp->prefix[EIGRP_FILTER_IN] = NULL;
|
||||
eigrp->prefix[EIGRP_FILTER_OUT] = NULL;
|
||||
|
||||
eigrp->routemap[EIGRP_FILTER_IN] = NULL;
|
||||
eigrp->routemap[EIGRP_FILTER_OUT] = NULL;
|
||||
|
||||
QOBJ_REG(eigrp, eigrp);
|
||||
return eigrp;
|
||||
}
|
||||
|
||||
static void
|
||||
eigrp_add (struct eigrp *eigrp)
|
||||
{
|
||||
listnode_add(eigrp_om->eigrp, eigrp);
|
||||
}
|
||||
|
||||
static void
|
||||
eigrp_delete (struct eigrp *eigrp)
|
||||
{
|
||||
listnode_delete(eigrp_om->eigrp, eigrp);
|
||||
}
|
||||
|
||||
struct eigrp *
|
||||
eigrp_get (const char *AS)
|
||||
{
|
||||
struct eigrp *eigrp;
|
||||
|
||||
eigrp = eigrp_lookup();
|
||||
if (eigrp == NULL)
|
||||
{
|
||||
eigrp = eigrp_new(AS);
|
||||
eigrp_add(eigrp);
|
||||
}
|
||||
|
||||
return eigrp;
|
||||
}
|
||||
|
||||
/* Shut down the entire process */
|
||||
void
|
||||
eigrp_terminate (void)
|
||||
{
|
||||
struct eigrp *eigrp;
|
||||
struct listnode *node, *nnode;
|
||||
|
||||
/* shutdown already in progress */
|
||||
if (CHECK_FLAG(eigrp_om->options, EIGRP_MASTER_SHUTDOWN))
|
||||
return;
|
||||
|
||||
SET_FLAG(eigrp_om->options, EIGRP_MASTER_SHUTDOWN);
|
||||
|
||||
/* exit immediately if EIGRP not actually running */
|
||||
if (listcount(eigrp_om->eigrp) == 0)
|
||||
exit(0);
|
||||
|
||||
for (ALL_LIST_ELEMENTS(eigrp_om->eigrp, node, nnode, eigrp))
|
||||
eigrp_finish(eigrp);
|
||||
}
|
||||
|
||||
void
|
||||
eigrp_finish (struct eigrp *eigrp)
|
||||
{
|
||||
|
||||
eigrp_finish_final(eigrp);
|
||||
|
||||
/* eigrp being shut-down? If so, was this the last eigrp instance? */
|
||||
if (CHECK_FLAG(eigrp_om->options, EIGRP_MASTER_SHUTDOWN)
|
||||
&& (listcount(eigrp_om->eigrp) == 0))
|
||||
exit(0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Final cleanup of eigrp instance */
|
||||
static void
|
||||
eigrp_finish_final (struct eigrp *eigrp)
|
||||
{
|
||||
|
||||
close(eigrp->fd);
|
||||
|
||||
if (zclient)
|
||||
zclient_free(zclient);
|
||||
|
||||
list_delete(eigrp->eiflist);
|
||||
list_delete(eigrp->oi_write_q);
|
||||
list_delete(eigrp->topology_changes_externalIPV4);
|
||||
list_delete(eigrp->topology_changes_internalIPV4);
|
||||
|
||||
eigrp_topology_cleanup(eigrp->topology_table);
|
||||
eigrp_topology_free(eigrp->topology_table);
|
||||
|
||||
eigrp_nbr_delete(eigrp->neighbor_self);
|
||||
|
||||
eigrp_delete(eigrp);
|
||||
|
||||
XFREE(MTYPE_EIGRP_TOP,eigrp);
|
||||
|
||||
}
|
||||
|
||||
/*Look for existing eigrp process*/
|
||||
struct eigrp *
|
||||
eigrp_lookup (void)
|
||||
{
|
||||
if (listcount(eigrp_om->eigrp) == 0)
|
||||
return NULL;
|
||||
|
||||
return listgetdata(listhead(eigrp_om->eigrp));
|
||||
}
|
13
eigrpd/eigrpd.conf.sample
Normal file
13
eigrpd/eigrpd.conf.sample
Normal file
|
@ -0,0 +1,13 @@
|
|||
! -*- eigrpd -*-
|
||||
!
|
||||
! EIGRPDd sample configuration file
|
||||
!
|
||||
!
|
||||
hostname eigrpd
|
||||
password zebra
|
||||
!enable password please-set-at-here
|
||||
!
|
||||
!router eigrp 4453
|
||||
! network 192.168.1.0/24
|
||||
!
|
||||
log stdout
|
54
eigrpd/eigrpd.h
Normal file
54
eigrpd/eigrpd.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* EIGRP main header.
|
||||
* Copyright (C) 2013-2014
|
||||
* Authors:
|
||||
* Donnie Savage
|
||||
* Jan Janovic
|
||||
* Matej Perina
|
||||
* Peter Orsag
|
||||
* Peter Paluch
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _ZEBRA_EIGRPD_H
|
||||
#define _ZEBRA_EIGRPD_H
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#include "filter.h"
|
||||
#include "log.h"
|
||||
|
||||
/* Set EIGRP version is "classic" - wide metrics comes next */
|
||||
#define EIGRP_MAJOR_VERSION 1
|
||||
#define EIGRP_MINOR_VERSION 2
|
||||
|
||||
/* Extern variables. */
|
||||
extern struct zclient *zclient;
|
||||
extern struct thread_master *master;
|
||||
extern struct eigrp_master *eigrp_om;
|
||||
|
||||
/* Prototypes */
|
||||
extern void eigrp_master_init (void);
|
||||
extern void eigrp_terminate (void);
|
||||
extern void eigrp_finish (struct eigrp *);
|
||||
extern struct eigrp *eigrp_get (const char *);
|
||||
extern struct eigrp *eigrp_lookup (void);
|
||||
extern void eigrp_router_id_update (struct eigrp *);
|
||||
|
||||
#endif /* _ZEBRA_EIGRPD_H */
|
|
@ -31,7 +31,8 @@ libfrr_la_SOURCES = \
|
|||
spf_backoff.c \
|
||||
libfrr.c \
|
||||
strlcpy.c \
|
||||
strlcat.c
|
||||
strlcat.c \
|
||||
sha256.c
|
||||
|
||||
BUILT_SOURCES = route_types.h gitversion.h command_parse.h command_lex.h
|
||||
|
||||
|
@ -55,6 +56,7 @@ pkginclude_HEADERS = \
|
|||
spf_backoff.h \
|
||||
srcdest_table.h \
|
||||
libfrr.h \
|
||||
sha256.h \
|
||||
# end
|
||||
|
||||
noinst_HEADERS = \
|
||||
|
|
|
@ -1398,6 +1398,7 @@ cmd_exit (struct vty *vty)
|
|||
case ZEBRA_NODE:
|
||||
case BGP_NODE:
|
||||
case RIP_NODE:
|
||||
case EIGRP_NODE:
|
||||
case RIPNG_NODE:
|
||||
case OSPF_NODE:
|
||||
case OSPF6_NODE:
|
||||
|
@ -1479,6 +1480,7 @@ DEFUN (config_end,
|
|||
case ZEBRA_NODE:
|
||||
case RIP_NODE:
|
||||
case RIPNG_NODE:
|
||||
case EIGRP_NODE:
|
||||
case BGP_NODE:
|
||||
case BGP_ENCAP_NODE:
|
||||
case BGP_ENCAPV6_NODE:
|
||||
|
|
|
@ -91,6 +91,7 @@ enum node_type
|
|||
TABLE_NODE, /* rtm_table selection node. */
|
||||
RIP_NODE, /* RIP protocol mode node. */
|
||||
RIPNG_NODE, /* RIPng protocol mode node. */
|
||||
EIGRP_NODE, /* EIGRP protocol mode node. */
|
||||
BGP_NODE, /* BGP protocol mode which includes BGP4+ */
|
||||
BGP_VPNV4_NODE, /* BGP MPLS-VPN PE exchange. */
|
||||
BGP_VPNV6_NODE, /* BGP MPLS-VPN PE exchange. */
|
||||
|
@ -356,6 +357,7 @@ struct cmd_element
|
|||
#define REDIST_STR "Redistribute information from another routing protocol\n"
|
||||
#define CLEAR_STR "Reset functions\n"
|
||||
#define RIP_STR "RIP information\n"
|
||||
#define EIGRP_STR "EIGRP information\n"
|
||||
#define BGP_STR "BGP information\n"
|
||||
#define BGP_SOFT_STR "Soft reconfig inbound and outbound updates\n"
|
||||
#define BGP_SOFT_IN_STR "Send route-refresh unless using 'soft-reconfiguration inbound'\n"
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "version.h"
|
||||
#include "memory_vty.h"
|
||||
#include "zclient.h"
|
||||
#include "log_int.h"
|
||||
|
||||
const char frr_sysconfdir[] = SYSCONFDIR;
|
||||
const char frr_vtydir[] = DAEMON_VTY_DIR;
|
||||
|
@ -303,7 +304,7 @@ struct thread_master *frr_init(void)
|
|||
openzlog (di->progname, di->logname, di->instance,
|
||||
LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
|
||||
#if defined(HAVE_CUMULUS)
|
||||
zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl);
|
||||
zlog_set_level (ZLOG_DEST_SYSLOG, zlog_default->default_lvl);
|
||||
#endif
|
||||
|
||||
zprivs_init(di->privs);
|
||||
|
|
|
@ -1044,6 +1044,8 @@ proto_redistnum(int afi, const char *s)
|
|||
return ZEBRA_ROUTE_STATIC;
|
||||
else if (strmatch (s, "rip"))
|
||||
return ZEBRA_ROUTE_RIP;
|
||||
else if (strmatch (s, "eigrp"))
|
||||
return ZEBRA_ROUTE_EIGRP;
|
||||
else if (strmatch (s, "ospf"))
|
||||
return ZEBRA_ROUTE_OSPF;
|
||||
else if (strmatch (s, "isis"))
|
||||
|
|
|
@ -52,6 +52,7 @@ ZEBRA_ROUTE_OSPF6, ospf6, ospf6d, 'O', 0, 1, "OSPFv3"
|
|||
ZEBRA_ROUTE_ISIS, isis, isisd, 'I', 1, 1, "IS-IS"
|
||||
ZEBRA_ROUTE_BGP, bgp, bgpd, 'B', 1, 1, "BGP"
|
||||
ZEBRA_ROUTE_PIM, pim, pimd, 'P', 1, 0, "PIM"
|
||||
ZEBRA_ROUTE_EIGRP, eigrp, eigrpd, 'E', 1, 0, "EIGRP"
|
||||
ZEBRA_ROUTE_NHRP, nhrp, nhrpd, 'N', 1, 1, "NHRP"
|
||||
# HSLS and OLSR both are AFI independent (so: 1, 1), however
|
||||
# we want to disable for them for general Quagga distribution.
|
||||
|
@ -86,6 +87,7 @@ ZEBRA_ROUTE_OSPF6, "Open Shortest Path First (IPv6) (OSPFv3)"
|
|||
ZEBRA_ROUTE_ISIS, "Intermediate System to Intermediate System (IS-IS)"
|
||||
ZEBRA_ROUTE_BGP, "Border Gateway Protocol (BGP)"
|
||||
ZEBRA_ROUTE_PIM, "Protocol Independent Multicast (PIM)"
|
||||
ZEBRA_ROUTE_EIGRP, "Enhanced Interior Gateway Routing Protocol (EIGRP)"
|
||||
ZEBRA_ROUTE_NHRP, "Next Hop Resolution Protocol (NHRP)"
|
||||
ZEBRA_ROUTE_HSLS, "Hazy-Sighted Link State Protocol (HSLS)"
|
||||
ZEBRA_ROUTE_VNC, "Virtual Network Control (VNC)"
|
||||
|
|
425
lib/sha256.c
Normal file
425
lib/sha256.c
Normal file
|
@ -0,0 +1,425 @@
|
|||
/*-
|
||||
* Copyright 2005,2007,2009 Colin Percival
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <zebra.h>
|
||||
#include "sha256.h"
|
||||
|
||||
static inline uint32_t
|
||||
be32dec(const void *pp)
|
||||
{
|
||||
const uint8_t *p = (uint8_t const *)pp;
|
||||
|
||||
return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) +
|
||||
((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24));
|
||||
}
|
||||
|
||||
static inline void
|
||||
be32enc(void *pp, uint32_t x)
|
||||
{
|
||||
uint8_t * p = (uint8_t *)pp;
|
||||
|
||||
p[3] = x & 0xff;
|
||||
p[2] = (x >> 8) & 0xff;
|
||||
p[1] = (x >> 16) & 0xff;
|
||||
p[0] = (x >> 24) & 0xff;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode a length len/4 vector of (uint32_t) into a length len vector of
|
||||
* (unsigned char) in big-endian form. Assumes len is a multiple of 4.
|
||||
*/
|
||||
static void
|
||||
be32enc_vect(unsigned char *dst, const uint32_t *src, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len / 4; i++)
|
||||
be32enc(dst + i * 4, src[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode a big-endian length len vector of (unsigned char) into a length
|
||||
* len/4 vector of (uint32_t). Assumes len is a multiple of 4.
|
||||
*/
|
||||
static void
|
||||
be32dec_vect(uint32_t *dst, const unsigned char *src, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len / 4; i++)
|
||||
dst[i] = be32dec(src + i * 4);
|
||||
}
|
||||
|
||||
/* Elementary functions used by SHA256 */
|
||||
#define Ch(x, y, z) ((x & (y ^ z)) ^ z)
|
||||
#define Maj(x, y, z) ((x & (y | z)) | (y & z))
|
||||
#define SHR(x, n) (x >> n)
|
||||
#define ROTR(x, n) ((x >> n) | (x << (32 - n)))
|
||||
#define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
|
||||
#define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
|
||||
#define s0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3))
|
||||
#define s1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10))
|
||||
|
||||
/* SHA256 round function */
|
||||
#define RND(a, b, c, d, e, f, g, h, k) \
|
||||
t0 = h + S1(e) + Ch(e, f, g) + k; \
|
||||
t1 = S0(a) + Maj(a, b, c); \
|
||||
d += t0; \
|
||||
h = t0 + t1;
|
||||
|
||||
/* Adjusted round function for rotating state */
|
||||
#define RNDr(S, W, i, k) \
|
||||
RND(S[(64 - i) % 8], S[(65 - i) % 8], \
|
||||
S[(66 - i) % 8], S[(67 - i) % 8], \
|
||||
S[(68 - i) % 8], S[(69 - i) % 8], \
|
||||
S[(70 - i) % 8], S[(71 - i) % 8], \
|
||||
W[i] + k)
|
||||
|
||||
/*
|
||||
* SHA256 block compression function. The 256-bit state is transformed via
|
||||
* the 512-bit input block to produce a new state.
|
||||
*/
|
||||
static void
|
||||
SHA256_Transform(uint32_t * state, const unsigned char block[64])
|
||||
{
|
||||
uint32_t W[64];
|
||||
uint32_t S[8];
|
||||
uint32_t t0, t1;
|
||||
int i;
|
||||
|
||||
/* 1. Prepare message schedule W. */
|
||||
be32dec_vect(W, block, 64);
|
||||
for (i = 16; i < 64; i++)
|
||||
W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16];
|
||||
|
||||
/* 2. Initialize working variables. */
|
||||
memcpy(S, state, 32);
|
||||
|
||||
/* 3. Mix. */
|
||||
RNDr(S, W, 0, 0x428a2f98);
|
||||
RNDr(S, W, 1, 0x71374491);
|
||||
RNDr(S, W, 2, 0xb5c0fbcf);
|
||||
RNDr(S, W, 3, 0xe9b5dba5);
|
||||
RNDr(S, W, 4, 0x3956c25b);
|
||||
RNDr(S, W, 5, 0x59f111f1);
|
||||
RNDr(S, W, 6, 0x923f82a4);
|
||||
RNDr(S, W, 7, 0xab1c5ed5);
|
||||
RNDr(S, W, 8, 0xd807aa98);
|
||||
RNDr(S, W, 9, 0x12835b01);
|
||||
RNDr(S, W, 10, 0x243185be);
|
||||
RNDr(S, W, 11, 0x550c7dc3);
|
||||
RNDr(S, W, 12, 0x72be5d74);
|
||||
RNDr(S, W, 13, 0x80deb1fe);
|
||||
RNDr(S, W, 14, 0x9bdc06a7);
|
||||
RNDr(S, W, 15, 0xc19bf174);
|
||||
RNDr(S, W, 16, 0xe49b69c1);
|
||||
RNDr(S, W, 17, 0xefbe4786);
|
||||
RNDr(S, W, 18, 0x0fc19dc6);
|
||||
RNDr(S, W, 19, 0x240ca1cc);
|
||||
RNDr(S, W, 20, 0x2de92c6f);
|
||||
RNDr(S, W, 21, 0x4a7484aa);
|
||||
RNDr(S, W, 22, 0x5cb0a9dc);
|
||||
RNDr(S, W, 23, 0x76f988da);
|
||||
RNDr(S, W, 24, 0x983e5152);
|
||||
RNDr(S, W, 25, 0xa831c66d);
|
||||
RNDr(S, W, 26, 0xb00327c8);
|
||||
RNDr(S, W, 27, 0xbf597fc7);
|
||||
RNDr(S, W, 28, 0xc6e00bf3);
|
||||
RNDr(S, W, 29, 0xd5a79147);
|
||||
RNDr(S, W, 30, 0x06ca6351);
|
||||
RNDr(S, W, 31, 0x14292967);
|
||||
RNDr(S, W, 32, 0x27b70a85);
|
||||
RNDr(S, W, 33, 0x2e1b2138);
|
||||
RNDr(S, W, 34, 0x4d2c6dfc);
|
||||
RNDr(S, W, 35, 0x53380d13);
|
||||
RNDr(S, W, 36, 0x650a7354);
|
||||
RNDr(S, W, 37, 0x766a0abb);
|
||||
RNDr(S, W, 38, 0x81c2c92e);
|
||||
RNDr(S, W, 39, 0x92722c85);
|
||||
RNDr(S, W, 40, 0xa2bfe8a1);
|
||||
RNDr(S, W, 41, 0xa81a664b);
|
||||
RNDr(S, W, 42, 0xc24b8b70);
|
||||
RNDr(S, W, 43, 0xc76c51a3);
|
||||
RNDr(S, W, 44, 0xd192e819);
|
||||
RNDr(S, W, 45, 0xd6990624);
|
||||
RNDr(S, W, 46, 0xf40e3585);
|
||||
RNDr(S, W, 47, 0x106aa070);
|
||||
RNDr(S, W, 48, 0x19a4c116);
|
||||
RNDr(S, W, 49, 0x1e376c08);
|
||||
RNDr(S, W, 50, 0x2748774c);
|
||||
RNDr(S, W, 51, 0x34b0bcb5);
|
||||
RNDr(S, W, 52, 0x391c0cb3);
|
||||
RNDr(S, W, 53, 0x4ed8aa4a);
|
||||
RNDr(S, W, 54, 0x5b9cca4f);
|
||||
RNDr(S, W, 55, 0x682e6ff3);
|
||||
RNDr(S, W, 56, 0x748f82ee);
|
||||
RNDr(S, W, 57, 0x78a5636f);
|
||||
RNDr(S, W, 58, 0x84c87814);
|
||||
RNDr(S, W, 59, 0x8cc70208);
|
||||
RNDr(S, W, 60, 0x90befffa);
|
||||
RNDr(S, W, 61, 0xa4506ceb);
|
||||
RNDr(S, W, 62, 0xbef9a3f7);
|
||||
RNDr(S, W, 63, 0xc67178f2);
|
||||
|
||||
/* 4. Mix local working variables into global state */
|
||||
for (i = 0; i < 8; i++)
|
||||
state[i] += S[i];
|
||||
|
||||
/* Clean the stack. */
|
||||
memset(W, 0, 256);
|
||||
memset(S, 0, 32);
|
||||
t0 = t1 = 0;
|
||||
}
|
||||
|
||||
static unsigned char PAD[64] = {
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/* Add padding and terminating bit-count. */
|
||||
static void
|
||||
SHA256_Pad(SHA256_CTX * ctx)
|
||||
{
|
||||
unsigned char len[8];
|
||||
uint32_t r, plen;
|
||||
|
||||
/*
|
||||
* Convert length to a vector of bytes -- we do this now rather
|
||||
* than later because the length will change after we pad.
|
||||
*/
|
||||
be32enc_vect(len, ctx->count, 8);
|
||||
|
||||
/* Add 1--64 bytes so that the resulting length is 56 mod 64 */
|
||||
r = (ctx->count[1] >> 3) & 0x3f;
|
||||
plen = (r < 56) ? (56 - r) : (120 - r);
|
||||
SHA256_Update(ctx, PAD, (size_t)plen);
|
||||
|
||||
/* Add the terminating bit-count */
|
||||
SHA256_Update(ctx, len, 8);
|
||||
}
|
||||
|
||||
/* SHA-256 initialization. Begins a SHA-256 operation. */
|
||||
void
|
||||
SHA256_Init(SHA256_CTX * ctx)
|
||||
{
|
||||
|
||||
/* Zero bits processed so far */
|
||||
ctx->count[0] = ctx->count[1] = 0;
|
||||
|
||||
/* Magic initialization constants */
|
||||
ctx->state[0] = 0x6A09E667;
|
||||
ctx->state[1] = 0xBB67AE85;
|
||||
ctx->state[2] = 0x3C6EF372;
|
||||
ctx->state[3] = 0xA54FF53A;
|
||||
ctx->state[4] = 0x510E527F;
|
||||
ctx->state[5] = 0x9B05688C;
|
||||
ctx->state[6] = 0x1F83D9AB;
|
||||
ctx->state[7] = 0x5BE0CD19;
|
||||
}
|
||||
|
||||
/* Add bytes into the hash */
|
||||
void
|
||||
SHA256_Update(SHA256_CTX * ctx, const void *in, size_t len)
|
||||
{
|
||||
uint32_t bitlen[2];
|
||||
uint32_t r;
|
||||
const unsigned char *src = in;
|
||||
|
||||
/* Number of bytes left in the buffer from previous updates */
|
||||
r = (ctx->count[1] >> 3) & 0x3f;
|
||||
|
||||
/* Convert the length into a number of bits */
|
||||
bitlen[1] = ((uint32_t)len) << 3;
|
||||
bitlen[0] = (uint32_t)(len >> 29);
|
||||
|
||||
/* Update number of bits */
|
||||
if ((ctx->count[1] += bitlen[1]) < bitlen[1])
|
||||
ctx->count[0]++;
|
||||
ctx->count[0] += bitlen[0];
|
||||
|
||||
/* Handle the case where we don't need to perform any transforms */
|
||||
if (len < 64 - r) {
|
||||
memcpy(&ctx->buf[r], src, len);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Finish the current block */
|
||||
memcpy(&ctx->buf[r], src, 64 - r);
|
||||
SHA256_Transform(ctx->state, ctx->buf);
|
||||
src += 64 - r;
|
||||
len -= 64 - r;
|
||||
|
||||
/* Perform complete blocks */
|
||||
while (len >= 64) {
|
||||
SHA256_Transform(ctx->state, src);
|
||||
src += 64;
|
||||
len -= 64;
|
||||
}
|
||||
|
||||
/* Copy left over data into buffer */
|
||||
memcpy(ctx->buf, src, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA-256 finalization. Pads the input data, exports the hash value,
|
||||
* and clears the context state.
|
||||
*/
|
||||
void
|
||||
SHA256_Final(unsigned char digest[32], SHA256_CTX * ctx)
|
||||
{
|
||||
|
||||
/* Add padding */
|
||||
SHA256_Pad(ctx);
|
||||
|
||||
/* Write the hash */
|
||||
be32enc_vect(digest, ctx->state, 32);
|
||||
|
||||
/* Clear the context state */
|
||||
memset((void *)ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
|
||||
/* Initialize an HMAC-SHA256 operation with the given key. */
|
||||
void
|
||||
HMAC__SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen)
|
||||
{
|
||||
unsigned char pad[64];
|
||||
unsigned char khash[32];
|
||||
const unsigned char * K = _K;
|
||||
size_t i;
|
||||
|
||||
/* If Klen > 64, the key is really SHA256(K). */
|
||||
if (Klen > 64) {
|
||||
SHA256_Init(&ctx->ictx);
|
||||
SHA256_Update(&ctx->ictx, K, Klen);
|
||||
SHA256_Final(khash, &ctx->ictx);
|
||||
K = khash;
|
||||
Klen = 32;
|
||||
}
|
||||
|
||||
/* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */
|
||||
SHA256_Init(&ctx->ictx);
|
||||
memset(pad, 0x36, 64);
|
||||
for (i = 0; i < Klen; i++)
|
||||
pad[i] ^= K[i];
|
||||
SHA256_Update(&ctx->ictx, pad, 64);
|
||||
|
||||
/* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */
|
||||
SHA256_Init(&ctx->octx);
|
||||
memset(pad, 0x5c, 64);
|
||||
for (i = 0; i < Klen; i++)
|
||||
pad[i] ^= K[i];
|
||||
SHA256_Update(&ctx->octx, pad, 64);
|
||||
|
||||
/* Clean the stack. */
|
||||
memset(khash, 0, 32);
|
||||
}
|
||||
|
||||
/* Add bytes to the HMAC-SHA256 operation. */
|
||||
void
|
||||
HMAC__SHA256_Update(HMAC_SHA256_CTX * ctx, const void *in, size_t len)
|
||||
{
|
||||
|
||||
/* Feed data to the inner SHA256 operation. */
|
||||
SHA256_Update(&ctx->ictx, in, len);
|
||||
}
|
||||
|
||||
/* Finish an HMAC-SHA256 operation. */
|
||||
void
|
||||
HMAC__SHA256_Final(unsigned char digest[32], HMAC_SHA256_CTX * ctx)
|
||||
{
|
||||
unsigned char ihash[32];
|
||||
|
||||
/* Finish the inner SHA256 operation. */
|
||||
SHA256_Final(ihash, &ctx->ictx);
|
||||
|
||||
/* Feed the inner hash to the outer SHA256 operation. */
|
||||
SHA256_Update(&ctx->octx, ihash, 32);
|
||||
|
||||
/* Finish the outer SHA256 operation. */
|
||||
SHA256_Final(digest, &ctx->octx);
|
||||
|
||||
/* Clean the stack. */
|
||||
memset(ihash, 0, 32);
|
||||
}
|
||||
|
||||
/**
|
||||
* PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
|
||||
* Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
|
||||
* write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
|
||||
*/
|
||||
void
|
||||
PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt,
|
||||
size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen)
|
||||
{
|
||||
HMAC_SHA256_CTX PShctx, hctx;
|
||||
size_t i;
|
||||
uint8_t ivec[4];
|
||||
uint8_t U[32];
|
||||
uint8_t T[32];
|
||||
uint64_t j;
|
||||
int k;
|
||||
size_t clen;
|
||||
|
||||
/* Compute HMAC state after processing P and S. */
|
||||
HMAC__SHA256_Init(&PShctx, passwd, passwdlen);
|
||||
HMAC__SHA256_Update(&PShctx, salt, saltlen);
|
||||
|
||||
/* Iterate through the blocks. */
|
||||
for (i = 0; i * 32 < dkLen; i++) {
|
||||
/* Generate INT(i + 1). */
|
||||
be32enc(ivec, (uint32_t)(i + 1));
|
||||
|
||||
/* Compute U_1 = PRF(P, S || INT(i)). */
|
||||
memcpy(&hctx, &PShctx, sizeof(HMAC_SHA256_CTX));
|
||||
HMAC__SHA256_Update(&hctx, ivec, 4);
|
||||
HMAC__SHA256_Final(U, &hctx);
|
||||
|
||||
/* T_i = U_1 ... */
|
||||
memcpy(T, U, 32);
|
||||
|
||||
for (j = 2; j <= c; j++) {
|
||||
/* Compute U_j. */
|
||||
HMAC__SHA256_Init(&hctx, passwd, passwdlen);
|
||||
HMAC__SHA256_Update(&hctx, U, 32);
|
||||
HMAC__SHA256_Final(U, &hctx);
|
||||
|
||||
/* ... xor U_j ... */
|
||||
for (k = 0; k < 32; k++)
|
||||
T[k] ^= U[k];
|
||||
}
|
||||
|
||||
/* Copy as many bytes as necessary into buf. */
|
||||
clen = dkLen - i * 32;
|
||||
if (clen > 32)
|
||||
clen = 32;
|
||||
memcpy(&buf[i * 32], T, clen);
|
||||
}
|
||||
|
||||
/* Clean PShctx, since we never called _Final on it. */
|
||||
memset(&PShctx, 0, sizeof(HMAC_SHA256_CTX));
|
||||
}
|
58
lib/sha256.h
Normal file
58
lib/sha256.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*-
|
||||
* Copyright 2005,2007,2009 Colin Percival
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: src/lib/libmd/sha256.h,v 1.2 2006/01/17 15:35:56 phk Exp $
|
||||
*/
|
||||
|
||||
#ifndef _SHA256_H_
|
||||
#define _SHA256_H_
|
||||
|
||||
typedef struct SHA256Context {
|
||||
uint32_t state[8];
|
||||
uint32_t count[2];
|
||||
unsigned char buf[64];
|
||||
} SHA256_CTX;
|
||||
|
||||
typedef struct HMAC_SHA256Context {
|
||||
SHA256_CTX ictx;
|
||||
SHA256_CTX octx;
|
||||
} HMAC_SHA256_CTX;
|
||||
|
||||
void SHA256_Init(SHA256_CTX *);
|
||||
void SHA256_Update(SHA256_CTX *, const void *, size_t);
|
||||
void SHA256_Final(unsigned char [32], SHA256_CTX *);
|
||||
void HMAC__SHA256_Init(HMAC_SHA256_CTX *, const void *, size_t);
|
||||
void HMAC__SHA256_Update(HMAC_SHA256_CTX *, const void *, size_t);
|
||||
void HMAC__SHA256_Final(unsigned char [32], HMAC_SHA256_CTX *);
|
||||
|
||||
/**
|
||||
* PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
|
||||
* Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
|
||||
* write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
|
||||
*/
|
||||
void PBKDF2_SHA256(const uint8_t *, size_t, const uint8_t *, size_t,
|
||||
uint64_t, uint8_t *, size_t);
|
||||
|
||||
#endif /* !_SHA256_H_ */
|
|
@ -734,6 +734,7 @@ vty_end_config (struct vty *vty)
|
|||
case ZEBRA_NODE:
|
||||
case RIP_NODE:
|
||||
case RIPNG_NODE:
|
||||
case EIGRP_NODE:
|
||||
case BGP_NODE:
|
||||
case BGP_VPNV4_NODE:
|
||||
case BGP_VPNV6_NODE:
|
||||
|
@ -1161,6 +1162,7 @@ vty_stop_input (struct vty *vty)
|
|||
case ZEBRA_NODE:
|
||||
case RIP_NODE:
|
||||
case RIPNG_NODE:
|
||||
case EIGRP_NODE:
|
||||
case BGP_NODE:
|
||||
case RMAP_NODE:
|
||||
case OSPF_NODE:
|
||||
|
|
44
pkgsrc/eigrpd.sh.in
Normal file
44
pkgsrc/eigrpd.sh.in
Normal file
|
@ -0,0 +1,44 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# eigrpd is part of the quagga routing beast
|
||||
#
|
||||
# PROVIDE: eigrpd
|
||||
# REQUIRE: zebra
|
||||
##
|
||||
|
||||
PATH=/sbin:/bin:/usr/sbin:/usr/bin:@prefix@/sbin:@prefix@/bin
|
||||
export PATH
|
||||
|
||||
if [ -f /etc/rc.subr ]
|
||||
then
|
||||
. /etc/rc.subr
|
||||
fi
|
||||
|
||||
name="eigrpd"
|
||||
rcvar=$name
|
||||
required_files="@sysconfdir@/${name}.conf"
|
||||
command="@prefix@/sbin/${name}"
|
||||
command_args="-d"
|
||||
|
||||
start_precmd="zebra_precmd"
|
||||
socket_dir=@localstatedir@
|
||||
pidfile="${socket_dir}/${name}.pid"
|
||||
|
||||
zebra_precmd()
|
||||
{
|
||||
rc_flags="$(
|
||||
set -- $rc_flags
|
||||
while [ $# -ne 0 ]; do
|
||||
if [ X"$1" = X-P -o X"$1" = X-A ]; then
|
||||
break
|
||||
fi
|
||||
shift
|
||||
done
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "-P 0"
|
||||
fi
|
||||
) $rc_flags"
|
||||
}
|
||||
|
||||
load_rc_config $name
|
||||
run_rc_command "$1"
|
|
@ -71,6 +71,12 @@ if NHRPD
|
|||
vtysh_scan += $(top_srcdir)/nhrpd/nhrp_vty.c
|
||||
endif
|
||||
|
||||
if EIGRPD
|
||||
vtysh_scan += $(top_srcdir)/eigrpd/eigrp_dump.c
|
||||
vtysh_scan += $(top_srcdir)/eigrpd/eigrp_routemap.c
|
||||
vtysh_scan += $(top_srcdir)/eigrpd/eigrp_vty.c
|
||||
endif
|
||||
|
||||
vtysh_cmd_FILES = $(vtysh_scan) \
|
||||
$(top_srcdir)/lib/keychain.c $(top_srcdir)/lib/routemap.c \
|
||||
$(top_srcdir)/lib/filter.c $(top_srcdir)/lib/plist.c \
|
||||
|
|
|
@ -52,6 +52,7 @@ $ignore{'"router bgp " "(1-4294967295)"'} = "ignore";
|
|||
$ignore{'"router bgp " "(1-4294967295)" " <view|vrf> WORD"'} = "ignore";
|
||||
$ignore{'"router bgp [(1-4294967295) [<view|vrf> WORD]]"'} = "ignore";
|
||||
$ignore{'"router isis WORD"'} = "ignore";
|
||||
$ignore('"router eigrp (1-65535)"'} = "ignore";
|
||||
$ignore{'"router zebra"'} = "ignore";
|
||||
$ignore{'"address-family ipv4"'} = "ignore";
|
||||
$ignore{'"address-family ipv4 [<unicast|multicast|vpn|encap>]"'} = "ignore";
|
||||
|
|
|
@ -75,6 +75,7 @@ struct vtysh_client vtysh_client[] =
|
|||
{ .fd = -1, .name = "isisd", .flag = VTYSH_ISISD, .next = NULL},
|
||||
{ .fd = -1, .name = "pimd", .flag = VTYSH_PIMD, .next = NULL},
|
||||
{ .fd = -1, .name = "nhrpd", .flag = VTYSH_NHRPD, .next = NULL},
|
||||
{ .fd = -1, .name = "eigrpd", .flag = VTYSH_EIGRPD, .next = NULL},
|
||||
{ .fd = -1, .name = "watchfrr", .flag = VTYSH_WATCHFRR, .next = NULL},
|
||||
};
|
||||
|
||||
|
@ -994,6 +995,12 @@ static struct cmd_node ospf_node =
|
|||
"%s(config-router)# "
|
||||
};
|
||||
|
||||
static struct cmd_node eigrp_node =
|
||||
{
|
||||
EIGRP_NODE,
|
||||
"%s(config-router)# "
|
||||
};
|
||||
|
||||
static struct cmd_node ripng_node =
|
||||
{
|
||||
RIPNG_NODE,
|
||||
|
@ -1332,6 +1339,18 @@ DEFUNSH (VTYSH_OSPFD,
|
|||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUNSH (VTYSH_EIGRPD,
|
||||
router_eigrp,
|
||||
router_eigrp_cmd,
|
||||
"router eigrp (1-65535)",
|
||||
"Enable a routing process\n"
|
||||
"Start EIGRP configuration\n"
|
||||
"AS number to use\n")
|
||||
{
|
||||
vty->node = EIGRP_NODE;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUNSH (VTYSH_OSPF6D,
|
||||
router_ospf6,
|
||||
router_ospf6_cmd,
|
||||
|
@ -1515,6 +1534,7 @@ vtysh_exit (struct vty *vty)
|
|||
case RIPNG_NODE:
|
||||
case OSPF_NODE:
|
||||
case OSPF6_NODE:
|
||||
case EIGRP_NODE:
|
||||
case LDP_NODE:
|
||||
case LDP_L2VPN_NODE:
|
||||
case ISIS_NODE:
|
||||
|
@ -1716,6 +1736,24 @@ DEFUNSH (VTYSH_OSPFD,
|
|||
return vtysh_exit_ospfd (self, vty, argc, argv);
|
||||
}
|
||||
|
||||
DEFUNSH (VTYSH_EIGRPD,
|
||||
vtysh_exit_eigrpd,
|
||||
vtysh_exit_eigrpd_cmd,
|
||||
"exit",
|
||||
"Exit current mode and down to previous mode\n")
|
||||
{
|
||||
return vtysh_exit (vty);
|
||||
}
|
||||
|
||||
DEFUNSH (VTYSH_EIGRPD,
|
||||
vtysh_quit_eigrpd,
|
||||
vtysh_quit_eigrpd_cmd,
|
||||
"quit",
|
||||
"Exit current mode and down to previous mode\n")
|
||||
{
|
||||
return vtysh_exit (vty);
|
||||
}
|
||||
|
||||
DEFUNSH (VTYSH_OSPF6D,
|
||||
vtysh_exit_ospf6d,
|
||||
vtysh_exit_ospf6d_cmd,
|
||||
|
@ -1799,7 +1837,7 @@ DEFUNSH (VTYSH_INTERFACE,
|
|||
}
|
||||
|
||||
/* TODO Implement "no interface command in isisd. */
|
||||
DEFSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_LDPD,
|
||||
DEFSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_EIGRPD|VTYSH_LDPD,
|
||||
vtysh_no_interface_cmd,
|
||||
"no interface IFNAME",
|
||||
NO_STR
|
||||
|
@ -1883,13 +1921,13 @@ DEFUNSH (VTYSH_VRF,
|
|||
|
||||
/* TODO Implement interface description commands in ripngd, ospf6d
|
||||
* and isisd. */
|
||||
DEFSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_OSPFD|VTYSH_LDPD,
|
||||
DEFSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_OSPFD|VTYSH_EIGRPD|VTYSH_LDPD,
|
||||
vtysh_interface_desc_cmd,
|
||||
"description LINE...",
|
||||
"Interface specific description\n"
|
||||
"Characters describing this interface\n")
|
||||
|
||||
DEFSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_OSPFD,
|
||||
DEFSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_OSPFD|VTYSH_EIGRPD,
|
||||
vtysh_no_interface_desc_cmd,
|
||||
"no description",
|
||||
NO_STR
|
||||
|
@ -3118,6 +3156,7 @@ vtysh_init_vty (void)
|
|||
install_node (&bgp_vnc_nve_group_node, NULL);
|
||||
install_node (&bgp_vnc_l2_group_node, NULL);
|
||||
install_node (&ospf_node, NULL);
|
||||
install_node (&eigrp_node, NULL);
|
||||
install_node (&ripng_node, NULL);
|
||||
install_node (&ospf6_node, NULL);
|
||||
install_node (&ldp_node, NULL);
|
||||
|
@ -3158,6 +3197,7 @@ vtysh_init_vty (void)
|
|||
vtysh_install_default (BGP_VNC_L2_GROUP_NODE);
|
||||
#endif
|
||||
vtysh_install_default (OSPF_NODE);
|
||||
vtysh_install_default (EIGRP_NODE);
|
||||
vtysh_install_default (RIPNG_NODE);
|
||||
vtysh_install_default (OSPF6_NODE);
|
||||
vtysh_install_default (LDP_NODE);
|
||||
|
@ -3187,6 +3227,8 @@ vtysh_init_vty (void)
|
|||
install_element (RIPNG_NODE, &vtysh_quit_ripngd_cmd);
|
||||
install_element (OSPF_NODE, &vtysh_exit_ospfd_cmd);
|
||||
install_element (OSPF_NODE, &vtysh_quit_ospfd_cmd);
|
||||
install_element (EIGRP_NODE, &vtysh_exit_eigrpd_cmd);
|
||||
install_element (EIGRP_NODE, &vtysh_quit_eigrpd_cmd);
|
||||
install_element (OSPF6_NODE, &vtysh_exit_ospf6d_cmd);
|
||||
install_element (OSPF6_NODE, &vtysh_quit_ospf6d_cmd);
|
||||
#if defined (HAVE_LDPD)
|
||||
|
@ -3251,6 +3293,7 @@ vtysh_init_vty (void)
|
|||
install_element (RIP_NODE, &vtysh_end_all_cmd);
|
||||
install_element (RIPNG_NODE, &vtysh_end_all_cmd);
|
||||
install_element (OSPF_NODE, &vtysh_end_all_cmd);
|
||||
install_element (EIGRP_NODE, &vtysh_end_all_cmd);
|
||||
install_element (OSPF6_NODE, &vtysh_end_all_cmd);
|
||||
install_element (LDP_NODE, &vtysh_end_all_cmd);
|
||||
install_element (LDP_IPV4_NODE, &vtysh_end_all_cmd);
|
||||
|
@ -3298,6 +3341,7 @@ vtysh_init_vty (void)
|
|||
install_element (VRF_NODE, &vtysh_exit_vrf_cmd);
|
||||
install_element (VRF_NODE, &vtysh_quit_vrf_cmd);
|
||||
|
||||
install_element (CONFIG_NODE, &router_eigrp_cmd);
|
||||
install_element (CONFIG_NODE, &router_rip_cmd);
|
||||
install_element (CONFIG_NODE, &router_ripng_cmd);
|
||||
install_element (CONFIG_NODE, &router_ospf_cmd);
|
||||
|
|
|
@ -36,6 +36,7 @@ DECLARE_MGROUP(MVTYSH)
|
|||
#define VTYSH_LDPD 0x200
|
||||
#define VTYSH_WATCHFRR 0x400
|
||||
#define VTYSH_NHRPD 0x800
|
||||
#define VTYSH_EIGRPD 0x1000
|
||||
|
||||
/* commands in REALLYALL are crucial to correct vtysh operation */
|
||||
#define VTYSH_REALLYALL ~0U
|
||||
|
|
Loading…
Reference in a new issue