Example #1
0
/*! Perform system bind on the OS backing socket.
 * \param ep       Endpoint context
 * \param fd       Callers FD
 * \param ip_addr_be32  Local address to which to bind
 * \param port_be16     [in] requested port [out] assigned port
 * \return         0 - success & [port_be16] updated
 *                 CI_SOCKET_HANDOVER, Pass to OS, OS bound ok, (no error)
 *                 CI_SOCKET_ERROR & errno set
 */
ci_inline int __ci_bind(ci_netif *ni, ci_sock_cmn *s,
                        ci_uint32 ip_addr_be32, ci_uint16* port_be16 )
{
  int rc;
  ci_uint16 user_port; /* Port number specified by user, not by OS.
                        * See bug 4015 for details */
  union ci_sockaddr_u sa_u;

  ci_assert(s->domain == AF_INET || s->domain == AF_INET6);

  ci_assert( port_be16 );

  user_port = *port_be16;
#if CI_CFG_FAKE_IPV6
  ci_assert(s->domain == AF_INET || s->domain == AF_INET6);
  if( s->domain == AF_INET )
    ci_make_sockaddr(&sa_u.sin, s->domain, user_port, ip_addr_be32);
  else
    ci_make_sockaddr6(&sa_u.sin6, s->domain, user_port, ip_addr_be32);
#else
  ci_assert(s->domain == AF_INET);
  ci_make_sockaddr(&sa_u.sin, s->domain, user_port, ip_addr_be32);
#endif

#ifdef __ci_driver__
  rc = efab_tcp_helper_bind_os_sock(netif2tcp_helper_resource(ni),
                                    SC_SP(s),
                                    &sa_u.sa, sizeof(sa_u), port_be16);
#else
  rc = ci_tcp_helper_bind_os_sock(ni, SC_SP(s), &sa_u.sa,
                                  sizeof(sa_u), port_be16);
#endif

  /* bug1781: only do this if the earlier bind succeeded. 
   * check if we can handle this socket */
  if( rc != 0 )
    return rc;
  if( user_port != 0 )
    s->s_flags |= CI_SOCK_FLAG_PORT_BOUND;
  if( ip_addr_be32 != INADDR_ANY )
    s->s_flags |= CI_SOCK_FLAG_ADDR_BOUND;
  s->s_flags &= ~CI_SOCK_FLAG_CONNECT_MUST_BIND;

#ifndef __ci_driver__
  /* We do not call bind() to alien address from in-kernel code */
  if( ip_addr_be32 != INADDR_ANY &&
      !cicp_user_addr_is_local_efab(CICP_HANDLE(ni), &ip_addr_be32) )
    s->s_flags |= CI_SOCK_FLAG_BOUND_ALIEN;
#endif
  
  return rc;
}
Example #2
0
/* To handle bind we just let the underlying OS socket make all
 * of the decisions for us.  If The bind leaves things such that
 * the source address is not one of ours then we hand it over to the
 * OS (by returning CI_SOCKET_HANDOVER) - in which case the OS socket
 * will be bound as expected. */
int ci_udp_bind(citp_socket* ep, ci_fd_t fd, const struct sockaddr* addr,
                socklen_t addrlen)
{
    int rc;
    ci_uint16 local_port;

    CHECK_UEP(ep);
    LOG_UC(log("%s("SF_FMT", addrlen=%d)", __FUNCTION__,
               SF_PRI_ARGS(ep,fd), addrlen));

    /* Make sure we have no filters.
     *
     * ?? TODO: Under what circumstances could we possibly have filters here?
     * _WIN32 only perhaps?
     */
    ci_udp_clr_filters(ep);

    rc = ci_tcp_helper_bind_os_sock(fd, addr, addrlen, &local_port);

    if( rc == CI_SOCKET_ERROR )
        return rc;
    return ci_udp_bind_conclude(ep, addr, local_port );
}