1 | #include "globals.h"
|
---|
2 | #if defined MODULE_CAMD35 || defined MODULE_CAMD35_TCP
|
---|
3 |
|
---|
4 | #include "cscrypt/md5.h"
|
---|
5 | #include "module-cacheex.h"
|
---|
6 | #include "oscam-aes.h"
|
---|
7 | #include "oscam-chk.h"
|
---|
8 | #include "oscam-client.h"
|
---|
9 | #include "oscam-ecm.h"
|
---|
10 | #include "oscam-emm.h"
|
---|
11 | #include "oscam-net.h"
|
---|
12 | #include "oscam-string.h"
|
---|
13 | #include "oscam-reader.h"
|
---|
14 |
|
---|
15 | //CMD00 - ECM (request)
|
---|
16 | //CMD01 - ECM (response)
|
---|
17 | //CMD02 - EMM (in clientmode - set EMM, in server mode - EMM data) - obsolete
|
---|
18 | //CMD03 - ECM (cascading request)
|
---|
19 | //CMD04 - ECM (cascading response)
|
---|
20 | //CMD05 - EMM (emm request) send cardata/cardinfo to client
|
---|
21 | //CMD06 - EMM (incomming EMM in server mode)
|
---|
22 | //CMD19 - EMM (incomming EMM in server mode) only seen with caid 0x1830
|
---|
23 | //CMD08 - Stop sending requests to the server for current srvid,prvid,caid
|
---|
24 | //CMD44 - MPCS/OScam internal error notification
|
---|
25 |
|
---|
26 | //CMD0x3d - CACHEEX Cache-push id request
|
---|
27 | //CMD0x3e - CACHEEX Cache-push id answer
|
---|
28 | //CMD0x3f - CACHEEX cache-push
|
---|
29 |
|
---|
30 | //used variable ncd_skey for storing remote node id: ncd_skey[0..7] : 8
|
---|
31 | //bytes node id ncd_skey[8] : 1=valid node id ncd_skey[9] : 1=remote node id
|
---|
32 | //already requested ncd_skey[10] : counter to check for ip changes, >30 do
|
---|
33 | //dns resolve ncd_skey[11] : renew remote node every 256 cache pushs
|
---|
34 |
|
---|
35 | #define REQ_SIZE 584 // 512 + 20 + 0x34
|
---|
36 |
|
---|
37 | static int32_t camd35_send(struct s_client *cl, uchar *buf, int32_t buflen)
|
---|
38 | {
|
---|
39 | int32_t l;
|
---|
40 | unsigned char rbuf[REQ_SIZE+15+4], *sbuf = rbuf + 4;
|
---|
41 |
|
---|
42 | if (!cl->udp_fd || !cl->crypted) return(-1); //exit if no fd or aes key not set!
|
---|
43 |
|
---|
44 | //Fix ECM len > 255
|
---|
45 | if (buflen <= 0)
|
---|
46 | buflen = ((buf[0] == 0)? (((buf[21]&0x0f)<< 8) | buf[22])+3 : buf[1]);
|
---|
47 | l = 20 + (((buf[0] == 3) || (buf[0] == 4)) ? 0x34 : 0) + buflen;
|
---|
48 | memcpy(rbuf, cl->ucrc, 4);
|
---|
49 | memcpy(sbuf, buf, l);
|
---|
50 | memset(sbuf + l, 0xff, 15); // set unused space to 0xff for newer camd3's
|
---|
51 | i2b_buf(4, crc32(0L, sbuf+20, buflen), sbuf + 4);
|
---|
52 | l = boundary(4, l);
|
---|
53 | cs_ddump_mask(cl->typ == 'c'?D_CLIENT:D_READER, sbuf, l, "send %d bytes to %s", l, username(cl));
|
---|
54 | aes_encrypt_idx(cl, sbuf, l);
|
---|
55 |
|
---|
56 | int32_t status;
|
---|
57 | if (cl->is_udp) {
|
---|
58 | status = sendto(cl->udp_fd, rbuf, l+4, 0, (struct sockaddr *)&cl->udp_sa, cl->udp_sa_len);
|
---|
59 | if (status == -1) set_null_ip(&SIN_GET_ADDR(cl->udp_sa));
|
---|
60 | } else {
|
---|
61 | status = send(cl->udp_fd, rbuf, l + 4, 0);
|
---|
62 |
|
---|
63 | if (cl->typ == 'p' && cl->reader) {
|
---|
64 | if (status == -1) network_tcp_connection_close(cl->reader, "can't send");
|
---|
65 | } else if (cl->typ=='c') {
|
---|
66 | if (status == -1) cs_disconnect_client(cl);
|
---|
67 | }
|
---|
68 | }
|
---|
69 | if (status != -1){
|
---|
70 | if(cl->reader){
|
---|
71 | cl->reader->last_s = time((time_t *) 0);
|
---|
72 | }
|
---|
73 | cl->last = time((time_t *) 0);
|
---|
74 | }
|
---|
75 | return status;
|
---|
76 | }
|
---|
77 |
|
---|
78 | static int32_t camd35_auth_client(struct s_client *cl, uchar *ucrc)
|
---|
79 | {
|
---|
80 | int32_t rc=1;
|
---|
81 | uint32_t crc;
|
---|
82 | struct s_auth *account;
|
---|
83 | unsigned char md5tmp[MD5_DIGEST_LENGTH];
|
---|
84 |
|
---|
85 | if (cl->upwd[0])
|
---|
86 | return(memcmp(cl->ucrc, ucrc, 4) ? 1 : 0);
|
---|
87 | cl->crypted=1;
|
---|
88 | crc=(((ucrc[0]<<24) | (ucrc[1]<<16) | (ucrc[2]<<8) | ucrc[3]) & 0xffffffffL);
|
---|
89 | for (account=cfg.account; (account) && (!cl->upwd[0]); account=account->next)
|
---|
90 | if (crc==crc32(0L, MD5((unsigned char *)account->usr, strlen(account->usr), md5tmp), MD5_DIGEST_LENGTH))
|
---|
91 | {
|
---|
92 | rc=cs_auth_client(cl, account, NULL);
|
---|
93 | if (!rc) {
|
---|
94 | memcpy(cl->ucrc, ucrc, 4);
|
---|
95 | cs_strncpy((char *)cl->upwd, account->pwd, sizeof(cl->upwd));
|
---|
96 | aes_set_key(cl, (char *) MD5(cl->upwd, strlen((char *)cl->upwd), md5tmp));
|
---|
97 | return 0;
|
---|
98 | }
|
---|
99 | }
|
---|
100 | return(rc);
|
---|
101 | }
|
---|
102 |
|
---|
103 | static int32_t camd35_recv(struct s_client *client, uchar *buf, int32_t l)
|
---|
104 | {
|
---|
105 | int32_t rc, s, rs, n=0, buflen=0, len=0;
|
---|
106 | for (rc=rs=s=0; !rc; s++) {
|
---|
107 | switch(s) {
|
---|
108 | case 0:
|
---|
109 | if (!client->udp_fd) return(-9);
|
---|
110 | if (client->is_udp && client->typ == 'c') {
|
---|
111 | rs=recv_from_udpipe(buf);
|
---|
112 | } else {
|
---|
113 | //read minimum packet size (4 byte ucrc + 32 byte data) to detect packet size (tcp only)
|
---|
114 | rs = recv(client->udp_fd, buf, client->is_udp ? l : 36, 0);
|
---|
115 | }
|
---|
116 | if (rs < 24) rc = -1;
|
---|
117 | break;
|
---|
118 | case 1:
|
---|
119 | switch (camd35_auth_client(client, buf)) {
|
---|
120 | case 0: break; // ok
|
---|
121 | case 1: rc=-2; break; // unknown user
|
---|
122 | default: rc=-9; break; // error's from cs_auth()
|
---|
123 | }
|
---|
124 | memmove(buf, buf+4, rs-=4);
|
---|
125 | break;
|
---|
126 | case 2:
|
---|
127 | aes_decrypt(client, buf, rs);
|
---|
128 | if (rs!=boundary(4, rs))
|
---|
129 | cs_debug_mask(client->typ == 'c'?D_CLIENT:D_READER,
|
---|
130 | "WARNING: packet size has wrong decryption boundary");
|
---|
131 |
|
---|
132 | n=(buf[0]==3) ? 0x34 : 0;
|
---|
133 |
|
---|
134 | //Fix for ECM request size > 255 (use ecm length field)
|
---|
135 | if(buf[0]==0)
|
---|
136 | buflen = (((buf[21]&0x0f)<< 8) | buf[22])+3;
|
---|
137 | else if (buf[0] == 0x3d || buf[0] == 0x3e || buf[0] == 0x3f) //cacheex-push
|
---|
138 | buflen = buf[1] | (buf[2] << 8);
|
---|
139 | else
|
---|
140 | buflen = buf[1];
|
---|
141 |
|
---|
142 | n = boundary(4, n+20+buflen);
|
---|
143 | if (!(client->is_udp && client->typ == 'c') && (rs < n) && ((n-32) > 0)) {
|
---|
144 | len = recv(client->udp_fd, buf+32, n-32, 0); // read the rest of the packet
|
---|
145 | if (len>0) {
|
---|
146 | rs+=len;
|
---|
147 | aes_decrypt(client, buf+32, len);
|
---|
148 | }
|
---|
149 | }
|
---|
150 |
|
---|
151 | cs_ddump_mask(client->typ == 'c'?D_CLIENT:D_READER,
|
---|
152 | buf, rs, "received %d bytes from %s", rs, remote_txt());
|
---|
153 |
|
---|
154 | if (n<rs)
|
---|
155 | cs_debug_mask(client->typ == 'c'?D_CLIENT:D_READER,
|
---|
156 | "ignoring %d bytes of garbage", rs-n);
|
---|
157 | else
|
---|
158 | if (n>rs) rc=-3;
|
---|
159 | break;
|
---|
160 | case 3:
|
---|
161 | if (crc32(0L, buf+20, buflen)!=b2i(4, buf+4)) rc=-4;
|
---|
162 | if (!rc) rc=n;
|
---|
163 | break;
|
---|
164 | }
|
---|
165 | }
|
---|
166 |
|
---|
167 | if ((rs>0) && ((rc==-1)||(rc==-2))) {
|
---|
168 | cs_ddump_mask(client->typ == 'c'?D_CLIENT:D_READER, buf, rs,
|
---|
169 | "received %d bytes from %s (native)", rs, remote_txt());
|
---|
170 | }
|
---|
171 | if(rc>=0) client->last = time((time_t *) 0); // last client action is now
|
---|
172 | switch(rc) {
|
---|
173 | //case 0: break;
|
---|
174 | case -1: cs_log("packet is too small (received %d bytes, expected %d bytes)", rs, l); break;
|
---|
175 | case -2:
|
---|
176 | if (cs_auth_client(client, 0, "unknown user"))
|
---|
177 | cs_disconnect_client(client);
|
---|
178 | break;
|
---|
179 | case -3: cs_log("incomplete request !"); break;
|
---|
180 | case -4: cs_log("checksum error (wrong password ?)"); break;
|
---|
181 | //default: cs_debug_mask(D_TRACE, "camd35_recv returns rc=%d", rc); break;
|
---|
182 | }
|
---|
183 |
|
---|
184 | return(rc);
|
---|
185 | }
|
---|
186 |
|
---|
187 | /*
|
---|
188 | * server functions
|
---|
189 | */
|
---|
190 |
|
---|
191 | static void camd35_request_emm(ECM_REQUEST *er)
|
---|
192 | {
|
---|
193 | int32_t i;
|
---|
194 | time_t now;
|
---|
195 | uchar mbuf[1024];
|
---|
196 | struct s_client *cl = cur_client();
|
---|
197 | struct s_reader *aureader = NULL, *rdr = NULL;
|
---|
198 |
|
---|
199 | if (er->selected_reader && !er->selected_reader->audisabled && ll_contains(cl->aureader_list, er->selected_reader))
|
---|
200 | aureader = er->selected_reader;
|
---|
201 |
|
---|
202 | if (!aureader && cl->aureader_list) {
|
---|
203 | LL_ITER itr = ll_iter_create(cl->aureader_list);
|
---|
204 | while ((rdr = ll_iter_next(&itr))) {
|
---|
205 | if (emm_reader_match(rdr, er->caid, er->prid)) {
|
---|
206 | aureader=rdr;
|
---|
207 | break;
|
---|
208 | }
|
---|
209 | }
|
---|
210 | }
|
---|
211 |
|
---|
212 | if (!aureader)
|
---|
213 | return; // TODO
|
---|
214 |
|
---|
215 | uint16_t au_caid = aureader->caid;
|
---|
216 |
|
---|
217 | // Bulcrypt has 2 caids and aureader->caid can't be used.
|
---|
218 | // Use 5581 for AU.
|
---|
219 | if (!au_caid && (er->caid == 0x5581 || er->caid == 0x4aee))
|
---|
220 | au_caid = 0x5581;
|
---|
221 |
|
---|
222 | time(&now);
|
---|
223 | if (!memcmp(cl->lastserial, aureader->hexserial, 8))
|
---|
224 | if (abs(now-cl->last) < 180) return;
|
---|
225 |
|
---|
226 | memcpy(cl->lastserial, aureader->hexserial, 8);
|
---|
227 | cl->last = now;
|
---|
228 |
|
---|
229 | if (au_caid)
|
---|
230 | {
|
---|
231 | cl->disable_counter = 0;
|
---|
232 | cs_log("%s emm-request sent (reader=%s, caid=%04X, auprovid=%06X)",
|
---|
233 | username(cur_client()), aureader->label, aureader->caid,
|
---|
234 | aureader->auprovid ? aureader->auprovid : b2i(4, aureader->prid[0]));
|
---|
235 | }
|
---|
236 | else
|
---|
237 | if (cl->disable_counter > 2)
|
---|
238 | return;
|
---|
239 | else
|
---|
240 | cl->disable_counter++;
|
---|
241 |
|
---|
242 | memset(mbuf, 0, sizeof(mbuf));
|
---|
243 | mbuf[2] = mbuf[3] = 0xff; // must not be zero
|
---|
244 | i2b_buf(2, er->srvid, mbuf + 8);
|
---|
245 |
|
---|
246 | //override request provid with auprovid if set in CMD05
|
---|
247 | if(aureader->auprovid) {
|
---|
248 | if(aureader->auprovid != er->prid)
|
---|
249 | i2b_buf(4, aureader->auprovid, mbuf + 12);
|
---|
250 | else
|
---|
251 | i2b_buf(4, er->prid, mbuf + 12);
|
---|
252 | } else {
|
---|
253 | i2b_buf(4, er->prid, mbuf + 12);
|
---|
254 | }
|
---|
255 |
|
---|
256 | i2b_buf(2, er->pid, mbuf + 16);
|
---|
257 | mbuf[0] = 5;
|
---|
258 | mbuf[1] = 111;
|
---|
259 | if (au_caid)
|
---|
260 | {
|
---|
261 | mbuf[39] = 1; // no. caids
|
---|
262 | mbuf[20] = au_caid >> 8; // caid's (max 8)
|
---|
263 | mbuf[21] = au_caid & 0xff;
|
---|
264 | if (au_caid == 0x5581) {
|
---|
265 | // Bulcrypt have two CAIDs, add the second one
|
---|
266 | mbuf[39]++;
|
---|
267 | mbuf[22] = 0x4aee >> 8;
|
---|
268 | mbuf[23] = 0x4aee & 0xff;
|
---|
269 | }
|
---|
270 | memcpy(mbuf + 40, aureader->hexserial, 6); // serial now 6 bytes
|
---|
271 | mbuf[47] = aureader->nprov;
|
---|
272 | for (i = 0; i < aureader->nprov; i++)
|
---|
273 | {
|
---|
274 | if ((au_caid >= 0x1700 && au_caid <= 0x1799) || // Betacrypt
|
---|
275 | (au_caid >= 0x0600 && au_caid <= 0x0699)) // Irdeto (don't know if this is correct, cause I don't own a IRDETO-Card)
|
---|
276 | {
|
---|
277 | mbuf[48 + (i*5)] = aureader->prid[i][0];
|
---|
278 | memcpy(&mbuf[50 + (i*5)], &aureader->prid[i][1], 3);
|
---|
279 | }
|
---|
280 | else
|
---|
281 | {
|
---|
282 | mbuf[48 + (i * 5)] = aureader->prid[i][2];
|
---|
283 | mbuf[49 + (i * 5)] =aureader->prid[i][3];
|
---|
284 | memcpy(&mbuf[50 + (i * 5)], &aureader->sa[i][0],4); // for conax we need at least 4 Bytes
|
---|
285 | }
|
---|
286 | }
|
---|
287 | //we think client/server protocols should deliver all information, and only readers should discard EMM
|
---|
288 | mbuf[128] = (aureader->blockemm & EMM_GLOBAL) ? 0: 1;
|
---|
289 | mbuf[129] = (aureader->blockemm & EMM_SHARED) ? 0: 1;
|
---|
290 | mbuf[130] = (aureader->blockemm & EMM_UNIQUE) ? 0: 1;
|
---|
291 | //mbuf[131] = aureader->card_system; //Cardsystem for Oscam client
|
---|
292 | }
|
---|
293 | else // disable emm
|
---|
294 | mbuf[20] = mbuf[39] = mbuf[40] = mbuf[47] = mbuf[49] = 1;
|
---|
295 |
|
---|
296 | memcpy(mbuf + 10, mbuf + 20, 2);
|
---|
297 | camd35_send(cl, mbuf, 0); // send with data-len 111 for camd3 > 3.890
|
---|
298 | mbuf[1]++;
|
---|
299 | camd35_send(cl, mbuf, 0); // send with data-len 112 for camd3 < 3.890
|
---|
300 | }
|
---|
301 |
|
---|
302 | static void camd35_send_dcw(struct s_client *client, ECM_REQUEST *er)
|
---|
303 | {
|
---|
304 | uchar *buf;
|
---|
305 | buf = er->src_data; // get orig request
|
---|
306 |
|
---|
307 | if (!buf) {
|
---|
308 | cs_log("camd35: src_data missing.");
|
---|
309 | return;
|
---|
310 | }
|
---|
311 |
|
---|
312 | if (((er->rcEx > 0) || (er->rc == E_INVALID)) && !client->c35_suppresscmd08)
|
---|
313 | {
|
---|
314 | buf[0] = 0x08;
|
---|
315 | buf[1] = 2;
|
---|
316 | memset(buf + 20, 0, buf[1]);
|
---|
317 | buf[22] = er->rc; //put rc in byte 22 - hopefully don't break legacy camd3
|
---|
318 | }
|
---|
319 | else if (er->rc == E_STOPPED)
|
---|
320 | {
|
---|
321 | buf[0] = 0x08;
|
---|
322 | buf[1] = 2;
|
---|
323 | buf[20] = 0;
|
---|
324 | /*
|
---|
325 | * the second Databyte should be forseen for a sleeptime in minutes
|
---|
326 | * whoever knows the camd3 protocol related to CMD08 - please help!
|
---|
327 | * on tests this don't work with native camd3
|
---|
328 | */
|
---|
329 | buf[21] = client->c35_sleepsend;
|
---|
330 | cs_log("%s stop request send", client->account->usr);
|
---|
331 | }
|
---|
332 | else
|
---|
333 | {
|
---|
334 | // Send CW
|
---|
335 | if ((er->rc < E_NOTFOUND) || (er->rc == E_FAKE))
|
---|
336 | {
|
---|
337 | if (buf[0]==3)
|
---|
338 | memmove(buf + 20 + 16, buf + 20 + buf[1], 0x34);
|
---|
339 | buf[0]++;
|
---|
340 | buf[1] = 16;
|
---|
341 | memcpy(buf+20, er->cw, buf[1]);
|
---|
342 | }
|
---|
343 | else
|
---|
344 | {
|
---|
345 | // Send old CMD44 to prevent cascading problems with older mpcs/oscam versions
|
---|
346 | buf[0] = 0x44;
|
---|
347 | buf[1] = 0;
|
---|
348 | }
|
---|
349 | }
|
---|
350 | camd35_send(client, buf, 0);
|
---|
351 | camd35_request_emm(er);
|
---|
352 |
|
---|
353 | if (er->src_data) {
|
---|
354 | free(er->src_data);
|
---|
355 | er->src_data = NULL;
|
---|
356 | }
|
---|
357 | }
|
---|
358 |
|
---|
359 | static void camd35_process_ecm(uchar *buf)
|
---|
360 | {
|
---|
361 | ECM_REQUEST *er;
|
---|
362 | if (!(er = get_ecmtask()))
|
---|
363 | return;
|
---|
364 | // er->l = buf[1];
|
---|
365 | //fix ECM LEN issue
|
---|
366 | er->ecmlen =(((buf[21]&0x0f)<< 8) | buf[22])+3;
|
---|
367 | if (!cs_malloc(&er->src_data, 0x34 + 20 + er->ecmlen))
|
---|
368 | return;
|
---|
369 | memcpy(er->src_data, buf, 0x34 + 20 + er->ecmlen); // save request
|
---|
370 | er->srvid = b2i(2, buf+ 8);
|
---|
371 | er->caid = b2i(2, buf+10);
|
---|
372 | er->prid = b2i(4, buf+12);
|
---|
373 | //er->pid = b2i(2, buf+16); value is ecmtask idx see camd35_recv_chk 941
|
---|
374 | memcpy(er->ecm, buf + 20, er->ecmlen);
|
---|
375 | get_cw(cur_client(), er);
|
---|
376 | }
|
---|
377 |
|
---|
378 | static void camd35_process_emm(uchar *buf)
|
---|
379 | {
|
---|
380 | EMM_PACKET epg;
|
---|
381 | memset(&epg, 0, sizeof(epg));
|
---|
382 | epg.emmlen = buf[1];
|
---|
383 | memcpy(epg.caid, buf + 10, 2);
|
---|
384 | memcpy(epg.provid, buf + 12 , 4);
|
---|
385 | memcpy(epg.emm, buf + 20, epg.emmlen);
|
---|
386 | do_emm(cur_client(), &epg);
|
---|
387 | }
|
---|
388 |
|
---|
389 | static int32_t tcp_connect(struct s_client *cl)
|
---|
390 | {
|
---|
391 | if (cl->is_udp) { // check for udp client
|
---|
392 | if (!IP_ISSET(SIN_GET_ADDR(cl->udp_sa)) || cl->reader->last_s-cl->reader->last_g > cl->reader->tcp_rto) // check ip or if client reached timeout
|
---|
393 | if (!hostResolve(cl->reader)) return 0; // could not resolve client
|
---|
394 | }
|
---|
395 |
|
---|
396 | if (!cl->reader->tcp_connected) { // client not connected
|
---|
397 | int32_t handle=0;
|
---|
398 | handle = network_tcp_connection_open(cl->reader); // try to connect
|
---|
399 | if (handle<0) { // got no handle -> error!
|
---|
400 | cl->reader->last_s = 0; // set last send to zero
|
---|
401 | cl->reader->last_g = 0; // set last receive to zero
|
---|
402 | cl->last = 0; // set last client action to zero
|
---|
403 | return(0);
|
---|
404 | }
|
---|
405 |
|
---|
406 | cl->reader->tcp_connected = 1;
|
---|
407 | cl->reader->card_status = CARD_INSERTED;
|
---|
408 | cl->reader->last_s = time(NULL); // reset last send
|
---|
409 | cl->reader->last_g = time(NULL); // reset last receive
|
---|
410 | cl->last = time(NULL); // reset last client action
|
---|
411 | cl->pfd = cl->udp_fd = handle;
|
---|
412 | }
|
---|
413 | if (!cl->udp_fd) return(0); // Check if client has no handle -> error
|
---|
414 | if (cl->reader->last_s-cl->reader->last_g > cl->reader->tcp_rto) { // check if client reached timeout, if so disconnect client
|
---|
415 | //cs_log("last_s:%d, last_g:%d, tcp_rto:%d, diff:%d",(int)cl->reader->last_s,(int)cl->reader->last_g,(int)cl->reader->tcp_rto,
|
---|
416 | // (int)(cl->reader->last_s - cl->reader->last_g));
|
---|
417 | network_tcp_connection_close(cl->reader, "rto");
|
---|
418 | return 0;
|
---|
419 | }
|
---|
420 |
|
---|
421 | return(1); // all ok
|
---|
422 | }
|
---|
423 |
|
---|
424 | /*
|
---|
425 | * client functions
|
---|
426 | */
|
---|
427 | int32_t camd35_client_init(struct s_client *cl)
|
---|
428 | {
|
---|
429 |
|
---|
430 | unsigned char md5tmp[MD5_DIGEST_LENGTH];
|
---|
431 | cs_strncpy((char *)cl->upwd, cl->reader->r_pwd, sizeof(cl->upwd));
|
---|
432 | i2b_buf(4, crc32(0L, MD5((unsigned char *)cl->reader->r_usr, strlen(cl->reader->r_usr), md5tmp), 16), cl->ucrc);
|
---|
433 | aes_set_key(cl, (char *)MD5(cl->upwd, strlen((char *)cl->upwd), md5tmp));
|
---|
434 | cl->crypted=1;
|
---|
435 |
|
---|
436 | cs_log("camd35 proxy %s:%d", cl->reader->device, cl->reader->r_port);
|
---|
437 |
|
---|
438 | return(0);
|
---|
439 | }
|
---|
440 |
|
---|
441 | #ifdef CS_CACHEEX
|
---|
442 | uint8_t camd35_node_id[8];
|
---|
443 |
|
---|
444 | /**
|
---|
445 | * send own id
|
---|
446 | */
|
---|
447 | void camd35_cache_push_send_own_id(struct s_client *cl, uint8_t *mbuf) {
|
---|
448 | uint8_t rbuf[32]; //minimal size
|
---|
449 |
|
---|
450 | if (!cl->crypted) return;
|
---|
451 |
|
---|
452 | cs_debug_mask(D_CACHEEX, "cacheex: received id request from node %" PRIu64 "X %s", cacheex_node_id(mbuf+20), username(cl));
|
---|
453 |
|
---|
454 | memset(rbuf, 0, sizeof(rbuf));
|
---|
455 | rbuf[0] = 0x3e;
|
---|
456 | rbuf[1] = 12;
|
---|
457 | rbuf[2] = 0;
|
---|
458 | memcpy(rbuf+20, camd35_node_id, 8);
|
---|
459 | cs_debug_mask(D_CACHEEX, "cacheex: sending own id %" PRIu64 "X request %s", cacheex_node_id(camd35_node_id), username(cl));
|
---|
460 | camd35_send(cl, rbuf, 12); //send adds +20
|
---|
461 | }
|
---|
462 |
|
---|
463 | /**
|
---|
464 | * request remote id
|
---|
465 | */
|
---|
466 | void camd35_cache_push_request_remote_id(struct s_client *cl) {
|
---|
467 | uint8_t rbuf[32];//minimal size
|
---|
468 |
|
---|
469 | memset(rbuf, 0, sizeof(rbuf));
|
---|
470 | rbuf[0] = 0x3d;
|
---|
471 | rbuf[1] = 12;
|
---|
472 | rbuf[2] = 0;
|
---|
473 | memcpy(rbuf+20, camd35_node_id, 8);
|
---|
474 | cs_debug_mask(D_CACHEEX, "cacheex: sending id request to %s", username(cl));
|
---|
475 | camd35_send(cl, rbuf, 12); //send adds +20
|
---|
476 | }
|
---|
477 |
|
---|
478 | /**
|
---|
479 | * store received remote id
|
---|
480 | */
|
---|
481 | void camd35_cache_push_receive_remote_id(struct s_client *cl, uint8_t *buf) {
|
---|
482 |
|
---|
483 | memcpy(cl->ncd_skey, buf+20, 8);
|
---|
484 | cl->ncd_skey[8] = 1;
|
---|
485 | cs_debug_mask(D_CACHEEX, "cacheex: received id answer from %s: %" PRIu64 "X", username(cl), cacheex_node_id(cl->ncd_skey));
|
---|
486 | }
|
---|
487 |
|
---|
488 |
|
---|
489 | int32_t camd35_cache_push_chk(struct s_client *cl, ECM_REQUEST *er)
|
---|
490 | {
|
---|
491 | uint8_t oldnode = 0; // used to indicate a previous remote node id was present
|
---|
492 |
|
---|
493 | if (ll_count(er->csp_lastnodes) >= cacheex_maxhop(cl)) { //check max 10 nodes to push:
|
---|
494 | cs_debug_mask(D_CACHEEX, "cacheex: nodelist reached %d nodes, no push", cacheex_maxhop(cl));
|
---|
495 | return 0;
|
---|
496 | }
|
---|
497 |
|
---|
498 | if (cl->reader) {
|
---|
499 | if(!tcp_connect(cl)){
|
---|
500 | cs_debug_mask(D_CACHEEX, "cacheex: not connected %s -> no push", username(cl));
|
---|
501 | return 0;
|
---|
502 | }
|
---|
503 | }
|
---|
504 | //cs_debug_mask(D_CACHEEX, "ncd[8]=%d [9]=%d [10]=%d [11]=%d", cl->ncd_skey[8], cl->ncd_skey[9], cl->ncd_skey[10], cl->ncd_skey[11]);
|
---|
505 |
|
---|
506 | if(cl->reader){ // check for reader connection (if not exists then in servermode!)
|
---|
507 | if(cl->reader->last_s-cl->reader->last_g > cl->reader->tcp_rto-20) // Cache-ex as clientpusher renew remote nodeid before rto kicks in
|
---|
508 | cl->ncd_skey[9] = 0; //reset requestmemory -> inits a remote node id request
|
---|
509 | }
|
---|
510 | else
|
---|
511 | if (cl->ncd_skey[8]==0 || !(++cl->ncd_skey[11])) // tcp: renew remote id every 256 pushes or if no remote nodeid present:
|
---|
512 | cl->ncd_skey[9] = 0; //reset requestmemory -> inits a remote node id request
|
---|
513 |
|
---|
514 | //Update remote id:
|
---|
515 | if (!cl->ncd_skey[9]) {
|
---|
516 | cl->ncd_skey[9] = 1; //remember request
|
---|
517 | camd35_cache_push_request_remote_id(cl);
|
---|
518 | oldnode = cl->ncd_skey[8]; // if we have a previous node store it
|
---|
519 | cl->ncd_skey[8]=0; // reset nodeid
|
---|
520 | }
|
---|
521 | if (!oldnode && !cl->ncd_skey[8]) { // We have no remote node -> no push
|
---|
522 | cs_debug_mask(D_CACHEEX, "cacheex: push without remote node %s - ignored", username(cl));
|
---|
523 | cl->ncd_skey[9] = 0; //reset requestmemory -> inits a remote node id request
|
---|
524 | return 0;
|
---|
525 | }
|
---|
526 |
|
---|
527 | uint8_t *remote_node = cl->ncd_skey;
|
---|
528 |
|
---|
529 | //search existing peer nodes:
|
---|
530 | LL_LOCKITER *li = ll_li_create(er->csp_lastnodes, 0);
|
---|
531 | uint8_t *node;
|
---|
532 | while ((node = ll_li_next(li))) {
|
---|
533 | cs_debug_mask(D_CACHEEX, "cacheex: check node %" PRIu64 "X == %" PRIu64 "X ?", cacheex_node_id(node), cacheex_node_id(remote_node));
|
---|
534 | if (memcmp(node, remote_node, 8) == 0) {
|
---|
535 | break;
|
---|
536 | }
|
---|
537 | }
|
---|
538 | ll_li_destroy(li);
|
---|
539 |
|
---|
540 | //node found, so we got it from there, do not push:
|
---|
541 | if (node) {
|
---|
542 | cs_debug_mask(D_CACHEEX,
|
---|
543 | "cacheex: node %" PRIu64 "X found in list => skip push!", cacheex_node_id(node));
|
---|
544 | return 0;
|
---|
545 | }
|
---|
546 |
|
---|
547 | cs_debug_mask(D_CACHEEX, "cacheex: push ok %" PRIu64 "X to %" PRIu64 "X %s", cacheex_node_id(camd35_node_id), cacheex_node_id(remote_node), username(cl));
|
---|
548 |
|
---|
549 | return 1;
|
---|
550 | }
|
---|
551 | int32_t camd35_cache_push_out(struct s_client *cl, struct ecm_request_t *er)
|
---|
552 | {
|
---|
553 | int8_t rc = (er->rc<E_NOTFOUND)?E_FOUND:er->rc;
|
---|
554 | if (rc != E_FOUND && rc != E_UNHANDLED) return -1; //Maybe later we could support other rcs
|
---|
555 |
|
---|
556 | //E_FOUND : we have the CW,
|
---|
557 | //E_UNHANDLED : incoming ECM request
|
---|
558 |
|
---|
559 | if (cl->reader) {
|
---|
560 | if(!tcp_connect(cl)){
|
---|
561 | cs_debug_mask(D_CACHEEX, "cacheex: not connected %s -> no push", username(cl));
|
---|
562 | return (-1);
|
---|
563 | }
|
---|
564 | }
|
---|
565 |
|
---|
566 | uint32_t size = sizeof(er->ecmd5)+sizeof(er->csp_hash)+sizeof(er->cw)+sizeof(uint8_t) +
|
---|
567 | (ll_count(er->csp_lastnodes)+1)*8;
|
---|
568 | unsigned char *buf;
|
---|
569 | if (!cs_malloc(&buf, size + 20)) //camd35_send() adds +20
|
---|
570 | return -1;
|
---|
571 |
|
---|
572 | buf[0]=0x3f; //New Command: Cache-push
|
---|
573 | buf[1]=size & 0xff;
|
---|
574 | buf[2]=size >> 8;
|
---|
575 | buf[3]=rc;
|
---|
576 |
|
---|
577 | i2b_buf(2, er->srvid, buf + 8);
|
---|
578 | i2b_buf(2, er->caid, buf + 10);
|
---|
579 | i2b_buf(4, er->prid, buf + 12);
|
---|
580 | //i2b_buf(2, er->idx, buf + 16); // Not relevant...?
|
---|
581 |
|
---|
582 | uint8_t *ofs = buf+20;
|
---|
583 |
|
---|
584 | //write oscam ecmd5:
|
---|
585 | memcpy(ofs, er->ecmd5, sizeof(er->ecmd5)); //16
|
---|
586 | ofs += sizeof(er->ecmd5);
|
---|
587 |
|
---|
588 | //write csp hashcode:
|
---|
589 | memcpy(ofs, &er->csp_hash, sizeof(er->csp_hash)); //4
|
---|
590 | ofs += sizeof(er->csp_hash);
|
---|
591 |
|
---|
592 | //write cw:
|
---|
593 | memcpy(ofs, er->cw, sizeof(er->cw)); //16
|
---|
594 | ofs += sizeof(er->cw);
|
---|
595 |
|
---|
596 | //write node count:
|
---|
597 | *ofs = ll_count(er->csp_lastnodes)+1;
|
---|
598 | ofs++;
|
---|
599 |
|
---|
600 | //write own node:
|
---|
601 | memcpy(ofs, camd35_node_id, 8);
|
---|
602 | ofs += 8;
|
---|
603 |
|
---|
604 | //write other nodes:
|
---|
605 | LL_LOCKITER *li = ll_li_create(er->csp_lastnodes, 0);
|
---|
606 | uint8_t *node;
|
---|
607 | while ((node=ll_li_next(li))) {
|
---|
608 | memcpy(ofs, node, 8);
|
---|
609 | ofs+=8;
|
---|
610 | }
|
---|
611 | ll_li_destroy(li);
|
---|
612 |
|
---|
613 | int32_t res = camd35_send(cl, buf, size);
|
---|
614 | free(buf);
|
---|
615 | return res;
|
---|
616 | }
|
---|
617 |
|
---|
618 |
|
---|
619 | void camd35_cache_push_in(struct s_client *cl, uchar *buf)
|
---|
620 | {
|
---|
621 | int8_t rc = buf[3];
|
---|
622 | if (rc != E_FOUND && rc != E_UNHANDLED) //Maybe later we could support other rcs
|
---|
623 | return;
|
---|
624 |
|
---|
625 | ECM_REQUEST *er;
|
---|
626 | uint16_t size = buf[1] | (buf[2] << 8);
|
---|
627 | if (size < sizeof(er->ecmd5) + sizeof(er->csp_hash) + sizeof(er->cw)) {
|
---|
628 | cs_debug_mask(D_CACHEEX, "cacheex: %s received old cash-push format! data ignored!", username(cl));
|
---|
629 | return;
|
---|
630 | }
|
---|
631 |
|
---|
632 | if (!(er = get_ecmtask()))
|
---|
633 | return;
|
---|
634 |
|
---|
635 | er->srvid = b2i(2, buf+ 8);
|
---|
636 | er->caid = b2i(2, buf+10);
|
---|
637 | er->prid = b2i(4, buf+12);
|
---|
638 | er->pid = b2i(2, buf+16);
|
---|
639 | er->rc = rc;
|
---|
640 |
|
---|
641 | er->ecmlen = 0;
|
---|
642 |
|
---|
643 | uint8_t *ofs = buf+20;
|
---|
644 |
|
---|
645 | //Read ecmd5
|
---|
646 | memcpy(er->ecmd5, ofs, sizeof(er->ecmd5)); //16
|
---|
647 | ofs+= sizeof(er->ecmd5);
|
---|
648 |
|
---|
649 | if (!check_cacheex_filter(cl, er))
|
---|
650 | return;
|
---|
651 |
|
---|
652 | //Read csp_hash:
|
---|
653 | memcpy(&er->csp_hash, ofs, sizeof(er->csp_hash)); //4
|
---|
654 | ofs+=sizeof(er->csp_hash);
|
---|
655 |
|
---|
656 | //Read cw:
|
---|
657 | memcpy(er->cw, ofs, sizeof(er->cw)); //16
|
---|
658 | ofs += sizeof(er->cw);
|
---|
659 |
|
---|
660 | //Check auf neues Format:
|
---|
661 | uint8_t *data;
|
---|
662 | if (size > (sizeof(er->ecmd5) + sizeof(er->csp_hash) + sizeof(er->cw))) {
|
---|
663 |
|
---|
664 | //Read lastnodes:
|
---|
665 | uint8_t count = *ofs;
|
---|
666 | ofs++;
|
---|
667 |
|
---|
668 | //check max nodes:
|
---|
669 | if (count > cacheex_maxhop(cl)) {
|
---|
670 | cs_debug_mask(D_CACHEEX, "cacheex: received %d nodes (max=%d), ignored! %s", (int32_t)count, cacheex_maxhop(cl), username(cl));
|
---|
671 | free(er);
|
---|
672 | return;
|
---|
673 | }
|
---|
674 | cs_debug_mask(D_CACHEEX, "cacheex: received %d nodes %s", (int32_t)count, username(cl));
|
---|
675 | er->csp_lastnodes = ll_create("csp_lastnodes");
|
---|
676 | while (count) {
|
---|
677 | if (!cs_malloc(&data, 8))
|
---|
678 | break;
|
---|
679 | memcpy(data, ofs, 8);
|
---|
680 | ofs+=8;
|
---|
681 | ll_append(er->csp_lastnodes, data);
|
---|
682 | count--;
|
---|
683 | cs_debug_mask(D_CACHEEX, "cacheex: received node %" PRIu64 "X %s", cacheex_node_id(data), username(cl));
|
---|
684 | }
|
---|
685 | }
|
---|
686 | else {
|
---|
687 | cs_debug_mask(D_CACHEEX, "cacheex: received old cachex from %s", username(cl));
|
---|
688 | er->csp_lastnodes = ll_create("csp_lastnodes");
|
---|
689 | }
|
---|
690 |
|
---|
691 | //store remote node id if we got one. The remote node is the first node in the node list
|
---|
692 | data = ll_has_elements(er->csp_lastnodes);
|
---|
693 | if (data && !cl->ncd_skey[8]) { //Ok, this is tricky, we use newcamd key storage for saving the remote node
|
---|
694 | memcpy(cl->ncd_skey, data, 8);
|
---|
695 | cl->ncd_skey[8] = 1; //Mark as valid node
|
---|
696 | }
|
---|
697 | cs_debug_mask(D_CACHEEX, "cacheex: received cacheex from remote node id %" PRIu64 "X", cacheex_node_id(cl->ncd_skey));
|
---|
698 |
|
---|
699 | //for compatibility: add peer node if no node received (not working now, maybe later):
|
---|
700 | if (!ll_count(er->csp_lastnodes) && cl->ncd_skey[8]) {
|
---|
701 | if (!cs_malloc(&data, 8))
|
---|
702 | return;
|
---|
703 | memcpy(data, cl->ncd_skey, 8);
|
---|
704 | ll_append(er->csp_lastnodes, data);
|
---|
705 | cs_debug_mask(D_CACHEEX, "cacheex: added missing remote node id %" PRIu64 "X", cacheex_node_id(data));
|
---|
706 | }
|
---|
707 |
|
---|
708 | // if (!ll_count(er->csp_lastnodes)) {
|
---|
709 | // if (!cs_malloc(&data, 8))
|
---|
710 | // break;
|
---|
711 | // memcpy(data, &cl->ip, 4);
|
---|
712 | // memcpy(data+4, &cl->port, 2);
|
---|
713 | // memcpy(data+6, &cl->is_udp, 1);
|
---|
714 | // ll_append(er->csp_lastnodes, data);
|
---|
715 | // cs_debug_mask(D_CACHEEX, "cacheex: added compat remote node id %" PRIu64 "X", cacheex_node_id(data));
|
---|
716 | // }
|
---|
717 |
|
---|
718 | cacheex_add_to_cache(cl, er);
|
---|
719 | }
|
---|
720 |
|
---|
721 | #endif
|
---|
722 |
|
---|
723 | static void * camd35_server(struct s_client *client __attribute__((unused)), uchar *mbuf, int32_t n)
|
---|
724 | {
|
---|
725 | if (client->reader){
|
---|
726 | client->reader->last_g = time((time_t *) 0); // last receive is now
|
---|
727 | cs_log("CAMD35_SERVER last = %d, last_s = %d, last_g = %d", (int) client->last, (int) client->reader->last_s, (int) client->reader->last_g);
|
---|
728 | }
|
---|
729 | client->last= time((time_t *) 0); // last client action is now
|
---|
730 |
|
---|
731 | switch(mbuf[0]) {
|
---|
732 | case 0: // ECM
|
---|
733 | case 3: // ECM (cascading)
|
---|
734 | camd35_process_ecm(mbuf);
|
---|
735 | break;
|
---|
736 | #ifdef CS_CACHEEX
|
---|
737 | case 0x3d: // Cache-push id request
|
---|
738 | camd35_cache_push_send_own_id(client, mbuf);
|
---|
739 | break;
|
---|
740 | case 0x3e: // Cache-push id answer
|
---|
741 | camd35_cache_push_receive_remote_id(client, mbuf);
|
---|
742 | break;
|
---|
743 | case 0x3f: // Cache-push
|
---|
744 | camd35_cache_push_in(client, mbuf);
|
---|
745 | break;
|
---|
746 | #endif
|
---|
747 | case 6: // EMM
|
---|
748 | case 19: // EMM
|
---|
749 | camd35_process_emm(mbuf);
|
---|
750 | break;
|
---|
751 | default:
|
---|
752 | cs_log("unknown camd35 command from %s! (%d) n=%d", username(client), mbuf[0], n);
|
---|
753 | }
|
---|
754 |
|
---|
755 | return NULL; //to prevent compiler message
|
---|
756 | }
|
---|
757 |
|
---|
758 | static int32_t camd35_send_ecm(struct s_client *client, ECM_REQUEST *er, uchar *buf)
|
---|
759 | {
|
---|
760 | static const char *typtext[]={"ok", "invalid", "sleeping"};
|
---|
761 |
|
---|
762 | if (client->stopped) {
|
---|
763 | if (er->srvid == client->lastsrvid && er->caid == client->lastcaid && er->pid == client->lastpid){
|
---|
764 | cs_log("%s is stopped - requested by server (%s)",
|
---|
765 | client->reader->label, typtext[client->stopped]);
|
---|
766 | return(-1);
|
---|
767 | }
|
---|
768 | else {
|
---|
769 | client->stopped = 0;
|
---|
770 | }
|
---|
771 | }
|
---|
772 |
|
---|
773 | client->lastsrvid = er->srvid;
|
---|
774 | client->lastcaid = er->caid;
|
---|
775 | client->lastpid = er->pid;
|
---|
776 |
|
---|
777 |
|
---|
778 |
|
---|
779 | if (!tcp_connect(client)) return -1;
|
---|
780 |
|
---|
781 | client->reader->card_status = CARD_INSERTED; //for udp
|
---|
782 |
|
---|
783 | memset(buf, 0, 20);
|
---|
784 | memset(buf + 20, 0xff, er->ecmlen+15);
|
---|
785 | buf[1]=er->ecmlen;
|
---|
786 | i2b_buf(2, er->srvid, buf + 8);
|
---|
787 | i2b_buf(2, er->caid, buf + 10);
|
---|
788 | i2b_buf(4, er->prid, buf + 12);
|
---|
789 | i2b_buf(2, er->idx, buf + 16);
|
---|
790 | buf[18] = 0xff;
|
---|
791 | buf[19] = 0xff;
|
---|
792 | memcpy(buf + 20, er->ecm, er->ecmlen);
|
---|
793 | return((camd35_send(client, buf, 0) < 1) ? (-1) : 0);
|
---|
794 | }
|
---|
795 |
|
---|
796 | static int32_t camd35_send_emm(EMM_PACKET *ep)
|
---|
797 | {
|
---|
798 | uchar buf[512];
|
---|
799 | struct s_client *cl = cur_client();
|
---|
800 |
|
---|
801 |
|
---|
802 | if (!tcp_connect(cl)) return -1;
|
---|
803 |
|
---|
804 | memset(buf, 0, 20);
|
---|
805 | memset(buf+20, 0xff, ep->emmlen+15);
|
---|
806 |
|
---|
807 | buf[0]=0x06;
|
---|
808 | buf[1]=ep->emmlen;
|
---|
809 | memcpy(buf+10, ep->caid, 2);
|
---|
810 | memcpy(buf+12, ep->provid, 4);
|
---|
811 | memcpy(buf+20, ep->emm, ep->emmlen);
|
---|
812 |
|
---|
813 | return((camd35_send(cl, buf, 0)<1) ? 0 : 1);
|
---|
814 | }
|
---|
815 |
|
---|
816 | static int32_t camd35_recv_chk(struct s_client *client, uchar *dcw, int32_t *rc, uchar *buf, int32_t rc2 __attribute__((unused)))
|
---|
817 | {
|
---|
818 | if (client->reader){
|
---|
819 | client->reader->last_g = time((time_t *) 0); // last receive is now
|
---|
820 | }
|
---|
821 |
|
---|
822 | uint16_t idx;
|
---|
823 | static const char *typtext[]={"ok", "invalid", "sleeping"};
|
---|
824 | struct s_reader *rdr = client->reader;
|
---|
825 |
|
---|
826 | // reading CMD05 Emm request and set serial
|
---|
827 | if (buf[0] == 0x05 && buf[1] == 111) {
|
---|
828 |
|
---|
829 | //cs_log("CMD05: %s", cs_hexdump(1, buf, buf[1], tmp, sizeof(tmp)));
|
---|
830 | rdr->nprov = 0; //reset if number changes on reader change
|
---|
831 | rdr->nprov = buf[47];
|
---|
832 | rdr->caid = b2i(2, buf + 20);
|
---|
833 | rdr->auprovid = b2i(4, buf + 12);
|
---|
834 |
|
---|
835 | int32_t i;
|
---|
836 | for (i=0; i<rdr->nprov; i++) {
|
---|
837 | if (((rdr->caid >= 0x1700) && (rdr->caid <= 0x1799)) || // Betacrypt
|
---|
838 | ((rdr->caid >= 0x0600) && (rdr->caid <= 0x0699))) // Irdeto (don't know if this is correct, cause I don't own a IRDETO-Card)
|
---|
839 | {
|
---|
840 | rdr->prid[i][0] = buf[48 + (i*5)];
|
---|
841 | memcpy(&rdr->prid[i][1], &buf[50 + (i * 5)], 3);
|
---|
842 | } else {
|
---|
843 | rdr->prid[i][2] = buf[48 + (i * 5)];
|
---|
844 | rdr->prid[i][3] = buf[49+ (i * 5)];
|
---|
845 | memcpy(&rdr->sa[i][0], &buf[50 + (i * 5)], 4);
|
---|
846 | }
|
---|
847 | }
|
---|
848 |
|
---|
849 | memcpy(rdr->hexserial, buf + 40, 6);
|
---|
850 | rdr->hexserial[6] = 0;
|
---|
851 | rdr->hexserial[7] = 0;
|
---|
852 |
|
---|
853 | rdr->blockemm = 0;
|
---|
854 | rdr->blockemm |= (buf[128]==1) ? 0 : EMM_GLOBAL;
|
---|
855 | rdr->blockemm |= (buf[129]==1) ? 0 : EMM_SHARED;
|
---|
856 | rdr->blockemm |= (buf[130]==1) ? 0 : EMM_UNIQUE;
|
---|
857 | cs_log("%s CMD05 AU request for caid: %04X auprovid: %06X",
|
---|
858 | rdr->label,
|
---|
859 | rdr->caid,
|
---|
860 | rdr->auprovid);
|
---|
861 | }
|
---|
862 |
|
---|
863 | if (buf[0] == 0x08
|
---|
864 | && ((rdr->ph.type == MOD_CONN_TCP && !cfg.c35_tcp_suppresscmd08)
|
---|
865 | || (rdr->ph.type == MOD_CONN_UDP
|
---|
866 | && !cfg.c35_udp_suppresscmd08))) {
|
---|
867 | if (buf[21] == 0xFF) {
|
---|
868 | client->stopped = 2; // server says sleep
|
---|
869 | rdr->card_status = NO_CARD;
|
---|
870 | } else {
|
---|
871 | #ifdef WITH_LB
|
---|
872 | if (!cfg.lb_mode) {
|
---|
873 | #endif
|
---|
874 | client->stopped = 1; // server says invalid
|
---|
875 | rdr->card_status = CARD_FAILURE;
|
---|
876 | #ifdef WITH_LB
|
---|
877 | }
|
---|
878 | #endif
|
---|
879 | }
|
---|
880 |
|
---|
881 | cs_log(
|
---|
882 | "%s CMD08 (%02X - %d) stop request by server (%s)", rdr->label, buf[21], buf[21], typtext[client->stopped]);
|
---|
883 | }
|
---|
884 |
|
---|
885 | #ifdef CS_CACHEEX
|
---|
886 | if (buf[0] == 0x3d) { // Cache-push id request
|
---|
887 | camd35_cache_push_send_own_id(client, buf);
|
---|
888 | return -1;
|
---|
889 | }
|
---|
890 | if (buf[0] == 0x3e) { // Cache-push id answer
|
---|
891 | camd35_cache_push_receive_remote_id(client, buf);
|
---|
892 | return -1;
|
---|
893 | }
|
---|
894 | if (buf[0] == 0x3f) { //cache-push
|
---|
895 | camd35_cache_push_in(client, buf);
|
---|
896 | return -1;
|
---|
897 | }
|
---|
898 | #endif
|
---|
899 |
|
---|
900 | // CMD44: old reject command introduced in mpcs
|
---|
901 | // keeping this for backward compatibility
|
---|
902 | if ((buf[0] != 1) && (buf[0] != 0x44) && (buf[0] != 0x08))
|
---|
903 | return(-1);
|
---|
904 |
|
---|
905 | idx = b2i(2, buf+16);
|
---|
906 |
|
---|
907 | *rc = ((buf[0] != 0x44) && (buf[0] != 0x08));
|
---|
908 |
|
---|
909 | memcpy(dcw, buf+20, 16);
|
---|
910 | return(idx);
|
---|
911 | }
|
---|
912 |
|
---|
913 | /*
|
---|
914 | * module definitions
|
---|
915 | */
|
---|
916 | #ifdef MODULE_CAMD35
|
---|
917 | void module_camd35(struct s_module *ph)
|
---|
918 | {
|
---|
919 | ph->ptab.nports = 1;
|
---|
920 | ph->ptab.ports[0].s_port = cfg.c35_port;
|
---|
921 |
|
---|
922 | ph->desc="camd35";
|
---|
923 | ph->type=MOD_CONN_UDP;
|
---|
924 | ph->large_ecm_support = 1;
|
---|
925 | ph->listenertype = LIS_CAMD35UDP;
|
---|
926 | IP_ASSIGN(ph->s_ip, cfg.c35_srvip);
|
---|
927 | ph->s_handler=camd35_server;
|
---|
928 | ph->recv=camd35_recv;
|
---|
929 | ph->send_dcw=camd35_send_dcw;
|
---|
930 | ph->c_init=camd35_client_init;
|
---|
931 | ph->c_recv_chk=camd35_recv_chk;
|
---|
932 | ph->c_send_ecm=camd35_send_ecm;
|
---|
933 | ph->c_send_emm=camd35_send_emm;
|
---|
934 | #ifdef CS_CACHEEX
|
---|
935 | ph->c_cache_push=camd35_cache_push_out;
|
---|
936 | ph->c_cache_push_chk=camd35_cache_push_chk;
|
---|
937 | #endif
|
---|
938 | ph->num=R_CAMD35;
|
---|
939 | }
|
---|
940 | #endif
|
---|
941 |
|
---|
942 | #ifdef MODULE_CAMD35_TCP
|
---|
943 | void module_camd35_tcp(struct s_module *ph)
|
---|
944 | {
|
---|
945 | ph->desc="cs378x";
|
---|
946 | ph->type=MOD_CONN_TCP;
|
---|
947 | ph->large_ecm_support = 1;
|
---|
948 | ph->listenertype = LIS_CAMD35TCP;
|
---|
949 | ph->ptab = cfg.c35_tcp_ptab;
|
---|
950 | IP_ASSIGN(ph->s_ip, cfg.c35_tcp_srvip);
|
---|
951 | ph->s_handler=camd35_server;
|
---|
952 | ph->recv=camd35_recv;
|
---|
953 | ph->send_dcw=camd35_send_dcw;
|
---|
954 | ph->c_init=camd35_client_init;
|
---|
955 | ph->c_recv_chk=camd35_recv_chk;
|
---|
956 | ph->c_send_ecm=camd35_send_ecm;
|
---|
957 | ph->c_send_emm=camd35_send_emm;
|
---|
958 | #ifdef CS_CACHEEX
|
---|
959 | ph->c_cache_push=camd35_cache_push_out;
|
---|
960 | ph->c_cache_push_chk=camd35_cache_push_chk;
|
---|
961 | #endif
|
---|
962 | ph->num=R_CS378X;
|
---|
963 | }
|
---|
964 | #endif
|
---|
965 | #endif
|
---|