void radegast_idle(void) { struct s_client *client = cur_client(); struct s_reader *rdr = client->reader; time_t now = time(NULL); if(!rdr) { return; } if(rdr->tcp_ito > 0) { int32_t time_diff; time_diff = abs(now - rdr->last_s); if(time_diff > (rdr->tcp_ito)) { network_tcp_connection_close(rdr, "inactivity"); return; } } else if(rdr->tcp_ito == -1) { radegast_connect(); return; } }
static void radegast_process_ecm(uchar *buf, int32_t l) { int32_t i, n, sl; ECM_REQUEST *er; if (!(er=get_ecmtask())) return; for (i=0; i<l; i+=(sl+2)) { sl=buf[i+1]; switch(buf[i]) { case 2: // CAID (upper byte only, oldstyle) er->caid=buf[i+2]<<8; break; case 10: // CAID er->caid=b2i(2, buf+i+2); break; case 3: // ECM DATA er->l=sl; memcpy(er->ecm, buf+i+2, er->l); break; case 6: // PROVID (ASCII) n=(sl>6) ? 3 : (sl>>1); er->prid=cs_atoi((char *) buf+i+2+sl-(n<<1), n, 0); break; case 7: // KEYNR (ASCII), not needed break; case 8: // ECM PROCESS PID ?? don't know, not needed break; } } if (l!=i) cs_log("WARNING: ECM-request corrupt"); else get_cw(cur_client(), er); }
static void * radegast_server(void *cli) { int32_t n; uchar mbuf[1024]; struct s_client * client = (struct s_client *) cli; client->thread=pthread_self(); pthread_setspecific(getclient, cli); radegast_auth_client(cur_client()->ip); while ((n=get_request(mbuf))>0) { switch(mbuf[0]) { case 1: radegast_process_ecm(mbuf+2, mbuf[1]); break; default: radegast_process_unknown(mbuf); } } cs_disconnect_client(client); return NULL; }
int32_t constcw_analyse_file(uint16_t c_caid, uint32_t c_prid, uint16_t c_sid, uchar *dcw) { //CAID:PROVIDER:SID:PMT:PID::XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX FILE *fp; char token[512]; uint32_t caid, provid, sid, pmt, pid; int32_t cw[16]; // FIXME c_prid = c_prid; fp=fopen(cur_client()->reader->device, "r"); if (!fp) return (0); while (fgets(token, sizeof(token), fp)){ if (token[0]=='#') continue; sscanf(token, "%4x:%6x:%4x:%4x:%4x::%2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x", &caid, &provid, &sid, &pmt, &pid, &cw[0], &cw[1], &cw[2], &cw[3], &cw[4], &cw[5], &cw[6], &cw[7], &cw[8], &cw[9], &cw[10], &cw[11], &cw[12], &cw[13], &cw[14], &cw[15]); //cs_log("Line found: %s", token); if (c_caid == caid && c_sid == sid){ fclose(fp); int8_t i; for(i = 0; i < 16; ++i) dcw[i] = (uchar) cw[i]; cs_log("Entry found: %04X:%06X:%04X:%04X:%04X::%s", caid, provid, sid, pmt, pid, cs_hexdump(1, dcw, 16, token, sizeof(token))); return 1; } } fclose(fp); return 0; }
/* * This function writes the current CW from ECM struct to a cwl file. * The filename is re-calculated and file re-opened every time. * This will consume a bit cpu time, but nothing has to be stored between * each call. If not file exists, a header is prepended */ void logCWtoFile(ECM_REQUEST *er, uchar *cw) { FILE *pfCWL; char srvname[128]; /* %s / %s _I %04X _ %s .cwl */ char buf[256 + sizeof(srvname)]; char date[9]; unsigned char i, parity, writeheader = 0; struct tm timeinfo; /* * search service name for that id and change characters * causing problems in file name */ get_servicename(cur_client(), er->srvid, er->caid, srvname); for(i = 0; srvname[i]; i++) if(srvname[i] == ' ') { srvname[i] = '_'; } /* calc log file name */ time_t walltime = cs_time(); localtime_r(&walltime, &timeinfo); strftime(date, sizeof(date), "%Y%m%d", &timeinfo); snprintf(buf, sizeof(buf), "%s/%s_I%04X_%s.cwl", cfg.cwlogdir, date, er->srvid, srvname); /* open failed, assuming file does not exist, yet */ if((pfCWL = fopen(buf, "r")) == NULL) { writeheader = 1; } else { /* we need to close the file if it was opened correctly */ fclose(pfCWL); } if((pfCWL = fopen(buf, "a+")) == NULL) { /* maybe this fails because the subdir does not exist. Is there a common function to create it? for the moment do not print32_t to log on every ecm cs_log(""error opening cw logfile for writing: %s (errno=%d %s)", buf, errno, strerror(errno)); */ return; } if(writeheader) { /* no global macro for cardserver name :( */ fprintf(pfCWL, "# OSCam cardserver v%s - http://www.streamboard.tv/oscam/\n", CS_VERSION); fprintf(pfCWL, "# control word log file for use with tsdec offline decrypter\n"); strftime(buf, sizeof(buf), "DATE %Y-%m-%d, TIME %H:%M:%S, TZ %Z\n", &timeinfo); fprintf(pfCWL, "# %s", buf); fprintf(pfCWL, "# CAID 0x%04X, SID 0x%04X, SERVICE \"%s\"\n", er->caid, er->srvid, srvname); } parity = er->ecm[0] & 1; fprintf(pfCWL, "%d ", parity); for(i = parity * 8; i < 8 + parity * 8; i++) { fprintf(pfCWL, "%02X ", cw[i]); } /* better use incoming time er->tps rather than current time? */ strftime(buf, sizeof(buf), "%H:%M:%S\n", &timeinfo); fprintf(pfCWL, "# %s", buf); fflush(pfCWL); fclose(pfCWL); }
static int32_t oscam_ser_check_ecm(ECM_REQUEST *er, uchar *buf, int32_t l) { int32_t i; struct s_serial_client *serialdata = cur_client()->serialdata; if (l<16) { cs_log(incomplete, l); return(1); } switch(serialdata->connected) { case P_HSIC: er->ecmlen = l-12; er->caid = b2i(2, buf+1 ); er->prid = b2i(3, buf+3 ); er->pid = b2i(2, buf+6 ); er->srvid= b2i(2, buf+10); memcpy(er->ecm, buf+12, er->ecmlen); break; case P_SSSP: er->pid=b2i(2, buf+3); for (i=0; (i<8) && (serialdata->sssp_tab[i].pid!=er->pid); i++); if (i>=serialdata->sssp_num) { cs_debug_mask(D_CLIENT, "illegal request, unknown pid=%04X", er->pid); return(2); } er->ecmlen = l-5; er->srvid= serialdata->sssp_srvid; er->caid = serialdata->sssp_tab[i].caid; er->prid = serialdata->sssp_tab[i].prid; memcpy(er->ecm, buf+5, er->ecmlen); break; case P_BOMBA: er->ecmlen = l; memcpy(er->ecm, buf, er->ecmlen); break; case P_DSR95: buf[l]='\0'; // prepare for trim trim((char *)buf+13); // strip spc, nl, cr ... er->ecmlen = strlen((char *)buf+13)>>1; er->prid=cs_atoi((char *)buf+3, 3, 0); // ignore errors er->caid=cs_atoi((char *)buf+9, 2, 0); // ignore errors if (cs_atob(er->ecm, (char *)buf+13, er->ecmlen)<0) { cs_log("illegal characters in ecm-request"); return(1); } if( serialdata->dsr9500type==P_DSR_WITHSID ) { er->ecmlen -= 2; er->srvid=cs_atoi((char *)buf+13+(er->ecmlen << 1), 2, 0); } break; case P_GS: er->ecmlen = ((buf[3]<<8)|buf[2]) - 6; er->srvid = (buf[5]<<8)|buf[4]; // sid er->caid = (buf[7]<<8)|buf[6]; er->prid = 0; if (er->ecmlen > 256) er->ecmlen = 256; memcpy(er->ecm, buf+10, er->ecmlen); break; case P_ALPHA: l=oscam_ser_alpha_convert(buf, l); er->ecmlen= b2i(2, buf+1 )-2; er->caid = b2i(2, buf+3 ); if ((er->ecmlen!=l-5) || (er->ecmlen>257)) { cs_log(incomplete, l); return(1); } memcpy(er->ecm, buf+5, er->ecmlen); break; case P_GBOX: er->srvid = b2i(2, buf+serialdata->gbox_lens.cat_len+3+3); er->ecmlen = serialdata->gbox_lens.ecm_len+3; memcpy(er->ecm, buf+serialdata->gbox_lens.cat_len+3+serialdata->gbox_lens.pmt_len+3, 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 oscam_ser_parse_url(char *url, struct s_serial_client *serialdata, char *pcltype) { char *service, *usr, *dev, *baud=NULL, *dummy, *para; char cltype; cltype = pcltype?(*pcltype):cur_client()->typ; serialdata->oscam_ser_proto=P_AUTO; if( (dummy=strstr(url, "://")) ) { int32_t i; service=url; url=dummy+3; *dummy=0; for (i=1; i<=P_MAX; i++) if (!strcmp(service, proto_txt[i])) serialdata->oscam_ser_proto=i; } if (!(cltype == 'c') && (serialdata->oscam_ser_proto==P_AUTO)) return(0); switch(serialdata->oscam_ser_proto) // set the defaults { case P_GS: serialdata->oscam_ser_timeout=500; serialdata->oscam_ser_baud=B19200; break; default: serialdata->oscam_ser_timeout=50; #ifdef B115200 serialdata->oscam_ser_baud=B115200; #else serialdata->oscam_ser_baud=B9600; #endif } switch( serialdata->oscam_ser_proto ) { case P_DSR95: serialdata->dsr9500type=(cltype == 'c')?P_DSR_AUTO:P_DSR_WITHSID; break; case P_DSR95_OLD: serialdata->dsr9500type=P_DSR_AUTO; serialdata->oscam_ser_proto=P_DSR95; } usr=url; if( (dev=strchr(usr, '@')) ) { *dev++='\0'; if( (dummy=strchr(usr, ':')) ) // fake pwd *dummy++='\0'; if ((cltype == 'c') && (!usr[0])) return(0); } else { if (cltype == 'c') return(0); // user needed in server-mode dev=usr; } if( (baud=strchr(dev, ':')) )// port = baud *baud++='\0'; dummy=baud ? baud : dev; if( (para=strchr(dummy, '?')) ) { char *ptr1, *ptr2, *saveptr1 = NULL; *para++='\0'; for (ptr1=strtok_r(para, "&", &saveptr1); ptr1; ptr1=strtok_r(NULL, "&", &saveptr1)) { if (!(ptr2=strchr(ptr1, '='))) continue; *ptr2++='\0'; strtolower(ptr1); if (!strcmp("delay" , ptr1)) serialdata->oscam_ser_delay =atoi(ptr2); if (!strcmp("timeout", ptr1)) serialdata->oscam_ser_timeout=atoi(ptr2); } } if (baud) { trim(baud); #ifdef B115200 if (!strcmp(baud, "115200")) serialdata->oscam_ser_baud=B115200; else #endif #ifdef B57600 if (!strcmp(baud, "57600")) serialdata->oscam_ser_baud=B57600; else #endif if (!strcmp(baud, "38400")) serialdata->oscam_ser_baud=B38400; else if (!strcmp(baud, "19200")) serialdata->oscam_ser_baud=B19200; else if (!strcmp(baud, "9600")) serialdata->oscam_ser_baud=B9600; } if( (para=strchr(dev, ',')) )// device = ip/hostname and port { *para++='\0'; serialdata->oscam_ser_port=atoi(para); } else serialdata->oscam_ser_port=0; cs_strncpy(serialdata->oscam_ser_usr, usr, sizeof(serialdata->oscam_ser_usr)); cs_strncpy(serialdata->oscam_ser_device, dev, sizeof(serialdata->oscam_ser_device)); return(serialdata->oscam_ser_baud); }
static void radegast_process_unknown(uchar *buf) { uchar answer[2]={0x81, 0x00}; radegast_send(cur_client(), answer); cs_log("unknown request %02X, len=%d", buf[0], buf[1]); }
int32_t stapi_open(void) { uint32_t ErrorCode; DIR *dirp; struct dirent entry, *dp = NULL; struct stat buf; int32_t i; char pfad[80]; stapi_on = 1; int32_t stapi_priority = 0; dirp = opendir(PROCDIR); if(!dirp) { cs_log("opendir failed (errno=%d %s)", errno, strerror(errno)); return 0; } memset(dev_list, 0, sizeof(struct STDEVICE)*PTINUM); if(dvbapi_priority) { struct s_dvbapi_priority *p; for(p = dvbapi_priority; p != NULL; p = p->next) { if(p->type == 's') { stapi_priority = 1; break; } } } if(!stapi_priority) { cs_log("WARNING: no PTI devices defined, stapi disabled"); return 0; } oscam_stapi5_GetRevision(); oscam_sttkd_GetRevision(); i = 0; while(!cs_readdir_r(dirp, &entry, &dp)) { if(!dp) { break; } snprintf(pfad, sizeof(pfad), "%s%s", PROCDIR, dp->d_name); if(stat(pfad, &buf) != 0) { continue; } if(!(buf.st_mode & S_IFDIR && strncmp(dp->d_name, ".", 1) != 0)) { continue; } int32_t do_open = 0; struct s_dvbapi_priority *p; for(p = dvbapi_priority; p != NULL; p = p->next) { if(p->type != 's') { continue; } if(strcmp(dp->d_name, p->devname) == 0) { do_open = 1; break; } } if(!do_open) { cs_log("PTI: %s skipped", dp->d_name); continue; } ErrorCode = oscam_stapi5_Open(dp->d_name, &dev_list[i].SessionHandle); if(ErrorCode != 0) { cs_log("STPTI_Open ErrorCode: %d", ErrorCode); continue; } //debug //oscam_stapi_Capability(dp->d_name); cs_strncpy(dev_list[i].name, dp->d_name, sizeof(dev_list[i].name)); cs_log("PTI: %s open %d", dp->d_name, i); ErrorCode = oscam_stapi5_SignalAllocate(dev_list[i].SessionHandle, &dev_list[i].SignalHandle); if(ErrorCode != 0) { cs_log("SignalAllocate: ErrorCode: %d SignalHandle: %x", ErrorCode, dev_list[i].SignalHandle); } i++; if(i >= PTINUM) { break; } } closedir(dirp); if(i == 0) { return 0; } uint8_t TKD_InstanceID = 0; memset(&tkd_desc_info, 0, sizeof(tkd_desc_info[0]) * MAX_DESCRAMBLER); for(TKD_InstanceID = 0; TKD_InstanceID < TKD_MAX_NUMBER; TKD_InstanceID++) { /* Generate the device name dynamically based upon the Instance ID */ snprintf(TKD_DeviceName[TKD_InstanceID], sizeof(TKD_DeviceName), "TKD_%02d", TKD_InstanceID); ErrorCode = oscam_sttkd_Open(TKD_DeviceName[TKD_InstanceID], &TKDHandle[TKD_InstanceID]); if(ErrorCode != 0) cs_log("oscam_sttkd_Open: DeviceName: %s, TKDHandle: 0x%08X, ErrorCode: %d", TKD_DeviceName[TKD_InstanceID], TKDHandle[TKD_InstanceID], ErrorCode); } SAFE_MUTEX_INIT(&filter_lock, NULL); for(i = 0; i < PTINUM; i++) { if(dev_list[i].SessionHandle == 0) { continue; } struct read_thread_param *para; if(!cs_malloc(¶, sizeof(struct read_thread_param))) { return 0; } para->id = i; para->cli = cur_client(); int32_t ret = start_thread("stapi read", stapi_read_thread, (void *)para, &dev_list[i].thread, 1, 0); if(ret) { return 0; } } atexit(stapi_off); cs_log("liboscam_stapi5 v.%s initialized", oscam_stapi5_LibVersion()); return 1; }
static uint8_t get_log_header(char *txt, int32_t txt_size, uint8_t* hdr_logcount_offset, uint8_t* hdr_date_offset, uint8_t* hdr_time_offset, uint8_t* hdr_info_offset) { struct s_client *cl = cur_client(); struct tm lt; int32_t tmp; cs_ftime(&log_ts); time_t walltime = cs_walltime(&log_ts); localtime_r(&walltime, <); tmp = snprintf(txt, txt_size, "[LOG000]%04d/%02d/%02d %02d:%02d:%02d %08X %c ", lt.tm_year + 1900, lt.tm_mon + 1, lt.tm_mday, lt.tm_hour, lt.tm_min, lt.tm_sec, cl ? cl->tid : 0, cl ? cl->typ : ' ' ); if(tmp == 39) { if(hdr_logcount_offset != NULL) { // depends on snprintf(...) format (*hdr_logcount_offset) = 4; } if(hdr_date_offset != NULL) { // depends on snprintf(...) format (*hdr_date_offset) = *hdr_logcount_offset + 4; } if(hdr_time_offset != NULL) { // depends on snprintf(...) format (*hdr_time_offset) = *hdr_date_offset + 11; } if(hdr_info_offset != NULL) { // depends on snprintf(...) format (*hdr_info_offset) = *hdr_time_offset + 9; } return (uint8_t)tmp; } if(hdr_logcount_offset != NULL) { (*hdr_logcount_offset) = 0; } if(hdr_date_offset != NULL) { (*hdr_date_offset) = 0; } if(hdr_time_offset != NULL) { (*hdr_time_offset) = 0; } if(hdr_info_offset != NULL) { (*hdr_info_offset) = 0; } return 0; }
const char *remote_txt(void) { return cur_client()->typ == 'c' ? "client" : "remote server"; }
int32_t radegast_cli_init(struct s_client *cl) { *cl = *cl; //prevent compiler warning struct sockaddr_in loc_sa; int32_t handle; cur_client()->pfd=0; if (cur_client()->reader->r_port<=0) { cs_log("radegast: invalid port %d for server %s", cur_client()->reader->r_port, cur_client()->reader->device); return(1); } cur_client()->ip=0; memset((char *)&loc_sa,0,sizeof(loc_sa)); loc_sa.sin_family = AF_INET; #ifdef LALL if (cfg.serverip[0]) loc_sa.sin_addr.s_addr = inet_addr(cfg.serverip); else #endif loc_sa.sin_addr.s_addr = INADDR_ANY; loc_sa.sin_port = htons(cur_client()->reader->l_port); if ((cur_client()->udp_fd=socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))<0) { cs_log("radegast: Socket creation failed (errno=%d %s)", errno, strerror(errno)); cs_exit(1); } #ifdef SO_PRIORITY if (cfg.netprio) setsockopt(cur_client()->udp_fd, SOL_SOCKET, SO_PRIORITY, (void *)&cfg.netprio, sizeof(uintptr_t)); #endif if (!cur_client()->reader->tcp_ito) { uint32_t keep_alive = cur_client()->reader->tcp_ito?1:0; setsockopt(cur_client()->udp_fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keep_alive, sizeof(uintptr_t)); } memset((char *)&cur_client()->udp_sa,0,sizeof(cur_client()->udp_sa)); cur_client()->udp_sa.sin_family = AF_INET; cur_client()->udp_sa.sin_port = htons((uint16_t)cur_client()->reader->r_port); cs_log("radegast: proxy %s:%d (fd=%d)", cur_client()->reader->device, cur_client()->reader->r_port, cur_client()->udp_fd); handle = network_tcp_connection_open(); if(handle < 0) return -1; cur_client()->reader->tcp_connected = 2; cur_client()->reader->card_status = CARD_INSERTED; cur_client()->reader->last_g = cur_client()->reader->last_s = time((time_t *)0); cs_debug_mask(D_CLIENT, "radegast: last_s=%d, last_g=%d", cur_client()->reader->last_s, cur_client()->reader->last_g); cur_client()->pfd=cur_client()->udp_fd; return(0); }
static void write_to_log_int(char *txt, uint8_t header_len, uint8_t hdr_logcount_offset, uint8_t hdr_date_offset, uint8_t hdr_time_offset, uint8_t hdr_info_offset) { #if !defined(WEBIF) && !defined(MODULE_MONITOR) if(cfg.disablelog) { return; } #endif char *newtxt = cs_strdup(txt); if(!newtxt) { return; } struct s_log *log; if(!cs_malloc(&log, sizeof(struct s_log))) { NULLFREE(newtxt); return; } log->txt = newtxt; log->header_len = header_len; log->header_logcount_offset = hdr_logcount_offset; log->header_date_offset = hdr_date_offset; log->header_time_offset = hdr_time_offset; log->header_info_offset = hdr_info_offset; log->direct_log = 0; struct s_client *cl = cur_client(); log->cl_usr = ""; if(!cl) { log->cl_text = "undef"; log->cl_typ = ' '; } else { switch(cl->typ) { case 'c': case 'm': if(cl->account) { log->cl_text = cl->account->usr; log->cl_usr = cl->account->usr; } else { log->cl_text = ""; } break; case 'p': case 'r': log->cl_text = cl->reader ? cl->reader->label : ""; break; default: log->cl_text = "server"; break; } log->cl_typ = cl->typ; } if(exit_oscam == 1 || cfg.disablelog) //Exit or log disabled. if disabled, just display on webif/monitor { char buf[LOG_BUF_SIZE]; cs_strncpy(buf, log->txt, LOG_BUF_SIZE); write_to_log(buf, log, 1); NULLFREE(log->txt); NULLFREE(log); } else { log_list_add(log); } }
void log_emm_request(struct s_reader *rdr){ cs_log("%s emm-request sent (reader=%s, caid=%04X, auprovid=%06X)", username(cur_client()), rdr->label, rdr->caid, rdr->auprovid ? rdr->auprovid : b2i(4, rdr->prid[0])); }
int32_t stapi_open(void) { uint32_t ErrorCode; DIR *dirp; struct dirent entry, *dp = NULL; struct stat buf; int32_t i; char pfad[80]; stapi_on=1; int32_t stapi_priority=0; dirp = opendir(PROCDIR); if (!dirp) { cs_log("opendir failed (errno=%d %s)", errno, strerror(errno)); return 0; } memset(dev_list, 0, sizeof(struct STDEVICE)*PTINUM); if (dvbapi_priority) { struct s_dvbapi_priority *p; for (p=dvbapi_priority; p != NULL; p=p->next) { if (p->type=='s') { stapi_priority=1; break; } } } if (!stapi_priority) { cs_log("WARNING: no PTI devices defined, stapi disabled"); return 0; } oscam_stapi_CheckVersion(); i=0; while (!cs_readdir_r(dirp, &entry, &dp)) { if (!dp) break; snprintf(pfad, sizeof(pfad), "%s%s", PROCDIR, dp->d_name); if (stat(pfad,&buf) != 0) continue; if (!(buf.st_mode & S_IFDIR && strncmp(dp->d_name, ".", 1)!=0)) continue; int32_t do_open=0; struct s_dvbapi_priority *p; for (p=dvbapi_priority; p != NULL; p=p->next) { if (p->type!='s') continue; if(strcmp(dp->d_name, p->devname)==0) { do_open=1; break; } } if (!do_open) { cs_log("PTI: %s skipped", dp->d_name); continue; } ErrorCode= oscam_stapi_Open(dp->d_name, &dev_list[i].SessionHandle); if (ErrorCode != 0) { cs_log("STPTI_Open ErrorCode: %d", ErrorCode); continue; } //debug //oscam_stapi_Capability(dp->d_name); cs_strncpy(dev_list[i].name,dp->d_name, sizeof(dev_list[i].name)); cs_log("PTI: %s open %d", dp->d_name, i); ErrorCode = oscam_stapi_SignalAllocate(dev_list[i].SessionHandle, &dev_list[i].SignalHandle); if (ErrorCode != 0) cs_log("SignalAllocate: ErrorCode: %d SignalHandle: %x", ErrorCode, dev_list[i].SignalHandle); i++; if (i>=PTINUM) break; } closedir(dirp); if (i==0) return 0; pthread_mutex_init(&filter_lock, NULL); for (i=0;i<PTINUM;i++) { if (dev_list[i].SessionHandle==0) continue; struct read_thread_param *para; if (!cs_malloc(¶, sizeof(struct read_thread_param))) return 0; para->id=i; para->cli=cur_client(); int32_t ret = pthread_create(&dev_list[i].thread, NULL, stapi_read_thread, (void *)para); if(ret){ cs_log("ERROR: can't create stapi read thread (errno=%d %s)", ret, strerror(ret)); return 0; } else pthread_detach(dev_list[i].thread); } atexit(stapi_off); cs_log("liboscam_stapi v.%s initialized", oscam_stapi_LibVersion()); return 1; }
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; }