source: trunk/module-camd35.c@ 3181

Last change on this file since 3181 was 3181, checked in by dingo35, 10 years ago

Adding threadsafety FIXMEs, feel free to join checking..

File size: 19.9 KB
Line 
1//FIXME Not checked on threadsafety yet; after checking please remove this line
2#include "globals.h"
3extern struct s_reader *reader;
4
5//CMD00 - ECM (request)
6//CMD01 - ECM (response)
7//CMD02 - EMM (in clientmode - set EMM, in server mode - EMM data) - obsolete
8//CMD03 - ECM (cascading request)
9//CMD04 - ECM (cascading response)
10//CMD05 - EMM (emm request) send cardata/cardinfo to client
11//CMD06 - EMM (incomming EMM in server mode)
12//CMD19 - EMM (incomming EMM in server mode) only seen with caid 0x1830
13//CMD08 - Stop sending requests to the server for current srvid,prvid,caid
14//CMD44 - MPCS/OScam internal error notification
15
16#define REQ_SIZE 328 // 256 + 20 + 0x34
17
18static int camd35_send(uchar *buf)
19{
20 int l;
21 unsigned char rbuf[REQ_SIZE+15+4], *sbuf = rbuf + 4;
22
23 if (!client[cs_idx].udp_fd) return(-1);
24 l = 20 + buf[1] + (((buf[0] == 3) || (buf[0] == 4)) ? 0x34 : 0);
25 memcpy(rbuf, client[cs_idx].ucrc, 4);
26 memcpy(sbuf, buf, l);
27 memset(sbuf + l, 0xff, 15); // set unused space to 0xff for newer camd3's
28 memcpy(sbuf + 4, i2b(4, crc32(0L, sbuf+20, sbuf[1])), 4);
29 l = boundary(4, l);
30 cs_ddump(sbuf, l, "send %d bytes to %s", l, remote_txt());
31 aes_encrypt(sbuf, l);
32
33 int status;
34 if (client[cs_idx].is_udp) {
35 status = sendto(client[cs_idx].udp_fd, rbuf, l+4, 0,
36 (struct sockaddr *)&client[cs_idx].udp_sa,
37 sizeof(client[cs_idx].udp_sa));
38 if (status == -1) client[cs_idx].udp_sa.sin_addr.s_addr = 0;
39 }
40 else {
41 status = send(client[cs_idx].udp_fd, rbuf, l + 4, 0);
42 if (status == -1) network_tcp_connection_close(&reader[client[cs_idx].ridx], client[cs_idx].pfd);
43 }
44 return status;
45}
46
47static int camd35_auth_client(uchar *ucrc)
48{
49 int rc=1;
50 ulong crc;
51 struct s_auth *account;
52
53 if (client[cs_idx].upwd[0])
54 return(memcmp(client[cs_idx].ucrc, ucrc, 4) ? 1 : 0);
55 client[cs_idx].crypted=1;
56 crc=(((ucrc[0]<<24) | (ucrc[1]<<16) | (ucrc[2]<<8) | ucrc[3]) & 0xffffffffL);
57 for (account=cfg->account; (account) && (!client[cs_idx].upwd[0]); account=account->next)
58 if (crc==crc32(0L, MD5((unsigned char *)account->usr, strlen(account->usr), NULL), 16))
59 {
60 memcpy(client[cs_idx].ucrc, ucrc, 4);
61 strcpy((char *)client[cs_idx].upwd, account->pwd);
62 aes_set_key((char *) MD5(client[cs_idx].upwd, strlen((char *)client[cs_idx].upwd), NULL));
63 rc=cs_auth_client(account, NULL);
64 }
65 return(rc);
66}
67
68static int camd35_recv(uchar *buf, int l)
69{
70 int rc, s, rs, n=0;
71 unsigned char recrc[4];
72 for (rc=rs=s=0; !rc; s++) switch(s)
73 {
74 case 0:
75 if (client[cs_idx].is_server)
76 {
77 if (!client[cs_idx].udp_fd) return(-9);
78 if (client[cs_idx].is_udp)
79 rs=recv_from_udpipe(buf);
80 else
81 rs=recv(client[cs_idx].udp_fd, buf, l, 0);
82 }
83 else
84 {
85 if (!client[cs_idx].udp_fd) return(-9);
86 rs = recv(client[cs_idx].udp_fd, buf, l, 0);
87 }
88 if (rs < 24) rc = -1;
89 break;
90 case 1:
91 memcpy(recrc, buf, 4);
92 memmove(buf, buf+4, rs-=4);
93 switch (camd35_auth_client(recrc))
94 {
95 case 0: break; // ok
96 case 1: rc=-2; break; // unknown user
97 default: rc=-9; break; // error's from cs_auth()
98 }
99 break;
100 case 2:
101 aes_decrypt(buf, rs);
102 cs_ddump(buf, rs, "received %d bytes from %s", rs, remote_txt());
103 if (rs!=boundary(4, rs))
104 cs_debug("WARNING: packet size has wrong decryption boundary");
105 //n=(buf[0]==3) ? n=0x34 : 0; this was original, but statement below seems more logical -- dingo35
106 n=(buf[0]==3) ? 0x34 : 0;
107 n=boundary(4, n+20+buf[1]);
108 if (n<rs)
109 cs_debug("ignoring %d bytes of garbage", rs-n);
110 else
111 if (n>rs) rc=-3;
112 break;
113 case 3:
114 if (crc32(0L, buf+20, buf[1])!=b2i(4, buf+4)) rc=-4;
115 if (!rc) rc=n;
116 break;
117 }
118 if ((rs>0) && ((rc==-1)||(rc==-2)))
119 cs_ddump(buf, rs, "received %d bytes from %s (native)", rs, remote_txt);
120 client[cs_idx].last=time((time_t *) 0);
121 switch(rc)
122 {
123 case -1: cs_log("packet to small (%d bytes)", rs);
124 break;
125 case -2: cs_auth_client(0, "unknown user");
126 break;
127 case -3: cs_log("incomplete request !");
128 break;
129 case -4: cs_log("checksum error (wrong password ?)");
130 break;
131 }
132 return(rc);
133}
134
135/*
136 * server functions
137 */
138
139static void camd35_request_emm(ECM_REQUEST *er)
140{
141 int i, au;
142 time_t now;
143 uchar mbuf[1024];
144
145 au = client[cs_idx].au;
146 if ((au < 0) || (au > CS_MAXREADER))
147 return; // TODO
148
149 time(&now);
150 if (!memcmp(client[cs_idx].lastserial, reader[au].hexserial, 8))
151 if (abs(now-client[cs_idx].last) < 180) return;
152
153 memcpy(client[cs_idx].lastserial, reader[au].hexserial, 8);
154 client[cs_idx].last = now;
155
156 if (reader[au].caid[0])
157 {
158 client[cs_idx].disable_counter = 0;
159 log_emm_request(au);
160 }
161 else
162 if (client[cs_idx].disable_counter > 2)
163 return;
164 else
165 client[cs_idx].disable_counter++;
166
167 memset(mbuf, 0, sizeof(mbuf));
168 mbuf[2] = mbuf[3] = 0xff; // must not be zero
169 memcpy(mbuf + 8, i2b(2, er->srvid), 2);
170
171 //override request provid with auprovid if set in CMD05
172 if(reader[au].auprovid) {
173 if(reader[au].auprovid != er->prid)
174 memcpy(mbuf + 12, i2b(4, reader[au].auprovid), 4);
175 else
176 memcpy(mbuf + 12, i2b(4, er->prid), 4);
177 } else {
178 memcpy(mbuf + 12, i2b(4, er->prid), 4);
179 }
180
181 memcpy(mbuf + 16, i2b(2, er->pid), 2);
182 mbuf[0] = 5;
183 mbuf[1] = 111;
184 if (reader[au].caid[0])
185 {
186 mbuf[39] = 1; // no. caids
187 mbuf[20] = reader[au].caid[0]>>8; // caid's (max 8)
188 mbuf[21] = reader[au].caid[0]&0xff;
189 memcpy(mbuf + 40, reader[au].hexserial, 6); // serial now 6 bytes
190 mbuf[47] = reader[au].nprov;
191 for (i = 0; i < reader[au].nprov; i++)
192 {
193 if (((reader[au].caid[0] >= 0x1700) && (reader[au].caid[0] <= 0x1799)) || // Betacrypt
194 ((reader[au].caid[0] >= 0x0600) && (reader[au].caid[0] <= 0x0699))) // Irdeto (don't know if this is correct, cause I don't own a IRDETO-Card)
195 {
196 mbuf[48 + (i*5)] = reader[au].prid[i][0];
197 memcpy(&mbuf[50 + (i*5)], &reader[au].prid[i][1], 3);
198 }
199 else
200 {
201 mbuf[48 + (i * 5)] = reader[au].prid[i][2];
202 mbuf[49 + (i * 5)] =reader[au].prid[i][3];
203 memcpy(&mbuf[50 + (i * 5)], &reader[au].sa[i][0],4); // for conax we need at least 4 Bytes
204 }
205 }
206 //we think client/server protocols should deliver all information, and only readers should discard EMM
207 mbuf[128] = (reader[au].blockemm_g == 1) ? 0: 1;
208 mbuf[129] = (reader[au].blockemm_s == 1) ? 0: 1;
209 mbuf[130] = (reader[au].blockemm_u == 1) ? 0: 1;
210 //mbuf[131] = reader[au].card_system; //Cardsystem for Oscam client
211 }
212 else // disable emm
213 mbuf[20] = mbuf[39] = mbuf[40] = mbuf[47] = mbuf[49] = 1;
214
215 memcpy(mbuf + 10, mbuf + 20, 2);
216 camd35_send(mbuf); // send with data-len 111 for camd3 > 3.890
217 mbuf[1]++;
218 camd35_send(mbuf); // send with data-len 112 for camd3 < 3.890
219}
220
221static void camd35_send_dcw(ECM_REQUEST *er)
222{
223 uchar *buf;
224 buf = client[cs_idx].req + (er->cpti * REQ_SIZE); // get orig request
225
226 if (((er->rcEx > 0) || (er->rc == 8)) && !client[cs_idx].c35_suppresscmd08)
227 {
228 buf[0] = 0x08;
229 buf[1] = 2;
230 memset(buf + 20, 0, buf[1]);
231 }
232 else if (er->rc == 13)
233 {
234 buf[0] = 0x08;
235 buf[1] = 2;
236 buf[20] = 0;
237 /*
238 * the second Databyte should be forseen for a sleeptime in minutes
239 * whoever knows the camd3 protocol related to CMD08 - please help!
240 * on tests this don't work with native camd3
241 */
242 buf[21] = client[cs_idx].c35_sleepsend;
243 cs_log("%s stop request send", client[cs_idx].usr);
244 }
245 else
246 {
247 // Send CW
248 if ((er->rc < 4) || (er->rc == 7))
249 {
250 if (buf[0]==3)
251 memmove(buf + 20 + 16, buf + 20 + buf[1], 0x34);
252 buf[0]++;
253 buf[1] = 16;
254 memcpy(buf+20, er->cw, buf[1]);
255 }
256 else
257 {
258 // Send old CMD44 to prevent cascading problems with older mpcs/oscam versions
259 buf[0] = 0x44;
260 buf[1] = 0;
261 }
262 }
263 camd35_send(buf);
264 camd35_request_emm(er);
265}
266
267static void camd35_process_ecm(uchar *buf)
268{
269 ECM_REQUEST *er;
270 if (!(er = get_ecmtask()))
271 return;
272 er->l = buf[1];
273 memcpy(client[cs_idx].req + (er->cpti*REQ_SIZE), buf, 0x34 + 20 + er->l); // save request
274 er->srvid = b2i(2, buf+ 8);
275 er->caid = b2i(2, buf+10);
276 er->prid = b2i(4, buf+12);
277 er->pid = b2i(2, buf+16);
278 memcpy(er->ecm, buf + 20, er->l);
279 get_cw(er);
280}
281
282static void camd35_process_emm(uchar *buf)
283{
284 int au;
285 EMM_PACKET epg;
286 memset(&epg, 0, sizeof(epg));
287 au = client[cs_idx].au;
288 if ((au < 0) || (au > CS_MAXREADER)) return; // TODO
289 epg.l = buf[1];
290 memcpy(epg.caid, buf + 10, 2);
291 memcpy(epg.provid, buf + 12 , 4);
292 memcpy(epg.emm, buf + 20, epg.l);
293 do_emm(&epg);
294}
295
296static void camd35_server(void *idx)
297{
298 int n;
299 uchar mbuf[1024];
300
301 int cidx=(int)idx;
302 client[cidx].thread=pthread_self();
303
304 client[cs_idx].req=(uchar *)malloc(CS_MAXPENDING*REQ_SIZE);
305 if (!client[cs_idx].req)
306 {
307 cs_log("Cannot allocate memory (errno=%d)", errno);
308 cs_exit(1);
309 }
310 memset(client[cs_idx].req, 0, CS_MAXPENDING*REQ_SIZE);
311
312 client[cs_idx].is_udp = (ph[client[cs_idx].ctyp].type == MOD_CONN_UDP);
313
314 while ((n=process_input(mbuf, sizeof(mbuf), cfg->cmaxidle))>0)
315 {
316 switch(mbuf[0])
317 {
318 case 0: // ECM
319 case 3: // ECM (cascading)
320 camd35_process_ecm(mbuf);
321 break;
322 case 6: // EMM
323 case 19: // EMM
324 camd35_process_emm(mbuf);
325 break;
326 default:
327 cs_log("unknown camd35 command! (%d)", mbuf[0]);
328 }
329 }
330
331 if(client[cs_idx].req) { free(client[cs_idx].req); client[cs_idx].req=0;}
332
333 cs_disconnect_client();
334}
335
336/*
337 * client functions
338 */
339
340static void casc_set_account()
341{
342 strcpy((char *)client[cs_idx].upwd, reader[client[cs_idx].ridx].r_pwd);
343 memcpy(client[cs_idx].ucrc, i2b(4, crc32(0L, MD5((unsigned char *)reader[client[cs_idx].ridx].r_usr, strlen(reader[client[cs_idx].ridx].r_usr), NULL), 16)), 4);
344 aes_set_key((char *)MD5(client[cs_idx].upwd, strlen((char *)client[cs_idx].upwd), NULL));
345 client[cs_idx].crypted=1;
346}
347
348int camd35_client_init()
349{
350 static struct sockaddr_in loc_sa;
351 struct protoent *ptrp;
352 int p_proto;//, sock_type;
353 char ptxt[16];
354
355 client[cs_idx].pfd=0;
356 if (reader[client[cs_idx].ridx].r_port<=0)
357 {
358 cs_log("invalid port %d for server %s", reader[client[cs_idx].ridx].r_port, reader[client[cs_idx].ridx].device);
359 return(1);
360 }
361 client[cs_idx].is_udp=(reader[client[cs_idx].ridx].typ==R_CAMD35);
362 if( (ptrp=getprotobyname(client[cs_idx].is_udp ? "udp" : "tcp")) )
363 p_proto=ptrp->p_proto;
364 else
365 p_proto=(client[cs_idx].is_udp) ? 17 : 6; // use defaults on error
366
367 client[cs_idx].ip=0;
368 memset((char *)&loc_sa,0,sizeof(loc_sa));
369 loc_sa.sin_family = AF_INET;
370#ifdef LALL
371 if (cfg->serverip[0])
372 loc_sa.sin_addr.s_addr = inet_addr(cfg->serverip);
373 else
374#endif
375 loc_sa.sin_addr.s_addr = INADDR_ANY;
376 loc_sa.sin_port = htons(reader[client[cs_idx].ridx].l_port);
377
378 if ((client[cs_idx].udp_fd=socket(PF_INET, client[cs_idx].is_udp ? SOCK_DGRAM : SOCK_STREAM, p_proto))<0)
379 {
380 cs_log("Socket creation failed (errno=%d)", errno);
381 cs_exit(1);
382 }
383
384#ifdef SO_PRIORITY
385 if (cfg->netprio)
386 setsockopt(client[cs_idx].udp_fd, SOL_SOCKET, SO_PRIORITY, (void *)&cfg->netprio, sizeof(ulong));
387#endif
388
389 if (reader[client[cs_idx].ridx].l_port>0)
390 {
391 if (bind(client[cs_idx].udp_fd, (struct sockaddr *)&loc_sa, sizeof (loc_sa))<0)
392 {
393 cs_log("bind failed (errno=%d)", errno);
394 close(client[cs_idx].udp_fd);
395 return(1);
396 }
397 sprintf(ptxt, ", port=%d", reader[client[cs_idx].ridx].l_port);
398 }
399 else
400 ptxt[0]='\0';
401
402 casc_set_account();
403 memset((char *)&client[cs_idx].udp_sa, 0, sizeof(client[cs_idx].udp_sa));
404 client[cs_idx].udp_sa.sin_family=AF_INET;
405 client[cs_idx].udp_sa.sin_port=htons((u_short)reader[client[cs_idx].ridx].r_port);
406
407 cs_log("proxy %s:%d (fd=%d%s)",
408 reader[client[cs_idx].ridx].device, reader[client[cs_idx].ridx].r_port,
409 client[cs_idx].udp_fd, ptxt);
410
411 if (client[cs_idx].is_udp) {
412 client[cs_idx].pfd=client[cs_idx].udp_fd;
413 }
414
415 return(0);
416}
417
418int camd35_client_init_log()
419{
420 struct sockaddr_in loc_sa;
421 struct protoent *ptrp;
422 int p_proto;
423
424 if (reader[client[cs_idx].ridx].log_port<=0)
425 {
426 cs_log("invalid port %d for camd3-loghost", reader[client[cs_idx].ridx].log_port);
427 return(1);
428 }
429
430 ptrp=getprotobyname("udp");
431 if (ptrp)
432 p_proto=ptrp->p_proto;
433 else
434 p_proto=17; // use defaults on error
435
436 memset((char *)&loc_sa,0,sizeof(loc_sa));
437 loc_sa.sin_family = AF_INET;
438 loc_sa.sin_addr.s_addr = INADDR_ANY;
439 loc_sa.sin_port = htons(reader[client[cs_idx].ridx].log_port);
440
441 if ((logfd=socket(PF_INET, SOCK_DGRAM, p_proto))<0)
442 {
443 cs_log("Socket creation failed (errno=%d)", errno);
444 return(1);
445 }
446
447 if (bind(logfd, (struct sockaddr *)&loc_sa, sizeof(loc_sa))<0)
448 {
449 cs_log("bind failed (errno=%d)", errno);
450 close(logfd);
451 return(1);
452 }
453
454 cs_log("camd3 loghost initialized (fd=%d, port=%d)",
455 logfd, reader[client[cs_idx].ridx].log_port);
456
457 return(0);
458}
459
460static int tcp_connect()
461{
462 if (!reader[client[cs_idx].ridx].tcp_connected)
463 {
464 int handle=0;
465 handle = network_tcp_connection_open();
466 if (handle<0) return(0);
467
468 reader[client[cs_idx].ridx].tcp_connected = 1;
469 reader[client[cs_idx].ridx].card_status = CARD_INSERTED;
470 reader[client[cs_idx].ridx].last_s = reader[client[cs_idx].ridx].last_g = time((time_t *)0);
471 client[cs_idx].pfd = client[cs_idx].udp_fd = handle;
472 }
473 if (!client[cs_idx].udp_fd) return(0);
474 return(1);
475}
476
477static int camd35_send_ecm(ECM_REQUEST *er, uchar *buf)
478{
479 char *typtext[]={"ok", "invalid", "sleeping"};
480
481 if (client[cs_idx].stopped) {
482 if (er->srvid == client[cs_idx].lastsrvid && er->caid == client[cs_idx].lastcaid && er->pid == client[cs_idx].lastpid){
483 cs_log("%s is stopped - requested by server (%s)",
484 reader[client[cs_idx].ridx].label, typtext[client[cs_idx].stopped]);
485 return(-1);
486 }
487 else {
488 client[cs_idx].stopped = 0;
489 }
490 }
491
492 client[cs_idx].lastsrvid = er->srvid;
493 client[cs_idx].lastcaid = er->caid;
494 client[cs_idx].lastpid = er->pid;
495
496 if (client[cs_idx].is_udp) {
497 if (!client[cs_idx].udp_sa.sin_addr.s_addr || reader[client[cs_idx].ridx].last_s-reader[client[cs_idx].ridx].last_g > reader[client[cs_idx].ridx].tcp_rto)
498 if (!hostResolve(client[cs_idx].ridx)) return -1;
499 }
500 else {
501 if (!tcp_connect()) return -1;
502 }
503
504 reader[client[cs_idx].ridx].card_status = CARD_INSERTED; //for udp
505
506 memset(buf, 0, 20);
507 memset(buf + 20, 0xff, er->l+15);
508 buf[1]=er->l;
509 memcpy(buf + 8, i2b(2, er->srvid), 2);
510 memcpy(buf + 10, i2b(2, er->caid ), 2);
511 memcpy(buf + 12, i2b(4, er->prid ), 4);
512 // memcpy(buf+16, i2b(2, er->pid ), 2);
513 // memcpy(buf+16, &er->idx , 2);
514 memcpy(buf + 16, i2b(2, er->idx ), 2);
515 buf[18] = 0xff;
516 buf[19] = 0xff;
517 memcpy(buf + 20, er->ecm , er->l);
518 return((camd35_send(buf) < 1) ? (-1) : 0);
519}
520
521static int camd35_send_emm(EMM_PACKET *ep)
522{
523 uchar buf[512];
524
525 if (client[cs_idx].is_udp) {
526 if (!client[cs_idx].udp_sa.sin_addr.s_addr || reader[client[cs_idx].ridx].last_s-reader[client[cs_idx].ridx].last_g > reader[client[cs_idx].ridx].tcp_rto)
527 if (!hostResolve(client[cs_idx].ridx)) return -1;
528 }
529 else {
530 if (!tcp_connect()) return -1;
531 }
532
533 memset(buf, 0, 20);
534 memset(buf+20, 0xff, ep->l+15);
535
536 buf[0]=0x06;
537 buf[1]=ep->l;
538 memcpy(buf+10, ep->caid, 2);
539 memcpy(buf+12, ep->provid, 4);
540 memcpy(buf+20, ep->emm, ep->l);
541
542 return((camd35_send(buf)<1) ? 0 : 1);
543}
544
545static int camd35_recv_chk(uchar *dcw, int *rc, uchar *buf)
546{
547 ushort idx;
548 char *typtext[]={"ok", "invalid", "sleeping"};
549
550 // reading CMD05 Emm request and set serial
551 if (buf[0] == 0x05 && buf[1] == 111) {
552
553 //cs_log("CMD05: %s", cs_hexdump(1, buf, buf[1]));
554 reader[client[cs_idx].ridx].nprov = 0; //reset if number changes on reader change
555 reader[client[cs_idx].ridx].nprov = buf[47];
556 reader[client[cs_idx].ridx].caid[0] = b2i(2, buf + 20);
557 reader[client[cs_idx].ridx].auprovid = b2i(4, buf + 12);
558
559 int i;
560 for (i=0; i<reader[client[cs_idx].ridx].nprov; i++) {
561 if (((reader[client[cs_idx].ridx].caid[0] >= 0x1700) && (reader[client[cs_idx].ridx].caid[0] <= 0x1799)) || // Betacrypt
562 ((reader[client[cs_idx].ridx].caid[0] >= 0x0600) && (reader[client[cs_idx].ridx].caid[0] <= 0x0699))) // Irdeto (don't know if this is correct, cause I don't own a IRDETO-Card)
563 {
564 reader[client[cs_idx].ridx].prid[i][0] = buf[48 + (i*5)];
565 memcpy(&reader[client[cs_idx].ridx].prid[i][1], &buf[50 + (i * 5)], 3);
566 } else {
567 reader[client[cs_idx].ridx].prid[i][2] = buf[48 + (i * 5)];
568 reader[client[cs_idx].ridx].prid[i][3] = buf[49+ (i * 5)];
569 memcpy(&reader[client[cs_idx].ridx].sa[i][0], &buf[50 + (i * 5)], 4);
570 }
571 }
572
573 memcpy(reader[client[cs_idx].ridx].hexserial, buf + 40, 6);
574 reader[client[cs_idx].ridx].hexserial[6] = 0;
575 reader[client[cs_idx].ridx].hexserial[7] = 0;
576
577 reader[client[cs_idx].ridx].blockemm_g = (buf[128]==1) ? 0: 1;
578 reader[client[cs_idx].ridx].blockemm_s = (buf[129]==1) ? 0: 1;
579 reader[client[cs_idx].ridx].blockemm_u = (buf[130]==1) ? 0: 1;
580 reader[client[cs_idx].ridx].card_system = get_cardsystem(reader[client[cs_idx].ridx].caid[0]);
581 cs_log("%s CMD05 AU request for caid: %04X auprovid: %06lX",
582 reader[client[cs_idx].ridx].label,
583 reader[client[cs_idx].ridx].caid[0],
584 reader[client[cs_idx].ridx].auprovid);
585 }
586
587 if (buf[0] == 0x08) {
588 if(buf[21] == 0xFF) {
589 client[cs_idx].stopped = 2; // server says sleep
590 reader[client[cs_idx].ridx].card_status = NO_CARD;
591 } else {
592 client[cs_idx].stopped = 1; // server says invalid
593 reader[client[cs_idx].ridx].card_status = CARD_FAILURE;
594 }
595 cs_log("%s CMD08 (%02X - %d) stop request by server (%s)",
596 reader[client[cs_idx].ridx].label, buf[21], buf[21], typtext[client[cs_idx].stopped]);
597 }
598
599 // CMD44: old reject command introduced in mpcs
600 // keeping this for backward compatibility
601 if ((buf[0] != 1) && (buf[0] != 0x44) && (buf[0] != 0x08))
602 return(-1);
603
604 idx = b2i(2, buf+16);
605
606 *rc = ((buf[0] != 0x44) && (buf[0] != 0x08));
607
608 memcpy(dcw, buf+20, 16);
609 return(idx);
610}
611
612static int camd35_recv_log(ushort *caid, ulong *provid, ushort *srvid)
613{
614 int i;
615 uchar buf[512], *ptr, *ptr2;
616 ushort idx=0;
617 if (!logfd) return(-1);
618 if ((i=recv(logfd, buf, sizeof(buf), 0))<=0) return(-1);
619 buf[i]=0;
620
621 if (!(ptr=(uchar *)strstr((char *)buf, " -> "))) return(-1);
622 ptr+=4;
623 if (strstr((char *)ptr, " decoded ")) return(-1); // skip "found"s
624 if (!(ptr2=(uchar *)strchr((char *)ptr, ' '))) return(-1); // corrupt
625 *ptr2=0;
626
627 for (i=0, ptr2=(uchar *)strtok((char *)ptr, ":"); ptr2; i++, ptr2=(uchar *)strtok(NULL, ":"))
628 {
629 trim((char *)ptr2);
630 switch(i)
631 {
632 case 0: *caid =cs_atoi((char *)ptr2, strlen((char *)ptr2)>>1, 0); break;
633 case 1: *provid=cs_atoi((char *)ptr2, strlen((char *)ptr2)>>1, 0); break;
634 case 2: *srvid =cs_atoi((char *)ptr2, strlen((char *)ptr2)>>1, 0); break;
635 case 3: idx =cs_atoi((char *)ptr2, strlen((char *)ptr2)>>1, 0); break;
636 }
637 if (errno) return(-1);
638 }
639 return(idx&0x1FFF);
640}
641
642/*
643 * module definitions
644 */
645
646void module_camd35(struct s_module *ph)
647{
648 static PTAB ptab;
649 ptab.ports[0].s_port = cfg->c35_port;
650 ph->ptab = &ptab;
651 ph->ptab->nports = 1;
652
653 strcpy(ph->desc, "camd 3.5x");
654 ph->type=MOD_CONN_UDP;
655 ph->multi=1;
656 ph->watchdog=1;
657 ph->s_ip=cfg->c35_srvip;
658 ph->s_handler=camd35_server;
659 ph->recv=camd35_recv;
660 ph->send_dcw=camd35_send_dcw;
661 ph->c_multi=1;
662 ph->c_init=camd35_client_init;
663 ph->c_recv_chk=camd35_recv_chk;
664 ph->c_send_ecm=camd35_send_ecm;
665 ph->c_send_emm=camd35_send_emm;
666 ph->c_init_log=camd35_client_init_log;
667 ph->c_recv_log=camd35_recv_log;
668 ph->num=R_CAMD35;
669}
670
671void module_camd35_tcp(struct s_module *ph)
672{
673 strcpy(ph->desc, "cs378x");
674 ph->type=MOD_CONN_TCP;
675 ph->multi=1;
676 ph->watchdog=1;
677 ph->ptab=&cfg->c35_tcp_ptab;
678 if (ph->ptab->nports==0)
679 ph->ptab->nports=1; // show disabled in log
680 ph->s_ip=cfg->c35_tcp_srvip;
681 ph->s_handler=camd35_server;
682 ph->recv=camd35_recv;
683 ph->send_dcw=camd35_send_dcw;
684 ph->c_multi=1;
685 ph->c_init=camd35_client_init;
686 ph->c_recv_chk=camd35_recv_chk;
687 ph->c_send_ecm=camd35_send_ecm;
688 ph->c_send_emm=camd35_send_emm;
689 ph->c_init_log=camd35_client_init_log;
690 ph->c_recv_log=camd35_recv_log;
691 ph->num=R_CS378X;
692}
Note: See TracBrowser for help on using the repository browser.