tsdecrypt reads and decrypts CSA encrypted incoming mpeg transport stream over UDP/RTP using code words obtained from OSCAM or similar CAM server. tsdecrypt communicates with CAM server using cs378x (camd35 over tcp) protocol or newcamd protocol. https://georgi.unixsol.org/programs/tsdecrypt/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

tables.c 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. /*
  2. * Process PSI tables
  3. * Copyright (C) 2011 Unix Solutions Ltd.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2
  7. * as published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License (COPYING file) for more details.
  13. *
  14. */
  15. #include <string.h>
  16. #include "data.h"
  17. #include "tables.h"
  18. #include "camd.h"
  19. #include "filter.h"
  20. #include "libtsfuncs/tsfuncs.h"
  21. #include "libfuncs/libfuncs.h"
  22. extern void show_ts_pack(struct ts *ts, uint16_t pid, char *wtf, char *extra, uint8_t *ts_packet);
  23. #define handle_table_changes(TABLE) \
  24. do { \
  25. show_ts_pack(ts, pid, #TABLE, NULL, ts_packet); \
  26. ts->cur##TABLE = ts_##TABLE##_push_packet(ts->cur##TABLE, ts_packet); \
  27. if (!ts->cur##TABLE->initialized) \
  28. return; \
  29. if (ts_##TABLE##_is_same(ts->TABLE, ts->cur##TABLE)) { \
  30. ts_##TABLE##_clear(ts->cur##TABLE); \
  31. return; \
  32. } \
  33. ts_##TABLE##_free(&ts->TABLE); \
  34. ts->TABLE = ts_##TABLE##_copy(ts->cur##TABLE); \
  35. ts_##TABLE##_clear(ts->cur##TABLE); \
  36. if (ts->debug_level >= 1) \
  37. ts_##TABLE##_dump(ts->TABLE); \
  38. } while(0)
  39. void process_pat(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
  40. int i;
  41. int num_services = 0;
  42. uint16_t f_service = 0, f_pid = 0;
  43. if (pid != 0x00)
  44. return;
  45. handle_table_changes(pat);
  46. for (i=0;i<ts->pat->programs_num;i++) {
  47. struct ts_pat_program *prg = ts->pat->programs[i];
  48. if (prg->pid && prg->program != 0) {
  49. num_services++;
  50. ts->pmt_pid = prg->pid;
  51. ts->service_id = prg->program;
  52. if (prg->program == ts->forced_service_id) {
  53. f_pid = prg->pid;
  54. f_service = prg->program;
  55. }
  56. }
  57. }
  58. if (f_service && f_pid) {
  59. ts->pmt_pid = f_pid;
  60. ts->service_id = f_service;
  61. }
  62. if (num_services > 1 && !f_service) {
  63. ts_LOGf("PAT | %d services exists. Consider using --input-service parameter.\n",
  64. num_services);
  65. for (i = 0; i < ts->pat->programs_num; i++) {
  66. struct ts_pat_program *prg = ts->pat->programs[i];
  67. if (prg->pid && prg->program != 0) {
  68. ts_LOGf("PAT | Service 0x%04x (%5d) with PMT PID %04x (%d)\n",
  69. prg->program, prg->program,
  70. prg->pid, prg->pid);
  71. }
  72. }
  73. }
  74. ts_LOGf("PAT | Using service 0x%04x (%d), PMT pid: %04x (%d)\n",
  75. ts->service_id, ts->service_id,
  76. ts->pmt_pid, ts->pmt_pid);
  77. if (num_services > 1) {
  78. ts_pat_clear(ts->genpat);
  79. ts->genpat = ts_pat_init(ts->genpat, ts->pat->section_header->ts_id_number);
  80. ts_pat_add_program(ts->genpat, ts->service_id, ts->pmt_pid);
  81. }
  82. }
  83. void process_cat(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
  84. if (pid != 0x01)
  85. return;
  86. handle_table_changes(cat);
  87. if (ts->camd.constant_codeword)
  88. return;
  89. if (ts->forced_caid) {
  90. ts->emm_caid = ts->forced_caid;
  91. ts_get_emm_info_by_caid(ts->cat, ts->emm_caid, &ts->emm_pid);
  92. } else {
  93. ts_get_emm_info(ts->cat, ts->req_CA_sys, &ts->emm_caid, &ts->emm_pid);
  94. }
  95. if (ts->forced_emm_pid)
  96. ts_get_emm_info_by_pid(ts->cat, &ts->emm_caid, ts->forced_emm_pid);
  97. if (ts->emm_caid) {
  98. char *CA_sys = ts_get_CA_sys_txt(ts_get_CA_sys(ts->emm_caid));
  99. ts_LOGf("--- | EMM CAID: 0x%04x (%s)\n", ts->emm_caid, CA_sys);
  100. if (!ts->forced_emm_pid) {
  101. ts_LOGf("--- | EMM pid : 0x%04x (%s)\n", ts->emm_pid, CA_sys);
  102. } else {
  103. ts_LOGf("--- | EMM pid : 0x%04x (%s) (forced: 0x%04x)\n",
  104. ts->emm_pid, CA_sys, ts->forced_emm_pid);
  105. ts->emm_pid = ts->forced_emm_pid;
  106. }
  107. } else {
  108. ts_LOGf("*** | ERROR: Can't detect EMM pid.\n");
  109. }
  110. }
  111. void process_pmt(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
  112. int i;
  113. if (!pid || pid != ts->pmt_pid)
  114. return;
  115. // Mark PMT as valid and the received timestamp
  116. ts->last_pmt_ts = time(NULL);
  117. ts->have_valid_pmt = 1;
  118. handle_table_changes(pmt);
  119. pidmap_clear(&ts->pidmap);
  120. pidmap_set(&ts->pidmap, 0x0000); // PAT
  121. pidmap_set(&ts->pidmap, 0x0011); // SDT
  122. if (ts->nit_passthrough)
  123. pidmap_set(&ts->pidmap, 0x0010); // NIT
  124. if (ts->eit_passthrough)
  125. pidmap_set(&ts->pidmap, 0x0012); // EIT
  126. if (ts->tdt_passthrough)
  127. pidmap_set(&ts->pidmap, 0x0014); // TDT/TOT
  128. pidmap_set(&ts->pidmap, ts->pmt->ts_header.pid); // PMT PID
  129. pidmap_set(&ts->pidmap, ts->pmt->PCR_pid); // PCR
  130. for (i=0;i<ts->pmt->streams_num;i++) {
  131. struct ts_pmt_stream *stream = ts->pmt->streams[i];
  132. pidmap_set(&ts->pidmap, stream->pid); // Data
  133. }
  134. if (ts->camd.constant_codeword)
  135. return;
  136. if (ts->forced_caid) {
  137. ts->ecm_caid = ts->forced_caid;
  138. ts_get_ecm_info_by_caid(ts->pmt, ts->ecm_caid, &ts->ecm_pid);
  139. } else {
  140. ts_get_ecm_info(ts->pmt, ts->req_CA_sys, &ts->ecm_caid, &ts->ecm_pid);
  141. }
  142. if (ts->forced_ecm_pid)
  143. ts_get_ecm_info_by_pid(ts->pmt, &ts->ecm_caid, ts->forced_ecm_pid);
  144. if (ts->ecm_caid) {
  145. char *CA_sys = ts_get_CA_sys_txt(ts_get_CA_sys(ts->ecm_caid));
  146. ts_LOGf("--- | ECM CAID: 0x%04x (%s)\n", ts->ecm_caid, CA_sys);
  147. if (!ts->forced_ecm_pid) {
  148. ts_LOGf("--- | ECM pid : 0x%04x (%s)\n", ts->ecm_pid, CA_sys);
  149. } else {
  150. ts_LOGf("--- | ECM pid : 0x%04x (%s) (forced: 0x%04x)\n",
  151. ts->ecm_pid, CA_sys, ts->forced_ecm_pid);
  152. ts->ecm_pid = ts->forced_ecm_pid;
  153. }
  154. } else {
  155. ts_LOGf("*** | ERROR: Can't detect ECM pid.\n");
  156. }
  157. if (ts->req_CA_sys == CA_IRDETO) {
  158. memset(ts->irdeto_chid, 0, sizeof(ts->irdeto_chid));
  159. ts->irdeto_max_chids = 0;
  160. }
  161. }
  162. static int sdt_parse_service_name_desc(
  163. int desc_len, uint8_t *desc,
  164. uint8_t *service_type,
  165. uint8_t *pname_len, uint8_t **pname,
  166. uint8_t *sname_len, uint8_t **sname)
  167. {
  168. int ofs = 0;
  169. *pname_len = 0;
  170. *sname_len = 0;
  171. *pname = NULL;
  172. *sname = NULL;
  173. while (ofs + 2 < desc_len) {
  174. uint8_t tag = desc[ofs++];
  175. uint8_t len = desc[ofs++];
  176. if (tag != 0x48) {
  177. ofs += len;
  178. continue;
  179. }
  180. // Parse descriptor 0x48 - service_descriptor
  181. // +3 == +1 for service type, +1 for provider len, +1 for service len
  182. if (ofs + 3 > desc_len)
  183. break;
  184. *service_type = desc[ofs++];
  185. *pname_len = desc[ofs++];
  186. if (*pname_len)
  187. *pname = desc + ofs;
  188. ofs += *pname_len;
  189. if (ofs > desc_len)
  190. break;
  191. *sname_len = desc[ofs++];
  192. if (*sname_len)
  193. *sname = desc + ofs;
  194. return 1;
  195. }
  196. return 0;
  197. }
  198. void process_sdt(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
  199. int i;
  200. if (pid != 0x11)
  201. return;
  202. handle_table_changes(sdt);
  203. for(i=0;i<ts->sdt->streams_num;i++) {
  204. struct ts_sdt_stream *stream = ts->sdt->streams[i];
  205. uint8_t service_type;
  206. uint8_t *pname, *sname;
  207. uint8_t pname_len, sname_len;
  208. if (sdt_parse_service_name_desc(
  209. stream->descriptor_size, stream->descriptor_data,
  210. &service_type,
  211. &pname_len, &pname, &sname_len, &sname))
  212. {
  213. int r;
  214. for (r = 0; r < pname_len; r++) {
  215. if (pname[r] < ' ')
  216. pname[r] = '*';
  217. }
  218. for (r = 0; r < sname_len; r++) {
  219. if (sname[r] < ' ')
  220. sname[r] = '*';
  221. }
  222. ts_LOGf("SDT | Service 0x%04x (%5d) Type: 0x%02x (%s) Provider: \"%.*s\" Service: \"%.*s\"\n",
  223. stream->service_id, stream->service_id,
  224. service_type,
  225. // The service types are described in Table 87 of
  226. // ETSI EN 300 468 v1.12.1 and also in annex I of the
  227. // same document.
  228. service_type == 0x01 ? "Tv" :
  229. service_type == 0x02 ? "Radio" :
  230. service_type == 0x11 ? "Tv/HD" :
  231. service_type == 0x16 ? "Tv/h264" :
  232. service_type == 0x19 ? "Tv/HD/h264" :
  233. service_type == 0x1c ? "Tv/3d" : "unknown",
  234. pname_len, (char *)pname,
  235. sname_len, (char *)sname);
  236. } else {
  237. ts_LOGf("SDT | Service 0x%04x (%5d)\n",
  238. stream->service_id, stream->service_id);
  239. }
  240. }
  241. }
  242. #define dump_sz (15)
  243. #define dump_buf_sz (dump_sz * 6)
  244. static void __process_emm(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
  245. char dump[dump_buf_sz];
  246. show_ts_pack(ts, pid, "emm", NULL, ts_packet);
  247. ts->emm_input_count++;
  248. ts->emm = ts_privsec_push_packet(ts->emm, ts_packet);
  249. if (!ts->emm->initialized)
  250. return;
  251. struct ts_header *th = &ts->emm->ts_header;
  252. struct ts_section_header *sec = ts->emm->section_header;
  253. int emm_ok = 1;
  254. if (ts->emm_filters_num)
  255. emm_ok = filter_match_emm(ts, sec->section_data, sec->section_data_len);
  256. if (ts->debug_level >= 2) {
  257. ts_hex_dump_buf(dump, dump_buf_sz, sec->section_data, min(dump_sz, sec->section_data_len), 0);
  258. ts_LOGf("EMM | SID 0x%04x CAID: 0x%04x PID 0x%04x Table: 0x%02x Length: %4d %s %s..\n",
  259. ts->service_id,
  260. ts->emm_caid,
  261. th->pid,
  262. sec->table_id,
  263. sec->section_data_len,
  264. emm_ok == 1 ? "Data:" : "SKIP:",
  265. dump);
  266. }
  267. if (emm_ok)
  268. camd_process_packet(ts, camd_msg_alloc(EMM_MSG, ts->emm_caid, ts->service_id, sec->section_data, sec->section_data_len));
  269. else
  270. ts->emm_skipped_count++;
  271. ts_privsec_copy(ts->emm, ts->last_emm);
  272. ts_privsec_clear(ts->emm);
  273. }
  274. static void __process_ecm(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
  275. char dump[dump_buf_sz];
  276. ts->ecm = ts_privsec_push_packet(ts->ecm, ts_packet);
  277. if (!ts->ecm->initialized)
  278. return;
  279. if (ts->req_CA_sys == CA_IRDETO) {
  280. uint8_t idx = ts->ecm->section_header->section_data[4];
  281. uint8_t max_idx = ts->ecm->section_header->section_data[5];
  282. uint16_t chid = (ts->ecm->section_header->section_data[6] << 8) | ts->ecm->section_header->section_data[7];
  283. if (max_idx != ts->irdeto_max_chids) {
  284. memset(ts->irdeto_chid, 0, sizeof(ts->irdeto_chid));
  285. ts->irdeto_max_chids = max_idx;
  286. }
  287. bool ecm_ok = false;
  288. const char *filter_type;
  289. switch (ts->irdeto_ecm_filter_type) {
  290. case IRDETO_FILTER_IDX : ecm_ok = (idx == ts->irdeto_ecm_idx); filter_type = " BY IDX"; break;
  291. case IRDETO_FILTER_CHID: ecm_ok = (chid == ts->irdeto_ecm_chid); filter_type = " BY CHID"; break;
  292. }
  293. if (ts->irdeto_chid[idx].seen < 1) {
  294. ts_LOGf("CAS | Seen Irdeto CHID 0x%04x (idx %u/%u)%s%s\n", chid, idx, max_idx,
  295. ecm_ok ? " *SELECTED*" : "",
  296. ecm_ok ? filter_type : "");
  297. ts->irdeto_chid[idx].seen++;
  298. }
  299. if (!ecm_ok) {
  300. ts_privsec_clear(ts->ecm);
  301. return;
  302. }
  303. }
  304. struct ts_header *th = &ts->ecm->ts_header;
  305. struct ts_section_header *sec = ts->ecm->section_header;
  306. // ECMs should be in these tables.
  307. if (sec->section_data[0] != 0x80 && sec->section_data[0] != 0x81) {
  308. ts_privsec_clear(ts->ecm);
  309. return;
  310. }
  311. int duplicate = ts_privsec_is_same(ts->ecm, ts->last_ecm);
  312. if (duplicate && !ts->is_cw_error)
  313. ts->ecm_duplicate_count++;
  314. if (!ts->ecm_change_time.tv_sec && !ts->ecm_change_time.tv_usec) // The first time
  315. gettimeofday(&ts->ecm_change_time, NULL);
  316. if (!duplicate || ts->is_cw_error) {
  317. if (ts->ecm_cw_log) {
  318. struct timeval tv;
  319. gettimeofday(&tv, NULL);
  320. ts_LOGf("ECC | SID 0x%04x ------------ EcmChng: %5llu ms\n",
  321. ts->service_id,
  322. timeval_diff_msec(&ts->ecm_change_time, &tv));
  323. ts_hex_dump_buf(dump, dump_buf_sz, sec->section_data, min(dump_sz, sec->section_data_len), 0);
  324. ts_LOGf("ECM | SID 0x%04x CAID: 0x%04x PID 0x%04x Table: 0x%02x Length: %4d Data: %s..\n",
  325. ts->service_id,
  326. ts->ecm_caid,
  327. th->pid,
  328. sec->table_id,
  329. sec->section_data_len,
  330. dump);
  331. }
  332. gettimeofday(&ts->ecm_change_time, NULL);
  333. ts->is_cw_error = 0;
  334. camd_process_packet(ts, camd_msg_alloc(ECM_MSG, ts->ecm_caid, ts->service_id, sec->section_data, sec->section_data_len));
  335. } else if (ts->debug_level >= 3) {
  336. ts_LOGf("ECM | SID 0x%04x CAID: 0x%04x PID 0x%04x Table: 0x%02x Length: %4d Data: -dup-\n",
  337. ts->service_id,
  338. ts->ecm_caid,
  339. th->pid,
  340. sec->table_id,
  341. sec->section_data_len);
  342. }
  343. ts_privsec_copy(ts->ecm, ts->last_ecm);
  344. ts_privsec_clear(ts->ecm);
  345. show_ts_pack(ts, pid, !duplicate ? "ecm" : "ec+", NULL, ts_packet);
  346. }
  347. // There are cryptosystems that are puting more than one PSI table
  348. // in TS packet. IRDETO is such example. Because libtsfuncs assumes
  349. // that one ts packet can produce maximum 1 PSI table, the following
  350. // workaround is used for EMM/ECM private sections. Basically we detect
  351. // if after the section there is something else than 0xff (filler) and
  352. // if there is something change ts_packet pointer field to point to
  353. // start of the potential section and reparse section.
  354. void process_ecm(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
  355. int section_end;
  356. if (!ts->process_ecm)
  357. return;
  358. if (!ts->ecm_pid || ts->ecm_pid != pid)
  359. return;
  360. process_psi:
  361. ts->tmp_ecm = ts_privsec_push_packet(ts->tmp_ecm, ts_packet);
  362. if (!ts->tmp_ecm->initialized) {
  363. __process_ecm(ts, pid, ts_packet);
  364. return;
  365. }
  366. section_end = ts->tmp_ecm->section_header->pointer_field + ts->tmp_ecm->section_header->section_length + 3 + 4 + 1;
  367. if (section_end < 188 && ts_packet[section_end] != 0xff) {
  368. __process_ecm(ts, pid, ts_packet);
  369. ts_packet[4] = ts_packet[4] + ts->tmp_ecm->section_header->section_length + 3;
  370. ts_privsec_clear(ts->tmp_ecm);
  371. goto process_psi;
  372. } else {
  373. __process_ecm(ts, pid, ts_packet);
  374. }
  375. ts_privsec_clear(ts->tmp_ecm);
  376. }
  377. void process_emm(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
  378. int section_end;
  379. if (!ts->process_emm)
  380. return;
  381. process_psi:
  382. ts->tmp_emm = ts_privsec_push_packet(ts->tmp_emm, ts_packet);
  383. if (!ts->tmp_emm->initialized) {
  384. __process_emm(ts, pid, ts_packet);
  385. return;
  386. }
  387. section_end = ts->tmp_emm->section_header->pointer_field + ts->tmp_emm->section_header->section_length + 3 + 4 + 1;
  388. if (section_end < 188 && ts_packet[section_end] != 0xff) {
  389. __process_emm(ts, pid, ts_packet);
  390. ts_packet[4] = ts_packet[4] + ts->tmp_emm->section_header->section_length + 3;
  391. ts_privsec_clear(ts->tmp_emm);
  392. goto process_psi;
  393. } else {
  394. __process_emm(ts, pid, ts_packet);
  395. }
  396. ts_privsec_clear(ts->tmp_emm);
  397. }