/* $Id: misc.c,v 1.226 2006/10/18 10:51:52 rav Exp $ */ /* Intro {{{ * ---------------------------------------------------------------- * DConnect Daemon * * #(@) Copyright (c) 2002, DConnect development team * #(@) Homepage: http://www.dc.ds.pg.gda.pl/ * * ---------------------------------------------------------------- * }}} */ #include "pch.h" extern userrec_t *user[]; extern hub_t *hub[]; extern config_t conf; extern int NUSERS; extern int NHUBS; extern char *__progname; extern const char *reserved_nicks[]; extern FILE* file_net; extern FILE* file_proto; extern FILE* file_wrng; extern FILE* file_con; extern FILE* file_chat; extern char DAEMON; extern pthread_mutex_t mutex_inet_ntoa; extern pthread_mutex_t mutex_my_hosts_access; extern pthread_mutex_t mutex_myinfo; extern int allow_severity; extern int deny_severity; extern time_t last_penalties_update; /* controlled free() {{{ */ void my_free1(void *p) { void **ptr=(void**) p; if (ptr&&*ptr) free(*ptr); *ptr=NULL; } /* }}} */ /* controlled realloc() {{{ */ void *my_realloc(void *ptr,size_t size) { void *tmp=NULL; if (size>MAXBLOCK) { debug(DEBUG_WRNG|DEBUG_NET|DEBUG_PROTO,"my_realloc() failed: MAXBLOCK already reached"); my_free(ptr); return NULL; } tmp=realloc(ptr,size); if (tmp==NULL) { debug(DEBUG_WRNG|DEBUG_NET|DEBUG_PROTO,"my_realloc() failed: %s",strerror(errno)); exit(0); } return tmp; } /* }}} */ /* controlled malloc() {{{ */ void *my_malloc(size_t size) { return my_realloc(NULL,size); } /* }}} */ char *my_inet_ntoa(struct in_addr addr) { char *buf=NULL; pthread_mutex_lock(&mutex_inet_ntoa); my_duplicate(inet_ntoa(addr),&buf); pthread_mutex_unlock(&mutex_inet_ntoa); return buf; } void my_duplicate(char *str, char **duplicate) { my_free(*duplicate); *duplicate=strdup(str); if (!duplicate) debug(DEBUG_PROTO,"my_duplicate() failed: %s",strerror(errno)); } /* get_progname() - from openssh {{{ */ char *get_progname(char *argv0) { #ifdef HAVE___PROGNAME extern char *__progname; return __progname; #else char *p; if (argv0==NULL) return "unknown"; p=strrchr(argv0,'/'); if (p==NULL) p=argv0; else p++; return p; #endif } /* }}} */ /* randomize() - feed a random numbers generator {{{ */ void randomize( void ) { unsigned int seed=0; FILE * rdev = fopen( "/dev/urandom", "r" ); if ( rdev != NULL ) { seed = fgetc( rdev ); fclose( rdev ); } seed += getpid() + time( NULL ); srand( seed ); } /* }}} */ /* lockgen() - lock generator: 'salt Pk=privkey' {{{ */ void lock_gen(char *lock) { int i, n; // debug(DEBUG_PROTO,"lockgen() enter"); n=sprintf(lock,"%s","EXTENDEDPROTOCOL"); for(i=n;i> 4); save = lock[i]; } tmp[0] ^= tmp[i - 1]; key = malloc(10*(SALT_LEN-1)+1); offset = 0; for(i = 0; ikey=key; } /* my_vsnprintf() - allocate a sufficiently large string and print into it {{{ */ /* simplified version */ char *my_vsprintf(const char *fmt, va_list ap) { int n=-1, size=8192; char *p=NULL; // debug(DEBUG_PROTO,"my_vsprintf() enter"); if ((p=my_malloc((size_t)size))==NULL) return NULL; while (1) { n=vsnprintf(p,(size_t)size,fmt,ap); if (n!=-1 && n2.1 if ((p=my_realloc(p,(size_t)size))==NULL) return NULL; } // debug(DEBUG_PROTO,"my_vsprintf() leave"); return p; } /* }}} */ char *my_sprintf(const char *fmt, ...) { char *p=NULL; va_list args; va_start(args, fmt); p=my_vsprintf(fmt,args); va_end(args); return p; } /* }}} */ void debug_print(int level, FILE *file, char *timer, char *str) { if(!level || !file) return; fprintf(file,"[%s] %s\r\n",timer,str); fflush(file); } /* debug() - debugging / logging {{{ */ void debug(char level,const char *fmt,...) { char *str=NULL,timer[50]; unsigned char lvl; time_t tm; va_list args; lvl=conf.log_level&level; if(!lvl) return; /* compose the debug message */ va_start(args,fmt); str=(char *)my_vsprintf(fmt,args); va_end(args); time(&tm); strftime(timer,sizeof(timer),"%Y.%m.%d %T",localtime(&tm)); /* print to syslog */ if (lvl&DEBUG_SYS) { openlog("dcd",LOG_PID|LOG_CONS,LOG_DAEMON); syslog(LOG_NOTICE,"%s\n",str); closelog(); } debug_print(lvl&DEBUG_STD ,stderr ,timer,str); debug_print(lvl&DEBUG_NET ,file_net ,timer,str); debug_print(lvl&DEBUG_PROTO ,file_proto ,timer,str); debug_print(lvl&DEBUG_WRNG ,file_wrng ,timer,str); debug_print(lvl&DEBUG_CON ,file_con ,timer,str); debug_print(lvl&DEBUG_CHAT ,file_chat ,timer,str); my_free(str); } /* }}} */ /* nick2id() - convert user's nick to table index {{{ */ int nick2id(char *nick) { int i; for(i=0;inick && !strcasecmp(user[i]->nick,nick)) return i; return -1; } /* }}} */ /* ip2hub() - convert user's nick to table index {{{ */ int ip2hub(char *ip) { int i; for(i=0;iip,ip)) return i; return -1; } /* }}} */ /* validnick() - check if a given nick is a valid one returns one of NICK_* communicate {{{ */ char validnick(userrec_t *usr,char *nick) { int n=0; if (!nick || !*nick) return NICK_IS_EMPTY; /* if nick is not too long */ if (strlen(nick)+1>NICK_LEN) return NICK_IS_TOO_LONG; /* if nick contains not valid characters */ if (strlen(nick)>0 && nick[0]=='#') return NICK_IS_WITH_INVALID_CHARACTERS; for(n=0;n' || nick[n]=='?') return NICK_IS_WITH_INVALID_CHARACTERS; /* if nick is already in use */ if (nick2id(nick)!=-1) return NICK_IS_ALREADY_USED; /* if nick requiers password/ usr->password will contain password to check*/ if (!usr->cons && validlogin(usr,nick,NULL)) return NICK_REQUIRES_PASSWORD; /* if nick is not one of constatntly reserved nicks */ n=0; while(reserved_nicks[n][0]) if (!strcasecmp(nick,reserved_nicks[n++])) return NICK_IS_RESERVED; /* if nick matches any of allowed patterns */ if (!usr->cons && *(conf.conf_nallow) && !nick_allowed(usr,nick)) return NICK_IS_NOT_IN_PATTERNS; /* user nick is valid */ return NICK_IS_OK; } /* }}} */ /* validkey() - check for a valid $Key sequence - FIXME {{{ */ char validkey(userrec_t *usr, char *key) { int ec=0; if (!key || !*key) goto leave; ec=!strcmp(usr->key,key); leave: my_free(usr->key); return ec; } /* }}} */ int compare_myinfo(myinfo_t *myinfo0, myinfo_t *myinfo1) { int ecode=1; pthread_mutex_lock(&mutex_myinfo); // debug(DEBUG_PROTO,"in compare_myinfo()"); ecode=strcmp(myinfo1->cache,myinfo0->cache); // debug(DEBUG_PROTO,"out compare_myinfo()"); pthread_mutex_unlock(&mutex_myinfo); return ecode; } char *flag_myinfo(myinfo_t *myinfo) { static char *flags[]={ "", //0 "Normal", //1 "Away", //2 "Away", //3 "Server; uptime > 2 hours, > 2 GB shared, upload > 200 MB", //4 "Server; uptime > 2 hours, > 2 GB shared, upload > 200 MB", //5 "Server Away; uptime > 2 hours, > 2 GB shared, upload > 200 MB", //6 "Server Away; uptime > 2 hours, > 2 GB shared, upload > 200 MB", //7 "Fireball; upload > 100 kB/s", //8 "Fireball; upload > 100 kB/s", //9 "Fireball Away; upload > 100 kB/s", //10 "Fireball Away; upload > 100 kB/s" //11 }; return flags[myinfo->flag]; } void move_myinfo(myinfo_t *from, myinfo_t *to) { // debug(DEBUG_PROTO,"in move_myinfo()"); pthread_mutex_lock(&mutex_myinfo); // *to=*from; strcpy(to->desc,from->desc); strcpy(to->ctype,from->ctype); to->flag=from->flag; strcpy(to->email,from->email); to->share=from->share; strcpy(to->cache,from->cache); pthread_mutex_unlock(&mutex_myinfo); // debug(DEBUG_PROTO,"out move_myinfo()"); } /* fill_myinfo() - fill user's record with data received in $MyINFO {{{ */ int fill_myinfo(userrec_t *usr, myinfo_t *myinfo, char *info, char *line) { char *tmp=info, *all, *nick, *desc, *space, *ctype, flag, *email, *share; all=strsep(&tmp," "); if (!tmp || strcmp(all,"$ALL")) return MyINFO_ALL; nick=strsep(&tmp," "); if (!tmp || strcmp(nick,usr->nick)) return MyINFO_NICK; desc=strsep(&tmp,"$"); if(!tmp || strlen(desc)>DESC_LEN-1) return MyINFO_DESC; space=strsep(&tmp,"$"); if(!tmp || *space!=' ') return MyINFO_SPACE; ctype=strsep(&tmp,"$"); if(!tmp || strlen(ctype)<1 || strlen(ctype)>CTYPE_LEN-1) return MyINFO_SPEED; flag=ctype[strlen(ctype)-1]; if (flag<1 && flag>11) return MyINFO_FLAG; ctype[strlen(ctype)-1]='\000'; email=strsep(&tmp,"$"); if(!tmp || strlen(email)>EMAIL_LEN-1) return MyINFO_EMAIL; share=strsep(&tmp,"$"); if(!tmp || strlen(share)>SHARE_LEN-1) return MyINFO_SHARE; strcpy(myinfo->desc,desc); strcpy(myinfo->email,email); strcpy(myinfo->ctype,ctype); myinfo->flag=flag; sscanf(share,"%"SCNu64,&(myinfo->share)); strcpy(myinfo->cache,line); return MyINFO_OK; } /* }}} */ /* check_timeout() - check clients' times {{{ */ void check_timeout(userrec_t *usr) { time_t tv; // debug(DEBUG_PROTO,"check_timeout enter"); if ((!conf.idle_timeout && !conf.register_timeout)) return; time(&tv); if (conf.idle_timeout&&(usr->cons==0) && tv-usr->idle>conf.idle_timeout) { usr->reason=strdup("idle timeout"); user_set_state(usr, STATE_QUIT); return; } if (conf.register_timeout && tv-usr->idle>conf.register_timeout) { if (conf.minslots && user_tst_state(usr,STATE_SR)) { pubmsg(usr,"Your client did not respond to slots checking"); pubmsg(usr,"Sorry, You must leave"); pubmsg(usr,"dcgui-qt/dctc - Please share a file of name 'fakesearch.txt' with more than 0 bytes inside!"); pubmsg(usr,"It also could be a connection problem"); usr->reason=strdup("slot checking timout"); user_set_state(usr, STATE_QUIT); } if (!user_tst_state(usr,STATE_REGISTERED|STATE_QUIT)) { pubmsg(usr,"REGISTRATION TIMEOUT"); usr->reason=strdup("registration timeout"); user_set_state(usr, STATE_QUIT); } } // debug(DEBUG_PROTO,"check_timeout leave"); } /* }}} */ int my_hosts_access(struct request_info *req) { int ec=1; pthread_mutex_lock(&mutex_my_hosts_access); ec=hosts_access(req); pthread_mutex_unlock(&mutex_my_hosts_access); return ec; } /* denied() - check if remote host is not allowed to connect {{{ */ char denied(int sock) { int ec=1; struct request_info req; // debug(DEBUG_PROTO,"denied() enter") ; request_init(&req,RQ_DAEMON,__progname,RQ_FILE,sock,0); fromhost(&req); if (my_hosts_access(&req)) ec=0; // debug(DEBUG_PROTO,"denied() leave()"); return ec; } /* }}} */ /* make_path() - compose direct path to file {{{ */ void make_path(char *dir,char **file) { char *tmp=NULL,*p; if (!**file) return; my_duplicate(*file,&tmp); p=strrchr(tmp,'/'); if (p) p++; else p=tmp; *file=(char *)my_realloc(*file,strlen(dir)+strlen(p)+2); sprintf(*file,"%s%s%s",dir,(dir[strlen(dir)-1]=='/')?"":"/",p); my_free(tmp); } /* }}} */ /* make_paths() - compose direct paths to files for further use {{{ */ void make_paths(config_t *conf) { /* path to main log file */ make_path(conf->log_dir,&(conf->log_main)); /* path to net log file */ make_path(conf->log_dir,&(conf->log_net)); /* path to proto log file */ make_path(conf->log_dir,&(conf->log_proto)); /* path to wrng log file */ make_path(conf->log_dir,&(conf->log_wrng)); /* path to console log file */ make_path(conf->log_dir,&(conf->log_con)); /* path to chat log file */ make_path(conf->log_dir,&(conf->log_chat)); /* path to welcome message file */ make_path(CONFIGDIR,&(conf->conf_welcome)); /* path to motd file */ make_path(CONFIGDIR,&(conf->conf_motd)); /* path to bans file */ make_path(CONFIGDIR,&(conf->conf_banned)); /* path to dcd users file */ make_path(CONFIGDIR,&(conf->conf_cusers)); /* path to console host access file */ make_path(CONFIGDIR,&(conf->conf_callow)); /* path to allowed nicks file */ make_path(CONFIGDIR,&(conf->conf_nallow)); /* path to penalties file */ make_path(CONFIGDIR,&(conf->conf_penalties)); /* path to rules file */ make_path(CONFIGDIR,&(conf->conf_rules)); make_path(CONFIGDIR,&(conf->conf_hublinks)); make_path(CONFIGDIR,&(conf->conf_usercommands)); } /* }}} */ /* uptime() - return string representing uptime {{{ */ void uptime(time_t starttime, char *str) { time_t up; long d; int h,m,s; time(&up); up-=starttime; if (up<0) up=0; d=up/(3600*24); up%=3600*24; h=up/3600; up%=3600; m=up/60; s=up%60; if (d) snprintf(str,32,"%ld day%s, %02d:%02d:%02d",d,(d==1)?"":"s",h,m,s); else snprintf(str,32,"%02d:%02d:%02d",h,m,s); } /* }}} */ /* toggle_flag() - toggle configuration flag {{{ */ inline void toggle_flag(config_t *conf,userrec_t *usr,unsigned char flag) { if (conf->flags&flag) conf->flags&=~flag; else conf->flags|=flag; disttcpf(usr,"Option has been turned %s.\r\n",(conf->flags&flag)?"on":"off"); } /* }}} */ int add2buf(char **buf, char *string) { char *tmp; int len=1; if (!string || !*string) return 0; if (*buf) len+=strlen(*buf); len+=strlen(string); tmp=my_malloc(len); if(!tmp) return 0; tmp[0]=0; if (*buf) strcat(tmp,*buf); strcat(tmp,string); my_free(*buf); *buf=tmp; return len; } /* VIM Settings {{{ * Local variables: * tab-width: 4 * c-basic-offset: 4 * soft-stop-width: 4 * c indent on * End: * vim600: sw=4 ts=4 sts=4 cindent fdm=marker * vim<600: sw=4 ts=4 * }}} */