source: trunk/oscam-config.c @ 5375

Last change on this file since 5375 was 5374, checked in by alno, 8 years ago

try fix for saving services with WebIf

File size: 139.3 KB
Line 
1//FIXME Not checked on threadsafety yet; after checking please remove this line
2
3#include "globals.h"
4
5#ifdef OS_MACOSX
6#include <net/if_dl.h>
7#include <ifaddrs.h>
8#elif defined OS_SOLARIS
9#include <net/if.h>
10#include <net/if_arp.h>
11#include <sys/sockio.h>
12#else
13#include <net/if.h>
14#endif
15
16#ifdef CS_WITH_BOXKEYS
17#  include "oscam-boxkeys.np"
18#endif
19
20#define CONFVARWIDTH 30
21
22static const char *cs_conf="oscam.conf";
23static const char *cs_user="oscam.user";
24static const char *cs_srvr="oscam.server";
25static const char *cs_srid="oscam.srvid";
26static const char *cs_trid="oscam.tiers";
27static const char *cs_l4ca="oscam.guess";
28static const char *cs_cert="oscam.cert";
29static const char *cs_sidt="oscam.services";
30#ifdef CS_ANTICASC
31static const char *cs_ac="oscam.ac";
32#endif
33
34//Todo #ifdef CCCAM
35static const char *cs_provid="oscam.provid";
36
37#ifdef IRDETO_GUESSING
38static const char *cs_ird="oscam.ird";
39#endif
40
41static char token[4096];
42
43typedef enum cs_proto_type
44{
45    TAG_GLOBAL, // must be first !
46    TAG_MONITOR,    // monitor
47    TAG_CAMD33, // camd 3.3x
48    TAG_CAMD35, // camd 3.5x UDP
49    TAG_NEWCAMD,    // newcamd
50    TAG_RADEGAST,   // radegast
51    TAG_SERIAL, // serial (static)
52    TAG_CS357X, // camd 3.5x UDP
53    TAG_CS378X, // camd 3.5x TCP
54    TAG_GBOX,   // gbox
55#ifdef MODULE_CCCAM
56    TAG_CCCAM,  // cccam
57#endif
58    TAG_CONSTCW,    // constcw
59    TAG_DVBAPI, // dvbapi
60    TAG_WEBIF,  // webif
61    TAG_ANTICASC,   // anti-cascading
62    TAG_LCD     // LCD
63} cs_proto_type_t;
64
65static const char *cctag[]={"global", "monitor", "camd33", "camd35", "newcamd", "radegast", "serial",
66              "cs357x", "cs378x", "gbox",
67#ifdef MODULE_CCCAM
68              "cccam",
69#endif
70              "constcw", "dvbapi", "webif", "anticasc",
71#ifdef LCDSUPPORT
72              "lcd",
73#endif
74              NULL};
75
76
77/* Returns the default value if string length is zero, otherwise atoi is called*/
78int32_t strToIntVal(char *value, int32_t defaultvalue){
79    if (strlen(value) == 0) return defaultvalue;
80    int32_t i = strtol(value, NULL, 10);
81    if (i < 0) return defaultvalue;
82    else return i;
83}
84
85/* Returns the default value if string length is zero, otherwise strtoul is called*/
86uint32_t strToUIntVal(char *value, uint32_t defaultvalue){
87    if (strlen(value) == 0) return defaultvalue;
88    uint32_t i = strtoul(value, NULL, 10);
89    if (errno != 0) return defaultvalue;
90    else return i;
91}
92
93#ifdef DEBUG_SIDTAB
94static void show_sidtab(struct s_sidtab *sidtab)
95{
96  for (; sidtab; sidtab=sidtab->next)
97  {
98    int32_t i;
99    char buf[1024];
100    char *saveptr = buf;
101    cs_log("label=%s", sidtab->label);
102    snprintf(buf, sizeof(buf), "caid(%d)=", sidtab->num_caid);
103    for (i=0; i<sidtab->num_caid; i++)
104      snprintf(buf+strlen(buf), 1024-(buf-saveptr), "%04X ", sidtab->caid[i]);
105    cs_log("%s", buf);
106    snprintf(buf, sizeof(buf), "provider(%d)=", sidtab->num_provid);
107    for (i=0; i<sidtab->num_provid; i++)
108      snprintf(buf+strlen(buf), 1024-(buf-saveptr), "%08X ", sidtab->provid[i]);
109    cs_log("%s", buf);
110    snprintf(buf, sizeof(buf), "services(%d)=", sidtab->num_srvid);
111    for (i=0; i<sidtab->num_srvid; i++)
112      snprintf(buf+strlen(buf), 1024-(buf-saveptr), "%04X ", sidtab->srvid[i]);
113    cs_log("%s", buf);
114  }
115}
116#endif
117
118void chk_iprange(char *value, struct s_ip **base)
119{
120    int32_t i = 0;
121    char *ptr1, *ptr2, *saveptr1 = NULL;
122    struct s_ip *fip, *lip, *cip;
123
124    cs_malloc(&cip, sizeof(struct s_ip), SIGINT);
125    fip = cip;
126
127    for (ptr1=strtok_r(value, ",", &saveptr1); ptr1; ptr1=strtok_r(NULL, ",", &saveptr1)) {
128            if (i == 0)
129                ++i;
130        else {
131            cs_malloc(&cip, sizeof(struct s_ip), SIGINT);
132            lip->next = cip;
133        }
134
135        if( (ptr2=strchr(trim(ptr1), '-')) ) {
136            *ptr2++ ='\0';
137            cip->ip[0]=cs_inet_addr(trim(ptr1));
138            cip->ip[1]=cs_inet_addr(trim(ptr2));
139        } else {
140            cip->ip[0]=cip->ip[1]=cs_inet_addr(ptr1);
141        }
142        lip = cip;
143    }
144    lip = *base;
145    *base = fip;
146    clear_sip(&lip);
147}
148
149void chk_caidtab(char *caidasc, CAIDTAB *ctab)
150{
151    int32_t i;
152    char *ptr1, *ptr2, *ptr3, *saveptr1 = NULL;
153    CAIDTAB newctab;
154    memset(&newctab, 0, sizeof(CAIDTAB));
155    for (i = 1; i < CS_MAXCAIDTAB; newctab.mask[i++] = 0xffff);
156
157    for (i = 0, ptr1 = strtok_r(caidasc, ",", &saveptr1); (i < CS_MAXCAIDTAB) && (ptr1); ptr1 = strtok_r(NULL, ",", &saveptr1)) {
158        uint32_t caid, mask, cmap;
159        if( (ptr3 = strchr(trim(ptr1), ':')) )
160            *ptr3++ = '\0';
161        else
162            ptr3 = "";
163
164        if( (ptr2 = strchr(trim(ptr1), '&')) )
165            *ptr2++ = '\0';
166        else
167            ptr2 = "";
168
169        if (((caid = a2i(ptr1, 2)) | (mask = a2i(ptr2,-2)) | (cmap = a2i(ptr3, 2))) < 0x10000) {
170            newctab.caid[i] = caid;
171            newctab.mask[i] = mask;
172            newctab.cmap[i++] = cmap;
173        }
174    }
175    memcpy(ctab, &newctab, sizeof(CAIDTAB));
176}
177
178void chk_caidvaluetab(char *lbrlt, CAIDVALUETAB *tab, int32_t minvalue)
179{
180        int32_t i;
181        char *ptr1, *ptr2, *saveptr1 = NULL;
182        CAIDVALUETAB newtab;
183        memset(&newtab, 0, sizeof(CAIDVALUETAB));
184
185        for (i = 0, ptr1 = strtok_r(lbrlt, ",", &saveptr1); (i < CS_MAX_CAIDVALUETAB) && (ptr1); ptr1 = strtok_r(NULL, ",", &saveptr1)) {
186                int32_t caid, value;
187
188                if( (ptr2 = strchr(trim(ptr1), ':')) )
189                        *ptr2++ = '\0';
190                else
191                        ptr2 = "";
192
193                if (((caid = a2i(ptr1, 2)) < 0xFFFF) | ((value = atoi(ptr2)) < 10000)) {
194                        newtab.caid[i] = caid;
195                        if (value < minvalue) value = minvalue;
196                        newtab.value[i] = value;
197                        newtab.n = ++i;
198                }
199        }
200        memcpy(tab, &newtab, sizeof(CAIDVALUETAB));
201}
202
203/*
204 * Creates a string ready to write as a token into config or WebIf. You must free the returned value through free_mk_t().
205 */
206char *mk_t_caidvaluetab(CAIDVALUETAB *tab)
207{
208        if (!tab->n) return "";
209        int32_t i, size = 2 + tab->n * (4 + 1 + 5 + 1); //caid + ":" + time + ","
210        char *buf = cs_malloc(&buf, size, SIGINT);
211        char *ptr = buf;
212
213        for (i = 0; i < tab->n; i++) {
214                ptr += snprintf(ptr, size-(ptr-buf), "%s%04X:%d", i?",":"", tab->caid[i], tab->value[i]);
215        }
216        *ptr = 0;
217        return buf;
218}
219
220void chk_tuntab(char *tunasc, TUNTAB *ttab)
221{
222    int32_t i;
223    char *ptr1, *ptr2, *ptr3, *saveptr1 = NULL;
224    TUNTAB newttab;
225    memset(&newttab, 0 , sizeof(TUNTAB));
226
227    for (i = 0, ptr1 = strtok_r(tunasc, ",", &saveptr1); (i < CS_MAXTUNTAB) && (ptr1); ptr1 = strtok_r(NULL, ",", &saveptr1)) {
228        uint32_t bt_caidfrom, bt_caidto, bt_srvid;
229        if( (ptr3 = strchr(trim(ptr1), ':')) )
230            *ptr3++ = '\0';
231        else
232            ptr3 = "";
233
234        if( (ptr2 = strchr(trim(ptr1), '.')) )
235            *ptr2++ = '\0';
236        else
237            ptr2 = "";
238
239        if ((bt_caidfrom = a2i(ptr1, 2)) | (bt_srvid = a2i(ptr2,-2)) | (bt_caidto = a2i(ptr3, 2))) {
240            newttab.bt_caidfrom[i] = bt_caidfrom;
241            newttab.bt_caidto[i] = bt_caidto;
242            newttab.bt_srvid[i++] = bt_srvid;
243            newttab.n = i;
244        }
245    }
246    memcpy(ttab, &newttab, sizeof(TUNTAB));
247}
248
249void chk_services(char *labels, SIDTABBITS *sidok, SIDTABBITS *sidno)
250{
251    int32_t i;
252    char *ptr, *saveptr1 = NULL;
253    SIDTAB *sidtab;
254    SIDTABBITS newsidok, newsidno;
255    newsidok = newsidno = 0;
256    for (ptr=strtok_r(labels, ",", &saveptr1); ptr; ptr=strtok_r(NULL, ",", &saveptr1)) {
257        for (trim(ptr), i = 0, sidtab = cfg.sidtab; sidtab; sidtab = sidtab->next, i++) {
258            if (!strcmp(sidtab->label, ptr)) newsidok|=((SIDTABBITS)1<<i);
259            if ((ptr[0]=='!') && (!strcmp(sidtab->label, ptr+1))) newsidno|=((SIDTABBITS)1<<i);
260        }
261    }
262    *sidok = newsidok;
263    *sidno = newsidno;
264}
265
266void chk_ftab(char *zFilterAsc, FTAB *ftab, const char *D_USE(zType), const char *D_USE(zName), const char *zFiltName)
267{
268    int32_t i, j;
269    char *ptr1, *ptr2, *ptr3, *saveptr1 = NULL;
270    char *ptr[CS_MAXFILTERS] = {0};
271    FTAB newftab;
272    memset(&newftab, 0, sizeof(FTAB));
273   
274    for( i = 0, ptr1 = strtok_r(zFilterAsc, ";", &saveptr1); (i < CS_MAXFILTERS) && (ptr1); ptr1 = strtok_r(NULL, ";", &saveptr1), i++ ) {
275        ptr[i] = ptr1;
276        if( (ptr2 = strchr(trim(ptr1), ':')) ) {
277            *ptr2++ ='\0';
278            newftab.filts[i].caid = (uint16_t)a2i(ptr1, 4);
279            ptr[i] = ptr2;
280        }
281        else if (zFiltName && zFiltName[0] == 'c') {
282            cs_log("PANIC: CAID field not found in CHID parameter!");
283            return;
284        }
285        newftab.nfilts++;
286    }
287
288    if( newftab.nfilts ) {
289        cs_debug_mask(D_CLIENT, "%s '%s' %s filter(s):", zType, zName, zFiltName);
290    }
291    for( i = 0; i < newftab.nfilts; i++ ) {
292        cs_debug_mask(D_CLIENT, "CAID #%d: %04X", i, newftab.filts[i].caid);
293        for( j = 0, ptr3 = strtok_r(ptr[i], ",", &saveptr1); (j < CS_MAXPROV) && (ptr3); ptr3 = strtok_r(NULL, ",", &saveptr1), j++ ) {
294            newftab.filts[i].prids[j] = a2i(ptr3,6);
295            newftab.filts[i].nprids++;
296            cs_debug_mask(D_CLIENT, "%s #%d: %06X", zFiltName, j, newftab.filts[i].prids[j]);
297        }
298    }
299    memcpy(ftab, &newftab, sizeof(FTAB));
300}
301
302void chk_cltab(char *classasc, CLASSTAB *clstab)
303{
304    int32_t i;
305    char *ptr1, *saveptr1 = NULL;
306    CLASSTAB newclstab;
307    memset(&newclstab, 0, sizeof(newclstab));
308    newclstab.an = newclstab.bn = 0;
309    for( i = 0, ptr1 = strtok_r(classasc, ",", &saveptr1); (i < CS_MAXCAIDTAB) && (ptr1); ptr1 = strtok_r(NULL, ",", &saveptr1) ) {
310        ptr1 = trim(ptr1);
311        if( ptr1[0] == '!' )
312            newclstab.bclass[newclstab.bn++] = (uchar)a2i(ptr1+1, 2);
313        else
314            newclstab.aclass[newclstab.an++] = (uchar)a2i(ptr1, 2);
315    }
316    memcpy(clstab, &newclstab, sizeof(CLASSTAB));
317}
318
319void chk_port_tab(char *portasc, PTAB *ptab)
320{
321    int32_t i, j, nfilts, ifilt, iport;
322    PTAB *newptab;
323    char *ptr1, *ptr2, *ptr3, *saveptr1 = NULL;
324    char *ptr[CS_MAXPORTS] = {0};
325    int32_t port[CS_MAXPORTS] = {0};
326    if(!cs_malloc(&newptab, sizeof(PTAB), -1)) return;
327
328    for (nfilts = i = 0, ptr1 = strtok_r(portasc, ";", &saveptr1); (i < CS_MAXPORTS) && (ptr1); ptr1 = strtok_r(NULL, ";", &saveptr1), i++) {
329        ptr[i] = ptr1;
330        if( (ptr2=strchr(trim(ptr1), '@')) ) {
331            *ptr2++ ='\0';
332            newptab->ports[i].s_port = atoi(ptr1);
333
334            //checking for des key for port
335            newptab->ports[i].ncd_key_is_set = 0;   //default to 0
336            if( (ptr3=strchr(trim(ptr1), '{')) ) {
337                *ptr3++='\0';
338                if (key_atob_l(ptr3, newptab->ports[i].ncd_key, 28))
339                    fprintf(stderr, "newcamd: error in DES Key for port %s -> ignored\n", ptr1);
340                else
341                    newptab->ports[i].ncd_key_is_set = 1;
342            }
343
344            ptr[i] = ptr2;
345            port[i] = newptab->ports[i].s_port;
346            newptab->nports++;
347        }
348        nfilts++;
349    }
350
351    if( nfilts == 1 && strlen(portasc) < 6 && newptab->ports[0].s_port == 0 ) {
352        newptab->ports[0].s_port = atoi(portasc);
353        newptab->nports = 1;
354    }
355
356    iport = ifilt = 0;
357    for (i=0; i<nfilts; i++) {
358        if( port[i] != 0 )
359            iport = i;
360        for (j = 0, ptr3 = strtok_r(ptr[i], ",", &saveptr1); (j < CS_MAXPROV) && (ptr3); ptr3 = strtok_r(NULL, ",", &saveptr1), j++) {
361            if( (ptr2=strchr(trim(ptr3), ':')) ) {
362                *ptr2++='\0';
363                newptab->ports[iport].ftab.nfilts++;
364                ifilt = newptab->ports[iport].ftab.nfilts-1;
365                newptab->ports[iport].ftab.filts[ifilt].caid = (uint16_t)a2i(ptr3, 4);
366                newptab->ports[iport].ftab.filts[ifilt].prids[j] = a2i(ptr2, 6);
367            } else {
368                newptab->ports[iport].ftab.filts[ifilt].prids[j] = a2i(ptr3, 6);
369            }
370            newptab->ports[iport].ftab.filts[ifilt].nprids++;
371        }
372    }
373    memcpy(ptab, newptab, sizeof(PTAB));
374    free(newptab);
375}
376
377#ifdef MODULE_CCCAM
378void chk_cccam_ports(char *value)
379{
380    int32_t i;
381    char *ptr, *saveptr1 = NULL;
382    uint16_t newcc_port[CS_MAXPORTS];
383    memset(newcc_port, 0, sizeof(newcc_port));
384
385    for (i=0, ptr=strtok_r(value, ",", &saveptr1); ptr && i<CS_MAXPORTS; ptr=strtok_r(NULL, ",", &saveptr1)) {
386        newcc_port[i] = atoi(ptr);
387        if (newcc_port[i]) i++;
388    }
389    memcpy(cfg.cc_port, newcc_port, sizeof(cfg.cc_port));
390}
391#endif
392
393#ifdef NOTUSED
394static void chk_srvip(char *value, in_addr_t *ip)
395{
396    int32_t i;
397    char *ptr, *saveptr1 = NULL;
398    for (i=0, ptr=strtok_r(value, ",", &saveptr1); ptr; ptr=strtok_r(NULL, ",", &saveptr1))
399        if (i<8) ip[i++] = inet_addr(ptr);
400}
401#endif
402
403void chk_t_global(const char *token, char *value)
404{
405    char *saveptr1 = NULL;
406
407#ifdef QBOXHD_LED
408    if (!strcmp(token, "disableqboxhdled")) {
409        cfg.disableqboxhdled = strToIntVal(value, 0);
410        return;
411    }
412#endif
413
414    if (!strcmp(token, "disablelog")) {
415        cfg.disablelog = strToIntVal(value, 0);
416        return;
417    }
418
419    if (!strcmp(token, "disableuserfile")) {
420        cfg.disableuserfile = strToIntVal(value, 1);
421        return;
422    }
423
424    if (!strcmp(token, "disablemail")) {
425        cfg.disablemail = strToIntVal(value, 1);
426        return;
427    }
428
429    if (!strcmp(token, "loghistorysize")) {
430        uint32_t newsize = strToUIntVal(value, 4096);
431        if (newsize < 1024) {
432            fprintf(stderr, "WARNING: loghistorysize is too small, adjusted to 1024\n");
433            newsize = 1024;
434        }
435        cs_reinit_loghist(newsize);
436        return;
437    }
438
439    if (!strcmp(token, "serverip")) {
440        if (strlen(value) == 0) {
441            cfg.srvip = 0;
442            return;
443        } else {
444            cfg.srvip=cs_inet_addr(value);
445            return;
446        }
447    }
448
449    if (!strcmp(token, "logfile")) {
450        cfg.logtostdout = 0;
451        cfg.logtosyslog = 0;
452        NULLFREE(cfg.logfile);
453        if (strlen(value) > 0) {
454            char *pch;
455            for(pch = strtok_r(value, ";", &saveptr1); pch != NULL; pch = strtok_r(NULL, ";", &saveptr1)){
456                pch=trim(pch);
457                if(!strcmp(pch, "stdout")) cfg.logtostdout = 1;
458                else if(!strcmp(pch, "syslog")) cfg.logtosyslog = 1;
459                else {
460                    NULLFREE(cfg.logfile);
461                    if(!cs_malloc(&(cfg.logfile), strlen(pch) + 1, -1)) continue;
462                    else memcpy(cfg.logfile, pch, strlen(pch) + 1);
463                }
464            }
465        } else {
466            if(cs_malloc(&(cfg.logfile), strlen(CS_LOGFILE) + 1, -1))
467                memcpy(cfg.logfile, CS_LOGFILE, strlen(CS_LOGFILE) + 1);
468            else cfg.logtostdout = 1;
469        }
470        return;
471    }
472
473    if (!strcmp(token, "usrfile")) {
474        NULLFREE(cfg.usrfile);
475        if (strlen(value) > 0) {
476            if(!cs_malloc(&(cfg.usrfile), strlen(value) + 1, -1)) return;
477            memcpy(cfg.usrfile, value, strlen(value) + 1);
478        } else cfg.disableuserfile = 1;
479        return;
480    }
481
482    if (!strcmp(token, "mailfile")) {
483        NULLFREE(cfg.mailfile);
484        if (strlen(value) > 0) {
485            if(!cs_malloc(&(cfg.mailfile), strlen(value) + 1, -1)) return;
486            memcpy(cfg.mailfile, value, strlen(value) + 1);
487        } else cfg.disablemail = 1;
488        return;
489    }
490
491    if (!strcmp(token, "cwlogdir")) {
492        NULLFREE(cfg.cwlogdir);
493        if (strlen(value) > 0) {
494            if(!cs_malloc(&(cfg.cwlogdir), strlen(value) + 1, -1)) return;
495            memcpy(cfg.cwlogdir, value, strlen(value) + 1);
496        }
497        return;
498    }
499
500    if (!strcmp(token, "emmlogdir")) {
501        NULLFREE(cfg.emmlogdir);
502        if (strlen(value) > 0) {
503            if(!cs_malloc(&(cfg.emmlogdir), strlen(value) + 1, -1)) return;
504            memcpy(cfg.emmlogdir, value, strlen(value) + 1);
505        }
506        return;
507    }
508
509    if (!strcmp(token, "usrfileflag")) {
510        cfg.usrfileflag = strToIntVal(value, 0);
511        return;
512    }
513
514    if (!strcmp(token, "clienttimeout")) {
515        cfg.ctimeout = strToUIntVal(value, CS_CLIENT_TIMEOUT);
516        if (cfg.ctimeout < 100) cfg.ctimeout *= 1000;
517        return;
518    }
519
520    if (!strcmp(token, "fallbacktimeout")) {
521        cfg.ftimeout = strToUIntVal(value, (CS_CLIENT_TIMEOUT / 2));
522        if (cfg.ftimeout < 100) cfg.ftimeout *= 1000;
523        return;
524    }
525
526    if (!strcmp(token, "clientmaxidle")) {
527        cfg.cmaxidle = strToUIntVal(value, CS_CLIENT_MAXIDLE);
528        return;
529    }
530
531    if (!strcmp(token, "cachedelay")) {
532        cfg.delay = strToUIntVal(value, CS_DELAY);
533        return;
534    }
535
536    if (!strcmp(token, "bindwait")) {
537        cfg.bindwait = strToIntVal(value, CS_BIND_TIMEOUT);
538        return;
539    }
540
541    if (!strcmp(token, "netprio")) {
542        cfg.netprio = strToIntVal(value, 0);
543        return;
544    }
545
546    if (!strcmp(token, "sleep")) {
547        cfg.tosleep = strToIntVal(value, 0);
548        return;
549    }
550
551    if (!strcmp(token, "unlockparental")) {
552        cfg.ulparent = strToIntVal(value, 0);
553        return;
554    }
555
556    if (!strcmp(token, "nice")) {
557        if (strlen(value) == 0) {
558            cfg.nice = 99;
559            return;
560        } else {
561            cfg.nice = atoi(value);
562            if ((cfg.nice<-20) || (cfg.nice>20)) cfg.nice = 99;
563            if (cfg.nice != 99) cs_setpriority(cfg.nice);  // ignore errors
564            return;
565        }
566    }
567
568    if (!strcmp(token, "serialreadertimeout")) {
569        if (cfg.srtimeout < 100)
570            cfg.srtimeout = strtoul(value, NULL, 10) * 1000;
571        else
572            cfg.srtimeout = strtoul(value, NULL, 10);
573        if (cfg.srtimeout <= 0)
574            cfg.srtimeout = 1500;
575        return;
576    }
577
578    if (!strcmp(token, "maxlogsize")) {
579        cfg.max_log_size = strToIntVal(value, 10);
580        if(cfg.max_log_size != 0 && cfg.max_log_size <= 10) cfg.max_log_size = 10;
581        return;
582    }
583
584    if( !strcmp(token, "waitforcards")) {
585        cfg.waitforcards = strToIntVal(value, 1);
586        return;
587    }
588
589    if( !strcmp(token, "waitforcards_extra_delay")) {
590        cfg.waitforcards_extra_delay = strToIntVal(value, 0);
591        return;
592    }
593
594    if( !strcmp(token, "preferlocalcards")) {
595        cfg.preferlocalcards = strToIntVal(value, 0);
596        return;
597    }
598
599    if( !strcmp(token, "saveinithistory")) {
600        cfg.saveinithistory = strToIntVal(value, 0);
601        return;
602    }
603
604    if (!strcmp(token, "readerrestartseconds")) {
605        cfg.reader_restart_seconds = strToIntVal(value, 5);
606        return;
607    }
608
609    if (!strcmp(token, "dropdups")) {
610        cfg.dropdups = strToIntVal(value, 0);
611        return;
612    }
613
614#ifdef WITH_LB
615    if (!strcmp(token, "readerautoloadbalance") || !strcmp(token, "lb_mode")) {
616        cfg.lb_mode = strToIntVal(value, DEFAULT_LB_MODE);
617        return;
618    }
619
620    if (!strcmp(token, "readerautoloadbalance_save") || !strcmp(token, "lb_save")) {
621        cfg.lb_save = strToIntVal(value, 0);
622        if (cfg.lb_save  > 0 && cfg.lb_save  < 100) {
623            cfg.lb_save = 100;
624            fprintf(stderr, "Warning: '%s' corrected to the minimum -> 100\n", token);
625        }
626        return;
627    }
628
629    if (!strcmp(token, "lb_nbest_readers")) {
630        cfg.lb_nbest_readers = strToIntVal(value, DEFAULT_NBEST);
631        if (cfg.lb_nbest_readers < 2)
632            cfg.lb_nbest_readers = DEFAULT_NBEST;
633        return;
634    }
635
636    if (!strcmp(token, "lb_nfb_readers")) {
637        cfg.lb_nfb_readers = strToIntVal(value, DEFAULT_NFB);
638        return;
639    }
640
641    if (!strcmp(token, "lb_min_ecmcount")) {
642        cfg.lb_min_ecmcount = strToIntVal(value, DEFAULT_MIN_ECM_COUNT);
643        return;
644    }
645
646    if (!strcmp(token, "lb_max_ecmcount")) {
647        cfg.lb_max_ecmcount = strToIntVal(value, DEFAULT_MAX_ECM_COUNT);
648        return;
649    }
650
651    if (!strcmp(token, "lb_reopen_seconds")) {
652        cfg.lb_reopen_seconds = strToIntVal(value, DEFAULT_REOPEN_SECONDS);
653        return;
654    }
655
656    if (!strcmp(token, "lb_retrylimit")) {
657        cfg.lb_retrylimit = strToIntVal(value, DEFAULT_RETRYLIMIT);
658        return;
659    }
660
661    if (!strcmp(token, "lb_retrylimits")) {
662        chk_caidvaluetab(value, &cfg.lb_retrylimittab, 50);
663        return;
664    }
665
666    if (!strcmp(token, "lb_nbest_percaid")) {
667        chk_caidvaluetab(value, &cfg.lb_nbest_readers_tab, 1);
668        return;
669    }
670
671    if (!strcmp(token, "lb_noproviderforcaid")) {
672        if(strlen(value) == 0)
673            clear_caidtab(&cfg.lb_noproviderforcaid);
674        else
675            chk_caidtab(value, &cfg.lb_noproviderforcaid);
676        return;
677    }
678
679    if (!strcmp(token, "lb_savepath")) {
680        NULLFREE(cfg.lb_savepath);
681        cfg.lb_savepath = strnew(value);
682        return;
683    }
684
685    if (!strcmp(token, "lb_stat_cleanup")) {
686        cfg.lb_stat_cleanup = strToIntVal(value, DEFAULT_LB_STAT_CLEANUP);
687        return;
688    }
689
690    if (!strcmp(token, "lb_use_locking")) {
691        cfg.lb_use_locking = strToIntVal(value, DEFAULT_LB_USE_LOCKING);
692        return;
693    }
694
695    if (!strcmp(token, "lb_reopen_mode")) {
696        cfg.lb_reopen_mode = strToIntVal(value, DEFAULT_LB_REOPEN_MODE);
697        return;
698    }
699
700    if (!strcmp(token, "lb_max_readers")) {
701        cfg.lb_max_readers = strToIntVal(value, 0);
702        return;
703    }
704
705    if (!strcmp(token, "lb_auto_betatunnel")) {
706        cfg.lb_auto_betatunnel = strToIntVal(value, DEFAULT_LB_AUTO_BETATUNNEL);
707        return;
708    }
709#endif
710
711    if (!strcmp(token, "resolvegethostbyname")) {
712        cfg.resolve_gethostbyname = strToIntVal(value, 0);
713        return;
714    }
715
716    if (!strcmp(token, "failbantime")) {
717        cfg.failbantime = strToIntVal(value, 0);
718        return;
719    }
720
721    if (!strcmp(token, "failbancount")) {
722        cfg.failbancount = strToIntVal(value, 0);
723        return;
724    }
725
726    if (!strcmp(token, "suppresscmd08")) {
727        cfg.c35_suppresscmd08 = strToIntVal(value, 0);
728        return;
729    }
730
731#ifdef CS_WITH_DOUBLECHECK
732    if (!strcmp(token, "double_check")) {
733        cfg.double_check = strToIntVal(value, 0);
734        return;
735    }
736#endif
737
738
739    if (token[0] != '#')
740        fprintf(stderr, "Warning: keyword '%s' in global section not recognized\n", token);
741}
742
743#ifdef CS_ANTICASC
744void chk_t_ac(char *token, char *value)
745{
746    if (!strcmp(token, "enabled")) {
747        cfg.ac_enabled = strToIntVal(value, 0);
748        if( cfg.ac_enabled > 0 )
749            cfg.ac_enabled = 1;
750        return;
751    }
752
753    if (!strcmp(token, "numusers")) {
754        cfg.ac_users = strToIntVal(value, 0);
755        return;
756    }
757
758    if (!strcmp(token, "sampletime")) {
759        cfg.ac_stime = atoi(value);
760        if( cfg.ac_stime < 0 )
761            cfg.ac_stime = 2;
762        return;
763    }
764
765    if (!strcmp(token, "samples")) {
766        cfg.ac_samples = atoi(value);
767        if( cfg.ac_samples < 2 || cfg.ac_samples > 10)
768            cfg.ac_samples = 10;
769        return;
770    }
771
772    if (!strcmp(token, "penalty")) {
773        cfg.ac_penalty = atoi(value);
774        if( cfg.ac_penalty < 0 )
775            cfg.ac_penalty = 0;
776        return;
777    }
778
779    if (!strcmp(token, "aclogfile")) {
780        cs_strncpy(cfg.ac_logfile, value, sizeof(cfg.ac_logfile));
781        return;
782    }
783
784    if( !strcmp(token, "fakedelay") ) {
785        cfg.ac_fakedelay = atoi(value);
786        if( cfg.ac_fakedelay < 100 || cfg.ac_fakedelay > 1000 )
787            cfg.ac_fakedelay = 1000;
788        return;
789    }
790
791    if( !strcmp(token, "denysamples") ) {
792        cfg.ac_denysamples = atoi(value);
793        if( cfg.ac_denysamples < 2 || cfg.ac_denysamples > cfg.ac_samples - 1 )
794            cfg.ac_denysamples=cfg.ac_samples-1;
795        return;
796    }
797
798    if (token[0] != '#')
799        fprintf(stderr, "Warning: keyword '%s' in anticascading section not recognized\n",token);
800}
801#endif
802
803void chk_t_monitor(char *token, char *value)
804{
805    if (!strcmp(token, "port")) {
806        cfg.mon_port = strToIntVal(value, 0);
807        return;
808    }
809
810    if (!strcmp(token, "serverip")) {
811        if(strlen(value) == 0) {
812            cfg.mon_srvip = 0;
813            return;
814        } else {
815            cfg.mon_srvip=cs_inet_addr(value);
816            return;
817        }
818    }
819
820    if (!strcmp(token, "nocrypt")) {
821        if(strlen(value) == 0) {
822            clear_sip(&cfg.mon_allowed);
823            return;
824        } else {
825            chk_iprange(value, &cfg.mon_allowed);
826            return;
827        }
828    }
829
830    if (!strcmp(token, "aulow")) {
831        cfg.mon_aulow = strToIntVal(value, 0);
832        return;
833    }
834
835    if (!strcmp(token, "monlevel")) {
836        cfg.mon_level = strToIntVal(value, 0);
837        return;
838    }
839
840    if (!strcmp(token, "hideclient_to")) {
841        cfg.mon_hideclient_to = strToIntVal(value, 0);
842        return;
843    }
844
845    if (!strcmp(token, "appendchaninfo")) {
846        cfg.mon_appendchaninfo = strToIntVal(value, 0);
847        return;
848    }
849
850    if (token[0] != '#')
851        fprintf(stderr, "Warning: keyword '%s' in monitor section not recognized\n",token);
852}
853
854#ifdef WEBIF
855void chk_t_webif(char *token, char *value)
856{
857    if (!strcmp(token, "httpport")) {
858        if(strlen(value) == 0) {
859            cfg.http_port = 0;
860            return;
861        } else {
862            if (value[0]=='+') {
863#ifdef WITH_SSL
864                cfg.http_use_ssl=1;
865#else
866                fprintf(stderr, "Warning: OSCam compiled without SSL support.\n");
867#endif
868                cfg.http_port = atoi(value+1);
869            } else {
870                cfg.http_port = atoi(value);
871            }
872            return;
873        }
874    }
875
876    if (!strcmp(token, "httpuser")) {
877        cs_strncpy(cfg.http_user, value, sizeof(cfg.http_user));
878        return;
879    }
880
881    if (!strcmp(token, "httppwd")) {
882        cs_strncpy(cfg.http_pwd, value, sizeof(cfg.http_pwd));
883        return;
884    }
885
886    if (!strcmp(token, "httpcss")) {
887        cs_strncpy(cfg.http_css, value, sizeof(cfg.http_css));
888        return;
889    }
890
891    if (!strcmp(token, "httpjscript")) {
892        cs_strncpy(cfg.http_jscript, value, sizeof(cfg.http_jscript));
893        return;
894    }
895
896    if (!strcmp(token, "httpscript")) {
897        cs_strncpy(cfg.http_script, value, sizeof(cfg.http_script));
898        return;
899    }
900
901    if (!strcmp(token, "httphelplang")) {
902        cs_strncpy(cfg.http_help_lang, value, sizeof(cfg.http_help_lang));
903        return;
904    }
905
906    if (!strcmp(token, "httpcert")) {
907        cs_strncpy(cfg.http_cert, value, sizeof(cfg.http_cert));
908        return;
909    }
910
911    if (!strcmp(token, "httptpl")) {
912        cfg.http_tpl[0] = '\0';
913        cs_strncpy(cfg.http_tpl, value, sizeof(cfg.http_tpl));
914        if(strlen(value) != 0) {
915            if(strlen(cfg.http_tpl) < (sizeof(cfg.http_tpl)-2) && cfg.http_tpl[strlen(cfg.http_tpl)-1] != '/') {
916                cfg.http_tpl[strlen(cfg.http_tpl)] = '/';
917                cfg.http_tpl[strlen(cfg.http_tpl)] = '\0';
918            }
919        }
920        return;
921    }
922
923    if (!strcmp(token, "httprefresh")) {
924        cfg.http_refresh = strToIntVal(value, 0);
925        return;
926    }
927
928    if (!strcmp(token, "httphideidleclients")) {
929        cfg.http_hide_idle_clients = strToIntVal(value, 0);
930        return;
931    }
932
933    if (!strcmp(token, "httpallowed")) {
934        if(strlen(value) == 0) {
935            clear_sip(&cfg.http_allowed);
936            return;
937        } else {
938            chk_iprange(value, &cfg.http_allowed);
939            return;
940        }
941    }
942
943    if (!strcmp(token, "httpreadonly")) {
944        cfg.http_readonly = strToIntVal(value, 0);
945        return;
946    }
947
948    if (!strcmp(token, "httpdyndns")) {
949        cs_strncpy((char *)cfg.http_dyndns, value, sizeof(cfg.http_dyndns));
950        return;
951    }
952
953    if (!strcmp(token, "httpsavefullcfg")) {
954        cfg.http_full_cfg = strToIntVal(value, 0);
955        return;
956    }
957
958    if (token[0] != '#')
959        fprintf(stderr, "Warning: keyword '%s' in webif section not recognized\n",token);
960}
961#endif
962
963
964void chk_t_camd33(char *token, char *value)
965{
966    if (!strcmp(token, "port")) {
967        cfg.c33_port = strToIntVal(value, 0);
968        return;
969    }
970
971    if (!strcmp(token, "serverip")) {
972        if(strlen(value) == 0) {
973            cfg.c33_srvip = 0;
974            return;
975        } else {
976            cfg.c33_srvip = cs_inet_addr(value);
977            return;
978        }
979    }
980
981    if (!strcmp(token, "nocrypt")) {
982        if(strlen(value) == 0) {
983            clear_sip(&cfg.c33_plain);
984            return;
985        } else {
986            chk_iprange(value, &cfg.c33_plain);
987            return;
988        }
989    }
990
991    if (!strcmp(token, "passive")) {
992        cfg.c33_passive = strToIntVal(value, 0);
993        return;
994    }
995
996    if (!strcmp(token, "key")) {
997        if(strlen(value) == 0) {
998            cfg.c33_crypted = 0;
999            return;
1000        }
1001        if (key_atob_l(value, cfg.c33_key, 32)) {
1002            fprintf(stderr, "Configuration camd3.3x: Error in Key\n");
1003            cfg.c33_crypted = 0;
1004            memset(cfg.c33_key, 0, sizeof(cfg.c33_key));
1005            return;
1006        }
1007        cfg.c33_crypted=1;
1008        return;
1009    }
1010
1011    if (token[0] != '#')
1012        fprintf(stderr, "Warning: keyword '%s' in camd33 section not recognized\n",token);
1013}
1014
1015void chk_t_camd35(char *token, char *value)
1016{
1017    if (!strcmp(token, "port")) {
1018        cfg.c35_port = strToIntVal(value, 0);
1019        return;
1020    }
1021
1022    if (!strcmp(token, "serverip")) {
1023        if(strlen(value) == 0) {
1024            cfg.c35_srvip = 0;
1025            return;
1026        } else {
1027            cfg.c35_srvip = cs_inet_addr(value);
1028            return;
1029        }
1030    }
1031
1032    if (!strcmp(token, "suppresscmd08")) {
1033        cfg.c35_udp_suppresscmd08 = strToIntVal(value, 0);
1034        return;
1035    }
1036
1037    if (token[0] != '#')
1038        fprintf(stderr, "Warning: keyword '%s' in camd35 section not recognized\n", token);
1039}
1040
1041void chk_t_camd35_tcp(char *token, char *value)
1042{
1043    if (!strcmp(token, "port")) {
1044        if(strlen(value) == 0) {
1045            clear_ptab(&cfg.c35_tcp_ptab);
1046            return;
1047        } else {
1048            chk_port_tab(value, &cfg.c35_tcp_ptab);
1049            return;
1050        }
1051    }
1052
1053    if (!strcmp(token, "serverip")) {
1054        if(strlen(value) == 0) {
1055            cfg.c35_tcp_srvip = 0;
1056            return;
1057        } else {
1058            cfg.c35_tcp_srvip = cs_inet_addr(value);
1059            return;
1060        }
1061    }
1062
1063    if (!strcmp(token, "suppresscmd08")) {
1064        cfg.c35_tcp_suppresscmd08 = strToIntVal(value, 0);
1065        return;
1066    }
1067
1068    if (token[0] != '#')
1069        fprintf(stderr, "Warning: keyword '%s' in camd35 tcp section not recognized\n", token);
1070}
1071
1072void chk_t_newcamd(char *token, char *value)
1073{
1074    if (!strcmp(token, "port")) {
1075        if(strlen(value) == 0) {
1076            clear_ptab(&cfg.ncd_ptab);
1077            return;
1078        } else {
1079            chk_port_tab(value, &cfg.ncd_ptab);
1080            return;
1081        }
1082    }
1083
1084    if (!strcmp(token, "serverip")) {
1085        if(strlen(value) == 0) {
1086            cfg.ncd_srvip = 0;
1087            return;
1088        } else {
1089            cfg.ncd_srvip = cs_inet_addr(value);
1090            return;
1091        }
1092    }
1093
1094    if (!strcmp(token, "allowed")) {
1095        if(strlen(value) == 0) {
1096            clear_sip(&cfg.ncd_allowed);
1097            return;
1098        } else {
1099            chk_iprange(value, &cfg.ncd_allowed);
1100            return;
1101        }
1102    }
1103
1104    if (!strcmp(token, "key")) {
1105        if(strlen(value) == 0){
1106            memset(cfg.ncd_key, 0, sizeof(cfg.ncd_key));
1107            return;
1108        }
1109        if (key_atob_l(value, cfg.ncd_key, 28)) {
1110            fprintf(stderr, "Configuration newcamd: Error in Key\n");
1111            memset(cfg.ncd_key, 0, sizeof(cfg.ncd_key));
1112        }
1113        return;
1114    }
1115
1116    if (!strcmp(token, "keepalive")) {
1117        cfg.ncd_keepalive = strToIntVal(value, 1);
1118        return;
1119    }
1120
1121    if (!strcmp(token, "mgclient")) {
1122        cfg.ncd_mgclient = strToIntVal(value, 0);
1123        return;
1124    }
1125
1126    if (token[0] != '#')
1127        fprintf(stderr, "Warning: keyword '%s' in newcamd section not recognized\n", token);
1128}
1129
1130#ifdef MODULE_CCCAM
1131void chk_t_cccam(char *token, char *value)
1132{
1133    if (!strcmp(token, "port")) {
1134        chk_cccam_ports(value);
1135        return;
1136    }
1137    //if (!strcmp(token, "serverip")) { cfg.cc_srvip=cs_inet_addr(value); return; }
1138
1139    if (!strcmp(token, "reshare")) {
1140        cfg.cc_reshare = strToIntVal(value, 0);
1141        return;
1142    }
1143
1144    if (!strcmp(token, "stealth")) {
1145        cfg.cc_stealth = strToIntVal(value, 1);
1146        return;
1147    }
1148
1149    if (!strcmp(token, "nodeid")) {
1150        int8_t i, valid=0;
1151        memset(cfg.cc_fixed_nodeid, 0, 8);
1152        for (i=0;i<8 && value[i] != 0;i++) {
1153            cfg.cc_fixed_nodeid[i] = gethexval(value[i*2]) << 4 | gethexval(value[i*2+1]);
1154            if (cfg.cc_fixed_nodeid[i])
1155                valid=1;
1156        }
1157        cfg.cc_use_fixed_nodeid = valid && i == 8;
1158        return;
1159    }
1160
1161    if (!strcmp(token, "reshare_mode")) {
1162        cfg.cc_reshare_services = strToIntVal(value, 0);
1163        return;
1164    }
1165
1166    if (!strcmp(token, "ignorereshare")) {
1167        cfg.cc_ignore_reshare = strToIntVal(value, 0);
1168        return;
1169    }
1170
1171    if (!strcmp(token, "forward_origin_card")) {
1172        cfg.cc_forward_origin_card = strToIntVal(value, 0);
1173        return;
1174    }
1175
1176    // cccam version
1177    if (!strcmp(token, "version")) {
1178        memset(cfg.cc_version, 0, sizeof(cfg.cc_version));
1179        if (strlen(value) > sizeof(cfg.cc_version) - 1) {
1180            fprintf(stderr, "cccam config: version too long\n");
1181        } else
1182            cs_strncpy((char*)cfg.cc_version, value, sizeof(cfg.cc_version));
1183        return;
1184    }
1185    // cccam: Update cards interval
1186    if (!strcmp(token, "updateinterval")) {
1187        if (value[0] == '-')
1188            cfg.cc_update_interval = DEFAULT_UPDATEINTERVAL;
1189        else
1190            cfg.cc_update_interval = strToIntVal(value, DEFAULT_UPDATEINTERVAL);
1191        return;
1192    }
1193
1194    // cccam: Kind of card updates
1195    if (!strcmp(token, "minimizecards")) {
1196        cfg.cc_minimize_cards = strToIntVal(value, 0);
1197        return;
1198    }
1199
1200    // cccam: keep clients connected
1201    if (!strcmp(token, "keepconnected")) {
1202        cfg.cc_keep_connected = strToIntVal(value, 0);
1203        return;
1204    }
1205
1206
1207    if (token[0] != '#')
1208        fprintf(stderr, "Warning: keyword '%s' in cccam section not recognized\n",token);
1209}
1210#endif
1211
1212void chk_t_radegast(char *token, char *value)
1213{
1214    if (!strcmp(token, "port")) {
1215        cfg.rad_port = strToIntVal(value, 0);
1216        return;
1217    }
1218
1219    if (!strcmp(token, "serverip")) {
1220        if(strlen(value) == 0) {
1221            cfg.rad_srvip = 0;
1222            return;
1223        } else {
1224            cfg.rad_srvip = cs_inet_addr(value);
1225            return;
1226        }
1227    }
1228
1229    if (!strcmp(token, "allowed")) {
1230        if(strlen(value) == 0) {
1231            clear_sip(&cfg.rad_allowed);
1232            return;
1233        } else {
1234            chk_iprange(value, &cfg.rad_allowed);
1235            return;
1236        }
1237    }
1238
1239    if (!strcmp(token, "user")) {
1240        cs_strncpy(cfg.rad_usr, value, sizeof(cfg.rad_usr));
1241        return;
1242    }
1243
1244    if (token[0] != '#')
1245        fprintf(stderr, "Warning: keyword '%s' in radegast section not recognized\n", token);
1246}
1247
1248void chk_t_serial(char *token, char *value)
1249{
1250    if (!strcmp(token, "device")) {
1251        cs_strncpy(cfg.ser_device, value, sizeof(cfg.ser_device));
1252        return;
1253    }
1254    if (token[0] != '#')
1255        fprintf(stderr, "Warning: keyword '%s' in serial section not recognized\n", token);
1256}
1257
1258void chk_t_gbox(char *token, char *value)
1259{
1260    if (!strcmp(token, "gsmsfile")) {
1261        memset(cfg.gbox_gsms_path, 0, sizeof(cfg.gbox_gsms_path));
1262        cs_strncpy(cfg.gbox_gsms_path, value, sizeof(cfg.gbox_gsms_path) - 1);
1263        return;
1264    }
1265
1266    if (!strcmp(token, "hostname")) {
1267        memset(cfg.gbox_hostname, 0, sizeof(cfg.gbox_hostname));
1268        cs_strncpy(cfg.gbox_hostname, value, sizeof(cfg.gbox_hostname) - 1);
1269        return;
1270    }
1271
1272    if (!strcmp(token, "password")) {
1273        memset(cfg.gbox_key, 0, sizeof(cfg.gbox_key));
1274        cs_strncpy(cfg.gbox_key, value, sizeof(cfg.gbox_key) - 1);
1275        return;
1276    }
1277
1278    if (!strcmp(token, "port")) {
1279        cfg.gbox_port = strToIntVal(value, 0);
1280        return;
1281    }
1282
1283    if (token[0] != '#')
1284        fprintf(stderr, "Warning: keyword '%s' in gbox section not recognized\n",token);
1285}
1286
1287#ifdef HAVE_DVBAPI
1288void chk_t_dvbapi(char *token, char *value)
1289{
1290    if (!strcmp(token, "enabled")) {
1291        cfg.dvbapi_enabled = strToIntVal(value, 0);
1292        return;
1293    }
1294
1295    if (!strcmp(token, "au")) {
1296        cfg.dvbapi_au = strToIntVal(value, 0);
1297        return;
1298    }
1299
1300    if (!strcmp(token, "pmt_mode")) {
1301        cfg.dvbapi_pmtmode = strToIntVal(value, 0);
1302        return;
1303    }
1304
1305    if (!strcmp(token, "request_mode")) {
1306        cfg.dvbapi_requestmode = strToIntVal(value, 0);
1307        return;
1308    }
1309
1310    if (!strcmp(token, "boxtype")) {
1311        int32_t i;
1312        for (i=1;i<=BOXTYPES;i++) {
1313            if (strcmp(value, boxdesc[i])==0) {
1314                cfg.dvbapi_boxtype=i;
1315                return;
1316            }
1317        }
1318
1319        cfg.dvbapi_boxtype=0;
1320        return;
1321    }
1322
1323    if (!strcmp(token, "user")) {
1324        cs_strncpy(cfg.dvbapi_usr, value, sizeof(cfg.dvbapi_usr));
1325        return;
1326    }
1327
1328    if(!strcmp(token, "services")) {
1329        chk_services(value, &cfg.dvbapi_sidtabok, &cfg.dvbapi_sidtabno);
1330        return;
1331    }
1332
1333    //obsolete
1334    if (!strcmp(token, "priority")) {
1335        dvbapi_chk_caidtab(value, 'p');
1336        return;
1337    }
1338
1339    if (!strcmp(token, "ignore")) {
1340        dvbapi_chk_caidtab(value, 'i');
1341        return;
1342    }
1343
1344    if (!strcmp(token, "cw_delay")) {
1345        dvbapi_chk_caidtab(value, 'd');
1346        return;
1347    }
1348
1349    if (token[0] != '#')
1350        fprintf(stderr, "Warning: keyword '%s' in dvbapi section not recognized\n",token);
1351}
1352#endif
1353
1354#ifdef LCDSUPPORT
1355void chk_t_lcd(char *token, char *value)
1356{
1357
1358    if (!strcmp(token, "lcd_outputpath")) {
1359        NULLFREE(cfg.lcd_output_path);
1360        if (strlen(value) > 0) {
1361            if(!cs_malloc(&(cfg.lcd_output_path), strlen(value) + 1, -1)) return;
1362            memcpy(cfg.lcd_output_path, value, strlen(value) + 1);
1363        }
1364        return;
1365    }
1366
1367    if (!strcmp(token, "lcd_hideidle")) {
1368        cfg.lcd_hide_idle = strToIntVal(value, 0);
1369        return;
1370    }
1371
1372    if (!strcmp(token, "lcd_writeintervall")) {
1373        cfg.lcd_write_intervall = strToIntVal(value, 10);
1374        if (cfg.lcd_write_intervall < 5)
1375            cfg.lcd_write_intervall = 5;
1376        return;
1377    }
1378
1379    if (token[0] != '#')
1380        fprintf(stderr, "Warning: keyword '%s' in lcd section not recognized\n",token);
1381}
1382#endif
1383
1384static void chk_token(char *token, char *value, int32_t tag)
1385{
1386    switch(tag) {
1387        case TAG_GLOBAL  : chk_t_global(token, value); break;
1388        case TAG_MONITOR : chk_t_monitor(token, value); break;
1389        case TAG_CAMD33  : chk_t_camd33(token, value); break;
1390        case TAG_CAMD35  :
1391        case TAG_CS357X  : chk_t_camd35(token, value); break;
1392        case TAG_NEWCAMD : chk_t_newcamd(token, value); break;
1393        case TAG_RADEGAST: chk_t_radegast(token, value); break;
1394        case TAG_SERIAL  : chk_t_serial(token, value); break;
1395        case TAG_CS378X  : chk_t_camd35_tcp(token, value); break;
1396#ifdef MODULE_CCCAM
1397        case TAG_CCCAM   : chk_t_cccam(token, value); break;
1398#endif
1399        case TAG_GBOX    : chk_t_gbox(token, value); break;
1400
1401#ifdef HAVE_DVBAPI
1402        case TAG_DVBAPI  : chk_t_dvbapi(token, value); break;
1403#else
1404        case TAG_DVBAPI  : fprintf(stderr, "OSCam compiled without DVB API support. Parameter %s ignored\n", token); break;
1405#endif
1406
1407
1408#ifdef WEBIF
1409        case TAG_WEBIF   : chk_t_webif(token, value); break;
1410#else
1411        case TAG_WEBIF   : fprintf(stderr, "OSCam compiled without Webinterface support. Parameter %s ignored\n", token); break;
1412#endif
1413
1414
1415#ifdef CS_ANTICASC
1416        case TAG_ANTICASC: chk_t_ac(token, value); break;
1417#else
1418        case TAG_ANTICASC: fprintf(stderr, "OSCam compiled without Anticascading support. Parameter %s ignored\n", token); break;
1419#endif
1420
1421#ifdef LCDSUPPORT
1422        case TAG_LCD: chk_t_lcd(token, value); break;
1423#else
1424        case TAG_LCD: fprintf(stderr, "OSCam compiled without LCD support. Parameter %s ignored\n", token); break;
1425#endif
1426
1427    }
1428}
1429
1430void init_len4caid()
1431{
1432    int32_t nr;
1433    FILE *fp;
1434    char *value;
1435
1436    memset(len4caid, 0, sizeof(uint16_t)<<8);
1437    snprintf(token, sizeof(token), "%s%s", cs_confdir, cs_l4ca);
1438    if (!(fp = fopen(token, "r")))
1439        return;
1440    for(nr = 0; fgets(token, sizeof(token), fp);) {
1441        int32_t i, c;
1442        char *ptr;
1443        if (!(value=strchr(token, ':')))
1444            continue;
1445        *value++ ='\0';
1446        if( (ptr = strchr(value, '#')) )
1447            *ptr = '\0';
1448        if (strlen(trim(token)) != 2)
1449            continue;
1450        if (strlen(trim(value)) != 4)
1451            continue;
1452        if ((i = byte_atob(token)) < 0)
1453            continue;
1454        if ((c = word_atob(value)) < 0)
1455            continue;
1456        len4caid[i] = c;
1457        nr++;
1458    }
1459    fclose(fp);
1460    cs_log("%d lengths for caid guessing loaded", nr);
1461    return;
1462}
1463
1464int32_t search_boxkey(uint16_t caid, char *key)
1465{
1466    int32_t i, rc = 0;
1467    FILE *fp;
1468    char c_caid[512];
1469
1470    snprintf(c_caid, sizeof(c_caid), "%s%s", cs_confdir, cs_cert);
1471    fp = fopen(c_caid, "r");
1472    if (fp) {
1473        for (; (!rc) && fgets(c_caid, sizeof(c_caid), fp);) {
1474            char *c_provid, *c_key;
1475
1476            c_provid = strchr(c_caid, '#');
1477            if (c_provid)
1478                *c_provid = '\0';
1479            if (!(c_provid = strchr(c_caid, ':')))
1480                continue;
1481            *c_provid++ ='\0';
1482            if (!(c_key = strchr(c_provid, ':')))
1483                continue;
1484            *c_key++ ='\0';
1485            if (word_atob(trim(c_caid))!=caid)
1486                continue;
1487            if ((i=(strlen(trim(c_key))>>1)) > 256)
1488                continue;
1489            if (cs_atob((uchar *)key, c_key, i) < 0) {
1490                cs_log("wrong key in \"%s\"", cs_cert);
1491                continue;
1492            }
1493            rc = 1;
1494        }
1495        fclose(fp);
1496    }
1497#ifdef OSCAM_INBUILD_KEYS
1498    for(i=0; (!rc) && (npkey[i].keylen); i++)
1499        if (rc=((caid==npkey[i].caid) && (npkey[i].provid==0)))
1500            memcpy(key, npkey[i].key, npkey[i].keylen);
1501#endif
1502    return(rc);
1503}
1504
1505int32_t init_config()
1506{
1507    int32_t tag=TAG_GLOBAL;
1508    FILE *fp;
1509    char *value=NULL;
1510
1511#ifndef CS_EMBEDDED
1512#ifdef PRIO_PROCESS
1513    errno=0;
1514    if ((cfg.nice = getpriority(PRIO_PROCESS, 0)) == (-1))
1515    if (errno)
1516#endif
1517#endif
1518    cfg.nice = 99;
1519    cfg.ctimeout = CS_CLIENT_TIMEOUT;
1520    cfg.ftimeout = CS_CLIENT_TIMEOUT / 2;
1521    cfg.cmaxidle = CS_CLIENT_MAXIDLE;
1522    cfg.delay = CS_DELAY;
1523    cfg.bindwait = CS_BIND_TIMEOUT;
1524    cfg.mon_level = 2;
1525    cfg.mon_hideclient_to = 0;
1526    cfg.srtimeout = 1500;
1527    cfg.ulparent = 0;
1528    cfg.logfile = NULL;
1529    cfg.usrfile = NULL;
1530    cfg.mailfile = NULL;
1531    cfg.max_log_size = 10;
1532    cfg.disableuserfile = 1;
1533    cfg.disablemail = 1;
1534#ifdef CS_LOGHISTORY
1535    cfg.loghistorysize = 0;
1536    cs_reinit_loghist(4096);
1537#endif
1538    cfg.cwlogdir = NULL;
1539    cfg.emmlogdir = NULL;
1540    cfg.reader_restart_seconds = 5;
1541    cfg.waitforcards = 1;
1542    cfg.waitforcards_extra_delay = 500;
1543#ifdef QBOXHD_LED
1544    cfg.disableqboxhdled = 1;
1545#endif
1546
1547#ifdef WEBIF
1548    cs_strncpy(cfg.http_user, "", sizeof(cfg.http_user));
1549    cs_strncpy(cfg.http_pwd, "", sizeof(cfg.http_pwd));
1550    cs_strncpy(cfg.http_css, "", sizeof(cfg.http_css));
1551    cs_strncpy(cfg.http_help_lang, "en", sizeof(cfg.http_help_lang));
1552    cfg.http_refresh = 0;
1553    cfg.http_hide_idle_clients = 0;
1554    cfg.mon_hideclient_to = 15;
1555    cs_strncpy(cfg.http_tpl, "", sizeof(cfg.http_tpl));
1556#endif
1557    cfg.ncd_keepalive = 1;
1558#ifdef CS_ANTICASC
1559    cfg.ac_enabled = 0;
1560    cfg.ac_users = 0;
1561    cfg.ac_stime = 2;
1562    cfg.ac_samples = 10;
1563    cfg.ac_denysamples = 8;
1564    cfg.ac_fakedelay = 1000;
1565    cs_strncpy(cfg.ac_logfile, "./oscam_ac.log", sizeof(cfg.ac_logfile));
1566#endif
1567#ifdef MODULE_CCCAM
1568    cfg.cc_update_interval = DEFAULT_UPDATEINTERVAL;
1569    cfg.cc_keep_connected = 1;
1570    cfg.cc_reshare = 10;
1571#endif
1572
1573#ifdef WITH_LB
1574    //loadbalancer defaults:
1575    cfg.lb_mode = DEFAULT_LB_MODE;
1576    cfg.lb_nbest_readers = DEFAULT_NBEST;
1577    cfg.lb_nfb_readers = DEFAULT_NFB;
1578    cfg.lb_min_ecmcount = DEFAULT_MIN_ECM_COUNT;
1579    cfg.lb_max_ecmcount = DEFAULT_MAX_ECM_COUNT;
1580    cfg.lb_reopen_seconds = DEFAULT_REOPEN_SECONDS;
1581    cfg.lb_retrylimit = DEFAULT_RETRYLIMIT;
1582    cfg.lb_stat_cleanup = DEFAULT_LB_STAT_CLEANUP;
1583    cfg.lb_auto_betatunnel = DEFAULT_LB_AUTO_BETATUNNEL;
1584    //end loadbalancer defaults
1585#endif
1586
1587#ifdef LCDSUPPORT
1588    cfg.lcd_hide_idle = 0;
1589    cfg.lcd_write_intervall = 10;
1590#endif
1591
1592    snprintf(token, sizeof(token), "%s%s", cs_confdir, cs_conf);
1593    if (!(fp = fopen(token, "r"))) {
1594        fprintf(stderr, "Cannot open config file '%s' (errno=%d %s)\n", token, errno, strerror(errno));
1595        exit(1);
1596    }
1597    while (fgets(token, sizeof(token), fp)) {
1598        int32_t i, l;
1599        //void *ptr;
1600        if ((l = strlen(trim(token))) < 3)
1601            continue;
1602        if ((token[0] == '[') && (token[l-1] == ']')) {
1603            for (token[l-1] = 0, tag = -1, i = TAG_GLOBAL; cctag[i]; i++)
1604                if (!strcmp(cctag[i], strtolower(token+1)))
1605                    tag = i;
1606            continue;
1607        }
1608        if (!(value=strchr(token, '=')))
1609            continue;
1610        *value++ ='\0';
1611        chk_token(trim(strtolower(token)), trim(value), tag);
1612    }
1613    fclose(fp);
1614
1615    if (cfg.logfile == NULL && cfg.logtostdout == 0 && cfg.logtosyslog == 0) {
1616        if(cs_malloc(&(cfg.logfile), strlen(CS_LOGFILE) + 1, -1))
1617            memcpy(cfg.logfile, CS_LOGFILE, strlen(CS_LOGFILE) + 1);
1618        else cfg.logtostdout = 1;
1619    }
1620    if(cfg.usrfile == NULL) cfg.disableuserfile = 1;
1621    if(cfg.mailfile == NULL) cfg.disablemail = 1;
1622
1623    cs_init_log();
1624    cs_init_statistics();
1625    if (cfg.ftimeout >= cfg.ctimeout) {
1626        cfg.ftimeout = cfg.ctimeout - 100;
1627        cs_log("WARNING: fallbacktimeout adjusted to %u ms (must be smaller than clienttimeout (%u ms))", cfg.ftimeout, cfg.ctimeout);
1628    }
1629    if(cfg.ftimeout < cfg.srtimeout) {
1630        cfg.ftimeout = cfg.srtimeout + 100;
1631        cs_log("WARNING: fallbacktimeout adjusted to %u ms (must be greater than serialreadertimeout (%u ms))", cfg.ftimeout, cfg.srtimeout);
1632    }
1633    if(cfg.ctimeout < cfg.srtimeout) {
1634        cfg.ctimeout = cfg.srtimeout + 100;
1635        cs_log("WARNING: clienttimeout adjusted to %u ms (must be greater than serialreadertimeout (%u ms))", cfg.ctimeout, cfg.srtimeout);
1636    }
1637#ifdef CS_ANTICASC
1638    if( cfg.ac_denysamples+1 > cfg.ac_samples ) {
1639        cfg.ac_denysamples = cfg.ac_samples - 1;
1640        cs_log("WARNING: DenySamples adjusted to %d", cfg.ac_denysamples);
1641    }
1642#endif
1643    return 0;
1644}
1645
1646void chk_account(const char *token, char *value, struct s_auth *account)
1647{
1648    int32_t i;
1649    char *ptr1, *saveptr1 = NULL;
1650
1651    if (!strcmp(token, "user")) {
1652        cs_strncpy(account->usr, value, sizeof(account->usr));
1653        return;
1654    }
1655
1656    if (!strcmp(token, "pwd")) {
1657        cs_strncpy(account->pwd, value, sizeof(account->pwd));
1658        return;
1659    }
1660#ifdef WEBIF
1661    if (!strcmp(token, "description")) {
1662        cs_strncpy(account->description, value, sizeof(account->description));
1663        return;
1664    }
1665#endif
1666
1667    if (!strcmp(token, "hostname")) {
1668        cs_strncpy((char *)account->dyndns, value, sizeof(account->dyndns));
1669        return;
1670    }
1671
1672    if (!strcmp(token, "betatunnel")) {
1673        if(strlen(value) == 0) {
1674            clear_tuntab(&account->ttab);
1675            return;
1676        } else {
1677            chk_tuntab(value, &account->ttab);
1678            return;
1679        }
1680    }
1681
1682    if (!strcmp(token, "uniq")) {
1683        account->uniq = strToIntVal(value, 0);
1684        return;
1685    }
1686
1687    if (!strcmp(token, "sleep")) {
1688        account->tosleep = strToIntVal(value, cfg.tosleep);
1689        return;
1690    }
1691
1692    if (!strcmp(token, "sleepsend")) {
1693        uint32_t tmp = strToUIntVal(value, 0);
1694        if (tmp > 0xFF)
1695            account->c35_sleepsend = 0xFF;
1696        else account->c35_sleepsend = tmp;
1697        return;
1698    }
1699
1700    if (!strcmp(token, "monlevel")) {
1701        account->monlvl = strToIntVal(value, 0);
1702        return;
1703    }
1704
1705    if (!strcmp(token, "caid")) {
1706        if(strlen(value) == 0) {
1707            clear_caidtab(&account->ctab);
1708            return;
1709        } else {
1710            chk_caidtab(value, &account->ctab);
1711            return;
1712        }
1713    }
1714
1715    if (!strcmp(token, "disabled")) {
1716        account->disabled = strToIntVal(value, 0);
1717        return;
1718    }
1719
1720    if (!strcmp(token, "suppresscmd08")) {
1721        account->c35_suppresscmd08 = strToIntVal(value, 0);
1722        return;
1723    }
1724
1725#ifdef MODULE_CCCAM
1726    if (!strcmp(token, "cccmaxhops")) {
1727        account->cccmaxhops = strToIntVal(value, 10);
1728        return;
1729    }
1730
1731    if (!strcmp(token, "cccreshare")) {
1732        account->cccreshare = strToIntVal(value, -1);
1733        if (account->cccreshare == cfg.cc_reshare)
1734            account->cccreshare = -1;
1735        return;
1736    }
1737
1738    if (!strcmp(token, "cccignorereshare")) {
1739        account->cccignorereshare = strToIntVal(value, -1);
1740        if (account->cccignorereshare == cfg.cc_ignore_reshare)
1741            account->cccignorereshare = -1;
1742        return;
1743    }
1744
1745    if (!strcmp(token, "cccstealth")) {
1746        account->cccstealth = strToIntVal(value, -1);
1747        if (account->cccstealth == cfg.cc_stealth)
1748            account->cccstealth = -1;
1749        return;
1750    }
1751#endif
1752
1753    if (!strcmp(token, "keepalive")) {
1754        account->ncd_keepalive = strToIntVal(value, 1);
1755        return;
1756    }
1757    /*
1758    *  case insensitive
1759    */
1760    strtolower(value);
1761
1762    if (!strcmp(token, "au")) {
1763
1764        // set default values for usage during runtime from Webif
1765        account->autoau = 0;
1766
1767        if (!account->aureader_list)
1768            account->aureader_list = ll_create();
1769
1770        if(value && value[0] == '1') {
1771            account->autoau = 1;
1772        }
1773        ll_clear(account->aureader_list);
1774       
1775        // exit if invalid or no value
1776        if ((strlen(value) == 0) || (value[0] == '0'))
1777            return;
1778           
1779        LL_ITER itr = ll_iter_create(configured_readers);       
1780        struct s_reader *rdr;
1781        char *pch;
1782
1783        for (pch = strtok_r(value, ",", &saveptr1); pch != NULL; pch = strtok_r(NULL, ",", &saveptr1)) {
1784            ll_iter_reset(&itr);
1785            while ((rdr = ll_iter_next(&itr))) {
1786                if (((rdr->label[0]) && (!strcmp(rdr->label, pch))) || account->autoau) {
1787                    ll_append(account->aureader_list, rdr);
1788                }
1789            }
1790        }
1791        return;
1792    }
1793
1794    if (!strcmp(token, "group")) {
1795        account->grp = 0;
1796        for (ptr1=strtok_r(value, ",", &saveptr1); ptr1; ptr1=strtok_r(NULL, ",", &saveptr1)) {
1797            int32_t g;
1798            g = atoi(ptr1);
1799            if ((g>0) && (g < 65)) account->grp|=(((uint64_t)1)<<(g-1));
1800        }
1801        return;
1802    }
1803
1804    if(!strcmp(token, "services")) {
1805        chk_services(value, &account->sidtabok, &account->sidtabno);
1806        return;
1807    }
1808
1809    if(!strcmp(token, "ident")) { /*ToDo ftab clear*/
1810        chk_ftab(value, &account->ftab, "user", account->usr, "provid");
1811        return;
1812    }
1813
1814    if(!strcmp(token, "class")) {
1815        chk_cltab(value, &account->cltab);
1816        return;
1817    }
1818
1819    if(!strcmp(token, "chid")) {
1820        chk_ftab(value, &account->fchid, "user", account->usr, "chid");
1821        return;
1822    }
1823
1824    if (!strcmp(token, "expdate")) {
1825        if (!value[0]) {
1826            account->expirationdate=(time_t)NULL;
1827            return;
1828        }
1829        struct tm cstime;
1830        memset(&cstime,0,sizeof(cstime));
1831        for (i=0, ptr1=strtok_r(value, "-/", &saveptr1); (i<3)&&(ptr1); ptr1=strtok_r(NULL, "-/", &saveptr1), i++) {
1832            switch(i) {
1833                case 0: cstime.tm_year=atoi(ptr1)-1900; break;
1834                case 1: cstime.tm_mon =atoi(ptr1)-1;    break;
1835                case 2: cstime.tm_mday=atoi(ptr1);      break;
1836            }
1837        }
1838        account->expirationdate=mktime(&cstime);
1839        return;
1840    }
1841
1842    if (!strcmp(token, "allowedtimeframe")) {
1843        if(strlen(value) == 0) {
1844            account->allowedtimeframe[0] = 0;
1845            account->allowedtimeframe[1] = 0;
1846        } else {
1847            int32_t allowed[4];
1848            if (sscanf(value, "%d:%d-%d:%d", &allowed[0], &allowed[1], &allowed[2], &allowed[3]) != 4) {
1849                account->allowedtimeframe[0] = 0;
1850                account->allowedtimeframe[1] = 0;
1851                fprintf(stderr, "Warning: value '%s' is not valid for allowedtimeframe (hh:mm-hh:mm)\n", value);
1852            } else {
1853                account->allowedtimeframe[0] = (allowed[0]*60) + allowed[1];
1854                account->allowedtimeframe[1] = (allowed[2]*60) + allowed[3];
1855            }
1856        }
1857        return;
1858    }
1859
1860    if (!strcmp(token, "failban")) {
1861        account->failban = strToIntVal(value, 0);
1862        return;
1863    }
1864
1865#ifdef CS_ANTICASC
1866    if( !strcmp(token, "numusers") ) {
1867        account->ac_users = strToIntVal(value, 0);
1868        return;
1869    }
1870
1871    if( !strcmp(token, "penalty") ) {
1872        account->ac_penalty = strToIntVal(value, 0);
1873        return;
1874    }
1875#endif
1876
1877    if (token[0] != '#')
1878        fprintf(stderr, "Warning: keyword '%s' in account section not recognized\n",token);
1879}
1880
1881int32_t write_services()
1882{
1883    int32_t i;
1884    FILE *f;
1885    struct s_sidtab *sidtab = cfg.sidtab;
1886    char tmpfile[256];
1887    char destfile[256];
1888    char bakfile[256];
1889    char *ptr;
1890
1891    snprintf(destfile, sizeof(destfile),"%s%s", cs_confdir, cs_sidt);
1892    snprintf(tmpfile, sizeof(tmpfile), "%s%s.tmp", cs_confdir, cs_sidt);
1893    snprintf(bakfile, sizeof(bakfile),"%s%s.bak", cs_confdir, cs_sidt);
1894
1895    if (!(f=fopen(tmpfile, "w"))){
1896        cs_log("Cannot open file \"%s\" (errno=%d %s)", tmpfile, errno, strerror(errno));
1897        return(1);
1898    }
1899    fprintf(f,"# oscam.services generated automatically by Streamboard OSCAM %s build #%s\n", CS_VERSION, CS_SVN_VERSION);
1900    fprintf(f,"# Read more: http://streamboard.gmc.to/svn/oscam/trunk/Distribution/doc/txt/oscam.services.txt\n\n");
1901
1902    while(sidtab != NULL){
1903        ptr = sidtab->label;
1904        while (*ptr) {
1905            if (*ptr == ' ') *ptr = '_';
1906            ptr++;
1907        }
1908        fprintf(f,"[%s]\n", sidtab->label);
1909        fprintf_conf(f, CONFVARWIDTH, "caid", "");
1910        for (i=0; i<sidtab->num_caid; i++){
1911            if (i==0) fprintf(f,"%04X", sidtab->caid[i]);
1912            else fprintf(f,",%04X", sidtab->caid[i]);
1913        }
1914        fputc((int)'\n', f);
1915        fprintf_conf(f, CONFVARWIDTH, "provid", "");
1916        for (i=0; i<sidtab->num_provid; i++){
1917            if (i==0) fprintf(f,"%06X", sidtab->provid[i]);
1918            else fprintf(f,",%06X", sidtab->provid[i]);
1919        }
1920        fputc((int)'\n', f);
1921        fprintf_conf(f, CONFVARWIDTH, "srvid", "");
1922        for (i=0; i<sidtab->num_srvid; i++){
1923            if (i==0) fprintf(f,"%04X", sidtab->srvid[i]);
1924            else fprintf(f,",%04X", sidtab->srvid[i]);
1925        }
1926        fprintf(f,"\n\n");
1927        sidtab=sidtab->next;
1928    }
1929
1930    fclose(f);
1931    return(safe_overwrite_with_bak(destfile, tmpfile, bakfile, 0));
1932}
1933
1934int32_t write_config()
1935{
1936    int32_t i;
1937    FILE *f;
1938    char *value, *saveptr1 = NULL;
1939    char tmpfile[256];
1940    char destfile[256];
1941    char bakfile[256];
1942
1943    snprintf(destfile, sizeof(destfile),"%s%s", cs_confdir, cs_conf);
1944    snprintf(tmpfile, sizeof(tmpfile), "%s%s.tmp", cs_confdir, cs_conf);
1945    snprintf(bakfile, sizeof(bakfile),"%s%s.bak", cs_confdir, cs_conf);
1946
1947    if (!(f=fopen(tmpfile, "w"))){
1948        cs_log("Cannot open file \"%s\" (errno=%d %s)", tmpfile, errno, strerror(errno));
1949        return(1);
1950    }
1951    fprintf(f,"# oscam.conf generated automatically by Streamboard OSCAM %s build #%s\n", CS_VERSION, CS_SVN_VERSION);
1952    fprintf(f,"# Read more: http://streamboard.gmc.to/svn/oscam/trunk/Distribution/doc/txt/oscam.conf.txt\n\n");
1953
1954    /*global settings*/
1955    fprintf(f,"[global]\n");
1956    if (cfg.srvip != 0 || cfg.http_full_cfg)
1957        fprintf_conf(f, CONFVARWIDTH, "serverip", "%s\n", cs_inet_ntoa(cfg.srvip));
1958    if (cfg.usrfile != NULL || cfg.http_full_cfg)
1959        fprintf_conf(f, CONFVARWIDTH, "usrfile", "%s\n", cfg.usrfile?cfg.usrfile:"");
1960    if (cfg.mailfile != NULL || cfg.http_full_cfg)
1961        fprintf_conf(f, CONFVARWIDTH, "mailfile", "%s\n", cfg.mailfile?cfg.mailfile:"");
1962    if (cfg.logfile != NULL || cfg.logtostdout == 1 || cfg.logtosyslog == 1 || cfg.http_full_cfg){
1963        value = mk_t_logfile();
1964        fprintf_conf(f, CONFVARWIDTH, "logfile", "%s\n", value);
1965        free_mk_t(value);
1966    }
1967    if (cfg.cwlogdir != NULL || cfg.http_full_cfg)
1968        fprintf_conf(f, CONFVARWIDTH, "cwlogdir", "%s\n", cfg.cwlogdir?cfg.cwlogdir:"");
1969    if (cfg.emmlogdir != NULL || cfg.http_full_cfg)
1970        fprintf_conf(f, CONFVARWIDTH, "emmlogdir", "%s\n", cfg.emmlogdir?cfg.emmlogdir:"");
1971#ifdef QBOXHD_LED
1972    if (cfg.disableqboxhdled || cfg.http_full_cfg)
1973        fprintf_conf(f, CONFVARWIDTH, "disableqboxhdled", "%d\n", cfg.disableqboxhdled);
1974#endif
1975    if (cfg.disablelog || cfg.http_full_cfg)
1976        fprintf_conf(f, CONFVARWIDTH, "disablelog", "%d\n", cfg.disablelog);
1977    if ((cfg.usrfile && cfg.disableuserfile == 0) || cfg.http_full_cfg)
1978        fprintf_conf(f, CONFVARWIDTH, "disableuserfile", "%d\n", cfg.usrfile?cfg.disableuserfile:1);
1979    if ((cfg.mailfile && cfg.disablemail == 0) || cfg.http_full_cfg)
1980        fprintf_conf(f, CONFVARWIDTH, "disablemail", "%d\n", cfg.mailfile?cfg.disablemail:1);
1981    if ((cfg.loghistorysize != 4096) || cfg.http_full_cfg)
1982        fprintf_conf(f, CONFVARWIDTH, "loghistorysize", "%u\n", cfg.loghistorysize);
1983    if (cfg.usrfileflag || cfg.http_full_cfg)
1984        fprintf_conf(f, CONFVARWIDTH, "usrfileflag", "%d\n", cfg.usrfileflag);
1985    if (cfg.ctimeout != CS_CLIENT_TIMEOUT || cfg.http_full_cfg)
1986        fprintf_conf(f, CONFVARWIDTH, "clienttimeout", "%u\n", cfg.ctimeout);
1987    if ((cfg.ftimeout && cfg.ftimeout != (CS_CLIENT_TIMEOUT /2)) || cfg.http_full_cfg)
1988        fprintf_conf(f, CONFVARWIDTH, "fallbacktimeout", "%u\n", cfg.ftimeout);
1989    if (cfg.cmaxidle != CS_CLIENT_MAXIDLE || cfg.http_full_cfg)
1990        fprintf_conf(f, CONFVARWIDTH, "clientmaxidle", "%u\n", cfg.cmaxidle);
1991    if (cfg.failbantime || cfg.http_full_cfg)
1992        fprintf_conf(f, CONFVARWIDTH, "failbantime", "%d\n", cfg.failbantime);
1993    if (cfg.failbancount || cfg.http_full_cfg)
1994        fprintf_conf(f, CONFVARWIDTH, "failbancount", "%d\n", cfg.failbancount);
1995    if (cfg.delay != CS_DELAY || cfg.http_full_cfg)
1996        fprintf_conf(f, CONFVARWIDTH, "cachedelay", "%u\n", cfg.delay); //deprecated
1997    if (cfg.bindwait != CS_BIND_TIMEOUT || cfg.http_full_cfg)
1998        fprintf_conf(f, CONFVARWIDTH, "bindwait", "%d\n", cfg.bindwait);
1999    if (cfg.netprio || cfg.http_full_cfg)
2000        fprintf_conf(f, CONFVARWIDTH, "netprio", "%ld\n", cfg.netprio);
2001    if (cfg.tosleep || cfg.http_full_cfg)
2002        fprintf_conf(f, CONFVARWIDTH, "sleep", "%d\n", cfg.tosleep);
2003    if (cfg.ulparent || cfg.http_full_cfg)
2004        fprintf_conf(f, CONFVARWIDTH, "unlockparental", "%d\n", cfg.ulparent);
2005    if (cfg.nice != 99 || cfg.http_full_cfg)
2006        fprintf_conf(f, CONFVARWIDTH, "nice", "%d\n", cfg.nice);
2007    if (cfg.srtimeout != 1500 || cfg.http_full_cfg)
2008        fprintf_conf(f, CONFVARWIDTH, "serialreadertimeout", "%u\n", cfg.srtimeout);
2009    if (cfg.c35_suppresscmd08 || cfg.http_full_cfg)
2010        fprintf_conf(f, CONFVARWIDTH, "suppresscmd08", "%d\n", cfg.c35_suppresscmd08);
2011    if (cfg.max_log_size != 10 || cfg.http_full_cfg)
2012        fprintf_conf(f, CONFVARWIDTH, "maxlogsize", "%d\n", cfg.max_log_size);
2013    if (!cfg.waitforcards || cfg.http_full_cfg)
2014        fprintf_conf(f, CONFVARWIDTH, "waitforcards", "%d\n", cfg.waitforcards);
2015    if (cfg.waitforcards_extra_delay != 500 || cfg.http_full_cfg)
2016        fprintf_conf(f, CONFVARWIDTH, "waitforcards_extra_delay", "%d\n", cfg.waitforcards_extra_delay);
2017    if (cfg.preferlocalcards || cfg.http_full_cfg)
2018        fprintf_conf(f, CONFVARWIDTH, "preferlocalcards", "%d\n", cfg.preferlocalcards);
2019    if (cfg.saveinithistory || cfg.http_full_cfg)
2020        fprintf_conf(f, CONFVARWIDTH, "saveinithistory", "%d\n", cfg.saveinithistory);
2021    if (cfg.reader_restart_seconds != 5 || cfg.http_full_cfg)
2022        fprintf_conf(f, CONFVARWIDTH, "readerrestartseconds", "%d\n", cfg.reader_restart_seconds);
2023    if (cfg.dropdups || cfg.http_full_cfg)
2024        fprintf_conf(f, CONFVARWIDTH, "dropdups", "%d\n", cfg.dropdups);
2025
2026#ifdef WITH_LB
2027    if (cfg.lb_mode != DEFAULT_LB_MODE || cfg.http_full_cfg)
2028        fprintf_conf(f, CONFVARWIDTH, "lb_mode", "%d\n", cfg.lb_mode);
2029    if (cfg.lb_save || cfg.http_full_cfg)
2030        fprintf_conf(f, CONFVARWIDTH, "lb_save", "%d\n", cfg.lb_save);
2031    if (cfg.lb_nbest_readers != DEFAULT_NBEST || cfg.http_full_cfg)
2032        fprintf_conf(f, CONFVARWIDTH, "lb_nbest_readers", "%d\n", cfg.lb_nbest_readers);
2033    if (cfg.lb_nfb_readers != DEFAULT_NFB || cfg.http_full_cfg)
2034        fprintf_conf(f, CONFVARWIDTH, "lb_nfb_readers", "%d\n", cfg.lb_nfb_readers);
2035    if (cfg.lb_min_ecmcount != DEFAULT_MIN_ECM_COUNT || cfg.http_full_cfg)
2036        fprintf_conf(f, CONFVARWIDTH, "lb_min_ecmcount", "%d\n", cfg.lb_min_ecmcount);
2037    if (cfg.lb_max_ecmcount != DEFAULT_MAX_ECM_COUNT || cfg.http_full_cfg)
2038        fprintf_conf(f, CONFVARWIDTH, "lb_max_ecmcount", "%d\n", cfg.lb_max_ecmcount);
2039    if (cfg.lb_reopen_seconds != DEFAULT_REOPEN_SECONDS || cfg.http_full_cfg)
2040        fprintf_conf(f, CONFVARWIDTH, "lb_reopen_seconds", "%d\n", cfg.lb_reopen_seconds);
2041    if (cfg.lb_retrylimit != DEFAULT_RETRYLIMIT || cfg.http_full_cfg)
2042        fprintf_conf(f, CONFVARWIDTH, "lb_retrylimit", "%d\n", cfg.lb_retrylimit);
2043    if (cfg.lb_retrylimittab.n > 0 || cfg.http_full_cfg) {
2044        char *value = mk_t_caidvaluetab(&cfg.lb_retrylimittab);
2045        fprintf_conf(f, CONFVARWIDTH, "lb_retrylimits", "%s\n", value);
2046        free_mk_t(value);
2047    }
2048    if (cfg.lb_nbest_readers_tab.n > 0 || cfg.http_full_cfg) {
2049        char *value = mk_t_caidvaluetab(&cfg.lb_nbest_readers_tab);
2050        fprintf_conf(f, CONFVARWIDTH, "lb_nbest_percaid", "%s\n", value);
2051        free_mk_t(value);
2052    }
2053
2054    if (cfg.lb_noproviderforcaid.caid[0] || cfg.http_full_cfg) {
2055        value = mk_t_caidtab(&cfg.lb_noproviderforcaid);
2056        fprintf_conf(f, CONFVARWIDTH, "lb_noproviderforcaid", "%s\n", value);
2057        free_mk_t(value);
2058    }
2059
2060    if (cfg.lb_savepath || cfg.http_full_cfg)
2061        fprintf_conf(f, CONFVARWIDTH, "lb_savepath", "%s\n", cfg.lb_savepath?cfg.lb_savepath:"");
2062    if (cfg.lb_stat_cleanup != DEFAULT_LB_STAT_CLEANUP || cfg.http_full_cfg)
2063        fprintf_conf(f, CONFVARWIDTH, "lb_stat_cleanup", "%d\n", cfg.lb_stat_cleanup);
2064    if (cfg.lb_use_locking != DEFAULT_LB_USE_LOCKING || cfg.http_full_cfg)
2065        fprintf_conf(f, CONFVARWIDTH, "lb_use_locking", "%d\n", cfg.lb_use_locking);
2066    if (cfg.lb_reopen_mode != DEFAULT_LB_REOPEN_MODE || cfg.http_full_cfg)
2067        fprintf_conf(f, CONFVARWIDTH, "lb_reopen_mode", "%d\n", cfg.lb_reopen_mode);
2068    if (cfg.lb_max_readers || cfg.http_full_cfg)
2069        fprintf_conf(f, CONFVARWIDTH, "lb_max_readers", "%d\n", cfg.lb_max_readers);
2070    if (cfg.lb_auto_betatunnel != DEFAULT_LB_AUTO_BETATUNNEL || cfg.http_full_cfg)
2071        fprintf_conf(f, CONFVARWIDTH, "lb_auto_betatunnel", "%d\n", cfg.lb_auto_betatunnel);
2072#endif
2073
2074    if (cfg.resolve_gethostbyname || cfg.http_full_cfg)
2075        fprintf_conf(f, CONFVARWIDTH, "resolvegethostbyname", "%d\n", cfg.resolve_gethostbyname);
2076
2077#ifdef CS_WITH_DOUBLECHECK
2078    if (cfg.double_check ||(!cfg.double_check && cfg.http_full_cfg))
2079        fprintf_conf(f, CONFVARWIDTH, "double_check", "%d\n", cfg.double_check);
2080#endif
2081
2082    fputc((int)'\n', f);
2083
2084    /*monitor settings*/
2085    if(cfg.mon_port || cfg.mon_appendchaninfo || cfg.mon_hideclient_to != 0 || cfg.mon_aulow != 30) {
2086        fprintf(f,"[monitor]\n");
2087        if (cfg.mon_port != 0 || cfg.http_full_cfg)
2088            fprintf_conf(f, CONFVARWIDTH, "port", "%d\n", cfg.mon_port);
2089        if (cfg.mon_srvip != 0 || cfg.http_full_cfg)
2090            fprintf_conf(f, CONFVARWIDTH, "serverip", "%s\n", cs_inet_ntoa(cfg.mon_srvip));
2091        value = mk_t_iprange(cfg.mon_allowed);
2092        if(strlen(value) > 0 || cfg.http_full_cfg)
2093            fprintf_conf(f, CONFVARWIDTH, "nocrypt", "%s\n", value);
2094        free_mk_t(value);
2095        if(cfg.mon_aulow != 30 || cfg.http_full_cfg)
2096            fprintf_conf(f, CONFVARWIDTH, "aulow", "%d\n", cfg.mon_aulow);
2097        if(cfg.mon_hideclient_to != 0 || cfg.http_full_cfg)
2098            fprintf_conf(f, CONFVARWIDTH, "hideclient_to", "%d\n", cfg.mon_hideclient_to);
2099        if(cfg.mon_level != 2 || cfg.http_full_cfg)
2100            fprintf_conf(f, CONFVARWIDTH, "monlevel", "%d\n", cfg.mon_level);
2101        if(cfg.mon_appendchaninfo != 2 || cfg.http_full_cfg)
2102            fprintf_conf(f, CONFVARWIDTH, "appendchaninfo", "%d\n", cfg.mon_appendchaninfo);
2103        fputc((int)'\n', f);
2104    }
2105
2106    /*newcamd*/
2107    if ((cfg.ncd_ptab.nports > 0) && (cfg.ncd_ptab.ports[0].s_port > 0)){
2108
2109        fprintf(f,"[newcamd]\n");
2110
2111        value = mk_t_newcamd_port();
2112        fprintf_conf(f, CONFVARWIDTH, "port", "%s\n", value);
2113        free_mk_t(value);
2114
2115        if (cfg.ncd_srvip != 0)
2116            fprintf_conf(f, CONFVARWIDTH, "serverip", "%s\n", cs_inet_ntoa(cfg.ncd_srvip));
2117        fprintf_conf(f, CONFVARWIDTH, "key", "");
2118        for (i = 0; i < 14; i++) fprintf(f,"%02X", cfg.ncd_key[i]);
2119        fprintf(f,"\n");
2120        value = mk_t_iprange(cfg.ncd_allowed);
2121        if(strlen(value) > 0 || cfg.http_full_cfg)
2122            fprintf_conf(f, CONFVARWIDTH, "allowed", "%s\n", value);
2123        free_mk_t(value);
2124        if(cfg.ncd_keepalive != 1 || cfg.http_full_cfg)
2125            fprintf_conf(f, CONFVARWIDTH, "keepalive", "%d\n", cfg.ncd_keepalive);
2126        if(cfg.ncd_mgclient != 0 || cfg.http_full_cfg)
2127            fprintf_conf(f, CONFVARWIDTH, "mgclient", "%d\n", cfg.ncd_mgclient);
2128        fprintf(f,"\n");
2129    }
2130
2131    /*camd3.3*/
2132    if ( cfg.c33_port > 0) {
2133        fprintf(f,"[camd33]\n");
2134        fprintf_conf(f, CONFVARWIDTH, "port", "%d\n", cfg.c33_port);
2135        if (cfg.c33_srvip != 0)
2136            fprintf_conf(f, CONFVARWIDTH, "serverip", "%s\n", cs_inet_ntoa(cfg.c33_srvip));
2137        if(cfg.c33_passive != 0 || cfg.http_full_cfg)
2138            fprintf_conf(f, CONFVARWIDTH, "passive", "%d\n", cfg.c33_passive);
2139        fprintf_conf(f, CONFVARWIDTH, "key", ""); for (i = 0; i < (int) sizeof(cfg.c33_key); ++i) fprintf(f,"%02X", cfg.c33_key[i]); fputc((int)'\n', f);
2140        value = mk_t_iprange(cfg.c33_plain);
2141        if(strlen(value) > 0 || cfg.http_full_cfg)
2142            fprintf_conf(f, CONFVARWIDTH, "nocrypt", "%s\n", value);
2143        free_mk_t(value);
2144        fprintf(f,"\n");
2145    }
2146
2147    /*camd3.5*/
2148    if ( cfg.c35_port > 0) {
2149        fprintf(f,"[cs357x]\n");
2150        fprintf_conf(f, CONFVARWIDTH, "port", "%d\n", cfg.c35_port);
2151        if (cfg.c35_srvip != 0)
2152            fprintf_conf(f, CONFVARWIDTH, "serverip", "%s\n", cs_inet_ntoa(cfg.c35_srvip));
2153        if (cfg.c35_udp_suppresscmd08 || cfg.http_full_cfg)
2154            fprintf_conf(f, CONFVARWIDTH, "suppresscmd08", "%d\n", cfg.c35_udp_suppresscmd08);
2155        fprintf(f,"\n");
2156    }
2157
2158    /*camd3.5 TCP*/
2159    if ((cfg.c35_tcp_ptab.nports > 0) && (cfg.c35_tcp_ptab.ports[0].s_port > 0)) {
2160        fprintf(f,"[cs378x]\n");
2161
2162        value = mk_t_camd35tcp_port();
2163        fprintf_conf(f, CONFVARWIDTH, "port", "%s\n", value);
2164        free_mk_t(value);
2165
2166        if (cfg.c35_tcp_srvip != 0)
2167            fprintf_conf(f, CONFVARWIDTH, "serverip", "%s\n", cs_inet_ntoa(cfg.c35_tcp_srvip));
2168        if (cfg.c35_tcp_suppresscmd08 || cfg.http_full_cfg)
2169            fprintf_conf(f, CONFVARWIDTH, "suppresscmd08", "%d\n", cfg.c35_tcp_suppresscmd08);
2170        fputc((int)'\n', f);
2171    }
2172
2173    /*Radegast*/
2174    if ( cfg.rad_port > 0) {
2175        fprintf(f,"[radegast]\n");
2176        fprintf_conf(f, CONFVARWIDTH, "port", "%d\n", cfg.rad_port);
2177        if (cfg.rad_srvip != 0)
2178            fprintf_conf(f, CONFVARWIDTH, "serverip", "%s\n", cs_inet_ntoa(cfg.rad_srvip));
2179        fprintf_conf(f, CONFVARWIDTH, "user", "%s\n", cfg.rad_usr);
2180        value = mk_t_iprange(cfg.rad_allowed);
2181        if(strlen(value) > 0 || cfg.http_full_cfg)
2182            fprintf_conf(f, CONFVARWIDTH, "allowed", "%s\n", value);
2183        free_mk_t(value);
2184        fprintf(f,"\n");
2185    }
2186
2187    /*serial*/
2188    if (cfg.ser_device[0]){
2189        fprintf(f,"[serial]\n");
2190        char sdevice[512];
2191        cs_strncpy(sdevice, cfg.ser_device, sizeof(sdevice));
2192        char *ptr;
2193        char delimiter[2]; delimiter[0] = 1; delimiter[1] = '\0';
2194
2195        for(ptr = strtok_r(sdevice, delimiter, &saveptr1); ptr != NULL; ptr = strtok_r(NULL, delimiter, &saveptr1)) {
2196            fprintf_conf(f, CONFVARWIDTH, "device", "%s\n", ptr);
2197        }
2198        fprintf(f,"\n");
2199    }
2200
2201    /*gbox*/
2202    if ( cfg.gbox_port > 0) {
2203        fprintf(f,"[gbox]\n");
2204        fprintf_conf(f, CONFVARWIDTH, "hostname", "%s\n", cfg.gbox_hostname);
2205        fprintf_conf(f, CONFVARWIDTH, "port", "%d\n", cfg.gbox_port);
2206        fprintf_conf(f, CONFVARWIDTH, "password", "%s\n", cfg.gbox_key);
2207        fprintf(f,"\n");
2208    }
2209
2210#ifdef MODULE_CCCAM
2211    /*cccam*/
2212    if ( cfg.cc_port[0] > 0) {
2213        fprintf(f,"[cccam]\n");
2214        value = mk_t_cccam_port();
2215        fprintf_conf(f, CONFVARWIDTH, "port", "%s\n", value);
2216        free_mk_t(value);
2217
2218        if(cfg.cc_reshare != 10 || cfg.http_full_cfg)
2219            fprintf_conf(f, CONFVARWIDTH, "reshare", "%d\n", cfg.cc_reshare);
2220        if(cfg.cc_ignore_reshare != 0 || cfg.http_full_cfg)
2221            fprintf_conf(f, CONFVARWIDTH, "ignorereshare", "%d\n", cfg.cc_ignore_reshare);
2222        if(cfg.cc_forward_origin_card != 0 || cfg.http_full_cfg)
2223            fprintf_conf(f, CONFVARWIDTH, "forward_origin_card", "%d\n", cfg.cc_forward_origin_card);
2224        if(cfg.cc_version || cfg.http_full_cfg)
2225            fprintf_conf(f, CONFVARWIDTH, "version", "%s\n", cfg.cc_version);
2226        if(cfg.cc_update_interval != DEFAULT_UPDATEINTERVAL || cfg.http_full_cfg)
2227            fprintf_conf(f, CONFVARWIDTH, "updateinterval", "%d\n", cfg.cc_update_interval);
2228        if(cfg.cc_minimize_cards != 0 || cfg.http_full_cfg)
2229            fprintf_conf(f, CONFVARWIDTH, "minimizecards", "%d\n", cfg.cc_minimize_cards);
2230        if(cfg.cc_keep_connected != 1 || cfg.http_full_cfg)
2231            fprintf_conf(f, CONFVARWIDTH, "keepconnected", "%d\n", cfg.cc_keep_connected);
2232        if(cfg.cc_stealth != 0 || cfg.http_full_cfg)
2233            fprintf_conf(f, CONFVARWIDTH, "stealth", "%d\n", cfg.cc_stealth);
2234        if(cfg.cc_use_fixed_nodeid || cfg.http_full_cfg)
2235            fprintf_conf(f, CONFVARWIDTH, "nodeid", "%02X%02X%02X%02X%02X%02X%02X%02X\n",
2236                cfg.cc_fixed_nodeid[0], cfg.cc_fixed_nodeid[1], cfg.cc_fixed_nodeid[2], cfg.cc_fixed_nodeid[3],
2237                cfg.cc_fixed_nodeid[4], cfg.cc_fixed_nodeid[5], cfg.cc_fixed_nodeid[6], cfg.cc_fixed_nodeid[7]);
2238        if(cfg.cc_reshare_services != 0 || cfg.http_full_cfg)
2239            fprintf_conf(f, CONFVARWIDTH, "reshare_mode", "%d\n", cfg.cc_reshare_services);
2240        fprintf(f,"\n");
2241    }
2242#endif
2243
2244#ifdef HAVE_DVBAPI
2245    /*dvb-api*/
2246    if (cfg.dvbapi_enabled > 0) {
2247        fprintf(f,"[dvbapi]\n");
2248        fprintf_conf(f, CONFVARWIDTH, "enabled", "%d\n", cfg.dvbapi_enabled);
2249        if(cfg.dvbapi_au != 0 || cfg.http_full_cfg)
2250            fprintf_conf(f, CONFVARWIDTH, "au", "%d\n", cfg.dvbapi_au);
2251        fprintf_conf(f, CONFVARWIDTH, "boxtype", "%s\n", boxdesc[cfg.dvbapi_boxtype]);
2252        fprintf_conf(f, CONFVARWIDTH, "user", "%s\n", cfg.dvbapi_usr);
2253        if(cfg.dvbapi_pmtmode != 0 || cfg.http_full_cfg)
2254            fprintf_conf(f, CONFVARWIDTH, "pmt_mode", "%d\n", cfg.dvbapi_pmtmode);
2255        if(cfg.dvbapi_requestmode != 0 || cfg.http_full_cfg)
2256            fprintf_conf(f, CONFVARWIDTH, "request_mode", "%d\n", cfg.dvbapi_requestmode);
2257
2258        fputc((int)'\n', f);
2259    }
2260#endif
2261
2262#ifdef WEBIF
2263    /*webinterface*/
2264    if (cfg.http_port > 0) {
2265        fprintf(f,"[webif]\n");
2266        if (cfg.http_use_ssl) {
2267            fprintf_conf(f, CONFVARWIDTH, "httpport", "+%d\n", cfg.http_port);
2268        } else {
2269            fprintf_conf(f, CONFVARWIDTH, "httpport", "%d\n", cfg.http_port);
2270        }
2271
2272        if(strcmp(cfg.http_help_lang, "en") != 0 || cfg.http_full_cfg)
2273            fprintf_conf(f, CONFVARWIDTH, "httphelplang", "%s\n", cfg.http_help_lang);
2274        if(strlen(cfg.http_user) > 0 || cfg.http_full_cfg)
2275            fprintf_conf(f, CONFVARWIDTH, "httpuser", "%s\n", cfg.http_user);
2276        if(strlen(cfg.http_pwd) > 0 || cfg.http_full_cfg)
2277            fprintf_conf(f, CONFVARWIDTH, "httppwd", "%s\n", cfg.http_pwd);
2278        if(strlen(cfg.http_cert) > 0 || cfg.http_full_cfg)
2279            fprintf_conf(f, CONFVARWIDTH, "httpcert", "%s\n", cfg.http_cert);
2280        if(strlen(cfg.http_css) > 0 || cfg.http_full_cfg)
2281            fprintf_conf(f, CONFVARWIDTH, "httpcss", "%s\n", cfg.http_css);
2282        if(strlen(cfg.http_jscript) > 0 || cfg.http_full_cfg)
2283            fprintf_conf(f, CONFVARWIDTH, "httpjscript", "%s\n", cfg.http_jscript);
2284        if(strlen(cfg.http_tpl) > 0 || cfg.http_full_cfg)
2285            fprintf_conf(f, CONFVARWIDTH, "httptpl", "%s\n", cfg.http_tpl);
2286        if(strlen(cfg.http_script) > 0 || cfg.http_full_cfg)
2287            fprintf_conf(f, CONFVARWIDTH, "httpscript", "%s\n", cfg.http_script);
2288        if(cfg.http_refresh > 0 || cfg.http_full_cfg)
2289            fprintf_conf(f, CONFVARWIDTH, "httprefresh", "%d\n", cfg.http_refresh);
2290        value = mk_t_iprange(cfg.http_allowed);
2291        if(strlen(value) > 0 || cfg.http_full_cfg)
2292            fprintf_conf(f, CONFVARWIDTH, "httpallowed", "%s\n", value);
2293        free_mk_t(value);
2294        if(strlen((const char *) (cfg.http_dyndns)) > 0 || cfg.http_full_cfg)
2295            fprintf_conf(f, CONFVARWIDTH, "httpdyndns", "%s\n", cfg.http_dyndns);
2296        if(cfg.http_hide_idle_clients || cfg.http_full_cfg)
2297            fprintf_conf(f, CONFVARWIDTH, "httphideidleclients", "%d\n", cfg.http_hide_idle_clients);
2298        if(cfg.http_readonly || cfg.http_full_cfg)
2299            fprintf_conf(f, CONFVARWIDTH, "httpreadonly", "%d\n", cfg.http_readonly);
2300        if(cfg.http_full_cfg)
2301            fprintf_conf(f, CONFVARWIDTH, "httpsavefullcfg", "%d\n", cfg.http_full_cfg);
2302
2303        fputc((int)'\n', f);
2304    }
2305#endif
2306
2307#ifdef CS_ANTICASC
2308    if(cfg.ac_enabled) {
2309        fprintf(f,"[anticasc]\n");
2310        fprintf_conf(f, CONFVARWIDTH, "enabled", "%d\n", cfg.ac_enabled);
2311        if(cfg.ac_users != 0 || cfg.http_full_cfg)
2312            fprintf_conf(f, CONFVARWIDTH, "numusers", "%d\n", cfg.ac_users);
2313        if(cfg.ac_stime != 2 || cfg.http_full_cfg)
2314            fprintf_conf(f, CONFVARWIDTH, "sampletime", "%d\n", cfg.ac_stime);
2315        if(cfg.ac_samples != 10 || cfg.http_full_cfg)
2316            fprintf_conf(f, CONFVARWIDTH, "samples", "%d\n", cfg.ac_samples);
2317        if(cfg.ac_penalty != 0 || cfg.http_full_cfg)
2318            fprintf_conf(f, CONFVARWIDTH, "penalty", "%d\n", cfg.ac_penalty);
2319        if(cfg.ac_logfile || cfg.http_full_cfg)
2320            fprintf_conf(f, CONFVARWIDTH, "aclogfile", "%s\n", cfg.ac_logfile);
2321        if(cfg.ac_denysamples != 8 || cfg.http_full_cfg)
2322            fprintf_conf(f, CONFVARWIDTH, "denysamples", "%d\n", cfg.ac_denysamples);
2323        if(cfg.ac_fakedelay != 1000 || cfg.http_full_cfg)
2324            fprintf_conf(f, CONFVARWIDTH, "fakedelay", "%d\n", cfg.ac_fakedelay);
2325        fputc((int)'\n', f);
2326    }
2327#endif
2328
2329#ifdef LCDSUPPORT
2330    fprintf(f,"[lcd]\n");
2331    if(cfg.lcd_output_path != NULL) {
2332        if(strlen(cfg.lcd_output_path) > 0 || cfg.http_full_cfg)
2333            fprintf_conf(f, CONFVARWIDTH, "lcd_outputpath", "%s\n", cfg.lcd_output_path);
2334    }
2335    if(cfg.lcd_hide_idle != 0 || cfg.http_full_cfg)
2336        fprintf_conf(f, CONFVARWIDTH, "lcd_hideidle", "%d\n", cfg.lcd_hide_idle);
2337    if(cfg.lcd_write_intervall != 10 || cfg.http_full_cfg)
2338        fprintf_conf(f, CONFVARWIDTH, "lcd_writeintervall", "%d\n", cfg.lcd_write_intervall);
2339#endif
2340
2341    fclose(f);
2342
2343    return(safe_overwrite_with_bak(destfile, tmpfile, bakfile, 0));
2344}
2345
2346int32_t write_userdb(struct s_auth *authptr)
2347{
2348    FILE *f;
2349    struct s_auth *account;
2350    char *value;
2351    char tmpfile[256];
2352    char destfile[256];
2353    char bakfile[256];
2354
2355    snprintf(destfile, sizeof(destfile),"%s%s", cs_confdir, cs_user);
2356    snprintf(tmpfile, sizeof(tmpfile), "%s%s.tmp", cs_confdir, cs_user);
2357    snprintf(bakfile, sizeof(bakfile),"%s%s.bak", cs_confdir, cs_user);
2358
2359  if (!(f=fopen(tmpfile, "w"))){
2360    cs_log("Cannot open file \"%s\" (errno=%d %s)", tmpfile, errno, strerror(errno));
2361    return(1);
2362  }
2363  fprintf(f,"# oscam.user generated automatically by Streamboard OSCAM %s build #%s\n", CS_VERSION, CS_SVN_VERSION);
2364  fprintf(f,"# Read more: http://streamboard.gmc.to/svn/oscam/trunk/Distribution/doc/txt/oscam.user.txt\n\n");
2365
2366  //each account
2367    for (account=authptr; (account) ; account=account->next){
2368        fprintf(f,"[account]\n");
2369        fprintf_conf(f, CONFVARWIDTH, "user", "%s\n", account->usr);
2370        fprintf_conf(f, CONFVARWIDTH, "pwd", "%s\n", account->pwd);
2371#ifdef WEBIF
2372        if (account->description[0] || cfg.http_full_cfg)
2373            fprintf_conf(f, CONFVARWIDTH, "description", "%s\n", account->description);
2374#endif
2375        if (account->disabled || cfg.http_full_cfg)
2376            fprintf_conf(f, CONFVARWIDTH, "disabled", "%d\n", account->disabled);
2377
2378        if (account->expirationdate || cfg.http_full_cfg) {
2379            struct tm timeinfo;
2380            localtime_r(&account->expirationdate, &timeinfo);
2381            char buf [80];
2382            strftime (buf,80,"%Y-%m-%d",&timeinfo);
2383            if(strcmp(buf,"1970-01-01"))
2384                fprintf_conf(f, CONFVARWIDTH, "expdate", "%s\n", buf);
2385            else
2386                fprintf_conf(f, CONFVARWIDTH, "expdate", "\n");
2387        }
2388
2389
2390        if(account->allowedtimeframe[0] && account->allowedtimeframe[1]) {
2391            fprintf_conf(f, CONFVARWIDTH, "allowedtimeframe", "%02d:%02d-%02d:%02d\n",
2392                    account->allowedtimeframe[0]/60,
2393                    account->allowedtimeframe[0]%60,
2394                    account->allowedtimeframe[1]/60,
2395                    account->allowedtimeframe[1]%60 );
2396        } else {
2397            if (cfg.http_full_cfg)
2398                fprintf_conf(f, CONFVARWIDTH, "allowedtimeframe", "\n");
2399        }
2400
2401        //group
2402        if (account->grp || cfg.http_full_cfg) {
2403            value = mk_t_group(account->grp);
2404            fprintf_conf(f, CONFVARWIDTH, "group", "%s\n", value);
2405            free_mk_t(value);
2406        }
2407
2408        if (account->dyndns[0] || cfg.http_full_cfg)
2409            fprintf_conf(f, CONFVARWIDTH, "hostname", "%s\n", account->dyndns);
2410
2411        if (account->uniq || cfg.http_full_cfg)
2412            fprintf_conf(f, CONFVARWIDTH, "uniq", "%d\n", account->uniq);
2413
2414        if (account->tosleep != cfg.tosleep || cfg.http_full_cfg)
2415            fprintf_conf(f, CONFVARWIDTH, "sleep", "%d\n", account->tosleep);
2416
2417        if (account->monlvl != cfg.mon_level || cfg.http_full_cfg)
2418            fprintf_conf(f, CONFVARWIDTH, "monlevel", "%d\n", account->monlvl);
2419
2420        if (account->autoau == 1)
2421            fprintf_conf(f, CONFVARWIDTH, "au", "1\n");
2422        else if (account->aureader_list) {
2423
2424            value = mk_t_aureader(account);
2425            if (strlen(value) > 0)
2426                fprintf_conf(f, CONFVARWIDTH, "au", "%s\n", value);
2427            free_mk_t(value);
2428
2429        } else if (cfg.http_full_cfg) fprintf_conf(f, CONFVARWIDTH, "au", "\n");
2430
2431        value = mk_t_service((uint64_t)account->sidtabok, (uint64_t)account->sidtabno);
2432        if (strlen(value) > 0 || cfg.http_full_cfg)
2433            fprintf_conf(f, CONFVARWIDTH, "services", "%s\n", value);
2434        free_mk_t(value);
2435
2436        //CAID
2437        if (account->ctab.caid[0] || cfg.http_full_cfg) {
2438            value = mk_t_caidtab(&account->ctab);
2439            fprintf_conf(f, CONFVARWIDTH, "caid", "%s\n", value);
2440            free_mk_t(value);
2441        }
2442
2443        //betatunnel
2444        if (account->ttab.bt_caidfrom[0] || cfg.http_full_cfg) {
2445            value = mk_t_tuntab(&account->ttab);
2446            fprintf_conf(f, CONFVARWIDTH, "betatunnel", "%s\n", value);
2447            free_mk_t(value);
2448        }
2449
2450        //ident
2451        if (account->ftab.nfilts || cfg.http_full_cfg) {
2452            value = mk_t_ftab(&account->ftab);
2453            fprintf_conf(f, CONFVARWIDTH, "ident", "%s\n", value);
2454            free_mk_t(value);
2455        }
2456
2457        //CHID
2458        if (account->fchid.nfilts || cfg.http_full_cfg) {
2459            value = mk_t_ftab(&account->fchid);
2460            fprintf_conf(f, CONFVARWIDTH, "chid", "%s\n", value);
2461            free_mk_t(value);
2462        }
2463
2464        //class
2465        if ((account->cltab.bn > 0 || account->cltab.an > 0) || cfg.http_full_cfg) {
2466            value = mk_t_cltab(&account->cltab);
2467            fprintf_conf(f, CONFVARWIDTH, "class", "%s\n", value);
2468            free_mk_t(value);
2469        }
2470
2471        if ((account->c35_suppresscmd08 != cfg.c35_suppresscmd08) || cfg.http_full_cfg)
2472            fprintf_conf(f, CONFVARWIDTH, "suppresscmd08", "%d\n", account->c35_suppresscmd08);
2473
2474#ifdef MODULE_CCCAM
2475        if (account->cccmaxhops != 10 || cfg.http_full_cfg)
2476            fprintf_conf(f, CONFVARWIDTH, "cccmaxhops", "%d\n", account->cccmaxhops);
2477
2478        if ((account->cccreshare != cfg.cc_reshare && account->cccreshare != -1) || cfg.http_full_cfg)
2479            fprintf_conf(f, CONFVARWIDTH, "cccreshare", "%d\n", account->cccreshare);
2480
2481        if ((account->cccignorereshare != cfg.cc_ignore_reshare && account->cccignorereshare != -1) || cfg.http_full_cfg)
2482            fprintf_conf(f, CONFVARWIDTH, "cccignorereshare", "%d\n", account->cccignorereshare);
2483
2484        if ((account->cccstealth != cfg.cc_stealth && account->cccstealth != -1 ) || cfg.http_full_cfg)
2485            fprintf_conf(f, CONFVARWIDTH, "cccstealth", "%d\n", account->cccstealth);
2486#endif
2487
2488        if (account->c35_sleepsend || cfg.http_full_cfg)
2489            fprintf_conf(f, CONFVARWIDTH, "sleepsend", "%u\n", account->c35_sleepsend);
2490
2491        if (account->failban || cfg.http_full_cfg)
2492            fprintf_conf(f, CONFVARWIDTH, "failban", "%d\n", account->failban);
2493
2494        if ((account->ncd_keepalive != cfg.ncd_keepalive) || cfg.http_full_cfg)
2495            fprintf_conf(f, CONFVARWIDTH, "keepalive", "%d\n", account->ncd_keepalive);
2496
2497#ifdef CS_ANTICASC
2498        if (account->ac_users || cfg.http_full_cfg)
2499            fprintf_conf(f, CONFVARWIDTH, "numusers", "%d\n", account->ac_users);
2500        if (account->ac_penalty || cfg.http_full_cfg)
2501            fprintf_conf(f, CONFVARWIDTH, "penalty", "%d\n", account->ac_penalty);
2502#endif
2503        fputc((int)'\n', f);
2504    }
2505  fclose(f);
2506
2507  return(safe_overwrite_with_bak(destfile, tmpfile, bakfile, 0));
2508}
2509
2510int32_t write_server()
2511{
2512    int32_t j;
2513    char *value;
2514    FILE *f;
2515
2516    char tmpfile[256];
2517    char destfile[256];
2518    char bakfile[256];
2519
2520    snprintf(destfile, sizeof(destfile),"%s%s", cs_confdir, cs_srvr);
2521    snprintf(tmpfile, sizeof(tmpfile), "%s%s.tmp", cs_confdir, cs_srvr);
2522    snprintf(bakfile, sizeof(bakfile),"%s%s.bak", cs_confdir, cs_srvr);
2523
2524    if (!(f=fopen(tmpfile, "w"))){
2525        cs_log("Cannot open file \"%s\" (errno=%d %s)", tmpfile, errno, strerror(errno));
2526        return(1);
2527    }
2528    fprintf(f,"# oscam.server generated automatically by Streamboard OSCAM %s build #%s\n", CS_VERSION, CS_SVN_VERSION);
2529    fprintf(f,"# Read more: http://streamboard.gmc.to/svn/oscam/trunk/Distribution/doc/txt/oscam.server.txt\n\n");
2530
2531    struct s_reader *rdr;
2532    LL_ITER itr = ll_iter_create(configured_readers);
2533    while((rdr = ll_iter_next(&itr))) {
2534        if ( rdr->label[0]) {
2535            int32_t isphysical = (rdr->typ & R_IS_NETWORK)?0:1;
2536            char *ctyp = reader_get_type_desc(rdr, 0);
2537
2538            fprintf(f,"[reader]\n");
2539
2540            fprintf_conf(f, CONFVARWIDTH, "label", "%s\n", rdr->label);
2541
2542            if (rdr->enable == 0 || cfg.http_full_cfg)
2543                fprintf_conf(f, CONFVARWIDTH, "enable", "%d\n", rdr->enable);
2544
2545            fprintf_conf(f, CONFVARWIDTH, "protocol", "%s\n", ctyp);
2546            fprintf_conf(f, CONFVARWIDTH, "device", "%s", rdr->device);
2547
2548            if ((rdr->r_port || cfg.http_full_cfg) && !isphysical)
2549                fprintf(f, ",%d", rdr->r_port);
2550            if ((rdr->l_port || cfg.http_full_cfg) && !isphysical && strncmp(ctyp, "cccam", 5))
2551                fprintf(f, ",%d", rdr->l_port);
2552            if ((rdr->slot || cfg.http_full_cfg) && !strncmp(ctyp, "sc8in1", 6))
2553                fprintf(f, ":%d", rdr->slot);
2554            fprintf(f, "\n");
2555
2556#ifdef LIBUSB
2557            if (!(rdr->typ & R_IS_NETWORK))
2558                if (rdr->device_endpoint || cfg.http_full_cfg)
2559                    fprintf_conf(f, CONFVARWIDTH, "device_out_endpoint", "0x%2X\n", rdr->device_endpoint);
2560#endif
2561
2562            if (rdr->ncd_key[0] || rdr->ncd_key[13] || cfg.http_full_cfg) {
2563                fprintf_conf(f, CONFVARWIDTH, "key", "");
2564                if(rdr->ncd_key[0] || rdr->ncd_key[13]){
2565                    for (j = 0; j < 14; j++) {
2566                        fprintf(f, "%02X", rdr->ncd_key[j]);
2567                    }
2568                }
2569                fprintf(f, "\n");
2570            }
2571
2572            if ((rdr->r_usr[0] || cfg.http_full_cfg) && !isphysical)
2573                fprintf_conf(f, CONFVARWIDTH, "user", "%s\n", rdr->r_usr);
2574
2575            if (strlen(rdr->r_pwd) > 0 || cfg.http_full_cfg)
2576                fprintf_conf(f, CONFVARWIDTH, "password", "%s\n", rdr->r_pwd);
2577
2578            if(strcmp(rdr->pincode, "none") || cfg.http_full_cfg)
2579                fprintf_conf(f, CONFVARWIDTH, "pincode", "%s\n", rdr->pincode);
2580
2581            if ((rdr->emmfile || cfg.http_full_cfg) && isphysical)
2582                fprintf_conf(f, CONFVARWIDTH, "readnano", "%s\n", rdr->emmfile?rdr->emmfile:"");
2583
2584            value = mk_t_service((uint64_t)rdr->sidtabok, (uint64_t)rdr->sidtabno);
2585            if (strlen(value) > 0 || cfg.http_full_cfg)
2586                fprintf_conf(f, CONFVARWIDTH, "services", "%s\n", value);
2587            free_mk_t(value);
2588
2589            if ((rdr->tcp_ito || cfg.http_full_cfg) && !isphysical && rdr->typ != R_CCCAM)
2590                fprintf_conf(f, CONFVARWIDTH, "inactivitytimeout", "%d\n", rdr->tcp_ito);
2591
2592            if ((rdr->tcp_rto != 30 || cfg.http_full_cfg) && !isphysical)
2593                fprintf_conf(f, CONFVARWIDTH, "reconnecttimeout", "%d\n", rdr->tcp_rto);
2594
2595            if ((rdr->ncd_disable_server_filt || cfg.http_full_cfg) && rdr->typ == R_NEWCAMD)
2596                fprintf_conf(f, CONFVARWIDTH, "disableserverfilter", "%d\n", rdr->ncd_disable_server_filt);
2597
2598            if ((rdr->smargopatch || cfg.http_full_cfg) && isphysical)
2599                fprintf_conf(f, CONFVARWIDTH, "smargopatch", "%d\n", rdr->smargopatch);
2600
2601            if ((rdr->show_cls != 10 || cfg.http_full_cfg) && isphysical)
2602                fprintf_conf(f, CONFVARWIDTH, "showcls", "%d\n", rdr->show_cls);
2603
2604            if (rdr->fallback || cfg.http_full_cfg)
2605                fprintf_conf(f, CONFVARWIDTH, "fallback", "%d\n", rdr->fallback);
2606
2607            if (rdr->log_port || cfg.http_full_cfg)
2608                fprintf_conf(f, CONFVARWIDTH, "logport", "%d\n", rdr->log_port);
2609
2610            value = mk_t_caidtab(&rdr->ctab);
2611            if (strlen(value) > 0 || cfg.http_full_cfg)
2612                fprintf_conf(f, CONFVARWIDTH, "caid", "%s\n", value);
2613            free_mk_t(value);
2614
2615            if (rdr->boxid && isphysical)
2616                fprintf_conf(f, CONFVARWIDTH, "boxid", "%08X\n", rdr->boxid);
2617            else if (cfg.http_full_cfg && isphysical)
2618                fprintf_conf(f, CONFVARWIDTH, "boxid", "\n");
2619
2620            if((rdr->fix_9993 || cfg.http_full_cfg) && isphysical)
2621                fprintf_conf(f, CONFVARWIDTH, "fix9993", "%d\n", rdr->fix_9993);
2622
2623            // rsakey
2624            int32_t len = check_filled(rdr->rsa_mod, 120);
2625            if (len > 0 && isphysical) {
2626                if(len > 64) len = 120;
2627                else len = 64;
2628                fprintf_conf(f, CONFVARWIDTH, "rsakey", "%s\n", cs_hexdump(0, rdr->rsa_mod, len));
2629            } else if(cfg.http_full_cfg && isphysical)
2630                fprintf_conf(f, CONFVARWIDTH, "rsakey", "\n");
2631
2632            if ((rdr->force_irdeto || cfg.http_full_cfg) && isphysical) {
2633                fprintf_conf(f, CONFVARWIDTH, "force_irdeto", "%d\n", rdr->force_irdeto);
2634            }
2635
2636            len = check_filled(rdr->nagra_boxkey, 8);
2637            if ((len > 0 || cfg.http_full_cfg) && isphysical)
2638                fprintf_conf(f, CONFVARWIDTH, "boxkey", "%s\n", len>0?cs_hexdump(0, rdr->nagra_boxkey, 8):"");
2639
2640            if ((rdr->atr[0] || cfg.http_full_cfg) && isphysical) {
2641                fprintf_conf(f, CONFVARWIDTH, "atr", "");
2642                if(rdr->atr[0]){
2643                    for (j=0; j < rdr->atrlen/2; j++) {
2644                        fprintf(f, "%02X", rdr->atr[j]);
2645                    }
2646                }
2647                fprintf(f, "\n");
2648            }
2649
2650            value = mk_t_ecmwhitelist(rdr->ecmWhitelist);
2651            if (strlen(value) > 0 || cfg.http_full_cfg)
2652                fprintf_conf(f, CONFVARWIDTH, "ecmwhitelist", "%s\n", value);
2653            free_mk_t(value);
2654
2655            if (isphysical) {
2656                if (rdr->detect&0x80)
2657                    fprintf_conf(f, CONFVARWIDTH, "detect", "!%s\n", RDR_CD_TXT[rdr->detect&0x7f]);
2658                else
2659                    fprintf_conf(f, CONFVARWIDTH, "detect", "%s\n", RDR_CD_TXT[rdr->detect&0x7f]);
2660            }
2661
2662            if ((rdr->nagra_read || cfg.http_full_cfg) && isphysical)
2663                fprintf_conf(f, CONFVARWIDTH, "nagra_read", "%d\n", rdr->nagra_read);
2664
2665            if ((rdr->mhz || cfg.http_full_cfg) && isphysical)
2666                fprintf_conf(f, CONFVARWIDTH, "mhz", "%d\n", rdr->mhz);
2667
2668            if ((rdr->cardmhz || cfg.http_full_cfg) && isphysical)
2669                fprintf_conf(f, CONFVARWIDTH, "cardmhz", "%d\n", rdr->cardmhz);
2670
2671            value = mk_t_ftab(&rdr->ftab);
2672            if (strlen(value) > 0 || cfg.http_full_cfg)
2673                fprintf_conf(f, CONFVARWIDTH, "ident", "%s\n", value);
2674            free_mk_t(value);
2675
2676            //Todo: write reader class
2677
2678            value = mk_t_ftab(&rdr->fchid);
2679            if (strlen(value) > 0 || cfg.http_full_cfg)
2680                fprintf_conf(f, CONFVARWIDTH, "chid", "%s\n", value);
2681            free_mk_t(value);
2682
2683            value = mk_t_cltab(&rdr->cltab);
2684            if (strlen(value) > 0 || cfg.http_full_cfg)
2685                fprintf_conf(f, CONFVARWIDTH, "class", "%s\n", value);
2686            free_mk_t(value);
2687
2688            value = mk_t_aeskeys(rdr);
2689            if (strlen(value) > 0 || cfg.http_full_cfg)
2690                fprintf_conf(f, CONFVARWIDTH, "aeskeys", "%s\n", value);
2691            free_mk_t(value);
2692
2693            if ((rdr->show_cls && !rdr->show_cls == 10) || cfg.http_full_cfg)
2694                fprintf_conf(f, CONFVARWIDTH, "showcls", "%d\n", rdr->show_cls);
2695
2696            value = mk_t_group(rdr->grp);
2697            if (strlen(value) > 0 || cfg.http_full_cfg)
2698                fprintf_conf(f, CONFVARWIDTH, "group", "%s\n", value);
2699            free_mk_t(value);
2700
2701            if (rdr->cachemm || cfg.http_full_cfg)
2702                fprintf_conf(f, CONFVARWIDTH, "emmcache", "%d,%d,%d\n", rdr->cachemm, rdr->rewritemm, rdr->logemm);
2703
2704            if ((rdr->blockemm & EMM_UNKNOWN) || cfg.http_full_cfg)
2705                fprintf_conf(f, CONFVARWIDTH, "blockemm-unknown", "%d\n", (rdr->blockemm & EMM_UNKNOWN) ? 1: 0);
2706
2707            if ((rdr->blockemm & EMM_UNIQUE) || cfg.http_full_cfg)
2708                fprintf_conf(f, CONFVARWIDTH, "blockemm-u", "%d\n", (rdr->blockemm & EMM_UNIQUE) ? 1: 0);
2709
2710            if ((rdr->blockemm & EMM_SHARED) || cfg.http_full_cfg)
2711                fprintf_conf(f, CONFVARWIDTH, "blockemm-s", "%d\n", (rdr->blockemm & EMM_SHARED) ? 1: 0);
2712
2713            if ((rdr->blockemm & EMM_GLOBAL) || cfg.http_full_cfg)
2714                fprintf_conf(f, CONFVARWIDTH, "blockemm-g", "%d\n", (rdr->blockemm & EMM_GLOBAL) ? 1: 0);
2715
2716#ifdef WITH_LB
2717            if (rdr->lb_weight != 100 || cfg.http_full_cfg)
2718                fprintf_conf(f, CONFVARWIDTH, "lb_weight", "%d\n", rdr->lb_weight);
2719#endif
2720
2721            //savenano
2722            value = mk_t_nano(rdr, 0x02);
2723            if (strlen(value) > 0 || cfg.http_full_cfg)
2724                fprintf_conf(f, CONFVARWIDTH, "savenano", "%s\n", value);
2725            free_mk_t(value);
2726
2727            //blocknano
2728            value = mk_t_nano(rdr, 0x01);
2729            if (strlen(value) > 0 || cfg.http_full_cfg)
2730                fprintf_conf(f, CONFVARWIDTH, "blocknano", "%s\n", value);
2731            free_mk_t(value);
2732
2733#ifdef MODULE_CCCAM
2734            if (rdr->typ == R_CCCAM) {
2735                if (rdr->cc_version[0] || cfg.http_full_cfg)
2736                    fprintf_conf(f, CONFVARWIDTH, "cccversion", "%s\n", rdr->cc_version);
2737
2738                if (rdr->cc_maxhop != 10 || cfg.http_full_cfg)
2739                    fprintf_conf(f, CONFVARWIDTH, "cccmaxhops", "%d\n", rdr->cc_maxhop);
2740
2741                if (rdr->cc_mindown > 0 || cfg.http_full_cfg)
2742                    fprintf_conf(f, CONFVARWIDTH, "cccmindown", "%d\n", rdr->cc_mindown);
2743
2744                if (rdr->cc_want_emu || cfg.http_full_cfg)
2745                    fprintf_conf(f, CONFVARWIDTH, "cccwantemu", "%d\n", rdr->cc_want_emu);
2746
2747                if (rdr->cc_keepalive || cfg.http_full_cfg)
2748                    fprintf_conf(f, CONFVARWIDTH, "ccckeepalive", "%d\n", rdr->cc_keepalive);
2749
2750                if ((rdr->cc_reshare != cfg.cc_reshare && rdr->cc_reshare != -1) || cfg.http_full_cfg)
2751                    fprintf_conf(f, CONFVARWIDTH, "cccreshare", "%d\n", rdr->cc_reshare);
2752            }
2753            else if (rdr->cc_hop > 0 || cfg.http_full_cfg)
2754                fprintf_conf(f, CONFVARWIDTH, "ccchop", "%d\n", rdr->cc_hop);
2755#endif
2756
2757            if ((rdr->deprecated || cfg.http_full_cfg) && isphysical)
2758                fprintf_conf(f, CONFVARWIDTH, "deprecated", "%d\n", rdr->deprecated);
2759
2760            if (rdr->audisabled || cfg.http_full_cfg)
2761                fprintf_conf(f, CONFVARWIDTH, "audisabled", "%d\n", rdr->audisabled);
2762
2763            if (rdr->auprovid)
2764                fprintf_conf(f, CONFVARWIDTH, "auprovid", "%06lX\n", rdr->auprovid);
2765            else if (cfg.http_full_cfg)
2766                fprintf_conf(f, CONFVARWIDTH, "auprovid", "\n");
2767
2768            if ((rdr->ndsversion || cfg.http_full_cfg) && isphysical)
2769                fprintf_conf(f, CONFVARWIDTH, "ndsversion", "%d\n", rdr->ndsversion);
2770
2771            if ((rdr->ratelimitecm || cfg.http_full_cfg) && isphysical) {
2772                fprintf_conf(f, CONFVARWIDTH, "ratelimitecm", "%d\n", rdr->ratelimitecm);
2773                fprintf_conf(f, CONFVARWIDTH, "ratelimitseconds", "%d\n", rdr->ratelimitseconds);
2774            }
2775            fprintf(f, "\n\n");
2776        }
2777    }
2778    fclose(f);
2779
2780    return(safe_overwrite_with_bak(destfile, tmpfile, bakfile, 0));
2781}
2782
2783void write_versionfile() {
2784
2785#ifndef OS_CYGWIN32
2786  // /tmp/oscam.version file (Uptime + Version)
2787  char targetfile[256];
2788  snprintf(targetfile, sizeof(targetfile),"%s%s", get_tmp_dir(), "/oscam.version");
2789  FILE *fp;
2790
2791  if (!(fp=fopen(targetfile, "w"))) {
2792      cs_log("Cannot open %s (errno=%d %s)", targetfile, errno, strerror(errno));
2793  } else {
2794      time_t now = time((time_t)0);
2795      struct tm st;
2796      localtime_r(&now, &st);
2797      fprintf(fp, "Unix starttime: %d\n", (int)now);
2798      fprintf(fp, "Starttime:      %02d.%02d.%02d", st.tm_mday, st.tm_mon+1, st.tm_year%100);
2799      fprintf(fp, " %02d:%02d:%02d\n", st.tm_hour, st.tm_min, st.tm_sec);
2800      fprintf(fp, "Version:        %s  Rev. %s\n", CS_VERSION, CS_SVN_VERSION);
2801      fprintf(fp, "Max PID:        unlimited\n\n\n");
2802      fprintf(fp, "Active modules:\n");
2803
2804#ifdef WEBIF
2805      fprintf(fp, "Web interface support:      yes\n");
2806#else
2807      fprintf(fp, "Web interface support:      no\n");
2808#endif
2809#ifdef WITH_SSL
2810      fprintf(fp, "SSL support:                yes\n");
2811#else
2812      fprintf(fp, "SSL support:                no\n");
2813#endif
2814#ifdef HAVE_DVBAPI
2815      fprintf(fp, "DVB API support             yes\n");
2816#ifdef WITH_STAPI
2817      fprintf(fp, "DVB API with STAPI support: yes\n");
2818#else
2819      fprintf(fp, "DVB API with STAPI support: no\n");
2820#endif
2821#else
2822      fprintf(fp, "DVB API support             no\n");
2823#endif
2824#ifdef CS_ANTICASC
2825      fprintf(fp, "Anti-cascading support:     yes\n");
2826#else
2827      fprintf(fp, "Anti-cascading support:     no\n");
2828#endif
2829#ifdef CS_WITH_DOUBLECHECK
2830      fprintf(fp, "ECM doublecheck:            yes\n");
2831#else
2832      fprintf(fp, "ECM doublecheck:            no\n");
2833#endif
2834#ifdef IRDETO_GUESSING
2835      fprintf(fp, "Irdeto guessing:            yes\n");
2836#else
2837      fprintf(fp, "Irdeto guessing:            no\n");
2838#endif
2839#ifdef WITH_DEBUG
2840      fprintf(fp, "Debug mode:                 yes\n");
2841#else
2842      fprintf(fp, "Debug mode:                 no\n");
2843#endif
2844#ifdef CS_LED
2845      fprintf(fp, "LED support:                yes\n");
2846#else
2847      fprintf(fp, "LED support:                no\n");
2848#endif
2849#ifdef QBOXHD_LED
2850      fprintf(fp, "Q-Box HD LED support:       yes\n");
2851#else
2852      fprintf(fp, "Q-Box HD LED support:       no\n");
2853#endif
2854#ifdef CS_LOGHISTORY
2855      fprintf(fp, "Log history:                yes\n");
2856#else
2857      fprintf(fp, "Log history:                no\n");
2858#endif
2859#ifdef MODULE_MONITOR
2860      fprintf(fp, "Monitor:                    yes\n");
2861#else
2862      fprintf(fp, "Monitor:                    no\n");
2863#endif
2864#ifdef WITH_LB
2865      fprintf(fp, "Loadbalancing support:      yes\n");
2866#else
2867      fprintf(fp, "Loadbalancing support:      no\n");
2868#endif
2869#ifdef LCDSUPPORT
2870      fprintf(fp, "LCD support:                yes\n");
2871#else
2872      fprintf(fp, "LCD support:                no\n");
2873#endif
2874#ifdef MODULE_CAMD33
2875      fprintf(fp, "camd 3.3x:                  yes\n");
2876#else
2877      fprintf(fp, "camd 3.3x:                  no\n");
2878#endif
2879#ifdef MODULE_CAMD35
2880      fprintf(fp, "camd 3.5 UDP:               yes\n");
2881#else
2882      fprintf(fp, "camd 3.5 UDP:               no\n");
2883#endif
2884#ifdef MODULE_CAMD35_TCP
2885      fprintf(fp, "camd 3.5 TCP:               yes\n");
2886#else
2887      fprintf(fp, "camd 3.5 TCP:               no\n");
2888#endif
2889#ifdef MODULE_NEWCAMD
2890      fprintf(fp, "newcamd:                    yes\n");
2891#else
2892      fprintf(fp, "newcamd:                    no\n");
2893#endif
2894#ifdef MODULE_CCCAM
2895      fprintf(fp, "CCcam:                      yes\n");
2896#else
2897      fprintf(fp, "CCcam:                      no\n");
2898#endif
2899#ifdef MODULE_GBOX
2900      fprintf(fp, "gbox:                       yes\n");
2901#else
2902      fprintf(fp, "gbox:                       no\n");
2903#endif
2904#ifdef MODULE_RADEGAST
2905      fprintf(fp, "radegast:                   yes\n");
2906#else
2907      fprintf(fp, "radegast:                   no\n");
2908#endif
2909#ifdef MODULE_SERIAL
2910      fprintf(fp, "serial:                     yes\n");
2911#else
2912      fprintf(fp, "serial:                     no\n");
2913#endif
2914#ifdef MODULE_CONSTCW
2915      fprintf(fp, "constant CW:                yes\n");
2916#else
2917      fprintf(fp, "constant CW:                no\n");
2918#endif
2919#ifdef WITH_CARDREADER
2920      fprintf(fp, "Cardreader:                 yes\n");
2921
2922    #ifdef READER_NAGRA
2923      fprintf(fp, "Nagra:                      yes\n");
2924    #else
2925      fprintf(fp, "Nagra:                      no\n");
2926    #endif
2927    #ifdef READER_IRDETO
2928      fprintf(fp, "Irdeto:                     yes\n");
2929    #else
2930      fprintf(fp, "Irdeto:                     no\n");
2931    #endif
2932    #ifdef READER_CONAX
2933      fprintf(fp, "Conax:                      yes\n");
2934    #else
2935      fprintf(fp, "Conax:                      no\n");
2936    #endif
2937    #ifdef READER_CRYPTOWORKS
2938      fprintf(fp, "Cryptoworks:                yes\n");
2939    #else
2940      fprintf(fp, "Cryptoworks:                no\n");
2941    #endif
2942    #ifdef READER_SECA
2943      fprintf(fp, "Seca:                       yes\n");
2944    #else
2945      fprintf(fp, "Seca:                       no\n");
2946    #endif
2947    #ifdef READER_VIACCESS
2948      fprintf(fp, "Viaccess:                   yes\n");
2949    #else
2950      fprintf(fp, "Viaccess:                   no\n");
2951    #endif
2952    #ifdef READER_VIDEOGUARD
2953      fprintf(fp, "NDS Videoguard:             yes\n");
2954    #else
2955      fprintf(fp, "NDS Videoguard:             no\n");
2956    #endif
2957    #ifdef READER_DRE
2958      fprintf(fp, "DRE Crypt:                  yes\n");
2959    #else
2960      fprintf(fp, "DRE Crypt:                  no\n");
2961    #endif
2962
2963    #ifdef READER_TONGFANG
2964      fprintf(fp, "TONGFANG:                   yes\n");
2965    #else
2966      fprintf(fp, "TONGFANG:                   no\n");
2967    #endif
2968#else
2969      fprintf(fp, "Cardreader:                 no\n");
2970#endif
2971
2972      fclose(fp);
2973  }
2974#endif
2975
2976}
2977
2978int32_t init_free_userdb(struct s_auth *ptr) {
2979    int32_t nro;
2980    for (nro = 0; ptr; nro++) {
2981        struct s_auth *ptr_next;
2982        ptr_next = ptr->next;
2983        ll_destroy(ptr->aureader_list);
2984        ptr->next = NULL;
2985        add_garbage(ptr);
2986        ptr = ptr_next;
2987    }
2988    cs_log("userdb %d accounts freed", nro);
2989
2990    return nro;
2991}
2992
2993struct s_auth *init_userdb()
2994{
2995    struct s_auth *authptr = NULL;
2996    int32_t tag = 0, nr = 0, expired = 0, disabled = 0;
2997    //int32_t first=1;
2998    FILE *fp;
2999    char *value;
3000    struct s_auth *account=NULL;
3001
3002    snprintf(token, sizeof(token), "%s%s", cs_confdir, cs_user);
3003    if (!(fp = fopen(token, "r"))) {
3004        cs_log("Cannot open file \"%s\" (errno=%d %s)", token, errno, strerror(errno));
3005        return authptr;
3006    }
3007
3008    while (fgets(token, sizeof(token), fp)) {
3009        int32_t i, l;
3010        void *ptr;
3011
3012        if ((l=strlen(trim(token))) < 3)
3013            continue;
3014
3015        if ((token[0] == '[') && (token[l-1] == ']')) {
3016            token[l - 1] = 0;
3017            tag = (!strcmp("account", strtolower(token + 1)));
3018
3019            if(!cs_malloc(&ptr, sizeof(struct s_auth), -1)) return authptr;
3020            if (account)
3021                account->next = ptr;
3022            else
3023                authptr = ptr;
3024
3025            account = ptr;
3026            account->allowedtimeframe[0] = 0;
3027            account->allowedtimeframe[1] = 0;
3028            account->aureader_list = NULL;
3029            account->monlvl = cfg.mon_level;
3030            account->tosleep = cfg.tosleep;
3031            account->c35_suppresscmd08 = cfg.c35_suppresscmd08;
3032            account->cccmaxhops = 10;
3033            account->cccreshare = -1; //-1 = use cfg.
3034            account->cccignorereshare = -1;
3035            account->cccstealth = -1;
3036            account->ncd_keepalive = cfg.ncd_keepalive;
3037            account->firstlogin = 0;
3038            for (i = 1; i < CS_MAXCAIDTAB; account->ctab.mask[i++] = 0xffff);
3039            for (i = 1; i < CS_MAXTUNTAB; account->ttab.bt_srvid[i++] = 0x0000);
3040            nr++;
3041
3042#ifdef CS_ANTICASC
3043            account->ac_users = cfg.ac_users;
3044            account->ac_penalty = cfg.ac_penalty;
3045#endif
3046            continue;
3047        }
3048
3049        if (!tag)
3050            continue;
3051
3052        if (!(value=strchr(token, '=')))
3053            continue;
3054
3055        *value++ = '\0';
3056        chk_account(trim(strtolower(token)), trim(value), account);
3057    }
3058
3059    fclose(fp);
3060
3061    for(account = authptr; account; account = account->next){
3062        if(account->expirationdate && account->expirationdate < time(NULL))
3063            ++expired;
3064
3065        if(account->disabled)
3066            ++disabled;
3067    }
3068
3069    cs_log("userdb reloaded: %d accounts loaded, %d expired, %d disabled", nr, expired, disabled);
3070    return authptr;
3071}
3072
3073void free_sidtab(struct s_sidtab *ptr)
3074{
3075        if (!ptr) return;
3076        add_garbage(ptr->caid); //no need to check on NULL first, freeing NULL doesnt do anything
3077        add_garbage(ptr->provid);
3078        add_garbage(ptr->srvid);
3079        add_garbage(ptr);
3080}
3081
3082static void chk_entry4sidtab(char *value, struct s_sidtab *sidtab, int32_t what)
3083{
3084  int32_t i, b;
3085  char *ptr, *saveptr1 = NULL;
3086  uint16_t *slist=(uint16_t *) 0;
3087  uint32_t *llist=(uint32_t *) 0;
3088  uint32_t caid;
3089  char buf[strlen(value) + 1];
3090  cs_strncpy(buf, value, sizeof(buf));
3091  b=(what==1) ? sizeof(uint32_t) : sizeof(uint16_t);
3092  for (i=0, ptr=strtok_r(value, ",", &saveptr1); ptr; ptr=strtok_r(NULL, ",", &saveptr1))
3093  {
3094    caid=a2i(ptr, b);
3095    if (!errno) i++;
3096  }
3097  //if (!i) return(0);
3098  if (b==sizeof(uint16_t)){
3099    if(!cs_malloc(&slist, i*sizeof(uint16_t), -1)) return;
3100  } else {
3101    if(!cs_malloc(&llist, i*sizeof(uint32_t), -1)) return;
3102  }
3103  cs_strncpy(value, buf, sizeof(buf));
3104  for (i=0, ptr=strtok_r(value, ",", &saveptr1); ptr; ptr=strtok_r(NULL, ",", &saveptr1))
3105  {
3106    caid=a2i(ptr, b);
3107    if (errno) continue;
3108    if (b==sizeof(uint16_t))
3109      slist[i++]=(uint16_t) caid;
3110    else
3111      llist[i++]=caid;
3112  }
3113  switch (what)
3114  {
3115    case 0: add_garbage(sidtab->caid);
3116            sidtab->caid=slist;
3117            sidtab->num_caid=i;
3118            break;
3119    case 1: add_garbage(sidtab->provid);
3120            sidtab->provid=llist;
3121            sidtab->num_provid=i;
3122            break;
3123    case 2: add_garbage(sidtab->srvid);
3124            sidtab->srvid=slist;
3125            sidtab->num_srvid=i;
3126            break;
3127  }
3128}
3129
3130void chk_sidtab(char *token, char *value, struct s_sidtab *sidtab)
3131{
3132  if (!strcmp(token, "caid")) { chk_entry4sidtab(value, sidtab, 0); return; }
3133  if (!strcmp(token, "provid")) { chk_entry4sidtab(value, sidtab, 1); return; }
3134  if (!strcmp(token, "ident")) { chk_entry4sidtab(value, sidtab, 1); return; }
3135  if (!strcmp(token, "srvid")) { chk_entry4sidtab(value, sidtab, 2); return; }
3136  if (token[0] != '#')
3137    fprintf(stderr, "Warning: keyword '%s' in sidtab section not recognized\n",token);
3138}
3139
3140void init_free_sidtab() {
3141        struct s_sidtab *nxt, *ptr = cfg.sidtab;
3142        while (ptr) {
3143                nxt = ptr->next;
3144                free_sidtab(ptr);
3145                ptr = nxt;
3146        }
3147        cfg.sidtab = NULL;
3148}
3149
3150int32_t init_sidtab() {
3151  int32_t nr, nro;
3152  FILE *fp;
3153  char *value;
3154  struct s_sidtab *ptr;
3155  struct s_sidtab *sidtab=(struct s_sidtab *)0;
3156
3157  snprintf(token, sizeof(token), "%s%s", cs_confdir, cs_sidt);
3158  if (!(fp=fopen(token, "r")))
3159  {
3160    cs_log("Cannot open file \"%s\" (errno=%d %s)", token, errno, strerror(errno));
3161    return(1);
3162  }
3163  for (nro=0, ptr=cfg.sidtab; ptr; nro++)
3164  {
3165    struct s_sidtab *ptr_next;
3166    ptr_next=ptr->next;
3167    free_sidtab(ptr);
3168    ptr=ptr_next;
3169  }
3170  nr=0;
3171  while (fgets(token, sizeof(token), fp))
3172  {
3173    int32_t l;
3174    void *ptr;
3175    if ((l=strlen(trim(token)))<3) continue;
3176    if ((token[0]=='[') && (token[l-1]==']'))
3177    {
3178      token[l-1]=0;
3179      if (!cs_malloc(&ptr, sizeof(struct s_sidtab), -1)) return(1);
3180      if (sidtab)
3181        sidtab->next=ptr;
3182      else
3183        cfg.sidtab=ptr;
3184      sidtab=ptr;
3185      nr++;
3186      memset(sidtab, 0, sizeof(struct s_sidtab));
3187      cs_strncpy(sidtab->label, strtolower(token+1), sizeof(sidtab->label));
3188      continue;
3189    }
3190    if (!sidtab) continue;
3191    if (!(value=strchr(token, '='))) continue;
3192    *value++='\0';
3193    chk_sidtab(trim(strtolower(token)), trim(strtolower(value)), sidtab);
3194  }
3195  fclose(fp);
3196
3197#ifdef DEBUG_SIDTAB
3198  show_sidtab(cfg.sidtab);
3199#endif
3200  cs_log("services reloaded: %d services freed, %d services loaded", nro, nr);
3201  return(0);
3202}
3203
3204//Todo #ifdef CCCAM
3205int32_t init_provid() {
3206    int32_t nr;
3207    FILE *fp;
3208    char *payload, *saveptr1 = NULL;
3209    static struct s_provid *provid=(struct s_provid *)0;
3210    snprintf(token, sizeof(token), "%s%s", cs_confdir, cs_provid);
3211
3212    if (!(fp=fopen(token, "r"))) {
3213        cs_log("can't open file \"%s\" (err=%d %s), no provids's loaded", token, errno, strerror(errno));
3214        return(0);
3215    }
3216    nr=0;
3217    while (fgets(token, sizeof(token), fp)) {
3218
3219        int32_t l;
3220        void *ptr;
3221        char *tmp;
3222        tmp = trim(token);
3223
3224        if (tmp[0] == '#') continue;
3225        if ((l = strlen(tmp)) < 11) continue;
3226        if (!(payload = strchr(token, '|'))) continue;
3227        *payload++ = '\0';
3228
3229        if (!cs_malloc(&ptr, sizeof(struct s_provid), -1)) return(1);
3230        if (provid)
3231            provid->next = ptr;
3232        else
3233            cfg.provid = ptr;
3234
3235        provid = ptr;
3236        memset(provid, 0, sizeof(struct s_provid));
3237
3238        int32_t i;
3239        char *ptr1;
3240        for (i = 0, ptr1 = strtok_r(payload, "|", &saveptr1); ptr1; ptr1 = strtok_r(NULL, "|", &saveptr1), i++){
3241            switch(i){
3242            case 0:
3243                cs_strncpy(provid->prov, trim(ptr1), sizeof(provid->prov));
3244                break;
3245            case 1:
3246                cs_strncpy(provid->sat, trim(ptr1), sizeof(provid->sat));
3247                break;
3248            case 2:
3249                cs_strncpy(provid->lang, trim(ptr1), sizeof(provid->lang));
3250                break;
3251            }
3252        }
3253
3254        char *providasc = strchr(token, ':');
3255        *providasc++ = '\0';
3256        provid->provid = a2i(providasc, 3);
3257        provid->caid = a2i(token, 3);
3258        nr++;
3259    }
3260
3261    fclose(fp);
3262    if (nr>0)
3263        cs_log("%d provid's loaded", nr);
3264    else{
3265        cs_log("oscam.provid loading failed, wrong format?");
3266    }
3267    return(0);
3268}
3269
3270int32_t init_srvid()
3271{
3272    int32_t nr = 0, i;
3273    FILE *fp;
3274    char *payload, *tmp, *saveptr1 = NULL;
3275    struct s_srvid *srvid=NULL, *new_cfg_srvid[16], *last_srvid[16];
3276    snprintf(token, sizeof(token), "%s%s", cs_confdir, cs_srid);
3277    // A cache for strings within srvids. A checksum is calculated which is the start point in the array (some kind of primitive hash algo).
3278    // From this point, a sequential search is done. This greatly reduces the amount of string comparisons.
3279    char **stringcache[1024];
3280    int32_t allocated[1024] = { 0 };
3281    int32_t used[1024] = { 0 };
3282    struct timeb ts, te;
3283  cs_ftime(&ts);
3284
3285    memset(last_srvid, 0, sizeof(last_srvid));
3286    memset(new_cfg_srvid, 0, sizeof(new_cfg_srvid));
3287
3288    if (!(fp=fopen(token, "r"))) {
3289        cs_log("can't open file \"%s\" (err=%d %s), no service-id's loaded", token, errno, strerror(errno));
3290        return(0);
3291    }
3292
3293    while (fgets(token, sizeof(token), fp)) {
3294        int32_t l, j, len=0, len2;
3295        uint32_t pos;
3296        tmp = trim(token);
3297
3298        if (tmp[0] == '#') continue;
3299        if ((l=strlen(tmp)) < 6) continue;
3300        if (!(payload=strchr(token, '|'))) continue;
3301        *payload++ = '\0';
3302
3303        if (!cs_malloc(&srvid, sizeof(struct s_srvid), -1)) return(1);
3304
3305        char tmptxt[128];
3306
3307        int32_t offset[4] = { -1, -1, -1, -1 };
3308        char *ptr1, *searchptr[4] = { NULL, NULL, NULL, NULL };
3309        char **ptrs[4] = { &srvid->prov, &srvid->name, &srvid->type, &srvid->desc };
3310
3311        for (i = 0, ptr1 = strtok_r(payload, "|", &saveptr1); ptr1 && (i < 4) ; ptr1 = strtok_r(NULL, "|", &saveptr1), ++i){
3312            // check if string is in cache
3313            len2 = strlen(ptr1);
3314            pos = 0;
3315            for(j = 0; j < len2; ++j) pos += (uint8_t)ptr1[j];
3316            pos = pos%1024;
3317            for(j = 0; j < used[pos]; ++j){
3318                if (!strcmp(stringcache[pos][j], ptr1)){
3319                    searchptr[i]=stringcache[pos][j];
3320                    break;
3321                }
3322            }
3323            if (searchptr[i]) continue;
3324
3325            offset[i]=len;
3326            cs_strncpy(tmptxt+len, trim(ptr1), sizeof(tmptxt)-len);
3327            len+=strlen(ptr1)+1;
3328        }
3329
3330        char *tmpptr;
3331        if (!cs_malloc(&tmpptr, len, 0))
3332            continue;
3333
3334        srvid->data=tmpptr;
3335        memcpy(tmpptr, tmptxt, len);
3336
3337        for (i=0;i<4;i++) {
3338            if (searchptr[i]) {
3339                *ptrs[i] = searchptr[i];
3340                continue;
3341            }
3342            if (offset[i]>-1){
3343                *ptrs[i] = tmpptr + offset[i];
3344                // store string in stringcache
3345                tmp = *ptrs[i];
3346                len2 = strlen(tmp);
3347                pos = 0;
3348                for(j = 0; j < len2; ++j) pos += (uint8_t)tmp[j];
3349                pos = pos%1024;
3350                if(used[pos] >= allocated[pos]){
3351                    if(allocated[pos] == 0) cs_malloc(&stringcache[pos], 16 * sizeof(char*), SIGINT);
3352                    else cs_realloc(&stringcache[pos], (allocated[pos] + 16) * sizeof(char*), SIGINT);
3353                    allocated[pos] += 16;
3354                }
3355                stringcache[pos][used[pos]] = tmp;
3356                used[pos] += 1;
3357            }
3358        }
3359
3360        char *srvidasc = strchr(token, ':');
3361        *srvidasc++ = '\0';
3362        srvid->srvid = dyn_word_atob(srvidasc) & 0xFFFF;
3363        //printf("srvid %s - %d\n",srvidasc,srvid->srvid );
3364
3365        if (srvid->srvid<0) {
3366            free(tmpptr);
3367            free(srvid);
3368            continue;
3369        }
3370
3371        srvid->ncaid = 0;
3372        for (i = 0, ptr1 = strtok_r(token, ",", &saveptr1); (ptr1) && (i < 10) ; ptr1 = strtok_r(NULL, ",", &saveptr1), i++){
3373            srvid->caid[i] = dyn_word_atob(ptr1);
3374            srvid->ncaid = i+1;
3375            //cs_debug_mask(D_CLIENT, "ld caid: %04X srvid: %04X Prov: %s Chan: %s",srvid->caid[i],srvid->srvid,srvid->prov,srvid->name);
3376        }
3377        nr++;
3378
3379        if (new_cfg_srvid[srvid->srvid>>12])
3380            last_srvid[srvid->srvid>>12]->next = srvid;
3381        else
3382            new_cfg_srvid[srvid->srvid>>12] = srvid;
3383
3384        last_srvid[srvid->srvid>>12] = srvid;
3385    }
3386    for(i = 0; i < 1024; ++i){
3387        if(allocated[i] > 0) free(stringcache[i]);
3388    }
3389
3390    cs_ftime(&te);
3391    int32_t time = 1000*(te.time-ts.time)+te.millitm-ts.millitm;
3392
3393    fclose(fp);
3394    if (nr > 0) {
3395        cs_log("%d service-id's loaded in %dms", nr, time);
3396        if (nr > 2000) {
3397            cs_log("WARNING: You risk high CPU load and high ECM times with more than 2000 service-id´s!");
3398            cs_log("HINT: --> use optimized lists from http://streamboard.gmc.to/wiki/index.php/Srvid");
3399        }
3400    } else {
3401        cs_log("oscam.srvid loading failed, old format");
3402    }
3403
3404    //this allows reloading of srvids, so cleanup of old data is needed:
3405    memcpy(last_srvid, cfg.srvid, sizeof(last_srvid));  //old data
3406    memcpy(cfg.srvid, new_cfg_srvid, sizeof(last_srvid));   //assign after loading, so everything is in memory
3407
3408    struct s_client *cl;
3409    for (cl=first_client->next; cl ; cl=cl->next)
3410        cl->last_srvidptr=NULL;
3411
3412    struct s_srvid *ptr;
3413    for (i=0; i<16; i++) {
3414        while (last_srvid[i]) { //cleanup old data:
3415            ptr = last_srvid[i]->next;
3416            free(last_srvid[i]->data);
3417            free(last_srvid[i]);
3418            last_srvid[i] = ptr;
3419        }
3420    }
3421
3422    return(0);
3423}
3424
3425int32_t init_tierid()
3426{
3427    int32_t nr;
3428    FILE *fp;
3429    char *payload, *saveptr1 = NULL;
3430    static struct s_tierid *tierid=NULL, *new_cfg_tierid=NULL;
3431    snprintf(token, sizeof(token), "%s%s", cs_confdir, cs_trid);
3432
3433    if (!(fp=fopen(token, "r"))) {
3434        cs_log("can't open file \"%s\" (err=%d %s), no tier-id's loaded", token, errno, strerror(errno));
3435        return(0);
3436    }
3437
3438    nr=0;
3439    while (fgets(token, sizeof(token), fp)) {
3440
3441        int32_t l;
3442        void *ptr;
3443        char *tmp;
3444        tmp = trim(token);
3445
3446        if (tmp[0] == '#') continue;
3447        if ((l=strlen(tmp)) < 6) continue;
3448        if (!(payload=strchr(token, '|'))) continue;
3449        *payload++ = '\0';
3450
3451        if (!cs_malloc(&ptr,sizeof(struct s_tierid), -1)) return(1);
3452        if (tierid)
3453            tierid->next = ptr;
3454        else
3455            new_cfg_tierid = ptr;
3456
3457        tierid = ptr;
3458        memset(tierid, 0, sizeof(struct s_tierid));
3459
3460        int32_t i;
3461        char *ptr1 = strtok_r(payload, "|", &saveptr1);
3462        if (ptr1)
3463            cs_strncpy(tierid->name, trim(ptr1), sizeof(tierid->name));
3464
3465        char *tieridasc = strchr(token, ':');
3466        *tieridasc++ = '\0';
3467        tierid->tierid = dyn_word_atob(tieridasc);
3468        //printf("tierid %s - %d\n",tieridasc,tierid->tierid );
3469
3470        tierid->ncaid = 0;
3471        for (i = 0, ptr1 = strtok_r(token, ",", &saveptr1); (ptr1) && (i < 10) ; ptr1 = strtok_r(NULL, ",", &saveptr1), i++){
3472            tierid->caid[i] = dyn_word_atob(ptr1);
3473            tierid->ncaid = i+1;
3474            // cs_log("ld caid: %04X tierid: %04X name: %s",tierid->caid[i],tierid->tierid,tierid->name);
3475        }
3476        nr++;
3477    }
3478
3479    fclose(fp);
3480    if (nr>0)
3481        cs_log("%d tier-id's loaded", nr);
3482    else{
3483        cs_log("%s loading failed", cs_trid);
3484    }
3485
3486    //reload function:
3487    tierid = cfg.tierid;
3488    cfg.tierid = new_cfg_tierid;
3489    struct s_tierid *ptr;
3490    while (tierid) {
3491        ptr = tierid->next;
3492        free(tierid);
3493        tierid = ptr;
3494    }
3495
3496    return(0);
3497}
3498
3499void chk_reader(char *token, char *value, struct s_reader *rdr)
3500{
3501    int32_t i;
3502    char *ptr, *ptr2, *ptr3, *saveptr1 = NULL;
3503    /*
3504     *  case sensitive first
3505     */
3506    if (!strcmp(token, "device")) {
3507        for (i = 0, ptr = strtok_r(value, ",", &saveptr1); (i < 3) && (ptr); ptr = strtok_r(NULL, ",", &saveptr1), i++) {
3508            trim(ptr);
3509            switch(i) {
3510                case 0:
3511                    cs_strncpy(rdr->device, ptr, sizeof(rdr->device));
3512                    break;
3513
3514                case 1:
3515                    rdr->r_port = atoi(ptr);
3516                    break;
3517
3518                case 2:
3519                    rdr->l_port = atoi(ptr);
3520                    break;
3521            }
3522        }
3523        return;
3524    }
3525
3526#ifdef LIBUSB
3527    if (!strcmp(token, "device_out_endpoint")) {
3528        if (strlen(value) > 0) {
3529            sscanf(value, "0x%2X", &i);
3530            rdr->device_endpoint = i;
3531        } else {
3532            rdr->device_endpoint = 0;
3533        }
3534        return;
3535    }
3536#endif
3537
3538    if (!strcmp(token, "key")) {
3539        if (strlen(value) == 0){
3540            return;
3541        } else if (key_atob_l(value, rdr->ncd_key, 28)) {
3542            fprintf(stderr, "Configuration newcamd: Error in Key\n");
3543            memset(rdr->ncd_key, 0, sizeof(rdr->ncd_key));
3544        }
3545        return;
3546    }
3547
3548    if (!strcmp(token, "password")) {
3549        cs_strncpy(rdr->r_pwd, value, sizeof(rdr->r_pwd));
3550        return;
3551    }
3552
3553    if (!strcmp(token, "user")) {
3554        cs_strncpy(rdr->r_usr, value, sizeof(rdr->r_usr));
3555        return;
3556    }
3557
3558  if (!strcmp(token, "mg-encrypted")) {
3559    uchar key[16];
3560    uchar mac[6];
3561    uchar *buf = NULL;
3562    int32_t len = 0;
3563
3564    memset(&key, 0, 16);
3565    memset(&mac, 0, 6);
3566
3567    for (i = 0, ptr = strtok_r(value, ",", &saveptr1); (i < 2) && (ptr); ptr = strtok_r(NULL, ",", &saveptr1), i++) {
3568      trim(ptr);
3569      switch(i) {
3570        case 0:
3571          len = strlen(ptr) / 2 + (16 - (strlen(ptr) / 2) % 16);
3572          if(!cs_malloc(&buf,len, -1)) return;
3573          key_atob_l(ptr, buf, strlen(ptr));
3574          cs_log("enc %d: %s", len, ptr);
3575          break;
3576
3577        case 1:
3578          key_atob_l(ptr, mac, 12);
3579          cs_log("mac: %s", ptr);
3580          break;
3581      }
3582    }
3583
3584    if (!memcmp(mac, "\x00\x00\x00\x00\x00\x00", 6)) {
3585#ifdef OS_MACOSX
3586      // no mac address specified so use mac of en0 on local box
3587      struct ifaddrs *ifs, *current;
3588
3589      if (getifaddrs(&ifs) == 0)
3590      {
3591         for (current = ifs; current != 0; current = current->ifa_next)
3592         {
3593            if (current->ifa_addr->sa_family == AF_LINK && strcmp(current->ifa_name, "en0") == 0)
3594            {
3595               struct sockaddr_dl *sdl = (struct sockaddr_dl *)current->ifa_addr;
3596               memcpy(mac, LLADDR(sdl), sdl->sdl_alen);
3597               break;
3598            }
3599         }
3600         freeifaddrs(ifs);
3601      }
3602#elif defined OS_SOLARIS
3603            // no mac address specified so use first filled mac
3604            int32_t j, sock, niccount;
3605            struct ifreq nicnumber[16];
3606            struct ifconf ifconf;
3607            struct arpreq arpreq;
3608
3609            if ((sock=socket(AF_INET,SOCK_DGRAM,0)) > -1){
3610                ifconf.ifc_buf = (caddr_t)nicnumber;
3611                ifconf.ifc_len = sizeof(nicnumber);
3612                if (!ioctl(sock,SIOCGIFCONF,(char*)&ifconf)){
3613                    niccount = ifconf.ifc_len/(sizeof(struct ifreq));
3614                    for(i = 0; i < niccount, ++i){
3615                        memset(&arpreq, 0, sizeof(arpreq));
3616                        ((struct sockaddr_in*)&arpreq.arp_pa)->sin_addr.s_addr = ((struct sockaddr_in*)&nicnumber[i].ifr_addr)->sin_addr.s_addr;
3617                        if (!(ioctl(sock,SIOCGARP,(char*)&arpreq))){
3618                            for (j = 0; j < 6; ++j)
3619                                mac[j] = (unsigned char)arpreq.arp_ha.sa_data[j];
3620                            if(check_filled(mac, 6) > 0) break;
3621                        }
3622                    }
3623                }
3624                close(sock);
3625            }
3626#else
3627      // no mac address specified so use mac of eth0 on local box
3628      int32_t fd = socket(PF_INET, SOCK_STREAM, 0);
3629
3630      struct ifreq ifreq;
3631      memset(&ifreq, 0, sizeof(ifreq));
3632      snprintf(ifreq.ifr_name, sizeof(ifreq.ifr_name), "eth0");
3633
3634      ioctl(fd, SIOCGIFHWADDR, &ifreq);
3635      memcpy(mac, ifreq.ifr_ifru.ifru_hwaddr.sa_data, 6);
3636
3637      close(fd);
3638#endif
3639            cs_debug_mask(D_TRACE, "Determined local mac address for mg-encrypted as %s", cs_hexdump(1, mac, 6));
3640    }
3641
3642    // decrypt encrypted mgcamd gbox line
3643    for (i = 0; i < 6; i++)
3644      key[i * 2] = mac[i];
3645
3646    AES_KEY aeskey;
3647    AES_set_decrypt_key(key, 128, &aeskey);
3648    for (i = 0; i < len; i+=16)
3649      AES_decrypt(buf + i,buf + i, &aeskey);
3650
3651    // parse d-line
3652    for (i = 0, ptr = strtok_r((char *)buf, " {", &saveptr1); (i < 5) && (ptr); ptr = strtok_r(NULL, " {", &saveptr1), i++) {
3653      trim(ptr);
3654      switch(i) {
3655        case 1:    // hostname
3656          cs_strncpy(rdr->device, ptr, sizeof(rdr->device));
3657          break;
3658        case 2:   // local port
3659          cfg.gbox_port = atoi(ptr);  // ***WARNING CHANGE OF GLOBAL LISTEN PORT FROM WITHIN READER!!!***
3660          break;
3661        case 3:   // remote port
3662          rdr->r_port = atoi(ptr);
3663          break;
3664        case 4:   // password
3665          cs_strncpy(rdr->r_pwd, ptr, sizeof(rdr->r_pwd));
3666          break;
3667      }
3668    }
3669
3670    free(buf);
3671    return;
3672  }
3673
3674    //legacy parameter containing account=user,pass
3675    if (!strcmp(token, "account")) {
3676        if (strstr(value, ",")) {
3677            for (i = 0, ptr = strtok_r(value, ",", &saveptr1); (i < 2) && (ptr); ptr = strtok_r(NULL, ",", &saveptr1), i++) {
3678                trim(ptr);
3679                switch(i) {
3680                    case 0:
3681                        cs_strncpy(rdr->r_usr, ptr, sizeof(rdr->r_usr));
3682                        break;
3683
3684                    case 1:
3685                        cs_strncpy(rdr->r_pwd, ptr, sizeof(rdr->r_pwd));
3686                        break;
3687                }
3688            }
3689        } else {
3690            cs_strncpy(rdr->r_usr, value, sizeof(rdr->r_usr));
3691        }
3692        return;
3693    }
3694
3695    if (!strcmp(token, "pincode")) {
3696        cs_strncpy(rdr->pincode, value, sizeof(rdr->pincode));
3697        return;
3698    }
3699
3700    if (!strcmp(token, "readnano")) {
3701        NULLFREE(rdr->emmfile);
3702        if (strlen(value) > 0) {
3703            if(!cs_malloc(&(rdr->emmfile), strlen(value) + 1, -1)) return;
3704            memcpy(rdr->emmfile, value, strlen(value) + 1);
3705        }
3706        return;
3707    }
3708
3709    /*
3710     *  case insensitive
3711     */
3712    strtolower(value);
3713
3714    if (!strcmp(token, "enable")) {
3715        rdr->enable  = strToIntVal(value, 0);
3716        return;
3717    }
3718
3719    if (!strcmp(token, "services")) {
3720        if(strlen(value) == 0) {
3721            rdr->sidtabok = 0;
3722            rdr->sidtabno = 0;
3723            return;
3724        } else {
3725            chk_services(value, &rdr->sidtabok, &rdr->sidtabno);
3726            return;
3727        }
3728    }
3729
3730    if (!strcmp(token, "inactivitytimeout")) {
3731        rdr->tcp_ito  = strToIntVal(value, 0);
3732        return;
3733    }
3734
3735    if (!strcmp(token, "reconnecttimeout")) {
3736        rdr->tcp_rto  = strToIntVal(value, 30);
3737        return;
3738    }
3739
3740    if (!strcmp(token, "disableserverfilter")) {
3741        rdr->ncd_disable_server_filt  = strToIntVal(value, 0);
3742        return;
3743    }
3744
3745    //FIXME workaround for Smargo until native mode works
3746    if (!strcmp(token, "smargopatch")) {
3747        rdr->smargopatch  = strToIntVal(value, 0);
3748        return;
3749    }
3750
3751    if (!strcmp(token, "label")) {
3752        int32_t found = 0;
3753        for(i = 0; i < (int)strlen(value); i++) {
3754            if (value[i] == ' ') {
3755                value[i] = '_';
3756                found++;
3757            }
3758        }
3759
3760        if (found) fprintf(stderr, "Configuration reader: corrected label to %s\n",value);
3761        cs_strncpy(rdr->label, value, sizeof(rdr->label));
3762        return;
3763    }
3764
3765    if (!strcmp(token, "fallback")) {
3766        rdr->fallback  = strToIntVal(value, 0);
3767        return;
3768    }
3769
3770    if (!strcmp(token, "logport")) {
3771        rdr->log_port  = strToIntVal(value, 0);
3772        return;
3773    }
3774
3775    if (!strcmp(token, "caid")) {
3776        if(strlen(value) == 0) {
3777            clear_caidtab(&rdr->ctab);
3778            return;
3779        } else {
3780            chk_caidtab(value, &rdr->ctab);
3781            return;
3782        }
3783    }
3784
3785  if (!strcmp(token, "boxid")) {
3786    if(strlen(value) == 0) {
3787      rdr->boxid = 0;
3788      return;
3789    } else {
3790      rdr->boxid = a2i(value, 4);
3791      return;
3792    }
3793  }
3794
3795  if (!strcmp(token, "fix9993")) {
3796    rdr->fix_9993 = strToIntVal(value, 0);
3797    return;
3798  }
3799
3800    if (!strcmp(token, "rsakey")) {
3801        int32_t len = strlen(value);
3802        if(len != 128 && len != 240) {
3803            memset(rdr->rsa_mod, 0, 120);
3804            return;
3805        } else {
3806            if (key_atob_l(value, rdr->rsa_mod, len)) {
3807                fprintf(stderr, "Configuration reader: Error in rsakey\n");
3808                memset(rdr->rsa_mod, 0, sizeof(rdr->rsa_mod));
3809            }
3810            return;
3811        }
3812    }
3813
3814    if (!strcmp(token, "boxkey")) {
3815        if(strlen(value) != 16 ) {
3816            memset(rdr->nagra_boxkey, 0, 16);
3817            return;
3818        } else {
3819            if (key_atob_l(value, rdr->nagra_boxkey, 16)) {
3820                fprintf(stderr, "Configuration reader: Error in boxkey\n");
3821                memset(rdr->nagra_boxkey, 0, sizeof(rdr->nagra_boxkey));
3822            }
3823            return;
3824        }
3825    }
3826
3827    if (!strcmp(token, "force_irdeto")) {
3828        rdr->force_irdeto  = strToIntVal(value, 0);
3829        return;
3830    }
3831
3832
3833    if ((!strcmp(token, "atr"))) {
3834        memset(rdr->atr, 0, sizeof(rdr->atr));
3835        rdr->atrlen = strlen(value);
3836        if(rdr->atrlen == 0) {
3837            return;
3838        } else {
3839            if(rdr->atrlen > (int32_t)sizeof(rdr->atr) * 2)
3840                rdr->atrlen = (int32_t)sizeof(rdr->atr) * 2;
3841            key_atob_l(value, rdr->atr, rdr->atrlen);
3842            return;
3843        }
3844    }
3845
3846    if (!strcmp(token, "ecmwhitelist")) {
3847        struct s_ecmWhitelist *tmp, *last;
3848        struct s_ecmWhitelistIdent *tmpIdent, *lastIdent;
3849        struct s_ecmWhitelistLen *tmpLen, *lastLen;
3850        for(tmp = rdr->ecmWhitelist; tmp; tmp=tmp->next){
3851            for(tmpIdent = tmp->idents; tmpIdent; tmpIdent=tmpIdent->next){
3852                for(tmpLen = tmpIdent->lengths; tmpLen; tmpLen=tmpLen->next){
3853                    add_garbage(tmpLen);
3854                }
3855                add_garbage(tmpIdent);
3856            }
3857            add_garbage(tmp);
3858        }
3859        rdr->ecmWhitelist = NULL;
3860        if(strlen(value) > 0){
3861            char *saveptr1=NULL, *saveptr2 = NULL;
3862            for (ptr = strtok_r(value, ";", &saveptr1); ptr; ptr = strtok_r(NULL, ";", &saveptr1)) {
3863                int16_t caid = 0, len;
3864                uint32_t ident = 0;
3865                ptr2=strchr(ptr,':');
3866                if(ptr2 != NULL){
3867                    ptr2[0] = '\0';
3868                    ++ptr2;
3869                    ptr3=strchr(ptr,'@');
3870                    if(ptr3 != NULL){
3871                        ptr3[0] = '\0';
3872                        ++ptr3;
3873                        ident = (uint32_t)a2i(ptr3, 6);
3874                    }
3875                    caid = (int16_t)dyn_word_atob(ptr);
3876                } else ptr2 = ptr;
3877                for (ptr2 = strtok_r(ptr2, ",", &saveptr2); ptr2; ptr2 = strtok_r(NULL, ",", &saveptr2)) {
3878                    len = (int16_t)dyn_word_atob(ptr2);
3879                    last = NULL, tmpIdent = NULL, lastIdent = NULL, tmpLen = NULL, lastLen = NULL;
3880                    for(tmp = rdr->ecmWhitelist; tmp; tmp=tmp->next){
3881                        last = tmp;
3882                        if(tmp->caid == caid){
3883                            for(tmpIdent = tmp->idents; tmpIdent; tmpIdent=tmpIdent->next){
3884                                lastIdent = tmpIdent;
3885                                if(tmpIdent->ident == ident){
3886                                    for(tmpLen = tmpIdent->lengths; tmpLen; tmpLen=tmpLen->next){
3887                                        lastLen = tmpLen;
3888                                        if(tmpLen->len == len) break;
3889                                    }
3890                                    break;
3891                                }
3892                            }
3893                        }
3894                    }
3895                    if(tmp == NULL){
3896                        if (cs_malloc(&tmp, sizeof(struct s_ecmWhitelist), -1)) {
3897                            tmp->caid = caid;
3898                            tmp->idents = NULL;
3899                            tmp->next = NULL;
3900                            if(last == NULL){
3901                                rdr->ecmWhitelist = tmp;
3902                            } else {
3903                                last->next = tmp;
3904                            }
3905                        }
3906                    }
3907                    if(tmp != NULL && tmpIdent == NULL){
3908                        if (cs_malloc(&tmpIdent, sizeof(struct s_ecmWhitelistIdent), -1)) {
3909                            tmpIdent->ident = ident;
3910                            tmpIdent->lengths = NULL;
3911                            tmpIdent->next = NULL;
3912                            if(lastIdent == NULL){
3913                                tmp->idents = tmpIdent;
3914                            } else {
3915                                lastIdent->next = tmpIdent;
3916                            }
3917                        }
3918                    }
3919                    if(tmp != NULL && tmpIdent != NULL && tmpLen == NULL){
3920                        if (cs_malloc(&tmpLen, sizeof(struct s_ecmWhitelistLen), -1)) {
3921                            tmpLen->len = len;
3922                            tmpLen->next = NULL;
3923                            if(lastLen == NULL){
3924                                tmpIdent->lengths = tmpLen;
3925                            } else {
3926                                lastLen->next = tmpLen;
3927                            }
3928                        }
3929                    }
3930                }
3931            }
3932        }
3933        return;
3934    }
3935
3936    if (!strcmp(token, "detect")) {
3937        for (i = 0; RDR_CD_TXT[i]; i++) {
3938            if (!strcmp(value, RDR_CD_TXT[i])) {
3939                rdr->detect = i;
3940            }
3941            else {
3942                if ((value[0] == '!') && (!strcmp(value+1, RDR_CD_TXT[i])))
3943                    rdr->detect = i|0x80;
3944            }
3945        }
3946        return;
3947    }
3948
3949    if (!strcmp(token, "nagra_read")) {
3950        rdr->nagra_read  = strToIntVal(value, 0);
3951        return;
3952    }
3953
3954    if (!strcmp(token, "mhz")) {
3955        rdr->mhz  = strToIntVal(value, 0);
3956        return;
3957    }
3958
3959    if (!strcmp(token, "cardmhz")) {
3960        rdr->cardmhz  = strToIntVal(value, 0);
3961        return;
3962    }
3963
3964    if (!strcmp(token, "protocol")) {
3965
3966        for (i=0; i<CS_MAX_MOD; i++) {
3967            if (!strcmp(value, cardreader[i].desc)) {
3968                rdr->crdr = cardreader[i];
3969                rdr->crdr.active = 1;
3970                rdr->typ = cardreader[i].typ; //FIXME
3971                return;
3972            }
3973        }
3974
3975        if (!strcmp(value, "mp35")) {
3976            rdr->typ = R_MP35;
3977            return;
3978        }
3979
3980        if (!strcmp(value, "mouse")) {
3981            rdr->typ = R_MOUSE;
3982            return;
3983        }
3984
3985        if (!strcmp(value, "sc8in1")) {
3986            rdr->typ = R_SC8in1;
3987            return;
3988        }
3989
3990        if (!strcmp(value, "smartreader")) {
3991            rdr->typ = R_SMART;
3992            return;
3993        }
3994
3995        if (!strcmp(value, "internal")) {
3996            rdr->typ = R_INTERNAL;
3997            return;
3998        }
3999
4000#ifdef HAVE_PCSC
4001        if (!strcmp(value, "pcsc")) {
4002            rdr->typ = R_PCSC;
4003            return;
4004        }
4005#endif
4006
4007        if (!strcmp(value, "serial")) {
4008            rdr->typ = R_SERIAL;
4009            return;
4010        }
4011
4012        if (!strcmp(value, "camd35")) {
4013            rdr->typ = R_CAMD35;
4014            return;
4015        }
4016
4017        if (!strcmp(value, "cs378x")) {
4018            rdr->typ = R_CS378X;
4019            return;
4020        }
4021
4022        if (!strcmp(value, "cs357x")) {
4023            rdr->typ = R_CAMD35;
4024            return;
4025        }
4026
4027        if (!strcmp(value, "gbox")) {
4028            rdr->typ = R_GBOX;
4029            return;
4030        }
4031
4032        if (!strcmp(value, "cccam") || !strcmp(value, "cccam ext")) {
4033            rdr->typ = R_CCCAM;
4034            //strcpy(value, "1");
4035            //chk_caidtab(value, &rdr->ctab);
4036            //this is a MAJOR hack for auto multiple caid support (not currently working due to ncd table issue)
4037            return;
4038        }
4039
4040        if (!strcmp(value, "constcw")) {
4041            rdr->typ = R_CONSTCW;
4042            return;
4043        }
4044
4045        if (!strcmp(value, "radegast")) {
4046            rdr->typ = R_RADEGAST;
4047            return;
4048        }
4049
4050        if (!strcmp(value, "newcamd") || !strcmp(value, "newcamd525")) {
4051            rdr->typ = R_NEWCAMD;
4052            rdr->ncd_proto = NCD_525;
4053            return;
4054        }
4055
4056        if (!strcmp(value, "newcamd524")) {
4057            rdr->typ = R_NEWCAMD;
4058            rdr->ncd_proto = NCD_524;
4059            return;
4060        }
4061
4062        fprintf(stderr, "WARNING: value '%s' in protocol-line not recognized, assuming MOUSE\n",value);
4063        rdr->typ = R_MOUSE;
4064        return;
4065    }
4066
4067    if (!strcmp(token, "ident")) {
4068        if(strlen(value) == 0) {
4069            clear_ftab(&rdr->ftab);
4070            return;
4071        } else {
4072            chk_ftab(value, &rdr->ftab,"reader",rdr->label,"provid");
4073            return;
4074        }
4075    }
4076
4077    if (!strcmp(token, "class")) {
4078        chk_cltab(value, &rdr->cltab);
4079        return;
4080    }
4081
4082    if (!strcmp(token, "chid")) {
4083        chk_ftab(value, &rdr->fchid,"reader",rdr->label,"chid");
4084        return;
4085    }
4086
4087    if (!strcmp(token, "showcls")) {
4088        rdr->show_cls  = strToIntVal(value, 0);
4089        return;
4090    }
4091
4092    if (!strcmp(token, "group")) {
4093        rdr->grp = 0;
4094        for (ptr = strtok_r(value, ",", &saveptr1); ptr; ptr = strtok_r(NULL, ",", &saveptr1)) {
4095            int32_t g;
4096            g = atoi(ptr);
4097            if ((g>0) && (g<65)) {
4098                rdr->grp |= (((uint64_t)1)<<(g-1));
4099            }
4100        }
4101        return;
4102    }
4103
4104    if (!strcmp(token, "emmcache")) {
4105        if(strlen(value) == 0) {
4106            rdr->cachemm = 0;
4107            rdr->rewritemm = 0;
4108            rdr->logemm = 0;
4109            return;
4110        } else {
4111            for (i = 0, ptr = strtok_r(value, ",", &saveptr1); (i < 3) && (ptr); ptr = strtok_r(NULL, ",", &saveptr1), i++) {
4112                switch(i)
4113                {
4114                    case 0:
4115                        rdr->cachemm = atoi(ptr);
4116                        break;
4117
4118                    case 1:
4119                        rdr->rewritemm = atoi(ptr);
4120                        break;
4121
4122                    case 2: rdr->logemm = atoi(ptr);
4123                    break;
4124                }
4125            }
4126
4127            if (rdr->rewritemm <= 0) {
4128                fprintf(stderr, "Notice: Setting EMMCACHE to %i,1,%i instead of %i,%i,%i. ",
4129                        rdr->cachemm, rdr->logemm,
4130                        rdr->cachemm, rdr->rewritemm,
4131                        rdr->logemm);
4132
4133                fprintf(stderr, "Zero or negative number of rewrites is silly\n");
4134                rdr->rewritemm = 1;
4135            }
4136            return;
4137        }
4138    }
4139
4140    if (!strcmp(token, "blocknano")) {
4141        rdr->b_nano = 0;
4142        if (strlen(value) > 0) {
4143            if (!strcmp(value,"all")) {
4144                rdr->b_nano = 0xFFFF;
4145            } else {
4146                for (ptr = strtok_r(value, ",", &saveptr1); ptr; ptr = strtok_r(NULL, ",", &saveptr1)) {
4147                    i = (byte_atob(ptr) % 0x80);
4148                    if (i >= 0 && i <= 16)
4149                        rdr->b_nano |= (1 << i);
4150                }
4151            }
4152        }
4153        return;
4154    }
4155
4156    if (!strcmp(token, "savenano")) {
4157        rdr->s_nano = 0;
4158        if (strlen(value) > 0) {
4159            if (!strcmp(value,"all")) {
4160                rdr->s_nano = 0xFFFF;
4161            } else {
4162                for (ptr = strtok_r(value, ",", &saveptr1); ptr; ptr = strtok_r(NULL, ",", &saveptr1)) {
4163                    i = (byte_atob(ptr) % 0x80);
4164                    if (i >= 0 && i <= 16)
4165                        rdr->s_nano |= (1 << i);
4166                }
4167            }
4168        }
4169        return;
4170    }
4171
4172    if (!strcmp(token, "blockemm-unknown")) {
4173        i=atoi(value);
4174        if (!i && (rdr->blockemm & EMM_UNKNOWN))
4175            rdr->blockemm -= EMM_UNKNOWN;
4176        if (i)
4177            rdr->blockemm |= EMM_UNKNOWN;
4178        return;
4179    }
4180
4181    if (!strcmp(token, "blockemm-u")) {
4182        i=atoi(value);
4183        if (!i && (rdr->blockemm & EMM_UNIQUE))
4184            rdr->blockemm -= EMM_UNIQUE;
4185        if (i)
4186            rdr->blockemm |= EMM_UNIQUE;
4187        return;
4188    }
4189
4190    if (!strcmp(token, "blockemm-s")) {
4191        i=atoi(value);
4192        if (!i && (rdr->blockemm & EMM_SHARED))
4193            rdr->blockemm -= EMM_SHARED;
4194        if (i)
4195            rdr->blockemm |= EMM_SHARED;
4196        return;
4197    }
4198
4199    if (!strcmp(token, "blockemm-g")) {
4200        i=atoi(value);
4201        if (!i && (rdr->blockemm & EMM_GLOBAL))
4202            rdr->blockemm -= EMM_GLOBAL;
4203        if (i)
4204            rdr->blockemm |= EMM_GLOBAL;
4205        return;
4206    }
4207
4208#ifdef WITH_LB
4209    if (!strcmp(token, "lb_weight")) {
4210        if(strlen(value) == 0) {
4211            rdr->lb_weight = 100;
4212            return;
4213        } else {
4214            rdr->lb_weight = atoi(value);
4215            if (rdr->lb_weight > 1000) rdr->lb_weight = 1000;
4216            else if (rdr->lb_weight <= 0) rdr->lb_weight = 100;
4217            return;
4218        }
4219    }
4220#endif
4221
4222#ifdef MODULE_CCCAM
4223    if (!strcmp(token, "cccversion")) {
4224        // cccam version
4225        memset(rdr->cc_version, 0, sizeof(rdr->cc_version));
4226        if (strlen(value) > sizeof(rdr->cc_version) - 1) {
4227            fprintf(stderr, "cccam config: version too long.\n");
4228        }   else   
4229            cs_strncpy(rdr->cc_version, value, sizeof(rdr->cc_version));
4230        return;
4231    }
4232
4233    if (!strcmp(token, "cccmaxhop") || !strcmp(token, "cccmaxhops")) { //Schlocke: cccmaxhops is better!
4234        // cccam max card distance
4235        rdr->cc_maxhop  = strToIntVal(value, 10);
4236        return;
4237    }
4238
4239    if (!strcmp(token, "cccmindown") ) {
4240        // cccam min downhops
4241        rdr->cc_mindown  = strToIntVal(value, 0);
4242        return;
4243    }
4244
4245    if (!strcmp(token, "cccwantemu")) {
4246        rdr->cc_want_emu  = strToIntVal(value, 0);
4247        return;
4248    }
4249
4250    if (!strcmp(token, "ccckeepalive")) {
4251        rdr->cc_keepalive  = strToIntVal(value, 0);
4252        return;
4253    }
4254
4255    if (!strcmp(token, "ccchopsaway") || !strcmp(token, "cccreshar")  || !strcmp(token, "cccreshare")) {
4256        rdr->cc_reshare = atoi(value);
4257        if (rdr->cc_reshare == cfg.cc_reshare)
4258            rdr->cc_reshare = -1;
4259        return;
4260    }
4261
4262    if (!strcmp(token, "ccchop")) {
4263        rdr->cc_hop = strToIntVal(value, 0);
4264        return;
4265    }
4266#endif
4267
4268    if (!strcmp(token, "deprecated")) {
4269        rdr->deprecated  = strToIntVal(value, 0);
4270        return;
4271    }
4272
4273    if (!strcmp(token, "audisabled")) {
4274        rdr->audisabled  = strToIntVal(value, 0);
4275        return;
4276    }
4277
4278    if (!strcmp(token, "auprovid")) {
4279        if (strlen(value) == 0) {
4280            rdr->auprovid = 0;
4281            return;
4282        } else {
4283            rdr->auprovid = a2i(value, 3);
4284            return;
4285        }
4286    }
4287    // new code for multiple aes key per reader
4288    if (!strcmp(token, "aeskeys")) {
4289        parse_aes_keys(rdr,value);
4290        return;
4291    }
4292
4293    if (!strcmp(token, "ndsversion")) {
4294        rdr->ndsversion = strToIntVal(value, 0);
4295        return;
4296    }
4297
4298
4299#ifdef AZBOX
4300    if (!strcmp(token, "mode")) {
4301        rdr->mode = strToIntVal(value, -1);
4302        return;
4303    }
4304#endif
4305
4306    //ratelimit
4307    if (!strcmp(token, "ratelimitecm")) {
4308        if (strlen(value) == 0) {
4309            rdr->ratelimitecm = 0;
4310            return;
4311        } else {
4312            rdr->ratelimitecm = atoi(value);
4313            int32_t h;
4314            for (h=0;h<rdr->ratelimitecm;h++) rdr->rlecmh[h].last=-1;
4315            return;
4316        }
4317    }
4318    if (!strcmp(token, "ratelimitseconds")) {
4319        if (strlen(value) == 0) {
4320            if (rdr->ratelimitecm>0) {
4321                rdr->ratelimitseconds = 10;
4322            } else {
4323                rdr->ratelimitseconds = 0;
4324            }
4325            return;
4326        } else {
4327            rdr->ratelimitseconds = atoi(value);
4328            return;
4329        }
4330    }
4331    if (token[0] != '#')
4332        fprintf(stderr, "Warning: keyword '%s' in reader section not recognized\n",token);
4333}
4334
4335#ifdef IRDETO_GUESSING
4336int32_t init_irdeto_guess_tab()
4337{
4338  int32_t i, j, skip;
4339  int32_t b47;
4340  FILE *fp;
4341  char token[128], *ptr, *saveptr1 = NULL;
4342  char zSid[5];
4343  uchar b3;
4344  uint16_t caid, sid;
4345  struct s_irdeto_quess *ird_row, *head;
4346
4347  memset(cfg.itab, 0, sizeof(cfg.itab));
4348  snprintf(token, sizeof(token), "%s%s", cs_confdir, cs_ird);
4349  if (!(fp=fopen(token, "r")))
4350  {
4351    cs_log("can't open file \"%s\" (errno=%d %s) irdeto guessing not loaded",
4352           token, errno, strerror(errno));
4353    return(1);
4354  }
4355  while (fgets(token, sizeof(token), fp))
4356  {
4357    if( strlen(token)<20 ) continue;
4358    for( i=b3=b47=caid=sid=skip=0, ptr=strtok_r(token, ":", &saveptr1); (i<4)&&(ptr); ptr=strtok_r(NULL, ":", &saveptr1), i++ )
4359    {
4360      trim(ptr);
4361      if( *ptr==';' || *ptr=='#' || *ptr=='-' ) {
4362        skip=1;
4363        break;
4364      }
4365      switch(i)
4366      {
4367        case 0: b3   = a2i(ptr, 2); break;
4368        case 1: b47  = a2i(ptr, 8); break;
4369        case 2: caid = a2i(ptr, 4); break;
4370        case 3:
4371          for( j=0; j<4; j++ )
4372            zSid[j]=ptr[j];
4373          zSid[4]=0;
4374          sid  = a2i(zSid, 4);
4375          break;
4376      }
4377    }
4378    if( !skip )
4379    {
4380      if (!cs_malloc(&ird_row, sizeof(struct s_irdeto_quess), -1)) return(1);
4381      ird_row->b47  = b47;
4382      ird_row->caid = caid;
4383      ird_row->sid  = sid;
4384      ird_row->next = 0;
4385
4386      head = cfg.itab[b3];
4387      if( head ) {
4388        while( head->next )
4389          head=head->next;
4390        head->next=ird_row;
4391      }
4392      else
4393        cfg.itab[b3]=ird_row;
4394        //cs_debug_mask(D_CLIENT, "%02X:%08X:%04X:%04X", b3, b47, caid, sid);
4395    }
4396  }
4397  fclose(fp);
4398
4399  for( i=0; i<0xff; i++ )
4400  {
4401    head=cfg.itab[i];
4402    while(head)
4403    {
4404      cs_debug_mask(D_CLIENT, "itab[%02X]: b47=%08X, caid=%04X, sid=%04X",
4405               i, head->b47, head->caid, head->sid);
4406      head=head->next;
4407    }
4408  }
4409  return(0);
4410}
4411#endif
4412
4413/**
4414 * frees a reader
4415 **/
4416void free_reader(struct s_reader *rdr)
4417{
4418    NULLFREE(rdr->emmfile);
4419
4420    struct s_ecmWhitelist *tmp;
4421    struct s_ecmWhitelistIdent *tmpIdent;
4422    struct s_ecmWhitelistLen *tmpLen;
4423    for(tmp = rdr->ecmWhitelist; tmp; tmp=tmp->next){
4424        for(tmpIdent = tmp->idents; tmpIdent; tmpIdent=tmpIdent->next){
4425            for(tmpLen = tmpIdent->lengths; tmpLen; tmpLen=tmpLen->next){
4426                add_garbage(tmpLen);
4427            }
4428            add_garbage(tmpIdent);
4429        }
4430        add_garbage(tmp);
4431    }
4432    rdr->ecmWhitelist = NULL;
4433
4434    clear_ftab(&rdr->ftab);
4435
4436#ifdef WITH_LB
4437    ll_destroy_data(rdr->lb_stat);
4438#endif
4439    add_garbage(rdr);
4440}
4441
4442int32_t init_readerdb()
4443{
4444    int32_t tag = 0;
4445    FILE *fp;
4446    char *value;
4447
4448    snprintf(token, sizeof(token), "%s%s", cs_confdir, cs_srvr);
4449    if (!(fp=fopen(token, "r"))) {
4450        cs_log("can't open file \"%s\" (errno=%d %s)\n", token, errno, strerror(errno));
4451        return(1);
4452    }
4453    struct s_reader *rdr;
4454    cs_malloc(&rdr, sizeof(struct s_reader), SIGINT);
4455    configured_readers = ll_create();
4456    ll_append(configured_readers, rdr);
4457    while (fgets(token, sizeof(token), fp)) {
4458        int32_t i, l;
4459        if ((l = strlen(trim(token))) < 3)
4460            continue;
4461        if ((token[0] == '[') && (token[l-1] == ']')) {
4462            token[l-1] = 0;
4463            tag = (!strcmp("reader", strtolower(token+1)));
4464            if (rdr->label[0] && rdr->typ) {
4465                struct s_reader *newreader;
4466                if(cs_malloc(&newreader, sizeof(struct s_reader), -1)){
4467                    ll_append(configured_readers, newreader);
4468                    rdr = newreader;
4469                }
4470            }
4471            rdr->enable = 1;
4472            rdr->tcp_rto = 30;
4473            rdr->show_cls = 10;
4474            rdr->nagra_read = 0;
4475            rdr->mhz = 357;
4476            rdr->cardmhz = 357;
4477            rdr->deprecated = 0;
4478            rdr->force_irdeto = 0;
4479#ifdef MODULE_CCCAM
4480            rdr->cc_reshare = -1;
4481            rdr->cc_maxhop = 10;
4482            rdr->cc_mindown = 0;
4483#endif
4484#ifdef WITH_LB
4485            rdr->lb_weight = 100;
4486#endif
4487            cs_strncpy(rdr->pincode, "none", sizeof(rdr->pincode));
4488            rdr->ndsversion = 0;
4489            rdr->ecmWhitelist = NULL;
4490            for (i=1; i<CS_MAXCAIDTAB; rdr->ctab.mask[i++]=0xffff);
4491            continue;
4492        }
4493
4494        if (!tag)
4495            continue;
4496        if (!(value=strchr(token, '=')))
4497            continue;
4498        *value++ ='\0';
4499        chk_reader(trim(strtolower(token)), trim(value), rdr);
4500    }
4501    LL_ITER itr = ll_iter_create(configured_readers);
4502    struct s_reader *cur=NULL;
4503    while((rdr = ll_iter_next(&itr))) { //build active readers list
4504        int32_t i;
4505        if (rdr->device[0] && (rdr->typ & R_IS_CASCADING)) {
4506            for (i=0; i<CS_MAX_MOD; i++) {
4507                if (ph[i].num && rdr->typ==ph[i].num) {
4508                    rdr->ph=ph[i];
4509                    rdr->ph.active=1;
4510                }
4511            }
4512        }
4513
4514        if (rdr->enable) {
4515            if (!first_active_reader) {
4516                first_active_reader = rdr; //init list
4517                cur = rdr;
4518            }
4519            else {
4520                cur->next = rdr; //add to end of list
4521                cur = rdr; //advance list
4522            }
4523        }
4524    }
4525    fclose(fp);
4526    return(0);
4527}
4528
4529#ifdef CS_ANTICASC
4530void init_ac()
4531{
4532  int32_t nr;
4533  FILE *fp;
4534  char *saveptr1 = NULL;
4535
4536  snprintf(token, sizeof(token), "%s%s", cs_confdir, cs_ac);
4537  if (!(fp=fopen(token, "r")))
4538  {
4539    cs_log("can't open file \"%s\" (errno=%d %s) anti-cascading table not loaded",
4540            token, errno, strerror(errno));
4541    return;
4542  }
4543
4544  for(nr=0; fgets(token, sizeof(token), fp);)
4545  {
4546    int32_t i, skip;
4547    uint16_t caid, sid, chid, dwtime;
4548    uint32_t  provid;
4549    char *ptr, *ptr1;
4550    struct s_cpmap *ptr_cpmap;
4551    static struct s_cpmap *cpmap=(struct s_cpmap *)0;
4552
4553    if( strlen(token)<4 ) continue;
4554
4555    caid=sid=chid=dwtime=0;
4556    provid=0;
4557    skip=0;
4558    ptr1=0;
4559    for( i=0, ptr=strtok_r(token, "=", &saveptr1); (i<2)&&(ptr); ptr=strtok_r(NULL, "=", &saveptr1), i++ )
4560    {
4561      trim(ptr);
4562      if( *ptr==';' || *ptr=='#' || *ptr=='-' ) {
4563        skip=1;
4564        break;
4565      }
4566      switch( i )
4567      {
4568        case 0:
4569          ptr1=ptr;
4570          break;
4571        case 1:
4572          dwtime = atoi(ptr);
4573          break;
4574      }
4575    }
4576
4577    if( !skip )
4578    {
4579      for( i=0, ptr=strtok_r(ptr1, ":", &saveptr1); (i<4)&&(ptr); ptr=strtok_r(NULL, ":", &saveptr1), i++ )
4580      {
4581        trim(ptr);
4582        switch( i )
4583        {
4584        case 0:
4585          if( *ptr=='*' ) caid = 0;
4586          else caid = a2i(ptr, 4);
4587          break;
4588        case 1:
4589          if( *ptr=='*' ) provid = 0;
4590          else provid = a2i(ptr, 6);
4591          break;
4592        case 2:
4593          if( *ptr=='*' ) sid = 0;
4594          else sid = a2i(ptr, 4);
4595          break;
4596        case 3:
4597          if( *ptr=='*' ) chid = 0;
4598          else chid = a2i(ptr, 4);
4599          break;
4600        }
4601      }
4602      if (!cs_malloc(&ptr_cpmap, sizeof(struct s_cpmap), -1)) return;
4603      if( cpmap )
4604        cpmap->next=ptr_cpmap;
4605      else
4606        cfg.cpmap=ptr_cpmap;
4607      cpmap=ptr_cpmap;
4608
4609      cpmap->caid   = caid;
4610      cpmap->provid = provid;
4611      cpmap->sid    = sid;
4612      cpmap->chid   = chid;
4613      cpmap->dwtime = dwtime;
4614      cpmap->next   = 0;
4615
4616      cs_debug_mask(D_CLIENT, "nr=%d, caid=%04X, provid=%06X, sid=%04X, chid=%04X, dwtime=%d",
4617                nr, caid, provid, sid, chid, dwtime);
4618      nr++;
4619    }
4620  }
4621  fclose(fp);
4622  //cs_log("%d lengths for caid guessing loaded", nr);
4623  return;
4624}
4625#endif
4626
4627/*
4628 * Creates a string ready to write as a token into config or WebIf for CAIDs. You must free the returned value through free_mk_t().
4629 */
4630char *mk_t_caidtab(CAIDTAB *ctab){
4631    int32_t i = 0, needed = 1, pos = 0;
4632    while(ctab->caid[i]){
4633        if(ctab->mask[i]) needed += 10;
4634        else needed += 5;
4635        if(ctab->cmap[i]) needed += 5;
4636        ++i;
4637    }
4638    char *value;
4639    if(needed == 1 || !cs_malloc(&value, needed * sizeof(char), -1)) return "";
4640    char *saveptr = value;
4641    i = 0;
4642    while(ctab->caid[i]) {
4643        if(i == 0) {
4644            snprintf(value + pos, needed-(value-saveptr), "%04X", ctab->caid[i]);
4645            pos += 4;
4646        } else {
4647            snprintf(value + pos, needed-(value-saveptr), ",%04X", ctab->caid[i]);
4648            pos += 5;
4649        }
4650        if((ctab->mask[i]) && (ctab->mask[i] != 0xFFFF)){
4651            snprintf(value + pos, needed-(value-saveptr), "&%04X", ctab->mask[i]);
4652            pos += 5;
4653        }
4654        if(ctab->cmap[i]){
4655            snprintf(value + pos, needed-(value-saveptr), ":%04X", ctab->cmap[i]);
4656            pos += 5;
4657        }
4658        ++i;
4659    }
4660    value[pos] = '\0';
4661    return value;
4662}
4663
4664/*
4665 * Creates a string ready to write as a token into config or WebIf for TunTabs. You must free the returned value through free_mk_t().
4666 */
4667char *mk_t_tuntab(TUNTAB *ttab){
4668    int32_t i, needed = 1, pos = 0;
4669    for (i=0; i<ttab->n; i++) {
4670        if(ttab->bt_srvid[i]) needed += 10;
4671        else needed += 5;
4672        if(ttab->bt_caidto[i]) needed += 5;
4673    }
4674    char *value;
4675    if(needed == 1 || !cs_malloc(&value, needed * sizeof(char), -1)) return "";
4676    char *saveptr = value;
4677    for (i=0; i<ttab->n; i++) {
4678        if(i == 0) {
4679            snprintf(value + pos, needed-(value-saveptr), "%04X", ttab->bt_caidfrom[i]);
4680            pos += 4;
4681        } else {
4682            snprintf(value + pos, needed-(value-saveptr), ",%04X", ttab->bt_caidfrom[i]);
4683            pos += 5;
4684        }
4685        if(ttab->bt_srvid[i]){
4686            snprintf(value + pos, needed-(value-saveptr), ".%04X", ttab->bt_srvid[i]);
4687            pos += 5;
4688        }
4689        if(ttab->bt_caidto[i]){
4690            snprintf(value + pos, needed-(value-saveptr), ":%04X", ttab->bt_caidto[i]);
4691            pos += 5;
4692        }
4693    }
4694    value[pos] = '\0';
4695    return value;
4696}
4697
4698/*
4699 * Creates a string ready to write as a token into config or WebIf for groups. You must free the returned value through free_mk_t().
4700 */
4701char *mk_t_group(uint64_t grp){
4702    int32_t i = 0, needed = 1, pos = 0, dot = 0;
4703
4704    for(i = 0; i < 64; i++){
4705        if (grp&((uint64_t)1<<i)){
4706            needed += 2;
4707            if(i > 9) needed += 1;
4708        }
4709    }
4710    char *value;
4711    if(needed == 1 || !cs_malloc(&value, needed * sizeof(char), -1)) return "";
4712    char * saveptr = value;
4713    for(i = 0; i < 64; i++){
4714        if (grp&((uint64_t)1<<i)){
4715            if (dot == 0){
4716                snprintf(value + pos, needed-(value-saveptr), "%d", i+1);
4717                if (i > 8)pos += 2;
4718                else pos += 1;
4719                dot = 1;
4720            } else {
4721                snprintf(value + pos, needed-(value-saveptr), ",%d", i+1);
4722                if (i > 8)pos += 3;
4723                else pos += 2;
4724            }
4725        }
4726    }
4727    value[pos] = '\0';
4728    return value;
4729}
4730
4731/*
4732 * Creates a string ready to write as a token into config or WebIf for FTabs (CHID, Ident). You must free the returned value through free_mk_t().
4733 */
4734char *mk_t_ftab(FTAB *ftab){
4735    int32_t i = 0, j = 0, needed = 1, pos = 0;
4736
4737    if (ftab->nfilts != 0) {
4738        needed = ftab->nfilts * 5;
4739        for (i = 0; i < ftab->nfilts; ++i)
4740            needed += ftab->filts[i].nprids * 7;
4741    }
4742
4743    char *value;
4744    if(needed == 1 || !cs_malloc(&value, needed * sizeof(char), -1)) return "";
4745    char *saveptr = value;
4746    char *dot="";
4747    for (i = 0; i < ftab->nfilts; ++i){
4748        snprintf(value + pos, needed-(value-saveptr), "%s%04X", dot, ftab->filts[i].caid);
4749        pos += 4;
4750        if (i > 0) pos += 1;
4751        dot=":";
4752        for (j = 0; j < ftab->filts[i].nprids; ++j) {
4753            snprintf(value + pos, needed-(value-saveptr), "%s%06X", dot, ftab->filts[i].prids[j]);
4754            pos += 7;
4755            dot=",";
4756        }
4757        dot=";";
4758    }
4759
4760    value[pos] = '\0';
4761    return value;
4762}
4763
4764/*
4765 * Creates a string ready to write as a token into config or WebIf for the camd35 tcp ports. You must free the returned value through free_mk_t().
4766 */
4767char *mk_t_camd35tcp_port(){
4768    int32_t i, j, pos = 0, needed = 1;
4769
4770    /* Precheck to determine how long the resulting string will maximally be (might be a little bit smaller but that shouldn't hurt) */
4771    for(i = 0; i < cfg.c35_tcp_ptab.nports; ++i) {
4772        /* Port is maximally 5 chars long, plus the @caid, plus the ";" between ports */
4773        needed += 11;
4774        if (cfg.c35_tcp_ptab.ports[i].ftab.filts[0].nprids > 1){
4775            needed += cfg.c35_tcp_ptab.ports[i].ftab.filts[0].nprids * 7;
4776        }
4777    }
4778    char *value;
4779    if(needed == 1 || !cs_malloc(&value, needed * sizeof(char), -1)) return "";
4780    char *saveptr = value;
4781    char *dot1 = "", *dot2;
4782    for(i = 0; i < cfg.c35_tcp_ptab.nports; ++i) {
4783        pos += snprintf(value + pos, needed-(value-saveptr), "%s%d@%04X", dot1, cfg.c35_tcp_ptab.ports[i].s_port, cfg.c35_tcp_ptab.ports[i].ftab.filts[0].caid);
4784        if (cfg.c35_tcp_ptab.ports[i].ftab.filts[0].nprids > 1) {
4785            dot2 = ":";
4786            for (j = 0; j < cfg.c35_tcp_ptab.ports[i].ftab.filts[0].nprids; ++j) {
4787                pos += snprintf(value + pos, needed-(value-saveptr), "%s%X", dot2, cfg.c35_tcp_ptab.ports[i].ftab.filts[0].prids[j]);
4788                dot2 = ",";
4789            }
4790        }
4791        dot1=";";
4792    }
4793    return value;
4794}
4795
4796#ifdef MODULE_CCCAM
4797/*
4798 * Creates a string ready to write as a token into config or WebIf for the cccam tcp ports. You must free the returned value through free_mk_t().
4799 */
4800char *mk_t_cccam_port(){
4801    int32_t i, pos = 0, needed = CS_MAXPORTS*6+8;
4802
4803    char *value;
4804    if(!cs_malloc(&value, needed * sizeof(char), -1)) return "";
4805    char *dot = "";
4806    for(i = 0; i < CS_MAXPORTS; i++) {
4807        if (!cfg.cc_port[i]) break;
4808
4809        pos += snprintf(value + pos, needed-pos, "%s%d", dot, cfg.cc_port[i]);
4810        dot=",";
4811    }
4812    return value;
4813}
4814#endif
4815
4816
4817/*
4818 * Creates a string ready to write as a token into config or WebIf for AESKeys. You must free the returned value through free_mk_t().
4819 */
4820char *mk_t_aeskeys(struct s_reader *rdr){
4821    AES_ENTRY *current = rdr->aes_list;
4822    int32_t i, pos = 0, needed = 1, prevKeyid = 0, prevCaid = 0;
4823    uint32_t prevIdent = 0;
4824
4825    /* Precheck for the approximate size that we will need; it's a bit overestimated but we correct that at the end of the function */
4826    while(current) {
4827        /* The caid, ident, "@" and the trailing ";" need to be output when they are changing */
4828        if(prevCaid != current->caid || prevIdent != current->ident) needed += 12 + (current->keyid * 2);
4829        /* "0" keys are not saved so we need to check for gaps */
4830        else if(prevKeyid != current->keyid + 1) needed += (current->keyid - prevKeyid - 1) * 2;
4831        /* The 32 byte key plus either the (heading) ":" or "," */
4832        needed += 33;
4833        prevCaid = current->caid;
4834        prevIdent = current->ident;
4835        prevKeyid = current->keyid;
4836        current = current->next;
4837    }
4838
4839    /* Set everything back and now create the string */
4840    current = rdr->aes_list;
4841    prevCaid = 0;
4842    prevIdent = 0;
4843    prevKeyid = 0;
4844    char tmp[needed];
4845    char dot;
4846    if(needed == 1) tmp[0] = '\0';
4847    char tmpkey[33];
4848    while(current) {
4849        /* A change in the ident or caid means that we need to output caid and ident */
4850        if(prevCaid != current->caid || prevIdent != current->ident){
4851            if(pos > 0) {
4852                tmp[pos] = ';';
4853                ++pos;
4854            }
4855            pos += snprintf(tmp+pos, sizeof(tmp)-pos, "%04X@%06X", current->caid, current->ident);
4856            prevKeyid = -1;
4857            dot = ':';
4858        } else dot = ',';
4859        /* "0" keys are not saved so we need to check for gaps and output them! */
4860        for (i = prevKeyid + 1; i < current->keyid; ++i) {
4861            pos += snprintf(tmp+pos, sizeof(tmp)-pos, "%c0", dot);
4862            dot = ',';
4863        }
4864        tmp[pos] = dot;
4865        ++pos;
4866        for (i = 0; i < 16; ++i) snprintf(tmpkey + (i*2), sizeof(tmpkey) - (i*2), "%02X", current->plainkey[i]);
4867        /* A key consisting of only FFs has a special meaning (just return what the card outputted) and can be specified more compact */
4868        if(strcmp(tmpkey, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF") == 0) pos += snprintf(tmp+pos, sizeof(tmp)-pos, "FF");
4869        else pos += snprintf(tmp+pos, sizeof(tmp)-pos, "%s", tmpkey);
4870        prevCaid = current->caid;
4871        prevIdent = current->ident;
4872        prevKeyid = current->keyid;
4873        current = current->next;
4874    }
4875
4876    /* copy to result array of correct size */
4877    char *value;
4878    if(pos == 0 || !cs_malloc(&value, (pos + 1) * sizeof(char), -1)) return "";
4879    memcpy(value, tmp, pos + 1);
4880    return(value);
4881}
4882
4883/*
4884 * Creates a string ready to write as a token into config or WebIf for the Newcamd Port. You must free the returned value through free_mk_t().
4885 */
4886char *mk_t_newcamd_port(){
4887    int32_t i, j, k, pos = 0, needed = 1;
4888
4889    /* Precheck to determine how long the resulting string will maximally be (might be a little bit smaller but that shouldn't hurt) */
4890    for(i = 0; i < cfg.ncd_ptab.nports; ++i){
4891        /* Port is maximally 5 chars long, plus the @caid, plus the ";" between ports */
4892        needed += 11;
4893        if(cfg.ncd_ptab.ports[i].ncd_key_is_set) needed += 30;
4894        if (cfg.ncd_ptab.ports[i].ftab.filts[0].nprids > 0){
4895            needed += cfg.ncd_ptab.ports[i].ftab.filts[0].nprids * 7;
4896        }
4897    }
4898    char *value;
4899    if(needed == 1 || !cs_malloc(&value, needed * sizeof(char), -1)) return "";
4900    char *dot1 = "", *dot2;
4901
4902    for(i = 0; i < cfg.ncd_ptab.nports; ++i){
4903        pos += snprintf(value + pos, needed-pos,  "%s%d", dot1, cfg.ncd_ptab.ports[i].s_port);
4904
4905        // separate DES Key for this port
4906        if(cfg.ncd_ptab.ports[i].ncd_key_is_set){
4907            pos += snprintf(value + pos, needed-pos, "{");
4908            for (k = 0; k < 14; k++)
4909                pos += snprintf(value + pos, needed-pos, "%02X", cfg.ncd_ptab.ports[i].ncd_key[k]);
4910            pos += snprintf(value + pos, needed-pos, "}");
4911        }
4912
4913        pos += snprintf(value + pos, needed-pos, "@%04X", cfg.ncd_ptab.ports[i].ftab.filts[0].caid);
4914
4915        if (cfg.ncd_ptab.ports[i].ftab.filts[0].nprids > 0){
4916            dot2 = ":";
4917            for (j = 0; j < cfg.ncd_ptab.ports[i].ftab.filts[0].nprids; ++j){
4918                pos += snprintf(value + pos, needed-pos, "%s%06X", dot2, (int)cfg.ncd_ptab.ports[i].ftab.filts[0].prids[j]);
4919                dot2 = ",";
4920            }
4921        }
4922        dot1=";";
4923    }
4924    return value;
4925}
4926
4927/*
4928 * Creates a string ready to write as a token into config or WebIf for au readers. You must free the returned value through free_mk_t().
4929 */
4930char *mk_t_aureader(struct s_auth *account){
4931    int32_t pos = 0;
4932    char *dot = "";
4933
4934    char *value;
4935    if(ll_count(account->aureader_list) == 0 || !cs_malloc(&value, 256 * sizeof(char), -1)) return "";
4936    value[0] = '\0';
4937
4938    struct s_reader *rdr;
4939    LL_ITER itr = ll_iter_create(account->aureader_list);
4940    while ((rdr = ll_iter_next(&itr))) {
4941        pos += snprintf(value + pos, 256-pos, "%s%s", dot, rdr->label);
4942        dot = ",";
4943    }
4944
4945    return value;
4946}
4947
4948/*
4949 * Creates a string ready to write as a token into config or WebIf for blocknano and savenano. You must free the returned value through free_mk_t().
4950 * flag 0x01 for blocknano or 0x02 for savenano
4951 */
4952char *mk_t_nano(struct s_reader *rdr, uchar flag){
4953    int32_t i, pos = 0, needed = 0;
4954    uint16_t nano = 0;
4955
4956    if (flag==0x01)
4957        nano=rdr->b_nano;
4958    else
4959        nano=rdr->s_nano;
4960
4961    for (i=0; i<16; i++)
4962        if ((1 << i) & nano)
4963            needed++;
4964
4965    char *value;
4966    if (nano == 0xFFFF) {
4967        if(!cs_malloc(&value, (3 * sizeof(char)) + 1, -1)) return "";
4968        snprintf(value, 4, "all");
4969    } else {
4970        if(needed == 0 || !cs_malloc(&value, (needed * 3 * sizeof(char)) + 1, -1)) return "";
4971        value[0] = '\0';
4972        for (i=0; i<16; i++) {
4973            if ((1 << i) & nano)
4974                pos += snprintf(value + pos, (needed*3)+1-pos, "%s%02x", pos ? "," : "", (i+0x80));
4975        }
4976    }
4977    return value;
4978}
4979
4980/*
4981 * Creates a string ready to write as a token into config or WebIf for the sidtab. You must free the returned value through free_mk_t().
4982 */
4983char *mk_t_service( uint64_t sidtabok, uint64_t sidtabno){
4984    int32_t i, pos;
4985    char *dot;
4986    char *value;
4987    struct s_sidtab *sidtab = cfg.sidtab;
4988    if(!sidtab || (!sidtabok && !sidtabno) || !cs_malloc(&value, 1024, -1)) return "";
4989    value[0] = '\0';
4990
4991    for (i=pos=0,dot=""; sidtab; sidtab=sidtab->next,i++){
4992        if (sidtabok&((SIDTABBITS)1<<i)) {
4993            pos += snprintf(value + pos, 1024 - pos, "%s%s", dot, sidtab->label);
4994            dot = ",";
4995        }
4996        if (sidtabno&((SIDTABBITS)1<<i)) {
4997            pos += snprintf(value + pos, 1024 - pos, "%s!%s", dot, sidtab->label);
4998            dot = ",";
4999        }
5000    }
5001    return value;
5002}
5003
5004/*
5005 * Creates a string ready to write as a token into config or WebIf for the logfile parameter. You must free the returned value through free_mk_t().
5006 */
5007char *mk_t_logfile(){
5008    int32_t pos = 0, needed = 1;
5009    char *value, *dot = "";
5010
5011    if(cfg.logtostdout == 1) needed += 7;
5012    if(cfg.logtosyslog == 1) needed += 7;
5013    if(cfg.logfile != NULL) needed += strlen(cfg.logfile);
5014    if(needed == 1 || !cs_malloc(&value, needed * sizeof(