- fix Building without Nagra not possible at Nagra_Merlin https://trac.streamboard...
[oscam.git] / module-monitor.c
blobcdd425db5b5f49b0060d15c6bf0743b1e96ce7d8
1 #define MODULE_LOG_PREFIX "monitor"
3 #include "globals.h"
4 #ifdef MODULE_MONITOR
5 #include "cscrypt/md5.h"
6 #include "module-monitor.h"
7 #include "oscam-aes.h"
8 #include "oscam-array.h"
9 #include "oscam-client.h"
10 #include "oscam-config.h"
11 #include "oscam-conf-chk.h"
12 #include "oscam-lock.h"
13 #include "oscam-net.h"
14 #include "oscam-reader.h"
15 #include "oscam-string.h"
16 #include "oscam-work.h"
18 extern char *entitlement_type[];
20 struct monitor_data
22 bool auth;
23 uint8_t ucrc[4];
24 struct aes_keys aes_keys;
25 int32_t seq;
26 int32_t counter;
27 char btxt[256];
30 static int8_t monitor_check_ip(void)
32 int32_t ok = 0;
33 struct s_client *cur_cl = cur_client();
34 struct monitor_data *module_data = cur_cl->module_data;
36 if(module_data->auth) { return 0; }
37 ok = check_ip(cfg.mon_allowed, cur_cl->ip);
38 if(!ok)
40 cs_auth_client(cur_cl, (struct s_auth *)0, "invalid ip");
41 return -1;
43 return 0;
46 static int8_t monitor_auth_client(char *usr, char *pwd)
48 struct s_auth *account;
49 struct s_client *cur_cl = cur_client();
50 struct monitor_data *module_data = cur_cl->module_data;
52 if(module_data->auth) { return 0; }
53 if((!usr) || (!pwd))
55 cs_auth_client(cur_cl, (struct s_auth *)0, NULL);
56 return -1;
58 for(account = cfg.account; account; account = account->next)
60 if(account->monlvl && streq(usr, account->usr) && streq(pwd, account->pwd))
62 module_data->auth = 1;
63 break;
66 if(!module_data->auth)
68 cs_auth_client(cur_cl, (struct s_auth *)0, "invalid account");
69 return -1;
71 if(cs_auth_client(cur_cl, account, NULL))
72 { return -1; }
73 return 0;
76 static int32_t secmon_auth_client(uint8_t *ucrc)
78 uint32_t crc;
79 struct s_auth *account;
80 struct s_client *cur_cl = cur_client();
81 struct monitor_data *module_data = cur_cl->module_data;
82 uint8_t md5tmp[MD5_DIGEST_LENGTH];
84 if(module_data->auth)
86 int32_t s = memcmp(module_data->ucrc, ucrc, 4);
87 if(s)
88 { cs_log("wrong user-crc or garbage !?"); }
89 return !s;
92 cur_cl->crypted = 1;
93 crc = (ucrc[0] << 24) | (ucrc[1] << 16) | (ucrc[2] << 8) | ucrc[3];
95 for(account = cfg.account; (account) && (!module_data->auth); account = account->next)
97 if((account->monlvl) &&
98 (crc == crc32(0L, MD5((uint8_t *)account->usr, cs_strlen(account->usr), md5tmp), MD5_DIGEST_LENGTH)))
100 memcpy(module_data->ucrc, ucrc, 4);
101 aes_set_key(&module_data->aes_keys, (char *)MD5((uint8_t *)ESTR(account->pwd), cs_strlen(ESTR(account->pwd)), md5tmp));
102 if(cs_auth_client(cur_cl, account, NULL))
103 { return -1; }
104 module_data->auth = 1;
108 if(!module_data->auth)
110 cs_auth_client(cur_cl, (struct s_auth *)0, "invalid user");
111 return -1;
113 return module_data->auth;
116 int32_t monitor_send_idx(struct s_client *cl, char *txt)
118 struct monitor_data *module_data = cl->module_data;
119 int32_t l;
120 uint8_t buf[256 + 32];
121 if(!cl->udp_fd)
122 { return -1; }
123 struct timespec req_ts;
124 req_ts.tv_sec = 0;
125 req_ts.tv_nsec = 500000;
126 nanosleep(&req_ts, NULL); // avoid lost udp-pakkets
127 if(!cl->crypted)
128 { return sendto(cl->udp_fd, txt, cs_strlen(txt), 0, (struct sockaddr *)&cl->udp_sa, cl->udp_sa_len); }
129 l = cs_strlen(txt);
130 if(l > 255)
131 { l = 255; }
132 buf[0] = '&';
133 buf[9] = l;
134 l = boundary(4, l + 5) + 5;
135 memcpy(buf + 1, module_data->ucrc, 4);
136 cs_strncpy((char *)buf + 10, txt, sizeof(buf) - 10);
137 memset(buf+10+buf[9], 0, l-10-buf[9]);
138 uint8_t tmp[10];
139 memcpy(buf + 5, i2b_buf(4, crc32(0L, buf + 10, l - 10), tmp), 4);
140 aes_encrypt_idx(&module_data->aes_keys, buf + 5, l - 5);
141 return sendto(cl->udp_fd, buf, l, 0, (struct sockaddr *)&cl->udp_sa, cl->udp_sa_len);
144 #define monitor_send(t) monitor_send_idx(cur_client(), t)
146 static int32_t monitor_recv(struct s_client *client, uint8_t *buf, int32_t UNUSED(buflen))
148 int32_t n = recv_from_udpipe(buf);
149 if(!n)
150 { return buf[0] = 0; }
151 if(!client->module_data && !cs_malloc(&client->module_data, sizeof(struct monitor_data)))
152 { return 0; }
153 if(buf[0] == '&')
155 int32_t bsize;
156 if(n < 21) // 5+16 is minimum
158 cs_log("packet too small!");
159 return buf[0] = 0;
161 int32_t res = secmon_auth_client(buf + 1);
162 if(res == -1)
164 cs_disconnect_client(client);
165 return 0;
167 if(!res)
169 return buf[0] = 0;
171 struct monitor_data *module_data = client->module_data;
172 aes_decrypt(&module_data->aes_keys, buf + 5, 16);
173 bsize = boundary(4, buf[9] + 5) + 5;
174 if(n < bsize)
176 cs_log("packet-size mismatch !");
177 return buf[0] = 0;
179 aes_decrypt(&module_data->aes_keys, buf + 21, n - 21);
180 uint8_t tmp[10];
181 if(memcmp(buf + 5, i2b_buf(4, crc32(0L, buf + 10, n - 10), tmp), 4))
183 cs_log("CRC error ! wrong password ?");
184 return buf[0] = 0;
186 n = buf[9];
187 memmove(buf, buf + 10, n);
189 else
191 if(monitor_check_ip() == -1)
193 cs_disconnect_client(client);
194 return 0;
197 buf[n] = '\0';
198 n = cs_strlen(trim((char *)buf));
199 if(n) { client->last = time((time_t *) 0); }
200 return n;
203 static void monitor_send_info(char *txt, int32_t last)
205 struct s_client *cur_cl = cur_client();
206 struct monitor_data *module_data = cur_cl->module_data;
207 char buf[16];
208 if(txt)
210 if(!module_data->btxt[0])
212 module_data->counter = 0;
213 txt[2] = 'B';
215 else
216 { module_data->counter++; }
217 snprintf(buf, sizeof(buf), "%03d", module_data->counter);
218 memcpy(txt + 4, buf, 3);
219 txt[3] = '0' + module_data->seq;
221 else if(!last)
222 { return; }
224 if(!last)
226 if(module_data->btxt[0]) { monitor_send(module_data->btxt); }
227 cs_strncpy(module_data->btxt, txt, sizeof(module_data->btxt));
228 return;
231 if(txt && module_data->btxt[0])
233 monitor_send(module_data->btxt);
234 txt[2] = 'E';
235 cs_strncpy(module_data->btxt, txt, sizeof(module_data->btxt));
237 else
239 if(txt)
240 { cs_strncpy(module_data->btxt, txt, sizeof(module_data->btxt)); }
241 module_data->btxt[2] = (module_data->btxt[2] == 'B') ? 'S' : 'E';
244 if(module_data->btxt[0])
246 monitor_send(module_data->btxt);
247 module_data->seq = (module_data->seq + 1) % 10;
249 module_data->btxt[0] = 0;
252 static char *monitor_client_info(char id, struct s_client *cl, char *sbuf)
254 char channame[CS_SERVICENAME_SIZE];
255 sbuf[0] = '\0';
257 if(cl)
259 char ldate[16], ltime[16];
260 const char *usr;
261 int32_t lsec, isec, con, cau, lrt = - 1;
262 time_t now;
263 struct tm lt;
264 now = time((time_t *)0);
266 if((cfg.hideclient_to <= 0) ||
267 (now - cl->lastecm < cfg.hideclient_to) ||
268 (now - cl->lastemm < cfg.hideclient_to) ||
269 (cl->typ != 'c'))
271 lsec = now - cl->login;
272 isec = now - cl->last;
273 usr = username(cl);
274 if(cl->dup)
275 { con = 2; }
276 else if((cl->tosleep) && (now - cl->lastswitch > cl->tosleep))
277 { con = 1; }
278 else
279 { con = 0; }
281 // no AU reader == 0 / AU ok == 1 / Last EMM > aulow == -1
282 if(cl->typ == 'c' || cl->typ == 'p' || cl->typ == 'r')
284 if((cl->typ == 'c' && ll_count(cl->aureader_list) == 0) ||
285 ((cl->typ == 'p' || cl->typ == 'r') && cl->reader->audisabled))
286 { cau = 0; }
288 else if((now - cl->lastemm) / 60 > cfg.aulow)
289 { cau = (-1); }
291 else
292 { cau = 1; }
294 else
296 cau = 0;
299 if(cl->typ == 'r')
301 int32_t i;
302 struct s_reader *rdr;
303 for(i = 0, rdr = first_active_reader; rdr ; rdr = rdr->next, i++)
304 if(cl->reader == rdr)
305 { lrt = i; }
307 if(lrt >= 0)
309 lrt = 10 + cl->reader->card_status;
312 else
314 lrt = cl->cwlastresptime;
316 localtime_r(&cl->login, &lt);
317 // snprintf(ldate, sizeof(ldate), " %02d.%02d.%02d", lt.tm_mday, lt.tm_mon + 1, lt.tm_year % 100);
318 int32_t cnr = get_threadnum(cl);
319 snprintf(ltime, sizeof(ldate), "%02d:%02d:%02d", lt.tm_hour, lt.tm_min, lt.tm_sec);
320 snprintf(sbuf, 256, "[%c--CCC]%8X|%c|%d|%s|%d|%d|%s|%d|%s|%s|%s|%d|%04X@%06X:%04X|%s|%d|%d|%d|%d|%d|%d|%d|%d|%d|%d\n",
321 id, cl->tid, cl->typ, cnr, usr, cau, cl->crypted,
322 cs_inet_ntoa(cl->ip), cl->port, client_get_proto(cl),
323 ldate, ltime, lsec, cl->last_caid, cl->last_provid, cl->last_srvid,
324 get_servicename_or_null(cl, cl->last_srvid, cl->last_provid, cl->last_caid, channame, sizeof(channame)), isec, con,
325 cl->cwfound, cl->cwnot, cl->cwcache, cl->cwignored,
326 cl->cwtout, cl->emmok, cl->emmnok, lrt);
329 return sbuf;
332 static void monitor_process_info(void)
334 time_t now = time((time_t *)0);
335 char sbuf[256];
336 struct s_client *cl, *cur_cl = cur_client();
338 for(cl = first_client; cl ; cl = cl->next)
340 if((cfg.hideclient_to <= 0) ||
341 (now - cl->lastecm < cfg.hideclient_to) ||
342 (now - cl->lastemm < cfg.hideclient_to) ||
343 (cl->typ != 'c'))
345 if((cur_cl->monlvl < 2) && (cl->typ != 's'))
347 if((cur_cl->account && cl->account && strcmp(cur_cl->account->usr, cl->account->usr)) ||
348 ((cl->typ != 'c') && (cl->typ != 'm')))
349 { continue; }
351 monitor_send_info(monitor_client_info('I', cl, sbuf), 0);
354 monitor_send_info(NULL, 1);
357 static void monitor_send_details(char *txt, uint32_t tid)
359 char buf[512];
360 snprintf(buf, sizeof(buf), "[D-----]%8X|%s\n", tid, txt);
361 monitor_send_info(buf, 0);
364 static void monitor_send_details_version(void)
366 char buf[256];
367 snprintf(buf, sizeof(buf), "[V-0000]version=%s, build=%s, system=%s\n", CS_VERSION, CS_SVN_VERSION, CS_TARGET);
368 monitor_send_info(buf, 1);
371 static void monitor_send_keepalive_ack(void)
373 char buf[32];
374 snprintf(buf, sizeof(buf), "[K-0000]keepalive_ack\n");
375 monitor_send_info(buf, 1);
378 static void monitor_process_details_master(char *buf, uint32_t pid)
380 snprintf(buf, 256, "Version=%sr%s", CS_VERSION, CS_SVN_VERSION);
381 monitor_send_details(buf, pid);
382 snprintf(buf, 256, "System=%s", CS_TARGET);
383 monitor_send_details(buf, pid);
384 snprintf(buf, 256, "DebugLevel=%d", cs_dblevel);
385 monitor_send_details(buf, pid);
386 snprintf(buf, 256, "MaxClients=UNLIMITED");
387 monitor_send_details(buf, pid);
388 snprintf(buf, 256, "ClientMaxIdle=%d sec", cfg.cmaxidle);
389 monitor_send_details(buf, pid);
390 if(cfg.max_log_size)
392 snprintf(buf, 256, "MaxLogsize=%d Kb", cfg.max_log_size);
394 else
396 snprintf(buf, 256, "MaxLogsize=unlimited");
398 monitor_send_details(buf, pid);
399 snprintf(buf, 256, "ClientTimeout=%u ms", cfg.ctimeout);
400 monitor_send_details(buf, pid);
401 snprintf(buf, 256, "CacheDelay=%d ms", cfg.delay);
402 monitor_send_details(buf, pid);
403 if(cfg.cwlogdir)
405 snprintf(buf, 256, "CwlogDir=%s", cfg.cwlogdir);
406 monitor_send_details(buf, pid);
408 if(cfg.preferlocalcards)
410 snprintf(buf, 256, "PreferlocalCards=%d", cfg.preferlocalcards);
411 monitor_send_details(buf, pid);
413 if(cfg.waitforcards)
415 snprintf(buf, 256, "WaitforCards=%d", cfg.waitforcards);
416 monitor_send_details(buf, pid);
418 snprintf(buf, 256, "LogFile=%s", cfg.logfile);
419 monitor_send_details(buf, pid);
420 if(cfg.mailfile)
422 snprintf(buf, 256, "MailFile=%s", cfg.mailfile);
423 monitor_send_details(buf, pid);
425 if(cfg.usrfile)
427 snprintf(buf, 256, "UsrFile=%s", cfg.usrfile);
428 monitor_send_details(buf, pid);
430 monitor_send_details(buf, pid);
431 snprintf(buf, 256, "Sleep=%d", cfg.tosleep);
432 monitor_send_details(buf, pid);
433 snprintf(buf, 256, "Monitorport=%d", cfg.mon_port);
434 monitor_send_details(buf, pid);
435 snprintf(buf, 256, "Nice=%d", cfg.nice);
436 monitor_send_details(buf, pid);
437 #ifdef WEBIF
438 snprintf(buf, 256, "Restartmode=%d", cs_get_restartmode());
439 monitor_send_details(buf, pid);
440 #else
441 snprintf(buf, 256, "Restartmode=%s", "no");
442 monitor_send_details(buf, pid);
443 #endif
445 // monitor_send_details(buf, pid);
449 static void monitor_process_details_reader(struct s_client *cl)
451 char tbuffer1[64], tbuffer2[64], buf[256] = { 0 }, tmpbuf[256] = { 0 }, valid_to[32] = { 0 };
452 struct s_reader *rdr = cl->reader;
453 if(!rdr)
455 monitor_send_details("Reader do not exist or it is not started.", cl->tid);
456 return;
459 if(rdr->card_valid_to)
461 struct tm vto_t;
462 localtime_r(&rdr->card_valid_to, &vto_t);
463 strftime(valid_to, sizeof(valid_to) - 1, "%Y-%m-%d", &vto_t);
465 else
467 cs_strncpy(valid_to, "n/a", sizeof(valid_to));
470 snprintf(tmpbuf, sizeof(tmpbuf) - 1, "Cardsystem: %s Reader: %s ValidTo: %s HexSerial: %s ATR: %s",
471 rdr->csystem ? rdr->csystem->desc : "-",
472 rdr->label,
473 valid_to,
474 cs_hexdump(1, rdr->hexserial, 8, tbuffer2, sizeof(tbuffer2)),
475 rdr->card_atr_length
476 ? cs_hexdump(1, rdr->card_atr, rdr->card_atr_length, buf, sizeof(buf))
477 : ""
479 monitor_send_details(tmpbuf, cl->tid);
481 if(!rdr->ll_entitlements)
483 monitor_send_details("No entitlements for the reader.", cl->tid);
484 return;
487 S_ENTITLEMENT *item;
488 LL_ITER itr = ll_iter_create(rdr->ll_entitlements);
489 time_t now = (time(NULL) / 86400) * 86400;
491 while((item = ll_iter_next(&itr)))
493 struct tm start_t, end_t;
495 localtime_r(&item->start, &start_t);
496 localtime_r(&item->end , &end_t);
498 strftime(tbuffer1, sizeof(tbuffer1) - 1, "%Y-%m-%d %H:%M %z", &start_t);
499 strftime(tbuffer2, sizeof(tbuffer2) - 1, "%Y-%m-%d %H:%M %z", &end_t);
501 char *entresname = get_tiername(item->id & 0xFFFF, item->caid, buf);
502 if(!entresname[0])
503 { entresname = get_provider(item->provid, item->caid, buf, sizeof(buf)); }
505 snprintf(tmpbuf, sizeof(tmpbuf) - 1, "%s Type: %s CAID: %04X Provid: %06X ID: %08X%08X Class: %08X StartDate: %s ExpireDate: %s Name: %s",
506 item->end > now ? "active " : "expired",
507 entitlement_type[item->type],
508 item->caid,
509 item->provid,
510 (uint32_t)(item->id >> 32),
511 (uint32_t)(item->id),
512 item->class,
513 tbuffer1,
514 tbuffer2,
515 entresname
517 monitor_send_details(tmpbuf, cl->tid);
522 static void monitor_process_details(char *arg)
524 uint32_t tid = 0; //using threadid 8 positions hex see oscam-log.c //FIXME untested but pid isnt working anyway with threading
525 struct s_client *cl = NULL, *cl1;
526 char sbuf[256];
528 if(!arg)
529 { cl = first_client; } // no arg - show master
530 else
532 if(sscanf(arg, "%X", &tid) == 1)
534 for(cl1 = first_client; cl1 ; cl1 = cl1->next)
535 if(cl1->tid == tid)
537 cl = cl1;
538 break;
543 if(!cl)
544 { monitor_send_details("Invalid TID", tid); }
545 else
547 //monitor_send_info(monitor_client_info('D', idx), 0); // FIXME
548 switch(cl->typ)
550 case 's':
551 monitor_process_details_master(sbuf, cl->tid);
552 break;
553 case 'c':
554 case 'm':
555 monitor_send_details(monitor_client_info(1, cl, sbuf), cl->tid);
556 break;
557 case 'r':
558 monitor_process_details_reader(cl); // with client->typ='r' client->ridx is always filled and valid, so no need checking
559 break;
560 case 'p':
561 monitor_send_details(monitor_client_info(1, cl, sbuf), cl->tid);
562 break;
565 monitor_send_info(NULL, 1);
568 static void monitor_send_login(void)
570 char buf[64];
571 struct s_client *cur_cl = cur_client();
572 struct monitor_data *module_data = cur_cl->module_data;
573 if(module_data->auth && cur_cl->account)
574 { snprintf(buf, sizeof(buf), "[A-0000]1|%.42s logged in\n", cur_cl->account->usr); }
575 else
576 { cs_strncpy(buf, "[A-0000]0|not logged in\n", sizeof(buf)); }
577 monitor_send_info(buf, 1);
580 static void monitor_login(char *usr)
582 char *pwd = NULL;
583 int8_t res = 0;
584 if((usr) && (pwd = strchr(usr, ' ')))
585 { * pwd++ = 0; }
586 if(pwd)
587 { res = monitor_auth_client(trim(usr), trim(pwd)); }
588 else
589 { res = monitor_auth_client(NULL, NULL); }
591 if(res == -1)
593 cs_disconnect_client(cur_client());
594 return;
596 monitor_send_login();
599 static void monitor_logsend(char *flag)
601 if(!flag) { return; } //no arg
603 struct s_client *cur_cl = cur_client();
604 if(strcmp(flag, "on"))
606 if(strcmp(flag, "onwohist"))
608 cur_cl->log = 0;
609 return;
613 if(cur_cl->log) // already on
614 { return; }
616 if(!strcmp(flag, "on") && cfg.loghistorylines)
618 if(cfg.loghistorylines && log_history)
620 LL_ITER it = ll_iter_create(log_history);
621 struct s_log_history *hist;
623 while((hist = (struct s_log_history*)ll_iter_next(&it)))
625 char p_usr[32], p_txt[512];
626 size_t pos1 = strcspn(hist->txt, "\t") + 1;
628 cs_strncpy(p_usr, hist->txt , pos1 > sizeof(p_usr) ? sizeof(p_usr) : pos1);
630 if((p_usr[0]) && ((cur_cl->monlvl > 1) || (cur_cl->account && !strcmp(p_usr, cur_cl->account->usr))))
632 snprintf(p_txt, sizeof(p_txt), "[LOG%03d]%s", cur_cl->logcounter, hist->txt + pos1);
633 cur_cl->logcounter = (cur_cl->logcounter + 1) % 1000;
634 monitor_send(p_txt);
640 cur_cl->log = 1;
643 static void monitor_set_debuglevel(char *flag)
645 if(flag)
647 cs_dblevel = atoi(flag);
648 #ifndef WITH_DEBUG
649 cs_log("*** Warning: Debug Support not compiled in ***");
650 #else
651 cs_log("%s debug_level=%d", "all", cs_dblevel);
652 #endif
656 static void monitor_get_account(void)
658 struct s_auth *account;
659 char buf[256];
660 int32_t count = 0;
662 for(account = cfg.account; (account); account = account->next)
664 count++;
665 snprintf(buf, sizeof(buf), "[U-----]%s\n", account->usr);
666 monitor_send_info(buf, 0);
668 snprintf(buf, sizeof(buf), "[U-----] %i User registered\n", count);
669 monitor_send_info(buf, 1);
670 return;
673 static void monitor_set_account(char *args)
675 struct s_auth *account;
676 char delimiter[] = " =";
677 char *ptr, *saveptr1 = NULL;
678 int32_t argidx, i, found;
679 char *argarray[3];
680 static const char *token[] = {"au", "sleep", "uniq", "monlevel", "group", "services", "betatunnel", "ident", "caid", "chid", "class", "hostname", "expdate", "keepalive", "disabled"};
681 int32_t tokencnt = sizeof(token) / sizeof(char *);
682 char buf[256], tmp[64];
684 argidx = 0;
685 found = 0;
687 snprintf(tmp, sizeof(tmp), "%s", args);
688 snprintf(buf, sizeof(buf), "[S-0000]setuser: %s check\n", tmp);
689 monitor_send_info(buf, 0);
691 ptr = strtok_r(args, delimiter, &saveptr1);
693 // resolve arguments
694 while(ptr != NULL)
696 argarray[argidx] = trim(ptr);
697 ptr = strtok_r(NULL, delimiter, &saveptr1);
698 argidx++;
701 if(argidx != 3)
703 snprintf(buf, sizeof(buf), "[S-0000]setuser: %s failed - wrong number of parameters (%d)\n", tmp, argidx);
704 monitor_send_info(buf, 0);
705 snprintf(buf, sizeof(buf), "[S-0000]setuser: %s end\n", tmp);
706 monitor_send_info(buf, 1);
707 return;
710 // search account
711 for(account = cfg.account; (account) ; account = account->next)
713 if(!strcmp(argarray[0], account->usr))
715 found = 1;
716 break;
720 if(found != 1)
722 snprintf(buf, sizeof(buf), "[S-0000]setuser: %s failed - user %s not found\n", tmp , argarray[0]);
723 monitor_send_info(buf, 0);
724 snprintf(buf, sizeof(buf), "[S-0000]setuser: %s end\n", tmp);
725 monitor_send_info(buf, 1);
726 return;
729 found = -1;
730 for(i = 0; i < tokencnt; i++)
732 if(!strcmp(argarray[1], token[i]))
734 // preparing the parameters before re-load
735 switch(i)
737 case 6:
738 tuntab_clear(&account->ttab);
739 break; // betatunnel
741 case 8:
742 caidtab_clear(&account->ctab);
743 break; // Caid
745 found = i;
749 if(found < 0)
751 snprintf(buf, sizeof(buf), "[S-0000]setuser: parameter %s not exist. possible values:\n", argarray[1]);
752 monitor_send_info(buf, 0);
753 for(i = 0; i < tokencnt; i++)
755 snprintf(buf, sizeof(buf), "[S-0000]%s\n", token[i]);
756 monitor_send_info(buf, 0);
758 snprintf(buf, sizeof(buf), "[S-0000]setuser: %s end\n", tmp);
759 monitor_send_info(buf, 1);
760 return;
762 else
764 chk_account(token[found], argarray[2], account);
767 if(write_userdb() == 0)
768 { cs_reinit_clients(cfg.account); }
770 snprintf(buf, sizeof(buf), "[S-0000]setuser: %s done - param %s set to %s\n", tmp, argarray[1], argarray[2]);
771 monitor_send_info(buf, 1);
774 static void monitor_set_server(char *args)
776 char delimiter[] = "=";
777 char *ptr, *saveptr1;
778 int32_t argidx, i;
779 char *argarray[3];
780 static const char *token[] = {"clienttimeout", "fallbacktimeout", "clientmaxidle", "cachedelay", "bindwait", "netprio", "sleep", "unlockparental", "serialreadertimeout", "maxlogsize", "showecmdw", "waitforcards", "preferlocalcards"};
781 char buf[256];
783 argidx = 0;
784 ptr = strtok_r(args, delimiter, &saveptr1);
786 // resolve arguments
787 while(ptr != NULL)
789 argarray[argidx] = trim(ptr);
790 ptr = strtok_r(NULL, delimiter, &saveptr1);
791 argidx++;
794 if(argidx != 2)
796 snprintf(buf, sizeof(buf), "[S-0000]setserver failed - wrong number of parameters (%d)\n", argidx);
797 monitor_send_info(buf, 1);
798 return;
801 trim(argarray[0]);
802 trim(argarray[1]);
803 strtolower(argarray[0]);
805 for(i = 0; i < 13; i++)
806 if(!strcmp(argarray[0], token[i])) { break; }
808 if(i < 13)
810 config_set("global", token[i], argarray[1]);
811 snprintf(buf, sizeof(buf), "[S-0000]setserver done - param %s set to %s\n", argarray[0], argarray[1]);
812 monitor_send_info(buf, 1);
814 else
816 snprintf(buf, sizeof(buf), "[S-0000]setserver failed - parameter %s not exist\n", argarray[0]);
817 monitor_send_info(buf, 1);
818 return;
821 /*Hide by blueven. Introduce new fallbacktimeout_percaid.
823 * if (cfg.ftimeout>=cfg.ctimeout) {
824 cfg.ftimeout = cfg.ctimeout - 100;
825 snprintf(buf, sizeof(buf), "[S-0000]setserver WARNING: fallbacktimeout adjusted to %u ms\n", cfg.ftimeout);
826 monitor_send_info(buf, 1);
828 //kill(first_client->pid, SIGUSR1);
831 #ifdef WEBIF
832 static void monitor_restart_server(void)
834 cs_restart_oscam();
836 #endif
838 static void monitor_list_commands(const char *args[], int32_t cmdcnt)
840 int32_t i;
841 for(i = 0; i < cmdcnt; i++)
843 char buf[64];
844 snprintf(buf, sizeof(buf), "[S-0000]commands: %s\n", args[i]);
845 if(i < cmdcnt - 1)
846 { monitor_send_info(buf, 0); }
847 else
848 { monitor_send_info(buf, 1); }
852 static int32_t monitor_process_request(char *req)
854 int32_t i, rc;
855 static const char *cmd[] = {"login",
856 "exit",
857 "log",
858 "status",
859 "shutdown",
860 "reload",
861 "details",
862 "version",
863 "debug",
864 "getuser",
865 "setuser",
866 "setserver",
867 "commands",
868 "keepalive",
869 "reread"
870 #ifdef WEBIF
871 , "restart"
872 #endif
875 int32_t cmdcnt = sizeof(cmd) / sizeof(char *); // Calculate the amount of items in array
876 char *arg;
877 struct s_client *cur_cl = cur_client();
878 struct monitor_data *module_data = cur_cl->module_data;
880 if((arg = strchr(req, ' ')))
882 *arg++ = 0;
883 trim(arg);
885 //trim(req);
887 if(!module_data->auth && strcmp(req, cmd[0]) != 0)
888 { monitor_login(NULL); }
890 for(rc = 1, i = 0; i < cmdcnt; i++)
892 if(!strcmp(req, cmd[i]))
894 switch(i)
896 case 0:
897 monitor_login(arg);
898 break; // login
900 case 1:
901 cs_disconnect_client(cur_cl);
902 break; // exit
904 case 2:
905 monitor_logsend(arg);
906 break; // log
908 case 3:
909 monitor_process_info();
910 break; // status
912 case 4:
913 if(cur_cl->monlvl > 3) { cs_exit_oscam(); }
914 break; // shutdown
916 case 5:
917 if(cur_cl->monlvl > 2) { cs_accounts_chk(); }
918 break; // reload
920 case 6:
921 monitor_process_details(arg);
922 break; // details
924 case 7:
925 monitor_send_details_version();
926 break; // version
928 case 8:
929 if(cur_cl->monlvl > 3) { monitor_set_debuglevel(arg); }
930 break; // debuglevel
932 case 9:
933 if(cur_cl->monlvl > 3) { monitor_get_account(); }
934 break; // getuser
936 case 10:
937 if(cur_cl->monlvl > 3) { monitor_set_account(arg); }
938 break; // setuser
940 case 11:
941 if(cur_cl->monlvl > 3) { monitor_set_server(arg); }
942 break; // setserver
944 case 12:
945 if(cur_cl->monlvl > 3) { monitor_list_commands(cmd, cmdcnt); }
946 break; // list commands
948 case 13:
949 if(cur_cl->monlvl > 3) { monitor_send_keepalive_ack(); }
950 break; // keepalive
952 case 14:
954 char buf[64]; // reread
955 snprintf(buf, sizeof(buf), "[S-0000]reread\n");
956 monitor_send_info(buf, 1);
957 cs_card_info();
958 break;
960 #ifdef WEBIF
961 case 15:
962 if(cur_cl->monlvl > 3) { monitor_restart_server(); }
963 break; // keepalive
964 #endif
965 default:
966 continue;
968 break;
971 return rc;
974 static void *monitor_server(struct s_client *client, uint8_t *mbuf, int32_t UNUSED(n))
976 client->typ = 'm';
977 monitor_process_request((char *)mbuf);
979 return NULL;
982 static void monitor_cleanup(struct s_client *client)
984 NULLFREE(client->module_data);
987 void module_monitor(struct s_module *ph)
989 ph->ptab.nports = 1;
990 ph->ptab.ports[0].s_port = cfg.mon_port;
991 ph->desc = "monitor";
992 ph->type = MOD_CONN_UDP;
993 IP_ASSIGN(ph->s_ip, cfg.mon_srvip);
994 ph->s_handler = monitor_server;
995 ph->recv = monitor_recv;
996 ph->cleanup = monitor_cleanup;
997 //ph->send_dcw=NULL;
999 #endif