Пример #1
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;
}
Пример #2
0
void runSuccess() {
    char buf[] = "hi";
    //@ assert \valid((char*)buf);
    struct addrinfo ai;
    struct gaicb g1 = {
            .ar_name = buf,
            .ar_service = buf,
            .ar_request = &ai,
    };
    struct gaicb *list[] = {NULL, &g1};
    if (!getaddrinfo_a(anyint(), list, 2, NULL)) {
        gai_cancel(&g1);
    }
}
Пример #3
0
void testValues() {
    f = 2;
    
    char buf[] = "hi";
    //@ assert \valid((char*)buf);
    struct addrinfo ai;
    struct gaicb g1 = {
            .ar_name = buf,
            .ar_service = buf,
            .ar_request = &ai,
    };
    struct gaicb *list[] = {NULL, &g1};
    if (!getaddrinfo_a(anyint(), list, 2, NULL)) {
        gai_cancel(&g1);
    }

    //@ assert f == 2;
    //@ assert vacuous: \false;
}
Пример #4
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;
}
Пример #5
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);
}
Пример #6
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
}
Пример #7
0
//---------------------------------
int ResolverRequest::addRequest(const char *hostName)
{
    int i, emptyIndex = -1;

    DWORD   oldestTime  = 0x7fffffff;
    int     oldestIndex = -1;

    // find usable slot
    for(i=0; i<RESOLV_COUNT; i++) {
        if(requests[i].startTime == 0) {      // start time 0 means it's empty (not running)
            emptyIndex = i;
            break;
        }
                                            // if it's running and it's older than the currently found oldest, mark it
        if(oldestTime > requests[i].startTime) {
            oldestTime  = requests[i].startTime;
            oldestIndex = i;
        }
    }

    // get pointer to that slot
    Tresolv *r;
    int      usedIndex;

    if(emptyIndex != -1) {      // if found empty slot, use it
        r = &requests[emptyIndex];
        usedIndex = emptyIndex;
    } else {                    // if not found empty slot, cancel existing and use it
        gai_cancel(&requests[oldestIndex].req);       // try to cancel
        r = &requests[oldestIndex];
        usedIndex = oldestIndex;
    }

    r->startTime                = Utils::getCurrentMs();    // store start time
    r->getaddrinfoHasFinished   = 0;                        // mark that we did not finish yet
    r->count                    = 0;                        // no IPs stored yet
    r->processed                = 0;                        // not processed yet
    memset(r->canonName, 0, 256);                           // no canon name yet

    memset (r->hostName, 0, 256);
    strncpy(r->hostName, hostName, 255);                    // copy host name to our array
    r->req.ar_name      = r->hostName;                      // store pointer to that array

    //-------------------
    // check and possibly resolve dotted IP
    int a,b,c,d;
    int iRes = sscanf(hostName, "%d.%d.%d.%d", &a, &b, &c, &d);
    
    if(iRes == 4) {         // succeeded to get IP parts
        if(IS_VALID_IP_NUMBER(a) && IS_VALID_IP_NUMBER(b) && IS_VALID_IP_NUMBER(c) && IS_VALID_IP_NUMBER(d)) {

            BYTE *pIps = (BYTE *) r->data;
            pIps[0]     = a;    // store that IP
            pIps[1]     = b;
            pIps[2]     = c;
            pIps[3]     = d;
            
            r->count    = 1;    // store count
            
            strcpy(r->canonName, r->hostName);                          // pretend that the string is canonical name
            
            r->getaddrinfoHasFinished   = 1;                            // resolve finished
            r->processed                = 1;
            
            return usedIndex;
        }
    }
    //-------------------
    
    r->hints.ai_flags   = AI_CANONNAME;                     // get the official name of the host
    r->req.ar_request   = &r->hints;

    gaicb *pReq = &r->req;
    int ret = getaddrinfo_a(GAI_NOWAIT, &pReq, 1, NULL);

    if (ret) {
        Debug::out(LOG_DEBUG, "addRequest() failed");
        return -1;
    }

    Debug::out(LOG_DEBUG, "addRequest() - resolving %s under index %d", hostName, usedIndex);
    return usedIndex;           // return index under which this request runs
}
Пример #8
0
int iio_cmdsrv_connect(const char *addr, const char *port, const char protocol, struct iio_cmdsrv *handle)
{
	struct addrinfo hints, *servinfo, *p;
	int rv;
	char s[INET6_ADDRSTRLEN];
	struct timeval timeout;
	struct gaicb *in[1];

	if (addr && port) {
		strcpy(handle->addr, (char *)addr);
		strcpy(handle->port, (char *)port);
		handle->sockfd = -1;
	} else {
		close(handle->sockfd);
	}

	memset(&hints, 0, sizeof (struct addrinfo));
	hints.ai_family = AF_INET;
	if(protocol == TCP) {
		hints.ai_socktype = SOCK_STREAM;
	} else if(protocol == UDP) {
		hints.ai_socktype = SOCK_DGRAM;
		hints.ai_protocol = IPPROTO_UDP;
	}

	in[0] =(gaicb*)malloc(sizeof(*in[0]));
	memset(in[0], 0, sizeof (*in[0]));
	in[0]->ar_name = handle->addr;
	in[0]->ar_service = handle->port;
	in[0]->ar_request = &hints;

	/* Get ready to make this time out */
	rv = getaddrinfo_a(GAI_WAIT, in, 1, NULL);
	if (rv != 0) {
		syslog(LOG_ERR, "%s: getaddrinfo_a failed\n", __func__);
		return 1;
	}
	servinfo = in[0]->ar_result;

	// loop through all the results and connect to the first we can
	for(p = servinfo; p != NULL; p = p->ai_next) {
		handle->sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
		if (handle->sockfd == -1) {
			syslog(LOG_ERR, "%s: socket failed\n", __func__);
			continue;
		}

		timeout.tv_sec = 1;
		timeout.tv_usec = 0;
		setsockopt(handle->sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval));
		setsockopt(handle->sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval));

		if (connect(handle->sockfd, p->ai_addr, p->ai_addrlen) == -1) {
			close(handle->sockfd);
			handle->sockfd = -1;
			syslog(LOG_ERR, "%s: connection failed\n", __func__);
			continue;
		}

		break;
	}

	if (p == NULL) {
		syslog(LOG_ERR, "%s: connection failed\n", __func__);
		return 2;
	}

	inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr),
		s, sizeof s);

	freeaddrinfo(servinfo);
	free(in[0]);

	return 0;
}