/* * ircd-ratbox: A slightly useful ircd. * class.c: Controls connection classes. * * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center * Copyright (C) 1996-2002 Hybrid Development Team * Copyright (C) 2002-2005 ircd-ratbox development team * * 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 */ #include "stdinc.h" #include "defaults.h" #include "class.h" #include "client.h" #include "ircd.h" #include "numeric.h" #include "s_conf.h" #include "s_newconf.h" #include "send.h" #include "match.h" #define BAD_PING -2 rb_dlink_list class_list; struct Class *default_class; struct Class * make_class(void) { struct Class *tmp; tmp = rb_malloc(sizeof(struct Class)); ConFreq(tmp) = DEFAULT_CONNECTFREQUENCY; PingFreq(tmp) = DEFAULT_PINGFREQUENCY; MaxUsers(tmp) = 1; MaxSendq(tmp) = DEFAULT_SENDQ; tmp->ip_limits = rb_new_patricia(PATRICIA_BITS); return tmp; } void free_class(struct Class *tmp) { if(tmp->ip_limits) rb_destroy_patricia(tmp->ip_limits, NULL); rb_free(tmp->class_name); rb_free(tmp); } /* * get_conf_ping * * inputs - pointer to struct ConfItem * output - ping frequency * side effects - NONE */ static int get_conf_ping(struct ConfItem *aconf) { if((aconf) && ClassPtr(aconf)) return (ConfPingFreq(aconf)); return (BAD_PING); } /* * get_client_class * * inputs - pointer to client struct * output - pointer to name of class * side effects - NONE */ const char * get_client_class(struct Client *target_p) { const char *retc = "unknown"; if(target_p == NULL || IsMe(target_p)) return retc; if(IsServer(target_p)) { struct server_conf *server_p = target_p->localClient->att_sconf; return server_p->class_name; } else { struct ConfItem *aconf; aconf = target_p->localClient->att_conf; if((aconf == NULL) || (aconf->className == NULL)) retc = "default"; else retc = aconf->className; } return (retc); } /* * get_client_ping * * inputs - pointer to client struct * output - ping frequency * side effects - NONE */ int get_client_ping(struct Client *target_p) { int ping = 0; if(IsServer(target_p)) { struct server_conf *server_p = target_p->localClient->att_sconf; ping = PingFreq(server_p->class); } else { struct ConfItem *aconf; aconf = target_p->localClient->att_conf; if(aconf != NULL) ping = get_conf_ping(aconf); else ping = DEFAULT_PINGFREQUENCY; } if(ping <= 0) ping = DEFAULT_PINGFREQUENCY; return ping; } /* * get_con_freq * * inputs - pointer to class struct * output - connection frequency * side effects - NONE */ int get_con_freq(struct Class *clptr) { if(clptr) return (ConFreq(clptr)); return (DEFAULT_CONNECTFREQUENCY); } /* add_class() * * input - class to add * output - * side effects - class is added to class_list if new, else old class * is updated with new values. */ void add_class(struct Class *classptr) { struct Class *tmpptr; tmpptr = find_class(classptr->class_name); if(tmpptr == default_class) { rb_dlinkAddAlloc(classptr, &class_list); CurrUsers(classptr) = 0; } else { MaxUsers(tmpptr) = MaxUsers(classptr); MaxLocal(tmpptr) = MaxLocal(classptr); MaxGlobal(tmpptr) = MaxGlobal(classptr); MaxIdent(tmpptr) = MaxIdent(classptr); PingFreq(tmpptr) = PingFreq(classptr); MaxSendq(tmpptr) = MaxSendq(classptr); ConFreq(tmpptr) = ConFreq(classptr); CidrIpv4Bitlen(tmpptr) = CidrIpv4Bitlen(classptr); CidrIpv6Bitlen(tmpptr) = CidrIpv6Bitlen(classptr); CidrAmount(tmpptr) = CidrAmount(classptr); free_class(classptr); } } /* * find_class * * inputs - string name of class * output - corresponding class pointer * side effects - NONE */ struct Class * find_class(const char *classname) { struct Class *cltmp; rb_dlink_node *ptr; if(classname == NULL) return default_class; RB_DLINK_FOREACH(ptr, class_list.head) { cltmp = ptr->data; if(!strcmp(ClassName(cltmp), classname)) return cltmp; } return default_class; } /* * check_class * * inputs - NONE * output - NONE * side effects - */ void check_class() { struct Class *cltmp; rb_dlink_node *ptr; rb_dlink_node *next_ptr; RB_DLINK_FOREACH_SAFE(ptr, next_ptr, class_list.head) { cltmp = ptr->data; if(MaxUsers(cltmp) < 0) { rb_dlinkDestroy(ptr, &class_list); if(CurrUsers(cltmp) <= 0) free_class(cltmp); } } } /* * initclass * * inputs - NONE * output - NONE * side effects - */ void initclass() { default_class = make_class(); ClassName(default_class) = rb_strdup("default"); } /* * report_classes * * inputs - pointer to client to report to * output - NONE * side effects - class report is done to this client */ void report_classes(struct Client *source_p) { struct Class *cltmp; rb_dlink_node *ptr; RB_DLINK_FOREACH(ptr, class_list.head) { cltmp = ptr->data; sendto_one_numeric(source_p, RPL_STATSYLINE, form_str(RPL_STATSYLINE), ClassName(cltmp), PingFreq(cltmp), ConFreq(cltmp), MaxUsers(cltmp), MaxSendq(cltmp), MaxLocal(cltmp), MaxIdent(cltmp), MaxGlobal(cltmp), MaxIdent(cltmp), CurrUsers(cltmp)); } /* also output the default class */ sendto_one_numeric(source_p, RPL_STATSYLINE, form_str(RPL_STATSYLINE), ClassName(default_class), PingFreq(default_class), ConFreq(default_class), MaxUsers(default_class), MaxSendq(default_class), MaxLocal(default_class), MaxIdent(default_class), MaxGlobal(default_class), MaxIdent(default_class), CurrUsers(default_class)); } /* * get_sendq * * inputs - pointer to client * output - sendq for this client as found from its class * side effects - NONE */ long get_sendq(struct Client *client_p) { if(client_p == NULL || IsMe(client_p)) return DEFAULT_SENDQ; if(IsServer(client_p)) { struct server_conf *server_p; server_p = client_p->localClient->att_sconf; return MaxSendq(server_p->class); } else { struct ConfItem *aconf = client_p->localClient->att_conf; if(aconf != NULL && aconf->status & CONF_CLIENT) return ConfMaxSendq(aconf); } return DEFAULT_SENDQ; }