Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
int eigrp_fsm_event_keep_state(struct eigrp_fsm_action_message *msg) {

	struct eigrp_prefix_entry *prefix = msg->prefix;
	struct eigrp_neighbor_entry *entry = msg->entry;

	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, msg->entry);
			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;
}
Ejemplo n.º 3
0
/* ARGSUSED */
void eigrp_route_map_update(const char *notused)
{
	int i;
	struct eigrp *e;
	e = eigrp_lookup();

	if (e) {
		for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
			if (e->route_map[i].name)
				e->route_map[i].map = route_map_lookup_by_name(
					e->route_map[i].name);
		}
	}
}
Ejemplo n.º 4
0
void eigrp_routemap_update_redistribute(void)
{
	int i;
	struct eigrp *e;

	e = eigrp_lookup();

	if (e) {
		for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
			if (e->route_map[i].name)
				e->route_map[i].map = route_map_lookup_by_name(
					e->route_map[i].name);
		}
	}
}
Ejemplo n.º 5
0
/* 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;
}
Ejemplo n.º 6
0
void eigrp_if_rmap_update(struct if_rmap *if_rmap)
{
	struct interface *ifp;
	struct eigrp_interface *ei, *ei2;
	struct listnode *node, *nnode;
	struct route_map *rmap;
	struct eigrp *e;

	ifp = if_lookup_by_name(if_rmap->ifname);
	if (ifp == NULL)
		return;

	ei = NULL;
	e = eigrp_lookup();
	for (ALL_LIST_ELEMENTS(e->eiflist, node, nnode, ei2)) {
		if (strcmp(ei2->ifp->name, ifp->name) == 0) {
			ei = ei2;
			break;
		}
	}

	if (if_rmap->routemap[IF_RMAP_IN]) {
		rmap = route_map_lookup_by_name(if_rmap->routemap[IF_RMAP_IN]);
		if (rmap)
			ei->routemap[IF_RMAP_IN] = rmap;
		else
			ei->routemap[IF_RMAP_IN] = NULL;
	} else
		ei->routemap[EIGRP_FILTER_IN] = NULL;

	if (if_rmap->routemap[IF_RMAP_OUT]) {
		rmap = route_map_lookup_by_name(if_rmap->routemap[IF_RMAP_OUT]);
		if (rmap)
			ei->routemap[IF_RMAP_OUT] = rmap;
		else
			ei->routemap[IF_RMAP_OUT] = NULL;
	} else
		ei->routemap[EIGRP_FILTER_OUT] = NULL;
}
Ejemplo n.º 7
0
/**
 * @fn eigrp_update_send_GR_part
 *
 * @param[in]		nbr		contains neighbor who would receive Graceful restart
 *
 * @return void
 *
 * @par
 * Function used for sending Graceful restart Update packet
 * and if there are multiple chunks, send only one of them.
 * It is called from thread. Do not call it directly.
 *
 * Uses nbr_gr_packet_type from neighbor.
 */
static void
eigrp_update_send_GR_part(struct eigrp_neighbor *nbr)
{
	struct eigrp_packet *ep;
	u_int16_t length = EIGRP_HEADER_LEN;
	struct listnode *node, *nnode;
	struct eigrp_prefix_entry *pe;
	struct prefix_ipv4 *dest_addr;
	struct eigrp *e;
	struct access_list *alist, *alist_i;
	struct prefix_list *plist, *plist_i;
	struct list *prefixes;
	u_int32_t flags;
	unsigned int send_prefixes;
	struct TLV_IPv4_Internal_type *tlv_max;

	/* get prefixes to send to neighbor */
	prefixes = nbr->nbr_gr_prefixes_send;

	send_prefixes = 0;
	length = EIGRP_HEADER_LEN;

	/* if there already were last packet chunk, we won't continue */
	if(nbr->nbr_gr_packet_type == EIGRP_PACKET_PART_LAST)
		return;

	/* if this is first packet chunk, we need to decide,
	 * if there will be one or more chunks */
	if(nbr->nbr_gr_packet_type == EIGRP_PACKET_PART_FIRST)
	{
		if(prefixes->count <= EIGRP_TLV_MAX_IPv4)
		{
			/* there will be only one chunk */
			flags = EIGRP_INIT_FLAG + EIGRP_RS_FLAG + EIGRP_EOT_FLAG;
			nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_LAST;
		}
		else
		{
			/* there will be more chunks */
			flags = EIGRP_INIT_FLAG + EIGRP_RS_FLAG;
			nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_NA;
		}
	}
	else
	{
		/* this is not first chunk, and we need to decide,
		 * if there will be more chunks */
		if(prefixes->count <= EIGRP_TLV_MAX_IPv4)
		{
			/* this is last chunk */
			flags = EIGRP_EOT_FLAG;
			nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_LAST;
		}
		else
		{
			/* there will be more chunks */
			flags = 0;
			nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_NA;
		}
	}

	ep = eigrp_packet_new(nbr->ei->ifp->mtu);

	/* Prepare EIGRP Graceful restart UPDATE header */
	eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei, ep->s,
			flags,
			nbr->ei->eigrp->sequence_number,
			nbr->recv_sequence_number);

	// 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);
	}

	for (ALL_LIST_ELEMENTS(nbr->ei->eigrp->topology_table, node, nnode, pe))
	{

		/*
		* Filtering
		*/
		dest_addr = pe->destination_ipv4;
		/* get list from eigrp process */
		e = eigrp_lookup();
		/* 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];


		/* 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))
		{
			/* do not send filtered route */
			zlog_info("Filtered prefix %s won't be sent out.",
					inet_ntoa(dest_addr->prefix));
		}
		else
		{
			/* sending route which wasn't filtered */
			length += eigrp_add_internalTLV_to_stream(ep->s, pe);
			send_prefixes++;
		}



		alist = e->list[EIGRP_FILTER_IN];
		plist = e->prefix[EIGRP_FILTER_IN];
		alist_i = nbr->ei->list[EIGRP_FILTER_IN];
		plist_i = nbr->ei->prefix[EIGRP_FILTER_IN];


		/* 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))
		{
			/* do not send filtered route */
			zlog_info("Filtered prefix %s will be removed.",
					inet_ntoa(dest_addr->prefix));

			tlv_max = eigrp_IPv4_InternalTLV_new();
			tlv_max->type = EIGRP_TLV_IPv4_INT;
			tlv_max->length = 28U;
			tlv_max->metric = pe->reported_metric;
			/* set delay to MAX */
			tlv_max->metric.delay = EIGRP_MAX_METRIC;
			tlv_max->destination = pe->destination_ipv4->prefix;
			tlv_max->prefix_length = pe->destination_ipv4->prefixlen;


			/* prepare message for FSM */
			struct eigrp_fsm_action_message *fsm_msg;
			fsm_msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
			  sizeof(struct eigrp_fsm_action_message));

			struct eigrp_neighbor_entry *entry =
			  eigrp_prefix_entry_lookup(pe->entries, nbr);

			fsm_msg->packet_type = EIGRP_OPC_UPDATE;
			fsm_msg->eigrp = e;
			fsm_msg->data_type = EIGRP_TLV_IPv4_INT;
			fsm_msg->adv_router = nbr;
			fsm_msg->data.ipv4_int_type = tlv_max;
			fsm_msg->entry = entry;
			fsm_msg->prefix = pe;

			/* send message to FSM */
			int event = eigrp_get_fsm_event(fsm_msg);
			eigrp_fsm_event(fsm_msg, event);

			/* free memory used by TLV */
			eigrp_IPv4_InternalTLV_free (tlv_max);
		}
		/*
		* End of filtering
		*/
		
		/* NULL the pointer */
		dest_addr = NULL;

		/* delete processed prefix from list */
		listnode_delete(prefixes, pe);

		/* if there are enough prefixes, send packet */
		if(send_prefixes >= EIGRP_TLV_MAX_IPv4)
			break;
	}

	/* compute Auth digest */
	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 (IS_DEBUG_EIGRP_PACKET(0, RECV))
		zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]",
			   ep->length, ep->sequence_number, inet_ntoa(ep->dst));


	/*Put packet to retransmission queue*/
	eigrp_fifo_push_head(nbr->retrans_queue, ep);

	if (nbr->retrans_queue->count == 1)
	{
		eigrp_send_packet_reliably(nbr);
	}
}
Ejemplo n.º 8
0
void
eigrp_update_send (struct eigrp_interface *ei)
{
  struct eigrp_packet *ep;
  struct listnode *node, *nnode, *nnode2;
  struct eigrp_neighbor *nbr;
  struct eigrp_prefix_entry *pe;
  u_char has_tlv;
  struct access_list *alist;
  struct prefix_list *plist;
  struct access_list *alist_i;
  struct prefix_list *plist_i;
  struct eigrp *e;
  struct prefix_ipv4 *dest_addr;

  u_int16_t length = EIGRP_HEADER_LEN;

  ep = eigrp_packet_new(ei->ifp->mtu);

  /* Prepare EIGRP INIT UPDATE header */
  eigrp_packet_header_init(EIGRP_OPC_UPDATE, 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_UPDATE)
        {

    	  /* Get destination address from prefix */
    	  dest_addr = pe->destination_ipv4;

    	  /*
		   * 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_OUT];
		  plist = e->prefix[EIGRP_FILTER_OUT];
		  alist_i = ei->list[EIGRP_FILTER_OUT];
		  plist_i = ei->prefix[EIGRP_FILTER_OUT];

		  /* 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("PROC OUT: Skipping");
			  //pe->reported_metric.delay = EIGRP_MAX_METRIC;
			  zlog_info("PROC OUT Prefix: %s", inet_ntoa(dest_addr->prefix));
			  continue;
		  } else {
			  zlog_info("PROC OUT: NENastavujem metriku ");
			  length += eigrp_add_internalTLV_to_stream(ep->s, pe);
			  has_tlv = 1;
		  }
		  /*
		   * End of filtering
		   */

		  /* NULL the pointer */
		  dest_addr = NULL;

        }
    }

  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;

  if (IS_DEBUG_EIGRP_PACKET(0, RECV))
    zlog_debug("Enqueuing Update length[%u] Seq [%u]",
               length, ep->sequence_number);

  for (ALL_LIST_ELEMENTS(ei->nbrs, node, nnode, 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);
            }
        }
    }
}
Ejemplo n.º 9
0
void
eigrp_update_send_EOT (struct eigrp_neighbor *nbr)
{
  struct eigrp_packet *ep;
//  struct eigrp_packet *ep_multicast;
  u_int16_t length = EIGRP_HEADER_LEN;
  struct eigrp_neighbor_entry *te;
  struct eigrp_prefix_entry *pe;
  struct listnode *node, *node2, *nnode, *nnode2;
  struct access_list *alist;
  struct prefix_list *plist;
  struct access_list *alist_i;
  struct prefix_list *plist_i;
  struct eigrp *e;
  struct prefix_ipv4 *dest_addr;

  ep = eigrp_packet_new(nbr->ei->ifp->mtu);

  /* Prepare EIGRP EOT UPDATE header */
  eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei, ep->s, EIGRP_EOT_FLAG,
                           nbr->ei->eigrp->sequence_number,
                           nbr->recv_sequence_number);

  // 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);
    }

  for (ALL_LIST_ELEMENTS(nbr->ei->eigrp->topology_table, node, nnode, pe))
    {
      for (ALL_LIST_ELEMENTS(pe->entries, node2, nnode2, te))
        {
          if ((te->ei == nbr->ei)
              && (te->prefix->nt == EIGRP_TOPOLOGY_TYPE_REMOTE))
            continue;


          /* Get destination address from prefix */
		  dest_addr = pe->destination_ipv4;

		  /*
		   * 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_OUT];
		  plist = e->prefix[EIGRP_FILTER_OUT];
		  alist_i = nbr->ei->list[EIGRP_FILTER_OUT];
		  plist_i = nbr->ei->prefix[EIGRP_FILTER_OUT];

		  /* 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("PROC OUT EOT: Skipping");
			  //pe->reported_metric.delay = EIGRP_MAX_METRIC;
			  zlog_info("PROC OUT EOT Prefix: %s", inet_ntoa(dest_addr->prefix));
			  continue;
		  } else {
			  zlog_info("PROC OUT EOT: NENastavujem metriku ");
			  length += eigrp_add_internalTLV_to_stream(ep->s, pe);
		  }
		  /*
		   * End of filtering
		   */

		  /* NULL the pointer */
		  dest_addr = NULL;

        }
    }

  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 (IS_DEBUG_EIGRP_PACKET(0, RECV))
    zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]",
               ep->length, ep->sequence_number, inet_ntoa(ep->dst));

  /*Put packet to retransmission queue*/
  eigrp_fifo_push_head(nbr->retrans_queue, ep);

  if (nbr->retrans_queue->count == 1)
    {
      eigrp_send_packet_reliably(nbr);
    }

}
Ejemplo n.º 10
0
/*
 * EIGRP UPDATE read function
 */
void
eigrp_update_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 eigrp_prefix_entry *pe;
  struct eigrp_neighbor_entry *ne;
  u_int32_t flags;
  u_int16_t type;
  uint16_t  length;
  u_char same;
  struct access_list *alist;
  struct prefix_list *plist;
  struct eigrp *e;
  u_char graceful_restart;
  u_char graceful_restart_final;
  struct list *nbr_prefixes;
  int ret;

  /* increment statistics. */
  ei->update_in++;

  /* get neighbor struct */
  nbr = eigrp_nbr_get(ei, eigrph, iph);

  /* neighbor must be valid, eigrp_nbr_get creates if none existed */
  assert(nbr);

  flags = ntohl(eigrph->flags);

  if (flags & EIGRP_CR_FLAG)
    {
      return;
    }

  same = 0;
  graceful_restart = 0;
  graceful_restart_final = 0;
  if((nbr->recv_sequence_number) == (ntohl(eigrph->sequence)))
      same = 1;

  nbr->recv_sequence_number = ntohl(eigrph->sequence);
  if (IS_DEBUG_EIGRP_PACKET(0, RECV))
    zlog_debug("Processing Update size[%u] int(%s) nbr(%s) seq [%u] flags [%0x]",
               size, ifindex2ifname(nbr->ei->ifp->ifindex),
               inet_ntoa(nbr->src),
               nbr->recv_sequence_number, flags);


    if((flags == (EIGRP_INIT_FLAG+EIGRP_RS_FLAG+EIGRP_EOT_FLAG)) && (!same))
    {
    	/* Graceful restart Update received with all routes */

		zlog_info("Neighbor %s (%s) is resync: peer graceful-restart",
				  inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex));

		/* get all prefixes from neighbor from topology table */
    	nbr_prefixes = eigrp_neighbor_prefixes_lookup(eigrp, nbr);
    	graceful_restart = 1;
    	graceful_restart_final = 1;
    }
    else if((flags == (EIGRP_INIT_FLAG+EIGRP_RS_FLAG)) && (!same))
    {
    	/* Graceful restart Update received, routes also in next packet */

		zlog_info("Neighbor %s (%s) is resync: peer graceful-restart",
				  inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex));

		/* get all prefixes from neighbor from topology table */
    	nbr_prefixes = eigrp_neighbor_prefixes_lookup(eigrp, nbr);
    	/* save prefixes to neighbor for later use */
    	nbr->nbr_gr_prefixes = nbr_prefixes;
    	graceful_restart = 1;
    	graceful_restart_final = 0;
    }
    else if((flags == (EIGRP_EOT_FLAG)) && (!same))
	{
		/* If there was INIT+RS Update packet before,
		 *  consider this as GR EOT */

		if(nbr->nbr_gr_prefixes != NULL)
		{
			/* this is final packet of GR */
			nbr_prefixes = nbr->nbr_gr_prefixes;
			nbr->nbr_gr_prefixes = NULL;

			graceful_restart = 1;
			graceful_restart_final = 1;
		}

	}
    else if((flags == (0)) && (!same))
	{
		/* If there was INIT+RS Update packet before,
		 *  consider this as GR not final packet */

		if(nbr->nbr_gr_prefixes != NULL)
		{
			/* this is GR not final route packet */
			nbr_prefixes = nbr->nbr_gr_prefixes;

			graceful_restart = 1;
			graceful_restart_final = 0;
		}

	}
    else if((flags & EIGRP_INIT_FLAG) && (!same))
    {   /* When in pending state, send INIT update only if it wasn't
        already sent before (only if init_sequence is 0) */
        if((nbr->state == EIGRP_NEIGHBOR_PENDING) && (nbr->init_sequence_number == 0))
          eigrp_update_send_init(nbr);

        if (nbr->state == EIGRP_NEIGHBOR_UP)
          {
            eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_DOWN);
            eigrp_topology_neighbor_down(nbr->ei->eigrp,nbr);
            nbr->recv_sequence_number = ntohl(eigrph->sequence);
            zlog_info("Neighbor %s (%s) is down: peer restarted",
                      inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex));
            eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_PENDING);
            zlog_info("Neighbor %s (%s) is pending: new adjacency",
                      inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex));
            eigrp_update_send_init(nbr);
          }
    }

  /*If there is topology information*/
  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);

          /*searching if destination exists */
          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 exists it comes to DUAL*/
          if (dest != NULL)
            {
        	  /* remove received prefix from neighbor prefix list if in GR */
        	  if(graceful_restart)
        		  remove_received_prefix_gr(nbr_prefixes, 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);

              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 = dest;
              int event = eigrp_get_fsm_event(msg);
              eigrp_fsm_event(msg, event);
            }
          else
            {
              /*Here comes topology information save*/
              pe = eigrp_prefix_entry_new();
              pe->serno = eigrp->serno;
              pe->destination_ipv4 = dest_addr;
              pe->af = AF_INET;
              pe->state = EIGRP_FSM_STATE_PASSIVE;
              pe->nt = EIGRP_TOPOLOGY_TYPE_REMOTE;

              ne = eigrp_neighbor_entry_new();
              ne->ei = ei;
              ne->adv_router = nbr;
              ne->reported_metric = tlv->metric;
              ne->reported_distance = eigrp_calculate_metrics(eigrp,
                  &tlv->metric);

              //TODO: Work in progress
              /*
               * Filtering
               */
        	  e = eigrp_lookup();
        	  /* get access-list from eigrp process */
        	  alist = e->list[EIGRP_FILTER_IN];
			  zlog_info("PROC IN Prefix: %s", inet_ntoa(dest_addr->prefix));
			  if (alist) {
				  zlog_info ("ALIST PROC IN: %s", alist->name);
			  } else {
				  zlog_info("ALIST PROC IN je prazdny");
			  }

			  /* Check if access-list fits */
			  if (alist && access_list_apply (alist,
						 (struct prefix *) dest_addr) == FILTER_DENY)
			  {
				  /* If yes, set reported metric to Max */
				  zlog_info("PROC alist IN: Skipping");
				  //ne->reported_metric.delay = EIGRP_MAX_METRIC;
				  zlog_info("PROC IN Prefix: %s", inet_ntoa(dest_addr->prefix));
				  eigrp_IPv4_InternalTLV_free (tlv);
				  continue;
			  } else {
				  zlog_info("PROC alist IN: NENastavujem metriku ");
			  }

			  plist = e->prefix[EIGRP_FILTER_IN];

			  if (plist) {
				  zlog_info ("PLIST PROC IN: %s", plist->name);
			  } else {
				  zlog_info("PLIST PROC IN je prazdny");
			  }

			  /* Check if prefix-list fits */
			  if (plist && prefix_list_apply (plist,
						 (struct prefix *) dest_addr) == FILTER_DENY)
			  {
				  /* If yes, set reported metric to Max */
				  zlog_info("PLIST PROC IN: Skipping");
				  //ne->reported_metric.delay = EIGRP_MAX_METRIC;
				  zlog_info("PLIST PROC IN Prefix: %s", inet_ntoa(dest_addr->prefix));
				  eigrp_IPv4_InternalTLV_free (tlv);
				  continue;
			  } else {
				  zlog_info("PLIST PROC IN: NENastavujem metriku ");
			  }

			  //Check route-map

			  /*if (e->routemap[EIGRP_FILTER_IN])
			  {
			  	 ret = route_map_apply (e->routemap[EIGRP_FILTER_IN],
			  				   (struct prefix *)dest_addr, RMAP_EIGRP, NULL);

			  	 if (ret == RMAP_DENYMATCH)
			  	 {
			  	    zlog_debug ("%s is filtered by route-map",inet_ntoa (dest_addr->prefix));
			  	    continue;
			  	 }
			  }*/

			  /*Get access-list from current interface */
			  zlog_info("Checking access_list on interface: %s",ei->ifp->name);
			  alist = ei->list[EIGRP_FILTER_IN];
			  if (alist) {
			  	  zlog_info ("ALIST INT IN: %s", alist->name);
			  } else {
			  	  zlog_info("ALIST INT IN je prazdny");
			  	}

			  /* Check if access-list fits */
			  if (alist && access_list_apply (alist, (struct prefix *) dest_addr) == FILTER_DENY)
			  {
				  /* If yes, set reported metric to Max */
			  	  zlog_info("INT alist IN: Skipping");
			  	  //ne->reported_metric.delay = EIGRP_MAX_METRIC;
			  	  zlog_info("INT IN Prefix: %s", inet_ntoa(dest_addr->prefix));
			  	  eigrp_IPv4_InternalTLV_free (tlv);
			  	  continue;
			  	} else {
			  	  zlog_info("INT IN: NENastavujem metriku ");
			  }

			  plist = ei->prefix[EIGRP_FILTER_IN];

			  if (plist) {
				  zlog_info ("PLIST INT IN: %s", plist->name);
			  } else {
				  zlog_info("PLIST INT IN je prazdny");
			  }

			  /* Check if prefix-list fits */
			  if (plist && prefix_list_apply (plist,
						 (struct prefix *) dest_addr) == FILTER_DENY)
			  {
				  /* If yes, set reported metric to Max */
				  zlog_info("PLIST INT IN: Skipping");
				  //ne->reported_metric.delay = EIGRP_MAX_METRIC;
				  zlog_info("PLIST INT IN Prefix: %s", inet_ntoa(dest_addr->prefix));
				  eigrp_IPv4_InternalTLV_free (tlv);
				  continue;
			  } else {
				  zlog_info("PLIST INT IN: NENastavujem metriku ");
			  }

			  //Check route-map

			  /*if (ei->routemap[EIGRP_FILTER_IN])
			  {
				 ret = route_map_apply (ei->routemap[EIGRP_FILTER_IN],
							   (struct prefix *)dest_addr, RMAP_EIGRP, NULL);

				 if (ret == RMAP_DENYMATCH)
				 {
					zlog_debug ("%s is filtered by route-map",inet_ntoa (dest_addr->prefix));
					continue;
				 }
			  }*/
			  /*
			   * End of filtering
			   */

			  ne->distance = eigrp_calculate_total_metrics(eigrp, ne);

			  zlog_info("<DEBUG PROC IN Distance: %x", ne->distance);
			  zlog_info("<DEBUG PROC IN Delay: %x", ne->total_metric.delay);

              pe->fdistance = pe->distance = pe->rdistance =
                  ne->distance;
              ne->prefix = pe;
              ne->flags = EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG;

              eigrp_prefix_entry_add(eigrp->topology_table, pe);
              eigrp_neighbor_entry_add(pe, ne);
              pe->distance = pe->fdistance = pe->rdistance = ne->distance;
              pe->reported_metric = ne->total_metric;
              eigrp_topology_update_node_flags(pe);

              pe->req_action |= EIGRP_FSM_NEED_UPDATE;
              listnode_add(eigrp->topology_changes_internalIPV4, pe);
            }
          eigrp_IPv4_InternalTLV_free (tlv);
        }
    }

    /* ask about prefixes not present in GR update,
     * if this is final GR packet */
    if(graceful_restart_final)
    {
    	eigrp_update_receive_GR_ask(eigrp, nbr, nbr_prefixes);
    }

  /*
   * We don't need to send separate Ack for INIT Update. INIT will be acked in EOT Update.
   */
  if ((nbr->state == EIGRP_NEIGHBOR_UP) && !(flags == EIGRP_INIT_FLAG))
    {
      eigrp_hello_send_ack(nbr);
    }

  eigrp_query_send_all(eigrp);
  eigrp_update_send_all(eigrp, ei);
}
Ejemplo n.º 11
0
void eigrp_zebra_init(void)
{
	struct zclient_options opt = {.receive_notify = false};

	zclient = zclient_new_notify(master, &opt);

	zclient_init(zclient, ZEBRA_ROUTE_EIGRP, 0, &eigrpd_privs);
	zclient->zebra_connected = eigrp_zebra_connected;
	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_add = eigrp_zebra_read_route;
	zclient->redistribute_route_del = eigrp_zebra_read_route;
	zclient->route_notify_owner = eigrp_zebra_route_notify_owner;
}


/* Zebra route add and delete treatment. */
static int eigrp_zebra_read_route(int command, struct zclient *zclient,
				  zebra_size_t length, vrf_id_t vrf_id)
{
	struct zapi_route api;
	struct eigrp *eigrp;

	if (zapi_route_decode(zclient->ibuf, &api) < 0)
		return -1;

	if (IPV4_NET127(ntohl(api.prefix.u.prefix4.s_addr)))
		return 0;

	eigrp = eigrp_lookup();
	if (eigrp == NULL)
		return 0;

	if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) {

	} else /* if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL) */
	{
	}

	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;
	struct eigrp_interface *ei;

	ifp = zebra_interface_add_read(zclient->ibuf, vrf_id);

	if (!ifp->info)
		return 0;

	ei = ifp->info;

	ei->params.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;

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

	if (ifp->info)
		eigrp_if_free(ifp->info, INTERFACE_DOWN_BY_ZEBRA);

	if_set_index(ifp, 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;

	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;
	ei = ifp->info;
	if (!ei)
		return 0;

	/* 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;

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

	if (ifp->info)
		eigrp_if_up(ifp->info);

	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;

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

	if (ifp->info)
		eigrp_if_down(ifp->info);

	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(ifname_tmp, VRF_DEFAULT);
}