Пример #1
0
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;
}
Пример #2
0
static struct bgp_nexthop_cache *
zlookup_read_ipv6 (void)
{
  struct stream *s;
  uint16_t length;
  u_char version, marker;
  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);

  /* XXX: ignoring nbytes, see also zread_lookup */
  stream_read (s, zlookup->sock, 2);
  length = stream_getw (s);

  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: ignoring command */  
  stream_getw (s);
  
  /* XXX: not actually doing anything with raddr */
  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;
}
Пример #3
0
static int decomp_fetch_byte_callback(void *opaque)
{
  stream_mtfdecomp *sm = opaque;

  return stream_getc(sm->input);
}
Пример #4
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 __attribute__((unused));
  u_char version, marker;
  int nbytes __attribute__((unused));
  struct in_addr addr __attribute__((unused));
  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, VRF_DEFAULT);
  
  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. */
  /* XXX: not using nbytes */
  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;
    }
  
  /* XXX: not using command */
  command = stream_getw (s);
  
  /* XXX: not using addr */
  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);
      switch (nexthop_type)
	{
	case ZEBRA_NEXTHOP_IPV4:
	  nexthop.s_addr = stream_get_ipv4 (s);
	  break;
	case ZEBRA_NEXTHOP_IPV4_IFINDEX:
	  nexthop.s_addr = stream_get_ipv4 (s);
	  /* ifindex */ (void)stream_getl (s);
	  break;
	default:
	  /* do nothing */
	  break;
	}
      *igpnexthop = nexthop;

      return 1;
    }
  else
    return 0;
}
Пример #5
0
static int redist_read_ipv4_route(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;
  int min_len = 4;

  if (length < min_len) {
    zlog_warn("%s %s: short buffer: length=%d min=%d",
	      __FILE__, __PRETTY_FUNCTION__,
	      length, min_len);
    return -1;
  }

  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 length. */
  memset(&p, 0, sizeof(struct prefix_ipv4));
  p.family = AF_INET;
  p.prefixlen = stream_getc(s);

  min_len +=
    PSIZE(p.prefixlen) +
    CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP) ? 5 : 0 +
    CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX) ? 5 : 0 +
    CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE) ? 1 : 0 +
    CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC) ? 4 : 0;

  if (PIM_DEBUG_ZEBRA) {
    zlog_debug("%s %s: length=%d min_len=%d flags=%s%s%s%s",
	       __FILE__, __PRETTY_FUNCTION__,
	       length, min_len,
	       CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP) ? "nh" : "",
	       CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX) ? " ifi" : "",
	       CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE) ? " dist" : "",
	       CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC) ? " metr" : "");
  }

  if (length < min_len) {
    zlog_warn("%s %s: short buffer: length=%d min_len=%d flags=%s%s%s%s",
	      __FILE__, __PRETTY_FUNCTION__,
	      length, min_len,
	      CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP) ? "nh" : "",
	      CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX) ? " ifi" : "",
	      CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE) ? " dist" : "",
	      CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC) ? " metr" : "");
    return -1;
  }

  /* IPv4 prefix. */
  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);
  }

  api.distance = CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE) ?
    stream_getc(s) :
    0;

  api.metric = CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC) ?
    stream_getl(s) :
    0;

  switch (command) {
  case ZEBRA_IPV4_ROUTE_ADD:
    if (PIM_DEBUG_ZEBRA) {
      char buf[2][INET_ADDRSTRLEN];
      zlog_debug("%s: add %s %s/%d "
		 "nexthop %s ifindex %ld metric%s %u distance%s %u",
		 __PRETTY_FUNCTION__,
		 zebra_route_string(api.type),
		 inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])),
		 p.prefixlen,
		 inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
		 ifindex,
		 CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC) ? "-recv" : "-miss",
		 api.metric,
		 CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE) ? "-recv" : "-miss",
		 api.distance);
    }
    break;
  case ZEBRA_IPV4_ROUTE_DELETE:
    if (PIM_DEBUG_ZEBRA) {
      char buf[2][INET_ADDRSTRLEN];
      zlog_debug("%s: delete %s %s/%d "
		 "nexthop %s ifindex %ld metric%s %u distance%s %u",
		 __PRETTY_FUNCTION__,
		 zebra_route_string(api.type),
		 inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])),
		 p.prefixlen,
		 inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
		 ifindex,
		 CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC) ? "-recv" : "-miss",
		 api.metric,
		 CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE) ? "-recv" : "-miss",
		 api.distance);
    }
    break;
  default:
    zlog_warn("%s: unknown command=%d", __PRETTY_FUNCTION__, command);
    return -1;
  }

  sched_rpf_cache_refresh();

  return 0;
}
Пример #6
0
/* Zebra client message read function. */
static int
zclient_read (struct thread *thread)
{
  int ret;
  size_t already;
  uint16_t length, command;
  uint8_t marker, version;
  struct zclient *zclient;

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

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

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

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

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

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

  length -= ZEBRA_HEADER_SIZE;

  #ifdef ZCLIENT_DEBUG
    zlog_debug("zclient 0x%p command 0x%x \n", zclient, command);
  #endif

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

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

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

  return 0;
}
Пример #7
0
/* Zebra route add and delete treatment. */
static int
zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length)
{
  struct stream *s;
  struct zapi_ipv6 api;
  struct in6_addr nexthop;
  struct prefix_ipv6 p;

  s = zclient->ibuf;
  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);
      stream_getl (s); /* ifindex, unused */
    }
  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;

  /* Simply ignore link-local address. */
  if (IN6_IS_ADDR_LINKLOCAL (&p.prefix))
    return 0;

  if (command == ZEBRA_IPV6_ROUTE_ADD)
    {
      if (BGP_DEBUG(zebra, ZEBRA))
	{
	  char buf[2][INET6_ADDRSTRLEN];
	  zlog_debug("Zebra rcvd: IPv6 route add %s %s/%d nexthop %s metric %u",
		     zebra_route_string(api.type),
		     inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])),
		     p.prefixlen,
		     inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
		     api.metric);
	}
      bgp_redistribute_add ((struct prefix *)&p, NULL, &nexthop,
			    api.metric, api.type);
    }
  else
    {
      if (BGP_DEBUG(zebra, ZEBRA))
	{
	  char buf[2][INET6_ADDRSTRLEN];
	  zlog_debug("Zebra rcvd: IPv6 route delete %s %s/%d "
		     "nexthop %s metric %u",
		     zebra_route_string(api.type),
		     inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])),
		     p.prefixlen,
		     inet_ntop(AF_INET6, &nexthop, buf[1], sizeof(buf[1])),
		     api.metric);
	}
      bgp_redistribute_delete ((struct prefix *) &p, api.type);
    }
  
  return 0;
}
Пример #8
0
/* peek into option, stores ASN to *as4 if the AS4 capability was found.
 * Returns  0 if no as4 found, as4cap value otherwise.
 */
as_t
peek_for_as4_capability (struct peer *peer, u_char length)
{
    struct stream *s = BGP_INPUT (peer);
    size_t orig_getp = stream_get_getp (s);
    size_t end = orig_getp + length;
    as_t as4 = 0;

    /* The full capability parser will better flag the error.. */
    if (STREAM_READABLE(s) < length)
        return 0;

    if (BGP_DEBUG (as4, AS4))
        zlog_info ("%s [AS4] rcv OPEN w/ OPTION parameter len: %u,"
                   " peeking for as4",
                   peer->host, length);
    /* the error cases we DONT handle, we ONLY try to read as4 out of
     * correctly formatted options.
     */
    while (stream_get_getp(s) < end)
    {
        u_char opt_type;
        u_char opt_length;

        /* Check the length. */
        if (stream_get_getp (s) + 2 > end)
            goto end;

        /* Fetch option type and length. */
        opt_type = stream_getc (s);
        opt_length = stream_getc (s);

        /* Option length check. */
        if (stream_get_getp (s) + opt_length > end)
            goto end;

        if (opt_type == BGP_OPEN_OPT_CAP)
        {
            unsigned long capd_start = stream_get_getp (s);
            unsigned long capd_end = capd_start + opt_length;

            assert (capd_end <= end);

            while (stream_get_getp (s) < capd_end)
            {
                struct capability_header hdr;

                if (stream_get_getp (s) + 2 > capd_end)
                    goto end;

                hdr.code = stream_getc (s);
                hdr.length = stream_getc (s);

                if ((stream_get_getp(s) +  hdr.length) > capd_end)
                    goto end;

                if (hdr.code == CAPABILITY_CODE_AS4)
                {
                    if (BGP_DEBUG (as4, AS4))
                        zlog_info ("[AS4] found AS4 capability, about to parse");
                    as4 = bgp_capability_as4 (peer, &hdr);

                    goto end;
                }
                stream_forward_getp (s, hdr.length);
            }
        }
    }

end:
    stream_set_getp (s, orig_getp);
    return as4;
}
Пример #9
0
int
main (int argc, char **argv)
{
  int ret;
  FILE *fp;
  struct stream *s;
  time_t now;
  int type;
  int subtype;
  size_t len;
  int source_as;
  int dest_as;
  int ifindex;
  int family;
  struct in_addr sip;
  struct in_addr dip;
  u_int16_t viewno, seq_num;
  struct prefix_ipv4 p;

  s = stream_new (10000);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	      attr_parse (s, attrlen);

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

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

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

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

	  printf ("\n");
	}
    }
  fclose (fp);
  return 0;
}
Пример #10
0
/* Zebra client message read function. */
int
zclient_read (struct thread *thread)
{
  int ret;
  int nbytes;
  int sock;
  zebra_size_t length;
  zebra_command_t command;
#undef	zclient
  struct_zclient *zclient;

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

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

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

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

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

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

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

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

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

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

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

  return 0;
}
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;
}
Пример #12
0
static int stream_get(stream_t *stream, ph_var_err_t *error)
{
  int c;

  if (stream->state != STREAM_STATE_OK) {
    return stream->state;
  }

  if (!stream->buffer[stream->buffer_pos]) {
    uint8_t count;

    c = stream_getc(stream);
    if (c == STREAM_STATE_EOF) {
      return c;
    }

    stream->buffer[0] = c;
    stream->buffer_pos = 0;

    count = ph_utf8_seq_len(c);
    if (!count) {
      goto out;
    }

    if (count > 1) {
      /* multi-byte UTF-8 sequence */
      int i;

      assert(count >= 2);

      for (i = 1; i < count; i++) {
        stream->buffer[i] = stream_getc(stream);
      }

      if (!utf8_check_full(stream->buffer, count)) {
        goto out;
      }

      stream->buffer[count] = '\0';
    } else {
      stream->buffer[1] = '\0';
    }
  }

  c = stream->buffer[stream->buffer_pos++];

  stream->position++;
  if (c == '\n') {
    stream->line++;
    stream->last_column = stream->column;
    stream->column = 0;
  } else if (ph_utf8_seq_len(c) > 0) {
    /* track the Unicode character column, so increment only if
       this is the first character of a UTF-8 sequence */
    stream->column++;
  }

  return c;

out:
  stream->state = STREAM_STATE_ERROR;
  error_set(error, stream_to_lex(stream),
      "unable to decode byte 0x%02x", (uint8_t)c);
  return STREAM_STATE_ERROR;
}
Пример #13
0
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;
  char prefixstr[128], nexthopstr[128];

  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;

  /* log */
  if (IS_OSPF6_DUMP_ZEBRA)
    {
      prefix2str ((struct prefix *)&p, prefixstr, sizeof (prefixstr));
      inet_ntop (AF_INET6, &nexthop, nexthopstr, sizeof (nexthopstr));

      if (command == ZEBRA_IPV6_ROUTE_ADD)
	zlog_info ("ZEBRA: Receive add %s route: %s nexthop:%s ifindex:%ld",
		   zebra_route_name [api.type], prefixstr,
		   nexthopstr, ifindex);
      else
	zlog_info ("ZEBRA: Receive remove %s route: %s nexthop:%s ifindex:%ld",
		   zebra_route_name [api.type], prefixstr,
		   nexthopstr, ifindex);
    }
 
  if (command == ZEBRA_IPV6_ROUTE_ADD)
    ospf6_asbr_route_add (api.type, ifindex, (struct prefix *) &p,
                          api.nexthop_num, nexthop);
  else
    ospf6_asbr_route_remove (api.type, ifindex, (struct prefix *) &p);

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

  return 0;
}
Пример #14
0
static int
bgp_capability_restart (struct peer *peer, struct capability_header *caphdr)
{
    struct stream *s = BGP_INPUT (peer);
    u_int16_t restart_flag_time;
    size_t end = stream_get_getp (s) + caphdr->length;

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

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

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

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

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

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

        }
    }
    return 0;
}
Пример #15
0
/* Handler of zebra service request. */
static int
zebra_client_read (struct thread *thread)
{
  int sock;
  struct zserv *client;
  size_t already;
  uint16_t length, command;
  uint8_t marker, version;

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

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

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

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

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

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

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

  length -= ZEBRA_HEADER_SIZE;

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

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

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

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

  stream_reset (client->ibuf);
  zebra_event (ZEBRA_READ, sock, client);
  return 0;
}
Пример #16
0
/**
 * Parse given capability.
 * XXX: This is reading into a stream, but not using stream API
 *
 * @param[out] mp_capability Set to 1 on return iff one or more Multiprotocol
 *                           capabilities were encountered.
 */
static int
bgp_capability_parse (struct peer *peer, size_t length, int *mp_capability,
                      u_char **error)
{
    int ret;
    struct stream *s = BGP_INPUT (peer);
    size_t end = stream_get_getp (s) + length;

    assert (STREAM_READABLE (s) >= length);

    while (stream_get_getp (s) < end)
    {
        size_t start;
        u_char *sp = stream_pnt (s);
        struct capability_header caphdr;

        /* We need at least capability code and capability length. */
        if (stream_get_getp(s) + 2 > end)
        {
            zlog_info ("%s Capability length error (< header)", peer->host);
            bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSPECIFIC);
            return -1;
        }

        caphdr.code = stream_getc (s);
        caphdr.length = stream_getc (s);
        start = stream_get_getp (s);

        /* Capability length check sanity check. */
        if (start + caphdr.length > end)
        {
            zlog_info ("%s Capability length error (< length)", peer->host);
            bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSPECIFIC);
            return -1;
        }

        if (BGP_DEBUG (normal, NORMAL))
            zlog_debug ("%s OPEN has %s capability (%u), length %u",
                        peer->host,
                        LOOKUP (capcode_str, caphdr.code),
                        caphdr.code, caphdr.length);

        /* Length sanity check, type-specific, for known capabilities */
        switch (caphdr.code)
        {
        case CAPABILITY_CODE_MP:
        case CAPABILITY_CODE_REFRESH:
        case CAPABILITY_CODE_REFRESH_OLD:
        case CAPABILITY_CODE_ORF:
        case CAPABILITY_CODE_ORF_OLD:
        case CAPABILITY_CODE_RESTART:
        case CAPABILITY_CODE_AS4:
        case CAPABILITY_CODE_DYNAMIC:
            /* Check length. */
            if (caphdr.length < cap_minsizes[caphdr.code])
            {
                zlog_info ("%s %s Capability length error: got %u,"
                           " expected at least %u",
                           peer->host,
                           LOOKUP (capcode_str, caphdr.code),
                           caphdr.length,
                           (unsigned) cap_minsizes[caphdr.code]);
                bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
                                 BGP_NOTIFY_OPEN_UNSPECIFIC);
                return -1;
            }
            if (caphdr.length
                    && caphdr.length % cap_modsizes[caphdr.code] != 0)
            {
                zlog_info ("%s %s Capability length error: got %u,"
                           " expected a multiple of %u",
                           peer->host,
                           LOOKUP (capcode_str, caphdr.code),
                           caphdr.length,
                           (unsigned) cap_modsizes[caphdr.code]);
                bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
                                 BGP_NOTIFY_OPEN_UNSPECIFIC);
                return -1;
            }
        /* we deliberately ignore unknown codes, see below */
        default:
            break;
        }

        switch (caphdr.code)
        {
        case CAPABILITY_CODE_MP:
        {
            *mp_capability = 1;

            /* Ignore capability when override-capability is set. */
            if (! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
            {
                /* Set negotiated value. */
                ret = bgp_capability_mp (peer, &caphdr);

                /* Unsupported Capability. */
                if (ret < 0)
                {
                    /* Store return data. */
                    memcpy (*error, sp, caphdr.length + 2);
                    *error += caphdr.length + 2;
                }
            }
        }
        break;
        case CAPABILITY_CODE_REFRESH:
        case CAPABILITY_CODE_REFRESH_OLD:
        {
            /* BGP refresh capability */
            if (caphdr.code == CAPABILITY_CODE_REFRESH_OLD)
                SET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV);
            else
                SET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV);
        }
        break;
        case CAPABILITY_CODE_ORF:
        case CAPABILITY_CODE_ORF_OLD:
            if (bgp_capability_orf_entry (peer, &caphdr))
                return -1;
            break;
        case CAPABILITY_CODE_RESTART:
            if (bgp_capability_restart (peer, &caphdr))
                return -1;
            break;
        case CAPABILITY_CODE_DYNAMIC:
            SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV);
            break;
        case CAPABILITY_CODE_AS4:
            /* Already handled as a special-case parsing of the capabilities
             * at the beginning of OPEN processing. So we care not a jot
             * for the value really, only error case.
             */
            if (!bgp_capability_as4 (peer, &caphdr))
                return -1;
            break;
        default:
            if (caphdr.code > 128)
            {
                /* We don't send Notification for unknown vendor specific
                   capabilities.  It seems reasonable for now...  */
                zlog_warn ("%s Vendor specific capability %d",
                           peer->host, caphdr.code);
            }
            else
            {
                zlog_warn ("%s unrecognized capability code: %d - ignored",
                           peer->host, caphdr.code);
                memcpy (*error, sp, caphdr.length + 2);
                *error += caphdr.length + 2;
            }
        }
        if (stream_get_getp(s) != (start + caphdr.length))
        {
            if (stream_get_getp(s) > (start + caphdr.length))
                zlog_warn ("%s Cap-parser for %s read past cap-length, %u!",
                           peer->host, LOOKUP (capcode_str, caphdr.code),
                           caphdr.length);
            stream_set_getp (s, start + caphdr.length);
        }
    }
    return 0;
}
Пример #17
0
/* 
 * Parse the ZEBRA_IPV4_ROUTE_ADD sent from client. Update rib and
 * add kernel route. 
 */
static int
zread_ipv4_add (struct zserv *client, u_short length)
{
  int i;
  struct rib *rib;
  struct prefix_ipv4 p;
  u_char message;
  struct in_addr nexthop;
  u_char nexthop_num;
  u_char nexthop_type;
  struct stream *s;
  unsigned int ifindex;
  u_char ifname_len;
  safi_t safi;	


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

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

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

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

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

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

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

  /* Metric. */
  if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
    rib->metric = stream_getl (s);
    
  /* Table */
  rib->table=zebrad.rtm_table_default;
  rib_add_ipv4_multipath (&p, rib, safi);
  return 0;
}
Пример #18
0
/**
 * Parse open option.
 *
 * @param[out] mp_capability @see bgp_capability_parse() for semantics.
 */
int
bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability)
{
    int ret;
    u_char *error;
    u_char error_data[BGP_MAX_PACKET_SIZE];
    struct stream *s = BGP_INPUT(peer);
    size_t end = stream_get_getp (s) + length;

    ret = 0;
    error = error_data;

    if (BGP_DEBUG (normal, NORMAL))
        zlog_debug ("%s rcv OPEN w/ OPTION parameter len: %u",
                    peer->host, length);

    while (stream_get_getp(s) < end)
    {
        u_char opt_type;
        u_char opt_length;

        /* Must have at least an OPEN option header */
        if (STREAM_READABLE(s) < 2)
        {
            zlog_info ("%s Option length error", peer->host);
            bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
                             BGP_NOTIFY_OPEN_UNSPECIFIC);
            return -1;
        }

        /* Fetch option type and length. */
        opt_type = stream_getc (s);
        opt_length = stream_getc (s);

        /* Option length check. */
        if (STREAM_READABLE (s) < opt_length)
        {
            zlog_info ("%s Option length error", peer->host);
            bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
                             BGP_NOTIFY_OPEN_UNSPECIFIC);
            return -1;
        }

        if (BGP_DEBUG (normal, NORMAL))
            zlog_debug ("%s rcvd OPEN w/ optional parameter type %u (%s) len %u",
                        peer->host, opt_type,
                        opt_type == BGP_OPEN_OPT_AUTH ? "Authentication" :
                        opt_type == BGP_OPEN_OPT_CAP ? "Capability" : "Unknown",
                        opt_length);

        switch (opt_type)
        {
        case BGP_OPEN_OPT_AUTH:
            ret = bgp_auth_parse (peer, opt_length);
            break;
        case BGP_OPEN_OPT_CAP:
            ret = bgp_capability_parse (peer, opt_length, mp_capability, &error);
            break;
        default:
            bgp_notify_send (peer,
                             BGP_NOTIFY_OPEN_ERR,
                             BGP_NOTIFY_OPEN_UNSUP_PARAM);
            ret = -1;
            break;
        }

        /* Parse error.  To accumulate all unsupported capability codes,
           bgp_capability_parse does not return -1 when encounter
           unsupported capability code.  To detect that, please check
           error and erro_data pointer, like below.  */
        if (ret < 0)
            return -1;
    }

    /* All OPEN option is parsed.  Check capability when strict compare
       flag is enabled.*/
    if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
    {
        /* If Unsupported Capability exists. */
        if (error != error_data)
        {
            bgp_notify_send_with_data (peer,
                                       BGP_NOTIFY_OPEN_ERR,
                                       BGP_NOTIFY_OPEN_UNSUP_CAPBL,
                                       error_data, error - error_data);
            return -1;
        }

        /* Check local capability does not negotiated with remote
           peer. */
        if (! strict_capability_same (peer))
        {
            bgp_notify_send (peer,
                             BGP_NOTIFY_OPEN_ERR,
                             BGP_NOTIFY_OPEN_UNSUP_CAPBL);
            return -1;
        }
    }

    /* Check there are no common AFI/SAFIs and send Unsupported Capability
       error. */
    if (*mp_capability &&
            ! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
    {
        if (! peer->afc_nego[AFI_IP][SAFI_UNICAST]
                && ! peer->afc_nego[AFI_IP][SAFI_MULTICAST]
                && ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
                && ! peer->afc_nego[AFI_IP][SAFI_ENCAP]
                && ! peer->afc_nego[AFI_IP6][SAFI_UNICAST]
                && ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
                && ! peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
                && ! peer->afc_nego[AFI_IP6][SAFI_ENCAP])
        {
            plog_err (peer->log, "%s [Error] Configured AFI/SAFIs do not "
                      "overlap with received MP capabilities",
                      peer->host);

            if (error != error_data)

                bgp_notify_send_with_data (peer,
                                           BGP_NOTIFY_OPEN_ERR,
                                           BGP_NOTIFY_OPEN_UNSUP_CAPBL,
                                           error_data, error - error_data);
            else
                bgp_notify_send (peer,
                                 BGP_NOTIFY_OPEN_ERR,
                                 BGP_NOTIFY_OPEN_UNSUP_CAPBL);
            return -1;
        }
    }
    return 0;
}
Пример #19
0
/* Zebra server IPv4 prefix delete function. */
static int
zread_ipv4_delete (struct zserv *client, u_short length)
{
  int i;
  struct stream *s;
  struct zapi_ipv4 api;
  struct in_addr nexthop, *nexthop_p;
  unsigned long ifindex;
  struct prefix_ipv4 p;
  u_char nexthop_num;
  u_char nexthop_type;
  u_char ifname_len;
  
  s = client->ibuf;
  ifindex = 0;
  nexthop.s_addr = 0;
  nexthop_p = NULL;

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

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

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

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

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

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

  /* Metric. */
  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
    api.metric = stream_getl (s);
  else
    api.metric = 0;
    
  rib_delete_ipv4 (api.type, api.flags, &p, nexthop_p, ifindex,
		   client->rtm_table, api.safi);
  return 0;
}
Пример #20
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 if(type == ZEBRA_INTERFACE_ADDRESS_DELETE)
    {
      ifc = connected_delete_by_prefix(ifp, &p);
    }
    else
	{
		  zlog(NULL, LOG_CRIT, "line %u, function %s",
		 __LINE__,(__func__ ? __func__ : "?"));
	  zlog_backtrace(LOG_CRIT);
	  return NULL;
 	}

 
  return ifc;
}
Пример #21
0
/* Zebra server IPv6 prefix delete function. */
static int
zread_ipv6_delete (struct zserv *client, u_short length)
{
  int i;
  struct stream *s;
  struct zapi_ipv6 api;
  struct in6_addr nexthop;
  unsigned long ifindex;
  struct prefix_ipv6 p;
  
  s = client->ibuf;
  ifindex = 0;
  memset (&nexthop, 0, sizeof (struct in6_addr));

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

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

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

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

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

  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
    api.distance = stream_getc (s);
  else
    api.distance = 0;
  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
    api.metric = stream_getl (s);
  else
    api.metric = 0;
    
  if (IN6_IS_ADDR_UNSPECIFIED (&nexthop))
    rib_delete_ipv6 (api.type, api.flags, &p, NULL, ifindex, client->rtm_table, api.safi);
  else
    rib_delete_ipv6 (api.type, api.flags, &p, &nexthop, ifindex, client->rtm_table, api.safi);
  return 0;
}
Пример #22
0
static int
bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr)
{
  struct stream *s = BGP_INPUT (peer);
  struct capability_orf_entry entry;
  afi_t afi;
  safi_t safi;
  u_char type;
  u_char mode;
  u_int16_t sm_cap = 0; /* capability send-mode receive */
  u_int16_t rm_cap = 0; /* capability receive-mode receive */ 
  int i;

  /* ORF Entry header */
  bgp_capability_mp_data (s, &entry.mpc);
  entry.num = stream_getc (s);
  afi = entry.mpc.afi;
  safi = entry.mpc.safi;
  
  if (BGP_DEBUG (normal, NORMAL))
    zlog_debug ("%s ORF Cap entry for afi/safi: %u/%u",
	        peer->host, entry.mpc.afi, entry.mpc.safi);

  /* Check AFI and SAFI. */
  if (!bgp_afi_safi_valid_indices (entry.mpc.afi, &safi))
    {
      zlog_info ("%s Addr-family %d/%d not supported."
                 " Ignoring the ORF capability",
                 peer->host, entry.mpc.afi, entry.mpc.safi);
      return 0;
    }
  
  /* validate number field */
  if (sizeof (struct capability_orf_entry) + (entry.num * 2) > hdr->length)
    {
      zlog_info ("%s ORF Capability entry length error,"
                 " Cap length %u, num %u",
                 peer->host, hdr->length, entry.num);
      bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
      return -1;
    }

  for (i = 0 ; i < entry.num ; i++)
    {
      type = stream_getc(s);
      mode = stream_getc(s);
      
      /* ORF Mode error check */
      switch (mode)
        {
          case ORF_MODE_BOTH:
          case ORF_MODE_SEND:
          case ORF_MODE_RECEIVE:
            break;
          default:
	    bgp_capability_orf_not_support (peer, afi, safi, type, mode);
	    continue;
	}
      /* ORF Type and afi/safi error checks */
      /* capcode versus type */
      switch (hdr->code)
        {
          case CAPABILITY_CODE_ORF:
            switch (type)
              {
                case ORF_TYPE_PREFIX:
                  break;
                default:
                  bgp_capability_orf_not_support (peer, afi, safi, type, mode);
                  continue;
              }
            break;
          case CAPABILITY_CODE_ORF_OLD:
            switch (type)
              {
                case ORF_TYPE_PREFIX_OLD:
                  break;
                default:
                  bgp_capability_orf_not_support (peer, afi, safi, type, mode);
                  continue;
              }
            break;
          default:
            bgp_capability_orf_not_support (peer, afi, safi, type, mode);
            continue;
        }
                
      /* AFI vs SAFI */
      if (!((afi == AFI_IP && safi == SAFI_UNICAST)
            || (afi == AFI_IP && safi == SAFI_MULTICAST)
            || (afi == AFI_IP6 && safi == SAFI_UNICAST)))
        {
          bgp_capability_orf_not_support (peer, afi, safi, type, mode);
          continue;
        }
      
      if (BGP_DEBUG (normal, NORMAL))
        zlog_debug ("%s OPEN has %s ORF capability"
                    " as %s for afi/safi: %d/%d",
                    peer->host, LOOKUP (orf_type_str, type),
                    LOOKUP (orf_mode_str, mode),
                    entry.mpc.afi, safi);

      if (hdr->code == CAPABILITY_CODE_ORF)
	{
          sm_cap = PEER_CAP_ORF_PREFIX_SM_RCV;
          rm_cap = PEER_CAP_ORF_PREFIX_RM_RCV;
	}
      else if (hdr->code == CAPABILITY_CODE_ORF_OLD)
	{
          sm_cap = PEER_CAP_ORF_PREFIX_SM_OLD_RCV;
          rm_cap = PEER_CAP_ORF_PREFIX_RM_OLD_RCV;
	}
      else
	{
	  bgp_capability_orf_not_support (peer, afi, safi, type, mode);
	  continue;
	}

      switch (mode)
	{
	  case ORF_MODE_BOTH:
	    SET_FLAG (peer->af_cap[afi][safi], sm_cap);
	    SET_FLAG (peer->af_cap[afi][safi], rm_cap);
	    break;
	  case ORF_MODE_SEND:
	    SET_FLAG (peer->af_cap[afi][safi], sm_cap);
	    break;
	  case ORF_MODE_RECEIVE:
	    SET_FLAG (peer->af_cap[afi][safi], rm_cap);
	    break;
	}
    }
  return 0;
}
Пример #23
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;
}