Ejemplo n.º 1
0
static void 
bgp_capability_mp_data (struct stream *s, struct capability_mp_data *mpc)
{
  mpc->afi = stream_getw (s);
  mpc->reserved = stream_getc (s);
  mpc->safi = stream_getc (s);
}
Ejemplo n.º 2
0
static int
attr_parse (struct stream *s, u_int16_t len)
{
  u_int flag;
  u_int type;
  u_int16_t length;
  u_int16_t lim;

  lim = s->getp + len;

  printf ("attr_parse s->getp %zd, len %d, lim %d\n", s->getp, len, lim);

  while (s->getp < lim)
    {
      flag = stream_getc (s);
      type = stream_getc (s);

      if (flag & BGP_ATTR_FLAG_EXTLEN)
	length = stream_getw (s);
      else
	length = stream_getc (s);

      printf ("FLAG: %d\n", flag);
      printf ("TYPE: %d\n", type);
      printf ("Len: %d\n", length);

      switch (type)
	{
	case BGP_ATTR_ORIGIN:
	  {
	    u_char origin;
	    origin = stream_getc (s);
	    printf ("ORIGIN: %d\n", origin);
	  }
	  break;
	case BGP_ATTR_AS_PATH:
	  {
	    struct aspath *aspath;

	    aspath = aspath_parse (s, length, 1);
	    printf ("ASPATH: %s\n", aspath->str);
	    aspath_free(aspath);
	  }
	  break;
	case BGP_ATTR_NEXT_HOP:
	  {
	    struct in_addr nexthop;
	    nexthop.s_addr = stream_get_ipv4 (s);
	    printf ("NEXTHOP: %s\n", inet_ntoa (nexthop));
	  }
	  break;
	default:
	  stream_getw_from (s, length);
	  break;
	}
    }

  return 0;
}
Ejemplo n.º 3
0
/*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;

	uint16_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) {
			struct prefix dest_addr;

			stream_set_getp(s, s->getp - sizeof(uint16_t));

			tlv = eigrp_read_ipv4_tlv(s);

			dest_addr.family = AFI_IP;
			dest_addr.u.prefix4 = 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;
				struct eigrp_nexthop_entry *entry =
					eigrp_prefix_entry_lookup(dest->entries,
								  nbr);
				msg.packet_type = EIGRP_OPC_SIAQUERY;
				msg.eigrp = eigrp;
				msg.data_type = EIGRP_INT;
				msg.adv_router = nbr;
				msg.metrics = tlv->metric;
				msg.entry = entry;
				msg.prefix = dest;
				eigrp_fsm_event(&msg);
			}
			eigrp_IPv4_InternalTLV_free(tlv);
		}
	}
	eigrp_hello_send_ack(nbr);
}
Ejemplo n.º 4
0
unsigned int
are_checksums_same (void)
{
  int same = 0;
  int first_iter = 1;
  struct listnode * node, * nnode;
  struct sisis_listener * listener;
  u_int16_t chksum_swp;
  int i =  0;

  for(ALL_LIST_ELEMENTS (sm->listen_sockets, node, nnode, listener))
  {
    zlog_debug("iter: %d", i);
    i++;
    zlog_debug("getp before: %d", stream_get_getp(listener->chksum_stream));
    zlog_debug("endp before: %d", stream_get_endp(listener->chksum_stream));
    if(stream_get_endp(listener->chksum_stream) != stream_get_getp(listener->chksum_stream))
    {
      u_int16_t chksum = stream_getw(listener->chksum_stream);
      zlog_debug("getp after: %d", stream_get_getp(listener->chksum_stream));
      zlog_debug("endp after: %d", stream_get_endp(listener->chksum_stream));
      zlog_debug("checksum: %d", chksum);
      if(first_iter)
      {
        chksum_swp = chksum;
        first_iter = 0;
      }
      else if(chksum == chksum_swp)
      {
        same = 1;
        chksum_swp = chksum;
      }
      else
      {
        return 0;
      }
    }
  }

  return same;
}
static struct list* mcp_pppd_interface_parse(struct stream *data_s)
{
	int type;
	int len;
	struct list* digt_list;
	struct pppd_interface_info* info = NULL;

    digt_list = list_new();
    digt_list->del = (void (*) (void *))mcp_ppp_config_info_free;
	
	while(STREAM_READABLE(data_s) >= 4)
	{
		type = stream_getw(data_s);
		len = stream_getw(data_s);
		//zlog_debug("<%s,%d> type:%d len:%d", __FUNCTION__, __LINE__, type, len);
		if(STREAM_READABLE(data_s) < 2) {
			zlog_err("mcp<%s:%d> stream readable bytes %d less %d",__FUNCTION__,__LINE__,((data_s)->endp-(data_s)->getp),len);
			return NULL;
		}

		switch(type)
		{
		    case PPP_INTERFACE_SEQ: 
		        info = mcp_pppd_interface_new();
				info->seq = stream_getl(data_s);
				//zlog_err("yang test ...seq:%u", (info->seq));
				break;
				
			case PPP_INTERFACE_GWID: 
				info->gwid= stream_getl(data_s);
				//zlog_err("yang test ...gwid:%s", remark_ip2str(info->gwid));
				break;

			case PPP_INTERFACE_SEVTYPE: 
			    info->dev_type = stream_getl(data_s);
				//zlog_err("yang test ...dev_type:%u", (info->dev_type));
				break;
				
            case PPP_INTERFACE_INTERFACEID:
                info->interfaceid = stream_getl(data_s);
				//zlog_err("yang test ...dev_type:%u", (info->dev_type));
				break;

			case PPP_INTERFACE_MULTIFLAGE:
			    info->multi_group = stream_getl(data_s);
				//zlog_err("yang test ...multi_flag:%u", (info->multi_group));
				break;
				
			case PPP_INTERFACE_INTERFACEIP: 
			    memset(info->interfaceip, 0, sizeof(info->interfaceip));
				stream_get(info->interfaceip, data_s, len);
				//zlog_err("yang test interfaceip:%s", info->interfaceip);
				break;

			case PPP_INTERFACE_ENABLE:
			    info->enable = stream_getl(data_s);
			    break;

			case PPP_INTERFACE_AUTHTYPE:
			    info->auth_type = stream_getl(data_s);
				//zlog_err("yang test ...auth_type:%u", (info->auth_type));
			    break;
			    
			case PPP_INTERFACE_AUTHNAME:
			    memset(info->auth_name, 0, sizeof(info->auth_name));
				stream_get(info->auth_name, data_s, len);
				//zlog_err("yang test auth_name:%s", info->auth_name);
				break;

			case PPP_INTERFACE_USERNAME:
			    memset(info->username, 0, sizeof(info->username));
				stream_get(info->username, data_s, len);
				//zlog_err("yang test username:%s", info->username);
                break;
                
			case PPP_INTERFACE_PSWD:
				memset(info->pswd, 0, sizeof(info->pswd));
				stream_get(info->pswd, data_s, len);
				//zlog_err("yang test pswd:%s", info->pswd);
                break;

            case PPP_INTERFACE_TIME:
				memset(info->time, 0, sizeof(info->time));
				stream_get(info->time, data_s, len);
				//zlog_err("yang test time:%s", info->time);
                break;
                
            case PPP_INTERFACE_REMARK:
                memset(info->remark, 0, sizeof(info->remark));
				stream_get(info->remark, data_s, len);
				//zlog_err("yang test remark:%s", info->remark);
                break;

             case PPP_INTERFACE_ACTION:
                info->action = stream_getl(data_s);
                listnode_add(digt_list, info);
				//zlog_err("yang test ...action:%u", (info->action));
                break;
            
			default:
			    list_delete(digt_list);
				zlog_err("mcp<%s:%d> wrong type:%u",__FUNCTION__,__LINE__,type);
				goto error;
		}		
	}

	return digt_list;

error:
	return NULL;	
}
static struct list* mcp_ppp_multilink_info_parse(struct stream *data_s)
{
	int type;
	int len;
	struct list* digt_list;
	struct pppd_multilink_info* info = NULL;

    digt_list = list_new();
    digt_list->del = (void (*) (void *))mcp_ppp_config_info_free;
	
	while(STREAM_READABLE(data_s) >= 4)
	{
		type = stream_getw(data_s);
		len = stream_getw(data_s);
		//zlog_debug("<%s,%d> type:%d len:%d", __FUNCTION__, __LINE__, type, len);
		if(STREAM_READABLE(data_s) < 2) {
			zlog_err("mcp<%s:%d> stream readable bytes %d less %d",__FUNCTION__,__LINE__,((data_s)->endp-(data_s)->getp),len);
			return NULL;
		}

		switch(type)
		{
		    case PPP_MULTILINK_INFO_SEQ: 
		        info = mcp_pppd_multilink_malloc_new();
				info->seq = stream_getl(data_s);
				//zlog_err("yang test ...seq:%u", (info->seq));
				break;
				
			case PPP_MULTILINK_INFO_GWID: 
				info->gwid= stream_getl(data_s);
				//zlog_err("yang test ...gwid:%s", remark_ip2str(info->gwid));
				break;

			case PPP_MULTILINK_INFO_MULTIIP: 
			    memset(info->multi_ip, 0, sizeof(info->multi_ip));
				stream_get(info->multi_ip, data_s, len);
				//zlog_err("yang test multi_ip:%s", info->multi_ip);
				break;
				
            case PPP_MULTILINK_INFO_TIME:
                memset(info->create_time, 0, sizeof(info->create_time));
                stream_get(info->create_time, data_s, len);
				//zlog_err("yang test create_time:%s", info->create_time);
				break;
				
			case PPP_MULTILINK_INFO_REMARK: 
			    memset(info->remark, 0, sizeof(info->remark));
				stream_get(info->remark, data_s, len);
				//zlog_err("yang test remark:%s", info->remark);
				break;

			case PPP_MULTILINK_INFO_ACTION:
			    info->action = stream_getl(data_s);
			    listnode_add(digt_list, info);
				//zlog_err("yang test ...action:%u", (info->action));
				break;
			    
			default:
			    list_delete(digt_list);
				zlog_err("mcp<%s:%d> wrong type:%u",__FUNCTION__,__LINE__,type);
				goto error;
		}		
	}

	return digt_list;

error:
	return NULL;	
}
Ejemplo n.º 7
0
static int
svz_tunnel_read(struct thread * thread)
{
  uint16_t length, command;
  uint8_t marker, version;
  struct stream * dbuf;
  int ret;
  size_t already;
  struct tclient * tclient;

  zlog_notice("Reading packet from Zebra!");

  /* Get socket to zebra. */
  tclient = THREAD_ARG (thread);
  tclient->t_read = NULL;

  stream_reset(tclient->ibuf);

  /* Read zebra header (if we don't have it already). */
  if ((already = stream_get_endp(tclient->ibuf)) < ZEBRA_HEADER_SIZE)
  {
    ssize_t nbyte;
    if (((nbyte = stream_read_try(tclient->ibuf, tclient->sock,
                                   ZEBRA_HEADER_SIZE-already)) == 0) ||
        (nbyte == -1))
    {
      return svz_tunnel_failed(tclient);
    }
    if (nbyte != (ssize_t)(ZEBRA_HEADER_SIZE-already))
    {
      /* Try again later. */
      svz_tunnel_event (TCLIENT_READ, tclient);
      return 0;
    }
    already = ZEBRA_HEADER_SIZE;   
  }

  dbuf = stream_dup(tclient->ibuf);

  stream_set_getp(dbuf, 0);

  length = stream_getw(dbuf);
  marker = stream_getc(dbuf);
  version = stream_getc(dbuf);
  command = stream_getw(dbuf);
 
  if(already < length)
  {
    ssize_t nbyte;
    if (((nbyte = stream_read_try(tclient->ibuf, tclient->sock,
                                  length-already)) == 0) ||
       (nbyte == -1)) 
     {       
         zlog_debug("zebra connection closed socket [%d].", tclient->sock);
         return svz_tunnel_failed(tclient);
     }        
     if (nbyte != (ssize_t)(length-already))
     {        
       /* Try again later. */
       svz_tunnel_event (TCLIENT_READ, tclient);
       return 0;
     }
  }

  stream_free(dbuf);

  shim_receive(tclient);

  svz_tunnel_event(TCLIENT_READ, tclient);

  return 0;
}
Ejemplo n.º 8
0
static struct bgp_nexthop_cache *
zlookup_read_ipv6 (void)
{
  struct stream *s;
  uint16_t length;
  u_char version, marker;
  uint16_t  command;
  int nbytes;
  struct in6_addr raddr;
  uint32_t metric;
  int i;
  u_char nexthop_num;
  struct nexthop *nexthop;
  struct bgp_nexthop_cache *bnc;

  s = zlookup->ibuf;
  stream_reset (s);

  nbytes = stream_read (s, zlookup->sock, 2);
  length = stream_getw (s);

  nbytes = stream_read (s, zlookup->sock, length - 2);
  marker = stream_getc (s);
  version = stream_getc (s);
  
  if (version != ZSERV_VERSION || marker != ZEBRA_HEADER_MARKER)
    {
      zlog_err("%s: socket %d version mismatch, marker %d, version %d",
               __func__, zlookup->sock, marker, version);
      return NULL;
    }
    
  command = stream_getw (s);
  
  stream_get (&raddr, s, 16);

  metric = stream_getl (s);
  nexthop_num = stream_getc (s);

  if (nexthop_num)
    {
      bnc = bnc_new ();
      bnc->valid = 1;
      bnc->metric = metric;
      bnc->nexthop_num = nexthop_num;

      for (i = 0; i < nexthop_num; i++)
	{
	  nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
	  nexthop->type = stream_getc (s);
	  switch (nexthop->type)
	    {
	    case ZEBRA_NEXTHOP_IPV6:
	      stream_get (&nexthop->gate.ipv6, s, 16);
	      break;
	    case ZEBRA_NEXTHOP_IPV6_IFINDEX:
	    case ZEBRA_NEXTHOP_IPV6_IFNAME:
	      stream_get (&nexthop->gate.ipv6, s, 16);
	      nexthop->ifindex = stream_getl (s);
	      break;
	    case ZEBRA_NEXTHOP_IFINDEX:
	    case ZEBRA_NEXTHOP_IFNAME:
	      nexthop->ifindex = stream_getl (s);
	      break;
	    default:
	      /* do nothing */
	      break;
	    }
	  bnc_nexthop_add (bnc, nexthop);
	}
    }
  else
    return NULL;

  return bnc;
}
static struct bgp_nexthop_cache *
zlookup_read (void)
{
  struct stream *s;
  uint16_t length;
  u_char marker;
  u_char version;
  uint16_t command __attribute__((unused));
  int nbytes __attribute__((unused));
  struct in_addr raddr __attribute__((unused));
  uint32_t metric;
  int i;
  u_char nexthop_num;
  struct nexthop *nexthop;
  struct bgp_nexthop_cache *bnc;

  s = zlookup->ibuf;
  stream_reset (s);

  /* nbytes not being checked */
  nbytes = stream_read (s, zlookup->sock, 2);
  length = stream_getw (s);

  nbytes = stream_read (s, zlookup->sock, length - 2);
  marker = stream_getc (s);
  version = stream_getc (s);
  
  if (version != ZSERV_VERSION || marker != ZEBRA_HEADER_MARKER)
    {
      zlog_err("%s: socket %d version mismatch, marker %d, version %d",
               __func__, zlookup->sock, marker, version);
      return NULL;
    }
  
  /* XXX: not checking command */
  command = stream_getw (s);
  
  /* XXX: not doing anything with raddr */
  raddr.s_addr = stream_get_ipv4 (s);
  metric = stream_getl (s);
  nexthop_num = stream_getc (s);

  if (nexthop_num)
    {
      bnc = bnc_new ();
      bnc->valid = 1;
      bnc->metric = metric;
      bnc->nexthop_num = nexthop_num;

      for (i = 0; i < nexthop_num; i++)
	{
	  nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
	  nexthop->type = stream_getc (s);
	  switch (nexthop->type)
	    {
	    case ZEBRA_NEXTHOP_IPV4:
	      nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
	      break;
	    case ZEBRA_NEXTHOP_IPV4_IFINDEX:
	      nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
	      nexthop->ifindex = stream_getl (s);
	      break;
	    case ZEBRA_NEXTHOP_IFINDEX:
	    case ZEBRA_NEXTHOP_IFNAME:
	      nexthop->ifindex = stream_getl (s);
	      break;
            default:
              /* do nothing */
              break;
	    }
	  bnc_nexthop_add (bnc, nexthop);
	}
    }
  else
    return NULL;

  return bnc;
}
Ejemplo n.º 10
0
Archivo: zserv.c Proyecto: OPSF/uClinux
/* Handler of zebra service request. */
static int
zebra_client_read (struct thread *thread)
{
  int sock;
  struct zserv *client;
  int nbyte;
  u_short length;
  u_char command;

  /* Get thread data.  Reset reading thread because I'm running. */
  sock = THREAD_FD (thread);
  client = THREAD_ARG (thread);
  client->t_read = NULL;

  /* Read length and command. */
  nbyte = stream_read (client->ibuf, sock, 3);
  if (nbyte <= 0) 
    {
      if (IS_ZEBRA_DEBUG_EVENT)
	zlog_debug ("connection closed socket [%d]", sock);
      zebra_client_close (client);
      return -1;
    }
  length = stream_getw (client->ibuf);
  command = stream_getc (client->ibuf);

  if (length < 3) 
    {
      if (IS_ZEBRA_DEBUG_EVENT)
	zlog_debug ("length %d is less than 3 ", length);
      zebra_client_close (client);
      return -1;
    }

  length -= 3;

  /* Read rest of data. */
  if (length)
    {
      nbyte = stream_read (client->ibuf, sock, length);
      if (nbyte <= 0) 
	{
	  if (IS_ZEBRA_DEBUG_EVENT)
	    zlog_debug ("connection closed [%d] when reading zebra data", sock);
	  zebra_client_close (client);
	  return -1;
	}
    }

  /* Debug packet information. */
  if (IS_ZEBRA_DEBUG_EVENT)
    zlog_debug ("zebra message comes from socket [%d]", sock);

  if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
    zlog_debug ("zebra message received [%s] %d", 
	       zebra_command_str[command], length);

  switch (command) 
    {
    case ZEBRA_ROUTER_ID_ADD:
      zread_router_id_add (client, length);
      break;
    case ZEBRA_ROUTER_ID_DELETE:
      zread_router_id_delete (client, length);
      break;
    case ZEBRA_INTERFACE_ADD:
      zread_interface_add (client, length);
      break;
    case ZEBRA_INTERFACE_DELETE:
      zread_interface_delete (client, length);
      break;
    case ZEBRA_IPV4_ROUTE_ADD:
      zread_ipv4_add (client, length);
      break;
    case ZEBRA_IPV4_ROUTE_DELETE:
      zread_ipv4_delete (client, length);
      break;
#ifdef HAVE_IPV6
    case ZEBRA_IPV6_ROUTE_ADD:
      zread_ipv6_add (client, length);
      break;
    case ZEBRA_IPV6_ROUTE_DELETE:
      zread_ipv6_delete (client, length);
      break;
#endif /* HAVE_IPV6 */
    case ZEBRA_REDISTRIBUTE_ADD:
      zebra_redistribute_add (command, client, length);
      break;
    case ZEBRA_REDISTRIBUTE_DELETE:
      zebra_redistribute_delete (command, client, length);
      break;
    case ZEBRA_REDISTRIBUTE_DEFAULT_ADD:
      zebra_redistribute_default_add (command, client, length);
      break;
    case ZEBRA_REDISTRIBUTE_DEFAULT_DELETE:
      zebra_redistribute_default_delete (command, client, length);
      break;
    case ZEBRA_IPV4_NEXTHOP_LOOKUP:
      zread_ipv4_nexthop_lookup (client, length);
      break;
#ifdef HAVE_IPV6
    case ZEBRA_IPV6_NEXTHOP_LOOKUP:
      zread_ipv6_nexthop_lookup (client, length);
      break;
#endif /* HAVE_IPV6 */
    case ZEBRA_IPV4_IMPORT_LOOKUP:
      zread_ipv4_import_lookup (client, length);
      break;
    default:
      zlog_info ("Zebra received unknown command %d", command);
      break;
    }

  stream_reset (client->ibuf);
  zebra_event (ZEBRA_READ, sock, client);

  return 0;
}
Ejemplo n.º 11
0
/* 
 * Parse the ZEBRA_IPV4_ROUTE_ADD sent from client. Update rib and
 * add kernel route. 
 */
static int
zread_ipv4_add (struct zserv *client, u_short length)
{
  int i;
  struct rib *rib;
  struct prefix_ipv4 p;
  u_char message;
  struct in_addr nexthop;
  u_char nexthop_num;
  u_char nexthop_type;
  struct stream *s;
  unsigned int ifindex;
  u_char ifname_len;
  safi_t safi;	


  /* Get input stream.  */
  s = client->ibuf;

  /* Allocate new rib. */
  rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
  
  /* Type, flags, message. */
  rib->type = stream_getc (s);
  rib->flags = stream_getc (s);
  message = stream_getc (s); 
  safi = stream_getw (s);
  rib->uptime = time (NULL);

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

  /* Nexthop parse. */
  if (CHECK_FLAG (message, ZAPI_MESSAGE_NEXTHOP))
    {
      nexthop_num = stream_getc (s);

      for (i = 0; i < nexthop_num; i++)
	{
	  nexthop_type = stream_getc (s);

	  switch (nexthop_type)
	    {
	    case ZEBRA_NEXTHOP_IFINDEX:
	      ifindex = stream_getl (s);
	      nexthop_ifindex_add (rib, ifindex);
	      break;
	    case ZEBRA_NEXTHOP_IFNAME:
	      ifname_len = stream_getc (s);
	      stream_forward_getp (s, ifname_len);
	      break;
	    case ZEBRA_NEXTHOP_IPV4:
	      nexthop.s_addr = stream_get_ipv4 (s);
	      nexthop_ipv4_add (rib, &nexthop, NULL);
	      break;
	    case ZEBRA_NEXTHOP_IPV4_IFINDEX:
	      nexthop.s_addr = stream_get_ipv4 (s);
	      ifindex = stream_getl (s);
	      nexthop_ipv4_ifindex_add (rib, &nexthop, NULL, ifindex);
	      break;
	    case ZEBRA_NEXTHOP_IPV6:
	      stream_forward_getp (s, IPV6_MAX_BYTELEN);
	      break;
            case ZEBRA_NEXTHOP_BLACKHOLE:
              nexthop_blackhole_add (rib);
              break;
            }
	}
    }

  /* Distance. */
  if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
    rib->distance = stream_getc (s);

  /* Metric. */
  if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
    rib->metric = stream_getl (s);
    
  /* Table */
  rib->table=zebrad.rtm_table_default;
  rib_add_ipv4_multipath (&p, rib, safi);
  return 0;
}
Ejemplo n.º 12
0
/* Handler of zebra service request. */
static int
zebra_client_read (struct thread *thread)
{
  int sock;
  struct zserv *client;
  size_t already;
  uint16_t length, command;
  uint8_t marker, version;

  /* Get thread data.  Reset reading thread because I'm running. */
  sock = THREAD_FD (thread);
  client = THREAD_ARG (thread);
  client->t_read = NULL;

  if (client->t_suicide)
    {
      zebra_client_close(client);
      return -1;
    }

  /* Read length and command (if we don't have it already). */
  if ((already = stream_get_endp(client->ibuf)) < ZEBRA_HEADER_SIZE)
    {
      ssize_t nbyte;
      if (((nbyte = stream_read_try (client->ibuf, sock,
				     ZEBRA_HEADER_SIZE-already)) == 0) ||
	  (nbyte == -1))
	{
	  if (IS_ZEBRA_DEBUG_EVENT)
	    zlog_debug ("connection closed socket [%d]", sock);
	  zebra_client_close (client);
	  return -1;
	}
      if (nbyte != (ssize_t)(ZEBRA_HEADER_SIZE-already))
	{
	  /* Try again later. */
	  zebra_event (ZEBRA_READ, sock, client);
	  return 0;
	}
      already = ZEBRA_HEADER_SIZE;
    }

  /* Reset to read from the beginning of the incoming packet. */
  stream_set_getp(client->ibuf, 0);

  /* Fetch header values */
  length = stream_getw (client->ibuf);
  marker = stream_getc (client->ibuf);
  version = stream_getc (client->ibuf);
  command = stream_getw (client->ibuf);

  if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION)
    {
      zlog_err("%s: socket %d version mismatch, marker %d, version %d",
               __func__, sock, marker, version);
      zebra_client_close (client);
      return -1;
    }
  if (length < ZEBRA_HEADER_SIZE) 
    {
      zlog_warn("%s: socket %d message length %u is less than header size %d",
	        __func__, sock, length, ZEBRA_HEADER_SIZE);
      zebra_client_close (client);
      return -1;
    }
  if (length > STREAM_SIZE(client->ibuf))
    {
      zlog_warn("%s: socket %d message length %u exceeds buffer size %lu",
	        __func__, sock, length, (u_long)STREAM_SIZE(client->ibuf));
      zebra_client_close (client);
      return -1;
    }

  /* Read rest of data. */
  if (already < length)
    {
      ssize_t nbyte;
      if (((nbyte = stream_read_try (client->ibuf, sock,
				     length-already)) == 0) ||
	  (nbyte == -1))
	{
	  if (IS_ZEBRA_DEBUG_EVENT)
	    zlog_debug ("connection closed [%d] when reading zebra data", sock);
	  zebra_client_close (client);
	  return -1;
	}
      if (nbyte != (ssize_t)(length-already))
        {
	  /* Try again later. */
	  zebra_event (ZEBRA_READ, sock, client);
	  return 0;
	}
    }

  length -= ZEBRA_HEADER_SIZE;

  /* Debug packet information. */
  if (IS_ZEBRA_DEBUG_EVENT)
    zlog_debug ("zebra message comes from socket [%d]", sock);

  if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
    zlog_debug ("zebra message received [%s] %d", 
	       zserv_command_string (command), length);

  switch (command) 
    {
    case ZEBRA_ROUTER_ID_ADD:
      zread_router_id_add (client, length);
      break;
    case ZEBRA_ROUTER_ID_DELETE:
      zread_router_id_delete (client, length);
      break;
    case ZEBRA_INTERFACE_ADD:
      zread_interface_add (client, length);
      break;
    case ZEBRA_INTERFACE_DELETE:
      zread_interface_delete (client, length);
      break;
    case ZEBRA_IPV4_ROUTE_ADD:
      zread_ipv4_add (client, length);
      break;
    case ZEBRA_IPV4_ROUTE_DELETE:
      zread_ipv4_delete (client, length);
      break;
#ifdef HAVE_IPV6
    case ZEBRA_IPV6_ROUTE_ADD:
      zread_ipv6_add (client, length);
      break;
    case ZEBRA_IPV6_ROUTE_DELETE:
      zread_ipv6_delete (client, length);
      break;
#endif /* HAVE_IPV6 */
    case ZEBRA_REDISTRIBUTE_ADD:
      zebra_redistribute_add (command, client, length);
      break;
    case ZEBRA_REDISTRIBUTE_DELETE:
      zebra_redistribute_delete (command, client, length);
      break;
    case ZEBRA_REDISTRIBUTE_DEFAULT_ADD:
      zebra_redistribute_default_add (command, client, length);
      break;
    case ZEBRA_REDISTRIBUTE_DEFAULT_DELETE:
      zebra_redistribute_default_delete (command, client, length);
      break;
    case ZEBRA_IPV4_NEXTHOP_LOOKUP:
      zread_ipv4_nexthop_lookup (client, length);
      break;
#ifdef HAVE_IPV6
    case ZEBRA_IPV6_NEXTHOP_LOOKUP:
      zread_ipv6_nexthop_lookup (client, length);
      break;
#endif /* HAVE_IPV6 */
    case ZEBRA_IPV4_IMPORT_LOOKUP:
      zread_ipv4_import_lookup (client, length);
      break;
    case ZEBRA_HELLO:
      zread_hello (client);
      break;
    default:
      zlog_info ("Zebra received unknown command %d", command);
      break;
    }

  if (client->t_suicide)
    {
      /* No need to wait for thread callback, just kill immediately. */
      zebra_client_close(client);
      return -1;
    }

  stream_reset (client->ibuf);
  zebra_event (ZEBRA_READ, sock, client);
  return 0;
}
Ejemplo n.º 13
0
/* Zebra client message read function. */
int
zclient_read (struct thread *thread)
{
  int ret;
  int nbytes;
  int sock;
  zebra_size_t length;
  zebra_command_t command;
#undef	zclient
  struct_zclient *zclient;

  /* Get socket to zebra. */
  sock = THREAD_FD (thread);
  zclient = THREAD_ARG (thread);
  zclient->t_read = NULL;

  /* Clear input buffer. */
  stream_reset (zclient->ibuf);

  /* Read zebra header. */
  nbytes = stream_read (zclient->ibuf, sock, ZEBRA_HEADER_SIZE);

  /* zebra socket is closed. */
  if (nbytes == 0) 
    {
      if (zclient_debug)
       zlog_debug ("zclient connection closed socket [%d].", sock);
      zclient->fail++;
      zclient_stop (zclient);
      zclient_event (ZCLIENT_CONNECT, zclient);
      return -1;
    }

  /* zebra read error. */
  if (nbytes < 0 || nbytes != ZEBRA_HEADER_SIZE)
    {
      if (zclient_debug)
        zlog_debug ("Can't read all packet (length %d).", nbytes);
      zclient->fail++;
      zclient_stop (zclient);
      zclient_event (ZCLIENT_CONNECT, zclient);
      return -1;
    }

  /* Fetch length and command. */
  length = stream_getw (zclient->ibuf);
  command = stream_getc (zclient->ibuf);

  /* Length check. */
  if (length >= zclient->ibuf->size)
    {
      stream_free (zclient->ibuf);
      zclient->ibuf = stream_new (length + 1);
    }
  length -= ZEBRA_HEADER_SIZE;

  /* Read rest of zebra packet. */
  nbytes = stream_read (zclient->ibuf, sock, length);
 if (nbytes != length)
   {
     if (zclient_debug)
       zlog_debug ("zclient connection closed socket [%d].", sock);
     zclient->fail++;
     zclient_stop (zclient);
     zclient_event (ZCLIENT_CONNECT, zclient);
     return -1;
   }

  if (zclient_debug)
    zlog_debug("zclient 0x%p command 0x%x \n", zclient, command);

  switch (command)
    {
    case ZEBRA_ROUTER_ID_UPDATE:
      if (zclient->router_id_update)
	ret = (*zclient->router_id_update) (command, zclient, length);
      break;
    case ZEBRA_INTERFACE_ADD:
      if (zclient->interface_add)
	ret = (*zclient->interface_add) (command, zclient, length);
      break;
    case ZEBRA_INTERFACE_DELETE:
      if (zclient->interface_delete)
	ret = (*zclient->interface_delete) (command, zclient, length);
      break;
    case ZEBRA_INTERFACE_ADDRESS_ADD:
      if (zclient->interface_address_add)
	ret = (*zclient->interface_address_add) (command, zclient, length);
      break;
    case ZEBRA_INTERFACE_ADDRESS_DELETE:
      if (zclient->interface_address_delete)
	ret = (*zclient->interface_address_delete) (command, zclient, length);
      break;
    case ZEBRA_INTERFACE_UP:
      if (zclient->interface_up)
	ret = (*zclient->interface_up) (command, zclient, length);
      break;
    case ZEBRA_INTERFACE_DOWN:
      if (zclient->interface_down)
	ret = (*zclient->interface_down) (command, zclient, length);
      break;
    case ZEBRA_IPV4_ROUTE_ADD:
      if (zclient->ipv4_route_add)
	ret = (*zclient->ipv4_route_add) (command, zclient, length);
      break;
    case ZEBRA_IPV4_ROUTE_DELETE:
      if (zclient->ipv4_route_delete)
	ret = (*zclient->ipv4_route_delete) (command, zclient, length);
      break;
    case ZEBRA_IPV6_ROUTE_ADD:
      if (zclient->ipv6_route_add)
	ret = (*zclient->ipv6_route_add) (command, zclient, length);
      break;
    case ZEBRA_IPV6_ROUTE_DELETE:
      if (zclient->ipv6_route_delete)
	ret = (*zclient->ipv6_route_delete) (command, zclient, length);
      break;
    default:
      break;
    }

  /* Register read thread. */
  zclient_event (ZCLIENT_READ, zclient);

  return 0;
}
Ejemplo n.º 14
0
int
main (int argc, char **argv)
{
  int ret;
  FILE *fp;
  struct stream *s;
  time_t now;
  int type;
  int subtype;
  size_t len;
  int source_as;
  int dest_as;
  int ifindex;
  int family;
  struct in_addr sip;
  struct in_addr dip;
  u_int16_t viewno, seq_num;
  struct prefix_ipv4 p;

  s = stream_new (10000);

  if (argc != 2)
    {
      fprintf (stderr, "Usage: %s FILENAME\n", argv[0]);
      exit (1);
    }
  fp = fopen (argv[1], "r");
  if (!fp)
    {
      perror ("fopen");
      exit (1);
    }
  
  while (1)
    {
      stream_reset (s);

      ret = fread (s->data, 12, 1, fp);
      if (!ret || feof (fp))
	{
	  printf ("END OF FILE\n");
	  break;
	}
      if (ferror (fp))
	{
	  printf ("ERROR OF FREAD\n");
	  break;
	}

      /* Extract header. */
      now = stream_getl (s);
      type = stream_getw (s);
      subtype = stream_getw (s);
      len = stream_getl (s);

      printf ("TIME: %s", ctime (&now));

      /* printf ("TYPE: %d/%d\n", type, subtype); */

      if (type == MSG_PROTOCOL_BGP4MP)
	printf ("TYPE: BGP4MP");
      else if (type == MSG_PROTOCOL_BGP4MP_ET)
	printf ("TYPE: BGP4MP_ET");
      else if (type == MSG_TABLE_DUMP)
	printf ("TYPE: MSG_TABLE_DUMP");
      else
	printf ("TYPE: Unknown %d", type);

      if (type == MSG_TABLE_DUMP)
	switch (subtype)
	  {
	  case AFI_IP:
	    printf ("/AFI_IP\n");
	    break;
	  case AFI_IP6:
	    printf ("/AFI_IP6\n");
	    break;
	  default:
	    printf ("/UNKNOWN %d", subtype);
	    break;
	  }
      else
	{
	  switch (subtype)
	    {
	    case BGP4MP_STATE_CHANGE:
	      printf ("/CHANGE\n");
	      break;
	    case BGP4MP_MESSAGE:
	      printf ("/MESSAGE\n");
	      break;
	    case BGP4MP_ENTRY:
	      printf ("/ENTRY\n");
	      break;
	    case BGP4MP_SNAPSHOT:
	      printf ("/SNAPSHOT\n");
	      break;
	    default:
	      printf ("/UNKNOWN %d", subtype);
	      break;
	    }
	}

      printf ("len: %zd\n", len);

      ret = fread (s->data + 12, len, 1, fp);
      if (feof (fp))
	{
	  printf ("ENDOF FILE 2\n");
	  break;
	}
      if (ferror (fp))
	{
	  printf ("ERROR OF FREAD 2\n");
	  break;
	}

      /* printf ("now read %d\n", len); */

      if (type == MSG_TABLE_DUMP)
	{
	  u_char status;
	  time_t originated;
	  struct in_addr peer;
	  u_int16_t attrlen;

	  viewno = stream_getw (s);
	  seq_num = stream_getw (s);
	  printf ("VIEW: %d\n", viewno);
	  printf ("SEQUENCE: %d\n", seq_num);

	  /* start */
	  while (s->getp < len - 16)
	    {
	      p.prefix.s_addr = stream_get_ipv4 (s);
	      p.prefixlen = stream_getc (s);
	      printf ("PREFIX: %s/%d\n", inet_ntoa (p.prefix), p.prefixlen);

	      status = stream_getc (s);
	      originated = stream_getl (s);
	      peer.s_addr = stream_get_ipv4 (s);
	      source_as = stream_getw(s);

	      printf ("FROM: %s AS%d\n", inet_ntoa (peer), source_as);
	      printf ("ORIGINATED: %s", ctime (&originated));

	      attrlen = stream_getw (s);
	      printf ("ATTRLEN: %d\n", attrlen);

	      attr_parse (s, attrlen);

	      printf ("STATUS: 0x%x\n", status);
	    }
	}
      else
	{
	  source_as = stream_getw (s);
	  dest_as = stream_getw (s);
	  printf ("source_as: %d\n", source_as);
	  printf ("dest_as: %d\n", dest_as);

	  ifindex = stream_getw (s);
	  family = stream_getw (s);

	  printf ("ifindex: %d\n", ifindex);
	  printf ("family: %d\n", family);

	  sip.s_addr = stream_get_ipv4 (s);
	  dip.s_addr = stream_get_ipv4 (s);
	  
	  printf ("saddr: %s\n", inet_ntoa (sip));
	  printf ("daddr: %s\n", inet_ntoa (dip));

	  printf ("\n");
	}
    }
  fclose (fp);
  return 0;
}
Ejemplo n.º 15
0
int
shim_sisis_read(struct thread * thread)
{
  struct sisis_listener *listener;
  int sisis_sock;
  uint16_t length, checksum;
  int already;
  u_int ifindex;
  struct shim_interface * si;
  struct in6_addr src;
  char src_buf[INET6_ADDRSTRLEN];
  struct in6_addr dst;
  char dst_buf[INET6_ADDRSTRLEN];

  zlog_notice("Reading packet from SISIS connection!");

  /* first of all get listener pointer. */
  listener = THREAD_ARG (thread);
  sisis_sock = THREAD_FD (thread);

  stream_reset(listener->ibuf);

  if ((already = stream_get_endp(listener->ibuf)) < SVZ_OUT_HEADER_SIZE)
  {
    ssize_t nbytes;
    if (((nbytes = stream_read_try (listener->ibuf, sisis_sock, SVZ_OUT_HEADER_SIZE-already)) == 0) || (nbytes == -1))
    {
      return -1;
    }

    if(nbytes != (SVZ_OUT_HEADER_SIZE - already))
    {
      listener->read_thread = thread_add_read (master, shim_sisis_read, listener, sisis_sock);
      return 0;
    }

    already = SVZ_OUT_HEADER_SIZE;
  }

  stream_set_getp(listener->ibuf, 0);

  length = stream_getw(listener->ibuf);
  checksum = stream_getw(listener->ibuf);

  if(length > STREAM_SIZE(listener->ibuf))
  {
    struct stream * ns; 
    zlog_warn("message size exceeds buffer size");
    ns = stream_new(length);
    stream_copy(ns, listener->ibuf);
    stream_free(listener->ibuf);
    listener->ibuf = ns; 
  }

  if(already < length)
  {
    ssize_t nbytes;
    if(((nbytes = stream_read_try(listener->ibuf, sisis_sock, length-already)) == 0) || nbytes == -1) 
    {   
      return -1; 
    }   
    if(nbytes != (length-already))
    {   
      listener->read_thread = thread_add_read (master, shim_sisis_read, listener, sisis_sock);
      return 0;
    }   
  } 

  unsigned int num_of_addrs = number_of_sisis_addrs_for_process_type(SISIS_PTYPE_RIBCOMP_OSPF6);
  unsigned int num_of_listeners = number_of_listeners();
 
  zlog_notice("Number of addr: %d", num_of_addrs);
  zlog_notice("Number of listeners: %d", num_of_listeners);

  pthread_mutex_lock(&bmap_mutex);
  struct bmap * bmap = bmap_set(checksum);

  // if we added initially
  // set timer at which to recycle bmap 
  // if there are no more processes sending data
  if(bmap->count == 0)
  {
    uint16_t * chcksum_ptr = malloc(sizeof(uint16_t));
    *chcksum_ptr = checksum;
  
    listener->bmap_thread = thread_add_timer_msec (master, svz_sisis_clean_bmap, chcksum_ptr, 100);
  }

  bmap->count++;
  zlog_notice("# of streams %d for checksum %d with length %d", bmap->count, checksum, length);
 
  float received_ratio = (float)bmap->count/(float)num_of_addrs;
  stream_putw(listener->chksum_stream, checksum);
  if((received_ratio > 1.0/2.0) && !bmap->sent)
  {
    if(are_checksums_same())
    {
      zlog_notice("Checksums are all the same");

    if(primary_listener == NULL)
      primary_listener = listener;

    reset_checksum_streams();
    svz_send(listener->ibuf);
    bmap->sent = 1;
    }
    else
    {
      zlog_notice("Checksums are not all the same");
      stream_fifo_push(listener->dif, listener->ibuf);
      listener->dif_size++;
    }
  }
  else if(!bmap->sent)
  {
    zlog_notice("Not enough processes have sent their data; buffering...");
  }
  else
  {
    zlog_notice("Data has already been sent...");
  }

  if((bmap->count == num_of_addrs) && (bmap->sent))
  {
    zlog_notice("Bmap no longer needed, freeing...");

    bmap->count = 0;
    bmap->sent = 0;

    clear_checksum_streams(checksum);
    bmap_unset(checksum);
  } 
  pthread_mutex_unlock(&bmap_mutex);

  if (sisis_sock < 0) 
    /* Connection was closed during packet processing. */
    return -1; 

  /* Register read thread. */
//  stream_reset(listener->ibuf);

  /* prepare for next packet. */
  listener->read_thread = thread_add_read (master, shim_sisis_read, listener, sisis_sock);

  return 0;
}
static int zclient_read_nexthop(struct zclient *zlookup,
				struct pim_zlookup_nexthop nexthop_tab[],
				const int tab_size,
				struct in_addr addr)
{
  int num_ifindex = 0;
  struct stream *s;
  const uint16_t MIN_LEN = 14; /* getc=1 getc=1 getw=2 getipv4=4 getc=1 getl=4 getc=1 */
  uint16_t length, len;
  u_char marker;
  u_char version;
  uint16_t command;
  int nbytes;
  struct in_addr raddr;
  uint8_t distance;
  uint32_t metric;
  int nexthop_num;
  int i;

  if (PIM_DEBUG_ZEBRA) {
    char addr_str[100];
    pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
    zlog_debug("%s: addr=%s", 
	       __PRETTY_FUNCTION__,
	       addr_str);
  }

  s = zlookup->ibuf;
  stream_reset(s);

  nbytes = stream_read(s, zlookup->sock, 2);
  if (nbytes < 2) {
    zlog_err("%s %s: failure reading zclient lookup socket: nbytes=%d",
	     __FILE__, __PRETTY_FUNCTION__, nbytes);
    zclient_lookup_failed(zlookup);
    return -1;
  }
  length = stream_getw(s);

  len = length - 2;

  if (len < MIN_LEN) {
    zlog_err("%s %s: failure reading zclient lookup socket: len=%d < MIN_LEN=%d",
	     __FILE__, __PRETTY_FUNCTION__, len, MIN_LEN);
    zclient_lookup_failed(zlookup);
    return -2;
  }

  nbytes = stream_read(s, zlookup->sock, len);
  if (nbytes < (length - 2)) {
    zlog_err("%s %s: failure reading zclient lookup socket: nbytes=%d < len=%d",
	     __FILE__, __PRETTY_FUNCTION__, nbytes, len);
    zclient_lookup_failed(zlookup);
    return -3;
  }
  marker = stream_getc(s);
  version = stream_getc(s);
  
  if (version != ZSERV_VERSION || marker != ZEBRA_HEADER_MARKER) {
    zlog_err("%s: socket %d version mismatch, marker %d, version %d",
	     __func__, zlookup->sock, marker, version);
    return -4;
  }
    
  command = stream_getw(s);
  if (command != ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB) {
    zlog_err("%s: socket %d command mismatch: %d",
            __func__, zlookup->sock, command);
    return -5;
  }

  raddr.s_addr = stream_get_ipv4(s);

  if (raddr.s_addr != addr.s_addr) {
    char addr_str[100];
    char raddr_str[100];
    pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
    pim_inet4_dump("<raddr?>", raddr, raddr_str, sizeof(raddr_str));
    zlog_warn("%s: address mismatch: addr=%s raddr=%s", 
	       __PRETTY_FUNCTION__,
	       addr_str, raddr_str);
    /* warning only */
  }

  distance = stream_getc(s);
  metric = stream_getl(s);
  nexthop_num = stream_getc(s);

  if (nexthop_num < 1) {
    zlog_err("%s: socket %d bad nexthop_num=%d",
            __func__, zlookup->sock, nexthop_num);
    return -6;
  }

  len -= MIN_LEN;

  for (i = 0; i < nexthop_num; ++i) {
    enum nexthop_types_t nexthop_type;

    if (len < 1) {
      zlog_err("%s: socket %d empty input expecting nexthop_type: len=%d",
	       __func__, zlookup->sock, len);
      return -7;
    }
    
    nexthop_type = stream_getc(s);
    --len;

    switch (nexthop_type) {
    case ZEBRA_NEXTHOP_IFINDEX:
    case ZEBRA_NEXTHOP_IFNAME:
    case ZEBRA_NEXTHOP_IPV4_IFINDEX:
      if (num_ifindex >= tab_size) {
	char addr_str[100];
	pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
	zlog_warn("%s %s: found too many nexthop ifindexes (%d > %d) for address %s",
		 __FILE__, __PRETTY_FUNCTION__,
		 (num_ifindex + 1), tab_size, addr_str);
	return num_ifindex;
      }
      if (nexthop_type == ZEBRA_NEXTHOP_IPV4_IFINDEX) {
	if (len < 4) {
	  zlog_err("%s: socket %d short input expecting nexthop IPv4-addr: len=%d",
		   __func__, zlookup->sock, len);
	  return -8;
	}
	nexthop_tab[num_ifindex].nexthop_addr.s_addr = stream_get_ipv4(s);
	len -= 4;
      }
      else {
	nexthop_tab[num_ifindex].nexthop_addr.s_addr = PIM_NET_INADDR_ANY;
      }
      nexthop_tab[num_ifindex].ifindex           = stream_getl(s);
      nexthop_tab[num_ifindex].protocol_distance = distance;
      nexthop_tab[num_ifindex].route_metric      = metric;
      ++num_ifindex;
      break;
    case ZEBRA_NEXTHOP_IPV4:
      if (num_ifindex >= tab_size) {
	char addr_str[100];
	pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
	zlog_warn("%s %s: found too many nexthop ifindexes (%d > %d) for address %s",
		 __FILE__, __PRETTY_FUNCTION__,
		 (num_ifindex + 1), tab_size, addr_str);
	return num_ifindex;
      }
      nexthop_tab[num_ifindex].nexthop_addr.s_addr = stream_get_ipv4(s);
      len -= 4;
      nexthop_tab[num_ifindex].ifindex             = 0;
      nexthop_tab[num_ifindex].protocol_distance   = distance;
      nexthop_tab[num_ifindex].route_metric        = metric;
      {
	char addr_str[100];
	char nexthop_str[100];
	pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
	pim_inet4_dump("<nexthop?>", nexthop_tab[num_ifindex].nexthop_addr, nexthop_str, sizeof(nexthop_str));
	zlog_warn("%s %s: zebra returned recursive nexthop %s for address %s",
		  __FILE__, __PRETTY_FUNCTION__,
		  nexthop_str, addr_str);
      }
      ++num_ifindex;
      break;
    default:
      /* do nothing */
      {
	char addr_str[100];
	pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
	zlog_warn("%s %s: found non-ifindex nexthop type=%d for address %s",
		 __FILE__, __PRETTY_FUNCTION__,
		  nexthop_type, addr_str);
      }
      break;
    }
  }

  return num_ifindex;
}
Ejemplo n.º 17
0
/*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;
  struct eigrp_prefix_entry *temp_tn;
  struct eigrp_neighbor_entry *temp_te;

  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);
}
Ejemplo n.º 18
0
/* Zebra server IPv4 prefix delete function. */
static int
zread_ipv4_delete (struct zserv *client, u_short length)
{
  int i;
  struct stream *s;
  struct zapi_ipv4 api;
  struct in_addr nexthop, *nexthop_p;
  unsigned long ifindex;
  struct prefix_ipv4 p;
  u_char nexthop_num;
  u_char nexthop_type;
  u_char ifname_len;
  
  s = client->ibuf;
  ifindex = 0;
  nexthop.s_addr = 0;
  nexthop_p = NULL;

  /* Type, flags, message. */
  api.type = stream_getc (s);
  api.flags = stream_getc (s);
  api.message = stream_getc (s);
  api.safi = stream_getw (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));

  /* Nexthop, ifindex, distance, metric. */
  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
    {
      nexthop_num = stream_getc (s);

      for (i = 0; i < nexthop_num; i++)
	{
	  nexthop_type = stream_getc (s);

	  switch (nexthop_type)
	    {
	    case ZEBRA_NEXTHOP_IFINDEX:
	      ifindex = stream_getl (s);
	      break;
	    case ZEBRA_NEXTHOP_IFNAME:
	      ifname_len = stream_getc (s);
	      stream_forward_getp (s, ifname_len);
	      break;
	    case ZEBRA_NEXTHOP_IPV4:
	      nexthop.s_addr = stream_get_ipv4 (s);
	      nexthop_p = &nexthop;
	      break;
	    case ZEBRA_NEXTHOP_IPV4_IFINDEX:
	      nexthop.s_addr = stream_get_ipv4 (s);
	      ifindex = stream_getl (s);
	      break;
	    case ZEBRA_NEXTHOP_IPV6:
	      stream_forward_getp (s, IPV6_MAX_BYTELEN);
	      break;
	    }
	}
    }

  /* Distance. */
  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
    api.distance = stream_getc (s);
  else
    api.distance = 0;

  /* Metric. */
  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
    api.metric = stream_getl (s);
  else
    api.metric = 0;
    
  rib_delete_ipv4 (api.type, api.flags, &p, nexthop_p, ifindex,
		   client->rtm_table, api.safi);
  return 0;
}
Ejemplo n.º 19
0
/* Zebra client message read function. */
static int
zclient_read (struct thread *thread)
{
  size_t already;
  uint16_t length, command;
  uint8_t marker, version;
  struct zclient *zclient;

  /* Get socket to zebra. */
  zclient = THREAD_ARG (thread);
  zclient->t_read = NULL;

  /* Read zebra header (if we don't have it already). */
  if ((already = stream_get_endp(zclient->ibuf)) < ZEBRA_HEADER_SIZE)
    {
      ssize_t nbyte;
      if (((nbyte = stream_read_try(zclient->ibuf, zclient->sock,
				     ZEBRA_HEADER_SIZE-already)) == 0) ||
	  (nbyte == -1))
	{
	  if (zclient_debug)
	   zlog_debug ("zclient connection closed socket [%d].", zclient->sock);
	  return zclient_failed(zclient);
	}
      if (nbyte != (ssize_t)(ZEBRA_HEADER_SIZE-already))
	{
	  /* Try again later. */
	  zclient_event (ZCLIENT_READ, zclient);
	  return 0;
	}
      already = ZEBRA_HEADER_SIZE;
    }

  /* Reset to read from the beginning of the incoming packet. */
  stream_set_getp(zclient->ibuf, 0);

  /* Fetch header values. */
  length = stream_getw (zclient->ibuf);
  marker = stream_getc (zclient->ibuf);
  version = stream_getc (zclient->ibuf);
  command = stream_getw (zclient->ibuf);
  
  if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION)
    {
      zlog_err("%s: socket %d version mismatch, marker %d, version %d",
               __func__, zclient->sock, marker, version);
      return zclient_failed(zclient);
    }
  
  if (length < ZEBRA_HEADER_SIZE) 
    {
      zlog_err("%s: socket %d message length %u is less than %d ",
	       __func__, zclient->sock, length, ZEBRA_HEADER_SIZE);
      return zclient_failed(zclient);
    }

  /* Length check. */
  if (length > STREAM_SIZE(zclient->ibuf))
    {
      struct stream *ns;
      zlog_warn("%s: message size %u exceeds buffer size %lu, expanding...",
	        __func__, length, (u_long)STREAM_SIZE(zclient->ibuf));
      ns = stream_new(length);
      stream_copy(ns, zclient->ibuf);
      stream_free (zclient->ibuf);
      zclient->ibuf = ns;
    }

  /* Read rest of zebra packet. */
  if (already < length)
    {
      ssize_t nbyte;
      if (((nbyte = stream_read_try(zclient->ibuf, zclient->sock,
				     length-already)) == 0) ||
	  (nbyte == -1))
	{
	  if (zclient_debug)
	    zlog_debug("zclient connection closed socket [%d].", zclient->sock);
	  return zclient_failed(zclient);
	}
      if (nbyte != (ssize_t)(length-already))
	{
	  /* Try again later. */
	  zclient_event (ZCLIENT_READ, zclient);
	  return 0;
	}
    }

  length -= ZEBRA_HEADER_SIZE;

  if (zclient_debug)
    zlog_debug("zclient 0x%p command 0x%x \n", (void *)zclient, command);

  switch (command)
    {
    case ZEBRA_ROUTER_ID_UPDATE:
      if (zclient->router_id_update)
	(*zclient->router_id_update) (command, zclient, length);
      break;
    case ZEBRA_INTERFACE_ADD:
      if (zclient->interface_add)
	(*zclient->interface_add) (command, zclient, length);
      break;
    case ZEBRA_INTERFACE_DELETE:
      if (zclient->interface_delete)
	(*zclient->interface_delete) (command, zclient, length);
      break;
    case ZEBRA_INTERFACE_ADDRESS_ADD:
      if (zclient->interface_address_add)
	(*zclient->interface_address_add) (command, zclient, length);
      break;
    case ZEBRA_INTERFACE_ADDRESS_DELETE:
      if (zclient->interface_address_delete)
	(*zclient->interface_address_delete) (command, zclient, length);
      break;
    case ZEBRA_INTERFACE_UP:
      if (zclient->interface_up)
	(*zclient->interface_up) (command, zclient, length);
      break;
    case ZEBRA_INTERFACE_DOWN:
      if (zclient->interface_down)
	(*zclient->interface_down) (command, zclient, length);
      break;
    case ZEBRA_IPV4_ROUTE_ADD:
      if (zclient->ipv4_route_add)
	(*zclient->ipv4_route_add) (command, zclient, length);
      break;
    case ZEBRA_IPV4_ROUTE_DELETE:
      if (zclient->ipv4_route_delete)
	(*zclient->ipv4_route_delete) (command, zclient, length);
      break;
    case ZEBRA_IPV6_ROUTE_ADD:
      if (zclient->ipv6_route_add)
	(*zclient->ipv6_route_add) (command, zclient, length);
      break;
    case ZEBRA_IPV6_ROUTE_DELETE:
      if (zclient->ipv6_route_delete)
	(*zclient->ipv6_route_delete) (command, zclient, length);
      break;
    default:
      break;
    }

  if (zclient->sock < 0)
    /* Connection was closed during packet processing. */
    return -1;

  /* Register read thread. */
  stream_reset(zclient->ibuf);
  zclient_event (ZCLIENT_READ, zclient);

  return 0;
}
Ejemplo n.º 20
0
/* Zebra server IPv6 prefix delete function. */
static int
zread_ipv6_delete (struct zserv *client, u_short length)
{
  int i;
  struct stream *s;
  struct zapi_ipv6 api;
  struct in6_addr nexthop;
  unsigned long ifindex;
  struct prefix_ipv6 p;
  
  s = client->ibuf;
  ifindex = 0;
  memset (&nexthop, 0, sizeof (struct in6_addr));

  /* Type, flags, message. */
  api.type = stream_getc (s);
  api.flags = stream_getc (s);
  api.message = stream_getc (s);
  api.safi = stream_getw (s);

  /* IPv4 prefix. */
  memset (&p, 0, sizeof (struct prefix_ipv6));
  p.family = AF_INET6;
  p.prefixlen = stream_getc (s);
  stream_get (&p.prefix, s, PSIZE (p.prefixlen));

  /* Nexthop, ifindex, distance, metric. */
  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
    {
      u_char nexthop_type;

      api.nexthop_num = stream_getc (s);
      for (i = 0; i < api.nexthop_num; i++)
	{
	  nexthop_type = stream_getc (s);

	  switch (nexthop_type)
	    {
	    case ZEBRA_NEXTHOP_IPV6:
	      stream_get (&nexthop, s, 16);
	      break;
	    case ZEBRA_NEXTHOP_IFINDEX:
	      ifindex = stream_getl (s);
	      break;
	    }
	}
    }

  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
    api.distance = stream_getc (s);
  else
    api.distance = 0;
  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
    api.metric = stream_getl (s);
  else
    api.metric = 0;
    
  if (IN6_IS_ADDR_UNSPECIFIED (&nexthop))
    rib_delete_ipv6 (api.type, api.flags, &p, NULL, ifindex, client->rtm_table, api.safi);
  else
    rib_delete_ipv6 (api.type, api.flags, &p, &nexthop, ifindex, client->rtm_table, api.safi);
  return 0;
}
Ejemplo n.º 21
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.º 22
0
int
shim_sisis_read(struct thread * thread)
{
  struct sisis_listener *listener;
  int sisis_sock;
  uint16_t length, command, checksum;
  int already;
  u_int ifindex;
  struct shim_interface * si;
  struct in6_addr src;
  char src_buf[INET6_ADDRSTRLEN];
  struct in6_addr dst;
  char dst_buf[INET6_ADDRSTRLEN];

  zlog_notice("Reading packet from SISIS connection!\n");

  /* first of all get listener pointer. */
  listener = THREAD_ARG (thread);
  sisis_sock = THREAD_FD (thread);

  if ((already = stream_get_endp(listener->ibuf)) < SV_HEADER_SIZE)
  {
    ssize_t nbytes;
    if (((nbytes = stream_read_try (listener->ibuf, sisis_sock, SV_HEADER_SIZE-already)) == 0) || (nbytes == -1))
    {
      return -1;
    }

    if(nbytes != (SV_HEADER_SIZE - already))
    {
      listener->thread = thread_add_read (master, shim_sisis_read, listener, sisis_sock);
      return 0;
    }
    already = SV_HEADER_SIZE;
  }

  stream_set_getp(listener->ibuf, 0);

  /* read header packet. */
  length = stream_getw (listener->ibuf);
  command = stream_getw (listener->ibuf);

  // will be 0 so may be discarded
  stream_get (&src, listener->ibuf, sizeof (struct in6_addr));
  stream_get (&dst, listener->ibuf, sizeof (struct in6_addr));

  ifindex = stream_getl(listener->ibuf);
  checksum = stream_getw(listener->ibuf);

  inet_ntop(AF_INET6, &src, src_buf, sizeof(src_buf));
  inet_ntop(AF_INET6, &dst, dst_buf, sizeof(dst_buf));

  zlog_debug("SISIS: length: %d, command: %d, ifindex: %d, checksum: %d sock %d, src: %s, dst: %s\n", length, command, ifindex, checksum, sisis_sock, src_buf, dst_buf);

  if(length > STREAM_SIZE(listener->ibuf))
  {
    struct stream * ns;
    zlog_warn("message size exceeds buffer size");
    ns = stream_new(length);
    stream_copy(ns, listener->ibuf);
    stream_free(listener->ibuf);
    listener->ibuf = ns;
  }

  if(already < length)
  {
    ssize_t nbytes;
    if(((nbytes = stream_read_try(listener->ibuf, sisis_sock, length-already)) == 0) || nbytes == -1)
    {
      return -1;
    }
    if(nbytes != (length-already))
    {
      listener->thread = thread_add_read (master, shim_sisis_read, listener, sisis_sock);
      return 0;
    }
  }

  length -= SV_HEADER_SIZE;

  switch(command)
  {
    case SV_JOIN_ALLSPF:
      zlog_debug("join allspf received");
      shim_join_allspfrouters (ifindex);
      break;
    case SV_LEAVE_ALLSPF:
      zlog_debug("leave allspf received");
      shim_leave_allspfrouters (ifindex);
      zlog_debug("index: %d\n", ifindex);
      break;
    case SV_JOIN_ALLD:
      zlog_debug("join alld received");
      shim_join_alldrouters (ifindex);
      zlog_debug("index: %d", ifindex);
      break;
    case SV_LEAVE_ALLD:
      zlog_debug("leave alld received");
      shim_leave_alldrouters (ifindex);
      zlog_debug("index: %d", ifindex);
      break;
    case SV_MESSAGE:
      zlog_debug("SISIS message received");
      unsigned int num_of_addrs = number_of_sisis_addrs_for_process_type(SISIS_PTYPE_RIBCOMP_OSPF6);
      unsigned int num_of_listeners = number_of_listeners();
      zlog_debug("num of listeners: %d, num of addrs: %d", num_of_listeners, num_of_addrs);
      float received_ratio = num_of_listeners/num_of_addrs;
      listener->chksum = checksum;
      if(received_ratio > (1/2))
      {
        if(are_checksums_same())
        {
          si = shim_interface_lookup_by_ifindex (ifindex);
          reset_checksums();
          shim_send(&src, &dst, si, listener->ibuf, length);
//          shim_send(si->linklocal_addr, &dst, si, listener->ibuf, length);
        }
        else
        {
          zlog_notice("Checksums are not all the same");
        }
      }
      else
      {
        zlog_notice("Not enough processes have sent their data: buffering ...");
      }
      break;
    default:
      break;
  }

  if (sisis_sock < 0)
    /* Connection was closed during packet processing. */
    return -1;

  /* Register read thread. */
  stream_reset(listener->ibuf);

  /* prepare for next packet. */
  listener->thread = thread_add_read (master, shim_sisis_read, listener, sisis_sock);

  return 0;
}
Ejemplo n.º 23
0
static int
bgp_import_check (struct prefix *p, u_int32_t *igpmetric,
                  struct in_addr *igpnexthop)
{
  struct stream *s;
  int ret;
  u_int16_t length, command;
  u_char version, marker;
  int nbytes;
  struct in_addr addr;
  struct in_addr nexthop;
  u_int32_t metric = 0;
  u_char nexthop_num;
  u_char nexthop_type;

  /* If lookup connection is not available return valid. */
  if (zlookup->sock < 0)
    {
      if (igpmetric)
	*igpmetric = 0;
      return 1;
    }

  /* Send query to the lookup connection */
  s = zlookup->obuf;
  stream_reset (s);
  zclient_create_header (s, ZEBRA_IPV4_IMPORT_LOOKUP);
  
  stream_putc (s, p->prefixlen);
  stream_put_in_addr (s, &p->u.prefix4);
  
  stream_putw_at (s, 0, stream_get_endp (s));
  
  /* Write the packet. */
  ret = writen (zlookup->sock, s->data, stream_get_endp (s));

  if (ret < 0)
    {
      zlog_err ("can't write to zlookup->sock");
      close (zlookup->sock);
      zlookup->sock = -1;
      return 1;
    }
  if (ret == 0)
    {
      zlog_err ("zlookup->sock connection closed");
      close (zlookup->sock);
      zlookup->sock = -1;
      return 1;
    }

  /* Get result. */
  stream_reset (s);

  /* Fetch length. */
  nbytes = stream_read (s, zlookup->sock, 2);
  length = stream_getw (s);

  /* Fetch whole data. */
  nbytes = stream_read (s, zlookup->sock, length - 2);
  marker = stream_getc (s);
  version = stream_getc (s);

  if (version != ZSERV_VERSION || marker != ZEBRA_HEADER_MARKER)
    {
      zlog_err("%s: socket %d version mismatch, marker %d, version %d",
               __func__, zlookup->sock, marker, version);
      return 0;
    }
    
  command = stream_getw (s);
  
  addr.s_addr = stream_get_ipv4 (s);
  metric = stream_getl (s);
  nexthop_num = stream_getc (s);

  /* Set IGP metric value. */
  if (igpmetric)
    *igpmetric = metric;

  /* If there is nexthop then this is active route. */
  if (nexthop_num)
    {
      nexthop.s_addr = 0;
      nexthop_type = stream_getc (s);
      if (nexthop_type == ZEBRA_NEXTHOP_IPV4)
	{
	  nexthop.s_addr = stream_get_ipv4 (s);
	  if (igpnexthop)
	    *igpnexthop = nexthop;
	}
      else
	*igpnexthop = nexthop;

      return 1;
    }
  else
    return 0;
}
Ejemplo n.º 24
0
static int
bgp_capability_restart (struct peer *peer, struct capability_header *caphdr)
{
    struct stream *s = BGP_INPUT (peer);
    u_int16_t restart_flag_time;
    size_t end = stream_get_getp (s) + caphdr->length;

    SET_FLAG (peer->cap, PEER_CAP_RESTART_RCV);
    restart_flag_time = stream_getw(s);
    if (CHECK_FLAG (restart_flag_time, RESTART_R_BIT))
        SET_FLAG (peer->cap, PEER_CAP_RESTART_BIT_RCV);

    UNSET_FLAG (restart_flag_time, 0xF000);
    peer->v_gr_restart = restart_flag_time;

    if (BGP_DEBUG (normal, NORMAL))
    {
        zlog_debug ("%s OPEN has Graceful Restart capability", peer->host);
        zlog_debug ("%s Peer has%srestarted. Restart Time : %d",
                    peer->host,
                    CHECK_FLAG (peer->cap, PEER_CAP_RESTART_BIT_RCV) ? " "
                    : " not ",
                    peer->v_gr_restart);
    }

    while (stream_get_getp (s) + 4 <= end)
    {
        afi_t afi = stream_getw (s);
        safi_t safi = stream_getc (s);
        u_char flag = stream_getc (s);

        if (!bgp_afi_safi_valid_indices (afi, &safi))
        {
            if (BGP_DEBUG (normal, NORMAL))
                zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported."
                            " Ignore the Graceful Restart capability",
                            peer->host, afi, safi);
        }
        else if (!peer->afc[afi][safi])
        {
            if (BGP_DEBUG (normal, NORMAL))
                zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled."
                            " Ignore the Graceful Restart capability",
                            peer->host, afi, safi);
        }
        else
        {
            if (BGP_DEBUG (normal, NORMAL))
                zlog_debug ("%s Address family %s is%spreserved", peer->host,
                            afi_safi_print (afi, safi),
                            CHECK_FLAG (peer->af_cap[afi][safi],
                                        PEER_CAP_RESTART_AF_PRESERVE_RCV)
                            ? " " : " not ");

            SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV);
            if (CHECK_FLAG (flag, RESTART_F_BIT))
                SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV);

        }
    }
    return 0;
}