revert breaks some stupid old compilers
[oscam.git] / module-gbox-remm.c
bloba01f60542855091a61582617e74f255c22defa6f
1 #define MODULE_LOG_PREFIX "gbox/remm"
3 #include "globals.h"
5 #ifdef MODULE_GBOX
6 #include "module-gbox-remm.h"
7 #include "module-gbox.h"
8 #include "module-gbox-helper.h"
9 #include "oscam-string.h"
10 #include "oscam-client.h"
11 #include "oscam-lock.h"
12 #include "oscam-time.h"
13 #include "oscam-reader.h"
14 #include "oscam-files.h"
15 #include "module-dvbapi.h"
16 #include "oscam-emm.h"
18 static void gbox_send_remm_ack_msg(struct s_client *cli, uint16_t caid, uint32_t provider, uint8_t dvbapi_stat, uint8_t ack)
20 uchar outbuf[32];
21 struct gbox_peer *peer = cli->gbox;
22 uint16_t local_gbox_id = gbox_get_local_gbox_id();
23 uint32_t local_gbox_pw = gbox_get_local_gbox_password();
25 gbox_message_header(outbuf, MSG_REM_EMM, peer->gbox.password, local_gbox_pw);
26 outbuf[10] = MSGID_REMM_ACK;
27 i2b_buf(2, peer->gbox.id, outbuf +11);
28 i2b_buf(2, local_gbox_id, outbuf + 13);
29 outbuf[15] = ack;
30 outbuf[16] = dvbapi_stat;
31 i2b_buf(2, caid, outbuf +17);
32 i2b_buf(4, provider, outbuf +19);
33 outbuf[23] = 0;
34 outbuf[24] = 0;
35 outbuf[25] = 0;
36 outbuf[26] = 0;
38 gbox_send(cli, outbuf, 27);
40 if (ack == PEER_AU_BLOCKED)
41 { cs_log("<- send REJECT REMM msg to peer %04X for caid: %04X", peer->gbox.id, caid); }
42 if (ack == PEER_AU_READY)
43 { cs_log("<- send ACCEPT REMM msg to peer %04X for caid: %04X", peer->gbox.id, caid); }
44 if (ack == PEER_AU_UNREADY)
45 { cs_log("<- send WARNING to peer %04X: my dvbapi unready for AU caid: %04X", peer->gbox.id, caid); }
46 return;
49 static void gbox_recvd_remm_ack_msg(struct s_client *cli, uchar *buf, int32_t n)
51 if (!cli || !cli->gbox || !buf || n != 27) { return; }
52 struct gbox_peer *peer;
53 peer = cli->gbox;
55 uint8_t ack = buf[15];
56 uint8_t dvbapi_stat = buf[16];
57 uint16_t rpeer = b2i(2, buf +11);
58 uint16_t rcaid = b2i(2, buf +17);
59 //uint32_t rprovid = b2i(4, buf +19);
62 if (ack == PEER_AU_BLOCKED)
63 { cs_log("-> Peer %04X %s rejected REMM for caid %04X - requesting peer %04X blocked", peer->gbox.id, cli->reader->label, rcaid, rpeer ); }
64 if (ack == PEER_AU_READY)
65 { cs_log("-> MSG from peer %04X %s: Accept REMM REQ for caid %04X", peer->gbox.id, cli->reader->label, rcaid); }
66 if (ack == PEER_AU_UNREADY)
68 cs_log("-> WARNING: Peer %04X %s dvbapi AU unready for caid %04X", peer->gbox.id, cli->reader->label, rcaid);
69 cs_log_dbg(D_EMM," Peer %04X dvbapi AU status: dvbapi_au: %1d - dvbapi_usr_autoau: %1d - dvbapi_usr_aulist: %1d",
70 peer->gbox.id, (dvbapi_stat & 1) ? 1 : 0, (dvbapi_stat & 2) ? 1 : 0, (dvbapi_stat & 4) ? 1 : 0 );
74 static uint8_t check_dvbapi_au_ready( void)
76 #ifdef HAVE_DVBAPI
78 uint8_t dvbapi_stat = 0;
79 if (module_dvbapi_enabled())
81 if(cfg.dvbapi_au)
82 { dvbapi_stat |= 1; }
84 struct s_client *cl;
85 cs_readlock(__func__, &clientlist_lock);
86 for(cl = first_client; cl; cl = cl->next)
88 if(cl->typ == 'c' && cl->account && is_dvbapi_usr(cl->account->usr))
90 if(cl->account->autoau)
92 dvbapi_stat |= 2;
93 break;
95 if(ll_count(cl->account->aureader_list))
97 dvbapi_stat |= 4;
98 break;
102 cs_readunlock(__func__, &clientlist_lock);
104 return dvbapi_stat;
105 #else
106 return 0;
107 #endif
110 static int8_t check_valid_remm_peer(uint16_t peer_id)
112 if (cfg.accept_remm_peer_num > 0)
114 int i;
115 for (i = 0; i < cfg.accept_remm_peer_num; i++)
117 if (cfg.accept_remm_peer[i] == peer_id)
118 { return 1; }
121 return 0;
124 static void gbox_recvd_remm_req(struct s_client *cli, uchar *buf, int32_t n)
126 if (!cli || !cli->gbox || !buf || !cli->reader || n != 122) { return; }
128 struct gbox_peer *peer;
129 peer = cli->gbox;
131 uint16_t rcaid = b2i(2, buf +23);
132 uint32_t rprovid = b2i(4, buf +17);
133 //uint16_t tcli_peer = b2i(2, buf +11);
134 //uint16_t tsrv_peer = b2i(2, buf +13);
136 uint8_t dvbapi_stat = check_dvbapi_au_ready();
138 if (!check_valid_remm_peer( peer->gbox.id))
140 gbox_send_remm_ack_msg(cli, rcaid, rprovid, dvbapi_stat, PEER_AU_BLOCKED);
141 handle_attack(cli, GBOX_ATTACK_REMM_REQ_BLOCKED, peer->gbox.id);
142 cs_log("Reject REMM REQ for caid %04X) - peer %04X blocked for AU", rcaid, peer->gbox.id);
143 return;
147 if (tcli_peer != local_gbox.id)
148 { forward remm req to target client peer}
150 struct s_reader *rdr = cli->reader;
151 rdr->last_g = time(NULL); // last receive is now
153 rdr->auprovid = rprovid;
154 rdr->caid = rcaid;
156 memcpy(rdr->hexserial, buf +29, 6);
157 rdr->hexserial[6] = 0;
158 rdr->hexserial[7] = 0;
159 rdr->nprov = buf[37];
161 int32_t i;
162 for(i = 0; i < rdr->nprov; i++)
164 if(caid_is_betacrypt(rdr->caid) || caid_is_irdeto(rdr->caid))
166 rdr->prid[i][0] = buf[38 + (i * 5)];
167 memcpy(&rdr->prid[i][1], &buf[40 + (i * 5)], 3);
169 else
171 rdr->prid[i][2] = buf[38 + (i * 5)];
172 rdr->prid[i][3] = buf[39 + (i * 5)];
173 memcpy(&rdr->sa[i][0], &buf[40 + (i * 5)], 4);
177 rdr->blockemm = 0;
178 rdr->blockemm |= (buf[118] == 1) ? 0 : EMM_GLOBAL;
179 rdr->blockemm |= (buf[119] == 1) ? 0 : EMM_SHARED;
180 rdr->blockemm |= (buf[120] == 1) ? 0 : EMM_UNIQUE;
181 rdr->blockemm |= (buf[121] == 1) ? 0 : EMM_UNKNOWN;
183 cs_log("-> REMM REQ for caid %04X from peer %04X:%s", rdr->caid, peer->gbox.id, rdr->label);
185 if (dvbapi_stat == 3 || dvbapi_stat == 5)
187 gbox_send_remm_ack_msg(cli, rdr->caid, rdr->auprovid, dvbapi_stat, PEER_AU_READY);
188 cs_log_dbg(D_EMM,"my dvbapi ready for AU: dvbapi_au: %1d - dvbapi_usr_autoau: %1d - dvbapi_usr_aulist: %1d",(dvbapi_stat & 1) ? 1 : 0, (dvbapi_stat & 2) ? 1 : 0, (dvbapi_stat & 4) ? 1 : 0 );
190 else
192 gbox_send_remm_ack_msg(cli, rdr->caid, rdr->auprovid, dvbapi_stat, PEER_AU_UNREADY);
193 cs_log_dbg(D_EMM,"dvbapi status: dvbapi_au: %1d - dvbapi_usr_autoau: %1d - dvbapi_usr_aulist: %1d",(dvbapi_stat & 1) ? 1 : 0, (dvbapi_stat & 2) ? 1 : 0, (dvbapi_stat & 4) ? 1 : 0 );
198 static void gbox_recvd_remm_data(struct s_client *cli, uchar *buf, int32_t buflen, int32_t emmlen)
200 if(!cli || !cli->gbox || !buf || buflen < 30 || emmlen +27 > buflen || emmlen < 3 || emmlen + 27 > MAX_EMM_SIZE)
201 { return; }
203 struct gbox_peer *peer;
204 peer = cli->gbox;
206 uint16_t rcaid = b2i(2, buf + 15);
207 uint32_t recvd_remm_crc = b2i(4, buf + 23);
208 uint32_t calc_remm_crc = gbox_get_checksum(&buf[0] +27, emmlen);
209 cs_log_dbg(D_EMM,"received remm from peer: %04X caid: %04X (remm_crc = %08X - calc_remm_crc = %08X)",
210 peer->gbox.id, rcaid, recvd_remm_crc, calc_remm_crc);
211 if(recvd_remm_crc == calc_remm_crc)
213 EMM_PACKET remm;
214 memset(&remm, 0, sizeof(remm));
215 remm.emmlen = emmlen;
216 memcpy(remm.caid, buf +15, 2);
217 memcpy(remm.provid, buf +17 , 4);
218 memcpy(remm.emm, buf +27, remm.emmlen);
219 do_emm(cur_client(), &remm);
221 else
222 { cs_log_dbg(D_EMM,"reject received REMM from peer %04X caid: %04X - crc failed - %08X != %08X", peer->gbox.id, rcaid, recvd_remm_crc, calc_remm_crc); }
224 return;
227 void gbox_recvd_remm_cmd_switch(struct s_client *cli, uchar *buf, int32_t n)
229 if (!cli || !cli->gbox || !buf || n < 26) { return; }
230 struct gbox_peer *peer;
231 peer = cli->gbox;
233 uint8_t cmd_id = buf[10];
235 switch(cmd_id)
237 case MSGID_REMM_REQ:
238 cs_log_dbg(D_EMM,"-> Incoming REMM request (%d bytes) from %04X %s - %s", n, peer->gbox.id, username(cli), cli->reader->device);
239 gbox_recvd_remm_req(cli, buf, n);
240 break;
241 case MSGID_REMM_DATA:
242 cs_log_dbg(D_EMM,"-> Incoming gbox remote EMM data (%d bytes total - %d bytes emm-len) from %04X %s - %s", n,
243 buf[21], peer->gbox.id, username(cli), cli->reader->device);
244 gbox_recvd_remm_data(cli, buf, n, buf[21]); //buf[21]) = emm lenght
245 break;
246 case MSGID_REMM_ACK:
247 cs_log_dbg(D_EMM,"-> Incoming REMM ACK (%d bytes) from %04X %s - %s", n, peer->gbox.id, username(cli), cli->reader->device);
248 gbox_recvd_remm_ack_msg(cli, buf, n);
249 break;
250 default:
251 cs_log("received unknown remm cmd_id: %d %d bytes from %04X %s - %s", cmd_id, n, peer->gbox.id, username(cli), cli->reader->device);
252 return;
256 void gbox_send_remm_req(struct s_client *cli, ECM_REQUEST *er)
258 if (!cli || !cli->gbox || !er) { return; }
259 int32_t i;
260 uchar mbuf[1024];
261 struct s_client *cl = cur_client();
262 struct gbox_peer *peer = cli->gbox;
263 struct s_reader *aureader = NULL, *rdr = NULL;
265 if(er->selected_reader && !er->selected_reader->audisabled && ll_contains(cl->aureader_list, er->selected_reader))
266 { aureader = er->selected_reader; }
268 if(!aureader && cl->aureader_list)
270 LL_ITER itr = ll_iter_create(cl->aureader_list);
271 while((rdr = ll_iter_next(&itr)))
273 if(emm_reader_match(rdr, er->caid, er->prid))
275 aureader = rdr;
276 break;
281 if(!aureader)
282 { return; }
284 uint16_t au_caid = aureader->caid;
286 if(!au_caid && caid_is_bulcrypt(er->caid)) // Bulcrypt has 2 caids and aureader->caid can't be used. Use ECM_REQUEST caid for AU.
287 { au_caid = er->caid; }
289 if(cl->lastcaid != er->caid)
290 { cl->disable_counter = 0; }
292 cl->lastcaid = er->caid;
293 cl->disable_counter++;
295 if (cl->disable_counter < 6) //delay 5 ecm
296 { return; }
298 if(!memcmp(cl->lastserial, aureader->hexserial, 8))
300 cl->disable_counter = 0;
301 return;
304 memcpy(cl->lastserial, aureader->hexserial, 8);
306 if(au_caid)
307 { cl->disable_counter = 0; }
308 else
309 { return; }
311 memset(mbuf, 0, sizeof(mbuf));
313 uint16_t local_gbox_id = gbox_get_local_gbox_id();
314 uint32_t local_gbox_pw = gbox_get_local_gbox_password();
316 gbox_message_header(mbuf, MSG_REM_EMM, peer->gbox.password, local_gbox_pw);
317 mbuf[10] = MSGID_REMM_REQ;
318 i2b_buf(2, peer->gbox.id, mbuf + 11);
319 i2b_buf(2, local_gbox_id, mbuf + 13);
320 i2b_buf(2, er->srvid, mbuf + 15);
322 //override emm provid with auprovid if set in server reader config
323 if(aureader->auprovid)
325 if(aureader->auprovid != er->prid)
326 { i2b_buf(4, aureader->auprovid, mbuf +17); }
327 else
328 { i2b_buf(4, er->prid, mbuf +17); }
330 else
331 { i2b_buf(4, er->prid, mbuf +17); }
333 i2b_buf(2, er->pid, mbuf +21);
334 i2b_buf(2, au_caid, mbuf +23);
335 memcpy(mbuf +29, aureader->hexserial, 6); // serial 6 bytes
336 mbuf[37] = aureader->nprov;
338 for(i = 0; i < aureader->nprov; i++)
340 if(caid_is_betacrypt(au_caid) || caid_is_irdeto(au_caid))
342 mbuf[38 + (i * 5)] = aureader->prid[i][0];
343 memcpy(&mbuf[40 + (i * 5)], &aureader->prid[i][1], 3);
345 else
347 mbuf[38 + (i * 5)] = aureader->prid[i][2];
348 mbuf[39 + (i * 5)] = aureader->prid[i][3];
349 memcpy(&mbuf[40 + (i * 5)], &aureader->sa[i][0], 4); // for conax we need at least 4 Bytes
351 if(i >= 15) { break; }
354 mbuf[118] = 0; //(aureader->blockemm & EMM_GLOBAL && !(aureader->saveemm & EMM_GLOBAL)) ? 0 : 1;
355 mbuf[119] = (aureader->blockemm & EMM_SHARED && !(aureader->saveemm & EMM_SHARED)) ? 0 : 1;
356 mbuf[120] = (aureader->blockemm & EMM_UNIQUE && !(aureader->saveemm & EMM_UNIQUE)) ? 0 : 1;
357 mbuf[121] = (aureader->blockemm & EMM_UNKNOWN && !(aureader->saveemm & EMM_UNKNOWN)) ? 0 : 1;
359 cs_log("<- send REMM REQ to %s peer-id %04X for reader=%s, caid=%04X, auprovid=%06X",
360 username(cur_client()), peer->gbox.id, aureader->label, au_caid,
361 aureader->auprovid ? aureader->auprovid : b2i(4, aureader->prid[0]));
362 cs_log_dump_dbg(D_EMM, mbuf, 122, "<- send remm request, (data_len=%d):", 122);
363 gbox_send(cli, mbuf, 122);
364 return;
367 int32_t gbox_send_remm_data(EMM_PACKET *ep)
369 uint8_t *buf;
370 struct s_client *cli = cur_client();
371 struct gbox_peer *peer = cli->gbox;
373 if(!cli->gbox || !cli->reader->tcp_connected || !ep)
374 { return 0; }
376 if(!cs_malloc(&buf, ep->emmlen +27 +15))
377 { return -1; }
379 memset(buf, 0, 26);
380 memset(buf +27, 0xff, ep->emmlen + 15);
382 uint32_t remm_crc = gbox_get_checksum(&ep->emm[0], ep->emmlen);
383 uint16_t local_gbox_id = gbox_get_local_gbox_id();
384 uint32_t local_gbox_pw = gbox_get_local_gbox_password();
386 gbox_message_header(buf, MSG_REM_EMM, peer->gbox.password, local_gbox_pw);
387 buf[10] = MSGID_REMM_DATA;
388 i2b_buf(2, peer->gbox.id, buf +11);
389 i2b_buf(2, local_gbox_id, buf +13);
390 memcpy(buf +15, ep->caid, 2);
391 memcpy(buf +17, ep->provid, 4);
392 buf[21] = ep->emmlen;
393 i2b_buf(4, remm_crc, buf +23);
394 memcpy(buf +27, ep->emm, ep->emmlen);
395 cs_log("<- send remm to: %s peer: %04X emmlength: %d crc: %08X",username(cur_client()), peer->gbox.id, ep->emmlen, remm_crc);
396 cs_log_dump_dbg(D_EMM, buf, 27 + ep->emmlen, "<- gbox send emm, (data-len=%d):", 27 + ep->emmlen);
397 gbox_send(cli, buf, 27 + ep->emmlen);
399 NULLFREE(buf);
400 return 1;
402 #endif