static void camd35_process_ecm(uchar *buf, int buflen) { ECM_REQUEST er; if (!buf || buflen < 23) return; uint16_t ecmlen = (((buf[21] & 0x0f)<< 8) | buf[22])+3; if (ecmlen + 20 > buflen) return; er.ecmlen = ecmlen; er.srvid = b2i(2, buf+ 8); er.caid = b2i(2, buf+10); er.prid = b2i(4, buf+12); memcpy(er.ecm, buf + 20, er.ecmlen); if (!ProcessECM(er.caid,er.ecm,er.cw)) { er.rc = E_FOUND; } else er.rc = E_NOTFOUND; if (er.rc == E_NOTFOUND) { buf[0] = 0x08; buf[1] = 2; memset(buf + 20, 0, buf[1]); buf[22] = er.rc; //put rc in byte 22 - hopefully don't break legacy camd3 } else { if (buf[0]==3) memmove(buf + 20 + 16, buf + 20 + buf[1], 0x34); buf[0]++; buf[1] = 16; memcpy(buf+20, er.cw, buf[1]); } camd35_send(buf, 0); }
/** * request remote id */ void camd35_cacheex_push_request_remote_id(struct s_client *cl) { uint8_t rbuf[32];//minimal size memset(rbuf, 0, sizeof(rbuf)); rbuf[0] = 0x3d; rbuf[1] = 12; rbuf[2] = 0; memcpy(rbuf + 20, camd35_node_id, 8); cs_log_dbg(D_CACHEEX, "cacheex: sending id request to %s", username(cl)); camd35_send(cl, rbuf, 12); //send adds +20 }
/** * send own id */ void camd35_cacheex_push_send_own_id(struct s_client *cl, uint8_t *mbuf) { uint8_t rbuf[32]; //minimal size if(!cl->crypted) { return; } cs_log_dbg(D_CACHEEX, "cacheex: received id request from node %" PRIu64 "X %s", cacheex_node_id(mbuf + 20), username(cl)); memset(rbuf, 0, sizeof(rbuf)); rbuf[0] = 0x3e; rbuf[1] = 12; rbuf[2] = 0; memcpy(rbuf + 20, camd35_node_id, 8); cs_log_dbg(D_CACHEEX, "cacheex: sending own id %" PRIu64 "X request %s", cacheex_node_id(camd35_node_id), username(cl)); camd35_send(cl, rbuf, 12); //send adds +20 }
static void camd35_process_ecm(uchar *buf, int buflen){ ECM_REQUEST er; if (!buf || buflen < 23) return; uint16_t ecmlen = (((buf[21] & 0x0f)<< 8) | buf[22])+3; if (ecmlen + 20 > buflen) return; er.ecmlen = ecmlen; er.srvid = b2i(2, buf+ 8); er.caid = b2i(2, buf+10); er.prid = b2i(4, buf+12); er.rc = buf[3]; ProcessECM(er.caid,buf + 20,er.cw); if (er.rc == E_STOPPED) { buf[0] = 0x08; buf[1] = 2; buf[20] = 0; /* * the second Databyte should be forseen for a sleeptime in minutes * whoever knows the camd3 protocol related to CMD08 - please help! * on tests this don't work with native camd3 */ buf[21] = 0; } if ((er.rc == E_NOTFOUND) || (er.rc == E_INVALID)) { buf[0] = 0x08; buf[1] = 2; memset(buf + 20, 0, buf[1]); buf[22] = er.rc; //put rc in byte 22 - hopefully don't break legacy camd3 } else { if (buf[0]==3) memmove(buf + 20 + 16, buf + 20 + buf[1], 0x34); buf[0]++; buf[1] = 16; memcpy(buf+20, er.cw, buf[1]); } camd35_send(buf, 0); }
static void camd35_process_ecm(uchar *buf, int buflen){ ECM_REQUEST er; if (!buf || buflen < 23) return; uint16_t ecmlen = (((buf[21] & 0x0f)<< 8) | buf[22])+3; if (ecmlen + 20 > buflen) return; er.ecmlen = ecmlen; er.srvid = b2i(2, buf+ 8); er.caid = b2i(2, buf+10); er.prid = b2i(4, buf+12); memcpy(er.ecm, buf + 20, er.ecmlen); // ======================================================================== // HANDLE ECM HERE! Following 5 lines are just here for testing! // ======================================================================== cs_log("SRVID: %04X", er.srvid); cs_log("CAID: %04X", er.caid); cs_log("PRID: %04X", er.prid); er.rc = E_FOUND; memset(&er.cw, 0x02, sizeof(er.cw)); if (er.rc == E_NOTFOUND){ buf[0] = 0x08; buf[1] = 2; memset(buf + 20, 0, buf[1]); buf[22] = er.rc; //put rc in byte 22 - hopefully don't break legacy camd3 } else { if (buf[0]==3) memmove(buf + 20 + 16, buf + 20 + buf[1], 0x34); buf[0]++; buf[1] = 16; memcpy(buf+20, er.cw, buf[1]); } camd35_send(buf, 0); }
static void camd35_process_ecm(uchar *buf, int buflen) { ECM_REQUEST er; uint16_t ecmlen = 0; if(!buf || buflen < 23) { return; } ecmlen = (((buf[21] & 0x0f) << 8) | buf[22]) + 3; if(ecmlen + 20 > buflen) { return; } memset(&er, 0, sizeof(ECM_REQUEST)); er.rc = E_UNHANDLED; er.ecmlen = ecmlen; er.srvid = b2i(2, buf + 8); er.caid = b2i(2, buf + 10); er.prid = b2i(4, buf + 12); cs_log_debug("ProcessECM CAID: %X", er.caid); cs_log_hexdump("ProcessECM: ", buf+20, ecmlen); if(ProcessECM(er.caid,buf+20,er.cw)) { er.rc = E_NOTFOUND; cs_log_debug("CW not found"); } else { er.rc = E_FOUND; cs_log_hexdump("Found CW: ", er.cw, 16); } if((er.rc == E_NOTFOUND || (er.rc == E_INVALID)) && !suppresscmd08) { buf[0] = 0x08; buf[1] = 2; memset(buf + 20, 0, buf[1]); buf[22] = er.rc; //put rc in byte 22 - hopefully don't break legacy camd3 } else if(er.rc == E_STOPPED) { buf[0] = 0x08; buf[1] = 2; buf[20] = 0; /* * the second Databyte should be forseen for a sleeptime in minutes * whoever knows the camd3 protocol related to CMD08 - please help! * on tests this don't work with native camd3 */ buf[21] = 0; cs_log("client stop request send"); } else { // Send CW if((er.rc < E_NOTFOUND) || (er.rc == E_FAKE)) { if(buf[0] == 3) { memmove(buf + 20 + 16, buf + 20 + buf[1], 0x34); } buf[0]++; buf[1] = 16; memcpy(buf + 20, er.cw, buf[1]); } else { // Send old CMD44 to prevent cascading problems with older mpcs/oscam versions buf[0] = 0x44; buf[1] = 0; } } camd35_send(buf, 0); }
static int32_t camd35_cacheex_push_out(struct s_client *cl, struct ecm_request_t *er) { int8_t rc = (er->rc < E_NOTFOUND) ? E_FOUND : er->rc; if(rc != E_FOUND && rc != E_UNHANDLED) { return -1; } //Maybe later we could support other rcs //E_FOUND : we have the CW, //E_UNHANDLED : incoming ECM request if(cl->reader) { if(!camd35_tcp_connect(cl)) { cs_log_dbg(D_CACHEEX, "cacheex: not connected %s -> no push", username(cl)); return (-1); } } uint32_t size = sizeof(er->ecmd5) + sizeof(er->csp_hash) + sizeof(er->cw) + sizeof(uint8_t) + (ll_count(er->csp_lastnodes) + 1) * 8; unsigned char *buf; if(!cs_malloc(&buf, size + 20)) //camd35_send() adds +20 { return -1; } buf[0] = 0x3f; //New Command: Cache-push buf[1] = size & 0xff; buf[2] = size >> 8; buf[3] = rc; i2b_buf(2, er->srvid, buf + 8); i2b_buf(2, er->caid, buf + 10); i2b_buf(4, er->prid, buf + 12); //i2b_buf(2, er->idx, buf + 16); // Not relevant...? if(er->cwc_cycletime && er->cwc_next_cw_cycle < 2) { buf[18] = er->cwc_cycletime; // contains cwc stage3 cycletime if(er->cwc_next_cw_cycle == 1) { buf[18] = (buf[18] | 0x80); } // set bit 8 to high if(cl->typ == 'c' && cl->account && cl->account->cacheex.mode) { cl->account->cwc_info++; } else if((cl->typ == 'p' || cl->typ == 'r') && (cl->reader && cl->reader->cacheex.mode)) { cl->cwc_info++; } cs_log_dbg(D_CWC, "CWC (CE) push to %s cycletime: %isek - nextcwcycle: CW%i for %04X@%06X:%04X", username(cl), er->cwc_cycletime, er->cwc_next_cw_cycle, er->caid, er->prid, er->srvid); } buf[19] = er->ecm[0] != 0x80 && er->ecm[0] != 0x81 ? 0 : er->ecm[0]; uint8_t *ofs = buf + 20; //write oscam ecmd5: memcpy(ofs, er->ecmd5, sizeof(er->ecmd5)); //16 ofs += sizeof(er->ecmd5); //write csp hashcode: i2b_buf(4, htonl(er->csp_hash), ofs); ofs += 4; //write cw: memcpy(ofs, er->cw, sizeof(er->cw)); //16 ofs += sizeof(er->cw); //write node count: *ofs = ll_count(er->csp_lastnodes) + 1; ofs++; //write own node: memcpy(ofs, camd35_node_id, 8); ofs += 8; //write other nodes: LL_LOCKITER *li = ll_li_create(er->csp_lastnodes, 0); uint8_t *node; while((node = ll_li_next(li))) { memcpy(ofs, node, 8); ofs += 8; } ll_li_destroy(li); int32_t res = camd35_send(cl, buf, size); NULLFREE(buf); return res; }