Example #1
0
static int32_t cacheex_add_to_cache_int(struct s_client *cl, ECM_REQUEST *er, int8_t csp)
{
    if(er->rc >= E_NOTFOUND) {
        return 0;
    }

    if(!cl)
    {
        return 0;
    }
    if(!csp && cl->reader && cl->reader->cacheex.mode != 2)  //from reader
    {
        cs_debug_mask(D_CACHEEX, "CACHEX received, but disabled for %s", username(cl));
        return 0;
    }
    if(!csp && !cl->reader && cl->account && cl->account->cacheex.mode != 3)  //from user
    {
        cs_debug_mask(D_CACHEEX, "CACHEX received, but disabled for %s", username(cl));
        return 0;
    }
    if(!csp && !cl->reader && !cl->account)    //not active!
    {
        cs_debug_mask(D_CACHEEX, "CACHEX received, but invalid client state %s", username(cl));
        return 0;
    }

    uint8_t i, c;
    uint8_t null = 0;
    for(i = 0; i < 16; i += 4)
    {
        c = ((er->cw[i] + er->cw[i + 1] + er->cw[i + 2]) & 0xff);
        null |= (er->cw[i] | er->cw[i + 1] | er->cw[i + 2]);
        if(er->cw[i + 3] != c)
        {
            cs_ddump_mask(D_CACHEEX, er->cw, 16, "push received cw with chksum error from %s", csp ? "csp" : username(cl));
            cl->cwcacheexerr++;
            if(cl->account)
            {
                cl->account->cwcacheexerr++;
            }
            return 0;
        }
    }

    if(null == 0 || chk_is_null_CW(er->cw))
    {
        cs_ddump_mask(D_CACHEEX, er->cw, 16, "push received null cw from %s", csp ? "csp" : username(cl));
        cl->cwcacheexerr++;
        if(cl->account)
        {
            cl->account->cwcacheexerr++;
        }
        return 0;
    }

    er->grp |= cl->grp;  //ok for mode2 reader too: cl->reader->grp
    er->rc = E_CACHEEX;
    er->cacheex_src = cl;
    er->selected_reader = cl->reader;
    er->client = NULL; //No Owner! So no fallback!

    if(check_client(cl))
    {
        cl->cwcacheexgot++;
        if(cl->account)
        {
            cl->account->cwcacheexgot++;
        }
        first_client->cwcacheexgot++;
    }

    add_hitcache(cl, er);  //we have to call it before add_cache, because in chk_process we could remove it!
    add_cache(er);
    cacheex_add_stats(cl, er->caid, er->srvid, er->prid, 1);

    cs_writelock(&ecm_pushed_deleted_lock);
    er->next = ecm_pushed_deleted;
    ecm_pushed_deleted = er;
    cs_writeunlock(&ecm_pushed_deleted_lock);

    return 1;  //NO free, we have to wait cache push out stuff ends.
}
Example #2
0
static int32_t cacheex_add_to_cache_int(struct s_client *cl, ECM_REQUEST *er, int8_t csp)
{
	if(er->rc >= E_NOTFOUND) { return 0; }

	if(!cl)
		{ return 0; }
	if(!csp && cl->reader && cl->reader->cacheex.mode != 2)  //from reader
	{
		cs_log_dbg(D_CACHEEX, "CACHEX received, but disabled for %s", username(cl));
		return 0;
	}
	if(!csp && !cl->reader && cl->account && cl->account->cacheex.mode != 3)  //from user
	{
		cs_log_dbg(D_CACHEEX, "CACHEX received, but disabled for %s", username(cl));
		return 0;
	}
	if(!csp && !cl->reader && !cl->account)    //not active!
	{
		cs_log_dbg(D_CACHEEX, "CACHEX received, but invalid client state %s", username(cl));
		return 0;
	}

	if(!cfg.disablecrccws && ((cl->typ == 'c' && !cl->account->disablecrccacheex) || ( cl->typ == 'p' && !cl->reader->disablecrccws)))
	{
		uint8_t selectedForIgnChecksum = chk_if_ignore_checksum(er, &cfg.disablecrccws_only_for);
		if(cl->typ == 'c')
		{
			selectedForIgnChecksum += chk_if_ignore_checksum(er, &cl->account->disablecrccacheex_only_for);
		}
		if(cl->typ == 'p')
		{
			selectedForIgnChecksum += chk_if_ignore_checksum(er, &cl->reader->disablecrccws_only_for);
		}
		if(!selectedForIgnChecksum)
		{
			uint8_t i, c;
			for(i = 0; i < 16; i += 4)
			{
				c = ((er->cw[i] + er->cw[i + 1] + er->cw[i + 2]) & 0xff);

				if(er->cw[i + 3] != c)
				{
					cs_log_dump_dbg(D_CACHEEX, er->cw, 16, "push received cw with chksum error from %s", csp ? "csp" : username(cl));
					cl->cwcacheexerr++;
					if(cl->account)
						{ cl->account->cwcacheexerr++; }
					return 0;
				}
			}
		}
	}

	// Skip check for BISS1 - cw could be indeed zero
	// Skip check for BISS2 - we use the extended cw, so the "simple" cw is always zero
	if(chk_is_null_CW(er->cw) && !caid_is_biss(er->caid))
	{
		cs_log_dump_dbg(D_CACHEEX, er->cw, 16, "push received null cw from %s", csp ? "csp" : username(cl));
		cl->cwcacheexerr++;
		if(cl->account)
			{ cl->account->cwcacheexerr++; }
		return 0;
	}

	// Don't check for BISS1 and BISS2 mode 1/E or fake caid (ECM is fake for them)
	// Don't check for BISS2 mode CA (ECM table is always 0x80)
	if(!caid_is_biss(er->caid) && !caid_is_fake(er->caid) && get_odd_even(er) == 0)
	{
		cs_log_dbg(D_CACHEEX, "push received ecm with null odd/even byte from %s", csp ? "csp" : username(cl));
		cl->cwcacheexerr++;
		if(cl->account)
			{ cl->account->cwcacheexerr++; }
		return 0;
	}

	if(!chk_halfCW(er, er->cw))
	{
		log_cacheex_cw(er, "bad half cw");
		cl->cwcacheexerr++;
		if(cl->account)
			{ cl->account->cwcacheexerr++; }
		return 0;
	}

	if((csp && cfg.csp.block_fakecws) || (cl->reader && cl->reader->cacheex.block_fakecws)
			|| (!cl->reader && cl->account && cl->account->cacheex.block_fakecws))
	{
		if(chk_is_fakecw(er->cw))
		{
			cs_log_dbg(D_CACHEEX, "push received fake cw from %s", csp ? "csp" : username(cl));
			cl->cwcacheexerr++;
			if(cl->account)
				{ cl->account->cwcacheexerr++; }
			return 0;
		}
	}

	er->grp |= cl->grp; // ok for mode2 reader too: cl->reader->grp
	er->rc = E_CACHEEX;
	er->cacheex_src = cl;
	er->selected_reader = cl->reader;
	er->client = NULL; // No Owner! So no fallback!

	if(check_client(cl))
	{
		cl->cwcacheexgot++;
		if(cl->account)
			{ cl->account->cwcacheexgot++; }
		first_client->cwcacheexgot++;
	}

	cacheex_add_hitcache(cl, er); // we have to call it before add_cache, because in chk_process we could remove it!
	add_cache(er);
	cacheex_add_stats(cl, er->caid, er->srvid, er->prid, 1);

	cs_writelock(__func__, &ecm_pushed_deleted_lock);
	er->next = ecm_pushed_deleted;
	ecm_pushed_deleted = er;
	cs_writeunlock(__func__, &ecm_pushed_deleted_lock);

	return 1; // NO free, we have to wait cache push out stuff ends.
}