void client_check_status(struct s_client *cl) { if (!cl || cl->kill || !cl->init_done) return; switch (cl->typ) { case 'm': case 'c': // Check clients for exceeding cmaxidle by checking cl->last if (!(cl->ncd_keepalive && (get_module(cl)->listenertype & LIS_NEWCAMD)) && cl->last && cfg.cmaxidle && (time(NULL) - cl->last) > (time_t)cfg.cmaxidle) { add_job(cl, ACTION_CLIENT_IDLE, NULL, 0); } break; case 'r': cardreader_checkhealth(cl, cl->reader); break; case 'p': { struct s_reader *rdr = cl->reader; if (!rdr || !rdr->enable || !rdr->active) //reader is disabled or restarting at this moment break; // execute reader do idle on proxy reader after a certain time (rdr->tcp_ito = inactivitytimeout) // disconnect when no keepalive available if ((rdr->tcp_ito && is_cascading_reader(rdr)) || rdr->typ == R_CCCAM) { time_t now = time(NULL); int32_t time_diff = abs(now - rdr->last_check); if (time_diff > 60 || (time_diff > 30 && rdr->typ == R_CCCAM)) { //check 1x per minute or every 30s for cccam add_job(rdr->client, ACTION_READER_IDLE, NULL, 0); rdr->last_check = now; } } break; } } }
static void cs_waitforcardinit(void) { if (cfg.waitforcards) { cs_log("waiting for local card init"); int32_t card_init_done; do { card_init_done = 1; struct s_reader *rdr; LL_ITER itr = ll_iter_create(configured_readers); while((rdr = ll_iter_next(&itr))) { if (rdr->enable && !is_cascading_reader(rdr) && (rdr->card_status == CARD_NEED_INIT || rdr->card_status == UNKNOWN)) { card_init_done = 0; break; } } if (!card_init_done) cs_sleepms(300); // wait a little bit //alarm(cfg.cmaxidle + cfg.ctimeout / 1000 + 1); } while (!card_init_done && !exit_oscam); if (cfg.waitforcards_extra_delay>0 && !exit_oscam) cs_sleepms(cfg.waitforcards_extra_delay); cs_log("init for all local cards done"); } }
void client_check_status(struct s_client *cl) { if(!cl || cl->kill || !cl->init_done) { return; } switch(cl->typ) { case 'm': case 'c': if((get_module(cl)->listenertype & LIS_CCCAM) && cl->last && (time(NULL) - cl->last) > (time_t)12) { add_job(cl, ACTION_CLIENT_IDLE, NULL, 0); } //Check umaxidle to avoid client is killed for inactivity, it has priority than cmaxidle if(!cl->account->umaxidle) break; // Check user for exceeding umaxidle by checking cl->last if(!(cl->ncd_keepalive && (get_module(cl)->listenertype & LIS_NEWCAMD)) && cl->account->umaxidle>0 && cl->last && (time(NULL) - cl->last) > (time_t)cl->account->umaxidle) { add_job(cl, ACTION_CLIENT_IDLE, NULL, 0); } // Check clients for exceeding cmaxidle by checking cl->last if(!(cl->ncd_keepalive && (get_module(cl)->listenertype & LIS_NEWCAMD)) && cl->last && cl->account->umaxidle==-1 && cfg.cmaxidle && (time(NULL) - cl->last) > (time_t)cfg.cmaxidle) { add_job(cl, ACTION_CLIENT_IDLE, NULL, 0); } break; case 'r': cardreader_checkhealth(cl, cl->reader); break; case 'p': { struct s_reader *rdr = cl->reader; if(!rdr || !rdr->enable || !rdr->active) //reader is disabled or restarting at this moment { break; } // execute reader do idle on proxy reader after a certain time (rdr->tcp_ito = inactivitytimeout) // disconnect when no keepalive available if((rdr->tcp_ito && is_cascading_reader(rdr)) || (rdr->typ == R_CCCAM) || (rdr->typ == R_CAMD35) || (rdr->typ == R_CS378X) || (rdr->typ == R_SCAM) || (rdr->tcp_ito != 0 && rdr->typ == R_RADEGAST)) { time_t now = time(NULL); int32_t time_diff = llabs(now - rdr->last_check); if(time_diff > 60 || (time_diff > 12 && (rdr->typ == R_CCCAM || rdr->typ == R_CAMD35 || rdr->typ == R_CS378X)) || ((time_diff > (rdr->tcp_rto?rdr->tcp_rto:60)) && rdr->typ == R_RADEGAST)) //check 1x per minute or every 10s for cccam/camd35 or reconnecttimeout radegast if 0 defaut 60s { add_job(rdr->client, ACTION_READER_IDLE, NULL, 0); rdr->last_check = now; } } break; } } }
void module_reader_set(struct s_reader *rdr) { int i; if(!is_cascading_reader(rdr)) { return; } for(i = 0; i < CS_MAX_MOD; i++) { struct s_module *module = &modules[i]; if(module->num && module->num == rdr->typ) rdr->ph = *module; } }
int32_t reader_do_emm(struct s_reader * reader, EMM_PACKET *ep) { int32_t i, rc, ecs; unsigned char md5tmp[MD5_DIGEST_LENGTH]; struct timeb tps; struct s_client *cl = reader->client; if(!cl) return 0; cs_ftime(&tps); MD5(ep->emm, ep->emm[2], md5tmp); for (i = ecs = 0; i < CS_EMMCACHESIZE; i++) { if (!memcmp(cl->emmcache[i].emmd5, md5tmp, CS_EMMSTORESIZE)) { cl->emmcache[i].count++; if (reader->cachemm) { if (cl->emmcache[i].count > reader->rewritemm) { ecs = 2; //skip emm } else { ecs = 1; //rewrite emm } } break; } } // Ecs=0 not found in cache // Ecs=1 found in cache, rewrite emm // Ecs=2 skip if ((rc = ecs) < 2) { if (is_cascading_reader(reader)) { rdr_debug_mask(reader, D_READER, "network emm reader"); if (reader->ph.c_send_emm) { rc = reader->ph.c_send_emm(ep); } else { rdr_debug_mask(reader, D_READER, "send_emm() support missing"); rc = 0; } } else { rdr_debug_mask(reader, D_READER, "local emm reader"); rc = cardreader_do_emm(reader, ep); } if (!ecs) i = reader_store_emm(ep->type, md5tmp); } reader_log_emm(reader, ep, i, rc, &tps); return rc; }
void module_reader_set(struct s_reader *rdr) { int i; if (!is_cascading_reader(rdr)) return; for (i = 0; i < CS_MAX_MOD; i++) { struct s_module *module = &modules[i]; if (module->num && module->num == rdr->typ) { rdr->ph = *module; if (rdr->device[0]) rdr->ph.active = 1; } } }
static void reader_log_emm(struct s_reader * reader, EMM_PACKET *ep, int32_t i, int32_t rc, struct timeb *tps) { char *rtxt[] = { "error", is_cascading_reader(reader) ? "sent" : "written", "skipped", "blocked" }; char *typedesc[] = { "unknown", "unique", "shared", "global" }; struct s_client *cl = reader->client; struct timeb tpe; if (reader->logemm & (1 << rc)) { cs_ftime(&tpe); if (!tps) tps = &tpe; rdr_log(reader, "%s emmtype=%s, len=%d, idx=%d, cnt=%d: %s (%ld ms)", username(ep->client), typedesc[cl->emmcache[i].type], ep->emm[2], i, cl->emmcache[i].count, rtxt[rc], 1000 * (tpe.time - tps->time) + tpe.millitm - tps->millitm); } if (rc) { cl->lastemm = time(NULL); led_status_emm_ok(); } #if defined(WEBIF) || defined(LCDSUPPORT) //counting results switch (rc) { case 0: reader->emmerror[ep->type]++; break; case 1: reader->emmwritten[ep->type]++; break; case 2: reader->emmskipped[ep->type]++; break; case 3: reader->emmblocked[ep->type]++; break; } #endif }
void do_emm(struct s_client * client, EMM_PACKET *ep) { char *typtext[]={"unknown", "unique", "shared", "global"}; char tmp[17]; int32_t emmnok=0; struct s_reader *aureader = NULL; cs_ddump_mask(D_EMM, ep->emm, ep->emmlen, "emm:"); int8_t cl_dvbapi = 0, assemble = 0; #ifdef HAVE_DVBAPI cl_dvbapi = streq(cfg.dvbapi_usr, client->account->usr); #endif if (client->account->emm_reassembly > 1 || (client->account->emm_reassembly && cl_dvbapi)) assemble = 1; LL_ITER itr = ll_iter_create(client->aureader_list); while ((aureader = ll_iter_next(&itr))) { if (!aureader->enable) continue; uint16_t caid = b2i(2, ep->caid); uint32_t provid = b2i(4, ep->provid); if (aureader->audisabled) { rdr_debug_mask(aureader, D_EMM, "AU is disabled"); /* we have to write the log for blocked EMM here because this EMM never reach the reader module where the rest of EMM log is done. */ if (aureader->logemm & 0x10) { rdr_log(aureader, "%s emmtype=%s, len=%d, idx=0, cnt=1: audisabled (0 ms)", client->account->usr, typtext[ep->type], ep->emm[2]); } continue; } if (!(aureader->grp & client->grp)) { rdr_debug_mask(aureader, D_EMM, "skip emm, group mismatch"); continue; } //TODO: provider possibly not set yet, this is done in get_emm_type() if (!emm_reader_match(aureader, caid, provid)) continue; struct s_cardsystem *cs = NULL; if (is_cascading_reader(aureader)) { // network reader (R_CAMD35 R_NEWCAMD R_CS378X R_CCCAM) if (!aureader->ph.c_send_emm) // no emm support continue; cs = get_cardsystem_by_caid(caid); if (!cs) { rdr_debug_mask(aureader, D_EMM, "unable to find cardsystem for caid %04X", caid); continue; } } else { // local reader if (aureader->csystem.active) cs=&aureader->csystem; } if (cs && cs->get_emm_type) { if (!cs->get_emm_type(ep, aureader)) { rdr_debug_mask(aureader, D_EMM, "emm skipped, get_emm_type() returns error"); emmnok++; continue; } } if (cs && cs->get_emm_filter) { if (!do_simple_emm_filter(aureader, cs, ep)) { rdr_debug_mask(aureader, D_EMM, "emm skipped, emm_filter() returns invalid"); emmnok++; continue; } } if (cs && cs->do_emm_reassembly) { if (assemble) { if (!cs->do_emm_reassembly(client, ep)) return; } else { rdr_debug_mask(aureader, D_EMM, "processing raw emm"); } } rdr_debug_mask_sensitive(aureader, D_EMM, "emmtype %s. Reader serial {%s}.", typtext[ep->type], cs_hexdump(0, aureader->hexserial, 8, tmp, sizeof(tmp))); rdr_debug_mask_sensitive(aureader, D_EMM, "emm UA/SA: {%s}.", cs_hexdump(0, ep->hexserial, 8, tmp, sizeof(tmp))); client->last = time(NULL); saveemm(aureader, ep); int32_t is_blocked = 0; switch (ep->type) { case UNKNOWN: is_blocked = (aureader->blockemm & EMM_UNKNOWN) == EMM_UNKNOWN; break; case UNIQUE : is_blocked = (aureader->blockemm & EMM_UNIQUE ) == EMM_UNIQUE; break; case SHARED : is_blocked = (aureader->blockemm & EMM_SHARED ) == EMM_SHARED; break; case GLOBAL : is_blocked = (aureader->blockemm & EMM_GLOBAL ) == EMM_GLOBAL; break; } // if not already blocked we check for block by len if (!is_blocked) is_blocked = cs_emmlen_is_blocked( aureader, ep->emm[2] ) ; if (is_blocked != 0) { #ifdef WEBIF aureader->emmblocked[ep->type]++; is_blocked = aureader->emmblocked[ep->type]; #endif /* we have to write the log for blocked EMM here because this EMM never reach the reader module where the rest of EMM log is done. */ if (aureader->logemm & 0x08) { rdr_log(aureader, "%s emmtype=%s, len=%d, idx=0, cnt=%d: blocked (0 ms)", client->account->usr, typtext[ep->type], ep->emm[2], is_blocked); } continue; } client->lastemm = time((time_t*)0); client->emmok++; if (client->account) client->account->emmok++; first_client->emmok++; //Check emmcache early: int32_t i; unsigned char md5tmp[CS_EMMSTORESIZE]; struct s_client *au_cl = aureader->client; MD5(ep->emm, ep->emm[2], md5tmp); ep->client = client; for (i=0; i<CS_EMMCACHESIZE; i++) { if (!memcmp(au_cl->emmcache[i].emmd5, md5tmp, CS_EMMSTORESIZE)) { rdr_debug_mask(aureader, D_EMM, "emm found in cache: count %d rewrite %d", au_cl->emmcache[i].count, aureader->rewritemm); if (aureader->cachemm && (au_cl->emmcache[i].count > aureader->rewritemm)) { reader_log_emm(aureader, ep, i, 2, NULL); return; } break; } } EMM_PACKET *emm_pack; if (cs_malloc(&emm_pack, sizeof(EMM_PACKET))) { rdr_debug_mask(aureader, D_EMM, "emm is being sent to reader"); memcpy(emm_pack, ep, sizeof(EMM_PACKET)); add_job(aureader->client, ACTION_READER_EMM, emm_pack, sizeof(EMM_PACKET)); } } if (emmnok > 0 && emmnok == ll_count(client->aureader_list)) { client->emmnok++; if (client->account) client->account->emmnok++; first_client->emmnok++; } }
void azbox_send_dcw(struct s_client *client, ECM_REQUEST *er) { cs_debug_mask(D_DVBAPI, LOG_PREFIX "send_dcw"); FILE *ecmtxt; if ((ecmtxt = fopen(ECMINFO_FILE, "w"))) { char tmp[25]; if(er->rc <= E_CACHEEX) { fprintf(ecmtxt, "caid: 0x%04X\npid: 0x%04X\nprov: 0x%06X\n", er->caid, er->pid, (uint) er->prid); fprintf(ecmtxt, "reader: %s\n", er->selected_reader->label); if (is_cascading_reader(er->selected_reader)) fprintf(ecmtxt, "from: %s\n", er->selected_reader->device); else fprintf(ecmtxt, "from: local\n"); fprintf(ecmtxt, "protocol: %s\n", reader_get_type_desc(er->selected_reader, 1)); fprintf(ecmtxt, "hops: %d\n", er->selected_reader->currenthops); fprintf(ecmtxt, "ecm time: %.3f\n", (float) client->cwlastresptime/1000); fprintf(ecmtxt, "cw0: %s\n", cs_hexdump(1,demux[0].lastcw[0],8, tmp, sizeof(tmp))); fprintf(ecmtxt, "cw1: %s\n", cs_hexdump(1,demux[0].lastcw[1],8, tmp, sizeof(tmp))); fclose(ecmtxt); ecmtxt = NULL; } else { fprintf(ecmtxt, "ECM information not found\n"); fclose(ecmtxt); } } openxcas_busy = 0; int32_t i; for (i=0; i < MAX_DEMUX; i++) { if (er->rc >= E_NOTFOUND) { cs_debug_mask(D_DVBAPI, "cw not found"); if (demux[i].pidindex==-1) dvbapi_try_next_caid(i); openxcas_stop_filter(openxcas_stream_id, OPENXCAS_FILTER_ECM); openxcas_remove_filter(openxcas_stream_id, OPENXCAS_FILTER_ECM); unsigned char mask[12]; unsigned char comp[12]; memset(&mask, 0x00, sizeof(mask)); memset(&comp, 0x00, sizeof(comp)); mask[0] = 0xfe; comp[0] = 0x80; if (openxcas_add_filter(openxcas_stream_id, OPENXCAS_FILTER_ECM, 0, 0xffff, openxcas_ecm_pid, mask, comp, (void *)azbox_openxcas_ecm_callback) < 0) { cs_log(LOG_PREFIX "unable to add ecm filter (0)"); if (openxcas_add_filter(openxcas_stream_id, OPENXCAS_FILTER_ECM, openxcas_caid, 0xffff, openxcas_ecm_pid, mask, comp, (void *)azbox_openxcas_ecm_callback) < 0) cs_log(LOG_PREFIX "unable to add ecm filter (%04x)", openxcas_caid); else cs_debug_mask(D_DVBAPI, LOG_PREFIX "ecm filter added, pid = %x, caid = %x", openxcas_ecm_pid, openxcas_caid); } else cs_debug_mask(D_DVBAPI, LOG_PREFIX "ecm filter added, pid = %x, caid = %x", openxcas_ecm_pid, 0); if (openxcas_start_filter(openxcas_stream_id, openxcas_seq, OPENXCAS_FILTER_ECM) < 0) cs_log(LOG_PREFIX "unable to start ecm filter"); else cs_debug_mask(D_DVBAPI, LOG_PREFIX "ecm filter started"); return; } } unsigned char nullcw[8]; memset(nullcw, 0, 8); int32_t n; for (n=0;n<2;n++) { if (memcmp(er->cw + (n * 8), demux[0].lastcw[n], 8) && memcmp(er->cw + (n * 8), nullcw, 8)) { memcpy(demux[0].lastcw[n], er->cw + (n * 8), 8); memcpy(openxcas_cw + (n * 8), er->cw + (n * 8), 8); } } if (openxcas_set_key(openxcas_stream_id, openxcas_seq, 0, openxcas_cipher_idx, openxcas_cw, openxcas_cw + 8) != 1) cs_log(LOG_PREFIX "set cw failed"); else cs_ddump_mask(D_DVBAPI, openxcas_cw, 16, LOG_PREFIX "write cws to descrambler"); }