./ MultiCS.r82 / cli-camd35.c
/////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void camd35_send_keepalive(struct server_data *srv) { uint8_t buf[64]; #ifdef CACHEEX if (srv->cacheex_mode) { // Request Nodeid memset(buf, 0, 32); buf[0] = 0x3D; buf[1] = 12; memcpy( buf+20, cccam_nodeid, 8); camd35_sendto( srv->handle, srv->host->ip, srv->port, &srv->encryptkey, srv->ucrc, buf, 20+12); } else #endif { // keepalive uint8_t buf[64]; memset(buf,0, 21); buf[0] = 0x37; buf[1] = 1; camd35_sendto( srv->handle, srv->host->ip, srv->port, &srv->encryptkey, srv->ucrc, buf, 20+1); } } /////////////////////////////////////////////////////////////////////////////// int camd35_sendecm_srv(struct server_data *srv, ECM_DATA *ecm) { srv->ecm.msgid++; if (srv->ecm.msgid>0xfff) srv->ecm.msgid = 1; unsigned char buf[1024]; memset(buf, 0, 20); buf[0] = 0; // Command buf[1] = 0; // Length buf[8] = ecm->sid>>8; buf[9] = ecm->sid&0xff; buf[10] = ecm->caid>>8; buf[11] = ecm->caid&0xff; buf[12] = ecm->provid>>24; buf[13] = ecm->provid>>16; buf[14] = ecm->provid>>8; buf[15] = ecm->provid&0xff; buf[16] = srv->ecm.msgid>>8; buf[17] = srv->ecm.msgid; memcpy( buf+20, ecm->ecm, ecm->ecmlen); camd35_sendto( srv->handle, srv->host->ip, srv->port, &srv->encryptkey, srv->ucrc, buf, 20+ecm->ecmlen); return 1; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void camd35_srv_recvmsg(struct server_data *srv) { uint8_t cw[16]; struct cardserver_data *cs; struct sockaddr_in si_other; socklen_t slen = sizeof(si_other); unsigned char buf[1024]; int received = recvfrom( srv->handle, buf, sizeof(buf), 0, (struct sockaddr*)&si_other, &slen); if ( (received<20)||(received>1020) ) return; uint32_t ucrc = (buf[0]<<24)|(buf[1]<<16)|(buf[2]<<8)|buf[3]; //Check for client if (srv->ucrc!=ucrc) return; // aes_decrypt( &srv->decryptkey, buf+4, received-4); #ifdef DEBUG_NETWORK if (flag_debugnet) { unsigned int recv_ip; unsigned short recv_port; memcpy( &recv_ip, &si_other.sin_addr, 4); recv_port = ntohs(si_other.sin_port); debugf(0," camd35: Recv data (length=%d) from address (%s:%d)\n", received, ip2string(recv_ip), recv_port ); debughex(buf,received); } #endif switch (buf[4]) { case CAMD_ECM_REPLY: srv->lastdcwtime = GetTickCount(); if (!srv->busy) { debugf(getdbgflag(DBG_SERVER,0,srv->id)," [!] dcw error from camd35 server (%s:%d), unknown ecm request\n",srv->host->name,srv->port); break; } // if (buf[5]!=0x10) { debugf(getdbgflag(DBG_SERVER,0,srv->id)," [!] dcw error from camd35 server (%s:%d), wrong length!!!\n",srv->host->name,srv->port); break; } // Check for DCW if (!acceptDCW( buf+24 ) ) { srv->ecmerrdcw++; debugf(getdbgflag(DBG_SERVER,0,srv->id)," [!] dcw error from camd35 server (%s:%d), bad dcw!!!\n",srv->host->name,srv->port); break; } // Checl Stored ECM ECM_DATA *ecm = srv->ecm.request; if (!ecm) { debugf(getdbgflag(DBG_SERVER,0,srv->id)," [!] dcw error from camd35 server (%s:%d), ecm not found!!!\n",srv->host->name,srv->port); break; } // srv->busy = 0; pipe_cmd( prg.pipe.ecm[1], PIPE_SRV_AVAILABLE ); pthread_mutex_lock(&prg.lockecm); //### // check for ECM validity if (ecm->hash!=srv->ecm.hash) { debugf(getdbgflag(DBG_SERVER,0,srv->id)," [!] dcw error from camd35 server (%s:%d), ecm deleted!!!\n",srv->host->name,srv->port); pthread_mutex_unlock(&prg.lockecm); break; } srv->ecmok++; srv->lastecmoktime = GetTickCount()-srv->lastecmtime; srv->ecmoktime += srv->lastecmoktime; ecm_setsrvflagdcw( ecm, srv->id, ECM_SRV_REPLY_GOOD, buf+24 ); debugf(getdbgflagpro(DBG_SERVER,0,srv->id,ecm->cs->id)," <= cw from camd35 server (%s:%d) ch %04x:%06x:%04x (%dms)\n", srv->host->name,srv->port, ecm->caid,ecm->provid,ecm->sid, GetTickCount()-srv->lastecmtime); if (ecm->dcwstatus!=STAT_DCW_SUCCESS) { static char msg[] = "Good dcw from camd35 server"; ecm->statusmsg = msg; // Store ECM Answer ecm_setdcw( ecm, buf+24, DCW_SOURCE_SERVER, srv->id ); } else { //TODO: check same dcw between cards srv->ecmerrdcw ++; if ( memcmp( ecm->cw, buf+24, 16) ) debugf(getdbgflagpro(DBG_SERVER,0,srv->id,ecm->cs->id)," !!! different dcw from camd35 server (%s:%d)\n",srv->host->name,srv->port); } #ifdef SID_FILTER // ADD IN SID LIST cs= ecm->cs; if (cs) { cardsids_update( srv->busycard, ecm->provid, ecm->sid, 1); srv_cstatadd( srv, cs->id, 1 , srv->lastecmoktime); } #endif pthread_mutex_unlock(&prg.lockecm); //### break; case 0x44: srv->lastdcwtime = GetTickCount(); if (!srv->busy) { debugf(getdbgflag(DBG_SERVER,0,srv->id)," [!] dcw error from camd35 server (%s:%d), unknown ecm request\n",srv->host->name,srv->port); break; } // Checl Stored ECM ecm = srv->ecm.request; if (!ecm) { debugf(getdbgflag(DBG_SERVER,0,srv->id)," [!] dcw error from camd35 server (%s:%d), ecm not found!!!\n",srv->host->name,srv->port); break; } // srv->busy = 0; pipe_cmd( prg.pipe.ecm[1], PIPE_SRV_AVAILABLE ); pthread_mutex_lock(&prg.lockecm); //### // check for ECM validity if (ecm->hash!=srv->ecm.hash) { debugf(getdbgflag(DBG_SERVER,0,srv->id)," [!] dcw error from camd35 server (%s:%d), ecm deleted!!!\n",srv->host->name,srv->port); pthread_mutex_unlock(&prg.lockecm); break; } cs= ecm->cs; ecm_setsrvflag(ecm, srv->id, ECM_SRV_REPLY_FAIL); debugf(getdbgflagpro(DBG_SERVER,0,srv->id,ecm->cs->id)," <| decode failed from camd35 server (%s:%d) ch %04x:%06x:%04x (%dms)\n", srv->host->name,srv->port, ecm->caid,ecm->provid,ecm->sid, GetTickCount()-srv->lastecmtime); #ifdef SID_FILTER // ADD IN SID LIST if (cs) { cardsids_update( srv->busycard, ecm->provid, ecm->sid, -1); srv_cstatadd( srv, cs->id, 0 , 0); } #endif pthread_mutex_unlock(&prg.lockecm); //### wakeup_sendecm(); // Wakeup ecm waiting for availabe servers break; // Keepalive case CAMD_KEEPALIVE: srv->keepalive.status = 0; //debugf(0," server(camd35): Keepalive from (%s:%d)\n", srv->host->name, srv->port); if (srv->connection.status<=0) { debugf(0," connect to camd35 server (%s:%d)\n", srv->host->name, srv->port); srv->connection.status = 1; srv->connection.time = GetTickCount(); } break; // Request Nodeid case CAMD_CEX_IDREPLY: srv->keepalive.status = 0; //debugf(0," server(camd35): Got Nodeid from (%s:%d)\n", srv->host->name, srv->port); memcpy( srv->nodeid, buf+24, 8); if (srv->connection.status<=0) { char str[8*3+1]; array2hex( srv->nodeid, str, 8); debugf(0," connected to camd35 server (%s:%d), Nodeid = %s\n", srv->host->name, srv->port, str); srv->connection.status = 1; srv->connection.time = GetTickCount(); } break; #ifdef CACHEEX // push out case CAMD_CEX_PUSH: memcpy( cw, buf+44, 16); if (!acceptDCW(cw)) break; //srv->cacheex.totalrep++; struct cache_data cacheex; cacheex.sid = (buf[12]<<8)|buf[13]; cacheex.caid = (buf[14]<<8)|buf[15]; cacheex.provid = (buf[16]<<24)|(buf[17]<<16)|(buf[18]<<8)|buf[19]; // Look for cardserver cs = getcsbycaprovid(cacheex.caid, cacheex.provid); if ( !cs || !cs->option.fallowcacheex ) { srv->cacheex.badcw++; break; } if ((buf[23]&0xFE)==0x80) cacheex.tag = buf[23]; else cacheex.tag = 0; memcpy( cacheex.ecmd5, buf+24, 16); //if ( !checkECMD5(cacheex.ecmd5) ) cli->cacheex.totalcsp++; cacheex.hash = (buf[43]<<24) | (buf[42]<<16) | (buf[41]<<8) | buf[40]; if (!cacheex_check(&cacheex)) break; //debugf( getdbgflag(DBG_CACHEEX, 0, 0)," CACHEEX PUSH from client(%d) %04x:%06x:%04x (%08x)\n",cli->id,cacheex.caid,cacheex.provid,cacheex.sid,cacheex.hash); srv->cacheex.got[0]++; int uphop = buf[60]; if (uphop<10) srv->cacheex.got[uphop]++; // pthread_mutex_lock( &prg.lockcache ); int res = cache_setdcw( &cacheex, cw, NO_CYCLE, PEER_CACHEEX_SERVER | srv->id ); pthread_mutex_unlock( &prg.lockcache ); if (res&DCW_ERROR) { if ( !(res&DCW_SKIP)) srv->cacheex.badcw++; } else if (res&DCW_CYCLE) { if ( cs->option.cacheex.maxhop>uphop ) { uint8_t nodeid[8]; memcpy( nodeid, buf+61, 8); pipe_send_cacheex_push_cache(&cacheex, cw, nodeid); //cacheex_push(&cacheex, cw, nodeid); } } //debugf(0," camd35: push out from server %04x:%06x:%04x|%02x:%08x\n", cacheex.caid,cacheex.provid,cacheex.sid, cacheex.tag,cacheex.hash); break; #endif } } // CACHEEX MODE 2 void *camd35_srv_recvmsg_thread(struct server_data *srv) { srv->pid = syscall(SYS_gettid); while (!prg.restart) { if (srv->handle<=0) { srv->pid = 0; return NULL; } // struct pollfd pfd; pfd.fd = srv->handle; pfd.events = POLLIN | POLLPRI; int retval = poll(&pfd, 1, 3009); if (retval==0) continue; // timeout if (retval<0) { disconnect_srv(srv); srv->pid = 0; return NULL; } camd35_srv_recvmsg(srv); } return NULL; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// int camd35_connect_srv(struct server_data *srv, int fd) { uint8_t buf[64]; #ifdef CACHEEX if (srv->cacheex_mode) { // Request Nodeid memset(buf, 0, 32); buf[0] = CAMD_CEX_IDREQUEST; buf[1] = 12; memcpy( buf+20, cccam_nodeid, 8); camd35_sendto( fd, srv->host->ip, srv->port, &srv->encryptkey, srv->ucrc, buf, 20+12); struct pollfd pfd; pfd.fd = fd; pfd.events = POLLIN | POLLPRI; int ret = poll(&pfd, 1, 3000); while (ret>0) { struct sockaddr_in si_other; socklen_t slen = sizeof(si_other); unsigned char buf[1024]; int received = recvfrom( fd, buf, sizeof(buf), 0, (struct sockaddr*)&si_other, &slen); if ( (received<20)||(received>1020) ) break; uint32_t ucrc = (buf[0]<<24)|(buf[1]<<16)|(buf[2]<<8)|buf[3]; if (srv->ucrc!=ucrc) break; aes_decrypt( &srv->decryptkey, buf+4, received-4); if (buf[4]==CAMD_CEX_IDREPLY) { // good memcpy( srv->nodeid, buf+24, 8); array2hex( srv->nodeid, buf, 8); debugf(0," Connected to camd35 server (%s:%d), Nodeid = %s\n", srv->host->name, srv->port, buf); srv->connection.status = 1; srv->connection.time = GetTickCount(); srv->keepalive.status = 0; srv->keepalive.time = GetTickCount(); srv->handle = fd; if (srv->cacheex_mode==2) { if (!create_thread(&srv->tid, (threadfn)camd35_srv_recvmsg_thread, srv)) { disconnect_srv(srv); } } else pipe_wakeup( prg.pipe.cacheex[1] ); return 0; } break; } close(fd); } else #endif { // keepalive uint8_t buf[64]; memset(buf,0, 21); buf[0] = CAMD_KEEPALIVE; buf[1] = 1; camd35_sendto( fd, srv->host->ip, srv->port, &srv->encryptkey, srv->ucrc, buf, 20+1); struct pollfd pfd; pfd.fd = fd; pfd.events = POLLIN | POLLPRI; int ret = poll(&pfd, 1, 3000); while (ret>0) { struct sockaddr_in si_other; socklen_t slen = sizeof(si_other); unsigned char buf[1024]; int received = recvfrom( fd, buf, sizeof(buf), 0, (struct sockaddr*)&si_other, &slen); if ( (received<20)||(received>1020) ) break; uint32_t ucrc = (buf[0]<<24)|(buf[1]<<16)|(buf[2]<<8)|buf[3]; if (srv->ucrc!=ucrc) break; aes_decrypt( &srv->decryptkey, buf+4, received-4); if (buf[4]==CAMD_KEEPALIVE) { // good //SetUP Cards int count = 0; while (srv->sharelimits[count].caid!=0xFFFF) { struct cs_card_data *pcard = malloc( sizeof(struct cs_card_data) ); memset(pcard, 0, sizeof(struct cs_card_data) ); pcard->caid = srv->sharelimits[count].caid; pcard->nbprov = 1; pcard->prov[0] = srv->sharelimits[count].provid; pcard->uphops = srv->sharelimits[count].uphops; pcard->next = srv->card; srv->card = pcard; count++; } // debugf(0," Connected to camd35 server (%s:%d)\n", srv->host->name, srv->port); srv->connection.status = 1; srv->connection.time = GetTickCount(); srv->keepalive.status = 0; srv->keepalive.time = GetTickCount(); srv->handle = fd; #ifdef EPOLL_ECM pipe_pointer( prg.pipe.ecm[1], PIPE_SRV_CONNECTED, srv ); #else pipe_cmd( prg.pipe.ecm[1], PIPE_SRV_CONNECTED ); #endif return 0; } break; } close(fd); } return 1; }