./ MultiCS.r69 / main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/prctl.h>
#include <netdb.h>
#include <errno.h>
#include <pthread.h>
#include <poll.h>
#include <signal.h>
#include "common.h"
#include "tools.h"
#include "debug.h"
#include "sockets.h"
#include "threads.h"
#include "convert.h"
#include "des.h"
#include "md5.h"
#include "sha1.h"
#include "msg-newcamd.h"
#ifdef CCCAM
#include "msg-cccam.h"
#endif
#ifdef RADEGAST
#include "msg-radegast.h"
#endif
#include "ecmdata.h"
#include "parser.h"
#include "config.h"
#include "httpserver.h"
char config_file[256] = "/var/etc/multics.cfg";
char cccam_nodeid[8];
int flag_debugscr;
#ifdef DEBUG_NETWORK
int flag_debugnet;
#endif
int flag_debugfile;
char debug_file[256];
char sms_file[256];
///
///
struct config_data cfg;
struct program_data prg;
uint ecm_check_time = 0;
uint cs_dcw_check_time = 0;
#ifdef MGCAMD_SRV
uint mg_dcw_check_time = 0;
#endif
#ifdef CCCAM_SRV
uint cc_dcw_check_time = 0;
#endif
#ifdef FREECCCAM_SRV
uint frcc_dcw_check_time = 0;
#endif
#ifdef RADEGAST_SRV
uint rdgd_dcw_check_time = 0;
#endif
#ifdef CHECK_HACKER
struct ip_hacker_data *iplist_get( uint32 ip )
{
struct ip_hacker_data *iplist = prg.iplist;
while (iplist) {
if (iplist->ip==ip) return iplist;
iplist = iplist->next;
}
iplist = malloc( sizeof(struct ip_hacker_data) );
memset(iplist, 0, sizeof(struct ip_hacker_data) );
iplist->ip = ip;
iplist->next = prg.iplist;
prg.iplist = iplist;
return iplist;
}
#endif
///////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////
// 0: different ; 1:~equivalent
int cmp_cards( struct cs_card_data* card1, struct cs_card_data* card2)
{
int i,j,found;
int nbsame = 0;
int nbdiff = 0;
if (card1->caid!=card2->caid) return 0;
/*
if ( ((card1->caid & 0xff00)==0x1800)
|| ((card1->caid & 0xff00)==0x0900)
|| ((card1->caid & 0xff00)==0x0b00) ) return 1;
*/
if ( ((card1->caid & 0xff00)!=0x0100) && ((card1->caid & 0xff00)!=0x0500) ) return 1;
for(i=0; i<card1->nbprov;i++) {
found = 0;
for(j=0; j<card2->nbprov;j++)
if (card1->prov[i]==card2->prov[j]) {
found = 1;
break;
}
if (found) nbsame++; else nbdiff++;
}
if ( (nbsame==card1->nbprov)||(nbsame==card2->nbprov) ) return 1;
return 0;
}
// Get Any card to decode
struct cs_card_data *srv_findcard( struct cs_server_data *srv, struct cardserver_data *cs, uint16 ecmcaid, uint32 ecmprov)
{
// check for card to decode
struct cs_card_data *pcard = srv->card;
struct cs_card_data *selcard = NULL;
int i;
while (pcard) {
if ( ecmcaid == pcard->caid ) {
for (i=0; i<pcard->nbprov;i++) if (ecmprov==pcard->prov[i]) break;
if ( ( i<pcard->nbprov ) || ( cs && cmp_cards(pcard, &cs->card) ) ) {
if (srv->type==TYPE_NEWCAMD) {
selcard = pcard;
break;
}
else if (srv->type==TYPE_CCCAM) { // select card on hop1 if is there
if (selcard) {
if (pcard->uphops<selcard->uphops) selcard = pcard;
else if (pcard->uphops==selcard->uphops) {
// Get Stable Card
if (pcard->shareid<selcard->shareid) selcard = pcard;
}
} else selcard = pcard;
}
if (srv->type==TYPE_RADEGAST) {
selcard = pcard;
break;
}
else break;
}
}
pcard = pcard->next;
}
return selcard;
}
void srv_cstatadd( struct cs_server_data *srv, int csid, int ok, uint32 ecmoktime)
{
int i;
for(i=0; i<MAX_CSPORTS; i++) {
if (!srv->cstat[i].csid) {
srv->cstat[i].csid = csid;
srv->cstat[i].ecmnb = 1;
if (ok) {
srv->cstat[i].ecmok = 1;
srv->cstat[i].ecmoktime = ecmoktime;
}
else {
srv->cstat[i].ecmok = 0;
srv->cstat[i].ecmoktime = 0;
}
break;
}
else if (srv->cstat[i].csid==csid) {
srv->cstat[i].ecmnb++;
if (ok) {
srv->cstat[i].ecmok++;
srv->cstat[i].ecmoktime += ecmoktime;
}
break;
}
}
}
int card_sharelimits(struct sharelimit_data sharelimits[100], uint16_t caid, uint32_t provid)
{
int i;
int uphops1 = 10; // for 0:0
int uphops2 = 10; // for caid:0
for (i=0; i<100; i++) {
if (sharelimits[i].caid==0xffff) break;
if (!sharelimits[i].caid) {
if (!sharelimits[i].provid) uphops1 = sharelimits[i].uphops;
}
else if (sharelimits[i].caid==caid) {
if (sharelimits[i].provid==provid) return sharelimits[i].uphops;
else if (!sharelimits[i].provid) uphops2 = sharelimits[i].uphops;
}
}
if (uphops2<uphops1) return uphops2; else return uphops1;// Max UPHOPS
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
#ifdef SID_FILTER
// check for card existance
int istherecard(struct cs_server_data *srv, struct cs_card_data *acard)
{
struct cs_card_data *card = srv->card;
while(card) {
if (card==acard) return 1;
card = card->next;
}
return 0;
}
int match_card( uint16 caid, uint32 prov, struct cs_card_data* card)
{
if (caid!=card->caid) return 0;
// Dont care about provider for caid non via/seca
if ( ((card->caid & 0xff00)!=0x0100) && ((card->caid & 0xff00)!=0x0500) ) return 1;
int i;
for(i=0; i<card->nbprov;i++) if (prov==card->prov[i]) return 1;
return 0;
}
// Search for a card with best sid val.
// TODO: option validecmtime-ecmtime
int sidata_getval(struct cs_server_data *srv, struct cardserver_data *cs, uint16 caid, uint32 prov, uint16 sid, struct cs_card_data **selcard )
{
struct cs_card_data *card = NULL;
*selcard = NULL;
if ( (srv->type==TYPE_NEWCAMD) || (srv->type==TYPE_RADEGAST) ) {
card = srv->card;
while (card) {
if ( match_card(caid,prov,card) ) break;
card = card->next;
}
*selcard = card;
if (card) {
struct sid_data *sidata = card->sids[sid>>8];
while (sidata) {
if (sidata->sid==sid)
if (sidata->prov==prov) return sidata->val;
sidata = sidata->next;
}
}
return 0; // Channel not found in sid cache
}
#ifdef CCCAM_CLI
else if (srv->type==TYPE_CCCAM) {
// Search for availabe card cannot be found in sids
*selcard = NULL;
int selsidvalue = 0;
card = srv->card;
while (card) {
if ( match_card(caid,prov,card)
|| ( !prov && cs && cmp_cards(card, &cs->card) ) // use for prov=0
) {
// Search fo sid
int sidvalue = 0; // by default
struct sid_data *sidata = card->sids[sid>>8];
while (sidata) {
if ( (sidata->sid==sid)&&(sidata->prov==prov) ) {
sidvalue = sidata->val;
break;
}
sidata = sidata->next;
}
// Check with Selected card (sidvalue) TODO: classify by ecmtime, decode, stability
if (*selcard) {
if ( selsidvalue<0 ) {
if (sidvalue>=0) { *selcard = card; selsidvalue = sidvalue; }
else if (card->uphops<(*selcard)->uphops) { *selcard = card; selsidvalue = sidvalue; }
}
else if ( selsidvalue==0 ) {
if (sidvalue>0) { *selcard = card; selsidvalue = sidvalue; }
else if (sidvalue==0) if (card->uphops<(*selcard)->uphops) { *selcard = card; selsidvalue = sidvalue; }
}
else if (sidvalue>0) if (card->uphops<(*selcard)->uphops) { *selcard = card; selsidvalue = sidvalue; }
}
else { *selcard = card; selsidvalue = sidvalue; }
}
card = card->next;
}
return selsidvalue;
}
#endif
return 0;
}
void cardsids_add(struct cs_card_data *card, uint32 prov, uint16 sid,int val)
{
if (!sid) return;
struct sid_data *sidata = malloc( sizeof(struct sid_data) );
memset( sidata, 0, sizeof(struct sid_data) );
sidata->sid=sid;
sidata->prov=prov;
sidata->val=val;
sidata->next = card->sids[sid>>8];
card->sids[sid>>8] = sidata;
}
int cardsids_update(struct cs_card_data *card, uint32 prov, uint16 sid,int val)
{
if (!sid) return 0;
struct sid_data *sidata = card->sids[sid>>8];
while (sidata) {
if (sidata->sid==sid)
if (sidata->prov==prov) {
if ( (sidata->val<100) && (sidata->val>-100) ) {
if (sidata->val>0) {
if (val>0) sidata->val +=val;
else sidata->val =0;
}
else if (sidata->val<0) {
if (val<0) sidata->val +=val;
else sidata->val=0;
}
else sidata->val +=val; // else a card that has decode success one time cannot return to decode failed
}
return 1;
}
sidata = sidata->next;
}
if ( !sidata && sid ) {
cardsids_add( card, prov, sid,val);
}
return 1;
}
#endif
///////////////////////////////////////////////////////////////////////////////
// Common profile functions
///////////////////////////////////////////////////////////////////////////////
struct cardserver_data *getcsbycaidprov( uint16 caid, uint32 prov)
{
int i;
if (!caid) return NULL;
struct cardserver_data *cs = cfg.cardserver;
while (cs) {
if (cs->card.caid==caid) {
for(i=0; i<cs->card.nbprov;i++) if (cs->card.prov[i]==prov) return cs;
if ( ((cs->card.caid & 0xff00)==0x1800)
|| ((cs->card.caid & 0xff00)==0x0900)
|| ((cs->card.caid & 0xff00)==0x0b00) ) return cs;
}
cs = cs->next;
}
return NULL;
}
struct cardserver_data *getcsbyid(uint32 id)
{
if (!id) return NULL;
struct cardserver_data *cs = cfg.cardserver;
while (cs) {
if (cs->id==id) return cs;
cs = cs->next;
}
return NULL;
}
struct cardserver_data *getcsbyport(int port)
{
struct cardserver_data *cs = cfg.cardserver;
while (cs) {
if (cs->newcamd.port==port) return cs;
cs = cs->next;
}
return NULL;
}
///////////////////////////////////////////////////////////////////////////////
// Return
// 0: not accepted
// 1: accepted
int accept_sid(struct cardserver_data *cs, uint16_t sid, uint16_t chid )
{
int i;
// Check for Accepted sids
if (!sid) {
if (!cs->option.faccept0sid) return 0;
}
else {
if (cs->sids) {
if (!cs->isdeniedsids) {
int accepted = 0;
struct sid_chid_data *sids = cs->sids;
for(i=0;i<MAX_SIDS;i++,sids++) {
if (!sids->sid) {
if (!sids->chid) break; // end of sids
else if (sids->chid==chid) {
accepted = 1;
break;
}
}
else if ( (sids->sid==sid)&&(!sids->chid||(sids->chid==chid)) ) {
accepted = 1;
break;
}
}
if (!accepted) return 0;
}
else {
int accepted = 1;
struct sid_chid_data *sids = cs->sids;
for(i=0;i<MAX_SIDS;i++,sids++) {
if (!sids->sid) {
if (!sids->chid) break; // end of sids
else if (sids->chid==chid) {
accepted = 0;
break;
}
}
else if ( (sids->sid==sid)&&(!sids->chid||(sids->chid==chid)) ) {
accepted = 0;
break;
}
}
if (!accepted) return 0;
}
}
}
return 1;
}
int accept_prov(struct cardserver_data *cs, uint32 prov)
{
int i;
// Check for provid, accept provid==0
if (prov) {
for (i=0; i<cs->card.nbprov;i++) if (prov==cs->card.prov[i]) break;
if (i>=cs->card.nbprov) return 0;
}
else {
if (!cs->option.faccept0provider) return 0;
}
return 1;
}
int accept_caid(struct cardserver_data *cs, uint16_t caid)
{
// Check for caid, accept caid=0
if (caid) {
if (caid!=cs->card.caid) return 0;
}
else {
if (!cs->option.faccept0caid) return 0;
}
return 1;
}
int accept_ecmlen(int ecmlen)
{
if ( (ecmlen<20)||(ecmlen>300) ) return 0;
return 1;
}
char *cs_accept_ecm(struct cardserver_data *cs, uint16_t caid, uint32_t provid, uint16_t sid, uint16_t chid )
{
// Check for caid
if ( !accept_caid(cs,caid) ) return("Wrong caid");
// Check for provid
if ( !accept_prov(cs,provid) ) return("Wrong provider");
// Check for sid
if ( !accept_sid(cs,sid,chid) ) return("Channel denied");
return NULL;
}
///////////////////////////////////////////////////////////////////////////////
void ecm_setdcw( struct cardserver_data *cs, ECM_DATA *ecm, uchar dcw[16], int srctype, int srcid);
#include "dcwfilter.c"
#include "pipe.c"
#include "clustredcache.c"
#include "cli-common.c"
#include "cli-newcamd.c"
#ifdef CCCAM_CLI
#include "cli-cccam.c"
#endif
#include "srv-newcamd.c"
#ifdef MGCAMD_SRV
#include "srv-mgcamd.c"
#endif
#ifdef CCCAM_SRV
#include "srv-cccam.c"
#endif
#ifdef FREECCCAM_SRV
#include "srv-freecccam.c"
#endif
#ifdef RADEGAST_CLI
#include "cli-radegast.c"
#endif
#ifdef RADEGAST_SRV
#include "srv-radegast.c"
#endif
#include "th-srv.c" // Servers Connnection
#include "th-dns.c" // Dns Resolving
#include "th-ecm.c" // Check/send ecm request to servers & Check/send dcw to clients
#include "th-cfg.c" // Reread Config
#include "th-date.c"
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
pthread_t cli_tid;
int checkthread;
unsigned int seed2;
uint8 fastrnd2()
{
unsigned int offset = 12923+(GetTickCount()&0xff);
unsigned int multiplier = 4079+(GetTickCount()&0xff);
seed2 = seed2 * multiplier + offset;
return (uint8)(seed2 % 0xFF);
}
int mainprocess()
{
gettimeofday( &startime, NULL );
// INIT
pthread_mutex_init(&prg.lock, NULL);
pthread_mutex_init(&prg.lockecm, NULL);
pthread_mutex_init(&prg.lockcli, NULL);
pthread_mutex_init(&prg.locksrv, NULL);
#ifdef CCCAM_SRV
pthread_mutex_init(&prg.locksrvcc, NULL); // CC Client connection
pthread_mutex_init(&prg.lockcccli, NULL);
#endif
#ifdef FREECCCAM_SRV
pthread_mutex_init(&prg.locksrvfreecc, NULL); // CC Client connection
pthread_mutex_init(&prg.lockfreecccli, NULL);
#endif
#ifdef MGCAMD_SRV
pthread_mutex_init(&prg.locksrvmg, NULL); // Client connection
pthread_mutex_init(&prg.lockclimg, NULL);
#endif
#ifdef RADEGAST_SRV
pthread_mutex_init(&prg.lockrdgdsrv, NULL); // Client connection
pthread_mutex_init(&prg.lockrdgdcli, NULL);
#endif
// Main Loops(THREADS)
pthread_mutex_init(&prg.lockdnsth, NULL); // DNS lookup Thread
pthread_mutex_init(&prg.locksrvth, NULL); // Connection to cardservers
pthread_mutex_init(&prg.lockmain, NULL); // Messages Recv
pthread_mutex_init(&prg.locksrvcs, NULL); // CS Client connection
pthread_mutex_init(&prg.lockhttp, NULL); // HTTP Server
pthread_mutex_init(&prg.lockdns, NULL);
pthread_mutex_init(&prg.lockdcw, NULL);
#ifdef CACHE_ACTION
pthread_mutex_init(&prg.lockaction, NULL);
#endif
pthread_mutex_init(&prg.lockcache, NULL);
pthread_mutex_init(&prg.lockthreaddate, NULL);
gettimeofday( &prg.exectime, NULL );
memset(&trace, 0, sizeof(struct trace_data) );
/* Create the pipe. */
if (socketpair(AF_UNIX, SOCK_STREAM, 0, srvsocks) < 0) { perror("opening stream socket pair"); exit(1); }
#ifdef CACHE_ACTION
if (pipe (sendcache_pipe)) { // Cache -> ecm
printf ("Pipe failed.\n");
return -1;
}
#endif
srand (time(NULL));
#ifdef CCCAM
// NODE ID: 8675e141 217e6912
cccam_nodeid[0] = 0x11;
cccam_nodeid[1] = 0x22;
cccam_nodeid[2] = 0x33;
cccam_nodeid[3] = 0x44;
cccam_nodeid[4] = 0xff & fastrnd2();
cccam_nodeid[5] = 0xff & fastrnd2();
cccam_nodeid[6] = 0xff & fastrnd2();
cccam_nodeid[7] = 0xff & fastrnd2();
#endif
start_thread_config();
usleep(100000);
init_ecmdata();
// THREADS - detached
start_thread_dns();
sleep(1);
start_thread_srv();
start_thread_date();
#ifdef HTTP_SRV
start_thread_http();
#endif
start_thread_recv_msg();
sleep(1); // wait for dns & servers connections
start_thread_cache();
create_prio_thread(&cli_tid, (threadfn)cs_connect_cli_thread,NULL, 50);
#ifdef RADEGAST_SRV
pthread_t rdgd_cli_tid;
create_prio_thread(&rdgd_cli_tid, (threadfn)rdgd_connect_cli_thread, NULL, 50); // Lock server
#endif
#ifdef CCCAM_SRV
pthread_t cc_cli_tid;
create_prio_thread(&cc_cli_tid, (threadfn)cc_connect_cli_thread, NULL, 50); // Lock server
#endif
#ifdef FREECCCAM_SRV
pthread_t freecc_cli_tid;
create_prio_thread(&freecc_cli_tid, (threadfn)freecc_connect_cli_thread, NULL, 50); // Lock server
#endif
#ifdef MGCAMD_SRV
start_thread_mgcamd();
#endif
return 0;
}
#ifdef SIG_HANDLER
#include <execinfo.h>
#include <ucontext.h>
#ifdef REG_EIP
#define INDEX_IP REG_EIP
#else
#ifdef REG_RIP
#define INDEX_IP REG_RIP
#else
#ifdef PT_NIP
#define INDEX_IP PT_NIP
#endif
#endif
#endif
void sighandler(int sig, siginfo_t *info, void *secret) {
ucontext_t *uc = (ucontext_t *)secret;
printf(" Got signal %d ", sig);
printf(" faulty address is %p ", info->si_addr);
#ifdef PT_NIP
printf(" from 0x%016X\n", uc->uc_mcontext.uc_regs->gregs[PT_NIP]);
#else
printf(" from 0x%016X\n", uc->uc_mcontext.gregs[INDEX_IP]);
#endif
fdebugf(" Got signal %d ", info->si_signo);
fdebugf(" faulty address is %p ", info->si_addr);
#ifdef PT_NIP
fdebugf(" from 0x%016X\n", uc->uc_mcontext.uc_regs->gregs[PT_NIP]);
#else
fdebugf(" from 0x%016X\n", uc->uc_mcontext.gregs[INDEX_IP]);
#endif
exit(0);
}
void install_handler (void)
{
struct sigaction sa;
memset(&sa, 0, sizeof(sigaction));
sa.sa_sigaction = (void *)sighandler;
sigemptyset (&sa.sa_mask);
sa.sa_flags = SA_RESTART | SA_SIGINFO;
sigaction(SIGSEGV, &sa, NULL);
sigaction(SIGFPE, &sa, NULL);
}
#endif
int main(int argc, char *argv[])
{
int option_background = 0; // default
int fork_return;
char *args;
int i,j;
char pg[] = "Multi CardServer r"REVISION_STR" - by ";
char evil[] = "evileyes";
char email[] = " (email:evileyes@live.fr)\n";
if ( (evil[0]!='e')||(evil[1]!='v')||(evil[2]!='i')||(evil[3]!='l')||(evil[4]!='e')||(evil[5]!='y')||(evil[6]!='e')||(evil[7]!='s') ) exit(0);
printf("%s", pg);
#ifdef SIG_HANDLER
install_handler();
#endif
if ( (evil[0]!='e')||(evil[1]!='v')||(evil[2]!='i')||(evil[3]!='l')||(evil[4]!='e')||(evil[5]!='y')||(evil[6]!='e')||(evil[7]!='s') ) exit(0);
printf("%s", evil );
flag_debugscr = 0;
flag_debugfile = 0;
#ifdef DEBUG_NETWORK
flag_debugnet = 0;
#endif
printf("%s", email );
// Extract filename
char *p = argv[0];
char *slash = p;
char *dot = NULL;
while (*p) {
if (*p=='/') slash = p+1;
else if (*p=='.') dot = p;
p++;
}
char path[255];
if (dot>slash) memcpy( path, slash, dot-slash); else strcpy(path, slash);
// Set Config name
sprintf( config_file, "/var/etc/%s.cfg", path);
// sprintf( sid_file, "/var/etc/%s.sid", path);
// sprintf( card_file, "/var/etc/%s.card", path);
sprintf( debug_file, "/var/tmp/%s.log", path);
sprintf( sms_file, "/var/tmp/%s.sms", path);
// Parse Options
for (i=1;i<argc;i++) {
args = *(argv+i);
if (args[0]=='-') {
if (args[1]=='h') {
printf("USAGE\n\tmultics [-b] [-v] [-f] [-n] [-C <configfile>]\n\
OPTIONS\n\
\t-b run in background\n\
\t-C <configfile> use <configfile> instead of default config file (/var/etc/multics.cfg)\n\
\t-f write to log file (/var/tmp/multics.log)\n\
\t-n print network packets\n\
\t-v print on screen\n\
\t-h this help message\n");
return 0;
}
else if (args[1]=='C') {
i++;
if (i<argc) {
args = *(argv+i);
strcpy( config_file, args );
}
}
else {
for(j=1; j<strlen(args); j++) {
if (args[j]=='b') option_background = 1;
else if (args[j]=='v') flag_debugscr = 1;
#ifdef DEBUG_NETWORK
else if (args[j]=='n') flag_debugnet = 1;
#endif
else if (args[j]=='f') flag_debugfile = 1;
}
}
}
}
if (option_background==1) {
fork_return = fork();
if( fork_return < 0) {
debugf(0," unable to create child process, exiting.\n");
exit(-1);
}
if (fork_return>0) {
//debugf(" main process, exiting.\n");
exit(0);
}
//else mainprocess();
}
prg.pid_main = getpid();
mainprocess();
sleep(1);
prg.restart = 0;
while (1) {
if (prg.restart==1) { // restart()
if ( (evil[0]!='e')||(evil[1]!='v')||(evil[2]!='i')||(evil[3]!='l')||(evil[4]!='e')||(evil[5]!='y')||(evil[6]!='e')||(evil[7]!='s') ) exit(0);
debugf(0," Restarting...\n");
//TODO:stop threads
int fork_return;
done_config(&cfg);
fork_return = vfork();
if( fork_return < 0) {
printf("unable to create child process, exiting.\n");
}
else if (fork_return==0) {
fork_return = vfork();
if (fork_return < 0) {
printf("unable to create child process, exiting.\n");
}
else if (fork_return==0) {
execvp( argv[0], argv );
perror("execvp");
}
exit(0);
}
debugf(0," Stopped.\n");
exit(0);
}
sleep(2);
}
return 0;
}