source: trunk/module-monitor.c@ 109

Last change on this file since 109 was 93, checked in by smurzch2, 11 years ago

Change timeouts from seconds to milliseconds.

Thanks for this patch to okmikel.
Timeouts are now ajustable in ms instead of seconds in the oscam.conf.
Values <= 100 are still interpreted as seconds because of compatibility reasons
to old config files

File size: 13.7 KB
Line 
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
8
9static int auth=0;
10
11static void monitor_check_ip()
12{
13 int ok=0;
14 struct s_ip *p_ip;
15
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)
20 {
21 cs_auth_client((struct s_auth *)0, "invalid ip");
22 cs_exit(0);
23 }
24}
25
26static void monitor_auth_client(char *usr, char *pwd)
27{
28 struct s_auth *account;
29
30 if (auth) return;
31 if ((!usr) || (!pwd))
32 {
33 cs_auth_client((struct s_auth *)0, NULL);
34 cs_exit(0);
35 }
36 for (account=cfg->account, auth=0; (account) && (!auth);)
37 {
38 if (account->monlvl)
39 auth=!(strcmp(usr, account->usr) | strcmp(pwd, account->pwd));
40 if (!auth)
41 account=account->next;
42 }
43 if (!auth)
44 {
45 cs_auth_client((struct s_auth *)0, "invalid account");
46 cs_exit(0);
47 }
48 if (cs_auth_client(account, NULL))
49 cs_exit(0);
50}
51
52static int secmon_auth_client(uchar *ucrc)
53{
54 ulong crc;
55 struct s_auth *account;
56
57 if (auth)
58 {
59 int s=memcmp(client[cs_idx].ucrc, ucrc, 4);
60 if (s)
61 cs_log("wrong user-crc or garbage !?");
62 return(!s);
63 }
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((unsigned char *)account->usr, strlen(account->usr), NULL), 16)))
69 {
70 memcpy(client[cs_idx].ucrc, ucrc, 4);
71 aes_set_key((char *)MD5((unsigned char *)account->pwd, strlen(account->pwd), NULL));
72 if (cs_auth_client(account, NULL))
73 cs_exit(0);
74 auth=1;
75 }
76 if (!auth)
77 {
78 cs_auth_client((struct s_auth *)0, "invalid user");
79 cs_exit(0);
80 }
81 return(auth);
82}
83
84int monitor_send_idx(int idx, char *txt)
85{
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((char *)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)));
105}
106
107#define monitor_send(t) monitor_send_idx(cs_idx, t)
108
109static int monitor_recv(uchar *buf, int l)
110{
111 int n;
112 uchar nbuf[3] = { 'U', 0, 0 };
113 static int bpos=0;
114 static uchar *bbuf=NULL;
115 if (!bbuf)
116 {
117 bbuf=(uchar *)malloc(l);
118 if (!bbuf)
119 {
120 cs_log("Cannot allocate memory (errno=%d)", errno);
121 cs_exit(1);
122 }
123 }
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]=='&')
131 {
132 int bsize;
133 if (n<21) // 5+16 is minimum
134 {
135 cs_log("packet to short !");
136 return(buf[0]=0);
137 }
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)
144 {
145// cs_log("DO >>>> copy-back");
146 memcpy(bbuf, buf+bsize, bpos=n-bsize);
147 n=bsize;
148 if (!write(client[cs_idx].ufd, nbuf, sizeof(nbuf))) cs_exit(1); // trigger new event
149 }
150 else if (n<bsize)
151 {
152 cs_log("packet-size mismatch !");
153 return(buf[0]=0);
154 }
155 aes_decrypt(buf+21, n-21);
156 if (memcmp(buf+5, i2b(4, crc32(0L, buf+10, n-10)), 4))
157 {
158 cs_log("CRC error ! wrong password ?");
159 return(buf[0]=0);
160 }
161 n=buf[9];
162 memmove(buf, buf+10, n);
163 }
164 else
165 {
166 uchar *p;
167 monitor_check_ip();
168 buf[n]='\0';
169 if ((p=(uchar *)strchr((char *)buf, 10)) && (bpos=n-(p-buf)-1))
170 {
171 memcpy(bbuf, p+1, bpos);
172 n=p-buf;
173 if (!write(client[cs_idx].ufd, nbuf, sizeof(nbuf))) cs_exit(1); // trigger new event
174 }
175 }
176 buf[n]='\0';
177 if (n=strlen(trim((char *)buf)))
178 client[cs_idx].last=time((time_t *) 0);
179 return(n);
180}
181
182static void monitor_send_info(char *txt, int last)
183{
184 static int seq=0, counter=0;
185 static char btxt[256] = {0};
186 char buf[8];
187 if (txt)
188 {
189 if (!btxt[0])
190 {
191 counter=0;
192 txt[2]='B';
193 }
194 else
195 counter++;
196 sprintf(buf, "%03d", counter);
197 memcpy(txt+4, buf, 3);
198 txt[3]='0'+seq;
199 }
200 else
201 if (!last)
202 return;
203
204 if (!last)
205 {
206 if (btxt[0]) monitor_send(btxt);
207 strncpy(btxt, txt, sizeof(btxt));
208 return;
209 }
210
211 if (txt && btxt[0])
212 {
213 monitor_send(btxt);
214 txt[2]='E';
215 strncpy(btxt, txt, sizeof(btxt));
216 }
217 else
218 {
219 if (txt)
220 strncpy(btxt, txt, sizeof(btxt));
221 btxt[2]=(btxt[2]=='B') ? 'S' : 'E';
222 }
223
224 if (btxt[0])
225 {
226 monitor_send(btxt);
227 seq=(seq+1)%10;
228 }
229 btxt[0]=0;
230}
231
232static int cs_idx2ridx(int idx)
233{
234 int i;
235 for (i=0; i<CS_MAXREADER; i++)
236 if (reader[i].cs_idx==idx)
237 return(i);
238 return(-1);
239}
240
241static char *monitor_get_srvname(int id)
242{
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);
251}
252
253static char *monitor_get_proto(int idx)
254{
255 int i;
256 char *ctyp;
257 switch(client[idx].typ)
258 {
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
266 {
267 switch(reader[i].typ) // TODO like ph
268 {
269 case R_MOUSE : ctyp="mouse"; break;
270 case R_INTERN : ctyp="intern"; break;
271 case R_SMART : ctyp="smartreader"; break;
272 case R_CAMD35 : ctyp="camd 3.5x";break;
273 case R_CAMD33 : ctyp="camd 3.3x";break;
274 case R_NEWCAMD : ctyp="newcamd"; break;
275 case R_RADEGAST: ctyp="radegast"; break;
276 case R_SERIAL : ctyp="serial"; break;
277 case R_GBOX : ctyp="gbox"; break;
278 default : ctyp="unknown"; break;
279 }
280 }
281 break;
282 default : ctyp=ph[client[idx].ctyp].desc;
283 }
284 return(ctyp);
285}
286
287static char *monitor_client_info(char id, int i)
288{
289 static char sbuf[256];
290
291 sbuf[0]='\0';
292 if (client[i].pid)
293 {
294 char ldate[16], ltime[16], *usr;
295 int lsec, isec, cnr, con, cau;
296 time_t now;
297 struct tm *lt;
298 now=time((time_t)0);
299
300 if ((cfg->mon_hideclient_to <= 0) ||
301 (((now-client[i].lastecm)/60)<cfg->mon_hideclient_to) ||
302 (((now-client[i].lastemm)/60)<cfg->mon_hideclient_to) ||
303 (client[i].typ!='c'))
304 {
305 lsec=now-client[i].login;
306 isec=now-client[i].last;
307 usr=client[i].usr;
308 if (((client[i].typ=='r') || (client[i].typ=='p')) &&
309 (con=cs_idx2ridx(i))>=0)
310 usr=reader[con].label;
311 if (client[i].dup)
312 con=2;
313 else
314 if ((client[i].tosleep) &&
315 (now-client[i].lastswitch>client[i].tosleep))
316 con=1;
317 else
318 con=0;
319 if (i-cdiff>0)
320 cnr=i-cdiff;
321 else
322 cnr=(i>1) ? i-1 : 0;
323 if( (cau=client[i].au+1) )
324 if ((now-client[i].lastemm)/60>cfg->mon_aulow)
325 cau=-cau;
326 lt=localtime(&client[i].login);
327 sprintf(ldate, "%2d.%02d.%02d",
328 lt->tm_mday, lt->tm_mon+1, lt->tm_year % 100);
329 sprintf(ltime, "%2d:%02d:%02d",
330 lt->tm_hour, lt->tm_min, lt->tm_sec);
331 sprintf(sbuf, "[%c--CCC]%d|%c|%d|%s|%d|%d|%s|%d|%s|%s|%s|%d|%04X:%04X|%s|%d|%d\n",
332 id, client[i].pid, client[i].typ, cnr, usr, cau, client[i].crypted,
333 cs_inet_ntoa(client[i].ip), client[i].port, monitor_get_proto(i),
334 ldate, ltime, lsec, client[i].last_caid, client[i].last_srvid,
335 monitor_get_srvname(client[i].last_srvid), isec, con);
336 }
337 }
338 return(sbuf);
339}
340
341static void monitor_process_info()
342{
343 int i;
344 time_t now;
345
346 now=time((time_t)0);
347 for (i=0; i<CS_MAXPID; i++)
348 if ((cfg->mon_hideclient_to <= 0) ||
349 (((now-client[i].lastecm)/60)<cfg->mon_hideclient_to) ||
350 (((now-client[i].lastemm)/60)<cfg->mon_hideclient_to) ||
351 (client[i].typ!='c'))
352 if (client[i].pid)
353 {
354 if ((client[cs_idx].monlvl<2) && (client[i].typ!='s'))
355 {
356 if ((strcmp(client[cs_idx].usr, client[i].usr)) ||
357 ((client[i].typ!='c') && (client[i].typ!='m')))
358 continue;
359 }
360 monitor_send_info(monitor_client_info('I', i), 0);
361 }
362 monitor_send_info(NULL, 1);
363}
364
365static void monitor_send_details(char *txt, int pid)
366{
367 char buf[256];
368 snprintf(buf, 255, "[D-----]%d|%s\n", pid, txt);
369 monitor_send_info(buf, 0);
370}
371
372static void monitor_process_details_master(char *buf, int pid)
373{
374 if (cfg->nice!=99)
375 sprintf(buf+200, ", nice=%d", cfg->nice);
376 else
377 buf[200]='\0';
378 sprintf(buf, "version=%s, system=%s%s", CS_VERSION_X, cs_platform(buf+100), buf+200);
379 monitor_send_details(buf, pid);
380
381 sprintf(buf, "max. clients=%d, client max. idle=%d sec", CS_MAXPID-2, cfg->cmaxidle);
382 monitor_send_details(buf, pid);
383
384 if( cfg->max_log_size )
385 sprintf(buf+200, "%d Kb", cfg->max_log_size);
386 else
387 strcpy(buf+200, "unlimited");
388 sprintf(buf, "max. logsize=%s", buf+200);
389 monitor_send_details(buf, pid);
390
391 sprintf(buf, "client timeout=%lu ms, cache delay=%ld ms", cfg->ctimeout, cfg->delay);
392 monitor_send_details(buf, pid);
393
394//#ifdef CS_NOSHM
395// sprintf(buf, "shared memory initialized (size=%d, fd=%d)", shmsize, shmid);
396//#else
397// sprintf(buf, "shared memory initialized (size=%d, id=%d)", shmsize, shmid);
398//#endif
399// monitor_send_details(buf, pid);
400}
401
402#ifdef CS_RDR_INIT_HIST
403static void monitor_process_details_reader(int pid, int idx)
404{
405 int r_idx;
406 char *p;
407 if ((r_idx=cs_idx2ridx(idx))>=0)
408 for (p=(char *)reader[r_idx].init_history; *p; p+=strlen(p)+1)
409 monitor_send_details(p, pid);
410 else
411 monitor_send_details("Missing reader index !", pid);
412}
413#endif
414
415static void monitor_process_details(char *arg)
416{
417 int pid, idx, val;
418 char sbuf[256];
419 if (!arg) return;
420 if ((idx=idx_from_pid(pid=atoi(arg)))<0)
421 monitor_send_details("Invalid PID", pid);
422 else
423 {
424 monitor_send_info(monitor_client_info('D', idx), 0);
425 switch(client[idx].typ)
426 {
427 case 's':
428 monitor_process_details_master(sbuf, pid);
429 break;
430 case 'c': case 'm':
431 break;
432 case 'r':
433#ifdef CS_RDR_INIT_HIST
434 monitor_process_details_reader(pid, idx);
435#endif
436 break;
437 case 'p':
438 break;
439 }
440 }
441 monitor_send_info(NULL, 1);
442}
443
444static void monitor_send_login(void)
445{
446 char buf[64];
447 if (auth)
448 sprintf(buf, "[A-0000]1|%s logged in\n", client[cs_idx].usr);
449 else
450 strcpy(buf, "[A-0000]0|not logged in\n");
451 monitor_send_info(buf, 1);
452}
453
454static void monitor_login(char *usr)
455{
456 char *pwd=NULL;
457 if ((usr) && (pwd=strchr(usr, ' ')))
458 *pwd++=0;
459 if (pwd)
460 monitor_auth_client(trim(usr), trim(pwd));
461 else
462 monitor_auth_client(NULL, NULL);
463 monitor_send_login();
464}
465
466static void monitor_logsend(char *flag)
467{
468#ifdef CS_LOGHISTORY
469 int i;
470#endif
471 if (strcmp(flag, "on"))
472 {
473 client[cs_idx].log=0;
474 return;
475 }
476 if (client[cs_idx].log) // already on
477 return;
478#ifdef CS_LOGHISTORY
479 for (i=(*loghistidx+3) % CS_MAXLOGHIST; i!=*loghistidx; i=(i+1) % CS_MAXLOGHIST)
480 {
481 char *p_usr, *p_txt;
482 p_usr=(char *)(loghist+(i*CS_LOGHISTSIZE));
483 p_txt=p_usr+32;
484 if ((p_txt[0]) &&
485 ((client[cs_idx].monlvl>1) || (!strcmp(p_usr, client[cs_idx].usr))))
486 {
487 char sbuf[8];
488 sprintf(sbuf, "%03d", client[cs_idx].logcounter);
489 client[cs_idx].logcounter=(client[cs_idx].logcounter+1) % 1000;
490 memcpy(p_txt+4, sbuf, 3);
491 monitor_send(p_txt);
492 }
493 }
494#endif
495 client[cs_idx].log=1;
496}
497
498static int monitor_process_request(char *req)
499{
500 int i, rc;
501 char *cmd[]={"login", "exit", "log", "status", "shutdown", "reload", "details"};
502// char *cmd[]={"login", "exit", "log", "status", "shutdown", "reload"};
503 char *arg;
504 if( (arg=strchr(req, ' ')) )
505 {
506 *arg++=0;
507 trim(arg);
508 }
509 trim(req);
510 if ((!auth) && (strcmp(req, cmd[0])))
511 monitor_login(NULL);
512 for (rc=1, i=0; i<7; i++)
513 if (!strcmp(req, cmd[i]))
514 {
515 switch(i)
516 {
517 case 0: monitor_login(arg); break;
518 case 1: rc=0; break;
519 case 2: monitor_logsend(arg); break;
520 case 3: monitor_process_info(); break;
521 case 4: if (client[cs_idx].monlvl>3)
522 kill(client[0].pid, SIGQUIT);
523 break;
524 case 5: if (client[cs_idx].monlvl>2)
525 kill(client[0].pid, SIGHUP);
526 break;
527 case 6: monitor_process_details(arg); break;
528 default: continue;
529 }
530 break;
531 }
532 return(rc);
533}
534
535static void monitor_server()
536{
537 int n;
538 client[cs_idx].typ='m';
539 while (((n=process_input(mbuf, sizeof(mbuf), cfg->cmaxidle))>=0) &&
540 monitor_process_request((char *)mbuf));
541 cs_disconnect_client();
542}
543
544void module_monitor(struct s_module *ph)
545{
546 static PTAB ptab;
547 ptab.ports[0].s_port = cfg->mon_port;
548 ph->ptab = &ptab;
549 ph->ptab->nports = 1;
550
551 if (cfg->mon_aulow<1)
552 cfg->mon_aulow=30;
553 strcpy(ph->desc, "monitor");
554 ph->type=MOD_CONN_UDP;
555 ph->multi=0;
556 ph->watchdog=1;
557 ph->s_ip=cfg->mon_srvip;
558 ph->s_handler=monitor_server;
559 ph->recv=monitor_recv;
560// ph->send_dcw=NULL;
561}
Note: See TracBrowser for help on using the repository browser.