source: trunk/oscam.c@ 70

Last change on this file since 70 was 70, checked in by rorothetroll, 12 years ago

csctapi/io_serial.c : fix the serial port read/write wait routine to use select instead of poll

This make them compatible with Mac OS X and now oscamd works on OS X. The same code off course
still works on linux and other unix platforms. I let that code ran for 24h before commiting this code.
If you have any issue let me know and I'llr evert to poll for non compatible machines.

all the others : fix all the warning due to sign difference (mostly uchar versus char). This make the code compile

with -Werror on the more strict version of gcc (which is the case on OS X). I also noticed that in a lot of places
the code use a buffer defined as an uchar * ... and use strings functions (strnXXXX) where some memcpy/memcmp .. function
would have been preferable as we're suposedly manipulation a binary buffer. Anyway I fixed all of them and it now compile
without any warning or error on linux and OS X (and also probably on all the other unices but we will have to try before
adding -Werror on the other platform).

File size: 57.8 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 //kill(client[i].pid, SIGUSR2);
418}
419
420static void cs_child_chk(int i)
421{
422 while (waitpid(0, NULL, WNOHANG)>0);
423 for (i=1; i<CS_MAXPID; i++)
424 if (client[i].pid)
425 if (kill(client[i].pid, 0)) {
426 if ((client[i].typ!='c') && (client[i].typ!='m'))
427 {
428 char *txt="";
429 *log_fd=0;
430 switch(client[i].typ)
431 {
432#ifdef CS_ANTICASC
433 case 'a': txt="anticascader"; break;
434#endif
435 case 'l': txt="logger"; break;
436 case 'p': txt="proxy"; break;
437 case 'r': txt="reader"; break;
438 case 'n': txt="resolver"; break;
439 }
440 cs_log("PANIC: %s lost !! (pid=%d)", txt, client[i].pid);
441 cs_exit(1);
442 }
443 else
444 {
445#ifdef CS_ANTICASC
446 char usr[32];
447 ushort ac_idx;
448 ushort ac_limit;
449 uchar ac_penalty;
450 if( cfg->ac_enabled )
451 {
452 strncpy(usr, client[i].usr, sizeof(usr)-1);
453 ac_idx = client[i].ac_idx;
454 ac_limit = client[i].ac_limit;
455 ac_penalty = client[i].ac_penalty;
456 }
457#endif
458 if (client[i].fd_m2c) close(client[i].fd_m2c);
459 if (client[i].ufd) close(client[i].ufd);
460 memset(&client[i], 0, sizeof(struct s_client));
461#ifdef CS_ANTICASC
462 if( cfg->ac_enabled )
463 {
464 client[i].ac_idx = ac_idx;
465 client[i].ac_limit = ac_limit;
466 client[i].ac_penalty = ac_penalty;
467 strcpy(client[i].usr, usr);
468 }
469#endif
470 client[i].au=(-1);
471 }
472 }
473 return;
474}
475
476int cs_fork(in_addr_t ip, in_port_t port)
477{
478 int i;
479 pid_t pid;
480 for (i=1; (i<CS_MAXPID) && (client[i].pid); i++);
481 if (i<CS_MAXPID)
482 {
483 int fdp[2];
484 memset(&client[i], 0, sizeof(struct s_client));
485 client[i].au=(-1);
486 if (pipe(fdp))
487 {
488 cs_log("Cannot create pipe (errno=%d)", errno);
489 cs_exit(1);
490 }
491 switch(pid=fork())
492 {
493 case -1:
494 cs_log("PANIC: Cannot fork() (errno=%d)", errno);
495 cs_exit(1);
496 case 0: // HERE is client
497 alarm(0);
498 set_signal_handler(SIGALRM, 0, cs_alarm);
499 set_signal_handler(SIGCHLD, 1, SIG_IGN);
500 set_signal_handler(SIGHUP , 1, SIG_IGN);
501 set_signal_handler(SIGINT , 1, SIG_IGN);
502 set_signal_handler(SIGUSR1, 1, cs_debug_level);
503 is_server=((ip) || (port<90)) ? 1 : 0;
504 fd_m2c=fdp[0];
505 close(fdp[1]);
506 close(mfdr);
507 if( port!=97 ) cs_close_log();
508 mfdr=0;
509 cs_ptyp=D_CLIENT;
510 cs_idx=i;
511#ifndef CS_NOSHM
512 shmid=0;
513#endif
514 break;
515 default: // HERE is master
516 client[i].fd_m2c=fdp[1];
517 client[i].dbglvl=cs_dblevel;
518 close(fdp[0]);
519 if (ip)
520 {
521 client[i].typ='c'; // dynamic client
522 client[i].ip=ip;
523 client[i].port=port;
524 cs_log("client(%d) connect from %s (pid=%d, pipfd=%d)",
525 i-cdiff, cs_inet_ntoa(ip), pid, client[i].fd_m2c);
526 }
527 else
528 {
529 client[i].stat=1;
530 switch(port)
531 {
532 case 99: client[i].typ='r'; // reader
533 client[i].sidtabok=reader[ridx].sidtabok;
534 client[i].sidtabno=reader[ridx].sidtabno;
535 reader[ridx].fd=client[i].fd_m2c;
536 reader[ridx].cs_idx=i;
537 if (reader[ridx].r_port)
538 cs_log("proxy started (pid=%d, server=%s)",
539 pid, reader[ridx].device);
540 else
541 {
542 if (reader[ridx].typ==R_MOUSE)
543 cs_log("reader started (pid=%d, device=%s, detect=%s%s, mhz=%d)",
544 pid, reader[ridx].device,
545 reader[ridx].detect&0x80 ? "!" : "",
546 RDR_CD_TXT[reader[ridx].detect&0x7f],
547 reader[ridx].mhz);
548 else
549 cs_log("reader started (pid=%d, device=%s)",
550 pid, reader[ridx].device);
551 client[i].ip=client[0].ip;
552 strcpy(client[i].usr, client[0].usr);
553 }
554 cdiff=i;
555 break;
556 case 98: client[i].typ='n'; // resolver
557 client[i].ip=client[0].ip;
558 strcpy(client[i].usr, client[0].usr);
559 cs_log("resolver started (pid=%d, delay=%d sec)",
560 pid, cfg->resolvedelay);
561 cdiff=i;
562 break;
563 case 97: client[i].typ='l'; // logger
564 client[i].ip=client[0].ip;
565 strcpy(client[i].usr, client[0].usr);
566 cs_log("logger started (pid=%d)", pid);
567 cdiff=i;
568 break;
569#ifdef CS_ANTICASC
570 case 96: client[i].typ='a';
571 client[i].ip=client[0].ip;
572 strcpy(client[i].usr, client[0].usr);
573 cs_log("anticascader started (pid=%d, delay=%d min)",
574 pid, cfg->ac_stime);
575 cdiff=i;
576 break;
577#endif
578 default: client[i].typ='c'; // static client
579 client[i].ip=client[0].ip;
580 client[i].ctyp=port;
581 cs_log("%s: initialized (pid=%d%s)", ph[port].desc,
582 pid, ph[port].logtxt ? ph[port].logtxt : "");
583 break;
584 }
585 }
586 client[i].login=client[i].last=time((time_t *)0);
587 client[i].pid=pid; // MUST be last -> wait4master()
588 cs_last_idx=i;
589 i=0;
590 }
591 }
592 else
593 {
594 cs_log("max connections reached -> reject client %s", cs_inet_ntoa(ip));
595 i=(-1);
596 }
597 return(i);
598}
599
600static void init_signal()
601{
602 int i;
603 for (i=1; i<NSIG; i++)
604 set_signal_handler(i, 3, cs_exit);
605 set_signal_handler(SIGWINCH, 1, SIG_IGN);
606// set_signal_handler(SIGPIPE , 0, SIG_IGN);
607 set_signal_handler(SIGPIPE , 0, cs_sigpipe);
608// set_signal_handler(SIGALRM , 0, cs_alarm);
609 set_signal_handler(SIGALRM , 0, cs_master_alarm);
610 set_signal_handler(SIGCHLD , 1, cs_child_chk);
611// set_signal_handler(SIGHUP , 1, cs_accounts_chk);
612 set_signal_handler(SIGHUP , 1, cs_sighup);
613 set_signal_handler(SIGUSR1, 1, cs_debug_level);
614 set_signal_handler(SIGUSR2, 1, cs_card_info);
615 set_signal_handler(SIGCONT, 1, SIG_IGN);
616 cs_log("signal handling initialized (type=%s)",
617#ifdef CS_SIGBSD
618 "bsd"
619#else
620 "sysv"
621#endif
622 );
623 return;
624}
625
626static void init_shm()
627{
628#ifdef CS_NOSHM
629 //int i, fd;
630 char *buf;
631 if ((shmid=open(cs_memfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR))<0)
632 {
633 fprintf(stderr, "Cannot create mmaped file (errno=%d)", errno);
634 cs_exit(1);
635 }
636
637 buf=(char *)malloc(shmsize);
638 memset(buf, 0, shmsize);
639 write(shmid, buf, shmsize);
640 free(buf);
641
642 ecmcache=(struct s_ecm *)mmap((void *)0, (size_t) shmsize,
643 PROT_READ|PROT_WRITE, MAP_SHARED, shmid, 0);
644#else
645 struct shmid_ds sd;
646 char *shmerr_txt="Cannot %s shared memory (errno=%d)\n";
647 if ((shmid=shmget(IPC_PRIVATE, shmsize, IPC_CREAT | 0600))<0)
648 {
649 fprintf(stderr, shmerr_txt, "create", errno);
650 shmid=0;
651 cs_exit(1);
652 }
653 if ((ecmcache=(struct s_ecm *)shmat(shmid, 0, 0))==(void *)(-1))
654 {
655 fprintf(stderr, shmerr_txt, "attach", errno);
656 cs_exit(1);
657 }
658 memset(ecmcache, 0, shmsize);
659 shmctl(shmid, IPC_RMID, &sd);
660#endif
661#ifdef CS_ANTICASC
662 acasc=(struct s_acasc_shm *)&ecmcache[CS_ECMCACHESIZE];
663 ecmidx=(int *)&acasc[CS_MAXPID];
664#else
665 ecmidx=(int *)&ecmcache[CS_ECMCACHESIZE];
666#endif
667 mcl=(int *)((void *)ecmidx+sizeof(int));
668 logidx=(int *)((void *)mcl+sizeof(int));
669 c_start=(int *)((void *)logidx+sizeof(int));
670 log_fd=(int *)((void *)c_start+sizeof(int));
671 oscam_sem=(int *)((void *)log_fd+sizeof(int));
672 client=(struct s_client *)((void *)oscam_sem+sizeof(int));
673 reader=(struct s_reader *)&client[CS_MAXPID];
674#ifdef CS_WITH_GBOX
675 Cards=(struct card_struct*)&reader[CS_MAXREADER];
676 IgnoreList=(unsigned long*)&Cards[CS_MAXCARDS];
677 idstore=(struct idstore_struct*)&IgnoreList[CS_MAXIGNORE];
678 cfg=(struct s_config *)&idstore[CS_MAXPID];
679#else
680 cfg=(struct s_config *)&reader[CS_MAXREADER];
681#endif
682#ifdef CS_LOGHISTORY
683 loghistidx=(int *)((void *)cfg+sizeof(struct s_config));
684 loghist=(char *)((void *)loghistidx+sizeof(int));
685#endif
686
687#ifdef DEBUG_SHM_POINTER
688 printf("SHM ALLOC: %x\n", shmsize);
689 printf("SHM START: %p\n", (void *) ecmcache);
690 printf("SHM ST1: %p %x (%x)\n", (void *) ecmidx, ((void *) ecmidx) - ((void *) ecmcache), CS_ECMCACHESIZE*(sizeof(struct s_ecm)));
691 printf("SHM ST2: %p %x (%x)\n", (void *) oscam_sem, ((void *) oscam_sem) - ((void *) ecmidx), sizeof(int));
692 printf("SHM ST3: %p %x (%x)\n", (void *) client, ((void *) client) - ((void *) oscam_sem), sizeof(int));
693 printf("SHM ST4: %p %x (%x)\n", (void *) reader, ((void *) reader) - ((void *) client), CS_MAXPID*(sizeof(struct s_client)));
694 printf("SHM ST5: %p %x (%x)\n", (void *) cfg, ((void *) cfg) - ((void *) reader), CS_MAXREADER*(sizeof(struct s_reader)));
695 printf("SHM ST6: %p %x (%x)\n", ((void *) cfg)+sizeof(struct s_config), sizeof(struct s_config), sizeof(struct s_config));
696 printf("SHM ENDE: %p\n", ((void *) cfg)+sizeof(struct s_config));
697 printf("SHM SIZE: %x\n", ((void *) cfg)-((void *) ecmcache) + sizeof(struct s_config));
698 fflush(stdout);
699#endif
700
701 *ecmidx=0;
702 *logidx=0;
703 *oscam_sem=0;
704 client[0].pid=getpid();
705 client[0].login=time((time_t *)0);
706 client[0].ip=cs_inet_addr("127.0.0.1");
707 client[0].typ='s';
708 client[0].au=(-1);
709 client[0].dbglvl=cs_dblevel;
710 strcpy(client[0].usr, "root");
711#ifdef CS_LOGHISTORY
712 *loghistidx=0;
713 memset(loghist, 0, CS_MAXLOGHIST*CS_LOGHISTSIZE);
714#endif
715}
716
717static int start_listener(struct s_module *ph, int port_idx)
718{
719 int ov=1, timeout, is_udp, i;
720 char ptxt[2][32];
721 //struct hostent *ptrh; /* pointer to a host table entry */
722 struct protoent *ptrp; /* pointer to a protocol table entry */
723 struct sockaddr_in sad; /* structure to hold server's address */
724
725 ptxt[0][0]=ptxt[1][0]='\0';
726 if (!ph->ptab->ports[port_idx].s_port)
727 {
728 cs_log("%s: disabled", ph->desc);
729 return(0);
730 }
731 is_udp=(ph->type==MOD_CONN_UDP);
732
733 memset((char *)&sad,0,sizeof(sad)); /* clear sockaddr structure */
734 sad.sin_family = AF_INET; /* set family to Internet */
735 if (!ph->s_ip)
736 ph->s_ip=cfg->srvip;
737 if (ph->s_ip)
738 {
739 sad.sin_addr.s_addr=ph->s_ip;
740 sprintf(ptxt[0], ", ip=%s", inet_ntoa(sad.sin_addr));
741 }
742 else
743 sad.sin_addr.s_addr=INADDR_ANY;
744 timeout=cfg->bindwait;
745 //ph->fd=0;
746 ph->ptab->ports[port_idx].fd = 0;
747
748 if (ph->ptab->ports[port_idx].s_port > 0) /* test for illegal value */
749 sad.sin_port = htons((u_short)ph->ptab->ports[port_idx].s_port);
750 else
751 {
752 cs_log("%s: Bad port %d", ph->desc, ph->ptab->ports[port_idx].s_port);
753 return(0);
754 }
755
756 /* Map transport protocol name to protocol number */
757
758 if( (ptrp=getprotobyname(is_udp ? "udp" : "tcp")) )
759 ov=ptrp->p_proto;
760 else
761 ov=(is_udp) ? 17 : 6; // use defaults on error
762
763 if ((ph->ptab->ports[port_idx].fd=socket(PF_INET,is_udp ? SOCK_DGRAM : SOCK_STREAM, ov))<0)
764 {
765 cs_log("%s: Cannot create socket (errno=%d)", ph->desc, errno);
766 return(0);
767 }
768
769 ov=1;
770 if (setsockopt(ph->ptab->ports[port_idx].fd, SOL_SOCKET, SO_REUSEADDR, (void *)&ov, sizeof(ov))<0)
771 {
772 cs_log("%s: setsockopt failed (errno=%d)", ph->desc, errno);
773 close(ph->ptab->ports[port_idx].fd);
774 return(ph->ptab->ports[port_idx].fd=0);
775 }
776
777#ifdef SO_REUSEPORT
778 setsockopt(ph->ptab->ports[port_idx].fd, SOL_SOCKET, SO_REUSEPORT, (void *)&ov, sizeof(ov));
779#endif
780
781#ifdef SO_PRIORITY
782 if (cfg->netprio)
783 if (!setsockopt(ph->ptab->ports[port_idx].fd, SOL_SOCKET, SO_PRIORITY, (void *)&cfg->netprio, sizeof(ulong)))
784 sprintf(ptxt[1], ", prio=%ld", cfg->netprio);
785#endif
786
787 if( !is_udp )
788 {
789 ulong keep_alive = 1;
790 setsockopt(ph->ptab->ports[port_idx].fd, SOL_SOCKET, SO_KEEPALIVE,
791 (void *)&keep_alive, sizeof(ulong));
792 }
793
794 while (timeout--)
795 {
796 if (bind(ph->ptab->ports[port_idx].fd, (struct sockaddr *)&sad, sizeof (sad))<0)
797 {
798 if (timeout)
799 {
800 cs_log("%s: Bind request failed, waiting another %d seconds",
801 ph->desc, timeout);
802 sleep(1);
803 }
804 else
805 {
806 cs_log("%s: Bind request failed, giving up", ph->desc);
807 close(ph->ptab->ports[port_idx].fd);
808 return(ph->ptab->ports[port_idx].fd=0);
809 }
810 }
811 else timeout=0;
812 }
813
814 if (!is_udp)
815 if (listen(ph->ptab->ports[port_idx].fd, CS_QLEN)<0)
816 {
817 cs_log("%s: Cannot start listen mode (errno=%d)", ph->desc, errno);
818 close(ph->ptab->ports[port_idx].fd);
819 return(ph->ptab->ports[port_idx].fd=0);
820 }
821
822 cs_log("%s: initialized (fd=%d, port=%d%s%s%s)",
823 ph->desc, ph->ptab->ports[port_idx].fd,
824 ph->ptab->ports[port_idx].s_port,
825 ptxt[0], ptxt[1], ph->logtxt ? ph->logtxt : "");
826
827 for( i=0; i<ph->ptab->ports[port_idx].ftab.nfilts; i++ ) {
828 int j;
829 cs_log("CAID: %04X", ph->ptab->ports[port_idx].ftab.filts[i].caid );
830 for( j=0; j<ph->ptab->ports[port_idx].ftab.filts[i].nprids; j++ )
831 cs_log("provid #%d: %06X", j, ph->ptab->ports[port_idx].ftab.filts[i].prids[j]);
832 }
833 return(ph->ptab->ports[port_idx].fd);
834}
835
836static void *cs_client_resolve(void *dummy)
837{
838 while (1)
839 {
840 struct hostent *rht;
841 struct s_auth *account;
842 struct sockaddr_in udp_sa;
843
844 for (account=cfg->account; account; account=account->next)
845 if (account->dyndns[0])
846 {
847 if (rht=gethostbyname((const char *)account->dyndns))
848 {
849 memcpy(&udp_sa.sin_addr, rht->h_addr, sizeof(udp_sa.sin_addr));
850 account->dynip=cs_inet_order(udp_sa.sin_addr.s_addr);
851 }
852 else
853 cs_log("can't resolve hostname %s (user: %s)", account->dyndns, account->usr);
854 client[cs_idx].last=time((time_t)0);
855 }
856 sleep(cfg->resolvedelay);
857 }
858}
859
860static void start_client_resolver()
861{
862 int i;
863 pthread_t tid;
864
865 if (i=pthread_create(&tid, (pthread_attr_t *)0, cs_client_resolve, (void *) 0))
866 cs_log("ERROR: can't create resolver-thread (err=%d)", i);
867 else
868 {
869 cs_log("resolver thread started");
870 pthread_detach(tid);
871 }
872}
873
874void cs_resolve()
875{
876 int i, idx;
877 struct hostent *rht;
878 struct s_auth *account;
879 for (i=0; i<CS_MAXREADER; i++)
880 if ((idx=reader[i].cs_idx) && (reader[i].typ & R_IS_NETWORK))
881 {
882 client[cs_idx].last=time((time_t)0);
883 if (rht=gethostbyname(reader[i].device))
884 {
885 memcpy(&client[idx].udp_sa.sin_addr, rht->h_addr,
886 sizeof(client[idx].udp_sa.sin_addr));
887 client[idx].ip=cs_inet_order(client[idx].udp_sa.sin_addr.s_addr);
888 }
889 else
890 cs_log("can't resolve %s", reader[i].device);
891 client[cs_idx].last=time((time_t)0);
892 }
893}
894
895#ifdef USE_PTHREAD
896static void *cs_logger(void *dummy)
897#else
898static void cs_logger(void)
899#endif
900{
901 *log_fd=client[cs_idx].fd_m2c;
902 while(1)
903 {
904 uchar *ptr;
905 //struct timeval tv;
906 fd_set fds;
907
908 FD_ZERO(&fds);
909 FD_SET(fd_m2c, &fds);
910 select(fd_m2c+1, &fds, 0, 0, 0);
911#ifndef USE_PTHREAD
912 if (master_pid!=getppid())
913 cs_exit(0);
914#endif
915 if (FD_ISSET(fd_m2c, &fds))
916 {
917 int n;
918// switch(n=read_from_pipe(fd_m2c, &ptr, 1))
919 n=read_from_pipe(fd_m2c, &ptr, 1);
920//if (n!=PIP_ID_NUL) printf("received %d bytes\n", n); fflush(stdout);
921 switch(n)
922 {
923 case PIP_ID_LOG:
924 cs_write_log(ptr);
925 break;
926 }
927 }
928 }
929}
930
931static void start_resolver()
932{
933 int i;
934#ifdef USE_PTHREAD
935 pthread_t tid;
936 if (i=pthread_create(&tid, (pthread_attr_t *)0, cs_logger, (void *) 0))
937 cs_log("ERROR: can't create logging-thread (err=%d)", i);
938 else
939 {
940 cs_log("logging thread started");
941 pthread_detach(tid);
942 }
943#endif
944 sleep(1); // wait for reader
945 while(1)
946 {
947 if (master_pid!=getppid())
948 cs_exit(0);
949 cs_resolve();
950 for (i=0; i<cfg->resolvedelay; i++)
951 if (master_pid!=getppid())
952 cs_exit(0);
953 else
954 sleep(1);
955// sleep(cfg->resolvedelay);
956 }
957}
958
959#ifdef CS_ANTICASC
960static void start_anticascader()
961{
962 int i;
963
964 use_ac_log=1;
965 set_signal_handler(SIGHUP, 1, ac_init_stat);
966
967 ac_init_stat(0);
968 while(1)
969 {
970 for( i=0; i<cfg->ac_stime*60; i++ )
971 if( master_pid!=getppid() )
972 cs_exit(0);
973 else
974 sleep(1);
975
976 if (master_pid!=getppid())
977 cs_exit(0);
978
979 ac_do_stat();
980 }
981}
982#endif
983
984static void init_cardreader()
985{
986 for (ridx=0; ridx<CS_MAXREADER; ridx++)
987 if (reader[ridx].device[0])
988 switch(cs_fork(0, 99))
989 {
990 case -1:
991 cs_exit(1);
992 case 0:
993 break;
994 default:
995 wait4master();
996 start_cardreader();
997 }
998}
999
1000static void init_service(int srv)
1001{
1002#ifdef USE_PTHREAD
1003 uchar dummy[1]={0x00};
1004#endif
1005
1006 switch(cs_fork(0, srv))
1007 {
1008 case -1:
1009 cs_exit(1);
1010 case 0:
1011 break;
1012 default:
1013 wait4master();
1014 switch(srv)
1015 {
1016#ifdef CS_ANTICASC
1017 case 96: start_anticascader();
1018#endif
1019#ifdef USE_PTHREAD
1020 case 97: cs_logger(dummy);
1021#else
1022 case 97: cs_logger();
1023#endif
1024 case 98: start_resolver();
1025 }
1026 }
1027}
1028
1029void wait4master()
1030{
1031 int i;
1032 for (i=0; (i<1000) && (client[cs_idx].pid!=getpid()); i++)
1033 usleep(1000L);
1034 if (client[cs_idx].pid!=getpid())
1035 {
1036 cs_log("PANIC: client not found in shared memory");
1037 cs_exit(1);
1038 }
1039 cs_debug("starting client %d with ip %s",
1040 cs_idx-cdiff, cs_inet_ntoa(client[cs_idx].ip));
1041}
1042
1043static void cs_fake_client(char *usr)
1044{
1045 int i;
1046 for (i=cdiff+1; i<CS_MAXPID; i++)
1047 if ((client[i].pid) && (client[i].typ=='c') &&
1048 (!client[i].dup) && (!strcmp(client[i].usr, usr)))
1049 {
1050 client[i].dup=1;
1051 client[i].au=(-1);
1052 cs_log("client %d duplicate user '%s', set to fake", i-cdiff, usr);
1053 }
1054}
1055
1056int cs_auth_client(struct s_auth *account, char *e_txt)
1057{
1058 int rc=0;
1059 char buf[16];
1060 char *t_crypt="encrypted";
1061 char *t_plain="plain";
1062 char *t_grant=" granted";
1063 char *t_reject=" rejected";
1064 char *t_msg[]= { buf, "invalid access", "invalid ip", "unknown reason" };
1065 client[cs_idx].grp=0xffffffff;
1066 client[cs_idx].au=(-1);
1067 switch((long)account)
1068 {
1069 case -2: // gbx-dummy
1070 client[cs_idx].dup=0;
1071 break;
1072 case 0: // reject access
1073 rc=1;
1074 cs_log("%s %s-client %s%s (%s)",
1075 client[cs_idx].crypted ? t_crypt : t_plain,
1076 ph[client[cs_idx].ctyp].desc,
1077 client[cs_idx].ip ? cs_inet_ntoa(client[cs_idx].ip) : "",
1078 client[cs_idx].ip ? t_reject : t_reject+1,
1079 e_txt ? e_txt : t_msg[rc]);
1080 break;
1081 default: // grant/check access
1082 if (client[cs_idx].ip && account->dyndns[0])
1083 if (client[cs_idx].ip != account->dynip)
1084 rc=2;
1085 if (!rc)
1086 {
1087 client[cs_idx].dup=0;
1088 if (client[cs_idx].typ=='c')
1089 {
1090 client[cs_idx].grp=account->grp;
1091 client[cs_idx].au=account->au;
1092 client[cs_idx].tosleep=(60*account->tosleep);
1093 memcpy(&client[cs_idx].ctab, &account->ctab, sizeof(client[cs_idx].ctab));
1094 if (account->uniq)
1095 cs_fake_client(account->usr);
1096 client[cs_idx].ftab = account->ftab; // IDENT filter
1097 client[cs_idx].cltab = account->cltab; // CLASS filter
1098 client[cs_idx].fchid = account->fchid; // CHID filter
1099 client[cs_idx].sidtabok= account->sidtabok; // services
1100 client[cs_idx].sidtabno= account->sidtabno; // services
1101 client[cs_idx].pcrc = crc32(0L, MD5((uchar *)account->pwd, strlen(account->pwd), NULL), 16);
1102 memcpy(&client[cs_idx].ttab, &account->ttab, sizeof(client[cs_idx].ttab));
1103#ifdef CS_ANTICASC
1104 ac_init_client(account);
1105#endif
1106 }
1107 }
1108 client[cs_idx].monlvl=account->monlvl;
1109 strcpy(client[cs_idx].usr, account->usr);
1110 case -1: // anonymous grant access
1111 if (rc)
1112 t_grant=t_reject;
1113 else
1114 {
1115 if (client[cs_idx].typ=='m')
1116 sprintf(t_msg[0], "lvl=%d", client[cs_idx].monlvl);
1117 else
1118 sprintf(t_msg[0], "au=%d", client[cs_idx].au+1);
1119 }
1120 cs_log("%s %s-client %s%s (%s, %s)",
1121 client[cs_idx].crypted ? t_crypt : t_plain,
1122 e_txt ? e_txt : ph[client[cs_idx].ctyp].desc,
1123 client[cs_idx].ip ? cs_inet_ntoa(client[cs_idx].ip) : "",
1124 client[cs_idx].ip ? t_grant : t_grant+1,
1125 username(cs_idx), t_msg[rc]);
1126 break;
1127 }
1128 return(rc);
1129}
1130
1131void cs_disconnect_client(void)
1132{
1133 char buf[32]={0};
1134 if (client[cs_idx].ip)
1135 sprintf(buf, " from %s", cs_inet_ntoa(client[cs_idx].ip));
1136 cs_log("%s disconnected%s", username(cs_idx), buf);
1137 cs_exit(0);
1138}
1139
1140int check_ecmcache(ECM_REQUEST *er, ulong grp)
1141{
1142 int i;
1143// cs_ddump(ecmd5, CS_ECMSTORESIZE, "ECM search");
1144//cs_log("cache CHECK: grp=%lX", grp);
1145 for(i=0; i<CS_ECMCACHESIZE; i++)
1146 if ((grp & ecmcache[i].grp) &&
1147 (!memcmp(ecmcache[i].ecmd5, er->ecmd5, CS_ECMSTORESIZE)))
1148 {
1149//cs_log("cache found: grp=%lX cgrp=%lX", grp, ecmcache[i].grp);
1150 memcpy(er->cw, ecmcache[i].cw, 16);
1151 return(1);
1152 }
1153 return(0);
1154}
1155
1156static void store_ecm(ECM_REQUEST *er)
1157{
1158//cs_log("store ecm from reader %d", er->reader[0]);
1159 memcpy(ecmcache[*ecmidx].ecmd5, er->ecmd5, CS_ECMSTORESIZE);
1160 memcpy(ecmcache[*ecmidx].cw, er->cw, 16);
1161 ecmcache[*ecmidx].caid=er->caid;
1162 ecmcache[*ecmidx].prid=er->prid;
1163 ecmcache[*ecmidx].grp =reader[er->reader[0]].grp;
1164// cs_ddump(ecmcache[*ecmidx].ecmd5, CS_ECMSTORESIZE, "ECM stored (idx=%d)", *ecmidx);
1165 *ecmidx=(*ecmidx+1) % CS_ECMCACHESIZE;
1166}
1167
1168void store_logentry(char *txt)
1169{
1170#ifdef CS_LOGHISTORY
1171 char *ptr;
1172 ptr=(char *)(loghist+(*loghistidx*CS_LOGHISTSIZE));
1173 ptr[0]='\1'; // make username unusable
1174 ptr[1]='\0';
1175 if ((client[cs_idx].typ=='c') || (client[cs_idx].typ=='m'))
1176 strncpy(ptr, client[cs_idx].usr, 31);
1177 strncpy(ptr+32, txt, CS_LOGHISTSIZE-33);
1178 *loghistidx=(*loghistidx+1) % CS_MAXLOGHIST;
1179#endif
1180}
1181
1182/*
1183 * write_to_pipe():
1184 * write all kind of data to pipe specified by fd
1185 */
1186int write_to_pipe(int fd, int id, uchar *data, int n)
1187{
1188 uchar buf[1024+3+sizeof(int)];
1189
1190//printf("WRITE_START pid=%d", getpid()); fflush(stdout);
1191 if ((id<0) || (id>PIP_ID_MAX))
1192 return(PIP_ID_ERR);
1193 memcpy(buf, PIP_ID_TXT[id], 3);
1194 memcpy(buf+3, &n, sizeof(int));
1195 memcpy(buf+3+sizeof(int), data, n);
1196 n+=3+sizeof(int);
1197//n=write(fd, buf, n);
1198//printf("WRITE_END pid=%d", getpid()); fflush(stdout);
1199//return(n);
1200 if( !fd )
1201 cs_log("write_to_pipe: fd==0");
1202 return(write(fd, buf, n));
1203}
1204
1205/*
1206 * read_from_pipe():
1207 * read all kind of data from pipe specified by fd
1208 * special-flag redir: if set AND data is ECM: this will redirected to appr. client
1209 */
1210int read_from_pipe(int fd, uchar **data, int redir)
1211{
1212 int rc;
1213 static int hdr=0;
1214 static uchar buf[1024+1+3+sizeof(int)];
1215
1216 *data=(uchar *)0;
1217 rc=PIP_ID_NUL;
1218
1219 if (!hdr)
1220 {
1221 if (bytes_available(fd))
1222 {
1223 if (read(fd, buf, 3+sizeof(int))==3+sizeof(int))
1224 memcpy(&hdr, buf+3, sizeof(int));
1225 else
1226 cs_log("WARNING: pipe header to small !");
1227 }
1228 }
1229 if (hdr)
1230 {
1231 int l;
1232 for (l=0; (rc<0) && (PIP_ID_TXT[l]); l++)
1233 if (!memcmp(buf, PIP_ID_TXT[l], 3))
1234 rc=l;
1235
1236 if (rc<0)
1237 {
1238 fprintf(stderr, "WARNING: pipe garbage");
1239 fflush(stderr);
1240 cs_log("WARNING: pipe garbage");
1241 rc=PIP_ID_ERR;
1242 }
1243 else
1244 {
1245 l=hdr;
1246 if ((l+3-1+sizeof(int))>sizeof(buf))
1247 {
1248 cs_log("WARNING: packet size (%d) to large", l);
1249 l=sizeof(buf)+3-1+sizeof(int);
1250 }
1251 if (!bytes_available(fd))
1252 return(PIP_ID_NUL);
1253 hdr=0;
1254 if (read(fd, buf+3+sizeof(int), l)==l)
1255 *data=buf+3+sizeof(int);
1256 else
1257 {
1258 cs_log("WARNING: pipe data to small !");
1259 return(PIP_ID_ERR);
1260 }
1261 buf[l+3+sizeof(int)]=0;
1262 if ((redir) && (rc==PIP_ID_ECM))
1263 {
1264 //int idx;
1265 ECM_REQUEST *er;
1266 er=(ECM_REQUEST *)(buf+3+sizeof(int));
1267 if( er->cidx && client[er->cidx].fd_m2c )
1268 if (!write(client[er->cidx].fd_m2c, buf, l+3+sizeof(int))) cs_exit(1);
1269 rc=PIP_ID_DIR;
1270 }
1271 }
1272 }
1273 return(rc);
1274}
1275
1276/*
1277 * write_ecm_request():
1278 */
1279int write_ecm_request(int fd, ECM_REQUEST *er)
1280{
1281 return(write_to_pipe(fd, PIP_ID_ECM, (uchar *) er, sizeof(ECM_REQUEST)));
1282}
1283
1284int write_ecm_DCW(int fd, ECM_REQUEST *er)
1285{
1286 return(write_to_pipe(fd, PIP_ID_DCW, (uchar *) er, sizeof(ECM_REQUEST)));
1287}
1288
1289int write_ecm_answer(int fd, ECM_REQUEST *er)
1290{
1291 int i, f;
1292 uchar c;
1293 for (i=f=0; i<16; i+=4)
1294 {
1295 c=((er->cw[i]+er->cw[i+1]+er->cw[i+2]) & 0xff);
1296 if (er->cw[i+3]!=c)
1297 {
1298 f=1;
1299 er->cw[i+3]=c;
1300 }
1301 }
1302 if (f)
1303 cs_debug("notice: changed dcw checksum bytes");
1304
1305 er->reader[0]=ridx;
1306//cs_log("answer from reader %d (rc=%d)", er->reader[0], er->rc);
1307 er->caid=er->ocaid;
1308 if (er->rc==1||(er->gbxRidx&&er->rc==0)){
1309 store_ecm(er);
1310 }
1311
1312 return(write_ecm_request(fd, er));
1313}
1314
1315static int cs_read_timer(int fd, uchar *buf, int l, int msec)
1316{
1317 struct timeval tv;
1318 fd_set fds;
1319 int rc;
1320
1321 if (!fd) return(-1);
1322 tv.tv_sec = msec / 1000;
1323 tv.tv_usec = (msec % 1000) * 1000;
1324 FD_ZERO(&fds);
1325 FD_SET(pfd, &fds);
1326
1327 select(fd+1, &fds, 0, 0, &tv);
1328
1329 rc=0;
1330 if (FD_ISSET(pfd, &fds))
1331 if (!(rc=read(fd, buf, l)))
1332 rc=-1;
1333
1334 return(rc);
1335}
1336
1337ECM_REQUEST *get_ecmtask()
1338{
1339 int i, n;
1340 ECM_REQUEST *er=0;
1341
1342 if (!ecmtask)
1343 {
1344 n=(ph[client[cs_idx].ctyp].multi)?CS_MAXPENDING:1;
1345 if( (ecmtask=(ECM_REQUEST *)malloc(n*sizeof(ECM_REQUEST))) )
1346 memset(ecmtask, 0, n*sizeof(ECM_REQUEST));
1347 }
1348
1349 n=(-1);
1350 if (!ecmtask)
1351 {
1352 cs_log("Cannot allocate memory (errno=%d)", errno);
1353 n=(-2);
1354 }
1355 else
1356 if (ph[client[cs_idx].ctyp].multi)
1357 {
1358 for (i=0; (n<0) && (i<CS_MAXPENDING); i++)
1359 if (ecmtask[i].rc<100)
1360 er=&ecmtask[n=i];
1361 }
1362 else
1363 er=&ecmtask[n=0];
1364
1365 if (n<0)
1366 cs_log("WARNING: ecm pending table overflow !");
1367 else
1368 {
1369 memset(er, 0, sizeof(ECM_REQUEST));
1370 er->rc=100;
1371 er->cpti=n;
1372 er->cidx=cs_idx;
1373 cs_ftime(&er->tps);
1374 }
1375 return(er);
1376}
1377
1378int send_dcw(ECM_REQUEST *er)
1379{
1380 static char *stxt[]={"found", "cache1", "cache2", "emu",
1381 "not found", "timeout", "sleeping",
1382 "fake", "invalid", "corrupt"};
1383 static char *stxtEx[]={"", "group", "caid", "ident", "class", "chid", "queue"};
1384 static char *stxtWh[]={"", "user ", "reader ", "server ", "lserver "};
1385 char sby[32]="";
1386 char erEx[32]="";
1387 char uname[38]="";
1388 struct timeb tpe;
1389 ushort lc, *lp;
1390 for (lp=(ushort *)er->ecm+(er->l>>2), lc=0; lp>=(ushort *)er->ecm; lp--)
1391 lc^=*lp;
1392 cs_ftime(&tpe);
1393 if(er->gbxFrom)
1394 snprintf(uname,sizeof(uname)-1, "%s(%04X)", username(cs_idx), er->gbxFrom);
1395 else
1396 snprintf(uname,sizeof(uname)-1, "%s", username(cs_idx));
1397 if (er->rc==0)
1398 {
1399 if(reader[er->reader[0]].typ==R_GBOX)
1400 snprintf(sby, sizeof(sby)-1, " by %s(%04X)", reader[er->reader[0]].label,er->gbxCWFrom);
1401 else
1402 snprintf(sby, sizeof(sby)-1, " by %s", reader[er->reader[0]].label);
1403 }
1404 if (er->rc<4) er->rcEx=0;
1405 if (er->rcEx)
1406 snprintf(erEx, sizeof(erEx)-1, "rejected %s%s", stxtWh[er->rcEx>>4],
1407 stxtEx[er->rcEx&0xf]);
1408 cs_log("%s (%04X&%06X/%04X/%02X:%04X): %s (%d ms)%s",
1409 uname, er->caid, er->prid, er->srvid, er->l, lc,
1410 er->rcEx?erEx:stxt[er->rc],
1411 1000*(tpe.time-er->tps.time)+tpe.millitm-er->tps.millitm, sby);
1412 er->caid=er->ocaid;
1413 switch(er->rc)
1414 {
1415 case 2:
1416 case 1: client[cs_idx].cwcache++;
1417 case 3:
1418 case 0: client[cs_idx].cwfound++; break;
1419 default: client[cs_idx].cwnot++;
1420 if (er->rc>5)
1421 client[cs_idx].cwcache++;
1422 }
1423#ifdef CS_ANTICASC
1424 ac_chk(er, 1);
1425#endif
1426
1427 if( cfg->show_ecm_dw && !client[cs_idx].dbglvl )
1428 cs_dump(er->cw, 16, 0);
1429 if (er->rc==7) er->rc=0;
1430 ph[client[cs_idx].ctyp].send_dcw(er);
1431 return 0;
1432}
1433
1434static void chk_dcw(int fd)
1435{
1436 ECM_REQUEST *er, *ert;
1437 if (read_from_pipe(fd, (uchar **)&er, 0)!=PIP_ID_ECM)
1438 return;
1439 //cs_log("dcw check from reader %d for idx %d (rc=%d)", er->reader[0], er->cpti, er->rc);
1440 ert=&ecmtask[er->cpti];
1441 if (ert->rc<100)
1442 return; // already done
1443 if( (er->caid!=ert->caid) || memcmp(er->ecm , ert->ecm , sizeof(er->ecm)) )
1444 return; // obsolete
1445 ert->rcEx=er->rcEx;
1446 if (er->rc>0) // found
1447 {
1448 ert->rc=(er->rc==2)?2:0;
1449 ert->rcEx=0;
1450 ert->reader[0]=er->reader[0];
1451 memcpy(ert->cw , er->cw , sizeof(er->cw));
1452 ert->gbxCWFrom=er->gbxCWFrom;
1453 }
1454 else // not found (from ONE of the readers !)
1455 {
1456 int i;
1457 ert->reader[er->reader[0]]=0;
1458 for (i=0; (ert) && (i<CS_MAXREADER); i++)
1459 if (ert->reader[i]) // we have still another chance
1460 ert=(ECM_REQUEST *)0;
1461 if (ert) ert->rc=4;
1462 }
1463 if (ert) send_dcw(ert);
1464 return;
1465}
1466
1467ulong chk_provid(uchar *ecm, ushort caid)
1468{
1469 int i;
1470 ulong provid=0;
1471 switch(caid)
1472 {
1473 case 0x100: // seca
1474 provid=b2i(2, ecm+3);
1475 break;
1476 case 0x500: // viaccess
1477 i=(ecm[4]==0xD2) ? 3 : 0; // tpsflag -> offset+3
1478 if ((ecm[5+i]==3) && ((ecm[4+i]==0x90) || (ecm[4+i]==0x40)))
1479 provid=(b2i(3, ecm+6+i) & 0xFFFFF0);
1480 default:
1481 // cryptoworks ?
1482 if( caid&0x0d00 && ecm[8]==0x83 && ecm[9]==1 )
1483 provid=(ulong)ecm[10];
1484 }
1485 return(provid);
1486}
1487
1488/*
1489void guess_irdeto(ECM_REQUEST *er)
1490{
1491 uchar b3;
1492 int b47;
1493 //ushort chid;
1494 struct s_irdeto_quess *ptr;
1495
1496 b3 = er->ecm[3];
1497 ptr = cfg->itab[b3];
1498 if( !ptr ) {
1499 cs_debug("unknown irdeto byte 3: %02X", b3);
1500 return;
1501 }
1502 b47 = b2i(4, er->ecm+4);
1503 //chid = b2i(2, er->ecm+6);
1504 //cs_debug("ecm: b47=%08X, ptr->b47=%08X, ptr->caid=%04X", b47, ptr->b47, ptr->caid);
1505 while( ptr )
1506 {
1507 if( b47==ptr->b47 )
1508 {
1509 if( er->srvid && (er->srvid!=ptr->sid) )
1510 {
1511 cs_debug("sid mismatched (ecm: %04X, guess: %04X), wrong oscam.ird file?",
1512 er->srvid, ptr->sid);
1513 return;
1514 }
1515 er->caid=ptr->caid;
1516 er->srvid=ptr->sid;
1517 er->chid=(ushort)ptr->b47;
1518// cs_debug("quess_irdeto() found caid=%04X, sid=%04X, chid=%04X",
1519// er->caid, er->srvid, er->chid);
1520 return;
1521 }
1522 ptr=ptr->next;
1523 }
1524}
1525*/
1526
1527void guess_cardsystem(ECM_REQUEST *er)
1528{
1529 ushort last_hope=0;
1530
1531 // viaccess - check by provid-search
1532 if( (er->prid=chk_provid(er->ecm, 0x500)) )
1533 er->caid=0x500;
1534
1535 // nagra
1536 // is ecm[1] always 0x30 ?
1537 // is ecm[3] always 0x07 ?
1538 if ((er->ecm[6]==1) && (er->ecm[4]==er->ecm[2]-2))
1539 er->caid=0x1801;
1540
1541 // seca2 - very poor
1542 if ((er->ecm[8]==0x10) && ((er->ecm[9]&0xF1)==1))
1543 last_hope=0x100;
1544
1545 // is cryptoworks, but which caid ?
1546 if ((er->ecm[3]==0x81) && (er->ecm[4]==0xFF) &&
1547 (!er->ecm[5]) && (!er->ecm[6]) && (er->ecm[7]==er->ecm[2]-5))
1548 last_hope=0xd00;
1549
1550/*
1551 if (!er->caid && er->ecm[2]==0x31 && er->ecm[0x0b]==0x28)
1552 guess_irdeto(er);
1553*/
1554
1555 if (!er->caid) // guess by len ..
1556 er->caid=len4caid[er->ecm[2]+3];
1557
1558 if (!er->caid)
1559 er->caid=last_hope;
1560}
1561
1562void request_cw(ECM_REQUEST *er, int flag)
1563{
1564 int i;
1565 er->level=flag;
1566 flag=(flag)?3:1; // flag specifies with/without fallback-readers
1567 for (i=0; i<CS_MAXREADER; i++)
1568 if (er->reader[i]&flag)
1569 write_ecm_request(reader[i].fd, er);
1570}
1571
1572void get_cw(ECM_REQUEST *er)
1573{
1574 int i, j, m, rejected;
1575 //uchar orig_caid[sizeof(er->caid)];
1576 time_t now;
1577//test the guessing ...
1578//cs_log("caid should be %04X, provid %06X", er->caid, er->prid);
1579//er->caid=0;
1580
1581 client[cs_idx].lastecm=time((time_t)0);
1582
1583 if (!er->caid)
1584 guess_cardsystem(er);
1585
1586 if( (er->caid & 0xFF00)==0x600 && !er->chid )
1587 er->chid = (er->ecm[6]<<8)|er->ecm[7];
1588
1589 if (!er->prid)
1590 er->prid=chk_provid(er->ecm, er->caid);
1591
1592// quickfix for 0100:000065
1593 if (er->caid == 0x100 && er->prid == 0x65 && er->srvid == 0)
1594 er->srvid = 0x0642;
1595
1596 if( (!er->prid) && client[cs_idx].ncd_server )
1597 {
1598 int pi = client[cs_idx].port_idx;
1599 if( pi>=0 && cfg->ncd_ptab.nports && cfg->ncd_ptab.nports >= pi )
1600 er->prid = cfg->ncd_ptab.ports[pi].ftab.filts[0].prids[0];
1601 }
1602
1603//cs_log("caid IS NOW .. %04X, provid %06X", er->caid, er->prid);
1604
1605 rejected=0;
1606 if (er->rc>99) // rc<100 -> ecm error
1607 {
1608 now=time((time_t *) 0);
1609 m=er->caid;
1610 er->ocaid=er->caid;
1611
1612 i=er->srvid;
1613 if ((i!=client[cs_idx].last_srvid) || (!client[cs_idx].lastswitch))
1614 client[cs_idx].lastswitch=now;
1615 if ((client[cs_idx].tosleep) &&
1616 (now-client[cs_idx].lastswitch>client[cs_idx].tosleep))
1617 er->rc=6; // sleeping
1618 client[cs_idx].last_srvid=i;
1619 client[cs_idx].last_caid=m;
1620
1621 for (j=0; (j<6) && (er->rc>99); j++)
1622 switch(j)
1623 {
1624 case 0: if (client[cs_idx].dup)
1625 er->rc=7; // fake
1626 break;
1627 case 1: if (!chk_bcaid(er, &client[cs_idx].ctab))
1628 {
1629// cs_log("chk_bcaid failed");
1630 er->rc=8; // invalid
1631 er->rcEx=E2_CAID;
1632 }
1633 break;
1634 case 2: if (!chk_srvid(er, cs_idx))
1635 er->rc=8;
1636 break;
1637 case 3: if (!chk_ufilters(er))
1638 er->rc=8;
1639 break;
1640 case 4: if (!chk_sfilter(er, ph[client[cs_idx].ctyp].ptab))
1641 er->rc=8;
1642 break;
1643 case 5: if( (i=er->l-(er->ecm[2]+3)) )
1644 {
1645 if (i>0)
1646 {
1647 cs_debug("warning: ecm size adjusted from 0x%X to 0x%X",
1648 er->l, er->ecm[2]+3);
1649 er->l=(er->ecm[2]+3);
1650 }
1651 else
1652 er->rc=9; // corrupt
1653 }
1654 break;
1655 }
1656
1657 if (&client[cs_idx].ttab) // Betatunneling
1658 // moved behind the check routines, because newcamd-ECM will fail if ecm is converted before
1659 {
1660 int n;
1661 ulong mask_all=0xFFFF;
1662 TUNTAB *ttab;
1663 ttab=&client[cs_idx].ttab;
1664 for (n=0; (n<CS_MAXCAIDTAB); n++)
1665 if ((er->caid==ttab->bt_caidfrom[n]) && ((er->srvid==ttab->bt_srvid[n]) || (ttab->bt_srvid[n])==mask_all))
1666 {
1667 int l;
1668 char hack_n3[13]={0x70, 0x51, 0xc7, 0x00, 0x00, 0x00, 0x01, 0x10, 0x10, 0x00, 0x87, 0x12, 0x07};
1669 char hack_n2[13]={0x70, 0x51, 0xc9, 0x00, 0x00, 0x00, 0x01, 0x10, 0x10, 0x00, 0x48, 0x12, 0x07};
1670 er->caid=ttab->bt_caidto[n];
1671 er->prid=0;
1672 er->l=(er->ecm[2]+3);
1673 memmove(er->ecm+14, er->ecm+4, er->l-1);
1674 if (er->l > 0x88)
1675 {
1676 memcpy(er->ecm+1, hack_n3, 13);
1677 if (er->ecm[0]==0x81) er->ecm[12]+= 1;
1678 }
1679 else memcpy(er->ecm+1, hack_n2, 13);
1680 er->l+=10;
1681 er->ecm[2]=er->l-3;
1682 cs_debug("ecm converted from: 0x%X to betacrypt: 0x%X for service id:0x%X",
1683 ttab->bt_caidfrom[n], ttab->bt_caidto[n], ttab->bt_srvid[n]);
1684 }
1685 }
1686
1687 memcpy(er->ecmd5, MD5(er->ecm, er->l, NULL), CS_ECMSTORESIZE);
1688
1689 if (check_ecmcache(er, client[cs_idx].grp))
1690 er->rc=1; // cache1
1691
1692#ifdef CS_ANTICASC
1693 ac_chk(er, 0);
1694#endif
1695 if( er->rc<100 && er->rc!=1 )
1696 rejected=1;
1697 }
1698
1699 if( !rejected && er->rc!=1 )
1700 {
1701 for (i=m=0; i<CS_MAXREADER; i++)
1702 if (matching_reader(er, &reader[i])&&(i!=ridx))
1703 m|=er->reader[i]=(reader[i].fallback)?2:1;
1704
1705 switch(m)
1706 {
1707 case 0: er->rc=4; // no reader -> not found
1708 if (!er->rcEx) er->rcEx=E2_GROUP;
1709 break;
1710 case 2: for (i=0; i<CS_MAXREADER; i++) // fallbacks only, switch them.
1711 er->reader[i]>>=1;
1712 }
1713 }
1714 if (er->rc<100)
1715 {
1716 if (cfg->delay) usleep(cfg->delay);
1717 send_dcw(er);
1718 return;
1719 }
1720
1721 er->rcEx=0;
1722 request_cw(er, 0);
1723}
1724
1725void log_emm_request(int auidx)
1726{
1727// cs_log("%s send emm-request (reader=%s, caid=%04X)",
1728// cs_inet_ntoa(client[cs_idx].ip), reader[auidx].label, reader[auidx].caid[0]);
1729 cs_log("%s emm-request sent (reader=%s, caid=%04X)",
1730 username(cs_idx), reader[auidx].label, reader[auidx].caid[0]);
1731}
1732
1733void do_emm(EMM_PACKET *ep)
1734{
1735 int au;//, ephs;
1736 au=client[cs_idx].au;
1737
1738 if ((au<0) || (au>=CS_MAXREADER))
1739 return;
1740 client[cs_idx].lastemm=time((time_t)0);
1741 cs_ddump(reader[au].hexserial, 8, "reader serial:");
1742 cs_ddump(ep->hexserial, 8, "emm SA:");
1743// if ((!reader[au].fd) || (reader[au].b_nano[ep->emm[3]])) // blocknano is obsolete
1744 if ((!reader[au].fd) || // reader has no fd
1745 (reader[au].caid[0]!=b2i(2,ep->caid)) || // wrong caid
1746 (memcmp(reader[au].hexserial, ep->hexserial, 8))) // wrong serial
1747 return;
1748
1749 ep->cidx=cs_idx;
1750 write_to_pipe(reader[au].fd, PIP_ID_EMM, (uchar *) ep, sizeof(EMM_PACKET));
1751}
1752
1753static int comp_timeb(struct timeb *tpa, struct timeb *tpb)
1754{
1755 if (tpa->time>tpb->time) return(1);
1756 if (tpa->time<tpb->time) return(-1);
1757 if (tpa->millitm>tpb->millitm) return(1);
1758 if (tpa->millitm<tpb->millitm) return(-1);
1759 return(0);
1760}
1761
1762static void build_delay(struct timeb *tpe, struct timeb *tpc)
1763{
1764 if (comp_timeb(tpe, tpc)>0)
1765 {
1766 tpe->time=tpc->time;
1767 tpe->millitm=tpc->millitm;
1768 }
1769}
1770
1771struct timeval *chk_pending(struct timeb tp_ctimeout)
1772{
1773 int i;
1774 ulong td;
1775 struct timeb tpn, tpe, tpc; // <n>ow, <e>nd, <c>heck
1776 static struct timeval tv;
1777
1778 ECM_REQUEST *er;
1779 cs_ftime(&tpn);
1780 tpe=tp_ctimeout; // latest delay -> disconnect
1781
1782 if (ecmtask)
1783 i=(ph[client[cs_idx].ctyp].multi)?CS_MAXPENDING:1;
1784 else
1785 i=0;
1786//cs_log("num pend=%d", i);
1787 for (--i; i>=0; i--)
1788 if (ecmtask[i].rc>=100) // check all pending ecm-requests
1789 {
1790 int act, j;
1791 er=&ecmtask[i];
1792 tpc=er->tps;
1793 tpc.time+=(er->stage) ? cfg->ctimeout : cfg->ftimeout;
1794 if (!er->stage)
1795 {
1796 for (j=0, act=1; (act) && (j<CS_MAXREADER); j++)
1797 if (er->reader[j]&1)
1798 act=0;
1799//cs_log("stage 0, act=%d r0=%d, r1=%d, r2=%d, r3=%d, r4=%d r5=%d", act,
1800// er->reader[0], er->reader[1], er->reader[2],
1801// er->reader[3], er->reader[4], er->reader[5]);
1802 if (act)
1803 {
1804 er->stage++;
1805 request_cw(er, er->stage);
1806 tpc.time+=cfg->ctimeout-cfg->ftimeout;
1807 }
1808 }
1809 if (comp_timeb(&tpn, &tpc)>0) // action needed
1810 {
1811//cs_log("Action now %d.%03d", tpn.time, tpn.millitm);
1812//cs_log(" %d.%03d", tpc.time, tpc.millitm);
1813 if (er->stage)
1814 {
1815 er->rc=5; // timeout
1816 send_dcw(er);
1817 continue;
1818 }
1819 else
1820 {
1821 er->stage++;
1822 request_cw(er, er->stage);
1823 tpc.time+=cfg->ctimeout-cfg->ftimeout;
1824 }
1825 }
1826 build_delay(&tpe, &tpc);
1827 }
1828 td=(tpe.time-tpn.time)*1000+(tpe.millitm-tpn.millitm)+5;
1829 tv.tv_sec = td/1000;
1830 tv.tv_usec = (td%1000)*1000;
1831//cs_log("delay %d.%06d", tv.tv_sec, tv.tv_usec);
1832 return(&tv);
1833}
1834
1835int process_input(uchar *buf, int l, int timeout)
1836{
1837 int rc;
1838 fd_set fds;
1839 struct timeb tp;
1840
1841 if (master_pid!=getppid()) cs_exit(0);
1842 if (!pfd) return(-1);
1843 cs_ftime(&tp);
1844 tp.time+=timeout;
1845 if (ph[client[cs_idx].ctyp].watchdog)
1846 alarm(cfg->cmaxidle+2);
1847 while (1)
1848 {
1849 FD_ZERO(&fds);
1850 FD_SET(pfd, &fds);
1851 FD_SET(fd_m2c, &fds);
1852
1853 rc=select(((pfd>fd_m2c)?pfd:fd_m2c)+1, &fds, 0, 0, chk_pending(tp));
1854 if (master_pid!=getppid()) cs_exit(0);
1855 if (rc<0)
1856 {
1857 if (errno==EINTR) continue;
1858 else return(0);
1859 }
1860
1861 if (FD_ISSET(fd_m2c, &fds)) // read from pipe
1862 chk_dcw(fd_m2c);
1863
1864 if (FD_ISSET(pfd, &fds)) // read from client
1865 {
1866 rc=ph[client[cs_idx].ctyp].recv(buf, l);
1867 break;
1868 }
1869 if (tp.time<=time((time_t *)0)) // client maxidle reached
1870 {
1871 rc=(-9);
1872 break;
1873 }
1874 }
1875 if (ph[client[cs_idx].ctyp].watchdog)
1876 alarm(cfg->cmaxidle+2);
1877 return(rc);
1878}
1879
1880static void process_master_pipe()
1881{
1882 int n;
1883 uchar *ptr;
1884
1885 switch(n=read_from_pipe(mfdr, &ptr, 1))
1886 {
1887 case PIP_ID_LOG:
1888 cs_write_log(ptr);
1889 break;
1890 case PIP_ID_HUP:
1891 cs_accounts_chk();
1892 break;
1893 }
1894}
1895
1896void cs_log_config()
1897{
1898 uchar buf[2048];
1899
1900 if (cfg->nice!=99)
1901 sprintf((char *)buf, ", nice=%d", cfg->nice);
1902 else
1903 buf[0]='\0';
1904 cs_log("version=%s, system=%s%s", CS_VERSION_X, cs_platform((char *)buf+64), buf);
1905 cs_log("max. clients=%d, client max. idle=%d sec",
1906#ifdef CS_ANTICASC
1907 CS_MAXPID-3, cfg->cmaxidle);
1908#else
1909 CS_MAXPID-2, cfg->cmaxidle);
1910#endif
1911 if( cfg->max_log_size )
1912 sprintf((char *)buf, "%d Kb", cfg->max_log_size);
1913 else
1914 strcpy((char *)buf, "unlimited");
1915 cs_log("max. logsize=%s", buf);
1916 cs_log("client timeout=%d sec, cache delay=%d msec",
1917 cfg->ctimeout, cfg->delay);
1918#ifdef CS_NOSHM
1919 cs_log("shared memory initialized (size=%d, fd=%d)", shmsize, shmid);
1920#else
1921 cs_log("shared memory initialized (size=%d, id=%d)", shmsize, shmid);
1922#endif
1923}
1924
1925int main (int argc, char *argv[])
1926{
1927 struct sockaddr_in cad; /* structure to hold client's address */
1928 int scad; /* length of address */
1929 //int fd; /* socket descriptors */
1930 int i, j, n;
1931 int bg=0;
1932 int gfd; //nph,
1933 int fdp[2];
1934 uchar buf[2048];
1935 void (*mod_def[])(struct s_module *)=
1936 {
1937 module_monitor,
1938 module_camd33,
1939 module_camd35,
1940 module_camd35_tcp,
1941 module_newcamd,
1942#ifdef CS_WITH_GBOX
1943 module_gbox,
1944#endif
1945 module_radegast,
1946 module_oscam_ser,
1947 0
1948 };
1949
1950 while ((i=getopt(argc, argv, "bc:d:hm:"))!=EOF)
1951 {
1952 switch(i)
1953 {
1954 case 'b': bg=1;
1955 break;
1956 case 'c': strncpy(cs_confdir, optarg, sizeof(cs_confdir)-1);
1957 break;
1958 case 'd': cs_dblevel=atoi(optarg);
1959 break;
1960 case 'm':
1961#ifdef CS_NOSHM
1962 strncpy(cs_memfile, optarg, sizeof(cs_memfile)-1);
1963 break;
1964#endif
1965 case 'h':
1966 default : usage();
1967 }
1968 }
1969 if (cs_confdir[strlen(cs_confdir)]!='/') strcat(cs_confdir, "/");
1970 init_shm();
1971 init_config();
1972 for (i=0; mod_def[i]; i++) // must be later BEFORE init_config()
1973 {
1974 memset(&ph[i], 0, sizeof(struct s_module));
1975 mod_def[i](&ph[i]);
1976 }
1977
1978 cs_log("auth size=%d", sizeof(struct s_auth));
1979 //cs_log_config();
1980 cfg->delay*=1000;
1981 init_sidtab();
1982 init_readerdb();
1983 init_userdb();
1984 init_signal();
1985 cs_set_mloc(30, "init");
1986 init_srvid();
1987 init_len4caid();
1988 //init_irdeto_guess_tab();
1989 cs_init_statistics(cfg->usrfile);
1990
1991 if (pipe(fdp))
1992 {
1993 cs_log("Cannot create pipe (errno=%d)", errno);
1994 cs_exit(1);
1995 }
1996 mfdr=fdp[0];
1997 fd_c2m=fdp[1];
1998 gfd=mfdr+1;
1999
2000#ifdef OS_MACOSX
2001 if (bg && daemon_compat(1,0))
2002#else
2003 if (bg && daemon(1,0))
2004#endif
2005 {
2006 cs_log("Error starting in background (errno=%d)", errno);
2007 cs_exit(1);
2008 }
2009 master_pid=client[0].pid=getpid();
2010 if (cfg->pidfile[0])
2011 {
2012 FILE *fp;
2013 if (!(fp=fopen(cfg->pidfile, "w")))
2014 {
2015 cs_log("Cannot open pid-file (errno=%d)", errno);
2016 cs_exit(1);
2017 }
2018 fprintf(fp, "%d\n", getpid());
2019 fclose(fp);
2020 }
2021
2022 for (i=0; i<CS_MAX_MOD; i++)
2023 if( (ph[i].type & MOD_CONN_NET) && ph[i].ptab )
2024 for(j=0; j<ph[i].ptab->nports; j++)
2025 {
2026 start_listener(&ph[i], j);
2027 if( ph[i].ptab->ports[j].fd+1>gfd )
2028 gfd=ph[i].ptab->ports[j].fd+1;
2029 }
2030
2031 start_client_resolver();
2032 init_service(97); // logger
2033 init_service(98); // resolver
2034 init_cardreader();
2035#ifdef CS_ANTICASC
2036 if( !cfg->ac_enabled )
2037 cs_log("anti cascading disabled");
2038 else
2039 {
2040 init_ac();
2041 init_service(96);
2042 }
2043#endif
2044
2045 for (i=0; i<CS_MAX_MOD; i++)
2046 if (ph[i].type & MOD_CONN_SERIAL) // for now: oscam_ser only
2047 if (ph[i].s_handler)
2048 ph[i].s_handler(i);
2049
2050 cs_close_log();
2051 *mcl=1;
2052 while (1)
2053 {
2054 fd_set fds;
2055
2056 do
2057 {
2058 FD_ZERO(&fds);
2059 FD_SET(mfdr, &fds);
2060 for (i=0; i<CS_MAX_MOD; i++)
2061 if ( (ph[i].type & MOD_CONN_NET) && ph[i].ptab )
2062 for (j=0; j<ph[i].ptab->nports; j++)
2063 if (ph[i].ptab->ports[j].fd)
2064 FD_SET(ph[i].ptab->ports[j].fd, &fds);
2065 errno=0;
2066 cs_set_mloc(0, "before select");
2067 select(gfd, &fds, 0, 0, 0);
2068 cs_set_mloc(60, "after select");
2069 } while (errno==EINTR);
2070 cs_set_mloc(-1, "event (global)");
2071
2072 client[0].last=time((time_t *)0);
2073 scad = sizeof(cad);
2074 if (FD_ISSET(mfdr, &fds))
2075 {
2076 cs_set_mloc(-1, "event: master-pipe");
2077 process_master_pipe();
2078 }
2079 for (i=0; i<CS_MAX_MOD; i++)
2080 {
2081 if( (ph[i].type & MOD_CONN_NET) && ph[i].ptab )
2082 {
2083 for( j=0; j<ph[i].ptab->nports; j++ )
2084 {
2085 if( ph[i].ptab->ports[j].fd && FD_ISSET(ph[i].ptab->ports[j].fd, &fds) )
2086 {
2087 if (ph[i].type==MOD_CONN_UDP)
2088 {
2089 cs_set_mloc(-1, "event: udp-socket");
2090 if ((n=recvfrom(ph[i].ptab->ports[j].fd, buf+3, sizeof(buf)-3, 0, (struct sockaddr *)&cad, (socklen_t *)&scad))>0)
2091 {
2092 int idx;
2093 idx=idx_from_ip(cs_inet_order(cad.sin_addr.s_addr), ntohs(cad.sin_port));
2094 if (!idx)
2095 {
2096 if (pipe(fdp))
2097 {
2098 cs_log("Cannot create pipe (errno=%d)", errno);
2099 cs_exit(1);
2100 }
2101 switch(cs_fork(cs_inet_order(cad.sin_addr.s_addr), ntohs(cad.sin_port)))
2102 {
2103 case -1:
2104 close(fdp[0]);
2105 close(fdp[1]);
2106 break;
2107 case 0:
2108 client[idx=cs_last_idx].ufd=fdp[1];
2109 close(fdp[0]);
2110 break;
2111 default:
2112// close(fdp[1]); // now used to simulate event
2113 pfd=fdp[0];
2114 wait4master();
2115 client[cs_idx].ctyp=i;
2116 client[cs_idx].port_idx=j;
2117 client[cs_idx].udp_fd=ph[i].ptab->ports[j].fd;
2118 client[cs_idx].udp_sa=cad;
2119 if (ph[client[cs_idx].ctyp].watchdog)
2120 alarm(cfg->cmaxidle<<2);
2121 ph[i].s_handler(cad); // never return
2122 }
2123 }
2124 if (idx)
2125 {
2126 unsigned short rl;
2127 rl=n;
2128 buf[0]='U';
2129 memcpy(buf+1, &rl, 2);
2130 if (!write(client[idx].ufd, buf, n+3)) cs_exit(1);
2131 }
2132 }
2133 }
2134 else
2135 {
2136 cs_set_mloc(-1, "event: tcp-socket");
2137 if ((pfd=accept(ph[i].ptab->ports[j].fd, (struct sockaddr *)&cad, (socklen_t *)&scad))>0)
2138 {
2139 switch(cs_fork(cs_inet_order(cad.sin_addr.s_addr), ntohs(cad.sin_port)))
2140 {
2141 case -1:
2142 case 0:
2143 close(pfd);
2144 break;
2145 default:
2146 wait4master();
2147 client[cs_idx].ctyp=i;
2148 client[cs_idx].udp_fd=pfd;
2149 client[cs_idx].port_idx=j;
2150 if (ph[client[cs_idx].ctyp].watchdog)
2151 alarm(cfg->cmaxidle<<2);
2152 ph[i].s_handler();
2153 }
2154 }
2155 }
2156 }
2157 }
2158 } // if (ph[i].type & MOD_CONN_NET)
2159 }
2160 }
2161 cs_exit(1);
2162}
Note: See TracBrowser for help on using the repository browser.