./ MultiCS.r69 / srv-cccam.c
/////////////////////////////////////////////////////////////////////////////// // File: srv-cccam.c /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // PROTO /////////////////////////////////////////////////////////////////////////////// void *cc_connect_cli_thread(void *param); void cc_cli_recvmsg(struct cc_client_data *cli); struct cccamserver_data *getcccamserverbyid(uint32_t id) { struct cccamserver_data *cccam = cfg.cccam.server; while (cccam) { if (!(cccam->flags&FLAG_REMOVE)) if (cccam->id==id) return cccam; cccam = cccam->next; } return NULL; } struct cc_client_data *getcccamclientbyid(uint32_t id) { struct cccamserver_data *cccam = cfg.cccam.server; while (cccam) { if (!(cccam->flags&FLAG_REMOVE)) { struct cc_client_data *cli = cccam->client; while (cli) { if (!(cli->flags&FLAG_REMOVE)) if (cli->id==id) return cli; cli = cli->next; } } cccam = cccam->next; } return NULL; } struct cc_client_data *getcccamclientbyname(struct cccamserver_data *cccam, char *name) { if (!(cccam->flags&FLAG_REMOVE)) { struct cc_client_data *cli = cccam->client; while (cli) { if (!(cli->flags&FLAG_REMOVE)) if ( !strcmp(cli->user,name) ) return cli; cli = cli->next; } } return NULL; } /////////////////////////////////////////////////////////////////////////////// // CCCAM SERVER: DISCONNECT CLIENTS /////////////////////////////////////////////////////////////////////////////// void cc_disconnect_cli(struct cc_client_data *cli) { if (cli->handle>0) { debugf(getdbgflag(DBG_CCCAM,cli->srvid,cli->id)," CCcam: client '%s' disconnected \n", cli->user); close(cli->handle); cli->handle = INVALID_SOCKET; uint ticks = GetTickCount(); cli->uptime += ticks-cli->connected; cli->connected = ticks; // Last Seen } } /////////////////////////////////////////////////////////////////////////////// // CCCAM SERVER: CONNECT CLIENTS /////////////////////////////////////////////////////////////////////////////// unsigned int seed; uint8 fast_rnd() { unsigned int offset = 12923; unsigned int multiplier = 4079; seed = seed * multiplier + offset; return (uint8)(seed % 0xFF); } /////////////////////////////////////////////////////////////////////////////// int cc_sendinfo_cli(struct cc_client_data *cli, int sendversion) { uint8 buf[CC_MAXMSGSIZE]; memset(buf, 0, CC_MAXMSGSIZE); memcpy(buf, cfg.cccam.nodeid, 8 ); memcpy(buf + 8, cfg.cccam.version, 32); // cccam version (ascii) memcpy(buf + 40, cfg.cccam.build, 32); // build number (ascii) if (sendversion) { buf[38] = REVISION >> 8; buf[37] = REVISION & 0xff; buf[36] = 0; buf[35] = 'S'; buf[34] = 'C'; buf[33] = 'M'; } //debugdump(cfg.cccam.nodeid,8,"Sending server data version: %s, build: %s nodeid ", cfg.cccam.version, cfg.cccam.build); return cc_msg_send( cli->handle, &cli->sendblock, CC_MSG_SRV_INFO, 0x48, buf); } /////////////////////////////////////////////////////////////////////////////// int cc_sendcard_cli(struct cardserver_data *cs, struct cc_client_data *cli, int uphops) { uint8 buf[CC_MAXMSGSIZE]; memset(buf, 0, sizeof(buf)); buf[0] = cs->id >> 24; buf[1] = cs->id >> 16; buf[2] = cs->id >> 8; buf[3] = cs->id & 0xff; buf[4] = cs->id >> 24; buf[5] = cs->id >> 16; buf[6] = cs->id >> 8; buf[7] = cs->id & 0xff; buf[8] = cs->card.caid >> 8; buf[9] = cs->card.caid & 0xff; buf[10] = uphops; buf[11] = cli->dnhops; // Dnhops //buf[20] = cs->card.nbprov; int j; int nbprov = 0; for (j=0; j<cs->card.nbprov; j++) { if ( card_sharelimits(cli->sharelimits, cs->card.caid, cs->card.prov[j]) ) { //memcpy(buf + 21 + (j*7), card->provs[j], 7); buf[21+nbprov*7] = 0xff&(cs->card.prov[j]>>16); buf[22+nbprov*7] = 0xff&(cs->card.prov[j]>>8); buf[23+nbprov*7] = 0xff&(cs->card.prov[j]); /* buf[24+nbprov*7] = 0xff&(cs->card.prov[j].ua>>24); buf[25+nbprov*7] = 0xff&(cs->card.prov[j].ua>>16); buf[26+nbprov*7] = 0xff&(cs->card.prov[j].ua>>8); buf[27+nbprov*7] = 0xff&(cs->card.prov[j].ua); */ nbprov++; } } if (!nbprov) return 0; // Denied buf[20] = nbprov; buf[21 + (nbprov*7)] = 1; memcpy(buf + 22 + (nbprov*7), cfg.cccam.nodeid, 8); cc_msg_send( cli->handle, &cli->sendblock, CC_MSG_CARD_ADD, 30 + (nbprov*7), buf); return 1; } /////////////////////////////////////////////////////////////////////////////// void cc_sendcards_cli(struct cc_client_data *cli) { int nbcard=0; struct cardserver_data *cs = cfg.cardserver; int i; if (cli->csport[0]) { for(i=0;i<MAX_CSPORTS;i++) { if(cli->csport[i]) { cs = getcsbyport(cli->csport[i]); if (cs) if (cc_sendcard_cli(cs, cli,0)) nbcard++; } else break; } } else if (cfg.cccam.csport[0]) { for(i=0;i<MAX_CSPORTS;i++) { if(cfg.cccam.csport[i]) { cs = getcsbyport(cfg.cccam.csport[i]); if (cs) if (cc_sendcard_cli(cs, cli,0)) nbcard++; } else break; } } else { while (cs) { if (cc_sendcard_cli(cs, cli,0)) nbcard++; cs = cs->next; } } debugf(getdbgflag(DBG_CCCAM,cli->srvid,cli->id)," CCcam: %d cards --> client(%s)\n", nbcard, cli->user); } struct cc_connect_cli_data { struct cccamserver_data *cccam; int sock; uint32 ip; }; /////////////////////////////////////////////////////////////////////////////// void *cc_connect_cli(struct cc_connect_cli_data *param) { uint8 buf[CC_MAXMSGSIZE]; uint8 data[20]; int i; struct cc_crypt_block sendblock; // crypto state block struct cc_crypt_block recvblock; // crypto state block char usr[64]; char pwd[255]; // Store data from param struct cccamserver_data *cccam = param->cccam; int sock = param->sock; uint32 ip = param->ip; free(param); #ifdef CHECK_HACKER struct ip_hacker_data *iplist = iplist_get( ip ); iplist->nbconn++; if (iplist->count>0) { if ( (GetTickCount()-iplist->lastseen)<(1000*iplist->count) ) { close(sock); return NULL; } if (iplist->count>10) if ( (GetTickCount()-iplist->lastseen)<(5000*iplist->count) ) { close(sock); return NULL; } if (iplist->count>20) if ( (GetTickCount()-iplist->lastseen)<(20000*iplist->count) ) { close(sock); return NULL; } if (iplist->count>30) if ( (GetTickCount()-iplist->lastseen)<(60000*iplist->count) ) { close(sock); return NULL; } } iplist->lastseen = GetTickCount(); iplist->count++; #endif memset(usr, 0, sizeof(usr)); memset(pwd, 0, sizeof(pwd)); // create & send random seed for(i=0; i<12; i++ ) data[i]=fast_rnd(); // Create Multics ID data[3] = (data[0]^'M') + data[1] + data[2]; data[7] = data[4] + (data[5]^'C') + data[6]; data[11] = data[8] + data[9] + (data[10]^'S'); //Create checksum for "O" cccam: for (i = 0; i < 4; i++) { data[12 + i] = (data[i] + data[4 + i] + data[8 + i]) & 0xff; } send_nonb(sock, data, 16, 100); //XOR init bytes with 'CCcam' cc_crypt_xor(data); //SHA1 SHA_CTX ctx; SHA1_Init(&ctx); SHA1_Update(&ctx, data, 16); SHA1_Final(buf, &ctx); //init crypto states cc_crypt_init(&sendblock, buf, 20); cc_decrypt(&sendblock, data, 16); cc_crypt_init(&recvblock, data, 16); cc_decrypt(&recvblock, buf, 20); //debugdump(buf, 20, "CCcam: SHA1 hash:"); memcpy(usr,buf,20); if ((i=recv_nonb(sock, buf, 20,3000)) == 20) { #ifdef DEBUG_NETWORK if (flag_debugnet) { debugf(getdbgflag(DBG_CCCAM,cccam->id,0)," CCcam%d: receive SHA1 hash %d\n", cccam->id, i); debughex(buf,i); } #endif cc_decrypt(&recvblock, buf, 20); //debugf(getdbgflag(DBG_CCCAM,cccam->id,0)," Decrypted SHA1 hash (20):\n"); debughex(buf,20); if ( memcmp(buf,usr,20)!=0 ) { //debugf(getdbgflag(DBG_CCCAM,cccam->id,0)," cc_connect_cli(): wrong sha1 hash from client! (%s)\n",ip2string(ip)); close(sock); return NULL; } } else { //debugf(getdbgflag(DBG_CCCAM,cccam->id,0)," cc_connect_cli(): recv sha1 timeout\n"); close(sock); return NULL; } // receive username i = recv_nonb(sock, buf, 20,3000); #ifdef DEBUG_NETWORK if (flag_debugnet) { debugf(getdbgflag(DBG_CCCAM,cccam->id,0)," CCcam%d: receive username %d\n", cccam->id, i); debughex(buf,i); } #endif if (i == 20) { cc_decrypt(&recvblock, buf, i); memcpy(usr,buf,20); //strcpy(usr, (char*)buf); //debugf(getdbgflag(DBG_CCCAM,cccam->id,0)," cc_connect_cli(): username '%s'\n", usr); } else { //debugf(getdbgflag(DBG_CCCAM,cccam->id,0)," cc_connect_cli(): recv user timeout\n"); close(sock); return NULL; } #ifdef CHECK_HACKER strcpy(iplist->user,usr); #endif // Check for username pthread_mutex_lock(&prg.lockcccli); int found = 0; struct cc_client_data *cli = cccam->client; while (cli) { if (!strcmp(cli->user,usr)) { if (IS_DISABLED(cli->flags)) { // Connect only enabled clients pthread_mutex_unlock(&prg.lockcccli); debugf(getdbgflag(DBG_CCCAM,cli->srvid,cli->id)," CCcam%d: connection refused for client '%s' (%s), client disabled\n", cccam->id, usr, ip2string(ip)); close(sock); return NULL; } found = 1; break; } cli = cli->next; } pthread_mutex_unlock(&prg.lockcccli); if (!found) { debugf(getdbgflag(DBG_CCCAM,cccam->id,0)," CCcam%d: Unknown Client '%s' (%s)\n", cccam->id, usr, ip2string(ip)); close(sock); return NULL; } // Check for Host if (cli->host) { struct host_data *host = cli->host; host->clip = ip; if ( host->ip && (host->ip!=ip) ) { uint sec = getseconds()+60; if ( host->checkiptime > sec ) host->checkiptime = sec; debugf(getdbgflag(DBG_CCCAM,cli->srvid,cli->id)," CCcam%d: Aborted connection from Client '%s' (%s), ip refused\n", cccam->id, usr, ip2string(ip)); cli->nbloginerror++; close(sock); return NULL; } } // Encrypted Password if ((i=recv_nonb(sock, buf, 6,3000)) == 6) { memset(pwd, 0, sizeof(pwd)); strcpy(pwd, cli->pass); cc_encrypt(&recvblock, (uint8*)pwd, strlen(pwd)); cc_decrypt(&recvblock, buf, 6); if ( memcmp(buf,"CCcam\0",6) ) { debugf(getdbgflag(DBG_CCCAM,cli->srvid,cli->id)," CCcam%d: login failed from client '%s'\n", cccam->id, usr); cli->nbloginerror++; close(sock); return NULL; } } else { debugf(getdbgflag(DBG_CCCAM,cli->srvid,cli->id)," CCcam%d: login failed from client '%s', error receiving crypted password\n", cccam->id, usr); cli->nbloginerror++; close(sock); return NULL; } if (cli->ip==ip) cli->nbdiffip++; // Disconnect old connection if isthere any if (cli->handle>0) { if (cli->ip==ip) { debugf(getdbgflag(DBG_CCCAM,cli->srvid,cli->id)," CCcam%d: Client '%s' (%s) already connected\n", cccam->id, usr, ip2string(ip)); cc_disconnect_cli(cli); } else { if ( (GetTickCount()-cli->lastecmtime) < 60000 ) { debugf(getdbgflag(DBG_CCCAM,cli->srvid,cli->id)," CCcam%d: Client '%s' (%s) already connected with different ip, Connection aborted for recent activity\n", cccam->id, usr, ip2string(ip)); cli->nbloginerror++; close(sock); return NULL; } debugf(getdbgflag(DBG_CCCAM,cli->srvid,cli->id)," CCcam%d: Client '%s' (%s) already connected with different ip \n", cccam->id, usr, ip2string(ip)); cc_disconnect_cli(cli); } } cli->nblogin++; // Send passwd ack memset(buf, 0, 20); memcpy(buf, "CCcam\0", 6); //debugf(getdbgflag(DBG_CCCAM,cli->srvid,cli->id),"Server: send ack '%s'\n",buf); cc_encrypt(&sendblock, buf, 20); send_nonb(sock, buf, 20, 100); //cli->ecmnb=0; //cli->ecmok=0; memcpy(&cli->sendblock,&sendblock,sizeof(sendblock)); memcpy(&cli->recvblock,&recvblock,sizeof(recvblock)); debugf(getdbgflag(DBG_CCCAM,cli->srvid,cli->id)," CCcam%d: client '%s' connected\n", cccam->id, usr); // Recv cli data memset(buf, 0, sizeof(buf)); i = cc_msg_recv( sock, &cli->recvblock, buf, 3000); if ( i<65 ) { debugf(getdbgflag(DBG_CCCAM,cli->srvid,cli->id)," CCcam%d: Error recv cli data (%d)\n", cccam->id,i); debughex(buf,i); close(sock); return NULL; } // Setup Client Data // pthread_mutex_lock(&prg.lockcccli); memcpy( cli->nodeid, buf+24, 8); memcpy( cli->version, buf+33, 31); memcpy( cli->build, buf+65, 31 ); debugf(getdbgflag(DBG_CCCAM,cli->srvid,cli->id)," CCcam%d: client '%s' running version %s build %s\n", cccam->id, usr, cli->version, cli->build); // cli->nodeid,8, cli->cardsent = 0; cli->ecm.busy = 0; cli->connected = cli->lastactivity = cli->lastecmtime = GetTickCount(); cli->ip = ip; cli->chkrecvtime = 0; cli->handle = sock; #ifdef CHECK_HACKER iplist->count = 10; // for reconnect #endif // pthread_mutex_unlock(&prg.lockcccli); // send cli data ack cc_msg_send( sock, &cli->sendblock, CC_MSG_CLI_INFO, 0, NULL); //cc_msg_send( sock, &cli->sendblock, CC_MSG_BAD_ECM, 0, NULL); int sendversion = ( (cli->version[28]=='W')&&(cli->version[29]='H')&&(cli->version[30]='O') ); cc_sendinfo_cli(cli, sendversion); //cc_msg_send( sock, &cli->sendblock, CC_MSG_BAD_ECM, 0, NULL); cli->cardsent = 1; //TODO: read from client packet CC_MSG_BAD_ECM //len = cc_msg_recv(cli->handle, &cli->recvblock, buf, 3); usleep(10000); cc_sendcards_cli(cli); cli->handle = sock; pipe_wakeup( srvsocks[1] ); return cli; } //////////////////////////////////////////////////////////////////////////////// void *cc_connect_cli_thread(void *param) { SOCKET client_sock =-1; struct sockaddr_in client_addr; socklen_t socklen = sizeof(client_addr); pthread_t srv_tid; while(1) { pthread_mutex_lock(&prg.locksrvcc); struct pollfd pfd[MAX_CSPORTS]; int pfdcount = 0; struct cccamserver_data *cccam = cfg.cccam.server; while (cccam) { if ( !IS_DISABLED(cccam->flags) && (cccam->handle>0) ) { cccam->ipoll = pfdcount; pfd[pfdcount].fd = cccam->handle; pfd[pfdcount++].events = POLLIN | POLLPRI; } else cccam->ipoll = -1; cccam = cccam->next; } int retval = poll(pfd, pfdcount, 3000); if (retval>0) { struct cccamserver_data *cccam = cfg.cccam.server; while (cccam) { if ( !IS_DISABLED(cccam->flags) && (cccam->handle>0) && (cccam->ipoll>=0) && (cccam->handle==pfd[cccam->ipoll].fd) ) { if ( pfd[cccam->ipoll].revents & (POLLIN|POLLPRI) ) { client_sock = accept( cccam->handle, (struct sockaddr*)&client_addr, /*(socklen_t*)*/&socklen); if ( client_sock<=0 ) { debugf(getdbgflag(DBG_CCCAM,cccam->id,0)," CCcam%d: Accept failed (errno=%d)\n", cccam->id,errno); //usleep(30000); } else { ///SetSocketKeepalive(client_sock); no keepalive debugf(getdbgflag(DBG_CCCAM,cccam->id,0)," CCcam%d: new connection (%s)\n", cccam->id, ip2string(client_addr.sin_addr.s_addr) ); struct cc_connect_cli_data *clicondata = malloc( sizeof(struct cc_connect_cli_data) ); clicondata->cccam = cccam; clicondata->sock = client_sock; clicondata->ip = client_addr.sin_addr.s_addr; create_prio_thread(&srv_tid, (threadfn)cc_connect_cli,clicondata, 50); } } } cccam = cccam->next; } } pthread_mutex_unlock(&prg.locksrvcc); usleep(3000); }// While } /////////////////////////////////////////////////////////////////////////////// // CCCAM SERVER: RECEIVE MESSAGES FROM CLIENTS /////////////////////////////////////////////////////////////////////////////// void cc_store_ecmclient(int ecmid, struct cc_client_data *cli) { uint32 ticks = GetTickCount(); cli->ecm.dcwtime = cli->dcwtime; cli->ecm.recvtime = ticks; cli->ecm.id = ecmid; cli->ecm.status = STAT_ECM_SENT; ecm_addip(ecmid, cli->ip); } /////////////////////////////////////////////////////////////////////////////// // Receive messages from client void cc_cli_recvmsg(struct cc_client_data *cli) { unsigned char buf[CC_MAXMSGSIZE]; unsigned char data[CC_MAXMSGSIZE]; // for other use unsigned int cardid; int len; if (cli->handle>0) { len = cc_msg_chkrecv(cli->handle,&cli->recvblock); if (len==0) { debugf(getdbgflag(DBG_CCCAM,cli->srvid,cli->id)," CCcam: client '%s' read failed %d\n", cli->user,len); cc_disconnect_cli(cli); } else if (len==-1) { if (!cli->chkrecvtime) cli->chkrecvtime = GetTickCount(); else if ( (cli->chkrecvtime+500)<GetTickCount() ) { debugf(getdbgflag(DBG_CCCAM,cli->srvid,cli->id)," CCcam: client '%s' read failed %d\n", cli->user,len); cc_disconnect_cli(cli); } } else if (len>0) { cli->chkrecvtime = 0; len = cc_msg_recv( cli->handle, &cli->recvblock, buf, 3); if (len==0) { debugf(getdbgflag(DBG_CCCAM,cli->srvid,cli->id)," CCcam: client '%s' read failed %d\n", cli->user,len); cc_disconnect_cli(cli); } else if (len<0) { debugf(getdbgflag(DBG_CCCAM,cli->srvid,cli->id)," CCcam: client '%s' read failed %d(%d)\n", cli->user,len,errno); cc_disconnect_cli(cli); } else if (len>0) { cli->lastactivity = GetTickCount(); switch (buf[1]) { case CC_MSG_ECM_REQUEST: cli->ecmnb++; cli->lastecmtime = GetTickCount(); if (cli->ecm.busy) { // send decode failed cli->ecmdenied++; cc_msg_send( cli->handle, &cli->sendblock, CC_MSG_ECM_NOK2, 0, NULL); debugf(getdbgflag(DBG_CCCAM,cli->srvid,cli->id)," <|> decode failed to CCcam client '%s', too many ecm requests\n", cli->user); break; } //Check for card availability memcpy( data, buf+17, len-17); cardid = buf[10]<<24 | buf[11]<<16 | buf[12]<<8 | buf[13]; uint16 caid = buf[4]<<8 | buf[5]; uint16 sid = buf[14]<<8 | buf[15]; uint32_t provid = ecm_getprovid( data, caid ); if (provid==0) provid = buf[6]<<24 | buf[7]<<16 | buf[8]<<8 | buf[9]; // Check for Profile struct cardserver_data *cs=getcsbyid( cardid ); if (!cs) { // check for cs by caid:prov cs = getcsbycaidprov(caid,provid); if (!cs) { cli->ecmdenied++; cc_msg_send( cli->handle, &cli->sendblock, CC_MSG_ECM_NOK2, 0, NULL); debugf(getdbgflag(DBG_CCCAM,cli->srvid,cli->id)," <|> decode failed to CCcam client '%s', card-id %x (%04x:%06x) not found\n",cli->user, cardid, caid,provid); break; } } char *error = cs_accept_ecm(cs,caid,provid,sid,ecm_getchid(data,caid)); if (error) { cs->ecmdenied++; cli->ecmdenied++; cc_msg_send( cli->handle, &cli->sendblock, CC_MSG_ECM_NOK2, 0, NULL); debugf(getdbgflagpro(DBG_CCCAM,cli->srvid,cli->id,cs->id)," <|> decode failed to CCcam client '%s' ch %04x:%06x:%04x, %s\n", cli->user, caid,provid,sid, error); break; } // Check ECM length if ( !accept_ecmlen(len) ) { cli->ecmdenied++; cs->ecmdenied++; buf[1] = 0; buf[2] = 0; cc_msg_send( cli->handle, &cli->sendblock, CC_MSG_ECM_NOK2, 0, NULL); debugf(getdbgflagpro(DBG_CCCAM,cli->srvid,cli->id,cs->id)," <|> decode failed to CCcam client '%s' ch %04x:%06x:%04x, ecm length error(%d)\n", cli->user,caid,provid,sid, len); break; } // ACCEPTED //cs->ecmaccepted++; //cli->ecmaccepted++; // XXX: check ecm tag = 0x80,0x81 pthread_mutex_lock(&prg.lockecm); // Search for ECM int ecmid = search_ecmdata_dcw( data, len-17, sid); // dont get failed ecm request from cache if ( ecmid!=-1 ) { ECM_DATA *ecm=getecmbyid(ecmid); ecm->lastrecvtime = GetTickCount(); //TODO: Add another card for sending ecm cc_store_ecmclient(ecmid, cli); debugf(getdbgflagpro(DBG_CCCAM,cli->srvid,cli->id,cs->id)," <- ecm from CCcam client '%s' ch %04x:%06x:%04x*\n", cli->user, caid, provid, sid); cli->ecm.busy=1; cli->ecm.hash = ecm->hash; cli->ecm.cardid = cardid; } else { cs->ecmaccepted++; // Setup ECM Request for Server(s) ecmid = store_ecmdata(cs->id, &data[0], len-17, sid, caid, provid); ECM_DATA *ecm=getecmbyid(ecmid); cc_store_ecmclient(ecmid, cli); debugf(getdbgflagpro(DBG_CCCAM,cli->srvid,cli->id,cs->id)," <- ecm from CCcam client '%s' ch %04x:%06x:%04x (>%dms)\n",cli->user,caid,provid,sid, cli->ecm.dcwtime); cli->ecm.busy=1; cli->ecm.hash = ecm->hash; cli->ecm.cardid = cardid; if (cs->option.fallowcache && cfg.cache.peer) { pipe_send_cache_find(ecm, cs); ecm->waitcache = 1; ecm->dcwstatus = STAT_DCW_WAITCACHE; } else ecm->dcwstatus = STAT_DCW_WAIT; } checkfreeze_checkECM( ecmid, cli->ecm.lastid); ecm_check_time = cc_dcw_check_time = 0; pthread_mutex_unlock(&prg.lockecm); break; case CC_MSG_KEEPALIVE: //printf(" Keepalive from client '%s'\n",cli->user); cc_msg_send( cli->handle, &cli->sendblock, CC_MSG_KEEPALIVE, 0, NULL); break; case CC_MSG_BAD_ECM: //debugf(getdbgflag(DBG_CCCAM,cli->srvid,cli->id)," CCcam: cmd 0x05 ACK from client '%s'\n",cli->user); //if (cli->cardsent==0) { // cc_sendcards_cli(cli); // cli->cardsent=1; //} break; //default: debugf(getdbgflag(DBG_CCCAM,cli->srvid,cli->id)," CCcam: Unknown Packet ID : %02x from client '%s'\n", buf[1],cli->user); } } } } } //////////////////////////////////////////////////////////////////////////////// // CCCAM SERVER: SEND DCW TO CLIENTS //////////////////////////////////////////////////////////////////////////////// void cc_senddcw_cli(struct cc_client_data *cli) { unsigned char buf[CC_MAXMSGSIZE]; if (cli->ecm.status==STAT_DCW_SENT) { debugf(getdbgflag(DBG_CCCAM,cli->srvid,cli->id)," +> cw send failed to CCcam client '%s', cw already sent\n", cli->user); return; } if (cli->handle<=0) { debugf(getdbgflag(DBG_CCCAM,cli->srvid,cli->id)," +> cw send failed to CCcam client '%s', client disconnected\n", cli->user); return; } if (!cli->ecm.busy) { debugf(getdbgflag(DBG_CCCAM,cli->srvid,cli->id)," +> cw send failed to CCcam client '%s', no ecm request\n", cli->user); return; } ECM_DATA *ecm = getecmbyid(cli->ecm.id); //FREEZE int enablefreeze=0; if ( (cli->ecm.lastcaid==ecm->caid)&&(cli->ecm.lastprov==ecm->provid)&&(cli->ecm.lastsid==ecm->sid) ) { if ( (cli->ecm.laststatus=1)&&(cli->lastdcwtime+200<GetTickCount()) ) enablefreeze = 1; } else cli->zap++; // cli->ecm.lastcaid = ecm->caid; cli->ecm.lastprov = ecm->provid; cli->ecm.lastsid = ecm->sid; cli->ecm.lastdecodetime = GetTickCount()-cli->ecm.recvtime; cli->ecm.lastid = cli->ecm.id; if ( (ecm->dcwstatus==STAT_DCW_SUCCESS)&&(ecm->hash==cli->ecm.hash) ) { cli->ecm.lastdcwsrctype = ecm->dcwsrctype; cli->ecm.lastdcwsrcid = ecm->dcwsrcid; cli->ecm.laststatus=1; cli->ecmok++; cli->lastdcwtime = GetTickCount(); cli->ecmoktime += GetTickCount()-cli->ecm.recvtime; //cli->lastecmoktime = GetTickCount()-cli->ecm.recvtime; memcpy( buf, ecm->cw, 16 ); cc_crypt_cw( cli->nodeid, cli->ecm.cardid , buf); cc_msg_send( cli->handle, &cli->sendblock, CC_MSG_ECM_REQUEST, 16, buf); cc_encrypt(&cli->sendblock, buf, 16); // additional crypto step debugf(getdbgflagpro(DBG_CCCAM,cli->srvid,cli->id,ecm->csid)," => cw to CCcam client '%s' ch %04x:%06x:%04x (%dms)\n", cli->user, ecm->caid,ecm->provid,ecm->sid, GetTickCount()-cli->ecm.recvtime); } else { //if (ecm->data->dcwstatus==STAT_DCW_FAILED) if (enablefreeze) { cli->freeze++; /* fdebugf( "## FREEZE:\nClient: %s - CHN: %04X:%06X:%04X (%dms)\n", cli->user, ecm->caid, ecm->provid, ecm->sid, GetTickCount()-cli->ecm.recvtime); char http_buf[4048]; array2hex( ecm->ecm, http_buf, ecm->ecmlen); fdebugf( "ECM: %s\n", http_buf); #ifdef CHECK_NEXTDCW if ( (ecm->lastdecode.status>0)&&(ecm->lastdecode.counter>0) ) { array2hex( ecm->lastdecode.dcw, http_buf, 16 ); fdebugf( "Last DCW: %s\n", http_buf); fdebugf( "Total wrong DCW = %d\n", ecm->lastdecode.error); fdebugf( "Total Consecutif DCW = %d\nECM Interval = %ds\n", ecm->lastdecode.counter, ecm->lastdecode.dcwchangetime/1000); } #endif if (ecm->server[0].srvid) { int i; for(i=0; i<20; i++) { if (!ecm->server[i].srvid) break; char* str_srvstatus[] = { "WAIT", "OK", "NOK", "BUSY" }; struct cs_server_data *srv = getsrvbyid(ecm->server[i].srvid); if (srv) { fdebugf( "%d (%s:%d) -> %s (%dms)", i+1, srv->host->name, srv->port, str_srvstatus[ecm->server[i].flag], ecm->server[i].sendtime - ecm->recvtime ); // Recv Time if (ecm->server[i].statustime>ecm->server[i].sendtime) fdebugf( " from %dms to %dms", ecm->server[i].statustime - ecm->recvtime, ecm->server[i].statustime-ecm->server[i].sendtime ); // DCW if (ecm->server[i].flag==ECM_SRV_REPLY_GOOD) { array2hex( ecm->server[i].dcw, http_buf, 16 ); fdebugf( "DCW: %s", http_buf); } fdebugf( "\n"); } } } */ } cli->ecm.lastdcwsrctype = DCW_SOURCE_NONE; cli->ecm.lastdcwsrcid = 0; cli->ecm.laststatus=0; cc_msg_send( cli->handle, &cli->sendblock, CC_MSG_ECM_NOK1, 0, NULL); debugf(getdbgflagpro(DBG_CCCAM,cli->srvid,cli->id,ecm->csid)," |> decode failed to CCcam client '%s' ch %04x:%06x:%04x (%dms)\n", cli->user, ecm->caid,ecm->provid,ecm->sid, GetTickCount()-cli->ecm.recvtime); } cli->ecm.busy=0; cli->ecm.status = STAT_DCW_SENT; } /////////////////////////////////////////////////////////////////////////////// // Check sending cw to clients uint32 cc_check_sendcw() { uint restime = GetTickCount() + 10000; uint clitime = 0; struct cccamserver_data *cccam = cfg.cccam.server; while (cccam) { if ( !IS_DISABLED(cccam->flags) && (cccam->handle>0) ) { struct cc_client_data *cli = cccam->client; uint ticks = GetTickCount(); while (cli) { if ( !IS_DISABLED(cli->flags)&&(cli->handle>0)&&(cli->ecm.busy) ) { //&&(cli->ecm.status==STAT_ECM_SENT) ) { clitime = ticks+11000; pthread_mutex_lock(&prg.lockecm); //### // Check for DCW ANSWER ECM_DATA *ecm = getecmbyid(cli->ecm.id); if (ecm->hash!=cli->ecm.hash) cc_senddcw_cli( cli ); // Check for FAILED if (ecm->dcwstatus==STAT_DCW_FAILED) { static char msg[] = "decode failed"; cli->ecm.statmsg=msg; cc_senddcw_cli( cli ); } // Check for SUCCESS else if (ecm->dcwstatus==STAT_DCW_SUCCESS) { // check for client allowed cw time if ( (cli->ecm.recvtime+cli->ecm.dcwtime)<=ticks ) { static char msg[] = "good dcw"; cli->ecm.statmsg = msg; cc_senddcw_cli( cli ); } else clitime = cli->ecm.recvtime+cli->ecm.dcwtime; } // check for timeout / no server again else if (ecm->dcwstatus==STAT_DCW_WAIT){ uint32 timeout; struct cardserver_data *cs = getcsbyid( ecm->csid); if (cs) timeout = cs->option.dcw.timeout; else timeout = 5700; if ( (cli->ecm.recvtime+timeout) < ticks ) { static char msg[] = "dcw timeout"; cli->ecm.statmsg=msg; cc_senddcw_cli( cli ); } else clitime = cli->ecm.recvtime+timeout; } if (restime>clitime) restime = clitime; pthread_mutex_unlock(&prg.lockecm); //### } cli = cli->next; } } cccam = cccam->next; } return (restime+1); } /////////////////////////////////////////////////////////////////////////////// // CCCAM SERVER: START/STOP /////////////////////////////////////////////////////////////////////////////// pthread_t cc_cli_tid; int start_thread_cccam() { create_prio_thread(&cc_cli_tid, cc_connect_cli_thread, NULL, 50); // Lock server return 0; } void done_cccamsrv() { // if (close(cfg.cccam.handle)) debugf(getdbgflag(DBG_CCCAM,cccam->id,0),"Close failed(%d)",cfg.cccam.handle); }