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.

filter.c 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /*
  2. * Filtering functions
  3. * Copyright (C) 2012 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 <ctype.h>
  16. #include <string.h>
  17. #include "data.h"
  18. #include "filter.h"
  19. int filter_parse(char *filter_def, struct filter *filter) {
  20. int i, j, k, ret = 0;
  21. char *str1, *saveptr1;
  22. char *f = strdup(filter_def);
  23. memset(filter, 0, sizeof(struct filter));
  24. snprintf(filter->name, sizeof(filter->name), "NONAME");
  25. for (j = 1, str1 = f; ; j++, str1 = NULL) {
  26. char *token = strtok_r(str1, "/", &saveptr1);
  27. if (token == NULL)
  28. break;
  29. if (j == 1) { // First token, the command
  30. if (strstr(token, "accept_all") == token || strstr(token, "acceptall") == token) {
  31. filter->action = FILTER_ACCEPT_ALL;
  32. ret = 1;
  33. goto OUT; // Other tokens are not needed
  34. } else if (strstr(token, "reject_all") == token || strstr(token, "rejectall") == token) {
  35. filter->action = FILTER_REJECT_ALL;
  36. ret = 1;
  37. goto OUT; // Other tokens are not needed
  38. } else if (strstr(token, "accept") == token) {
  39. filter->action = FILTER_ACCEPT;
  40. continue; // Continue looking for other tokes
  41. } else if (strstr(token, "reject") == token) {
  42. filter->action = FILTER_REJECT;
  43. continue; // Continue looking for other tokes
  44. } else {
  45. fprintf(stderr, "ERROR: Unknown filter command: %s\n", token);
  46. ret = 0;
  47. goto OUT; // Other tokens are not needed
  48. }
  49. }
  50. if (j == 2) { // Second token, the settings
  51. char *str2, *saveptr2;
  52. for (k = 1, str2 = token; ; k++, str2 = NULL) {
  53. char *token2 = strtok_r(str2, ",", &saveptr2);
  54. if (token2 == NULL)
  55. break;
  56. char *eq = strrchr(token2, '=');
  57. if (eq) {
  58. if (strstr(token2, "ofs") == token2 || strstr(token2, "offset") == token2) {
  59. filter->offset = strtoul(eq + 1, NULL, 0);
  60. } else if (strstr(token2, "name") == token2) {
  61. snprintf(filter->name, sizeof(filter->name), "%s", eq + 1);
  62. } else if (strstr(token2, "data") == token2) {
  63. char *data = eq + 1;
  64. int len = strlen(data), consumed = 0;
  65. for (i = 0; i < len; i++) { // Parse data (01 02 03 04 ...)
  66. char ch = toupper(data[i]);
  67. // Skip 0x prefixes
  68. if (i + 1 < len && ch == '0' && toupper(data[i + 1]) == 'X')
  69. continue;
  70. if (!isxdigit(ch))
  71. continue;
  72. ch -= ch > 64 ? 55 : 48; // hex2dec
  73. if (consumed % 2 == 0) {
  74. filter->data[filter->data_len ] += ch << 4;
  75. } else {
  76. filter->data[filter->data_len++] += ch;
  77. if (filter->data_len + 1 >= MAX_FILTER_LEN) {
  78. fprintf(stderr, "WARN : Too much filter data (max %d bytes), ignoring last bytes: %s\n",
  79. MAX_FILTER_LEN, data + i + 2);
  80. break;
  81. }
  82. }
  83. consumed++;
  84. }
  85. ret = filter->data_len;
  86. } else {
  87. fprintf(stderr, "WARN : Unknown filter setting: %s\n", token2);
  88. }
  89. }
  90. }
  91. }
  92. }
  93. OUT:
  94. FREE(f);
  95. return ret;
  96. }
  97. void filter_dump(struct filter *filter, char *buffer, unsigned int buf_len) {
  98. unsigned int pos = 0;
  99. memset(buffer, 0, buf_len);
  100. pos += snprintf(buffer + pos, buf_len - pos, "Action: %s",
  101. filter->action == FILTER_ACCEPT_ALL ? "ACCEPT_ALL (default)" :
  102. filter->action == FILTER_REJECT_ALL ? "REJECT_ALL (default)" :
  103. filter->action == FILTER_ACCEPT ? "ACCEPT" :
  104. filter->action == FILTER_REJECT ? "REJECT" : "???");
  105. if (filter->action == FILTER_ACCEPT || filter->action == FILTER_REJECT)
  106. pos += snprintf(buffer + pos, buf_len - pos, " Name: %-20s", filter->name);
  107. if (filter->action == FILTER_ACCEPT || filter->action == FILTER_REJECT) {
  108. char tmp[MAX_FILTER_LEN * 6];
  109. ts_hex_dump_buf(tmp, sizeof(tmp), filter->data, filter->data_len, 0);
  110. pos += snprintf(buffer + pos, buf_len - pos, " Offset: %2d Data: %s", filter->offset, tmp);
  111. }
  112. }
  113. static enum filter_action filter_match(uint8_t *data, unsigned int data_len, struct filter *filter) {
  114. if (filter->action == FILTER_ACCEPT_ALL || filter->action == FILTER_REJECT_ALL)
  115. return filter->action;
  116. if (filter->action == FILTER_ACCEPT || filter->action == FILTER_REJECT) {
  117. if (filter->data_len + filter->offset > data_len)
  118. return FILTER_NO_MATCH;
  119. if (memcmp(data + filter->offset, filter->data, filter->data_len) == 0)
  120. return filter->action;
  121. }
  122. return FILTER_NO_MATCH;
  123. }
  124. int filter_match_emm(struct ts *ts, uint8_t *data, unsigned int data_len) {
  125. int i, ret = 1;
  126. for (i = 0; i < ts->emm_filters_num; i++) {
  127. enum filter_action result = filter_match(data, data_len, &ts->emm_filters[i]);
  128. switch (result) {
  129. case FILTER_NO_MATCH : continue;
  130. case FILTER_ACCEPT_ALL: ret = 1; continue;
  131. case FILTER_ACCEPT : ret = 1; break;
  132. case FILTER_REJECT_ALL: ret = 0; continue;
  133. case FILTER_REJECT : ret = 0; break;
  134. }
  135. }
  136. return ret;
  137. }