source: trunk/module-camd35.c @ 5375

Last change on this file since 5375 was 5310, checked in by Admin, 8 years ago

Replace i2b with i2b_buf. cl->dump is now only used in cs_hexdump function...

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