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; } 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_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; } } if(null == 0 || chk_is_null_CW(er->cw)) { 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; } if(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. }
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. }