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 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  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 for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  17. */
  18. #include "data.h"
  19. #include "tables.h"
  20. #include "camd.h"
  21. #include "libtsfuncs/tsfuncs.h"
  22. #include "libfuncs/libfuncs.h"
  23. extern void show_ts_pack(struct ts *ts, uint16_t pid, char *wtf, char *extra, uint8_t *ts_packet);
  24. #define handle_table_changes(TABLE) \
  25. do { \
  26. show_ts_pack(ts, pid, #TABLE, NULL, ts_packet); \
  27. ts->cur##TABLE = ts_##TABLE##_push_packet(ts->cur##TABLE, ts_packet); \
  28. if (!ts->cur##TABLE->initialized) \
  29. return; \
  30. if (ts_##TABLE##_is_same(ts->TABLE, ts->cur##TABLE)) { \
  31. ts_##TABLE##_clear(ts->cur##TABLE); \
  32. return; \
  33. } \
  34. ts_##TABLE##_free(&ts->TABLE); \
  35. ts->TABLE = ts_##TABLE##_copy(ts->cur##TABLE); \
  36. ts_##TABLE##_clear(ts->cur##TABLE); \
  37. if (ts->debug_level >= 1) \
  38. ts_##TABLE##_dump(ts->TABLE); \
  39. } while(0)
  40. void process_pat(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
  41. int i;
  42. int num_services = 0;
  43. uint16_t f_service = 0, f_pid = 0;
  44. if (pid != 0x00)
  45. return;
  46. handle_table_changes(pat);
  47. for (i=0;i<ts->pat->programs_num;i++) {
  48. struct ts_pat_program *prg = ts->pat->programs[i];
  49. if (prg->pid && prg->program != 0) {
  50. num_services++;
  51. ts->pmt_pid = prg->pid;
  52. ts->service_id = prg->program;
  53. if (prg->program == ts->forced_service_id) {
  54. f_pid = prg->pid;
  55. f_service = prg->program;
  56. }
  57. }
  58. }
  59. if (f_service && f_pid) {
  60. ts->pmt_pid = f_pid;
  61. ts->service_id = f_service;
  62. }
  63. if (num_services > 1 && !f_service) {
  64. ts_LOGf("PAT | %d services exists. Consider using --input-service parameter.\n",
  65. num_services);
  66. for (i = 0; i < ts->pat->programs_num; i++) {
  67. struct ts_pat_program *prg = ts->pat->programs[i];
  68. if (prg->pid && prg->program != 0) {
  69. ts_LOGf("PAT | Service 0x%04x (%5d) with PMT PID %04x (%d)\n",
  70. prg->program, prg->program,
  71. prg->pid, prg->pid);
  72. }
  73. }
  74. }
  75. ts_LOGf("PAT | Using service 0x%04x (%d), PMT pid: %04x (%d)\n",
  76. ts->service_id, ts->service_id,
  77. ts->pmt_pid, ts->pmt_pid);
  78. if (num_services > 1) {
  79. ts_pat_clear(ts->genpat);
  80. ts->genpat = ts_pat_init(ts->genpat, ts->pat->section_header->ts_id_number);
  81. ts_pat_add_program(ts->genpat, ts->service_id, ts->pmt_pid);
  82. }
  83. }
  84. void process_cat(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
  85. if (pid != 0x01)
  86. return;
  87. handle_table_changes(cat);
  88. if (ts->forced_caid) {
  89. ts->emm_caid = ts->forced_caid;
  90. ts_get_emm_info_by_caid(ts->cat, ts->emm_caid, &ts->emm_pid);
  91. } else {
  92. ts_get_emm_info(ts->cat, ts->req_CA_sys, &ts->emm_caid, &ts->emm_pid);
  93. }
  94. if (ts->forced_emm_pid)
  95. ts_get_emm_info_by_pid(ts->cat, &ts->emm_caid, ts->forced_emm_pid);
  96. if (ts->emm_caid) {
  97. char *CA_sys = ts_get_CA_sys_txt(ts_get_CA_sys(ts->emm_caid));
  98. ts_LOGf("--- | EMM CAID: 0x%04x (%s)\n", ts->emm_caid, CA_sys);
  99. if (!ts->forced_emm_pid) {
  100. ts_LOGf("--- | EMM pid : 0x%04x (%s)\n", ts->emm_pid, CA_sys);
  101. } else {
  102. ts_LOGf("--- | EMM pid : 0x%04x (%s) (forced: 0x%04x)\n",
  103. ts->emm_pid, CA_sys, ts->forced_emm_pid);
  104. ts->emm_pid = ts->forced_emm_pid;
  105. }
  106. } else {
  107. ts_LOGf("*** | ERROR: Can't detect EMM pid.\n");
  108. }
  109. }
  110. void process_pmt(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
  111. int i;
  112. if (!pid || pid != ts->pmt_pid)
  113. return;
  114. handle_table_changes(pmt);
  115. pidmap_clear(&ts->pidmap);
  116. pidmap_set(&ts->pidmap, 0x0000); // PAT
  117. pidmap_set(&ts->pidmap, 0x0011); // SDT
  118. if (ts->nit_passthrough)
  119. pidmap_set(&ts->pidmap, 0x0010); // NIT
  120. if (ts->eit_passthrough)
  121. pidmap_set(&ts->pidmap, 0x0012); // EIT
  122. if (ts->tdt_passthrough)
  123. pidmap_set(&ts->pidmap, 0x0014); // TDT/TOT
  124. pidmap_set(&ts->pidmap, ts->pmt->ts_header.pid); // PMT PID
  125. pidmap_set(&ts->pidmap, ts->pmt->PCR_pid); // PCR
  126. for (i=0;i<ts->pmt->streams_num;i++) {
  127. struct ts_pmt_stream *stream = ts->pmt->streams[i];
  128. pidmap_set(&ts->pidmap, stream->pid); // Data
  129. }
  130. if (ts->forced_caid) {
  131. ts->ecm_caid = ts->forced_caid;
  132. ts_get_ecm_info_by_caid(ts->pmt, ts->ecm_caid, &ts->ecm_pid);
  133. } else {
  134. ts_get_ecm_info(ts->pmt, ts->req_CA_sys, &ts->ecm_caid, &ts->ecm_pid);
  135. }
  136. if (ts->forced_ecm_pid)
  137. ts_get_ecm_info_by_pid(ts->pmt, &ts->ecm_caid, ts->forced_ecm_pid);
  138. if (ts->ecm_caid) {
  139. char *CA_sys = ts_get_CA_sys_txt(ts_get_CA_sys(ts->ecm_caid));
  140. ts_LOGf("--- | ECM CAID: 0x%04x (%s)\n", ts->ecm_caid, CA_sys);
  141. if (!ts->forced_ecm_pid) {
  142. ts_LOGf("--- | ECM pid : 0x%04x (%s)\n", ts->ecm_pid, CA_sys);
  143. } else {
  144. ts_LOGf("--- | ECM pid : 0x%04x (%s) (forced: 0x%04x)\n",
  145. ts->ecm_pid, CA_sys, ts->forced_ecm_pid);
  146. ts->ecm_pid = ts->forced_ecm_pid;
  147. }
  148. } else {
  149. ts_LOGf("*** | ERROR: Can't detect ECM pid.\n");
  150. }
  151. }
  152. static int sdt_parse_service_name_desc(
  153. int desc_len, uint8_t *desc,
  154. uint8_t *pname_len, uint8_t **pname,
  155. uint8_t *sname_len, uint8_t **sname)
  156. {
  157. int ofs = 0;
  158. *pname_len = 0;
  159. *sname_len = 0;
  160. *pname = NULL;
  161. *sname = NULL;
  162. while (ofs + 2 < desc_len) {
  163. uint8_t tag = desc[ofs++];
  164. uint8_t len = desc[ofs++];
  165. if (tag != 0x48) {
  166. ofs += len;
  167. continue;
  168. }
  169. // Parse descriptor 0x48 - Service name descriptor
  170. // +3 == +1 for service type, +1 for provider len, +1 for service len
  171. if (ofs + 3 > desc_len)
  172. break;
  173. ofs++; // Skip service type
  174. *pname_len = desc[ofs++];
  175. if (*pname_len)
  176. *pname = desc + ofs;
  177. ofs += *pname_len;
  178. if (ofs > desc_len)
  179. break;
  180. *sname_len = desc[ofs++];
  181. if (*sname_len)
  182. *sname = desc + ofs;
  183. ofs += *sname_len;
  184. return 1;
  185. }
  186. return 0;
  187. }
  188. void process_sdt(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
  189. int i;
  190. if (pid != 0x11)
  191. return;
  192. handle_table_changes(sdt);
  193. for(i=0;i<ts->sdt->streams_num;i++) {
  194. struct ts_sdt_stream *stream = ts->sdt->streams[i];
  195. uint8_t *pname, *sname;
  196. uint8_t pname_len, sname_len;
  197. if (sdt_parse_service_name_desc(
  198. stream->descriptor_size, stream->descriptor_data,
  199. &pname_len, &pname, &sname_len, &sname))
  200. {
  201. ts_LOGf("SDT | Service 0x%04x (%5d) Provider: \"%.*s\" Service: \"%.*s\"\n",
  202. stream->service_id, stream->service_id,
  203. pname_len, (char *)pname,
  204. sname_len, (char *)sname);
  205. } else {
  206. ts_LOGf("SDT | Service 0x%04x (%5d)\n",
  207. stream->service_id, stream->service_id);
  208. }
  209. }
  210. }
  211. #define dump_sz (16)
  212. #define dump_buf_sz (dump_sz * 6)
  213. static void __process_emm(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
  214. char dump[dump_buf_sz];
  215. show_ts_pack(ts, pid, "emm", NULL, ts_packet);
  216. if (!ts->emm_send)
  217. return;
  218. ts->emm = ts_privsec_push_packet(ts->emm, ts_packet);
  219. if (!ts->emm->initialized)
  220. return;
  221. struct ts_header *th = &ts->emm->ts_header;
  222. struct ts_section_header *sec = ts->emm->section_header;
  223. if (ts->debug_level >= 2) {
  224. ts_hex_dump_buf(dump, dump_buf_sz, sec->section_data, min(dump_sz, sec->section_data_len), 0);
  225. ts_LOGf("EMM | CAID: 0x%04x PID 0x%04x SID 0x%04x Table: 0x%02x Length: %3d Data: %s..\n",
  226. ts->emm_caid,
  227. th->pid,
  228. ts->service_id,
  229. sec->table_id,
  230. sec->section_data_len,
  231. dump);
  232. }
  233. camd_process_packet(ts, camd_msg_alloc(EMM_MSG, ts->emm_caid, ts->service_id, sec->section_data, sec->section_data_len));
  234. ts_privsec_copy(ts->emm, ts->last_emm);
  235. ts_privsec_clear(ts->emm);
  236. }
  237. static void __process_ecm(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
  238. char dump[dump_buf_sz];
  239. ts->ecm = ts_privsec_push_packet(ts->ecm, ts_packet);
  240. if (!ts->ecm->initialized)
  241. return;
  242. if (ts->req_CA_sys == CA_IRDETO) {
  243. int type = ts->ecm->section_header->section_data[4];
  244. if (type != ts->irdeto_ecm) {
  245. ts_privsec_clear(ts->ecm);
  246. return;
  247. }
  248. }
  249. struct ts_header *th = &ts->ecm->ts_header;
  250. struct ts_section_header *sec = ts->ecm->section_header;
  251. // ECMs should be in these tables.
  252. if (sec->section_data[0] != 0x80 && sec->section_data[0] != 0x81) {
  253. ts_privsec_clear(ts->ecm);
  254. return;
  255. }
  256. int duplicate = ts_privsec_is_same(ts->ecm, ts->last_ecm);
  257. if (duplicate && !ts->is_cw_error)
  258. ts->ecm_duplicate_count++;
  259. if (!duplicate || ts->is_cw_error) {
  260. if (ts->ecm_cw_log) {
  261. ts_hex_dump_buf(dump, dump_buf_sz, sec->section_data, min(dump_sz, sec->section_data_len), 0);
  262. ts_LOGf("ECM | CAID: 0x%04x PID 0x%04x SID 0x%04x Table: 0x%02x Length: %3d Data: %s..\n",
  263. ts->ecm_caid,
  264. th->pid,
  265. ts->service_id,
  266. sec->table_id,
  267. sec->section_data_len,
  268. dump);
  269. }
  270. ts->is_cw_error = 0;
  271. camd_process_packet(ts, camd_msg_alloc(ECM_MSG, ts->ecm_caid, ts->service_id, sec->section_data, sec->section_data_len));
  272. } else if (ts->debug_level >= 3) {
  273. ts_LOGf("ECM | CAID: 0x%04x PID 0x%04x Table: 0x%02x Length: %3d Data: -dup-\n",
  274. ts->ecm_caid,
  275. th->pid,
  276. sec->table_id,
  277. sec->section_data_len);
  278. }
  279. ts_privsec_copy(ts->ecm, ts->last_ecm);
  280. ts_privsec_clear(ts->ecm);
  281. show_ts_pack(ts, pid, !duplicate ? "ecm" : "ec+", NULL, ts_packet);
  282. }
  283. // There are cryptosystems that are puting more than one PSI table
  284. // in TS packet. IRDETO is such example. Because libtsfuncs assumes
  285. // that one ts packet can produce maximum 1 PSI table, the following
  286. // workaround is used for EMM/ECM private sections. Basically we detect
  287. // if after the section there is something else than 0xff (filler) and
  288. // if there is something change ts_packet pointer field to point to
  289. // start of the potential section and reparse section.
  290. void process_ecm(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
  291. int section_end;
  292. if (ts->emm_only)
  293. return;
  294. if (!ts->ecm_pid || ts->ecm_pid != pid)
  295. return;
  296. process_psi:
  297. ts->tmp_ecm = ts_privsec_push_packet(ts->tmp_ecm, ts_packet);
  298. if (!ts->tmp_ecm->initialized) {
  299. __process_ecm(ts, pid, ts_packet);
  300. return;
  301. }
  302. section_end = ts->tmp_ecm->section_header->pointer_field + ts->tmp_ecm->section_header->section_length + 3 + 4 + 1;
  303. if (section_end < 188 && ts_packet[section_end] != 0xff) {
  304. __process_ecm(ts, pid, ts_packet);
  305. ts_packet[4] = ts_packet[4] + ts->tmp_ecm->section_header->section_length + 3;
  306. ts_privsec_clear(ts->tmp_ecm);
  307. goto process_psi;
  308. } else {
  309. __process_ecm(ts, pid, ts_packet);
  310. }
  311. ts_privsec_clear(ts->tmp_ecm);
  312. }
  313. void process_emm(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
  314. int section_end;
  315. if (!ts->emm_pid || ts->emm_pid != pid)
  316. return;
  317. process_psi:
  318. ts->tmp_emm = ts_privsec_push_packet(ts->tmp_emm, ts_packet);
  319. if (!ts->tmp_emm->initialized) {
  320. __process_emm(ts, pid, ts_packet);
  321. return;
  322. }
  323. section_end = ts->tmp_emm->section_header->pointer_field + ts->tmp_emm->section_header->section_length + 3 + 4 + 1;
  324. if (section_end < 188 && ts_packet[section_end] != 0xff) {
  325. __process_emm(ts, pid, ts_packet);
  326. ts_packet[4] = ts_packet[4] + ts->tmp_emm->section_header->section_length + 3;
  327. ts_privsec_clear(ts->tmp_emm);
  328. goto process_psi;
  329. } else {
  330. __process_emm(ts, pid, ts_packet);
  331. }
  332. ts_privsec_clear(ts->tmp_emm);
  333. }