source: trunk/oscam-simples.c@ 4149

Last change on this file since 4149 was 3987, checked in by schlocke, 13 years ago

cccam: fixed connection lost/reset/dups

File size: 24.4 KB
Line 
1//FIXME Not checked on threadsafety yet; after checking please remove this line
2#include <sys/time.h>
3#include "globals.h"
4#include "module-cccam.h"
5
6void aes_set_key(char *key)
7{
8 AES_set_decrypt_key((const unsigned char *)key, 128, &cur_client()->aeskey_decrypt);
9 AES_set_encrypt_key((const unsigned char *)key, 128, &cur_client()->aeskey);
10}
11
12void aes_decrypt(uchar *buf, int n)
13{
14 int i;
15 for(i=0; i<n; i+=16)
16 AES_decrypt(buf+i, buf+i, &cur_client()->aeskey_decrypt);
17}
18
19void aes_encrypt_idx(struct s_client *cl, uchar *buf, int n)
20{
21 int i;
22 for(i=0; i<n; i+=16)
23 AES_encrypt(buf+i, buf+i, &cl->aeskey);
24}
25
26void add_aes_entry(struct s_reader *rdr, ushort caid, uint32 ident, int keyid, uchar *aesKey)
27{
28 AES_ENTRY *new_entry;
29 AES_ENTRY *next,*current;
30
31 // create de AES key entry for the linked list
32 new_entry=malloc(sizeof(AES_ENTRY));
33 if(!new_entry) {
34 cs_log("Error alocation memory for AES key entry");
35 return;
36 }
37
38 new_entry->caid=caid;
39 new_entry->ident=ident;
40 new_entry->keyid=keyid;
41 if(memcmp(aesKey,"\xFF\xFF",2)) {
42 AES_set_decrypt_key((const unsigned char *)aesKey, 128, &(new_entry->key));
43 // cs_log("adding key : %s",cs_hexdump(1,aesKey,16));
44 }
45 else {
46 memset(&new_entry->key,0,sizeof(AES_KEY));
47 // cs_log("adding fake key");
48 }
49 new_entry->next=NULL;
50
51 //if list is empty, new_entry is the new head
52 if(!rdr->aes_list) {
53 rdr->aes_list=new_entry;
54 return;
55 }
56
57 //happend it to the list
58 current=rdr->aes_list;
59 next=current->next;
60 while(next) {
61 current=next;
62 next=current->next;
63 }
64
65 current->next=new_entry;
66
67}
68
69void parse_aes_entry(struct s_reader *rdr,char *value) {
70 ushort caid;
71 ushort dummy;
72 uint32 ident;
73 int len;
74 char *tmp;
75 int nb_keys,key_id;
76 uchar aes_key[16];
77 char *save=NULL;
78
79 tmp=strtok_r(value,"@",&save);
80 caid=a2i(tmp,2);
81 tmp=strtok_r(NULL,":",&save);
82 ident=a2i(tmp,3);
83
84 // now we need to split the key ane add the entry to the reader.
85 nb_keys=0;
86 key_id=0;
87 while((tmp=strtok_r(NULL,",",&save))) {
88 dummy=0;
89 len=strlen(tmp);
90 if(len!=32) {
91 dummy=a2i(tmp,1);
92 // FF means the card will do the AES decrypt
93 // 00 means we don't have the aes.
94 if((dummy!=0xFF && dummy!=0x00) || len>2) {
95 key_id++;
96 cs_log("AES key length error .. not adding");
97 continue;
98 }
99 if(dummy==0x00) {
100 key_id++;
101 continue;
102 }
103 }
104 nb_keys++;
105 if(dummy)
106 memset(aes_key,0xFF,16);
107 else
108 key_atob(tmp,aes_key);
109 // now add the key to the reader... TBD
110 add_aes_entry(rdr,caid,ident,key_id,aes_key);
111 key_id++;
112 }
113
114 cs_log("%d AES key(s) added on reader %s for %04x:%06x", nb_keys, rdr->label, caid, ident);
115}
116
117void parse_aes_keys(struct s_reader *rdr,char *value)
118{
119 // value format is caid1@ident1:key0,key1;caid2@indent2:key0,key1
120 char *entry;
121 char *save=NULL;
122
123 rdr->aes_list=NULL;
124 for (entry=strtok_r(value, ";",&save); entry; entry=strtok_r(NULL, ";",&save)) {
125 parse_aes_entry(rdr,entry);
126 }
127
128 /*
129 AES_ENTRY *current;
130 current=rdr->aes_list;
131 while(current) {
132 cs_log("**************************");
133 cs_log("current = %p",current);
134 cs_log("CAID = %04x",current->caid);
135 cs_log("IDENT = %06x",current->ident);
136 cs_log("keyID = %d",current->keyid);
137 cs_log("next = %p",current->next);
138 cs_log("**************************");
139 current=current->next;
140 }
141 */
142}
143
144int aes_decrypt_from_list(AES_ENTRY *list, ushort caid, uint32 provid,int keyid, uchar *buf, int n)
145{
146 AES_ENTRY *current;
147 AES_KEY dummy;
148 int i;
149 int ok=1;
150 int error=0;
151
152 current=list;
153 while(current) {
154 if(current->caid==caid && current->ident==provid && current->keyid==keyid)
155 break;
156 current=current->next;
157 }
158
159 if(!current) {
160 cs_log("AES Decrypt : key id %d not found for CAID %04X , provider %06x",keyid,caid,provid);
161 return error; // we don't have the key to decode this buffer.
162 }
163 else {
164 // hack for card that do the AES decrypt themsleves
165 memset(&dummy,0,sizeof(AES_KEY));
166 if(!memcmp(&current->key,&dummy,sizeof(AES_KEY))) {
167 return ok;
168 }
169 // decode the key
170 for(i=0; i<n; i+=16)
171 AES_decrypt(buf+i, buf+i, &(current->key));
172 }
173 return ok; // all ok, key decoded.
174}
175
176int aes_present(AES_ENTRY *list, ushort caid, uint32 provid,int keyid)
177{
178 AES_ENTRY *current;
179 int ok=1;
180 int error=0;
181
182 current=list;
183 while(current) {
184 if(current->caid==caid && current->ident==provid && current->keyid==keyid)
185 break;
186 current=current->next;
187 }
188
189 if(!current) {
190 cs_log("AES Decrypt : key id %d not found for CAID %04X , provider %06x",keyid,caid,provid);
191 return error; // we don't have the key to decode this buffer.
192 }
193
194 return ok;
195}
196
197void aes_clear_entries(struct s_reader *rdr)
198{
199
200 AES_ENTRY *current;
201 AES_ENTRY *next;
202
203 current=NULL;
204 next=rdr->aes_list;
205 while(next) {
206 current=next;
207 next=current->next;
208 free(current);
209 }
210 rdr->aes_list=NULL;
211}
212
213char *remote_txt(void)
214{
215 if (cur_client()->typ == 'c')
216 return("client");
217 else
218 return("remote server");
219}
220
221char *trim(txt)
222char *txt;
223{
224 register int l;
225 register char *p1, *p2;
226
227 if (*txt==' ')
228 {
229 for (p1=p2=txt;
230 (*p1==' ') || (*p1=='\t') || (*p1=='\n') || (*p1=='\r');
231 p1++);
232 while (*p1)
233 *p2++=*p1++;
234 *p2='\0';
235 }
236 if ((l=strlen(txt))>0)
237 for (p1=txt+l-1;
238 (*p1==' ') || (*p1=='\t') || (*p1=='\n') || (*p1=='\r');
239 *p1--='\0');
240
241 return(txt);
242}
243
244char *strtolower(char *txt)
245{
246 char *p;
247 for (p=txt; *p; p++)
248 if (isupper((uchar)*p)) *p=tolower((uchar)*p);
249 return(txt);
250}
251
252int gethexval(char c)
253{
254 if ((c>='0') && (c<='9')) return(c-'0');
255 if ((c>='A') && (c<='F')) return(c-'A'+10);
256 if ((c>='a') && (c<='f')) return(c-'a'+10);
257 return(-1);
258}
259
260int cs_atob(uchar *buf, char *asc, int n)
261{
262 int i, rc;
263 for (i=0; i<n; i++)
264 {
265 if ((rc=(gethexval(asc[i<<1])<<4)|gethexval(asc[(i<<1)+1]))&0x100)
266 return(-1);
267 buf[i]=rc;
268 }
269 return(n);
270}
271
272ulong cs_atoi(char *asc, int l, int val_on_err)
273{
274 int i, n=0;
275 ulong rc=0;
276 for (i=((l-1)<<1), errno=0; (i>=0) && (n<4); i-=2)
277 {
278 int b;
279 b=(gethexval(asc[i])<<4) | gethexval(asc[i+1]);
280 if (b<0)
281 {
282 errno=EINVAL;
283 rc=(val_on_err) ? 0xFFFFFFFF : 0;
284 break;
285 }
286 rc|=b<<(n<<3);
287 n++;
288 }
289 return(rc);
290}
291
292int byte_atob(char *asc)
293{
294 int rc;
295
296 if (strlen(trim(asc))!=2)
297 rc=(-1);
298 else
299 if ((rc=(gethexval(asc[0])<<4)|gethexval(asc[1]))&0x100)
300 rc=(-1);
301 return(rc);
302}
303
304long word_atob(char *asc)
305{
306 long rc;
307
308 if (strlen(trim(asc))!=4)
309 rc=(-1);
310 else
311 {
312 rc=gethexval(asc[0])<<12 | gethexval(asc[1])<<8 |
313 gethexval(asc[2])<<4 | gethexval(asc[3]);
314 if (rc&0x10000)
315 rc=(-1);
316 }
317 return(rc);
318}
319
320/*
321 * dynamic word_atob
322 * converts an 1-4 digit asc hexstring
323 */
324long dyn_word_atob(char *asc)
325{
326 long rc = (-1);
327 int i, len = strlen(trim(asc));
328
329 if (len <= 4 && len > 0) {
330 for(i = 0, rc = 0; i < len; i++)
331 rc = rc << 4 | gethexval(asc[i]);
332
333 if (rc & 0x10000)
334 rc = (-1);
335 }
336 return(rc);
337}
338
339int key_atob(char *asc, uchar *bin)
340{
341 int i, n1, n2, rc;
342 for (i=rc=0; i<32; i+=2)
343 {
344 if ((n1=gethexval(asc[i ]))<0) rc=(-1);
345 if ((n2=gethexval(asc[i+1]))<0) rc=(-1);
346 bin[i>>1]=(n1<<4)+(n2&0xff);
347 }
348 return(rc);
349}
350
351int key_atob14(char *asc, uchar *bin)
352{
353 int i, n1, n2, rc;
354 for (i=rc=0; i<28; i+=2)
355 {
356 if ((n1=gethexval(asc[i ]))<0) rc=(-1);
357 if ((n2=gethexval(asc[i+1]))<0) rc=(-1);
358 bin[i>>1]=(n1<<4)+(n2&0xff);
359 }
360 return(rc);
361}
362
363int key_atob_l(char *asc, uchar *bin, int l)
364{
365 int i, n1, n2, rc;
366 for (i=rc=0; i<l; i+=2)
367 {
368 if ((n1=gethexval(asc[i ]))<0) rc=(-1);
369 if ((n2=gethexval(asc[i+1]))<0) rc=(-1);
370 bin[i>>1]=(n1<<4)+(n2&0xff);
371 }
372 return(rc);
373}
374
375char *cs_hexdump(int m, const uchar *buf, int n)
376{
377 //TODO: not threadsafe
378 int i;
379 char *dump = (char *)cur_client()->dump;
380
381 dump[i=0]='\0';
382 m=(m)?3:2;
383 if (m*n>=(int)sizeof(cur_client()->dump)) n=(sizeof(cur_client()->dump)/m)-1;
384 while (i<n)
385 sprintf(dump+(m*i++), "%02X%s", *buf++, (m>2)?" ":"");
386 return(dump);
387}
388
389static int inet_byteorder=0;
390in_addr_t cs_inet_order(in_addr_t n)
391{
392 if (!inet_byteorder)
393 inet_byteorder=((inet_addr("1.2.3.4")+1)==inet_addr("1.2.3.5")) ? 1 : 2;
394 switch (inet_byteorder)
395 {
396 case 1:
397 break;
398 case 2:
399 n=((n&0xff000000) >> 24 ) |
400 ((n&0x00ff0000) >> 8 ) |
401 ((n&0x0000ff00) << 8 ) |
402 ((n&0x000000ff) << 24 );
403 break;
404 }
405 return(n);
406}
407
408char *cs_inet_ntoa(in_addr_t n)
409{
410 struct in_addr in;
411 in.s_addr=cs_inet_order(n);
412 return((char *)inet_ntoa(in));
413}
414
415in_addr_t cs_inet_addr(char *txt)
416{
417 if (!inet_byteorder)
418 inet_byteorder=((inet_addr("1.2.3.4")+1)==inet_addr("1.2.3.5")) ? 1 : 2;
419 if (inet_byteorder == 1)
420 return(inet_addr(txt));
421 else
422 return(inet_network(txt));
423}
424
425ulong b2i(int n, uchar *b)
426{
427 switch(n)
428 {
429 case 2:
430 return ((b[0]<<8) | b[1]);
431 case 3:
432 return ((b[0]<<16) | (b[1]<<8) | b[2]);
433 case 4:
434 return (((b[0]<<24) | (b[1]<<16) | (b[2]<<8) | b[3]) & 0xffffffffL);
435 default:
436 cs_log("Error in b2i, n=%i",n);
437 }
438 return 0;
439}
440
441ullong b2ll(int n, uchar *b)
442{
443 int i;
444 ullong k=0;
445 for(i=0; i<n; k+=b[i++])
446 k<<=8;
447 return(k);
448}
449
450uchar *i2b(int n, ulong i)
451{
452 uchar *b = cur_client()->dump;
453 switch(n)
454 {
455 case 2:
456 b[0]=(i>> 8) & 0xff;
457 b[1]=(i ) & 0xff;
458 break;
459 case 3:
460 b[0]=(i>>16) & 0xff;
461 b[1]=(i>> 8) & 0xff;
462 b[2]=(i ) & 0xff;
463 case 4:
464 b[0]=(i>>24) & 0xff;
465 b[1]=(i>>16) & 0xff;
466 b[2]=(i>> 8) & 0xff;
467 b[3]=(i ) & 0xff;
468 break;
469 }
470 return(b);
471}
472
473ulong a2i(char *asc, int bytes)
474{
475 int i, n;
476 ulong rc;
477 for (rc=i=0, n=strlen(trim(asc))-1; i<(abs(bytes)<<1); n--, i++)
478 if (n>=0)
479 {
480 int rcl;
481 if ((rcl=gethexval(asc[n]))<0)
482 {
483 errno=EINVAL;
484 return(0x1F1F1F);
485 }
486 rc|=(rcl<<(i<<2));
487 }
488 else
489 if (bytes<0)
490 rc|=(0xf<<(i<<2));
491 errno=0;
492 return(rc);
493}
494
495int boundary(int exp, int n)
496{
497 return((((n-1)>>exp)+1)<<exp);
498}
499
500void cs_ftime(struct timeb *tp)
501{
502#ifdef NO_FTIME
503 struct timeval tv;
504 gettimeofday(&tv, (struct timezone *)0);
505 tp->time=tv.tv_sec;
506 tp->millitm=tv.tv_usec/1000;
507#else
508 ftime(tp);
509#endif
510}
511
512void cs_sleepms(unsigned int msec)
513{
514 //does not interfere with signals like sleep and usleep do
515 struct timespec req_ts;
516 req_ts.tv_sec = msec/1000;
517 req_ts.tv_nsec = (msec % 1000) * 1000000L;
518 nanosleep (&req_ts, NULL);
519}
520
521void cs_sleepus(unsigned int usec)
522{
523 //does not interfere with signals like sleep and usleep do
524 struct timespec req_ts;
525 req_ts.tv_sec = usec/1000000;
526 req_ts.tv_nsec = (usec % 1000000) * 1000L;
527 nanosleep (&req_ts, NULL);
528}
529
530int bytes_available(int fd)
531{
532 fd_set rfds;
533 fd_set erfds;
534 int select_ret;
535 int in_fd;
536
537 in_fd=fd;
538
539 FD_ZERO(&rfds);
540 FD_SET(in_fd, &rfds);
541
542 FD_ZERO(&erfds);
543 FD_SET(in_fd, &erfds);
544
545 select_ret = select(in_fd+1, &rfds, NULL, &erfds, NULL);
546 if (select_ret==-1)
547 {
548 cs_log("ERROR reading from fd %d select_ret=%i, errno=%d",in_fd, select_ret, errno);
549 return 0;
550 }
551
552 if (FD_ISSET(in_fd, &erfds))
553 {
554 cs_log("ERROR reading from fd %d select_ret=%i, errno=%d",in_fd, select_ret, errno);
555 return 0;
556 }
557 if (FD_ISSET(in_fd,&rfds))
558 return 1;
559 else
560 return 0;
561}
562
563
564#ifdef OS_CYGWIN32
565#include <windows.h>
566void cs_setpriority(int prio)
567{
568 HANDLE WinId;
569 ulong wprio;
570 switch((prio+20)/10)
571 {
572 case 0: wprio=REALTIME_PRIORITY_CLASS; break;
573 case 1: wprio=HIGH_PRIORITY_CLASS; break;
574 case 2: wprio=NORMAL_PRIORITY_CLASS; break;
575 default: wprio=IDLE_PRIORITY_CLASS; break;
576 }
577 WinId=GetCurrentProcess();
578 SetPriorityClass(WinId, wprio);
579}
580#else
581void cs_setpriority(int prio)
582{
583#ifdef PRIO_PROCESS
584 setpriority(PRIO_PROCESS, 0, prio); // ignore errors
585#endif
586}
587#endif
588
589#ifdef WEBIF
590/* Helper function for urldecode.*/
591int x2i(int i){
592 i=toupper(i);
593 i = i - '0';
594 if(i > 9) i = i - 'A' + '9' + 1;
595 return i;
596}
597
598/* Decodes values in a http url */
599void urldecode(char *s){
600 int c, c1, n;
601 char *s0,*t;
602 t = s0 = s;
603 n = strlen(s);
604 while(n >0){
605 c = *s++;
606 if(c == '+') c = ' ';
607 else if(c == '%' && n > 2){
608 c = *s++;
609 c1 = c;
610 c = *s++;
611 c = 16*x2i(c1) + x2i(c);
612 n -= 2;
613 }
614 *t++ = c;
615 n--;
616 }
617 *t = 0;
618}
619
620/* Helper function for urlencode.*/
621char to_hex(char code){
622 static const char hex[] = "0123456789abcdef";
623 return hex[(int)code & 15];
624}
625
626/* Encode values in a http url. Note: Be sure to free() the returned string after use */
627char *urlencode(char *str){
628 char *pstr = str, *buf = (char *) malloc((strlen(str) * 3 + 1) * sizeof(char)), *pbuf = buf;
629 while (*pstr) {
630 if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~') *pbuf++ = *pstr;
631 else if (*pstr == ' ') *pbuf++ = '+';
632 else {
633 *pbuf++ = '%';
634 *pbuf++ = to_hex(*pstr >> 4);
635 *pbuf++ = to_hex(*pstr & 15);
636 }
637 ++pstr;
638 }
639 *pbuf = '\0';
640 pbuf = (char *) malloc((strlen(buf) + 1) * sizeof(char));
641 strcpy(pbuf, buf);
642 free(buf);
643 return pbuf;
644}
645
646/* Converts a char array to a char array with hex values (needed for example for md5). The hex2ascii
647 array is a lookup table with the corresponding hex string on the array position of the integer representation
648 of the ascii value. Note that you need to "free" the resulting array after usage or you'll get a memory leak!*/
649char *char_to_hex(const unsigned char* p_array, unsigned int p_array_len, char hex2ascii[256][2]) {
650 unsigned char* str = (unsigned char*)malloc(p_array_len*2+1);
651 str[p_array_len*2] = '\0';
652 const unsigned char* p_end = p_array + p_array_len;
653 size_t pos=0;
654 const unsigned char* p;
655 for( p = p_array; p != p_end; p++, pos+=2 ) {
656 str[pos] = hex2ascii[*p][0];
657 str[pos+1] = hex2ascii[*p][1];
658 }
659 return (char*)str;
660}
661
662/* Creates a random string with specified length. Note that dst must be one larger than size to hold the trailing \0*/
663void create_rand_str(char *dst, int size){
664 static const char text[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
665 int i;
666 for (i = 0; i < size; ++i){
667 dst[i] = text[rand() % (sizeof(text) - 1)];
668 }
669 dst[i] = '\0';
670}
671#endif
672
673/* Converts a long64 value to a char array in bitwise representation.
674 Note that the result array MUST be at least 65 bit large and that
675 this function assumes long values to hold only values up to 64bits and to be positive!
676 the result of e.g. long 7 is 1110000000000000000000000000000000000000000000000000000000000000 this means the array
677 is reversed */
678void sidtabbits2bitchar(SIDTABBITS value, char *result){
679 int pos;
680 for (pos=0;pos<MAX_SIDBITS;pos++) result[pos]='0';
681 result[pos] = '\0';
682
683 pos=0;
684 while (value > 0 && pos < MAX_SIDBITS){
685 if(value % 2 == 1) result[pos]='1';
686 else result[pos]='0';
687 value=value / (SIDTABBITS)2;
688 pos++;
689 }
690}
691
692
693/* Converts a long value to a char array in bitwise representation.
694 Note that the result array MUST be at least 33 bit large and that
695 this function assumes long values to hold only values up to 32bits and to be positive!
696 the result of e.g. long 7 is 11100000000000000000000000000000 this means the array
697 is reversed */
698void long2bitchar(long value, char *result){
699 int pos;
700 for (pos=0;pos<32;pos++) result[pos]='0';
701 result[pos] = '\0';
702
703 pos=0;
704 while (value > 0 && pos < 32){
705 if(value % 2 == 1) result[pos]='1';
706 else result[pos]='0';
707 value=value / 2;
708 pos++;
709 }
710}
711
712/* Converts a uint64 value to a char array in bitwise representation.
713 Note that the result array MUST be at least 65 bit large and that
714 this function assumes long values to hold only values up to 64bits and to be positive!
715 the result of e.g. long 7 is 11100000000000000000000000000000000000000000000000000000000000000 this means the array
716 is reversed */
717void uint642bitchar(uint64 value, char *result){
718 int pos;
719 for (pos=0;pos<64;pos++) result[pos]='0';
720 result[pos] = '\0';
721
722 pos=0;
723 while (value > 0 && pos < 64){
724 if(value % 2 == 1) result[pos]='1';
725 else result[pos]='0';
726 value=value / (uint64)2;
727 pos++;
728 }
729}
730
731/* Return 1 if the file exists, else 0 */
732int file_exists(const char * filename){
733 FILE *file;
734 if ((file = fopen(filename, "r"))){
735 fclose(file);
736 return 1;
737 }
738 return 0;
739}
740
741/* Clears the s_ip structure provided. The pointer will be set to NULL so everything is cleared.*/
742void clear_sip(struct s_ip **sip){
743 struct s_ip *cip = *sip, *lip;
744 for (*sip = NULL; cip != NULL; cip = lip){
745 lip = cip->next;
746 free(cip);
747 }
748}
749
750/* Clears the s_ftab struct provided by setting nfilts and nprids to zero. */
751void clear_ftab(struct s_ftab *ftab){
752 int i, j;
753 for (i = 0; i < CS_MAXFILTERS; i++) {
754 ftab->filts[i].caid = 0;
755 for (j = 0; j < CS_MAXPROV; j++)
756 ftab->filts[i].prids[j] = 0;
757 ftab->filts[i].nprids = 0;
758 }
759 ftab->nfilts = 0;
760}
761
762/* Clears the s_ptab struct provided by setting nfilts and nprids to zero. */
763void clear_ptab(struct s_ptab *ptab){
764 int i;
765 for (i = 0; i < ptab->nports; i++) {
766 ptab->ports[i].ftab.nfilts = 0;
767 ptab->ports[i].ftab.filts[0].nprids = 0;
768 }
769 ptab->nports = 0;
770}
771
772/* Clears given caidtab */
773void clear_caidtab(struct s_caidtab *ctab){
774 int i;
775 for (i = 0; i < CS_MAXCAIDTAB; i++) {
776 ctab->caid[i] = 0;
777 ctab->mask[i] = 0;
778 ctab->cmap[i] = 0;
779 }
780}
781
782/* Clears given tuntab */
783void clear_tuntab(struct s_tuntab *ttab){
784 int i;
785 for (i = 0; i < CS_MAXTUNTAB; i++) {
786 ttab->bt_caidfrom[i] = 0;
787 ttab->bt_caidto[i] = 0;
788 ttab->bt_srvid[i] = 0;
789 }
790}
791/* Overwrites destfile with tmpfile. If forceBakOverWrite = 0, the bakfile will not be overwritten if it exists, else it will be.*/
792int safe_overwrite_with_bak(char *destfile, char *tmpfile, char *bakfile, int forceBakOverWrite){
793 if (file_exists(destfile)) {
794 if(forceBakOverWrite != 0 && file_exists(bakfile)){
795 if(remove(bakfile) < 0) cs_log("Error removing backup conf file %s (errno=%d)! Will try to proceed nonetheless...", bakfile, errno);
796 }
797 if(file_exists(bakfile)){
798 if(remove(destfile) < 0) {
799 cs_log("Error removing original conf file %s (errno=%d). Will maintain original one!", destfile, errno);
800 if(remove(tmpfile) < 0) cs_log("Error removing temp conf file %s (errno=%d)!", tmpfile, errno);
801 return(1);
802 }
803 } else {
804 if(rename(destfile, bakfile) < 0){
805 cs_log("Error renaming original conf file %s to %s (errno=%d). Will maintain original one!", destfile, bakfile, errno);
806 if(remove(tmpfile) < 0) cs_log("Error removing temp conf file %s (errno=%d)!", tmpfile, errno);
807 return(1);
808 }
809 }
810 if(rename(tmpfile, destfile) < 0){
811 cs_log("Error renaming new conf file %s to %s (errno=%d). The config will be missing upon next startup as this is non-recoverable!", tmpfile, destfile, errno);
812 return(1);
813 }
814 } else {
815 if(rename(tmpfile, destfile) < 0){
816 cs_log("Error renaming new conf file %s to %s (errno=%d). The config will be missing upon next startup as this is non-recoverable!", tmpfile, destfile, errno);
817 return(1);
818 }
819 }
820 return(0);
821}
822
823/* Replacement of fprintf which adds necessary whitespace to fill up the varname to a fixed width.
824 If varname is longer than varnameWidth, no whitespace is added*/
825void fprintf_conf(FILE *f, int varnameWidth, const char *varname, const char *fmtstring, ...){
826 int varlen = strlen(varname);
827 int max = (varlen > varnameWidth) ? varlen : varnameWidth;
828 char varnamebuf[max + 3];
829 char *ptr = varnamebuf + varlen;
830 va_list argptr;
831
832 strcpy(varnamebuf, varname);
833 while(varlen < varnameWidth){
834 ptr[0] = ' ';
835 ++ptr;
836 ++varlen;
837 }
838 strcpy(ptr, "= ");
839 fwrite(varnamebuf, sizeof(char), strlen(varnamebuf), f);
840 if(strlen(fmtstring) > 0){
841 va_start(argptr, fmtstring);
842 vfprintf(f, fmtstring, argptr);
843 va_end(argptr);
844 }
845}
846
847/* Ordinary strncpy does not terminate the string if the source is exactly as long or longer as the specified size. This can raise security issues.
848 This function is a replacement which makes sure that a \0 is always added. num should be the real size of char array (do not subtract -1). */
849void cs_strncpy(char * destination, const char * source, size_t num){
850 uint32 l, size = strlen(source);
851 if(size > num - 1) l = num - 1;
852 else l = size;
853 memcpy(destination, source, l);
854 destination[l] = '\0';
855}
856
857char *get_servicename(int srvid, int caid){
858 int i;
859 struct s_srvid *this = cfg->srvid;
860 static char name[83];
861
862 for (name[0] = 0; this && (!name[0]); this = this->next)
863 if (this->srvid == srvid)
864 for (i=0; i<this->ncaid; i++)
865 if (this->caid[i] == caid)
866 cs_strncpy(name, this->name, 32);
867
868 if (!name[0]) sprintf(name, "%04X:%04X unknown", caid, srvid);
869 if (!srvid) name[0] = '\0';
870 return(name);
871}
872
873char *get_tiername(int tierid, int caid){
874 int i;
875 struct s_tierid *this = cfg->tierid;
876 static char name[83];
877
878 for (name[0] = 0; this && (!name[0]); this = this->next)
879 if (this->tierid == tierid)
880 for (i=0; i<this->ncaid; i++)
881 if (this->caid[i] == caid)
882 cs_strncpy(name, this->name, 32);
883
884 //if (!name[0]) sprintf(name, "%04X:%04X unknown", caid, tierid);
885 if (!tierid) name[0] = '\0';
886 return(name);
887}
888
889char *get_provider(int caid, ulong provid){
890 struct s_provid *this = cfg->provid;
891 static char name[83];
892
893 for (name[0] = 0; this && (!name[0]); this = this->next)
894 if (this->caid == caid && this->provid == provid)
895 snprintf(name, 83, "%s / %s / %s", this->prov, this->sat, this->lang);
896
897 if (!name[0]) snprintf(name, 83, "%04X:%06lX unknown", caid, provid);
898 if (!caid) name[0] = '\0';
899 return(name);
900}
901
902void make_non_blocking(int fd) {
903 int fl;
904 fl=fcntl(fd, F_GETFL);
905 fcntl(fd, F_SETFL, fl | O_NONBLOCK | O_NDELAY);
906}
907
908unsigned int seed;
909
910uchar fast_rnd() {
911 unsigned int offset = 12923;
912 unsigned int multiplier = 4079;
913
914 seed = seed * multiplier + offset;
915 return (uchar) (seed % 0xFF);
916}
917
918void init_rnd() {
919 seed = (unsigned int) time((time_t*)0);
920}
921
922int hexserialset(struct s_reader *rdr)
923{
924 int i;
925
926 if (!rdr) return 0;
927
928 for (i = 0; i < 8; i++)
929 if (rdr->hexserial[i])
930 return 1;
931 return 0;
932}
933
934static char *netw_ext_prot[] = { "cccam", "cccam ext", "newcamd524" };
935
936char *reader_get_type_desc(struct s_reader * rdr, int extended)
937{
938 static char *typtxt[] = { "unknown", "mouse", "mouse", "sc8in1", "mp35", "mouse", "internal", "smartreader", "pcsc" };
939 char *desc = typtxt[0];
940
941 if (rdr->typ & R_IS_NETWORK)
942 desc = rdr->ph.desc;
943 else
944 desc = typtxt[rdr->typ];
945
946 if ((rdr->typ == R_NEWCAMD) && (rdr->ncd_proto == NCD_524))
947 desc = netw_ext_prot[2];
948
949 else if (rdr->typ == R_CCCAM)
950 desc = netw_ext_prot[0];
951
952 else if (rdr->client && rdr->client->cc && ((struct cc_data *)rdr->client->cc)->extended_mode) {
953 desc = netw_ext_prot[extended];
954 }
955
956 return (desc);
957}
958
959char *monitor_get_proto(struct s_client *cl)
960{
961 char *ctyp;
962 switch(cl->typ) {
963 case 's' : ctyp = "server"; break;
964 case 'p' :
965 case 'r' : ctyp = reader_get_type_desc(cl->reader, 1); break;
966 case 'c' :
967 if (cl->cc && ((struct cc_data *)cl->cc)->extended_mode) {
968 ctyp = netw_ext_prot[1];
969 break;
970 }
971 default : ctyp = ph[cl->ctyp].desc;
972 }
973 return(ctyp);
974}
975
976/*
977 * resolve clienttype for newcamdprotocol
978 */
979char *get_ncd_client_name(char *client_id)
980{
981 static const int max_id_idx = 29;
982 static const char *ncd_service_ids[] = { "0000", "5644", "4C43", "4333", "7264", "6762", "6D67", "7763", "6E73", "6378", "6B61",
983 "6576", "4343", "5456", "414C", "0666", "0667", "9911", "434C", "4765", "5342",
984 "6E65", "4E58", "4453", "8888", "7363", "0669", "0665", "0769", "4543" };
985
986 static char *ncd_service_names[] = { "generic", "vdr-sc", "LCE", "camd3", "radegast", "gbox2CS", "mgcamd", //actually a const so threadsafe
987 "WinCSC", "NewCS", "cx", "Kaffeine", "evocamd", "CCcam", "Tecview",
988 "AlexCS", "rqcamd", "rq-echo-client", "ACamd", "Cardlink", "Octagon", "SBCL",
989 "NextYE2k", "NextYE2k", "DiabloCam/UW", "OScam", "Scam", "rq-sssp-client/CW",
990 "rq-sssp-client/CS", "JlsRq", "eyetvCamd", "unknown - please report" };
991
992 int idx = 0;
993 for (idx = 0; idx <= max_id_idx; idx++) {
994 if(!memcmp(ncd_service_ids[idx], client_id, 4))
995 return ncd_service_names[idx];
996
997 }
998
999 return ncd_service_names[max_id_idx+1];
1000}
Note: See TracBrowser for help on using the repository browser.