diff -Nru oscam-1.20-10232~r10004/debian/changelog oscam-1.20-10238~r10010/debian/changelog --- oscam-1.20-10232~r10004/debian/changelog 2014-11-18 11:40:43.000000000 +0000 +++ oscam-1.20-10238~r10010/debian/changelog 2014-11-19 19:38:50.000000000 +0000 @@ -1,77 +1,50 @@ -oscam (1.20-10232~r10004-trusty) trusty; urgency=medium +oscam (1.20-10238~r10010-trusty) trusty; urgency=medium - * [r10004] - - - DVBAPI: Due to wrong parsing of PMT channels couldnt be decoded (Example: Eurosport SD on 23.5 using 0100:00006a) - - - - * [r10003] - - Added documentation for new parameter 'nds_swap_cw'. - + * [r10010] - * [r10002] + - Fix for emm on betatunnel caids (Tnx Gismo2004 for providing patch!) - - CCcam: dont touch emmcounters since oscam-emm will do that! (tnx Gismo2004 for this find!) + * [r10009] - * [r10001] + - Tryfix dvbapi to let the fake ecm created for BISS and fake ecmpids pass the now more strict cache check - - Bufferoverflow protection + * [r10008] - * [r10000] + Fix compilation error without cacchex module in prev commit. - Patch by Ultra47 - The patch includes following things: - - better Graph.svg - - New: Uptime in Footer - - New: more Informationen in Sysinfo (cached Memory, processes, swap memory, free men inkl. buffered & cached) - - failban Patch => thx to hook - - pollindicatorfix => thx to hook - - fix for ECM History if polling disabled + * [r10007] + Improved wait_until_ctimeout. + Don't use/save hitcache if max_hit_time=0. - * [r9999] - - Move emmcache from client to reader - - Dvbapi refreshes every 30 seconds emmfilters to catch rotating cardserials delivered by networkreaders like camd35 - - On FTA channels emmfilters are started for all caids specified for a networkreader - - If networkreader asks for specific au caid only that one is used (instead of all known caids for that reader) - + * [r10006] + Fix half cw check for normal/cacheex-1 readers. + Fix msgs, now shown with cacheex debug log. - * [r9998] - smartreader protocol + * [r10005] - Changed OK ERROR define, to avoid conflict with the opposed defined OK ERROR in reader-common.h + Removed nds_swap_cw paramter and swap cw code. Now wrong half cws are dropped. + Removed cwc-light, now checks for half cws are done in oscam core. + Add check for odd/even byte for all ecm's. Ecm's with null odd/even byte are dropped. + Some small fixs. - * [r9997] - - WebIf: Patch by Ultra47 - - Solution for different colors of Oscamlogo - - - * [r9996] - - Improvements in #9994. - + * [r10004] - * [r9995] + - DVBAPI: Due to wrong parsing of PMT channels couldnt be decoded (Example: Eurosport SD on 23.5 using 0100:00006a) - Use better parameter's name for #9994: - nds_swapp_cw -> nds_swap_cw - -- Andrey Pavlenko Tue, 18 Nov 2014 14:40:42 +0300 + -- Andrey Pavlenko Wed, 19 Nov 2014 22:38:49 +0300 diff -Nru oscam-1.20-10232~r10004/globals.h oscam-1.20-10238~r10010/globals.h --- oscam-1.20-10232~r10004/globals.h 2014-11-18 11:40:37.000000000 +0000 +++ oscam-1.20-10238~r10010/globals.h 2014-11-19 19:38:43.000000000 +0000 @@ -1858,7 +1858,6 @@ #endif int32_t max_cache_time; //seconds ecms are stored in ecmcwcache int32_t max_hitcache_time; //seconds hits are stored in cspec_hitcache (to detect dyn wait_time) - int8_t nds_swap_cw; //0: no swapp cw if odd/even byte is not correct; 1: swapp cw to match odd/even byte int8_t block_same_ip; //0=allow all, 1=block client requests to reader with same ip (default=1) int8_t block_same_name; //0=allow all, 1=block client requests to reader with same name (default=1) diff -Nru oscam-1.20-10232~r10004/module-cacheex.c oscam-1.20-10238~r10010/module-cacheex.c --- oscam-1.20-10232~r10004/module-cacheex.c 2014-11-18 11:40:37.000000000 +0000 +++ oscam-1.20-10238~r10010/module-cacheex.c 2014-11-19 19:38:43.000000000 +0000 @@ -457,6 +457,26 @@ return 0; } + + if(get_odd_even(er)==0){ + cs_debug_mask(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; + } + + er->grp |= cl->grp; //ok for mode2 reader too: cl->reader->grp er->rc = E_CACHEEX; er->cacheex_src = cl; @@ -497,6 +517,22 @@ { free_push_in_ecm(er); } } + +void log_cacheex_cw(ECM_REQUEST *er, char *reason){ + uint8_t *data; + uchar remotenodeid[16]; + data = ll_last_element(er->csp_lastnodes); + if(data) + { + memcpy(remotenodeid, data, 8); + } + + char buf_ecm[109]; + format_ecm(er, buf_ecm, 109); + cs_debug_mask(D_CACHEEX,"got pushed ecm [%s]: %s - odd/even 0x%x - CSP cw: %s - pushed from %s, at hop %d, origin node-id %" PRIu64 "X", + reason, buf_ecm, er->ecm[0], (checkECMD5(er)?"NO":"YES"), er->from_csp ? "csp" : username((er->cacheex_src?er->cacheex_src:er->client)), ll_count(er->csp_lastnodes), er->csp_lastnodes ? cacheex_node_id(remotenodeid): 0); +} + //Format: //caid:prov:srvid:pid:chid:ecmlen=caid:prov:srvid:pid:chid:ecmlen[,validfrom,validto] //validfrom: default=-2000 diff -Nru oscam-1.20-10232~r10004/module-cacheex.h oscam-1.20-10238~r10010/module-cacheex.h --- oscam-1.20-10232~r10004/module-cacheex.h 2014-11-18 11:40:37.000000000 +0000 +++ oscam-1.20-10238~r10010/module-cacheex.h 2014-11-19 19:38:43.000000000 +0000 @@ -16,6 +16,7 @@ extern void cacheex_add_to_cache(struct s_client *cl, ECM_REQUEST *er); extern void cacheex_add_to_cache_from_csp(struct s_client *cl, ECM_REQUEST *er); #ifdef CS_CACHEEX +void log_cacheex_cw(ECM_REQUEST *er, char *s); extern void cacheex_init(void); extern void cacheex_clear_account_stats(struct s_auth *account); extern void cacheex_clear_client_stats(struct s_client *client); diff -Nru oscam-1.20-10232~r10004/module-cw-cycle-check.c oscam-1.20-10238~r10010/module-cw-cycle-check.c --- oscam-1.20-10232~r10004/module-cw-cycle-check.c 2014-11-18 11:40:37.000000000 +0000 +++ oscam-1.20-10238~r10010/module-cw-cycle-check.c 2014-11-19 19:38:43.000000000 +0000 @@ -693,6 +693,8 @@ { return 2; } if(!(chk_ctab_ex(er->caid, &cfg.cwcycle_check_caidtab))) // dont check caid not in list { return 1; } // no match leave the check + if(is_halfCW_er(er)) + { return 1; } // half cw cycle, checks are done in ecm-handler memcpy(er->cw, cw, 16); char er_ecmf[ECM_FMT_LEN]; @@ -714,53 +716,6 @@ cs_debug_mask(D_CWC | D_TRACE, "cyclecheck EA: %s rc: %i reader: %s", er_ecmf, rc, c_reader); - if(er->caid == 0x09C4 || er->caid == 0x098C || er->caid == 0x09CD || er->caid == 0x0963) // CWC light for NDS - { - switch(checkvalidCW(er, c_reader, 1)) - { - case 0: // NDS CWCYCLE NOK - count_nok(client); - snprintf(er->cwc_msg_log, sizeof(er->cwc_msg_log), "cwc NDS NOK"); - if(cfg.onbadcycle > 0) // ignore ECM Request - { - cs_log("cyclecheck [Bad CW Cycle] for: %s %s from: %s -> drop cw (ECM Answer)", user, er_ecmf, c_reader); //D_CWC| D_TRACE - return 0; - } - else // only logging - { - cs_log("cyclecheck [Bad CW Cycle] for: %s %s from: %s -> do nothing", user, er_ecmf, c_reader);//D_CWC| D_TRACE - return 1; - } - - case 1: // NDS Cycle OK - count_ok(client); - snprintf(er->cwc_msg_log, sizeof(er->cwc_msg_log), "cwc NDS OK"); - return 1; - - case 2: // CycleCheck NDS Swapp drop or ignored - if(cfg.onbadcycle == 2) - { - count_nok(client); - snprintf(er->cwc_msg_log, sizeof(er->cwc_msg_log), "cwc NDS Swapp"); - cs_log("cyclecheck [Swapped NDS CW] for: %s %s from: %s -> drop cw", user, er_ecmf, c_reader);//D_CWC| D_TRACE - return 0; - } - else - { - count_ign(client); - snprintf(er->cwc_msg_log, sizeof(er->cwc_msg_log), "cwc NDS Swapp"); - cs_log("cyclecheck [Swapped NDS CW] for: %s %s from: %s -> pass through", user, er_ecmf, c_reader);//D_CWC| D_TRACE - return 1; - } - - case 5: //answer from fixed Fallbackreader with Bad Cycle - count_nok(client); - snprintf(er->cwc_msg_log, sizeof(er->cwc_msg_log), "cwc NDS NOK but IGN (fixed FB)"); - cs_log("cyclecheck [Bad CW Cycle] for: %s %s from: %s -> But Ignored because of answer from Fixed Fallback Reader", user, er_ecmf, c_reader); - return 1; - } - } - switch(checkcwcycle_int(er, er_ecmf, user, cw, c_reader, cycletime_fr, next_cw_cycle_fr)) { diff -Nru oscam-1.20-10232~r10004/module-dvbapi.c oscam-1.20-10238~r10010/module-dvbapi.c --- oscam-1.20-10232~r10004/module-dvbapi.c 2014-11-18 11:40:37.000000000 +0000 +++ oscam-1.20-10238~r10010/module-dvbapi.c 2014-11-19 19:38:43.000000000 +0000 @@ -975,7 +975,6 @@ LL_ITER itr = ll_iter_create(cl->aureader_list); while((rdr = ll_iter_next(&itr))) { - if(!rdr->client || rdr->audisabled != 0 || !rdr->enable || (!is_network_reader(rdr) && rdr->card_status != CARD_INSERTED)) { continue; } @@ -985,15 +984,17 @@ { caid = ncaid = demux[demux_index].EMMpids[c].CAID; if(!caid) continue; - if(emm_reader_match(rdr, caid, 0)) + + if(chk_is_betatunnel_caid(caid) == 2) + { + ncaid = tunemm_caid_map(FROM_TO, caid, demux[demux_index].program_number); + } + + if (emm_reader_match(rdr, caid, 0) || emm_reader_match(rdr, ncaid, 0)) { cs = get_cardsystem_by_caid(caid); if(cs) { - if(chk_is_betatunnel_caid(caid) == 1) - { - ncaid = tunemm_caid_map(TO_FROM, caid, demux[demux_index].program_number); - } if(caid != ncaid && dvbapi_find_emmpid(demux_index, EMM_UNIQUE | EMM_SHARED | EMM_GLOBAL, ncaid, 0) > -1) { cs->get_tunemm_filter(rdr, &dmx_filter, &filter_count); @@ -1530,6 +1531,7 @@ { int32_t j, n; er->ecmlen = 5; + er->ecm[0] = 0x80; // to pass the cache check it must be 0x80 or 0x81 er->ecm[1] = 0x00; er->ecm[2] = 0x02; i2b_buf(2, er->srvid, er->ecm + 3); diff -Nru oscam-1.20-10232~r10004/oscam-cache.c oscam-1.20-10238~r10010/oscam-cache.c --- oscam-1.20-10232~r10004/oscam-cache.c 2014-11-18 11:40:37.000000000 +0000 +++ oscam-1.20-10238~r10010/oscam-cache.c 2014-11-19 19:38:43.000000000 +0000 @@ -118,24 +118,26 @@ CW *get_first_cw(ECMHASH *ecmhash, ECM_REQUEST *er){ if(!ecmhash) return NULL; - if(er->caid >> 8 == 0x09 && !cfg.nds_swap_cw){ - node *j; - CW *cw; - - j = get_first_node_list(&ecmhash->ll_cw); - while (j) { - cw = get_data_from_node(j); - if(cw && cw->odd_even==get_odd_even(er)){ - return cw; - } - j = j->next; - } + node *j; + CW *cw; + + j = get_first_node_list(&ecmhash->ll_cw); + while (j) { + cw = get_data_from_node(j); - return NULL; + if(cw + && cw->odd_even==get_odd_even(er) +#ifdef CW_CYCLE_CHECK + && !cw->got_bad_cwc +#endif + ){ + return cw; + } - }else{ - return get_first_elem_list(&ecmhash->ll_cw); + j = j->next; } + + return NULL; } int compare_csp_hash(const void *arg, const void *obj){ @@ -216,6 +218,12 @@ }else{ cs_debug_mask(D_CWC, "cyclecheck [BAD CW Cycle] from Int. Cache detected.. {client %s, caid %04X, srvid %04X} [check_cache] -> skip cache answer", (cl ? cl->account->usr : "-"), er->caid, er->srvid); cw->got_bad_cwc = 1; // no need to check it again + +#ifdef CS_CACHEEX + if(er->cacheex_src){ + log_cacheex_cw(er, "bad CWC cw"); + } +#endif pthread_rwlock_unlock(&cache_lock); return NULL; } @@ -243,8 +251,6 @@ void add_cache(ECM_REQUEST *er){ if(!er->csp_hash) return; - if(chk_is_null_CW(er->cw)) return; - if(!chk_NDS_valid_CW(er)) return; ECMHASH *result = NULL; CW *cw = NULL; @@ -522,6 +528,8 @@ void add_hitcache(struct s_client *cl, ECM_REQUEST *er) { + if (!cfg.max_hitcache_time) //we don't want check/save hitcache + return; if (!cfg.cacheex_wait_timetab.n) return; uint32_t cacheex_wait_time = get_cacheex_wait_time(er,NULL); diff -Nru oscam-1.20-10232~r10004/oscam-chk.c oscam-1.20-10238~r10010/oscam-chk.c --- oscam-1.20-10232~r10004/oscam-chk.c 2014-11-18 11:40:37.000000000 +0000 +++ oscam-1.20-10238~r10010/oscam-chk.c 2014-11-19 19:38:43.000000000 +0000 @@ -982,25 +982,49 @@ } + /** - * Check for wrong swapped NDS CWs + * Check for ecm request that expects half cw format **/ -int8_t chk_NDS_valid_CW(ECM_REQUEST *er) +int8_t is_halfCW_er(ECM_REQUEST *er) { - if(er->caid >> 8 == 0x09 && er->cw && er->rc < E_NOTFOUND && !cfg.nds_swap_cw && (!checkCWpart(er->cw, 0) || !checkCWpart(er->cw, 1))){ + if( + er->caid >> 8 == 0x09 + && + (er->caid == 0x09C4 || er->caid == 0x098C || er->caid == 0x0963 || er->caid == 0x09CD || er->caid == 0x0919 || er->caid == 0x093B) + ) + return 1; + + return 0; +} + +/** + * Check for wrong half CWs + **/ +int8_t chk_halfCW(ECM_REQUEST *er, uchar *cw) +{ + if(is_halfCW_er(er) && cw){ + + int8_t part1 = checkCWpart(cw, 0); + int8_t part2 = checkCWpart(cw, 1); + + //check for correct half cw format + if(part1 && part2){ + return 0; + } + + //check for correct cw position if( - (get_odd_even(er) == 0x80 && checkCWpart(er->cw, 0) && !checkCWpart(er->cw, 1)) //xxxxxxxx00000000 + (get_odd_even(er) == 0x80 && part1 && !part2) //xxxxxxxx00000000 || - (get_odd_even(er) == 0x81 && !checkCWpart(er->cw, 0) && checkCWpart(er->cw, 1)) //00000000xxxxxxxx + (get_odd_even(er) == 0x81 && !part1 && part2) //00000000xxxxxxxx ) { return 1; } - else - { - return 0; //not correct swapped cw's - } + + return 0; //not correct swapped cw }else return 1; diff -Nru oscam-1.20-10232~r10004/oscam-chk.h oscam-1.20-10238~r10010/oscam-chk.h --- oscam-1.20-10232~r10004/oscam-chk.h 2014-11-18 11:40:37.000000000 +0000 +++ oscam-1.20-10238~r10010/oscam-chk.h 2014-11-19 19:38:43.000000000 +0000 @@ -31,7 +31,8 @@ int32_t chk_caid_rdr(struct s_reader *rdr, uint16_t caid); int32_t chk_bcaid(ECM_REQUEST *er, CAIDTAB *ctab); int32_t chk_is_null_CW(uchar cw[]); -int8_t chk_NDS_valid_CW(ECM_REQUEST *er); +int8_t is_halfCW_er(ECM_REQUEST *er); +int8_t chk_halfCW(ECM_REQUEST *er, uchar *cw); int32_t chk_is_null_nodeid(uint8_t node_id[], uint8_t len); bool check_client(struct s_client *cl); diff -Nru oscam-1.20-10232~r10004/oscam-config-global.c oscam-1.20-10238~r10010/oscam-config-global.c --- oscam-1.20-10232~r10004/oscam-config-global.c 2014-11-18 11:40:37.000000000 +0000 +++ oscam-1.20-10238~r10010/oscam-config-global.c 2014-11-19 19:38:43.000000000 +0000 @@ -316,7 +316,6 @@ DEF_OPT_STR("mailfile" , OFS(mailfile), NULL), DEF_OPT_STR("cwlogdir" , OFS(cwlogdir), NULL), DEF_OPT_STR("emmlogdir" , OFS(emmlogdir), NULL), - DEF_OPT_INT8("nds_swap_cw" , OFS(nds_swap_cw), 0), #ifdef WITH_LB DEF_OPT_INT32("lb_mode" , OFS(lb_mode), DEFAULT_LB_MODE), DEF_OPT_INT32("lb_save" , OFS(lb_save), 0), diff -Nru oscam-1.20-10232~r10004/oscam-ecm.c oscam-1.20-10238~r10010/oscam-ecm.c --- oscam-1.20-10232~r10004/oscam-ecm.c 2014-11-18 11:40:37.000000000 +0000 +++ oscam-1.20-10238~r10010/oscam-ecm.c 2014-11-19 19:38:43.000000000 +0000 @@ -80,22 +80,18 @@ cs_debug_mask(D_LB, "{client %s, caid %04X, prid %06X, srvid %04X} cacheex timeout! ", (check_client(er->client) ? er->client->account->usr : "-"), er->caid, er->prid, er->srvid); //check if "normal" readers selected, if not send NOT FOUND! - if( !cfg.wait_until_ctimeout - && - ( - (!er->from_cacheex1_client && (er->reader_count + er->fallback_reader_count - er->cacheex_reader_count) <= 0) //not-cacheex-1 client and no normal readers available (or filtered by LB) - || - (er->from_cacheex1_client && !er->reader_nocacheex_avail) //cacheex1-client and no normal readers available for others clients - ) - ) + //cacheex1-client (having always no "normal" reader), or not-cacheex-1 client with no normal readers available (or filtered by LB) + if( (er->reader_count + er->fallback_reader_count - er->cacheex_reader_count) <= 0 ) { - er->rc = E_NOTFOUND; - er->selected_reader = NULL; - er->rcEx = 0; - - cs_debug_mask(D_LB, "{client %s, caid %04X, prid %06X, srvid %04X} cacheex timeout: NO \"normal\" readers... not_found! ", (check_client(er->client) ? er->client->account->usr : "-"), er->caid, er->prid, er->srvid); - send_dcw(er->client, er); - return; + if(!cfg.wait_until_ctimeout){ + er->rc = E_NOTFOUND; + er->selected_reader = NULL; + er->rcEx = 0; + + cs_debug_mask(D_LB, "{client %s, caid %04X, prid %06X, srvid %04X} cacheex timeout: NO \"normal\" readers... not_found! ", (check_client(er->client) ? er->client->account->usr : "-"), er->caid, er->prid, er->srvid); + send_dcw(er->client, er); + return; + } } else { @@ -1176,20 +1172,6 @@ er->rc = E_FOUND; } - if (er->caid >> 8 == 0x09 && er->cw && er->rc < E_NOTFOUND){ - if (er->ecm[0] == 0x80 && checkCWpart(er->cw, 1) && !checkCWpart(er->cw, 0)){ // wrong: even ecm should only have even part of cw used - cs_debug_mask(D_TRACE,"NDS videoguard controlword swapped"); - memcpy(er->cw, er->cw + 8, 8); // move card cw answer to right part! - memset(er->cw+8,0,8); // blanc old position - } - - if (er->ecm[0] == 0x81 && checkCWpart(er->cw, 0) && !checkCWpart(er->cw, 1)){ // wrong: odd ecm should only have odd part of cw used - cs_debug_mask(D_TRACE,"NDS videoguard controlword swapped"); - memcpy(er->cw+8, er->cw, 8); // move card cw answer to right part! - memset(er->cw,0,8); // blanc old position - } - } - if(cfg.double_check && er->rc == E_FOUND && er->selected_reader && is_double_check_caid(er)) { if(er->checked == 0) //First CW, save it and wait for next one @@ -1427,10 +1409,6 @@ if(!ert) { return; } - //cache update - if(ea && ea->rc < E_NOTFOUND) - add_cache_from_reader(ert, eardr, ert->csp_hash, ert->ecmd5, ea->cw, ert->caid, ert->prid, ert->srvid ); - //ecm request already answered! if(ert->rc < E_99) { @@ -1462,7 +1440,7 @@ //check if check_cw enabled if(eardr && cacheex_reader(eardr)){ //IF mode-1 reader CWCHECK check_cw = get_cwcheck(ert); - if(check_cw.counter>1) //if answer from cacheex-1 reader, and we have to check cw counter, not send answer to client! thread check_cache will send answer to client! + if(check_cw.counter>1) //if answer from cacheex-1 reader, and we have to check cw counter, not send answer to client! thread check_cache will check counter and send answer to client! return; } #endif @@ -1495,10 +1473,8 @@ { #ifdef CS_CACHEEX - /* if not wait_time expired and wait_time due to hitcache, or ecm is cacheex-1 and there are other normal readers for check INT cache, we have to wait wait_time expires before send rc to client! - * (Before cacheex_wait_time_expired, this answered reader is obviously a cacheex mode 1 reader!) - */ - if((!ert->cacheex_wait_time_expired && ert->cacheex_hitcache) || (ert->from_cacheex1_client && ert->reader_nocacheex_avail)) + // if not wait_time expired and wait_time due to hitcache (or awtime>0), we have to wait cacheex before call readers. This one is (should be) answer by ex1-readers + if(cacheex_reader(eardr) && !ert->cacheex_wait_time_expired && ert->cacheex_hitcache) { return; } #endif @@ -1555,7 +1531,11 @@ } } - if(!reader_left) // no more matching reader + if(!reader_left // no more matching reader +#ifdef CS_CACHEEX + && !cfg.wait_until_ctimeout +#endif + ) { ert->rc = E_NOTFOUND; } //so we set the return code break; @@ -1678,7 +1658,6 @@ return 0; } - //SPECIAL CHECKs for rc if(rc < E_NOTFOUND && cw && chk_is_null_CW(cw)) //if cw=0 by anticascading { @@ -1686,7 +1665,7 @@ cs_debug_mask(D_TRACE | D_LB, "WARNING: reader %s send fake cw, set rc=E_NOTFOUND!", reader ? reader->label : "-"); } - if(!chk_NDS_valid_CW(er)){ + if(rc < E_NOTFOUND && cw && !chk_halfCW(er,cw)){ rc = E_NOTFOUND; cs_debug_mask(D_TRACE | D_LB, "WARNING: reader %s send wrong swapped NDS cw, set rc=E_NOTFOUND!", reader ? reader->label : "-"); } @@ -1788,7 +1767,12 @@ if(!ea->is_pending) //not for pending ea - only once for ea { - send_reader_stat(reader, er, ea, ea->rc); //send stats for LB + //cache update + if(ea && ea->rc < E_NOTFOUND && ea->cw) + add_cache_from_reader(er, reader, er->csp_hash, er->ecmd5, ea->cw, er->caid, er->prid, er->srvid ); + + //readers stats for LB + send_reader_stat(reader, er, ea, ea->rc); //reader checks char ecmd5[17 * 3]; @@ -2269,6 +2253,11 @@ } } + //cheks for odd/even byte + if(get_odd_even(er)==0){ + cs_debug_mask(D_TRACE, "warning: ecm with null odd/even byte from %s", (check_client(er->client)?er->client->account->usr:"-")); + er->rc = E_INVALID; + } //not continue, send rc to client if(er->rc < E_UNHANDLED)