示例#1
0
/**
 * Acquire existing session from sotrage or create new one.
 * All session MUST be requested through this function.
 * @param[in] ip IPv4 address of client.
 * @param[in] existing_only Do only existing sssion search.
 * @return New client.
 */
struct zsession *session_acquire(uint32_t ip, bool existing_only)
{
    struct zsession *sess = NULL;
    size_t sidx = STORAGE_IDX(ip);

    // search for existing session
    pthread_rwlock_rdlock(&zinst()->sessions_lock[sidx]);
    HASH_FIND(hh, zinst()->sessions[sidx], &ip, sizeof(ip), sess);
    if (NULL != sess) {
        __atomic_add_fetch(&sess->refcnt, 1, __ATOMIC_RELAXED);
    }
    pthread_rwlock_unlock(&zinst()->sessions_lock[sidx]);

    // or create new session
    if (!existing_only && NULL == sess) {
        pthread_rwlock_wrlock(&zinst()->sessions_lock[sidx]);

        HASH_FIND(hh, zinst()->sessions[sidx], &ip, sizeof(ip), sess);
        if (NULL != sess) {
            __atomic_add_fetch(&sess->refcnt, 1, __ATOMIC_RELAXED);
        } else {
            sess = session_create();
            sess->ip = ip;
            __atomic_store_n(&sess->last_activity, ztime(false), __ATOMIC_RELAXED);
            __atomic_add_fetch(&sess->refcnt, 1, __ATOMIC_RELAXED); // sessions storage reference

            HASH_ADD(hh, zinst()->sessions[sidx], ip, sizeof(ip), sess);
        }

        pthread_rwlock_unlock(&zinst()->sessions_lock[sidx]);
    }

    return sess;
}
示例#2
0
文件: radius.c 项目: intersvyaz/zerod
/**
 * Prepare accounting request data.
 * @param[in] session Session.
 * @param[in,out] req Accounting data request.
 */
static void zrad_acct_prepare(zscope_t *scope, zsession_t *session, zrad_acct_req_t *req)
{
    zclient_t *client = zsession_get_client(session);

    pthread_spin_lock(&client->lock);
    req->username = client->login;
    snprintf(req->session_id, sizeof(req->session_id), "%s-%" PRIu32, client->login, session->ip);
    pthread_spin_unlock(&client->lock);

    zclient_release(client);

    req->calling_station_id = session->ip_str;
    req->framed_ip_addr = session->ip;

    req->nas_id = scope->cfg->radius.nas_id;

    req->traff_down = atomic_load_acquire(&session->traff_down);
    req->traff_up = atomic_load_acquire(&session->traff_up);

    req->octets_down = (uint32_t) (req->traff_down % UINT32_MAX);
    req->octets_up = (uint32_t) (req->traff_up % UINT32_MAX);

    req->packets_down = atomic_load_acquire(&session->packets_down) % UINT32_MAX;
    req->packets_up = atomic_load_acquire(&session->packets_up) % UINT32_MAX;

    req->gigawords_down = (uint32_t) (req->traff_down / UINT32_MAX);
    req->gigawords_up = (uint32_t) (req->traff_up / UINT32_MAX);

    req->authentic = PW_RADIUS;

    if (PW_STATUS_STOP == req->status) {
        req->session_time = (uint32_t) USEC2SEC(ztime() - session->create_time);
    }
}
示例#3
0
static void overlord_auth(struct zsession *sess)
{
    uint64_t last_auth = atomic_load_explicit(&sess->last_auth, memory_order_acquire);
    uint64_t curr_time = ztime(false);
    if ((curr_time - last_auth) > zcfg()->session_auth_interval) {

        if (0 == last_auth) {
            zero_syslog(LOG_INFO, "New session %s", ipv4_to_str(htonl(sess->ip)));
        }
        session_authenticate(sess);
        atomic_store_explicit(&sess->last_auth, curr_time, memory_order_release);
    }
}
示例#4
0
/**
 * Apply filters on packet and send it to listeners on success.
 * @param[in] mon Monitor instance.
 * @param[in] packet Packet buffer.
 * @param[in] len Packet length.
 */
void zmonitor_mirror_packet(struct zmonitor *mon, unsigned const char *packet, size_t len)
{
    pthread_rwlock_rdlock(&mon->lock);

    if (likely(!utarray_len(&mon->monitors))) {
        goto end;
    }

    uint64_t ts = ztime(false);
    struct pcap_pkthdr pkthdr = {
        .ts = {0},
        .caplen = (uint32_t) len,
        .len = (uint32_t) len
    };
示例#5
0
static void overlord_acct(struct zsession *sess)
{
    // update accounting
    int ret;

    if (sess->accounting_alive) {
        ret = session_accounting(sess, PW_STATUS_ALIVE, 0);
    } else {
        ret = session_accounting(sess, PW_STATUS_START, 0);
        sess->accounting_alive = (0 == ret);
    }

    if (REJECT_RC == ret) {
        // accounting rejected, mark session for deletion
        atomic_store_explicit(&sess->delete_flag, true, memory_order_release);
    } else {
        atomic_store_explicit(&sess->last_acct, ztime(false), memory_order_release);
    }
}
示例#6
0
/**
 * Server session.
 * - Authenticate sessions.
 * - Upload accounting.
 * - Remove inactive sessions.
 */
static void overlord_serve_session(struct zsession *sess)
{
    uint64_t curr_time = ztime(true);
    zclock(true); // refresh

    // remove inactive, long duration or marked for deletion session
    uint32_t term_cause = 0;
    if (atomic_load_explicit(&sess->delete_flag, memory_order_acquire)) {
        term_cause = PW_ADMIN_RESET;
        zero_syslog(LOG_INFO, "Removed marked for deletion session %s", ipv4_to_str(htonl(sess->ip)));
    } else if (overlord_sess_is_idle_timeout(sess, curr_time)) {
        term_cause = PW_IDLE_TIMEOUT;
        zero_syslog(LOG_INFO, "Removed inactive session %s", ipv4_to_str(htonl(sess->ip)));
    } else if ((curr_time - sess->create_time) > atomic_load_explicit(&sess->max_duration, memory_order_acquire)) {
        term_cause = PW_SESSION_TIMEOUT;
        zero_syslog(LOG_INFO, "Removed long duration session %s", ipv4_to_str(htonl(sess->ip)));
    }

    if (term_cause) {
        if (sess->accounting_alive) {
            session_accounting(sess, PW_STATUS_STOP, term_cause);
        }
        session_remove(sess);
    } else {
        overlord_nat_cleanup(sess);
        overlord_apply_deferred_rules(sess);

        // authenticate session
        if (0 == sess->client->id) {
            overlord_auth(sess);

        } else if ((curr_time - atomic_load_explicit(&sess->last_acct, memory_order_acquire)) >
                   atomic_load_explicit(&sess->acct_interval, memory_order_acquire)) {
            overlord_acct(sess);
        }
    }
}