Esempio n. 1
0
void
bgp_dump_packet_func (struct bgp_dump *bgp_dump, struct peer *peer,
		      struct stream *packet)
{
  struct stream *obuf;

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

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

  /* Dump header and common part. */
  bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE);
  bgp_dump_common (obuf, peer);

  /* Packet contents. */
  stream_put (obuf, STREAM_DATA (packet), stream_get_endp (packet));
  
  /* Set length. */
  bgp_dump_set_size (obuf, MSG_PROTOCOL_BGP4MP);

  /* Write to the stream. */
  fwrite (STREAM_DATA (obuf), stream_get_putp (obuf), 1, bgp_dump->fp);
  fflush (bgp_dump->fp);
}
Esempio n. 2
0
/* Dump BGP status change. */
void
bgp_dump_state (struct peer *peer, int status_old, int status_new)
{
  struct stream *obuf;

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

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

  bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_STATE_CHANGE);
  bgp_dump_common (obuf, peer);

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

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

  /* Write to the stream. */
  fwrite (STREAM_DATA (obuf), stream_get_putp (obuf), 1, bgp_dump_all.fp);
  fflush (bgp_dump_all.fp);
}
Esempio n. 3
0
File: zserv.c Progetto: OPSF/uClinux
/*
 * The zebra server sends the clients  a ZEBRA_IPV4_ROUTE_ADD or a
 * ZEBRA_IPV6_ROUTE_ADD via zsend_route_multipath in the following
 * situations:
 * - when the client starts up, and requests default information
 *   by sending a ZEBRA_REDISTRIBUTE_DEFAULT_ADD to the zebra server, in the
 * - case of rip, ripngd, ospfd and ospf6d, when the client sends a
 *   ZEBRA_REDISTRIBUTE_ADD as a result of the "redistribute" vty cmd,
 * - when the zebra server redistributes routes after it updates its rib
 *
 * The zebra server sends clients a ZEBRA_IPV4_ROUTE_DELETE or a
 * ZEBRA_IPV6_ROUTE_DELETE via zsend_route_multipath when:
 * - a "ip route"  or "ipv6 route" vty command is issued, a prefix is
 * - deleted from zebra's rib, and this info
 *   has to be redistributed to the clients 
 * 
 * XXX The ZEBRA_IPV*_ROUTE_ADD message is also sent by the client to the
 * zebra server when the client wants to tell the zebra server to add a
 * route to the kernel (zapi_ipv4_add etc. ).  Since it's essentially the
 * same message being sent back and forth, this function and
 * zapi_ipv{4,6}_{add, delete} should be re-written to avoid code
 * duplication.
 */
int
zsend_route_multipath (int cmd, struct zserv *client, struct prefix *p,
                       struct rib *rib)
{
  int psize;
  struct stream *s;
  struct nexthop *nexthop;
  unsigned long nhnummark = 0;
  int nhnum = 0;
  u_char zapi_flags = ZAPI_MESSAGE_NEXTHOP | ZAPI_MESSAGE_IFINDEX;
  
  s = client->obuf;
  stream_reset (s);

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

  /* Put command, type and nexthop. */
  stream_putc (s, cmd);
  stream_putc (s, rib->type);
  stream_putc (s, rib->flags);

  /* 
   * XXX no need to set ZAPI_MESSAGE_NEXTHOP if we are going to
   * send empty nexthop?
   */
  if (cmd == ZEBRA_IPV4_ROUTE_ADD || ZEBRA_IPV6_ROUTE_ADD)
    zapi_flags |= ZAPI_MESSAGE_METRIC;

  stream_putc (s, zapi_flags);

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

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

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

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

          break;
        }
    }

  /* Metric */
  stream_putl (s, rib->metric);

  /* Write next-hop number */
  if (nhnummark)
    stream_putc_at (s, nhnummark, nhnum);
  
  /* Write packet size. */
  stream_putw_at (s, 0, stream_get_endp (s));

  zebra_server_send_message (client->sock, s->data, stream_get_endp (s));

  return 0;
}
Esempio n. 4
0
void
bgp_dump_routes_entry (struct prefix *p, struct bgp_info *info, int afi,
		       int type, unsigned int seq)
{
  struct stream *obuf;
  struct attr *attr;
  struct peer *peer;
  int plen;
  int safi = 0;

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

  attr = info->attr;
  peer = info->peer;

  /* We support MRT's old format. */
  if (type == MSG_TABLE_DUMP)
    {
      bgp_dump_header (obuf, MSG_TABLE_DUMP, afi);
      stream_putw (obuf, 0);	/* View # */
      stream_putw (obuf, seq);	/* Sequence number. */
    }
  else
    {
      bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_ENTRY);
      
      stream_putl (obuf, info->uptime); /* Time Last Change */
      stream_putw (obuf, afi);	/* Address Family */
      stream_putc (obuf, safi);	/* SAFI */
    }

  if (afi == AFI_IP)
    {
      if (type == MSG_TABLE_DUMP)
	{
	  /* Prefix */
	  stream_put_in_addr (obuf, &p->u.prefix4);
	  stream_putc (obuf, p->prefixlen);

	  /* Status */
	  stream_putc (obuf, 1);

	  /* Originated */
	  stream_putl (obuf, info->uptime);

	  /* Peer's IP address */
	  stream_put_in_addr (obuf, &peer->su.sin.sin_addr);

	  /* Peer's AS number. */
	  stream_putw (obuf, peer->as);

	  /* Dump attribute. */
	  bgp_dump_routes_attr (obuf, attr, p);
	}
      else
	{
	  /* Next-Hop-Len */
	  stream_putc (obuf, IPV4_MAX_BYTELEN);
	  stream_put_in_addr (obuf, &attr->nexthop);
	  stream_putc (obuf, p->prefixlen);
	  plen = PSIZE (p->prefixlen);
	  stream_put (obuf, &p->u.prefix4, plen);
	  bgp_dump_routes_attr (obuf, attr, p);
	}
    }
#ifdef HAVE_IPV6
  else if (afi == AFI_IP6)
    {
      if (type == MSG_TABLE_DUMP)
	{
	  /* Prefix */
	  stream_write (obuf, (u_char *)&p->u.prefix6, IPV6_MAX_BYTELEN);
	  stream_putc (obuf, p->prefixlen);

	  /* Status */
	  stream_putc (obuf, 1);

	  /* Originated */
	  stream_putl (obuf, info->uptime);

	  /* Peer's IP address */
	  stream_write (obuf, (u_char *)&peer->su.sin6.sin6_addr,
			IPV6_MAX_BYTELEN);

	  /* Peer's AS number. */
	  stream_putw (obuf, peer->as);

	  /* Dump attribute. */
	  bgp_dump_routes_attr (obuf, attr, p);
	}
      else
	{
	  ;
	}
    }
#endif /* HAVE_IPV6 */

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

  fwrite (STREAM_DATA (obuf), stream_get_putp (obuf), 1, bgp_dump_routes.fp);
  fflush (bgp_dump_routes.fp);
}
Esempio n. 5
0
void
bgp_dump_set_size (struct stream *s, int type)
{
  stream_putl_at (s, 8, stream_get_putp (s) - BGP_DUMP_HEADER_SIZE);
}
Esempio n. 6
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);
}
Esempio n. 7
0
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 = BGP_SAFI_VPNV4;

  stream_putc (s, BGP_OPEN_OPT_CAP);
  capp = stream_get_putp (s);           /* Set Capability Len Pointer */
  stream_putc (s, 0);                   /* Capability Length */
  stream_putc (s, code);                /* Capability Code */
  orfp = stream_get_putp (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_putp (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_putp (s) - orfp - 1;
  stream_putc_at (s, orfp, orf_len);

  /* Total Capability Len. */
  cap_len = stream_get_putp (s) - capp - 1;
  stream_putc_at (s, capp, cap_len);
}