Пример #1
0
/* Fake execution of the thread with given arguemment.  */
struct thread *
thread_execute (struct thread_master *master,
                int (*func)(struct thread *), 
                void *arg,
                int val)
{
  struct thread dummy; 

  pal_mem_set (&dummy, 0, sizeof (struct thread));

  dummy.type = THREAD_EVENT;
  dummy.master = NULL;
  dummy.func = func;
  dummy.arg = arg;
  dummy.u.val = val;
  thread_call (&dummy);

  return NULL;
}
Пример #2
0
/* Fake execution of the thread with given arguemment.  */
struct thread *
thread_execute (struct lib_globals *zg,
                int (*func)(struct thread *),
                void *arg,
                int val)
{
  struct thread dummy;

  /* Set the global VR context to PVR. */
  if (zg)
    zg->vr_in_cxt = ipi_vr_get_privileged(zg);

  pal_mem_set (&dummy, 0, sizeof (struct thread));

  dummy.type = THREAD_EVENT;
  dummy.master = NULL;
  dummy.func = func;
  dummy.arg = arg;
  dummy.u.val = val;
  thread_call (&dummy);

  return NULL;
}
Пример #3
0
    /* Add thread to Listen Thread List */
    tmp_lnode = XCALLOC (MTYPE_TMP,
                         sizeof (struct bgp_listen_sock_lnode));
    if (! tmp_lnode)
      {
        zlog_err (&BLG, "[NETWORK] Server Sock:"
                  " Cannot allocate memory (%d) @ %s:%d",
                  sizeof (struct bgp_peer_inconn_req), __FILE__, __LINE__);

        SSOCK_FD_CLOSE (&BLG, bgp_sock);
        BGP_READ_OFF (&BLG, t_accept);

        continue;
      }

    tmp_lnode->listen_sock = bgp_sock;
    tmp_lnode->t_accept = t_accept;
    if (bgp->listen_sock_lnode)
      tmp_lnode->next = bgp->listen_sock_lnode;
    bgp->listen_sock_lnode = tmp_lnode;

  } 

  pal_sock_freeaddrinfo (ainfo_head);

  return ret;
}
#else /* HAVE_IPV6 && !NRL */
s_int32_t
bpn_sock_listen (struct bgp *bgp, u_int16_t port)
{
  struct bgp_listen_sock_lnode *tmp_lnode;
  struct thread *t_accept;
  union sockunion su;
  s_int32_t bgp_sock;
  fib_id_t fib_id;
  s_int32_t ret;

  pal_mem_set (&su, 0, sizeof (union sockunion));

  t_accept = NULL;
  ret = 0;

  if (! bgp)
    {
      zlog_err (&BLG, "[NETWORK] Server Sock: Invalid 'bgp' instance");

      ret = -1;
      goto EXIT;
    }

  fib_id = LIB_VRF_GET_FIB_ID (bgp->owning_ivrf);

  /* Specify address family. */
  su.sa.sa_family = AF_INET;

  bgp_sock = pal_sock (&BLG, su.sa.sa_family, SOCK_STREAM, 0);
  if (bgp_sock < 0)
    {
      zlog_err (&BLG, "[NETWORK] Server Sock: socket() Failed, FIB-ID %d, "
                "Err:%d-%s", fib_id, errno, pal_strerror (errno));

      ret = -1;
      goto EXIT;
    }

  pal_sock_set_reuseaddr (bgp_sock, PAL_TRUE);
  pal_sock_set_reuseport (bgp_sock, PAL_TRUE);

  /* Bind socket to FIB. */
  ret = pal_sock_set_bindtofib (bgp_sock, fib_id);
  if (ret < 0)
    {
      zlog_err (&BLG, "[NETWORK] Server Sock: bindtofib() Failed, Sock %d"
                ", FIB-ID %d, Err:%d-%s", bgp_sock, fib_id, errno,
                pal_strerror (errno));

      SSOCK_FD_CLOSE (&BLG, bgp_sock);

      /* Ignore platform error */
      ret = 0;
      goto EXIT;
    }

  ret = sockunion_bind (&BLG, bgp_sock, &su, port, NULL);
  if (ret < 0)
    {
      zlog_err (&BLG, "[NETWORK] Server Sock: bind() Failed, Err: %d-%s",
                errno, pal_strerror (errno));

      SSOCK_FD_CLOSE (&BLG, bgp_sock);

      /* Ignore platform error */
      ret = 0;
      goto EXIT;
    }

#ifdef HAVE_TCP_MD5SIG
  bgp_md5_set_server (bgp, bgp_sock);
#endif /* TCP_MD5SIG */

  ret = pal_sock_listen (bgp_sock, BGP_SOCK_LISTEN_BACKLOG);
  if (ret < 0)
    {
      zlog_err (&BLG, "[NETWORK] Server Sock: listen() Failed, Sock %d, "
                "FIB-ID %d, Err:%d-%s", bgp_sock, fib_id, errno,
                pal_strerror (errno));

      SSOCK_FD_CLOSE (&BLG, bgp_sock);

      /* Ignore platform error */
      ret = 0;
      goto EXIT;
    }

  /* Start a fresh Accept Thread */
  BGP_READ_ON (&BLG, t_accept, bgp, bpn_sock_accept, bgp_sock);

  /* Add thread to Listen Thread List */
  tmp_lnode = XCALLOC (MTYPE_TMP, sizeof (struct bgp_listen_sock_lnode));
  if (! tmp_lnode)
    {
      zlog_err (&BLG, "[NETWORK] Server Sock:"
                " Cannot allocate memory (%d) @ %s:%d",
                sizeof (struct bgp_peer_inconn_req), __FILE__, __LINE__);

      SSOCK_FD_CLOSE (&BLG, bgp_sock);
      BGP_READ_OFF (&BLG, t_accept);

      ret = -1;
      goto EXIT;
    }

  tmp_lnode->listen_sock = bgp_sock;
  tmp_lnode->t_accept = t_accept;
  if (bgp->listen_sock_lnode)
    tmp_lnode->next = bgp->listen_sock_lnode;
  bgp->listen_sock_lnode = tmp_lnode;

 EXIT:

  return ret;
}
Пример #4
0
s_int32_t
bpn_sock_listen (struct bgp *bgp, u_int16_t port)
{
  struct bgp_listen_sock_lnode *tmp_lnode;
  u_int8_t port_str [SU_ADDRSTRLEN];
  struct pal_addrinfo *ainfo_save[2], *ainfo_head;
  struct pal_addrinfo *ainfo;
  struct pal_sockaddr_in4 ain4;
  struct pal_sockaddr_in6 ain6;
  struct pal_addrinfo req;
  struct thread *t_accept;
  s_int32_t bgp_sock;
  u_int8_t addr_set;
  fib_id_t fib_id;
  s_int32_t ret;	
  int i, flags = 1;

  pal_mem_set (&req, 0, sizeof (struct pal_addrinfo));
  t_accept = NULL;
  ainfo_save[0] = NULL;
  ainfo_save[1] = NULL;
  ret = 0;
  addr_set = 0;

  if (! bgp)
    {
      zlog_err (&BLG, "[NETWORK] Server Sock: Invalid 'bgp' instance");

      return -1;
    }

  fib_id = LIB_VRF_GET_FIB_ID (bgp->owning_ivrf);
  req.ai_flags = AI_PASSIVE;
  req.ai_family = AF_UNSPEC;
  req.ai_socktype = SOCK_STREAM;
  pal_snprintf (port_str, SU_ADDRSTRLEN, "%d", port);
  port_str[sizeof (port_str) - 1] = '\0';

  ret = pal_sock_getaddrinfo (NULL, port_str, &req, &ainfo);
  if (ret != 0)
    {
      zlog_err (&BLG, "[NETWORK] Server Sock: getaddrinfo() failed: %d-%s",
                errno, pal_strerror (errno));

      return ret;
    }

  ainfo_head = ainfo;
  /* IPv4 can connect to IPv6 socket, not other way around. */
  while (ainfo)
    {
      if (ainfo->ai_family == AF_INET)
        ainfo_save[1] = ainfo;
      else if (ainfo->ai_family == AF_INET6)
        ainfo_save[0] = ainfo;

      ainfo = ainfo->ai_next;
    }

  for (i = 0; i < 2; i++) {
    ainfo = ainfo_save[i];

    if (! ainfo)
      continue;

    if (ainfo->ai_family != AF_INET && ainfo->ai_family != AF_INET6)
      continue;

    bgp_sock = pal_sock (&BLG, ainfo->ai_family, ainfo->ai_socktype,
                         ainfo->ai_protocol);
    if (bgp_sock < 0)
      {
        zlog_err (&BLG, "[NETWORK] Server Sock: socket() Failed for AF"
                  "=%d, FIB-ID %d, Err:%d-%s", ainfo->ai_family,
                  fib_id, errno, pal_strerror (errno));

        continue;
      }

    /* set socket as ipv6 only */
    if (ainfo->ai_family == AF_INET6)
      {
        ret = setsockopt(bgp_sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &flags, sizeof(flags));
        if (ret < 0)
          {
            zlog_err (&BLG, "[NETWORK] Server Sock: socket() failed to"
                      "set option for AF=%d, Err:%d-%s", ainfo->ai_family,
                      errno, pal_strerror (errno));
          }
      }

    ret = pal_sock_set_reuseaddr (bgp_sock, PAL_TRUE);
    pal_sock_set_reuseport (bgp_sock, PAL_TRUE);

    /* Bind socket to FIB. */
    ret = pal_sock_set_bindtofib (bgp_sock, fib_id);
    if (ret < 0)
      {
        zlog_err (&BLG, "[NETWORK] Server Sock: bindtofib() Failed for"
                  " AF=%d, Sock %d, FIB-ID %d, Err:%d-%s",
                  ainfo->ai_family, bgp_sock, fib_id, errno,
                  pal_strerror (errno));

        SSOCK_FD_CLOSE (&BLG, bgp_sock);

        ret = 0;

        continue;
      }

    /* If the ai_addr is NULL, bind it to the port. */
    if (ainfo->ai_addr == NULL)
      {
        if (ainfo->ai_family == AF_INET)
          {
            pal_mem_set (&ain4, 0, sizeof (ain4)); 

            ain4.sin_family = AF_INET;
            ain4.sin_port   = pal_hton16 (port);

            ainfo->ai_addr    = (struct pal_sockaddr *) &ain4;
            ainfo->ai_addrlen = sizeof (struct pal_sockaddr_in4);
            addr_set = 1;
          }
        else if (ainfo->ai_family == AF_INET6)
          {
            pal_mem_set (&ain6, 0, sizeof (ain6));

            ain6.sin6_family = AF_INET6;
            ain6.sin6_port   = pal_hton16 (port);

            ainfo->ai_addr    = (struct pal_sockaddr *) &ain6;
            ainfo->ai_addrlen = sizeof (struct pal_sockaddr_in6);
            addr_set = 1;
          }
        else
          {
            zlog_err (&BLG, "[NETWORK] Server Sock: getaddrinfo() returned"
                      "invalid address"
                      " AF=%d, Sock %d",
                      ainfo->ai_family, bgp_sock);
              
            SSOCK_FD_CLOSE (&BLG, bgp_sock);
              
            ret = 0;
              
            continue;
          }
      }

    ret = pal_sock_bind (bgp_sock, ainfo->ai_addr, ainfo->ai_addrlen);

    if (addr_set)
      ainfo->ai_addr = NULL;

    if (ret < 0)
      {
        zlog_err (&BLG, "[NETWORK] Server Sock: bind() Failed for AF="
                  "%d, Err: %d-%s, port[%d]", ainfo->ai_family, errno,
                  pal_strerror (errno),  port);

        SSOCK_FD_CLOSE (&BLG, bgp_sock);

        ret = 0;

        continue;
      }

#ifdef HAVE_TCP_MD5SIG
    bgp_md5_set_server (bgp, bgp_sock);
#endif /* TCP_MD5SIG */

    ret = pal_sock_listen (bgp_sock, BGP_SOCK_LISTEN_BACKLOG);
    if (ret < 0)
      {
        zlog_err (&BLG, "[NETWORK] Server Sock: listen() Failed for "
                  "AF=%d, Sock %d, FIB-ID %d, Err:%d-%s",
                  ainfo->ai_family, bgp_sock, fib_id, errno,
                  pal_strerror (errno));

        SSOCK_FD_CLOSE (&BLG, bgp_sock);

        ret = 0;

        continue;
      }

    /* Start a fresh Accept Thread */
    t_accept = NULL;
    BGP_READ_ON (&BLG, t_accept, bgp, bpn_sock_accept, bgp_sock);

    /* Add thread to Listen Thread List */
    tmp_lnode = XCALLOC (MTYPE_TMP,
                         sizeof (struct bgp_listen_sock_lnode));
    if (! tmp_lnode)
      {
        zlog_err (&BLG, "[NETWORK] Server Sock:"
                  " Cannot allocate memory (%d) @ %s:%d",
                  sizeof (struct bgp_peer_inconn_req), __FILE__, __LINE__);

        SSOCK_FD_CLOSE (&BLG, bgp_sock);
        BGP_READ_OFF (&BLG, t_accept);

        continue;
      }

    tmp_lnode->listen_sock = bgp_sock;
    tmp_lnode->t_accept = t_accept;
    if (bgp->listen_sock_lnode)
      tmp_lnode->next = bgp->listen_sock_lnode;
    bgp->listen_sock_lnode = tmp_lnode;

  } 

  pal_sock_freeaddrinfo (ainfo_head);

  return ret;
}
Пример #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;
}
Пример #6
0
in_port_t
bpn_get_port_any (int family, int socktype, struct pal_sockaddr *sa)
{
  struct pal_addrinfo hints;
  struct pal_addrinfo *res;
  void *src;
  socklen_t size;
  in_port_t port_any = 0;
  char addr_str[INET6_ADDRSTRLEN];
  const char *s;
  int ret;

  pal_mem_set (&hints, 0, sizeof(hints));
  hints.ai_flags |= (AI_NUMERICHOST | AI_NUMERICSERV);
  hints.ai_family = family;
  hints.ai_socktype = socktype;

  switch (family)
    {
    case AF_INET:
      if (sa->sa_family != AF_INET)
        {
          zlog_warn (&BLG, "[NETWORK] %s: family mismatch (AF_INET - %d)",
                     __FUNCTION__, sa->sa_family);
          goto fallback;
        }
      src = &(((struct pal_sockaddr_in4 *)sa)->sin_addr);
      size = INET_ADDRSTRLEN;
      break;
#ifdef HAVE_IPV6
    case AF_INET6:
      if (sa->sa_family != AF_INET6)
        {
          zlog_warn (&BLG, "[NETWORK] %s: family mismatch (AF_INET6 - %d)",
                     __FUNCTION__, sa->sa_family);
          goto fallback;
        }
      src = &(((struct pal_sockaddr_in6 *)sa)->sin6_addr);
      size = INET6_ADDRSTRLEN;
      break;
#endif /* HAVE_IPV6 */
    default:
      zlog_warn (&BLG, "[NETWORK] %s: wrong family param (%d)",
                 __FUNCTION__, sa->sa_family);
      goto fallback;
    }
  s = pal_inet_ntop (family, src, addr_str, size);
  if (!s)
    {
      zlog_warn (&BLG, "[NETWORK] %s: inet_ntop(%d)", __FUNCTION__, errno);
      goto fallback;
    }
  ret = pal_sock_getaddrinfo (addr_str, NULL, &hints, &res);
  if (ret < 0)
    {
      zlog_warn (&BLG, "[NETWORK] %s: getaddrinfo(%d)", __FUNCTION__, errno);
      goto fallback;
    }
  switch (res->ai_family)
    {
    case AF_INET:
      port_any = ((struct pal_sockaddr_in4 *)(res->ai_addr))->sin_port;
      break;
#ifdef HAVE_IPV6
    case AF_INET6:
      port_any = ((struct pal_sockaddr_in6 *)(res->ai_addr))->sin6_port;
      break;
#endif /* HAVE_IPV6 */
    default:
      zlog_warn (&BLG, "[NETWORK] %s: wrong family from getaddrinfo(): %d",
                 __FUNCTION__, res->ai_family);
      break;
    }
  pal_sock_freeaddrinfo (res);

 fallback:
  return port_any;
}