diff options
| author | Donald Sharp <sharpd@cumulusnetworks.com> | 2017-03-08 23:07:46 -0500 | 
|---|---|---|
| committer | Donald Sharp <sharpd@cumulusnetworks.com> | 2017-03-08 23:07:46 -0500 | 
| commit | 7f57883ee6322b728e44f447da68ebc96b0664e9 (patch) | |
| tree | 8b1392c96f88324176f253d6fa7c64edc8d1a1a2 /eigrpd/eigrp_reply.c | |
| parent | baf9c436222ef0901caf2ba694f87a2746ddcd02 (diff) | |
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>
Diffstat (limited to 'eigrpd/eigrp_reply.c')
| -rw-r--r-- | eigrpd/eigrp_reply.c | 249 | 
1 files changed, 249 insertions, 0 deletions
diff --git a/eigrpd/eigrp_reply.c b/eigrpd/eigrp_reply.c new file mode 100644 index 0000000000..ff40e2e5c5 --- /dev/null +++ b/eigrpd/eigrp_reply.c @@ -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); +} +  | 
