Exemple #1
0
static int
splitFileObserver(TimeEventHandlerPtr event)
{
    int is_split_on = *(int*)event->data;
    int file_exists = fileExists(splitTunnelingFile);

    if(is_split_on && file_exists)
    {
        splitTunneling = 1;
    }
    else if(is_split_on && !file_exists)
    {
        splitTunneling = 0;
        destroyNetworkList();
    }
    else if(!is_split_on && file_exists)
    {
        int rc = parseSplitFile(splitTunnelingFile);
        if(rc < 0)
        {
            exit(1);
        }
        splitTunneling = 1;
    }
    event = scheduleTimeEvent(5, splitFileObserver, sizeof(splitTunneling), &splitTunneling);
    if(event == NULL)
    {
        do_log(L_ERROR, "Couldn't reschedule splitFileObserver");
        exit(1);
    }
    return 1;
}
Exemple #2
0
static int
dnsDelayedNotify(int error, GethostbynameRequestPtr request)
{
    TimeEventHandlerPtr handler;

    if(error)
        handler = scheduleTimeEvent(0,
                                    dnsDelayedErrorNotifyHandler,
                                    sizeof(*request), request);
    else
        handler = scheduleTimeEvent(0,
                                    dnsDelayedDoneNotifyHandler,
                                    sizeof(*request), request);
    if(handler == NULL) {
        do_log(L_ERROR, "Couldn't schedule DNS notification.\n");
        return -1;
    }
    return 1;
}
Exemple #3
0
static int
dnsTimeoutHandler(TimeEventHandlerPtr event)
{
    DnsQueryPtr query = *(DnsQueryPtr*)event->data;
    ObjectPtr object = query->object;
    int rc;

    /* People are reporting that this does happen.  And I have no idea why. */
    if(!queryInFlight(query)) {
        do_log(L_ERROR, "BUG: timing out martian query (%s, flags: 0x%x).\n",
               scrub(query->name->string), (unsigned)object->flags);
        return 1;
    }

    query->timeout = MAX(10, query->timeout * 2);

    if(query->timeout > dnsMaxTimeout) {
        abortObject(object, 501, internAtom("Timeout"));
        goto fail;
    } else {
        rc = sendQuery(query);
        if(rc < 0) {
            if(rc != -EWOULDBLOCK && rc != -EAGAIN && rc != -ENOBUFS) {
                abortObject(object, 501,
                            internAtomError(-rc,
                                            "Couldn't send DNS query"));
                goto fail;
            }
            /* else let it timeout */
        }
        query->timeout_handler =
            scheduleTimeEvent(query->timeout, dnsTimeoutHandler,
                              sizeof(query), &query);
        if(query->timeout_handler == NULL) {
            do_log(L_ERROR, "Couldn't schedule DNS timeout handler.\n");
            abortObject(object, 501,
                        internAtom("Couldn't schedule DNS timeout handler"));
            goto fail;
        }
        return 1;
    }

 fail:
    removeQuery(query);
    object->flags &= ~OBJECT_INPROGRESS;
    if(query->inet4) releaseAtom(query->inet4);
    if(query->inet6) releaseAtom(query->inet6);
    free(query);
    releaseNotifyObject(object);
    return 1;
}
Exemple #4
0
static void maybe_free_chunks(int arenas, int force)
{
	if (force || used_chunks >= CHUNKS(chunkHighMark)) {
		discardObjects(force, force);
	}

	if (arenas)
		free_chunk_arenas();

	if (used_chunks >= CHUNKS(chunkLowMark) && !objectExpiryScheduled) {
		TimeEventHandlerPtr event;
		event = scheduleTimeEvent(1, discardObjectsHandler, 0, NULL);
		if (event)
			objectExpiryScheduled = 1;
	}
}
Exemple #5
0
int
lingeringClose(int fd)
{
    int rc;
    LingeringClosePtr l;

    rc = shutdown(fd, 1);
    if(rc < 0) {
        if(errno != ENOTCONN) {
            do_log_error(L_ERROR, errno, "Shutdown failed");
        } else if(errno == EFAULT || errno == EBADF) {
            abort();
        }
        CLOSE(fd);
        return 1;
    }

    l = malloc(sizeof(LingeringCloseRec));
    if(l == NULL)
        goto fail;
    l->fd = fd;
    l->handler = NULL;
    l->timeout = NULL;

    l->timeout = scheduleTimeEvent(10, lingeringCloseTimeoutHandler,
                                   sizeof(LingeringClosePtr), &l);
    if(l->timeout == NULL) {
        free(l);
        goto fail;
    }

    l->handler = registerFdEvent(fd, POLLIN,
                                 lingeringCloseHandler,
                                 sizeof(LingeringClosePtr), &l);
    if(l->handler == NULL) {
        do_log(L_ERROR, "Couldn't schedule lingering close handler.\n");
        /* But don't close -- the timeout will do its work. */
    }
    return 1;

 fail:
    do_log(L_ERROR, "Couldn't schedule lingering close.\n");
    CLOSE(fd);
    return 1;
}
Exemple #6
0
void
initSplitTunneling(void)
{
    int rc;
    if(!splitTunnelingFile || !splitTunnelingFile->string || strlen(splitTunnelingFile->string) == 0)
    {
        return; //Do not do split tunneling if file is not specified
    }

    if(!splitTunnelingDnsServer)
    {
        do_log(L_ERROR, "No splitTunnelingDnsServer provided for split tunneling\n");
        exit(1);
    }
    if(psiphonServer && psiphonServer->string && strlen(psiphonServer->string) > 0)
    {
        memset(&psiphonServerAddr, 0, sizeof(psiphonServerAddr));
        rc = inet_aton(psiphonServer->string, &psiphonServerAddr);
        if(!rc)
        {
            do_log(L_ERROR, "Couldn't parse psiphonServer IP\n");
            exit(1);
        }
    }

    /* schedule splitFileObserver at this point*/
    rc = 0;
    TimeEventHandlerPtr event = scheduleTimeEvent(-1, splitFileObserver, sizeof(rc), &rc);
    if(event == NULL)
    {
        do_log(L_ERROR, "Couldn't schedule splitFileObserver\n");
        exit(1);
    }


}
Exemple #7
0
static int
really_do_dns(AtomPtr name, ObjectPtr object)
{
    int rc;
    DnsQueryPtr query;
    AtomPtr message = NULL;
    int id;
    AtomPtr a = NULL;

    if(a == NULL) {
        if(name == atomLocalhost || name == atomLocalhostDot) {
            char s[1 + sizeof(HostAddressRec)];
            memset(s, 0, sizeof(s));
            s[0] = DNS_A;
            s[1] = 4;
            s[2] = 127;
            s[3] = 0;
            s[4] = 0;
            s[5] = 1;
            a = internAtomN(s, 1 + sizeof(HostAddressRec));
            if(a == NULL) {
                abortObject(object, 501,
                            internAtom("Couldn't allocate address"));
                notifyObject(object);
                errno = ENOMEM;
                return -1;
            }
        }
    }

    if(a == NULL) {
        struct in_addr ina;
        rc = inet_aton(name->string, &ina);
        if(rc == 1) {
            char s[1 + sizeof(HostAddressRec)];
            memset(s, 0, sizeof(s));
            s[0] = DNS_A;
            s[1] = 4;
            memcpy(s + 2, &ina, 4);
            a = internAtomN(s, 1 + sizeof(HostAddressRec));
            if(a == NULL) {
                abortObject(object, 501,
                            internAtom("Couldn't allocate address"));
                notifyObject(object);
                errno = ENOMEM;
                return -1;
            }
        }
    }
#ifdef HAVE_IPv6
    if(a == NULL)
        a = rfc2732(name);
#endif

    if(a) {
        object->headers = a;
        object->age = current_time.tv_sec;
        object->expires = current_time.tv_sec + 240;
        object->flags &= ~(OBJECT_INITIAL | OBJECT_INPROGRESS);
        notifyObject(object);
        return 0;
    }

    rc = establishDnsSocket();
    if(rc < 0) {
        do_log_error(L_ERROR, -rc, "Couldn't establish DNS socket.\n");
        message = internAtomError(-rc, "Couldn't establish DNS socket");
        goto fallback;
    }

    /* The id is used to speed up detecting replies to queries that
       are no longer current -- see dnsReplyHandler. */
    id = (idSeed++) & 0xFFFF;

    query = malloc(sizeof(DnsQueryRec));
    if(query == NULL) {
        do_log(L_ERROR, "Couldn't allocate DNS query.\n");
        message = internAtom("Couldn't allocate DNS query");
        goto fallback;
    }
    query->id = id;
    query->inet4 = NULL;
    query->inet6 = NULL;
    query->name = name;
    query->time = current_time.tv_sec;
    query->object = retainObject(object);
    query->timeout = 4;
    query->timeout_handler = NULL;
    query->next = NULL;

    query->timeout_handler = 
        scheduleTimeEvent(query->timeout, dnsTimeoutHandler,
                          sizeof(query), &query);
    if(query->timeout_handler == NULL) {
        do_log(L_ERROR, "Couldn't schedule DNS timeout handler.\n");
        message = internAtom("Couldn't schedule DNS timeout handler");
        goto free_fallback;
    }
    insertQuery(query);

    object->flags |= OBJECT_INPROGRESS;
    rc = sendQuery(query);
    if(rc < 0) {
        if(rc != -EWOULDBLOCK && rc != -EAGAIN && rc != -ENOBUFS) {
            object->flags &= ~OBJECT_INPROGRESS;
            message = internAtomError(-rc, "Couldn't send DNS query");
            goto remove_fallback;
        }
        /* else let it timeout */
    }
    releaseAtom(message);
    return 1;

 remove_fallback:
    removeQuery(query);
 free_fallback:
    releaseObject(query->object);
    cancelTimeEvent(query->timeout_handler);
    free(query);
 fallback:
    if(dnsUseGethostbyname >= 1) {
        releaseAtom(message);
        do_log(L_WARN, "Falling back on gethostbyname.\n");
        return really_do_gethostbyname(name, object);
    } else {
        abortObject(object, 501, message);
        notifyObject(object);
        return 1;
    }
}