source: trunk/oscam.c@ 109

Last change on this file since 109 was 97, checked in by polo, 11 years ago

o patch for the newcamd idle bug, based on the fix from KrazyIvan in mpcs 1.0.
o changed the logging to see the newcamd-client dest port if a client connects to oscam.
thanks merek for this patch.

File size: 61.9 KB
Line 
1#define CS_CORE
2#include "globals.h"
3#ifdef CS_WITH_GBOX
4# include "csgbox/gbox.h"
5# define CS_VERSION_X CS_VERSION "-gbx-" GBXVERSION
6#else
7# define CS_VERSION_X CS_VERSION
8#endif
9/*****************************************************************************
10 Globals
11*****************************************************************************/
12int pfd=0; // Primary FD, must be closed on exit
13int mfdr=0; // Master FD (read)
14int fd_m2c=0; // FD Master -> Client (for clients / read )
15int fd_c2m=0; // FD Client -> Master (for clients / write )
16int fd_c2l=0; // FD Client -> Logger (for clients / write )
17int cs_dblevel=0; // Debug Level (TODO !!)
18int cs_idx=0; // client index (0=master, ...)
19int cs_ptyp=D_MASTER; // process-type
20struct s_module ph[CS_MAX_MOD]; // Protocols
21int maxph=0; // Protocols used
22int cs_hw=0; // hardware autodetect
23int is_server=0; // used in modules to specify function
24pid_t master_pid=0; // master pid OUTSIDE shm
25ushort len4caid[256]; // table for guessing caid (by len)
26char cs_confdir[128]=CS_CONFDIR;
27uchar mbuf[1024]; // global buffer
28ECM_REQUEST *ecmtask;
29EMM_PACKET epg;
30#ifdef CS_ANTICASC
31struct s_acasc ac_stat[CS_MAXPID];
32#endif
33
34/*****************************************************************************
35 Shared Memory
36*****************************************************************************/
37int *ecmidx; // Shared Memory
38int *logidx; // Shared Memory
39int *oscam_sem; // sem (multicam.o)
40int *c_start; // idx of 1st client
41int *log_fd; // log-process is running
42struct s_ecm *ecmcache; // Shared Memory
43struct s_client *client; // Shared Memory
44struct s_reader *reader; // Shared Memory
45
46struct card_struct *Cards; // Shared Memory
47struct idstore_struct *idstore; // Shared Memory
48unsigned long *IgnoreList; // Shared Memory
49
50struct s_config *cfg; // Shared Memory
51#ifdef CS_ANTICASC
52struct s_acasc_shm *acasc; // anti-cascading table indexed by account.ac_idx
53#endif
54#ifdef CS_LOGHISTORY
55int *loghistidx; // ptr to current entry
56char *loghist; // ptr of log-history
57#endif
58int *mcl=0; // Master close log?
59
60static int shmsize = CS_ECMCACHESIZE*(sizeof(struct s_ecm)) +
61 CS_MAXPID*(sizeof(struct s_client)) +
62 CS_MAXREADER*(sizeof(struct s_reader)) +
63#ifdef CS_WITH_GBOX
64 CS_MAXCARDS*(sizeof(struct card_struct))+
65 CS_MAXIGNORE*(sizeof(long))+
66 CS_MAXPID*(sizeof(struct idstore_struct))+
67#endif
68#ifdef CS_ANTICASC
69 CS_MAXPID*(sizeof(struct s_acasc_shm)) +
70#endif
71#ifdef CS_LOGHISTORY
72 CS_MAXLOGHIST*CS_LOGHISTSIZE + sizeof(int) +
73#endif
74 sizeof(struct s_config)+(6*sizeof(int));
75
76#ifdef CS_NOSHM
77char cs_memfile[128]=CS_MMAPFILE;
78#endif
79
80/*****************************************************************************
81 Statics
82*****************************************************************************/
83static char mloc[128]={0};
84static int shmid=0; // Shared Memory ID
85static int cs_last_idx=0; // client index of last fork (master only)
86static char* credit[] = {
87 "dukat for the great MpCS piece of code",
88 "all members of streamboard.de.vu for testing",
89 "scotty and aroureos for the first softcam (no longer used)",
90 "John Moore for the hsic-client (humax 5400) and the arm-support",
91 "doz21 for the sio-routines and his support on camd3-protocol",
92 "kindzadza for his support on radegast-protocol",
93 "DS and ago for several modules in mpcs development",
94 "dingo35 for seca reader-support",
95 "dingo35 and okmikel for newcamd-support",
96 "hellmaster1024 for gb*x-support",
97 "the vdr-sc team for several good ideas :-)",
98 NULL };
99
100static void cs_set_mloc(int ato, char *txt)
101{
102 if (ato>=0)
103 alarm(ato);
104 if (txt)
105 strcpy(mloc, txt);
106}
107
108char *cs_platform(char *buf)
109{
110 static char *hw=NULL;
111 if (!hw)
112 {
113#ifdef TUXBOX
114 struct stat st;
115 cs_hw=CS_HW_DBOX2; // dbox2, default for now
116 if (!stat("/dev/sci0", &st)) cs_hw=CS_HW_DREAM; // dreambox
117 switch(cs_hw)
118 {
119#ifdef PPC
120 case CS_HW_DBOX2: hw="dbox2" ; break;
121#endif
122 case CS_HW_DREAM: hw="dreambox"; break;
123 }
124#endif
125 if (!hw) hw=CS_OS_HW;
126 }
127 sprintf(buf, "%s-%s-%s", CS_OS_CPU, hw, CS_OS_SYS);
128 return(buf);
129}
130
131static void usage()
132{
133 int i;
134 fprintf(stderr, "\nOSCam cardserver v%s (%s) - (w) 2009 by smurzch\n", CS_VERSION_X, CS_OSTYPE);
135 fprintf(stderr, "\tbased on streamboard mp-cardserver v0.9d - (w) 2004-2007 by dukat\n\n");
136 fprintf(stderr, "oscam [-b] [-c config-dir]");
137#ifdef CS_NOSHM
138 fprintf(stderr, " [-m memory-file]");
139#endif
140 fprintf(stderr, "\n\n\t-b : start in background\n");
141 fprintf(stderr, "\t-c <dir> : read configuration from <dir>\n");
142 fprintf(stderr, "\t default=%s\n", CS_CONFDIR);
143#ifdef CS_NOSHM
144 fprintf(stderr, "\t-m <file>: use <file> as mmaped memory file\n");
145 fprintf(stderr, "\t default=%s\n", CS_MMAPFILE);
146#endif
147 fprintf(stderr, "\nthanks to ...\n");
148 for (i=0; credit[i]; i++)
149 fprintf(stderr, "\t%s\n", credit[i]);
150 fprintf(stderr, "\n");
151 exit(1);
152}
153
154#ifdef NEED_DAEMON
155#ifdef OS_MACOSX
156// this is done because daemon is being deprecated starting with 10.5 and -Werror will always trigger an error
157static int daemon_compat(int nochdir, int noclose)
158#else
159static int daemon(int nochdir, int noclose)
160#endif
161{
162 int fd;
163
164 switch (fork())
165 {
166 case -1: return (-1);
167 case 0: break;
168 default: _exit(0);
169 }
170
171 if (setsid()==(-1))
172 return(-1);
173
174 if (!nochdir)
175 (void)chdir("/");
176
177 if (!noclose && (fd=open("/dev/null", O_RDWR, 0)) != -1)
178 {
179 (void)dup2(fd, STDIN_FILENO);
180 (void)dup2(fd, STDOUT_FILENO);
181 (void)dup2(fd, STDERR_FILENO);
182 if (fd>2)
183 (void)close(fd);
184 }
185 return(0);
186}
187#endif
188
189int recv_from_udpipe(uchar *buf, int l)
190{
191 unsigned short n;
192 if (!pfd) return(-9);
193 if (!read(pfd, buf, 3)) cs_exit(1);
194 if (buf[0]!='U')
195 {
196 cs_log("INTERNAL PIPE-ERROR");
197 cs_exit(1);
198 }
199 memcpy(&n, buf+1, 2);
200 return(read(pfd, buf, n));
201}
202
203char *username(int idx)
204{
205 if (client[idx].usr[0])
206 return(client[idx].usr);
207 else
208 return("anonymous");
209}
210
211static int idx_from_ip(in_addr_t ip, in_port_t port)
212{
213 int i, idx;
214 for (i=idx=0; (i<CS_MAXPID) && (!idx); i++)
215 if ((client[i].ip==ip) && (client[i].port==port) &&
216 ((client[i].typ=='c') || (client[i].typ=='m')))
217 idx=i;
218 return(idx);
219}
220
221int idx_from_pid(pid_t pid)
222{
223 int i, idx;
224 for (i=0, idx=(-1); (i<CS_MAXPID) && (idx<0); i++)
225 if (client[i].pid==pid)
226 idx=i;
227 return(idx);
228}
229
230static long chk_caid(ushort caid, CAIDTAB *ctab)
231{
232 int n;
233 long rc;
234 for (rc=(-1), n=0; (n<CS_MAXCAIDTAB) && (rc<0); n++)
235 if ((caid & ctab->mask[n]) == ctab->caid[n])
236 rc=ctab->cmap[n] ? ctab->cmap[n] : caid;
237 return(rc);
238}
239
240int chk_bcaid(ECM_REQUEST *er, CAIDTAB *ctab)
241{
242 long caid;
243 if ((caid=chk_caid(er->caid, ctab))<0)
244 return(0);
245 er->caid=caid;
246 return(1);
247}
248
249/*
250 * void set_signal_handler(int sig, int flags, void (*sighandler)(int))
251 * flags: 1 = restart, 2 = don't modify if SIG_IGN, may be combined
252 */
253void set_signal_handler(int sig, int flags, void (*sighandler)(int))
254{
255#ifdef CS_SIGBSD
256 if ((signal(sig, sighandler)==SIG_IGN) && (flags & 2))
257 {
258 signal(sig, SIG_IGN);
259 siginterrupt(sig, 0);
260 }
261 else
262 siginterrupt(sig, (flags & 1) ? 0 : 1);
263#else
264 struct sigaction sa;
265 sigaction(sig, (struct sigaction *) 0, &sa);
266 if (!((flags & 2) && (sa.sa_handler==SIG_IGN)))
267 {
268 sigemptyset(&sa.sa_mask);
269 sa.sa_flags=(flags & 1) ? SA_RESTART : 0;
270 sa.sa_handler=sighandler;
271 sigaction(sig, &sa, (struct sigaction *) 0);
272 }
273#endif
274}
275
276static void cs_alarm(int sig)
277{
278 cs_debug("Got alarm signal");
279 cs_log("disconnect from %s (deadlock!)", cs_inet_ntoa(client[cs_idx].ip));
280 cs_exit(0);
281}
282
283static void cs_master_alarm(int sig)
284{
285 cs_log("PANIC: master deadlock! last location: %s", mloc);
286 fprintf(stderr, "PANIC: master deadlock! last location: %s", mloc);
287 fflush(stderr);
288 cs_exit(0);
289}
290
291static void cs_sigpipe(int sig)
292{
293 if ((cs_idx) && (master_pid!=getppid()))
294 cs_exit(0);
295 cs_log("Got sigpipe signal -> captured");
296}
297
298void cs_exit(int sig)
299{
300 int i;
301
302 set_signal_handler(SIGCHLD, 1, SIG_IGN);
303 set_signal_handler(SIGHUP , 1, SIG_IGN);
304 if (sig && (sig!=SIGQUIT))
305 cs_log("exit with signal %d", sig);
306 switch(client[cs_idx].typ)
307 {
308 case 'c': cs_statistics(cs_idx);
309 case 'm': break;
310 case 'n': *log_fd=0;
311 break;
312 case 's': *log_fd=0;
313 for (i=1; i<CS_MAXPID; i++)
314 if (client[i].pid)
315 kill(client[i].pid, SIGQUIT);
316 cs_log("cardserver down");
317#ifndef CS_NOSHM
318 if (ecmcache) shmdt((void *)ecmcache);
319#endif
320 break;
321 }
322 if (pfd) close(pfd);
323#ifdef CS_NOSHM
324 munmap((void *)ecmcache, (size_t)shmsize);
325 if (shmid) close(shmid);
326 unlink(CS_MMAPFILE); // ignore errors, last process must succeed
327#endif
328 exit(sig);
329}
330
331static void cs_reinit_clients()
332{
333 int i;
334 struct s_auth *account;
335
336 for( i=1; i<CS_MAXPID; i++ )
337 if( client[i].pid && client[i].typ=='c' && client[i].usr[0] )
338 {
339 for (account=cfg->account; (account) ; account=account->next)
340 if (!strcmp(client[i].usr, account->usr))
341 break;
342
343 if (account &&
344 client[i].pcrc==crc32(0L, MD5((uchar *)account->pwd, strlen(account->pwd), NULL), 16))
345 {
346 client[i].grp = account->grp;
347 client[i].au = account->au;
348 client[i].tosleep = (60*account->tosleep);
349 client[i].monlvl = account->monlvl;
350 client[i].fchid = account->fchid; // CHID filters
351 client[i].cltab = account->cltab; // Class
352 client[i].ftab = account->ftab; // Ident
353 client[i].sidtabok= account->sidtabok; // services
354 client[i].sidtabno= account->sidtabno; // services
355 memcpy(&client[i].ctab, &account->ctab, sizeof(client[i].ctab));
356 memcpy(&client[i].ttab, &account->ttab, sizeof(client[i].ttab));
357#ifdef CS_ANTICASC
358 client[i].ac_idx = account->ac_idx;
359 client[i].ac_penalty = account->ac_penalty;
360 client[i].ac_limit = (account->ac_users*100+80)*cfg->ac_stime;
361#endif
362 }
363 else
364 {
365 if (ph[client[i].ctyp].type & MOD_CONN_NET)
366 {
367 cs_debug("client '%s', pid=%d not found in db (or password changed)",
368 client[i].usr, client[i].pid);
369 kill(client[i].pid, SIGQUIT);
370 }
371 }
372 }
373}
374
375static void cs_sighup()
376{
377 uchar dummy[1]={0x00};
378 write_to_pipe(fd_c2m, PIP_ID_HUP, dummy, 1);
379}
380
381static void cs_accounts_chk()
382{
383 int i;
384
385 init_userdb();
386 cs_reinit_clients();
387#ifdef CS_ANTICASC
388 for (i=0; i<CS_MAXPID; i++)
389 if (client[i].typ=='a')
390 {
391 kill(client[i].pid, SIGHUP);
392 break;
393 }
394#endif
395}
396
397static void cs_debug_level()
398{
399 int i;
400
401 cs_dblevel ^= D_ALL_DUMP;
402 if (master_pid==getpid())
403 for (i=0; i<CS_MAXPID && client[i].pid; i++)
404 client[i].dbglvl=cs_dblevel;
405 else
406 client[cs_idx].dbglvl=cs_dblevel;
407 cs_log("%sdebug_level=%d", (master_pid==getpid())?"all ":"",cs_dblevel);
408}
409
410static void cs_card_info(int i)
411{
412 uchar dummy[1]={0x00};
413 for( i=1; i<CS_MAXPID; i++ )
414 if( client[i].pid && client[i].typ=='r' && client[i].fd_m2c ){
415 write_to_pipe(client[i].fd_m2c, PIP_ID_CIN, dummy, 1);
416 }
417
418 //kill(client[i].pid, SIGUSR2);
419}
420
421static void cs_child_chk(int i)
422{
423 while (waitpid(0, NULL, WNOHANG)>0);
424 for (i=1; i<CS_MAXPID; i++)
425 if (client[i].pid)
426 if (kill(client[i].pid, 0)) {
427 if ((client[i].typ!='c') && (client[i].typ!='m'))
428 {
429 char *txt="";
430 *log_fd=0;
431 switch(client[i].typ)
432 {
433#ifdef CS_ANTICASC
434 case 'a': txt="anticascader"; break;
435#endif
436 case 'l': txt="logger"; break;
437 case 'p': txt="proxy"; break;
438 case 'r': txt="reader"; break;
439 case 'n': txt="resolver"; break;
440 }
441 cs_log("PANIC: %s lost !! (pid=%d)", txt, client[i].pid);
442 cs_exit(1);
443 }
444 else
445 {
446#ifdef CS_ANTICASC
447 char usr[32];
448 ushort ac_idx;
449 ushort ac_limit;
450 uchar ac_penalty;
451 if( cfg->ac_enabled )
452 {
453 strncpy(usr, client[i].usr, sizeof(usr)-1);
454 ac_idx = client[i].ac_idx;
455 ac_limit = client[i].ac_limit;
456 ac_penalty = client[i].ac_penalty;
457 }
458#endif
459 if (client[i].fd_m2c) close(client[i].fd_m2c);
460 if (client[i].ufd) close(client[i].ufd);
461 memset(&client[i], 0, sizeof(struct s_client));
462#ifdef CS_ANTICASC
463 if( cfg->ac_enabled )
464 {
465 client[i].ac_idx = ac_idx;
466 client[i].ac_limit = ac_limit;
467 client[i].ac_penalty = ac_penalty;
468 strcpy(client[i].usr, usr);
469 }
470#endif
471 client[i].au=(-1);
472 }
473 }
474 return;
475}
476
477int cs_fork(in_addr_t ip, in_port_t port)
478{
479 int i;
480 pid_t pid;
481 for (i=1; (i<CS_MAXPID) && (client[i].pid); i++);
482 if (i<CS_MAXPID)
483 {
484 int fdp[2];
485 memset(&client[i], 0, sizeof(struct s_client));
486 client[i].au=(-1);
487 if (pipe(fdp))
488 {
489 cs_log("Cannot create pipe (errno=%d)", errno);
490 cs_exit(1);
491 }
492 switch(pid=fork())
493 {
494 case -1:
495 cs_log("PANIC: Cannot fork() (errno=%d)", errno);
496 cs_exit(1);
497 case 0: // HERE is client
498 alarm(0);
499 set_signal_handler(SIGALRM, 0, cs_alarm);
500 set_signal_handler(SIGCHLD, 1, SIG_IGN);
501 set_signal_handler(SIGHUP , 1, SIG_IGN);
502 set_signal_handler(SIGINT , 1, SIG_IGN);
503 set_signal_handler(SIGUSR1, 1, cs_debug_level);
504 is_server=((ip) || (port<90)) ? 1 : 0;
505 fd_m2c=fdp[0];
506 close(fdp[1]);
507 close(mfdr);
508 if( port!=97 ) cs_close_log();
509 mfdr=0;
510 cs_ptyp=D_CLIENT;
511 cs_idx=i;
512#ifndef CS_NOSHM
513 shmid=0;
514#endif
515 break;
516 default: // HERE is master
517 client[i].fd_m2c=fdp[1];
518 client[i].dbglvl=cs_dblevel;
519 close(fdp[0]);
520 if (ip)
521 {
522 client[i].typ='c'; // dynamic client
523 client[i].ip=ip;
524 client[i].port=port;
525 cs_log("client(%d) connect from %s (pid=%d, pipfd=%d)",
526 i-cdiff, cs_inet_ntoa(ip), pid, client[i].fd_m2c);
527 }
528 else
529 {
530 client[i].stat=1;
531 switch(port)
532 {
533 case 99: client[i].typ='r'; // reader
534 client[i].sidtabok=reader[ridx].sidtabok;
535 client[i].sidtabno=reader[ridx].sidtabno;
536 reader[ridx].fd=client[i].fd_m2c;
537 reader[ridx].cs_idx=i;
538 if (reader[ridx].r_port)
539 cs_log("proxy started (pid=%d, server=%s)",
540 pid, reader[ridx].device);
541 else
542 {
543 if (reader[ridx].typ==R_MOUSE || reader[ridx].typ==R_SMART)
544 cs_log("reader started (pid=%d, device=%s, detect=%s%s, mhz=%d)",
545 pid, reader[ridx].device,
546 reader[ridx].detect&0x80 ? "!" : "",
547 RDR_CD_TXT[reader[ridx].detect&0x7f],
548 reader[ridx].mhz);
549 else
550 cs_log("reader started (pid=%d, device=%s)",
551 pid, reader[ridx].device);
552 client[i].ip=client[0].ip;
553 strcpy(client[i].usr, client[0].usr);
554 }
555 cdiff=i;
556 break;
557 case 98: client[i].typ='n'; // resolver
558 client[i].ip=client[0].ip;
559 strcpy(client[i].usr, client[0].usr);
560 cs_log("resolver started (pid=%d, delay=%d sec)",
561 pid, cfg->resolvedelay);
562 cdiff=i;
563 break;
564 case 97: client[i].typ='l'; // logger
565 client[i].ip=client[0].ip;
566 strcpy(client[i].usr, client[0].usr);
567 cs_log("logger started (pid=%d)", pid);
568 cdiff=i;
569 break;
570#ifdef CS_ANTICASC
571 case 96: client[i].typ='a';
572 client[i].ip=client[0].ip;
573 strcpy(client[i].usr, client[0].usr);
574 cs_log("anticascader started (pid=%d, delay=%d min)",
575 pid, cfg->ac_stime);
576 cdiff=i;
577 break;
578#endif
579 default: client[i].typ='c'; // static client
580 client[i].ip=client[0].ip;
581 client[i].ctyp=port;
582 cs_log("%s: initialized (pid=%d%s)", ph[port].desc,
583 pid, ph[port].logtxt ? ph[port].logtxt : "");
584 break;
585 }
586 }
587 client[i].login=client[i].last=time((time_t *)0);
588 client[i].pid=pid; // MUST be last -> wait4master()
589 cs_last_idx=i;
590 i=0;
591 }
592 }
593 else
594 {
595 cs_log("max connections reached -> reject client %s", cs_inet_ntoa(ip));
596 i=(-1);
597 }
598 return(i);
599}
600
601static void init_signal()
602{
603 int i;
604 for (i=1; i<NSIG; i++)
605 set_signal_handler(i, 3, cs_exit);
606 set_signal_handler(SIGWINCH, 1, SIG_IGN);
607// set_signal_handler(SIGPIPE , 0, SIG_IGN);
608 set_signal_handler(SIGPIPE , 0, cs_sigpipe);
609// set_signal_handler(SIGALRM , 0, cs_alarm);
610 set_signal_handler(SIGALRM , 0, cs_master_alarm);
611 set_signal_handler(SIGCHLD , 1, cs_child_chk);
612// set_signal_handler(SIGHUP , 1, cs_accounts_chk);
613 set_signal_handler(SIGHUP , 1, cs_sighup);
614 set_signal_handler(SIGUSR1, 1, cs_debug_level);
615 set_signal_handler(SIGUSR2, 1, cs_card_info);
616 set_signal_handler(SIGCONT, 1, SIG_IGN);
617 cs_log("signal handling initialized (type=%s)",
618#ifdef CS_SIGBSD
619 "bsd"
620#else
621 "sysv"
622#endif
623 );
624 return;
625}
626
627static void init_shm()
628{
629#ifdef CS_NOSHM
630 //int i, fd;
631 char *buf;
632 if ((shmid=open(cs_memfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR))<0)
633 {
634 fprintf(stderr, "Cannot create mmaped file (errno=%d)", errno);
635 cs_exit(1);
636 }
637
638 buf=(char *)malloc(shmsize);
639 memset(buf, 0, shmsize);
640 write(shmid, buf, shmsize);
641 free(buf);
642
643 ecmcache=(struct s_ecm *)mmap((void *)0, (size_t) shmsize,
644 PROT_READ|PROT_WRITE, MAP_SHARED, shmid, 0);
645#else
646 struct shmid_ds sd;
647 char *shmerr_txt="Cannot %s shared memory (errno=%d)\n";
648 if ((shmid=shmget(IPC_PRIVATE, shmsize, IPC_CREAT | 0600))<0)
649 {
650 fprintf(stderr, shmerr_txt, "create", errno);
651 shmid=0;
652 cs_exit(1);
653 }
654 if ((ecmcache=(struct s_ecm *)shmat(shmid, 0, 0))==(void *)(-1))
655 {
656 fprintf(stderr, shmerr_txt, "attach", errno);
657 cs_exit(1);
658 }
659 memset(ecmcache, 0, shmsize);
660 shmctl(shmid, IPC_RMID, &sd);
661#endif
662#ifdef CS_ANTICASC
663 acasc=(struct s_acasc_shm *)&ecmcache[CS_ECMCACHESIZE];
664 ecmidx=(int *)&acasc[CS_MAXPID];
665#else
666 ecmidx=(int *)&ecmcache[CS_ECMCACHESIZE];
667#endif
668 mcl=(int *)((void *)ecmidx+sizeof(int));
669 logidx=(int *)((void *)mcl+sizeof(int));
670 c_start=(int *)((void *)logidx+sizeof(int));
671 log_fd=(int *)((void *)c_start+sizeof(int));
672 oscam_sem=(int *)((void *)log_fd+sizeof(int));
673 client=(struct s_client *)((void *)oscam_sem+sizeof(int));
674 reader=(struct s_reader *)&client[CS_MAXPID];
675#ifdef CS_WITH_GBOX
676 Cards=(struct card_struct*)&reader[CS_MAXREADER];
677 IgnoreList=(unsigned long*)&Cards[CS_MAXCARDS];
678 idstore=(struct idstore_struct*)&IgnoreList[CS_MAXIGNORE];
679 cfg=(struct s_config *)&idstore[CS_MAXPID];
680#else
681 cfg=(struct s_config *)&reader[CS_MAXREADER];
682#endif
683#ifdef CS_LOGHISTORY
684 loghistidx=(int *)((void *)cfg+sizeof(struct s_config));
685 loghist=(char *)((void *)loghistidx+sizeof(int));
686#endif
687
688#ifdef DEBUG_SHM_POINTER
689 printf("SHM ALLOC: %x\n", shmsize);
690 printf("SHM START: %p\n", (void *) ecmcache);
691 printf("SHM ST1: %p %x (%x)\n", (void *) ecmidx, ((void *) ecmidx) - ((void *) ecmcache), CS_ECMCACHESIZE*(sizeof(struct s_ecm)));
692 printf("SHM ST2: %p %x (%x)\n", (void *) oscam_sem, ((void *) oscam_sem) - ((void *) ecmidx), sizeof(int));
693 printf("SHM ST3: %p %x (%x)\n", (void *) client, ((void *) client) - ((void *) oscam_sem), sizeof(int));
694 printf("SHM ST4: %p %x (%x)\n", (void *) reader, ((void *) reader) - ((void *) client), CS_MAXPID*(sizeof(struct s_client)));
695 printf("SHM ST5: %p %x (%x)\n", (void *) cfg, ((void *) cfg) - ((void *) reader), CS_MAXREADER*(sizeof(struct s_reader)));
696 printf("SHM ST6: %p %x (%x)\n", ((void *) cfg)+sizeof(struct s_config), sizeof(struct s_config), sizeof(struct s_config));
697 printf("SHM ENDE: %p\n", ((void *) cfg)+sizeof(struct s_config));
698 printf("SHM SIZE: %x\n", ((void *) cfg)-((void *) ecmcache) + sizeof(struct s_config));
699 fflush(stdout);
700#endif
701
702 *ecmidx=0;
703 *logidx=0;
704 *oscam_sem=0;
705 client[0].pid=getpid();
706 client[0].login=time((time_t *)0);
707 client[0].ip=cs_inet_addr("127.0.0.1");
708 client[0].typ='s';
709 client[0].au=(-1);
710 client[0].dbglvl=cs_dblevel;
711 strcpy(client[0].usr, "root");
712#ifdef CS_LOGHISTORY
713 *loghistidx=0;
714 memset(loghist, 0, CS_MAXLOGHIST*CS_LOGHISTSIZE);
715#endif
716}
717
718static int start_listener(struct s_module *ph, int port_idx)
719{
720 int ov=1, timeout, is_udp, i;
721 char ptxt[2][32];
722 //struct hostent *ptrh; /* pointer to a host table entry */
723 struct protoent *ptrp; /* pointer to a protocol table entry */
724 struct sockaddr_in sad; /* structure to hold server's address */
725
726 ptxt[0][0]=ptxt[1][0]='\0';
727 if (!ph->ptab->ports[port_idx].s_port)
728 {
729 cs_log("%s: disabled", ph->desc);
730 return(0);
731 }
732 is_udp=(ph->type==MOD_CONN_UDP);
733
734 memset((char *)&sad,0,sizeof(sad)); /* clear sockaddr structure */
735 sad.sin_family = AF_INET; /* set family to Internet */
736 if (!ph->s_ip)
737 ph->s_ip=cfg->srvip;
738 if (ph->s_ip)
739 {
740 sad.sin_addr.s_addr=ph->s_ip;
741 sprintf(ptxt[0], ", ip=%s", inet_ntoa(sad.sin_addr));
742 }
743 else
744 sad.sin_addr.s_addr=INADDR_ANY;
745 timeout=cfg->bindwait;
746 //ph->fd=0;
747 ph->ptab->ports[port_idx].fd = 0;
748
749 if (ph->ptab->ports[port_idx].s_port > 0) /* test for illegal value */
750 sad.sin_port = htons((u_short)ph->ptab->ports[port_idx].s_port);
751 else
752 {
753 cs_log("%s: Bad port %d", ph->desc, ph->ptab->ports[port_idx].s_port);
754 return(0);
755 }
756
757 /* Map transport protocol name to protocol number */
758
759 if( (ptrp=getprotobyname(is_udp ? "udp" : "tcp")) )
760 ov=ptrp->p_proto;
761 else
762 ov=(is_udp) ? 17 : 6; // use defaults on error
763
764 if ((ph->ptab->ports[port_idx].fd=socket(PF_INET,is_udp ? SOCK_DGRAM : SOCK_STREAM, ov))<0)
765 {
766 cs_log("%s: Cannot create socket (errno=%d)", ph->desc, errno);
767 return(0);
768 }
769
770 ov=1;
771 if (setsockopt(ph->ptab->ports[port_idx].fd, SOL_SOCKET, SO_REUSEADDR, (void *)&ov, sizeof(ov))<0)
772 {
773 cs_log("%s: setsockopt failed (errno=%d)", ph->desc, errno);
774 close(ph->ptab->ports[port_idx].fd);
775 return(ph->ptab->ports[port_idx].fd=0);
776 }
777
778#ifdef SO_REUSEPORT
779 setsockopt(ph->ptab->ports[port_idx].fd, SOL_SOCKET, SO_REUSEPORT, (void *)&ov, sizeof(ov));
780#endif
781
782#ifdef SO_PRIORITY
783 if (cfg->netprio)
784 if (!setsockopt(ph->ptab->ports[port_idx].fd, SOL_SOCKET, SO_PRIORITY, (void *)&cfg->netprio, sizeof(ulong)))
785 sprintf(ptxt[1], ", prio=%ld", cfg->netprio);
786#endif
787
788 if( !is_udp )
789 {
790 ulong keep_alive = 1;
791 setsockopt(ph->ptab->ports[port_idx].fd, SOL_SOCKET, SO_KEEPALIVE,
792 (void *)&keep_alive, sizeof(ulong));
793 }
794
795 while (timeout--)
796 {
797 if (bind(ph->ptab->ports[port_idx].fd, (struct sockaddr *)&sad, sizeof (sad))<0)
798 {
799 if (timeout)
800 {
801 cs_log("%s: Bind request failed, waiting another %d seconds",
802 ph->desc, timeout);
803 sleep(1);
804 }
805 else
806 {
807 cs_log("%s: Bind request failed, giving up", ph->desc);
808 close(ph->ptab->ports[port_idx].fd);
809 return(ph->ptab->ports[port_idx].fd=0);
810 }
811 }
812 else timeout=0;
813 }
814
815 if (!is_udp)
816 if (listen(ph->ptab->ports[port_idx].fd, CS_QLEN)<0)
817 {
818 cs_log("%s: Cannot start listen mode (errno=%d)", ph->desc, errno);
819 close(ph->ptab->ports[port_idx].fd);
820 return(ph->ptab->ports[port_idx].fd=0);
821 }
822
823 cs_log("%s: initialized (fd=%d, port=%d%s%s%s)",
824 ph->desc, ph->ptab->ports[port_idx].fd,
825 ph->ptab->ports[port_idx].s_port,
826 ptxt[0], ptxt[1], ph->logtxt ? ph->logtxt : "");
827
828 for( i=0; i<ph->ptab->ports[port_idx].ftab.nfilts; i++ ) {
829 int j;
830 cs_log("CAID: %04X", ph->ptab->ports[port_idx].ftab.filts[i].caid );
831 for( j=0; j<ph->ptab->ports[port_idx].ftab.filts[i].nprids; j++ )
832 cs_log("provid #%d: %06X", j, ph->ptab->ports[port_idx].ftab.filts[i].prids[j]);
833 }
834 return(ph->ptab->ports[port_idx].fd);
835}
836
837static void *cs_client_resolve(void *dummy)
838{
839 while (1)
840 {
841 struct hostent *rht;
842 struct s_auth *account;
843 struct sockaddr_in udp_sa;
844
845 for (account=cfg->account; account; account=account->next)
846 if (account->dyndns[0])
847 {
848 if (rht=gethostbyname((const char *)account->dyndns))
849 {
850 memcpy(&udp_sa.sin_addr, rht->h_addr, sizeof(udp_sa.sin_addr));
851 account->dynip=cs_inet_order(udp_sa.sin_addr.s_addr);
852 }
853 else
854 cs_log("can't resolve hostname %s (user: %s)", account->dyndns, account->usr);
855 client[cs_idx].last=time((time_t)0);
856 }
857 sleep(cfg->resolvedelay);
858 }
859}
860
861static void start_client_resolver()
862{
863 int i;
864 pthread_t tid;
865
866 if (i=pthread_create(&tid, (pthread_attr_t *)0, cs_client_resolve, (void *) 0))
867 cs_log("ERROR: can't create resolver-thread (err=%d)", i);
868 else
869 {
870 cs_log("resolver thread started");
871 pthread_detach(tid);
872 }
873}
874
875void cs_resolve()
876{
877 int i, idx;
878 struct hostent *rht;
879 struct s_auth *account;
880 for (i=0; i<CS_MAXREADER; i++)
881 if ((idx=reader[i].cs_idx) && (reader[i].typ & R_IS_NETWORK))
882 {
883 client[cs_idx].last=time((time_t)0);
884 if (rht=gethostbyname(reader[i].device))
885 {
886 memcpy(&client[idx].udp_sa.sin_addr, rht->h_addr,
887 sizeof(client[idx].udp_sa.sin_addr));
888 client[idx].ip=cs_inet_order(client[idx].udp_sa.sin_addr.s_addr);
889 }
890 else
891 cs_log("can't resolve %s", reader[i].device);
892 client[cs_idx].last=time((time_t)0);
893 }
894}
895
896#ifdef USE_PTHREAD
897static void *cs_logger(void *dummy)
898#else
899static void cs_logger(void)
900#endif
901{
902 *log_fd=client[cs_idx].fd_m2c;
903 while(1)
904 {
905 uchar *ptr;
906 //struct timeval tv;
907 fd_set fds;
908
909 FD_ZERO(&fds);
910 FD_SET(fd_m2c, &fds);
911 select(fd_m2c+1, &fds, 0, 0, 0);
912#ifndef USE_PTHREAD
913 if (master_pid!=getppid())
914 cs_exit(0);
915#endif
916 if (FD_ISSET(fd_m2c, &fds))
917 {
918 int n;
919// switch(n=read_from_pipe(fd_m2c, &ptr, 1))
920 n=read_from_pipe(fd_m2c, &ptr, 1);
921//if (n!=PIP_ID_NUL) printf("received %d bytes\n", n); fflush(stdout);
922 switch(n)
923 {
924 case PIP_ID_LOG:
925 cs_write_log(ptr);
926 break;
927 }
928 }
929 }
930}
931
932static void start_resolver()
933{
934 int i;
935#ifdef USE_PTHREAD
936 pthread_t tid;
937 if (i=pthread_create(&tid, (pthread_attr_t *)0, cs_logger, (void *) 0))
938 cs_log("ERROR: can't create logging-thread (err=%d)", i);
939 else
940 {
941 cs_log("logging thread started");
942 pthread_detach(tid);
943 }
944#endif
945 sleep(1); // wait for reader
946 while(1)
947 {
948 if (master_pid!=getppid())
949 cs_exit(0);
950 cs_resolve();
951 for (i=0; i<cfg->resolvedelay; i++)
952 if (master_pid!=getppid())
953 cs_exit(0);
954 else
955 sleep(1);
956// sleep(cfg->resolvedelay);
957 }
958}
959
960#ifdef CS_ANTICASC
961static void start_anticascader()
962{
963 int i;
964
965 use_ac_log=1;
966 set_signal_handler(SIGHUP, 1, ac_init_stat);
967
968 ac_init_stat(0);
969 while(1)
970 {
971 for( i=0; i<cfg->ac_stime*60; i++ )
972 if( master_pid!=getppid() )
973 cs_exit(0);
974 else
975 sleep(1);
976
977 if (master_pid!=getppid())
978 cs_exit(0);
979
980 ac_do_stat();
981 }
982}
983#endif
984
985static void init_cardreader()
986{
987 for (ridx=0; ridx<CS_MAXREADER; ridx++)
988 if (reader[ridx].device[0])
989 switch(cs_fork(0, 99))
990 {
991 case -1:
992 cs_exit(1);
993 case 0:
994 break;
995 default:
996 wait4master();
997 start_cardreader();
998 }
999}
1000
1001static void init_service(int srv)
1002{
1003#ifdef USE_PTHREAD
1004 uchar dummy[1]={0x00};
1005#endif
1006
1007 switch(cs_fork(0, srv))
1008 {
1009 case -1:
1010 cs_exit(1);
1011 case 0:
1012 break;
1013 default:
1014 wait4master();
1015 switch(srv)
1016 {
1017#ifdef CS_ANTICASC
1018 case 96: start_anticascader();
1019#endif
1020#ifdef USE_PTHREAD
1021 case 97: cs_logger(dummy);
1022#else
1023 case 97: cs_logger();
1024#endif
1025 case 98: start_resolver();
1026 }
1027 }
1028}
1029
1030void wait4master()
1031{
1032 int i;
1033 for (i=0; (i<1000) && (client[cs_idx].pid!=getpid()); i++)
1034 usleep(1000L);
1035 if (client[cs_idx].pid!=getpid())
1036 {
1037 cs_log("PANIC: client not found in shared memory");
1038 cs_exit(1);
1039 }
1040 cs_debug("starting client %d with ip %s",
1041 cs_idx-cdiff, cs_inet_ntoa(client[cs_idx].ip));
1042}
1043
1044static void cs_fake_client(char *usr, int uniq, in_addr_t ip)
1045{
1046 /* - Uniq = 1: only one connection per user
1047 * - Uniq = 2: set user only to fake if source ip is different (e.g. for
1048 * newcamd clients with different CAID's -> Ports)
1049 */
1050
1051 int i;
1052
1053 for (i=cdiff+1; i<CS_MAXPID; i++) {
1054 if (client[i].pid
1055 && (client[i].typ == 'c')
1056 && !client[i].dup
1057 && !strcmp(client[i].usr, usr)
1058 && ((uniq == 1) || (client[i].ip != ip)))
1059 {
1060 client[cs_idx].dup = 1;
1061 client[cs_idx].au = -1;
1062 cs_log("client(%d) duplicate user '%s' from %s set to fake (uniq=%d)", cs_idx-cdiff, usr, cs_inet_ntoa(ip), uniq);
1063 break;
1064 }
1065 }
1066}
1067
1068int cs_auth_client(struct s_auth *account, char *e_txt)
1069{
1070 int rc=0;
1071 char buf[16];
1072 char *t_crypt="encrypted";
1073 char *t_plain="plain";
1074 char *t_grant=" granted";
1075 char *t_reject=" rejected";
1076 char *t_msg[]= { buf, "invalid access", "invalid ip", "unknown reason" };
1077 client[cs_idx].grp=0xffffffff;
1078 client[cs_idx].au=(-1);
1079 switch((long)account)
1080 {
1081 case -2: // gbx-dummy
1082 client[cs_idx].dup=0;
1083 break;
1084 case 0: // reject access
1085 rc=1;
1086 cs_log("%s %s-client %s%s (%s)",
1087 client[cs_idx].crypted ? t_crypt : t_plain,
1088 ph[client[cs_idx].ctyp].desc,
1089 client[cs_idx].ip ? cs_inet_ntoa(client[cs_idx].ip) : "",
1090 client[cs_idx].ip ? t_reject : t_reject+1,
1091 e_txt ? e_txt : t_msg[rc]);
1092 break;
1093 default: // grant/check access
1094 if (client[cs_idx].ip && account->dyndns[0])
1095 if (client[cs_idx].ip != account->dynip)
1096 rc=2;
1097 if (!rc)
1098 {
1099 client[cs_idx].dup=0;
1100 if (client[cs_idx].typ=='c')
1101 {
1102 client[cs_idx].grp=account->grp;
1103 client[cs_idx].au=account->au;
1104 client[cs_idx].tosleep=(60*account->tosleep);
1105 memcpy(&client[cs_idx].ctab, &account->ctab, sizeof(client[cs_idx].ctab));
1106 if (account->uniq)
1107 cs_fake_client(account->usr, account->uniq, client[cs_idx].ip);
1108 client[cs_idx].ftab = account->ftab; // IDENT filter
1109 client[cs_idx].cltab = account->cltab; // CLASS filter
1110 client[cs_idx].fchid = account->fchid; // CHID filter
1111 client[cs_idx].sidtabok= account->sidtabok; // services
1112 client[cs_idx].sidtabno= account->sidtabno; // services
1113 client[cs_idx].pcrc = crc32(0L, MD5((uchar *)account->pwd, strlen(account->pwd), NULL), 16);
1114 memcpy(&client[cs_idx].ttab, &account->ttab, sizeof(client[cs_idx].ttab));
1115#ifdef CS_ANTICASC
1116 ac_init_client(account);
1117#endif
1118 }
1119 }
1120 client[cs_idx].monlvl=account->monlvl;
1121 strcpy(client[cs_idx].usr, account->usr);
1122 case -1: // anonymous grant access
1123 if (rc)
1124 t_grant=t_reject;
1125 else
1126 {
1127 if (client[cs_idx].typ=='m')
1128 sprintf(t_msg[0], "lvl=%d", client[cs_idx].monlvl);
1129 else
1130 sprintf(t_msg[0], "au=%d", client[cs_idx].au+1);
1131 }
1132
1133 if(client[cs_idx].ncd_server)
1134 {
1135 cs_log("%s %s:%d-client %s%s (%s, %s)",
1136 client[cs_idx].crypted ? t_crypt : t_plain,
1137 e_txt ? e_txt : ph[client[cs_idx].ctyp].desc,
1138 cfg->ncd_ptab.ports[client[cs_idx].port_idx].s_port,
1139 client[cs_idx].ip ? cs_inet_ntoa(client[cs_idx].ip) : "",
1140 client[cs_idx].ip ? t_grant : t_grant+1,
1141 username(cs_idx), t_msg[rc]);
1142 }
1143 else
1144 {
1145 cs_log("%s %s-client %s%s (%s, %s)",
1146 client[cs_idx].crypted ? t_crypt : t_plain,
1147 e_txt ? e_txt : ph[client[cs_idx].ctyp].desc,
1148 client[cs_idx].ip ? cs_inet_ntoa(client[cs_idx].ip) : "",
1149 client[cs_idx].ip ? t_grant : t_grant+1,
1150 username(cs_idx), t_msg[rc]);
1151 }
1152
1153 break;
1154 }
1155 return(rc);
1156}
1157
1158void cs_disconnect_client(void)
1159{
1160 char buf[32]={0};
1161 if (client[cs_idx].ip)
1162 sprintf(buf, " from %s", cs_inet_ntoa(client[cs_idx].ip));
1163 cs_log("%s disconnected%s", username(cs_idx), buf);
1164 cs_exit(0);
1165}
1166
1167int check_ecmcache(ECM_REQUEST *er, ulong grp)
1168{
1169 int i;
1170// cs_ddump(ecmd5, CS_ECMSTORESIZE, "ECM search");
1171//cs_log("cache CHECK: grp=%lX", grp);
1172 for(i=0; i<CS_ECMCACHESIZE; i++)
1173 if ((grp & ecmcache[i].grp) &&
1174 (!memcmp(ecmcache[i].ecmd5, er->ecmd5, CS_ECMSTORESIZE)))
1175 {
1176//cs_log("cache found: grp=%lX cgrp=%lX", grp, ecmcache[i].grp);
1177 memcpy(er->cw, ecmcache[i].cw, 16);
1178 return(1);
1179 }
1180 return(0);
1181}
1182
1183static void store_ecm(ECM_REQUEST *er)
1184{
1185//cs_log("store ecm from reader %d", er->reader[0]);
1186 memcpy(ecmcache[*ecmidx].ecmd5, er->ecmd5, CS_ECMSTORESIZE);
1187 memcpy(ecmcache[*ecmidx].cw, er->cw, 16);
1188 ecmcache[*ecmidx].caid=er->caid;
1189 ecmcache[*ecmidx].prid=er->prid;
1190 ecmcache[*ecmidx].grp =reader[er->reader[0]].grp;
1191// cs_ddump(ecmcache[*ecmidx].ecmd5, CS_ECMSTORESIZE, "ECM stored (idx=%d)", *ecmidx);
1192 *ecmidx=(*ecmidx+1) % CS_ECMCACHESIZE;
1193}
1194
1195void store_logentry(char *txt)
1196{
1197#ifdef CS_LOGHISTORY
1198 char *ptr;
1199 ptr=(char *)(loghist+(*loghistidx*CS_LOGHISTSIZE));
1200 ptr[0]='\1'; // make username unusable
1201 ptr[1]='\0';
1202 if ((client[cs_idx].typ=='c') || (client[cs_idx].typ=='m'))
1203 strncpy(ptr, client[cs_idx].usr, 31);
1204 strncpy(ptr+32, txt, CS_LOGHISTSIZE-33);
1205 *loghistidx=(*loghistidx+1) % CS_MAXLOGHIST;
1206#endif
1207}
1208
1209/*
1210 * write_to_pipe():
1211 * write all kind of data to pipe specified by fd
1212 */
1213int write_to_pipe(int fd, int id, uchar *data, int n)
1214{
1215 uchar buf[1024+3+sizeof(int)];
1216
1217//printf("WRITE_START pid=%d", getpid()); fflush(stdout);
1218 if ((id<0) || (id>PIP_ID_MAX))
1219 return(PIP_ID_ERR);
1220 memcpy(buf, PIP_ID_TXT[id], 3);
1221 memcpy(buf+3, &n, sizeof(int));
1222 memcpy(buf+3+sizeof(int), data, n);
1223 n+=3+sizeof(int);
1224//n=write(fd, buf, n);
1225//printf("WRITE_END pid=%d", getpid()); fflush(stdout);
1226//return(n);
1227 if( !fd )
1228 cs_log("write_to_pipe: fd==0");
1229 return(write(fd, buf, n));
1230}
1231
1232/*
1233 * read_from_pipe():
1234 * read all kind of data from pipe specified by fd
1235 * special-flag redir: if set AND data is ECM: this will redirected to appr. client
1236 */
1237int read_from_pipe(int fd, uchar **data, int redir)
1238{
1239 int rc;
1240 static int hdr=0;
1241 static uchar buf[1024+1+3+sizeof(int)];
1242
1243 *data=(uchar *)0;
1244 rc=PIP_ID_NUL;
1245
1246 if (!hdr)
1247 {
1248 if (bytes_available(fd))
1249 {
1250 if (read(fd, buf, 3+sizeof(int))==3+sizeof(int))
1251 memcpy(&hdr, buf+3, sizeof(int));
1252 else
1253 cs_log("WARNING: pipe header to small !");
1254 }
1255 }
1256 if (hdr)
1257 {
1258 int l;
1259 for (l=0; (rc<0) && (PIP_ID_TXT[l]); l++)
1260 if (!memcmp(buf, PIP_ID_TXT[l], 3))
1261 rc=l;
1262
1263 if (rc<0)
1264 {
1265 fprintf(stderr, "WARNING: pipe garbage");
1266 fflush(stderr);
1267 cs_log("WARNING: pipe garbage");
1268 rc=PIP_ID_ERR;
1269 }
1270 else
1271 {
1272 l=hdr;
1273 if ((l+3-1+sizeof(int))>sizeof(buf))
1274 {
1275 cs_log("WARNING: packet size (%d) to large", l);
1276 l=sizeof(buf)+3-1+sizeof(int);
1277 }
1278 if (!bytes_available(fd))
1279 return(PIP_ID_NUL);
1280 hdr=0;
1281 if (read(fd, buf+3+sizeof(int), l)==l)
1282 *data=buf+3+sizeof(int);
1283 else
1284 {
1285 cs_log("WARNING: pipe data to small !");
1286 return(PIP_ID_ERR);
1287 }
1288 buf[l+3+sizeof(int)]=0;
1289 if ((redir) && (rc==PIP_ID_ECM))
1290 {
1291 //int idx;
1292 ECM_REQUEST *er;
1293 er=(ECM_REQUEST *)(buf+3+sizeof(int));
1294 if( er->cidx && client[er->cidx].fd_m2c )
1295 if (!write(client[er->cidx].fd_m2c, buf, l+3+sizeof(int))) cs_exit(1);
1296 rc=PIP_ID_DIR;
1297 }
1298 }
1299 }
1300 return(rc);
1301}
1302
1303/*
1304 * write_ecm_request():
1305 */
1306int write_ecm_request(int fd, ECM_REQUEST *er)
1307{
1308 return(write_to_pipe(fd, PIP_ID_ECM, (uchar *) er, sizeof(ECM_REQUEST)));
1309}
1310
1311int write_ecm_DCW(int fd, ECM_REQUEST *er)
1312{
1313 return(write_to_pipe(fd, PIP_ID_DCW, (uchar *) er, sizeof(ECM_REQUEST)));
1314}
1315
1316int write_ecm_answer(int fd, ECM_REQUEST *er)
1317{
1318 int i, f;
1319 uchar c;
1320 for (i=f=0; i<16; i+=4)
1321 {
1322 c=((er->cw[i]+er->cw[i+1]+er->cw[i+2]) & 0xff);
1323 if (er->cw[i+3]!=c)
1324 {
1325 f=1;
1326 er->cw[i+3]=c;
1327 }
1328 }
1329 if (f)
1330 cs_debug("notice: changed dcw checksum bytes");
1331
1332 er->reader[0]=ridx;
1333//cs_log("answer from reader %d (rc=%d)", er->reader[0], er->rc);
1334 er->caid=er->ocaid;
1335 if (er->rc==1||(er->gbxRidx&&er->rc==0)){
1336 store_ecm(er);
1337 }
1338
1339 return(write_ecm_request(fd, er));
1340}
1341
1342static int cs_read_timer(int fd, uchar *buf, int l, int msec)
1343{
1344 struct timeval tv;
1345 fd_set fds;
1346 int rc;
1347
1348 if (!fd) return(-1);
1349 tv.tv_sec = msec / 1000;
1350 tv.tv_usec = (msec % 1000) * 1000;
1351 FD_ZERO(&fds);
1352 FD_SET(pfd, &fds);
1353
1354 select(fd+1, &fds, 0, 0, &tv);
1355
1356 rc=0;
1357 if (FD_ISSET(pfd, &fds))
1358 if (!(rc=read(fd, buf, l)))
1359 rc=-1;
1360
1361 return(rc);
1362}
1363
1364ECM_REQUEST *get_ecmtask()
1365{
1366 int i, n;
1367 ECM_REQUEST *er=0;
1368
1369 if (!ecmtask)
1370 {
1371 n=(ph[client[cs_idx].ctyp].multi)?CS_MAXPENDING:1;
1372 if( (ecmtask=(ECM_REQUEST *)malloc(n*sizeof(ECM_REQUEST))) )
1373 memset(ecmtask, 0, n*sizeof(ECM_REQUEST));
1374 }
1375
1376 n=(-1);
1377 if (!ecmtask)
1378 {
1379 cs_log("Cannot allocate memory (errno=%d)", errno);
1380 n=(-2);
1381 }
1382 else
1383 if (ph[client[cs_idx].ctyp].multi)
1384 {
1385 for (i=0; (n<0) && (i<CS_MAXPENDING); i++)
1386 if (ecmtask[i].rc<100)
1387 er=&ecmtask[n=i];
1388 }
1389 else
1390 er=&ecmtask[n=0];
1391
1392 if (n<0)
1393 cs_log("WARNING: ecm pending table overflow !");
1394 else
1395 {
1396 memset(er, 0, sizeof(ECM_REQUEST));
1397 er->rc=100;
1398 er->cpti=n;
1399 er->cidx=cs_idx;
1400 cs_ftime(&er->tps);
1401 }
1402 return(er);
1403}
1404
1405int send_dcw(ECM_REQUEST *er)
1406{
1407 static char *stxt[]={"found", "cache1", "cache2", "emu",
1408 "not found", "timeout", "sleeping",
1409 "fake", "invalid", "corrupt"};
1410 static char *stxtEx[]={"", "group", "caid", "ident", "class", "chid", "queue"};
1411 static char *stxtWh[]={"", "user ", "reader ", "server ", "lserver "};
1412 char sby[32]="";
1413 char erEx[32]="";
1414 char uname[38]="";
1415 struct timeb tpe;
1416 ushort lc, *lp;
1417 for (lp=(ushort *)er->ecm+(er->l>>2), lc=0; lp>=(ushort *)er->ecm; lp--)
1418 lc^=*lp;
1419 cs_ftime(&tpe);
1420 if(er->gbxFrom)
1421 snprintf(uname,sizeof(uname)-1, "%s(%04X)", username(cs_idx), er->gbxFrom);
1422 else
1423 snprintf(uname,sizeof(uname)-1, "%s", username(cs_idx));
1424 if (er->rc==0)
1425 {
1426 if(reader[er->reader[0]].typ==R_GBOX)
1427 snprintf(sby, sizeof(sby)-1, " by %s(%04X)", reader[er->reader[0]].label,er->gbxCWFrom);
1428 else
1429 snprintf(sby, sizeof(sby)-1, " by %s", reader[er->reader[0]].label);
1430 }
1431 if (er->rc<4) er->rcEx=0;
1432 if (er->rcEx)
1433 snprintf(erEx, sizeof(erEx)-1, "rejected %s%s", stxtWh[er->rcEx>>4],
1434 stxtEx[er->rcEx&0xf]);
1435 cs_log("%s (%04X&%06X/%04X/%02X:%04X): %s (%d ms)%s",
1436 uname, er->caid, er->prid, er->srvid, er->l, lc,
1437 er->rcEx?erEx:stxt[er->rc],
1438 1000*(tpe.time-er->tps.time)+tpe.millitm-er->tps.millitm, sby);
1439 er->caid=er->ocaid;
1440 switch(er->rc)
1441 {
1442 case 2:
1443 case 1: client[cs_idx].cwcache++;
1444 case 3:
1445 case 0: client[cs_idx].cwfound++; break;
1446 default: client[cs_idx].cwnot++;
1447 if (er->rc>5)
1448 client[cs_idx].cwcache++;
1449 }
1450#ifdef CS_ANTICASC
1451 ac_chk(er, 1);
1452#endif
1453
1454 if( cfg->show_ecm_dw && !client[cs_idx].dbglvl )
1455 cs_dump(er->cw, 16, 0);
1456 if (er->rc==7) er->rc=0;
1457 ph[client[cs_idx].ctyp].send_dcw(er);
1458 return 0;
1459}
1460
1461static void chk_dcw(int fd)
1462{
1463 ECM_REQUEST *er, *ert;
1464 if (read_from_pipe(fd, (uchar **)&er, 0)!=PIP_ID_ECM)
1465 return;
1466 //cs_log("dcw check from reader %d for idx %d (rc=%d)", er->reader[0], er->cpti, er->rc);
1467 ert=&ecmtask[er->cpti];
1468 if (ert->rc<100)
1469 return; // already done
1470 if( (er->caid!=ert->caid) || memcmp(er->ecm , ert->ecm , sizeof(er->ecm)) )
1471 return; // obsolete
1472 ert->rcEx=er->rcEx;
1473 if (er->rc>0) // found
1474 {
1475 ert->rc=(er->rc==2)?2:0;
1476 ert->rcEx=0;
1477 ert->reader[0]=er->reader[0];
1478 memcpy(ert->cw , er->cw , sizeof(er->cw));
1479 ert->gbxCWFrom=er->gbxCWFrom;
1480 }
1481 else // not found (from ONE of the readers !)
1482 {
1483 int i;
1484 ert->reader[er->reader[0]]=0;
1485 for (i=0; (ert) && (i<CS_MAXREADER); i++)
1486 if (ert->reader[i]) // we have still another chance
1487 ert=(ECM_REQUEST *)0;
1488 if (ert) ert->rc=4;
1489 }
1490 if (ert) send_dcw(ert);
1491 return;
1492}
1493
1494ulong chk_provid(uchar *ecm, ushort caid)
1495{
1496 int i;
1497 ulong provid=0;
1498 switch(caid)
1499 {
1500 case 0x100: // seca
1501 provid=b2i(2, ecm+3);
1502 break;
1503 case 0x500: // viaccess
1504 i=(ecm[4]==0xD2) ? ecm[5] + 2 : 0; // skip d2 nano
1505 if ((ecm[5+i]==3) && ((ecm[4+i]==0x90) || (ecm[4+i]==0x40)))
1506 provid=(b2i(3, ecm+6+i) & 0xFFFFF0);
1507 default:
1508 // cryptoworks ?
1509 if( caid&0x0d00 && ecm[8]==0x83 && ecm[9]==1 )
1510 provid=(ulong)ecm[10];
1511 }
1512 return(provid);
1513}
1514
1515/*
1516void guess_irdeto(ECM_REQUEST *er)
1517{
1518 uchar b3;
1519 int b47;
1520 //ushort chid;
1521 struct s_irdeto_quess *ptr;
1522
1523 b3 = er->ecm[3];
1524 ptr = cfg->itab[b3];
1525 if( !ptr ) {
1526 cs_debug("unknown irdeto byte 3: %02X", b3);
1527 return;
1528 }
1529 b47 = b2i(4, er->ecm+4);
1530 //chid = b2i(2, er->ecm+6);
1531 //cs_debug("ecm: b47=%08X, ptr->b47=%08X, ptr->caid=%04X", b47, ptr->b47, ptr->caid);
1532 while( ptr )
1533 {
1534 if( b47==ptr->b47 )
1535 {
1536 if( er->srvid && (er->srvid!=ptr->sid) )
1537 {
1538 cs_debug("sid mismatched (ecm: %04X, guess: %04X), wrong oscam.ird file?",
1539 er->srvid, ptr->sid);
1540 return;
1541 }
1542 er->caid=ptr->caid;
1543 er->srvid=ptr->sid;
1544 er->chid=(ushort)ptr->b47;
1545// cs_debug("quess_irdeto() found caid=%04X, sid=%04X, chid=%04X",
1546// er->caid, er->srvid, er->chid);
1547 return;
1548 }
1549 ptr=ptr->next;
1550 }
1551}
1552*/
1553
1554void guess_cardsystem(ECM_REQUEST *er)
1555{
1556 ushort last_hope=0;
1557
1558 // viaccess - check by provid-search
1559 if( (er->prid=chk_provid(er->ecm, 0x500)) )
1560 er->caid=0x500;
1561
1562 // nagra
1563 // is ecm[1] always 0x30 ?
1564 // is ecm[3] always 0x07 ?
1565 if ((er->ecm[6]==1) && (er->ecm[4]==er->ecm[2]-2))
1566 er->caid=0x1801;
1567
1568 // seca2 - very poor
1569 if ((er->ecm[8]==0x10) && ((er->ecm[9]&0xF1)==1))
1570 last_hope=0x100;
1571
1572 // is cryptoworks, but which caid ?
1573 if ((er->ecm[3]==0x81) && (er->ecm[4]==0xFF) &&
1574 (!er->ecm[5]) && (!er->ecm[6]) && (er->ecm[7]==er->ecm[2]-5))
1575 last_hope=0xd00;
1576
1577/*
1578 if (!er->caid && er->ecm[2]==0x31 && er->ecm[0x0b]==0x28)
1579 guess_irdeto(er);
1580*/
1581
1582 if (!er->caid) // guess by len ..
1583 er->caid=len4caid[er->ecm[2]+3];
1584
1585 if (!er->caid)
1586 er->caid=last_hope;
1587}
1588
1589void request_cw(ECM_REQUEST *er, int flag, int reader_types)
1590{
1591 int i;
1592 if ((reader_types == 0) || (reader_types == 2))
1593 er->level=flag;
1594 flag=(flag)?3:1; // flag specifies with/without fallback-readers
1595 for (i=0; i<CS_MAXREADER; i++)
1596 {
1597 switch (reader_types)
1598 {
1599 // network and local cards
1600 default:
1601 case 0:
1602 if (er->reader[i]&flag)
1603 write_ecm_request(reader[i].fd, er);
1604 break;
1605 // only local cards
1606 case 1:
1607 if (!(reader[i].typ & R_IS_NETWORK))
1608 if (er->reader[i]&flag)
1609 write_ecm_request(reader[i].fd, er);
1610 break;
1611 // only network
1612 case 2:
1613 if ((reader[i].typ & R_IS_NETWORK))
1614 if (er->reader[i]&flag)
1615 write_ecm_request(reader[i].fd, er);
1616 break;
1617 }
1618 }
1619}
1620
1621void get_cw(ECM_REQUEST *er)
1622{
1623 int i, j, m, rejected;
1624 //uchar orig_caid[sizeof(er->caid)];
1625 time_t now;
1626//test the guessing ...
1627//cs_log("caid should be %04X, provid %06X", er->caid, er->prid);
1628//er->caid=0;
1629
1630 client[cs_idx].lastecm=time((time_t)0);
1631
1632 if (!er->caid)
1633 guess_cardsystem(er);
1634
1635 if( (er->caid & 0xFF00)==0x600 && !er->chid )
1636 er->chid = (er->ecm[6]<<8)|er->ecm[7];
1637
1638 if (!er->prid)
1639 er->prid=chk_provid(er->ecm, er->caid);
1640
1641// quickfix for 0100:000065
1642 if (er->caid == 0x100 && er->prid == 0x65 && er->srvid == 0)
1643 er->srvid = 0x0642;
1644
1645 if( (!er->prid) && client[cs_idx].ncd_server )
1646 {
1647 int pi = client[cs_idx].port_idx;
1648 if( pi>=0 && cfg->ncd_ptab.nports && cfg->ncd_ptab.nports >= pi )
1649 er->prid = cfg->ncd_ptab.ports[pi].ftab.filts[0].prids[0];
1650 }
1651
1652//cs_log("caid IS NOW .. %04X, provid %06X", er->caid, er->prid);
1653
1654 rejected=0;
1655 if (er->rc>99) // rc<100 -> ecm error
1656 {
1657 now=time((time_t *) 0);
1658 m=er->caid;
1659 er->ocaid=er->caid;
1660
1661 i=er->srvid;
1662 if ((i!=client[cs_idx].last_srvid) || (!client[cs_idx].lastswitch))
1663 client[cs_idx].lastswitch=now;
1664 if ((client[cs_idx].tosleep) &&
1665 (now-client[cs_idx].lastswitch>client[cs_idx].tosleep))
1666 er->rc=6; // sleeping
1667 client[cs_idx].last_srvid=i;
1668 client[cs_idx].last_caid=m;
1669
1670 for (j=0; (j<6) && (er->rc>99); j++)
1671 switch(j)
1672 {
1673 case 0: if (client[cs_idx].dup)
1674 er->rc=7; // fake
1675 break;
1676 case 1: if (!chk_bcaid(er, &client[cs_idx].ctab))
1677 {
1678// cs_log("chk_bcaid failed");
1679 er->rc=8; // invalid
1680 er->rcEx=E2_CAID;
1681 }
1682 break;
1683 case 2: if (!chk_srvid(er, cs_idx))
1684 er->rc=8;
1685 break;
1686 case 3: if (!chk_ufilters(er))
1687 er->rc=8;
1688 break;
1689 case 4: if (!chk_sfilter(er, ph[client[cs_idx].ctyp].ptab))
1690 er->rc=8;
1691 break;
1692 case 5: if( (i=er->l-(er->ecm[2]+3)) )
1693 {
1694 if (i>0)
1695 {
1696 cs_debug("warning: ecm size adjusted from 0x%X to 0x%X",
1697 er->l, er->ecm[2]+3);
1698 er->l=(er->ecm[2]+3);
1699 }
1700 else
1701 er->rc=9; // corrupt
1702 }
1703 break;
1704 }
1705
1706 if (&client[cs_idx].ttab) // Betatunneling
1707 // moved behind the check routines, because newcamd-ECM will fail if ecm is converted before
1708 {
1709 int n;
1710 ulong mask_all=0xFFFF;
1711 TUNTAB *ttab;
1712 ttab=&client[cs_idx].ttab;
1713 for (n=0; (n<CS_MAXCAIDTAB); n++)
1714 if ((er->caid==ttab->bt_caidfrom[n]) && ((er->srvid==ttab->bt_srvid[n]) || (ttab->bt_srvid[n])==mask_all))
1715 {
1716 int l;
1717 char hack_n3[13]={0x70, 0x51, 0xc7, 0x00, 0x00, 0x00, 0x01, 0x10, 0x10, 0x00, 0x87, 0x12, 0x07};
1718 char hack_n2[13]={0x70, 0x51, 0xc9, 0x00, 0x00, 0x00, 0x01, 0x10, 0x10, 0x00, 0x48, 0x12, 0x07};
1719 er->caid=ttab->bt_caidto[n];
1720 er->prid=0;
1721 er->l=(er->ecm[2]+3);
1722 memmove(er->ecm+14, er->ecm+4, er->l-1);
1723 if (er->l > 0x88)
1724 {
1725 memcpy(er->ecm+1, hack_n3, 13);
1726 if (er->ecm[0]==0x81) er->ecm[12]+= 1;
1727 }
1728 else memcpy(er->ecm+1, hack_n2, 13);
1729 er->l+=10;
1730 er->ecm[2]=er->l-3;
1731 cs_debug("ecm converted from: 0x%X to betacrypt: 0x%X for service id:0x%X",
1732 ttab->bt_caidfrom[n], ttab->bt_caidto[n], ttab->bt_srvid[n]);
1733 }
1734 }
1735
1736 memcpy(er->ecmd5, MD5(er->ecm, er->l, NULL), CS_ECMSTORESIZE);
1737
1738 if (check_ecmcache(er, client[cs_idx].grp))
1739 er->rc=1; // cache1
1740
1741#ifdef CS_ANTICASC
1742 ac_chk(er, 0);
1743#endif
1744 if( er->rc<100 && er->rc!=1 )
1745 rejected=1;
1746 }
1747
1748 if( !rejected && er->rc!=1 )
1749 {
1750 for (i=m=0; i<CS_MAXREADER; i++)
1751 if (matching_reader(er, &reader[i])&&(i!=ridx))
1752 m|=er->reader[i]=(reader[i].fallback)?2:1;
1753
1754 switch(m)
1755 {
1756 case 0: er->rc=4; // no reader -> not found
1757 if (!er->rcEx) er->rcEx=E2_GROUP;
1758 break;
1759 case 2: for (i=0; i<CS_MAXREADER; i++) // fallbacks only, switch them.
1760 er->reader[i]>>=1;
1761 }
1762 }
1763 if (er->rc<100)
1764 {
1765 if (cfg->delay) usleep(cfg->delay);
1766 send_dcw(er);
1767 return;
1768 }
1769
1770 er->rcEx=0;
1771 request_cw(er, 0, cfg->preferlocalcards ? 1 : 0);
1772}
1773
1774void log_emm_request(int auidx)
1775{
1776// cs_log("%s send emm-request (reader=%s, caid=%04X)",
1777// cs_inet_ntoa(client[cs_idx].ip), reader[auidx].label, reader[auidx].caid[0]);
1778 cs_log("%s emm-request sent (reader=%s, caid=%04X)",
1779 username(cs_idx), reader[auidx].label, reader[auidx].caid[0]);
1780}
1781
1782void do_emm(EMM_PACKET *ep)
1783{
1784 int au;//, ephs;
1785 au=client[cs_idx].au;
1786
1787 if ((au<0) || (au>=CS_MAXREADER))
1788 return;
1789 client[cs_idx].lastemm=time((time_t)0);
1790 cs_ddump(reader[au].hexserial, 8, "reader serial:");
1791 cs_ddump(ep->hexserial, 8, "emm SA:");
1792// if ((!reader[au].fd) || (reader[au].b_nano[ep->emm[3]])) // blocknano is obsolete
1793 if ((!reader[au].fd) || // reader has no fd
1794 (reader[au].caid[0]!=b2i(2,ep->caid)) || // wrong caid
1795 (memcmp(reader[au].hexserial, ep->hexserial, 8))) // wrong serial
1796 return;
1797
1798 ep->cidx=cs_idx;
1799 write_to_pipe(reader[au].fd, PIP_ID_EMM, (uchar *) ep, sizeof(EMM_PACKET));
1800}
1801
1802static int comp_timeb(struct timeb *tpa, struct timeb *tpb)
1803{
1804 if (tpa->time>tpb->time) return(1);
1805 if (tpa->time<tpb->time) return(-1);
1806 if (tpa->millitm>tpb->millitm) return(1);
1807 if (tpa->millitm<tpb->millitm) return(-1);
1808 return(0);
1809}
1810
1811static void build_delay(struct timeb *tpe, struct timeb *tpc)
1812{
1813 if (comp_timeb(tpe, tpc)>0)
1814 {
1815 tpe->time=tpc->time;
1816 tpe->millitm=tpc->millitm;
1817 }
1818}
1819
1820struct timeval *chk_pending(struct timeb tp_ctimeout)
1821{
1822 int i;
1823 ulong td;
1824 struct timeb tpn, tpe, tpc; // <n>ow, <e>nd, <c>heck
1825 static struct timeval tv;
1826
1827 ECM_REQUEST *er;
1828 cs_ftime(&tpn);
1829 tpe=tp_ctimeout; // latest delay -> disconnect
1830
1831 if (ecmtask)
1832 i=(ph[client[cs_idx].ctyp].multi)?CS_MAXPENDING:1;
1833 else
1834 i=0;
1835//cs_log("num pend=%d", i);
1836 for (--i; i>=0; i--)
1837 if (ecmtask[i].rc>=100) // check all pending ecm-requests
1838 {
1839 int act, j;
1840 er=&ecmtask[i];
1841 tpc=er->tps;
1842 tpc.millitm += (er->stage) ? cfg->ctimeout : cfg->ftimeout;
1843 tpc.time += tpc.millitm / 1000;
1844 tpc.millitm = tpc.millitm % 1000;
1845 if (!er->stage)
1846 {
1847 for (j=0, act=1; (act) && (j<CS_MAXREADER); j++)
1848 {
1849 if (cfg->preferlocalcards && !er->locals_done)
1850 {
1851 if ((er->reader[j]&1) && !(reader[j].typ & R_IS_NETWORK))
1852 act=0;
1853 }
1854 else if (cfg->preferlocalcards && er->locals_done)
1855 {
1856 if ((er->reader[j]&1) && (reader[j].typ & R_IS_NETWORK))
1857 act=0;
1858 }
1859 else
1860 {
1861 if (er->reader[j]&1)
1862 act=0;
1863 }
1864 }
1865//cs_log("stage 0, act=%d r0=%d, r1=%d, r2=%d, r3=%d, r4=%d r5=%d", act,
1866// er->reader[0], er->reader[1], er->reader[2],
1867// er->reader[3], er->reader[4], er->reader[5]);
1868 if (act)
1869 {
1870 int inc_stage = 1;
1871
1872 if (cfg->preferlocalcards && !er->locals_done)
1873 {
1874 int i;
1875
1876 er->locals_done = 1;
1877 for (i = 0; i < CS_MAXREADER; i++)
1878 {
1879 if (reader[i].typ & R_IS_NETWORK)
1880 {
1881 inc_stage = 0;
1882 }
1883 }
1884 }
1885 if (!inc_stage)
1886 {
1887 request_cw(er, er->stage, 2);
1888 tpc.millitm += 1000 * (tpn.time - er->tps.time) + tpn.millitm - er->tps.millitm;
1889 tpc.time += tpc.millitm / 1000;
1890 tpc.millitm = tpc.millitm % 1000;
1891 }
1892 else
1893 {
1894 er->locals_done = 0;
1895 er->stage++;
1896 request_cw(er, er->stage, cfg->preferlocalcards ? 1 : 0);
1897
1898 tpc.millitm += (cfg->ctimeout-cfg->ftimeout);
1899 tpc.time += tpc.millitm / 1000;
1900 tpc.millitm = tpc.millitm % 1000;
1901 }
1902 }
1903 }
1904 if (comp_timeb(&tpn, &tpc)>0) // action needed
1905 {
1906//cs_log("Action now %d.%03d", tpn.time, tpn.millitm);
1907//cs_log(" %d.%03d", tpc.time, tpc.millitm);
1908 if (er->stage)
1909 {
1910 er->rc=5; // timeout
1911 send_dcw(er);
1912 continue;
1913 }
1914 else
1915 {
1916 er->stage++;
1917 request_cw(er, er->stage, 0);
1918 tpc.millitm += (cfg->ctimeout-cfg->ftimeout);
1919 tpc.time += tpc.millitm / 1000;
1920 tpc.millitm = tpc.millitm % 1000;
1921 }
1922 }
1923 build_delay(&tpe, &tpc);
1924 }
1925 td=(tpe.time-tpn.time)*1000+(tpe.millitm-tpn.millitm)+5;
1926 tv.tv_sec = td/1000;
1927 tv.tv_usec = (td%1000)*1000;
1928//cs_log("delay %d.%06d", tv.tv_sec, tv.tv_usec);
1929 return(&tv);
1930}
1931
1932int process_input(uchar *buf, int l, int timeout)
1933{
1934 int rc;
1935 fd_set fds;
1936 struct timeb tp;
1937
1938 if (master_pid!=getppid()) cs_exit(0);
1939 if (!pfd) return(-1);
1940 cs_ftime(&tp);
1941 tp.time+=timeout;
1942 if (ph[client[cs_idx].ctyp].watchdog)
1943 alarm(cfg->cmaxidle + (cfg->ctimeout + 500) / 1000 + 1);
1944 while (1)
1945 {
1946 FD_ZERO(&fds);
1947 FD_SET(pfd, &fds);
1948 FD_SET(fd_m2c, &fds);
1949
1950 rc=select(((pfd>fd_m2c)?pfd:fd_m2c)+1, &fds, 0, 0, chk_pending(tp));
1951 if (master_pid!=getppid()) cs_exit(0);
1952 if (rc<0)
1953 {
1954 if (errno==EINTR) continue;
1955 else return(0);
1956 }
1957
1958 if (FD_ISSET(fd_m2c, &fds)) // read from pipe
1959 chk_dcw(fd_m2c);
1960
1961 if (FD_ISSET(pfd, &fds)) // read from client
1962 {
1963 rc=ph[client[cs_idx].ctyp].recv(buf, l);
1964 break;
1965 }
1966 if (tp.time<=time((time_t *)0)) // client maxidle reached
1967 {
1968 rc=(-9);
1969 break;
1970 }
1971 }
1972 if (ph[client[cs_idx].ctyp].watchdog)
1973 alarm(cfg->cmaxidle + (cfg->ctimeout + 500) / 1000 + 1);
1974 return(rc);
1975}
1976
1977static void process_master_pipe()
1978{
1979 int n;
1980 uchar *ptr;
1981
1982 switch(n=read_from_pipe(mfdr, &ptr, 1))
1983 {
1984 case PIP_ID_LOG:
1985 cs_write_log(ptr);
1986 break;
1987 case PIP_ID_HUP:
1988 cs_accounts_chk();
1989 break;
1990 }
1991}
1992
1993void cs_log_config()
1994{
1995 uchar buf[2048];
1996
1997 if (cfg->nice!=99)
1998 sprintf((char *)buf, ", nice=%d", cfg->nice);
1999 else
2000 buf[0]='\0';
2001 cs_log("version=%s, system=%s%s", CS_VERSION_X, cs_platform((char *)buf+64), buf);
2002 cs_log("max. clients=%d, client max. idle=%d sec",
2003#ifdef CS_ANTICASC
2004 CS_MAXPID-3, cfg->cmaxidle);
2005#else
2006 CS_MAXPID-2, cfg->cmaxidle);
2007#endif
2008 if( cfg->max_log_size )
2009 sprintf((char *)buf, "%d Kb", cfg->max_log_size);
2010 else
2011 strcpy((char *)buf, "unlimited");
2012 cs_log("max. logsize=%s", buf);
2013 cs_log("client timeout=%lu ms, fallback timeout=%lu ms, cache delay=%d ms",
2014 cfg->ctimeout, cfg->ftimeout, cfg->delay);
2015#ifdef CS_NOSHM
2016 cs_log("shared memory initialized (size=%d, fd=%d)", shmsize, shmid);
2017#else
2018 cs_log("shared memory initialized (size=%d, id=%d)", shmsize, shmid);
2019#endif
2020}
2021
2022int main (int argc, char *argv[])
2023{
2024 struct sockaddr_in cad; /* structure to hold client's address */
2025 int scad; /* length of address */
2026 //int fd; /* socket descriptors */
2027 int i, j, n;
2028 int bg=0;
2029 int gfd; //nph,
2030 int fdp[2];
2031 uchar buf[2048];
2032 void (*mod_def[])(struct s_module *)=
2033 {
2034 module_monitor,
2035 module_camd33,
2036 module_camd35,
2037 module_camd35_tcp,
2038 module_newcamd,
2039#ifdef CS_WITH_GBOX
2040 module_gbox,
2041#endif
2042 module_radegast,
2043 module_oscam_ser,
2044 0
2045 };
2046
2047 while ((i=getopt(argc, argv, "bc:d:hm:"))!=EOF)
2048 {
2049 switch(i)
2050 {
2051 case 'b': bg=1;
2052 break;
2053 case 'c': strncpy(cs_confdir, optarg, sizeof(cs_confdir)-1);
2054 break;
2055 case 'd': cs_dblevel=atoi(optarg);
2056 break;
2057 case 'm':
2058#ifdef CS_NOSHM
2059 strncpy(cs_memfile, optarg, sizeof(cs_memfile)-1);
2060 break;
2061#endif
2062 case 'h':
2063 default : usage();
2064 }
2065 }
2066 if (cs_confdir[strlen(cs_confdir)]!='/') strcat(cs_confdir, "/");
2067 init_shm();
2068 init_config();
2069 for (i=0; mod_def[i]; i++) // must be later BEFORE init_config()
2070 {
2071 memset(&ph[i], 0, sizeof(struct s_module));
2072 mod_def[i](&ph[i]);
2073 }
2074
2075 cs_log("auth size=%d", sizeof(struct s_auth));
2076 //cs_log_config();
2077 cfg->delay*=1000;
2078 init_sidtab();
2079 init_readerdb();
2080 init_userdb();
2081 init_signal();
2082 cs_set_mloc(30, "init");
2083 init_srvid();
2084 init_len4caid();
2085 //init_irdeto_guess_tab();
2086 cs_init_statistics(cfg->usrfile);
2087
2088 if (pipe(fdp))
2089 {
2090 cs_log("Cannot create pipe (errno=%d)", errno);
2091 cs_exit(1);
2092 }
2093 mfdr=fdp[0];
2094 fd_c2m=fdp[1];
2095 gfd=mfdr+1;
2096
2097#ifdef OS_MACOSX
2098 if (bg && daemon_compat(1,0))
2099#else
2100 if (bg && daemon(1,0))
2101#endif
2102 {
2103 cs_log("Error starting in background (errno=%d)", errno);
2104 cs_exit(1);
2105 }
2106 master_pid=client[0].pid=getpid();
2107 if (cfg->pidfile[0])
2108 {
2109 FILE *fp;
2110 if (!(fp=fopen(cfg->pidfile, "w")))
2111 {
2112 cs_log("Cannot open pid-file (errno=%d)", errno);
2113 cs_exit(1);
2114 }
2115 fprintf(fp, "%d\n", getpid());
2116 fclose(fp);
2117 }
2118
2119 for (i=0; i<CS_MAX_MOD; i++)
2120 if( (ph[i].type & MOD_CONN_NET) && ph[i].ptab )
2121 for(j=0; j<ph[i].ptab->nports; j++)
2122 {
2123 start_listener(&ph[i], j);
2124 if( ph[i].ptab->ports[j].fd+1>gfd )
2125 gfd=ph[i].ptab->ports[j].fd+1;
2126 }
2127
2128 start_client_resolver();
2129 init_service(97); // logger
2130 init_service(98); // resolver
2131 init_cardreader();
2132
2133 if (cfg->waitforcards)
2134 {
2135 int card_init_done;
2136
2137 cs_log("Waiting for local card init ....");
2138
2139 sleep(3); // short sleep for card detect to work proberly
2140
2141 for(;;)
2142 {
2143 card_init_done = 1;
2144
2145 for (i = 0; i < CS_MAXREADER; i++)
2146 {
2147 if (!reader[i].online && reader[i].card_status)
2148 {
2149 if (!(reader[i].card_status & CARD_FAILURE))
2150 {
2151 card_init_done = 0;
2152 break;
2153 }
2154 }
2155 }
2156
2157 if (card_init_done)
2158 break;
2159
2160 cs_sleepms(300); // wait a little bit
2161
2162 alarm(cfg->cmaxidle + cfg->ctimeout / 1000 + 1);
2163 }
2164
2165 cs_log("Init for all local cards done !");
2166 }
2167
2168
2169#ifdef CS_ANTICASC
2170 if( !cfg->ac_enabled )
2171 cs_log("anti cascading disabled");
2172 else
2173 {
2174 init_ac();
2175 init_service(96);
2176 }
2177#endif
2178
2179 for (i=0; i<CS_MAX_MOD; i++)
2180 if (ph[i].type & MOD_CONN_SERIAL) // for now: oscam_ser only
2181 if (ph[i].s_handler)
2182 ph[i].s_handler(i);
2183
2184 cs_close_log();
2185 *mcl=1;
2186 while (1)
2187 {
2188 fd_set fds;
2189
2190 do
2191 {
2192 FD_ZERO(&fds);
2193 FD_SET(mfdr, &fds);
2194 for (i=0; i<CS_MAX_MOD; i++)
2195 if ( (ph[i].type & MOD_CONN_NET) && ph[i].ptab )
2196 for (j=0; j<ph[i].ptab->nports; j++)
2197 if (ph[i].ptab->ports[j].fd)
2198 FD_SET(ph[i].ptab->ports[j].fd, &fds);
2199 errno=0;
2200 cs_set_mloc(0, "before select");
2201 select(gfd, &fds, 0, 0, 0);
2202 cs_set_mloc(60, "after select");
2203 } while (errno==EINTR);
2204 cs_set_mloc(-1, "event (global)");
2205
2206 client[0].last=time((time_t *)0);
2207 scad = sizeof(cad);
2208 if (FD_ISSET(mfdr, &fds))
2209 {
2210 cs_set_mloc(-1, "event: master-pipe");
2211 process_master_pipe();
2212 }
2213 for (i=0; i<CS_MAX_MOD; i++)
2214 {
2215 if( (ph[i].type & MOD_CONN_NET) && ph[i].ptab )
2216 {
2217 for( j=0; j<ph[i].ptab->nports; j++ )
2218 {
2219 if( ph[i].ptab->ports[j].fd && FD_ISSET(ph[i].ptab->ports[j].fd, &fds) )
2220 {
2221 if (ph[i].type==MOD_CONN_UDP)
2222 {
2223 cs_set_mloc(-1, "event: udp-socket");
2224 if ((n=recvfrom(ph[i].ptab->ports[j].fd, buf+3, sizeof(buf)-3, 0, (struct sockaddr *)&cad, (socklen_t *)&scad))>0)
2225 {
2226 int idx;
2227 idx=idx_from_ip(cs_inet_order(cad.sin_addr.s_addr), ntohs(cad.sin_port));
2228 if (!idx)
2229 {
2230 if (pipe(fdp))
2231 {
2232 cs_log("Cannot create pipe (errno=%d)", errno);
2233 cs_exit(1);
2234 }
2235 switch(cs_fork(cs_inet_order(cad.sin_addr.s_addr), ntohs(cad.sin_port)))
2236 {
2237 case -1:
2238 close(fdp[0]);
2239 close(fdp[1]);
2240 break;
2241 case 0:
2242 client[idx=cs_last_idx].ufd=fdp[1];
2243 close(fdp[0]);
2244 break;
2245 default:
2246// close(fdp[1]); // now used to simulate event
2247 pfd=fdp[0];
2248 wait4master();
2249 client[cs_idx].ctyp=i;
2250 client[cs_idx].port_idx=j;
2251 client[cs_idx].udp_fd=ph[i].ptab->ports[j].fd;
2252 client[cs_idx].udp_sa=cad;
2253 if (ph[client[cs_idx].ctyp].watchdog)
2254 alarm(cfg->cmaxidle + cfg->ctimeout / 1000 + 1);
2255 ph[i].s_handler(cad); // never return
2256 }
2257 }
2258 if (idx)
2259 {
2260 unsigned short rl;
2261 rl=n;
2262 buf[0]='U';
2263 memcpy(buf+1, &rl, 2);
2264 if (!write(client[idx].ufd, buf, n+3)) cs_exit(1);
2265 }
2266 }
2267 }
2268 else
2269 {
2270 cs_set_mloc(-1, "event: tcp-socket");
2271 if ((pfd=accept(ph[i].ptab->ports[j].fd, (struct sockaddr *)&cad, (socklen_t *)&scad))>0)
2272 {
2273 switch(cs_fork(cs_inet_order(cad.sin_addr.s_addr), ntohs(cad.sin_port)))
2274 {
2275 case -1:
2276 case 0:
2277 close(pfd);
2278 break;
2279 default:
2280 wait4master();
2281 client[cs_idx].ctyp=i;
2282 client[cs_idx].udp_fd=pfd;
2283 client[cs_idx].port_idx=j;
2284 if (ph[client[cs_idx].ctyp].watchdog)
2285 alarm(cfg->cmaxidle + cfg->ctimeout / 1000 + 1);
2286 ph[i].s_handler();
2287 }
2288 }
2289 }
2290 }
2291 }
2292 } // if (ph[i].type & MOD_CONN_NET)
2293 }
2294 }
2295 cs_exit(1);
2296}
Note: See TracBrowser for help on using the repository browser.