|
@@ -2,6 +2,10 @@
|
2
|
2
|
#include <stdlib.h>
|
3
|
3
|
#include <unistd.h>
|
4
|
4
|
#include <string.h>
|
|
5
|
+#include <sys/types.h>
|
|
6
|
+#include <sys/stat.h>
|
|
7
|
+#include <fcntl.h>
|
|
8
|
+#include <errno.h>
|
5
|
9
|
|
6
|
10
|
#include <dvbcsa/dvbcsa.h>
|
7
|
11
|
|
|
@@ -25,24 +29,33 @@ void LOG_func(const char *msg) {
|
25
|
29
|
}
|
26
|
30
|
|
27
|
31
|
void show_help(struct ts *ts) {
|
28
|
|
- printf("ts v1.0\n");
|
|
32
|
+ printf("tsdecrypt v1.0\n");
|
29
|
33
|
printf("Copyright (c) 2011 Unix Solutions Ltd.\n");
|
30
|
34
|
printf("\n");
|
31
|
|
- printf(" Usage: ts [opts] < mpeg_ts\n");
|
|
35
|
+ printf(" Usage: tsdecrypt [opts]\n");
|
|
36
|
+ printf("\n");
|
|
37
|
+ printf(" Input options:\n");
|
|
38
|
+ printf(" -I input | Where to read from. Supports files and multicast\n");
|
|
39
|
+ printf(" | -I 224.0.0.1:5000 (multicast receive)\n");
|
|
40
|
+ printf(" | -I file.ts (read from file)\n");
|
|
41
|
+ printf(" | -I - (read from STDIN, the default)\n");
|
32
|
42
|
printf("\n");
|
33
|
|
- printf(" Options:\n");
|
34
|
43
|
printf(" -c ca_system | default: %s valid: IRDETO, CONNAX, CRYPTOWORKS\n", ts_get_CA_sys_txt(ts->req_CA_sys));
|
35
|
44
|
printf("\n");
|
|
45
|
+ printf(" Output options:\n");
|
|
46
|
+ printf(" -O output | Where to send output. Supports files and multicast\n");
|
|
47
|
+ printf(" | -O 239.0.0.1:5000 (multicast send)\n");
|
|
48
|
+ printf(" | -O file.ts (write to file)\n");
|
|
49
|
+ printf(" | -O - (write to STDOUT, the default)\n");
|
|
50
|
+ printf("\n");
|
|
51
|
+ printf(" -i output_intf | default: %s\n", inet_ntoa(ts->output.intf));
|
|
52
|
+ printf(" -t output_ttl | default: %d\n", ts->output.ttl);
|
|
53
|
+ printf("\n");
|
36
|
54
|
printf(" CAMD35 server options:\n");
|
37
|
55
|
printf(" -s server_addr | default: disabled (format 1.2.3.4:2233)\n");
|
38
|
56
|
printf(" -U server_user | default: %s\n", ts->camd35.user);
|
39
|
57
|
printf(" -P server_pass | default: %s\n", ts->camd35.pass);
|
40
|
58
|
printf("\n");
|
41
|
|
- printf(" Output options (if output is disabled stdout is used for output):\n");
|
42
|
|
- printf(" -o output_addr | default: disabled (format: 239.78.78.78:5000)\n");
|
43
|
|
- printf(" -i output_intf | default: %s\n", inet_ntoa(ts->output_intf));
|
44
|
|
- printf(" -t output_ttl | default: %d\n", ts->output_ttl);
|
45
|
|
- printf("\n");
|
46
|
59
|
printf(" Filtering options:\n");
|
47
|
60
|
printf(" -e | EMM send (default: %s).\n", ts->emm_send ? "enabled" : "disabled");
|
48
|
61
|
printf(" | - Send EMMs to CAMD server for processing.\n");
|
|
@@ -51,7 +64,7 @@ void show_help(struct ts *ts) {
|
51
|
64
|
printf(" | - When PID filter is enabled only PAT/PMT/SDT/data\n");
|
52
|
65
|
printf(" | - packets are left in the output.\n");
|
53
|
66
|
printf("\n");
|
54
|
|
- printf(" -D debug_level | Message debug level. Bigger levels includes the levels bellow.\n");
|
|
67
|
+ printf(" -D debug_level | Message debug level.\n");
|
55
|
68
|
printf(" | 0 - default messages\n");
|
56
|
69
|
printf(" | 1 - show PSI tables\n");
|
57
|
70
|
printf(" | 2 - show EMMs\n");
|
|
@@ -60,9 +73,32 @@ void show_help(struct ts *ts) {
|
60
|
73
|
printf("\n");
|
61
|
74
|
}
|
62
|
75
|
|
|
76
|
+static int parse_io_param(struct io *io, char *opt, int open_flags, mode_t open_mode) {
|
|
77
|
+ io->type = WTF_IO;
|
|
78
|
+ char *p = strrchr(opt, ':');
|
|
79
|
+ if (!p) {
|
|
80
|
+ io->type = FILE_IO;
|
|
81
|
+ if (strcmp(opt, "-") != 0) {
|
|
82
|
+ io->fd = open(opt, open_flags, open_mode);
|
|
83
|
+ if (io->fd < 0) {
|
|
84
|
+ fprintf(stderr, "ERROR: Can not open file (%s): %s\n", opt, strerror(errno));
|
|
85
|
+ exit(1);
|
|
86
|
+ }
|
|
87
|
+ }
|
|
88
|
+ io->fname = strdup(opt);
|
|
89
|
+ return 0;
|
|
90
|
+ }
|
|
91
|
+ *p = 0x00;
|
|
92
|
+ io->type = NET_IO;
|
|
93
|
+ io->port = atoi(p + 1);
|
|
94
|
+ if (inet_aton(opt, &io->addr) == 0)
|
|
95
|
+ return 1;
|
|
96
|
+ return 0;
|
|
97
|
+}
|
|
98
|
+
|
63
|
99
|
void parse_options(struct ts *ts, int argc, char **argv) {
|
64
|
|
- int j, ca_err = 0, server_err = 1, output_addr_err = 0, output_intf_err = 0;
|
65
|
|
- while ((j = getopt(argc, argv, "cFs:o:i:t:U:P:epD:h")) != -1) {
|
|
100
|
+ int j, ca_err = 0, server_err = 1, input_addr_err = 0, output_addr_err = 0, output_intf_err = 0;
|
|
101
|
+ while ((j = getopt(argc, argv, "cFs:I:O:i:t:U:P:epD:h")) != -1) {
|
66
|
102
|
char *p = NULL;
|
67
|
103
|
switch (j) {
|
68
|
104
|
case 'c':
|
|
@@ -88,21 +124,21 @@ void parse_options(struct ts *ts, int argc, char **argv) {
|
88
|
124
|
server_err = 0;
|
89
|
125
|
break;
|
90
|
126
|
|
91
|
|
- case 'o':
|
92
|
|
- p = strrchr(optarg, ':');
|
93
|
|
- if (p) {
|
94
|
|
- *p = 0x00;
|
95
|
|
- ts->output_port = atoi(p + 1);
|
96
|
|
- }
|
97
|
|
- if (inet_aton(optarg, &ts->output_addr) == 0)
|
98
|
|
- output_addr_err = 1;
|
|
127
|
+ case 'I':
|
|
128
|
+ input_addr_err = parse_io_param(&ts->input, optarg, O_RDONLY, 0);
|
99
|
129
|
break;
|
|
130
|
+ case 'O':
|
|
131
|
+ output_addr_err = parse_io_param(&ts->output, optarg,
|
|
132
|
+ O_CREAT | O_WRONLY | O_TRUNC,
|
|
133
|
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
|
134
|
+ break;
|
|
135
|
+
|
100
|
136
|
case 'i':
|
101
|
|
- if (inet_aton(optarg, &ts->output_intf) == 0)
|
|
137
|
+ if (inet_aton(optarg, &ts->output.intf) == 0)
|
102
|
138
|
output_intf_err = 1;
|
103
|
139
|
break;
|
104
|
140
|
case 't':
|
105
|
|
- ts->output_ttl = atoi(optarg);
|
|
141
|
+ ts->output.ttl = atoi(optarg);
|
106
|
142
|
break;
|
107
|
143
|
|
108
|
144
|
case 'U':
|
|
@@ -130,12 +166,14 @@ void parse_options(struct ts *ts, int argc, char **argv) {
|
130
|
166
|
exit(0);
|
131
|
167
|
}
|
132
|
168
|
}
|
133
|
|
- if (ca_err || server_err) {
|
|
169
|
+ if (ca_err || server_err || input_addr_err || output_addr_err || ts->input.type == WTF_IO || ts->output.type == WTF_IO) {
|
134
|
170
|
show_help(ts);
|
135
|
171
|
if (ca_err)
|
136
|
172
|
fprintf(stderr, "ERROR: Requested CA system is unsupported.\n");
|
137
|
173
|
if (server_err)
|
138
|
174
|
fprintf(stderr, "ERROR: Server IP address is not set or it is invalid.\n");
|
|
175
|
+ if (input_addr_err)
|
|
176
|
+ fprintf(stderr, "ERROR: Input IP address is invalid.\n");
|
139
|
177
|
if (output_addr_err)
|
140
|
178
|
fprintf(stderr, "ERROR: Output IP address is invalid.\n");
|
141
|
179
|
if (output_intf_err)
|
|
@@ -143,14 +181,21 @@ void parse_options(struct ts *ts, int argc, char **argv) {
|
143
|
181
|
exit(1);
|
144
|
182
|
}
|
145
|
183
|
ts_LOGf("CA System : %s\n", ts_get_CA_sys_txt(ts->req_CA_sys));
|
146
|
|
- ts_LOGf("Server addr: %s:%u\n", inet_ntoa(ts->camd35.server_addr), ts->camd35.server_port);
|
|
184
|
+ if (ts->input.type == NET_IO) {
|
|
185
|
+ ts_LOGf("Input addr : udp://%s:%u/\n", inet_ntoa(ts->input.addr), ts->input.port);
|
|
186
|
+ } else if (ts->input.type == FILE_IO) {
|
|
187
|
+ ts_LOGf("Input file : %s\n", ts->input.fd == 0 ? "STDIN" : ts->input.fname);
|
|
188
|
+ }
|
|
189
|
+ if (ts->output.type == NET_IO) {
|
|
190
|
+ ts_LOGf("Output addr: udp://%s:%u/\n", inet_ntoa(ts->output.addr), ts->output.port);
|
|
191
|
+ ts_LOGf("Output intf: %s\n", inet_ntoa(ts->output.intf));
|
|
192
|
+ ts_LOGf("Output ttl : %d\n", ts->output.ttl);
|
|
193
|
+ } else if (ts->output.type == FILE_IO) {
|
|
194
|
+ ts_LOGf("Output file: %s\n", ts->output.fd == 1 ? "STDOUT" : ts->output.fname);
|
|
195
|
+ }
|
|
196
|
+ ts_LOGf("Server addr: tcp://%s:%u/\n", inet_ntoa(ts->camd35.server_addr), ts->camd35.server_port);
|
147
|
197
|
ts_LOGf("Server user: %s\n", ts->camd35.user);
|
148
|
198
|
ts_LOGf("Server pass: %s\n", ts->camd35.pass);
|
149
|
|
- if (ts->output_port) {
|
150
|
|
- ts_LOGf("Output addr: %s:%u\n", inet_ntoa(ts->output_addr), ts->output_port);
|
151
|
|
- ts_LOGf("Output intf: %s\n", inet_ntoa(ts->output_intf));
|
152
|
|
- ts_LOGf("Output ttl : %d\n", ts->output_ttl);
|
153
|
|
- }
|
154
|
199
|
ts_LOGf("EMM send : %s\n", ts->emm_send ? "enabled" : "disabled");
|
155
|
200
|
ts_LOGf("PID filter : %s\n", ts->pid_filter ? "enabled" : "disabled");
|
156
|
201
|
}
|
|
@@ -228,9 +273,9 @@ void ts_write_packets(struct ts *ts, uint8_t *data, ssize_t data_len) {
|
228
|
273
|
uint16_t pid = ts_packet_get_pid(ts_packet);
|
229
|
274
|
if (ts->pid_filter) {
|
230
|
275
|
if (pidmap_get(&ts->pidmap, pid)) // PAT or allowed PIDs
|
231
|
|
- write(ts->output_fd, ts_packet, 188);
|
|
276
|
+ write(ts->output.fd, ts_packet, 188);
|
232
|
277
|
} else {
|
233
|
|
- write(ts->output_fd, ts_packet, 188);
|
|
278
|
+ write(ts->output.fd, ts_packet, 188);
|
234
|
279
|
}
|
235
|
280
|
}
|
236
|
281
|
}
|
|
@@ -249,12 +294,12 @@ int main(int argc, char **argv) {
|
249
|
294
|
parse_options(&ts, argc, argv);
|
250
|
295
|
|
251
|
296
|
camd35_connect(&ts.camd35);
|
252
|
|
- if (ts.output_port)
|
253
|
|
- if (udp_connect_output(&ts) < 1)
|
|
297
|
+ if (ts.output.type == NET_IO)
|
|
298
|
+ if (udp_connect_output(&ts.output) < 1)
|
254
|
299
|
goto EXIT;
|
255
|
300
|
|
256
|
301
|
do {
|
257
|
|
- readen = read(ts.input_fd, ts_packet, FRAME_SIZE);
|
|
302
|
+ readen = read(ts.input.fd, ts_packet, FRAME_SIZE);
|
258
|
303
|
if (readen > 0) {
|
259
|
304
|
ts_process_packets(&ts, ts_packet, readen);
|
260
|
305
|
ts_write_packets(&ts, ts_packet, readen);
|