source: trunk/oscam.c @ 2953

Last change on this file since 2953 was 2953, checked in by rorothetroll, 9 years ago

added Seagate FreeAgent? DockStar? support. thanks Robby

File size: 87.4 KB
Line 
1#define CS_CORE
2#include "globals.h"
3#ifdef AZBOX
4#  include "openxcas/openxcas_api.h"
5#endif
6#ifdef CS_WITH_GBOX
7#  include "csgbox/gbox.h"
8#  define CS_VERSION_X  CS_VERSION "-gbx-" GBXVERSION
9#else
10#  define CS_VERSION_X  CS_VERSION
11#endif
12/*****************************************************************************
13        Globals
14*****************************************************************************/
15int ridx=0;
16int pfd=0;      // Primary FD, must be closed on exit
17int mfdr=0;     // Master FD (read)
18int fd_c2m=0;   // FD Client -> Master (for clients / write )
19int fd_c2l=0;   // FD Client -> Logger (for clients / write )
20int cs_dblevel=0;   // Debug Level (TODO !!)
21int cs_idx=0;   // client index (0=master, ...)
22int cs_ptyp=0; // process-type
23struct s_module ph[CS_MAX_MOD]; // Protocols
24int is_server=0;    // used in modules to specify function
25pid_t master_pid=0;   // master pid OUTSIDE shm
26ushort  len4caid[256];    // table for guessing caid (by len)
27char  cs_confdir[128]=CS_CONFDIR;
28uchar mbuf[1024];   // global buffer
29pthread_mutex_t gethostbyname_lock;
30ECM_REQUEST *ecmtask;
31#ifdef CS_ANTICASC
32struct s_acasc ac_stat[CS_MAXPID];
33#endif
34
35/*****************************************************************************
36        Shared Memory
37*****************************************************************************/
38int     *ecmidx;  // Shared Memory
39int     *logidx;  // Shared Memory
40int     *oscam_sem; // sem (multicam.o)
41int     *c_start; // idx of 1st client
42int     *log_fd;  // log-process is running
43struct  s_ecm     *ecmcache;  // Shared Memory
44struct  s_client  *client;    // Shared Memory
45struct  s_reader  *reader;    // Shared Memory
46
47struct  card_struct *Cards;   // Shared Memory
48struct  idstore_struct  *idstore;   // Shared Memory
49unsigned long *IgnoreList;    // Shared Memory
50
51struct  s_config  *cfg;       // Shared Memory
52#ifdef CS_ANTICASC
53struct  s_acasc_shm   *acasc; // anti-cascading table indexed by account.ac_idx
54#endif
55#ifdef CS_LOGHISTORY
56int     *loghistidx;  // ptr to current entry
57char    *loghist;     // ptr of log-history
58#endif
59int     *mcl=0;       // Master close log?
60
61static  int  shmsize =  CS_ECMCACHESIZE*(sizeof(struct s_ecm)) +
62                        CS_MAXPID*(sizeof(struct s_client)) +
63                        CS_MAXREADER*(sizeof(struct s_reader)) +
64#ifdef CS_WITH_GBOX
65                        CS_MAXCARDS*(sizeof(struct card_struct))+
66                        CS_MAXIGNORE*(sizeof(long))+
67                        CS_MAXPID*(sizeof(struct idstore_struct))+
68#endif
69#ifdef CS_ANTICASC
70                        CS_MAXPID*(sizeof(struct s_acasc_shm)) +
71#endif
72#ifdef CS_LOGHISTORY
73                        CS_MAXLOGHIST*CS_LOGHISTSIZE + sizeof(int) +
74#endif
75                        sizeof(struct s_config)+(6*sizeof(int));
76
77#ifdef CS_NOSHM
78char  cs_memfile[128]=CS_MMAPFILE;
79#endif
80
81/*****************************************************************************
82        Statics
83*****************************************************************************/
84static  char  mloc[128]={0};
85static  int shmid=0;    // Shared Memory ID
86static  int cs_last_idx=0;    // client index of last fork (master only)
87static char *logo = "  ___  ____   ___                \n / _ \\/ ___| / __|__ _ _ __ ___  \n| | | \\___ \\| |  / _` | '_ ` _ \\ \n| |_| |___) | |_| (_| | | | | | |\n \\___/|____/ \\___\\__,_|_| |_| |_|\n";
88
89static void cs_set_mloc(int ato, char *txt)
90{
91  if (ato>=0)
92    alarm(ato);
93  if (txt)
94    strcpy(mloc, txt);
95}
96
97static void usage()
98{
99  fprintf(stderr, "%s\n\n", logo);
100  fprintf(stderr, "OSCam cardserver v%s, build #%s (%s) - (w) 2009-2010 streamboard SVN\n", CS_VERSION_X, CS_SVN_VERSION, CS_OSTYPE);
101  fprintf(stderr, "\tsee http://streamboard.gmc.to:8001/wiki/ for more details\n");
102  fprintf(stderr, "\tbased on streamboard mp-cardserver v0.9d - (w) 2004-2007 by dukat\n");
103  fprintf(stderr, "\tinbuilt modules: ");
104#ifdef HAVE_DVBAPI
105#ifdef WITH_STAPI
106  fprintf(stderr, "dvbapi with stapi");
107#else
108  fprintf(stderr, "dvbapi ");
109#endif
110#endif
111#ifdef WEBIF
112  fprintf(stderr, "webinterface ");
113#endif
114#ifdef CS_ANTICASC
115  fprintf(stderr, "anticascading ");
116#endif
117#ifdef LIBUSB
118  fprintf(stderr, "smartreader ");
119#endif
120#ifdef HAVE_PCSC
121  fprintf(stderr, "pcsc ");
122#endif
123#ifdef CS_WITH_GBOX
124  fprintf(stderr, "gbox ");
125#endif
126#ifdef IRDETO_GUESSING
127  fprintf(stderr, "irdeto-guessing ");
128#endif
129#ifdef CS_LED
130  fprintf(stderr, "led-trigger ");
131#endif
132  fprintf(stderr, "\n\n");
133  fprintf(stderr, "oscam [-b] [-c config-dir] [-d]");
134#ifdef CS_NOSHM
135  fprintf(stderr, " [-m memory-file]");
136#endif
137  fprintf(stderr, " [-h]");
138  fprintf(stderr, "\n\n\t-b         : start in background\n");
139  fprintf(stderr, "\t-c <dir>   : read configuration from <dir>\n");
140  fprintf(stderr, "\t             default = %s\n", CS_CONFDIR);
141  fprintf(stderr, "\t-d <level> : debug level mask\n");
142  fprintf(stderr, "\t               0 = no debugging (default)\n");
143  fprintf(stderr, "\t               1 = detailed error messages\n");
144  fprintf(stderr, "\t               2 = ATR parsing info, ECM, EMM and CW dumps\n");
145  fprintf(stderr, "\t               4 = traffic from/to the reader\n");
146  fprintf(stderr, "\t               8 = traffic from/to the clients\n");
147  fprintf(stderr, "\t              16 = traffic to the reader-device on IFD layer\n");
148  fprintf(stderr, "\t              32 = traffic to the reader-device on I/O layer\n");
149  fprintf(stderr, "\t              64 = EMM logging\n");
150  fprintf(stderr, "\t             255 = debug all\n");
151#ifdef CS_NOSHM
152  fprintf(stderr, "\t-m <file>  : use <file> as mmaped memory file\n");
153  fprintf(stderr, "\t             default = %s\n", CS_MMAPFILE);
154#endif
155  fprintf(stderr, "\t-h         : show this help\n");
156  fprintf(stderr, "\n");
157  exit(1);
158}
159
160#ifdef NEED_DAEMON
161#ifdef OS_MACOSX
162// this is done because daemon is being deprecated starting with 10.5 and -Werror will always trigger an error
163static int daemon_compat(int nochdir, int noclose)
164#else
165static int daemon(int nochdir, int noclose)
166#endif
167{
168  int fd;
169
170  switch (fork())
171  {
172    case -1: return (-1);
173    case 0:  break;
174    default: _exit(0);
175  }
176
177  if (setsid()==(-1))
178    return(-1);
179
180  if (!nochdir)
181    (void)chdir("/");
182
183  if (!noclose && (fd=open("/dev/null", O_RDWR, 0)) != -1)
184  {
185    (void)dup2(fd, STDIN_FILENO);
186    (void)dup2(fd, STDOUT_FILENO);
187    (void)dup2(fd, STDERR_FILENO);
188    if (fd>2)
189      (void)close(fd);
190  }
191  return(0);
192}
193#endif
194
195int recv_from_udpipe(uchar *buf)
196{
197  unsigned short n;
198  if (!pfd) return(-9);
199  if (!read(pfd, buf, 3)) cs_exit(1);
200  if (buf[0]!='U')
201  {
202    cs_log("INTERNAL PIPE-ERROR");
203    cs_exit(1);
204  }
205  memcpy(&n, buf+1, 2);
206  return(read(pfd, buf, n));
207}
208
209char *username(int idx)
210{
211  if (client[idx].usr[0])
212    return(client[idx].usr);
213  else
214    return("anonymous");
215}
216
217static int idx_from_ip(in_addr_t ip, in_port_t port)
218{
219  int i, idx;
220  for (i=idx=0; (i<CS_MAXPID) && (!idx); i++)
221    if ((client[i].ip==ip) && (client[i].port==port) &&
222        ((client[i].typ=='c') || (client[i].typ=='m')))
223      idx=i;
224  return(idx);
225}
226
227int idx_from_pid(pid_t pid)
228{
229  int i, idx;
230  for (i=0, idx=(-1); (i<CS_MAXPID) && (idx<0); i++)
231    if (client[i].pid==pid)
232      idx=i;
233  return(idx);
234}
235
236static long chk_caid(ushort caid, CAIDTAB *ctab)
237{
238  int n;
239  long rc;
240  for (rc=(-1), n=0; (n<CS_MAXCAIDTAB) && (rc<0); n++)
241    if ((caid & ctab->mask[n]) == ctab->caid[n])
242      rc=ctab->cmap[n] ? ctab->cmap[n] : caid;
243  return(rc);
244}
245
246int chk_bcaid(ECM_REQUEST *er, CAIDTAB *ctab)
247{
248  long caid;
249  if ((caid=chk_caid(er->caid, ctab))<0)
250    return(0);
251  er->caid=caid;
252  return(1);
253}
254
255/*
256 * void set_signal_handler(int sig, int flags, void (*sighandler)(int))
257 * flags: 1 = restart, 2 = don't modify if SIG_IGN, may be combined
258 */
259void set_signal_handler(int sig, int flags, void (*sighandler)(int))
260{
261#ifdef CS_SIGBSD
262  if ((signal(sig, sighandler)==SIG_IGN) && (flags & 2))
263  {
264    signal(sig, SIG_IGN);
265    siginterrupt(sig, 0);
266  }
267  else
268    siginterrupt(sig, (flags & 1) ? 0 : 1);
269#else
270  struct sigaction sa;
271  sigaction(sig, (struct sigaction *) 0, &sa);
272  if (!((flags & 2) && (sa.sa_handler==SIG_IGN)))
273  {
274    sigemptyset(&sa.sa_mask);
275    sa.sa_flags=(flags & 1) ? SA_RESTART : 0;
276    sa.sa_handler=sighandler;
277    sigaction(sig, &sa, (struct sigaction *) 0);
278  }
279#endif
280}
281
282static void cs_alarm()
283{
284  cs_debug("Got alarm signal");
285  cs_log("disconnect from %s by watchdog", cs_inet_ntoa(client[cs_idx].ip));
286  cs_exit(0);
287}
288
289static void cs_master_alarm()
290{
291  cs_log("PANIC: master deadlock! last location: %s", mloc);
292  fprintf(stderr, "PANIC: master deadlock! last location: %s", mloc);
293  fflush(stderr);
294  cs_exit(0);
295}
296
297static void cs_sigpipe()
298{
299  if ((cs_idx) && (master_pid!=getppid()))
300    cs_exit(0);
301  cs_log("Got sigpipe signal -> captured");
302}
303
304void cs_exit(int sig)
305{
306   
307//#ifdef ST_LINUX
308//  Fortis_STSMART_Close();
309//  Fortis_STPTI_Close();
310//#endif
311
312  set_signal_handler(SIGCHLD, 1, SIG_IGN);
313  set_signal_handler(SIGHUP , 1, SIG_IGN);
314  if (sig && (sig!=SIGQUIT))
315    cs_log("exit with signal %d", sig);
316  switch(client[cs_idx].typ)
317  {
318    case 'c':
319        cs_statistics(cs_idx);
320        client[cs_idx].last_caid = 0xFFFF;
321        client[cs_idx].last_srvid = 0xFFFF;
322        cs_statistics(cs_idx);
323        break;
324    case 'm': break;
325    case 'n': *log_fd=0;
326              break;
327    case 'r':
328        // free AES entries allocated memory
329        if(reader[ridx].aes_list) {
330            aes_clear_entries(&reader[ridx]);
331        }
332        // close the device
333        reader_device_close(&reader[ridx]);
334        break;
335    case 's': *log_fd=0;
336              int i;
337              for (i=1; i<CS_MAXPID; i++)
338                if (client[i].pid)
339                  kill(client[i].pid, SIGQUIT);
340#ifdef CS_LED
341              cs_switch_led(LED1B, LED_OFF);
342              cs_switch_led(LED2, LED_OFF);
343              cs_switch_led(LED3, LED_OFF);
344              cs_switch_led(LED1A, LED_ON);
345#endif
346              if (cfg->pidfile != NULL) {
347                if (unlink(cfg->pidfile) < 0)
348                  cs_log("cannot remove pid file %s errno=(%d)", cfg->pidfile, errno);
349              }
350#ifndef OS_CYGWIN32
351              if (unlink("/tmp/oscam.version") < 0)
352                  cs_log("cannot remove /tmp/oscam.version errno=(%d)", errno);
353#endif
354              cs_log("cardserver down");
355#ifndef CS_NOSHM
356              if (ecmcache) shmdt((void *)ecmcache);
357#endif
358              break;
359  }
360  if (pfd) close(pfd);
361#ifdef CS_NOSHM
362  munmap((void *)ecmcache, (size_t)shmsize);
363  if (shmid) close(shmid);
364  unlink(CS_MMAPFILE);    // ignore errors, last process must succeed
365#endif
366  exit(sig);
367}
368
369void cs_reinit_clients()
370{
371    int i;
372    struct s_auth *account;
373
374    for( i = 1; i < CS_MAXPID; i++ )
375        if( client[i].pid && client[i].typ == 'c' && client[i].usr[0] ) {
376            for (account = cfg->account; (account) ; account = account->next)
377                if (!strcmp(client[i].usr, account->usr))
378                    break;
379
380            if (account && client[i].pcrc == crc32(0L, MD5((uchar *)account->pwd, strlen(account->pwd), NULL), 16)) {
381                client[i].grp       = account->grp;
382                client[i].au        = account->au;
383                client[i].autoau    = account->autoau;
384                client[i].expirationdate = account->expirationdate;
385                client[i].allowedtimeframe[0] = account->allowedtimeframe[0];
386                client[i].allowedtimeframe[1] = account->allowedtimeframe[1];
387                client[i].ncd_keepalive = account->ncd_keepalive;
388                client[i].c35_suppresscmd08 = account->c35_suppresscmd08;
389                client[i].tosleep   = (60*account->tosleep);
390                client[i].c35_sleepsend = account->c35_sleepsend;
391                client[i].monlvl    = account->monlvl;
392                client[i].disabled  = account->disabled;
393                client[i].fchid     = account->fchid;  // CHID filters
394                client[i].cltab     = account->cltab;  // Class
395
396                // newcamd module dosent like ident reloading
397                if(!client[i].ncd_server)
398                    client[i].ftab  = account->ftab;   // Ident
399
400                client[i].sidtabok  = account->sidtabok;   // services
401                client[i].sidtabno  = account->sidtabno;   // services
402
403                memcpy(&client[i].ctab, &account->ctab, sizeof(client[i].ctab));
404                memcpy(&client[i].ttab, &account->ttab, sizeof(client[i].ttab));
405
406#ifdef CS_ANTICASC
407                client[i].ac_idx    = account->ac_idx;
408                client[i].ac_penalty= account->ac_penalty;
409                client[i].ac_limit  = (account->ac_users * 100 + 80) * cfg->ac_stime;
410#endif
411            } else {
412                if (ph[client[i].ctyp].type & MOD_CONN_NET) {
413                    cs_debug("client '%s', pid=%d not found in db (or password changed)", client[i].usr, client[i].pid);
414                    kill(client[i].pid, SIGQUIT);
415                }
416            }
417        }
418}
419
420static void cs_sighup()
421{
422  uchar dummy[1]={0x00};
423  write_to_pipe(fd_c2m, PIP_ID_HUP, dummy, 1);
424}
425
426static void cs_accounts_chk()
427{
428  init_userdb(&cfg->account);
429  cs_reinit_clients();
430#ifdef CS_ANTICASC
431  int i;
432  for (i=0; i<CS_MAXPID; i++)
433    if (client[i].typ=='a')
434    {
435      kill(client[i].pid, SIGHUP);
436      break;
437    }
438#endif
439}
440
441static void cs_debug_level()
442{
443    int i;
444
445    //switch debuglevel forward one step if not set from outside
446    if(cfg->debuglvl == cs_dblevel) {
447        switch (cs_dblevel) {
448            case 0:
449                cs_dblevel = 1;
450                break;
451            case 64:
452                cs_dblevel = 255;
453                break;
454            case 255:
455                cs_dblevel = 0;
456                break;
457            default:
458                cs_dblevel <<= 1;
459        }
460    } else {
461        cs_dblevel = cfg->debuglvl;
462    }
463
464    cfg->debuglvl = cs_dblevel;
465
466    if (master_pid == getpid())
467        for (i=0; i<CS_MAXPID && client[i].pid; i++)
468            client[i].dbglvl = cs_dblevel;
469        else
470            client[cs_idx].dbglvl = cs_dblevel;
471        cs_log("%sdebug_level=%d", (master_pid == getpid())?"all ":"", cs_dblevel);
472}
473
474static void cs_card_info(int i)
475{
476  uchar dummy[1]={0x00};
477
478  for( i=1; i<CS_MAXPID; i++ )
479    if( client[i].pid && client[i].typ=='r' && client[i].fd_m2c ){
480      write_to_pipe(client[i].fd_m2c, PIP_ID_CIN, dummy, 1);
481    }
482
483      //kill(client[i].pid, SIGUSR2);
484}
485
486static void prepare_reader_restart(int ridx, int cs_idx)
487{
488  reader[ridx].pid = 0;
489  reader[ridx].cc = NULL;
490  reader[ridx].tcp_connected = 0;
491  reader[ridx].fd=0;
492  reader[ridx].cs_idx=0;
493  reader[ridx].last_s = 0;
494  reader[ridx].last_g = 0;
495  cs_debug_mask(D_TRACE, "reader %s closed (index=%d)", reader[ridx].label, ridx);
496  if (client[cs_idx].ufd) close(client[cs_idx].ufd);
497  if (client[cs_idx].fd_m2c_c) close(client[cs_idx].fd_m2c_c);
498  memset(&client[cs_idx], 0, sizeof(struct s_client));
499  client[cs_idx].au=(-1);
500}
501
502//Schlocke: restart cardreader after 5 seconds:
503static void restart_cardreader(int pridx, int force_now) {
504    ridx = pridx;
505    if (reader[ridx].cs_idx) {
506        if (reader[ridx].pid==client[reader[ridx].cs_idx].pid) {
507            int pid = reader[ridx].pid;
508            prepare_reader_restart(ridx, reader[ridx].cs_idx);
509            kill(pid, SIGKILL);
510        }
511    }
512    reader[ridx].ridx = ridx; //FIXME
513    if ((reader[ridx].device[0]) && (reader[ridx].enable == 1) && (!reader[ridx].deleted)) {
514        switch (cs_fork(0, 99)) {
515        case -1:
516            cs_exit(1);
517        case 0:
518            break;
519        default:
520            if (!force_now)
521                cs_sleepms(cfg->reader_restart_seconds * 1000); // SS: wait
522            cs_log("restarting reader %s (index=%d)", reader[ridx].label, ridx);
523
524            wait4master();
525            start_cardreader(&reader[ridx]);
526        }
527    }
528}
529
530
531static void cs_child_chk(int i)
532{
533  while (waitpid(0, NULL, WNOHANG)>0);
534  for (i=1; i<CS_MAXPID; i++)
535    if (client[i].pid)
536      if (kill(client[i].pid, 0)) {
537        if ((client[i].typ!='c') && (client[i].typ!='m'))
538        {
539          char *txt="";
540          switch(client[i].typ)
541          {
542#ifdef CS_ANTICASC
543            case 'a': txt="anticascader"; break;
544#endif
545            case 'l': txt="logger"; break;
546            case 'p': txt="proxy";  break;
547            case 'r': txt="reader"; break;
548            case 'n': txt="resolver"; break;
549#ifdef WEBIF
550            case 'h': txt="http";   break;
551#endif
552          }
553          cs_log("PANIC: %s lost !! (pid=%d)", txt, client[i].pid);
554          if (cfg->reader_restart_seconds && (client[i].typ == 'r' || client[i].typ == 'p'))
555          {
556            int old_pid = client[i].pid;
557            client[i].pid = 0;
558            for (ridx = 0; ridx < CS_MAXREADER; ridx++) 
559            {
560              if (reader[ridx].pid == old_pid)
561              {
562                prepare_reader_restart(ridx, i);
563                cs_log("restarting %s %s in %d seconds (index=%d)", reader[ridx].label, txt,
564                        cfg->reader_restart_seconds, ridx);
565        send_restart_cardreader(ridx, 0);
566                break;
567              }
568            }
569          }
570          else {
571              *log_fd=0;
572              cs_exit(1);
573          }
574        }
575        else
576        {
577#ifdef CS_ANTICASC
578          char usr[32];
579          ushort    ac_idx=0;
580          ushort    ac_limit=0;
581          uchar     ac_penalty=0;
582          if( cfg->ac_enabled )
583          {
584            cs_strncpy(usr, client[i].usr, sizeof(usr));
585            ac_idx = client[i].ac_idx;
586            ac_limit = client[i].ac_limit;
587            ac_penalty = client[i].ac_penalty;
588          }
589#endif
590          if (client[i].fd_m2c) close(client[i].fd_m2c);
591          if (client[i].ufd) close(client[i].ufd);
592          memset(&client[i], 0, sizeof(struct s_client));
593#ifdef CS_ANTICASC
594          if( cfg->ac_enabled )
595          {
596            client[i].ac_idx = ac_idx;
597            client[i].ac_limit = ac_limit;
598            client[i].ac_penalty = ac_penalty;
599            strcpy(client[i].usr, usr);
600          }
601#endif
602          client[i].au=(-1);
603
604#ifdef HAVE_DVBAPI
605          int phi = client[i].ctyp;
606          if (client[i].typ == 'c' && ph[phi].type & MOD_CONN_SERIAL) //Schlocke: dvbapi killed? restart
607          {
608              if (ph[phi].s_handler)
609                ph[phi].s_handler(phi);
610          }
611#endif
612        }
613      }
614  return;
615}
616
617int cs_fork(in_addr_t ip, in_port_t port)
618{
619  int i;
620  pid_t pid;
621  for (i=1; (i<CS_MAXPID) && (client[i].pid); i++); //find next available client index i
622  if (i<CS_MAXPID)
623  {
624    int fdp[2];
625    memset(&client[i], 0, sizeof(struct s_client));
626    client[i].au=(-1);
627    if (pipe(fdp))
628    {
629      cs_log("Cannot create pipe (errno=%d)", errno);
630      cs_exit(1);
631    }
632
633    make_non_blocking(fdp[0]);
634    make_non_blocking(fdp[1]);
635
636        if (reader[ridx].typ == R_SC8in1 && port == 99) { //SC8in1 reader gets threaded, not forked
637                        if (reader[ridx].handle == 0)
638                reader_device_init(&reader[ridx]); 
639            cs_log("creating thread for device %s slot %i with ridx %i=%i", reader[ridx].device, reader[ridx].slot, reader[ridx].ridx, ridx);
640            int rc;
641            pthread_t dummy;
642            rc = pthread_create(&dummy, NULL, start_cardreader, (void *)&reader[ridx]);
643            if (rc)
644            cs_log("ERROR; return code from pthread_create() is %d\n", rc);
645            //client part
646        is_server=((ip) || (port<90)) ? 1 : 0; //FIXME global should be local per thread
647        //cs_ptyp=D_CLIENT;
648            client[i].fd_m2c_c = fdp[0]; //store client read fd
649            cs_idx=i; //although thread runs in master process, reserve an cs_idx slot
650#ifndef CS_NOSHM
651            shmid=0;
652#endif
653            //master part
654            client[i].fd_m2c=fdp[1];
655            client[i].dbglvl=cs_dblevel;
656            client[i].stat=1;
657            client[i].typ='r';   // reader
658            client[i].sidtabok=reader[ridx].sidtabok;
659            client[i].sidtabno=reader[ridx].sidtabno;
660            reader[ridx].fd=client[i].fd_m2c;
661            reader[ridx].cs_idx=i; //although thread runs in master process, reserve an cs_idx slot
662            pid=getpid();
663            reader[ridx].pid=pid;
664      if (reader[ridx].r_port)
665                cs_log("proxy thread started (pid=%d, server=%s)",pid, reader[ridx].device);
666            else {
667                switch(reader[ridx].typ) {
668                    case R_MOUSE:
669                    case R_SMART:
670                        cs_log("reader thread started (pid=%d, device=%s, detect=%s%s, mhz=%d, cardmhz=%d)",pid, 
671                                reader[ridx].device,reader[ridx].detect&0x80 ? "!" : "",RDR_CD_TXT[reader[ridx].detect&0x7f],
672                                reader[ridx].mhz,reader[ridx].cardmhz);
673                        break;
674                    case R_SC8in1:
675                        cs_log("reader thread started (pid=%d, device=%s:%i, detect=%s%s, mhz=%d, cardmhz=%d)",pid, 
676                                reader[ridx].device,reader[ridx].slot,reader[ridx].detect&0x80 ? "!" : "",
677                                RDR_CD_TXT[reader[ridx].detect&0x7f],reader[ridx].mhz,reader[ridx].cardmhz);
678                        break;
679                    default:
680                        cs_log("reader thread started (pid=%d, device=%s)",pid, reader[ridx].device);
681                }
682                client[i].ip=client[0].ip;
683                strcpy(client[i].usr, client[0].usr);
684            }
685            cdiff=i;
686            client[i].login=client[i].last=time((time_t *)0);
687            client[i].pid=pid;    // MUST be last -> wait4master()
688            cs_last_idx=i;
689            i=0;
690        }
691        else {
692     pid=fork();
693     switch(pid)
694     {
695      case -1:
696        cs_log("PANIC: Cannot fork() (errno=%d)", errno);
697        cs_exit(1);
698      case  0:          // HERE is client
699        alarm(0);
700        set_signal_handler(SIGALRM, 0, cs_alarm);
701        set_signal_handler(SIGCHLD, 1, SIG_IGN);
702        set_signal_handler(SIGHUP , 1, SIG_IGN);
703        set_signal_handler(SIGINT , 1, SIG_IGN);
704        set_signal_handler(SIGUSR1, 1, cs_debug_level);
705        is_server=((ip) || (port<90)) ? 1 : 0;
706        client[i].fd_m2c_c=fdp[0];
707        close(fdp[1]);
708        close(mfdr);
709        //cs_log("FORK-CLIENT: fd_m2c_c=%d", client[i].fd_m2c_c);
710        //SS:if( port!=97 ) cs_close_log();
711        mfdr=0;
712        cs_ptyp=D_CLIENT;
713        cs_idx=i;
714#ifndef CS_NOSHM
715        shmid=0;
716#endif
717        break;
718      default:          // HERE is master
719        client[i].fd_m2c=fdp[1];
720        client[i].dbglvl=cs_dblevel;
721        close(fdp[0]);
722        //cs_log("FORK-MASTER: fd_m2c=%d", client[i].fd_m2c);
723        if (ip)
724        {
725          client[i].typ='c';      // dynamic client
726          client[i].ip=ip;
727          client[i].port=port;
728          cs_log("client(%d) connect from %s (pid=%d, pipfd=%d)",
729                  i-cdiff, cs_inet_ntoa(ip), pid, client[i].fd_m2c);
730        }
731        else
732        {
733          client[i].stat=1;
734          switch(port)
735          {
736            case 99: client[i].typ='r';   // reader that is not Sc8in1 gets forked, not threaded
737                     client[i].sidtabok=reader[ridx].sidtabok;
738                     client[i].sidtabno=reader[ridx].sidtabno;
739                     reader[ridx].fd=client[i].fd_m2c;
740                     reader[ridx].cs_idx=i;
741                     reader[ridx].pid=pid;
742                     if (reader[ridx].r_port)
743                       cs_log("proxy started (pid=%d, server=%s)",
744                              pid, reader[ridx].device);
745                     else
746                     {
747                       if (reader[ridx].typ==R_MOUSE || reader[ridx].typ==R_SMART)
748                         cs_log("reader started (pid=%d, device=%s, detect=%s%s, mhz=%d, cardmhz=%d)",
749                                pid, reader[ridx].device,
750                                reader[ridx].detect&0x80 ? "!" : "",
751                                RDR_CD_TXT[reader[ridx].detect&0x7f],
752                                reader[ridx].mhz,
753                reader[ridx].cardmhz);
754                        else
755                         cs_log("reader started (pid=%d, device=%s)",
756                                pid, reader[ridx].device);
757                       client[i].ip=client[0].ip;
758                       strcpy(client[i].usr, client[0].usr);
759                     }
760                     cdiff=i;
761                     break;
762            case 97: client[i].typ='l';   // logger
763                     client[i].ip=client[0].ip;
764                     strcpy(client[i].usr, client[0].usr);
765                     cs_log("logger started (pid=%d)", pid);
766                     cdiff=i;
767                     break;
768#ifdef CS_ANTICASC
769            case 96: client[i].typ='a';
770                     client[i].ip=client[0].ip;
771                     strcpy(client[i].usr, client[0].usr);
772                     cs_log("anticascader started (pid=%d, delay=%d min)",
773                            pid, cfg->ac_stime);
774                     cdiff=i;
775                     break;
776#endif
777
778#ifdef WEBIF
779            case 95: client[i].typ='h';     // http
780                     client[i].ip=client[0].ip;
781                     strcpy(client[i].usr, client[0].usr);
782                     cs_log("http started (pid=%d)",pid);
783                     cdiff=i;
784                     break;
785#endif
786
787            default: client[i].typ='c';   // static client
788                     client[i].ip=client[0].ip;
789                     client[i].ctyp=port;
790                     cs_log("%s: initialized (pid=%d%s)", ph[port].desc,
791                            pid, ph[port].logtxt ? ph[port].logtxt : "");
792                     break;
793          }
794        }
795        client[i].login=client[i].last=time((time_t *)0);
796        client[i].pid=pid;    // MUST be last -> wait4master()
797        cs_last_idx=i;
798        i=0;
799     }//switch
800        }//else
801  }
802  else
803  {
804    cs_log("max connections reached -> reject client %s", cs_inet_ntoa(ip));
805    i=(-1);
806  }
807  return(i);
808}
809
810static void init_signal()
811{
812  int i;
813  for (i=1; i<NSIG; i++)
814        set_signal_handler(i, 3, cs_exit);
815        set_signal_handler(SIGWINCH, 1, SIG_IGN);
816        //  set_signal_handler(SIGPIPE , 0, SIG_IGN);
817        set_signal_handler(SIGPIPE , 0, cs_sigpipe);
818        //  set_signal_handler(SIGALRM , 0, cs_alarm);
819        set_signal_handler(SIGALRM , 0, cs_master_alarm);
820        set_signal_handler(SIGCHLD , 1, cs_child_chk);
821        //  set_signal_handler(SIGHUP  , 1, cs_accounts_chk);
822        set_signal_handler(SIGHUP , 1, cs_sighup);
823        set_signal_handler(SIGUSR1, 1, cs_debug_level);
824        set_signal_handler(SIGUSR2, 1, cs_card_info);
825        set_signal_handler(SIGCONT, 1, SIG_IGN);
826        cs_log("signal handling initialized (type=%s)",
827#ifdef CS_SIGBSD
828        "bsd"
829#else
830        "sysv"
831#endif
832        );
833    return;
834}
835
836static void init_shm()
837{
838#ifdef CS_NOSHM
839  //int i, fd;
840  char *buf;
841  if ((shmid=open(cs_memfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR))<0)
842  {
843    fprintf(stderr, "Cannot create mmaped file (errno=%d)", errno);
844    cs_exit(1);
845  }
846
847  buf=(char *)malloc(shmsize);
848  memset(buf, 0, shmsize);
849  if (!write(shmid, buf, shmsize)) cs_exit(1);
850  free(buf);
851
852  ecmcache=(struct s_ecm *)mmap((void *)0, (size_t) shmsize,
853                                PROT_READ|PROT_WRITE, MAP_SHARED, shmid, 0);
854#else
855  struct shmid_ds sd;
856  char *shmerr_txt="Cannot %s shared memory (errno=%d)\n";
857  if ((shmid=shmget(IPC_PRIVATE, shmsize, IPC_CREAT | 0600))<0)
858  {
859    fprintf(stderr, shmerr_txt, "create", errno);
860    shmid=0;
861    cs_exit(1);
862  }
863  if ((ecmcache=(struct s_ecm *)shmat(shmid, 0, 0))==(void *)(-1))
864  {
865    fprintf(stderr, shmerr_txt, "attach", errno);
866    cs_exit(1);
867  }
868  memset(ecmcache, 0, shmsize);
869  shmctl(shmid, IPC_RMID, &sd);
870#endif
871#ifdef CS_ANTICASC
872  acasc=(struct s_acasc_shm *)&ecmcache[CS_ECMCACHESIZE];
873  ecmidx=(int *)&acasc[CS_MAXPID];
874#else
875  ecmidx=(int *)&ecmcache[CS_ECMCACHESIZE];
876#endif
877  mcl=(int *)((void *)ecmidx+sizeof(int));
878  logidx=(int *)((void *)mcl+sizeof(int));
879  c_start=(int *)((void *)logidx+sizeof(int));
880  log_fd=(int *)((void *)c_start+sizeof(int));
881  oscam_sem=(int *)((void *)log_fd+sizeof(int));
882  client=(struct s_client *)((void *)oscam_sem+sizeof(int));
883  reader=(struct s_reader *)&client[CS_MAXPID];
884#ifdef CS_WITH_GBOX
885  Cards=(struct card_struct*)&reader[CS_MAXREADER];
886  IgnoreList=(unsigned long*)&Cards[CS_MAXCARDS];
887  idstore=(struct idstore_struct*)&IgnoreList[CS_MAXIGNORE];
888  cfg=(struct s_config *)&idstore[CS_MAXPID];
889#else
890  cfg=(struct s_config *)&reader[CS_MAXREADER];
891#endif
892#ifdef CS_LOGHISTORY
893  loghistidx=(int *)((void *)cfg+sizeof(struct s_config));
894  loghist=(char *)((void *)loghistidx+sizeof(int));
895#endif
896
897#ifdef DEBUG_SHM_POINTER
898  printf("SHM ALLOC: %x\n", shmsize);
899  printf("SHM START: %p\n", (void *) ecmcache);
900  printf("SHM ST1: %p %x (%x)\n", (void *) ecmidx, ((void *) ecmidx) - ((void *) ecmcache), CS_ECMCACHESIZE*(sizeof(struct s_ecm)));
901  printf("SHM ST2: %p %x (%x)\n", (void *) oscam_sem, ((void *) oscam_sem) - ((void *) ecmidx), sizeof(int));
902  printf("SHM ST3: %p %x (%x)\n", (void *) client, ((void *) client) - ((void *) oscam_sem), sizeof(int));
903  printf("SHM ST4: %p %x (%x)\n", (void *) reader, ((void *) reader) - ((void *) client), CS_MAXPID*(sizeof(struct s_client)));
904  printf("SHM ST5: %p %x (%x)\n", (void *) cfg, ((void *) cfg) - ((void *) reader), CS_MAXREADER*(sizeof(struct s_reader)));
905  printf("SHM ST6: %p %x (%x)\n", ((void *) cfg)+sizeof(struct s_config), sizeof(struct s_config), sizeof(struct s_config));
906  printf("SHM ENDE: %p\n", ((void *) cfg)+sizeof(struct s_config));
907  printf("SHM SIZE: %x\n", ((void *) cfg)-((void *) ecmcache) + sizeof(struct s_config));
908  fflush(stdout);
909#endif
910
911  *ecmidx=0;
912  *logidx=0;
913  *oscam_sem=0;
914  client[0].pid=getpid();
915  client[0].login=time((time_t *)0);
916  client[0].ip=cs_inet_addr("127.0.0.1");
917  client[0].typ='s';
918  client[0].au=(-1);
919  client[0].dbglvl=cs_dblevel;
920
921  // get username master running under
922  struct passwd *pwd;
923  if ((pwd = getpwuid(getuid())) != NULL)
924    strcpy(client[0].usr, pwd->pw_name);
925  else
926    strcpy(client[0].usr, "root");
927
928  pthread_mutex_init(&gethostbyname_lock, NULL); 
929  init_stat();
930
931#ifdef CS_LOGHISTORY
932  *loghistidx=0;
933  memset(loghist, 0, CS_MAXLOGHIST*CS_LOGHISTSIZE);
934#endif
935}
936
937static int start_listener(struct s_module *ph, int port_idx)
938{
939  int ov=1, timeout, is_udp, i;
940  char ptxt[2][32];
941  //struct   hostent   *ptrh;     /* pointer to a host table entry */
942  struct   protoent  *ptrp;     /* pointer to a protocol table entry */
943  struct   sockaddr_in sad;     /* structure to hold server's address */
944
945  ptxt[0][0]=ptxt[1][0]='\0';
946  if (!ph->ptab->ports[port_idx].s_port)
947  {
948    cs_log("%s: disabled", ph->desc);
949    return(0);
950  }
951  is_udp=(ph->type==MOD_CONN_UDP);
952
953  memset((char  *)&sad,0,sizeof(sad)); /* clear sockaddr structure   */
954  sad.sin_family = AF_INET;            /* set family to Internet     */
955  if (!ph->s_ip)
956    ph->s_ip=cfg->srvip;
957  if (ph->s_ip)
958  {
959    sad.sin_addr.s_addr=ph->s_ip;
960    sprintf(ptxt[0], ", ip=%s", inet_ntoa(sad.sin_addr));
961  }
962  else
963    sad.sin_addr.s_addr=INADDR_ANY;
964  timeout=cfg->bindwait;
965  //ph->fd=0;
966  ph->ptab->ports[port_idx].fd = 0;
967
968  if (ph->ptab->ports[port_idx].s_port > 0)   /* test for illegal value    */
969    sad.sin_port = htons((u_short)ph->ptab->ports[port_idx].s_port);
970  else
971  {
972    cs_log("%s: Bad port %d", ph->desc, ph->ptab->ports[port_idx].s_port);
973    return(0);
974  }
975
976  /* Map transport protocol name to protocol number */
977
978  if( (ptrp=getprotobyname(is_udp ? "udp" : "tcp")) )
979    ov=ptrp->p_proto;
980  else
981    ov=(is_udp) ? 17 : 6; // use defaults on error
982
983  if ((ph->ptab->ports[port_idx].fd=socket(PF_INET,is_udp ? SOCK_DGRAM : SOCK_STREAM, ov))<0)
984  {
985    cs_log("%s: Cannot create socket (errno=%d)", ph->desc, errno);
986    return(0);
987  }
988
989  ov=1;
990  if (setsockopt(ph->ptab->ports[port_idx].fd, SOL_SOCKET, SO_REUSEADDR, (void *)&ov, sizeof(ov))<0)
991  {
992    cs_log("%s: setsockopt failed (errno=%d)", ph->desc, errno);
993    close(ph->ptab->ports[port_idx].fd);
994    return(ph->ptab->ports[port_idx].fd=0);
995  }
996
997#ifdef SO_REUSEPORT
998  setsockopt(ph->ptab->ports[port_idx].fd, SOL_SOCKET, SO_REUSEPORT, (void *)&ov, sizeof(ov));
999#endif
1000
1001#ifdef SO_PRIORITY
1002  if (cfg->netprio)
1003    if (!setsockopt(ph->ptab->ports[port_idx].fd, SOL_SOCKET, SO_PRIORITY, (void *)&cfg->netprio, sizeof(ulong)))
1004      sprintf(ptxt[1], ", prio=%ld", cfg->netprio);
1005#endif
1006
1007  if( !is_udp )
1008  {
1009    ulong keep_alive = 1;
1010    setsockopt(ph->ptab->ports[port_idx].fd, SOL_SOCKET, SO_KEEPALIVE,
1011               (void *)&keep_alive, sizeof(ulong));
1012  }
1013
1014  while (timeout--)
1015  {
1016    if (bind(ph->ptab->ports[port_idx].fd, (struct sockaddr *)&sad, sizeof (sad))<0)
1017    {
1018      if (timeout)
1019      {
1020        cs_log("%s: Bind request failed, waiting another %d seconds",
1021               ph->desc, timeout);
1022        cs_sleepms(1000);
1023      }
1024      else
1025      {
1026        cs_log("%s: Bind request failed, giving up", ph->desc);
1027        close(ph->ptab->ports[port_idx].fd);
1028        return(ph->ptab->ports[port_idx].fd=0);
1029      }
1030    }
1031    else timeout=0;
1032  }
1033
1034  if (!is_udp)
1035    if (listen(ph->ptab->ports[port_idx].fd, CS_QLEN)<0)
1036    {
1037      cs_log("%s: Cannot start listen mode (errno=%d)", ph->desc, errno);
1038      close(ph->ptab->ports[port_idx].fd);
1039      return(ph->ptab->ports[port_idx].fd=0);
1040    }
1041
1042  cs_log("%s: initialized (fd=%d, port=%d%s%s%s)",
1043         ph->desc, ph->ptab->ports[port_idx].fd,
1044         ph->ptab->ports[port_idx].s_port,
1045         ptxt[0], ptxt[1], ph->logtxt ? ph->logtxt : "");
1046
1047  for( i=0; i<ph->ptab->ports[port_idx].ftab.nfilts; i++ ) {
1048    int j;
1049    cs_log("CAID: %04X", ph->ptab->ports[port_idx].ftab.filts[i].caid );
1050    for( j=0; j<ph->ptab->ports[port_idx].ftab.filts[i].nprids; j++ )
1051      cs_log("provid #%d: %06X", j, ph->ptab->ports[port_idx].ftab.filts[i].prids[j]);
1052  }
1053  return(ph->ptab->ports[port_idx].fd);
1054}
1055
1056static void cs_client_resolve()
1057{
1058  while (1)
1059  {
1060    struct addrinfo hints, *res = NULL;
1061    struct s_auth *account;
1062       
1063    for (account=cfg->account; account; account=account->next)
1064      if (account->dyndns[0])
1065      {
1066        pthread_mutex_lock(&gethostbyname_lock);
1067        memset(&hints, 0, sizeof(hints));
1068        hints.ai_socktype = SOCK_STREAM;
1069        hints.ai_family = AF_INET;
1070        hints.ai_protocol = IPPROTO_TCP;
1071               
1072        int err = getaddrinfo((const char*)account->dyndns, NULL, &hints, &res);
1073        if (err != 0 || !res || !res->ai_addr) {
1074          cs_log("can't resolve %s, error: %s", account->dyndns, err ? gai_strerror(err) : "unknown");
1075        }
1076        else {
1077          account->dynip=cs_inet_order(((struct sockaddr_in *)(res->ai_addr))->sin_addr.s_addr);
1078        }
1079        if (res) freeaddrinfo(res);
1080        pthread_mutex_unlock(&gethostbyname_lock);
1081      }
1082    sleep(cfg->resolvedelay);
1083  }
1084}
1085
1086static void start_thread(void * startroutine, char * nameroutine)
1087{
1088  int i;
1089  pthread_t tid;
1090
1091  i=pthread_create(&tid, (pthread_attr_t *)0, startroutine, (void *) 0);
1092  if (i)
1093    cs_log("ERROR: can't create %s thread (err=%d)", i, nameroutine);
1094  else
1095  {
1096    cs_log("%s thread started", nameroutine);
1097    pthread_detach(tid);
1098  }
1099}
1100
1101static void cs_logger(void)
1102{
1103  *log_fd=client[cs_idx].fd_m2c;
1104  while(1)
1105  {
1106    uchar *ptr;
1107    //struct timeval tv;
1108    fd_set fds;
1109
1110    FD_ZERO(&fds);
1111    FD_SET(client[cs_idx].fd_m2c_c, &fds);
1112    select(client[cs_idx].fd_m2c_c+1, &fds, 0, 0, 0);
1113
1114    if (master_pid!=getppid())
1115      cs_exit(0);
1116
1117    if (FD_ISSET(client[cs_idx].fd_m2c_c, &fds))
1118    {
1119      int n;
1120//    switch(n=read_from_pipe(client[cs_idx].fd_m2c_c, &ptr, 1))
1121      n=read_from_pipe(client[cs_idx].fd_m2c_c, &ptr, 1);
1122//if (n!=PIP_ID_NUL) printf("received %d bytes\n", n); fflush(stdout);
1123      switch(n)
1124      {
1125        case PIP_ID_LOG:
1126          cs_write_log((char *)ptr);
1127          break;
1128      }
1129    }
1130  }
1131}
1132
1133#ifdef CS_ANTICASC
1134static void start_anticascader()
1135{
1136  int i;
1137
1138  use_ac_log=1;
1139  set_signal_handler(SIGHUP, 1, ac_init_stat);
1140
1141  ac_init_stat();
1142  while(1)
1143  {
1144    for( i=0; i<cfg->ac_stime*60; i++ )
1145      if( master_pid!=getppid() )
1146        cs_exit(0);
1147      else
1148        cs_sleepms(1000);
1149
1150    if (master_pid!=getppid())
1151      cs_exit(0);
1152
1153    ac_do_stat();
1154  }
1155}
1156#endif
1157
1158#ifdef WEBIF
1159static void cs_http()
1160{
1161    http_srv();
1162}
1163#endif
1164
1165
1166static void init_cardreader()
1167{
1168    for (ridx=0; ridx<CS_MAXREADER; ridx++) {
1169        reader[ridx].ridx = ridx; //FIXME
1170        if ((reader[ridx].device[0]) && (reader[ridx].enable == 1)) {
1171            switch(cs_fork(0, 99)) {
1172                case -1:
1173                    cs_exit(1);
1174                case  0:
1175                    break;
1176                default:
1177                wait4master();
1178                start_cardreader(&reader[ridx]);
1179            }
1180        }
1181    }
1182}
1183
1184static void init_service(int srv)
1185{
1186    switch(cs_fork(0, srv))
1187    {
1188    case -1:
1189    cs_exit(1);
1190    case  0:
1191        break;
1192    default:
1193        wait4master();
1194        switch(srv)
1195        {
1196#ifdef CS_ANTICASC
1197        case 96: start_anticascader();
1198#endif
1199        case 97: cs_logger();
1200#ifdef WEBIF
1201        case 95: cs_http();
1202#endif
1203        }
1204    }
1205}
1206
1207void wait4master()
1208{
1209  int i;
1210  for (i=0; (i<1000) && (client[cs_idx].pid!=getpid()); i++)
1211    cs_sleepms(1);
1212  if (client[cs_idx].pid!=getpid())
1213  {
1214    cs_log("PANIC: client not found in shared memory");
1215    cs_exit(1);
1216  }
1217  cs_debug("starting client %d with ip %s",
1218            cs_idx-cdiff, cs_inet_ntoa(client[cs_idx].ip));
1219}
1220
1221static void cs_fake_client(char *usr, int uniq, in_addr_t ip)
1222{
1223    /* Uniq = 1: only one connection per user
1224     *
1225     * Uniq = 2: set (new connected) user only to fake if source
1226     *           ip is different (e.g. for newcamd clients with
1227     *           different CAID's -> Ports)
1228     *
1229     * Uniq = 3: only one connection per user, but only the last
1230     *           login will survive (old mpcs behavior)
1231     *
1232     * Uniq = 4: set user only to fake if source ip is
1233     *           different, but only the last login will survive
1234     */
1235
1236    int i;
1237    for (i=cdiff+1; i<CS_MAXPID; i++)
1238    {
1239        if (client[i].pid && (client[i].typ == 'c') && !client[i].dup && !strcmp(client[i].usr, usr)
1240           && (uniq < 5) && ((uniq % 2) || (client[i].ip != ip)))
1241        {
1242            if (uniq  == 3 || uniq == 4)
1243            {
1244                client[i].dup = 1;
1245                client[i].au = -1;
1246                cs_log("client(%d) duplicate user '%s' from %s set to fake (uniq=%d)", i-cdiff, usr, cs_inet_ntoa(ip), uniq);
1247            }
1248            else
1249            {
1250                client[cs_idx].dup = 1;
1251                client[cs_idx].au = -1;
1252                cs_log("client(%d) duplicate user '%s' from %s set to fake (uniq=%d)", cs_idx-cdiff, usr, cs_inet_ntoa(ip), uniq);
1253                break;
1254            }
1255
1256        }
1257    }
1258
1259}
1260
1261int cs_auth_client(struct s_auth *account, char *e_txt)
1262{
1263    int rc=0;
1264    char buf[32];
1265    char *t_crypt="encrypted";
1266    char *t_plain="plain";
1267    char *t_grant=" granted";
1268    char *t_reject=" rejected";
1269    char *t_msg[]= { buf, "invalid access", "invalid ip", "unknown reason" };
1270    client[cs_idx].grp=0xffffffff;
1271    client[cs_idx].au=(-1);
1272    switch((long)account)
1273    {
1274#ifdef CS_WITH_GBOX
1275    case -2:            // gbx-dummy
1276    client[cs_idx].dup=0;
1277    break;
1278#endif
1279    case 0:           // reject access
1280        rc=1;
1281        cs_log("%s %s-client %s%s (%s)",
1282                client[cs_idx].crypted ? t_crypt : t_plain,
1283                ph[client[cs_idx].ctyp].desc,
1284                client[cs_idx].ip ? cs_inet_ntoa(client[cs_idx].ip) : "",
1285                client[cs_idx].ip ? t_reject : t_reject+1,
1286                e_txt ? e_txt : t_msg[rc]);
1287        break;
1288    default:            // grant/check access
1289        if (client[cs_idx].ip && account->dyndns[0]) {
1290            if (cfg->clientdyndns) {
1291                if (client[cs_idx].ip != account->dynip)
1292                    rc=2;
1293            }
1294            else
1295                cs_log("Warning: clientdyndns disabled in config. Enable clientdyndns to use hostname restrictions");
1296        }
1297
1298        if (!rc)
1299        {
1300            client[cs_idx].dup=0;
1301            if (client[cs_idx].typ=='c')
1302            {
1303                client[cs_idx].last_caid = 0xFFFE;
1304                client[cs_idx].last_srvid = 0xFFFE;
1305                client[cs_idx].expirationdate=account->expirationdate;
1306                client[cs_idx].disabled=account->disabled;
1307                client[cs_idx].c35_suppresscmd08 = account->c35_suppresscmd08;
1308                client[cs_idx].ncd_keepalive = account->ncd_keepalive;
1309                client[cs_idx].grp=account->grp;
1310                client[cs_idx].au=account->au;
1311                client[cs_idx].autoau=account->autoau;
1312                client[cs_idx].tosleep=(60*account->tosleep);
1313                client[cs_idx].c35_sleepsend = account->c35_sleepsend;
1314                memcpy(&client[cs_idx].ctab, &account->ctab, sizeof(client[cs_idx].ctab));
1315                if (account->uniq)
1316                    cs_fake_client(account->usr, account->uniq, client[cs_idx].ip);
1317                client[cs_idx].ftab  = account->ftab;   // IDENT filter
1318                client[cs_idx].cltab = account->cltab;  // CLASS filter
1319                client[cs_idx].fchid = account->fchid;  // CHID filter
1320                client[cs_idx].sidtabok= account->sidtabok;   // services
1321                client[cs_idx].sidtabno= account->sidtabno;   // services
1322                client[cs_idx].pcrc  = crc32(0L, MD5((uchar *)account->pwd, strlen(account->pwd), NULL), 16);
1323                memcpy(&client[cs_idx].ttab, &account->ttab, sizeof(client[cs_idx].ttab));
1324#ifdef CS_ANTICASC
1325                ac_init_client(account);
1326#endif
1327            }
1328        }
1329        client[cs_idx].monlvl=account->monlvl;
1330        strcpy(client[cs_idx].usr, account->usr);
1331    case -1:            // anonymous grant access
1332    if (rc)
1333        t_grant=t_reject;
1334    else
1335    {
1336        if (client[cs_idx].typ=='m')
1337            sprintf(t_msg[0], "lvl=%d", client[cs_idx].monlvl);
1338        else
1339        {
1340            if(client[cs_idx].autoau)
1341            {
1342                if(client[cs_idx].ncd_server)
1343                {
1344                    int r=0;
1345                    for(r=0;r<CS_MAXREADER;r++)
1346                    {
1347                        if(reader[r].caid[0]==cfg->ncd_ptab.ports[client[cs_idx].port_idx].ftab.filts[0].caid)
1348                        {
1349                            client[cs_idx].au=r;
1350                            break;
1351                        }
1352                    }
1353                    if(client[cs_idx].au<0) sprintf(t_msg[0], "au(auto)=%d", client[cs_idx].au+1);
1354                    else sprintf(t_msg[0], "au(auto)=%s", reader[client[cs_idx].au].label);
1355                }
1356                else
1357                {
1358                    sprintf(t_msg[0], "au=auto");
1359                }
1360            }
1361            else
1362            {
1363                if(client[cs_idx].au<0) sprintf(t_msg[0], "au=%d", client[cs_idx].au+1);
1364                else sprintf(t_msg[0], "au=%s", reader[client[cs_idx].au].label);
1365            }
1366        }
1367    }
1368    if(client[cs_idx].ncd_server)
1369    {
1370        cs_log("%s %s:%d-client %s%s (%s, %s)",
1371                client[cs_idx].crypted ? t_crypt : t_plain,
1372                e_txt ? e_txt : ph[client[cs_idx].ctyp].desc,
1373                cfg->ncd_ptab.ports[client[cs_idx].port_idx].s_port,
1374                client[cs_idx].ip ? cs_inet_ntoa(client[cs_idx].ip) : "",
1375                client[cs_idx].ip ? t_grant : t_grant+1,
1376                username(cs_idx), t_msg[rc]);
1377    }
1378    else
1379    {
1380        cs_log("%s %s-client %s%s (%s, %s)",
1381                client[cs_idx].crypted ? t_crypt : t_plain,
1382                e_txt ? e_txt : ph[client[cs_idx].ctyp].desc,
1383                client[cs_idx].ip ? cs_inet_ntoa(client[cs_idx].ip) : "",
1384                client[cs_idx].ip ? t_grant : t_grant+1,
1385                username(cs_idx), t_msg[rc]);
1386    }
1387
1388    break;
1389    }
1390    return(rc);
1391}
1392
1393void cs_disconnect_client(void)
1394{
1395    char buf[32]={0};
1396    if (client[cs_idx].ip)
1397        sprintf(buf, " from %s", cs_inet_ntoa(client[cs_idx].ip));
1398    cs_log("%s disconnected %s", username(cs_idx), buf);
1399    cs_exit(0);
1400}
1401
1402/**
1403 * cache 1: client-invoked
1404 * returns found ecm task index
1405 **/
1406int check_ecmcache1(ECM_REQUEST *er, ulong grp)
1407{
1408    int i;
1409    //cs_ddump(ecmd5, CS_ECMSTORESIZE, "ECM search");
1410    //cs_log("cache1 CHECK: grp=%lX", grp);
1411    for(i=0; i<CS_ECMCACHESIZE; i++) {
1412        if ((grp & ecmcache[i].grp) &&
1413             ecmcache[i].caid==er->caid &&
1414             (!memcmp(ecmcache[i].ecmd5, er->ecmd5, CS_ECMSTORESIZE)))
1415        {
1416            //cs_log("cache1 found: grp=%lX cgrp=%lX", grp, ecmcache[i].grp);
1417            memcpy(er->cw, ecmcache[i].cw, 16);
1418            er->reader[0] = ecmcache[i].reader;
1419            return(1);
1420        }
1421    }
1422    return(0);
1423}
1424
1425/**
1426 * cache 2: reader-invoked
1427 * returns 1 if found in cache. cw is copied to er
1428 **/
1429int check_ecmcache2(ECM_REQUEST *er, ulong grp)
1430{
1431    // disable cache2
1432    if (!reader[ridx].cachecm) return(0);
1433   
1434    int i;
1435    //cs_ddump(ecmd5, CS_ECMSTORESIZE, "ECM search");
1436    //cs_log("cache2 CHECK: grp=%lX", grp);
1437    for(i=0; i<CS_ECMCACHESIZE; i++) {
1438        if ((grp & ecmcache[i].grp) &&
1439             ecmcache[i].caid==er->caid &&
1440             (!memcmp(ecmcache[i].ecmd5, er->ecmd5, CS_ECMSTORESIZE)))
1441        {
1442            //cs_log("cache2 found: grp=%lX cgrp=%lX", grp, ecmcache[i].grp);
1443            memcpy(er->cw, ecmcache[i].cw, 16);
1444            return(1);
1445        }
1446    }
1447    return(0);
1448}
1449
1450
1451static void store_ecm(ECM_REQUEST *er)
1452{
1453    int rc;
1454    rc=*ecmidx;
1455    *ecmidx=(*ecmidx+1) % CS_ECMCACHESIZE;
1456    //cs_log("store ecm from reader %d", er->reader[0]);
1457    memcpy(ecmcache[rc].ecmd5, er->ecmd5, CS_ECMSTORESIZE);
1458    memcpy(ecmcache[rc].cw, er->cw, 16);
1459    ecmcache[rc].caid = er->caid;
1460    ecmcache[rc].grp = reader[er->reader[0]].grp;
1461    ecmcache[rc].reader = er->reader[0];
1462    //cs_ddump(ecmcache[*ecmidx].ecmd5, CS_ECMSTORESIZE, "ECM stored (idx=%d)", *ecmidx);
1463}
1464
1465void store_logentry(char *txt)
1466{
1467#ifdef CS_LOGHISTORY
1468    char *ptr;
1469    ptr=(char *)(loghist+(*loghistidx*CS_LOGHISTSIZE));
1470    ptr[0]='\1';    // make username unusable
1471    ptr[1]='\0';
1472    if ((client[cs_idx].typ=='c') || (client[cs_idx].typ=='m'))
1473        cs_strncpy(ptr, client[cs_idx].usr, 31);
1474    cs_strncpy(ptr+32, txt, CS_LOGHISTSIZE-33);
1475    *loghistidx=(*loghistidx+1) % CS_MAXLOGHIST;
1476#endif
1477}
1478
1479/*
1480 * write_to_pipe():
1481 * write all kind of data to pipe specified by fd
1482 */
1483int write_to_pipe(int fd, int id, uchar *data, int n)
1484{
1485  if( !fd ) {
1486        cs_log("write_to_pipe: fd==0 id: %d", id);
1487        return -1;
1488  }
1489
1490//printf("WRITE_START pid=%d", getpid()); fflush(stdout);
1491
1492  uchar buf[1024+3+sizeof(int)];
1493
1494  if ((id<0) || (id>PIP_ID_MAX))
1495    return(PIP_ID_ERR);
1496  memcpy(buf, PIP_ID_TXT[id], 3);
1497  memcpy(buf+3, &n, sizeof(int));
1498  memcpy(buf+3+sizeof(int), data, n);
1499  n+=3+sizeof(int);
1500
1501//n=write(fd, buf, n);
1502//printf("WRITE_END pid=%d", getpid()); fflush(stdout);
1503//return(n);
1504
1505  return(write(fd, buf, n));
1506}
1507
1508/*
1509 * read_from_pipe():
1510 * read all kind of data from pipe specified by fd
1511 * special-flag redir: if set AND data is ECM: this will redirected to appr. client
1512 */
1513int read_from_pipe(int fd, uchar **data, int redir)
1514{
1515  int rc;
1516  static int hdr=0;
1517  static uchar buf[1024+1+3+sizeof(int)];
1518
1519  *data=(uchar *)0;
1520  rc=PIP_ID_NUL;
1521
1522  if (!hdr)
1523  {
1524    if (bytes_available(fd))
1525    {
1526      if (read(fd, buf, 3+sizeof(int))==3+sizeof(int))
1527        memcpy(&hdr, buf+3, sizeof(int));
1528      else
1529        cs_log("WARNING: pipe header to small !");
1530    }
1531  }
1532  if (hdr)
1533  {
1534    int l;
1535    for (l=0; (rc<0) && (PIP_ID_TXT[l]); l++)
1536      if (!memcmp(buf, PIP_ID_TXT[l], 3))
1537        rc=l;
1538
1539    if (rc<0)
1540    {
1541      fprintf(stderr, "WARNING: pipe garbage from pipe %i", fd);
1542      fflush(stderr);
1543      cs_log("WARNING: pipe garbage from pipe %i", fd);
1544      rc=PIP_ID_ERR;
1545    }
1546    else
1547    {
1548      l=hdr;
1549      if ((l+3-1+sizeof(int))>sizeof(buf))
1550      {
1551        cs_log("WARNING: packet size (%d) to large", l);
1552        l=sizeof(buf)+3-1+sizeof(int);
1553      }
1554      if (!bytes_available(fd))
1555        return(PIP_ID_NUL);
1556      hdr=0;
1557      if (read(fd, buf+3+sizeof(int), l)==l)
1558        *data=buf+3+sizeof(int);
1559      else
1560      {
1561        cs_log("WARNING: pipe data to small !");
1562        return(PIP_ID_ERR);
1563      }
1564      buf[l+3+sizeof(int)]=0;
1565      if ((redir) && (rc==PIP_ID_ECM))
1566      {
1567        //int idx;
1568        ECM_REQUEST *er;
1569        er=(ECM_REQUEST *)(buf+3+sizeof(int));
1570        if( er->cidx && client[er->cidx].fd_m2c )
1571            if (!write(client[er->cidx].fd_m2c, buf, l+3+sizeof(int))) cs_exit(1);
1572        rc=PIP_ID_DIR;
1573      }
1574    }
1575  }
1576  return(rc);
1577}
1578
1579/*
1580 * write_ecm_request():
1581 */
1582int write_ecm_request(int fd, ECM_REQUEST *er)
1583{
1584  return(write_to_pipe(fd, PIP_ID_ECM, (uchar *) er, sizeof(ECM_REQUEST)));
1585}
1586
1587int write_ecm_DCW(int fd, ECM_REQUEST *er)
1588{
1589  return(write_to_pipe(fd, PIP_ID_DCW, (uchar *) er, sizeof(ECM_REQUEST)));
1590}
1591
1592/*
1593 * This function writes the current CW from ECM struct to a cwl file.
1594 * The filename is re-calculated and file re-opened every time.
1595 * This will consume a bit cpu time, but nothing has to be stored between
1596 * each call. If not file exists, a header is prepended
1597 */
1598void logCWtoFile(ECM_REQUEST *er)
1599{
1600    FILE *pfCWL;
1601    char srvname[128];
1602    /* %s / %s   _I  %04X  _  %s  .cwl  */
1603    char buf[256 + sizeof(srvname)];
1604    char date[7];
1605    unsigned char  i, parity, writeheader = 0;
1606    time_t t;
1607    struct tm *timeinfo;
1608    struct s_srvid *this;
1609
1610    /*
1611    * search service name for that id and change characters
1612    * causing problems in file name
1613    */
1614    srvname[0] = 0;
1615    for (this=cfg->srvid; this; this = this->next) {
1616        if (this->srvid == er->srvid) {
1617            cs_strncpy(srvname, this->name, sizeof(srvname));
1618            srvname[sizeof(srvname)-1] = 0;
1619            for (i = 0; srvname[i]; i++)
1620                if (srvname[i] == ' ') srvname[i] = '_';
1621            break;
1622        }
1623    }
1624
1625    /* calc log file name */
1626    time(&t);
1627    timeinfo = localtime(&t);
1628    strftime(date, sizeof(date), "%Y%m%d", timeinfo);
1629    sprintf(buf, "%s/%s_I%04X_%s.cwl", cfg->cwlogdir, date, er->srvid, srvname);
1630
1631    /* open failed, assuming file does not exist, yet */
1632    if((pfCWL = fopen(buf, "r")) == NULL) {
1633        writeheader = 1;
1634    } else {
1635    /* we need to close the file if it was opened correctly */
1636        fclose(pfCWL);
1637    }
1638
1639    if ((pfCWL = fopen(buf, "a+")) == NULL) {
1640        /* maybe this fails because the subdir does not exist. Is there a common function to create it?
1641            for the moment do not print to log on every ecm
1642            cs_log(""error opening cw logfile for writing: %s (errno %d)", buf, errno); */
1643        return;
1644    }
1645    if (writeheader) {
1646        /* no global macro for cardserver name :( */
1647        fprintf(pfCWL, "# OSCam cardserver v%s - http://streamboard.gmc.to:8001/oscam/wiki\n", CS_VERSION_X);
1648        fprintf(pfCWL, "# control word log file for use with tsdec offline decrypter\n");
1649        strftime(buf, sizeof(buf),"DATE %Y-%m-%d, TIME %H:%M:%S, TZ %Z\n", timeinfo);
1650        fprintf(pfCWL, "# %s", buf);
1651        fprintf(pfCWL, "# CAID 0x%04X, SID 0x%04X, SERVICE \"%s\"\n", er->caid, er->srvid, srvname);
1652    }
1653
1654    parity = er->ecm[0]&1;
1655    fprintf(pfCWL, "%d ", parity);
1656    for (i = parity * 8; i < 8 + parity * 8; i++)
1657        fprintf(pfCWL, "%02X ", er->cw[i]);
1658    /* better use incoming time er->tps rather than current time? */
1659    strftime(buf,sizeof(buf),"%H:%M:%S\n", timeinfo);
1660    fprintf(pfCWL, "# %s", buf);
1661    fflush(pfCWL);
1662    fclose(pfCWL);
1663}
1664
1665int write_ecm_answer(struct s_reader * reader, int fd, ECM_REQUEST *er)
1666{
1667  int i;
1668  uchar c;
1669  for (i=0; i<16; i+=4)
1670  {
1671    c=((er->cw[i]+er->cw[i+1]+er->cw[i+2]) & 0xff);
1672    if (er->cw[i+3]!=c)
1673    {
1674      cs_debug("notice: changed dcw checksum byte cw[%i] from %02x to %02x", i+3, er->cw[i+3],c);
1675      er->cw[i+3]=c;
1676    }
1677  }
1678
1679  er->reader[0]=reader->ridx;
1680//cs_log("answer from reader %d (rc=%d)", er->reader[0], er->rc);
1681  er->caid=er->ocaid;
1682
1683#ifdef CS_WITH_GBOX
1684  if (er->rc==1||(er->gbxRidx&&er->rc==0)) {
1685#else
1686  if (er->rc==1) {
1687#endif
1688    store_ecm(er);
1689
1690  /* CWL logging only if cwlogdir is set in config */
1691  if (cfg->cwlogdir != NULL)
1692    logCWtoFile(er);
1693  }
1694
1695  return(write_ecm_request(fd, er));
1696}
1697
1698  /*
1699static int cs_read_timer(int fd, uchar *buf, int l, int msec)
1700{
1701  struct timeval tv;
1702  fd_set fds;
1703  int rc;
1704
1705  if (!fd) return(-1);
1706  tv.tv_sec = msec / 1000;
1707  tv.tv_usec = (msec % 1000) * 1000;
1708  FD_ZERO(&fds);
1709  FD_SET(pfd, &fds);
1710
1711  select(fd+1, &fds, 0, 0, &tv);
1712
1713  rc=0;
1714  if (FD_ISSET(pfd, &fds))
1715    if (!(rc=read(fd, buf, l)))
1716      rc=-1;
1717
1718  return(rc);
1719}*/
1720
1721ECM_REQUEST *get_ecmtask()
1722{
1723    int i, n;
1724    ECM_REQUEST *er=0;
1725
1726    if (!ecmtask)
1727    {
1728        n=(ph[client[cs_idx].ctyp].multi)?CS_MAXPENDING:1;
1729        if( (ecmtask=(ECM_REQUEST *)malloc(n*sizeof(ECM_REQUEST))) )
1730            memset(ecmtask, 0, n*sizeof(ECM_REQUEST));
1731    }
1732
1733    n=(-1);
1734    if (!ecmtask)
1735    {
1736        cs_log("Cannot allocate memory (errno=%d)", errno);
1737        n=(-2);
1738    }
1739    else
1740        if (ph[client[cs_idx].ctyp].multi)
1741        {
1742            for (i=0; (n<0) && (i<CS_MAXPENDING); i++)
1743                if (ecmtask[i].rc<100)
1744                    er=&ecmtask[n=i];
1745        }
1746        else
1747            er=&ecmtask[n=0];
1748
1749    if (n<0)
1750        cs_log("WARNING: ecm pending table overflow !");
1751    else
1752    {
1753        memset(er, 0, sizeof(ECM_REQUEST));
1754        er->rc=100;
1755        er->cpti=n;
1756        er->cidx=cs_idx;
1757        cs_ftime(&er->tps);
1758    }
1759    return(er);
1760}
1761
1762void send_reader_stat(int ridx, ECM_REQUEST *er, int rc)
1763{
1764    if (!cfg->reader_auto_loadbalance || rc == 100)
1765        return;
1766    struct timeb tpe;
1767    cs_ftime(&tpe);
1768    int time = 1000*(tpe.time-er->tps.time)+tpe.millitm-er->tps.millitm;
1769
1770    ADD_READER_STAT add_stat;
1771    memset(&add_stat, 0, sizeof(ADD_READER_STAT));
1772    add_stat.ridx = ridx;
1773    add_stat.time = time;
1774    add_stat.rc   = rc;
1775    add_stat.caid = er->caid;
1776    add_stat.prid = er->prid;
1777    add_stat.srvid = er->srvid;
1778    write_to_pipe(fd_c2m, PIP_ID_STA, (uchar*)&add_stat, sizeof(ADD_READER_STAT));
1779}
1780
1781int hexserialset(int ridx)
1782{
1783    int i;
1784    for (i = 0; i < 8; i++)
1785        if (reader[ridx].hexserial[i])
1786            return 1;
1787    return 0;
1788}
1789
1790int send_dcw(ECM_REQUEST *er)
1791{
1792    static char *stxt[]={"found", "cache1", "cache2", "emu",
1793            "not found", "timeout", "sleeping",
1794            "fake", "invalid", "corrupt", "no card", "expdate", "disabled", "stopped"};
1795    static char *stxtEx[]={"", "group", "caid", "ident", "class", "chid", "queue", "peer"};
1796    static char *stxtWh[]={"", "user ", "reader ", "server ", "lserver "};
1797    char sby[32]="";
1798    char erEx[32]="";
1799    char uname[38]="";
1800    struct timeb tpe;
1801    ushort lc, *lp;
1802    for (lp=(ushort *)er->ecm+(er->l>>2), lc=0; lp>=(ushort *)er->ecm; lp--)
1803        lc^=*lp;
1804    cs_ftime(&tpe);
1805
1806#ifdef CS_WITH_GBOX
1807    if(er->gbxFrom)
1808        snprintf(uname,sizeof(uname)-1, "%s(%04X)", username(cs_idx), er->gbxFrom);
1809    else
1810#endif
1811        snprintf(uname,sizeof(uname)-1, "%s", username(cs_idx));
1812    if (er->rc==0)
1813    {
1814#ifdef CS_WITH_GBOX
1815        if(reader[er->reader[0]].typ==R_GBOX)
1816            snprintf(sby, sizeof(sby)-1, " by %s(%04X)", reader[er->reader[0]].label,er->gbxCWFrom);
1817        else
1818#endif
1819            // add marker to reader if ECM_REQUEST was betatunneled
1820            if(er->btun)
1821                snprintf(sby, sizeof(sby)-1, " by %s(btun)", reader[er->reader[0]].label);
1822            else
1823                snprintf(sby, sizeof(sby)-1, " by %s", reader[er->reader[0]].label);
1824    }
1825    if (er->rc<4) er->rcEx=0;
1826    if (er->rcEx)
1827        snprintf(erEx, sizeof(erEx)-1, "rejected %s%s", stxtWh[er->rcEx>>4],
1828                stxtEx[er->rcEx&0xf]);
1829
1830    client[cs_idx].cwlastresptime = 1000*(tpe.time-er->tps.time)+tpe.millitm-er->tps.millitm;
1831
1832#ifdef CS_LED
1833    if(!er->rc) cs_switch_led(LED2, LED_BLINK_OFF);
1834#endif
1835
1836    send_reader_stat(er->reader[0], er, er->rc);
1837   
1838    if(cfg->mon_appendchaninfo)
1839        cs_log("%s (%04X&%06X/%04X/%02X:%04X): %s (%d ms)%s - %s",
1840                uname, er->caid, er->prid, er->srvid, er->l, lc,
1841                er->rcEx?erEx:stxt[er->rc], client[cs_idx].cwlastresptime, sby, get_servicename(er->srvid, er->caid));
1842    else
1843        cs_log("%s (%04X&%06X/%04X/%02X:%04X): %s (%d ms)%s",
1844                uname, er->caid, er->prid, er->srvid, er->l, lc,
1845                er->rcEx?erEx:stxt[er->rc], client[cs_idx].cwlastresptime, sby);
1846#ifdef WEBIF
1847    if(er->rc == 0)
1848        snprintf(client[cs_idx].lastreader, sizeof(client[cs_idx].lastreader)-1, "%s", sby);
1849    else if ((er->rc == 1) || (er->rc == 2))
1850        snprintf(client[cs_idx].lastreader, sizeof(client[cs_idx].lastreader)-1, "by %s (cache)", reader[er->reader[0]].label);
1851    else
1852        snprintf(client[cs_idx].lastreader, sizeof(client[cs_idx].lastreader)-1, "%s", stxt[er->rc]);
1853#endif
1854
1855    if(!client[cs_idx].ncd_server && client[cs_idx].autoau && er->rcEx==0)
1856    {
1857        if(client[cs_idx].au>=0 && er->caid!=reader[client[cs_idx].au].caid[0])
1858        {
1859            client[cs_idx].au=(-1);
1860        }
1861        //martin
1862        //client[cs_idx].au=er->reader[0];
1863        //if(client[cs_idx].au<0)
1864        //{
1865        struct s_reader *cur = &reader[er->reader[0]];
1866       
1867        if (cur->typ == R_CCCAM && !cur->caid[0] && !cur->audisabled && 
1868                cur->card_system == get_cardsystem(er->caid) && hexserialset(er->reader[0]))
1869            client[cs_idx].au = er->reader[0];
1870        else if((er->caid == cur->caid[0]) && (!cur->audisabled)) {
1871            client[cs_idx].au = er->reader[0]; // First chance - check whether actual reader can AU
1872        } else {
1873            int r=0;
1874            for(r=0;r<CS_MAXREADER;r++) //second chance loop through all readers to find an AU reader
1875            {
1876                cur = &reader[r];
1877                if (matching_reader(er, cur)) {
1878                    if (cur->typ == R_CCCAM && !cur->caid[0] && !cur->audisabled && 
1879                        cur->card_system == get_cardsystem(er->caid) && hexserialset(r))
1880                    {
1881                        client[cs_idx].au = r;
1882                        break;
1883                    }
1884                    else if((er->caid == cur->caid[0]) && (er->prid == cur->auprovid) && (!cur->audisabled))
1885                    {
1886                        client[cs_idx].au=r;
1887                        break;
1888                    }
1889                }
1890            }
1891            if(r==CS_MAXREADER)
1892            {
1893                client[cs_idx].au=(-1);
1894            }
1895        }
1896        //}
1897    }
1898
1899    er->caid = er->ocaid;
1900    switch(er->rc) {
1901        case 0:
1902        case 3:
1903            // 0 - found
1904            // 3 - emu FIXME: obsolete ?
1905                    client[cs_idx].cwfound++;
1906                    break;
1907
1908        case 1:
1909        case 2:
1910            // 1 - cache1
1911            // 2 - cache2
1912            client[cs_idx].cwcache++;
1913            break;
1914
1915        case 4:
1916        case 9:
1917        case 10:
1918            // 4 - not found
1919            // 9 - corrupt
1920            // 10 - no card
1921            if (er->rcEx)
1922                client[cs_idx].cwignored++;
1923            else
1924                client[cs_idx].cwnot++;
1925            break;
1926
1927        case 5:
1928            // 5 - timeout
1929            client[cs_idx].cwtout++;
1930            break;
1931
1932        default:
1933            client[cs_idx].cwignored++;
1934    }
1935
1936#ifdef CS_ANTICASC
1937    ac_chk(er, 1);
1938#endif
1939
1940    cs_ddump_mask (D_ATR, er->cw, 16, "cw:");
1941    if (er->rc==7) er->rc=0;
1942    ph[client[cs_idx].ctyp].send_dcw(er);
1943    return 0;
1944}
1945
1946void chk_dcw(int fd)
1947{
1948  ECM_REQUEST *er, *ert;
1949  if (read_from_pipe(fd, (uchar **)(void *)&er, 0) != PIP_ID_ECM)
1950      return;
1951  //cs_log("dcw check from reader %d for idx %d (rc=%d)", er->reader[0], er->cpti, er->rc);
1952  ert=&ecmtask[er->cpti];
1953  if (ert->rc<100) {
1954    send_reader_stat(er->reader[0], er, (er->rc==0)?4:((er->rc==1)?0:er->rc));
1955    return; // already done
1956  }
1957  if( (er->caid!=ert->caid) || memcmp(er->ecm , ert->ecm , sizeof(er->ecm)) )
1958    return; // obsolete
1959  ert->rcEx=er->rcEx;
1960  if (er->rc>0) // found
1961  {
1962    switch(er->rc)
1963    {
1964      case 2:
1965        ert->rc=2;
1966        break;
1967      case 3:
1968        ert->rc=3;
1969        break;
1970      default:
1971        ert->rc=0;
1972    }
1973    ert->rcEx=0;
1974    ert->reader[0]=er->reader[0];
1975    memcpy(ert->cw , er->cw , sizeof(er->cw));
1976#ifdef CS_WITH_GBOX
1977    ert->gbxCWFrom=er->gbxCWFrom;
1978#endif
1979  }
1980  else    // not found (from ONE of the readers !)
1981  {
1982    //save reader informations for loadbalance-statistics:
1983    ECM_REQUEST *save_ert = ert;
1984    int save_ridx = er->reader[0];
1985
1986    //
1987    int i;
1988    ert->reader[er->reader[0]]=0;
1989    for (i=0; (ert) && (i<CS_MAXREADER); i++)
1990      if (ert->reader[i]) {// we have still another chance
1991        ert=(ECM_REQUEST *)0;
1992      }
1993    if (ert) ert->rc=4;
1994    else send_reader_stat(save_ridx, save_ert, 4);
1995  }
1996  if (ert) send_dcw(ert);
1997  return;
1998}
1999
2000ulong chk_provid(uchar *ecm, ushort caid) {
2001    int i, len, descriptor_length = 0;
2002    ulong provid = 0;
2003
2004    switch(caid >> 8) {
2005        case 0x01:
2006            // seca
2007            provid = b2i(2, ecm+3);
2008            break;
2009
2010        case 0x05:
2011            // viaccess
2012            i = (ecm[4] == 0xD2) ? ecm[5]+2 : 0;  // skip d2 nano
2013            if((ecm[5+i] == 3) && ((ecm[4+i] == 0x90) || (ecm[4+i] == 0x40)))
2014                provid = (b2i(3, ecm+6+i) & 0xFFFFF0);
2015           
2016            i = (ecm[6] == 0xD2) ? ecm[7]+2 : 0;  // skip d2 nano long ecm
2017            if((ecm[7+i] == 7) && ((ecm[6+i] == 0x90) || (ecm[6+i] == 0x40)))
2018                provid = (b2i(3, ecm+8+i) & 0xFFFFF0);
2019
2020            break;
2021
2022        case 0x0D:
2023            // cryptoworks
2024            len = (((ecm[1] & 0xf) << 8) | ecm[2])+3;
2025            for(i=8; i<len; i+=descriptor_length+2) {
2026                descriptor_length = ecm[i+1];
2027                if (ecm[i] == 0x83) {
2028                    provid = (ulong)ecm[i+2] & 0xFE;
2029                    break;
2030                }
2031            }
2032            break;
2033    }
2034    return(provid);
2035}
2036
2037#ifdef IRDETO_GUESSING
2038void guess_irdeto(ECM_REQUEST *er)
2039{
2040  uchar  b3;
2041  int    b47;
2042  //ushort chid;
2043  struct s_irdeto_quess *ptr;
2044
2045  b3  = er->ecm[3];
2046  ptr = cfg->itab[b3];
2047  if( !ptr ) {
2048    cs_debug("unknown irdeto byte 3: %02X", b3);
2049    return;
2050  }
2051  b47  = b2i(4, er->ecm+4);
2052  //chid = b2i(2, er->ecm+6);
2053  //cs_debug("ecm: b47=%08X, ptr->b47=%08X, ptr->caid=%04X", b47, ptr->b47, ptr->caid);
2054  while( ptr )
2055  {
2056    if( b47==ptr->b47 )
2057    {
2058      if( er->srvid && (er->srvid!=ptr->sid) )
2059      {
2060        cs_debug("sid mismatched (ecm: %04X, guess: %04X), wrong oscam.ird file?",
2061                  er->srvid, ptr->sid);
2062        return;
2063      }
2064      er->caid=ptr->caid;
2065      er->srvid=ptr->sid;
2066      er->chid=(ushort)ptr->b47;
2067//      cs_debug("quess_irdeto() found caid=%04X, sid=%04X, chid=%04X",
2068//               er->caid, er->srvid, er->chid);
2069      return;
2070    }
2071    ptr=ptr->next;
2072  }
2073}
2074#endif
2075
2076void cs_betatunnel(ECM_REQUEST *er)
2077{
2078    int n;
2079    ulong mask_all = 0xFFFF;
2080    TUNTAB *ttab;
2081    ttab = &client[cs_idx].ttab;
2082    for (n = 0; (n < CS_MAXTUNTAB); n++) {
2083        if ((er->caid==ttab->bt_caidfrom[n]) && ((er->srvid==ttab->bt_srvid[n]) || (ttab->bt_srvid[n])==mask_all)) {
2084            uchar hack_n3[13] = {0x70, 0x51, 0xc7, 0x00, 0x00, 0x00, 0x01, 0x10, 0x10, 0x00, 0x87, 0x12, 0x07};
2085            uchar hack_n2[13] = {0x70, 0x51, 0xc9, 0x00, 0x00, 0x00, 0x01, 0x10, 0x10, 0x00, 0x48, 0x12, 0x07};
2086            er->caid = ttab->bt_caidto[n];
2087            er->prid = 0;
2088            er->l = (er->ecm[2]+3);
2089            memmove(er->ecm+14, er->ecm+4, er->l-1);
2090            if (er->l > 0x88) {
2091                memcpy(er->ecm+1, hack_n3, 13);
2092                if (er->ecm[0] == 0x81)
2093                    er->ecm[12] += 1;
2094            }
2095            else {
2096                memcpy(er->ecm+1, hack_n2, 13);
2097            }
2098            er->l += 10;
2099            er->ecm[2] = er->l-3;
2100            er->btun = 1;
2101            client[cs_idx].cwtun++;
2102            cs_debug("ECM converted from: 0x%X to BetaCrypt: 0x%X for service id:0x%X",
2103                ttab->bt_caidfrom[n], ttab->bt_caidto[n], ttab->bt_srvid[n]);
2104        }
2105    }
2106}
2107
2108void guess_cardsystem(ECM_REQUEST *er)
2109{
2110  ushort last_hope=0;
2111
2112  // viaccess - check by provid-search
2113  if( (er->prid=chk_provid(er->ecm, 0x500)) )
2114    er->caid=0x500;
2115
2116  // nagra
2117  // is ecm[1] always 0x30 ?
2118  // is ecm[3] always 0x07 ?
2119  if ((er->ecm[6]==1) && (er->ecm[4]==er->ecm[2]-2))
2120    er->caid=0x1801;
2121
2122  // seca2 - very poor
2123  if ((er->ecm[8]==0x10) && ((er->ecm[9]&0xF1)==1))
2124    last_hope=0x100;
2125
2126  // is cryptoworks, but which caid ?
2127  if ((er->ecm[3]==0x81) && (er->ecm[4]==0xFF) &&
2128      (!er->ecm[5]) && (!er->ecm[6]) && (er->ecm[7]==er->ecm[2]-5))
2129    last_hope=0xd00;
2130
2131#ifdef IRDETO_GUESSING
2132  if (!er->caid && er->ecm[2]==0x31 && er->ecm[0x0b]==0x28) 
2133    guess_irdeto(er); 
2134#endif
2135
2136  if (!er->caid)    // guess by len ..
2137    er->caid=len4caid[er->ecm[2]+3];
2138
2139  if (!er->caid)
2140    er->caid=last_hope;
2141}
2142
2143void request_cw(ECM_REQUEST *er, int flag, int reader_types)
2144{
2145  int i;
2146  if ((reader_types == 0) || (reader_types == 2))
2147    er->level=flag;
2148  flag=(flag)?3:1;    // flag specifies with/without fallback-readers
2149  for (i=0; i<CS_MAXREADER; i++)
2150  {
2151        //if (reader[i].pid)
2152        //    cs_log("active reader: %d pid %d fd %d", i, reader[i].pid, reader[i].fd);
2153      int status = 0;
2154      switch (reader_types)
2155      {
2156          // network and local cards
2157          default:
2158          case 0:
2159              if (er->reader[i]&flag){
2160                  //cs_debug_mask(D_TRACE, "request_cw1 to reader %s ridx=%d fd=%d", reader[i].label, i, reader[i].fd);
2161                  status = write_ecm_request(reader[i].fd, er);
2162              }
2163              break;
2164              // only local cards
2165          case 1:
2166              if (!(reader[i].typ & R_IS_NETWORK))
2167                  if (er->reader[i]&flag) {
2168                      //cs_debug_mask(D_TRACE, "request_cw2 to reader %s ridx=%d fd=%d", reader[i].label, i, reader[i].fd);
2169                    status = write_ecm_request(reader[i].fd, er);
2170                  }
2171              break;
2172              // only network
2173          case 2:
2174              //cs_log("request_cw3 ridx=%d fd=%d", i, reader[i].fd);
2175              if ((reader[i].typ & R_IS_NETWORK))
2176                  if (er->reader[i]&flag) {
2177                      //cs_debug_mask(D_TRACE, "request_cw3 to reader %s ridx=%d fd=%d", reader[i].label, i, reader[i].fd);
2178                    status = write_ecm_request(reader[i].fd, er);
2179                  }
2180              break;
2181      }
2182      if (status == -1) {
2183                cs_log("request_cw() failed on reader %s (%d) errno=%d, %s", reader[i].label, i, errno, strerror(errno));
2184            if (reader[i].fd && reader[i].pid) {
2185                reader[i].fd_error++;
2186                if (reader[i].fd_error > 5) {
2187                    reader[i].fd_error = 0;
2188                    kill(client[reader[i].cs_idx].pid, 1); //Schlocke: This should restart the reader!
2189                } 
2190        }
2191      }
2192      else
2193        reader[i].fd_error = 0;
2194  }
2195}
2196
2197//receive best reader from master process. Call this function from client!
2198void recv_best_reader(ECM_REQUEST *er, int *reader_avail)
2199{
2200    GET_READER_STAT grs;
2201    memset(&grs, 0, sizeof(grs));
2202    grs.caid = er->caid;
2203    grs.prid = er->prid;
2204    grs.srvid = er->srvid;
2205    grs.cidx = cs_idx;
2206    memcpy(grs.ecmd5, er->ecmd5, sizeof(er->ecmd5));
2207    memcpy(grs.reader_avail, reader_avail, sizeof(int)*CS_MAXREADER);
2208    cs_debug_mask(D_TRACE, "requesting client %s best reader for %04X/%06X/%04X", username(cs_idx), grs.caid, grs.prid, grs.srvid);
2209
2210    int res_write = write_to_pipe(fd_c2m, PIP_ID_BES, (uchar*)&grs, sizeof(GET_READER_STAT));
2211    if (res_write <= 0) {
2212        cs_debug_mask(D_TRACE, "get best reader: write error!");
2213        return;
2214    }
2215   
2216    uchar *ptr;
2217    fd_set fds;
2218    do
2219    {
2220        struct timeval timeout;
2221        timeout.tv_sec = 1;
2222        timeout.tv_usec = 500;
2223        FD_ZERO(&fds);
2224        FD_SET(client[cs_idx].fd_m2c_c, &fds);
2225        int res = select(client[cs_idx].fd_m2c_c+1, &fds, 0, 0, &timeout);
2226        if (res == 0) {
2227            cs_debug_mask(D_TRACE, "get best reader: timeout!");
2228            return; //timeout
2229        }
2230        else if (res < 0) {
2231            cs_debug_mask(D_TRACE, "get best reader: failed!");
2232            return; //failed
2233        }
2234           
2235        if (master_pid!=getppid())
2236            cs_exit(0);
2237        if (FD_ISSET(client[cs_idx].fd_m2c_c, &fds))
2238        {
2239            int n = read_from_pipe(client[cs_idx].fd_m2c_c, &ptr, 1);
2240            if (n == PIP_ID_BES) {
2241                int *best_readers = (int*)ptr;
2242                memcpy(reader_avail, best_readers, sizeof(int)*CS_MAXREADER);
2243                return;
2244            }
2245            else if (n == PIP_ID_DIR)
2246                continue;
2247            else //should neven happen
2248                cs_debug_mask(D_TRACE, "get best reader: illegal paket? n=%d", n);
2249        } 
2250    } while (1);
2251}
2252
2253void get_cw(ECM_REQUEST *er)
2254{
2255    int i, j, m;
2256    time_t now = time((time_t)0);
2257
2258    client[cs_idx].lastecm = now;
2259
2260    if (!er->caid)
2261        guess_cardsystem(er);
2262
2263    /* Quickfix Area */
2264
2265    if( (er->caid & 0xFF00) == 0x600 && !er->chid )
2266        er->chid = (er->ecm[6]<<8)|er->ecm[7];
2267
2268    // quickfix for 0100:000065
2269    if (er->caid == 0x100 && er->prid == 0x65 && er->srvid == 0)
2270        er->srvid = 0x0642;
2271
2272    // Quickfixes for Opticum/Globo HD9500
2273    // Quickfix for 0500:030300
2274    if (er->caid == 0x500 && er->prid == 0x030300)
2275        er->prid = 0x030600;
2276
2277    // Quickfix for 0500:D20200
2278    if (er->caid == 0x500 && er->prid == 0xD20200)
2279        er->prid = 0x030600; 
2280
2281    /* END quickfixes */
2282
2283    if (!er->prid)
2284        er->prid = chk_provid(er->ecm, er->caid);
2285
2286    // Set providerid for newcamd clients if none is given
2287    if( (!er->prid) && client[cs_idx].ncd_server ) {
2288        int pi = client[cs_idx].port_idx;
2289        if( pi >= 0 && cfg->ncd_ptab.nports && cfg->ncd_ptab.nports >= pi )
2290            er->prid = cfg->ncd_ptab.ports[pi].ftab.filts[0].prids[0];
2291    }
2292
2293    // CAID not supported or found
2294    if (!er->caid) {
2295        er->rc = 8;
2296        er->rcEx = E2_CAID;
2297    }
2298
2299    // user expired
2300    if(client[cs_idx].expirationdate && client[cs_idx].expirationdate < client[cs_idx].lastecm)
2301        er->rc = 11;
2302
2303    // out of timeframe
2304    if(client[cs_idx].allowedtimeframe[0] && client[cs_idx].allowedtimeframe[1]) {
2305        struct tm *acttm;
2306        acttm = localtime(&now);
2307        int curtime = (acttm->tm_hour * 60) + acttm->tm_min;
2308        int mintime = client[cs_idx].allowedtimeframe[0];
2309        int maxtime = client[cs_idx].allowedtimeframe[1];
2310        if(!((mintime <= maxtime && curtime > mintime && curtime < maxtime) || (mintime > maxtime && (curtime > mintime || curtime < maxtime))))
2311            er->rc = 11;
2312    }
2313
2314    // user disabled
2315    if(client[cs_idx].disabled != 0)
2316        er->rc = 12;
2317
2318    // rc<100 -> ecm error
2319    if (er->rc > 99) {
2320
2321        m = er->caid;
2322        er->ocaid = er->caid;
2323        i = er->srvid;
2324
2325        if ((i != client[cs_idx].last_srvid) || (!client[cs_idx].lastswitch)) {
2326            if(cfg->usrfileflag)
2327                cs_statistics(cs_idx);
2328            client[cs_idx].lastswitch = now;
2329        }
2330
2331        // user sleeping
2332        if ((client[cs_idx].tosleep) && (now - client[cs_idx].lastswitch > client[cs_idx].tosleep)) {
2333            if (client[cs_idx].c35_sleepsend != 0) {
2334                er->rc = 13; // send stop command CMD08 {00 xx}
2335            } else {
2336                er->rc = 6;
2337            }
2338        }
2339
2340        client[cs_idx].last_srvid = i;
2341        client[cs_idx].last_caid = m;
2342
2343        for (j = 0; (j < 6) && (er->rc > 99); j++)
2344        {
2345            switch(j) {
2346
2347                case 0:
2348                    // fake (uniq)
2349                    if (client[cs_idx].dup)
2350                        er->rc = 7;
2351                    break;
2352
2353                case 1:
2354                    // invalid (caid)
2355                    if (!chk_bcaid(er, &client[cs_idx].ctab)) {
2356                        er->rc = 8;
2357                        er->rcEx = E2_CAID;
2358                        }
2359                    break;
2360
2361                case 2:
2362                    // invalid (srvid)
2363                    if (!chk_srvid(er, cs_idx))
2364                        er->rc = 8;
2365                    break;
2366
2367                case 3:
2368                    // invalid (ufilters)
2369                    if (!chk_ufilters(er))
2370                        er->rc = 8;
2371                    break;
2372
2373                case 4:
2374                    // invalid (sfilter)
2375                    if (!chk_sfilter(er, ph[client[cs_idx].ctyp].ptab))
2376                        er->rc = 8;
2377                    break;
2378
2379                case 5:
2380                    // corrupt
2381                    if( (i = er->l - (er->ecm[2] + 3)) ) {
2382                        if (i > 0) {
2383                            cs_debug("warning: ecm size adjusted from 0x%X to 0x%X",
2384                            er->l, er->ecm[2] + 3);
2385                            er->l = (er->ecm[2] + 3);
2386                        }
2387                        else
2388                            er->rc = 9;
2389                    }
2390                    break;
2391            }
2392        }
2393    }
2394   
2395    //Schlocke: above checks could change er->rc so
2396    if (er->rc > 99) {
2397        /*BetaCrypt tunneling
2398         *moved behind the check routines,
2399         *because newcamd ECM will fail
2400         *if ECM is converted before
2401         */
2402        if (&client[cs_idx].ttab)
2403            cs_betatunnel(er);
2404   
2405        // store ECM in cache
2406        memcpy(er->ecmd5, MD5(er->ecm, er->l, NULL), CS_ECMSTORESIZE);
2407
2408        // cache1
2409        if (check_ecmcache1(er, client[cs_idx].grp))
2410            er->rc = 1;
2411
2412#ifdef CS_ANTICASC
2413        ac_chk(er, 0);
2414#endif
2415    }
2416
2417    if(er->rc > 99) {
2418
2419        if (cfg->reader_auto_loadbalance) {
2420            int reader_avail[CS_MAXREADER];
2421            for (i =0; i < CS_MAXREADER; i++)
2422                reader_avail[i] = matching_reader(er, &reader[i]);
2423               
2424            recv_best_reader(er, reader_avail);
2425               
2426            for (i = m = 0; i < CS_MAXREADER; i++) {
2427                if (reader_avail[i]) {
2428                    m|=er->reader[i] = reader_avail[i];
2429                }
2430            }
2431        }
2432        else
2433        {
2434            for (i = m = 0; i < CS_MAXREADER; i++)
2435                if (matching_reader(er, &reader[i]))
2436                    m|=er->reader[i] = (reader[i].fallback)? 2: 1;
2437        }
2438
2439        switch(m) {
2440            // no reader -> not found
2441            case 0:
2442                er->rc = 4;
2443                if (!er->rcEx)
2444                    er->rcEx = E2_GROUP;
2445                break;
2446               
2447            // fallbacks only, switch them
2448            case 2:
2449                for (i = 0; i < CS_MAXREADER; i++)
2450                    er->reader[i]>>=1;
2451        }
2452    }
2453
2454    if (er->rc < 100) {
2455        if (cfg->delay)
2456            cs_sleepms(cfg->delay);
2457
2458        send_dcw(er);
2459        return;
2460    }
2461
2462    er->rcEx = 0;
2463    request_cw(er, 0, cfg->preferlocalcards ? 1 : 0);
2464}
2465
2466void log_emm_request(int auidx)
2467{
2468//  cs_log("%s send emm-request (reader=%s, caid=%04X)",
2469//         cs_inet_ntoa(client[cs_idx].ip), reader[auidx].label, reader[auidx].caid[0]);
2470  cs_log("%s emm-request sent (reader=%s, caid=%04X)",
2471         username(cs_idx), reader[auidx].label, reader[auidx].caid[0]);
2472}
2473
2474void do_emm(EMM_PACKET *ep)
2475{
2476    int au;
2477    char *typtext[]={"UNKNOWN", "UNIQUE", "SHARED", "GLOBAL"}; 
2478
2479    au = client[cs_idx].au;
2480    cs_ddump_mask(D_ATR, ep->emm, ep->l, "emm:");
2481
2482    //Unique Id matching for pay-per-view channels:
2483    if (client[cs_idx].autoau) {
2484        int i;
2485        for (i=0;i<CS_MAXREADER;i++) {
2486            if (reader[i].card_system>0 && !reader[i].audisabled) {
2487                if (reader_get_emm_type(ep, &reader[i])) { //decodes ep->type and ep->hexserial from the EMM
2488                    if (memcmp(ep->hexserial, reader[i].hexserial, sizeof(ep->hexserial))==0) {
2489                        au = i;
2490                        break; //
2491                    }
2492                }
2493            }
2494        }
2495    }
2496   
2497    if ((au < 0) || (au >= CS_MAXREADER)) {
2498        cs_debug_mask(D_EMM, "emm disabled, client has no au-reader!");
2499        return;
2500    }
2501
2502    if (reader[au].card_system>0) {
2503        if (!reader_get_emm_type(ep, &reader[au])) { //decodes ep->type and ep->hexserial from the EMM
2504            cs_debug_mask(D_EMM, "emm skipped");
2505            return;
2506        }
2507    }
2508    else {
2509        cs_debug_mask(D_EMM, "emm skipped, reader %s (%d) has no cardsystem defined!", reader[au].label, au); 
2510        return;
2511    }
2512
2513    cs_debug_mask(D_EMM, "emmtype %s. Reader %s has serial %s.", typtext[ep->type], reader[au].label, cs_hexdump(0, reader[au].hexserial, 8)); 
2514    cs_ddump_mask(D_EMM, ep->hexserial, 8, "emm UA/SA:");
2515    cs_ddump_mask(D_EMM, ep->emm, ep->l, "emm:");
2516
2517    switch (ep->type) {
2518        case UNKNOWN:
2519            if (reader[au].blockemm_unknown) {
2520#ifdef WEBIF
2521                reader[au].emmblocked[UNKNOWN]++;
2522#endif
2523                return;
2524            }
2525            break;
2526
2527        case UNIQUE:
2528            if (reader[au].blockemm_u) {
2529#ifdef WEBIF
2530                reader[au].emmblocked[UNIQUE]++;
2531#endif
2532                return;
2533            }
2534            break;
2535
2536        case SHARED:
2537            if (reader[au].blockemm_s) {
2538#ifdef WEBIF
2539                reader[au].emmblocked[SHARED]++;
2540#endif
2541                return;
2542            }
2543            break;
2544
2545        // FIXME only camd33 delivers hexserial from the net, newcamd, camd35 copy
2546        // cardreader hexserial in; reader_get_emm_type overwrites this with real SA value if known!
2547        case GLOBAL:
2548            if (reader[au].blockemm_g) {
2549#ifdef WEBIF
2550                reader[au].emmblocked[GLOBAL]++;
2551#endif
2552                return;
2553            }
2554            break;
2555    }
2556
2557    client[cs_idx].lastemm = time((time_t)0);
2558
2559    if (reader[au].card_system > 0) {
2560        if (!check_emm_cardsystem(&reader[au], ep)) {   // wrong caid
2561            client[cs_idx].emmnok++;
2562            return;
2563        }
2564        client[cs_idx].emmok++;
2565    }
2566    ep->cidx = cs_idx;
2567    cs_debug_mask(D_EMM, "emm is being sent to reader %s.", reader[au].label);
2568    write_to_pipe(reader[au].fd, PIP_ID_EMM, (uchar *) ep, sizeof(EMM_PACKET));
2569}
2570
2571static int comp_timeb(struct timeb *tpa, struct timeb *tpb)
2572{
2573  if (tpa->time>tpb->time) return(1);
2574  if (tpa->time<tpb->time) return(-1);
2575  if (tpa->millitm>tpb->millitm) return(1);
2576  if (tpa->millitm<tpb->millitm) return(-1);
2577  return(0);
2578}
2579
2580struct timeval *chk_pending(struct timeb tp_ctimeout)
2581{
2582    int i;
2583    ulong td;
2584    struct timeb tpn, tpe, tpc; // <n>ow, <e>nd, <c>heck
2585    static struct timeval tv;
2586
2587    ECM_REQUEST *er;
2588    cs_ftime(&tpn);
2589    tpe=tp_ctimeout;    // latest delay -> disconnect
2590
2591    if (ecmtask)
2592        i=(ph[client[cs_idx].ctyp].multi)?CS_MAXPENDING:1;
2593    else
2594        i=0;
2595
2596    //cs_log("num pend=%d", i);
2597
2598    for (--i; i>=0; i--) {
2599        if (ecmtask[i].rc>=100) { // check all pending ecm-requests
2600            er=&ecmtask[i];
2601            if (check_ecmcache1(er, client[cs_idx].grp)) { //Schlocke: caching dupplicate requests from different clients
2602                er->rc = 1;
2603                send_dcw(er);
2604            }
2605        }
2606        if (ecmtask[i].rc>=100) { // check all pending ecm-requests
2607            int act, j;
2608            er=&ecmtask[i];
2609            tpc=er->tps;
2610            tpc.millitm += (er->stage) ? cfg->ctimeout : cfg->ftimeout;
2611            tpc.time += tpc.millitm / 1000;
2612            tpc.millitm = tpc.millitm % 1000;
2613            if (!er->stage) {
2614                for (j=0, act=1; (act) && (j<CS_MAXREADER); j++) {
2615                    if (cfg->preferlocalcards && !er->locals_done) {
2616                        if ((er->reader[j]&1) && !(reader[j].typ & R_IS_NETWORK))
2617                            act=0;
2618                    } else if (cfg->preferlocalcards && er->locals_done) {
2619                        if ((er->reader[j]&1) && (reader[j].typ & R_IS_NETWORK))
2620                            act=0;
2621                    } else {
2622                        if (er->reader[j]&1)
2623                            act=0;
2624                    }
2625                }
2626
2627                //cs_log("stage 0, act=%d r0=%d, r1=%d, r2=%d, r3=%d, r4=%d r5=%d", act,
2628                //    er->reader[0], er->reader[1], er->reader[2],
2629                //    er->reader[3], er->reader[4], er->reader[5]);
2630
2631                if (act) {
2632                    int inc_stage = 1;
2633                    if (cfg->preferlocalcards && !er->locals_done) {
2634                        er->locals_done = 1;
2635                        for (j = 0; j < CS_MAXREADER; j++) {
2636                            if (reader[j].typ & R_IS_NETWORK)
2637                                inc_stage = 0;
2638                        }
2639                    }
2640                    if (!inc_stage) {
2641                        request_cw(er, er->stage, 2);
2642                        tpc.millitm += 1000 * (tpn.time - er->tps.time) + tpn.millitm - er->tps.millitm;
2643                        tpc.time += tpc.millitm / 1000;
2644                        tpc.millitm = tpc.millitm % 1000;
2645                    } else {
2646                        er->locals_done = 0;
2647                        er->stage++;
2648                        request_cw(er, er->stage, cfg->preferlocalcards ? 1 : 0);
2649
2650                        tpc.millitm += (cfg->ctimeout-cfg->ftimeout);
2651                        tpc.time += tpc.millitm / 1000;
2652                        tpc.millitm = tpc.millitm % 1000;
2653                    }
2654                }
2655            }
2656            if (comp_timeb(&tpn, &tpc)>0) { // action needed
2657                //cs_log("Action now %d.%03d", tpn.time, tpn.millitm);
2658                //cs_log("           %d.%03d", tpc.time, tpc.millitm);
2659                if (er->stage) {
2660                    er->rc=5; // timeout
2661                    if (cfg->reader_auto_loadbalance) {
2662                        int r;
2663                        for (r=0; r<CS_MAXREADER; r++)
2664                            if (er->reader[r])
2665                                send_reader_stat(r, er, 5);
2666                    }
2667                    send_dcw(er);
2668                    continue;
2669                } else {
2670                    er->stage++;
2671                    request_cw(er, er->stage, 0);
2672                    tpc.millitm += (cfg->ctimeout-cfg->ftimeout);
2673                    tpc.time += tpc.millitm / 1000;
2674                    tpc.millitm = tpc.millitm % 1000;
2675                }
2676            }
2677            //build_delay(&tpe, &tpc);
2678            if (comp_timeb(&tpe, &tpc)>0) {
2679                tpe.time=tpc.time;
2680                tpe.millitm=tpc.millitm;
2681            }
2682        }
2683    }
2684
2685    td=(tpe.time-tpn.time)*1000+(tpe.millitm-tpn.millitm)+5;
2686    tv.tv_sec = td/1000;
2687    tv.tv_usec = (td%1000)*1000;
2688    //cs_log("delay %d.%06d", tv.tv_sec, tv.tv_usec);
2689    return(&tv);
2690}
2691
2692int process_input(uchar *buf, int l, int timeout)
2693{
2694  int rc;
2695  fd_set fds;
2696  struct timeb tp;
2697
2698  if (master_pid!=getppid()) cs_exit(0);
2699  if (!pfd) return(-1);
2700  cs_ftime(&tp);
2701  tp.time+=timeout;
2702  if (ph[client[cs_idx].ctyp].watchdog)
2703      alarm(cfg->cmaxidle + (cfg->ctimeout + 500) / 1000 + 1);
2704  while (1)
2705  {
2706    FD_ZERO(&fds);
2707    FD_SET(pfd, &fds);
2708    FD_SET(client[cs_idx].fd_m2c_c, &fds);
2709
2710    rc=select(((pfd>client[cs_idx].fd_m2c_c)?pfd:client[cs_idx].fd_m2c_c)+1, &fds, 0, 0, chk_pending(tp));
2711    if (master_pid!=getppid()) cs_exit(0);
2712    if (rc<0)
2713    {
2714      if (errno==EINTR) continue;
2715      else return(0);
2716    }
2717
2718    if (FD_ISSET(client[cs_idx].fd_m2c_c, &fds))   // read from pipe
2719      chk_dcw(client[cs_idx].fd_m2c_c);
2720
2721    if (FD_ISSET(pfd, &fds))    // read from client
2722    {
2723      rc=ph[client[cs_idx].ctyp].recv(buf, l);
2724      break;
2725    }
2726    if (tp.time<=time((time_t *)0)) // client maxidle reached
2727    {
2728      rc=(-9);
2729      break;
2730    }
2731  }
2732  if (ph[client[cs_idx].ctyp].watchdog)
2733      alarm(cfg->cmaxidle + (cfg->ctimeout + 500) / 1000 + 1);
2734  return(rc);
2735}
2736
2737static void restart_clients()
2738{
2739    int i;
2740    cs_log("restarting clients");
2741    for (i=0; i<CS_MAXPID; i++) {
2742        if (client[i].pid && client[i].typ=='c' && ph[client[i].ctyp].type & MOD_CONN_NET) {
2743            kill(client[i].pid, SIGKILL);
2744            cs_log("killing client c%02d pid %d", i, client[i].pid);
2745        }
2746    }
2747}
2748
2749
2750// gets and send the best reader to the client. Called from master-process
2751void send_best_reader(GET_READER_STAT *grs)
2752{
2753    //cs_debug_mask(D_TRACE, "got request for best reader for %04X/%04X/%04X", grs->caid, grs->prid, grs->srvid);
2754    int best_reader[CS_MAXREADER];
2755    get_best_reader(grs, best_reader);
2756    //cs_debug_mask(D_TRACE, "sending best reader %d", ridx);
2757    write_to_pipe(client[grs->cidx].fd_m2c, PIP_ID_BES, (uchar*)&best_reader, sizeof(best_reader));
2758}
2759
2760void send_clear_reader_stat(int ridx)
2761{
2762  write_to_pipe(fd_c2m, PIP_ID_RES, (uchar*)&ridx, sizeof(ridx)); 
2763}
2764
2765void send_restart_cardreader(int ridx, int force_now)
2766{
2767  int restart_info[2];
2768  restart_info[0] = ridx;
2769  restart_info[1] = force_now;
2770  write_to_pipe(fd_c2m, PIP_ID_RST, (uchar*)&restart_info, sizeof(restart_info)); 
2771}
2772
2773static void process_master_pipe()
2774{
2775  int n;
2776  uchar *ptr;
2777
2778  switch(n=read_from_pipe(mfdr, &ptr, 1))
2779  {
2780    case PIP_ID_LOG:
2781        cs_write_log((char *)ptr);
2782        break;
2783    case PIP_ID_HUP:
2784        cs_accounts_chk();
2785        break;
2786    case PIP_ID_RST:{ //Restart Cardreader with ridx=prt[0]
2787        int *restart_info = (int *)ptr;
2788        restart_cardreader(restart_info[0], restart_info[1]);
2789        break; }
2790    case PIP_ID_KCL: //Kill all clients
2791        restart_clients();
2792        break;
2793    case PIP_ID_STA: //Add reader statistics
2794        add_reader_stat((ADD_READER_STAT *)ptr);
2795        break;
2796    case PIP_ID_BES: //Get best reader
2797        send_best_reader((GET_READER_STAT *)ptr);
2798        break;
2799    case PIP_ID_RES: //Reset reader statistics
2800    clear_reader_stat(*(int*)ptr);
2801    break;
2802  }
2803}
2804
2805void cs_log_config()
2806{
2807  uchar buf[20];
2808
2809  if (cfg->nice!=99)
2810    sprintf((char *)buf, ", nice=%d", cfg->nice);
2811  else
2812    buf[0]='\0';
2813  cs_log("version=%s, build #%s, system=%s-%s-%s%s", CS_VERSION_X, CS_SVN_VERSION, CS_OS_CPU, CS_OS_HW, CS_OS_SYS, buf);
2814  cs_log("max. clients=%d, client max. idle=%d sec",
2815#ifdef CS_ANTICASC
2816         CS_MAXPID-3, cfg->cmaxidle);
2817#else
2818         CS_MAXPID-2, cfg->cmaxidle);
2819#endif
2820  if( cfg->max_log_size )
2821    sprintf((char *)buf, "%d Kb", cfg->max_log_size);
2822  else
2823    strcpy((char *)buf, "unlimited");
2824  cs_log("max. logsize=%s", buf);
2825  cs_log("client timeout=%lu ms, fallback timeout=%lu ms, cache delay=%d ms",
2826         cfg->ctimeout, cfg->ftimeout, cfg->delay);
2827#ifdef CS_NOSHM
2828  cs_log("shared memory initialized (size=%d, fd=%d)", shmsize, shmid);
2829#else
2830  cs_log("shared memory initialized (size=%d, id=%d)", shmsize, shmid);
2831#endif
2832}
2833
2834void cs_waitforcardinit()
2835{
2836    if (cfg->waitforcards)
2837    {
2838        cs_log("waiting for local card init");
2839        int card_init_done, i;
2840        cs_sleepms(3000);  // short sleep for card detect to work proberly
2841        do {
2842            card_init_done = 1;
2843            for (i = 0; i < CS_MAXREADER; i++) {
2844                if (reader[i].card_status == CARD_NEED_INIT) {
2845                    card_init_done = 0;
2846                    break;
2847                }
2848            }
2849            cs_sleepms(300); // wait a little bit
2850            alarm(cfg->cmaxidle + cfg->ctimeout / 1000 + 1); 
2851        } while (!card_init_done);
2852        cs_log("init for all local cards done");
2853    }
2854}
2855
2856void cs_resolve()
2857{
2858  int i;
2859  for (i=0; i<CS_MAXREADER; i++)
2860    if (reader[i].enable && !reader[i].deleted && (reader[i].cs_idx) && (reader[i].typ & R_IS_NETWORK) && (reader[i].typ!=R_CONSTCW))
2861      hostResolve(i);
2862}
2863
2864static void loop_resolver()
2865{
2866  cs_sleepms(1000); // wait for reader
2867  while(cfg->resolvedelay > 0)
2868  {
2869    cs_resolve();
2870    cs_sleepms(1000*cfg->resolvedelay);
2871  }
2872}
2873             
2874int main (int argc, char *argv[])
2875{
2876
2877#ifdef CS_LED
2878  cs_switch_led(LED1A, LED_DEFAULT);
2879  cs_switch_led(LED1A, LED_ON);
2880#endif
2881
2882  struct   sockaddr_in cad;     /* structure to hold client's address */
2883  int      scad;                /* length of address */
2884  //int      fd;                  /* socket descriptors */
2885  int      i, j, n;
2886  int      bg=0;
2887  int      gfd; //nph,
2888  int      fdp[2];
2889  uchar    buf[2048];
2890  void (*mod_def[])(struct s_module *)=
2891  {
2892           module_monitor,
2893           module_camd33,
2894           module_camd35,
2895           module_camd35_tcp,
2896           module_newcamd,
2897           module_cccam,
2898           module_constcw,
2899#ifdef CS_WITH_GBOX
2900           module_gbox,
2901#endif
2902           module_radegast,
2903           module_oscam_ser,
2904#ifdef HAVE_DVBAPI
2905       module_dvbapi,
2906#endif
2907           0
2908  };
2909
2910  while ((i=getopt(argc, argv, "bc:d:hm:"))!=EOF)
2911  {
2912    switch(i)
2913    {
2914      case 'b': bg=1;
2915                break;
2916      case 'c': cs_strncpy(cs_confdir, optarg, sizeof(cs_confdir));
2917                break;
2918      case 'd': cs_dblevel=atoi(optarg);
2919                break;
2920      case 'm':
2921#ifdef CS_NOSHM
2922                cs_strncpy(cs_memfile, optarg, sizeof(cs_memfile));
2923                break;
2924#endif
2925      case 'h':
2926      default : usage();
2927    }
2928  }
2929  if (cs_confdir[strlen(cs_confdir)]!='/') strcat(cs_confdir, "/");
2930  init_shm();
2931  init_config();
2932  cfg->debuglvl = cs_dblevel; // give static debuglevel to outer world
2933  for (i=0; mod_def[i]; i++)  // must be later BEFORE init_config()
2934  {
2935    memset(&ph[i], 0, sizeof(struct s_module));
2936    mod_def[i](&ph[i]);
2937  }
2938
2939  cs_log("auth size=%d", sizeof(struct s_auth));
2940
2941  init_sidtab();
2942  init_readerdb();
2943  init_userdb(&cfg->account);
2944  init_signal();
2945  cs_set_mloc(30, "init");
2946  init_srvid();
2947  //Todo #ifdef CCCAM
2948  init_provid();
2949
2950  init_len4caid();
2951#ifdef IRDETO_GUESSING
2952  init_irdeto_guess_tab(); 
2953#endif
2954
2955
2956  if (pipe(fdp))
2957  {
2958    cs_log("Cannot create pipe (errno=%d)", errno);
2959    cs_exit(1);
2960  }
2961  mfdr=fdp[0];
2962  fd_c2m=fdp[1];
2963  gfd=mfdr+1;
2964
2965#ifdef OS_MACOSX
2966  if (bg && daemon_compat(1,0))
2967#else
2968  if (bg && daemon(1,0))
2969#endif
2970  {
2971    cs_log("Error starting in background (errno=%d)", errno);
2972    cs_exit(1);
2973  }
2974  master_pid=client[0].pid=getpid();
2975  if (cfg->pidfile != NULL)
2976  {
2977    FILE *fp;
2978    if (!(fp=fopen(cfg->pidfile, "w")))
2979    {
2980      cs_log("Cannot open pid-file (errno=%d)", errno);
2981      cs_exit(1);
2982    }
2983    fprintf(fp, "%d\n", getpid());
2984    fclose(fp);
2985  }
2986
2987#ifndef OS_CYGWIN32
2988  // /tmp/oscam.version file (Uptime + Version)
2989  FILE *fp;
2990  if (!(fp=fopen("/tmp/oscam.version", "w"))) {
2991      cs_log("Cannot open oscam.version (errno=%d)", errno);
2992  } else {
2993      time_t now = time((time_t)0);
2994      struct tm *st;
2995      st = localtime(&now);
2996      fprintf(fp, "uxstarttime: %d\n", (int)now);
2997      fprintf(fp, "starttime: %02d.%02d.%02d", st->tm_mday, st->tm_mon+1, st->tm_year%100);
2998      fprintf(fp, " %02d:%02d:%02d\n", st->tm_hour, st->tm_min, st->tm_sec);
2999      fprintf(fp, "version: %s#%s\n", CS_VERSION, CS_SVN_VERSION);
3000      fprintf(fp, "maxpid: %d\n", CS_MAXPID);
3001#ifdef WEBIF
3002      fprintf(fp, "webifsupport: yes\n");
3003#else
3004      fprintf(fp, "webifsupport: no\n");
3005#endif
3006#ifdef HAVE_DVBAPI
3007      fprintf(fp, "dvbapisupport: yes\n");
3008#else
3009      fprintf(fp, "dvbapisupport: no\n");
3010#endif
3011#ifdef CS_WITH_GBOX
3012      fprintf(fp, "gboxsupport: yes\n");
3013#else
3014      fprintf(fp, "gboxsupport: no\n");
3015#endif
3016#ifdef CS_ANTICASC
3017      fprintf(fp, "anticascsupport: yes\n");
3018#else
3019      fprintf(fp, "anticascsupport: no\n");
3020#endif
3021      fclose(fp);
3022  }
3023#endif
3024
3025
3026#ifdef AZBOX
3027  openxcas_debug_message_onoff(1);  // debug
3028
3029  if (openxcas_open_with_smartcard("oscamCAS") < 0) {
3030    cs_log("openxcas: could not init");
3031  }
3032#endif
3033
3034  for (i=0; i<CS_MAX_MOD; i++)
3035    if( (ph[i].type & MOD_CONN_NET) && ph[i].ptab )
3036      for(j=0; j<ph[i].ptab->nports; j++)
3037      {
3038        start_listener(&ph[i], j);
3039        if( ph[i].ptab->ports[j].fd+1>gfd )
3040          gfd=ph[i].ptab->ports[j].fd+1;
3041      }
3042
3043    //set time for server to now to avoid 0 in monitor/webif
3044    client[0].last=time((time_t *)0);
3045
3046    if(cfg->clientdyndns)
3047        start_thread((void *) &cs_client_resolve, "client resolver");
3048
3049  init_service(97); // logger
3050
3051  if (cfg->resolvedelay > 0)
3052    start_thread(&loop_resolver, "Resolver");
3053#ifdef WEBIF
3054  if(cfg->http_port == 0) 
3055    cs_log("http disabled"); 
3056  else 
3057    init_service(95); // http
3058#endif
3059  init_cardreader();
3060
3061  cs_waitforcardinit();
3062#ifdef CS_LED
3063  cs_switch_led(LED1A, LED_OFF);
3064  cs_switch_led(LED1B, LED_ON);
3065#endif
3066
3067#ifdef CS_ANTICASC
3068  if( !cfg->ac_enabled )
3069    cs_log("anti cascading disabled");
3070  else
3071  {
3072    init_ac();
3073    init_service(96);
3074  }
3075#endif
3076
3077  for (i=0; i<CS_MAX_MOD; i++)
3078    if (ph[i].type & MOD_CONN_SERIAL)   // for now: oscam_ser only
3079      if (ph[i].s_handler)
3080        ph[i].s_handler(i);
3081
3082  //cs_close_log();
3083  *mcl=1;
3084  while (1)
3085  {
3086    fd_set fds;
3087
3088    do
3089    {
3090      FD_ZERO(&fds);
3091      FD_SET(mfdr, &fds);
3092      for (i=0; i<CS_MAX_MOD; i++)
3093        if ( (ph[i].type & MOD_CONN_NET) && ph[i].ptab )
3094          for (j=0; j<ph[i].ptab->nports; j++)
3095            if (ph[i].ptab->ports[j].fd)
3096              FD_SET(ph[i].ptab->ports[j].fd, &fds);
3097      errno=0;
3098      cs_set_mloc(0, "before select");
3099      select(gfd, &fds, 0, 0, 0);
3100      cs_set_mloc(60, "after select");
3101    } while (errno==EINTR);
3102    cs_set_mloc(-1, "event (global)");
3103
3104    client[0].last=time((time_t *)0);
3105    scad = sizeof(cad);
3106    if (FD_ISSET(mfdr, &fds))
3107    {
3108      cs_set_mloc(-1, "event: master-pipe");
3109      process_master_pipe();
3110    }
3111    for (i=0; i<CS_MAX_MOD; i++)
3112    {
3113      if( (ph[i].type & MOD_CONN_NET) && ph[i].ptab )
3114      {
3115        for( j=0; j<ph[i].ptab->nports; j++ )
3116        {
3117          if( ph[i].ptab->ports[j].fd && FD_ISSET(ph[i].ptab->ports[j].fd, &fds) )
3118          {
3119            if (ph[i].type==MOD_CONN_UDP)
3120            {
3121              cs_set_mloc(-1, "event: udp-socket");
3122              if ((n=recvfrom(ph[i].ptab->ports[j].fd, buf+3, sizeof(buf)-3, 0, (struct sockaddr *)&cad, (socklen_t *)&scad))>0)
3123              {
3124                int idx;
3125                idx=idx_from_ip(cs_inet_order(cad.sin_addr.s_addr), ntohs(cad.sin_port));
3126                if (!idx)
3127                {
3128                  if (pipe(fdp))
3129                  {
3130                    cs_log("Cannot create pipe (errno=%d)", errno);
3131                    cs_exit(1);
3132                  }
3133                  switch(cs_fork(cs_inet_order(cad.sin_addr.s_addr), ntohs(cad.sin_port)))
3134                  {
3135                  case -1:
3136                    close(fdp[0]);
3137                    close(fdp[1]);
3138                    break;
3139                  case  0:
3140                    client[idx=cs_last_idx].ufd=fdp[1];
3141                    close(fdp[0]);
3142                    break;
3143                  default:
3144//                    close(fdp[1]);  // now used to simulate event
3145                    pfd=fdp[0];
3146                    wait4master();
3147                    client[cs_idx].ctyp=i;
3148                    client[cs_idx].port_idx=j;
3149                    client[cs_idx].udp_fd=ph[i].ptab->ports[j].fd;
3150                    client[cs_idx].udp_sa=cad;
3151                    if (ph[client[cs_idx].ctyp].watchdog)
3152                        alarm(cfg->cmaxidle + cfg->ctimeout / 1000 + 1);
3153                    ph[i].s_handler(cad);   // never return
3154                  }
3155                }
3156                if (idx)
3157                {
3158                  unsigned short rl;
3159                  rl=n;
3160                  buf[0]='U';
3161                  memcpy(buf+1, &rl, 2);
3162                  if (!write(client[idx].ufd, buf, n+3)) cs_exit(1);
3163                }
3164              }
3165            }
3166            else
3167            {
3168              cs_set_mloc(-1, "event: tcp-socket");
3169              if ((pfd=accept(ph[i].ptab->ports[j].fd, (struct sockaddr *)&cad, (socklen_t *)&scad))>0)
3170              {
3171                switch(cs_fork(cs_inet_order(cad.sin_addr.s_addr), ntohs(cad.sin_port)))
3172                {
3173                case -1:
3174                case  0:
3175                  close(pfd);
3176                  break;
3177                default:
3178                  wait4master();
3179                  client[cs_idx].ctyp=i;
3180                  client[cs_idx].udp_fd=pfd;
3181                  client[cs_idx].port_idx=j;
3182                  if (ph[client[cs_idx].ctyp].watchdog)
3183                      alarm(cfg->cmaxidle + cfg->ctimeout / 1000 + 1);
3184                  ph[i].s_handler();
3185                }
3186              }
3187            }
3188          }
3189        }
3190      } // if (ph[i].type & MOD_CONN_NET)
3191    }
3192  }
3193
3194
3195#ifdef AZBOX
3196  if (openxcas_close() < 0) {
3197    cs_log("openxcas: could not close");
3198  }
3199#endif
3200
3201  cs_exit(1);
3202}
3203
3204#ifdef CS_LED
3205void cs_switch_led(int led, int action) {
3206
3207    if(action < 2) { // only LED_ON and LED_OFF
3208        char ledfile[256];
3209        FILE *f;
3210
3211        #ifdef DOCKSTAR
3212            switch(led){
3213            case LED1A:snprintf(ledfile, 255, "/sys/class/leds/dockstar:orange:misc/brightness");
3214            break;
3215            case LED1B:snprintf(ledfile, 255, "/sys/class/leds/dockstar:green:health/brightness");
3216            break;
3217            case LED2:snprintf(ledfile, 255, "/sys/class/leds/dockstar:green:health/brightness");
3218            break;
3219            case LED3:snprintf(ledfile, 255, "/sys/class/leds/dockstar:orange:misc/brightness");
3220            break;
3221            }
3222        #else       
3223            switch(led){
3224            case LED1A:snprintf(ledfile, 255, "/sys/class/leds/nslu2:red:status/brightness");
3225            break;
3226            case LED1B:snprintf(ledfile, 255, "/sys/class/leds/nslu2:green:ready/brightness");
3227            break;
3228            case LED2:snprintf(ledfile, 255, "/sys/class/leds/nslu2:green:disk-1/brightness");
3229            break;
3230            case LED3:snprintf(ledfile, 255, "/sys/class/leds/nslu2:green:disk-2/brightness");
3231            break;
3232            }
3233        #endif
3234
3235        if (!(f=fopen(ledfile, "w"))){
3236            // FIXME: sometimes cs_log was not available when calling cs_switch_led -> signal 11
3237            //cs_log("Cannot open file \"%s\" (errno=%d)", ledfile, errno);
3238            return;
3239        }
3240        fprintf(f,"%d", action);
3241        fclose(f);
3242    } else { // LED Macros
3243        switch(action){
3244        case LED_DEFAULT:
3245            cs_switch_led(LED1A, LED_OFF);
3246            cs_switch_led(LED1B, LED_OFF);
3247            cs_switch_led(LED2, LED_ON);
3248            cs_switch_led(LED3, LED_OFF);
3249            break;
3250        case LED_BLINK_OFF:
3251            cs_switch_led(led, LED_OFF);
3252            cs_sleepms(100);
3253            cs_switch_led(led, LED_ON);
3254            break;
3255        case LED_BLINK_ON:
3256            cs_switch_led(led, LED_ON);
3257            cs_sleepms(300);
3258            cs_switch_led(led, LED_OFF);
3259            break;
3260        }
3261    }
3262}
3263#endif
Note: See TracBrowser for help on using the repository browser.