source: trunk/module-camd35.c@ 4149

Last change on this file since 4149 was 4141, checked in by dingo35, 13 years ago

all: simplify debug system, add D_DVBAPI = -d128, eliminate cs_ptyp which complicates stuff unnecc

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