source: trunk/module-newcamd.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: 36.1 KB
Line 
1#include "globals.h"
2
3#define CWS_NETMSGSIZE 272
4#define NCD_CLIENT_ID 0x8888
5
6#define CWS_FIRSTCMDNO 0xe0
7typedef enum
8{
9 MSG_CLIENT_2_SERVER_LOGIN = CWS_FIRSTCMDNO,
10 MSG_CLIENT_2_SERVER_LOGIN_ACK,
11 MSG_CLIENT_2_SERVER_LOGIN_NAK,
12 MSG_CARD_DATA_REQ,
13 MSG_CARD_DATA,
14 MSG_SERVER_2_CLIENT_NAME,
15 MSG_SERVER_2_CLIENT_NAME_ACK,
16 MSG_SERVER_2_CLIENT_NAME_NAK,
17 MSG_SERVER_2_CLIENT_LOGIN,
18 MSG_SERVER_2_CLIENT_LOGIN_ACK,
19 MSG_SERVER_2_CLIENT_LOGIN_NAK,
20 MSG_ADMIN,
21 MSG_ADMIN_ACK,
22 MSG_ADMIN_LOGIN,
23 MSG_ADMIN_LOGIN_ACK,
24 MSG_ADMIN_LOGIN_NAK,
25 MSG_ADMIN_COMMAND,
26 MSG_ADMIN_COMMAND_ACK,
27 MSG_ADMIN_COMMAND_NAK,
28 MSG_KEEPALIVE = CWS_FIRSTCMDNO + 0x1d,
29 MSG_SERVER_2_CLIENT_OSD = 0xd1,
30 MSG_SERVER_2_CLIENT_ALLCARDS = 0xd2,
31 MSG_SERVER_2_CLIENT_ADDCARD = 0xd3,
32 MSG_SERVER_2_CLIENT_REMOVECARD = 0xd4,
33 MSG_SERVER_2_CLIENT_CHANGE_KEY = 0xd5,
34 MSG_SERVER_2_CLIENT_GET_VERSION = 0xd6,
35 MSG_SERVER_2_CLIENT_ADDSID = 0xd7,
36 MSG_CLIENT_2_SERVER_CARDDISCOVER = 0xd8
37} net_msg_type_t;
38
39typedef enum
40{
41 COMMTYPE_CLIENT,
42 COMMTYPE_SERVER
43} comm_type_t;
44
45
46typedef struct custom_data
47{
48 unsigned short sid;
49 unsigned short caid;
50 int provid;
51 uchar x;
52} custom_data_t;
53
54#define REQ_SIZE 2
55
56static int network_message_send(int handle, uint16 *netMsgId, uint8 *buffer,
57 int len, uint8 *deskey, comm_type_t commType,
58 ushort sid, custom_data_t *cd)
59{
60 uint8 netbuf[CWS_NETMSGSIZE];
61 int head_size;
62 struct s_client *cl = cur_client();
63
64 head_size = (cl->ncd_proto==NCD_524)?8:12;
65
66 if (len < 3 || len + head_size > CWS_NETMSGSIZE || handle < 0)
67 return -1;
68 buffer[1] = (buffer[1] & 0xf0) | (((len - 3) >> 8) & 0x0f);
69 buffer[2] = (len - 3) & 0xff;
70 memcpy(netbuf+head_size, buffer, len);
71 len += head_size;
72 if (netMsgId) {
73 switch(commType)
74 {
75 case COMMTYPE_CLIENT:
76 (*netMsgId)++;
77 break;
78 case COMMTYPE_SERVER:
79 if( *netMsgId == 0xFFFE ) *netMsgId = 0; // ??? 0xFFFF ?
80 break;
81 }
82 netbuf[2] = (*netMsgId) >> 8;
83 netbuf[3] = (*netMsgId) & 0xff;
84 }
85 else
86 netbuf[2] = netbuf[3] = 0;
87 memset(netbuf+4, 0, (cl->ncd_proto==NCD_524)?4:8);
88 if( sid ) {
89 netbuf[(cl->ncd_proto==NCD_524)?6:4] = (uchar)(sid>>8); //sid
90 netbuf[(cl->ncd_proto==NCD_524)?7:5] = (uchar)(sid);
91 }
92 //if ((!ncd_proto==NCD_524) && (buffer[0] >= 0xd1) && (buffer[0]<= 0xd8)) { // extended proto for mg
93 //cs_debug_mask(D_CLIENT, "newcamd: extended: msg");
94 if (cd) {
95 cs_debug_mask(D_CLIENT, "newcamd: has cd");
96 netbuf[4] = cd->sid >> 8;
97 netbuf[5] = cd->sid & 0xff;
98 netbuf[6] = cd->caid >> 8;
99 netbuf[7] = cd->caid & 0xff;
100 netbuf[8] = (cd->provid >> 16) & 0xFF;
101 netbuf[9] = (cd->provid >> 8) & 0xff;
102 netbuf[10] = cd->provid & 0xff;
103 }
104 //}
105 netbuf[0] = (len - 2) >> 8;
106 netbuf[1] = (len - 2) & 0xff;
107 cs_ddump_mask(D_CLIENT, netbuf, len, "send %d bytes to %s", len, remote_txt());
108 if ((len = des_encrypt(netbuf, len, deskey)) < 0)
109 return -1;
110 netbuf[0] = (len - 2) >> 8;
111 netbuf[1] = (len - 2) & 0xff;
112 return send(handle, netbuf, len, 0);
113}
114
115static int network_message_receive(int handle, uint16 *netMsgId, uint8 *buffer,
116 uint8 *deskey, comm_type_t commType)
117{
118 int len, ncd_off, msgid;
119 uint8 netbuf[CWS_NETMSGSIZE];
120 int returnLen;
121 struct s_client *cl = cur_client();
122
123 if (!buffer || handle < 0)
124 return -1;
125 len = recv(handle, netbuf, 2, 0);
126 cs_debug_mask(D_CLIENT, "nmr(): len=%d, errno=%d", len, (len==-1)?errno:0);
127 if (!len) {
128 cs_debug_mask(D_CLIENT, "nmr: 1 return 0");
129 network_tcp_connection_close(cl, handle);
130 return 0;
131 }
132 if (len != 2) {
133 cs_debug_mask(D_CLIENT, "nmr: len!=2");
134 network_tcp_connection_close(cl, handle);
135 return -1;
136 }
137 if (((netbuf[0] << 8) | netbuf[1]) > CWS_NETMSGSIZE - 2) {
138 cs_debug_mask(D_CLIENT, "nmr: 1 return -1");
139 return -1;
140 }
141
142 len = recv(handle, netbuf+2, (netbuf[0] << 8) | netbuf[1], 0);
143 if (!len) {
144 cs_debug_mask(D_CLIENT, "nmr: 2 return 0");
145 return 0;
146 }
147 if (len != ((netbuf[0] << 8) | netbuf[1])) {
148 cs_debug_mask(D_CLIENT, "nmr: 2 return -1");
149 return -1;
150 }
151 len += 2;
152 if ((len = des_decrypt(netbuf, len, deskey)) < 11 ) { // 15(newcamd525) or 11 ???
153 cs_debug_mask(D_CLIENT, "nmr: can't decrypt, invalid des key?");
154 cs_sleepms(2000);
155 return -1;
156 }
157 //cs_ddump_mask(D_CLIENT, netbuf, len, "nmr: decrypted data, len=%d", len);
158 msgid = (netbuf[2] << 8) | netbuf[3];
159
160 if( cl->ncd_proto==NCD_AUTO ) {
161 // auto detect
162 int l5 = (((netbuf[13] & 0x0f) << 8) | netbuf[14]) + 3;
163 int l4 = (((netbuf[9] & 0x0f) << 8) | netbuf[10]) + 3;
164
165 if( (l5<=len-12) && ((netbuf[12]&0xF0)==0xE0 || (netbuf[12]&0xF0)==0x80) )
166 cl->ncd_proto = NCD_525;
167 else if( (l4<=len-8) && ((netbuf[8]&0xF0)==0xE0 || (netbuf[9]&0xF0)==0x80) )
168 cl->ncd_proto = NCD_524;
169 else {
170 cs_debug_mask(D_CLIENT, "nmr: 4 return -1");
171 return -1;
172 }
173
174 cs_debug_mask(D_CLIENT, "nmr: autodetect: newcamd52%d used", (cl->ncd_proto==NCD_525)?5:4);
175 }
176
177 ncd_off=(cl->ncd_proto==NCD_525)?4:0;
178
179 returnLen = (((netbuf[9+ncd_off] & 0x0f) << 8) | netbuf[10+ncd_off]) + 3;
180 if ( returnLen > (len-(8+ncd_off)) ) {
181 cs_debug_mask(D_CLIENT, "nmr: 4 return -1");
182 return -1;
183 }
184
185 //cs_ddump_mask(D_CLIENT, netbuf, len, "nmr: decrypted data");
186 if (netMsgId)
187 {
188 switch (commType)
189 {
190 case COMMTYPE_SERVER:
191 *netMsgId = msgid;
192 break;
193
194 case COMMTYPE_CLIENT:
195 //if (*netMsgId != ((netbuf[2] << 8) | netbuf[3])) {
196 cs_debug_mask(D_CLIENT, "nmr: netMsgId=%d, from server=%d, ", *netMsgId, msgid );
197 //return -2;
198 //}
199 break;
200
201 default:
202 cs_debug_mask(D_CLIENT, "nmr: 5 return -1");
203 return -1;
204 break;
205 }
206 }
207 switch(commType)
208 {
209 case COMMTYPE_SERVER:
210 buffer[0]=(cl->ncd_proto==NCD_525)?netbuf[4]:netbuf[6]; // sid
211 buffer[1]=(cl->ncd_proto==NCD_525)?netbuf[5]:netbuf[7];
212 break;
213 case COMMTYPE_CLIENT:
214 buffer[0]=netbuf[2]; // msgid
215 buffer[1]=netbuf[3];
216 break;
217 }
218
219 memcpy(buffer+2, netbuf+(8+ncd_off), returnLen);
220 return returnLen+2;
221}
222
223static void network_cmd_no_data_send(int handle, uint16 *netMsgId,
224 net_msg_type_t cmd, uint8 *deskey,
225 comm_type_t commType)
226{
227 uint8 buffer[CWS_NETMSGSIZE];
228
229 buffer[0] = cmd; buffer[1] = 0;
230 network_message_send(handle, netMsgId, buffer, 3, deskey, commType, 0, NULL);
231}
232
233static int network_cmd_no_data_receive(int handle, uint16 *netMsgId,
234 uint8 *deskey, comm_type_t commType)
235{
236 uint8 buffer[CWS_NETMSGSIZE];
237
238 if (network_message_receive(handle, netMsgId, buffer, deskey, commType) != 3+2)
239 return -1;
240 return buffer[2];
241}
242
243void newcamd_reply_ka()
244{
245 struct s_client *cl = cur_client();
246
247 if(!cl->udp_fd)
248 {
249 cs_debug_mask(D_CLIENT, "invalid client fd=%d", cl->udp_fd);
250 return;
251 }
252
253 cs_debug_mask(D_CLIENT, "send keepalive to client fd=%d", cl->udp_fd);
254
255 network_cmd_no_data_send(cl->udp_fd, &cl->ncd_msgid,
256 MSG_KEEPALIVE, cl->ncd_skey,COMMTYPE_SERVER);
257}
258
259static int connect_newcamd_server()
260{
261 int i;
262 uint8 buf[CWS_NETMSGSIZE];
263 uint8 keymod[14];
264 uint8 key[16];
265 int handle=0;
266
267 uint32 index;
268 uchar passwdcrypt[120];
269 uint8 login_answer;
270 int bytes_received;
271 struct s_client *cl = cur_client();
272
273 if(cl->reader->device[0] == 0 || cl->reader->r_pwd[0] == 0 ||
274 cl->reader->r_usr[0] == 0 || cl->reader->r_port == 0)
275 return -5;
276
277 // 1. Connect
278 handle = network_tcp_connection_open();
279 if(handle < 0) return -1;
280
281 // 2. Get init sequence
282 cl->reader->ncd_msgid = 0;
283 if( read(handle, keymod, sizeof(keymod)) != sizeof(keymod)) {
284 cs_log("server does not return 14 bytes");
285 network_tcp_connection_close(cl, handle);
286 return -2;
287 }
288 cs_ddump_mask(D_CLIENT, keymod, 14, "server init sequence:");
289 des_login_key_get(keymod, cl->reader->ncd_key, 14, key);
290
291 // 3. Send login info
292 index = 3;
293 buf[0] = MSG_CLIENT_2_SERVER_LOGIN;
294 buf[1] = 0;
295 strcpy((char *)buf+index, cl->reader->r_usr);
296 __md5_crypt(cl->reader->r_pwd, "$1$abcdefgh$", (char *)passwdcrypt);
297 index += strlen(cl->reader->r_usr)+1;
298 strcpy((char *)buf+index, (const char *)passwdcrypt);
299
300 network_message_send(handle, 0, buf, index+strlen((char *)passwdcrypt)+1, key,
301 COMMTYPE_CLIENT, NCD_CLIENT_ID, NULL);
302
303 // 3.1 Get login answer
304 login_answer=network_cmd_no_data_receive(handle, &cl->reader->ncd_msgid,
305 key, COMMTYPE_CLIENT);
306 if( login_answer == MSG_CLIENT_2_SERVER_LOGIN_NAK )
307 {
308 cs_log("login failed for user '%s'", cl->reader->r_usr);
309 network_tcp_connection_close(cl, handle);
310 return -3;
311 }
312 if( login_answer != MSG_CLIENT_2_SERVER_LOGIN_ACK )
313 {
314 cs_log("expected MSG_CLIENT_2_SERVER_LOGIN_ACK (%02X), received %02X",
315 MSG_CLIENT_2_SERVER_LOGIN_ACK, login_answer);
316 network_tcp_connection_close(cl, handle);
317 return -3;
318 }
319
320 // 3.2 Set connection info
321 cl->reader->tcp_connected = 1;
322
323 // 4. Send MSG_CARD_DATE_REQ
324 des_login_key_get(cl->reader->ncd_key, passwdcrypt, strlen((char *)passwdcrypt), key);
325
326 network_cmd_no_data_send(handle, &cl->reader->ncd_msgid, MSG_CARD_DATA_REQ,
327 key, COMMTYPE_CLIENT);
328 bytes_received = network_message_receive(handle, &cl->reader->ncd_msgid, buf,
329 key, COMMTYPE_CLIENT);
330 if( bytes_received < 16 || buf[2] != MSG_CARD_DATA ) {
331 cs_log("expected MSG_CARD_DATA (%02X), received %02X",
332 MSG_CARD_DATA, buf[2]);
333 network_tcp_connection_close(cl, handle);
334 return -4;
335 }
336
337 // 5. Parse CAID and PROVID(s)
338 cl->reader->caid[0] = (ushort)((buf[4+2]<<8) | buf[5+2]);
339
340 /* handle special serial format in newcamd. See newcamd_auth_client */
341 if (((cl->reader->caid[0] >> 8) == 0x17) || ((cl->reader->caid[0] >> 8) == 0x06)) {
342 memcpy(&cl->reader->hexserial, buf+10+2, 4);
343 int hexbase = cl->reader->hexserial[0];
344 cl->reader->hexserial[0] = cl->reader->hexserial[1];
345 cl->reader->hexserial[1] = cl->reader->hexserial[2];
346 cl->reader->hexserial[2] = cl->reader->hexserial[3];
347 cl->reader->hexserial[3] = hexbase;
348 }
349 else if (((cl->reader->caid[0] >> 8) == 0x05) || ((cl->reader->caid[0] >> 8) == 0x0D))
350 memcpy(&cl->reader->hexserial, buf+9+2, 5);
351 else
352 memcpy(&cl->reader->hexserial, buf+8+2, 6);
353
354 cs_log("Newcamd Server: %s:%d - UserID: %i", cl->reader->device, cl->reader->r_port, buf[3+2]);
355 cs_log("CAID: %04X - UA: %02X%02X%02X%02X%02X%02X%02X%02X - Provider # %i", cl->reader->caid[0], cl->reader->hexserial[0], cl->reader->hexserial[1], cl->reader->hexserial[2], cl->reader->hexserial[3], cl->reader->hexserial[4], cl->reader->hexserial[5], cl->reader->hexserial[6], cl->reader->hexserial[7], buf[14+2]);
356 cl->reader->nprov = buf[14+2];
357 memset(cl->reader->prid, 0x00, sizeof(cl->reader->prid));
358 for (i=0; i < cl->reader->nprov; i++) {
359 cl->reader->availkeys[i][0] = 1;
360 cl->reader->prid[i][0] = buf[15+2+11*i];
361 cl->reader->prid[i][1] = buf[16+2+11*i];
362 cl->reader->prid[i][2] = buf[17+2+11*i];
363 memcpy(&cl->reader->sa[i], buf+22+2+11*i, 4); // the 4 first bytes are not read
364 cs_log("Provider ID: %02X%02X%02X - SA: %02X%02X%02X%02X", cl->reader->prid[i][0], cl->reader->prid[i][1], cl->reader->prid[i][2], cl->reader->sa[i][0], cl->reader->sa[i][1], cl->reader->sa[i][2], cl->reader->sa[i][3]);
365 }
366 memcpy(cl->reader->ncd_skey, key, 16);
367
368 // 6. Set card inserted
369 cl->reader->tcp_connected = 2;
370 cl->reader->card_status = CARD_INSERTED;
371 cl->reader->last_g = cl->reader->last_s = time((time_t *)0);
372
373 // Only after connect() on cl->udp_fd (Linux)
374 cl->pfd=cl->udp_fd;
375
376 return 0;
377}
378
379static int newcamd_connect()
380{
381 struct s_client *cl = cur_client();
382
383 if (cl->reader->tcp_connected < 2 && connect_newcamd_server() < 0)
384 return 0;
385
386 if (!cl->udp_fd)
387 return 0;
388
389 return 1;
390}
391
392
393static int newcamd_send(uchar *buf, int ml, ushort sid)
394{
395 struct s_client *cl = cur_client();
396
397 if(!newcamd_connect())
398 return(-1);
399
400 return(network_message_send(cl->udp_fd, &cl->reader->ncd_msgid,
401 buf, ml, cl->reader->ncd_skey, COMMTYPE_CLIENT, sid, NULL));
402}
403
404static int newcamd_recv(struct s_client *client, uchar *buf, int UNUSED(l))
405{
406 int rc, rs;
407
408 if (client->typ == 'c')
409 {
410 rs=network_message_receive(client->udp_fd,
411 &client->ncd_msgid, buf,
412 client->ncd_skey, COMMTYPE_SERVER);
413 }
414 else
415 {
416 if (!client->udp_fd) return(-1);
417 rs=network_message_receive(client->udp_fd,
418 &client->reader->ncd_msgid,buf,
419 client->reader->ncd_skey, COMMTYPE_CLIENT);
420 }
421
422 if (rs<5) rc=(-1);
423 else rc=rs;
424
425 cs_ddump_mask(D_CLIENT, buf, rs, "received %d bytes from %s", rs, remote_txt());
426 client->last = time((time_t *) 0);
427
428 if( rc==-1 )
429 {
430 if (rs > 0)
431 cs_log("packet to small (%d bytes)", rs);
432 else
433 cs_log("Connection closed to %s", remote_txt());
434 }
435 return(rc);
436}
437
438static FILTER mk_user_au_ftab(struct s_reader *aureader)
439{
440 int i,j,found;
441 struct s_client *cl = cur_client();
442 FILTER filt;
443 FILTER *pufilt;
444
445 filt.caid = aureader->caid[0];
446 if (filt.caid == 0) filt.caid = cl->ftab.filts[0].caid;
447 filt.nprids = 0;
448 memset(&filt.prids, 0, sizeof(filt.prids));
449 pufilt = &cl->ftab.filts[0];
450
451 for( i=0; i<aureader->nprov; i++ )
452 filt.prids[filt.nprids++] = b2i(3, &aureader->prid[i][1]);
453
454 for( i=0; i<pufilt->nprids; i++ )
455 {
456 for( j=found=0; (!found)&&(j<filt.nprids); j++ )
457 if (pufilt->prids[i] == filt.prids[j]) found=1;
458 if( !found )
459 filt.prids[filt.nprids++] = pufilt->prids[i];
460 }
461
462 return filt;
463}
464
465static FILTER mk_user_ftab()
466{
467 FILTER *psfilt = 0;
468 FILTER filt;
469 int port_idx,i,j,k,c;
470 struct s_client *cl = cur_client();
471
472 filt.caid = 0;
473 filt.nprids = 0;
474 memset(&filt.prids, 0, sizeof(filt.prids));
475
476 port_idx = cl->port_idx;
477 psfilt = &cfg->ncd_ptab.ports[port_idx].ftab.filts[0];
478
479 // 1. CAID
480 // search server CAID in client CAID
481 for( c=i=0; i<CS_MAXCAIDTAB; i++ )
482 {
483 int ctab_caid;
484 ctab_caid = cl->ctab.caid[i]&cl->ctab.mask[i];
485 if( ctab_caid ) c++;
486
487 if( psfilt->caid==ctab_caid )
488 {
489 filt.caid=ctab_caid;
490 break;
491 }
492 }
493 if( c && !filt.caid )
494 {
495 cs_log("no valid CAID found in CAID for user '%s'", cl->usr);
496 return filt;
497 }
498
499 // search CAID in client IDENT
500 cs_debug_mask(D_CLIENT, "client[%8X].%s nfilts=%d, filt.caid=%04X", pthread_self(),
501 cl->usr, cl->ftab.nfilts, filt.caid);
502
503 if( !filt.caid && cl->ftab.nfilts )
504 {
505 int fcaids;
506 for( i=fcaids=0; i<cl->ftab.nfilts; i++ )
507 {
508 ushort ucaid=cl->ftab.filts[i].caid;
509 if( ucaid ) fcaids++;
510 if( ucaid && psfilt->caid==ucaid )
511 {
512 filt.caid = ucaid;
513 break;
514 }
515 }
516 if( fcaids==cl->ftab.nfilts && !filt.caid )
517 {
518 cs_log("no valid CAID found in IDENT for user '%s'", cl->usr);
519 //cs_disconnect_client();
520 return filt;
521 }
522 }
523 // empty client CAID - use server CAID
524 if( !filt.caid ) filt.caid=psfilt->caid;
525
526 // 2. PROVID
527 if( !cl->ftab.nfilts )
528 {
529 int add;
530 for (i=0; i<psfilt->nprids; i++) {
531 // use server PROVID(s) (and only those which are in user's groups)
532 add = 0;
533 struct s_reader *rdr;
534 for (rdr=first_reader; rdr ; rdr=rdr->next)
535 if (rdr->grp & cl->grp) {
536 if (!rdr->ftab.nfilts) {
537 if (rdr->typ & R_IS_NETWORK) add = 1;
538 for (j=0; !add && j<rdr->nprov; j++)
539 if (b2i(3, &rdr->prid[j][1]) == psfilt->prids[i]) add = 1;
540 } else {
541 for (j=0; !add && j<rdr->ftab.nfilts; j++) {
542 ulong rcaid = rdr->ftab.filts[j].caid;
543 if (!rcaid || rcaid == filt.caid) {
544 for (k=0; !add && k<rdr->ftab.filts[j].nprids; k++)
545 if (rdr->ftab.filts[j].prids[k] == psfilt->prids[i]) add = 1;
546 }
547 }
548 }
549 }
550 if (add) filt.prids[filt.nprids++] = psfilt->prids[i];
551 }
552 return filt;
553 }
554
555 // search in client IDENT
556 for( j=0; j<cl->ftab.nfilts; j++ )
557 {
558 ulong ucaid = cl->ftab.filts[j].caid;
559 cs_debug_mask(D_CLIENT, "client caid #%d: %04X", j, ucaid);
560 if( !ucaid || ucaid==filt.caid )
561 {
562 for (i=0; i<psfilt->nprids; i++)
563 {
564 cs_debug_mask(D_CLIENT, "search server provid #%d: %06X", i, psfilt->prids[i]);
565 if( cl->ftab.filts[j].nprids )
566 {
567 for( k=0; k<cl->ftab.filts[j].nprids; k++ )
568 if (cl->ftab.filts[j].prids[k] == psfilt->prids[i])
569 filt.prids[filt.nprids++]=cl->ftab.filts[j].prids[k];
570 } else {
571 filt.prids[filt.nprids++] = psfilt->prids[i];
572 // allow server PROVID(s) if no PROVID(s) specified in IDENT
573 }
574 }
575 }
576 }
577
578 if( !filt.nprids )
579 {
580 cs_log("no valid PROVID(s) found in CAID for user '%s'", cl->usr);
581 //cs_disconnect_client();
582 }
583
584 return filt;
585}
586
587static void newcamd_auth_client(in_addr_t ip, uint8 *deskey)
588{
589 int i, ok;
590 uchar *usr = NULL, *pwd = NULL;
591 char *client_name = NULL;
592 struct s_auth *account;
593 uchar buf[14];
594 uchar key[16];
595 uchar passwdcrypt[120];
596 struct s_reader *aureader=first_reader; //FIXME strange enough au was initialized to 0 = first reader, and not to -1 = no reader
597 struct s_ip *p_ip;
598 struct s_client *cl = cur_client();
599 uchar mbuf[1024];
600
601 ok = cfg->ncd_allowed ? 0 : 1;
602 for (p_ip=cfg->ncd_allowed; (p_ip) && (!ok); p_ip=p_ip->next)
603 ok=((ip>=p_ip->ip[0]) && (ip<=p_ip->ip[1]));
604
605 if (!ok)
606 {
607 cs_auth_client(cl, (struct s_auth *)0, NULL);
608 cs_exit(0);
609 }
610
611 // make random 14 bytes
612 for( i=0; i<14; i++ ) buf[i]=fast_rnd();
613
614 // send init sequence
615 send(cl->udp_fd, buf, 14, 0);
616 des_login_key_get(buf, deskey, 14, key);
617 memcpy(cl->ncd_skey, key, 16);
618 cl->ncd_msgid = 0;
619
620 i=process_input(mbuf, sizeof(mbuf), cfg->cmaxidle);
621 if ( i>0 )
622 {
623 if( mbuf[2] != MSG_CLIENT_2_SERVER_LOGIN )
624 {
625 cs_debug_mask(D_CLIENT, "expected MSG_CLIENT_2_SERVER_LOGIN (%02X), received %02X",
626 MSG_CLIENT_2_SERVER_LOGIN, mbuf[2]);
627 NULLFREE(cl->req);
628 cs_exit(0);
629 }
630 usr=mbuf+5;
631 pwd=usr+strlen((char *)usr)+1;
632 }
633 else
634 {
635 cs_debug_mask(D_CLIENT, "bad client login request");
636 NULLFREE(cl->req);
637 cs_exit(0);
638 }
639
640 sprintf(cl->ncd_client_id, "%02X%02X", mbuf[0], mbuf[1]);
641 client_name = get_ncd_client_name(cl->ncd_client_id);
642
643 for (ok=0, account=cfg->account; (usr) && (account) && (!ok); account=account->next)
644 {
645 cs_debug_mask(D_CLIENT, "account->usr=%s", account->usr);
646 if (strcmp((char *)usr, account->usr) == 0)
647 {
648 __md5_crypt(account->pwd, "$1$abcdefgh$", (char *)passwdcrypt);
649 cs_debug_mask(D_CLIENT, "account->pwd=%s", passwdcrypt);
650 if (strcmp((char *)pwd, (const char *)passwdcrypt) == 0)
651 {
652 cl->crypted=1;
653
654 if(cs_auth_client(cl, account, NULL) == 2) {
655 cs_log("hostname or ip mismatch for user %s (%s)", usr, client_name);
656 break;
657 }
658 else
659 {
660 cs_log("user %s authenticated successfully (%s)", usr, client_name);
661 ok = 1;
662 break;
663 }
664 }
665 else
666 cs_log("user %s is providing a wrong password (%s)", usr, client_name);
667 }
668 }
669
670 if (!ok && !account)
671 {
672 cs_log("user %s is trying to connect but doesnt exist ! (%s)", usr, client_name);
673 usr = 0;
674 }
675
676 // check for non ready reader and reject client
677 struct s_reader *rdr;
678 for (rdr=first_reader; rdr ; rdr=rdr->next) {
679 if(rdr->caid[0]==cfg->ncd_ptab.ports[cl->port_idx].ftab.filts[0].caid) {
680 if(rdr->card_status == CARD_NEED_INIT) {
681 cs_log("init for reader %s not finished -> reject client", rdr->label);
682 ok = 0;
683 }
684 break;
685 }
686 }
687
688 if (ok)
689 {
690 aureader = cl->aureader;
691 if (aureader)
692 {
693 if (cfg->ncd_ptab.ports[cl->port_idx].ftab.filts[0].caid != aureader->caid[0]
694 && cfg->ncd_ptab.ports[cl->port_idx].ftab.filts[0].caid != aureader->ftab.filts[0].caid
695 && aureader->typ != R_CCCAM) // disabling AU breaks cccam-au when cascading over newcamd, but with enabled au client was receiving wrong card data on faulty configured newcamd filters and when using betatunnel
696 {
697 cs_log("AU wont be used on this port -> disable AU");
698 aureader = NULL;
699 }
700 else
701 {
702 cs_log("AU enabled for user %s on reader %s", usr, aureader->label);
703 }
704 }
705 else
706 {
707 cs_log("AU disabled for user %s", usr);
708 }
709 }
710
711 network_cmd_no_data_send(cl->udp_fd, &cl->ncd_msgid,
712 (ok)?MSG_CLIENT_2_SERVER_LOGIN_ACK:MSG_CLIENT_2_SERVER_LOGIN_NAK,
713 cl->ncd_skey, COMMTYPE_SERVER);
714
715 if (ok)
716 {
717 FILTER *pufilt = 0;
718
719 des_login_key_get(deskey, passwdcrypt, strlen((char *)passwdcrypt), key);
720 memcpy(cl->ncd_skey, key, 16);
721
722 i=process_input(mbuf, sizeof(mbuf), cfg->cmaxidle);
723 if( i>0 )
724 {
725 int j,len=15;
726 if( mbuf[2] != MSG_CARD_DATA_REQ)
727 {
728 cs_debug_mask(D_CLIENT, "expected MSG_CARD_DATA_REQ (%02X), received %02X",
729 MSG_CARD_DATA_REQ, mbuf[2]);
730 NULLFREE(cl->req);
731 cs_exit(0);
732 }
733
734 // set userfilter
735 cl->ftab.filts[0] = mk_user_ftab();
736
737 // set userfilter for au enabled clients
738 if (aureader)
739 cl->ftab.filts[0] = mk_user_au_ftab(aureader);
740
741 pufilt = &cl->ftab.filts[0];
742 cl->ftab.nfilts = 1;
743
744 mbuf[0] = MSG_CARD_DATA;
745 mbuf[1] = 0x00;
746 mbuf[2] = 0x00;
747
748 if(aureader)
749 mbuf[3] = 1;
750 else
751 mbuf[3] = get_threadnum(cl)+10; // Unique user number
752
753 mbuf[4] = (uchar)(pufilt->caid>>8);
754 mbuf[5] = (uchar)(pufilt->caid);
755 mbuf[6] = 0x00;
756 mbuf[7] = 0x00;
757
758 if (aureader)
759 {
760 if (((pufilt->caid >> 8) == 0x17) || ((pufilt->caid >> 8) == 0x06)) // Betacrypt or Irdeto
761 {
762 // only 4 Bytes Hexserial for newcamd clients (Hex Base + Hex Serial)
763 // first 2 Byte always 00
764 mbuf[8]=0x00; //serial only 4 bytes
765 mbuf[9]=0x00; //serial only 4 bytes
766 // 1 Byte Hex Base (see reader-irdeto.c how this is stored in "aureader->hexserial")
767 mbuf[10]=aureader->hexserial[3];
768 // 3 Bytes Hex Serial (see reader-irdeto.c how this is stored in "aureader->hexserial")
769 mbuf[11]=aureader->hexserial[0];
770 mbuf[12]=aureader->hexserial[1];
771 mbuf[13]=aureader->hexserial[2];
772 }
773 else if (((pufilt->caid >> 8) == 0x05) || ((pufilt->caid >> 8) == 0x0D))
774 {
775 mbuf[8] = 0x00;
776 mbuf[9] = aureader->hexserial[0];
777 mbuf[10] = aureader->hexserial[1];
778 mbuf[11] = aureader->hexserial[2];
779 mbuf[12] = aureader->hexserial[3];
780 mbuf[13] = aureader->hexserial[4];
781 }
782 else
783 {
784 mbuf[8] = aureader->hexserial[0];
785 mbuf[9] = aureader->hexserial[1];
786 mbuf[10] = aureader->hexserial[2];
787 mbuf[11] = aureader->hexserial[3];
788 mbuf[12] = aureader->hexserial[4];
789 mbuf[13] = aureader->hexserial[5];
790 }
791 }
792 else
793 {
794 cl->aureader = NULL;
795 mbuf[8] = 0x00;
796 mbuf[9] = 0x00;
797 mbuf[10] = 0x00;
798 mbuf[11] = 0x00;
799 mbuf[12] = 0x00;
800 mbuf[13] = 0x00;
801 }
802 mbuf[14] = pufilt->nprids;
803 for( j=0; j<pufilt->nprids; j++)
804 {
805 if (((pufilt->caid >> 8) == 0x17) || ((pufilt->caid >> 8) == 0x06)) // Betacrypt or Irdeto
806 {
807 mbuf[15+11*j] = 0;
808 mbuf[16+11*j] = 0;
809 mbuf[17+11*j] = j;
810 }
811 else
812 {
813 mbuf[15+11*j] = (uchar)(pufilt->prids[j]>>16);
814 mbuf[16+11*j] = (uchar)(pufilt->prids[j]>>8);
815 mbuf[17+11*j] = (uchar)(pufilt->prids[j]);
816 }
817 mbuf[18+11*j] = 0x00;
818 mbuf[19+11*j] = 0x00;
819 mbuf[20+11*j] = 0x00;
820 mbuf[21+11*j] = 0x00;
821 if (aureader)
822 {
823 // check if user provid from IDENT exists on card
824 int k, found;
825 ulong rprid;
826 found=0;
827 if( pufilt->caid==aureader->caid[0] )
828 {
829 for( k=0; (k<aureader->nprov); k++ )
830 {
831 rprid=b2i(3, &aureader->prid[k][1]);
832 if( rprid==pufilt->prids[j] )
833 {
834 if (((pufilt->caid >> 8) == 0x17) || ((pufilt->caid >> 8) == 0x06)) // Betacrypt or Irdeto
835 {
836 mbuf[22+11*j] = aureader->prid[k][0];
837 mbuf[23+11*j] = aureader->prid[k][1];
838 mbuf[24+11*j] = aureader->prid[k][2];
839 mbuf[25+11*j] = aureader->prid[k][3];
840 }
841 else
842 {
843 mbuf[22+11*j] = aureader->sa[k][0];
844 mbuf[23+11*j] = aureader->sa[k][1];
845 mbuf[24+11*j] = aureader->sa[k][2];
846 mbuf[25+11*j] = aureader->sa[k][3];
847 }
848 found=1;
849 break;
850 }
851 }
852 }
853 if( !found )
854 {
855 mbuf[22+11*j] = 0x00;
856 mbuf[23+11*j] = 0x00;
857 mbuf[24+11*j] = 0x00;
858 mbuf[25+11*j] = 0x00;
859 }
860 }
861 else
862 {
863 if (((pufilt->caid >> 8) == 0x17) || ((pufilt->caid >> 8) == 0x06)) // Betacrypt or Irdeto
864 {
865 mbuf[22+11*j] = 0x00;
866 mbuf[23+11*j] = (uchar)(pufilt->prids[j]>>16);
867 mbuf[24+11*j] = (uchar)(pufilt->prids[j]>>8);
868 mbuf[25+11*j] = (uchar)(pufilt->prids[j]);
869 }
870 else
871 {
872 mbuf[22+11*j] = 0x00;
873 mbuf[23+11*j] = 0x00;
874 mbuf[24+11*j] = 0x00;
875 mbuf[25+11*j] = 0x00;
876 }
877 }
878 len+=11;
879 }
880
881 custom_data_t cd;
882 memset(&cd, 0, sizeof(cd));
883
884 if (aureader)
885 {
886 if (aureader->blockemm_g)
887 cd.sid |= 4;
888 if (aureader->blockemm_s)
889 cd.sid |= 2;
890 if (aureader->blockemm_u)
891 cd.sid |= 1;
892 }
893
894 if( network_message_send(cl->udp_fd, &cl->ncd_msgid,
895 mbuf, len, key, COMMTYPE_SERVER, 0, &cd) <0 )
896 {
897 NULLFREE(cl->req);
898 cs_exit(0);
899 }
900 }
901 }
902 else
903 {
904 cs_auth_client(cl, 0, usr ? "login failure" : "no such user");
905 NULLFREE(cl->req);
906 cs_exit(0);
907 }
908}
909
910static void newcamd_send_dcw(struct s_client *client, ECM_REQUEST *er)
911{
912 int len;
913 ushort cl_msgid;
914 uchar mbuf[1024];
915
916 if (!client->udp_fd) {
917 cs_debug_mask(D_CLIENT, "ncd_send_dcw: error: client->udp_fd=%d", client->udp_fd);
918 return;
919 }
920 memcpy(&cl_msgid, client->req+(er->cpti*REQ_SIZE), 2); // get client ncd_msgid + 0x8x
921 mbuf[0] = er->ecm[0];
922 if( client->ftab.filts[0].nprids==0 || er->rc>3 /*not found*/)
923 {
924 len=3;
925 mbuf[1] = mbuf[2] = 0x00;
926 }
927 else
928 {
929 len = 19;
930 mbuf[1] = mbuf[2] = 0x10;
931 memcpy(mbuf+3, er->cw, 16);
932 }
933
934 cs_debug_mask(D_CLIENT, "ncd_send_dcw: er->cpti=%d, cl_msgid=%d, %02X", er->cpti, cl_msgid, mbuf[0]);
935
936 network_message_send(client->udp_fd, &cl_msgid, mbuf, len,
937 client->ncd_skey, COMMTYPE_SERVER, 0, NULL);
938}
939
940static void newcamd_process_ecm(uchar *buf)
941{
942 int pi;
943 struct s_client *cl = cur_client();
944 ECM_REQUEST *er;
945
946 if (!(er=get_ecmtask())) {
947 return;
948 }
949 // save client ncd_msgid
950 memcpy(cl->req+(er->cpti*REQ_SIZE), &cl->ncd_msgid, 2);
951 cs_debug_mask(D_CLIENT, "ncd_process_ecm: er->cpti=%d, cl_msgid=%d, %02X", er->cpti,
952 cl->ncd_msgid, buf[2]);
953 er->l=buf[4]+3;
954 er->srvid = (buf[0]<<8)|buf[1];
955 er->caid = 0;
956 pi = cl->port_idx;
957 if( cfg->ncd_ptab.nports && cfg->ncd_ptab.nports >= pi )
958 er->caid=cfg->ncd_ptab.ports[pi].ftab.filts[0].caid;
959 memcpy(er->ecm, buf+2, er->l);
960 get_cw(cl, er);
961}
962
963static void newcamd_process_emm(uchar *buf)
964{
965 int ok=1;
966 ushort caid;
967 struct s_client *cl = cur_client();
968 EMM_PACKET epg;
969
970 memset(&epg, 0, sizeof(epg));
971 struct s_reader *aureader=cl->aureader;
972
973 // if client is not allowed to do AU just send back the OK-answer to
974 // the client and do nothing else with the received data
975 if (aureader)
976 {
977 epg.l=buf[2]+3;
978 caid = cl->ftab.filts[0].caid;
979 epg.caid[0] = (uchar)(caid>>8);
980 epg.caid[1] = (uchar)(caid);
981
982 epg.provid[0] = (uchar)(aureader->auprovid>>24);
983 epg.provid[1] = (uchar)(aureader->auprovid>>16);
984 epg.provid[2] = (uchar)(aureader->auprovid>>8);
985 epg.provid[3] = (uchar)(aureader->auprovid);
986
987/* if (caid == 0x0500)
988 {
989 ushort emm_head;
990
991 emm_head = (buf[0]<<8) | buf[1];
992 switch( emm_head )
993 {
994 case 0x8e70: // EMM-S
995 memcpy(epg.hexserial+1, buf+3, 4);
996 epg.hexserial[4]=aureader->hexserial[4];
997 break;
998 case 0x8870: // EMM-U
999 case 0x8c70: // confidential ?
1000 default:
1001 cs_log("unsupported emm type: %04X", emm_head);
1002 ok=0;
1003 }
1004 if( !ok ) cs_log("only EMM-S supported");
1005 }
1006 else*/
1007
1008 memcpy(epg.emm, buf, epg.l);
1009 if( ok )
1010 do_emm(cl, &epg);
1011 }
1012
1013 // Should always send an answer to client (also if au is disabled),
1014 // some clients will disconnect if they get no answer
1015 buf[1] = 0x10;
1016 buf[2] = 0x00;
1017 network_message_send(cl->udp_fd, &cl->ncd_msgid, buf, 3,
1018 cl->ncd_skey, COMMTYPE_SERVER, 0, NULL);
1019}
1020
1021static void * newcamd_server(void *cli)
1022{
1023 int rc;
1024 struct s_client * client = (struct s_client *) cli;
1025 client->thread=pthread_self();
1026 pthread_setspecific(getclient, cli);
1027 uchar mbuf[1024];
1028
1029 client->req=(uchar *)malloc(CS_MAXPENDING*REQ_SIZE);
1030 if (!client->req)
1031 {
1032 cs_log("Cannot allocate memory (errno=%d)", errno);
1033 cs_exit(1);
1034 }
1035
1036 memset(client->req, 0, CS_MAXPENDING*REQ_SIZE);
1037 client->ncd_server = 1;
1038 cs_log("client connected to %d port", cfg->ncd_ptab.ports[client->port_idx].s_port);
1039
1040 if (cfg->ncd_ptab.ports[client->port_idx].ncd_key_is_set) {
1041 //port has a des key specified
1042 newcamd_auth_client(client->ip, cfg->ncd_ptab.ports[client->port_idx].ncd_key);
1043 } else {
1044 //default global des key
1045 newcamd_auth_client(client->ip, cfg->ncd_key);
1046 }
1047
1048 // report all cards if using extended mg proto
1049 if (cfg->ncd_mgclient) {
1050 cs_debug_mask(D_CLIENT, "newcamd: extended: report all available cards");
1051 int j, k;
1052 uint8 buf[512];
1053 custom_data_t *cd = malloc(sizeof(struct custom_data));
1054 memset(cd, 0, sizeof(struct custom_data));
1055 memset(buf, 0, sizeof(buf));
1056
1057 buf[0] = MSG_SERVER_2_CLIENT_ADDCARD;
1058
1059 struct s_reader *rdr;
1060 for (rdr=first_reader; rdr ; rdr=rdr->next) {
1061 int flt = 0;
1062 if (!(rdr->grp & client->grp)) continue; //test - skip unaccesible readers
1063 if (rdr->ftab.filts) {
1064 for (j=0; j<CS_MAXFILTERS; j++) {
1065 if (rdr->ftab.filts[j].caid) {
1066 cd->caid = rdr->ftab.filts[j].caid;
1067 for (k=0; k<rdr->ftab.filts[j].nprids; k++) {
1068 cd->provid = rdr->ftab.filts[j].prids[k];
1069 cs_debug_mask(D_CLIENT, "newcamd: extended: report card");
1070
1071 network_message_send(client->udp_fd,
1072 &client->ncd_msgid, buf, 3,
1073 client->ncd_skey, COMMTYPE_SERVER, 0, cd);
1074
1075 flt = 1;
1076 }
1077 }
1078 }
1079 }
1080
1081 if (rdr->caid[0] && !flt) {
1082 if ((rdr->tcp_connected || rdr->card_status == CARD_INSERTED)) {
1083 cd->caid = rdr->caid[0];
1084 for (j=0; j<rdr->nprov; j++) {
1085 if (rdr->card_status == CARD_INSERTED)
1086 cd->provid = (rdr->prid[j][1]) << 16
1087 | (rdr->prid[j][2] << 8) | rdr->prid[j][3];
1088 else
1089 cd->provid = (rdr->prid[j][0]) << 16
1090 | (rdr->prid[j][1] << 8) | rdr->prid[j][2];
1091
1092 cs_debug_mask(D_CLIENT, "newcamd: extended: report card");
1093 network_message_send(client->udp_fd,
1094 &client->ncd_msgid, buf, 3,
1095 client->ncd_skey, COMMTYPE_SERVER, 0, cd);
1096 }
1097 }
1098 }
1099 }
1100 free(cd);
1101 }
1102
1103 // check for clienttimeout, if timeout occurs try to send keepalive / wait for answer
1104 // befor client was disconnected. If keepalive was disabled, exit after clienttimeout
1105 rc=-9;
1106 while(rc==-9)
1107 {
1108 if (!client->pfd) break;
1109 // process_input returns -9 on clienttimeout
1110 while ((rc=process_input(mbuf, sizeof(mbuf), cfg->cmaxidle))>0)
1111 {
1112 switch(mbuf[2])
1113 {
1114 case 0x80:
1115 case 0x81:
1116 newcamd_process_ecm(mbuf);
1117 break;
1118
1119 case MSG_KEEPALIVE:
1120 newcamd_reply_ka();
1121 break;
1122
1123 default:
1124 if(mbuf[2]>0x81 && mbuf[2]<0x90)
1125 newcamd_process_emm(mbuf+2);
1126 else
1127 {
1128 cs_debug_mask(D_CLIENT, "unknown newcamd command! (%d)", mbuf[2]);
1129 }
1130 }
1131 }
1132
1133 if(rc==-9)
1134 {
1135 if (client->ncd_keepalive)
1136 newcamd_reply_ka();
1137 else
1138 rc=0;
1139 }
1140 }
1141
1142 NULLFREE(client->req);
1143 cs_disconnect_client(client);
1144 return NULL;
1145}
1146
1147/*
1148* client functions
1149*/
1150
1151int newcamd_client_init(struct s_client *client)
1152{
1153 struct sockaddr_in loc_sa;
1154 struct protoent *ptrp;
1155 int p_proto;
1156 char ptxt[16];
1157
1158 client->pfd=0;
1159 if (client->reader->r_port<=0)
1160 {
1161 cs_log("invalid port %d for server %s", client->reader->r_port, client->reader->device);
1162 return(1);
1163 }
1164 if( (ptrp=getprotobyname("tcp")) )
1165 p_proto=ptrp->p_proto;
1166 else
1167 p_proto=6;
1168
1169 client->ip=0;
1170 memset((char *)&loc_sa,0,sizeof(loc_sa));
1171 loc_sa.sin_family = AF_INET;
1172#ifdef LALL
1173 if (cfg->serverip[0])
1174 loc_sa.sin_addr.s_addr = inet_addr(cfg->serverip);
1175 else
1176#endif
1177 loc_sa.sin_addr.s_addr = INADDR_ANY;
1178 loc_sa.sin_port = htons(client->reader->l_port);
1179
1180 if ((client->udp_fd=socket(PF_INET, SOCK_STREAM, p_proto))<0)
1181 {
1182 cs_log("Socket creation failed (errno=%d)", errno);
1183 cs_exit(1);
1184 }
1185
1186#ifdef SO_PRIORITY
1187 if (cfg->netprio)
1188 setsockopt(client->udp_fd, SOL_SOCKET, SO_PRIORITY,
1189 (void *)&cfg->netprio, sizeof(ulong));
1190#endif
1191 if (!client->reader->tcp_ito) {
1192 ulong keep_alive = client->reader->tcp_ito?1:0;
1193 setsockopt(client->udp_fd, SOL_SOCKET, SO_KEEPALIVE,
1194 (void *)&keep_alive, sizeof(ulong));
1195 }
1196
1197 if (client->reader->l_port>0)
1198 {
1199 if (bind(client->udp_fd, (struct sockaddr *)&loc_sa, sizeof (loc_sa))<0)
1200 {
1201 cs_log("bind failed (errno=%d)", errno);
1202 close(client->udp_fd);
1203 return(1);
1204 }
1205 sprintf(ptxt, ", port=%d", client->reader->l_port);
1206 }
1207 else
1208 ptxt[0]='\0';
1209
1210 memset((char *)&client->udp_sa,0,sizeof(client->udp_sa));
1211 client->udp_sa.sin_family = AF_INET;
1212 client->udp_sa.sin_port = htons((u_short)client->reader->r_port);
1213
1214 client->ncd_proto=client->reader->ncd_proto;
1215
1216 cs_log("proxy %s:%d newcamd52%d (fd=%d%s)",
1217 client->reader->device, client->reader->r_port,
1218 (client->reader->ncd_proto==NCD_525)?5:4, client->udp_fd, ptxt);
1219
1220 return(0);
1221}
1222
1223static int newcamd_send_ecm(struct s_client *client, ECM_REQUEST *er, uchar *buf)
1224{
1225 struct s_reader *rdr = client->reader;
1226
1227 if(!newcamd_connect())
1228 return (-1);
1229
1230 // check server filters
1231 if(!chk_rsfilter(rdr, er))
1232 return(-1);
1233
1234 memcpy(buf, er->ecm, er->l);
1235 return((newcamd_send(buf, er->l, er->srvid)<1) ? (-1) : 0);
1236}
1237
1238
1239static int newcamd_send_emm(EMM_PACKET *ep)
1240{
1241 uchar buf[200];
1242
1243 if(!newcamd_connect())
1244 return (-1);
1245
1246 memcpy(buf, ep->emm, ep->l);
1247 return((newcamd_send(buf, ep->l, 0)<1) ? 0 : 1);
1248}
1249
1250static int newcamd_recv_chk(struct s_client *client, uchar *dcw, int *rc, uchar *buf, int n)
1251{
1252 ushort idx;
1253 *client = *client; //suppress compiler error, but recv_chk should comply to other recv_chk routines...
1254 if( n<21 ) // no cw, ignore others
1255 return(-1);
1256 *rc = 1;
1257 idx = (buf[0] << 8) | buf[1];
1258 memcpy(dcw, buf+5, 16);
1259 return(idx);
1260}
1261
1262void module_newcamd(struct s_module *ph)
1263{
1264 strcpy(ph->desc, "newcamd");
1265 ph->type=MOD_CONN_TCP;
1266 ph->logtxt = ", crypted";
1267 ph->multi=1;
1268 ph->watchdog=1;
1269 ph->s_ip=cfg->ncd_srvip;
1270 ph->s_handler=newcamd_server;
1271 ph->recv=newcamd_recv;
1272 ph->send_dcw=newcamd_send_dcw;
1273 ph->ptab=&cfg->ncd_ptab;
1274 if( ph->ptab->nports==0 )
1275 ph->ptab->nports=1; // show disabled in log
1276 ph->c_multi=1;
1277 ph->c_init=newcamd_client_init;
1278 ph->c_recv_chk=newcamd_recv_chk;
1279 ph->c_send_ecm=newcamd_send_ecm;
1280 ph->c_send_emm=newcamd_send_emm;
1281 ph->num=R_NEWCAMD;
1282}
Note: See TracBrowser for help on using the repository browser.