Exemplo n.º 1
0
/* Dump common header. */
void
bgp_dump_header (struct stream *obuf, int type, int subtype)
{
  time_t now;

  /* Set header. */
  time (&now);

  /* Put dump packet header. */
  stream_putl (obuf, now);	
  stream_putw (obuf, type);
  stream_putw (obuf, subtype);

  stream_putl (obuf, 0);	/* len */
}
Exemplo n.º 2
0
int
main (void)
{
  struct stream *s;
  
  s = stream_new (1024);
  
  stream_putc (s, ham);
  stream_putw (s, ham);
  stream_putl (s, ham);
  stream_putq (s, ham);
  
  print_stream (s);
  
  stream_resize (s, stream_get_endp (s));
  
  print_stream (s);
  
  printf ("c: 0x%hhx\n", stream_getc (s));
  printf ("w: 0x%hx\n", stream_getw (s));
  printf ("l: 0x%x\n", stream_getl (s));
  printf ("q: 0x%" PRIu64 "\n", stream_getq (s));
  
  return 0;
}
Exemplo n.º 3
0
/* Dump common information. */
static void
bgp_dump_common (struct stream *obuf, struct peer *peer, int forceas4)
{
  char empty[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

  /* Source AS number and Destination AS number. */
  if (forceas4 || CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) )
    {
      stream_putl (obuf, peer->as);
      stream_putl (obuf, peer->local_as);
    }
  else
    {
      stream_putw (obuf, peer->as);
      stream_putw (obuf, peer->local_as);
    }

  if (peer->su.sa.sa_family == AF_INET)
    {
      stream_putw (obuf, peer->ifindex);
      stream_putw (obuf, AFI_IP);

      stream_put (obuf, &peer->su.sin.sin_addr, IPV4_MAX_BYTELEN);

      if (peer->su_local)
	stream_put (obuf, &peer->su_local->sin.sin_addr, IPV4_MAX_BYTELEN);
      else
	stream_put (obuf, empty, IPV4_MAX_BYTELEN);
    }
#ifdef HAVE_IPV6
  else if (peer->su.sa.sa_family == AF_INET6)
    {
      /* Interface Index and Address family. */
      stream_putw (obuf, peer->ifindex);
      stream_putw (obuf, AFI_IP6);

      /* Source IP Address and Destination IP Address. */
      stream_put (obuf, &peer->su.sin6.sin6_addr, IPV6_MAX_BYTELEN);

      if (peer->su_local)
	stream_put (obuf, &peer->su_local->sin6.sin6_addr, IPV6_MAX_BYTELEN);
      else
	stream_put (obuf, empty, IPV6_MAX_BYTELEN);
    }
#endif /* HAVE_IPV6 */
}
Exemplo n.º 4
0
Arquivo: zserv.c Projeto: OPSF/uClinux
int
zsend_interface_delete (struct zserv *client, struct interface *ifp)
{
  struct stream *s;

  /* Check this client need interface information. */
  if (! client->ifinfo)
    return -1;

  s = client->obuf;
  stream_reset (s);

  /* Packet length placeholder. */
  stream_putw (s, 0);

  /* Interface information. */
  stream_putc (s, ZEBRA_INTERFACE_DELETE);
  stream_put (s, ifp->name, INTERFACE_NAMSIZ);
  stream_putl (s, ifp->ifindex);
  stream_putc (s, ifp->status);
  stream_putl (s, ifp->flags);
  stream_putl (s, ifp->metric);
  stream_putl (s, ifp->mtu);
  stream_putl (s, ifp->mtu6);
  stream_putl (s, ifp->bandwidth);

  /* Write packet length. */
  stream_putw_at (s, 0, stream_get_endp (s));

  zebra_server_send_message (client->sock, s->data, stream_get_endp (s));

  return 0;
}
Exemplo n.º 5
0
Arquivo: zserv.c Projeto: OPSF/uClinux
/*
 * The cmd passed to zsend_interface_update  may be ZEBRA_INTERFACE_UP or
 * ZEBRA_INTERFACE_DOWN.
 *
 * The ZEBRA_INTERFACE_UP message is sent from the zebra server to
 * the clients in one of 2 situations:
 *   - an if_up is detected e.g., as a result of an RTM_IFINFO message
 *   - a vty command modifying the bandwidth of an interface is received.
 * The ZEBRA_INTERFACE_DOWN message is sent when an if_down is detected.
 */
int
zsend_interface_update (int cmd, struct zserv *client, struct interface *ifp)
{
  struct stream *s;

  /* Check this client need interface information. */
  if (! client->ifinfo)
    return -1;

  s = client->obuf;
  stream_reset (s);

  /* Place holder for size. */
  stream_putw (s, 0);

  /* Zebra command. */
  stream_putc (s, cmd);

  /* Interface information. */
  stream_put (s, ifp->name, INTERFACE_NAMSIZ);
  stream_putl (s, ifp->ifindex);
  stream_putc (s, ifp->status);
  stream_putl (s, ifp->flags);
  stream_putl (s, ifp->metric);
  stream_putl (s, ifp->mtu);
  stream_putl (s, ifp->mtu6);
  stream_putl (s, ifp->bandwidth);

  /* Write packet size. */
  stream_putw_at (s, 0, stream_get_endp (s));

  zebra_server_send_message (client->sock, s->data, stream_get_endp (s));

  return 0;
}
Exemplo n.º 6
0
Arquivo: zserv.c Projeto: OPSF/uClinux
/* Interface address is added/deleted. Send ZEBRA_INTERFACE_ADDRESS_ADD or
 * ZEBRA_INTERFACE_ADDRESS_DELETE to the client. 
 *
 * A ZEBRA_INTERFACE_ADDRESS_ADD is sent in the following situations:
 * - in response to a 3-byte ZEBRA_INTERFACE_ADD request
 *   from the client, after the ZEBRA_INTERFACE_ADD has been
 *   sent from zebra to the client
 * - redistribute new address info to all clients in the following situations
 *    - at startup, when zebra figures out the available interfaces
 *    - when an interface is added (where support for
 *      RTM_IFANNOUNCE or AF_NETLINK sockets is available), or when
 *      an interface is marked IFF_UP (i.e., an RTM_IFINFO message is
 *      received)
 *    - for the vty commands "ip address A.B.C.D/M [<secondary>|<label LINE>]"
 *      and "no bandwidth <1-10000000>", "ipv6 address X:X::X:X/M"
 *    - when an RTM_NEWADDR message is received from the kernel,
 * 
 * The call tree that triggers ZEBRA_INTERFACE_ADDRESS_DELETE: 
 *
 *                   zsend_interface_address(DELETE)
 *                           ^                         
 *                           |                        
 *          zebra_interface_address_delete_update    
 *             ^                        ^      ^
 *             |                        |      if_delete_update (not called on 
 *             |                        |                         Solaris)
 *         ip_address_uninstall        connected_delete_ipv4
 *         [ipv6_addresss_uninstall]   [connected_delete_ipv6]
 *             ^                        ^
 *             |                        |
 *             |                  RTM_NEWADDR on routing/netlink socket
 *             |
 *         vty commands:
 *     "no ip address A.B.C.D/M [label LINE]"
 *     "no ip address A.B.C.D/M secondary"
 *     ["no ipv6 address X:X::X:X/M"]
 *
 */
int
zsend_interface_address (int cmd, struct zserv *client, 
                         struct interface *ifp, struct connected *ifc)
{
  int blen;
  struct stream *s;
  struct prefix *p;

  /* Check this client need interface information. */
  if (! client->ifinfo)
    return -1;

  s = client->obuf;
  stream_reset (s);

  /* Place holder for size. */
  stream_putw (s, 0);

  stream_putc (s, cmd);
  stream_putl (s, ifp->ifindex);

  /* Interface address flag. */
  stream_putc (s, ifc->flags);

  /* Prefix information. */
  p = ifc->address;
  stream_putc (s, p->family);
  blen = prefix_blen (p);
  stream_put (s, &p->u.prefix, blen);

  /* 
   * XXX gnu version does not send prefixlen for ZEBRA_INTERFACE_ADDRESS_DELETE
   * but zebra_interface_address_delete_read() in the gnu version 
   * expects to find it
   */
  stream_putc (s, p->prefixlen);

  /* Destination. */
  p = ifc->destination;
  if (p)
    stream_put (s, &p->u.prefix, blen);
  else
    stream_put (s, NULL, blen);

  /* Write packet size. */
  stream_putw_at (s, 0, stream_get_endp (s));

  zebra_server_send_message (client->sock, s->data, stream_get_endp (s));

  return 0;
}
Exemplo n.º 7
0
size_t
zebra_interface_link_params_write (struct stream *s, struct interface *ifp)
{
  size_t w;
  struct if_link_params *iflp;
  int i;
  
  if (s == NULL || ifp == NULL || ifp->link_params == NULL)
    return 0;
  
  iflp = ifp->link_params;
  w = 0;
    
  w += stream_putl (s, iflp->lp_status);

  w += stream_putl (s, iflp->te_metric);
  w += stream_putf (s, iflp->max_bw);
  w += stream_putf (s, iflp->max_rsv_bw);
  
  w += stream_putl (s, MAX_CLASS_TYPE);
  for (i = 0; i < MAX_CLASS_TYPE; i++)
    w += stream_putf (s, iflp->unrsv_bw[i]);
  
  w += stream_putl (s, iflp->admin_grp);
  w += stream_putl (s, iflp->rmt_as);
  w += stream_put_in_addr (s, &iflp->rmt_ip);
  
  w += stream_putl (s, iflp->av_delay);
  w += stream_putl (s, iflp->min_delay);
  w += stream_putl (s, iflp->max_delay);
  w += stream_putl (s, iflp->delay_var);
  
  w += stream_putf (s, iflp->pkt_loss);
  w += stream_putf (s, iflp->res_bw);
  w += stream_putf (s, iflp->ava_bw);
  w += stream_putf (s, iflp->use_bw);
  
  return w;
}
static int ppp_tcp_client_keepalive_timer (struct thread *thread)
{
	struct ppp_mcp_sock *peer;
    struct stream* s_new;
    
	peer = THREAD_ARG (thread);
	peer->t_keepalive = NULL;
	
	PPPD_DEBUG_TCP("Timer (keepalive timer expire), peer:%s", peer->hostname);
	s_new = stream_new(1024);
	stream_putl(s_new, 4);
    ppp_put_control_to_stream(s_new, REMARK_KEEPALIVE_CMD);
    stream_fifo_push (peer->obuf, s_new);
    MCP_WRITE_ON (peer->t_write, ppp_tcp_write, peer, peer->fd);
	MCP_TIMER_ON (peer->t_keepalive, ppp_tcp_client_keepalive_timer, peer, CLIENT_CONNECT_KEEPALIVE_TIMER);
	return 0;
}
Exemplo n.º 9
0
s32 bgp_fec_announce_6pe(struct zclient *zc, struct prefix *p, struct bgp_info *info, struct bgp *bgp)
{
    u32 flags = 0;
    struct stream * s  = zc->obuf ;
    struct peer * peer = info->peer ;
    u32 gateway ,label ;
    struct rtm_fec_info_key key;
    struct in6_addr *nexthop = NULL;

    if( !info || !info->attr || !info->attr->extra ) 
        return -1 ;
        
    if (info->attr->extra->mp_nexthop_len == 16)
    {
    	nexthop = &info->attr->extra->mp_nexthop_global;
    }  
    /* If both global and link-local address present. */
    else if (info->attr->extra->mp_nexthop_len == 32)
	{
	    /* Workaround for Cisco's nexthop bug.  */
	    if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->extra->mp_nexthop_global)
	        && peer->su_remote->sa.sa_family == AF_INET6)
	    	nexthop = &peer->su_remote->sin6.sin6_addr;
	    else
	    	nexthop = &info->attr->extra->mp_nexthop_local;
	}
	if(NULL == nexthop || !IN6_IS_ADDR_V4MAPPED(nexthop))
	{
	    return -1;
	}
	memcpy (&gateway , ((s8 *)nexthop) + 12, 4);
    label  = decode_label ( bgp_info_extra_get(info)->tag) ;

    SET_FLAG(flags, ZAPI_FEC_GATEWAY);
    stream_reset(s);
    zclient_create_header(s,ZEBRA_MPLS_FEC6_INFO_ADD);
    stream_put_prefix(s,p);
	stream_putl(s, flags);
    stream_putl(s, ZEBRA_FEC_TYPE_6PE);
    if( peer )
        stream_putl(s,peer->nexthop.v4.s_addr);
    else
        stream_putl(s,0); // lsr_id = 0 
    stream_putl(s,label);
    stream_putl(s,gateway);

    stream_putw_at (s, 0, stream_get_endp (s));
    key.peer_addr = gateway;

    return rtm_fec_send(ZEBRA_MPLS_FEC6_INFO_ADD, zc, p, s, &key) ;
}
Exemplo n.º 10
0
Arquivo: zserv.c Projeto: OPSF/uClinux
/*
 * This function is called in the following situations:
 * - in response to a 3-byte ZEBRA_INTERFACE_ADD request
 *   from the client.
 * - at startup, when zebra figures out the available interfaces
 * - when an interface is added (where support for
 *   RTM_IFANNOUNCE or AF_NETLINK sockets is available), or when
 *   an interface is marked IFF_UP (i.e., an RTM_IFINFO message is
 *   received)
 */
int
zsend_interface_add (struct zserv *client, struct interface *ifp)
{
  struct stream *s;

  /* Check this client need interface information. */
  if (! client->ifinfo)
    return -1;

  s = client->obuf;
  stream_reset (s);

  /* Place holder for size. */
  stream_putw (s, 0);

  /* Message type. */
  stream_putc (s, ZEBRA_INTERFACE_ADD);

  /* Interface information. */
  stream_put (s, ifp->name, INTERFACE_NAMSIZ);
  stream_putl (s, ifp->ifindex);
  stream_putc (s, ifp->status);
  stream_putl (s, ifp->flags);
  stream_putl (s, ifp->metric);
  stream_putl (s, ifp->mtu);
  stream_putl (s, ifp->mtu6);
  stream_putl (s, ifp->bandwidth);
#ifdef HAVE_SOCKADDR_DL
  stream_put (s, &ifp->sdl, sizeof (ifp->sdl));
#else
  stream_putl (s, ifp->hw_addr_len);
  if (ifp->hw_addr_len)
    stream_put (s, ifp->hw_addr, ifp->hw_addr_len);
#endif /* HAVE_SOCKADDR_DL */

  /* Write packet size. */
  stream_putw_at (s, 0, stream_get_endp (s));

  zebra_server_send_message (client->sock, s->data, stream_get_endp (s));

  return 0;
}
Exemplo n.º 11
0
s32 bgp_fec_announce_6vpe(bgp_litevrf_config_t *litevrf, struct prefix *p, struct bgp_info *info)
{
    u32 flags = 0;
    struct stream * s  = zclient->obuf ;
    struct peer * peer = info->peer ;
    u32 gateway ,label ;
    struct rtm_fec_info_key key;
    struct in6_addr *nexthop = NULL;

    if( !info || !info->attr || !info->attr->extra ) 
        return -1 ;
        
    nexthop = &info->attr->extra->mp_nexthop_global;

    
	if(NULL == nexthop || !IN6_IS_ADDR_V4MAPPED(nexthop))
	{
	    return -1;
	}
	memcpy (&gateway , ((s8 *)nexthop) + 12, 4);
    label  = decode_label ( bgp_info_extra_get(info)->tag) ;

    SET_FLAG(flags, ZAPI_FEC_GATEWAY|ZAPI_FEC_LITEVRF);
    stream_reset(s);
    zclient_create_header(s,ZEBRA_MPLS_FEC6_INFO_ADD);
    stream_put_prefix(s,p);
	stream_putl(s, flags);
	stream_putl(s,litevrf->id);
    stream_putl(s, ZEBRA_FEC_TYPE_6VPE);
    if( peer )
        stream_putl(s,peer->nexthop.v4.s_addr);
    else
        stream_putl(s,0); // lsr_id = 0 
    stream_putl(s,label);
    stream_putl(s,gateway);

    stream_putw_at (s, 0, stream_get_endp (s));
    key.peer_addr = gateway;

    return rtm_fec_send(ZEBRA_MPLS_FEC6_INFO_ADD, zclient, p, s, &key) ;
}
Exemplo n.º 12
0
void remark_bundle_notify_mcp(unsigned int ifnum, unsigned int ifunit)
{
    struct remark_bundle bundleinfo;
    struct ppp_mcp_sock *peer;
    struct stream* s_new;

    return;
    peer = g_ppp_mcp_sock;
    
    bundleinfo.master = ifnum;
    bundleinfo.slave = ifunit;

    s_new = stream_new(1024);
    stream_putl(s_new, 4 + sizeof(struct remark_bundle));
    ppp_put_control_to_stream(s_new, REMARK_BUDLE_CMD);
    stream_put(s_new, (unsigned char*)(&bundleinfo), sizeof(struct remark_bundle));
    stream_fifo_push (peer->obuf, s_new);

    MCP_WRITE_ON (peer->t_write, ppp_tcp_write, peer, peer->fd);
//    MCP_TIMER_ON (peer->t_wait_bundle_ack, ppp_tcp_wait_notify_ack_timer, peer, CLIENT_WAIT_IPINFO_ACK_TIMER);

    return;
}
Exemplo n.º 13
0
void zebra_ipmr_route_stats(ZAPI_HANDLER_ARGS)
{
	struct mcast_route_data mroute;
	struct stream *s;
	int suc = -1;

	memset(&mroute, 0, sizeof(mroute));
	STREAM_GET(&mroute.sg.src, msg, 4);
	STREAM_GET(&mroute.sg.grp, msg, 4);
	STREAM_GETL(msg, mroute.ifindex);

	if (IS_ZEBRA_DEBUG_KERNEL) {
		char sbuf[40];
		char gbuf[40];

		strlcpy(sbuf, inet_ntoa(mroute.sg.src), sizeof(sbuf));
		strlcpy(gbuf, inet_ntoa(mroute.sg.grp), sizeof(gbuf));

		zlog_debug("Asking for (%s,%s) mroute information", sbuf, gbuf);
	}

	suc = kernel_get_ipmr_sg_stats(zvrf, &mroute);

stream_failure:
	s = stream_new(ZEBRA_MAX_PACKET_SIZ);

	stream_reset(s);

	zclient_create_header(s, ZEBRA_IPMR_ROUTE_STATS, zvrf_id(zvrf));
	stream_put_in_addr(s, &mroute.sg.src);
	stream_put_in_addr(s, &mroute.sg.grp);
	stream_put(s, &mroute.lastused, sizeof(mroute.lastused));
	stream_putl(s, suc);

	stream_putw_at(s, 0, stream_get_endp(s));
	zserv_send_message(client, s);
}
Exemplo n.º 14
0
static void
zserv_encode_interface (struct stream *s, struct interface *ifp)
{
  /* Interface information. */
  stream_put (s, ifp->name, INTERFACE_NAMSIZ);
  stream_putl (s, ifp->ifindex);
  stream_putc (s, ifp->status);
  stream_putq (s, ifp->flags);
  stream_putl (s, ifp->metric);
  stream_putl (s, ifp->mtu);
  stream_putl (s, ifp->mtu6);
  stream_putl (s, ifp->bandwidth);
#ifdef HAVE_STRUCT_SOCKADDR_DL
  stream_put (s, &ifp->sdl, sizeof (ifp->sdl_storage));
#else
  stream_putl (s, ifp->hw_addr_len);
  if (ifp->hw_addr_len)
    stream_put (s, ifp->hw_addr, ifp->hw_addr_len);
#endif /* HAVE_STRUCT_SOCKADDR_DL */

  /* Write packet size. */
  stream_putw_at (s, 0, stream_get_endp (s));
}
Exemplo n.º 15
0
Arquivo: zserv.c Projeto: OPSF/uClinux
int
zsend_ipv6_nexthop_lookup (struct zserv *client, struct in6_addr *addr)
{
  struct stream *s;
  struct rib *rib;
  unsigned long nump;
  u_char num;
  struct nexthop *nexthop;

  /* Lookup nexthop. */
  rib = rib_match_ipv6 (addr);

  /* Get output stream. */
  s = client->obuf;
  stream_reset (s);

  /* Fill in result. */
  stream_putw (s, 0);
  stream_putc (s, ZEBRA_IPV6_NEXTHOP_LOOKUP);
  stream_put (s, &addr, 16);

  if (rib)
    {
      stream_putl (s, rib->metric);
      num = 0;
      nump = s->putp;
      stream_putc (s, 0);
      for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
	if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
	  {
	    stream_putc (s, nexthop->type);
	    switch (nexthop->type)
	      {
	      case ZEBRA_NEXTHOP_IPV6:
		stream_put (s, &nexthop->gate.ipv6, 16);
		break;
	      case ZEBRA_NEXTHOP_IPV6_IFINDEX:
	      case ZEBRA_NEXTHOP_IPV6_IFNAME:
		stream_put (s, &nexthop->gate.ipv6, 16);
		stream_putl (s, nexthop->ifindex);
		break;
	      case ZEBRA_NEXTHOP_IFINDEX:
	      case ZEBRA_NEXTHOP_IFNAME:
		stream_putl (s, nexthop->ifindex);
		break;
	      default:
                /* do nothing */
		break;
	      }
	    num++;
	  }
      stream_putc_at (s, nump, num);
    }
  else
    {
      stream_putl (s, 0);
      stream_putc (s, 0);
    }

  stream_putw_at (s, 0, stream_get_endp (s));
  
  zebra_server_send_message (client->sock, s->data, stream_get_endp (s));

  return 0;
}
Exemplo n.º 16
0
Arquivo: zserv.c Projeto: OPSF/uClinux
/*
 * The zebra server sends the clients  a ZEBRA_IPV4_ROUTE_ADD or a
 * ZEBRA_IPV6_ROUTE_ADD via zsend_route_multipath in the following
 * situations:
 * - when the client starts up, and requests default information
 *   by sending a ZEBRA_REDISTRIBUTE_DEFAULT_ADD to the zebra server, in the
 * - case of rip, ripngd, ospfd and ospf6d, when the client sends a
 *   ZEBRA_REDISTRIBUTE_ADD as a result of the "redistribute" vty cmd,
 * - when the zebra server redistributes routes after it updates its rib
 *
 * The zebra server sends clients a ZEBRA_IPV4_ROUTE_DELETE or a
 * ZEBRA_IPV6_ROUTE_DELETE via zsend_route_multipath when:
 * - a "ip route"  or "ipv6 route" vty command is issued, a prefix is
 * - deleted from zebra's rib, and this info
 *   has to be redistributed to the clients 
 * 
 * XXX The ZEBRA_IPV*_ROUTE_ADD message is also sent by the client to the
 * zebra server when the client wants to tell the zebra server to add a
 * route to the kernel (zapi_ipv4_add etc. ).  Since it's essentially the
 * same message being sent back and forth, this function and
 * zapi_ipv{4,6}_{add, delete} should be re-written to avoid code
 * duplication.
 */
int
zsend_route_multipath (int cmd, struct zserv *client, struct prefix *p,
                       struct rib *rib)
{
  int psize;
  struct stream *s;
  struct nexthop *nexthop;
  unsigned long nhnummark = 0;
  int nhnum = 0;
  u_char zapi_flags = ZAPI_MESSAGE_NEXTHOP | ZAPI_MESSAGE_IFINDEX;
  
  s = client->obuf;
  stream_reset (s);

  /* Place holder for size. */
  stream_putw (s, 0);

  /* Put command, type and nexthop. */
  stream_putc (s, cmd);
  stream_putc (s, rib->type);
  stream_putc (s, rib->flags);

  /* 
   * XXX no need to set ZAPI_MESSAGE_NEXTHOP if we are going to
   * send empty nexthop?
   */
  if (cmd == ZEBRA_IPV4_ROUTE_ADD || ZEBRA_IPV6_ROUTE_ADD)
    zapi_flags |= ZAPI_MESSAGE_METRIC;

  stream_putc (s, zapi_flags);

  /* Prefix. */
  psize = PSIZE (p->prefixlen);
  stream_putc (s, p->prefixlen);
  stream_write (s, (u_char *) & p->u.prefix, psize);

  /* 
   * XXX The message format sent by zebra below does not match the format
   * of the corresponding message expected by the zebra server
   * itself (e.g., see zread_ipv4_add). The nexthop_num is not set correctly,
   * (is there a bug on the client side if more than one segment is sent?)
   * nexthop ZEBRA_NEXTHOP_IPV4 is never set, ZEBRA_NEXTHOP_IFINDEX 
   * is hard-coded.
   */
  /* Nexthop */
  for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
    {
      if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
        {
          nhnummark = stream_get_putp (s);
          stream_putc (s, 1); /* placeholder */
          nhnum++;

          switch(nexthop->type) 
            {
              case NEXTHOP_TYPE_IPV4:
              case NEXTHOP_TYPE_IPV4_IFINDEX:
                stream_put_in_addr (s, &nexthop->gate.ipv4);
                break;
#ifdef HAVE_IPV6
              case NEXTHOP_TYPE_IPV6:
              case NEXTHOP_TYPE_IPV6_IFINDEX:
              case NEXTHOP_TYPE_IPV6_IFNAME:
                stream_write (s, (u_char *) &nexthop->gate.ipv6, 16);
                break;
#endif
              default:
                if (cmd == ZEBRA_IPV4_ROUTE_ADD 
                    || cmd == ZEBRA_IPV4_ROUTE_DELETE)
                  {
                    struct in_addr empty;
                    memset (&empty, 0, sizeof (struct in_addr));
                    stream_write (s, (u_char *) &empty, IPV4_MAX_BYTELEN);
                  }
                else
                  {
                    struct in6_addr empty;
                    memset (&empty, 0, sizeof (struct in6_addr));
                    stream_write (s, (u_char *) &empty, IPV6_MAX_BYTELEN);
                  }
              }

          /* Interface index. */
          stream_putc (s, 1);
          stream_putl (s, nexthop->ifindex);

          break;
        }
    }

  /* Metric */
  stream_putl (s, rib->metric);

  /* Write next-hop number */
  if (nhnummark)
    stream_putc_at (s, nhnummark, nhnum);
  
  /* Write packet size. */
  stream_putw_at (s, 0, stream_get_endp (s));

  zebra_server_send_message (client->sock, s->data, stream_get_endp (s));

  return 0;
}
Exemplo n.º 17
0
static int
zsend_ipv4_nexthop_lookup (struct zserv *client, struct in_addr addr)
{
  struct stream *s;
  struct rib *rib;
  unsigned long nump;
  u_char num;
  struct nexthop *nexthop;

  /* Lookup nexthop. */
  rib = rib_match_ipv4 (addr);

  /* Get output stream. */
  s = client->obuf;
  stream_reset (s);

  /* Fill in result. */
  zserv_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP);
  stream_put_in_addr (s, &addr);

  if (rib)
    {
      if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
        zlog_debug("%s: Matching rib entry found.", __func__);
      stream_putl (s, rib->metric);
      num = 0;
      nump = stream_get_endp(s);
      stream_putc (s, 0);
      for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
	if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
	  {
	    stream_putc (s, nexthop->type);
	    switch (nexthop->type)
	      {
	      case ZEBRA_NEXTHOP_IPV4:
		stream_put_in_addr (s, &nexthop->gate.ipv4);
		break;
	      case ZEBRA_NEXTHOP_IPV4_IFINDEX:
		stream_put_in_addr (s, &nexthop->gate.ipv4);
		stream_putl (s, nexthop->ifindex);
		break;
	      case ZEBRA_NEXTHOP_IFINDEX:
	      case ZEBRA_NEXTHOP_IFNAME:
		stream_putl (s, nexthop->ifindex);
		break;
	      default:
                /* do nothing */
		break;
	      }
	    num++;
	  }
      stream_putc_at (s, nump, num);
    }
  else
    {
      if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
        zlog_debug("%s: No matching rib entry found.", __func__);
      stream_putl (s, 0);
      stream_putc (s, 0);
    }

  stream_putw_at (s, 0, stream_get_endp (s));
  
  return zebra_server_send_message(client);
}
Exemplo n.º 18
0
static int
zsend_ipv4_import_lookup (struct zserv *client, struct prefix_ipv4 *p)
{
  struct stream *s;
  struct rib *rib;
  unsigned long nump;
  u_char num;
  struct nexthop *nexthop;

  /* Lookup nexthop. */
  rib = rib_lookup_ipv4 (p);

  /* Get output stream. */
  s = client->obuf;
  stream_reset (s);

  /* Fill in result. */
  zserv_create_header (s, ZEBRA_IPV4_IMPORT_LOOKUP);
  stream_put_in_addr (s, &p->prefix);

  if (rib)
    {
      stream_putl (s, rib->metric);
      num = 0;
      nump = stream_get_endp(s);
      stream_putc (s, 0);
      for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
	if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
	  {
	    stream_putc (s, nexthop->type);
	    switch (nexthop->type)
	      {
	      case ZEBRA_NEXTHOP_IPV4:
		stream_put_in_addr (s, &nexthop->gate.ipv4);
		break;
	      case ZEBRA_NEXTHOP_IPV4_IFINDEX:
		stream_put_in_addr (s, &nexthop->gate.ipv4);
		stream_putl (s, nexthop->ifindex);
		break;
	      case ZEBRA_NEXTHOP_IFINDEX:
	      case ZEBRA_NEXTHOP_IFNAME:
		stream_putl (s, nexthop->ifindex);
		break;
	      default:
                /* do nothing */
		break;
	      }
	    num++;
	  }
      stream_putc_at (s, nump, num);
    }
  else
    {
      stream_putl (s, 0);
      stream_putc (s, 0);
    }

  stream_putw_at (s, 0, stream_get_endp (s));
  
  return zebra_server_send_message(client);
}
Exemplo n.º 19
0
/* Fill in capability open option to the packet. */
void
bgp_open_capability (struct stream *s, struct peer *peer)
{
    u_char len;
    unsigned long cp, capp, rcapp;
    afi_t afi;
    safi_t safi;
    as_t local_as;
    u_int32_t restart_time;

    /* Remember current pointer for Opt Parm Len. */
    cp = stream_get_endp (s);

    /* Opt Parm Len. */
    stream_putc (s, 0);

    /* Do not send capability. */
    if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN)
            || CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
        return;

    /* IPv4 unicast. */
    if (peer->afc[AFI_IP][SAFI_UNICAST])
    {
        peer->afc_adv[AFI_IP][SAFI_UNICAST] = 1;
        stream_putc (s, BGP_OPEN_OPT_CAP);
        stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
        stream_putc (s, CAPABILITY_CODE_MP);
        stream_putc (s, CAPABILITY_CODE_MP_LEN);
        stream_putw (s, AFI_IP);
        stream_putc (s, 0);
        stream_putc (s, SAFI_UNICAST);
    }
    /* IPv4 multicast. */
    if (peer->afc[AFI_IP][SAFI_MULTICAST])
    {
        peer->afc_adv[AFI_IP][SAFI_MULTICAST] = 1;
        stream_putc (s, BGP_OPEN_OPT_CAP);
        stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
        stream_putc (s, CAPABILITY_CODE_MP);
        stream_putc (s, CAPABILITY_CODE_MP_LEN);
        stream_putw (s, AFI_IP);
        stream_putc (s, 0);
        stream_putc (s, SAFI_MULTICAST);
    }
    /* IPv4 VPN */
    if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
    {
        peer->afc_adv[AFI_IP][SAFI_MPLS_VPN] = 1;
        stream_putc (s, BGP_OPEN_OPT_CAP);
        stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
        stream_putc (s, CAPABILITY_CODE_MP);
        stream_putc (s, CAPABILITY_CODE_MP_LEN);
        stream_putw (s, AFI_IP);
        stream_putc (s, 0);
        stream_putc (s, SAFI_MPLS_LABELED_VPN);
    }
    /* ENCAP */
    if (peer->afc[AFI_IP][SAFI_ENCAP])
    {
        peer->afc_adv[AFI_IP][SAFI_ENCAP] = 1;
        stream_putc (s, BGP_OPEN_OPT_CAP);
        stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
        stream_putc (s, CAPABILITY_CODE_MP);
        stream_putc (s, CAPABILITY_CODE_MP_LEN);
        stream_putw (s, AFI_IP);
        stream_putc (s, 0);
        stream_putc (s, SAFI_ENCAP);
    }
    /* IPv6 unicast. */
    if (peer->afc[AFI_IP6][SAFI_UNICAST])
    {
        peer->afc_adv[AFI_IP6][SAFI_UNICAST] = 1;
        stream_putc (s, BGP_OPEN_OPT_CAP);
        stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
        stream_putc (s, CAPABILITY_CODE_MP);
        stream_putc (s, CAPABILITY_CODE_MP_LEN);
        stream_putw (s, AFI_IP6);
        stream_putc (s, 0);
        stream_putc (s, SAFI_UNICAST);
    }
    /* IPv6 multicast. */
    if (peer->afc[AFI_IP6][SAFI_MULTICAST])
    {
        peer->afc_adv[AFI_IP6][SAFI_MULTICAST] = 1;
        stream_putc (s, BGP_OPEN_OPT_CAP);
        stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
        stream_putc (s, CAPABILITY_CODE_MP);
        stream_putc (s, CAPABILITY_CODE_MP_LEN);
        stream_putw (s, AFI_IP6);
        stream_putc (s, 0);
        stream_putc (s, SAFI_MULTICAST);
    }
    /* IPv6 VPN. */
    if (peer->afc[AFI_IP6][SAFI_MPLS_VPN])
    {
        peer->afc_adv[AFI_IP6][SAFI_MPLS_VPN] = 1;
        stream_putc (s, BGP_OPEN_OPT_CAP);
        stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
        stream_putc (s, CAPABILITY_CODE_MP);
        stream_putc (s, CAPABILITY_CODE_MP_LEN);
        stream_putw (s, AFI_IP6);
        stream_putc (s, 0);
        stream_putc (s, SAFI_MPLS_LABELED_VPN);
    }
    /* IPv6 ENCAP. */
    if (peer->afc[AFI_IP6][SAFI_ENCAP])
    {
        peer->afc_adv[AFI_IP6][SAFI_ENCAP] = 1;
        stream_putc (s, BGP_OPEN_OPT_CAP);
        stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
        stream_putc (s, CAPABILITY_CODE_MP);
        stream_putc (s, CAPABILITY_CODE_MP_LEN);
        stream_putw (s, AFI_IP6);
        stream_putc (s, 0);
        stream_putc (s, SAFI_ENCAP);
    }

    /* Route refresh. */
    SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
    stream_putc (s, BGP_OPEN_OPT_CAP);
    stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
    stream_putc (s, CAPABILITY_CODE_REFRESH_OLD);
    stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
    stream_putc (s, BGP_OPEN_OPT_CAP);
    stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
    stream_putc (s, CAPABILITY_CODE_REFRESH);
    stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);

    /* AS4 */
    SET_FLAG (peer->cap, PEER_CAP_AS4_ADV);
    stream_putc (s, BGP_OPEN_OPT_CAP);
    stream_putc (s, CAPABILITY_CODE_AS4_LEN + 2);
    stream_putc (s, CAPABILITY_CODE_AS4);
    stream_putc (s, CAPABILITY_CODE_AS4_LEN);
    if ( peer->change_local_as )
        local_as = peer->change_local_as;
    else
        local_as = peer->local_as;
    stream_putl (s, local_as );

    /* ORF capability. */
    for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
        for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
            if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
                    || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
            {
                bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF_OLD);
                bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF);
            }

    /* Dynamic capability. */
    if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
    {
        SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV);
        stream_putc (s, BGP_OPEN_OPT_CAP);
        stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN + 2);
        stream_putc (s, CAPABILITY_CODE_DYNAMIC);
        stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN);
    }

    /* Sending base graceful-restart capability irrespective of the config */
    SET_FLAG (peer->cap, PEER_CAP_RESTART_ADV);
    stream_putc (s, BGP_OPEN_OPT_CAP);
    capp = stream_get_endp (s);           /* Set Capability Len Pointer */
    stream_putc (s, 0);                   /* Capability Length */
    stream_putc (s, CAPABILITY_CODE_RESTART);
    rcapp = stream_get_endp (s);          /* Set Restart Capability Len Pointer */
    stream_putc (s, 0);
    restart_time = peer->bgp->restart_time;
    if (peer->bgp->t_startup)
    {
        SET_FLAG (restart_time, RESTART_R_BIT);
        SET_FLAG (peer->cap, PEER_CAP_RESTART_BIT_ADV);
    }
    stream_putw (s, restart_time);

    /* Send address-family specific graceful-restart capability only when GR config
       is present */
    if (bgp_flag_check (peer->bgp, BGP_FLAG_GRACEFUL_RESTART))
    {
        for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
            for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
                if (peer->afc[afi][safi])
                {
                    stream_putw (s, afi);
                    stream_putc (s, safi);
                    stream_putc (s, 0); //Forwarding is not retained as of now.
                }
    }

    /* Total Graceful restart capability Len. */
    len = stream_get_endp (s) - rcapp - 1;
    stream_putc_at (s, rcapp, len);

    /* Total Capability Len. */
    len = stream_get_endp (s) - capp - 1;
    stream_putc_at (s, capp, len);

    /* Total Opt Parm Len. */
    len = stream_get_endp (s) - cp - 1;
    stream_putc_at (s, cp, len);
}
Exemplo n.º 20
0
static int
send_client (struct rnh *rnh, struct zserv *client, vrf_id_t vrf_id)
{
  struct stream *s;
  struct rib *rib;
  unsigned long nump;
  u_char num;
  struct nexthop *nexthop;
  struct route_node *rn;

  rn = rnh->node;
  rib = rnh->state;

  /* Get output stream. */
  s = client->obuf;
  stream_reset (s);

  zserv_create_header (s, ZEBRA_NEXTHOP_UPDATE, vrf_id);

  stream_putw(s, rn->p.family);
  stream_put_prefix (s, &rn->p);

  if (rib)
    {
      stream_putl (s, rib->metric);
      num = 0;
      nump = stream_get_endp(s);
      stream_putc (s, 0);
      for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
	if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) &&
            ! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE) &&
	    CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
	  {
	    stream_putc (s, nexthop->type);
	    switch (nexthop->type)
	      {
	      case ZEBRA_NEXTHOP_IPV4:
		stream_put_in_addr (s, &nexthop->gate.ipv4);
		break;
	      case ZEBRA_NEXTHOP_IFINDEX:
	      case ZEBRA_NEXTHOP_IFNAME:
		stream_putl (s, nexthop->ifindex);
		break;
	      case ZEBRA_NEXTHOP_IPV4_IFINDEX:
	      case ZEBRA_NEXTHOP_IPV4_IFNAME:
		stream_put_in_addr (s, &nexthop->gate.ipv4);
		stream_putl (s, nexthop->ifindex);
		break;
#ifdef HAVE_IPV6
	      case ZEBRA_NEXTHOP_IPV6:
		stream_put (s, &nexthop->gate.ipv6, 16);
		break;
	      case ZEBRA_NEXTHOP_IPV6_IFINDEX:
	      case ZEBRA_NEXTHOP_IPV6_IFNAME:
		stream_put (s, &nexthop->gate.ipv6, 16);
		stream_putl (s, nexthop->ifindex);
		break;
#endif /* HAVE_IPV6 */
	      default:
                /* do nothing */
		break;
	      }
	    num++;
	  }
      stream_putc_at (s, nump, num);
    }
  else
    {
      stream_putl (s, 0);
      stream_putc (s, 0);
    }
  stream_putw_at (s, 0, stream_get_endp (s));

  client->nh_last_upd_time = quagga_time(NULL);
  client->last_write_cmd = ZEBRA_NEXTHOP_UPDATE;
  return zebra_server_send_message(client);
}
Exemplo n.º 21
0
 /* 
  * "xdr_encode"-like interface that allows daemon (client) to send
  * a message to zebra server for a route that needs to be
  * added/deleted to the kernel. Info about the route is specified
  * by the caller in a struct zapi_ipv4. zapi_ipv4_read() then writes
  * the info down the zclient socket using the stream_* functions.
  * 
  * The corresponding read ("xdr_decode") function on the server
  * side is zread_ipv4_add()/zread_ipv4_delete().
  *
  *  0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  * |            Length (2)         |    Command    | Route Type    |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  * | ZEBRA Flags   | Message Flags | Prefix length |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  * | Destination IPv4 Prefix for route                             |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  * | Nexthop count | 
  * +-+-+-+-+-+-+-+-+
  *
  * 
  * A number of IPv4 nexthop(s) or nexthop interface index(es) are then 
  * described, as per the Nexthop count. Each nexthop described as:
  *
  * +-+-+-+-+-+-+-+-+
  * | Nexthop Type  |  Set to one of ZEBRA_NEXTHOP_*
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  * |       IPv4 Nexthop address or Interface Index number          |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *
  * Alternatively, if the flags field has ZEBRA_FLAG_BLACKHOLE or
  * ZEBRA_FLAG_REJECT is set then Nexthop count is set to 1, then _no_ 
  * nexthop information is provided, and the message describes a prefix
  * to blackhole or reject route.
  *
  * If ZAPI_MESSAGE_DISTANCE is set, the distance value is written as a 1
  * byte value.
  * 
  * If ZAPI_MESSAGE_METRIC is set, the metric value is written as an 8
  * byte value.
  *
  * If ZAPI_MESSAGE_TAG is set, the tag value is written as a 4 byte value
  *
  * XXX: No attention paid to alignment.
  */ 
int
zapi_ipv4_route (u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p,
                 struct zapi_ipv4 *api)
{
  int i;
  int psize;
  struct stream *s;

  /* Reset stream. */
  s = zclient->obuf;
  stream_reset (s);

  zclient_create_header (s, cmd, api->vrf_id);
  
  /* Put type and nexthop. */
  stream_putc (s, api->type);
  stream_putc (s, api->flags);
  stream_putc (s, api->message);
  stream_putw (s, api->safi);

  /* Put prefix information. */
  psize = PSIZE (p->prefixlen);
  stream_putc (s, p->prefixlen);
  stream_write (s, (u_char *) & p->prefix, psize);

  /* Nexthop, ifindex, distance and metric information. */
  if (CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP))
    {
      if (CHECK_FLAG (api->flags, ZEBRA_FLAG_BLACKHOLE))
        {
          stream_putc (s, 1);
          stream_putc (s, ZEBRA_NEXTHOP_BLACKHOLE);
          /* XXX assert(api->nexthop_num == 0); */
          /* XXX assert(api->ifindex_num == 0); */
        }
      else
        stream_putc (s, api->nexthop_num + api->ifindex_num);

      for (i = 0; i < api->nexthop_num; i++)
        {
          stream_putc (s, ZEBRA_NEXTHOP_IPV4);
          stream_put_in_addr (s, api->nexthop[i]);
        }
      for (i = 0; i < api->ifindex_num; i++)
        {
          stream_putc (s, ZEBRA_NEXTHOP_IFINDEX);
          stream_putl (s, api->ifindex[i]);
        }
    }

  if (CHECK_FLAG (api->message, ZAPI_MESSAGE_DISTANCE))
    stream_putc (s, api->distance);
  if (CHECK_FLAG (api->message, ZAPI_MESSAGE_METRIC))
    stream_putl (s, api->metric);
  if (CHECK_FLAG (api->message, ZAPI_MESSAGE_MTU))
    stream_putl (s, api->mtu);
  if (CHECK_FLAG (api->message, ZAPI_MESSAGE_TAG))
    stream_putl (s, api->tag);

  /* Put length at the first point of the stream. */
  stream_putw_at (s, 0, stream_get_endp (s));

  return zclient_send_message(zclient);
}
Exemplo n.º 22
0
void
bgp_dump_routes_entry (struct prefix *p, struct bgp_info *info, int afi,
		       int type, unsigned int seq)
{
  struct stream *obuf;
  struct attr *attr;
  struct peer *peer;
  int plen;
  int safi = 0;

  /* Make dump stream. */
  obuf = bgp_dump_obuf;
  stream_reset (obuf);

  attr = info->attr;
  peer = info->peer;

  /* We support MRT's old format. */
  if (type == MSG_TABLE_DUMP)
    {
      bgp_dump_header (obuf, MSG_TABLE_DUMP, afi);
      stream_putw (obuf, 0);	/* View # */
      stream_putw (obuf, seq);	/* Sequence number. */
    }
  else
    {
      bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_ENTRY);
      
      stream_putl (obuf, info->uptime); /* Time Last Change */
      stream_putw (obuf, afi);	/* Address Family */
      stream_putc (obuf, safi);	/* SAFI */
    }

  if (afi == AFI_IP)
    {
      if (type == MSG_TABLE_DUMP)
	{
	  /* Prefix */
	  stream_put_in_addr (obuf, &p->u.prefix4);
	  stream_putc (obuf, p->prefixlen);

	  /* Status */
	  stream_putc (obuf, 1);

	  /* Originated */
	  stream_putl (obuf, info->uptime);

	  /* Peer's IP address */
	  stream_put_in_addr (obuf, &peer->su.sin.sin_addr);

	  /* Peer's AS number. */
	  stream_putw (obuf, peer->as);

	  /* Dump attribute. */
	  bgp_dump_routes_attr (obuf, attr, p);
	}
      else
	{
	  /* Next-Hop-Len */
	  stream_putc (obuf, IPV4_MAX_BYTELEN);
	  stream_put_in_addr (obuf, &attr->nexthop);
	  stream_putc (obuf, p->prefixlen);
	  plen = PSIZE (p->prefixlen);
	  stream_put (obuf, &p->u.prefix4, plen);
	  bgp_dump_routes_attr (obuf, attr, p);
	}
    }
#ifdef HAVE_IPV6
  else if (afi == AFI_IP6)
    {
      if (type == MSG_TABLE_DUMP)
	{
	  /* Prefix */
	  stream_write (obuf, (u_char *)&p->u.prefix6, IPV6_MAX_BYTELEN);
	  stream_putc (obuf, p->prefixlen);

	  /* Status */
	  stream_putc (obuf, 1);

	  /* Originated */
	  stream_putl (obuf, info->uptime);

	  /* Peer's IP address */
	  stream_write (obuf, (u_char *)&peer->su.sin6.sin6_addr,
			IPV6_MAX_BYTELEN);

	  /* Peer's AS number. */
	  stream_putw (obuf, peer->as);

	  /* Dump attribute. */
	  bgp_dump_routes_attr (obuf, attr, p);
	}
      else
	{
	  ;
	}
    }
#endif /* HAVE_IPV6 */

  /* Set length. */
  bgp_dump_set_size (obuf, type);

  fwrite (STREAM_DATA (obuf), stream_get_putp (obuf), 1, bgp_dump_routes.fp);
  fflush (bgp_dump_routes.fp);
}
Exemplo n.º 23
0
static void
bgp_dump_routes_index_table(struct bgp *bgp)
{
  struct peer *peer;
  struct listnode *node;
  uint16_t peerno = 0;
  struct stream *obuf;

  obuf = bgp_dump_obuf;
  stream_reset (obuf);

  /* MRT header */
  bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_PEER_INDEX_TABLE,
		   BGP_DUMP_ROUTES);

  /* Collector BGP ID */
  stream_put_in_addr (obuf, &bgp->router_id);

  /* View name */
  if(bgp->name)
    {
      stream_putw (obuf, strlen(bgp->name));
      stream_put(obuf, bgp->name, strlen(bgp->name));
    }
  else
    {
      stream_putw(obuf, 0);
    }

  /* Peer count */
  stream_putw (obuf, listcount(bgp->peer));

  /* Walk down all peers */
  for(ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
    {

      /* Peer's type */
      if (sockunion_family(&peer->su) == AF_INET)
        {
          stream_putc (obuf, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP);
        }
      else if (sockunion_family(&peer->su) == AF_INET6)
        {
          stream_putc (obuf, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP6);
        }

      /* Peer's BGP ID */
      stream_put_in_addr (obuf, &peer->remote_id);

      /* Peer's IP address */
      if (sockunion_family(&peer->su) == AF_INET)
        {
          stream_put_in_addr (obuf, &peer->su.sin.sin_addr);
        }
      else if (sockunion_family(&peer->su) == AF_INET6)
        {
          stream_write (obuf, (u_char *)&peer->su.sin6.sin6_addr,
                        IPV6_MAX_BYTELEN);
        }

      /* Peer's AS number. */
      /* Note that, as this is an AS4 compliant quagga, the RIB is always AS4 */
      stream_putl (obuf, peer->as);

      /* Store the peer number for this peer */
      peer->table_dump_index = peerno;
      peerno++;
    }

  bgp_dump_set_size(obuf, MSG_TABLE_DUMP_V2);

  fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_routes.fp);
  fflush (bgp_dump_routes.fp);
}
Exemplo n.º 24
0
static void
isis_zebra_route_add_ipv4 (struct prefix *prefix,
			   struct isis_route_info *route_info)
{
  u_char message, flags;
  int psize;
  struct stream *stream;
  struct isis_nexthop *nexthop;
  struct listnode *node;

  if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
    return;

  if (vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_ISIS], VRF_DEFAULT))
    {
      message = 0;
      flags = 0;

      SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP);
      SET_FLAG (message, ZAPI_MESSAGE_METRIC);
#if 0
      SET_FLAG (message, ZAPI_MESSAGE_DISTANCE);
#endif

      stream = zclient->obuf;
      stream_reset (stream);
      zclient_create_header (stream, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT);
      /* type */
      stream_putc (stream, ZEBRA_ROUTE_ISIS);
      /* flags */
      stream_putc (stream, flags);
      /* message */
      stream_putc (stream, message);
      /* SAFI */
      stream_putw (stream, SAFI_UNICAST);
      /* prefix information */
      psize = PSIZE (prefix->prefixlen);
      stream_putc (stream, prefix->prefixlen);
      stream_write (stream, (u_char *) & prefix->u.prefix4, psize);

      stream_putc (stream, listcount (route_info->nexthops));

      /* Nexthop, ifindex, distance and metric information */
      for (ALL_LIST_ELEMENTS_RO (route_info->nexthops, node, nexthop))
	{
	  /* FIXME: can it be ? */
	  if (nexthop->ip.s_addr != INADDR_ANY)
	    {
	      stream_putc (stream, ZEBRA_NEXTHOP_IPV4);
	      stream_put_in_addr (stream, &nexthop->ip);
	    }
	  else
	    {
	      stream_putc (stream, ZEBRA_NEXTHOP_IFINDEX);
	      stream_putl (stream, nexthop->ifindex);
	    }
	}
#if 0
      if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
	stream_putc (stream, route_info->depth);
#endif
      if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
	stream_putl (stream, route_info->cost);

      stream_putw_at (stream, 0, stream_get_endp (stream));
      zclient_send_message(zclient);
      SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
      UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
    }
Exemplo n.º 25
0
void
ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or)
{
  u_char message;
  u_char distance;
  u_char flags;
  int psize;
  struct stream *s;
  struct ospf_path *path;
  struct listnode *node;

  if (zclient->redist[ZEBRA_ROUTE_OSPF])
    {
      message = 0;
      flags = 0;

      /* OSPF pass nexthop and metric */
      SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP);
      SET_FLAG (message, ZAPI_MESSAGE_METRIC);

      /* Distance value. */
      distance = ospf_distance_apply (p, or);
      if (distance)
        SET_FLAG (message, ZAPI_MESSAGE_DISTANCE);

      /* Make packet. */
      s = zclient->obuf;
      stream_reset (s);

      /* Put command, type, flags, message. */
      zclient_create_header (s, ZEBRA_IPV4_ROUTE_ADD);
      stream_putc (s, ZEBRA_ROUTE_OSPF);
      stream_putc (s, flags);
      stream_putc (s, message);
      stream_putw (s, SAFI_UNICAST);

      /* Put prefix information. */
      psize = PSIZE (p->prefixlen);
      stream_putc (s, p->prefixlen);
      stream_write (s, (u_char *) & p->prefix, psize);

      /* Nexthop count. */
      stream_putc (s, or->paths->count);

      /* Nexthop, ifindex, distance and metric information. */
      for (ALL_LIST_ELEMENTS_RO (or->paths, node, path))
        {
          if (path->nexthop.s_addr != INADDR_ANY &&
	      path->ifindex != 0)
            {
              stream_putc (s, ZEBRA_NEXTHOP_IPV4_IFINDEX);
              stream_put_in_addr (s, &path->nexthop);
	      stream_putl (s, path->ifindex);
            }
          else if (path->nexthop.s_addr != INADDR_ANY)
            {
              stream_putc (s, ZEBRA_NEXTHOP_IPV4);
              stream_put_in_addr (s, &path->nexthop);
            }
          else
            {
              stream_putc (s, ZEBRA_NEXTHOP_IFINDEX);
              if (path->ifindex)
                stream_putl (s, path->ifindex);
              else
                stream_putl (s, 0);
            }

          if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
            {
	      char buf[2][INET_ADDRSTRLEN];
	      zlog_debug("Zebra: Route add %s/%d nexthop %s",
			 inet_ntop(AF_INET, &p->prefix,
				   buf[0], sizeof(buf[0])),
			 p->prefixlen,
			 inet_ntop(AF_INET, &path->nexthop,
				   buf[1], sizeof(buf[1])));
            }
        }

      if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
        stream_putc (s, distance);
      if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
        {
          if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL)
            stream_putl (s, or->cost + or->u.ext.type2_cost);
          else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
            stream_putl (s, or->u.ext.type2_cost);
          else
            stream_putl (s, or->cost);
        }

      stream_putw_at (s, 0, stream_get_endp (s));

      zclient_send_message(zclient);
    }
Exemplo n.º 26
0
/* Fill in capability open option to the packet. */
void
bgp_open_capability (struct stream *s, struct peer *peer)
{
  u_char len;
  unsigned long cp;
  afi_t afi;
  safi_t safi;
  as_t local_as;

  /* Remember current pointer for Opt Parm Len. */
  cp = stream_get_endp (s);

  /* Opt Parm Len. */
  stream_putc (s, 0);

  /* Do not send capability. */
  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN) 
      || CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
    return;

  /* IPv4 unicast. */
  if (peer->afc[AFI_IP][SAFI_UNICAST])
    {
      peer->afc_adv[AFI_IP][SAFI_UNICAST] = 1;
      stream_putc (s, BGP_OPEN_OPT_CAP);
      stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
      stream_putc (s, CAPABILITY_CODE_MP);
      stream_putc (s, CAPABILITY_CODE_MP_LEN);
      stream_putw (s, AFI_IP);
      stream_putc (s, 0);
      stream_putc (s, SAFI_UNICAST);
    }
  /* IPv4 multicast. */
  if (peer->afc[AFI_IP][SAFI_MULTICAST])
    {
      peer->afc_adv[AFI_IP][SAFI_MULTICAST] = 1;
      stream_putc (s, BGP_OPEN_OPT_CAP);
      stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
      stream_putc (s, CAPABILITY_CODE_MP);
      stream_putc (s, CAPABILITY_CODE_MP_LEN);
      stream_putw (s, AFI_IP);
      stream_putc (s, 0);
      stream_putc (s, SAFI_MULTICAST);
    }
  /* IPv4 VPN */
  if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
    {
      peer->afc_adv[AFI_IP][SAFI_MPLS_VPN] = 1;
      stream_putc (s, BGP_OPEN_OPT_CAP);
      stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
      stream_putc (s, CAPABILITY_CODE_MP);
      stream_putc (s, CAPABILITY_CODE_MP_LEN);
      stream_putw (s, AFI_IP);
      stream_putc (s, 0);
      stream_putc (s, SAFI_MPLS_LABELED_VPN);
    }
#ifdef HAVE_IPV6
  /* IPv6 unicast. */
  if (peer->afc[AFI_IP6][SAFI_UNICAST])
    {
      peer->afc_adv[AFI_IP6][SAFI_UNICAST] = 1;
      stream_putc (s, BGP_OPEN_OPT_CAP);
      stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
      stream_putc (s, CAPABILITY_CODE_MP);
      stream_putc (s, CAPABILITY_CODE_MP_LEN);
      stream_putw (s, AFI_IP6);
      stream_putc (s, 0);
      stream_putc (s, SAFI_UNICAST);
    }
  /* IPv6 multicast. */
  if (peer->afc[AFI_IP6][SAFI_MULTICAST])
    {
      peer->afc_adv[AFI_IP6][SAFI_MULTICAST] = 1;
      stream_putc (s, BGP_OPEN_OPT_CAP);
      stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
      stream_putc (s, CAPABILITY_CODE_MP);
      stream_putc (s, CAPABILITY_CODE_MP_LEN);
      stream_putw (s, AFI_IP6);
      stream_putc (s, 0);
      stream_putc (s, SAFI_MULTICAST);
    }
#endif /* HAVE_IPV6 */

  /* Route refresh. */
  SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
  stream_putc (s, BGP_OPEN_OPT_CAP);
  stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
  stream_putc (s, CAPABILITY_CODE_REFRESH_OLD);
  stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
  stream_putc (s, BGP_OPEN_OPT_CAP);
  stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
  stream_putc (s, CAPABILITY_CODE_REFRESH);
  stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);

  /* AS4 */
  SET_FLAG (peer->cap, PEER_CAP_AS4_ADV);
  stream_putc (s, BGP_OPEN_OPT_CAP);
  stream_putc (s, CAPABILITY_CODE_AS4_LEN + 2);
  stream_putc (s, CAPABILITY_CODE_AS4);
  stream_putc (s, CAPABILITY_CODE_AS4_LEN);
  if ( peer->change_local_as )
    local_as = peer->change_local_as;
  else
    local_as = peer->local_as;
  stream_putl (s, local_as );

  /* ORF capability. */
  for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
    for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
      if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
	  || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
	{
	  bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF_OLD);
	  bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF);
	}

  /* Dynamic capability. */
  if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
    {
      SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV);
      stream_putc (s, BGP_OPEN_OPT_CAP);
      stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN + 2);
      stream_putc (s, CAPABILITY_CODE_DYNAMIC);
      stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN);
    }

  /* Graceful restart capability */
  if (bgp_flag_check (peer->bgp, BGP_FLAG_GRACEFUL_RESTART))
    {
      SET_FLAG (peer->cap, PEER_CAP_RESTART_ADV);
      stream_putc (s, BGP_OPEN_OPT_CAP);
      stream_putc (s, CAPABILITY_CODE_RESTART_LEN + 2);
      stream_putc (s, CAPABILITY_CODE_RESTART);
      stream_putc (s, CAPABILITY_CODE_RESTART_LEN);
      stream_putw (s, peer->bgp->restart_time);
     }

  /* Total Opt Parm Len. */
  len = stream_get_endp (s) - cp - 1;
  stream_putc_at (s, cp, len);
}
Exemplo n.º 27
0
void
isis_zebra_route_add_ipv4 (struct prefix *prefix,
                           struct isis_route_info *route_info)
{
    u_char message, flags;
    int psize;
    struct stream *stream;
    struct isis_nexthop *nexthop;
    struct listnode *node;

    if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC))
        return;

    if (zclient->redist[ZEBRA_ROUTE_ISIS])
    {
        message = 0;
        flags = 0;

        SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP);
        SET_FLAG (message, ZAPI_MESSAGE_METRIC);
#if 0
        SET_FLAG (message, ZAPI_MESSAGE_DISTANCE);
#endif

        stream = zclient->obuf;
        stream_reset (stream);
        /* Length place holder. */
        stream_putw (stream, 0);
        /* command */
        stream_putc (stream, ZEBRA_IPV4_ROUTE_ADD);
        /* type */
        stream_putc (stream, ZEBRA_ROUTE_ISIS);
        /* flags */
        stream_putc (stream, flags);
        /* message */
        stream_putc (stream, message);
        /* prefix information */
        psize = PSIZE (prefix->prefixlen);
        stream_putc (stream, prefix->prefixlen);
        stream_write (stream, (u_char *) & prefix->u.prefix4, psize);

        stream_putc (stream, listcount (route_info->nexthops));

        /* Nexthop, ifindex, distance and metric information */
        for (node = listhead (route_info->nexthops); node; nextnode (node))
        {
            nexthop = getdata (node);
            /* FIXME: can it be ? */
            if (nexthop->ip.s_addr != INADDR_ANY)
            {
                stream_putc (stream, ZEBRA_NEXTHOP_IPV4);
                stream_put_in_addr (stream, &nexthop->ip);
            }
            else
            {
                stream_putc (stream, ZEBRA_NEXTHOP_IFINDEX);
                stream_putl (stream, nexthop->ifindex);
            }
        }
#if 0
        if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
            stream_putc (stream, route_info->depth);
#endif
        if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
            stream_putl (stream, route_info->cost);

        stream_putw_at (stream, 0, stream_get_endp (stream));
        writen (zclient->sock, stream->data, stream_get_endp (stream));
    }
}
Exemplo n.º 28
0
static void ppp_put_control_to_stream(struct stream* s, unsigned int control)
{
    stream_putl(s, control);

    return;
}
Exemplo n.º 29
0
/* Runs under child process. */
static unsigned int
bgp_dump_routes_func (int afi, int first_run, unsigned int seq)
{
  struct stream *obuf;
  struct bgp_info *info;
  struct bgp_node *rn;
  struct bgp *bgp;
  struct bgp_table *table;

  bgp = bgp_get_default ();
  if (!bgp)
    return seq;

  if (bgp_dump_routes.fp == NULL)
    return seq;

  /* Note that bgp_dump_routes_index_table will do ipv4 and ipv6 peers,
     so this should only be done on the first call to bgp_dump_routes_func.
     ( this function will be called once for ipv4 and once for ipv6 ) */
  if(first_run)
    bgp_dump_routes_index_table(bgp);

  obuf = bgp_dump_obuf;
  stream_reset(obuf);

  /* Walk down each BGP route. */
  table = bgp->rib[afi][SAFI_UNICAST];

  for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
    {
      if(!rn->info)
        continue;

      stream_reset(obuf);

      /* MRT header */
      if (afi == AFI_IP)
	bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV4_UNICAST,
			 BGP_DUMP_ROUTES);
      else if (afi == AFI_IP6)
	bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV6_UNICAST,
			 BGP_DUMP_ROUTES);

      /* Sequence number */
      stream_putl(obuf, seq);

      /* Prefix length */
      stream_putc (obuf, rn->p.prefixlen);

      /* Prefix */
      if (afi == AFI_IP)
        {
          /* We'll dump only the useful bits (those not 0), but have to align on 8 bits */
          stream_write(obuf, (u_char *)&rn->p.u.prefix4, (rn->p.prefixlen+7)/8);
        }
      else if (afi == AFI_IP6)
        {
          /* We'll dump only the useful bits (those not 0), but have to align on 8 bits */
          stream_write (obuf, (u_char *)&rn->p.u.prefix6, (rn->p.prefixlen+7)/8);
        }

      /* Save where we are now, so we can overwride the entry count later */
      int sizep = stream_get_endp(obuf);

      /* Entry count */
      uint16_t entry_count = 0;

      /* Entry count, note that this is overwritten later */
      stream_putw(obuf, 0);

      for (info = rn->info; info; info = info->next)
        {
          entry_count++;

          /* Peer index */
          stream_putw(obuf, info->peer->table_dump_index);

          /* Originated */
#ifdef HAVE_CLOCK_MONOTONIC
          stream_putl (obuf, time(NULL) - (bgp_clock() - info->uptime));
#else
          stream_putl (obuf, info->uptime);
#endif /* HAVE_CLOCK_MONOTONIC */

          /* Dump attribute. */
          /* Skip prefix & AFI/SAFI for MP_NLRI */
          bgp_dump_routes_attr (obuf, info->attr, &rn->p);
        }

      /* Overwrite the entry count, now that we know the right number */
      stream_putw_at (obuf, sizep, entry_count);

      seq++;

      bgp_dump_set_size(obuf, MSG_TABLE_DUMP_V2);
      fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_routes.fp);

    }

  fflush (bgp_dump_routes.fp);

  return seq;
}
Exemplo n.º 30
0
static struct bgp_info *
bgp_dump_route_node_record (int afi, struct bgp_node *rn,
                            struct bgp_info *info, unsigned int seq)
{
  struct stream *obuf;
  size_t sizep;
  size_t endp;

  obuf = bgp_dump_obuf;
  stream_reset (obuf);

  /* MRT header */
  if (afi == AFI_IP)
    bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV4_UNICAST,
                     BGP_DUMP_ROUTES);
  else if (afi == AFI_IP6)
    bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV6_UNICAST,
                     BGP_DUMP_ROUTES);

  /* Sequence number */
  stream_putl (obuf, seq);

  /* Prefix length */
  stream_putc (obuf, rn->p.prefixlen);

  /* Prefix */
  if (afi == AFI_IP)
    {
      /* We'll dump only the useful bits (those not 0), but have to
       * align on 8 bits */
      stream_write (obuf, (u_char *) &rn->p.u.prefix4, 
                    (rn->p.prefixlen + 7) / 8);
    }
  else if (afi == AFI_IP6)
    {
      /* We'll dump only the useful bits (those not 0), but have to
       * align on 8 bits */
      stream_write (obuf, (u_char *) &rn->p.u.prefix6,
                    (rn->p.prefixlen + 7) / 8);
    }

  /* Save where we are now, so we can overwride the entry count later */
  sizep = stream_get_endp (obuf);

  /* Entry count */
  uint16_t entry_count = 0;

  /* Entry count, note that this is overwritten later */
  stream_putw (obuf, 0);

  endp = stream_get_endp (obuf);
  for (; info; info = info->next)
    {
      size_t cur_endp;

      /* Peer index */
      stream_putw (obuf, info->peer->table_dump_index);

      /* Originated */
#ifdef HAVE_CLOCK_MONOTONIC
      stream_putl (obuf, time (NULL) - (bgp_clock () - info->uptime));
#else
      stream_putl (obuf, info->uptime);
#endif /* HAVE_CLOCK_MONOTONIC */

      /* Dump attribute. */
      /* Skip prefix & AFI/SAFI for MP_NLRI */
      bgp_dump_routes_attr (obuf, info->attr, &rn->p);

      cur_endp = stream_get_endp (obuf);
      if (cur_endp > BGP_MAX_PACKET_SIZE + BGP_DUMP_MSG_HEADER
          + BGP_DUMP_HEADER_SIZE)
        {
          stream_set_endp (obuf, endp);
          break;
        }

      entry_count++;
      endp = cur_endp;
    }

  /* Overwrite the entry count, now that we know the right number */
  stream_putw_at (obuf, sizep, entry_count);

  bgp_dump_set_size (obuf, MSG_TABLE_DUMP_V2);
  fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_routes.fp);

  return info;
}