Exemple #1
0
SXSocketRef SXCreateClientSocket(const char * ipaddr,
                                 unsigned short port,
                                 int domain,
                                 int type,
                                 int protocol,
                                 SXError * err_ret)
{
    SXSocketRef sockPtr = (SXSocketRef)sx_calloc(1, sizeof(sx_socket_t));

    if (sockPtr == NULL)
        ERR_RET(SX_ERROR_MEM_ALLOC);
    
    sockPtr->protocol = protocol;
    sockPtr->type = type;
    sockPtr->domain = domain;
    sx_obj_init(&sockPtr->obj, &SXFreeSocket);
    socklen_t addrlen;

    memset(&sockPtr->addr, 0, sizeof(struct sockaddr_storage));
    
    if ((sockPtr->sockfd = socket(domain, type, protocol)) == -1) {
        perror("socket");
        ERR_RET(SX_ERROR_SYS_SOCKET);
    }
    
    switch (domain) {
        case AF_INET:
            sockaddr_in(sockPtr->addr).sin_port = htons(port);
            sockaddr_in(sockPtr->addr).sin_len = sizeof(struct sockaddr_in);
            addrlen = sizeof(struct sockaddr_in);
            inet_pton(AF_INET, ipaddr, &sockaddr_in(sockPtr->addr).sin_addr);
            break;
        case AF_INET6:
            sockaddr_in6(sockPtr->addr).sin6_port = htons(port);
            sockaddr_in6(sockPtr->addr).sin6_len = sizeof(struct sockaddr_in6);
            addrlen = sizeof(struct sockaddr_in6);
            inet_pton(AF_INET6, ipaddr, &sockaddr_in6(sockPtr->addr).sin6_addr);
            break;
        default:
            ERR_RET(SX_ERROR_INVALID_IPADDR);
            return NULL;
    }
    
    int yes = 1;
    
    if (setsockopt(sockPtr->sockfd, SOL_SOCKET, SO_NOSIGPIPE, &yes, sizeof(int)) == -1) {
        perror("setsockopt");
        ERR_RET(SX_ERROR_SYS_SETSOCKOPT);
    }
    
    sockPtr->addr.ss_family = domain;
    
    ERR_RET(SX_SUCCESS);
    
    return sockPtr;
}
Exemple #2
0
/**
 * Sets the address to invalid, and m_addr to the default for the given type.
 *
 * @param type
 */
void sockAddrBase::init(Addr::Type type)
{
  switch (type)
  {
  case Addr::IPv4:
  {
    sockaddr_in *storage = getIPv4Storage();
    storage->sin_family = AF_INET;
    storage->sin_port = 0;
    storage->sin_addr.s_addr = INADDR_ANY;
  }
    break;
  case Addr::IPv6:
  {
    sockaddr_in6 *storage = getIPv6Storage();
    *storage = sockaddr_in6();
    storage->sin6_family = AF_INET6;
    storage->sin6_addr = in6addr_any;  /** Probably not necessary. Is  in6addr_any _guaranteed_ to be 0?*/
  }
    break;
  default:
    m_addr.ss_family = AF_UNSPEC;
    break;
  }
}
Exemple #3
0
SXError dns_lookup(SXSocketRef socket, const char * hostname, const char * service, struct addrinfo * hint) {
    struct addrinfo * info, * cinfo;
    
    if (getaddrinfo(hostname, service, hint, &info) != 0)
        return SX_ERROR_SYS_GET_ADDR_INFO;
    
    
    cinfo = info;
    
    while (cinfo != NULL) {
        cinfo = cinfo->ai_next;
        short port = htons(getservbyname(service, NULL)->s_port);
        memset(&socket->addr, 0, sizeof(struct sockaddr_storage));
        switch (cinfo->ai_family) {
            case AF_INET:
                socket->domain = AF_INET;
                socket->type = cinfo->ai_socktype;
                socket->protocol = cinfo->ai_protocol;
                
                sockaddr_in(socket->addr).sin_len = sizeof(struct sockaddr_in);
                sockaddr_in(socket->addr).sin_family = AF_INET;
                sockaddr_in(socket->addr).sin_addr = sockaddr_in(cinfo->ai_addr).sin_addr;
                sockaddr_in(socket->addr).sin_port = port;
                goto clean;
            case AF_INET6:
                sockaddr_in6(socket->addr).sin6_len = sizeof(struct sockaddr_in6);
                sockaddr_in6(socket->addr).sin6_family = AF_INET6;
                sockaddr_in6(socket->addr).sin6_port = port;
                sockaddr_in6(socket->addr).sin6_addr = sockaddr_in6(cinfo->ai_addr).sin6_addr;
                goto clean;
            default:
                goto cont;
        }
        
    cont:
        continue;
    }
    
clean:
    freeaddrinfo(info);
    
    return SX_SUCCESS;
}
Exemple #4
0
SXSocketRef SXCreateServerSocket(unsigned short port,
                                 int domain,
                                 int type,
                                 int protocol,
                                 SXError * err_ret)
{
    SXSocketRef sockPtr = (SXSocketRef)sx_calloc(1, sizeof(sx_socket_t));
    
    if (sockPtr == NULL)
        ERR_RET(SX_ERROR_MEM_ALLOC);
    
    sockPtr->domain = domain;
    sockPtr->type = type;
    sockPtr->protocol = protocol;
    sockPtr->ref_count = 1;
    sockPtr->port = port;
    socklen_t addrlen;
    
    memset(&sockPtr->addr, 0, sizeof(struct sockaddr_storage));
    
    if ((sockPtr->sockfd = socket(domain, type, protocol)) == -1) {
        perror("socket");
        ERR_RET(SX_ERROR_SYS_SOCKET);
    }
    
    switch (domain) {
        case AF_INET:
            sockaddr_in(sockPtr->addr).sin_addr.s_addr = INADDR_ANY;
            sockaddr_in(sockPtr->addr).sin_port = htons(port);
            sockaddr_in(sockPtr->addr).sin_len = sizeof(struct sockaddr_in);
            addrlen = sizeof(struct sockaddr_in);
            break;
        case AF_INET6:
            sockaddr_in6(sockPtr->addr).sin6_addr = in6addr_any;
            sockaddr_in6(sockPtr->addr).sin6_port = htons(port);
            sockaddr_in6(sockPtr->addr).sin6_len = sizeof(struct sockaddr_in6);
            addrlen = sizeof(struct sockaddr_in6);
            break;
        default:
            ERR_RET(SX_ERROR_INVALID_IPADDR);
            return NULL;
    }
    
    sockPtr->addr.ss_family = domain;
    
    int yes=1;
    
    if (setsockopt(sockPtr->sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
        perror("setsockopt");
        ERR_RET(SX_ERROR_SYS_SETSOCKOPT);
    }
    
    if (bind(sockPtr->sockfd, (struct sockaddr *)&sockPtr->addr, addrlen) == -1) {
        perror("bind");
        ERR_RET(SX_ERROR_SYS_BIND);
    }
    
    ERR_RET(SX_SUCCESS);
    
    return sockPtr;
}
Exemple #5
0
bool sockAddrBase::FromString(const char *str)
{
  // This is called from the constructor, so it must work with an uninitialized
  // structure.
  init(Addr::Invalid);
  // First determine if it is IPv4 or IPv6
  str = SkipWhite(str);
  const char *firstColon = strchr(str, ':');
  const char *firstDot = strchr(str, '.');
  const char *firstPercent = strchr(str, '%');

  if (!firstDot && !firstColon)
    return false;
  if (!firstColon
      || (firstDot && firstDot < firstColon))
  {
    // IPv4
    uint16_t port;
    uint32_t addr;

    if (firstPercent)
      return false;

    if (!firstColon)
    {
      if (!ParseIPv4(str, &addr, &str))
        return false;
      str = SkipWhite(str);
      if (*str != '\0')
        return false;
      init(Addr::IPv4);
      getIPv4Storage()->sin_addr.s_addr = addr;
      return true;
    }
    // Has dots and a colon, presumably its an IPv4 with port
    if (!m_allowPort)
      return false;

    if (!ParseIPv4Port(str, &addr, &port))
      return false;
    init(Addr::IPv4);
    getIPv4Storage()->sin_addr.s_addr = addr;
    SetPort(port);
    return true;
  }

  // Not IPv4
  if (!firstColon || (firstPercent && (firstPercent < firstColon)))
    return false;
  else
  {
    // IPv6
    sockaddr_in6 tmp = sockaddr_in6();

    if (firstPercent || *str == '[')
    {
      char addrStr[INET6_ADDRSTRLEN];
      const char *last, *lastBrace = NULL;

      if (*str == '[')
      {
        ++str;
        last = lastBrace = strchr(str,  ']');
        if (!lastBrace)
          return false;
      }
      if (firstPercent)
      {
        if (lastBrace && lastBrace < firstPercent + 2)
          return false;
        last = firstPercent;
      }

      if (last == str || size_t(last - str) >= sizeof(addrStr))
        return false;
      memcpy(addrStr, str, last - str);
      addrStr[last - str] = '\0';
      if (1 != inet_pton(AF_INET6, addrStr, &tmp.sin6_addr))
        return false;
      if (firstPercent)
      {
        // ONLY allow interface (scope) for link local addresses (for now)
        // Otherwise address comparison breaks for regular addresses, one of which has a
        // scope.
        if (!IN6_IS_ADDR_LINKLOCAL(&tmp.sin6_addr))
          return false;

        if (lastBrace)
        {
          // already checked that (lastBrace-firstPercent >= 2)
          memcpy(addrStr, firstPercent + 1, lastBrace - (firstPercent + 1));
          addrStr[lastBrace - (firstPercent + 1)] = '\0';
          last = addrStr;
        }
        else
          last = firstPercent + 1;

        unsigned int index = if_nametoindex(last);
        if (index == 0 || index > UINT32_MAX)
          return false;
        tmp.sin6_scope_id = uint32_t(index);
      }

      if (lastBrace)
      {
        last = lastBrace + 1;
        if (*last != ':')
        {
          last = SkipWhite(last);
          if (*last != '\0')
            return false;
        }
        else
        {
          // We have a port
          uint64_t val;

          if (!m_allowPort)
            return false;
          ++last;
          if (!StringToInt(last, val))
            return false;
          if (val > UINT16_MAX)
            return false;
          tmp.sin6_port = htons(uint16_t(val));
        }
      }
    }
    else
    {
      // no [] and no % so the string can be parsed directly
      if (1 != inet_pton(AF_INET6, str, &tmp.sin6_addr))
        return false;
    }

    // Set the actual value
    init(Addr::IPv6);
    sockaddr_in6 *storage = getIPv6Storage();
    storage->sin6_addr = tmp.sin6_addr;
    storage->sin6_port = tmp.sin6_port;
    storage->sin6_scope_id = tmp.sin6_scope_id;
    return true;
  }
}