⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ipban.c

📁 打魔兽战网的都知道他是什么
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 2000  Gediminas (gugini@fortas.ktu.lt) * Copyright (C) 2002  Bart硂miej Butyn (bartek@milc.com.pl) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. */#define IPBAN_INTERNAL_ACCESS#include "common/setup_before.h"#include <stdio.h>#ifdef HAVE_STDDEF_H# include <stddef.h>#else# ifndef NULL#  define NULL ((void *)0)# endif#endif#ifdef STDC_HEADERS# include <stdlib.h>#else# ifdef HAVE_MALLOC_H#  include <malloc.h># endif#endif#ifdef HAVE_STRING_H# include <string.h>#else# ifdef HAVE_STRINGS_H#  include <strings.h># endif#endif#include <ctype.h>#include "compat/strchr.h"#include "compat/strdup.h"#include "compat/strcasecmp.h"#include "compat/strsep.h"#include <errno.h>#include "compat/strerror.h"#ifdef TIME_WITH_SYS_TIME# include <sys/time.h># include <time.h>#else# ifdef HAVE_SYS_TIME_H#  include <sys/time.h># else#  include <time.h># endif#endif#include "common/eventlog.h"#include "common/util.h"#include "connection.h"#include "message.h"#include "prefs.h"#include "common/list.h"#include "common/xalloc.h"#include "server.h"#include "ipban.h"#include "common/setup_after.h"static int identify_ipban_function(const char * funcstr);static int ipban_func_del(t_connection * c, char const * cp);static int ipban_func_list(t_connection * c);static int ipban_func_check(t_connection * c, char const * cp);static int ipban_unload_entry(t_ipban_entry * e);static int ipban_identical_entry(t_ipban_entry * e1, t_ipban_entry * e2);static t_ipban_entry * ipban_str_to_ipban_entry(char const * cp);static char * ipban_entry_to_str(t_ipban_entry const * entry);static unsigned long ipban_str_to_ulong(char const * ipaddr);static int ipban_could_be_exact_ip_str(char const * str);static int ipban_could_be_ip_str(char const * ipstr);static void ipban_usage(t_connection * c);static t_list * ipbanlist_head = NULL;static time_t lastchecktime = 0;extern int ipbanlist_create(void){    ipbanlist_head = list_create();    return 0;}extern int ipbanlist_destroy(void){    t_elem *		curr;    t_ipban_entry *	entry;        if (ipbanlist_head)    {	LIST_TRAVERSE(ipbanlist_head,curr)	{	    entry = elem_get_data(curr);	    if (!entry) /* should not happen */	    {		eventlog(eventlog_level_error,__FUNCTION__,"ipbanlist contains NULL item");		continue;	    }	    if (list_remove_elem(ipbanlist_head,&curr)<0)		eventlog(eventlog_level_error,__FUNCTION__,"could not remove item from list");	    ipban_unload_entry(entry);	}	if (list_destroy(ipbanlist_head)<0)	    return -1;	ipbanlist_head = NULL;    }        return 0;}extern int ipbanlist_load(char const * filename){    FILE *		fp;    char *		buff;    char *		ip;    char *		timestr;    unsigned int	currline;    unsigned int	endtime;        if (!filename)    {        eventlog(eventlog_level_error,__FUNCTION__,"got NULL filename");	return -1;    }        if (!(fp = fopen(filename,"r")))    {        eventlog(eventlog_level_error,__FUNCTION__,"could not open banlist file \"%s\" for reading (fopen: %s)",filename,pstrerror(errno));	return -1;    }    for (currline=1; (buff = file_get_line(fp)); currline++)    {	ip = buff;		/* eat whitespace in front */	while (*ip=='\t' || *ip==' ') ip++;	if (*ip=='\0' || *ip=='#')	{	    continue;	}		/* eat whitespace in back */	while (ip[strlen(ip)-1]==' ' || ip[strlen(ip)-1]=='\t')	    ip[strlen(ip)-1] = '\0';		if (strchr(ip,' ') || strchr(ip,'\t'))	{	    timestr = ip;	    while (*timestr!=' ' && *timestr!='\t') timestr++;	    *timestr = '\0';	    timestr++;	    while (*timestr==' ' || *timestr=='\t') timestr++;	}	else	    timestr = NULL;	    	if (!timestr)	    endtime = 0;	else	    if (clockstr_to_seconds(timestr,&endtime)<0)	    {		eventlog(eventlog_level_error,__FUNCTION__,"could not convert to seconds. Banning pernamently.");		endtime = 0;	    }		if (ipbanlist_add(NULL,ip,endtime)!=0)	{	    eventlog(eventlog_level_warn,__FUNCTION__,"error in %.64s at line %u",filename,currline);	    continue;	}	    }        file_get_line(NULL); // clear file_get_line buffer    if (fclose(fp)<0)        eventlog(eventlog_level_error,__FUNCTION__,"could not close banlist file \"%s\" after reading (fclose: %s)",filename,pstrerror(errno));        return 0;}extern int ipbanlist_save(char const * filename){    t_elem const *	curr;    t_ipban_entry *	entry;    FILE *		fp;    char *		ipstr;    char		line[1024];        if (!filename)    {        eventlog(eventlog_level_error,__FUNCTION__,"got NULL filename");	return -1;    }        if (!(fp = fopen(filename,"w")))    {        eventlog(eventlog_level_error,__FUNCTION__,"could not open banlist file \"%s\" for writing (fopen: %s)",filename,pstrerror(errno));	return -1;    }/*    if (ftruncate(fp,0)<0)    {        eventlog(eventlog_level_error,__FUNCTION__,"could not truncate banlist file \"%s\" (ftruncate: %s)",filename,pstrerror(errno));	return -1;    }*/        LIST_TRAVERSE_CONST(ipbanlist_head,curr)    {	entry = elem_get_data(curr);	if (!entry)	{	    eventlog(eventlog_level_error,__FUNCTION__,"ipbanlist contains NULL element");	    continue;	}	if (!(ipstr = ipban_entry_to_str(entry)))	{	    eventlog(eventlog_level_error,__FUNCTION__,"got NULL ipstr");	    continue;	}	if (entry->endtime == 0)	    sprintf(line,"%s\n",ipstr);	else    	    sprintf(line,"%s %ld\n",ipstr,entry->endtime);	if (!(fwrite(line,strlen(line),1,fp)))	    eventlog(eventlog_level_error,__FUNCTION__,"could not write to banlist file (write: %s)",pstrerror(errno));	xfree(ipstr);    }	    if (fclose(fp)<0)    {        eventlog(eventlog_level_error,__FUNCTION__,"could not close banlist file \"%s\" after writing (fclose: %s)",filename,pstrerror(errno));	return -1;    }        return 0; }extern int ipbanlist_check(char const * ipaddr){    t_elem const *  curr;    t_ipban_entry * entry;    char *          whole;    char const *    ip1;    char const *    ip2;    char const *    ip3;    char const *    ip4;    int		    counter;        if (!ipaddr)    {	eventlog(eventlog_level_warn,__FUNCTION__,"got NULL ipaddr");	return -1;    }        whole = xstrdup(ipaddr);    eventlog(eventlog_level_debug,__FUNCTION__,"lastcheck: %u, now: %u, now-lc: %u.",(unsigned)lastchecktime,(unsigned)now,(unsigned)(now-lastchecktime));        if (now - lastchecktime >= (signed)prefs_get_ipban_check_int()) /* unsigned; no need to check prefs < 0 */    {	ipbanlist_unload_expired();	lastchecktime = now;    }        ip1 = strtok(whole,".");    ip2 = strtok(NULL,".");    ip3 = strtok(NULL,".");    ip4 = strtok(NULL,".");        if (!ip1 || !ip2 || !ip3 || !ip4)    {	eventlog(eventlog_level_warn,__FUNCTION__,"got bad IP address \"%s\"",ipaddr);	xfree(whole);	return -1;    }        eventlog(eventlog_level_debug,__FUNCTION__,"checking %s.%s.%s.%s",ip1,ip2,ip3,ip4);        counter = 0;    LIST_TRAVERSE_CONST(ipbanlist_head,curr)    {	entry = elem_get_data(curr);	if (!entry)	{	    eventlog(eventlog_level_error,__FUNCTION__,"ipbanlist contains NULL item");	    return -1;	}	counter++; 	switch (entry->type)	{	case ipban_type_exact:	    if (strcmp(entry->info1,ipaddr)==0)	    {		eventlog(eventlog_level_debug,__FUNCTION__,"address %s matched exact %s",ipaddr,entry->info1);		xfree(whole);		return counter;	    }	    eventlog(eventlog_level_debug,__FUNCTION__,"address %s does not match exact %s",ipaddr,entry->info1);	    continue;	 	case ipban_type_wildcard:	    if (strcmp(entry->info1,"*")!=0 && strcmp(ip1,entry->info1)!=0)	    {		eventlog(eventlog_level_debug,__FUNCTION__,"address %s does not match part 1 of wildcard %s.%s.%s.%s",ipaddr,entry->info1,entry->info2,entry->info3,entry->info4);		continue;	    }	    if (strcmp(entry->info2,"*")!=0 && strcmp(ip2,entry->info2)!=0)	    {		eventlog(eventlog_level_debug,__FUNCTION__,"address %s does not match part 2 of wildcard %s.%s.%s.%s",ipaddr,entry->info1,entry->info2,entry->info3,entry->info4);		continue;	    }	    if (strcmp(entry->info3,"*")!=0 && strcmp(ip3,entry->info3)!=0)	    {		eventlog(eventlog_level_debug,__FUNCTION__,"address %s does not match part 3 of wildcard %s.%s.%s.%s",ipaddr,entry->info1,entry->info2,entry->info3,entry->info4);		continue;	    }	    if (strcmp(entry->info4,"*")!=0 && strcmp(ip4,entry->info4)!=0)	    {		eventlog(eventlog_level_debug,__FUNCTION__,"address %s does not match part 4 of wildcard %s.%s.%s.%s",ipaddr,entry->info1,entry->info2,entry->info3,entry->info4);		continue;	    }	    	    eventlog(eventlog_level_debug,__FUNCTION__,"address %s matched wildcard %s.%s.%s.%s",ipaddr,entry->info1,entry->info2,entry->info3,entry->info4);	    xfree(whole);	    return counter;	    	case ipban_type_range:	    if ((ipban_str_to_ulong(ipaddr) >= ipban_str_to_ulong(entry->info1)) &&		(ipban_str_to_ulong(ipaddr) <= ipban_str_to_ulong(entry->info2)))	    {		eventlog(eventlog_level_debug,__FUNCTION__,"address %s matched range %s-%s",ipaddr,entry->info1,entry->info2);		xfree(whole);		return counter;	    }	    eventlog(eventlog_level_debug,__FUNCTION__,"address %s does not match range %s-%s",ipaddr,entry->info1,entry->info2);	    continue;		case ipban_type_netmask:	    {		unsigned long	lip1;		unsigned long	lip2;		unsigned long	netmask;		if (!(lip1 = ipban_str_to_ulong(ipaddr)))		    return -1;		if (!(lip2 = ipban_str_to_ulong(entry->info1)))		    return -1;		if (!(netmask = ipban_str_to_ulong(entry->info2)))		    return -1;		lip1 = lip1 & netmask;		lip2 = lip2 & netmask;				if (lip1 == lip2)		{		    eventlog(eventlog_level_debug,__FUNCTION__,"address %s matched netmask %s/%s",ipaddr,entry->info1,entry->info2);		    xfree(whole);		    return counter;		}		eventlog(eventlog_level_debug,__FUNCTION__,"address %s does not match netmask %s/%s",ipaddr,entry->info1,entry->info2);		continue;	    }			case ipban_type_prefix:	    {		unsigned long	lip1;		unsigned long	lip2;		int		prefix;						if (!(lip1 = ipban_str_to_ulong(ipaddr)))		    return -1;		if (!(lip2 = ipban_str_to_ulong(entry->info1)))		    return -1;		prefix = atoi(entry->info2);		lip1 = lip1 >> (32 - prefix);		lip2 = lip2 >> (32 - prefix);				if (lip1 == lip2)		{		    eventlog(eventlog_level_debug,__FUNCTION__,"address %s matched prefix %s/%s",ipaddr,entry->info1,entry->info2);		    xfree(whole);		    return counter;		}		eventlog(eventlog_level_debug,__FUNCTION__,"address %s does not match prefix %s/%s",ipaddr,entry->info1,entry->info2);		continue;	    }		default:  /* unknown type */	    eventlog(eventlog_level_warn,__FUNCTION__,"found bad ban type %d",(int)entry->type);	}    }        xfree(whole);    return 0;}extern int ipbanlist_add(t_connection * c, char const * cp, time_t endtime){    t_ipban_entry *	entry;    char		tstr[MAX_MESSAGE_LEN];        if (!(entry = ipban_str_to_ipban_entry(cp)))    {	if (c)	    message_send_text(c,message_type_error,c,"Bad IP.");        eventlog(eventlog_level_error,__FUNCTION__,"could not convert to t_ipban_entry: \"%s\"",cp);        return -1;    }    entry->endtime = endtime;    list_append_data(ipbanlist_head,entry);        if (c)    {		if (endtime == 0)	{            sprintf(tstr,"%s banned permamently by %s.",cp,conn_get_username(c));            eventlog(eventlog_level_info,__FUNCTION__,tstr);            message_send_admins(c,message_type_info,tstr);	    sprintf(tstr,"%s banned permamently.",cp);	    message_send_text(c,message_type_info,c,tstr);	}	else	{            sprintf(tstr,"%s banned for %.48s by %s.",cp,seconds_to_timestr(entry->endtime - now),conn_get_username(c));            eventlog(eventlog_level_info,__FUNCTION__,tstr);            message_send_admins(c,message_type_info,tstr);	    sprintf(tstr,"%s banned for %.48s.",cp,seconds_to_timestr(entry->endtime - now));	    message_send_text(c,message_type_info,c,tstr);	}    }    return 0;}extern int ipbanlist_unload_expired(void){    t_elem *		curr;    t_ipban_entry * 	entry;    char removed;        removed = 0;    LIST_TRAVERSE(ipbanlist_head,curr)    {	entry = elem_get_data(curr);	if (!entry)	{	    eventlog(eventlog_level_error,__FUNCTION__,"ipbanlist_contains NULL element");	    return -1;	}	if ((entry->endtime - now <= 0) && (entry->endtime != 0))	{	    eventlog(eventlog_level_debug,__FUNCTION__,"removing item: %s",entry->info1);	    removed = 1;	    if (list_remove_elem(ipbanlist_head,&curr)<0)		eventlog(eventlog_level_error,__FUNCTION__,"could not remove item");	    else		ipban_unload_entry(entry);	}    }    if (removed==1) ipbanlist_save(prefs_get_ipbanfile());    return 0;}extern time_t ipbanlist_str_to_time_t(t_connection * c, char const * timestr){    unsigned int	bmin;    char		minstr[MAX_TIME_STR];    unsigned int	i;    char		tstr[MAX_MESSAGE_LEN];        for (i=0; isdigit((int)timestr[i]) && i<sizeof(minstr)-1; i++)	minstr[i] = timestr[i];    minstr[i] = '\0';    if (timestr[i]!='\0')    {	if (c)	{	    if (strlen(minstr)<1)		message_send_text(c,message_type_info,c,"There was an error in time.");	    else		    {		sprintf(tstr,"There was an error in time. Banning only for: %s minutes.",minstr);	        message_send_text(c,message_type_info,c,tstr);	    }	}    }    if (clockstr_to_seconds(minstr,&bmin)<0) /* it thinks these are seconds but we treat them as minutes */    {        eventlog(eventlog_level_error,__FUNCTION__,"could not convert to minutes: \"%s\"",timestr);        return -1;    }    if (bmin == 0)    	return 0;    else    {		return now + bmin*60;    }}extern int handle_ipban_command(t_connection * c, char const * text){    char		subcommand[MAX_FUNC_LEN];    char		ipstr[MAX_IP_STR];    unsigned int 	i,j;        for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */    for (; text[i]==' '; i++);        for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get subcommand */	if (j<sizeof(subcommand)-1) subcommand[j++] = text[i];    subcommand[j] = '\0';    for (; text[i]==' '; i++);    for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get ip address */	if (j<sizeof(ipstr)-1) ipstr[j++] = text[i];    ipstr[j] = '\0';

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -