Create tag for version 0.99
[oscam.git] / module-monitor.c
blob5518dd09e6ccd866a778ec5ecf11987b5084d30f
1 #include "globals.h"
2 #ifdef CS_WITH_GBOX
3 # include "csgbox/gbox.h"
4 # define CS_VERSION_X CS_VERSION "-gbx-" GBXVERSION
5 #else
6 # define CS_VERSION_X CS_VERSION
7 #endif
9 static int auth=0;
11 static void monitor_check_ip()
13 int ok=0;
14 struct s_ip *p_ip;
16 if (auth) return;
17 for (p_ip=cfg->mon_allowed; (p_ip) && (!ok); p_ip=p_ip->next)
18 ok=((client[cs_idx].ip>=p_ip->ip[0]) && (client[cs_idx].ip<=p_ip->ip[1]));
19 if (!ok)
21 cs_auth_client((struct s_auth *)0, "invalid ip");
22 cs_exit(0);
26 static void monitor_auth_client(char *usr, char *pwd)
28 struct s_auth *account;
30 if (auth) return;
31 if ((!usr) || (!pwd))
33 cs_auth_client((struct s_auth *)0, NULL);
34 cs_exit(0);
36 for (account=cfg->account, auth=0; (account) && (!auth);)
38 if (account->monlvl)
39 auth=!(strcmp(usr, account->usr) | strcmp(pwd, account->pwd));
40 if (!auth)
41 account=account->next;
43 if (!auth)
45 cs_auth_client((struct s_auth *)0, "invalid account");
46 cs_exit(0);
48 if (cs_auth_client(account, NULL))
49 cs_exit(0);
52 static int secmon_auth_client(uchar *ucrc)
54 ulong crc;
55 struct s_auth *account;
57 if (auth)
59 int s=memcmp(client[cs_idx].ucrc, ucrc, 4);
60 if (s)
61 cs_log("wrong user-crc or garbage !?");
62 return(!s);
64 client[cs_idx].crypted=1;
65 crc=(ucrc[0]<<24) | (ucrc[1]<<16) | (ucrc[2]<<8) | ucrc[3];
66 for (account=cfg->account; (account) && (!auth); account=account->next)
67 if ((account->monlvl) &&
68 (crc==crc32(0L, MD5(account->usr, strlen(account->usr), NULL), 16)))
70 memcpy(client[cs_idx].ucrc, ucrc, 4);
71 aes_set_key(MD5(account->pwd, strlen(account->pwd), NULL));
72 if (cs_auth_client(account, NULL))
73 cs_exit(0);
74 auth=1;
76 if (!auth)
78 cs_auth_client((struct s_auth *)0, "invalid user");
79 cs_exit(0);
81 return(auth);
84 int monitor_send_idx(int idx, char *txt)
86 int l;
87 unsigned char buf[256+32];
88 if (!client[idx].udp_fd)
89 return(-1);
90 usleep(500L); // avoid lost udp-pakets ..
91 if (!client[idx].crypted)
92 return(sendto(client[idx].udp_fd, txt, strlen(txt), 0,
93 (struct sockaddr *)&client[idx].udp_sa,
94 sizeof(client[idx].udp_sa)));
95 buf[0]='&';
96 buf[9]=l=strlen(txt);
97 l=boundary(4, l+5)+5;
98 memcpy(buf+1, client[idx].ucrc, 4);
99 strcpy(buf+10, txt);
100 memcpy(buf+5, i2b(4, crc32(0L, buf+10, l-10)), 4);
101 aes_encrypt_idx(idx, buf+5, l-5);
102 return(sendto(client[idx].udp_fd, buf, l, 0,
103 (struct sockaddr *)&client[idx].udp_sa,
104 sizeof(client[idx].udp_sa)));
107 #define monitor_send(t) monitor_send_idx(cs_idx, t)
109 static int monitor_recv(uchar *buf, int l)
111 int n;
112 uchar nbuf[3] = { 'U', 0, 0 };
113 static int bpos=0;
114 static uchar *bbuf=NULL;
115 if (!bbuf)
117 bbuf=(uchar *)malloc(l);
118 if (!bbuf)
120 cs_log("Cannot allocate memory (errno=%d)", errno);
121 cs_exit(1);
124 if (bpos)
125 memcpy(buf, bbuf, n=bpos);
126 else
127 n=recv_from_udpipe(buf, l);
128 bpos=0;
129 if (!n) return(buf[0]=0);
130 if (buf[0]=='&')
132 int bsize;
133 if (n<21) // 5+16 is minimum
135 cs_log("packet to short !");
136 return(buf[0]=0);
138 if (!secmon_auth_client(buf+1))
139 return(buf[0]=0);
140 aes_decrypt(buf+5, 16);
141 bsize=boundary(4, buf[9]+5)+5;
142 // cs_log("n=%d bsize=%d", n, bsize);
143 if (n>bsize)
145 // cs_log("DO >>>> copy-back");
146 memcpy(bbuf, buf+bsize, bpos=n-bsize);
147 n=bsize;
148 write(client[cs_idx].ufd, nbuf, sizeof(nbuf)); // trigger new event
150 else if (n<bsize)
152 cs_log("packet-size mismatch !");
153 return(buf[0]=0);
155 aes_decrypt(buf+21, n-21);
156 if (memcmp(buf+5, i2b(4, crc32(0L, buf+10, n-10)), 4))
158 cs_log("CRC error ! wrong password ?");
159 return(buf[0]=0);
161 n=buf[9];
162 memmove(buf, buf+10, n);
164 else
166 uchar *p;
167 monitor_check_ip();
168 buf[n]='\0';
169 if ((p=strchr(buf, 10)) && (bpos=n-(p-buf)-1))
171 memcpy(bbuf, p+1, bpos);
172 n=p-buf;
173 write(client[cs_idx].ufd, nbuf, sizeof(nbuf)); // trigger new event
176 buf[n]='\0';
177 if (n=strlen(trim(buf)))
178 client[cs_idx].last=time((time_t *) 0);
179 return(n);
182 static void monitor_send_info(char *txt, int last)
184 static int seq=0, counter=0;
185 static char btxt[256] = {0};
186 char buf[8];
187 if (txt)
189 if (!btxt[0])
191 counter=0;
192 txt[2]='B';
194 else
195 counter++;
196 sprintf(buf, "%03.3d", counter);
197 memcpy(txt+4, buf, 3);
198 txt[3]='0'+seq;
200 else
201 if (!last)
202 return;
204 if (!last)
206 if (btxt[0]) monitor_send(btxt);
207 strncpy(btxt, txt, sizeof(btxt));
208 return;
211 if (txt && btxt[0])
213 monitor_send(btxt);
214 txt[2]='E';
215 strncpy(btxt, txt, sizeof(btxt));
217 else
219 if (txt)
220 strncpy(btxt, txt, sizeof(btxt));
221 btxt[2]=(btxt[2]=='B') ? 'S' : 'E';
224 if (btxt[0])
226 monitor_send(btxt);
227 seq=(seq+1)%10;
229 btxt[0]=0;
232 static int cs_idx2ridx(int idx)
234 int i;
235 for (i=0; i<CS_MAXREADER; i++)
236 if (reader[i].cs_idx==idx)
237 return(i);
238 return(-1);
241 static char *monitor_get_srvname(int id)
243 struct s_srvid *this=cfg->srvid;
244 static char name[83];
245 for (name[0]=0; this && (this->next) && (!name[0]); this=this->next)
246 if (this->srvid==id)
247 strncpy(name, this->name, 32);
248 if (!name[0]) sprintf(name, "[%04X]", id);
249 if (!id) name[0]='\0';
250 return(name);
253 static char *monitor_get_proto(int idx)
255 int i;
256 char *ctyp;
257 switch(client[idx].typ)
259 case 's': ctyp="server" ; break;
260 case 'n': ctyp="resolver" ; break;
261 case 'l': ctyp="logger" ; break;
262 case 'p':
263 case 'r': if ((i=cs_idx2ridx(idx))<0) // should never happen
264 ctyp=(client[idx].typ=='p') ? "proxy" : "reader";
265 else
267 switch(reader[i].typ) // TODO like ph
269 case R_MOUSE : ctyp="mouse"; break;
270 case R_INTERN : ctyp="intern"; break;
271 case R_CAMD35 : ctyp="camd 3.5x";break;
272 case R_CAMD33 : ctyp="camd 3.3x";break;
273 case R_NEWCAMD : ctyp="newcamd"; break;
274 case R_RADEGAST: ctyp="radegast"; break;
275 case R_SERIAL : ctyp="serial"; break;
276 case R_GBOX : ctyp="gbox"; break;
277 default : ctyp="unknown"; break;
280 break;
281 default : ctyp=ph[client[idx].ctyp].desc;
283 return(ctyp);
286 static char *monitor_client_info(char id, int i)
288 static char sbuf[256];
290 sbuf[0]='\0';
291 if (client[i].pid)
293 char ldate[16], ltime[16], *usr;
294 int lsec, isec, cnr, con, cau;
295 time_t now;
296 struct tm *lt;
297 now=time((time_t)0);
299 if ((cfg->mon_hideclient_to <= 0) ||
300 (((now-client[i].lastecm)/60)<cfg->mon_hideclient_to) ||
301 (((now-client[i].lastemm)/60)<cfg->mon_hideclient_to) ||
302 (client[i].typ!='c'))
304 lsec=now-client[i].login;
305 isec=now-client[i].last;
306 usr=client[i].usr;
307 if (((client[i].typ=='r') || (client[i].typ=='p')) &&
308 (con=cs_idx2ridx(i))>=0)
309 usr=reader[con].label;
310 if (client[i].dup)
311 con=2;
312 else
313 if ((client[i].tosleep) &&
314 (now-client[i].lastswitch>client[i].tosleep))
315 con=1;
316 else
317 con=0;
318 if (i-cdiff>0)
319 cnr=i-cdiff;
320 else
321 cnr=(i>1) ? i-1 : 0;
322 if( (cau=client[i].au+1) )
323 if ((now-client[i].lastemm)/60>cfg->mon_aulow)
324 cau=-cau;
325 lt=localtime(&client[i].login);
326 sprintf(ldate, "%2d.%02d.%02d",
327 lt->tm_mday, lt->tm_mon+1, lt->tm_year % 100);
328 sprintf(ltime, "%2d:%02d:%02d",
329 lt->tm_hour, lt->tm_min, lt->tm_sec);
330 sprintf(sbuf, "[%c--CCC]%d|%c|%d|%s|%d|%d|%s|%d|%s|%s|%s|%d|%04X:%04X|%s|%d|%d\n",
331 id, client[i].pid, client[i].typ, cnr, usr, cau, client[i].crypted,
332 cs_inet_ntoa(client[i].ip), client[i].port, monitor_get_proto(i),
333 ldate, ltime, lsec, client[i].last_caid, client[i].last_srvid,
334 monitor_get_srvname(client[i].last_srvid), isec, con);
337 return(sbuf);
340 static void monitor_process_info()
342 int i;
343 time_t now;
345 now=time((time_t)0);
346 for (i=0; i<CS_MAXPID; i++)
347 if ((cfg->mon_hideclient_to <= 0) ||
348 (((now-client[i].lastecm)/60)<cfg->mon_hideclient_to) ||
349 (((now-client[i].lastemm)/60)<cfg->mon_hideclient_to) ||
350 (client[i].typ!='c'))
351 if (client[i].pid)
353 if ((client[cs_idx].monlvl<2) && (client[i].typ!='s'))
355 if ((strcmp(client[cs_idx].usr, client[i].usr)) ||
356 ((client[i].typ!='c') && (client[i].typ!='m')))
357 continue;
359 monitor_send_info(monitor_client_info('I', i), 0);
361 monitor_send_info(NULL, 1);
364 static void monitor_send_details(char *txt, int pid)
366 char buf[256];
367 snprintf(buf, 255, "[D-----]%d|%s\n", pid, txt);
368 monitor_send_info(buf, 0);
371 static void monitor_process_details_master(char *buf, int pid)
373 if (cfg->nice!=99)
374 sprintf(buf+200, ", nice=%d", cfg->nice);
375 else
376 buf[200]='\0';
377 sprintf(buf, "version=%s, system=%s%s", CS_VERSION_X, cs_platform(buf+100), buf+200);
378 monitor_send_details(buf, pid);
380 sprintf(buf, "max. clients=%d, client max. idle=%d sec", CS_MAXPID-2, cfg->cmaxidle);
381 monitor_send_details(buf, pid);
383 if( cfg->max_log_size )
384 sprintf(buf+200, "%d Kb", cfg->max_log_size);
385 else
386 strcpy(buf+200, "unlimited");
387 sprintf(buf, "max. logsize=%s", buf+200);
388 monitor_send_details(buf, pid);
390 sprintf(buf, "client timeout=%d sec, cache delay=%d msec", cfg->ctimeout, cfg->delay);
391 monitor_send_details(buf, pid);
393 //#ifdef CS_NOSHM
394 // sprintf(buf, "shared memory initialized (size=%d, fd=%d)", shmsize, shmid);
395 //#else
396 // sprintf(buf, "shared memory initialized (size=%d, id=%d)", shmsize, shmid);
397 //#endif
398 // monitor_send_details(buf, pid);
401 #ifdef CS_RDR_INIT_HIST
402 static void monitor_process_details_reader(int pid, int idx)
404 int r_idx;
405 char *p;
406 if ((r_idx=cs_idx2ridx(idx))>=0)
407 for (p=reader[r_idx].init_history; *p; p+=strlen(p)+1)
408 monitor_send_details(p, pid);
409 else
410 monitor_send_details("Missing reader index !", pid);
412 #endif
414 static void monitor_process_details(char *arg)
416 int pid, idx, val;
417 char sbuf[256];
418 if (!arg) return;
419 if ((idx=idx_from_pid(pid=atoi(arg)))<0)
420 monitor_send_details("Invalid PID", pid);
421 else
423 monitor_send_info(monitor_client_info('D', idx), 0);
424 switch(client[idx].typ)
426 case 's':
427 monitor_process_details_master(sbuf, pid);
428 break;
429 case 'c': case 'm':
430 break;
431 case 'r':
432 #ifdef CS_RDR_INIT_HIST
433 monitor_process_details_reader(pid, idx);
434 #endif
435 break;
436 case 'p':
437 break;
440 monitor_send_info(NULL, 1);
443 static void monitor_send_login(void)
445 char buf[64];
446 if (auth)
447 sprintf(buf, "[A-0000]1|%s logged in\n", client[cs_idx].usr);
448 else
449 strcpy(buf, "[A-0000]0|not logged in\n");
450 monitor_send_info(buf, 1);
453 static void monitor_login(char *usr)
455 char *pwd=NULL;
456 if ((usr) && (pwd=strchr(usr, ' ')))
457 *pwd++=0;
458 if (pwd)
459 monitor_auth_client(trim(usr), trim(pwd));
460 else
461 monitor_auth_client(NULL, NULL);
462 monitor_send_login();
465 static void monitor_logsend(char *flag)
467 #ifdef CS_LOGHISTORY
468 int i;
469 #endif
470 if (strcmp(flag, "on"))
472 client[cs_idx].log=0;
473 return;
475 if (client[cs_idx].log) // already on
476 return;
477 #ifdef CS_LOGHISTORY
478 for (i=(*loghistidx+3) % CS_MAXLOGHIST; i!=*loghistidx; i=(i+1) % CS_MAXLOGHIST)
480 char *p_usr, *p_txt;
481 p_usr=(char *)(loghist+(i*CS_LOGHISTSIZE));
482 p_txt=p_usr+32;
483 if ((p_txt[0]) &&
484 ((client[cs_idx].monlvl>1) || (!strcmp(p_usr, client[cs_idx].usr))))
486 char sbuf[8];
487 sprintf(sbuf, "%03.3d", client[cs_idx].logcounter);
488 client[cs_idx].logcounter=(client[cs_idx].logcounter+1) % 1000;
489 memcpy(p_txt+4, sbuf, 3);
490 monitor_send(p_txt);
493 #endif
494 client[cs_idx].log=1;
497 static int monitor_process_request(char *req)
499 int i, rc;
500 char *cmd[]={"login", "exit", "log", "status", "shutdown", "reload", "details"};
501 // char *cmd[]={"login", "exit", "log", "status", "shutdown", "reload"};
502 char *arg;
503 if( (arg=strchr(req, ' ')) )
505 *arg++=0;
506 trim(arg);
508 trim(req);
509 if ((!auth) && (strcmp(req, cmd[0])))
510 monitor_login(NULL);
511 for (rc=1, i=0; i<7; i++)
512 if (!strcmp(req, cmd[i]))
514 switch(i)
516 case 0: monitor_login(arg); break;
517 case 1: rc=0; break;
518 case 2: monitor_logsend(arg); break;
519 case 3: monitor_process_info(); break;
520 case 4: if (client[cs_idx].monlvl>3)
521 kill(client[0].pid, SIGQUIT);
522 break;
523 case 5: if (client[cs_idx].monlvl>2)
524 kill(client[0].pid, SIGHUP);
525 break;
526 case 6: monitor_process_details(arg); break;
527 default: continue;
529 break;
531 return(rc);
534 static void monitor_server()
536 int n;
537 client[cs_idx].typ='m';
538 while (((n=process_input(mbuf, sizeof(mbuf), cfg->cmaxidle))>=0) &&
539 monitor_process_request(mbuf));
540 cs_disconnect_client();
543 void module_monitor(struct s_module *ph)
545 static PTAB ptab;
546 ptab.ports[0].s_port = cfg->mon_port;
547 ph->ptab = &ptab;
548 ph->ptab->nports = 1;
550 if (cfg->mon_aulow<1)
551 cfg->mon_aulow=30;
552 strcpy(ph->desc, "monitor");
553 ph->type=MOD_CONN_UDP;
554 ph->multi=0;
555 ph->watchdog=1;
556 ph->s_ip=cfg->mon_srvip;
557 ph->s_handler=monitor_server;
558 ph->recv=monitor_recv;
559 // ph->send_dcw=NULL;