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:
Donald Sharp 2017-03-08 23:07:46 -05:00
parent baf9c43622
commit 7f57883ee6
60 changed files with 17222 additions and 8 deletions

View file

@ -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 \

View file

@ -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
View 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

File diff suppressed because it is too large Load diff

45
eigrpd/Makefile.am Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load diff

143
eigrpd/eigrp_packet.h Normal file
View 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
View file

0
eigrpd/eigrp_pkt_tlv2.c Normal file
View file

226
eigrpd/eigrp_query.c Normal file
View 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
View 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

File diff suppressed because it is too large Load diff

18
eigrpd/eigrp_routemap.h Normal file
View 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
View 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
View 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

File diff suppressed because it is too large Load diff

36
eigrpd/eigrp_snmp.h Normal file
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load diff

1584
eigrpd/eigrp_vty.c Normal file

File diff suppressed because it is too large Load diff

42
eigrpd/eigrp_vty.h Normal file
View 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
View 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
View 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
View 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
View 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
View 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 */

View file

@ -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 = \

View file

@ -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:

View file

@ -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"

View file

@ -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);

View file

@ -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"))

View file

@ -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
View 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
View 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_ */

View file

@ -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
View 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"

View file

@ -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 \

View file

@ -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";

View file

@ -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);

View file

@ -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