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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  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. if (pid != 0x00)
  43. return;
  44. handle_table_changes(pat);
  45. for (i=0;i<ts->pat->programs_num;i++) {
  46. struct ts_pat_program *prg = ts->pat->programs[i];
  47. if (prg->pid) {
  48. if (prg->program != 0) {
  49. ts->pmt_pid = prg->pid;
  50. ts->service_id = prg->program;
  51. }
  52. }
  53. }
  54. }
  55. void process_cat(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
  56. if (pid != 0x01)
  57. return;
  58. handle_table_changes(cat);
  59. if (ts->forced_caid) {
  60. ts->emm_caid = ts->forced_caid;
  61. ts_get_emm_info_by_caid(ts->cat, ts->emm_caid, &ts->emm_pid);
  62. } else {
  63. ts_get_emm_info(ts->cat, ts->req_CA_sys, &ts->emm_caid, &ts->emm_pid);
  64. }
  65. if (ts->forced_emm_pid)
  66. ts_get_emm_info_by_pid(ts->cat, &ts->emm_caid, ts->forced_emm_pid);
  67. if (ts->emm_caid) {
  68. char *CA_sys = ts_get_CA_sys_txt(ts_get_CA_sys(ts->emm_caid));
  69. ts_LOGf("--- | EMM CAID: 0x%04x (%s)\n", ts->emm_caid, CA_sys);
  70. if (!ts->forced_emm_pid) {
  71. ts_LOGf("--- | EMM pid : 0x%04x (%s)\n", ts->emm_pid, CA_sys);
  72. } else {
  73. ts_LOGf("--- | EMM pid : 0x%04x (%s) (forced: 0x%04x)\n",
  74. ts->emm_pid, CA_sys, ts->forced_emm_pid);
  75. ts->emm_pid = ts->forced_emm_pid;
  76. }
  77. } else {
  78. ts_LOGf("*** | ERROR: Can't detect EMM pid.\n");
  79. }
  80. }
  81. void process_pmt(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
  82. int i;
  83. if (!pid || pid != ts->pmt_pid)
  84. return;
  85. handle_table_changes(pmt);
  86. pidmap_clear(&ts->pidmap);
  87. pidmap_set(&ts->pidmap, 0x0000); // PAT
  88. pidmap_set(&ts->pidmap, 0x0011); // SDT
  89. pidmap_set(&ts->pidmap, ts->pmt->ts_header.pid); // PMT PID
  90. pidmap_set(&ts->pidmap, ts->pmt->PCR_pid); // PCR
  91. for (i=0;i<ts->pmt->streams_num;i++) {
  92. struct ts_pmt_stream *stream = ts->pmt->streams[i];
  93. pidmap_set(&ts->pidmap, stream->pid); // Data
  94. }
  95. if (ts->forced_caid) {
  96. ts->ecm_caid = ts->forced_caid;
  97. ts_get_ecm_info_by_caid(ts->pmt, ts->ecm_caid, &ts->ecm_pid);
  98. } else {
  99. ts_get_ecm_info(ts->pmt, ts->req_CA_sys, &ts->ecm_caid, &ts->ecm_pid);
  100. }
  101. if (ts->forced_ecm_pid)
  102. ts_get_ecm_info_by_pid(ts->pmt, &ts->ecm_caid, ts->forced_ecm_pid);
  103. if (ts->ecm_caid) {
  104. char *CA_sys = ts_get_CA_sys_txt(ts_get_CA_sys(ts->ecm_caid));
  105. ts_LOGf("--- | ECM CAID: 0x%04x (%s)\n", ts->ecm_caid, CA_sys);
  106. if (!ts->forced_ecm_pid) {
  107. ts_LOGf("--- | ECM pid : 0x%04x (%s)\n", ts->ecm_pid, CA_sys);
  108. } else {
  109. ts_LOGf("--- | ECM pid : 0x%04x (%s) (forced: 0x%04x)\n",
  110. ts->ecm_pid, CA_sys, ts->forced_ecm_pid);
  111. ts->ecm_pid = ts->forced_ecm_pid;
  112. }
  113. } else {
  114. ts_LOGf("*** | ERROR: Can't detect ECM pid.\n");
  115. }
  116. }
  117. #define dump_sz (16)
  118. #define dump_buf_sz (dump_sz * 6)
  119. static void __process_emm(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
  120. char dump[dump_buf_sz];
  121. show_ts_pack(ts, pid, "emm", NULL, ts_packet);
  122. if (!ts->emm_send)
  123. return;
  124. ts->emm = ts_privsec_push_packet(ts->emm, ts_packet);
  125. if (!ts->emm->initialized)
  126. return;
  127. struct ts_header *th = &ts->emm->ts_header;
  128. struct ts_section_header *sec = ts->emm->section_header;
  129. if (ts->debug_level >= 2) {
  130. ts_hex_dump_buf(dump, dump_buf_sz, sec->section_data, min(dump_sz, sec->section_data_len), 0);
  131. ts_LOGf("EMM | CAID: 0x%04x PID 0x%04x Table: 0x%02x Length: %3d ----------- Data: %s..\n",
  132. ts->emm_caid,
  133. th->pid,
  134. sec->table_id,
  135. sec->section_data_len,
  136. dump);
  137. }
  138. camd_msg_process(ts, camd_msg_alloc_emm(ts->emm_caid, sec->section_data, sec->section_data_len));
  139. ts_privsec_copy(ts->emm, ts->last_emm);
  140. ts_privsec_clear(ts->emm);
  141. }
  142. static void __process_ecm(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
  143. char dump[dump_buf_sz];
  144. ts->ecm = ts_privsec_push_packet(ts->ecm, ts_packet);
  145. if (!ts->ecm->initialized)
  146. return;
  147. if (ts->req_CA_sys == CA_IRDETO) {
  148. int type = ts->ecm->section_header->section_data[4];
  149. if (type != ts->irdeto_ecm) {
  150. ts_privsec_clear(ts->ecm);
  151. return;
  152. }
  153. }
  154. struct ts_header *th = &ts->ecm->ts_header;
  155. struct ts_section_header *sec = ts->ecm->section_header;
  156. int duplicate = ts_privsec_is_same(ts->ecm, ts->last_ecm);
  157. if (duplicate && !ts->is_cw_error)
  158. ts->ecm_duplicate_count++;
  159. if (!duplicate || ts->is_cw_error) {
  160. if (ts->ecm_cw_log) {
  161. ts_hex_dump_buf(dump, dump_buf_sz, sec->section_data, min(dump_sz, sec->section_data_len), 0);
  162. ts_LOGf("ECM | CAID: 0x%04x PID 0x%04x Table: 0x%02x Length: %3d IDX: 0x%04x Data: %s..\n",
  163. ts->ecm_caid,
  164. th->pid,
  165. sec->table_id,
  166. sec->section_data_len,
  167. ts->ecm_counter,
  168. dump);
  169. }
  170. if (ts->is_cw_error)
  171. ts->ecm_counter--;
  172. ts->is_cw_error = 0;
  173. camd_msg_process(ts, camd_msg_alloc_ecm(ts->ecm_caid, ts->service_id, ts->ecm_counter++, sec->section_data, sec->section_data_len));
  174. } else if (ts->debug_level >= 3) {
  175. ts_LOGf("ECM | CAID: 0x%04x PID 0x%04x Table: 0x%02x Length: %3d IDX: 0x%04x Data: -dup-\n",
  176. ts->ecm_caid,
  177. th->pid,
  178. sec->table_id,
  179. sec->section_data_len,
  180. ts->ecm_counter - 1);
  181. }
  182. ts_privsec_copy(ts->ecm, ts->last_ecm);
  183. ts_privsec_clear(ts->ecm);
  184. show_ts_pack(ts, pid, !duplicate ? "ecm" : "ec+", NULL, ts_packet);
  185. }
  186. // There are cryptosystems that are puting more than one PSI table
  187. // in TS packet. IRDETO is such example. Because libtsfuncs assumes
  188. // that one ts packet can produce maximum 1 PSI table, the following
  189. // workaround is used for EMM/ECM private sections. Basically we detect
  190. // if after the section there is something else than 0xff (filler) and
  191. // if there is something change ts_packet pointer field to point to
  192. // start of the potential section and reparse section.
  193. void process_ecm(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
  194. int section_end;
  195. if (ts->emm_only)
  196. return;
  197. if (!ts->ecm_pid || ts->ecm_pid != pid)
  198. return;
  199. process_psi:
  200. ts->tmp_ecm = ts_privsec_push_packet(ts->tmp_ecm, ts_packet);
  201. if (!ts->tmp_ecm->initialized) {
  202. __process_ecm(ts, pid, ts_packet);
  203. return;
  204. }
  205. section_end = ts->tmp_ecm->section_header->pointer_field + ts->tmp_ecm->section_header->section_length + 3 + 4 + 1;
  206. if (section_end < 188 && ts_packet[section_end] != 0xff) {
  207. __process_ecm(ts, pid, ts_packet);
  208. ts_packet[4] = ts_packet[4] + ts->tmp_ecm->section_header->section_length + 3;
  209. ts_privsec_clear(ts->tmp_ecm);
  210. goto process_psi;
  211. } else {
  212. __process_ecm(ts, pid, ts_packet);
  213. }
  214. ts_privsec_clear(ts->tmp_ecm);
  215. }
  216. void process_emm(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
  217. int section_end;
  218. if (!ts->emm_pid || ts->emm_pid != pid)
  219. return;
  220. process_psi:
  221. ts->tmp_emm = ts_privsec_push_packet(ts->tmp_emm, ts_packet);
  222. if (!ts->tmp_emm->initialized) {
  223. __process_emm(ts, pid, ts_packet);
  224. return;
  225. }
  226. section_end = ts->tmp_emm->section_header->pointer_field + ts->tmp_emm->section_header->section_length + 3 + 4 + 1;
  227. if (section_end < 188 && ts_packet[section_end] != 0xff) {
  228. __process_emm(ts, pid, ts_packet);
  229. ts_packet[4] = ts_packet[4] + ts->tmp_emm->section_header->section_length + 3;
  230. ts_privsec_clear(ts->tmp_emm);
  231. goto process_psi;
  232. } else {
  233. __process_emm(ts, pid, ts_packet);
  234. }
  235. ts_privsec_clear(ts->tmp_emm);
  236. }