1 /*
2 * Copyright (C) 2014-2020 Catalin Toda <catalinii@yahoo.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17 * USA
18 *
19 */
20
21 #include "tables.h"
22 #include "adapter.h"
23 #include "ca.h"
24 #include "dvb.h"
25 #include "dvbapi.h"
26 #include "minisatip.h"
27 #include <arpa/inet.h>
28 #include <ctype.h>
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <math.h>
32 #include <net/if.h>
33 #include <netdb.h>
34 #include <netinet/in.h>
35 #include <stdint.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <sys/ioctl.h>
40 #include <sys/socket.h>
41 #include <sys/stat.h>
42 #include <sys/types.h>
43 #include <time.h>
44 #include <unistd.h>
45
46 #ifndef DISABLE_DDCI
47 #include "ddci.h"
48 #endif
49
50 #define DEFAULT_LOG LOG_TABLES
51
52 SCA ca[MAX_CA];
53 int nca;
54 SMutex ca_mutex;
55
add_ca(SCA_op * op,uint64_t adapter_mask)56 int add_ca(SCA_op *op, uint64_t adapter_mask) {
57 int i, new_ca;
58 del_ca(op);
59 for (i = 0; i < MAX_CA; i++)
60 if (!ca[i].enabled) {
61 mutex_lock(&ca_mutex);
62 if (!ca[i].enabled)
63 break;
64 mutex_unlock(&ca_mutex);
65 }
66 if (i == MAX_CA)
67 LOG_AND_RETURN(0, "No free CA slots for %p", ca);
68 new_ca = i;
69
70 ca[new_ca].enabled = 1;
71 ca[new_ca].adapter_mask = adapter_mask;
72 ca[new_ca].id = new_ca;
73 ca[new_ca].op = op;
74 memset(ca[new_ca].ad_info, 0, sizeof(ca[new_ca].ad_info));
75
76 if (new_ca >= nca)
77 nca = new_ca + 1;
78
79 init_ca_device(&ca[new_ca]);
80 mutex_unlock(&ca_mutex);
81 return new_ca;
82 }
83 extern SPMT *pmts[];
del_ca(SCA_op * op)84 void del_ca(SCA_op *op) {
85 int i, k, mask = 1;
86 adapter *ad;
87 mutex_lock(&ca_mutex);
88
89 for (i = 0; i < MAX_CA; i++) {
90 if (ca[i].enabled) {
91 if (ca[i].op == op) {
92 ca[i].enabled = 0;
93 for (k = 0; k < MAX_ADAPTERS;
94 k++) // delete ca_mask for all adapters
95 {
96 if ((ad = get_adapter_nw(k)))
97 ad->ca_mask &= ~mask;
98 }
99 for (k = 0; k < npmts; k++) // delete ca_mask for all the PMTs
100 if (pmts[k] && pmts[k]->enabled && pmts[k]->state &&
101 (pmts[k]->ca_mask & mask))
102 pmts[k]->ca_mask &= ~mask;
103 }
104 }
105 mask = mask << 1;
106 }
107 i = MAX_CA;
108 while (--i >= 0 && !ca[i].enabled)
109 ;
110 nca = i + 1;
111
112 // if (nca == 1)
113 // nca = 0;
114
115 mutex_unlock(&ca_mutex);
116 }
117
tables_ca_ts(adapter * ad)118 void tables_ca_ts(adapter *ad) {
119 int i, mask = 1;
120
121 for (i = 0; i < nca; i++) {
122 if (ca[i].enabled && (ad->ca_mask & mask) && ca[i].op->ca_ts) {
123 ca[i].op->ca_ts(ad);
124 }
125 mask = mask << 1;
126 }
127 }
128
add_caid_mask(int ica,int aid,int caid,int mask)129 void add_caid_mask(int ica, int aid, int caid, int mask) {
130 int i;
131 adapter *ad = get_adapter(aid);
132 if (!ad) {
133 LOG("%s: No adapter %d found ", __FUNCTION__, aid);
134 return;
135 }
136 if (ca[ica].enabled && ca[ica].ad_info[aid].caids < MAX_CAID_LEN) {
137 for (i = 0; i < ca[ica].ad_info[aid].caids; i++)
138 if (ca[ica].ad_info[aid].caid[i] == caid &&
139 ca[ica].ad_info[aid].mask[i] == mask)
140 return;
141 i = ca[ica].ad_info[aid].caids++;
142 ca[ica].ad_info[aid].caid[i] = caid;
143 ca[ica].ad_info[aid].mask[i] = mask;
144 LOG("CA %d can handle CAID %04X mask %04X on adapter %d at position %d",
145 ica, caid, mask, ad->id, i);
146 } else
147 LOG("CA not enabled %d or too many added CAIDs %d", ica,
148 ca[ica].ad_info[aid].caids);
149 }
150
tables_init_ca_for_device(int i,adapter * ad)151 int tables_init_ca_for_device(int i, adapter *ad) {
152 uint64_t mask = (1ULL << i);
153 int rv = 0;
154 if (i < 0 || i >= nca)
155 return 0;
156
157 if ((ca[i].adapter_mask & mask) &&
158 !(ad->ca_mask & mask)) // CA registered and not already initialized
159 {
160 if (ca[i].enabled && ca[i].op->ca_init_dev) {
161 if (ca[i].op->ca_init_dev(ad) == TABLES_RESULT_OK) {
162 LOGM("CA %d will handle adapter %d", i, ad->id);
163 ad->ca_mask = ad->ca_mask | mask;
164 rv = 1;
165 } else
166 LOGM("CA %d is disabled for adapter %d", i, ad->id);
167 }
168 }
169 return rv;
170 }
171
match_caid(SPMT * pmt,int caid,int mask)172 int match_caid(SPMT *pmt, int caid, int mask) {
173 int i;
174 for (i = 0; i < pmt->caids; i++)
175 if ((pmt->ca[i].id & mask) == caid) {
176 LOGM("%s: match caid %04X (%d/%d) with CA caid %04X and mask %04X",
177 __FUNCTION__, pmt->ca[i].id, i, pmt->caids, caid, mask);
178 return 1;
179 }
180 return 0;
181 }
182
close_pmt_for_ca(int i,adapter * ad,SPMT * pmt)183 void close_pmt_for_ca(int i, adapter *ad, SPMT *pmt) {
184 uint64_t mask = 1ULL << i;
185 if (!ad)
186 ad = get_adapter(pmt->adapter);
187 if (!ad)
188 return;
189 if (ca[i].enabled && (ad->ca_mask & mask) && (pmt->ca_mask & mask)) {
190 LOGM("Closing pmt %d for ca %d and adapter %d", pmt->id, i, ad->id);
191 if (ad && ca[i].op->ca_del_pmt)
192 ca[i].op->ca_del_pmt(ad, pmt);
193 pmt->ca_mask &= ~mask;
194 }
195 }
196
close_pmt_for_cas(adapter * ad,SPMT * pmt)197 int close_pmt_for_cas(adapter *ad, SPMT *pmt) {
198 int i;
199 if (!pmt || !pmt->ca_mask)
200 return 0;
201
202 if (!ad)
203 return 0;
204
205 LOGM("Closing pmt %d for adapter %d", pmt->id, ad->id);
206 for (i = 0; i < nca; i++)
207 if (ca[i].enabled)
208 close_pmt_for_ca(i, ad, pmt);
209 return 0;
210 }
211
disable_pmt_for_ca(int i,SPMT * pmt)212 void disable_pmt_for_ca(int i, SPMT *pmt) {
213 uint64_t mask = 1ULL << i;
214 if (i >= MAX_CA || i < 0)
215 return;
216 if (ca[i].enabled) {
217 close_pmt_for_ca(i, NULL, pmt);
218 pmt->disabled_ca_mask |= mask;
219 }
220 }
221
send_pmt_to_ca(int i,adapter * ad,SPMT * pmt)222 int send_pmt_to_ca(int i, adapter *ad, SPMT *pmt) {
223 uint64_t mask;
224 int rv = 0, result = 0;
225 mask = 1ULL << i;
226
227 if (ca[i].enabled && (ad->ca_mask & mask) && ca[i].op->ca_add_pmt &&
228 !(pmt->disabled_ca_mask & mask) && !(pmt->ca_mask & mask)) {
229 int j, send = 0;
230 for (j = 0; j < ca[i].ad_info[ad->id].caids; j++)
231 if (match_caid(pmt, ca[i].ad_info[ad->id].caid[j],
232 ca[i].ad_info[ad->id].mask[j])) {
233 LOG("CAID %04X and mask %04X matched PMT %d",
234 ca[i].ad_info[ad->id].caid[j],
235 ca[i].ad_info[ad->id].mask[j], pmt->id);
236 send = 1;
237 break;
238 }
239 result = TABLES_RESULT_ERROR_NORETRY;
240 if (send || ca[i].ad_info[ad->id].caids == 0) {
241 result = ca[i].op->ca_add_pmt(ad, pmt);
242 }
243
244 if (result == TABLES_RESULT_OK) {
245 pmt->ca_mask |= mask;
246 } else if (result == TABLES_RESULT_ERROR_NORETRY)
247 pmt->disabled_ca_mask |= mask;
248 disable_cw(pmt->id);
249 rv += (1 - result);
250 LOGM("In processing PMT %d, ca %d, CA matched %d, ca_pmt_add "
251 "returned %d, new ca_mask %d new disabled_ca_mask %d",
252 pmt->id, i, send, result, pmt->ca_mask, pmt->disabled_ca_mask);
253 }
254 return rv;
255 }
256
send_pmt_to_cas(adapter * ad,SPMT * pmt)257 int send_pmt_to_cas(adapter *ad, SPMT *pmt) {
258 int i, rv = 1;
259 if (!ad || (ad->ca_mask == (pmt->disabled_ca_mask | pmt->ca_mask))) {
260 LOGM("PMT %d does not require to be sent to any CA: ad_ca_mask %X, "
261 "pmt_ca_mask %X, disabled_ca_mask %X",
262 pmt->id, ad ? ad->ca_mask : -2, pmt->ca_mask,
263 pmt->disabled_ca_mask);
264 return 0;
265 }
266
267 LOG("Sending PMT %d to all CAs: ad_ca_mask %X, "
268 "pmt_ca_mask %X, disabled_ca_mask %X",
269 pmt->id, ad ? ad->ca_mask : -2, pmt->ca_mask, pmt->disabled_ca_mask);
270 for (i = 0; i < nca; i++)
271 if (ca[i].enabled)
272 rv += send_pmt_to_ca(i, ad, pmt);
273 if (pmt->state == PMT_STARTING)
274 pmt->state = PMT_RUNNING;
275 return rv;
276 }
277
send_pmt_to_ca_for_device(SCA * c,adapter * ad)278 void send_pmt_to_ca_for_device(SCA *c, adapter *ad) {
279 SPMT *pmt;
280 int i;
281 for (i = 0; i < npmts; i++)
282 if ((pmt = get_pmt(i)) && pmt->adapter == ad->id && pmt->state)
283 send_pmt_to_ca(c->id, ad, pmt);
284 }
285
tables_update_encrypted_status(adapter * ad,SPMT * pmt)286 void tables_update_encrypted_status(adapter *ad, SPMT *pmt) {
287 int i;
288 int status = pmt->encrypted;
289 if (!ad)
290 return;
291 LOGM("Updating status %d for pmt %d, ad mask %08X, pmt mask %08X", status,
292 pmt->id, ad->ca_mask, pmt->ca_mask);
293 for (i = 0; i < nca; i++)
294 if (ca[i].enabled && (ad->ca_mask & (1ULL << i)) &&
295 (pmt->ca_mask & (1ULL << i))) {
296 LOGM("Updating status %d pmt %d for ca %d and adapter %d", status,
297 pmt->id, i, ad->id);
298 if (status == TABLES_CHANNEL_ENCRYPTED && ca[i].op->ca_encrypted)
299 ca[i].op->ca_encrypted(ad, pmt);
300 else if (status == TABLES_CHANNEL_DECRYPTED &&
301 ca[i].op->ca_decrypted)
302 ca[i].op->ca_decrypted(ad, pmt);
303 }
304 }
305
tables_add_pid(adapter * ad,SPMT * pmt,int pid)306 void tables_add_pid(adapter *ad, SPMT *pmt, int pid) {
307 uint64_t i, mask;
308 for (i = 0; i < nca; i++) {
309 mask = 1ULL << i;
310 if (ca[i].enabled && (pmt->ca_mask & mask) && ca[i].op->ca_add_pid)
311 ca[i].op->ca_add_pid(ad, pmt, pid);
312 }
313 }
314
tables_del_pid(adapter * ad,SPMT * pmt,int pid)315 void tables_del_pid(adapter *ad, SPMT *pmt, int pid) {
316 uint64_t mask, i;
317 for (i = 0; i < nca; i++) {
318 mask = 1ULL << i;
319 if (ca[i].enabled && (pmt->ca_mask & mask) && ca[i].op->ca_del_pid)
320 ca[i].op->ca_del_pid(ad, pmt, pid);
321 }
322 }
323
register_ca_for_adapter(int i,int aid)324 int register_ca_for_adapter(int i, int aid) {
325 adapter *ad = get_adapter(aid);
326 uint64_t mask, rv;
327 if (i < 0 || i >= nca)
328 return 1;
329 if (!ad)
330 return 1;
331
332 mask = (1ULL << ad->id);
333 if ((ca[i].adapter_mask & mask) == 0) {
334 ca[i].adapter_mask |= mask;
335 rv = tables_init_ca_for_device(i, ad);
336 if (rv)
337 send_pmt_to_ca_for_device(&ca[i], ad);
338 return 0;
339 }
340 return 2;
341 }
342
unregister_ca_for_adapter(int i,int aid)343 int unregister_ca_for_adapter(int i, int aid) {
344 adapter *ad = get_adapter(aid);
345 uint64_t mask;
346 if (i < 0 || i >= nca)
347 return 1;
348 if (!ad)
349 return 1;
350
351 mask = (1ULL << ad->id);
352 ca[i].adapter_mask &= ~mask;
353 mask = (1ULL << i);
354 if (ad->ca_mask & mask) {
355 if (ca[i].op->ca_close_dev)
356 ca[i].op->ca_close_dev(ad);
357 ad->ca_mask &= ~mask;
358 LOG("Unregistering CA %d for adapter %d", i, ad->id);
359 }
360 return 0;
361 }
362
tables_init_device(adapter * ad)363 int tables_init_device(adapter *ad) {
364 int i;
365 int rv = 0;
366 for (i = 0; i < nca; i++)
367 if (ca[i].enabled)
368 rv += tables_init_ca_for_device(i, ad);
369 return rv;
370 }
371
init_ca_device(SCA * c)372 void init_ca_device(SCA *c) {
373 uint64_t init_cm;
374 int i;
375 adapter *ad;
376 if (!c->op->ca_add_pmt)
377 return;
378
379 for (i = 0; i < MAX_ADAPTERS; i++)
380 if ((ad = get_adapter_nw(i))) {
381 init_cm = ad->ca_mask;
382 // tables_init_device(ad);
383 tables_init_ca_for_device(c->id, ad);
384 if (init_cm != ad->ca_mask) {
385 send_pmt_to_ca_for_device(c, ad);
386 }
387 }
388 }
389
tables_close_device(adapter * ad)390 int tables_close_device(adapter *ad) {
391 uint64_t i, mask = 1;
392 int rv = 0;
393
394 for (i = 0; i < nca; i++) {
395 if (ca[i].enabled && (ad->ca_mask & mask) && ca[i].op->ca_close_dev) {
396 ca[i].op->ca_close_dev(ad);
397 }
398 }
399
400 ad->ca_mask = 0;
401 return rv;
402 }
403
tables_init()404 int tables_init() {
405 mutex_init(&ca_mutex);
406 #ifndef DISABLE_DVBCA
407 dvbca_init();
408 #endif
409 #ifndef DISABLE_DVBAPI
410 init_dvbapi();
411 #endif
412 return 0;
413 }
414
tables_destroy()415 int tables_destroy() {
416 int i;
417 for (i = 0; i < nca; i++) {
418 if (ca[i].enabled && ca[i].op->ca_close_ca)
419 ca[i].op->ca_close_ca(&ca[i]);
420 }
421 return 0;
422 }
423