Exemple #1
0
//---------------------------------
bool ResolverRequest::getaddrinfoHasFinished(int index)    // returns true if request has finished
{
    if(!slotIndexValid(index)) {                // out of bounds? false
        return false;
    }

    if(requests[index].startTime == 0) {        // not used? false
        return false;
    }

    Tresolv *r = &requests[index];

    if(r->getaddrinfoHasFinished) {             // if the request already finished, good
        return true;
    }

    // if we don't know if it finished yet, let's check it out
    r->error = gai_error(&r->req);

    if(r->error == EAI_INPROGRESS) {            // if still in progress, false
        return false;
    }

    r->getaddrinfoHasFinished = 1;              // ok, we're done
    return true;
}
Exemple #2
0
/* $begin getaddrinfo */
void Getaddrinfo(const char *node, const char *service, 
                 const struct addrinfo *hints, struct addrinfo **res)
{
    int rc;

    if ((rc = getaddrinfo(node, service, hints, res)) != 0) 
        gai_error(rc, "Getaddrinfo error");
}
Exemple #3
0
void Getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, 
                 size_t hostlen, char *serv, size_t servlen, int flags)
{
    int rc;

    if ((rc = getnameinfo(sa, salen, host, hostlen, serv, 
                          servlen, flags)) != 0) 
        gai_error(rc, "Getnameinfo error");
}
Exemple #4
0
/*
 * Test and see if the Internet is reachable; we do this by attempting
 * to resolve a DNS entry. The GLIBC getaddrinfo_a() function is used
 * so we can timeout if the query takes too long. We simply assume the
 * Internet access works if we're able to successfully resolve the entry.
 */
boolean checkInetAccess() {
    struct gaicb **requests = NULL;
    struct timespec timeout = {0};
    int ret_val = 0, loop_cnt = 0;
    boolean has_inet = FALSE;

    /* Setup our request */
    requests = realloc(requests, (1 * sizeof requests[0]));
    requests[0] = calloc(1, sizeof *requests[0]);
    requests[0]->ar_name = INET_TEST_HOST;

    /* Queue the request */
    ret_val = getaddrinfo_a(GAI_NOWAIT, &requests[0], 1, NULL);
    if (ret_val != 0) {
        DEBUG_LOG("getaddrinfo_a(): %s", gai_strerror(ret_val));
        return FALSE;
    }

    /* Wait for the request to complete, or hit the timeout */
    timeout.tv_nsec = 250000000;
    loop_cnt = 1;
    while (1) {
        /* Don't wait too long */
        if (loop_cnt >= 10) {
            DEBUG_LOG("Timeout value reached, returning...");
            has_inet = FALSE;
            break;
        }
        ++loop_cnt;
        /* Check the request */
        ret_val = gai_error(requests[0]);
        if (ret_val == EAI_INPROGRESS) {
            ;
        } else if (ret_val == 0) {
            has_inet = TRUE;
            break;
        } else {
            DEBUG_LOG("gai_error(): %s", gai_strerror(ret_val));
            has_inet = FALSE;
            break;
        }
        /* Sleep for a bit */
        if (nanosleep(&timeout, NULL) != 0) {
            DEBUG_LOG("nanosleep(): %s", strerror(errno));
            has_inet = FALSE;
            break;
        }
    }

    /* Done */
    freeaddrinfo(requests[0]->ar_request);
    freeaddrinfo(requests[0]->ar_result);
    free(requests);
    return has_inet;
}
Exemple #5
0
int _ribified_getaddrinfo(const char *node, const char *service,
                     const struct addrinfo *hints,
                     struct addrinfo **results) {

    struct gaicb cb = { .ar_name = node, .ar_service = service, .ar_request = hints, .ar_result = NULL };
    struct gaicb *cb_p[1] = { &cb };

    struct sigevent sevp;
    sevp.sigev_notify = SIGEV_SIGNAL;
    sevp.sigev_signo = SIGRTMIN; /* special support in epoll_worker.c */
    sevp.sigev_value.sival_ptr = current_ctx;
    sevp.sigev_notify_attributes = NULL;

    int res = getaddrinfo_a(GAI_NOWAIT, cb_p, 1, &sevp);
    if (!res) {
        yield();
        res = gai_error(cb_p[0]);
        *results = cb.ar_result;
    }
    return res;
}
Exemple #6
0
bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
{
    vIP.clear();

    {
        CNetAddr addr;
        if (addr.SetSpecial(std::string(pszName))) {
            vIP.push_back(addr);
            return true;
        }
    }

#ifdef HAVE_GETADDRINFO_A
    struct in_addr ipv4_addr;
#ifdef HAVE_INET_PTON
    if (inet_pton(AF_INET, pszName, &ipv4_addr) > 0) {
        vIP.push_back(CNetAddr(ipv4_addr));
        return true;
    }

    struct in6_addr ipv6_addr;
    if (inet_pton(AF_INET6, pszName, &ipv6_addr) > 0) {
        vIP.push_back(CNetAddr(ipv6_addr));
        return true;
    }
#else
    ipv4_addr.s_addr = inet_addr(pszName);
    if (ipv4_addr.s_addr != INADDR_NONE) {
        vIP.push_back(CNetAddr(ipv4_addr));
        return true;
    }
#endif
#endif

    struct addrinfo aiHint;
    memset(&aiHint, 0, sizeof(struct addrinfo));
    aiHint.ai_socktype = SOCK_STREAM;
    aiHint.ai_protocol = IPPROTO_TCP;
    aiHint.ai_family = AF_UNSPEC;
#ifdef WIN32
    aiHint.ai_flags = fAllowLookup ? 0 : AI_NUMERICHOST;
#else
    aiHint.ai_flags = fAllowLookup ? AI_ADDRCONFIG : AI_NUMERICHOST;
#endif

    struct addrinfo *aiRes = NULL;
#ifdef HAVE_GETADDRINFO_A
    struct gaicb gcb, *query = &gcb;
    memset(query, 0, sizeof(struct gaicb));
    gcb.ar_name = pszName;
    gcb.ar_request = &aiHint;
    int nErr = getaddrinfo_a(GAI_NOWAIT, &query, 1, NULL);
    if (nErr)
        return false;

    do {
        // Should set the timeout limit to a resonable value to avoid
        // generating unnecessary checking call during the polling loop,
        // while it can still response to stop request quick enough.
        // 2 seconds looks fine in our situation.
        struct timespec ts = { 2, 0 };
        gai_suspend(&query, 1, &ts);
        boost::this_thread::interruption_point();

        nErr = gai_error(query);
        if (0 == nErr)
            aiRes = query->ar_result;
    } while (nErr == EAI_INPROGRESS);
#else
    int nErr = getaddrinfo(pszName, NULL, &aiHint, &aiRes);
#endif
    if (nErr)
        return false;

    struct addrinfo *aiTrav = aiRes;
    while (aiTrav != NULL && (nMaxSolutions == 0 || vIP.size() < nMaxSolutions))
    {
        if (aiTrav->ai_family == AF_INET)
        {
            assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in));
            vIP.push_back(CNetAddr(((struct sockaddr_in*)(aiTrav->ai_addr))->sin_addr));
        }

        if (aiTrav->ai_family == AF_INET6)
        {
            assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in6));
            vIP.push_back(CNetAddr(((struct sockaddr_in6*)(aiTrav->ai_addr))->sin6_addr));
        }

        aiTrav = aiTrav->ai_next;
    }

    freeaddrinfo(aiRes);

    return (vIP.size() > 0);
}
Exemple #7
0
ipaddr ipremote(const char *name, int port, int mode, int64_t deadline) {
    ipaddr addr = mill_ipliteral(name, port, mode);
#if !defined __linux__
    return addr;
#else
    if(errno == 0)
       return addr;
    /* Let's do asynchronous DNS query here. */
    int efd = eventfd(0, 0);
    if(mill_slow(efd < 0))
        return addr;
    struct addrinfo request;
    memset(&request, 0, sizeof(request));
    request.ai_family = AF_UNSPEC;
    request.ai_socktype = SOCK_STREAM;
    struct gaicb gcb;
    memset(&gcb, 0, sizeof(gcb));
    gcb.ar_name = name;
    gcb.ar_service = NULL;
    gcb.ar_request = &request;
    gcb.ar_result = NULL;
    struct sigevent sev;
    memset(&sev, 0, sizeof(sev));
    /* The event will be delivered using a new thread rather than by a signal
       running of one of the coroutines' stack and possibly breaking it. */
    sev.sigev_notify = SIGEV_THREAD;
    sev.sigev_notify_function = mill_getaddrinfo_a_done;
    sev.sigev_value.sival_int = efd;
    struct gaicb *pgcb = &gcb;
    int rc = getaddrinfo_a(GAI_NOWAIT, &pgcb, 1, &sev);
    if(mill_slow(rc != 0)) {
        if(rc == EAI_AGAIN || rc == EAI_MEMORY) {
            close(efd);
            errno = ENOMEM;
            return addr;
        }
        mill_assert(0);
    }
    rc = fdwait(efd, FDW_IN, deadline);
    if(rc == 0) {
        gai_cancel(&gcb);
        rc = fdwait(efd, FDW_IN, -1);
    }
    mill_assert(rc == FDW_IN);
    close(efd);
    rc = gai_error(&gcb);
    if(rc != 0) {
        errno = EINVAL;
        return addr;
    }
    struct addrinfo *ipv4 = NULL;
    struct addrinfo *ipv6 = NULL;
    struct addrinfo *it = gcb.ar_result;
    while(it) {
        if(!ipv4 && it->ai_family == AF_INET)
            ipv4 = it;
        if(!ipv6 && it->ai_family == AF_INET6)
            ipv6 = it;
        if(ipv4 && ipv6)
            break;
        it = it->ai_next;
    }
    switch(mode) {
    case IPADDR_IPV4:
        ipv6 = NULL;
        break;
    case IPADDR_IPV6:
        ipv4 = NULL;
        break;
    case 0:
    case IPADDR_PREF_IPV4:
        if(ipv4)
           ipv6 = NULL;
        break;
    case IPADDR_PREF_IPV6:
        if(ipv6)
           ipv4 = NULL;
        break;
    default:
        mill_assert(0);
    }
    if(ipv4) {
        struct sockaddr_in *inaddr = (struct sockaddr_in*)&addr;
        memcpy(inaddr, ipv4->ai_addr, sizeof (struct sockaddr_in));
        inaddr->sin_port = htons(port);
    }
    if(ipv6) {
        struct sockaddr_in6 *inaddr = (struct sockaddr_in6*)&addr;
        memcpy(inaddr, ipv6->ai_addr, sizeof (struct sockaddr_in6));
        inaddr->sin6_port = htons(port);
    }
    freeaddrinfo(gcb.ar_result);
    errno = 0;
    return addr;
#endif
}
Exemple #8
0
int irc_conn_found(nl_list **list, fd_set *master, int *fdmax)
{
	int serverhandle=0;
	struct addrinfo *servinfo;
	while(*list)
	{
		if(gai_error((*list)->nl_details)) *list=(*list)->next;
		else break;
	}
	if(!*list) return(0); // 0 indicates failure as rv is new serverhandle value
	servinfo=(*list)->nl_details->ar_result;
	
#else /* ASYNCH_NL */
int irc_connect(char *server, const char *portno, fd_set *master, int *fdmax)
{
	int serverhandle=0;
	struct addrinfo hints, *servinfo;
	// Look up server
	memset(&hints, 0, sizeof(hints));
	hints.ai_family=AF_INET;
	hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
	int rv;
	if((rv=getaddrinfo(server, portno, &hints, &servinfo))!=0)
	{
		add_to_buffer(0, ERR, NORMAL, 0, false, (char *)gai_strerror(rv), "getaddrinfo: ");
		return(0); // 0 indicates failure as rv is new serverhandle value
	}
#endif /* ASYNCH_NL */
	char sip[INET_ADDRSTRLEN];
	struct addrinfo *p;
	// loop through all the results and connect to the first we can
	for(p=servinfo;p;p=p->ai_next)
	{
		inet_ntop(p->ai_family, &(((struct sockaddr_in*)p->ai_addr)->sin_addr), sip, sizeof(sip));
		if((serverhandle=socket(p->ai_family, p->ai_socktype, p->ai_protocol))==-1)
		{
			add_to_buffer(0, ERR, NORMAL, 0, false, strerror(errno), "socket: ");
			continue;
		}
		if(fcntl(serverhandle, F_SETFD, O_NONBLOCK)==-1)
		{
			close(serverhandle);
			add_to_buffer(0, ERR, NORMAL, 0, false, strerror(errno), "fcntl: ");
			continue;
		}
		connect_loop:
		if(connect(serverhandle, p->ai_addr, p->ai_addrlen)==-1)
		{
			if(errno!=EINPROGRESS)
			{
				if(errno==EINTR)
				{
					goto connect_loop;
				}
				else
				{
					close(serverhandle);
					add_to_buffer(0, ERR, NORMAL, 0, false, strerror(errno), "connect: ");
					continue;
				}
			}
		}
		break;
	}
	char cmsg[16+strlen(sip)];
	sprintf(cmsg, "fd=%d, ip=%s", serverhandle, sip);
	add_to_buffer(0, STA, DEBUG, 0, false, cmsg, "DBG connect: ");
	if(!p)
	{
		add_to_buffer(0, ERR, NORMAL, 0, false, "failed to connect to server", "/connect: ");
		return(0); // 0 indicates failure as rv is new serverhandle value
	}
	freeaddrinfo(servinfo);
	servinfo=NULL;
	FD_SET(serverhandle, master);
	*fdmax=max(*fdmax, serverhandle);
	return(serverhandle);
}