/* $Id$ */ #include #include #include "bbs.h" extern void utmplogin(int uid, int index, const int like[MAX_FRIEND], const int hate[MAX_REJECT]); extern int genfriendlist(int uid, int index, ocfs_t *fs, int maxfs); extern void utmplogoutall(void); #ifdef FAKEDATA FILE *fp; #endif #ifdef UTMPLOG FILE *logfp; #endif clock_t begin_clock; time_t begin_time; int count_flooding, count_login; #ifdef NOFLOODING /* 0 ok, 1 delay action, 2 reject */ int action_frequently(int uid) { int i; time_t now = time(NULL); time_t minute = now/60; time_t hour = minute/60; static time_t flood_base_minute; static time_t flood_base_hour; static struct { unsigned short lastlogin; // truncated time_t unsigned char minute_count; unsigned char hour_count; } flooding[MAX_USERS]; if(minute!=flood_base_minute) { for(i=0; i30 || flooding[uid].hour_count>60) { count_flooding++; return 2; } flooding[uid].minute_count++; flooding[uid].hour_count++; flooding[uid].lastlogin=now; if(flooding[uid].minute_count>5 || flooding[uid].hour_count>20) { count_flooding++; return 1; } return 0; } #endif /* NOFLOODING */ void syncutmp(int cfd) { int i; int like[MAX_FRIEND]; int hate[MAX_REJECT]; #ifdef UTMPLOG int x=-1; if(logfp && ftell(logfp)> 500*(1<<20)) { fclose(logfp); logfp=NULL; } if(logfp) fwrite(&x, sizeof(x), 1, logfp); #endif printf("logout all\n"); utmplogoutall(); fprintf(stderr,"sync begin\n"); for(i=0; i 500*(1<<20)) { fclose(logfp); logfp=NULL; } #endif Signal(SIGPIPE, SIG_IGN); while( (ch = getopt(argc, argv, "i:h")) != -1 ) switch( ch ){ case 'i': iface_ip = optarg; break; case 'h': default: fprintf(stderr, "usage: utmpserver [-i [interface_ip]:port]\n"); return 1; } #ifdef FAKEDATA fp=fopen("utmp.data","rb"); #else if( (sfd = tobind(iface_ip, port)) < 0 ) return 1; #endif while(1) { #ifdef FAKEDATA if(fread(&cmd, sizeof(cmd), 1, fp)==0) break; #else len = sizeof(clientaddr); if( (cfd = accept(sfd, (struct sockaddr *)&clientaddr, &len)) < 0 ){ if( errno != EINTR ) sleep(1); continue; } toread(cfd, &cmd, sizeof(cmd)); #endif if(cmd==-1) { syncutmp(cfd); #ifndef FAKEDATA close(cfd); #endif firstsync=1; continue; } if(!firstsync) { // don't accept client before first sync, to prevent incorrect friend data close(cfd); continue; } fail=0; #ifdef FAKEDATA fread(&uid, sizeof(uid), 1, fp); fread(&index, sizeof(index), 1, fp); #else if(cmd==-2) { if(toread(cfd, &index, sizeof(index)) <= 0) fail=1; if(toread(cfd, &uid, sizeof(uid)) <= 0) fail=1; } else if(cmd>=0) { // old client fail=1; } else { printf("unknown cmd=%d\n",cmd); } #endif if(index>=USHM_SIZE) { fprintf(stderr, "bad index=%d\n",index); fail=1; } if(fail) { #ifndef FAKEDATA close(cfd); #endif continue; } count_login++; processlogin(cfd, uid, index); if(count_login>=4000 || time(NULL)-begin_time>30*60) showstat(); #ifndef FAKEDATA close(cfd); #endif } #ifdef FAKEDATA fclose(fp); #endif return 0; }