예제 #1
0
/* 
 * Read interface up/down msg (ZEBRA_INTERFACE_UP/ZEBRA_INTERFACE_DOWN)
 * from zebra server.  The format of this message is the same as
 * that sent for ZEBRA_INTERFACE_ADD/ZEBRA_INTERFACE_DELETE (see
 * comments for zebra_interface_add_read), except that no sockaddr_dl
 * is sent at the tail of the message.
 */
struct interface *
zebra_interface_state_read (struct stream *s)
{
  struct interface *ifp;
  char ifname_tmp[INTERFACE_NAMSIZ];

  /* Read interface name. */
  stream_get (ifname_tmp, s, INTERFACE_NAMSIZ);

  /* Lookup this by interface index. */
  ifp = if_lookup_by_name_len (ifname_tmp,
			       strnlen(ifname_tmp, INTERFACE_NAMSIZ));

  /* If such interface does not exist, indicate an error */
  if (! ifp)
     return NULL;

  /* Read interface's index. */
  ifp->ifindex = stream_getl (s);

  /* Read interface's value. */
  ifp->status = stream_getc (s);
  ifp->flags = stream_getq (s);
  ifp->metric = stream_getl (s);
  ifp->mtu = stream_getl (s);
  ifp->mtu6 = stream_getl (s);
  ifp->bandwidth = stream_getl (s);

  return ifp;
}
예제 #2
0
파일: zclient.c 프로젝트: KaloNK/quagga
static void
link_params_set_value(struct stream *s, struct if_link_params *iflp)
{
  
  if (iflp == NULL)
    return;
  
  iflp->lp_status = stream_getl (s);
  iflp->te_metric = stream_getl (s);
  iflp->max_bw = stream_getf (s);
  iflp->max_rsv_bw = stream_getf (s);
  uint32_t bwclassnum = stream_getl (s);
  {
    unsigned int i;
    for (i = 0; i < bwclassnum && i < MAX_CLASS_TYPE; i++)
      iflp->unrsv_bw[i] = stream_getf (s);
    if (i < bwclassnum)
      zlog_err ("%s: received %d > %d (MAX_CLASS_TYPE) bw entries"
                " - outdated library?",
                __func__, bwclassnum, MAX_CLASS_TYPE);
  }
  iflp->admin_grp = stream_getl (s);
  iflp->rmt_as = stream_getl (s);
  iflp->rmt_ip.s_addr = stream_get_ipv4 (s);
  
  iflp->av_delay = stream_getl (s);
  iflp->min_delay = stream_getl (s);
  iflp->max_delay = stream_getl (s);
  iflp->delay_var = stream_getl (s);
  
  iflp->pkt_loss = stream_getf (s);
  iflp->res_bw = stream_getf (s);
  iflp->ava_bw = stream_getf (s);
  iflp->use_bw = stream_getf (s);
}
예제 #3
0
/* Zebra route add and delete treatment. */
static int
rip_zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length)
{
  struct stream *s;
  struct zapi_ipv4 api;
  unsigned long ifindex;
  struct in_addr nexthop;
  struct prefix_ipv4 p;
  
  s = zclient->ibuf;
  ifindex = 0;
  nexthop.s_addr = 0;

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

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

  /* Nexthop, ifindex, distance, metric. */
  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
    {
      api.nexthop_num = stream_getc (s);
      nexthop.s_addr = stream_get_ipv4 (s);
    }
  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
    {
      api.ifindex_num = stream_getc (s);
      ifindex = stream_getl (s);
    }
  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
    api.distance = stream_getc (s);
  else
    api.distance = 255;
  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
    api.metric = stream_getl (s);
  else
    api.metric = 0;

  /* Then fetch IPv4 prefixes. */
  if (command == ZEBRA_IPV4_ROUTE_ADD)
    rip_redistribute_add (api.type, RIP_ROUTE_REDISTRIBUTE, &p, ifindex, 
                          &nexthop, api.metric, api.distance);
  else 
    rip_redistribute_delete (api.type, RIP_ROUTE_REDISTRIBUTE, &p, ifindex);

  return 0;
}
예제 #4
0
static int
babel_zebra_read_ipv4 (int command, struct zclient *zclient,
		       zebra_size_t length)
{
    struct stream *s;
    struct zapi_ipv4 api;
    unsigned long ifindex = -1;
    struct in_addr nexthop;
    struct prefix_ipv4 prefix;

    s = zclient->ibuf;
    ifindex = 0;
    memset (&nexthop, 0, sizeof (struct in_addr));
    memset (&api, 0, sizeof(struct zapi_ipv4));
    memset (&prefix, 0, sizeof (struct prefix_ipv4));

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

    /* IPv6 prefix. */
    prefix.family = AF_INET;
    prefix.prefixlen = stream_getc (s);
    stream_get (&prefix.prefix, s, PSIZE (prefix.prefixlen));

    /* Nexthop, ifindex, distance, metric. */
    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) {
        api.nexthop_num = stream_getc (s);
        stream_get (&nexthop, s, sizeof(nexthop));
    }
    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) {
        api.ifindex_num = stream_getc (s);
        ifindex = stream_getl (s);
    }
    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
        api.distance = stream_getc (s);
    else
        api.distance = 0;
    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
        api.metric = stream_getl (s);
    else
        api.metric = 0;

    if (command == ZEBRA_IPV6_ROUTE_ADD) {
        babel_ipv4_route_add(&api, &prefix, ifindex, &nexthop);
    } else {
        babel_ipv4_route_delete(&api, &prefix, ifindex);
    }

    return 0;
}
예제 #5
0
/* Zebra route add and delete treatment. */
int
ripng_zebra_read_ipv6 (int command, struct zclient *zclient,
		       zebra_size_t length)
{
  struct stream *s;
  struct zapi_ipv6 api;
  unsigned long ifindex;
  struct in6_addr nexthop;
  struct prefix_ipv6 p;

  s = zclient->ibuf;
  ifindex = 0;
  memset (&nexthop, 0, sizeof (struct in6_addr));

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

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

  /* Nexthop, ifindex, distance, metric. */
  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
    {
      api.nexthop_num = stream_getc (s);
      stream_get (&nexthop, s, 16);
    }
  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
    {
      api.ifindex_num = stream_getc (s);
      ifindex = stream_getl (s);
    }
  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
    api.distance = stream_getc (s);
  else
    api.distance = 0;
  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
    api.metric = stream_getl (s);
  else
    api.metric = 0;

  if (command == ZEBRA_IPV6_ROUTE_ADD)
    ripng_redistribute_add (api.type, 0, &p, ifindex);
  else
    ripng_redistribute_delete (api.type, 0, &p, ifindex);

  return 0;
}
예제 #6
0
void
zebra_interface_if_set_value (struct stream *s, struct interface *ifp)
{
  /* Read interface's index. */
  ifp->ifindex = stream_getl (s);
  ifp->status = stream_getc (s);

  /* Read interface's value. */
  ifp->flags = stream_getq (s);
  ifp->metric = stream_getl (s);
  ifp->mtu = stream_getl (s);
  ifp->mtu6 = stream_getl (s);
  ifp->bandwidth = stream_getl (s);
}
예제 #7
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;
}
예제 #8
0
파일: ospf_dump.c 프로젝트: ton31337/frr
static void ospf_packet_ls_req_dump(struct stream *s, uint16_t length)
{
	uint32_t sp;
	uint32_t ls_type;
	struct in_addr ls_id;
	struct in_addr adv_router;

	sp = stream_get_getp(s);

	length -= OSPF_HEADER_SIZE;

	zlog_debug("Link State Request");
	zlog_debug("  # Requests %d", length / 12);

	for (; length > 0; length -= 12) {
		ls_type = stream_getl(s);
		ls_id.s_addr = stream_get_ipv4(s);
		adv_router.s_addr = stream_get_ipv4(s);

		zlog_debug("  LS type %d", ls_type);
		zlog_debug("  Link State ID %s", inet_ntoa(ls_id));
		zlog_debug("  Advertising Router %s", inet_ntoa(adv_router));
	}

	stream_set_getp(s, sp);
}
예제 #9
0
파일: isis_zebra.c 프로젝트: OPSF/uClinux
int
isis_zebra_read_ipv4 (int command, struct zclient *zclient,
                      zebra_size_t length)
{
    struct stream *stream;
    struct zapi_ipv4 api;
    struct prefix_ipv4 p;
    unsigned long ifindex;
    struct in_addr nexthop;

    stream = zclient->ibuf;
    memset (&p, 0, sizeof (struct prefix_ipv4));
    ifindex = 0;

    api.type = stream_getc (stream);
    api.flags = stream_getc (stream);
    api.message = stream_getc (stream);

    p.family = AF_INET;
    p.prefixlen = stream_getc (stream);
    stream_get (&p.prefix, stream, PSIZE (p.prefixlen));

    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
    {
        api.nexthop_num = stream_getc (stream);
        nexthop.s_addr = stream_get_ipv4 (stream);
    }
    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
    {
        api.ifindex_num = stream_getc (stream);
        ifindex = stream_getl (stream);
    }
    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
        api.distance = stream_getc (stream);
    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
        api.metric = stream_getl (stream);
    else
        api.metric = 0;

    if (command == ZEBRA_IPV4_ROUTE_ADD)
    {
        zlog_debug ("IPv4 Route add from Z");
    }

    return 0;
}
struct connected *
zebra_interface_address_read (int type, struct stream *s)
{
  unsigned int ifindex;
  struct interface *ifp;
  struct connected *ifc;
  struct prefix p, d;
  int family;
  int plen;
  u_char ifc_flags;

  memset (&p, 0, sizeof(p));
  memset (&d, 0, sizeof(d));

  /* Get interface index. */
  ifindex = stream_getl (s);

  /* Lookup index. */
  ifp = if_lookup_by_index (ifindex);
  if (ifp == NULL)
    {
      zlog_warn ("zebra_interface_address_read(%s): "
                 "Can't find interface by ifindex: %d ",
                 (type == ZEBRA_INTERFACE_ADDRESS_ADD? "ADD" : "DELETE"),
                 ifindex);
      return NULL;
    }

  /* Fetch flag. */
  ifc_flags = stream_getc (s);

  /* Fetch interface address. */
  family = p.family = stream_getc (s);

  plen = prefix_blen (&p);
  stream_get (&p.u.prefix, s, plen);
  p.prefixlen = stream_getc (s);

  /* Fetch destination address. */
  stream_get (&d.u.prefix, s, plen);
  d.family = family;

  if (type == ZEBRA_INTERFACE_ADDRESS_ADD) 
    {
       /* N.B. NULL destination pointers are encoded as all zeroes */
       ifc = connected_add_by_prefix(ifp, &p,(memconstant(&d.u.prefix,0,plen) ?
					      NULL : &d));
       if (ifc != NULL)
       ifc->flags = ifc_flags;
    }
  else
    {
      assert (type == ZEBRA_INTERFACE_ADDRESS_DELETE);
      ifc = connected_delete_by_prefix(ifp, &p);
    }

  return ifc;
}
예제 #11
0
파일: zclient.c 프로젝트: KaloNK/quagga
void
zebra_interface_if_set_value (struct stream *s, struct interface *ifp)
{
  u_char link_params_status = 0;

  /* Read interface's index. */
  ifp->ifindex = stream_getl (s);
  ifp->status = stream_getc (s);

  /* Read interface's value. */
  ifp->flags = stream_getq (s);
  ifp->metric = stream_getl (s);
  ifp->mtu = stream_getl (s);
  ifp->mtu6 = stream_getl (s);
  ifp->bandwidth = stream_getl (s);
  ifp->ll_type = stream_getl (s);
  ifp->hw_addr_len = stream_getl (s);
  if (ifp->hw_addr_len)
    stream_get (ifp->hw_addr, s, MIN(ifp->hw_addr_len, INTERFACE_HWADDR_MAX));

  /* Read Traffic Engineering status */
  link_params_status = stream_getc (s);
  /* Then, Traffic Engineering parameters if any */
  if (link_params_status)
    {
      struct if_link_params *iflp = if_link_params_get (ifp);
      link_params_set_value(s, iflp);
    }
}
예제 #12
0
static as_t
bgp_capability_as4 (struct peer *peer, struct capability_header *hdr)
{
  as_t as4 = stream_getl (BGP_INPUT(peer));
  
  if (BGP_DEBUG (as4, AS4))
    zlog_debug ("%s [AS4] about to set cap PEER_CAP_AS4_RCV, got as4 %u",
                peer->host, as4);
  SET_FLAG (peer->cap, PEER_CAP_AS4_RCV);
  
  return as4;
}
예제 #13
0
struct interface *
zebra_interface_add_read (struct stream *s)
{
  struct interface *ifp;
  char ifname_tmp[INTERFACE_NAMSIZ];

  /* Read interface name. */
  stream_get (ifname_tmp, s, INTERFACE_NAMSIZ);

  /* Lookup/create interface by name. */
  ifp = if_get_by_name_len (ifname_tmp, strnlen(ifname_tmp, INTERFACE_NAMSIZ));

  /* Read interface's index. */
  ifp->ifindex = stream_getl (s);

  /* Read interface's value. */
  ifp->status = stream_getc (s);
  ifp->flags = stream_getq (s);
  ifp->metric = stream_getl (s);
  ifp->mtu = stream_getl (s);
  ifp->mtu6 = stream_getl (s);
  ifp->bandwidth = stream_getl (s);
#ifdef HAVE_SOCKADDR_DL
  stream_get (&ifp->sdl, s, sizeof (ifp->sdl));
#else
  ifp->hw_addr_len = stream_getl (s);
  if (ifp->hw_addr_len)
    stream_get (ifp->hw_addr, s, ifp->hw_addr_len);
#endif /* HAVE_SOCKADDR_DL */
  
  return ifp;
}
int ppp_tcp_read(struct thread *thread)
{
	struct ppp_mcp_sock *peer;
	//int data_len;

	/* Yes first of all get peer pointer. */
	peer = THREAD_ARG (thread);
	peer->t_read = NULL;

	if (peer->fd < 0)
	{
		PPPD_DEBUG_TCP("read: peer's fd is negative value %d", peer->fd);
		return -1;
	}
    
	MCP_READ_ON (peer->t_read, ppp_tcp_read, peer, peer->fd);

    if (peer->packet_size == 0)
		peer->packet_size = MCP_PPP_HEADER_SIZE;

    if (stream_get_endp (peer->ibuf) < MCP_PPP_HEADER_SIZE) {
        if(mcp_pppd_read(peer) == -1)
            return 0;

        peer->packet_size = stream_getl(peer->ibuf);
        peer->control_cmd = stream_getl(peer->ibuf);
    }
		
    if(mcp_pppd_read(peer) == -1) {
        PPPD_DEBUG_TCP("ppp read tcp error:%s", peer->hostname);
        return 0;
    }
    mcp_pppd_tcp_read_deal(peer);
    stream_reset (peer->ibuf);
    peer->packet_size = 0;
    pppd_postpone_holdtime_timer(peer);
    
	return 0;

}
예제 #15
0
static as_t
bgp_capability_as4 (struct peer *peer, struct capability_header *hdr)
{
  SET_FLAG (peer->cap, PEER_CAP_AS4_RCV);
  
  if (hdr->length != CAPABILITY_CODE_AS4_LEN)
    {
      zlog_err ("%s AS4 capability has incorrect data length %d",
                peer->host, hdr->length);
      return 0;
    }
  
  as_t as4 = stream_getl (BGP_INPUT(peer));
  
  if (BGP_DEBUG (as4, AS4))
    zlog_debug ("%s [AS4] about to set cap PEER_CAP_AS4_RCV, got as4 %u",
                peer->host, as4);
  return as4;
}
예제 #16
0
void
zebra_interface_if_set_value (struct stream *s, struct interface *ifp)
{
  /* Read interface's index. */
  ifp->ifindex = stream_getl (s);
  ifp->status = stream_getc (s);

  /* Read interface's value. */
  ifp->flags = stream_getq (s);
  ifp->metric = stream_getl (s);
  ifp->mtu = stream_getl (s);
  ifp->mtu6 = stream_getl (s);
  ifp->bandwidth = stream_getl (s);
  ifp->ll_type = stream_getl (s);
  ifp->hw_addr_len = stream_getl (s);
  if (ifp->hw_addr_len)
    stream_get (ifp->hw_addr, s, MIN(ifp->hw_addr_len, INTERFACE_HWADDR_MAX));
}
예제 #17
0
파일: zserv.c 프로젝트: OPSF/uClinux
void
zebra_read_ipv6 (int command, struct zserv *client, u_short length)
{
  u_char type;
  u_char flags;
  struct in6_addr nexthop, *gate;
  u_char *lim;
  u_char *pnt;
  unsigned int ifindex;

  pnt = stream_pnt (client->ibuf);
  lim = pnt + length;

  type = stream_getc (client->ibuf);
  flags = stream_getc (client->ibuf);
  stream_get (&nexthop, client->ibuf, sizeof (struct in6_addr));
  
  while (stream_pnt (client->ibuf) < lim)
    {
      int size;
      struct prefix_ipv6 p;
      
      ifindex = stream_getl (client->ibuf);

      memset (&p, 0, sizeof (struct prefix_ipv6));
      p.family = AF_INET6;
      p.prefixlen = stream_getc (client->ibuf);
      size = PSIZE(p.prefixlen);
      stream_get (&p.prefix, client->ibuf, size);

      if (IN6_IS_ADDR_UNSPECIFIED (&nexthop))
        gate = NULL;
      else
        gate = &nexthop;

      if (command == ZEBRA_IPV6_ROUTE_ADD)
        rib_add_ipv6 (type, flags, &p, gate, ifindex, 0, 0, 0);
      else
        rib_delete_ipv6 (type, flags, &p, gate, ifindex, 0);
    }
}
예제 #18
0
파일: zclient.c 프로젝트: KaloNK/quagga
struct interface *
zebra_interface_link_params_read (struct stream *s)
{
  struct if_link_params *iflp;
  uint32_t ifindex = stream_getl (s);

  struct interface *ifp = if_lookup_by_index (ifindex);

  if (ifp == NULL || s == NULL)
    {
      zlog_err ("%s: unknown ifindex %u, shouldn't happen",
                __func__, ifindex);
      return NULL;
    }

  if ((iflp = if_link_params_get (ifp)) == NULL)
    return NULL;

  link_params_set_value(s, iflp);
  
  return ifp;
}
예제 #19
0
struct interface_FOO *
zebra_interface_add_read (struct stream *s)
{
  struct interface_FOO *ifp;
  char ifname_tmp[INTERFACE_NAMSIZ];

  /* Read interface name. */
  stream_get (ifname_tmp, s, INTERFACE_NAMSIZ);

  /* Lookup this by interface name. */
  ifp = if_lookup_by_name (ifname_tmp);

  /* If such interface does not exist, make new one. */
  if (! ifp)
    ifp = if_create (ifname_tmp, INTERFACE_NAMSIZ);

  /* Read interface's index. */
  ifp->ifindex = stream_getl (s);

  /* Read interface's value. */
  ifp->status = stream_getc (s);
  ifp->flags = stream_getl (s);
  ifp->metric = stream_getl (s);
  ifp->mtu = stream_getl (s);
  ifp->mtu6 = stream_getl (s);
  ifp->bandwidth = stream_getl (s);
#ifdef HAVE_SOCKADDR_DL
  stream_get (&ifp->sdl, s, sizeof (ifp->sdl));
#else
  ifp->hw_addr_len = stream_getl (s);
  if (ifp->hw_addr_len)
    stream_get (ifp->hw_addr, s, ifp->hw_addr_len);
#endif /* HAVE_SOCKADDR_DL */
  
  return ifp;
}
예제 #20
0
void
zebra_interface_if_set_value (struct stream *s, struct interface *ifp)
{
  /* Read interface's index. */
  ifp->ifindex = stream_getl (s);
  ifp->status = stream_getc (s);

  /* Read interface's value. */
  ifp->flags = stream_getq (s);
  ifp->metric = stream_getl (s);
  ifp->mtu = stream_getl (s);
  ifp->mtu6 = stream_getl (s);
  ifp->bandwidth = stream_getl (s);
#ifdef HAVE_STRUCT_SOCKADDR_DL
  stream_get (&ifp->sdl, s, sizeof (ifp->sdl_storage));
#else
  ifp->hw_addr_len = stream_getl (s);
  if (ifp->hw_addr_len)
    stream_get (ifp->hw_addr, s, ifp->hw_addr_len);
#endif /* HAVE_STRUCT_SOCKADDR_DL */
}
예제 #21
0
static int
ospf6_zebra_read_ipv6 (int command, struct zclient *zclient,
                       zebra_size_t length)
{
  struct stream *s;
  struct zapi_ipv6 api;
  unsigned long ifindex;
  struct prefix_ipv6 p;
  struct in6_addr *nexthop;

  s = zclient->ibuf;
  ifindex = 0;
  nexthop = NULL;
  memset (&api, 0, sizeof (api));

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

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

  /* Nexthop, ifindex, distance, metric. */
  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
    {
      api.nexthop_num = stream_getc (s);
      nexthop = (struct in6_addr *)
        malloc (api.nexthop_num * sizeof (struct in6_addr));
      stream_get (nexthop, s, api.nexthop_num * sizeof (struct in6_addr));
    }
  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
    {
      api.ifindex_num = stream_getc (s);
      ifindex = stream_getl (s);
    }
  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
    api.distance = stream_getc (s);
  else
    api.distance = 0;
  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
    api.metric = stream_getl (s);
  else
    api.metric = 0;

  if (IS_OSPF6_DEBUG_ZEBRA (RECV))
    {
      char prefixstr[128], nexthopstr[128];
      prefix2str ((struct prefix *)&p, prefixstr, sizeof (prefixstr));
      if (nexthop)
        inet_ntop (AF_INET6, nexthop, nexthopstr, sizeof (nexthopstr));
      else
        snprintf (nexthopstr, sizeof (nexthopstr), "::");

      zlog_debug ("Zebra Receive route %s: %s %s nexthop %s ifindex %ld",
		  (command == ZEBRA_IPV6_ROUTE_ADD ? "add" : "delete"),
		  zebra_route_string(api.type), prefixstr, nexthopstr, ifindex);
    }
 
  if (command == ZEBRA_IPV6_ROUTE_ADD)
    ospf6_asbr_redistribute_add (api.type, ifindex, (struct prefix *) &p,
                                 api.nexthop_num, nexthop);
  else
    ospf6_asbr_redistribute_remove (api.type, ifindex, (struct prefix *) &p);

  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
    free (nexthop);

  return 0;
}
예제 #22
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;
}
예제 #23
0
static struct bgp_nexthop_cache *
zlookup_read_ipv6 (void)
{
  struct stream *s;
  uint16_t length;
  u_char version, marker;
  uint16_t  command;
  int nbytes;
  struct in6_addr raddr;
  uint32_t metric;
  int i;
  u_char nexthop_num;
  struct nexthop *nexthop;
  struct bgp_nexthop_cache *bnc;

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

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

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

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

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

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

  return bnc;
}
예제 #24
0
파일: ospf_dump.c 프로젝트: ton31337/frr
static void ospf_packet_ls_upd_dump(struct stream *s, uint16_t length)
{
	uint32_t sp;
	struct lsa_header *lsa;
	int lsa_len;
	uint32_t count;

	length -= OSPF_HEADER_SIZE;

	sp = stream_get_getp(s);

	count = stream_getl(s);
	length -= 4;

	zlog_debug("Link State Update");
	zlog_debug("  # LSAs %d", count);

	while (length > 0 && count > 0) {
		if (length < OSPF_HEADER_SIZE || length % 4 != 0) {
			zlog_debug("  Remaining %d bytes; Incorrect length.",
				   length);
			break;
		}

		lsa = (struct lsa_header *)stream_pnt(s);
		lsa_len = ntohs(lsa->length);
		ospf_lsa_header_dump(lsa);

		switch (lsa->type) {
		case OSPF_ROUTER_LSA:
			ospf_router_lsa_dump(s, length);
			break;
		case OSPF_NETWORK_LSA:
			ospf_network_lsa_dump(s, length);
			break;
		case OSPF_SUMMARY_LSA:
		case OSPF_ASBR_SUMMARY_LSA:
			ospf_summary_lsa_dump(s, length);
			break;
		case OSPF_AS_EXTERNAL_LSA:
			ospf_as_external_lsa_dump(s, length);
			break;
		case OSPF_AS_NSSA_LSA:
			ospf_as_external_lsa_dump(s, length);
			break;
		case OSPF_OPAQUE_LINK_LSA:
		case OSPF_OPAQUE_AREA_LSA:
		case OSPF_OPAQUE_AS_LSA:
			ospf_opaque_lsa_dump(s, length);
			break;
		default:
			break;
		}

		stream_forward_getp(s, lsa_len);
		length -= lsa_len;
		count--;
	}

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

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

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

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

  len = length - 2;

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

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

  raddr.s_addr = stream_get_ipv4(s);

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

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

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

  len -= MIN_LEN;

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

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

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

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

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

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

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

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

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

  return bnc;
}
예제 #27
0
struct connected *
zebra_interface_address_read (int type, struct stream *s)
{
  unsigned int ifindex;
  struct interface *ifp;
  struct connected *ifc;
  struct prefix p, d;
  int family;
  int plen;
  u_char ifc_flags;

  memset (&p, 0, sizeof(p));
  memset (&d, 0, sizeof(d));

  /* Get interface index. */
  ifindex = stream_getl (s);

  /* Lookup index. */
  ifp = if_lookup_by_index (ifindex);
  if (ifp == NULL)
    {
      zlog_warn ("zebra_interface_address_read(%s): "
                 "Can't find interface by ifindex: %d ",
                 (type == ZEBRA_INTERFACE_ADDRESS_ADD? "ADD" : "DELETE"),
                 ifindex);
      return NULL;
    }

  /* Fetch flag. */
  ifc_flags = stream_getc (s);

  /* Fetch interface address. */
  family = p.family = stream_getc (s);

  plen = prefix_blen (&p);
  stream_get (&p.u.prefix, s, plen);
  p.prefixlen = stream_getc (s);

  /* Fetch destination address. */
  stream_get (&d.u.prefix, s, plen);
  d.family = family;

  if (type == ZEBRA_INTERFACE_ADDRESS_ADD) 
    {
       /* N.B. NULL destination pointers are encoded as all zeroes */
       ifc = connected_add_by_prefix(ifp, &p,(memconstant(&d.u.prefix,0,plen) ?
					      NULL : &d));
       if (ifc != NULL)
	 {
	   ifc->flags = ifc_flags;
	   if (ifc->destination)
	     ifc->destination->prefixlen = ifc->address->prefixlen;
	   else if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER))
	     {
	       /* carp interfaces on OpenBSD with 0.0.0.0/0 as "peer" */
	       char buf[BUFSIZ];
	       prefix2str (ifc->address, buf, sizeof(buf));
	       zlog_warn("warning: interface %s address %s "
		    "with peer flag set, but no peer address!",
		    ifp->name, buf);
	       UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
	     }
	 }
    }
  else
    {
      assert (type == ZEBRA_INTERFACE_ADDRESS_DELETE);
      ifc = connected_delete_by_prefix(ifp, &p);
    }

  return ifc;
}
예제 #28
0
파일: zserv.c 프로젝트: OPSF/uClinux
/* Zebra server IPv6 prefix add function. */
static void
zread_ipv6_add (struct zserv *client, u_short length)
{
  int i;
  struct stream *s;
  struct zapi_ipv6 api;
  struct in6_addr nexthop;
  unsigned long ifindex;
  struct prefix_ipv6 p;
  
  s = client->ibuf;
  ifindex = 0;
  memset (&nexthop, 0, sizeof (struct in6_addr));

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

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

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

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

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

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

  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
    api.metric = stream_getl (s);
  else
    api.metric = 0;
    
  if (IN6_IS_ADDR_UNSPECIFIED (&nexthop))
    rib_add_ipv6 (api.type, api.flags, &p, NULL, ifindex, 0, api.metric,
		  api.distance);
  else
    rib_add_ipv6 (api.type, api.flags, &p, &nexthop, ifindex, 0, api.metric,
		  api.distance);
}
예제 #29
0
파일: zserv.c 프로젝트: OPSF/uClinux
/* Zebra server IPv4 prefix delete function. */
static void
zread_ipv4_delete (struct zserv *client, u_short length)
{
  int i;
  struct stream *s;
  struct zapi_ipv4 api;
  struct in_addr nexthop;
  unsigned long ifindex;
  struct prefix_ipv4 p;
  u_char nexthop_num;
  u_char nexthop_type;
  u_char ifname_len;
  
  s = client->ibuf;
  ifindex = 0;
  nexthop.s_addr = 0;

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

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

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

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

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

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

  /* Metric. */
  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
    api.metric = stream_getl (s);
  else
    api.metric = 0;
    
  rib_delete_ipv4 (api.type, api.flags, &p, &nexthop, ifindex,
		   client->rtm_table);
}
예제 #30
0
파일: zserv.c 프로젝트: OPSF/uClinux
/* 
 * Parse the ZEBRA_IPV4_ROUTE_ADD sent from client. Update rib and
 * add kernel route. 
 */
static void
zread_ipv4_add (struct zserv *client, u_short length)
{
  int i;
  struct rib *rib;
  struct prefix_ipv4 p;
  u_char message;
  struct in_addr nexthop;
  u_char nexthop_num;
  u_char nexthop_type;
  struct stream *s;
  unsigned int ifindex;
  u_char ifname_len;

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

  /* Allocate new rib. */
  rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
  memset (rib, 0, sizeof (struct rib));

  /* Type, flags, message. */
  rib->type = stream_getc (s);
  rib->flags = stream_getc (s);
  message = stream_getc (s); 
  rib->uptime = time (NULL);

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

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

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

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

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

  /* Metric. */
  if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
    rib->metric = stream_getl (s);
    
  rib_add_ipv4_multipath (&p, rib);
}