Beispiel #1
0
/* Add connected IPv6 route to the interface. */
void
connected_add_ipv6 (struct interface *ifp, int flags, struct in6_addr *addr,
		    u_char prefixlen, struct in6_addr *broad,
		    const char *label)
{
  struct prefix_ipv6 *p;
  struct connected *ifc;

  /* Make connected structure. */
  ifc = connected_new ();
  ifc->ifp = ifp;
  ifc->flags = flags;
  /* If we get a notification from the kernel,
   * we can safely assume the address is known to the kernel */
  SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);

  /* Allocate new connected address. */
  p = prefix_ipv6_new ();
  p->family = AF_INET6;
  IPV6_ADDR_COPY (&p->prefix, addr);
  p->prefixlen = prefixlen;
  ifc->address = (struct prefix *) p;

  /* If there is broadcast or peer address. */
  if (broad)
    {
      if (IN6_IS_ADDR_UNSPECIFIED(broad))
	zlog_warn("warning: %s called for interface %s with unspecified "
		  "destination address; ignoring!", __func__, ifp->name);
      else
	{
	  p = prefix_ipv6_new ();
	  p->family = AF_INET6;
	  IPV6_ADDR_COPY (&p->prefix, broad);
	  p->prefixlen = prefixlen;
	  ifc->destination = (struct prefix *) p;
	}
    }
  if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER) && !ifc->destination)
    {
      zlog_warn("warning: %s called for interface %s "
		"with peer flag set, but no peer address supplied",
		__func__, ifp->name);
      UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
    }

  /* Label of this address. */
  if (label)
    ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);

  /* On Linux, we only get here when DAD is complete, therefore we can set
   * ZEBRA_IFC_REAL.
   *
   * On BSD, there currently doesn't seem to be a way to check for completion of
   * DAD, so we replicate the old behaviour and set ZEBRA_IFC_REAL, although DAD
   * might still be running.
   */
  SET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
  connected_update(ifp, ifc);
}
Beispiel #2
0
/* Add connected IPv6 route to the interface. */
void
connected_add_ipv6 (struct interface *ifp, int flags, struct in6_addr *addr,
		    u_char prefixlen, struct in6_addr *broad,
		    const char *label)
{
  struct prefix_ipv6 *p;
  struct connected *ifc;

  /* Make connected structure. */
  ifc = connected_new ();
  ifc->ifp = ifp;
  ifc->flags = flags;

  /* Allocate new connected address. */
  p = prefix_ipv6_new ();
  p->family = AF_INET6;
  IPV6_ADDR_COPY (&p->prefix, addr);
  p->prefixlen = prefixlen;
  ifc->address = (struct prefix *) p;

  /* If there is broadcast or peer address. */
  if (broad)
    {
      if (IN6_IS_ADDR_UNSPECIFIED(broad))
	zlog_warn("warning: %s called for interface %s with unspecified "
		  "destination address; ignoring!", __func__, ifp->name);
      else
	{
	  p = prefix_ipv6_new ();
	  p->family = AF_INET6;
	  IPV6_ADDR_COPY (&p->prefix, broad);
	  p->prefixlen = prefixlen;
	  ifc->destination = (struct prefix *) p;
	}
    }
  if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER) && !ifc->destination)
    {
      zlog_warn("warning: %s called for interface %s "
		"with peer flag set, but no peer address supplied",
		__func__, ifp->name);
      UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
    }

  /* Label of this address. */
  if (label)
    ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
  
  if ((ifc = connected_implicit_withdraw (ifp, ifc)) == NULL)
    return;
  
  connected_announce (ifp, ifc);
}
Beispiel #3
0
pcp_errno psd_add_pcp_server(pcp_ctx_t *ctx, struct sockaddr *sa,
        uint8_t version)
{
    struct in6_addr pcp_ip=IN6ADDR_ANY_INIT;
    uint16_t pcp_port;
    uint32_t scope_id=0;
    pcp_server_t *pcps=NULL;

    PCP_LOG_BEGIN(PCP_LOGLVL_DEBUG);

    if (sa->sa_family == AF_INET) {
        S6_ADDR32(&pcp_ip)[0]=0;
        S6_ADDR32(&pcp_ip)[1]=0;
        S6_ADDR32(&pcp_ip)[2]=htonl(0xFFFF);
        S6_ADDR32(&pcp_ip)[3]=((struct sockaddr_in *)sa)->sin_addr.s_addr;
        pcp_port=((struct sockaddr_in *)sa)->sin_port;
    } else {
        IPV6_ADDR_COPY(&pcp_ip, &((struct sockaddr_in6*)sa)->sin6_addr);
        pcp_port=((struct sockaddr_in6 *)sa)->sin6_port;
        scope_id=((struct sockaddr_in6 *)sa)->sin6_scope_id;
    }

    if (!pcp_port) {
        pcp_port=ntohs(PCP_SERVER_PORT);
    }

    pcps=get_pcp_server_by_ip(ctx, (struct in6_addr *)&pcp_ip);
    if (!pcps) {
        int pcps_indx=pcp_new_server(ctx, &pcp_ip, pcp_port, scope_id);

        if (pcps_indx >= 0) {
            pcps=get_pcp_server(ctx, pcps_indx);
        }

        if (pcps == NULL) {
            PCP_LOG(PCP_LOGLVL_ERR, "%s", "Can't add PCP server.\n");
            PCP_LOG_END(PCP_LOGLVL_DEBUG);
            return PCP_ERR_UNKNOWN;
        }
    } else {
        pcps->pcp_port=pcp_port;
    }

    pcps->pcp_version=version;
    pcps->server_state=pss_allocated;

    if (psd_fill_pcp_server_src(pcps)) {
        pcps->server_state=pss_unitialized;
        PCP_LOG(PCP_LOGLVL_INFO, "Failed to add PCP server %s",
                pcps->pcp_server_paddr);

        PCP_LOG_END(PCP_LOGLVL_DEBUG);
        return PCP_ERR_UNKNOWN;
    }

    PCP_LOG(PCP_LOGLVL_INFO, "Added PCP server %s", pcps->pcp_server_paddr);

    PCP_LOG_END(PCP_LOGLVL_DEBUG);
    return (pcp_errno)pcps->index;
}
Beispiel #4
0
/* Add connected IPv6 route to the interface. */
void
connected_add_ipv6 (struct interface *ifp, struct in6_addr *addr,
		    u_char prefixlen, struct in6_addr *broad,
		    const char *label)
{
  struct prefix_ipv6 *p;
  struct connected *ifc;

  /* Make connected structure. */
  ifc = connected_new ();
  ifc->ifp = ifp;

  /* Allocate new connected address. */
  p = prefix_ipv6_new ();
  p->family = AF_INET6;
  IPV6_ADDR_COPY (&p->prefix, addr);
  p->prefixlen = prefixlen;
  ifc->address = (struct prefix *) p;

  /* If there is broadcast or pointopoint address. */
  if (broad)
    {
      p = prefix_ipv6_new ();
      p->family = AF_INET6;
      IPV6_ADDR_COPY (&p->prefix, broad);
      ifc->destination = (struct prefix *) p;
    }

  /* Label of this address. */
  if (label)
    ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
  
  if ((ifc = connected_implicit_withdraw (ifp, ifc)) == NULL)
    return;
  
  connected_announce (ifp, ifc);
}
Beispiel #5
0
/* BGP Peer TCP Socket bind to 'update-source' address
 *
 * Specify the TCP client's source IP address.
 * This function must be called before calling connect().
 * The source port is set to "any port"
 * (i.e., picked by the kernel) unless a user specified it.
 */
s_int32_t
bpn_sock_bind_address (struct bgp_peer *peer,
                       pal_sock_handle_t sck_fd)
{
  struct prefix *if_prefix;
  struct interface *ifp;
  union sockunion uaddr;
  s_int32_t uaddr_len;
  s_int32_t ret;

  pal_mem_set (&uaddr, 0, sizeof (union sockunion));
  uaddr_len = 0;
  ret = 0;

  /* Ifname is exist. */
  if (peer->update_if)
    {
      ifp = if_lookup_by_name (&BGP_VR.owning_ivr->ifm,
                               peer->update_if);
      if (! ifp)
        {
          ret = -1;
          goto EXIT;
        }

      if_prefix = if_get_connected_address (ifp, peer->su.sa.sa_family);
      if (! if_prefix)
        {
          ret = -1;
          goto EXIT;
        }

      uaddr.sa.sa_family = if_prefix->family;

      if (uaddr.sa.sa_family == AF_INET)
        {
          uaddr.sin.sin_family = AF_INET;

          uaddr_len = sizeof (struct pal_sockaddr_in4);
#ifdef HAVE_SIN_LEN
          uaddr.sin.sin_len = pal_hton16 (uaddr_len);
#endif /* HAVE_SIN_LEN */
          IPV4_ADDR_COPY (&uaddr.sin.sin_addr, &if_prefix->u.prefix4);

          if (peer->sock_port == BGP_PORT_DEFAULT)
            uaddr.sin.sin_port = 
              bpn_get_port_any (AF_INET, SOCK_STREAM, &uaddr.sa);
          else
            uaddr.sin.sin_port = pal_hton16 (peer->sock_port);

        }
#ifdef HAVE_IPV6
      else if (BGP_CAP_HAVE_IPV6 && uaddr.sa.sa_family == AF_INET6)
        {
          uaddr.sin6.sin6_family = AF_INET6;

          uaddr_len = sizeof (struct pal_sockaddr_in6);
#ifdef HAVE_SIN_LEN
          uaddr.sin6.sin6_len = pal_hton16 (uaddr_len);
#endif /* HAVE_SIN_LEN */
          IPV6_ADDR_COPY (&uaddr.sin6.sin6_addr, &if_prefix->u.prefix6);

          if (peer->sock_port == BGP_PORT_DEFAULT)
            uaddr.sin6.sin6_port = 
              bpn_get_port_any (AF_INET6, SOCK_STREAM, &uaddr.sa);
          else
            uaddr.sin6.sin6_port = pal_hton16 (peer->sock_port);
        }
#endif /* HAVE_IPV6 */
      else
        {
          if (BGP_DEBUG (events, EVENTS))
            zlog_err (&BLG, "%s-%s [NETWORK] bind addr: socket (%d), "
                      "unknown update-interface family (%d)", peer->host,
                      BGP_PEER_DIR_STR (peer), sck_fd, uaddr.sa.sa_family);

          ret = -1;
          goto EXIT;
        }
    }
  else if (peer->update_source)
    {
      uaddr.sa.sa_family = peer->update_source->sa.sa_family;

      if (uaddr.sa.sa_family == AF_INET)
        {
          uaddr.sin.sin_family = AF_INET;

          uaddr_len = sizeof (struct pal_sockaddr_in4);

         if (peer->sock_port == BGP_PORT_DEFAULT)
           uaddr.sin.sin_port =
             bpn_get_port_any (AF_INET, SOCK_STREAM,
                               &peer->update_source->sa);
         else
           uaddr.sin.sin_port = pal_hton16 (peer->sock_port);

#ifdef HAVE_SIN_LEN
          uaddr.sin.sin_len = pal_hton16 (uaddr_len);
#endif /* HAVE_SIN_LEN */

          IPV4_ADDR_COPY (&uaddr.sin.sin_addr,
                          &peer->update_source->sin.sin_addr);
        }
#ifdef HAVE_IPV6
      else if (BGP_CAP_HAVE_IPV6 && uaddr.sa.sa_family == AF_INET6)
        {
          uaddr.sin6.sin6_family = AF_INET6;

          uaddr_len = sizeof (struct pal_sockaddr_in6);

         if (peer->sock_port == BGP_PORT_DEFAULT)
           uaddr.sin6.sin6_port =
             bpn_get_port_any (AF_INET6, SOCK_STREAM,
                               &peer->update_source->sa);
         else
           uaddr.sin.sin_port = pal_hton16 (peer->sock_port);

#ifdef HAVE_SIN_LEN
          uaddr.sin6.sin6_len = pal_hton16 (uaddr_len);
#endif /* HAVE_SIN_LEN */

          IPV6_ADDR_COPY (&uaddr.sin6.sin6_addr,
                          &peer->update_source->sin6.sin6_addr);
        }
#endif /* HAVE_IPV6 */
      else
        {
          if (BGP_DEBUG (events, EVENTS))
            zlog_err (&BLG, "%s-%s [NETWORK] bind addr: socket (%d), "
                      "unknown update-address family (%d)", peer->host,
                      BGP_PEER_DIR_STR (peer), sck_fd, uaddr.sa.sa_family);

          ret = -1;
          goto EXIT;
        }
    }

  if (uaddr_len)
    {
      ret = pal_sock_bind (sck_fd, (struct pal_sockaddr *) &uaddr, uaddr_len);

      if (ret < 0)
        if (BGP_DEBUG (events, EVENTS))
          zlog_err (&BLG, "%s-%s [NETWORK] bind addr: socket (%d), bind"
                    " failed (%d-%s)", peer->host, BGP_PEER_DIR_STR (peer),
                    sck_fd, errno, pal_strerror (errno));
    }

 EXIT:

  return ret;
}