source: trunk/module-newcamd.c@ 109

Last change on this file since 109 was 97, checked in by polo, 11 years ago

o patch for the newcamd idle bug, based on the fix from KrazyIvan in mpcs 1.0.
o changed the logging to see the newcamd-client dest port if a client connects to oscam.
thanks merek for this patch.

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