[gbx] - try fix ecm and cw messages
[oscam.git] / module-gbox-cards.c
blob8f0e7d37c77acf6518c045d1fc5498bf0ee65e69
1 #define MODULE_LOG_PREFIX "gbox"
3 #include "globals.h"
5 #ifdef MODULE_GBOX
6 #include "module-gbox.h"
7 #include "module-gbox-cards.h"
8 #include "module-gbox-helper.h"
9 #include "oscam-lock.h"
10 #include "oscam-garbage.h"
11 #include "oscam-files.h"
12 #include "oscam-chk.h"
13 #include "oscam-string.h"
14 #include "oscam-time.h"
16 LLIST *gbox_cards;
17 LLIST *gbox_backup_cards; // NEEDFIX: this list has to be cleaned from time to time
18 CS_MUTEX_LOCK gbox_cards_lock;
19 uint8_t checkcode[7];
21 GBOX_CARDS_ITER *gbox_cards_iter_create(void)
23 GBOX_CARDS_ITER *gci;
24 if(!cs_malloc(&gci, sizeof(GBOX_CARDS_ITER)))
25 { return NULL; }
26 cs_readlock(__func__, &gbox_cards_lock);
27 gci->it = ll_iter_create(gbox_cards);
28 return gci;
31 void gbox_cards_iter_destroy(GBOX_CARDS_ITER *gci)
33 cs_readunlock(__func__, &gbox_cards_lock);
34 if (gci) { add_garbage(gci); }
37 struct gbox_card *gbox_cards_iter_next(GBOX_CARDS_ITER *gci)
39 if (gci) { return ll_iter_next(&gci->it); }
40 else { return NULL; }
43 uint8_t gbox_get_crd_dist_lev(uint16_t crd_id)
45 uint8_t crd_dist = 0;
46 uint8_t crd_level = 0;
47 struct gbox_card *card;
48 cs_readlock(__func__, &gbox_cards_lock);
49 LL_ITER it = ll_iter_create(gbox_cards);
50 while((card = ll_iter_next(&it)))
52 if (card->type == GBOX_CARD_TYPE_GBOX && card->id.peer == crd_id)
54 crd_dist = card->dist;
55 crd_level = card->lvl;
56 break;
59 cs_readunlock(__func__, &gbox_cards_lock);
60 return ((crd_level << 4) | (crd_dist & 0xf));
63 void gbox_write_share_cards_info(void)
65 uint16_t card_count_shared = 0;
66 uint16_t card_count_expired = 0;
67 char *fext = FILE_SHARED_CARDS_INFO;
68 char *fname = get_gbox_tmp_fname(fext);
69 FILE *fhandle_shared;
70 fhandle_shared = fopen(fname, "w");
71 if(!fhandle_shared)
73 cs_log("Couldn't open %s: %s", fname, strerror(errno));
74 return;
77 struct gbox_card *card;
78 cs_readlock(__func__, &gbox_cards_lock);
79 LL_ITER it = ll_iter_create(gbox_cards);
80 while((card = ll_iter_next(&it)))
82 if (card->type == GBOX_CARD_TYPE_GBOX)
84 fprintf(fhandle_shared, "CardID %d at %s Card %08X Sl:%d Lev:%1d dist:%1d id:%04X\n",
85 card_count_shared, card->origin_peer->hostname, card->caprovid,
86 card->id.slot, card->lvl, card->dist, card->id.peer);
87 card_count_shared++;
90 cs_readunlock(__func__, &gbox_cards_lock);
91 fclose(fhandle_shared);
93 fext = FILE_BACKUP_CARDS_INFO;
94 fname = get_gbox_tmp_fname(fext);
95 FILE *fhandle_expired;
96 fhandle_expired = fopen(fname, "w");
97 if(!fhandle_expired)
99 cs_log("Couldn't open %s: %s", fname, strerror(errno));
100 return;
102 cs_readlock(__func__, &gbox_cards_lock);
103 LL_ITER it2 = ll_iter_create(gbox_backup_cards);
104 while((card = ll_iter_next(&it2)))
106 if (card->type == GBOX_CARD_TYPE_GBOX)
108 fprintf(fhandle_expired, "CardID %2d at %s Card %08X Sl:%2d Lev:%1d dist:%1d id:%04X\n",
109 card_count_expired, card->origin_peer->hostname, card->caprovid,
110 card->id.slot, card->lvl, card->dist, card->id.peer);
111 card_count_expired++;
114 cs_readunlock(__func__, &gbox_cards_lock);
115 fclose(fhandle_expired);
116 return;
119 void gbox_write_local_cards_info(void)
121 uint16_t card_count_local = 0;
122 char *fext = FILE_LOCAL_CARDS_INFO;
123 char *fname = get_gbox_tmp_fname(fext);
124 FILE *fhandle_local;
125 fhandle_local = fopen(fname, "w");
126 if(!fhandle_local)
128 cs_log("Couldn't open %s: %s", fname, strerror(errno));
129 return;
132 struct gbox_card *card;
133 cs_readlock(__func__, &gbox_cards_lock);
134 LL_ITER it = ll_iter_create(gbox_cards);
135 while((card = ll_iter_next(&it)))
137 switch (card->type)
139 case GBOX_CARD_TYPE_GBOX:
140 break;
141 case GBOX_CARD_TYPE_LOCAL:
142 fprintf(fhandle_local, "CardID:%2d %s %08X Sl:%2d id:%04X\n",
143 card_count_local, "Local_Card", card->caprovid, card->id.slot, card->id.peer);
144 card_count_local++;
145 break;
146 case GBOX_CARD_TYPE_BETUN:
147 fprintf(fhandle_local, "CardID:%2d %s %08X Sl:%2d id:%04X\n",
148 card_count_local, "Betun_Card", card->caprovid, card->id.slot, card->id.peer);
149 card_count_local++;
150 break;
151 case GBOX_CARD_TYPE_CCCAM:
152 fprintf(fhandle_local, "CardID:%2d %s %08X Sl:%2d id:%04X\n",
153 card_count_local, "CCcam_Card", card->caprovid, card->id.slot, card->id.peer);
154 card_count_local++;
155 break;
156 case GBOX_CARD_TYPE_PROXY:
157 fprintf(fhandle_local, "CardID:%2d %s %08X Sl:%2d id:%04X\n",
158 card_count_local, "Proxy_Card", card->caprovid, card->id.slot, card->id.peer);
159 card_count_local++;
160 break;
161 default:
162 cs_log("Invalid card type: %d in gbox_write_cards_info", card->type);
163 break;
166 cs_readunlock(__func__, &gbox_cards_lock);
167 fclose(fhandle_local);
170 void gbox_write_stats(void)
172 int32_t card_count = 0;
173 struct gbox_good_srvid *srvid_good = NULL;
174 struct gbox_bad_srvid *srvid_bad = NULL;
175 char *fext = FILE_STATS;
176 char *fname = get_gbox_tmp_fname(fext);
177 FILE *fhandle;
178 fhandle = fopen(fname, "w");
179 if(!fhandle)
181 cs_log("Couldn't open %s: %s", fname, strerror(errno));
182 return;
185 struct gbox_card *card;
186 cs_readlock(__func__, &gbox_cards_lock);
187 LL_ITER it = ll_iter_create(gbox_cards);
188 while((card = ll_iter_next(&it)))
190 if (card->type == GBOX_CARD_TYPE_GBOX)
192 fprintf(fhandle, "CardID %4d Card %08X id:%04X #CWs:%d AVGtime:%d ms\n",
193 card_count, card->caprovid, card->id.peer, card->no_cws_returned, card->average_cw_time);
194 fprintf(fhandle, "Good SIDs:\n");
195 LL_ITER it2 = ll_iter_create(card->goodsids);
196 while((srvid_good = ll_iter_next(&it2)))
197 { fprintf(fhandle, "%04X\n", srvid_good->srvid.sid); }
198 fprintf(fhandle, "Bad SIDs:\n");
199 it2 = ll_iter_create(card->badsids);
200 while((srvid_bad = ll_iter_next(&it2)))
201 { fprintf(fhandle, "%04X #%d\n", srvid_bad->srvid.sid, srvid_bad->bad_strikes); }
202 card_count++;
204 } // end of while ll_iter_next
205 cs_readunlock(__func__, &gbox_cards_lock);
207 fclose(fhandle);
208 return;
211 void init_gbox_cards(void)
213 gbox_cards = ll_create("gbox.cards");
214 gbox_backup_cards = ll_create("gbox.backup.cards");
215 cs_lock_create(__func__, &gbox_cards_lock, "gbox_cards_lock", 5000);
216 cs_writelock(__func__, &gbox_cards_lock);
217 checkcode[0] = 0x15;
218 checkcode[1] = 0x30;
219 checkcode[2] = 0x02;
220 checkcode[3] = 0x04;
221 checkcode[4] = 0x19;
222 checkcode[5] = 0x19;
223 checkcode[6] = 0x66;
224 cs_writeunlock(__func__, &gbox_cards_lock);
227 static void update_checkcode(struct gbox_card *card)
229 checkcode[0] ^= (0xFF & (card->caprovid >> 24));
230 checkcode[1] ^= (0xFF & (card->caprovid >> 16));
231 checkcode[2] ^= (0xFF & (card->caprovid >> 8));
232 checkcode[3] ^= (0xFF & (card->caprovid));
233 checkcode[4] ^= (0xFF & (card->id.slot));
234 checkcode[5] ^= (0xFF & (card->id.peer >> 8));
235 checkcode[6] ^= (0xFF & (card->id.peer));
238 static void gbox_free_card(struct gbox_card *card)
240 ll_destroy_data(&card->badsids);
241 ll_destroy_data(&card->goodsids);
242 add_garbage(card);
243 return;
246 static uint8_t closer_path_known(uint32_t caprovid, uint16_t id_peer, uint8_t slot, uint8_t distance)
248 uint8_t ret = 0;
249 struct gbox_card *card;
250 cs_readlock(__func__, &gbox_cards_lock);
251 LL_ITER it = ll_iter_create(gbox_cards);
252 while((card = ll_iter_next(&it)))
254 if (card->caprovid == caprovid && card->id.peer == id_peer && card->id.slot == slot && card->dist <= distance)
256 ret = 1;
257 break;
260 cs_readunlock(__func__, &gbox_cards_lock);
261 return ret;
264 static uint8_t got_from_backup(uint32_t caprovid, uint16_t id_peer, uint8_t slot, struct gbox_peer *origin_peer)
266 uint8_t ret = 0;
267 struct gbox_card *card;
268 cs_writelock(__func__, &gbox_cards_lock);
269 LL_ITER it = ll_iter_create(gbox_backup_cards);
270 while((card = ll_iter_next(&it)))
272 if (card->caprovid == caprovid && card->id.peer == id_peer && card->id.slot == slot)
274 cs_log_dbg(D_READER, "backup card from peer: %04X %08X", card->id.peer, card->caprovid );
275 ll_remove(gbox_backup_cards, card);
276 card->origin_peer = origin_peer;
277 ll_append(gbox_cards, card);
278 update_checkcode(card);
279 ret = 1;
280 break;
283 cs_writeunlock(__func__, &gbox_cards_lock);
284 return ret;
287 void gbox_add_card(uint16_t id_peer, uint32_t caprovid, uint8_t slot, uint8_t level, uint8_t distance, uint8_t type, struct gbox_peer *origin_peer)
289 uint16_t caid = gbox_get_caid(caprovid);
290 uint32_t provid = gbox_get_provid(caprovid);
292 if(!caprovid) // skip caprov 00000000
293 { return; }
294 // don't insert 0100:000000
295 if(caid_is_seca(caid) && (!provid))
296 { return; }
297 // skip CAID 18XX providers
298 if(caid_is_nagra(caid) && (provid))
299 { return; }
301 if (!closer_path_known(caprovid, id_peer, slot, distance) && !got_from_backup(caprovid, id_peer, slot, origin_peer))
303 struct gbox_card *card;
304 if(!cs_malloc(&card, sizeof(struct gbox_card)))
306 cs_log("Card allocation failed");
307 return;
309 cs_log_dbg(D_READER, "new card from peer: %04X %08X", id_peer, caprovid);
310 card->caprovid = caprovid;
311 card->id.peer = id_peer;
312 card->id.slot = slot;
313 card->dist = distance;
314 card->lvl = level;
315 card->badsids = ll_create("badsids");
316 card->goodsids = ll_create("goodsids");
317 card->no_cws_returned = 0;
318 card->average_cw_time = 0;
319 card->type = type;
320 card->origin_peer = origin_peer;
321 cs_writelock(__func__, &gbox_cards_lock);
322 ll_append(gbox_cards, card);
323 update_checkcode(card);
324 cs_writeunlock(__func__, &gbox_cards_lock);
327 return;
330 uint8_t *gbox_get_my_checkcode(void)
332 return &checkcode[0];
335 uint16_t gbox_count_cards(void)
337 return ll_count(gbox_cards);
340 uint16_t gbox_count_peer_cards(uint16_t peer_id)
342 uint16_t counter = 0;
343 struct gbox_card *card;
345 cs_readlock(__func__, &gbox_cards_lock);
346 LL_ITER it = ll_iter_create(gbox_cards);
347 while((card = ll_iter_next(&it)))
349 if (card->origin_peer && card->origin_peer->gbox.id == peer_id)
350 { counter++; }
352 cs_readunlock(__func__, &gbox_cards_lock);
354 return counter;
357 void gbox_delete_cards(uint8_t delete_type, uint16_t criteria)
359 struct gbox_card *card;
360 uint8_t found;
362 cs_writelock(__func__, &gbox_cards_lock);
363 LL_ITER it = ll_iter_create(gbox_cards);
364 while((card = ll_iter_next(&it)))
366 found = 0;
367 switch (delete_type)
369 case GBOX_DELETE_FROM_PEER:
370 if (card->origin_peer && card->origin_peer->gbox.id == criteria)
371 { found = 1; }
372 break;
373 case GBOX_DELETE_WITH_ID:
374 if (card->id.peer == criteria)
375 { found = 1; }
376 break;
377 case GBOX_DELETE_WITH_TYPE:
378 if (card->type == criteria)
379 { found = 1; }
380 break;
381 default:
382 cs_log("Invalid delete type: %d in gbox_delete_cards", delete_type);
383 break;
385 if (found)
387 cs_log_dbg(D_READER, "remove card from peer: %04X %08X", card->id.peer, card->caprovid);
388 ll_remove(gbox_cards, card);
389 ll_append(gbox_backup_cards, card);
390 update_checkcode(card);
393 cs_writeunlock(__func__, &gbox_cards_lock);
395 return;
398 static void gbox_free_list(LLIST *card_list)
400 if(card_list)
402 cs_writelock(__func__, &gbox_cards_lock);
403 LL_ITER it = ll_iter_create(card_list);
404 struct gbox_card *card;
405 while((card = ll_iter_next_remove(&it)))
406 { gbox_free_card(card); }
407 ll_destroy(&gbox_cards);
408 cs_writeunlock(__func__, &gbox_cards_lock);
410 return;
413 void gbox_free_cardlist(void)
415 gbox_free_list(gbox_cards);
416 gbox_free_list(gbox_backup_cards);
417 return;
420 void gbox_add_good_sid(uint16_t id_card, uint16_t caid, uint8_t slot, uint16_t sid_ok, uint32_t cw_time)
422 struct gbox_card *card = NULL;
423 struct gbox_good_srvid *srvid = NULL;
424 uint8_t factor = 0;
426 cs_writelock(__func__, &gbox_cards_lock);
427 LL_ITER it = ll_iter_create(gbox_cards);
428 while((card = ll_iter_next(&it)))
430 if(card->id.peer == id_card && gbox_get_caid(card->caprovid) == caid && card->id.slot == slot)
432 card->no_cws_returned++;
433 if (!card->no_cws_returned)
434 { card->no_cws_returned = 10; } // wrap around
435 if (card->no_cws_returned < 10)
436 { factor = card->no_cws_returned; }
437 else
438 { factor = 10; }
439 card->average_cw_time = ((card->average_cw_time * (factor-1)) + cw_time) / factor;
440 LL_ITER it2 = ll_iter_create(card->goodsids);
441 while((srvid = ll_iter_next(&it2)))
443 if(srvid->srvid.sid == sid_ok)
445 srvid->last_cw_received = time(NULL);
446 cs_writeunlock(__func__, &gbox_cards_lock);
447 return; // sid_ok is already in the list of goodsids
451 if(!cs_malloc(&srvid, sizeof(struct gbox_good_srvid)))
453 cs_writeunlock(__func__, &gbox_cards_lock);
454 cs_log("Good SID allocation failed");
455 return;
457 srvid->srvid.sid = sid_ok;
458 srvid->srvid.provid_id = gbox_get_provid(card->caprovid);
459 srvid->last_cw_received = time(NULL);
460 cs_log_dbg(D_READER, "Adding good SID: %04X for CAID: %04X Provider: %04X on CardID: %04X", sid_ok, caid, gbox_get_provid(card->caprovid), id_card);
461 ll_append(card->goodsids, srvid);
462 break;
464 } // end of ll_iter_next
465 // return dist_c;
466 cs_writeunlock(__func__, &gbox_cards_lock);
467 return;
470 void gbox_remove_bad_sid(uint16_t id_peer, uint8_t id_slot, uint16_t sid)
472 struct gbox_card *card = NULL;
473 struct gbox_bad_srvid *srvid = NULL;
475 cs_writelock(__func__, &gbox_cards_lock);
476 LL_ITER it2 = ll_iter_create(gbox_cards);
477 while((card = ll_iter_next(&it2)))
479 if(card->id.peer == id_peer && card->id.slot == id_slot)
481 LL_ITER it3 = ll_iter_create(card->badsids);
482 while((srvid = ll_iter_next(&it3)))
484 if(srvid->srvid.sid == sid)
486 ll_iter_remove_data(&it3); // remove sid_ok from badsids
487 break;
492 cs_writeunlock(__func__, &gbox_cards_lock);
495 uint8_t gbox_next_free_slot(uint16_t id)
497 struct gbox_card *c;
498 uint8_t lastslot = 0;
500 cs_readlock(__func__, &gbox_cards_lock);
501 LL_ITER it = ll_iter_create(gbox_cards);
502 while((c = ll_iter_next(&it)))
504 if(id == c->id.peer && c->id.slot > lastslot)
505 { lastslot = c->id.slot; }
507 cs_readunlock(__func__, &gbox_cards_lock);
508 return ++lastslot;
511 static int8_t is_already_pending(LLIST *pending_cards, uint16_t peer_id, uint8_t slot)
513 if (!pending_cards)
514 { return -1; }
516 int8_t ret = 0;
517 struct gbox_card_id *current_id;
518 LL_LOCKITER *li = ll_li_create(pending_cards, 0);
519 while ((current_id = ll_li_next(li)))
521 if (current_id->peer == peer_id && current_id->slot == slot)
523 ret = 1;
524 break;
527 ll_li_destroy(li);
528 return ret;
531 uint8_t gbox_get_cards_for_ecm(uint8_t *send_buf, int32_t len2, uint8_t max_cards, ECM_REQUEST *er, uint32_t *current_avg_card_time, uint16_t peer_id, uint8_t force_remm)
533 if (!send_buf || !er)
534 { return 0; }
536 uint8_t nb_matching_crds = 0;
537 struct gbox_good_srvid *srvid_good = NULL;
538 struct gbox_bad_srvid *srvid_bad = NULL;
539 uint8_t enough = 0;
540 uint8_t sid_verified = 0;
541 time_t time_since_lastcw;
543 // loop over good only
544 cs_readlock(__func__, &gbox_cards_lock);
545 LL_ITER it = ll_iter_create(gbox_cards);
546 LL_ITER it2;
547 struct gbox_card *card;
549 while((card = ll_iter_next(&it)))
551 if(card->origin_peer && card->origin_peer->gbox.id == peer_id && card->type == GBOX_CARD_TYPE_GBOX &&
552 gbox_get_caid(card->caprovid) == er->caid && gbox_get_provid(card->caprovid) == er->prid && !is_already_pending(er->gbox_cards_pending, card->id.peer, card->id.slot))
554 sid_verified = 0;
556 // check if sid is good
557 it2 = ll_iter_create(card->goodsids);
558 while((srvid_good = ll_iter_next(&it2)))
560 if(srvid_good->srvid.provid_id == er->prid && srvid_good->srvid.sid == er->srvid)
562 if (!enough || *current_avg_card_time > card->average_cw_time)
564 time_since_lastcw = llabs(srvid_good->last_cw_received - time(NULL));
565 *current_avg_card_time = card->average_cw_time;
566 if (enough)
567 { len2 = len2 - 3; }
568 else
570 nb_matching_crds++;
571 if (time_since_lastcw < GBOX_SID_CONFIRM_TIME && er->gbox_ecm_status == GBOX_ECM_NOT_ASKED)
572 { enough = 1; }
574 i2b_buf(2, card->id.peer, send_buf + len2);
575 send_buf[len2 + 2] = card->id.slot;
576 len2 = len2 + 3;
577 sid_verified = 1;
578 break;
583 if(nb_matching_crds == max_cards)
584 { break; }
587 cs_readunlock(__func__, &gbox_cards_lock);
589 // loop over bad and unknown cards
590 cs_writelock(__func__, &gbox_cards_lock);
591 it = ll_iter_create(gbox_cards);
592 while((card = ll_iter_next(&it)))
594 if(card->origin_peer && card->origin_peer->gbox.id == peer_id && card->type == GBOX_CARD_TYPE_GBOX &&
595 gbox_get_caid(card->caprovid) == er->caid && gbox_get_provid(card->caprovid) == er->prid && !is_already_pending(er->gbox_cards_pending, card->id.peer, card->id.slot) && !enough)
597 sid_verified = 0;
599 // check if sid is good
600 it2 = ll_iter_create(card->goodsids);
601 while((srvid_good = ll_iter_next(&it2)))
603 if(srvid_good->srvid.provid_id == er->prid && srvid_good->srvid.sid == er->srvid)
605 sid_verified = 1;
606 cs_log_dbg(D_READER, "ID: %04X SL: %02X SID: %04X is good", card->id.peer, card->id.slot, srvid_good->srvid.sid);
609 if(!sid_verified)
611 // check if sid is bad
612 LL_ITER itt = ll_iter_create(card->badsids);
613 while((srvid_bad = ll_iter_next(&itt)))
615 if(srvid_bad->srvid.provid_id == er->prid && srvid_bad->srvid.sid == er->srvid)
617 if (srvid_bad->bad_strikes < 3)
619 sid_verified = 2;
620 if(!force_remm)
622 srvid_bad->bad_strikes++;
624 else
626 srvid_bad->bad_strikes = 1;
627 //cs_log("cards.c - get card for ecm - Block bad SID: %04X - %d bad strikes", srvid_bad->srvid.sid, srvid_bad->bad_strikes);
630 else
631 { sid_verified = 1; }
632 cs_log_dbg(D_READER, "CRD_ID: %04X Slot: %d SID: %04X failed to relpy %d times", card->id.peer, card->id.slot, srvid_bad->srvid.sid, srvid_bad->bad_strikes);
633 break;
637 // sid is neither good nor bad
638 if(sid_verified != 1)
640 i2b_buf(2, card->id.peer, send_buf + len2);
641 send_buf[len2 + 2] = card->id.slot;
642 len2 = len2 + 3;
643 nb_matching_crds++;
645 if (!sid_verified)
647 if(!cs_malloc(&srvid_bad, sizeof(struct gbox_bad_srvid)))
649 cs_log("ServID allocation failed");
650 cs_writeunlock(__func__, &gbox_cards_lock);
651 return 0;
654 srvid_bad->srvid.sid = er->srvid;
655 srvid_bad->srvid.provid_id = gbox_get_provid(card->caprovid);
656 srvid_bad->bad_strikes = 1;
657 ll_append(card->badsids, srvid_bad);
658 cs_log_dbg(D_READER, "ID: %04X SL: %02X SID: %04X is not checked", card->id.peer, card->id.slot, srvid_bad->srvid.sid);
663 if(nb_matching_crds == max_cards)
664 { break; }
667 cs_writeunlock(__func__, &gbox_cards_lock);
668 return nb_matching_crds;
671 #endif