Пример #1
0
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;
}
Пример #2
0
int
zclient_send_linkmetrics_subscribe (struct zclient *zclient, uint16_t cmd)
{
    struct stream *s;

    if (zclient->sock < 0)
    {
        zlog_err ("%s: not connected to zebra", __func__);
        return -1;
    }

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

    zclient_create_header (s, cmd);

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

    if (zclient_send_message (zclient))
    {
        zlog_err ("%s: zclient_send_message() failed", __func__);
        return -1;
    }

    return 0;
}
Пример #3
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. */
  stream_putw (s, 0);
  stream_putc (s, ZEBRA_IPV4_IMPORT_LOOKUP);
  stream_put_in_addr (s, &p->prefix);

  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_IPV4:
		stream_put_in_addr (s, &nexthop->gate.ipv4);
		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;
}
Пример #4
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.
  *
  * 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);
  
  /* 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);

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

  return zclient_send_message(zclient);
}
Пример #5
0
/*
 * 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_FOO *ifp)
{
  struct stream *s;

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

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

  zserv_create_header (s, cmd);

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

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

  return zebra_server_send_message(client);
}
Пример #6
0
/* Router-id is updated. Send ZEBRA_ROUTER_ID_ADD to client. */
int
zsend_router_id_update (struct zserv *client, struct prefix *p)
{
  struct stream *s;
  int blen;

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

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

  /* Message type. */
  zserv_create_header (s, ZEBRA_ROUTER_ID_UPDATE);

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

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

  return zebra_server_send_message(client);
}
Пример #7
0
struct bgp_nexthop_cache *
zlookup_query_ipv6 (struct in6_addr *addr)
{
  int ret;
  struct stream *s;

  /* Check socket. */
  if (zlookup->sock < 0)
    return NULL;

  s = zlookup->obuf;
  stream_reset (s);
  zclient_create_header (s, ZEBRA_IPV6_NEXTHOP_LOOKUP);
  stream_put (s, addr, 16);
  stream_putw_at (s, 0, stream_get_endp (s));
  
  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 NULL;
    }
  if (ret == 0)
    {
      zlog_err ("zlookup->sock connection closed");
      close (zlookup->sock);
      zlookup->sock = -1;
      return NULL;
    }

  return zlookup_read_ipv6 ();
}
Пример #8
0
/* Router-id is updated. Send ZEBRA_ROUTER_ID_ADD to client. */
int
zsend_router_id_update (struct zserv *client, struct prefix *p)
{
  struct stream *s;
  int blen;

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

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

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

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

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

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

  return writen (client->sock, s->data, stream_get_endp (s));
}
Пример #9
0
/*
 * 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;
}
Пример #10
0
int
zapi_ipv6_route (u_char cmd, struct_zclient *zclient, struct prefix_ipv6 *p,
	       struct zapi_ipv6 *api)
{
  int i;
  int psize;
  struct stream *s;

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

  /* Length place holder. */
  stream_putw (s, 0);

  /* Put command, type and nexthop. */
  stream_putc (s, cmd);
  stream_putc (s, api->type);
  stream_putc (s, api->flags);
  stream_putc (s, api->message);
  
  /* 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))
    {
      stream_putc (s, api->nexthop_num + api->ifindex_num);

      for (i = 0; i < api->nexthop_num; i++)
	{
	  stream_putc (s, ZEBRA_NEXTHOP_IPV6);
	  stream_write (s, (u_char *)api->nexthop[i], 16);
	}
      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);

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

  return writen (zclient->sock, s->data, stream_get_endp (s));
}
Пример #11
0
/* 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;
}
Пример #12
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) ;
}
Пример #13
0
/* 
 * send a ZEBRA_REDISTRIBUTE_ADD or ZEBRA_REDISTRIBUTE_DELETE
 * for the route type (ZEBRA_ROUTE_KERNEL etc.). The zebra server will
 * then set/unset redist[type] in the client handle (a struct zserv) for the 
 * sending client
 */
int
zebra_redistribute_send (int command, struct zclient *zclient, int type)
{
  struct stream *s;

  s = zclient->obuf;
  stream_reset(s);
  
  zclient_create_header (s, command);
  stream_putc (s, type);
  
  stream_putw_at (s, 0, stream_get_endp (s));
  
  return zclient_send_message(zclient);
}
static int zclient_lookup_nexthop_once(struct zclient *zlookup,
				       struct pim_zlookup_nexthop nexthop_tab[],
				       const int tab_size,
				       struct in_addr addr)
{
  struct stream *s;
  int ret;

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

  /* Check socket. */
  if (zlookup->sock < 0) {
    zlog_err("%s %s: zclient lookup socket is not connected",
	     __FILE__, __PRETTY_FUNCTION__);
    zclient_lookup_failed(zlookup);
    return -1;
  }
  
  s = zlookup->obuf;
  stream_reset(s);
  zclient_create_header(s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB);
  stream_put_in_addr(s, &addr);
  stream_putw_at(s, 0, stream_get_endp(s));
  
  ret = writen(zlookup->sock, s->data, stream_get_endp(s));
  if (ret < 0) {
    zlog_err("%s %s: writen() failure writing to zclient lookup socket",
	     __FILE__, __PRETTY_FUNCTION__);
    zclient_lookup_failed(zlookup);
    return -2;
  }
  if (ret == 0) {
    zlog_err("%s %s: connection closed on zclient lookup socket",
	     __FILE__, __PRETTY_FUNCTION__);
    zclient_lookup_failed(zlookup);
    return -3;
  }
  
  return zclient_read_nexthop(zlookup, nexthop_tab,
			      tab_size, addr);
}
Пример #15
0
static int
zebra_hello_send (struct zclient *zclient)
{
  struct stream *s;

  if (zclient->redist_default)
    {
      s = zclient->obuf;
      stream_reset (s);

      zclient_create_header (s, ZEBRA_HELLO);
      stream_putc (s, zclient->redist_default);
      stream_putw_at (s, 0, stream_get_endp (s));
      return zclient_send_message(zclient);
    }

  return 0;
}
Пример #16
0
static int
zebra_hello_send (struct zclient *zclient)
{
  struct stream *s;

  if (zclient->redist_default)
    {
      s = zclient->obuf;
      stream_reset (s);

      /* The VRF ID in the HELLO message is always 0. */
      zclient_create_header (s, ZEBRA_HELLO, VRF_DEFAULT);
      stream_putc (s, zclient->redist_default);
      stream_putw_at (s, 0, stream_get_endp (s));
      return zclient_send_message(zclient);
    }

  return 0;
}
Пример #17
0
/*
 * 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;
}
Пример #18
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) ;
}
Пример #19
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));
}
Пример #20
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);
}
Пример #21
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;
}
Пример #22
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;
}
Пример #23
0
static 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. */
  zserv_create_header (s, ZEBRA_IPV6_NEXTHOP_LOOKUP);
  stream_put (s, &addr, 16);

  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_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));
  
  return zebra_server_send_message(client);
}
Пример #24
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);
    }
Пример #25
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));
    }
}
Пример #26
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);
}
Пример #27
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);
}
Пример #28
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);
    }
Пример #29
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;
}
Пример #30
0
/*
 * 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;
}