source: trunk/module-camd35.c@ 3172

Last change on this file since 3172 was 3172, checked in by _network, 10 years ago

remove global mbuf

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