ircd-irc2-2.11.2p2+dfsg/0000755000175000017500000000000011362646466013306 5ustar kurtkurtircd-irc2-2.11.2p2+dfsg/ircd/0000755000175000017500000000000011362646454014224 5ustar kurtkurtircd-irc2-2.11.2p2+dfsg/ircd/class.c0000644000175000017500000001636011027474443015476 0ustar kurtkurt/* * IRC - Internet Relay Chat, ircd/class.c * Copyright (C) 1990 Darren Reed * * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef lint static const volatile char rcsid[] = "@(#)$Id: class.c,v 1.28 2008/06/22 16:09:07 chopin Exp $"; #endif #include "os.h" #include "s_defines.h" #define CLASS_C #include "s_externs.h" #undef CLASS_C #ifdef ENABLE_CIDR_LIMITS #include "patricia_ext.h" #endif #define BAD_CONF_CLASS -1 #define BAD_PING -2 #define BAD_CLIENT_CLASS -3 aClass *classes; int get_conf_class(aConfItem *aconf) { if ((aconf) && Class(aconf)) return (ConfClass(aconf)); Debug((DEBUG_DEBUG,"No Class For %s", (aconf) ? aconf->name : "*No Conf*")); return (BAD_CONF_CLASS); } static int get_conf_ping(aConfItem *aconf) { if ((aconf) && Class(aconf)) return (ConfPingFreq(aconf)); Debug((DEBUG_DEBUG,"No Ping For %s", (aconf) ? aconf->name : "*No Conf*")); return (BAD_PING); } int get_client_class(aClient *acptr) { Reg Link *tmp; Reg aClass *cl; int retc = BAD_CLIENT_CLASS; if (acptr && !IsMe(acptr) && (acptr->confs)) for (tmp = acptr->confs; tmp; tmp = tmp->next) { if (!tmp->value.aconf || !(cl = tmp->value.aconf->class)) continue; retc = Class(cl); break; } Debug((DEBUG_DEBUG,"Returning Class %d For %s",retc,acptr->name)); return (retc); } int get_client_ping(aClient *acptr) { int ping = 0, ping2; aConfItem *aconf; Link *link; link = acptr->confs; if (link) while (link) { aconf = link->value.aconf; if (aconf->status & (CONF_CLIENT|CONF_CONNECT_SERVER| CONF_NOCONNECT_SERVER| CONF_ZCONNECT_SERVER)) { ping2 = get_conf_ping(aconf); if ((ping2 != BAD_PING) && ((ping > ping2) || !ping)) ping = ping2; } link = link->next; } else { ping = PINGFREQUENCY; Debug((DEBUG_DEBUG,"No Attached Confs")); } if (ping <= 0) ping = PINGFREQUENCY; Debug((DEBUG_DEBUG,"Client %s Ping %d", acptr->name, ping)); return (ping); } int get_con_freq(aClass *clptr) { if (clptr) return (MAX(60, ConFreq(clptr))); else return (CONNECTFREQUENCY); } /* * When adding a class, check to see if it is already present first. * if so, then update the information for that class, rather than create * a new entry for it and later delete the old entry. * if no present entry is found, then create a new one and add it in * immeadiately after the first one (class 0). */ void add_class(int class, int ping, int confreq, int maxli, int sendq, int bsendq, int hlocal, int uhlocal, int hglobal, int uhglobal #ifdef ENABLE_CIDR_LIMITS , char *cidrlen_s #endif ) { aClass *t, *p; #ifdef ENABLE_CIDR_LIMITS char *tmp; int cidrlen = 0, cidramount = 0; if(cidrlen_s) { if((tmp = index(cidrlen_s, '/'))) { *tmp++ = '\0'; cidramount = atoi(cidrlen_s); cidrlen = atoi(tmp); } } #endif t = find_class(class); if ((t == classes) && (class != 0)) { p = (aClass *)make_class(); NextClass(p) = NextClass(t); NextClass(t) = p; MaxSendq(p) = QUEUELEN; #ifdef ENABLE_CIDR_LIMITS CidrLen(p) = 0; p->ip_limits = NULL; #endif istat.is_class++; } else p = t; Debug((DEBUG_DEBUG, "Add Class %d: p %x t %x - cf: %d pf: %d ml: %d sq: %d.%d ml: %d.%d mg: %d.%d", class, p, t, confreq, ping, maxli, sendq, bsendq, hlocal, uhlocal, hglobal, uhglobal)); Class(p) = class; ConFreq(p) = confreq; PingFreq(p) = ping; MaxLinks(p) = maxli; if (sendq) MaxSendq(p) = sendq; MaxBSendq(p) = bsendq ? bsendq : 0; MaxHLocal(p) = hlocal; MaxUHLocal(p) = uhlocal; MaxHGlobal(p) = hglobal; MaxUHGlobal(p) = uhglobal; #ifdef ENABLE_CIDR_LIMITS if (cidrlen > 0 && CidrLen(p) == 0 && p->ip_limits == NULL) { CidrLen(p) = cidrlen; # ifdef INET6 p->ip_limits = (struct _patricia_tree_t *) patricia_new(128); # else p->ip_limits = (struct _patricia_tree_t *) patricia_new(32); # endif } if (CidrLen(p) != cidrlen) { /* Hmpf, sendto_somewhere maybe to warn? --B. */ Debug((DEBUG_NOTICE, "Cannot change cidrlen on the fly (class %d)", Class(p))); } if (CidrLen(p) > 0) MaxCidrAmount(p) = cidramount; #endif if (p != t) Links(p) = 0; } aClass *find_class(int cclass) { aClass *cltmp; for (cltmp = FirstClass(); cltmp; cltmp = NextClass(cltmp)) if (Class(cltmp) == cclass) return cltmp; return classes; } void check_class(void) { Reg aClass *cltmp, *cltmp2; Debug((DEBUG_DEBUG, "Class check:")); for (cltmp2 = cltmp = FirstClass(); cltmp; cltmp = NextClass(cltmp2)) { Debug((DEBUG_DEBUG, "Class %d : CF: %d PF: %d ML: %d LI: %d SQ: %ld", Class(cltmp), ConFreq(cltmp), PingFreq(cltmp), MaxLinks(cltmp), Links(cltmp), MaxSendq(cltmp))); if (MaxLinks(cltmp) < 0) { NextClass(cltmp2) = NextClass(cltmp); if (Links(cltmp) <= 0) { free_class(cltmp); istat.is_class--; } } else cltmp2 = cltmp; } } void initclass(void) { classes = (aClass *)make_class(); istat.is_class++; Class(FirstClass()) = 0; ConFreq(FirstClass()) = CONNECTFREQUENCY; PingFreq(FirstClass()) = PINGFREQUENCY; MaxLinks(FirstClass()) = MAXIMUM_LINKS; MaxSendq(FirstClass()) = QUEUELEN; MaxBSendq(FirstClass()) = 0; Links(FirstClass()) = 0; NextClass(FirstClass()) = NULL; MaxHLocal(FirstClass()) = 1; MaxUHLocal(FirstClass()) = 1; MaxHGlobal(FirstClass()) = 1; MaxUHGlobal(FirstClass()) = 1; #ifdef ENABLE_CIDR_LIMITS CidrLen(FirstClass()) = 0; FirstClass()->ip_limits = NULL; #endif } void report_classes(aClient *sptr, char *to) { Reg aClass *cltmp; char tmp[64] = ""; for (cltmp = FirstClass(); cltmp; cltmp = NextClass(cltmp)) { #ifdef ENABLE_CIDR_LIMITS if (MaxCidrAmount(cltmp) > 0 && CidrLen(cltmp) > 0) /* leading space is important */ snprintf(tmp, sizeof(tmp), " %d/%d", MaxCidrAmount(cltmp), CidrLen(cltmp)); else tmp[0] = '\0'; #endif sendto_one(sptr, replies[RPL_STATSYLINE], ME, BadTo(to), 'Y', Class(cltmp), PingFreq(cltmp), ConFreq(cltmp), MaxLinks(cltmp), MaxSendq(cltmp), MaxBSendq(cltmp), MaxHLocal(cltmp), MaxUHLocal(cltmp), MaxHGlobal(cltmp), MaxUHGlobal(cltmp), Links(cltmp), tmp); } } int get_sendq(aClient *cptr, int bursting) { Reg int sendq = QUEUELEN; Reg Link *tmp; Reg aClass *cl; if (cptr->serv && cptr->serv->nline) sendq = bursting && MaxBSendq(cptr->serv->nline->class) ? MaxBSendq(cptr->serv->nline->class) : MaxSendq(cptr->serv->nline->class); else if (cptr && !IsMe(cptr) && (cptr->confs)) for (tmp = cptr->confs; tmp; tmp = tmp->next) { if (!tmp->value.aconf || !(cl = tmp->value.aconf->class)) continue; sendq = bursting && MaxBSendq(cl) ? MaxBSendq(cl) : MaxSendq(cl); break; } return sendq; } ircd-irc2-2.11.2p2+dfsg/ircd/s_service.c0000644000175000017500000004563511022677072016360 0ustar kurtkurt/************************************************************************ * IRC - Internet Relay Chat, ircd/s_service.c * Copyright (C) 1990 Jarkko Oikarinen and * University of Oulu, Computing Center * * See file AUTHORS in IRC package for additional names of * the programmers. * * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef lint static const volatile char rcsid[] = "@(#)$Id: s_service.c,v 1.68 2008/06/08 06:37:46 chopin Exp $"; #endif #include "os.h" #include "s_defines.h" #define S_SERVICE_C #include "s_externs.h" #undef S_SERVICE_C aService *svctop = NULL; aService *make_service(aClient *cptr) { Reg aService *svc = cptr->service; if (svc) return svc; cptr->service = svc = (aService *)MyMalloc(sizeof(*svc)); bzero((char *)svc, sizeof(*svc)); cptr->name = svc->namebuf; svc->bcptr = cptr; if (svctop) svctop->prevs = svc; svc->nexts = svctop; svc->prevs = NULL; /* useless */ svctop = svc; return svc; } void free_service(aClient *cptr) { aService *serv; if ((serv = cptr->service)) { if (serv->nexts) serv->nexts->prevs = serv->prevs; if (serv->prevs) serv->prevs->nexts = serv->nexts; if (svctop == serv) svctop = serv->nexts; /* It's just the pointer, not even allocated in m_service. * Why would someone want to destroy that struct here? * So far commenting it out. --B. if (serv->servp) free_server(serv->servp, cptr); */ /* this is ok, ->server is a string. */ if (serv->server) MyFree(serv->server); MyFree(serv); cptr->service = NULL; } } static aClient *best_service(char *name, aClient *cptr) { Reg aClient *acptr = NULL; Reg aClient *bcptr; Reg aService *sp; int len = strlen(name); if (!index(name, '@') || !(acptr = find_service(name, cptr))) for (sp = svctop; sp; sp = sp->nexts) if ((bcptr = sp->bcptr) && !myncmp(name, bcptr->name, len)) { if (!acptr || bcptr->hopcount < acptr->hopcount) { acptr = bcptr; } } return (acptr ? acptr : cptr); } #ifdef USE_SERVICES /* ** check_services_butone ** check all local services except `cptr', and send `fmt' according to: ** action type on notice ** server origin */ void check_services_butone(long action, aServer *servp, aClient *cptr, char *fmt, ...) /* shouldn't cptr be named sptr? */ { char nbuf[NICKLEN + USERLEN + HOSTLEN + 3]; Reg aService *sp; *nbuf = '\0'; for (sp = svctop; sp; sp = sp->nexts) { if (!MyConnect(sp->bcptr) || (cptr && sp->bcptr == cptr->from)) { continue; } /* ** found a (local) service, check if action matches what's ** wanted AND if it comes from a server matching the dist */ if ((sp->wants & action) && (!servp || !match(sp->dist, servp->bcptr->name) || !match(sp->dist, servp->sid))) { if ((sp->wants & (SERVICE_WANT_PREFIX|SERVICE_WANT_UID)) && cptr && IsRegisteredUser(cptr) && (action & SERVICE_MASK_PREFIX)) { char buf[2048]; va_list va; va_start(va, fmt); (void)va_arg(va, char *); vsprintf(buf, fmt+3, va); va_end(va); if ((sp->wants & SERVICE_WANT_UID)) sendto_one(sp->bcptr, ":%s%s", cptr->user ? cptr->user->uid : cptr->name, buf); else sendto_one(sp->bcptr, ":%s!%s@%s%s", cptr->name, cptr->user->username, cptr->user->host, buf); } else { va_list va; va_start(va, fmt); vsendto_one(sp->bcptr, fmt, va); va_end(va); } } } return; } /* ** sendnum_toone ** send the NICK + USER + UMODE for sptr to cptr according to wants */ static void sendnum_toone(aClient *cptr, int wants, aClient *sptr, char *umode) { if (!*umode) umode = "+"; if ((wants & SERVICE_WANT_UID) && sptr->user) sendto_one(cptr, ":%s UNICK %s %s %s %s %s %s :%s", sptr->user->servp->sid, (wants & SERVICE_WANT_NICK) ? sptr->name : ".", sptr->user->uid, (wants & SERVICE_WANT_USER) ? sptr->user->username : ".", (wants & SERVICE_WANT_USER) ? sptr->user->host : ".", (wants & SERVICE_WANT_USER) ? sptr->user->sip : ".", (wants & (SERVICE_WANT_UMODE|SERVICE_WANT_OPER)) ? umode : "+", (wants & SERVICE_WANT_USER) ? sptr->info : ""); else if (wants & SERVICE_WANT_EXTNICK) /* extended NICK syntax */ sendto_one(cptr, "NICK %s %d %s %s %s %s :%s", (wants & SERVICE_WANT_NICK) ? sptr->name : ".", sptr->hopcount + 1, (wants & SERVICE_WANT_USER) ? sptr->user->username : ".", (wants & SERVICE_WANT_USER) ? sptr->user->host :".", (wants & SERVICE_WANT_USER) ? ((wants & SERVICE_WANT_SID) ? sptr->user->servp->sid : sptr->user->server) : ".", (wants & (SERVICE_WANT_UMODE|SERVICE_WANT_OPER)) ? umode : "+", (wants & SERVICE_WANT_USER) ? sptr->info : ""); else /* old style NICK + USER + UMODE */ { char nbuf[NICKLEN + USERLEN + HOSTLEN + 3]; char *prefix; if (wants & SERVICE_WANT_PREFIX) { sprintf(nbuf, "%s!%s@%s", sptr->name, sptr->user->username, sptr->user->host); prefix = nbuf; } else prefix = sptr->name; if (wants & SERVICE_WANT_NICK) sendto_one(cptr, "NICK %s :%d", sptr->name, sptr->hopcount+1); if (wants & SERVICE_WANT_USER) sendto_one(cptr, ":%s USER %s %s %s :%s", prefix, sptr->user->username, sptr->user->host, (wants & SERVICE_WANT_SID)? sptr->user->servp->sid : sptr->user->server, sptr->info); if (wants & (SERVICE_WANT_UMODE|SERVICE_WANT_OPER)) sendto_one(cptr, ":%s MODE %s %s", prefix, sptr->name, umode); } } /* ** check_services_num ** check all local services to eventually send NICK + USER + UMODE ** for new client sptr */ void check_services_num(aClient *sptr, char *umode) { Reg aService *sp; for (sp = svctop; sp; sp = sp->nexts) { if (!MyConnect(sp->bcptr)) { continue; } /* ** found a (local) service, check if action matches what's ** wanted AND if it comes from a server matching the dist */ if ((sp->wants & SERVICE_MASK_NUM) && (!match(sp->dist, sptr->user->server) || !match(sp->dist, sptr->user->servp->sid))) { sendnum_toone(sp->bcptr, sp->wants, sptr, umode); } } } aConfItem *find_conf_service(aClient *cptr, int type, aConfItem *aconf) { static char uhost[HOSTLEN+USERLEN+3]; Reg aConfItem *tmp; char *s; struct hostent *hp; int i; for (tmp = conf; tmp; tmp = tmp->next) { /* ** Accept if the *real* hostname (usually sockethost) ** matches host field of the configuration, the name field ** is the same, the type match is correct and nobody else ** is using this S-line. */ if (!(tmp->status & CONF_SERVICE)) continue; Debug((DEBUG_INFO,"service: cl=%d host (%s) name (%s) port=%d", tmp->clients, tmp->host, tmp->name, tmp->port)); Debug((DEBUG_INFO,"service: host (%s) name (%s) type=%d", cptr->sockhost, cptr->name, type)); if (tmp->clients || (type && tmp->port != type) || mycmp(tmp->name, cptr->name)) continue; if ((hp = cptr->hostp)) for (s = hp->h_name, i = 0; s; s = hp->h_aliases[i++]) { sprintf(uhost, "%s@%s", cptr->username, s); if (match(tmp->host, uhost) == 0) return tmp; } sprintf(uhost, "%s@%s", cptr->username, cptr->sockhost); if (match(tmp->host, uhost) == 0) return tmp; } return aconf; } #endif /* ** m_service ** ** <= 2.10 protocol: ** parv[0] = sender prefix ** parv[1] = service name ** parv[2] = server token (unused on pure 2.11 network) ** parv[3] = distribution code ** parv[4] = service type ** parv[5] = hopcount ** parv[6] = info ** ** 2.11 protocol ** parv[0] = sender prefix ** parv[1] = service name ** parv[2] = distribution mask ** parv[3] = service type ** parv[4] = info ** */ int m_service(aClient *cptr, aClient *sptr, int parc, char *parv[]) { aClient *acptr = NULL, *bcptr = NULL; aService *svc; #ifdef USE_SERVICES aConfItem *aconf; #endif aServer *sp = NULL; char *dist, *server = NULL, *info; int type, i; if (sptr->user) { sendto_one(sptr, replies[ERR_ALREADYREGISTRED], ME, BadTo(parv[0])); return 1; } if (parc < 5) { sendto_one(cptr, replies[ERR_NEEDMOREPARAMS], ME, BadTo(parv[0]), "SERVICE"); return 1; } /* Copy parameters into better documenting variables */ dist = parv[2]; type = strtol(parv[3], NULL, 0); info = parv[4]; /* * Change the sender's origin. */ if (IsServer(cptr)) { acptr = make_client(cptr); svc = make_service(acptr); add_client_to_list(acptr); strncpyzt(acptr->service->namebuf, parv[1], sizeof(acptr->service->namebuf)); /* 2.11 protocol - :SID SERVICE .. * - we know that the sptr contains the correct server */ acptr->hopcount = sptr->hopcount; sp = sptr->serv; if (sp == NULL) { sendto_flag(SCH_ERROR, "ERROR: SERVICE:%s without SERVER:%s from %s", acptr->name, server, get_client_name(cptr, FALSE)); return exit_client(NULL, acptr, &me, "No Such Server"); } if (match(dist, ME) && match(dist, me.serv->sid)) { sendto_flag(SCH_ERROR, "ERROR: SERVICE:%s DIST:%s from %s", acptr->name, dist, get_client_name(cptr, FALSE)); return exit_client(NULL, acptr, &me, "Distribution code mismatch"); } } #ifndef USE_SERVICES else { sendto_one(cptr, "ERROR :Server doesn't support services"); return 1; } #endif #ifdef USE_SERVICES if (!IsServer(cptr)) { char **isup = isupport; svc = make_service(sptr); sptr->hopcount = 0; server = ME; sp = me.serv; if (!do_nick_name(parv[1], 0)) { sendto_one(sptr, replies[ERR_ERRONEOUSNICKNAME], ME, BadTo(parv[0]), parv[1]); return 1; } if (strlen(parv[1]) + strlen(server) + 2 >= (size_t) HOSTLEN) { sendto_one(acptr, "ERROR :Servicename is too long."); sendto_flag(SCH_ERROR, "Access for service %d (%s) denied (%s)", type, parv[1], "servicename too long"); return exit_client(cptr, sptr, &me, "Name too long"); } strncpyzt(sptr->service->namebuf, parv[1], sizeof(sptr->service->namebuf)); if (!(aconf = find_conf_service(sptr, type, NULL))) { sendto_one(sptr, "ERROR :Access denied (service %d) %s", type, get_client_name(sptr, TRUE)); sendto_flag(SCH_ERROR, "Access denied (service %d) %s", type, get_client_name(sptr, TRUE)); return exit_client(cptr, sptr, &me, "Not enabled"); } if (!BadPtr(aconf->passwd) && !StrEq(aconf->passwd, sptr->passwd)) { sendto_flag(SCH_ERROR, "Access denied: (passwd mismatch) %s", get_client_name(sptr, TRUE)); return exit_client(cptr, sptr, &me, "Bad Password"); } (void)strcat(sptr->name, "@"), strcat(sptr->name, server); if (find_service(sptr->name, NULL)) { sendto_flag(SCH_ERROR, "Service %s already exists", get_client_name(sptr, TRUE)); return exit_client(cptr, sptr, &me, "Service Exists"); } attach_conf(sptr, aconf); sendto_one(sptr, replies[RPL_YOURESERVICE], ME, BadTo(sptr->name), sptr->name); sendto_one(sptr, replies[RPL_YOURHOST], ME, BadTo(sptr->name), get_client_name(&me, FALSE), version); while (*isup) { sendto_one(sptr,replies[RPL_ISUPPORT], ME, BadTo(sptr->name), *isup); isup++; } sendto_one(sptr, replies[RPL_MYINFO], ME, BadTo(sptr->name), ME, version); sendto_flag(SCH_NOTICE, "Service %s connected", get_client_name(sptr, TRUE)); istat.is_unknown--; istat.is_myservice++; if (istat.is_myservice > istat.is_m_myservice) istat.is_m_myservice = istat.is_myservice; /* local service, assign to acptr so we can use it later*/ acptr = sptr; } #endif istat.is_service++; if (istat.is_service > istat.is_m_service) istat.is_m_service = istat.is_service; SetService(acptr); svc->servp = sp; sp->refcnt++; svc->server = mystrdup(sp->bcptr->name); strncpyzt(svc->dist, dist, HOSTLEN); if (acptr->info != DefInfo) MyFree(acptr->info); if (strlen(info) > REALLEN) info[REALLEN] = '\0'; acptr->info = mystrdup(info); svc->wants = 0; svc->type = type; reorder_client_in_list(acptr); (void)add_to_client_hash_table(acptr->name, acptr); #ifdef USE_SERVICES check_services_butone(SERVICE_WANT_SERVICE, NULL, acptr, ":%s SERVICE %s %s %d :%s", sp->sid, acptr->name, dist, type, info); #endif sendto_flag(SCH_SERVICE, "Received SERVICE %s from %s via %s (%s %d %s)", acptr->name, sptr->name, get_client_name(cptr, TRUE), dist, acptr->hopcount, info); for (i = fdas.highest; i >= 0; i--) { if (!(bcptr = local[fdas.fd[i]]) || !IsServer(bcptr) || bcptr == cptr) continue; if (match(dist, bcptr->name)) continue; sendto_one(bcptr, ":%s SERVICE %s %s %d :%s", sp->sid, acptr->name, dist, type, info); } return 0; } /* ** Returns list of all matching services. ** parv[1] - string to match names against ** parv[2] - type of service */ int m_servlist(aClient *cptr, aClient *sptr, int parc, char *parv[]) { Reg aService *sp; Reg aClient *acptr; char *mask = BadPtr(parv[1]) ? "*" : parv[1]; int type = 0; if (parc > 2) type = BadPtr(parv[2]) ? 0 : strtol(parv[2], NULL, 0); for (sp = svctop; sp; sp = sp->nexts) if ((acptr = sp->bcptr) && (!type || type == sp->type) && (match(mask, acptr->name) == 0)) sendto_one(sptr, replies[RPL_SERVLIST], ME, BadTo(parv[0]), acptr->name, sp->server, sp->dist, sp->type, acptr->hopcount, acptr->info); sendto_one(sptr, replies[RPL_SERVLISTEND], ME, BadTo(parv[0]), mask, type); return 2; } #ifdef USE_SERVICES /* ** m_servset ** ** parv[0] = sender prefix ** parv[1] = data requested ** parv[2] = burst requested (optional) */ int m_servset(aClient *cptr, aClient *sptr, int parc, char *parv[]) { aClient *acptr; int burst = 0; if (!MyConnect(sptr)) { sendto_flag(SCH_ERROR, "%s issued a SERVSET (from %s)", sptr->name, get_client_name(cptr, TRUE)); return 1; } if (!IsService(sptr) || (IsService(sptr) && sptr->service->wants)) { sendto_one(sptr, replies[ERR_NOPRIVILEGES], ME, BadTo(parv[0])); return 1; } if (sptr->service->wants) return 1; /* check against configuration */ sptr->service->wants = strtol(parv[1], NULL, 0) & sptr->service->type; /* check that service is global for some requests */ if (strcmp(sptr->service->dist, "*")) sptr->service->wants &= ~SERVICE_MASK_GLOBAL; /* allow options */ sptr->service->wants |= (strtol(parv[1], NULL, 0) & ~SERVICE_MASK_ALL); /* send accepted SERVSET */ sendto_one(sptr, ":%s SERVSET %s :%d", sptr->name, sptr->name, sptr->service->wants); if (parc < 3 || ((burst = sptr->service->wants & strtol(parv[2], NULL, 0)) == 0)) return 0; /* ** services can request a connect burst. ** it is optional, because most services should not need it, ** so let's save some bandwidth. ** ** tokens are NOT used. (2.8.x like burst) ** distribution code is respected. ** service type also respected. */ cptr->flags |= FLAGS_CBURST; if (burst & SERVICE_WANT_SERVER) { int split; for (acptr = &me; acptr; acptr = acptr->prev) { if (!IsServer(acptr) && !IsMe(acptr)) continue; if (match(sptr->service->dist, acptr->name) && match(sptr->service->dist, acptr->serv->sid)) continue; split = (MyConnect(acptr) && mycmp(acptr->name, acptr->sockhost)); sendto_one(sptr, ":%s SERVER %s %d %s :%s", acptr->serv->up->name, acptr->name, acptr->hopcount+1, acptr->serv->sid, acptr->info); } } if (burst & (SERVICE_WANT_NICK|SERVICE_WANT_USER|SERVICE_WANT_SERVICE)) { char buf[BUFSIZE] = "+"; for (acptr = &me; acptr; acptr = acptr->prev) { /* acptr->from == acptr for acptr == cptr */ if (acptr->from == cptr) continue; if (IsPerson(acptr)) { if (match(sptr->service->dist, acptr->user->server) && match(sptr->service->dist, acptr->user->servp->sid)) continue; if (burst & SERVICE_WANT_UMODE) send_umode(NULL, acptr, 0, SEND_UMODES, buf); else if (burst & SERVICE_WANT_OPER) send_umode(NULL, acptr, 0, FLAGS_OPER, buf); sendnum_toone(sptr, burst, acptr, buf); } else if (IsService(acptr)) { if (!(burst & SERVICE_WANT_SERVICE)) continue; if (match(sptr->service->dist, acptr->service->server) && match(sptr->service->dist, acptr->service->servp->sid)) continue; sendto_one(sptr, "SERVICE %s %s %s %d %d :%s", acptr->name, acptr->service->server, acptr->service->dist, acptr->service->type, acptr->hopcount + 1, acptr->info); } } } if (burst & (SERVICE_WANT_CHANNEL|SERVICE_WANT_VCHANNEL|SERVICE_WANT_MODE|SERVICE_WANT_TOPIC)) { char modebuf[MODEBUFLEN], parabuf[MODEBUFLEN]; aChannel *chptr; for (chptr = channel; chptr; chptr = chptr->nextch) { if (chptr->users == 0) continue; if (burst&(SERVICE_WANT_CHANNEL|SERVICE_WANT_VCHANNEL)) sendto_one(sptr, "CHANNEL %s %d", chptr->chname, chptr->users); if (burst & SERVICE_WANT_MODE) { *modebuf = *parabuf = '\0'; modebuf[1] = '\0'; channel_modes(&me, modebuf, parabuf, chptr); sendto_one(sptr, "MODE %s %s", chptr->chname, modebuf); } if ((burst & SERVICE_WANT_TOPIC) && *chptr->topic) sendto_one(sptr, "TOPIC %s :%s", chptr->chname, chptr->topic); } } sendto_one(sptr, "EOB"); cptr->flags ^= FLAGS_CBURST; return 0; } #endif /* ** Send query to service. ** parv[1] - string to match name against ** parv[2] - string to send to service */ int m_squery(aClient *cptr, aClient *sptr, int parc, char *parv[]) { aClient *acptr; if (parc <= 2) { if (parc == 1) sendto_one(sptr, replies[ERR_NORECIPIENT], ME, BadTo(parv[0]), "SQUERY"); else if (parc == 2 || BadPtr(parv[1])) sendto_one(sptr, replies[ERR_NOTEXTTOSEND], ME, BadTo(parv[0])); return 1; } if ((acptr = best_service(parv[1], NULL))) if (MyConnect(acptr) && (acptr->service->wants & SERVICE_WANT_PREFIX)) sendto_one(acptr, ":%s!%s@%s SQUERY %s :%s", parv[0], sptr->user->username, sptr->user->host, acptr->name, parv[2]); else if (MyConnect(acptr) && (acptr->service->wants & SERVICE_WANT_UID)) sendto_one(acptr, ":%s SQUERY %s :%s", sptr->user->uid, acptr->name, parv[2]); else sendto_one(acptr, ":%s SQUERY %s :%s", parv[0], acptr->name, parv[2]); else sendto_one(sptr, replies[ERR_NOSUCHSERVICE], ME, BadTo(parv[0]), parv[1]); return 2; } ircd-irc2-2.11.2p2+dfsg/ircd/patricia_ext.h0000644000175000017500000001031111157044733017037 0ustar kurtkurt/* * Imported: Id: patricia.h 18598 2005-03-04 17:45:53Z androsyn * Dave Plonka * * This product includes software developed by the University of Michigan, * Merit Network, Inc., and their contributors. * * This file had been called "radix.h" in the MRT sources. * * I renamed it to "patricia.h" since it's not an implementation of a general * radix trie. Also, pulled in various requirements from "mrt.h" and added * some other things it could be used as a standalone API. */ #ifndef PATRICIA_C #define EXTERN extern #else /* PATRICIA_C */ #define EXTERN #endif /* PATRICIA_C */ #ifndef _PATRICIA_H #define _PATRICIA_H #include #include #include #include #include #include #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE !(FALSE) #endif #ifndef INET6_ADDRSTRLEN #define INET6_ADDRSTRLEN 46 #endif /* typedef unsigned int u_int; */ typedef void (*void_fn_t) (); #define prefix_touchar(prefix) ((u_char *)&(prefix)->add.sin) #define MAXLINE 1024 #define BIT_TEST(f, b) ((f) & (b)) #include #include typedef struct _prefix_t { u_short family; /* AF_INET | AF_INET6 */ u_short bitlen; /* same as mask? */ int ref_count; /* reference count */ union { struct in_addr sin; #ifdef INET6 struct in6_addr sin6; #endif /* IPV6 */ } add; } prefix_t; typedef struct _patricia_node_t { u_int bit; /* flag if this node used */ prefix_t *prefix; /* who we are in patricia tree */ struct _patricia_node_t *l, *r; /* left and right children */ struct _patricia_node_t *parent; /* may be used */ void *data; } patricia_node_t; typedef struct _patricia_tree_t { patricia_node_t *head; u_int maxbits; /* for IP, 32 bit addresses */ int num_active_node; /* for debug purpose */ } patricia_tree_t; EXTERN patricia_node_t *patricia_match_ip(patricia_tree_t *, struct IN_ADDR *); patricia_node_t *patricia_match_string(patricia_tree_t *, const char *); patricia_node_t *patricia_match_exact_string(patricia_tree_t *, const char *); patricia_node_t *patricia_search_exact(patricia_tree_t *, prefix_t *); patricia_node_t *patricia_search_best(patricia_tree_t *, prefix_t *); patricia_node_t *patricia_search_best2(patricia_tree_t *, prefix_t *, int); patricia_node_t *patricia_lookup(patricia_tree_t *, prefix_t *); EXTERN void patricia_remove(patricia_tree_t *, patricia_node_t *); EXTERN patricia_tree_t *patricia_new(int); void patricia_clear(patricia_tree_t *, void_fn_t); EXTERN void patricia_destroy(patricia_tree_t *, void_fn_t); void patricia_process(patricia_tree_t *, void_fn_t); void patricia_init(void); #if 0 prefix_t *ascii2prefix(int family, char *string); #endif patricia_node_t *patricia_make_and_lookup(patricia_tree_t *, const char *); EXTERN patricia_node_t *patricia_make_and_lookup_ip(patricia_tree_t *, struct IN_ADDR *, int); #define PATRICIA_MAXBITS 128 #define PATRICIA_NBIT(x) (0x80 >> ((x) & 0x7f)) #define PATRICIA_NBYTE(x) ((x) >> 3) #define PATRICIA_DATA_GET(node, type) (type *)((node)->data) #define PATRICIA_DATA_SET(node, value) ((node)->data = (void *)(value)) #define PATRICIA_WALK(Xhead, Xnode) \ do { \ patricia_node_t *Xstack[PATRICIA_MAXBITS+1]; \ patricia_node_t **Xsp = Xstack; \ patricia_node_t *Xrn = (Xhead); \ while ((Xnode = Xrn)) { \ if (Xnode->prefix) #define PATRICIA_WALK_ALL(Xhead, Xnode) \ do { \ patricia_node_t *Xstack[PATRICIA_MAXBITS+1]; \ patricia_node_t **Xsp = Xstack; \ patricia_node_t *Xrn = (Xhead); \ while ((Xnode = Xrn)) { \ if (1) #define PATRICIA_WALK_BREAK { \ if (Xsp != Xstack) { \ Xrn = *(--Xsp); \ } else { \ Xrn = (patricia_node_t *) 0; \ } \ continue; } #define PATRICIA_WALK_END \ if (Xrn->l) { \ if (Xrn->r) { \ *Xsp++ = Xrn->r; \ } \ Xrn = Xrn->l; \ } else if (Xrn->r) { \ Xrn = Xrn->r; \ } else if (Xsp != Xstack) { \ Xrn = *(--Xsp); \ } else { \ Xrn = (patricia_node_t *) 0; \ } \ } \ } while (0) #endif /* _PATRICIA_H */ ircd-irc2-2.11.2p2+dfsg/ircd/service_def.h0000644000175000017500000000523511023012025016627 0ustar kurtkurt /* The different things a service can `sniff' */ #define SERVICE_WANT_SERVICE 0x00000001 /* other services signing on/off */ #define SERVICE_WANT_OPER 0x00000002 /* operators, included in _UMODE */ #define SERVICE_WANT_UMODE 0x00000004 /* user modes, iow + local modes */ #define SERVICE_WANT_AWAY 0x00000008 /* away isn't propaged anymore.. */ #define SERVICE_WANT_KILL 0x00000010 /* KILLs */ #define SERVICE_WANT_NICK 0x00000020 /* all NICKs (new user, change) */ #define SERVICE_WANT_USER 0x00000040 /* USER signing on */ #define SERVICE_WANT_QUIT 0x00000080 /* all QUITs (users signing off) */ #define SERVICE_WANT_SERVER 0x00000100 /* servers signing on */ #define SERVICE_WANT_WALLOP 0x00000200 /* wallops */ #define SERVICE_WANT_SQUIT 0x00000400 /* servers signing off */ #define SERVICE_WANT_RQUIT 0x00000800 /* regular user QUITs (these which are also sent between servers) */ #define SERVICE_WANT_MODE 0x00001000 /* channel modes (not +ov) */ #define SERVICE_WANT_CHANNEL 0x00002000 /* channel creations/destructions */ #define SERVICE_WANT_VCHANNEL 0x00004000 /* channel joins/parts */ #define SERVICE_WANT_TOPIC 0x00008000 /* channel topics */ #define SERVICE_WANT_ERRORS 0x01000000 /* &ERRORS */ #define SERVICE_WANT_NOTICES 0x02000000 /* &NOTICES */ #define SERVICE_WANT_LOCAL 0x04000000 /* &LOCAL */ #define SERVICE_WANT_NUMERICS 0x08000000 /* &NUMERICS */ #define SERVICE_WANT_USERLOG 0x10000000 /* FNAME_USERLOG */ #define SERVICE_WANT_CONNLOG 0x20000000 /* FNAME_CONNLOG */ #define SERVICE_WANT_CLIENTS 0x40000000 /* &CLIENTS */ #define SERVICE_WANT_TKLINE 0x00100000 /* service wants to TKLINE */ #define SERVICE_WANT_KLINE 0x00200000 /* service wants to KLINE */ /* masks */ #define SERVICE_MASK_GLOBAL 0x00007000 /*for these,service must be global*/ #define SERVICE_MASK_PREFIX 0x00000FFF /* these actions have a prefix */ #define SERVICE_MASK_ALL 0x7F30FFFF /* all possible actions */ #define SERVICE_MASK_NUM (SERVICE_WANT_NICK|SERVICE_WANT_USER|\ SERVICE_WANT_UMODE) /* options */ #define SERVICE_WANT_PREFIX 0x00010000 /* to receive n!u@h instead of n */ #define SERVICE_WANT_SID 0x00020000 /* use serv token instead of name */ #define SERVICE_WANT_EXTNICK 0x00040000 /* user extended NICK syntax */ #define SERVICE_WANT_UID 0x00080000 /* user extended UID syntax */ /* A couple example types of services */ #define SERVICE_ALL SERVICE_MASK_ALL #define SERVICE_NICK SERVICE_WANT_NICK | \ SERVICE_WANT_QUIT | \ SERVICE_WANT_AWAY #define SERVICE_USERS SERVICE_WANT_NICK | \ SERVICE_WANT_USER | \ SERVICE_WANT_QUIT | \ SERVICE_WANT_AWAY | \ SERVICE_WANT_UMODE #define SERVICE_LINKS SERVICE_WANT_SERVER | \ SERVICE_WANT_SQUIT | \ SERVICE_WANT_WALLOP ircd-irc2-2.11.2p2+dfsg/ircd/fileio.h0000644000175000017500000000543110204445171015632 0ustar kurtkurt/* * ircd-ratbox: A slightly useful ircd. * fileio.h: The file input/output header. * * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center * Copyright (C) 1996-2002 Hybrid Development Team * Copyright (C) 2002-2004 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 * * $Id: fileio.h,v 1.1 2005/02/15 19:16:09 chopin Exp $ */ #ifndef INCLUDED_fileio_h #define INCLUDED_fileio_h #define FB_EOF 0x01 #define FB_FAIL 0x02 struct FileBuf { int fd; /* file descriptor */ char *endp; /* one past the end */ char *ptr; /* current read pos */ char *pbptr; /* pointer to push back char */ int flags; /* file state */ char buf[BUFSIZ]; /* buffer */ char pbuf[BUFSIZ + 1]; /* push back buffer */ }; /* XXX This shouldn't be here */ struct Client; /* * FileBuf is a mirror of the ANSI FILE struct, but it works for any * file descriptor. FileBufs are allocated when a file is opened with * fbopen, and they are freed when the file is closed using fbclose. */ typedef struct FileBuf FBFILE; /* * open a file and return a FBFILE*, see fopen(3) */ extern FBFILE *fbopen(const char *filename, const char *mode); /* * associate a file descriptor with a FBFILE* * if a FBFILE* is associated here it MUST be closed using fbclose * see fdopen(3) */ extern FBFILE *fdbopen(int fd, const char *mode); /* * close a file opened with fbopen, see fclose(3) */ extern void fbclose(FBFILE * fb); /* * return the next character from the file, EOF on end of file * see fgetc(3) */ extern int fbgetc(FBFILE * fb); /* * return next string in a file up to and including the newline character * see fgets(3) */ extern char *fbgets(char *buf, size_t len, FBFILE * fb); /* * ungets c to fb see ungetc(3) */ extern void fbungetc(char c, FBFILE * fb); /* * write a null terminated string to a file, see fputs(3) */ extern int fbputs(const char *str, FBFILE * fb); /* * return the status of the file associated with fb, see fstat(3) */ extern int fbstat(struct stat *sb, FBFILE * fb); /* * popen a file. */ extern FBFILE *fbpopen(const char *, const char *); #endif /* INCLUDED_fileio_h */ ircd-irc2-2.11.2p2+dfsg/ircd/s_debug.c0000644000175000017500000004434411277340323016000 0ustar kurtkurt/************************************************************************ * IRC - Internet Relay Chat, ircd/s_debug.c * Copyright (C) 1990 Jarkko Oikarinen and * University of Oulu, Computing Center * * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef lint static const volatile char rcsid[] = "@(#)$Id: s_debug.c,v 1.56 2009/11/13 20:25:55 chopin Exp $"; #endif #include "os.h" #include "s_defines.h" #define S_DEBUG_C #include "s_externs.h" #undef S_DEBUG_C /* * Option string. Must be before #ifdef DEBUGMODE. * spaces are not allowed. */ char serveropts[] = { #ifndef NO_IDENT 'a', #endif #ifdef CHROOTDIR 'c', #endif #ifdef CMDLINE_CONFIG 'C', #endif #ifdef DEBUGMODE 'D', #endif #ifdef RANDOM_NDELAY 'd', #endif #ifdef OPER_REHASH 'E', #endif #ifdef SLOW_ACCEPT 'f', #endif #ifdef CLONE_CHECK 'F', #endif #ifdef HUB 'H', #endif #ifdef BETTER_CDELAY 'h', #endif #ifdef DEFAULT_INVISIBLE 'I', #endif #ifdef JAPANESE 'j', #endif #ifdef OPER_DIE 'J', #endif #ifdef OPER_KILL # ifndef OPER_KILL_REMOTE 'k', # else 'K', # endif #endif #ifdef FAILED_OPERLOG 'l', #endif #ifdef LEAST_IDLE 'L', #endif #ifdef M4_PREPROC 'm', #endif #ifdef IDLE_FROM_MSG 'M', #endif #ifdef BETTER_NDELAY 'n', #endif #ifdef CRYPT_OPER_PASSWORD 'p', #endif #ifdef CRYPT_LINK_PASSWORD 'P', #endif #ifdef OPER_SQUIT_REMOTE 'Q', #endif #ifdef OPER_RESTART 'R', #endif #ifdef USE_SERVICES 's', #endif #ifdef ENABLE_SUMMON 'S', #endif #ifdef TOPIC_WHO_TIME 'T', #endif #ifndef NO_PREFIX 'u', #endif #ifdef USERS_SHOWS_UTMP 'U', #endif #ifdef ENABLE_SIDTRACE 'v', #endif #ifdef UNIXPORT 'X', #endif #ifdef USE_SYSLOG 'Y', #endif #ifdef ZIP_LINKS 'Z', #endif #ifdef INET6 '6', #endif '\0'}; #ifdef DEBUGMODE static char debugbuf[2*READBUF_SIZE]; /* needs to be big.. */ void debug(int level, char *form, ...) { int err = errno; #ifdef USE_SYSLOG if (level == DEBUG_ERROR) { # if HAVE_VSYSLOG va_list va; va_start(va, form); vsyslog(LOG_ERR, form, va); va_end(va); # else va_list va; va_start(va, form); vsprintf(debugbuf, form, va); va_end(va); syslog(LOG_ERR, "%s", debugbuf); # endif } #endif if ((debuglevel >= 0) && (level <= debuglevel)) { va_list va; va_start(va, form); (void)vsprintf(debugbuf, form, va); va_end(va); (void)fprintf(stderr, "%s\n", debugbuf); } errno = err; } #endif /* DEBUGMODE */ /* * This is part of the STATS replies. There is no offical numeric for this * since this isnt an official command, in much the same way as HASH isnt. * It is also possible that some systems wont support this call or have * different field names for "struct rusage". * -avalon */ void send_usage(aClient *cptr, char *nick) { #if HAVE_GETRUSAGE struct rusage rus; time_t secs, rup; #ifdef hz # define hzz hz #else # ifdef HZ # define hzz HZ # else int hzz = 1; # ifdef HPUX hzz = (int)sysconf(_SC_CLK_TCK); # endif # endif #endif if (getrusage(RUSAGE_SELF, &rus) == -1) { sendto_one(cptr,":%s NOTICE %s :Getruseage error: %s.", me.name, nick, strerror(errno)); return; } secs = rus.ru_utime.tv_sec + rus.ru_stime.tv_sec; rup = timeofday - me.since; if (secs == 0) secs = 1; sendto_one(cptr, ":%s %d %s :CPU Secs %lu:%lu User %lu:%lu System %lu:%lu", me.name, RPL_STATSDEBUG, nick, secs/60, secs%60, rus.ru_utime.tv_sec/60, rus.ru_utime.tv_sec%60, rus.ru_stime.tv_sec/60, rus.ru_stime.tv_sec%60); if (rup && hzz) sendto_one(cptr, ":%s %d %s :RSS %lu ShMem %lu Data %lu Stack %lu", me.name, RPL_STATSDEBUG, nick, rus.ru_maxrss, rus.ru_ixrss / (rup * hzz), rus.ru_idrss / (rup * hzz), rus.ru_isrss / (rup * hzz)); sendto_one(cptr, ":%s %d %s :Swaps %lu Reclaims %lu Faults %lu", me.name, RPL_STATSDEBUG, nick, rus.ru_nswap, rus.ru_minflt, rus.ru_majflt); sendto_one(cptr, ":%s %d %s :Block in %lu out %lu", me.name, RPL_STATSDEBUG, nick, rus.ru_inblock, rus.ru_oublock); sendto_one(cptr, ":%s %d %s :Msg Rcv %lu Send %lu", me.name, RPL_STATSDEBUG, nick, rus.ru_msgrcv, rus.ru_msgsnd); sendto_one(cptr, ":%s %d %s :Signals %lu Context Vol. %lu Invol %lu", me.name, RPL_STATSDEBUG, nick, rus.ru_nsignals, rus.ru_nvcsw, rus.ru_nivcsw); #else /* HAVE_GETRUSAGE */ # if HAVE_TIMES struct tms tmsbuf; time_t secs, mins; int hzz = 1, ticpermin; int umin, smin, usec, ssec; # ifdef HPUX hzz = sysconf(_SC_CLK_TCK); # endif ticpermin = hzz * 60; umin = tmsbuf.tms_utime / ticpermin; usec = (tmsbuf.tms_utime%ticpermin)/(float)hzz; smin = tmsbuf.tms_stime / ticpermin; ssec = (tmsbuf.tms_stime%ticpermin)/(float)hzz; secs = usec + ssec; mins = (secs/60) + umin + smin; secs %= hzz; if (times(&tmsbuf) == -1) { sendto_one(cptr, ":%s %d %s :times(2) error: %s.", me.name, RPL_STATSDEBUG, nick, strerror(errno)); return; } secs = tmsbuf.tms_utime + tmsbuf.tms_stime; sendto_one(cptr, ":%s %d %s :CPU Secs %lu:%lu User %lu:%lu System %lu:%lu", me.name, RPL_STATSDEBUG, nick, mins, secs, umin, usec, smin, ssec); # endif /* HAVE_TIMES */ #endif /* HAVE_GETRUSAGE */ sendto_one(cptr, ":%s %d %s :DBUF alloc %lu blocks %lu", me.name, RPL_STATSDEBUG, nick, istat.is_dbufuse, istat.is_dbufnow); #ifdef DEBUGMODE sendto_one(cptr, ":%s %d %s :Reads %lu Writes %lu", me.name, RPL_STATSDEBUG, nick, readcalls, writecalls); sendto_one(cptr, ":%s %d %s :Writes: <0 %d 0 %d <16 %d <32 %d <64 %d", me.name, RPL_STATSDEBUG, nick, writeb[0], writeb[1], writeb[2], writeb[3], writeb[4]); sendto_one(cptr, ":%s %d %s :<128 %d <256 %d <512 %d <1024 %d >1024 %d", me.name, RPL_STATSDEBUG, nick, writeb[5], writeb[6], writeb[7], writeb[8], writeb[9]); #endif return; } void send_defines(aClient *cptr, char *nick, char *extend) { sendto_one(cptr, ":%s %d %s :HUB:%s MS:%d", ME, RPL_STATSDEFINE, nick, #ifdef HUB "yes", #else "no", #endif MAXSERVERS); sendto_one(cptr, ":%s %d %s :LQ:%d MXC:%d TS:%d HRD:%d HGL:%d WWD:%d ATO:%d", ME, RPL_STATSDEFINE, nick, LISTENQUEUE, MAXCONNECTIONS, TIMESEC, HANGONRETRYDELAY, HANGONGOODLINK, WRITEWAITDELAY, ACCEPTTIMEOUT); sendto_one(cptr, ":%s %d %s :KCTL:%d DCTL:%d LDCTL:%d CF:%d MCPU:%d", ME, RPL_STATSDEFINE, nick, KILLCHASETIMELIMIT, DELAYCHASETIMELIMIT, LDELAYCHASETIMELIMIT, CLIENT_FLOOD, MAXCHANNELSPERUSER); sendto_one(cptr, ":%s %d %s :H:%d N:%d N0:%d D:%d U:%d R:%d T:%d C:%d P:%d K:%d", ME, RPL_STATSDEFINE, nick, HOSTLEN, LOCALNICKLEN, #ifdef MINLOCALNICKLEN MINLOCALNICKLEN, #else 1, #endif UIDLEN, USERLEN, REALLEN, TOPICLEN, CHANNELLEN, PASSWDLEN, KEYLEN); sendto_one(cptr, ":%s %d %s :BS:%d MXR:%d MXB:%d MXBL:%d PY:%d", ME, RPL_STATSDEFINE, nick, BUFSIZE, MAXRECIPIENTS, MAXBANS, MAXBANLENGTH, MAXPENALTY); sendto_one(cptr, ":%s %d %s :ZL:%d CM:%d CP:%d DC:%d", ME, RPL_STATSDEFINE, nick, #ifdef ZIP_LINKS ZIP_LEVEL, #else -1, #endif #ifdef CLONE_CHECK CLONE_MAX, CLONE_PERIOD, #else -1, -1, #endif #ifdef DELAY_CLOSE DELAY_CLOSE #else -1 #endif ); sendto_one(cptr, ":%s %d %s :AC:%d CA:%d S:%d SS:%d/%d/%d SU:%d/%d/%d", ME, RPL_STATSDEFINE, nick, iconf.aconnect, iconf.caccept, iconf.split, SPLIT_SERVERS, iconf.split_minservers, istat.is_eobservers, SPLIT_USERS, iconf.split_minusers, istat.is_user[0] + istat.is_user[1]); #ifdef CLIENTS_CHANNEL sendto_one(cptr, ":%s %d %s :CCL:0x%X", ME, RPL_STATSDEFINE, nick, CLIENTS_CHANNEL_LEVEL); #endif /* note that it's safe to check extend[1], it will at worst be null. ** if we ever need extend[2], check length first... --B. */ if (extend[1] == '5') { char **isup = isupport; while (*isup) { sendto_one(cptr, replies[RPL_ISUPPORT], ME, nick, *isup); isup++; } } } void count_memory(aClient *cptr, char *nick, int debug) { extern aChannel *channel; extern aClass *classes; extern aConfItem *conf; extern int _HASHSIZE, _CHANNELHASHSIZE; Reg aClient *acptr; Reg Link *link; Reg aChannel *chptr; Reg aConfItem *aconf; Reg aClass *cltmp; int lc = 0, d_lc = 0, /* local clients */ ch = 0, d_ch = 0, /* channels */ lcc = 0, d_lcc = 0, /* local client conf links */ rc = 0, d_rc = 0, /* remote clients */ us = 0, d_us = 0, /* user structs */ chu = 0, d_chu = 0, /* channel users */ chi = 0, d_chi = 0, /* channel invites */ chb = 0, d_chb = 0, /* channel bans */ chh = 0, d_chh = 0, /* channel in history */ wwu = 0, d_wwu = 0, /* whowas users */ cl = 0, d_cl = 0, /* classes */ co = 0, d_co = 0; /* conf lines */ int usi = 0, d_usi = 0, /* users invited */ usc = 0, d_usc = 0, /* users in channels */ aw = 0, d_aw = 0, /* aways set */ wwa = 0, d_wwa = 0, /* whowas aways */ wwuw = 0, d_wwuw = 0; /* whowas uwas */ u_long chm = 0, d_chm = 0, /* memory used by channels */ chhm = 0, d_chhm = 0, /* memory used by channel in history */ chbm = 0, d_chbm = 0, /* memory used by channel bans */ lcm = 0, d_lcm = 0, /* memory used by local clients */ rcm = 0, d_rcm = 0, /* memory used by remote clients */ awm = 0, d_awm = 0, /* memory used by aways */ wwam = 0, d_wwam = 0, /* whowas away memory used */ wwm = 0, d_wwm = 0, /* whowas array memory used */ dm = 0, d_dm = 0, /* delay array memory used */ com = 0, d_com = 0, /* memory used by conf lines */ db = 0, d_db = 0, /* memory used by dbufs */ rm = 0, d_rm = 0, /* res memory used */ totcl = 0, d_totcl = 0, totch = 0, d_totch = 0, totww = 0, d_totww = 0, tot = 0, d_tot = 0; time_t start = 0; if (debug) { start = time(NULL); count_whowas_memory(&d_wwu, &d_wwa, &d_wwam, &d_wwuw); d_wwm = sizeof(aName) * ww_size; d_dm = sizeof(aLock) * lk_size; } wwu = istat.is_wwusers; wwa = istat.is_wwaways; wwam = istat.is_wwawaysmem; wwuw = istat.is_wwuwas; wwm = sizeof(aName) * ww_size; dm = sizeof(aLock) * lk_size; /*lc = istat.is_unknown + istat.is_myclnt + istat.is_serv;*/ lc = istat.is_localc; lcc = istat.is_conflink; rc = istat.is_remc; us = istat.is_users; usi = istat.is_useri; usc = istat.is_userc; aw = istat.is_away; awm = istat.is_awaymem; if (debug) { for (acptr = client; acptr; acptr = acptr->next) { if (MyConnect(acptr)) { d_lc++; for (link = acptr->confs; link; link=link->next) { d_lcc++; } } else { d_rc++; } if (acptr->user) { invLink *ilink; d_us++; for (ilink = acptr->user->invited; ilink; ilink = ilink->next) { d_usi++; } d_usc += acptr->user->joined; if (acptr->user->away) { d_aw++; d_awm += (strlen(acptr->user->away)+1); } } } } lcm = lc * CLIENT_LOCAL_SIZE; rcm = rc * CLIENT_REMOTE_SIZE; d_lcm = d_lc * CLIENT_LOCAL_SIZE; d_rcm = d_rc * CLIENT_REMOTE_SIZE; ch = istat.is_chan; chm = istat.is_chanmem; chh = istat.is_hchan; chhm = istat.is_hchanmem; chi = istat.is_invite; chb = istat.is_bans; chbm = istat.is_banmem + chb * sizeof(Link); chu = istat.is_chanusers; if (debug) { for (chptr = channel; chptr; chptr = chptr->nextch) { if (chptr->users == 0) { d_chh++; d_chhm+=strlen(chptr->chname)+sizeof(aChannel); } else { d_ch++; d_chm += (strlen(chptr->chname) + sizeof(aChannel)); } for (link = chptr->members; link; link = link->next) { d_chu++; } for (link = chptr->invites; link; link = link->next) { d_chi++; } for (link = chptr->mlist; link; link = link->next) { d_chb++; d_chbm += strlen(link->value.cp) + 1; } } d_chbm += d_chb * sizeof(Link); } co = istat.is_conf; com = istat.is_confmem; cl = istat.is_class; if (debug) { for (aconf = conf; aconf; aconf = aconf->next) { d_co++; d_com += aconf->host ? strlen(aconf->host)+1 : 0; d_com += aconf->passwd ? strlen(aconf->passwd)+1 : 0; d_com += aconf->name ? strlen(aconf->name)+1 : 0; d_com += aconf->ping ? sizeof(*aconf->ping) : 0; d_com += sizeof(aConfItem); } for (cltmp = classes; cltmp; cltmp = cltmp->next) { d_cl++; } } if (debug) sendto_one(cptr, ":%s %d %s :Request processed in %u seconds", me.name, RPL_STATSDEBUG, nick, time(NULL) - start); sendto_one(cptr, ":%s %d %s :Client Local %d(%lu) Remote %d(%lu) Auth %d(%lu)", me.name, RPL_STATSDEBUG, nick, lc, lcm, rc, rcm, istat.is_auth, istat.is_authmem); if (debug && (lc != d_lc || lcm != d_lcm || rc != d_rc || rcm != d_rcm)) { sendto_one(cptr, ":%s %d %s :Client Local %d(%lu) Remote %d(%lu) [REAL]", me.name, RPL_STATSDEBUG, nick, d_lc, d_lcm, d_rc, d_rcm); } sendto_one(cptr, ":%s %d %s :Users %d in/visible %d/%d(%lu) Invites %d(%lu)", me.name, RPL_STATSDEBUG, nick, us, istat.is_user[1], istat.is_user[0], us*sizeof(anUser), usi, usi*sizeof(Link)); if (debug && (us != d_us || usi != d_usi)) { sendto_one(cptr, ":%s %d %s :Users %d(%lu) Invites %d(%lu) [REAL]", me.name, RPL_STATSDEBUG, nick, d_us, d_us*sizeof(anUser), d_usi, d_usi * sizeof(Link)); } sendto_one(cptr, ":%s %d %s :User channels %d(%lu) Aways %d(%lu)", me.name, RPL_STATSDEBUG, nick, usc, usc*sizeof(Link), aw, awm); if (debug && (usc != d_usc || aw != d_aw || awm != d_awm)) { sendto_one(cptr, ":%s %d %s :User channels %d(%lu) Aways %d(%lu) [REAL]", me.name, RPL_STATSDEBUG, nick, d_usc, d_usc*sizeof(Link), d_aw, d_awm); } sendto_one(cptr, ":%s %d %s :Attached confs %d(%lu)", me.name, RPL_STATSDEBUG, nick, lcc, lcc*sizeof(Link)); if (debug && lcc != d_lcc) { sendto_one(cptr, ":%s %d %s :Attached confs %d(%lu) [REAL]", me.name, RPL_STATSDEBUG, nick, d_lcc, d_lcc*sizeof(Link)); } totcl = lcm + rcm + us*sizeof(anUser) + usc*sizeof(Link) + awm; totcl += lcc*sizeof(Link) + usi*sizeof(Link); d_totcl = d_lcm + d_rcm + d_us*sizeof(anUser) + d_usc*sizeof(Link); d_totcl += d_awm + d_lcc*sizeof(Link) + d_usi*sizeof(Link); sendto_one(cptr, ":%s %d %s :Conflines %d(%lu)", me.name, RPL_STATSDEBUG, nick, co, com); if (debug && (co != d_co || com != d_com)) { sendto_one(cptr, ":%s %d %s :Conflines %d(%lu) [REAL]", me.name, RPL_STATSDEBUG, nick, d_co, d_com); } sendto_one(cptr, ":%s %d %s :Classes %d(%lu)", me.name, RPL_STATSDEBUG, nick, cl, cl*sizeof(aClass)); if (debug && cl != d_cl) { sendto_one(cptr, ":%s %d %s :Classes %d(%lu) [REAL]", me.name, RPL_STATSDEBUG, nick, d_cl, d_cl*sizeof(aClass)); } sendto_one(cptr, ":%s %d %s :Channels %d(%lu) Modes %d(%lu) History %d(%lu) Cache %d(%lu)", me.name, RPL_STATSDEBUG, nick, ch, chm, chb, chbm, chh, chhm, istat.is_cchan, istat.is_cchanmem); if (debug && (ch != d_ch || chm != d_chm || chb != d_chb || chbm != d_chbm || chh != d_chh || chhm != d_chhm)) { sendto_one(cptr, ":%s %d %s :Channels %d(%lu) Modes %d(%lu) History %d(%lu) [REAL]", me.name, RPL_STATSDEBUG, nick, d_ch, d_chm, d_chb, d_chbm, d_chh, d_chhm); } sendto_one(cptr, ":%s %d %s :Channel members %d(%lu) invite %d(%lu)", me.name, RPL_STATSDEBUG, nick, chu, chu*sizeof(Link), chi, chi*sizeof(Link)); if (debug && (chu != d_chu || chi != d_chi)) { sendto_one(cptr, ":%s %d %s :Channel members %d(%lu) invite %d(%lu) " "[REAL]", me.name, RPL_STATSDEBUG, nick, d_chu, d_chu*sizeof(Link), d_chi, d_chi*sizeof(Link)); } totch = chm + chhm + chbm + chu*sizeof(Link) + chi*sizeof(Link); d_totch = d_chm + d_chhm + d_chbm + d_chu*sizeof(Link) + d_chi*sizeof(Link); sendto_one(cptr, ":%s %d %s :Whowas users %d(%lu) away %d(%lu) links %d(%lu)", me.name, RPL_STATSDEBUG, nick, wwu, wwu*sizeof(anUser), wwa, wwam, wwuw, wwuw*sizeof(Link)); if (debug && (wwu != d_wwu || wwa != d_wwa || wwam != d_wwam || wwuw != d_wwuw)) { sendto_one(cptr, ":%s %d %s :Whowas users %d(%lu) away %d(%lu) " "links %d(%lu) [REAL]", me.name, RPL_STATSDEBUG, nick, d_wwu, d_wwu*sizeof(anUser), d_wwa, d_wwam, d_wwuw, d_wwuw*sizeof(Link)); } sendto_one(cptr, ":%s %d %s :Whowas array %d(%lu) Delay array %d(%lu)", me.name, RPL_STATSDEBUG, nick, ww_size, wwm, lk_size, dm); if (debug && (wwm != d_wwm || dm != d_dm)) { sendto_one(cptr, ":%s %d %s :Whowas array %d(%lu) Delay array %d(%lu) " "[REAL]", me.name, RPL_STATSDEBUG, nick, ww_size, d_wwm, lk_size, d_dm); } totww = wwu*sizeof(anUser) + wwam + wwm; d_totww = d_wwu*sizeof(anUser) + d_wwam + d_wwm; sendto_one(cptr, ":%s %d %s :Hash: client %d(%lu) chan %d(%lu)", me.name, RPL_STATSDEBUG, nick, _HASHSIZE, sizeof(aHashEntry) * _HASHSIZE, _CHANNELHASHSIZE, sizeof(aHashEntry) * _CHANNELHASHSIZE); d_db = db = istat.is_dbufnow * sizeof(dbufbuf); db = istat.is_dbufnow * sizeof(dbufbuf); sendto_one(cptr, ":%s %d %s :Dbuf blocks %lu(%lu) (> %lu [%lu]) (%lu < %lu) " "[%lu]", me.name, RPL_STATSDEBUG, nick, istat.is_dbufnow, db, istat.is_dbuf, (u_int) (((u_int)BUFFERPOOL) / ((u_int)sizeof(dbufbuf))), istat.is_dbufuse, istat.is_dbufmax, istat.is_dbufmore); d_rm = rm = cres_mem(cptr, nick); tot = totww + totch + totcl + com + cl*sizeof(aClass) + db + rm; tot += sizeof(aHashEntry) * _HASHSIZE; tot += sizeof(aHashEntry) * _CHANNELHASHSIZE; d_tot = d_totww + d_totch + d_totcl + d_com + d_cl*sizeof(aClass); d_tot += d_db + d_rm; d_tot += sizeof(aHashEntry) * _HASHSIZE; d_tot += sizeof(aHashEntry) * _CHANNELHASHSIZE; sendto_one(cptr, ":%s %d %s :Total: ww %lu ch %lu cl %lu co %lu db %lu", me.name, RPL_STATSDEBUG, nick, totww, totch, totcl, com,db); if (debug && tot != d_tot) { sendto_one(cptr, ":%s %d %s :Total: ww %lu ch %lu cl %lu co %lu " "db %lu [REAL]", me.name, RPL_STATSDEBUG, nick, d_totww, d_totch, d_totcl, d_com, d_db); sendto_one(cptr, ":%s %d %s :TOTAL: %lu [REAL]", me.name, RPL_STATSDEBUG, nick, d_tot); } sendto_one(cptr, ":%s %d %s :TOTAL: %d sbrk(0)-etext: %u", me.name, RPL_STATSDEBUG, nick, tot, (u_long)sbrk((size_t)0)-(u_long)sbrk0); return; } ircd-irc2-2.11.2p2+dfsg/ircd/s_externs.h0000644000175000017500000000331411157044733016402 0ustar kurtkurt/************************************************************************ * IRC - Internet Relay Chat, ircd/s_externs.h * Copyright (C) 1997 Alain Nissen * * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* This file includes all *_ext.h files containing external declarations * for the IRC server. */ #include "bsd_ext.h" #include "channel_ext.h" #include "class_ext.h" #include "dbuf_ext.h" #include "hash_ext.h" #include "ircd_ext.h" #include "list_ext.h" #include "match_ext.h" #include "packet_ext.h" #include "parse_ext.h" #include "res_comp_ext.h" #include "res_ext.h" #include "res_init_ext.h" #include "res_mkquery_ext.h" #include "s_auth_ext.h" #include "s_bsd_ext.h" #include "s_conf_ext.h" #include "s_debug_ext.h" #include "s_err_ext.h" #include "s_misc_ext.h" #include "s_numeric_ext.h" #include "s_serv_ext.h" #include "s_service_ext.h" #include "s_send_ext.h" #include "s_user_ext.h" #include "s_zip_ext.h" #include "s_id_ext.h" #include "send_ext.h" #include "support_ext.h" #include "version_ext.h" #include "whowas_ext.h" #include "patricia_ext.h" ircd-irc2-2.11.2p2+dfsg/ircd/s_auth_ext.h0000644000175000017500000000315107744057363016544 0ustar kurtkurt/************************************************************************ * IRC - Internet Relay Chat, ircd/s_auth_ext.h * Copyright (C) 1997 Alain Nissen * * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* This file contains external definitions for global variables and functions defined in ircd/s_auth.c. */ /* External definitions for global functions. */ #ifndef S_AUTH_C # if defined(USE_IAUTH) extern u_char iauth_options; extern u_int iauth_spawn; # endif # # define EXTERN extern #else /* S_AUTH_C */ # define EXTERN #endif /* S_AUTH_C */ #if defined(USE_IAUTH) EXTERN int vsendto_iauth (char *pattern, va_list va); EXTERN int sendto_iauth (char *pattern, ...); EXTERN void read_iauth(void); EXTERN void report_iauth_conf (aClient *, char *); EXTERN void report_iauth_stats (aClient *, char *); #endif EXTERN void start_auth (Reg aClient *cptr); EXTERN void send_authports (aClient *cptr); EXTERN void read_authports (Reg aClient *cptr); #undef EXTERN ircd-irc2-2.11.2p2+dfsg/ircd/res_comp.c0000644000175000017500000005112310127336166016173 0ustar kurtkurt/* * ++Copyright++ 1985, 1993 * - * Copyright (c) 1985, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Portions Copyright (c) 1993 by Digital Equipment Corporation. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. * - * --Copyright-- */ #if defined(LIBC_SCCS) && !defined(lint) static const volatile char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93"; static const volatile char rcsid[] = "$Id: res_comp.c,v 1.10 2004/10/01 20:22:14 chopin Exp $"; #endif /* LIBC_SCCS and not lint */ #include "os.h" #include "s_defines.h" #define RES_COMP_C #include "s_externs.h" #undef RES_COMP_C static int ns_name_ntop (const u_char *, char *, size_t); static int ns_name_pton (const char *, u_char *, size_t); static int ns_name_unpack (const u_char *, const u_char *, const u_char *, u_char *, size_t); static int ns_name_pack (const u_char *, u_char *, int, const u_char **, const u_char **); static int ns_name_uncompress (const u_char *, const u_char *, const u_char *, char *, size_t); static int ns_name_compress (const char *, u_char *, size_t, const u_char **, const u_char **); static int ns_name_skip (const u_char **, const u_char *); /* * Expand compressed domain name 'comp_dn' to full domain name. * 'msg' is a pointer to the begining of the message, * 'eomorig' points to the first location after the message, * 'exp_dn' is a pointer to a buffer of size 'length' for the result. * Return size of compressed name or -1 if there was an error. */ int ircd_dn_expand(const u_char *msg, const u_char *eom, const u_char *src, char *dst, int dstsiz) { int n = ns_name_uncompress(msg, eom, src, dst, (size_t)dstsiz); if (n > 0 && dst[0] == '.') dst[0] = '\0'; return (n); } /* * Pack domain name 'exp_dn' in presentation form into 'comp_dn'. * Return the size of the compressed name or -1. * 'length' is the size of the array pointed to by 'comp_dn'. */ int ircd_dn_comp(const char *src, u_char *dst, int dstsiz, u_char **dnptrs, u_char **lastdnptr) { return (ns_name_compress(src, dst, (size_t)dstsiz, (const u_char **)dnptrs, (const u_char **)lastdnptr)); } /* * Skip over a compressed domain name. Return the size or -1. */ int __ircd_dn_skipname(const u_char *ptr, const u_char *eom) { const u_char *saveptr = ptr; if (ns_name_skip(&ptr, eom) == -1) return (-1); return (ptr - saveptr); } /* * Verify that a domain name uses an acceptable character set. */ /* * Note the conspicuous absence of ctype macros in these definitions. On * non-ASCII hosts, we can't depend on string literals or ctype macros to * tell us anything about network-format data. The rest of the BIND system * is not careful about this, but for some reason, we're doing it right here. */ #define PERIOD 0x2e #define hyphenchar(c) ((c) == 0x2d) #define bslashchar(c) ((c) == 0x5c) #define periodchar(c) ((c) == PERIOD) #define asterchar(c) ((c) == 0x2a) #define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \ || ((c) >= 0x61 && (c) <= 0x7a)) #define digitchar(c) ((c) >= 0x30 && (c) <= 0x39) #define borderchar(c) (alphachar(c) || digitchar(c)) #define middlechar(c) (borderchar(c) || hyphenchar(c)) #define domainchar(c) ((c) > 0x20 && (c) < 0x7f) #if 0 /* it seems that we don't need these -krys */ int res_hnok(const char *dn) { int ppch = '\0', pch = PERIOD, ch = *dn++; while (ch != '\0') { int nch = *dn++; if (periodchar(ch)) { NULL; } else if (periodchar(pch)) { if (!borderchar(ch)) return (0); } else if (periodchar(nch) || nch == '\0') { if (!borderchar(ch)) return (0); } else { if (!middlechar(ch)) return (0); } ppch = pch, pch = ch, ch = nch; } return (1); } /* * hostname-like (A, MX, WKS) owners can have "*" as their first label * but must otherwise be as a host name. */ int res_ownok(const char *dn) { if (asterchar(dn[0])) { if (periodchar(dn[1])) return (res_hnok(dn+2)); if (dn[1] == '\0') return (1); } return (res_hnok(dn)); } /* * SOA RNAMEs and RP RNAMEs can have any printable character in their first * label, but the rest of the name has to look like a host name. */ int res_mailok(const char *dn) { int ch, escaped = 0; /* "." is a valid missing representation */ if (*dn == '\0') return(1); /* otherwise