static void camd35_request_emm(void) { uchar mbuf[1024]; uint16_t au_caid = 0x0500; memset(mbuf, 0, sizeof(mbuf)); mbuf[2] = mbuf[3] = 0xff; // must not be zero i2b_buf(4, 0x00030B00, &mbuf[12]); mbuf[0] = 5; mbuf[1] = 111; if(au_caid) { mbuf[39] = 1; // no. caids mbuf[20] = au_caid >> 8; // caid's (max 8) mbuf[21] = au_caid & 0xff; mbuf[47] = 0; mbuf[128] = 1; //EMM_GLOBAL mbuf[129] = 0; //EMM_SHARED mbuf[130] = 0; //EMM_UNIQUE } else // disable emm { mbuf[20] = mbuf[39] = mbuf[40] = mbuf[47] = mbuf[49] = 1; }
static int32_t __camd35_send(struct s_client *cl, uchar *buf, int32_t buflen, int answer_awaited) { int32_t l; unsigned char rbuf[REQ_SIZE + 15 + 4], *sbuf = rbuf + 4; if(!cl->udp_fd || !cl->crypted) { return (-1); } //exit if no fd or aes key not set! //Fix ECM len > 255 if(buflen <= 0) { buflen = ((buf[0] == 0) ? (((buf[21] & 0x0f) << 8) | buf[22]) + 3 : buf[1]); } l = 20 + (((buf[0] == 3) || (buf[0] == 4)) ? 0x34 : 0) + buflen; memcpy(rbuf, cl->ucrc, 4); memcpy(sbuf, buf, l); memset(sbuf + l, 0xff, 15); // set unused space to 0xff for newer camd3's i2b_buf(4, crc32(0L, sbuf + 20, buflen), sbuf + 4); l = boundary(4, l); cs_log_dump_dbg(cl->typ == 'c' ? D_CLIENT : D_READER, sbuf, l, "send %d bytes to %s", l, username(cl)); aes_encrypt_idx(cl->aes_keys, sbuf, l); int32_t status; if(cl->is_udp) { status = sendto(cl->udp_fd, rbuf, l + 4, 0, (struct sockaddr *)&cl->udp_sa, cl->udp_sa_len); if(status == -1) { set_null_ip(&SIN_GET_ADDR(cl->udp_sa)); } } else { status = send(cl->udp_fd, rbuf, l + 4, 0); if(cl->typ == 'p' && cl->reader) { if(status == -1) { network_tcp_connection_close(cl->reader, "can't send"); } } else if(cl->typ == 'c') { if(status == -1) { cs_disconnect_client(cl); } } } if(status != -1) { if(cl->reader && answer_awaited) { cl->reader->last_s = time(NULL); } if(cl->reader && !answer_awaited) { cl->reader->last_s = cl->reader->last_g = time(NULL); } cl->last = time(NULL); } return status; }
static int32_t viaccess_get_emm_type(EMM_PACKET *ep, struct s_reader * rdr) { uint32_t provid=0; rdr_debug_mask(rdr, D_EMM, "Entered viaccess_get_emm_type ep->emm[0]=%02x",ep->emm[0]); if (ep->emm[3] == 0x90 && ep->emm[4] == 0x03) { provid = ep->emm[5] << 16 | ep->emm[6] << 8 | (ep->emm[7] & 0xFE); i2b_buf(4, provid, ep->provid); } switch (ep->emm[0]) { case 0x88: ep->type=UNIQUE; memset(ep->hexserial, 0, 8); memcpy(ep->hexserial, ep->emm + 4, 4); rdr_debug_mask(rdr, D_EMM, "UNIQUE"); return(!memcmp(rdr->hexserial + 1, ep->hexserial, 4)); case 0x8A: case 0x8B: ep->type=GLOBAL; rdr_debug_mask(rdr, D_EMM, "GLOBAL"); return 1; case 0x8C: case 0x8D: ep->type=SHARED; rdr_debug_mask(rdr, D_EMM, "SHARED (part)"); return 0; case 0x8E: ep->type=SHARED; memset(ep->hexserial, 0, 8); memcpy(ep->hexserial, ep->emm + 3, 3); rdr_debug_mask(rdr, D_EMM, "SHARED"); //check for provider as serial (cccam only?) int8_t i; for (i=0;i<rdr->nprov;i++) { if (!memcmp(&rdr->prid[i][1], ep->hexserial, 3)) return 1; } return(!memcmp(&rdr->sa[0][0], ep->hexserial, 3)); default: ep->type = UNKNOWN; rdr_debug_mask(rdr, D_EMM, "UNKNOWN"); return 1; } }
static void camd35_request_emm(uint16_t caid, uint32_t provider, uint8_t* hexserial, uint8_t emm_global, uint8_t emm_shared, uint8_t emm_unique) { uint8_t mbuf[1024]; uint8_t prid[4]; memset(mbuf, 0, sizeof(mbuf)); mbuf[2] = mbuf[3] = 0xff; // must not be zero i2b_buf(4, provider, &mbuf[12]); mbuf[0] = 5; mbuf[1] = 111; if(caid) { mbuf[39] = 1; // no. caids mbuf[20] = caid >> 8; // caid's (max 8) mbuf[21] = caid & 0xff; memcpy(mbuf + 40, hexserial, 6); mbuf[47] = 1; prid[0] = provider >> 24; prid[1] = provider >> 16; prid[2] = provider >> 8; prid[3] = provider & 0xFF; if((caid >= 0x1700 && caid <= 0x1799) || // Betacrypt (caid >= 0x0600 && caid <= 0x0699)) // Irdeto (don't know if this is correct, cause I don't own a IRDETO-Card) { mbuf[48 + (0 * 5)] = prid[0]; memcpy(&mbuf[50 + (0 * 5)], &prid[1], 3); } else { mbuf[48 + (0 * 5)] = prid[2]; mbuf[49 + (0 * 5)] = prid[3]; } mbuf[127] = 0; //EMM_UNKNOWN mbuf[128] = emm_global; //EMM_GLOBAL mbuf[129] = emm_shared; //EMM_SHARED mbuf[130] = emm_unique; //EMM_UNIQUE } else // disable emm { mbuf[20] = mbuf[39] = mbuf[40] = mbuf[47] = mbuf[49] = 1; }
static int32_t camd35_send(uint8_t *buf, int32_t buflen) { int32_t l, status; unsigned char rbuf[REQ_SIZE + 15 + 4], *sbuf = rbuf + 4; //Fix ECM len > 255 if(buflen <= 0) { buflen = ((buf[0] == 0) ? (((buf[21] & 0x0f) << 8) | buf[22]) + 3 : buf[1]); } l = 20 + (((buf[0] == 3) || (buf[0] == 4)) ? 0x34 : 0) + buflen; memcpy(rbuf, cl_ucrc, 4); memcpy(sbuf, buf, l); memset(sbuf + l, 0xff, 15); // set unused space to 0xff for newer camd3's i2b_buf(4, crc32(0, sbuf + 20, buflen), sbuf + 4); l = boundary(4, l); cs_log_dbg(0, "send %d bytes to client", l); aes_encrypt_idx(&cl_aes_keys, sbuf, l); status = sendto(cl_sockfd, rbuf, l + 4, 0, (struct sockaddr *)&cl_socket, sizeof(cl_socket)); return status; }
int32_t monitor_send_idx(struct s_client *cl, char *txt) { int32_t l; unsigned char buf[256+32]; if (!cl->udp_fd) return -1; struct timespec req_ts; req_ts.tv_sec = 0; req_ts.tv_nsec = 500000; nanosleep (&req_ts, NULL);//avoid lost udp-pakkets if (!cl->crypted) return sendto(cl->udp_fd, txt, strlen(txt), 0, (struct sockaddr *)&cl->udp_sa, cl->udp_sa_len); buf[0]='&'; buf[9]=l=strlen(txt); l=boundary(4, l+5)+5; memcpy(buf+1, cl->ucrc, 4); cs_strncpy((char *)buf+10, txt, sizeof(buf)-10); uchar tmp[10]; memcpy(buf+5, i2b_buf(4, crc32(0L, buf+10, l-10), tmp), 4); aes_encrypt_idx(cl, buf+5, l-5); return sendto(cl->udp_fd, buf, l, 0, (struct sockaddr *)&cl->udp_sa, cl->udp_sa_len); }
static int32_t oscam_ser_send_ecm(struct s_client *client, ECM_REQUEST *er, uchar *buf) { char *tmp; switch(client->serialdata->oscam_ser_proto) { case P_HSIC: memset(buf, 0, 12); buf[0] = 2; i2b_buf(2, er->caid, buf + 1); i2b_buf(3, er->prid, buf + 3); i2b_buf(2, er->pid, buf + 6); i2b_buf(2, er->srvid, buf + 10); memcpy(buf + 12, er->ecm, er->ecmlen); oscam_ser_send(client, buf, 12 + er->ecmlen); break; case P_BOMBA: oscam_ser_send(client, er->ecm, er->ecmlen); break; case P_DSR95: if(cs_malloc(&tmp, er->ecmlen * 2 + 1)) { if(client->serialdata->dsr9500type == P_DSR_WITHSID) { snprintf((char *)buf, 512, "%c%08X%04X%s%04X\n\r", 3, er->prid, er->caid, cs_hexdump(0, er->ecm, er->ecmlen, tmp, er->ecmlen * 2 + 1), er->srvid); oscam_ser_send(client, buf, (er->ecmlen << 1) + 19); // 1 + 8 + 4 + l*2 + 4 + 2 } else { snprintf((char *)buf, 512, "%c%08X%04X%s\n\r", 3, er->prid, er->caid, cs_hexdump(0, er->ecm, er->ecmlen, tmp, er->ecmlen * 2 + 1)); oscam_ser_send(client, buf, (er->ecmlen << 1) + 15); // 1 + 8 + 4 + l*2 + 2 } free(tmp); } break; case P_ALPHA: buf[0] = 0x80; i2b_buf(2, 2 + er->ecmlen, buf + 1); i2b_buf(2, er->caid, buf + 3); memcpy(buf + 5, er->ecm, er->ecmlen); oscam_ser_send(client, buf, oscam_ser_alpha_convert(buf, 5 + er->ecmlen)); break; } return (0); }
static void oscam_ser_send_dcw(struct s_client *client, ECM_REQUEST *er) { uchar mbuf[23]; int32_t i; uchar crc; struct s_serial_client *serialdata=cur_client()->serialdata; if (er->rc<E_NOTFOUND) // found switch(serialdata->connected) { case P_HSIC: for (i=0, crc=HSIC_CRC; i<16; i++) crc^=er->cw[i]; memset(mbuf , 0x04 , 2); memset(mbuf+2 , 0x3a , 2); memcpy(mbuf+4 , er->cw, 16); memcpy(mbuf+20, &crc , 1); memset(mbuf+21, 0x1b , 2); oscam_ser_send(client, mbuf, 23); break; case P_SSSP: mbuf[0]=0xF2; mbuf[1]=0; mbuf[2]=16; memcpy(mbuf+3, er->cw, 16); oscam_ser_send(client, mbuf, 19); if (!serialdata->sssp_fix) { mbuf[0]=0xF1; mbuf[1]=0; mbuf[2]=2; i2b_buf(2, er->pid, mbuf + 3); oscam_ser_send(client, mbuf, 5); serialdata->sssp_fix=1; } break; case P_GBOX: case P_BOMBA: oscam_ser_send(client, er->cw, 16); break; case P_DSR95: mbuf[0]=4; memcpy(mbuf+1, er->cw, 16); oscam_ser_send(client, mbuf, 17); if( serialdata->dsr9500type==P_DSR_GNUSMAS ) { serialdata->samsung_0a=0; for( i=1; i<17; i++ ) if( mbuf[i]==0x0A ) serialdata->samsung_0a++; serialdata->samsung_dcw++; } break; case P_GS: mbuf[0]=0x03; mbuf[1]=0x08; mbuf[2]=0x10; mbuf[3]=0x00; memcpy(mbuf+4, er->cw, 16); oscam_ser_send(client, mbuf, 20); break; case P_ALPHA: mbuf[0]=0x88; mbuf[1]=0x00; mbuf[2]=0x10; memcpy(mbuf+3, er->cw, 16); oscam_ser_send(client, mbuf, 19); break; } else // not found switch(serialdata->connected) { case P_GS: mbuf[0]=0x03; mbuf[1]=0x09; mbuf[2]=0x00; mbuf[3]=0x00; oscam_ser_send(client, mbuf, 4); break; } serialdata->serial_errors=0; // clear error counter }
static int32_t cc_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 if(cl->reader) { if(!cl->reader->tcp_connected) { cc_cli_connect(cl); } } struct cc_data *cc = cl->cc; if(!cc || !cl->udp_fd) { 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; } // build ecm message //buf[0] = er->caid >> 8; //buf[1] = er->caid & 0xff; //buf[2] = er->prid >> 24; //buf[3] = er->prid >> 16; //buf[4] = er->prid >> 8; //buf[5] = er->prid & 0xff; //buf[10] = er->srvid >> 8; //buf[11] = er->srvid & 0xff; buf[12] = (sizeof(er->ecmd5) + sizeof(er->csp_hash) + sizeof(er->cw)) & 0xff; buf[13] = (sizeof(er->ecmd5) + sizeof(er->csp_hash) + sizeof(er->cw)) >> 8; //buf[12] = 0; //buf[13] = 0; buf[14] = rc; i2b_buf(2, er->caid, buf + 0); i2b_buf(4, er->prid, buf + 2); i2b_buf(2, er->srvid, buf + 10); 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, cc->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 = cc_cmd_send(cl, buf, size + 20, MSG_CACHE_PUSH); if(res > 0) // cache-ex is pushing out, so no receive but last_g should be updated otherwise disconnect! { if(cl->reader) { cl->reader->last_s = cl->reader->last_g = time((time_t *)0); } // correct if(cl) { cl->last = time(NULL); } } NULLFREE(buf); return res; }
void cc_cacheex_filter_out(struct s_client *cl) { struct s_reader *rdr = (cl->typ == 'c') ? NULL : cl->reader; int i = 0, j; CECSPVALUETAB *filter; //minimal size, keep it <= 512 for max UDP packet size without fragmentation int32_t size = 482; uint8_t buf[482]; memset(buf, 0, sizeof(buf)); //mode==2 send filters from rdr if(rdr && rdr->cacheex.mode == 2) { filter = &rdr->cacheex.filter_caidtab; } //mode==3 send filters from acc else if(cl->typ == 'c' && cl->account && cl->account->cacheex.mode == 3) { filter = &cl->account->cacheex.filter_caidtab; } else { return; } i2b_buf(2, filter->n, buf + i); i += 2; int32_t max_filters = 30; for(j=0; j<max_filters; j++) { if(j<CS_MAXCAIDTAB) { i2b_buf(4, filter->caid[j], buf + i); } i += 4; } for(j=0; j<max_filters && j<CS_MAXCAIDTAB; j++) { if(j<CS_MAXCAIDTAB) { i2b_buf(4, filter->cmask[j], buf + i); } i += 4; } for(j=0; j<max_filters && j<CS_MAXCAIDTAB; j++) { if(j<CS_MAXCAIDTAB) { i2b_buf(4, filter->prid[j], buf + i); } i += 4; } for(j=0; j<max_filters && j<CS_MAXCAIDTAB; j++) { if(j<CS_MAXCAIDTAB) { i2b_buf(4, filter->srvid[j], buf + i); } i += 4; } cs_log_dbg(D_CACHEEX, "cacheex: sending push filter request to %s", username(cl)); cc_cmd_send(cl, buf, size, MSG_CACHE_FILTER); }
static void camd35_request_emm(ECM_REQUEST *er) { int32_t i; time_t now; uchar mbuf[1024]; struct s_client *cl = cur_client(); struct s_reader *aureader = NULL, *rdr = NULL; if(er->selected_reader && !er->selected_reader->audisabled && ll_contains(cl->aureader_list, er->selected_reader)) { aureader = er->selected_reader; } if(!aureader && cl->aureader_list) { LL_ITER itr = ll_iter_create(cl->aureader_list); while((rdr = ll_iter_next(&itr))) { if(emm_reader_match(rdr, er->caid, er->prid)) { aureader = rdr; break; } } } if(!aureader) { return; } // TODO uint16_t au_caid = aureader->caid; if(!au_caid && caid_is_bulcrypt(er->caid)) // Bulcrypt has 2 caids and aureader->caid can't be used. Use ECM_REQUEST caid for AU. { au_caid = er->caid; } time(&now); if(!memcmp(cl->lastserial, aureader->hexserial, 8)) if(llabs(now - cl->last) < 180) { return; } memcpy(cl->lastserial, aureader->hexserial, 8); cl->last = now; if(au_caid) { cl->disable_counter = 0; cs_log("%s emm-request sent (reader=%s, caid=%04X, auprovid=%06X)", username(cur_client()), aureader->label, au_caid, aureader->auprovid ? aureader->auprovid : b2i(4, aureader->prid[0])); } else if(cl->disable_counter > 2) { return; } else { cl->disable_counter++; } memset(mbuf, 0, sizeof(mbuf)); mbuf[2] = mbuf[3] = 0xff; // must not be zero i2b_buf(2, er->srvid, mbuf + 8); //override request provid with auprovid if set in CMD05 if(aureader->auprovid) { if(aureader->auprovid != er->prid) { i2b_buf(4, aureader->auprovid, mbuf + 12); } else { i2b_buf(4, er->prid, mbuf + 12); } } else { i2b_buf(4, er->prid, mbuf + 12); } i2b_buf(2, er->pid, mbuf + 16); mbuf[0] = 5; mbuf[1] = 111; if(au_caid) { mbuf[39] = 1; // no. caids mbuf[20] = au_caid >> 8; // caid's (max 8) mbuf[21] = au_caid & 0xff; memcpy(mbuf + 40, aureader->hexserial, 6); // serial now 6 bytes mbuf[47] = aureader->nprov; for(i = 0; i < aureader->nprov; i++) { if((au_caid >= 0x1700 && au_caid <= 0x1799) || // Betacrypt (au_caid >= 0x0600 && au_caid <= 0x0699)) // Irdeto (don't know if this is correct, cause I don't own a IRDETO-Card) { mbuf[48 + (i * 5)] = aureader->prid[i][0]; memcpy(&mbuf[50 + (i * 5)], &aureader->prid[i][1], 3); } else { mbuf[48 + (i * 5)] = aureader->prid[i][2]; mbuf[49 + (i * 5)] = aureader->prid[i][3]; memcpy(&mbuf[50 + (i * 5)], &aureader->sa[i][0], 4); // for conax we need at least 4 Bytes } } //we think client/server protocols should deliver all information, and only readers should discard EMM mbuf[128] = (aureader->blockemm & EMM_GLOBAL && !(aureader->saveemm & EMM_GLOBAL)) ? 0 : 1; mbuf[129] = (aureader->blockemm & EMM_SHARED && !(aureader->saveemm & EMM_SHARED)) ? 0 : 1; mbuf[130] = (aureader->blockemm & EMM_UNIQUE && !(aureader->saveemm & EMM_UNIQUE)) ? 0 : 1; mbuf[127] = (aureader->blockemm & EMM_UNKNOWN && !(aureader->saveemm & EMM_UNKNOWN)) ? 0 : 1; } else // disable emm { mbuf[20] = mbuf[39] = mbuf[40] = mbuf[47] = mbuf[49] = 1; }
static int32_t monitor_recv(struct s_client * client, uchar *buf, int32_t l) { int32_t n; uchar nbuf[3] = { 'U', 0, 0 }; static int32_t bpos=0, res = 0; static uchar *bbuf=NULL; if (!bbuf) { if (!cs_malloc(&bbuf, l)) return 0; } if (bpos) memcpy(buf, bbuf, n=bpos); else n=recv_from_udpipe(buf); bpos=0; if (!n) return buf[0]=0; if (buf[0]=='&') { int32_t bsize; if (n<21) // 5+16 is minimum { cs_log("packet too small!"); return buf[0]=0; } res = secmon_auth_client(buf+1); if (res == -1) { cs_disconnect_client(client); return 0; } if (!res) return buf[0]=0; aes_decrypt(client, buf+5, 16); bsize=boundary(4, buf[9]+5)+5; // cs_log("n=%d bsize=%d", n, bsize); if (n>bsize) { // cs_log("DO >>>> copy-back"); memcpy(bbuf, buf+bsize, bpos=n-bsize); n=bsize; uchar *nbuf_cpy; if (cs_malloc(&nbuf_cpy, sizeof(nbuf))) { memcpy(nbuf_cpy, nbuf, sizeof(nbuf)); add_job(client, ACTION_CLIENT_UDP, &nbuf_cpy, sizeof(nbuf)); } } else if (n<bsize) { cs_log("packet-size mismatch !"); return buf[0]=0; } aes_decrypt(client, buf+21, n-21); uchar tmp[10]; if (memcmp(buf+5, i2b_buf(4, crc32(0L, buf+10, n-10), tmp), 4)) { cs_log("CRC error ! wrong password ?"); return buf[0]=0; } n=buf[9]; memmove(buf, buf+10, n); } else { uchar *p; if (monitor_check_ip() == -1) { cs_disconnect_client(client); return 0; } buf[n]='\0'; if ((p=(uchar *)strchr((char *)buf, 10)) && (bpos=n-(p-buf)-1)) { memcpy(bbuf, p+1, bpos); n=p-buf; uchar *nbuf_cpy; if (cs_malloc(&nbuf_cpy, sizeof(nbuf))) { memcpy(nbuf_cpy, nbuf, sizeof(nbuf)); add_job(client, ACTION_CLIENT_UDP, &nbuf_cpy, sizeof(nbuf)); } } } buf[n]='\0'; n=strlen(trim((char *)buf)); if (n) client->last=time((time_t *) 0); return n; }
static int32_t ghttp_capmt_notify(struct s_client *client, struct demux_s *demux) { uchar req[640], lenhdr[64] = ""; uchar *pids = NULL; uchar *end; char *encauth = NULL; int32_t ret; int8_t i, pids_len = 0, offs = 0; s_ghttp *context = (s_ghttp *)client->ghttp; if(!context) { return -1; } cs_debug_mask(D_CLIENT, "%s: capmt %x-%x-%x %d pids on adapter %d mask %x dmx index %d", client->reader->label, demux->onid, demux->tsid, demux->program_number, demux->ECMpidcount, demux->adapter_index, demux->ca_mask, demux->demux_index); if(demux->ECMpidcount > 0) { if(cs_malloc(&pids, demux->ECMpidcount * 8)) { pids_len = demux->ECMpidcount * 8; for(i = 0; i < demux->ECMpidcount; i++) { i2b_buf(2, demux->ECMpids[i].ECM_PID, pids + offs); i2b_buf(2, demux->ECMpids[i].CAID, pids + (offs += 2)); i2b_buf(4, demux->ECMpids[i].PROVID, pids + (offs += 2)); offs += 4; } snprintf((char *)lenhdr, sizeof(lenhdr), "\r\nContent-Length: %d", pids_len); } else { return -1; } } if(!context->host_id) { context->host_id = (uchar *)cs_strdup(client->reader->device); } encauth = _ghttp_basic_auth(client); if(encauth) // basic auth login { ret = snprintf((char *)req, sizeof(req), "%s /api/p/%x/%x/%x/%x/%x HTTP/1.1\r\nHost: %s\r\nAuthorization: Basic %s%s\r\n\r\n", ((pids_len > 0) ? "POST" : "GET"), demux->onid, demux->tsid, demux->program_number, demux->ECMpidcount, demux->enigma_namespace, context->host_id, encauth, lenhdr); free(encauth); } else { if(context->session_id) // session exists { ret = snprintf((char *)req, sizeof(req), "%s /api/p/%s/%x/%x/%x/%x/%x HTTP/1.1\r\nHost: %s%s\r\n\r\n", ((pids_len > 0) ? "POST" : "GET"), context->session_id, demux->onid, demux->tsid, demux->program_number, demux->ECMpidcount, demux->enigma_namespace, context->host_id, lenhdr); } else // no credentials configured, assume no session required { ret = snprintf((char *)req, sizeof(req), "%s /api/p/%x/%x/%x/%x/%x HTTP/1.1\r\nHost: %s%s\r\n\r\n", ((pids_len > 0) ? "POST" : "GET"), demux->onid, demux->tsid, demux->program_number, demux->ECMpidcount, demux->enigma_namespace, context->host_id, lenhdr); } } end = req + ret; if(pids_len > 0) { memcpy(end, pids, pids_len); cs_debug_mask(D_CLIENT, "%s: new unscrambling detected, switching to post", client->reader->label); _set_pid_status(context->post_contexts, demux->onid, demux->tsid, demux->program_number, 0); } cs_ddump_mask(D_CLIENT, pids, pids_len, "%s: sending capmt ecm pids - %s /api/p/%x/%x/%x/%x/%x", client->reader->label, (pids_len > 0) ? "POST" : "GET", demux->onid, demux->tsid, demux->program_number, demux->ECMpidcount, demux->enigma_namespace); ret = ghttp_send(client, req, ret + pids_len); if(pids_len > 0) { free(pids); } return 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; }
/** * send push filter */ void camd35_cacheex_send_push_filter(struct s_client *cl, uint8_t mode) { struct s_reader *rdr = cl->reader; int i = 20, j; CECSPVALUETAB *filter; //maximum size: 20+255 uint8_t buf[20+242]; memset(buf, 0, sizeof(buf)); buf[0] = 0x3c; buf[1] = 0xf2; //mode==2 send filters from rdr if(mode == 2 && rdr) { filter = &rdr->cacheex.filter_caidtab; } //mode==3 send filters from acc else if(mode == 3 && cl->typ == 'c' && cl->account) { filter = &cl->account->cacheex.filter_caidtab; } else { return; } i2b_buf(2, filter->n, buf + i); i += 2; int32_t max_filters = 15; for(j=0; j<max_filters; j++) { if(j<CS_MAXCAIDTAB) { i2b_buf(4, filter->caid[j], buf + i); } i += 4; } for(j=0; j<max_filters && j<CS_MAXCAIDTAB; j++) { if(j<CS_MAXCAIDTAB) { i2b_buf(4, filter->cmask[j], buf + i); } i += 4; } for(j=0; j<max_filters && j<CS_MAXCAIDTAB; j++) { if(j<CS_MAXCAIDTAB) { i2b_buf(4, filter->prid[j], buf + i); } i += 4; } for(j=0; j<max_filters && j<CS_MAXCAIDTAB; j++) { if(j<CS_MAXCAIDTAB) { i2b_buf(4, filter->srvid[j], buf + i); } i += 4; } cs_log_dbg(D_CACHEEX, "cacheex: sending push filter request to %s", username(cl)); camd35_send_without_timeout(cl, buf, 242); //send adds +20 }