Beispiel #1
0
/* Dump common header. */
static void
bgp_dump_header (struct stream *obuf, int type, int subtype, int dump_type)
{
  struct timeval clock;
  long msecs;
  time_t secs;

  if ((dump_type == BGP_DUMP_ALL_ET || dump_type == BGP_DUMP_UPDATES_ET)
      && type == MSG_PROTOCOL_BGP4MP)
    type = MSG_PROTOCOL_BGP4MP_ET;

  gettimeofday(&clock, NULL);

  secs = clock.tv_sec;
  msecs = clock.tv_usec;

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

  /* Adding microseconds for the MRT Extended Header */
  if (type == MSG_PROTOCOL_BGP4MP_ET)
    stream_putl (obuf, msecs);
}
Beispiel #2
0
void
clear_checksum_streams (uint16_t checksum)
{
  struct listnode * node, * nnode;
  struct sisis_listener * listener;

  for(ALL_LIST_ELEMENTS (sm->listen_sockets, node, nnode, listener))
  {
     if(stream_get_getp(listener->chksum_stream) < stream_get_endp(listener->chksum_stream))
     {
       uint16_t checksum_head = stream_getw(listener->chksum_stream);
       if(checksum_head != checksum)
       {
         stream_putw(listener->chksum_stream, checksum_head);
         uint16_t next_checksum = stream_peekw(listener->chksum_stream);
         while(next_checksum != checksum_head)
         {
           next_checksum = stream_getw(listener->chksum_stream);
           if(next_checksum != checksum)
             stream_putw(listener->chksum_stream, next_checksum);
         }
       }
     }
  }
}
Beispiel #3
0
/* Dump BGP status change. */
void
bgp_dump_state (struct peer *peer, int status_old, int status_new)
{
  int ret;
  struct stream *obuf;

  /* If dump file pointer is disabled return immediately. */
  if (bgp_dump_all.fp == NULL)
    return;

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

  bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_STATE_CHANGE_AS4);
  bgp_dump_common (obuf, peer, 1);/* force this in as4speak*/

  stream_putw (obuf, status_old);
  stream_putw (obuf, status_new);

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

  /* Write to the stream. */
  ret = fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_all.fp);
  if (ret != 1)
    {
      zlog_warn ("bgp_dump_state: fwrite returned %d, expected 1: %s", ret, strerror (errno));
    }
  fflush (bgp_dump_all.fp);
}
Beispiel #4
0
/* Dump BGP status change. */
void
bgp_dump_state (struct peer *peer, int status_old, int status_new)
{
  struct stream *obuf;

  /* If dump file pointer is disabled return immediately. */
  if (bgp_dump_all.fp == NULL)
    return;

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

  bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_STATE_CHANGE_AS4,
		   bgp_dump_all.type);
  bgp_dump_common (obuf, peer, 1);/* force this in as4speak*/

  stream_putw (obuf, status_old);
  stream_putw (obuf, status_new);

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

  /* Write to the stream. */
  fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_all.fp);
  fflush (bgp_dump_all.fp);
}
Beispiel #5
0
static void
rip_auth_write_leading_rte
(
  struct stream *s,
  struct rip_interface *ri,
  const u_int8_t key_id,
  char *auth_str,
  u_int16_t main_body_len
)
{
  u_int8_t dlen;

  if (IS_RIP_DEBUG_AUTH)
    zlog_debug ("writing authentication header for %uB of main body", main_body_len);
  stream_putw (s, RIP_FAMILY_AUTH);
  switch (ri->auth_type)
  {
  case RIP_AUTH_SIMPLE_PASSWORD:
    {
      u_int8_t padded_simple_password[RIP_AUTH_SIMPLE_SIZE] = { 0 };
      memcpy (padded_simple_password, auth_str, MIN (RIP_AUTH_SIMPLE_SIZE, strlen (auth_str)));
      stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);
      stream_put (s, padded_simple_password, RIP_AUTH_SIMPLE_SIZE);
      break;
    }
  case RIP_AUTH_HASH:
    if (IS_RIP_DEBUG_AUTH)
      zlog_debug ("hash algorithm is '%s'", LOOKUP (hash_algo_str, ri->hash_algo));
    stream_putw (s, RIP_AUTH_HASH);
    stream_putw (s, main_body_len);
    stream_putc (s, key_id);
    switch (ri->hash_algo)
    {
    case HASH_KEYED_MD5:
      /* Auth Data Len.  Set 16 for MD5 authentication data. Older ripds
       * however expect RIP_HEADER_SIZE + HASH_SIZE_MD5 so we allow for this
       * to be configurable. */
      dlen = ri->md5_auth_len;
      break;
    case HASH_HMAC_SHA1:
    case HASH_HMAC_SHA256:
    case HASH_HMAC_SHA384:
    case HASH_HMAC_SHA512:
      dlen = hash_digest_length[ri->hash_algo];
      break;
    default:
      assert (0);
    }
    if (IS_RIP_DEBUG_AUTH)
      zlog_debug ("declared auth data length is %uB", dlen);
    stream_putc (s, dlen);
    stream_putl (s, time (NULL)); /* Sequence Number (non-decreasing). */
    stream_putl (s, 0); /* reserved, MBZ */
    stream_putl (s, 0); /* reserved, MBZ */
    break;
  default:
    assert (0);
  }
}
Beispiel #6
0
void
zclient_create_header (struct stream *s, uint16_t command)
{
  /* length placeholder, caller can update */
  stream_putw (s, ZEBRA_HEADER_SIZE);
  stream_putc (s, ZEBRA_HEADER_MARKER);
  stream_putc (s, ZSERV_VERSION);
  stream_putw (s, command);
}
void
tipc_packet_create_header (struct stream *s, uint16_t cmd)
{
  /* length placeholder, caller can update */
  stream_putw (s, TIPC_PACKET_HEADER_SIZE);
  stream_putc (s, TIPC_PACKET_HEADER_MARKER);
  stream_putc (s, TIPC_PACKET_VERSION);
  stream_putw (s, cmd);
}
Beispiel #8
0
/* write RIP-2 hash authentication data trailer */
static void
rip_auth_write_trailer (struct stream *s, struct rip_interface *ri, char *auth_str)
{
  unsigned char digest[RIP_AUTH_MAX_SIZE];
  unsigned hash_error;

  if (IS_RIP_DEBUG_AUTH)
    zlog_debug ("writing authentication trailer after %zuB of main body", stream_get_endp (s));
  assert (ri->auth_type == RIP_AUTH_HASH);

  /* Set authentication data. */
  stream_putw (s, RIP_FAMILY_AUTH);
  stream_putw (s, RIP_AUTH_DATA);

  /* Generate a digest for the RIP packet and write it to the packet. */
  switch (ri->hash_algo)
  {
  case HASH_KEYED_MD5:
    if (IS_RIP_DEBUG_AUTH)
      zlog_debug ("%s: %zuB of input buffer, %zuB of key", __func__, stream_get_endp (s), strlen (auth_str));
    hash_error = hash_make_keyed_md5 ((caddr_t) STREAM_DATA (s), stream_get_endp (s), auth_str, strlen (auth_str), digest);
    stream_write (s, digest, HASH_SIZE_MD5);
    break;
#ifdef HAVE_LIBGCRYPT
  case HASH_HMAC_SHA1:
  case HASH_HMAC_SHA256:
  case HASH_HMAC_SHA384:
  case HASH_HMAC_SHA512:
    {
      u_int8_t compr_auth_str[RIP_AUTH_MAX_SIZE];
      size_t compr_authlen;
      /* RFC4822 2.5: Fill Apad, process whole packet with HMAC rounds. */
      size_t saved_endp = stream_get_endp (s);

      hash_key_compress_rfc4822 (ri->hash_algo, auth_str, strlen (auth_str), compr_auth_str, &compr_authlen);
      stream_write (s, hash_apad_sha512, hash_digest_length[ri->hash_algo]);
      if (IS_RIP_DEBUG_AUTH)
        zlog_debug ("%s: %zuB of input buffer, %zuB of key (%zuB compressed)",
          __func__, stream_get_endp (s), strlen (auth_str), compr_authlen);
      hash_error = hash_make_hmac (ri->hash_algo, STREAM_DATA (s),
        stream_get_endp (s), compr_auth_str, compr_authlen, STREAM_DATA (s) + saved_endp);
      break;
    }
#endif /* HAVE_LIBGCRYPT */
  default:
    assert (0);
  }
  if (hash_error)
    if (IS_RIP_DEBUG_AUTH)
      zlog_debug ("hash function returned error %u", hash_error);
}
Beispiel #9
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 */
}
Beispiel #10
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));
}
Beispiel #11
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;
}
Beispiel #12
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;
}
Beispiel #13
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);
}
Beispiel #14
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;
}
Beispiel #15
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;
}
Beispiel #16
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));
}
Beispiel #17
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;
}
Beispiel #18
0
/* Send simple Zebra message. */
int
#undef	zclient
zebra_message_send (struct_zclient *zclient, int command)
{
  struct stream *s;

  /* Get zclient output buffer. */
  s = zclient->obuf;
  stream_reset (s);

  /* Send very simple command only Zebra message. */
  stream_putw (s, 3);
  stream_putc (s, command);

  return writen (zclient->sock, s->data, 3);
}
Beispiel #19
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;
}
Beispiel #20
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, int sock, int type)
{
  int ret;
  struct stream *s;

  s = stream_new (ZEBRA_MAX_PACKET_SIZ);

  /* Total length of the messages. */
  stream_putw (s, 4);
  
  stream_putc (s, command);
  stream_putc (s, type);

  ret = writen (sock, s->data, 4);

  stream_free (s);

  return ret;
}
Beispiel #21
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 */
}
Beispiel #22
0
/* Dump common information. */
void
bgp_dump_common (struct stream *obuf, struct peer *peer)
{
  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. */
  stream_putw (obuf, peer->as);
  stream_putw (obuf, peer->local_as);

  if (peer->afc[AFI_IP][SAFI_UNICAST])
    {
      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->afc[AFI_IP6][SAFI_UNICAST])
    {
      /* 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 */
}
Beispiel #23
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;
}
Beispiel #24
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);
}
Beispiel #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));
    }
}
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);
    }
Beispiel #27
0
/* Take a sequence of payload (routing) RTE structures, decide on particular
 * authentication required for the given interface and build a complete RIP
 * packet in a stream structure. The packet will consist of header, optional
 * heading RTE, the payload RTEs and optional trailing data. Return the stream.
 */
int
rip_auth_make_packet
(
  struct rip_interface * ri,
  struct stream * packet,
  struct stream * rtes,
  const u_int8_t version,
  const u_int8_t command
)
{
  struct key *key = NULL;
  char *auth_str = NULL;

  if (IS_RIP_DEBUG_AUTH)
    zlog_debug ("interface auth type is '%s', inet RTEs payload size is %zuB",
      LOOKUP (rip_ffff_type_str, ri->auth_type), stream_get_endp (rtes));

  /* packet header, unconditional */
  stream_reset (packet);
  stream_putc (packet, command);
  stream_putc (packet, version);
  stream_putw (packet, 0);

  /* authentication leading RTE, conditional */
  if (version == RIPv2 && ri->auth_type != RIP_NO_AUTH)
  {
    if (ri->key_chain)
    {
      struct keychain *keychain;

      keychain = keychain_lookup (ri->key_chain);
      if (keychain)
      {
        if (IS_RIP_DEBUG_AUTH)
          zlog_debug ("trying configured key chain '%s'", ri->key_chain);
        key = key_lookup_for_send (keychain);
      }
      else
      {
        if (IS_RIP_DEBUG_AUTH)
          zlog_debug ("key chain '%s' is configured, but does not exist", ri->key_chain);
      }
    }
    /* Pick correct auth string for sends, prepare auth_str buffer for use.
     * (left justified and padded).
     *
     * presumes one of ri or key is valid, and that the auth strings they point
     * to are nul terminated. If neither are present, auth_str will be fully
     * zero padded.
     *
     */
    if (key && key->string)
    {
      if (IS_RIP_DEBUG_AUTH)
        zlog_debug ("using keychain '%s', key %u for sending", ri->key_chain, key->index);
      auth_str = key->string;
    }
    else if (ri->auth_str)
    {
      if (IS_RIP_DEBUG_AUTH)
        zlog_debug ("using interface authentication string");
      auth_str = ri->auth_str;
    }
    if (auth_str == NULL)
    {
      if (IS_RIP_DEBUG_AUTH)
        zlog_debug ("authentication string lookup failed");
      return -1;
    }

    rip_auth_write_leading_rte (packet, ri, key ? key->index % 256 : 1, auth_str,
      RIP_HEADER_SIZE + RIP_RTE_SIZE + stream_get_endp (rtes));
  }

  /* RTEs payload, unconditional */
  if (stream_get_endp (rtes) % RIP_RTE_SIZE)
  {
    zlog_err ("%s: malformed input RTE buffer", __func__);
    return -1;
  }
  stream_write (packet, STREAM_DATA (rtes), stream_get_endp (rtes));
  stream_reset (rtes);

  /* authentication trailing data, even more conditional */
  if (version == RIPv2 && ri->auth_type == RIP_AUTH_HASH)
    rip_auth_write_trailer (packet, ri, auth_str);

  return 0;
}
Beispiel #28
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;
}
Beispiel #29
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);
}
Beispiel #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;
}