1 #define MODULE_LOG_PREFIX "pandora"
7 #include "cscrypt/md5.h"
8 #include "oscam-client.h"
10 #include "oscam-net.h"
11 #include "oscam-string.h"
13 #define CWS_NETMSGSIZE 320
14 #define START_TIME 150000
15 #define MAX_TIME 500000
17 static void simple_crypt(uchar
*buf
, int len
, uchar
*key
, int key_len
)
20 for(i
= 0, x
= 0; i
< len
; i
++)
28 static void pandora_process_request(struct s_client
*cl
, uchar
*buf
, int32_t l
)
32 uchar md5tmp
[MD5_DIGEST_LENGTH
];
34 if(l
< 10 + CS_ECMSTORESIZE
+ 2)
37 if(!(er
= get_ecmtask()))
39 er
->caid
= b2i(2, buf
+ 1);
40 er
->srvid
= b2i(2, buf
+ 3);
41 er
->prid
= b2i(4, buf
+ 5);
42 //er->ecmcrc32 = crc32(0L, buf+10, CS_ECMSTORESIZE);
43 er
->chid
= b2i(2, buf
+ 10 + CS_ECMSTORESIZE
);
45 if(!cl
->pand_ignore_ecm
&& (l
>= 10 + CS_ECMSTORESIZE
+ 2 + 2))
47 ecmlen
= b2i(2, buf
+ 10 + CS_ECMSTORESIZE
+ 2);
49 if(ecmlen
< 0 || ecmlen
> MAX_ECM_SIZE
50 || ((10 + CS_ECMSTORESIZE
+ 2 + 2 + ecmlen
) > CWS_NETMSGSIZE
)
51 || ((10 + CS_ECMSTORESIZE
+ 2 + 2 + ecmlen
) > l
))
58 MD5(buf
+ 14 + CS_ECMSTORESIZE
, ecmlen
, md5tmp
),
62 memcpy(er
->ecm
, buf
+ 14 + CS_ECMSTORESIZE
, ecmlen
);
63 //set_ecmhash(cl, er);
73 { usleep(cl
->pand_autodelay
); }
77 static int pandora_recv(struct s_client
*cl
, uchar
*buf
, int32_t l
)
84 { ret
= recv_from_udpipe(buf
); }
87 ret
= recvfrom(cl
->udp_fd
, buf
, l
, 0, (struct sockaddr
*)&cl
->udp_sa
, &cl
->udp_sa_len
);
92 simple_crypt(buf
, ret
, cl
->pand_md5_key
, 16);
93 cl
->last
= time((time_t *) 0);
96 { pandora_process_request(cl
, buf
, ret
); }
100 static void pandora_send_dcw(struct s_client
*cl
, ECM_REQUEST
*er
)
102 uchar msgbuf
[CWS_NETMSGSIZE
], len
;
103 if(cfg
.pand_skip_send_dw
)
105 if(er
->rc
< E_NOTFOUND
)
107 msgbuf
[0] = 2; //DW_FOUND
108 memcpy(&msgbuf
[1], er
->cw
, 16);
110 cl
->pand_autodelay
= START_TIME
;
114 msgbuf
[0] = 0xFF; //DW_NOT_FOUND
116 if(cl
->pand_autodelay
< MAX_TIME
)
117 { cl
->pand_autodelay
+= 100000; }
119 simple_crypt(msgbuf
, len
, cl
->pand_md5_key
, 16);
120 sendto(cl
->udp_fd
, msgbuf
, len
, 0, (struct sockaddr
*) &cl
->udp_sa
, cl
->udp_sa_len
);
123 int pandora_auth_client(struct s_client
*cl
, IN_ADDR_T ip
)
126 struct s_auth
*account
;
129 // FIXME: Add IPv6 support
130 (void)ip
; // Prevent warning about unused var "ip"
132 if(!cl
->pand_ignore_ecm
&& cfg
.pand_allowed
)
135 for(ok
= 0, p_ip
= cfg
.pand_allowed
; (p_ip
) && (!ok
); p_ip
137 { ok
= ((ip
>= p_ip
->ip
[0]) && (ip
<= p_ip
->ip
[1])); }
141 cs_auth_client(cl
, (struct s_auth
*) 0, "IP not allowed");
147 for(ok
= 0, account
= cfg
.account
; cfg
.pand_usr
&& account
&& !ok
; account
= account
->next
)
149 ok
= streq(cfg
.pand_usr
, account
->usr
);
150 if(ok
&& cs_auth_client(cl
, account
, NULL
))
151 { cs_disconnect_client(cl
); }
154 { cs_auth_client(cl
, (struct s_auth
*)(-1), NULL
); }
158 static void *pandora_server(struct s_client
*cl
, uchar
*UNUSED(mbuf
),
161 uchar md5tmp
[MD5_DIGEST_LENGTH
];
166 cl
->pand_autodelay
= 150000;
167 memcpy(cl
->pand_md5_key
,
168 MD5((uchar
*)cfg
.pand_pass
, strlen(cfg
.pand_pass
), md5tmp
), 16);
169 cl
->pand_ignore_ecm
= (cfg
.pand_ecm
) ? 0 : 1;
171 pandora_auth_client(cl
, cl
->ip
);
176 cs_log("Password for Pandora share MUST be set !!!");
182 /************************************************************************************************************************
184 *************************************************************************************************************************/
185 int pandora_client_init(struct s_client
*cl
)
187 static struct sockaddr_in loc_sa
;
190 struct s_reader
*rdr
= cl
->reader
;
191 uchar md5tmp
[MD5_DIGEST_LENGTH
];
196 cs_log("invalid port %d for server %s", rdr
->r_port
, rdr
->device
);
199 p_proto
= IPPROTO_UDP
;
201 set_null_ip(&cl
->ip
);
202 memset((char *) &loc_sa
, 0, sizeof(loc_sa
));
203 loc_sa
.sin_family
= AF_INET
;
205 if(IP_ISSET(cfg
.srvip
))
206 { IP_ASSIGN(SIN_GET_ADDR(loc_sa
), cfg
.srvip
); }
208 { loc_sa
.sin_addr
.s_addr
= INADDR_ANY
; }
209 loc_sa
.sin_port
= htons(rdr
->l_port
);
211 if((cl
->udp_fd
= socket(PF_INET
, SOCK_DGRAM
, p_proto
)) < 0)
213 cs_log("Socket creation failed (errno=%d)", errno
);
218 setsockopt(cl
->udp_fd
, SOL_SOCKET
, SO_REUSEADDR
, &opt
, sizeof(opt
));
220 set_so_reuseport(cl
->udp_fd
);
222 set_socket_priority(cl
->udp_fd
, cfg
.netprio
);
226 if(bind(cl
->udp_fd
, (struct sockaddr
*) &loc_sa
, sizeof(loc_sa
)) < 0)
228 cs_log("bind failed (errno=%d)", errno
);
232 snprintf(ptxt
, sizeof(ptxt
), ", port=%d", rdr
->l_port
);
237 memcpy(cl
->pand_md5_key
, MD5((uchar
*)rdr
->r_pwd
, strlen(rdr
->r_pwd
), md5tmp
), 16);
240 //cl->grp = 0xFFFFFFFF;
241 //rdr->caid[0] = rdr->ctab.caid[0];
243 cl
->pand_send_ecm
= rdr
->pand_send_ecm
;
244 memset((char *) &cl
->udp_sa
, 0, sizeof(cl
->udp_sa
));
246 ((struct sockaddr_in
*)(&cl
->udp_sa
))->sin_family
= AF_INET
;
247 ((struct sockaddr_in
*)(&cl
->udp_sa
))->sin_port
= htons((u_short
) rdr
->r_port
);
249 cl
->udp_sa
.sin_family
= AF_INET
;
250 cl
->udp_sa
.sin_port
= htons((u_short
) rdr
->r_port
);
253 cs_log("proxy %s:%d pandora %s (%s)", rdr
->device
, rdr
->r_port
, rdr
->pand_send_ecm
? "with ECM support" : "", ptxt
);
255 cl
->pfd
= cl
->udp_fd
;
256 //set_nonblock(cl->udp_fd, true); //!!!!!
260 static int pandora_send_ecm(struct s_client
*cl
, ECM_REQUEST
*er
)
262 uchar md5tmp
[MD5_DIGEST_LENGTH
];
263 uchar msgbuf
[CWS_NETMSGSIZE
];
266 adel
= (cfg
.ctimeout
> 7) ? 7 : cfg
.ctimeout
;
269 msgbuf
[1] = er
->caid
>> 8;
270 msgbuf
[2] = er
->caid
& 0xFF;
271 msgbuf
[3] = er
->srvid
>> 8;
272 msgbuf
[4] = er
->srvid
& 0xFF;
273 msgbuf
[5] = er
->prid
>> 24;
274 msgbuf
[6] = er
->prid
>> 16;
275 msgbuf
[7] = er
->prid
>> 8;
276 msgbuf
[8] = er
->prid
& 0xFF;
278 memcpy(&msgbuf
[10], MD5(er
->ecm
, er
->ecmlen
, md5tmp
), CS_ECMSTORESIZE
);
279 msgbuf
[10 + CS_ECMSTORESIZE
] = er
->chid
>> 8;
280 msgbuf
[11 + CS_ECMSTORESIZE
] = er
->chid
& 0xFF;
281 len
= 12 + CS_ECMSTORESIZE
;
282 if(cl
->pand_send_ecm
)
284 if(len
+2+er
->ecmlen
> CWS_NETMSGSIZE
)
286 msgbuf
[12 + CS_ECMSTORESIZE
] = er
->ecmlen
>> 8;
287 msgbuf
[13 + CS_ECMSTORESIZE
] = er
->ecmlen
& 0xFF;
288 memcpy(&msgbuf
[14 + CS_ECMSTORESIZE
], er
->ecm
, er
->ecmlen
);
289 len
+= er
->ecmlen
+ 2;
291 simple_crypt(msgbuf
, len
, cl
->pand_md5_key
, 16);
292 ret
= sendto(cl
->pfd
, msgbuf
, len
, 0, (struct sockaddr
*) &cl
->udp_sa
, cl
->udp_sa_len
);
293 return ((ret
< len
) ? (-1) : 0);
296 static int pandora_recv_chk(struct s_client
*UNUSED(cl
), uchar
*dcw
, int *rc
,
297 uchar
*buf
, int UNUSED(n
))
302 memcpy(dcw
, buf
+ 1, 16);
306 void module_pandora(struct s_module
*ph
)
309 ph
->ptab
.ports
[0].s_port
= cfg
.pand_port
;
312 ph
->desc
= "pandora";
313 ph
->type
= MOD_CONN_UDP
;
314 ph
->large_ecm_support
= 1;
316 IP_ASSIGN(ph
->s_ip
, cfg
.pand_srvip
);
317 ph
->s_handler
= pandora_server
;
318 ph
->recv
= pandora_recv
;
319 ph
->send_dcw
= pandora_send_dcw
;
321 ph
->c_init
= pandora_client_init
;
322 ph
->c_recv_chk
= pandora_recv_chk
;
323 ph
->c_send_ecm
= pandora_send_ecm
;