예제 #1
0
static int
send_client (struct rnh *rnh, struct zserv *client, vrf_id_t vrf_id)
{
  struct stream *s;
  struct rib *rib;
  unsigned long nump;
  u_char num;
  struct nexthop *nexthop;
  struct route_node *rn;

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

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

  zserv_create_header (s, ZEBRA_NEXTHOP_UPDATE, vrf_id);

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

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

  client->nh_last_upd_time = quagga_time(NULL);
  client->last_write_cmd = ZEBRA_NEXTHOP_UPDATE;
  return zebra_server_send_message(client);
}
예제 #2
0
static void
bgp_open_capability_orf (struct stream *s, struct peer *peer,
                         afi_t afi, safi_t safi, u_char code)
{
  u_char cap_len;
  u_char orf_len;
  unsigned long capp;
  unsigned long orfp;
  unsigned long numberp;
  int number_of_orfs = 0;

  if (safi == SAFI_MPLS_VPN)
    safi = SAFI_MPLS_LABELED_VPN;

  stream_putc (s, BGP_OPEN_OPT_CAP);
  capp = stream_get_endp (s);           /* Set Capability Len Pointer */
  stream_putc (s, 0);                   /* Capability Length */
  stream_putc (s, code);                /* Capability Code */
  orfp = stream_get_endp (s);           /* Set ORF Len Pointer */
  stream_putc (s, 0);                   /* ORF Length */
  stream_putw (s, afi);
  stream_putc (s, 0);
  stream_putc (s, safi);
  numberp = stream_get_endp (s);        /* Set Number Pointer */
  stream_putc (s, 0);                   /* Number of ORFs */

  /* Address Prefix ORF */
  if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
      || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
    {
      stream_putc (s, (code == CAPABILITY_CODE_ORF ?
		   ORF_TYPE_PREFIX : ORF_TYPE_PREFIX_OLD));

      if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
	  && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
	{
	  SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
	  SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
	  stream_putc (s, ORF_MODE_BOTH);
	}
      else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
	{
	  SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
	  stream_putc (s, ORF_MODE_SEND);
	}
      else
	{
	  SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
	  stream_putc (s, ORF_MODE_RECEIVE);
	}
      number_of_orfs++;
    }

  /* Total Number of ORFs. */
  stream_putc_at (s, numberp, number_of_orfs);

  /* Total ORF Len. */
  orf_len = stream_get_endp (s) - orfp - 1;
  stream_putc_at (s, orfp, orf_len);

  /* Total Capability Len. */
  cap_len = stream_get_endp (s) - capp - 1;
  stream_putc_at (s, capp, cap_len);
}
예제 #3
0
/* Fill in capability open option to the packet. */
void
bgp_open_capability (struct stream *s, struct peer *peer)
{
  u_char len;
  unsigned long cp;
  afi_t afi;
  safi_t safi;
  as_t local_as;

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

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

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

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

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

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

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

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

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

  /* Total Opt Parm Len. */
  len = stream_get_endp (s) - cp - 1;
  stream_putc_at (s, cp, len);
}
예제 #4
0
/* Fill in capability open option to the packet. */
void
bgp_open_capability (struct stream *s, struct peer *peer)
{
    u_char len;
    unsigned long cp, capp, rcapp;
    afi_t afi;
    safi_t safi;
    as_t local_as;
    u_int32_t restart_time;

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

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

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

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

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

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

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

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

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

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

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

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

    /* Total Opt Parm Len. */
    len = stream_get_endp (s) - cp - 1;
    stream_putc_at (s, cp, len);
}
예제 #5
0
파일: zserv.c 프로젝트: MichaelQQ/Quagga-PE
static int
zsend_ipv4_import_lookup (struct zserv *client, struct prefix_ipv4 *p)
{
  struct stream *s;
  struct rib *rib;
  unsigned long nump;
  u_char num;
  struct nexthop *nexthop;

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

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

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

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

  stream_putw_at (s, 0, stream_get_endp (s));
  
  return zebra_server_send_message(client);
}
예제 #6
0
파일: zserv.c 프로젝트: MichaelQQ/Quagga-PE
static int
zsend_ipv4_nexthop_lookup (struct zserv *client, struct in_addr addr)
{
  struct stream *s;
  struct rib *rib;
  unsigned long nump;
  u_char num;
  struct nexthop *nexthop;

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

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

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

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

  stream_putw_at (s, 0, stream_get_endp (s));
  
  return zebra_server_send_message(client);
}
예제 #7
0
파일: zserv.c 프로젝트: MichaelQQ/Quagga-PE
/*
 * The zebra server sends the clients  a ZEBRA_IPV4_ROUTE_ADD or a
 * ZEBRA_IPV6_ROUTE_ADD via zsend_route_multipath in the following
 * situations:
 * - when the client starts up, and requests default information
 *   by sending a ZEBRA_REDISTRIBUTE_DEFAULT_ADD to the zebra server, in the
 * - case of rip, ripngd, ospfd and ospf6d, when the client sends a
 *   ZEBRA_REDISTRIBUTE_ADD as a result of the "redistribute" vty cmd,
 * - when the zebra server redistributes routes after it updates its rib
 *
 * The zebra server sends clients a ZEBRA_IPV4_ROUTE_DELETE or a
 * ZEBRA_IPV6_ROUTE_DELETE via zsend_route_multipath when:
 * - a "ip route"  or "ipv6 route" vty command is issued, a prefix is
 * - deleted from zebra's rib, and this info
 *   has to be redistributed to the clients 
 * 
 * XXX The ZEBRA_IPV*_ROUTE_ADD message is also sent by the client to the
 * zebra server when the client wants to tell the zebra server to add a
 * route to the kernel (zapi_ipv4_add etc. ).  Since it's essentially the
 * same message being sent back and forth, this function and
 * zapi_ipv{4,6}_{add, delete} should be re-written to avoid code
 * duplication.
 */
int
zsend_route_multipath (int cmd, struct zserv *client, struct prefix *p,
                       struct rib *rib)
{
  int psize;
  struct stream *s;
  struct nexthop *nexthop;
  unsigned long nhnummark = 0, messmark = 0;
  int nhnum = 0;
  u_char zapi_flags = 0;
  
  s = client->obuf;
  stream_reset (s);
  
  zserv_create_header (s, cmd);
  
  /* Put type and nexthop. */
  stream_putc (s, rib->type);
  stream_putc (s, rib->flags);
  
  /* marker for message flags field */
  messmark = stream_get_endp (s);
  stream_putc (s, 0);

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

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

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

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

          break;
        }
    }

  /* Metric */
  if (cmd == ZEBRA_IPV4_ROUTE_ADD || cmd == ZEBRA_IPV6_ROUTE_ADD)
    {
      SET_FLAG (zapi_flags, ZAPI_MESSAGE_DISTANCE);
      stream_putc (s, rib->distance);
      SET_FLAG (zapi_flags, ZAPI_MESSAGE_METRIC);
      stream_putl (s, rib->metric);
    }
  
  /* write real message flags value */
  stream_putc_at (s, messmark, zapi_flags);
  
  /* Write next-hop number */
  if (nhnummark)
    stream_putc_at (s, nhnummark, nhnum);
  
  /* Write packet size. */
  stream_putw_at (s, 0, stream_get_endp (s));

  return zebra_server_send_message(client);
}
예제 #8
0
/* Fill in capability open option to the packet. */
void
bgp_open_capability (struct stream *s, struct peer *peer)
{
  u_char len;
  unsigned long cp;
  afi_t afi;
  safi_t safi;

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

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

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

  /* When the peer is IPv4 unicast only, do not send capability. */
  if (! peer->afc[AFI_IP][SAFI_MULTICAST] 
      && ! peer->afc[AFI_IP][SAFI_MPLS_VPN]
      && ! peer->afc[AFI_IP6][SAFI_UNICAST] 
      && ! peer->afc[AFI_IP6][SAFI_MULTICAST]
      && CHECK_FLAG (peer->flags, PEER_FLAG_NO_ROUTE_REFRESH_CAP)
      && ! CHECK_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
		       PEER_FLAG_ORF_PREFIX_SM)
      && ! CHECK_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
		       PEER_FLAG_ORF_PREFIX_RM)
      && ! CHECK_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
		       PEER_FLAG_ORF_PREFIX_SM)
      && ! CHECK_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
		       PEER_FLAG_ORF_PREFIX_RM)
      && ! CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
    return;

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

  /* Route refresh. */
  if (! CHECK_FLAG (peer->flags, PEER_FLAG_NO_ROUTE_REFRESH_CAP))
    {
      SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
      stream_putc (s, BGP_OPEN_OPT_CAP);
      stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
      stream_putc (s, CAPABILITY_CODE_REFRESH_OLD);
      stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
      stream_putc (s, BGP_OPEN_OPT_CAP);
      stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
      stream_putc (s, CAPABILITY_CODE_REFRESH);
      stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
    }

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

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

  /* Total Opt Parm Len. */
  len = stream_get_putp (s) - cp - 1;
  stream_putc_at (s, cp, len);
}