diff -ru --new-file irc2.10.3p3/common/bsd.c irc2.10.3p3+sd7/common/bsd.c --- irc2.10.3p3/common/bsd.c Sun Mar 4 21:21:56 2001 +++ irc2.10.3p3+sd7/common/bsd.c Mon Feb 3 14:31:07 2003 @@ -105,7 +105,11 @@ #ifndef NOWRITEALARM (void)alarm(WRITEWAITDELAY); #endif +#ifdef USE_SSL + retval = safe_write(cptr, str, len); +#else retval = send(cptr->fd, str, len, 0); +#endif /* ** Convert WOULDBLOCK to a return of "0 bytes moved". This ** should occur only if socket was non-blocking. Note, that diff -ru --new-file irc2.10.3p3/common/class_def.h irc2.10.3p3+sd7/common/class_def.h --- irc2.10.3p3/common/class_def.h Tue Sep 23 23:47:53 1997 +++ irc2.10.3p3+sd7/common/class_def.h Mon Feb 3 14:31:07 2003 @@ -28,6 +28,9 @@ int maxHGlobal; int maxUHGlobal; int links; +#ifdef USE_SSL + int ssl; +#endif struct Class *next; } aClass; @@ -40,6 +43,9 @@ #define MaxUHLocal(x) ((x)->maxUHLocal) #define MaxHGlobal(x) ((x)->maxHGlobal) #define MaxUHGlobal(x) ((x)->maxUHGlobal) +#ifdef USE_SSL +#define UseSSL(x) ((x)->ssl) +#endif #define Links(x) ((x)->links) #define IncSendq(x) MaxSendq(x) = (int)((float)MaxSendq(x) * 1.1) diff -ru --new-file irc2.10.3p3/common/common_def.h irc2.10.3p3+sd7/common/common_def.h --- irc2.10.3p3/common/common_def.h Fri Feb 5 01:26:35 1999 +++ irc2.10.3p3+sd7/common/common_def.h Mon Feb 3 14:31:07 2003 @@ -54,6 +54,7 @@ #define PUNCT 8 #define DIGIT 16 #define SPACE 32 +#define VALID 64 #define isalpha(c) (char_atribs[(u_char)(c)]&ALPHA) #define isspace(c) (char_atribs[(u_char)(c)]&SPACE) @@ -74,6 +75,9 @@ #define isgraph(c) ((char_atribs[(u_char)(c)]&PRINT) && \ ((u_char)(c) != (u_char)0x20)) #define ispunct(c) (!(char_atribs[(u_char)(c)]&(CNTRL|ALPHA|DIGIT))) +#ifdef RESTRICT_USERNAMES +#define isvaliduser(c) (char_atribs[(u_char)(c)]&VALID) +#endif #ifdef DEBUGMODE # define Debug(x) debug x diff -ru --new-file irc2.10.3p3/common/match.c irc2.10.3p3+sd7/common/match.c --- irc2.10.3p3/common/match.c Thu Jul 5 00:44:40 2001 +++ irc2.10.3p3+sd7/common/match.c Mon Feb 3 14:31:07 2003 @@ -110,34 +110,37 @@ /* 16-23 */ CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, /* 24-31 */ CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, /* space */ PRINT|SPACE, -/* !"#$%&'( */ PRINT, PRINT, PRINT, PRINT, PRINT, PRINT, PRINT, PRINT, -/* )*+,-./ */ PRINT, PRINT, PRINT, PRINT, PRINT, PRINT, PRINT, -/* 0123 */ PRINT|DIGIT, PRINT|DIGIT, PRINT|DIGIT, PRINT|DIGIT, -/* 4567 */ PRINT|DIGIT, PRINT|DIGIT, PRINT|DIGIT, PRINT|DIGIT, -/* 89:; */ PRINT|DIGIT, PRINT|DIGIT, PRINT, PRINT, -/* <=>? */ PRINT, PRINT, PRINT, PRINT, -/* @ */ PRINT, -/* ABC */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* DEF */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* GHI */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* JKL */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* MNO */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* PQR */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* STU */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* VWX */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* YZ[ */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* \]^ */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* _` */ PRINT, PRINT, -/* abc */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* def */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* ghi */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* jkl */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* mno */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* pqr */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* stu */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* vwx */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* yz{ */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* \}~ */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, +/* !"#$ */ PRINT, PRINT, PRINT, PRINT, +/* %&'( */ PRINT, PRINT, PRINT, PRINT, +/* )*+ */ PRINT, PRINT, PRINT, +/* ,-. */ PRINT, PRINT|VALID, PRINT|VALID, +/* /01 */ PRINT, PRINT|DIGIT|VALID, PRINT|DIGIT|VALID, +/* 234 */ PRINT|DIGIT|VALID, PRINT|DIGIT|VALID, PRINT|DIGIT|VALID, +/* 567 */ PRINT|DIGIT|VALID, PRINT|DIGIT|VALID, PRINT|DIGIT|VALID, +/* 89: */ PRINT|DIGIT|VALID, PRINT|DIGIT|VALID, PRINT, +/* ;<= */ PRINT, PRINT, PRINT, +/* >?@ */ PRINT, PRINT, PRINT, +/* ABC */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* DEF */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* GHI */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* JKL */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* MNO */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* PQR */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* STU */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* VWX */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* YZ[ */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* \]^ */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA, +/* _` */ PRINT|VALID,PRINT, +/* abc */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* def */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* ghi */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* jkl */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* mno */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* pqr */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* stu */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* vwx */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* yz{ */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* \}~ */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA, /* del */ 0, /* 80-8f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90-9f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff -ru --new-file irc2.10.3p3/common/msg_def.h irc2.10.3p3+sd7/common/msg_def.h --- irc2.10.3p3/common/msg_def.h Fri Jan 23 15:28:07 1998 +++ irc2.10.3p3+sd7/common/msg_def.h Mon Feb 3 14:31:07 2003 @@ -32,6 +32,12 @@ #define MSG_QUIT "QUIT" /* QUIT */ #define MSG_SQUIT "SQUIT" /* SQUI */ #define MSG_KILL "KILL" /* KILL */ +#if defined(OPER_KLINE) || defined(LOCOP_KLINE) +#define MSG_KLINE "KLINE" /* KLIN */ +#endif +#if defined(OPER_TKLINE) || defined(LOCOP_TKLINE) +#define MSG_TKLINE "TKLINE" /* TKLI */ +#endif #define MSG_INFO "INFO" /* INFO */ #define MSG_LINKS "LINKS" /* LINK */ #define MSG_SUMMON "SUMMON" /* SUMM */ @@ -48,15 +54,19 @@ #define MSG_WALLOPS "WALLOPS" /* WALL */ #define MSG_TIME "TIME" /* TIME */ #define MSG_NAMES "NAMES" /* NAME */ +#define MSG_SNAMES "SNAMES" /* SNAMES */ #define MSG_ADMIN "ADMIN" /* ADMI */ #define MSG_TRACE "TRACE" /* TRAC */ #define MSG_NOTICE "NOTICE" /* NOTI */ #define MSG_JOIN "JOIN" /* JOIN */ +#define MSG_SJOIN "SJOIN" /* SJOIN */ +#define MSG_SCLEAN "SCLEAN" /* SCLEAN */ #define MSG_NJOIN "NJOIN" /* NJOIN */ #define MSG_PART "PART" /* PART */ #define MSG_LUSERS "LUSERS" /* LUSE */ #define MSG_MOTD "MOTD" /* MOTD */ #define MSG_MODE "MODE" /* MODE */ +#define MSG_SMODE "SMODE" /* SMODE */ #define MSG_UMODE "UMODE" /* UMOD */ #define MSG_KICK "KICK" /* KICK */ #define MSG_RECONECT "RECONNECT" /* RECONNECT -> RECO */ @@ -73,5 +83,10 @@ #define MSG_DIE "DIE" #define MSG_HASH "HAZH" /* HASH */ #define MSG_DNS "DNS" /* DNS -> DNSS */ - -#define MAXPARA 15 +#ifdef SERVER_MAP +#define MSG_MAP "MAP" +#endif +#ifdef OPER_SET +#define MSG_SET "SET" /* SET */ +#endif +#define MAXPARA 15 diff -ru --new-file irc2.10.3p3/common/numeric_def.h irc2.10.3p3+sd7/common/numeric_def.h --- irc2.10.3p3/common/numeric_def.h Sat Feb 10 21:11:05 2001 +++ irc2.10.3p3+sd7/common/numeric_def.h Mon Feb 3 14:31:07 2003 @@ -123,8 +123,18 @@ #define RPL_YOURHOST 002 #define RPL_CREATED 003 #define RPL_MYINFO 004 +#ifdef SEND_ISUPPORT +#define RPL_ISUPPORT 005 +#define RPL_BOUNCE 10 +#else #define RPL_BOUNCE 005 - +#endif +#ifdef SERVER_MAP +#define RPL_MAP 15 /* Undernet extension */ +#define RPL_MAPMORE 16 /* Undernet extension */ +#define RPL_MAPEND 17 /* Undernet extension */ +#define RPL_MAPSTART 18 /* +hemp */ +#endif /* * Errors are in the range from 400-599 currently and are grouped by what * commands they come from. @@ -232,6 +242,7 @@ #define RPL_NOTOPIC 331 #define RPL_TOPIC 332 +#define RPL_TOPICWHOTIME 333 #define RPL_INVITING 341 #define RPL_SUMMONING 342 @@ -299,7 +310,7 @@ #define RPL_STATSQLINE 217 #define RPL_STATSYLINE 218 #define RPL_ENDOFSTATS 219 - +#define RPL_STATSPLINE 220 #define RPL_UMODEIS 221 #define RPL_SERVICEINFO 231 @@ -335,3 +346,5 @@ #define RPL_TRACEEND 262 #define RPL_TRYAGAIN 263 +#define RPL_LOCALUSERS 265 +#define RPL_GLOBALUSERS 266 diff -ru --new-file irc2.10.3p3/common/os.h irc2.10.3p3+sd7/common/os.h --- irc2.10.3p3/common/os.h Thu Feb 3 19:57:00 2000 +++ irc2.10.3p3+sd7/common/os.h Mon Feb 3 14:31:07 2003 @@ -1,3 +1,5 @@ +#ifndef OS_H +#define OS_H /************************************************************************ * IRC - Internet Relay Chat, include/os.h * Copyright (C) 1997 Alain Nissen @@ -25,6 +27,13 @@ or need to be redefined for various reasons. */ +#include /* SSL stuff */ +#include +#include +#include +#include +#include + #include "setup.h" #if defined(linux) @@ -137,6 +146,9 @@ /* Linux 2.1.xx supports poll(), header files are not upto date yet */ # define POLLRDNORM 0x0040 # endif +#ifndef POLLWRNORM +#define POLLWRNORM 0x0100 +#endif #endif #if HAVE_STROPTS_H @@ -759,3 +771,4 @@ # define WHOSTENTP(x) (x) # define IRCDCONF_DELIMITER ':' #endif +#endif diff -ru --new-file irc2.10.3p3/common/parse.c irc2.10.3p3+sd7/common/parse.c --- irc2.10.3p3/common/parse.c Tue May 16 20:53:13 2000 +++ irc2.10.3p3+sd7/common/parse.c Mon Feb 3 14:31:07 2003 @@ -42,7 +42,32 @@ { MSG_NJOIN, m_njoin, MAXPARA, MSG_LAG|MSG_REG|MSG_NOU, 0, 0, 0L}, #endif { MSG_JOIN, m_join, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L}, +#ifndef CLIENT_COMPILE +# ifdef SOPER_SJOIN +# ifdef LOCOP_SJOIN + { MSG_SJOIN, m_sjoin, MAXPARA, MSG_REG|MSG_OP|MSG_LOP, 0, 0, 0L}, +# else + { MSG_SJOIN, m_sjoin, MAXPARA, MSG_REG|MSG_OP, 0, 0, 0L}, +# endif +# endif +# ifdef SOPER_SCLEAN +# ifdef LOCOP_SCLEAN + { MSG_SCLEAN, m_sclean, MAXPARA, MSG_REG|MSG_OP|MSG_LOP, 0, 0, 0L}, +# else + { MSG_SCLEAN, m_sclean, MAXPARA, MSG_REG|MSG_OP, 0, 0, 0L}, +# endif +# endif +#endif { MSG_MODE, m_mode, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L}, +#ifndef CLIENT_COMPILE +# ifdef SOPER_SMODE +# ifdef LOCOP_SMODE + { MSG_SMODE, m_smode, MAXPARA, MSG_REG|MSG_OP|MSG_LOP, 0, 0, 0L}, +# else + { MSG_SMODE, m_smode, MAXPARA, MSG_REG|MSG_OP, 0, 0, 0L}, +# endif +# endif +#endif { MSG_NICK, m_nick, MAXPARA, MSG_LAG, 0, 0, 0L}, { MSG_PART, m_part, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L}, { MSG_QUIT, m_quit, MAXPARA, MSG_LAG, 0, 0, 0L}, @@ -64,6 +89,12 @@ { MSG_KILL, m_kill, MAXPARA, MSG_LAG|MSG_REG|MSG_NOU, 0, 0, 0L}, #endif #ifndef CLIENT_COMPILE +#if defined(OPER_KLINE) || defined(LOCOP_KLINE) + { MSG_KLINE, m_kline, MAXPARA, MSG_LAG|MSG_REG|MSG_OP|MSG_LOP, 0,0, 0L}, +#endif +#if defined(OPER_TKLINE) || defined(LOCOP_TKLINE) + { MSG_TKLINE, m_tkline, MAXPARA, MSG_LAG|MSG_REG|MSG_OP|MSG_LOP, 0,0, 0L}, +#endif { MSG_USER, m_user, MAXPARA, MSG_LAG|MSG_NOU, 0, 0, 0L}, { MSG_AWAY, m_away, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L}, { MSG_UMODE, m_umode, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L}, @@ -74,6 +105,13 @@ { MSG_WHOWAS, m_whowas, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L}, { MSG_LIST, m_list, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L}, { MSG_NAMES, m_names, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L}, +# ifdef SOPER_SNAMES +# ifdef LOCOP_SNAMES + { MSG_SNAMES, m_snames, MAXPARA, MSG_REG|MSG_OP|MSG_LOP, 0, 0, 0L}, +# else + { MSG_SNAMES, m_snames, MAXPARA, MSG_REG|MSG_OP, 0, 0, 0L}, +# endif +# endif { MSG_USERHOST,m_userhost, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L}, { MSG_PASS, m_pass, MAXPARA, MSG_LAG|MSG_NOU, 0, 0, 0L}, { MSG_LUSERS, m_lusers, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L}, @@ -121,6 +159,12 @@ # endif , 0, 0, 0L}, #endif +#ifdef SERVER_MAP + { MSG_MAP, m_map, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L}, +#endif +#ifdef OPER_SET + { MSG_SET, m_set, MAXPARA, MSG_LAG|MSG_REGU|MSG_OP|MSG_LOP , 0, 0, 0L}, +#endif #endif /* !CLIENT_COMPILE */ { (char *) 0, (int (*)()) 0, 0, 0, 0, 0, 0L} }; @@ -172,6 +216,71 @@ return acptr; } +aClient *find_matching_client(mask,cptr) +char *mask; +Reg aClient *cptr; +{ + aClient *acptr = cptr; + Reg char *ch; + int wild = 0; + + /* try to find exact match */ + acptr = find_client(mask,NULL); + if (!acptr) + { + aServer *asptr; + int wild = 0, dot = 0; + /* check if we should check against wilds */ + for (ch = mask; *ch; ch++) + { + if (*ch == '*' || *ch == '?') + { + wild = 1; + break; + } + if (*ch == '.') + { + dot = 1; + break; + } + } + + if (!wild && !dot) + { + return cptr; + } + (void) collapse(mask); + + /* try to match some servername against mask */ + for (asptr = svrtop; asptr; asptr = asptr->nexts) + { + if (!match(asptr->bcptr->name,mask) || + !match(mask,asptr->bcptr->name)) + { + acptr = asptr->bcptr; + break; + } + } + + /* no match, try services */ + if (!acptr) + { + aService *sp; + for (sp = svctop;sp;sp = sp->nexts) + { + if (!match(sp->bcptr->name,mask) || + !match(mask,sp->bcptr->name)) + { + acptr = sp->bcptr; + break; + } + } + } + + } + + return acptr ? acptr : cptr; +} #else /* CLIENT_COMPILE */ aClient *find_client(name, cptr) @@ -189,7 +298,7 @@ return cptr; } #endif /* CLIENT_COMPILE */ - +#ifndef CLIENT_COMPILE /* ** Find a user@host (server or user). ** @@ -208,20 +317,39 @@ *count = 0; if (user) - for (c2ptr = client; c2ptr; c2ptr = c2ptr->next) - { - if (!MyClient(c2ptr)) /* implies mine and a user */ - continue; - if ((!host || !match(host, c2ptr->user->host)) && - mycmp(user, c2ptr->user->username) == 0) - { - (*count)++; - res = c2ptr; - } - } + { + if (host) + { + anUser *auptr; + for (auptr = hash_find_hostname(host,NULL); auptr; auptr = auptr->hnext) + { + if (MyConnect(auptr->bcptr) && !mycmp(user,auptr->username)) + { + (*count)++; + res = auptr->bcptr; + } + } + } + else + { + int i; + for (i = 0; i <= highest_fd; i++) + { + if (!(c2ptr = local[i]) || !IsRegisteredUser(c2ptr)) + { + continue; + } + if (!mycmp(user,c2ptr->user->username)) + { + (*count)++; + res = c2ptr; + } + } + } + } return res; } - +#endif /* !CLIENT_COMPILE */ /* ** Find server by name. ** @@ -555,7 +683,11 @@ mptr->bytes += i; #ifndef CLIENT_COMPILE if ((mptr->flags & MSG_LAG) && - !(IsServer(cptr) || IsService(cptr))) + !(IsServer(cptr) || IsService(cptr) +#ifdef CAN_FLOOD + || CanFlood(cptr)) +#endif + ) { /* Flood control partly migrated into penalty */ if (bootopt & BOOT_PROT) cptr->since += (1 + i / 100); @@ -667,14 +799,13 @@ ** Add penalty score for sucessfully parsed command if issued by ** a LOCAL user client. */ - if ((ret > 0) && IsRegisteredUser(cptr) && (bootopt & BOOT_PROT)) + if ((ret > 0) && IsRegisteredUser(cptr) && (bootopt & BOOT_PROT) +#ifdef CAN_FLOOD + && !CanFlood(cptr) +#endif + ) { cptr->since += ret; -/* only to lurk - sendto_one(cptr, - ":%s NOTICE %s :*** Penalty INCR [%s] +%d", - me.name, cptr->name, ch, ret); -*/ } #endif return (ret != FLUSH_BUFFER) ? 2 : FLUSH_BUFFER; @@ -765,7 +896,12 @@ if (index(sender, '.') /* <- buggy, it could be a service! */ && !index(sender, '@')) /* better.. */ { - sendto_flag(SCH_LOCAL, "Squitting unknown %s brought by %s.", +#ifdef LOCAL_REJECTIONS_ONLY + sendto_flag(SCH_NOTICE, +#else + sendto_flag(SCH_LOCAL, +#endif + "Squitting unknown %s brought by %s.", sender, get_client_name(cptr, FALSE)); sendto_one(cptr, ":%s SQUIT %s :(Unknown from %s)", me.name, sender, get_client_name(cptr, FALSE)); @@ -780,7 +916,12 @@ * if we get here and sender is a service, we should probably issue * a kill in this case! -krys */ - sendto_flag(SCH_LOCAL, "Dropping unknown %s brought by %s.", +#ifdef LOCAL_REJECTIONS_ONLY + sendto_flag(SCH_NOTICE, +#else + sendto_flag(SCH_LOCAL, +#endif + "Dropping unknown %s brought by %s.", sender, get_client_name(cptr, FALSE)); } #endif diff -ru --new-file irc2.10.3p3/common/parse_ext.h irc2.10.3p3+sd7/common/parse_ext.h --- irc2.10.3p3/common/parse_ext.h Wed Sep 3 20:45:17 1997 +++ irc2.10.3p3+sd7/common/parse_ext.h Mon Feb 3 14:31:07 2003 @@ -44,6 +44,7 @@ EXTERN aClient *find_mask __P((char *name, aClient *cptr)); EXTERN aServer *find_tokserver __P((int token, aClient *cptr, aClient *c2ptr)); EXTERN aClient *find_name __P((char *name, aClient *cptr)); +EXTERN aClient *find_matching_client __P((char *mask, aClient *cptr)); #else /* CLIENT_COMPILE */ EXTERN aClient *find_client __P((char *name, aClient *cptr)); EXTERN aClient *find_server __P((char *name, aClient *cptr)); diff -ru --new-file irc2.10.3p3/common/send.c irc2.10.3p3+sd7/common/send.c --- irc2.10.3p3/common/send.c Fri Oct 19 00:43:05 2001 +++ irc2.10.3p3+sd7/common/send.c Mon Feb 3 14:31:07 2003 @@ -1391,6 +1391,13 @@ { SCH_SERVICE, "&SERVICES", NULL }, { SCH_DEBUG, "&DEBUG", NULL }, { SCH_AUTH, "&AUTH", NULL }, +#ifdef SMODE_CHAN + { SCH_SMODE, "&SMODE", NULL }, +#endif + +#ifdef CLIENTS_CHANNEL + { SCH_CLIENTS, "&CLIENTS", NULL }, +#endif }; @@ -1515,6 +1522,12 @@ ** And the rest... just count, I got 154 --Beeth */ char linebuf[1500]; +#ifdef LOG_IP + char *rip,*lip; +#ifndef INET6 + char tip[18]; +#endif +#endif /* LOG_IP */ /* ** This is a potential buffer overflow. ** I mean, when you manage to keep ircd @@ -1522,6 +1535,9 @@ */ char buf[12]; int logfile; +#ifdef LOG_IP + u_short rport,lport; +#endif /* LOG_IP */ logfile = msg ? connlog : userlog; @@ -1543,15 +1559,63 @@ (int) (duration % 60)); } +#ifdef LOG_IP + /*- + * New connection log format after looooong discussion: + * [ident@remoteip#remoteport,localip#localport] + * --Yegg, 2001-05-09 + */ + lport = cptr->acpt != NULL ? cptr->acpt->port : 0; + rport = cptr->port; + +#ifdef INET6 + lip = cptr->acpt != NULL ? inetntop(AF_INET6, (char *)&cptr->acpt->ip, + mydummy, MYDUMMY_SIZE) : ""; + rip = inetntop(AF_INET6, (char *)&cptr->ip, + mydummy2, MYDUMMY_SIZE); +#else + if (cptr->acpt != NULL) + { + lip = inetntoa((char *)&cptr->acpt->ip); + strncpyzt(tip, lip, 18); + lip = tip; + } + else + { + lip = ""; + } + rip = inetntoa((char *)&cptr->ip); +#endif + +#endif /* LOG_IP */ + /* ** Aha, cptr->firsttime is time when user connected, ** so we syslog() it anyway. I'm waving big ** "rewrite log format" flag --Beeth. */ (void)sprintf(linebuf, - "%s (%s): %s@%s [%s] %c %lu %luKb %lu %luKb\n", +#ifndef LOG_IP +#ifdef LOG_IRCNAME + "%s (%s): %s@%s [%s] [%s] %c %lu %luKb %lu %luKb\n", +#else + "%s (%s): %s@%s [%s] %c %lu %luKb %lu %luKb\n", +#endif +#else /* LOG_IP */ +#ifdef LOG_IRCNAME + "%s (%s): %s@%s [%s@%s#%u,%s#%u] [%s] %c %lu %luKb %lu %luKb\n", +#else + "%s (%s): %s@%s [%s@%s#%u,%s#%u] %c %lu %luKb %lu %luKb\n", +#endif +#endif /* LOG_IP */ myctime(cptr->firsttime), msg ? msg : buf, username, hostname, cptr->auth, +#ifdef LOG_IP + rip,rport,lip,lport, +#endif /* LOG_IP */ +#ifdef LOG_IRCNAME + cptr->info, +#endif cptr->exitc, cptr->sendM, cptr->sendK, cptr->receiveM, cptr->receiveK); diff -ru --new-file irc2.10.3p3/common/struct_def.h irc2.10.3p3+sd7/common/struct_def.h --- irc2.10.3p3/common/struct_def.h Mon May 14 15:02:08 2001 +++ irc2.10.3p3+sd7/common/struct_def.h Mon Feb 3 14:31:07 2003 @@ -40,27 +40,28 @@ #define HOSTLEN 63 /* Length of hostname. Updated to */ /* comply with RFC1123 */ -#define NICKLEN 9 /* Necessary to put 9 here instead of 10 +#define NICKLEN 20 /* Necessary to put 9 here instead of 10 ** if s_msg.c/m_nick has been corrected. ** This preserves compatibility with old ** servers --msa */ #define USERLEN 10 #define REALLEN 50 -#define TOPICLEN 80 -#define CHANNELLEN 50 -#define PASSWDLEN 20 -#define KEYLEN 23 +#define TOPICLEN 250 +#define CHANNELLEN 100 +#define PASSWDLEN 30 +#define KEYLEN 80 #define BUFSIZE 512 /* WARNING: *DONT* CHANGE THIS!!!! */ -#define MAXRECIPIENTS 20 -#define MAXBANS 30 +#define MAXRECIPIENTS 50 +#define MAXBANS 100 #define MAXBANLENGTH 1024 #define BANLEN (USERLEN + NICKLEN + HOSTLEN + 3) #define MAXPENALTY 10 #define CHIDLEN 5 /* WARNING: *DONT* CHANGE THIS!!!! */ #define READBUF_SIZE 16384 /* used in s_bsd.c *AND* s_zip.c ! */ - + +#define MAXMODEPARAMS 3 /* do _!not!_ change this */ /* * Make up some numbers which should reflect average leaf server connect * queue max size. @@ -166,6 +167,9 @@ #define FLAGS_ZIP 0x400000 /* link is zipped */ #define FLAGS_ZIPRQ 0x800000 /* zip requested */ #define FLAGS_ZIPSTART 0x1000000 /* start of zip (ignore any CRLF) */ +#ifdef SPLIT_HANDLE +#define FLAGS_EOBWAIT 0x2000000 /* waiting for EOB */ +#endif #define FLAGS_HELD 0x8000000 /* connection held and reconnect try */ #define FLAGS_OPER 0x0001 /* Operator */ @@ -174,14 +178,43 @@ #define FLAGS_INVISIBLE 0x0008 /* makes user invisible */ #define FLAGS_RESTRICTED 0x0010 /* Restricted user */ #define FLAGS_AWAY 0x0020 /* user is away */ +#define FLAGS_FORCE 0x0100 /* user can force channel modes */ + +#define FLAGS_BADBOY 0x0200 /* delay close this client */ + +#ifdef ILINE_FLAGS +#ifdef RECOVER +#define FLAGS_IMMORTAL 0x0400 /* immortal user (recover from collision) */ +#endif +#define FLAGS_EXEMPT 0x0800 /* user is exempt from k-lines */ +#ifdef CAN_FLOOD +#define FLAGS_FLOOD 0x1000 /* user can flood !bad! */ +#endif +#ifdef USE_SSL +#define FLAGS_DOT 0x2000 /* '.' in username for non-ssl */ +#endif +#endif + +#ifdef CAN_FLOOD +#define _FLAGS_FLOOD FLAGS_FLOOD +#else +#define _FLAGS_FLOOD 0 +#endif + +#ifdef RECOVER +#define _FLAGS_IMMORTAL FLAGS_IMMORTAL +#else +#define _FLAGS_IMMORTAL 0 +#endif #define SEND_UMODES (FLAGS_INVISIBLE|FLAGS_OPER|FLAGS_WALLOP|FLAGS_AWAY) -#define ALL_UMODES (SEND_UMODES|FLAGS_LOCOP|FLAGS_RESTRICTED) +#define ALL_UMODES (SEND_UMODES|FLAGS_LOCOP|FLAGS_RESTRICTED|_FLAGS_IMMORTAL|_FLAGS_FLOOD) /* * flags macros. */ #define IsOper(x) ((x)->user && (x)->user->flags & FLAGS_OPER) +#define IsForce(x) ((x)->user && (x)->user->flags & FLAGS_FORCE) #define IsLocOp(x) ((x)->user && (x)->user->flags & FLAGS_LOCOP) #define IsInvisible(x) ((x)->user->flags & FLAGS_INVISIBLE) #define IsRestricted(x) ((x)->user && \ @@ -199,6 +232,7 @@ #define CBurst(x) ((x)->flags & FLAGS_CBURST) #define SetOper(x) ((x)->user->flags |= FLAGS_OPER) +#define SetForce(x) ((x)->user->flags |= FLAGS_FORCE) #define SetLocOp(x) ((x)->user->flags |= FLAGS_LOCOP) #define SetInvisible(x) ((x)->user->flags |= FLAGS_INVISIBLE) #define SetRestricted(x) ((x)->user->flags |= FLAGS_RESTRICTED) @@ -214,6 +248,7 @@ #define NoNewLine(x) ((x)->flags & FLAGS_NONL) #define ClearOper(x) ((x)->user->flags &= ~FLAGS_OPER) +#define ClearForce(x) ((x)->user->flags &= ~FLAGS_FORCE) #define ClearInvisible(x) ((x)->user->flags &= ~FLAGS_INVISIBLE) #define ClearRestricted(x) ((x)->user->flags &= ~FLAGS_RESTRICTED) #define ClearWallops(x) ((x)->user->flags &= ~FLAGS_WALLOP) @@ -222,6 +257,20 @@ #define ClearXAuth(x) ((x)->flags &= ~FLAGS_XAUTH) #define ClearWXAuth(x) ((x)->flags &= ~FLAGS_WXAUTH) +#ifdef SPLIT_HANDLE +#define SetBurst(x) ((x)->flags |= FLAGS_EOBWAIT) +#define ClearBurst(x) ((x)->flags &= ~FLAGS_EOBWAIT) +#define IsBurst(x) ((x)->flags & FLAGS_EOBWAIT) +#endif +#ifdef ILINE_FLAGS +#define IsKlineExempt(x) ((x)->user && (x)->user->flags & FLAGS_EXEMPT) +#endif +#ifdef CAN_FLOOD +#define CanFlood(x) ((x)->user && (x)->user->flags & FLAGS_FLOOD) +#endif +#ifdef RECOVER +#define IsImmortal(x) ((x)->user && (x)->user->flags & FLAGS_IMMORTAL) +#endif /* * defined debugging levels */ @@ -264,6 +313,12 @@ char *host; char *passwd; char *name; +#ifdef SPOOF + char *spoof; +#endif +#ifdef USE_SSL + char *cert; +#endif int port; u_int pref; /* preference value */ struct CPing *ping; @@ -276,6 +331,24 @@ #define CONF_ILLEGAL 0x80000000 #define CONF_MATCH 0x40000000 + +#ifdef DELAY_ACCEPT +#define CONF_DELAY 0x20000000 +#define CONF_ACTIVE 0x10000000 +#define CONF_SERVERONLY 0x8000000 +#endif + +#ifdef ILINE_FLAGS +#define CONF_FLOOD 0x200000 +#define CONF_EXEMPT 0x400000 /* user is exempted from K: */ +#define CONF_RNODNS 0x800000 +#define CONF_DOT 0x1000000 +#define CONF_IMMORTAL 0x2000000 + +/* put all your i-line flags here! -sd */ +#define CONF_ILINE_FLAGS (CONF_FLOOD|CONF_EXEMPT|CONF_RNODNS|CONF_DOT|CONF_IMMORTAL) +#endif + #define CONF_QUARANTINED_SERVER 0x000001 #define CONF_CLIENT 0x000002 #define CONF_RCLIENT 0x000004 @@ -299,6 +372,7 @@ #define CONF_BOUNCE 0x040000 #define CONF_OTHERKILL 0x080000 #define CONF_DENY 0x100000 +#define CONF_SSL 0x200000 #define CONF_OPS (CONF_OPERATOR | CONF_LOCOP) #define CONF_SERVER_MASK (CONF_CONNECT_SERVER | CONF_NOCONNECT_SERVER |\ @@ -307,7 +381,6 @@ CONF_SERVER_MASK) #define IsIllegal(x) ((x)->status & CONF_ILLEGAL) - typedef struct { u_long pi_id; u_long pi_seq; @@ -368,6 +441,8 @@ char username[USERLEN+1]; char host[HOSTLEN+1]; char *server; + struct User *hnext; + int hashv; }; struct Server { @@ -382,6 +457,10 @@ ** from anUser (field servp), aService (field ** servp) and aClient (field serv) */ + int usercnt[3]; /* # of clients - all, invisible, opers */ +#ifdef EXTRA_STATISTICS + int usermax; /* max # of users on this server */ +#endif struct Server *nexts, *prevs, *shnext; aClient *bcptr; char by[NICKLEN+1]; @@ -389,6 +468,7 @@ time_t lastload; /* penalty like counters, see s_serv.c ** should be in the local part, but.. */ + Link *down; /* list of downlinks */ }; struct Service { @@ -445,13 +525,23 @@ char *auth; u_short port; /* and the remote port# too :-) */ struct IN_ADDR ip; /* keep real ip# too */ +#if defined(SPOOF) && defined(OPERS_WATCHING_USERS) + struct IN_ADDR real_ip; +#endif struct hostent *hostp; char sockhost[HOSTLEN+1]; /* This is the host name from the socket ** and after which the connection was ** accepted. */ char passwd[PASSWDLEN+1]; + char *reason; /* internal quit reason */ char exitc; + +#ifdef USE_SSL + SSL *ssl; /* ssl structure, if NULL, ssl not used */ + int handshake; /* in SSL_accept() ? */ + int forcessl; +#endif }; #define CLIENT_LOCAL_SIZE sizeof(aClient) @@ -531,6 +621,14 @@ u_long bytes; }; +#define SET_TYPE_INT 0 +#define SET_TYPE_STRING 1 +struct Set_Message { + char *cmd; + int *value; + char **values; +}; + #define MSG_LAG 0x0001 #define MSG_NOU 0x0002 /* Not available to users */ #define MSG_SVC 0x0004 /* Services only */ @@ -570,6 +668,10 @@ u_int hashv; /* raw hash value */ Mode mode; char topic[TOPICLEN+1]; +#ifdef TOPICWHOTIME + char topic_nuh[BANLEN+1]; + time_t topic_time; +#endif int users; /* current membership total */ Link *members; /* channel members */ Link *invites; /* outstanding invitations */ @@ -674,6 +776,16 @@ x->prev->service->servp == x->serv))) typedef struct { +#ifdef EXTRA_STATISTICS + time_t is_last_cnt_t; /* timestamp for last count */ + u_long is_last_cnt; /* last count */ + u_long is_m_users; /* maximum users connected */ + u_long is_m_serv; /* maximum servers connected */ + u_long is_m_service; /* maximum services connected */ + u_long is_m_myclnt; /* maximum local clients */ + u_long is_m_myserv; /* maximum local servers */ + u_long is_m_myservice; /* maximum local services */ +#endif u_long is_user[2]; /* users, non[0] invis and invis[1] */ u_long is_serv; /* servers */ u_long is_service; /* services */ @@ -715,8 +827,21 @@ u_int is_dbufmin; /* min number of dbuf in use */ u_int is_dbufmax; /* max number of dbuf in use */ u_int is_dbufmore; /* how many times we increased the bufferpool*/ +#ifdef DELAY_CLOSE + u_long is_delayclosed; +#endif +#ifdef SPLIT_HANDLE + u_long is_eobservers; /* # of servers which sent EOB */ +#endif } istat_t; +typedef struct { + u_int split; + u_int aconnect; /* if we want aconnect or not */ +#ifdef DELAY_ACCEPT + u_int caccept; /* enable/disable client ports */ +#endif +} iconf_t; /* String manipulation macros */ /* strncopynt --> strncpyzt to avoid confusion, sematics changed @@ -771,7 +896,22 @@ #define SCH_SERVICE 9 #define SCH_DEBUG 10 #define SCH_AUTH 11 -#define SCH_MAX 11 +#define SCH_CLIENTS 12 +#define SCH_SMODE 13 + +#ifdef CLIENTS_CHANNEL + #ifdef SMODE_CHAN + #define SCH_MAX 14 + #else + #define SCH_MAX 13 + #endif +#else + #ifdef SMODE_CHAN + #define SCH_MAX 13 + #else + #define SCH_MAX 12 + #endif +#endif /* used for async dns values */ diff -ru --new-file irc2.10.3p3/common/support.c irc2.10.3p3+sd7/common/support.c --- irc2.10.3p3/common/support.c Thu May 31 17:00:02 2001 +++ irc2.10.3p3+sd7/common/support.c Mon Feb 3 14:31:07 2003 @@ -849,7 +849,7 @@ char *make_version() { int ve, re, mi, dv, pl; - char ver[15]; + char ver[50]; sscanf(PATCHLEVEL, "%2d%2d%2d%2d%2d", &ve, &re, &mi, &dv, &pl); /* version & revision */ @@ -863,7 +863,27 @@ sprintf(ver + strlen(ver), "p%d", pl); return mystrdup(ver); } +#ifndef CLIENTCOMPILE +#ifdef SEND_ISUPPORT +/* + * Make ISUPPORT string + */ +char *make_isupport() +{ + char tisupport[200]; + char *p = tisupport; +#ifdef SERVER_MAP + strcpy(tisupport,"MAP "); + p +=4; +#endif + SPRINTF(p,"PREFIX=(ov)@+ MODES=%d CHANTYPES=#&!+ MAXCHANNELS=%d NICKLEN=%d TOPICLEN=%d KICKLEN=%d NETWORK=%s CHANMODES=beI,k,l,imnpstaqr", + MAXMODEPARAMS, MAXCHANNELSPERUSER, NICKLEN, TOPICLEN, TOPICLEN,NETWORKNAME); + + return mystrdup(tisupport); +} +#endif +#endif #ifndef HAVE_TRUNCATE /* truncate: set a file to a specified length * I don't know of any UNIX that doesn't have truncate, but CYGWIN32 beta18 diff -ru --new-file irc2.10.3p3/common/support_ext.h irc2.10.3p3+sd7/common/support_ext.h --- irc2.10.3p3/common/support_ext.h Sat Dec 9 00:15:21 2000 +++ irc2.10.3p3+sd7/common/support_ext.h Mon Feb 3 14:31:07 2003 @@ -72,6 +72,9 @@ #endif /* USE_STDARG */ EXTERN int dgets __P((int fd, char *buf, int num)); EXTERN char *make_version(); +#ifdef SEND_ISUPPORT +EXTERN char *make_isupport(); +#endif #if SOLARIS_2_3 EXTERN struct hostent *solaris_gethostbyname __P((const char *name)); #endif /* SOLARIS_2_3 */ diff -ru --new-file irc2.10.3p3/iauth/a_conf.c irc2.10.3p3+sd7/iauth/a_conf.c --- irc2.10.3p3/iauth/a_conf.c Sat Apr 7 03:51:48 2001 +++ irc2.10.3p3+sd7/iauth/a_conf.c Mon Feb 3 14:31:07 2003 @@ -26,6 +26,7 @@ #define A_CONF_C #include "a_externs.h" #undef A_CONF_C +#undef USE_DSM static aModule *Mlist[16]; @@ -86,6 +87,7 @@ Mlist[Mcnt++] = &Module_rfc931; Mlist[Mcnt++] = &Module_socks; + Mlist[Mcnt++] = &Module_webproxy; Mlist[Mcnt++] = &Module_pipe; Mlist[Mcnt++] = &Module_lhex; Mlist[Mcnt] = NULL; @@ -247,6 +249,7 @@ (*last)->hostname = NULL; (*last)->address = NULL; (*last)->timeout = timeout; + (*last)->reason = NULL; if (Mlist[i] == &Module_rfc931) ident = *last; @@ -290,6 +293,17 @@ mystrdup(buffer + 10); continue; } + if (!strncasecmp(buffer+1, "reason = ", 9)) + { + if ((*last)->reason) + conf_err(lnnb, + "Duplicate reason keyword: ignored.", + cfile); + else + (*last)->reason = + mystrdup(buffer + 10); + continue; + } if (!strncasecmp(buffer+1, "host = ", 7)) { needh = 1; diff -ru --new-file irc2.10.3p3/iauth/a_conf_def.h irc2.10.3p3+sd7/iauth/a_conf_def.h --- irc2.10.3p3/iauth/a_conf_def.h Mon Jul 5 01:09:09 1999 +++ irc2.10.3p3+sd7/iauth/a_conf_def.h Mon Feb 3 14:31:07 2003 @@ -40,6 +40,7 @@ u_char in; /* instance number */ aModule *mod; /* module */ char *opt; /* options read from file */ + char *reason; /* reject reason */ char *popt; /* options to send to ircd */ void *data; /* private data: stats, ... */ aTarget *address; diff -ru --new-file irc2.10.3p3/iauth/a_externs.h irc2.10.3p3+sd7/iauth/a_externs.h --- irc2.10.3p3/iauth/a_externs.h Mon Apr 12 22:45:04 1999 +++ irc2.10.3p3+sd7/iauth/a_externs.h Mon Feb 3 14:31:07 2003 @@ -30,5 +30,6 @@ #include "mod_rfc931_ext.h" #include "mod_socks_ext.h" +#include "mod_webproxy_ext.h" #include "mod_pipe_ext.h" #include "mod_lhex_ext.h" diff -ru --new-file irc2.10.3p3/iauth/a_log_def.h irc2.10.3p3+sd7/iauth/a_log_def.h --- irc2.10.3p3/iauth/a_log_def.h Thu Oct 18 22:51:08 2001 +++ irc2.10.3p3+sd7/iauth/a_log_def.h Mon Feb 3 14:31:07 2003 @@ -37,5 +37,7 @@ #define ALOG_DSOCKSC 0x040000 /* debug: module socks cache */ #define ALOG_DPIPE 0x080000 /* debug: module pipe */ #define ALOG_DLHEX 0x100000 /* debug: module pipe */ +#define ALOG_DWEBPROXY 0x200000 /* debug: module webproxy */ +#define ALOG_DWEBPROXYC 0x400000 /* debug: module webproxy */ -#define ALOG_DALL 0x1F3700 /* any debug flag */ +#define ALOG_DALL 0x7F3700 /* any debug flag */ diff -ru --new-file irc2.10.3p3/iauth/mod_socks.c irc2.10.3p3+sd7/iauth/mod_socks.c --- irc2.10.3p3/iauth/mod_socks.c Thu May 31 02:40:00 2001 +++ irc2.10.3p3+sd7/iauth/mod_socks.c Mon Feb 3 14:31:07 2003 @@ -62,6 +62,7 @@ struct socks_private { struct proxylog *cache; + char *reason; u_int lifetime; u_char options; /* stats */ @@ -81,13 +82,19 @@ char *strver; { struct socks_private *mydata = cldata[cl].instance->data; + char *reason = mydata->reason; +#ifdef IAUTH_VERBOSE_REJECTS + char verbose = 'K'; +#else + char verbose = 'k'; +#endif /* open proxy */ if (mydata->options & OPT_DENY) { cldata[cl].state |= A_DENY; - sendto_ircd("k %d %s %u ", cl, cldata[cl].itsip, - cldata[cl].itsport); + sendto_ircd("%c %d %s %u #socks %s", verbose, cl, cldata[cl].itsip, + cldata[cl].itsport,reason ? reason : ""); } if (mydata->options & OPT_LOG) sendto_log(ALOG_FLOG, LOG_INFO, "socks%s: open proxy: %s[%s]", @@ -525,7 +532,10 @@ sprintf(cbuf, ", Cache %d (min)", mydata->lifetime); strcat(txtbuf, cbuf); mydata->lifetime *= 60; - + if (self->reason) + { + mydata->reason = mystrdup(self->reason); + } self->popt = mystrdup(tmpbuf+1); self->data = mydata; return txtbuf+2; diff -ru --new-file irc2.10.3p3/iauth/mod_webproxy.c irc2.10.3p3+sd7/iauth/mod_webproxy.c --- irc2.10.3p3/iauth/mod_webproxy.c Thu Jan 1 02:00:00 1970 +++ irc2.10.3p3+sd7/iauth/mod_webproxy.c Mon Feb 3 14:31:07 2003 @@ -0,0 +1,596 @@ +/************************************************************************ + * IRC - Internet Relay Chat, iauth/mod_webproxy.c + * Copyright (C) 2001 Dan Merillat + * + * Original code (iauth/mod_socks.c) is + * Copyright (C) 1998 Christophe Kalt + * + * 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 char rcsid[] = +"@(#)$Id: mod_webproxy.c,v 1.25 1999/08/13 21:06:30 chopin Exp $"; +#endif + +#include "os.h" +#include "a_defines.h" +#define MOD_WEBGATE_C +#include "a_externs.h" + +/****************************** PRIVATE *************************************/ + +#define CACHETIME 30 + +struct proxylog { + struct proxylog *next; + char ip[HOSTLEN + 1]; + u_char state; /* 0 = no proxy, 1 = open proxy, 2 = closed proxy */ + time_t expire; + u_int port; +}; + +#define OPT_LOG 0x001 +#define OPT_DENY 0x002 +#define OPT_PARANOID 0x004 +#define OPT_CAREFUL 0x008 +#define OPT_V4ONLY 0x010 +#define OPT_V5ONLY 0x020 +#define OPT_PROTOCOL 0x100 + +#define PROXY_NONE 0 +#define PROXY_OPEN 1 +#define PROXY_CLOSE 2 +#define PROXY_UNEXPECTED 3 +#define PROXY_BADPROTO 4 + +struct webproxy_private { + struct proxylog *cache; + u_int lifetime; + u_char options; + char *reason; + u_int ports[128]; + u_int portcount; + /* stats */ + u_int chitc, chito, chitn, cmiss, cnow, cmax; + u_int open[128], closed, noproxy; +}; +int webproxy_start(u_int); + +/* + * webproxy_open_proxy + * + * Found an open proxy for cl: deal with it! + */ + +static void +webproxy_open_proxy(cl,port) +int cl; +u_int port; +{ + struct webproxy_private *mydata = cldata[cl].instance->data; + char *reason = mydata->reason; +#ifdef IAUTH_VERBOSE_REJECTS + char verbose = 'K'; +#else + char verbose = 'k'; +#endif + char myreason[BUFSIZE]; + if (reason) + { + if (strstr(reason,"%d")) + { + sprintf(myreason,reason,port); + } + else + { + strcpy(myreason,reason); + } + myreason[300] = '\0'; + } + /* open proxy */ + if (mydata->options & OPT_DENY) { + cldata[cl].state |= A_DENY; + sendto_ircd("%c %d %s %u %s%d %s", verbose,cl, cldata[cl].itsip, + cldata[cl].itsport,"#webproxy-",port, + reason ? myreason : ""); + } + if (mydata->options & OPT_LOG) + sendto_log(ALOG_FLOG, LOG_INFO, "webproxy: open proxy: %s[%s], port %u", + cldata[cl].host, cldata[cl].itsip, + port); +} + +/* + * webproxy_add_cache + * + * Add an entry to the cache. + */ + +static void +webproxy_add_cache(cl, state) +int cl, state; +{ + struct webproxy_private *mydata = cldata[cl].instance->data; + struct proxylog *next; + + + if (state == PROXY_OPEN) { + if (cldata[cl].mod_status < mydata->portcount) + mydata->open[cldata[cl].mod_status] += 1; + + } else if (state == PROXY_NONE) + mydata->noproxy += 1; + else + /* state == PROXY_CLOSE|PROXY_UNEXPECTED|PROXY_BADPROTO */ + mydata->closed += 1; + + if (mydata->lifetime == 0) + return; + + mydata->cnow += 1; + if (mydata->cnow > mydata->cmax) + mydata->cmax = mydata->cnow; + + next = mydata->cache; + mydata->cache = (struct proxylog *) malloc(sizeof(struct proxylog)); + mydata->cache->expire = time(NULL) + mydata->lifetime; + strcpy(mydata->cache->ip, cldata[cl].itsip); + mydata->cache->port = mydata->ports[cldata[cl].mod_status - 1]; + mydata->cache->state = state; + mydata->cache->next = next; + DebugLog( + (ALOG_DWEBPROXYC, 0, + "webproxy_add_cache(%d): new cache %s, open=%d", cl, + mydata->cache->ip, state)); +} + +/* + * webproxy_check_cache + * + * Check cache for an entry. + */ +static int +webproxy_check_cache(cl) +{ + struct webproxy_private *mydata = cldata[cl].instance->data; + struct proxylog **last, *pl; + time_t now = time(NULL); + + if (!mydata || mydata->lifetime == 0) + return 0; + + DebugLog( + (ALOG_DWEBPROXYC, 0, + "webproxy_check_cache(%d): Checking cache for %s", cl, + cldata[cl].itsip)); + + last = &(mydata->cache); + while ((pl = *last)) { + DebugLog((ALOG_DWEBPROXYC, 0, "webproxy_check_cache(%d): cache %s", + cl, pl->ip)); + if (pl->expire < now) { + DebugLog((ALOG_DWEBPROXYC, 0, + "webproxy_check_cache(%d): free %s (%d < %d)", + cl, pl->ip, pl->expire, now)); + *last = pl->next; + free(pl); + mydata->cnow -= 1; + continue; + } + if (!strcasecmp(pl->ip, cldata[cl].itsip)) { + DebugLog((ALOG_DWEBPROXYC, 0, + "webproxy_check_cache(%d): match (%u)", cl, + pl->state)); + pl->expire = now + mydata->lifetime; /* dubious */ + if (pl->state == 1) { + webproxy_open_proxy(cl,pl->port); + mydata->chito += 1; + } else if (pl->state == 0) + mydata->chitn += 1; + else + mydata->chitc += 1; + return -1; + } + last = &(pl->next); + } + mydata->cmiss += 1; + return 0; +} + +static int +webproxy_write(u_int cl) +{ + + struct webproxy_private *mydata = cldata[cl].instance->data; + static u_char query[64]; /* big enough to hold all queries */ + static int query_len; /* lenght of socks4 query */ + static int wlen; + + + + query_len=snprintf(query, 64, "CONNECT %s:%d HTTP/1.0\n\n", + cldata[cl].ourip, cldata[cl].ourport); + + DebugLog((ALOG_DWEBPROXY, 0, "webproxy_write(%d): Checking %s:%u", + cl, cldata[cl].itsip, mydata->ports[cldata[cl].mod_status])); + if ((wlen=write(cldata[cl].wfd, query, query_len)) != query_len) { + /* most likely the connection failed */ + DebugLog( + (ALOG_DWEBPROXY, 0, + "webproxy_write(%d): write() failed: %d %s", cl, + wlen, strerror(errno))); + close(cldata[cl].wfd); + cldata[cl].rfd = cldata[cl].wfd = 0; + cldata[cl].buflen=0; + if (++cldata[cl].mod_status < mydata->portcount) + return webproxy_start(cl); + else + return 1; + } + cldata[cl].rfd = cldata[cl].wfd; + cldata[cl].wfd = 0; + return 0; +} + +static int +webproxy_read(u_int cl) +{ + /* Looking for "Connection established" + * HTTP/1.0 200 Connection established" */ + + struct webproxy_private *mydata = cldata[cl].instance->data; + int again = 1; + u_char state = PROXY_CLOSE; + char * lookfor="HTTP/1.0 200"; + u_int looklen=strlen(lookfor); + + /* data's in from the other end */ + if (cldata[cl].buflen < looklen) + return 0; + + /* zero it out so the debug log is sane */ + cldata[cl].inbuffer[cldata[cl].buflen]=0; + + /* got all we need */ + DebugLog( + (ALOG_DWEBPROXY, 0, "webproxy_read(%d): %d Got [%s]", + cl, mydata->ports[cldata[cl].mod_status], cldata[cl].inbuffer)); + + + if (!strncmp(cldata[cl].inbuffer, lookfor, looklen) || + !strncmp(cldata[cl].inbuffer, "HTTP/1.1 200",looklen) + ) { /* got it! */ + DebugLog((ALOG_DWEBPROXY, 0, "webproxy_read(%d): Open proxy on %s:%u", + cl, cldata[cl].itsip, mydata->ports[cldata[cl].mod_status])); + state = PROXY_OPEN; + webproxy_open_proxy(cl,mydata->ports[cldata[cl].mod_status]); + again = 0; + } + + cldata[cl].mod_status++; + close(cldata[cl].rfd); + cldata[cl].rfd = 0; + + if (again && cldata[cl].mod_status < mydata->portcount) { + cldata[cl].buflen = 0; + return webproxy_start(cl); + } + else { + webproxy_add_cache(cl, state); + return -1; + } + return 0; +} + +/******************************** PUBLIC ************************************/ + +/* + * webproxy_init + * + * This procedure is called when a particular module is loaded. + * Returns NULL if everything went fine, + * an error message otherwise. + */ + +char * +webproxy_init(AnInstance * self) +{ + struct webproxy_private *mydata; + char tmpbuf[80], cbuf[32]; + static char txtbuf[80]; + u_int portcount = 0; + + tmpbuf[0] = txtbuf[0] = '\0'; + + mydata = + (struct webproxy_private *) + malloc(sizeof(struct webproxy_private)); + bzero((char *) mydata, sizeof(struct webproxy_private)); + mydata->cache = NULL; + mydata->lifetime = CACHETIME; + if (!self->opt) + { + /* using default config: + ** log,deny,ports=3128;8080 + */ + mydata->options=OPT_DENY|OPT_LOG; + mydata->ports[portcount++] = 3128; + mydata->ports[portcount++] = 8080; + mydata->portcount=portcount; + strcat(tmpbuf, ",log"); + strcat(txtbuf, ", Log"); + strcat(tmpbuf, ",reject"); + strcat(txtbuf, ", Reject"); + strcat(tmpbuf, ",ports=3128;8080"); + strcat(txtbuf, ", Ports=3128;8080"); + + } + else + { + + char *ch = NULL, *portsp = NULL; + + if ((portsp=strstr(self->opt, "ports"))) + + { + char xbuf[128]; + char *c; + size_t slen; + bzero(xbuf,sizeof(xbuf)); + ch = strchr(portsp, '='); + if (!ch) + { + mydata->ports[portcount++] = 3128; + mydata->ports[portcount++] = 8080; + mydata->portcount=portcount; + } + else + { + c=index(ch, ','); + if (!c) + c=ch+strlen(ch); + /* now ch is at = and c is at the end of the ports line */ + ch++; + slen = (size_t) c - (size_t) ch; + if (slen > 30) + { + slen = 30; + } + memcpy(xbuf, ch, slen); + strcat(tmpbuf,",ports="); + + strcat(tmpbuf,xbuf); + ch=xbuf; + while((c=index(ch, ';'))) { + *c=0; + mydata->ports[portcount++]=atoi(ch); + ch=c+1; + } + mydata->ports[portcount++]=atoi(ch); + mydata->portcount=portcount; + } + } + if (strstr(self->opt, "log")) { + mydata->options |= OPT_LOG; + strcat(tmpbuf, ",log"); + strcat(txtbuf, ", Log"); + } + if (strstr(self->opt, "reject")) { + mydata->options |= OPT_DENY; + strcat(tmpbuf, ",reject"); + strcat(txtbuf, ", Reject"); + } + if (strstr(self->opt, "cache")) { + char *ch = index(self->opt, '='); + + if (ch) + mydata->lifetime = atoi(ch + 1); + } + } + sprintf(cbuf, ",cache=%d", mydata->lifetime); + strcat(tmpbuf, cbuf); + sprintf(cbuf, ", Cache %d (min)", mydata->lifetime); + strcat(txtbuf, cbuf); + mydata->lifetime *= 60; + if (self->reason) + { + mydata->reason = mystrdup(self->reason); + } + self->popt = mystrdup(tmpbuf + 1); + self->data = mydata; + return txtbuf + 2; +} + +/* + * webproxy_release + * + * This procedure is called when a particular module is unloaded. + */ +void +webproxy_release(self) +AnInstance *self; +{ + struct webproxy_private *mydata = self->data; + free(mydata); + free(self->popt); +} + +/* + * webproxy_stats + * + * This procedure is called regularly to update statistics sent to ircd. + */ +void +webproxy_stats(self) +AnInstance *self; +{ + struct webproxy_private *mydata = self->data; + char mybuf[256]; + int len; + int i; + + len=snprintf(mybuf, 256, "S webproxy port:open"); + for (i=0;iportcount;i++) + len+=snprintf(mybuf+len, 256-len, " %u:%u", + mydata->ports[i], mydata->open[i]); + + len+=snprintf(mybuf+len, 256-len, " closed %u noproxy %u", + mydata->closed, mydata->noproxy); + + sendto_ircd(mybuf); + + sendto_ircd + ("S webproxy cache open %u closed %u noproxy %u miss %u (%u <= %u)", + mydata->chito, mydata->chitc, mydata->chitn, mydata->cmiss, + mydata->cnow, mydata->cmax); +} + +/* + * webproxy_start + * + * This procedure is called to start the socks check procedure. + * Returns 0 if everything went fine, + * -1 otherwise (nothing to be done, or failure) + * + * It is responsible for sending error messages where appropriate. + * In case of failure, it's responsible for cleaning up (e.g. webproxy_clean + * will NOT be called) + */ +int +webproxy_start(cl) +u_int cl; +{ + + struct webproxy_private *mydata = cldata[cl].instance->data; + char *error; + int fd; + + if (cldata[cl].state & A_DENY) { + /* no point of doing anything */ + DebugLog((ALOG_DWEBPROXY, 0, + "webproxy_start(%d): A_DENY alredy set ", cl)); + return -1; + } + if (cldata[cl].mod_status == 0) + if (webproxy_check_cache(cl)) + return -1; + + if (strchr(cldata[cl].itsip,':')) + return -1; + + while (cldata[cl].mod_status < mydata->portcount) { + DebugLog( + (ALOG_DWEBPROXY, 0, "webproxy_start(%d): Connecting to %s:%u", + cl, cldata[cl].itsip, mydata->ports[cldata[cl].mod_status])); + fd = tcp_connect(cldata[cl].ourip, cldata[cl].itsip, + mydata->ports[cldata[cl].mod_status], + &error); + if (fd > 0) { + /*so that webproxy_work() is called when connected */ + cldata[cl].wfd = fd; + return 0; + } + DebugLog((ALOG_DWEBPROXY, 0, + "webproxy_start(%d): tcp_connect() reported %s", cl, + error)); + cldata[cl].mod_status++; + continue; + + } + + return -1; +} + +/* + * webproxy_work + * + * This procedure is called whenever there's new data in the buffer. + * Returns 0 if everything went fine, and there is more work to be done, + * Returns -1 if the module has finished its work (and cleaned up). + * + * It is responsible for sending error messages where appropriate. + */ +int +webproxy_work(cl) +u_int cl; +{ + struct webproxy_private *mydata = cldata[cl].instance->data; + + if (!mydata) + return -1; + + DebugLog( + (ALOG_DWEBPROXY, 0, "webproxy_work(%d): %d %d %d buflen=%d", + cl, mydata->ports[cldata[cl].mod_status], + cldata[cl].rfd, cldata[cl].wfd, + cldata[cl].buflen)); + + if (cldata[cl].wfd > 0) + /* + ** We haven't sent the query yet, the connection was just + ** established. + */ + return webproxy_write(cl); + else + return webproxy_read(cl); +} + +/* + * webproxy_clean + * + * This procedure is called whenever the module should interrupt its work. + * It is responsible for cleaning up any allocated data, and in particular + * closing file descriptors. + */ +void +webproxy_clean(cl) +u_int cl; +{ + DebugLog((ALOG_DWEBPROXY, 0, "webproxy_clean(%d): cleaning up", cl)); + /* + ** only one of rfd and wfd may be set at the same time, + ** in any case, they would be the same fd, so only close() once + */ + if (cldata[cl].rfd) + close(cldata[cl].rfd); + else if (cldata[cl].wfd) + close(cldata[cl].wfd); + cldata[cl].rfd = cldata[cl].wfd = 0; +} + +/* + * webproxy_timeout + * + * This procedure is called whenever the timeout set by the module is + * reached. + * + * Returns 0 if things are okay, -1 if check was aborted. + */ +int +webproxy_timeout(cl) +u_int cl; +{ + DebugLog( + (ALOG_DWEBPROXY, 0, + "webproxy_timeout(%d): calling webproxy_clean ", cl)); + webproxy_clean(cl); + return -1; +} + +aModule Module_webproxy = +{"webproxy", webproxy_init, webproxy_release, webproxy_stats, + webproxy_start, webproxy_work, webproxy_timeout, webproxy_clean +}; diff -ru --new-file irc2.10.3p3/iauth/mod_webproxy_ext.h irc2.10.3p3+sd7/iauth/mod_webproxy_ext.h --- irc2.10.3p3/iauth/mod_webproxy_ext.h Thu Jan 1 02:00:00 1970 +++ irc2.10.3p3+sd7/iauth/mod_webproxy_ext.h Mon Feb 3 14:31:07 2003 @@ -0,0 +1,3 @@ +#ifndef MOD_WEBPROXY_C +extern aModule Module_webproxy; +#endif /* MOD_WEBPROXY_C */ diff -ru --new-file irc2.10.3p3/ircd/channel.c irc2.10.3p3+sd7/ircd/channel.c --- irc2.10.3p3/ircd/channel.c Sat Jul 7 17:29:33 2001 +++ irc2.10.3p3+sd7/ircd/channel.c Mon Feb 3 14:31:07 2003 @@ -55,9 +55,14 @@ static int add_modeid __P((int, aClient *, aChannel *, char *)); static int del_modeid __P((int, aChannel *, char *)); static Link *match_modeid __P((int, aClient *, aChannel *)); +static void send_names_one __P((aClient *,aClient *,char *,aChannel *,int)); static char *PartFmt = ":%s PART %s :%s"; +#ifdef SOPERCHAN +static aChannel *soperchan = NULL; +#endif + /* * some buffers for rebuilding channel/nick lists with ,'s */ @@ -611,6 +616,20 @@ add_user_to_channel(chptr, mp, CHFL_CHANOP); chptr->mode.mode = smode|MODE_SECRET; +#ifdef CLIENTS_CHANNEL + chptr = get_channel(mp, "&CLIENTS", CREATE); + strcpy(chptr->topic,"SERVER MESSAGES: client activities [various]"); + add_user_to_channel(chptr, mp, CHFL_CHANOP); + chptr->mode.mode = smode|MODE_SECRET; +#endif + +#ifdef SMODE_CHAN + chptr = get_channel(mp, "&SMODE", CREATE); + strcpy(chptr->topic, "SERVER MESSAGES: server modes received"); + add_user_to_channel(chptr, mp, CHFL_CHANOP); + chptr->mode.mode = smode | MODE_SECRET; +#endif + setup_svchans(); } @@ -854,6 +873,88 @@ return; } +#ifdef SOPER_SMODE + +/* + * m_smode + * parv[0] - sender + * parv[1] - target (channel only) + * parv[2] - modes + * ... - args + */ + +int m_smode(cptr, sptr, parc, parv) +aClient *cptr, *sptr; +int parc; +char *parv[]; +{ + aChannel *chptr = NULL; + int penalty = 0; + + if (MyClient(sptr)) + { + if (parc < 3) + { + sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS, parv[0]), + "SMODE"); + return 0; + } + + clean_channelname(parv[1]); + + chptr = get_channel(sptr, parv[1], 0); + + if (!chptr) + { + sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL, parv[0]), + parv[1]); + return 0; + } + + if (!UseModes(parv[1])) + { + sendto_one(sptr, err_str(ERR_NOCHANMODES, parv[0]), + parv[1]); + return 0; + } + + SetForce(sptr); + + if (!set_mode(cptr, sptr, chptr, &penalty, parc - 2, + parv + 2, modebuf, parabuf)) + return 0; + + ClearForce(sptr); + +#ifdef SOPERCHAN + if (soperchan = get_channel(&me, SOPERCHAN, 0)) + sendto_channel_butone(&me, &me, soperchan, + ":%s NOTICE %s :%s requested SMODE %s %s %s", + ME, SOPERCHAN, parv[0], parv[1], modebuf, parabuf); +#endif + +#ifdef SMODE_CHAN + sendto_flag(SCH_SMODE, "Servermode: %s MODE %s %s %s", + ME, parv[1], modebuf, parabuf); +#endif + + if (modebuf[1] == 'e' || modebuf[1] == 'I') + sendto_match_servs_v(chptr, &me, SV_NMODE, + ":%s MODE %s %s %s", ME, parv[1], modebuf, + parabuf); + else + sendto_match_servs(chptr, &me, ":%s MODE %s %s %s", + ME, parv[1], modebuf, parabuf); + + sendto_channel_butserv(chptr, &me, ":%s MODE %s %s %s", ME, + parv[1], modebuf, parabuf); + } + + return 0; +} + +#endif + /* * m_mode * parv[0] - sender @@ -930,6 +1031,12 @@ sendto_one(sptr, err_str(num, parv[0]), name); continue; } +#ifdef SMODE_CHAN + if (IsServer(sptr)) + sendto_flag(SCH_SMODE, + "Servermode: %s MODE %s %s %s", + parv[0], name, modebuf, parabuf); +#endif if (strlen(modebuf) > (size_t)1) { /* got new mode to pass on */ if (modebuf[1] == 'e' || modebuf[1] == 'I') @@ -1004,6 +1111,7 @@ aClient *who; Mode *mode, oldm; Link *plp = NULL; + char buf[KEYLEN+1]; int compat = -1; /* to prevent mixing old/new modes */ *mbuf = *pbuf = '\0'; @@ -1012,7 +1120,7 @@ mode = &(chptr->mode); bcopy((char *)mode, (char *)&oldm, sizeof(Mode)); - ischop = IsServer(sptr) || is_chan_op(sptr, chptr); + ischop = IsServer(sptr) || is_chan_op(sptr, chptr) || IsForce(sptr); new = mode->mode; while (curr && *curr && count >= 0) @@ -1060,7 +1168,7 @@ } else /* not IsMember() */ { - if (!IsServer(sptr)) + if (!IsServer(sptr) && !IsForce(sptr)) { sendto_one(sptr, err_str(ERR_NOTONCHANNEL, sptr->name), chptr->chname); @@ -1099,7 +1207,7 @@ if (MyClient(sptr) || opcnt >= MAXMODEPARAMS + 1) #endif break; - if (!IsServer(sptr) && !IsMember(sptr, chptr)) + if (!IsServer(sptr) && !IsMember(sptr, chptr) && !IsForce(sptr)) { sendto_one(sptr, err_str(ERR_NOTONCHANNEL, sptr->name), @@ -1120,7 +1228,8 @@ parv[0], chptr->chname); break; } - if (who == cptr && whatt == MODE_ADD && *curr == 'o') + if (who == cptr && whatt == MODE_ADD && *curr == 'o' + && !IsForce(cptr)) break; if (whatt == MODE_ADD) @@ -1166,8 +1275,17 @@ break; case 'k': *penalty += 1; - if (--parc <= 0) - break; + if (--parc <= 0) { /* a channel key query --fiction */ + *(curr+1) = '\0'; /* Stop MODE # bb.. */ + if ((*chptr->mode.key) && IsMember(sptr, chptr)) { + strncpy(buf, chptr->mode.key, KEYLEN); + } + else { *buf = '\0'; }; + + sendto_one(sptr, rpl_str(RPL_CHANNELMODEIS, sptr->name), + chptr->chname, (*chptr->mode.key) ? "+k" : "+", buf); + break; + } parv++; /* check now so we eat the parameter if present */ if (keychange) @@ -1366,7 +1484,33 @@ * limit 'l' to only *1* change per mode command but * eat up others. */ - if (limitset || !ischop) + + /* channel limit query ("mode -l" is an exception to also unset limit + * without extra parameter). To not break stuff. --fiction + */ + + if ((parc-1 <= 0) && (whatt != MODE_DEL)) { + *(curr+1) = '\0'; /* Stop MODE # bb.. */ + if ((chptr->mode.limit) && IsMember(sptr, chptr)) { + SPRINTF(buf, "%d", chptr->mode.limit); + } + else { *buf = '\0'; }; + + sendto_one(sptr, rpl_str(RPL_CHANNELMODEIS, sptr->name), + chptr->chname, (chptr->mode.limit) ? "+l" : "+" , buf); + break; + } + + /* just pretend that there was a mode change to be able to + * return an error later --fiction + */ + + if (!ischop) { + count++; + break; + } + + if (limitset) { if (whatt == MODE_ADD && --parc > 0) parv++; @@ -1398,9 +1542,14 @@ *penalty += 2; break; } - sendto_one(cptr, err_str(ERR_NEEDMOREPARAMS, - cptr->name), "MODE +l"); - break; +/* sendto_one(cptr, err_str(ERR_NEEDMOREPARAMS, + cptr->name), "MODE +l"); + break; + +Obosleted by new syntax - "mode +l" or just +"mode l" gives current limit --fiction +*/ + case 'i' : /* falls through for default case */ if (whatt == MODE_DEL && ischop) while ((lp = chptr->invites)) @@ -1452,9 +1601,13 @@ if (whatt == MODE_ADD) { if (*ip == MODE_PRIVATE) + { new &= ~MODE_SECRET; + } else if (*ip == MODE_SECRET) + { new &= ~MODE_PRIVATE; + } new |= *ip; } else @@ -1469,6 +1622,7 @@ break; } curr++; + /* * Make sure modes strings such as "+m +t +p +i" are parsed * fully. @@ -1761,6 +1915,12 @@ else if (lp == NULL) return (ERR_BANNEDFROMCHAN); +#ifdef CLIENTS_CHANNEL + if (chptr->chname[0]=='&') { + if (!strcmp(chptr->chname,"&CLIENTS") && !IsAnOper(sptr)) + return (ERR_INVITEONLYCHAN); + } +#endif if ((chptr->mode.mode & MODE_INVITEONLY) && !match_modeid(CHFL_INVITE, sptr, chptr) && (lp == NULL)) @@ -1773,6 +1933,20 @@ (lp == NULL)) return (ERR_CHANNELISFULL); +#ifdef SMODE_CHAN + if (chptr->chname[0] == '&') + { + if (!strcmp(chptr->chname, "&SMODE") && +#ifdef LOCOP_SMODE_CHAN + !IsAnOper(sptr) +#else + !IsOper(sptr) +#endif + ) + return (ERR_INVITEONLYCHAN); + } +#endif + if (banned) sendto_channel_butone(&me, &me, chptr, ":%s NOTICE %s :%s carries an invitation (overriding ban on %s).", @@ -1986,6 +2160,76 @@ } } +#ifdef SOPER_SJOIN + +/* + * m_sjoin + * parv[0] - sender + * parv[1] - channel + */ + +int m_sjoin(cptr, sptr, parc, parv) +aClient *cptr, *sptr; +int parc; +char *parv[]; +{ + aChannel *chptr = NULL; + int penalty = 0; + char *p; + + if (MyClient(sptr)) + { + if (parc < 2) + { + sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS, parv[0]), + "SJOIN"); + return 0; + } + + clean_channelname(p = parv[1]); + + chptr = get_channel(sptr, parv[1], 0); + + if (!chptr) + { + sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL, parv[0]), + parv[1]); + return 0; + } + + if (check_channelmask(sptr, cptr, parv[1]) == -1) + return 0; + + if (IsMember(sptr, chptr)) + return 0; + +#ifdef SOPERCHAN + if (soperchan = get_channel(&me, SOPERCHAN, 0)) + sendto_channel_butone(&me, &me, soperchan, + ":%s NOTICE %s :%s requested SJOIN %s", + ME, SOPERCHAN, parv[0], parv[1]); +#endif + + add_user_to_channel(chptr, sptr, 0); + + if (parv[1][1] == '!') + sendto_match_servs_v(chptr, cptr, SV_NCHAN, + ":%s JOIN %s", parv[0], parv[1]); + else + sendto_match_servs(chptr, cptr, ":%s JOIN %s", + parv[0], parv[1]); + + sendto_channel_butserv(chptr, cptr, ":%s JOIN %s", parv[0], + parv[1]); + + m_names(cptr, sptr, 2, parv); + } + + return 0; +} + +#endif + /* ** m_join ** parv[0] = sender prefix @@ -2226,11 +2470,32 @@ ** channel so make them (rightfully) the Channel ** Operator. */ + /* do not make them Channel Operator if the server seems + ** to be splitted (i.e. if total server count is less + ** than a given number and channel count is less + ** than another given number or user count is + ** less than a third number. (francesco) + */ flags = 0; chop[0] = '\0'; - if (MyConnect(sptr) && UseModes(name) && - (!IsRestricted(sptr) || (*name == '&')) && !chptr->users && - !(chptr->history && *chptr->chname == '!')) +#ifdef SPLIT_HANDLE + if (MyConnect(sptr) && UseModes(name) && + ((*name != '#') || !iconf.split) && +#else + if ( + MyConnect(sptr) && + UseModes(name) && +#endif + ( + !IsRestricted(sptr) || + (*name == '&') + ) && + !chptr->users && + !( + chptr->history + && *chptr->chname == '!' + ) + ) { if (*name == '!') strcpy(chop, "\007O"); @@ -2269,11 +2534,18 @@ { /* no need if user is creating the channel */ if (chptr->users != 1) + { sendto_channel_butserv(chptr, sptr, ":%s MODE %s +%s %s %s", cptr->name, name, s, parv[0], *(s+1)=='v'?parv[0]:""); +#ifdef SMODE_CHAN + sendto_flag(SCH_SMODE, + "Servermode: %s JOIN %s (with mode +%s)", + parv[0], name, s); +#endif + } *--s = '\007'; } /* @@ -2287,10 +2559,20 @@ { del_invite(sptr, chptr); if (chptr->topic[0] != '\0') + { sendto_one(sptr, rpl_str(RPL_TOPIC, parv[0]), name, chptr->topic); +#ifdef TOPICWHOTIME + if (chptr->topic_time>0) + { + sendto_one(sptr, rpl_str(RPL_TOPICWHOTIME, parv[0]), + name, IsAnonymous(chptr) ? "Anonymous!Anonymous@Anomyous" : chptr->topic_nuh, + chptr->topic_time); + } +#endif + } parv[1] = name; - (void)m_names(cptr, sptr, 2, parv); + send_names_one(cptr,sptr,parv[0],chptr,1); if (IsAnonymous(chptr) && !IsQuiet(chptr)) { sendto_one(sptr, ":%s NOTICE %s :Channel %s has the anonymous flag set.", ME, chptr->chname, chptr->chname); @@ -2697,31 +2979,9 @@ sendto_serv_butone(cptr, ":%s KICK %s %s :%s", parv[0], name, nickbuf, comment); } /* loop on parv[1] */ - return penalty; } -int count_channels(sptr) -aClient *sptr; -{ -Reg aChannel *chptr; - Reg int count = 0; - - for (chptr = channel; chptr; chptr = chptr->nextch) - { - if (chptr->users) /* don't count channels in history */ -#ifdef SHOW_INVISIBLE_LUSERS - if (SecretChannel(chptr)) - { - if (IsAnOper(sptr)) - count++; - } - else -#endif - count++; - } - return (count); -} /* ** m_topic @@ -2781,14 +3041,28 @@ if (chptr->topic[0] == '\0') sendto_one(sptr, rpl_str(RPL_NOTOPIC, parv[0]), chptr->chname); - else + else { sendto_one(sptr, rpl_str(RPL_TOPIC, parv[0]), chptr->chname, chptr->topic); +#ifdef TOPICWHOTIME + sendto_one(sptr, rpl_str(RPL_TOPICWHOTIME, parv[0]), + chptr->chname, IsAnonymous(chptr) ? "Anonymous!anonymous@anonymous" : chptr->topic_nuh, + chptr->topic_time); +#endif + } } else if ((chptr->mode.mode & MODE_TOPICLIMIT) == 0 || is_chan_op(sptr, chptr)) { /* setting a topic */ strncpyzt(chptr->topic, topic, sizeof(chptr->topic)); +#ifdef TOPICWHOTIME + strcpy(chptr->topic_nuh, sptr->name); + strcat(chptr->topic_nuh, "!"); + strcat(chptr->topic_nuh, sptr->user->username); + strcat(chptr->topic_nuh, "@"); + strcat(chptr->topic_nuh, sptr->user->host); + chptr->topic_time = timeofday; +#endif sendto_match_servs(chptr, cptr,":%s TOPIC %s :%s", parv[0], chptr->chname, chptr->topic); @@ -2900,7 +3174,6 @@ return 2; } - /* ** m_list ** parv[0] = sender prefix @@ -2917,22 +3190,53 @@ if (parc > 2 && hunt_server(cptr, sptr, ":%s LIST %s %s", 2, parc, parv)) - return 10; + return MAXPENALTY; + if (BadPtr(parv[1])) + { + + Reg Link *lp; + if (!sptr->user) + { + sendto_one(sptr, rpl_str(RPL_LISTEND, parv[0])); + return 2; + } + +#ifdef LIST_ALIS_NOTE + if (MyConnect(sptr)) + { + sendto_one(sptr,":%s NOTICE %s :%s",ME,parv[0],LIST_ALIS_NOTE); + } +#endif + + /* First, show all +s/+p user is on */ + for (lp = sptr->user->channel; lp; lp = lp->next) + { + chptr = lp->value.chptr; + if (SecretChannel(chptr) || HiddenChannel(chptr)) + { + sendto_one(sptr, rpl_str(RPL_LIST, parv[0]), + chptr->chname,chptr->users, + chptr->topic); + } + } + + /* Second, show all visible channels + * +p channels users is not on, are not reported anymore - jv + */ for (chptr = channel; chptr; chptr = chptr->nextch) - { - if (!sptr->user || - !chptr->users || /* empty locked channel */ - (SecretChannel(chptr) && !IsMember(sptr, chptr))) + { + if (!chptr->users || /* empty locked channel */ + SecretChannel(chptr) || HiddenChannel(chptr)) continue; - name = ShowChannel(sptr, chptr) ? chptr->chname : NULL; - rlen += sendto_one(sptr, rpl_str(RPL_LIST, parv[0]), - name ? name : "*", chptr->users, - name ? chptr->topic : ""); - if (!MyConnect(sptr) && rlen > CHREPLLEN) - break; - } - else { + + sendto_one(sptr, rpl_str(RPL_LIST, parv[0]), + chptr->chname, chptr->users, + chptr->topic); + } + } + else + { parv[1] = canonize(parv[1]); for (; (name = strtoken(&p, parv[1], ",")); parv[1] = NULL) { @@ -2974,9 +3278,138 @@ return 2; } +/* + * send_names_one - send NAMES for one specific channel + * sends RPL_ENDOFNAMES when sendeon > 0 + */ +static void send_names_one(cptr,sptr,to,chptr,sendeon) +aClient *cptr,*sptr; +char *to; +aChannel *chptr; +int sendeon; +{ + Reg Link *lp; + Reg aClient *acptr; + char *pbuf = buf; + int pxlen,ismember,nlen,maxlen,showusers = 1, sent = 0; + + if (!chptr->users) /* channel in ND */ + { + showusers = 0; + } + else + { + ismember = (lp = find_channel_link(sptr->user->channel,chptr)) ? 1 : 0; + } + if (SecretChannel(chptr)) + { + if (!ismember) + { + showusers = 0; + } + else + { + *pbuf++ = '@'; + } + } + else if (HiddenChannel(chptr)) + { + *pbuf++ = '*'; + } + else + { + *pbuf++ = '='; + } + + if (showusers) + { + *pbuf++ = ' '; + pxlen = strlen(chptr->chname); + memcpy(pbuf,chptr->chname,pxlen); + pbuf += pxlen; + *pbuf++ = ' '; + *pbuf++ = ':'; + *pbuf = 0; + pxlen += 4; + if (IsAnonymous(chptr)) + { + if (ismember) + { + if (lp->flags & CHFL_CHANOP) + { + *pbuf++ = '@'; + } + else if (lp->flags & CHFL_VOICE) + { + *pbuf++ = '+'; + } + strcpy(pbuf,to); + } + sendto_one(sptr, rpl_str(RPL_NAMREPLY, to), buf); + } + else + { + /* server names + : : + spaces + "353" + nick length +\r\n + space for last + * entry. + */ + maxlen = BUFSIZE - 2 - 1 - strlen(ME) - 5 - strlen(to) - pxlen - NICKLEN - 2; + + for (lp = chptr->members;lp;lp=lp->next) + { + acptr = lp->value.cptr; + if (!ismember && IsInvisible(acptr)) + { + continue; + } + if (lp->flags & CHFL_CHANOP) + { + *pbuf++ = '@'; + } + else if (lp->flags & CHFL_VOICE) + { + *pbuf++ = '+'; + } + nlen = strlen(acptr->name); + /* This check is needed for server channels + * when someone removes +a mode from them. + * (server is member of such channel). + */ + if (nlen > NICKLEN) + { + nlen = NICKLEN; + } + memcpy(pbuf,acptr->name,nlen); + pbuf +=nlen; + *pbuf++ = ' '; + sent = 0; + if (((size_t) pbuf - (size_t) buf) > maxlen) + { + *pbuf = '\0'; + sendto_one(sptr, rpl_str(RPL_NAMREPLY, to), buf); + pbuf = buf + pxlen; + pbuf[0] = '\0'; + sent = 1; + } + } + if (!sent) + { + *pbuf = '\0'; + sendto_one(sptr, rpl_str(RPL_NAMREPLY, to), buf); + } + } + } + if (sendeon) + { + sendto_one(sptr, rpl_str(RPL_ENDOFNAMES, to), chptr->chname); + } + return; + +} + /************************************************************************ * m_names() - Added by Jto 27 Apr 1989 + * Rewritten by jv 27 Apr 2001 ************************************************************************/ /* @@ -2988,186 +3421,245 @@ aClient *cptr, *sptr; int parc; char *parv[]; +{ + Reg aChannel *chptr; + Reg aClient *acptr; + Reg Link *lp; + int maxlen ,pxlen,nlen,cansend = 0, sent = 1; + char *para = parc > 1 ? parv[1] : NULL,*name, *p = NULL, *pbuf = buf; + + if (parc > 2 && + hunt_server(cptr, sptr, ":%s NAMES %s %s", 2, parc, parv)) + { + return MAXPENALTY; + } + + if (!BadPtr(para)) + { + for (; (name = strtoken(&p,parv[1], ",")); parv[1] = NULL) + { + clean_channelname(name); + if BadPtr(name) + { + continue; + } + chptr = find_channel(name, NULL); + if (chptr) + { + send_names_one(cptr,sptr,parv[0],chptr,1); + } + else + { + sendto_one(sptr, rpl_str(RPL_ENDOFNAMES, parv[0]), name); + } + sent++; + if (!MyConnect(sptr) || sent > MAXPENALTY / 3) + { + break; + } + } + return sent ? 2 * sent : 2; + } + /* Client wants all nicks/channels which is seriously cpu intensive + * Allowed for local clients only. + * First, list all secret channels user is on + */ + for (lp = sptr->user->channel; lp; lp = lp->next) + { + chptr = lp->value.chptr; + if (SecretChannel(chptr)) + { + send_names_one(cptr,sptr,parv[0],chptr,0); + } + } + + /* Second, list all non-secret channels */ + for (chptr = channel; chptr; chptr = chptr->nextch) + { + if (!chptr->users || /* channel in CD */ + SecretChannel(chptr)) + { + continue; + } + send_names_one(cptr,sptr,parv[0],chptr,0); + } + /* Third, list all remaining users + * ie, those which aren't on any channel, or are at Anonymous one + */ + strcpy(pbuf,"* * :"); + pxlen = 5; + pbuf += pxlen; + maxlen = BUFSIZE - 2 - 1 - strlen(ME) - 5 - strlen(parv[0]) - 5 - NICKLEN - 2; + for (acptr = client; acptr ;acptr = acptr->next) + { + if (!IsPerson(acptr) || IsInvisible(acptr)) + { + continue; + } + + lp = acptr->user->channel; + cansend = 1; + while (lp) + { + chptr = lp->value.chptr; + if (PubChannel(chptr) || SecretChannel(chptr) || IsMember(sptr,chptr)) + { /* already shown */ + cansend = 0; + break; + } + lp = lp->next; + } + if (!cansend) + { + continue; + } + nlen = strlen(acptr->name); + if (nlen > NICKLEN) + { + nlen = NICKLEN; + } + + memcpy(pbuf, acptr->name, nlen); + pbuf += nlen; + *pbuf++ = ' '; + sent = 0; + if ((size_t) pbuf - (size_t) buf > maxlen) + { + *pbuf = '\0'; + sendto_one(sptr, rpl_str(RPL_NAMREPLY, parv[0]), buf,0); + sent = 1; + pbuf = buf + pxlen; + pbuf[0] = '\0'; + } + } + if (!sent) + { + *pbuf = '\0'; + sendto_one(sptr, rpl_str(RPL_NAMREPLY, parv[0]), buf,0); + } + sendto_one(sptr, rpl_str(RPL_ENDOFNAMES, parv[0]), "*"); + return MAXPENALTY; +} + +#ifdef SOPER_SNAMES + +/* + * m_snames (ripped m_names) + * parv[0] = sender prefix + * parv[1] = channel +*/ +int m_snames(cptr, sptr, parc, parv) +aClient *cptr, *sptr; +int parc; +char *parv[]; { Reg aChannel *chptr; Reg aClient *c2ptr; Reg Link *lp; - aChannel *ch2ptr = NULL; int idx, flag, len, mlen, rlen = 0; - char *s, *para = parc > 1 ? parv[1] : NULL; + char *s, *para; - if (parc > 2 && - hunt_server(cptr, sptr, ":%s NAMES %s %s", 2, parc, parv)) - return 10; + if (!MyClient(sptr)) + return 0; + + if (parc < 2) + { + sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS, parv[0]), + "SNAMES"); + return 0; + } mlen = strlen(ME) + 10; /* server names + : : + spaces + "353" */ mlen += strlen(parv[0]); - if (!BadPtr(para)) - { - s = index(para, ','); - if (s && MyConnect(sptr) && s != para) - { - parv[1] = ++s; - (void)m_names(cptr, sptr, parc, parv); - } - clean_channelname(para); - ch2ptr = find_channel(para, (aChannel *)NULL); - } + + clean_channelname(para = parv[1]); + chptr = get_channel(sptr, parv[1], 0); + + if (!chptr) + { + sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL, parv[0]), + parv[1]); + return 0; + } + +#ifdef SOPERCHAN + if (soperchan = get_channel(&me, SOPERCHAN, 0)) + sendto_channel_butone(&me, &me, soperchan, + ":%s NOTICE %s :%s requested SNAMES %s", + ME, SOPERCHAN, parv[0], parv[1]); +#endif *buf = '\0'; - /* - * First, do all visible channels (public and the one user self is) - */ + /* Find users on same channel (defined by chptr) */ - for (chptr = channel; chptr; chptr = chptr->nextch) - { - if (!chptr->users || /* locked empty channel */ - ((chptr != ch2ptr) && !BadPtr(para))) /* 'wrong' channel */ - continue; - if (!MyConnect(sptr) && (BadPtr(para) || (rlen > CHREPLLEN))) - break; - if ((BadPtr(para) || !HiddenChannel(chptr)) && - !ShowChannel(sptr, chptr)) - continue; /* -- users on this are not listed */ - - /* Find users on same channel (defined by chptr) */ - - (void)strcpy(buf, "* "); - len = strlen(chptr->chname); - (void)strcpy(buf + 2, chptr->chname); - (void)strcpy(buf + 2 + len, " :"); - - if (PubChannel(chptr)) - *buf = '='; - else if (SecretChannel(chptr)) - *buf = '@'; + (void)strcpy(buf, "* "); + len = strlen(chptr->chname); + (void)strcpy(buf + 2, chptr->chname); + (void)strcpy(buf + 2 + len, " :"); + + if (PubChannel(chptr)) + *buf = '='; + else if (SecretChannel(chptr)) + *buf = '@'; - if (IsAnonymous(chptr)) - { - if ((lp = find_user_link(chptr->members, sptr))) - { - if (lp->flags & CHFL_CHANOP) - (void)strcat(buf, "@"); - else if (lp->flags & CHFL_VOICE) - (void)strcat(buf, "+"); - (void)strcat(buf, parv[0]); - } - rlen += strlen(buf); - sendto_one(sptr, rpl_str(RPL_NAMREPLY, parv[0]), buf); - continue; - } - idx = len + 4; /* channel name + [@=] + 2?? */ - flag = 1; - for (lp = chptr->members; lp; lp = lp->next) - { - c2ptr = lp->value.cptr; - if (IsInvisible(c2ptr) && !IsMember(sptr,chptr)) - continue; - if (lp->flags & CHFL_CHANOP) - { - (void)strcat(buf, "@"); - idx++; - } - else if (lp->flags & CHFL_VOICE) - { - (void)strcat(buf, "+"); - idx++; - } - (void)strncat(buf, c2ptr->name, NICKLEN); - idx += strlen(c2ptr->name) + 1; - flag = 1; - (void)strcat(buf," "); - if (mlen + idx + NICKLEN + 1 > BUFSIZE - 2) - { - sendto_one(sptr, rpl_str(RPL_NAMREPLY, - parv[0]), buf); - (void)strncpy(buf, "* ", 3); - (void)strncpy(buf+2, chptr->chname, - len + 1); - (void)strcat(buf, " :"); - if (PubChannel(chptr)) - *buf = '='; - else if (SecretChannel(chptr)) - *buf = '@'; - idx = len + 4; - flag = 0; - } - } - if (flag) - { - rlen += strlen(buf); - sendto_one(sptr, rpl_str(RPL_NAMREPLY, parv[0]), buf); - } - } /* for(channels) */ - if (!BadPtr(para)) - { - if (!MyConnect(sptr) && (rlen > CHREPLLEN)) - sendto_one(sptr, err_str(ERR_TOOMANYMATCHES, parv[0]), - para); - sendto_one(sptr, rpl_str(RPL_ENDOFNAMES, parv[0]), para); - return(1); - } + idx = len + 4; /* channel name + [@=] + 2?? */ + flag = 1; - /* Second, do all non-public, non-secret channels in one big sweep */ + for (lp = chptr->members; lp; lp = lp->next) + { + c2ptr = lp->value.cptr; - (void)strncpy(buf, "* * :", 6); - idx = 5; - flag = 0; - for (c2ptr = client; c2ptr; c2ptr = c2ptr->next) - { - aChannel *ch3ptr; - int showflag = 0, secret = 0; + if (lp->flags & CHFL_CHANOP) + { + (void)strcat(buf, "@"); + idx++; + } + + else if (lp->flags & CHFL_VOICE) + { + (void)strcat(buf, "+"); + idx++; + } - if (!IsPerson(c2ptr) || IsInvisible(c2ptr)) - continue; - if (!MyConnect(sptr) && (BadPtr(para) || (rlen > CHREPLLEN))) - break; - lp = c2ptr->user->channel; - /* - * don't show a client if they are on a secret channel or - * they are on a channel sptr is on since they have already - * been show earlier. -avalon - */ - while (lp) - { - ch3ptr = lp->value.chptr; - if (PubChannel(ch3ptr) || IsMember(sptr, ch3ptr)) - showflag = 1; - if (SecretChannel(ch3ptr)) - secret = 1; - lp = lp->next; - } - if (showflag) /* have we already shown them ? */ - continue; - if (secret) /* on any secret channels ? */ - continue; (void)strncat(buf, c2ptr->name, NICKLEN); idx += strlen(c2ptr->name) + 1; - (void)strcat(buf," "); flag = 1; - if (mlen + idx + NICKLEN > BUFSIZE - 2) - { - rlen += strlen(buf); - sendto_one(sptr, rpl_str(RPL_NAMREPLY, parv[0]), buf); - (void)strncpy(buf, "* * :", 6); - idx = 5; + (void)strcat(buf," "); + if (mlen + idx + NICKLEN + 1 > BUFSIZE - 2) + { + sendto_one(sptr, rpl_str(RPL_NAMREPLY, + parv[0]), buf); + (void)strncpy(buf, "* ", 3); + (void)strncpy(buf+2, chptr->chname, + len + 1); + (void)strcat(buf, " :"); + if (PubChannel(chptr)) + *buf = '='; + else if (SecretChannel(chptr)) + *buf = '@'; + idx = len + 4; flag = 0; - } - } + } + } + if (flag) - { + { rlen += strlen(buf); sendto_one(sptr, rpl_str(RPL_NAMREPLY, parv[0]), buf); - } - if (!MyConnect(sptr) && rlen > CHREPLLEN) - sendto_one(sptr, err_str(ERR_TOOMANYMATCHES, parv[0]), - para ? para : "*"); - /* This is broken.. remove the recursion? */ - sendto_one(sptr, rpl_str(RPL_ENDOFNAMES, parv[0]), "*"); - return 2; + } + + sendto_one(sptr, rpl_str(RPL_ENDOFNAMES, parv[0]), para); + + sendto_channel_butone(&me, &me, chptr, + ":%s NOTICE %s :%s does SNAMES on this channel (%s)", + ME, parv[1], parv[0], parv[1]); + + return 0; } +#endif + void send_user_joins(cptr, user) aClient *cptr, *user; { @@ -3408,7 +3900,11 @@ if (curh_nb == 0) { #ifdef DEBUGMODE +#ifdef LOCAL_REJECTIONS_ONLY + sendto_flag(SCH_NOTICE, +#else sendto_flag(SCH_LOCAL, +#endif "Channel garbage: live %u (max %u), hist %u (extended)", cur_nb - 1, max_nb - 1, curh_nb); #endif @@ -3445,7 +3941,11 @@ } #ifdef DEBUGMODE +#ifdef LOCAL_REJECTIONS_ONLY + sendto_flag(SCH_NOTICE, +#else sendto_flag(SCH_LOCAL, +#endif "Channel garbage: live %u (max %u), hist %u (removed %u)%s", cur_nb - 1, max_nb - 1, curh_nb, del - istat.is_hchan, (split) ? " split detected" : ""); @@ -3453,3 +3953,156 @@ /* Check again after CHECKFREQ seconds */ return (time_t) (now + CHECKFREQ); } + +#ifdef SOPER_SCLEAN + +/* + * m_sclean + * parv[0] - sender + * parv[1] - channel + */ + +int m_sclean(cptr, sptr, parc, parv) +aClient *cptr, *sptr; +int parc; +char *parv[]; +{ + aChannel *chptr; + Link *p; + char *q, deopbuf[BUFSIZ] = { 0 }, deopbuf2[BUFSIZ] = { 0 }; + int deopcount = 0, newchan; + + if (!MyClient(sptr)) + return 0; + + if (parc < 2) + { + sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS, parv[0]), + "SCLEAN"); + return 0; + } + + clean_channelname(q = parv[1]); + + chptr = get_channel(sptr, parv[1], 0); + + if (!chptr) + { + sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL, parv[0]), parv[1]); + return 0; + } + + if (!UseModes(parv[1])) + { + sendto_one(sptr, err_str(ERR_NOCHANMODES, parv[0]), parv[1]); + return 0; + } + +#ifdef SOPERCHAN + if (soperchan = get_channel(&me, SOPERCHAN, 0)) + sendto_channel_butone(&me, &me, soperchan, + ":%s NOTICE %s :%s requested SCLEAN %s", + ME, SOPERCHAN, parv[0], parv[1]); +#endif + + newchan = parv[1][1] == '!'; + + for (p = chptr->members; p; p = p->next) + { + if (is_chan_op(p->value.cptr, chptr)) + { + p->flags = CHFL_CHANOP & MODE_DEL; + change_chan_flag(p, chptr); + if (!deopcount) { + strcpy(deopbuf, "-"); + deopbuf2[0] = 0; + } + strcat(deopbuf, "o"); + strcat(deopbuf2, p->value.cptr->name); + strcat(deopbuf2, " "); + deopcount++; + if (deopcount == 3) + { + if (newchan) + sendto_match_servs_v(chptr, &me, + SV_NCHAN, ":%s MODE %s %s %s", ME, + parv[1], deopbuf, deopbuf2); + else + sendto_match_servs(chptr, &me, + ":%s MODE %s %s %s", ME, parv[1], + deopbuf, deopbuf2); + +#ifdef SMODE_CHAN + sendto_flag(SCH_SMODE, "Servermode: %s MODE %s %s %s", + ME, parv[1], deopbuf); +#endif + + sendto_channel_butserv(chptr, &me, + ":%s MODE %s %s %s", ME, parv[1], deopbuf, deopbuf2); + + deopbuf[0] = 0; + deopcount = 0; + } + } + } + + if (deopcount) + { +#ifdef SMODE_CHAN + sendto_flag(SCH_SMODE, "Servermode: %s MODE %s %s %s", + ME, parv[1], deopbuf, deopbuf2); +#endif + if (newchan) + sendto_match_servs_v(chptr, &me, + SV_NCHAN, ":%s MODE %s %s %s", ME, + parv[1], deopbuf, deopbuf2); + else + sendto_match_servs(chptr, &me, + ":%s MODE %s %s %s", ME, parv[1], + deopbuf, deopbuf2); + + sendto_channel_butserv(chptr, &me, + ":%s MODE %s %s %s", ME, parv[1], deopbuf, deopbuf2); + } + + if (IsMember(sptr, chptr)) + { + if (newchan) + sendto_match_servs_v(chptr, cptr, SV_NCHAN, + ":%s PART %s", parv[0], parv[1]); + else + sendto_match_servs(chptr, cptr, ":%s PART %s", + parv[0], parv[1]); + + sendto_channel_butserv(chptr, cptr, ":%s PART %s", parv[0], + parv[1]); + + remove_user_from_channel(sptr, chptr); + } + + add_user_to_channel(chptr, sptr, CHFL_CHANOP); + +#ifdef SMODE_CHAN + sendto_flag(SCH_SMODE, "Servermode: %s JOIN %s (with mode +%s)", + parv[0], parv[1], "o"); +#endif + + if (newchan) + sendto_match_servs_v(chptr, cptr, SV_NCHAN, + ":%s JOIN %s\007o", parv[0], parv[1]); + else + sendto_match_servs(chptr, cptr, ":%s JOIN %s\007o", + parv[0], parv[1]); + + sendto_channel_butserv(chptr, cptr, ":%s JOIN %s", parv[0], + parv[1]); + +// m_names(cptr, sptr, 2, parv); + send_names_one(cptr, sptr, ME, chptr, 1); + sendto_channel_butserv(chptr, cptr, ":%s MODE %s +o %s", ME, + parv[1], sptr->name); + + return 0; +} + +#endif diff -ru --new-file irc2.10.3p3/ircd/channel_def.h irc2.10.3p3+sd7/ircd/channel_def.h --- irc2.10.3p3/ircd/channel_def.h Wed Sep 3 20:45:47 1997 +++ irc2.10.3p3+sd7/ircd/channel_def.h Mon Feb 3 14:31:07 2003 @@ -25,5 +25,3 @@ #define NullChn ((aChannel *)0) #define ChannelExists(n) (find_channel(n, NullChn) != NullChn) - -#define MAXMODEPARAMS 3 diff -ru --new-file irc2.10.3p3/ircd/channel_ext.h irc2.10.3p3+sd7/ircd/channel_ext.h --- irc2.10.3p3/ircd/channel_ext.h Fri Jan 23 15:28:13 1998 +++ irc2.10.3p3+sd7/ircd/channel_ext.h Mon Feb 3 14:31:07 2003 @@ -45,20 +45,25 @@ EXTERN void send_channel_modes __P((aClient *cptr, aChannel *chptr)); EXTERN void send_channel_members __P((aClient *cptr, aChannel *chptr)); EXTERN int m_mode __P((aClient *cptr, aClient *sptr, int parc, char *parv[])); +EXTERN int m_smode __P((aClient *cptr, aClient *sptr, int parc, char *parv[])); EXTERN void clean_channelname __P((Reg char *cn)); EXTERN void del_invite __P((aClient *cptr, aChannel *chptr)); EXTERN int m_join __P((Reg aClient *cptr, Reg aClient *sptr, int parc, char *parv[])); +EXTERN int m_sjoin __P((Reg aClient *cptr, Reg aClient *sptr, int parc, + char *parv[])); +EXTERN int m_sclean __P((Reg aClient *cptr, Reg aClient *sptr, int parc, + char *parv[])); EXTERN int m_njoin __P((Reg aClient *cptr, Reg aClient *sptr, int parc, char *parv[])); EXTERN int m_part __P((aClient *cptr, aClient *sptr, int parc, char *parv[])); EXTERN int m_kick __P((aClient *cptr, aClient *sptr, int parc, char *parv[])); -EXTERN int count_channels __P((aClient *sptr)); EXTERN int m_topic __P((aClient *cptr, aClient *sptr, int parc, char *parv[])); EXTERN int m_invite __P((aClient *cptr, aClient *sptr, int parc, char *parv[])); EXTERN int m_list __P((aClient *cptr, aClient *sptr, int parc, char *parv[])); EXTERN int m_names __P((aClient *cptr, aClient *sptr, int parc, char *parv[])); +EXTERN int m_snames __P((aClient *cptr, aClient *sptr, int parc, char *parv[])); EXTERN void send_user_joins __P((aClient *cptr, aClient *user)); EXTERN time_t collect_channel_garbage __P((time_t now)); #undef EXTERN diff -ru --new-file irc2.10.3p3/ircd/class.c irc2.10.3p3+sd7/ircd/class.c --- irc2.10.3p3/ircd/class.c Fri Dec 19 15:35:57 1997 +++ irc2.10.3p3+sd7/ircd/class.c Mon Feb 3 14:31:07 2003 @@ -134,8 +134,16 @@ * immeadiately after the first one (class 0). */ void add_class(class, ping, confreq, maxli, sendq, hlocal, uhlocal, - hglobal, uhglobal) -int class, ping, confreq, maxli, hlocal, uhlocal, hglobal, uhglobal; + hglobal, uhglobal +#ifdef USE_SSL +,ssl +#endif +) +int class, ping, confreq, maxli, hlocal, uhlocal, hglobal, uhglobal +#ifdef USE_SSL + ,ssl +#endif +; long sendq; { aClass *t, *p; @@ -165,6 +173,7 @@ MaxUHLocal(p) = uhlocal; MaxHGlobal(p) = hglobal; MaxUHGlobal(p) = uhglobal; + UseSSL(p) = ssl; if (p != t) Links(p) = 0; } diff -ru --new-file irc2.10.3p3/ircd/class_ext.h irc2.10.3p3+sd7/ircd/class_ext.h --- irc2.10.3p3/ircd/class_ext.h Tue Sep 23 23:47:56 1997 +++ irc2.10.3p3+sd7/ircd/class_ext.h Mon Feb 3 14:31:07 2003 @@ -38,9 +38,15 @@ EXTERN int get_client_class __P((aClient *acptr)); EXTERN int get_client_ping __P((aClient *acptr)); EXTERN int get_con_freq __P((aClass *clptr)); +#ifndef USE_SSL EXTERN void add_class __P((int class, int ping, int confreq, int maxli, long sendq, int hlocal, int uhlocal, int hglobal, int uhglobal)); +#else +EXTERN void add_class __P((int class, int ping, int confreq, int maxli, + long sendq, int hlocal, int uhlocal, + int hglobal, int uhglobal, int ssl)); +#endif EXTERN aClass *find_class __P((int cclass)); EXTERN void check_class(); EXTERN void initclass(); diff -ru --new-file irc2.10.3p3/ircd/hash.c irc2.10.3p3+sd7/ircd/hash.c --- irc2.10.3p3/ircd/hash.c Sun Feb 11 01:32:34 2001 +++ irc2.10.3p3+sd7/ircd/hash.c Mon Feb 3 14:31:07 2003 @@ -29,13 +29,16 @@ static aHashEntry *clientTable = NULL; static aHashEntry *channelTable = NULL; static aHashEntry *serverTable = NULL; +static aHashEntry *hostnameTable = NULL; static unsigned int *hashtab = NULL; static int clhits = 0, clmiss = 0, clsize = 0; static int chhits = 0, chmiss = 0, chsize = 0; +static int cnhits = 0, cnmiss = 0 ,cnsize = 0; static int svsize = 0; int _HASHSIZE = 0; int _CHANNELHASHSIZE = 0; int _SERVERSIZE = 0; +int _HOSTNAMEHASHSIZE = 0; /* * Hashing. @@ -74,6 +77,7 @@ char *nname; int *store; { + Reg u_char *name = (u_char *)nname; Reg u_char ch; Reg u_int hash = 1; @@ -123,6 +127,31 @@ return (hash); } + + +/* + * hash_host_name + */ +static u_int hash_host_name(hname, store) +char *hname; +int *store; +{ + + Reg u_char *name = (u_char *)hname; + Reg u_int hash = 0; + + for (; *name; name++) + { + hash = 31 * hash + hashtab[*name]; + } + + if (store) + *store = hash; + hash %= _HOSTNAMEHASHSIZE; + return (hash); +} + + /* bigger prime * * given a positive integer, return a prime number that's larger @@ -195,6 +224,21 @@ Debug((DEBUG_DEBUG, "Channel Hash Table Init: %d (%d)", _CHANNELHASHSIZE, size)); } +static void clear_hostname_hash_table(size) +int size; +{ + _HOSTNAMEHASHSIZE = bigger_prime(size); + cnhits = 0; + cnmiss = 0; + cnsize = 0; + if (!hostnameTable) + hostnameTable = (aHashEntry *)MyMalloc(_HOSTNAMEHASHSIZE * + sizeof(aHashEntry)); + bzero((char *)hostnameTable, sizeof(aHashEntry) * _HOSTNAMEHASHSIZE); + Debug((DEBUG_DEBUG, "Client Hash Table Init: %d (%d)", + _HOSTNAMEHASHSIZE, size)); +} + static void clear_server_hash_table(size) int size; @@ -218,6 +262,7 @@ : CHANNELHASHSIZE); clear_server_hash_table((_SERVERSIZE) ? _SERVERSIZE : SERVERSIZE); + clear_hostname_hash_table((_HOSTNAMEHASHSIZE) ? _HOSTNAMEHASHSIZE : HOSTNAMEHASHSIZE); /* * Moved multiplication out from the hashfunctions and into * a pre-generated lookup table. Should save some CPU usage @@ -236,6 +281,8 @@ Reg aClient *cptr; Reg aChannel *chptr; Reg aServer *sptr; + Reg anUser *user; + aHashEntry *otab = table; int osize = *size; @@ -282,19 +329,44 @@ clhits = 0; clsize = 0; clientTable = table; - + for (i = 0; i < osize; i++) { for (cptr = (aClient *)otab[i].list; cptr; cptr = next) { next = cptr->hnext; - (void)add_to_client_hash_table(cptr->name, + (void)add_to_client_hash_table(cptr->name, cptr); } } MyFree(otab); } + else if (otab == hostnameTable) + { + int i; + anUser *next; + Debug((DEBUG_ERROR, "Hostname Hash Table from %d to %d (%d)", + osize, new, clsize)); + sendto_flag(SCH_HASH, "Hostname Hash Table from %d to %d (%d)", + osize, new, clsize); + cnmiss = 0; + cnhits = 0; + cnsize = 0; + hostnameTable = table; + + for (i = 0; i < osize; i++) + { + for (user = (anUser *)otab[i].list; user; + user = next) + { + next = user->hnext; + (void)add_to_hostname_hash_table(user->host, + user); + } + } + MyFree(otab); + } else if (otab == serverTable) { Debug((DEBUG_ERROR, "Server Hash Table from %d to %d (%d)", @@ -352,6 +424,26 @@ } /* + * add_to_client_hash_table + */ +int add_to_hostname_hash_table(hostname, user) +char *hostname; +anUser *user; +{ + Reg u_int hashv; + + hashv = hash_host_name(hostname, &user->hashv); + user->hnext = (anUser *)hostnameTable[hashv].list; + hostnameTable[hashv].list = (void *)user; + hostnameTable[hashv].links++; + hostnameTable[hashv].hits++; + cnsize++; + if (cnsize > _HOSTNAMEHASHSIZE) + bigger_hash_table(&_HOSTNAMEHASHSIZE, hostnameTable, 0); + return 0; +} + +/* * add_to_server_hash_table */ int add_to_server_hash_table(sptr, cptr) @@ -456,7 +548,49 @@ } return 0; } +/* + * del_from_hostname_hash_table + */ +int del_from_hostname_hash_table(hostname, user) +char *hostname; +anUser *user; +{ + Reg anUser *tmp, *prev = NULL; + Reg u_int hashv; + hashv = user->hashv; + hashv %= _HOSTNAMEHASHSIZE; + for (tmp = (anUser *)hostnameTable[hashv].list; tmp; tmp = tmp->hnext) + { + if (tmp == user) + { + if (prev) + prev->hnext = tmp->hnext; + else + hostnameTable[hashv].list = (void *)tmp->hnext; + tmp->hnext = NULL; + if (hostnameTable[hashv].links > 0) + { + hostnameTable[hashv].links--; + cnsize--; + return 1; + } + else + { + sendto_flag(SCH_ERROR, "hn-hash table failure"); + Debug((DEBUG_ERROR, "hn-hash table failure")); + /* + * Should never actually return from here and + * if we do it is an error/inconsistency in the + * hash table. + */ + return -1; + } + } + prev = tmp; + } + return 0; +} /* * del_from_server_hash_table @@ -649,6 +783,30 @@ chmiss++; return chptr; } +/* + * hash_find_hostname + */ +anUser *hash_find_hostname(hostname, user) +char *hostname; +anUser *user; +{ + Reg anUser *tmp, *prv = NULL; + Reg aHashEntry *tmp3; + u_int hashv, hv; + + hashv = hash_host_name(hostname, &hv); + tmp3 = &hostnameTable[hashv]; + + for (tmp = (anUser *)tmp3->list; tmp; prv = tmp, tmp = tmp->hnext) + if (hv == tmp->hashv && !mycmp(hostname, tmp->host)) + { + cnhits++; + return (tmp); + } + cnmiss++; + return user; +} + /* * hash_find_channels @@ -746,14 +904,23 @@ if (parc > 1) { ch = *parv[1]; - if (islower(ch)) - table = clientTable; - else { - table = channelTable; - size = _CHANNELHASHSIZE; + switch (tolower(ch)) + { + case 'c': + table = channelTable; + size = _CHANNELHASHSIZE; + break; + case 'q': + table = hostnameTable; + size = _HOSTNAMEHASHSIZE; + break; + default: + table = clientTable; } - if (ch == 'L' || ch == 'l') + if (isupper(ch)) + { showlist = 1; + } } else { ch = '\0'; table = clientTable; @@ -950,6 +1117,8 @@ parv[0], clhits, clmiss); sendto_one(sptr,"NOTICE %s :Channel hits %d miss %d", parv[0], chhits, chmiss); + sendto_one(sptr,"NOTICE %s :Hostnames hits %d miss %d", + parv[0], cnhits, cnmiss); return 2; #endif } diff -ru --new-file irc2.10.3p3/ircd/hash_def.h irc2.10.3p3+sd7/ircd/hash_def.h --- irc2.10.3p3/ircd/hash_def.h Wed Sep 3 20:45:50 1997 +++ irc2.10.3p3+sd7/ircd/hash_def.h Mon Feb 3 14:31:07 2003 @@ -30,3 +30,5 @@ #define HASHSIZE ((int)((float)MAXCONNECTIONS*1.75)) #define CHANNELHASHSIZE ((int)(((float)MAXCONNECTIONS*1.75)/2.0)) #define SERVERSIZE (MAXCONNECTIONS/10) +#define HOSTNAMEHASHSIZE ((int)((float)MAXCONNECTIONS*1.75)) + diff -ru --new-file irc2.10.3p3/ircd/hash_ext.h irc2.10.3p3+sd7/ircd/hash_ext.h --- irc2.10.3p3/ircd/hash_ext.h Sun Jan 17 03:13:54 1999 +++ irc2.10.3p3+sd7/ircd/hash_ext.h Mon Feb 3 14:31:07 2003 @@ -40,10 +40,13 @@ EXTERN int add_to_client_hash_table __P((char *name, aClient *cptr)); EXTERN int add_to_channel_hash_table __P((char *name, aChannel *chptr)); EXTERN int add_to_server_hash_table __P((aServer *sptr, aClient *cptr)); +EXTERN int add_to_hostname_hash_table __P((char *hostname, anUser *user)); EXTERN int del_from_client_hash_table __P((char *name, aClient *cptr)); EXTERN int del_from_channel_hash_table __P((char *name, aChannel *chptr)); EXTERN int del_from_server_hash_table __P((aServer *sptr, aClient *cptr)); +EXTERN int del_from_hostname_hash_table __P((char *hostname, anUser *user)); EXTERN aClient *hash_find_client __P((char *name, aClient *cptr)); +EXTERN anUser *hash_find_hostname __P((char *hostname, anUser *user)); EXTERN aClient *hash_find_server __P((char *server, aClient *cptr)); EXTERN aChannel *hash_find_channel __P((char *name, aChannel *chptr)); EXTERN aChannel *hash_find_channels __P((char *name, aChannel *chptr)); diff -ru --new-file irc2.10.3p3/ircd/ircd.c irc2.10.3p3+sd7/ircd/ircd.c --- irc2.10.3p3/ircd/ircd.c Sun May 6 16:42:30 2001 +++ irc2.10.3p3+sd7/ircd/ircd.c Mon Feb 3 14:31:07 2003 @@ -30,10 +30,19 @@ aClient me; /* That's me */ aClient *client = &me; /* Pointer to beginning of Client list */ +#ifdef RECOVER +char md5me[RECOVER_SMDLEN]; +#endif static void open_debugfile(), setup_signals(), io_loop(); +#if defined(OPER_KLINE) || defined(LOCOP_KLINE) || \ + defined(OPER_TKLINE) || defined(LOCOP_TKLINE) +int kline_added = 0; +#endif + istat_t istat; +iconf_t iconf; char **myargv; int rehashed = 0; int portnum = -1; /* Server port number, listening this */ @@ -43,6 +52,7 @@ char *debugmode = ""; /* -"- -"- -"- -"- */ char *sbrk0; /* initial sbrk(0) */ char *tunefile = IRCDTUNE_PATH; +int initialconf = 1; static int dorehash = 0, dorestart = 0, restart_iauth = 0; @@ -54,6 +64,10 @@ time_t nextexpire = 1; /* next expire run on the dns cache */ time_t nextiarestart = 1; /* next time to check if iauth is alive */ +#ifdef DELAY_CLOSE +time_t nextdelayclose = 0; +#endif + #ifdef PROFIL extern etext(); @@ -337,6 +351,143 @@ return; } } +#ifdef DELAY_CLOSE +time_t delay_close(fd,reason) +int fd; +char *reason; +{ + struct fdlog + { + struct fdlog *next; + int fd; + time_t time; + char reason[BUFSIZE]; + }; + static struct fdlog *first = NULL, *last = NULL; + static int delayedfdnum = 0; + struct fdlog *next = first, *tmp; + + while (tmp = next) + if ((fd == -2) || (delayedfdnum == MAXCONNECTIONS / 10) + || tmp->time + DELAYCLOSETIME < timeofday) + { + next = tmp->next; + if (*(tmp->reason)) + { + send(tmp->fd,tmp->reason,strlen(tmp->reason),0); + } + close(tmp->fd); + delayedfdnum--; + MyFree(tmp); + if (!next) + { + if (first != last) + abort(); + first = last = NULL; + break; + } + first = next; + } + else + break; + + if (fd == -2) + { + nextdelayclose = 0; + return 0; + } + if (fd < 0) + return first ? first->time + DELAYCLOSETIME : 0; + /* disallow further receives */ + /* this should be shutdown(fd, SHUT_RD) but some OSes do- + * not define this. Check shutdown(2) if it matches. + * -- Beeth + */ +#ifndef SHUT_RD +#define SHUT_RD 0 +#endif + shutdown(fd, SHUT_RD); + + /* first create a new entry with fd and time */ + tmp = (struct fdlog *)MyMalloc(sizeof(*tmp)); + tmp->next = NULL; + tmp->fd = fd; + tmp->time = timeofday; + if (reason) + { + strncpy(tmp->reason,reason,BUFSIZE-3); + tmp->reason[BUFSIZE-3] = 0; + strcat(tmp->reason,"\r\n"); + } + delayedfdnum++; + istat.is_delayclosed++; + /* then add it to the list */ + if (last) + { + last->next = tmp; + last = tmp; + } + else + first = last = tmp; + + nextdelayclose = first ? first->time + DELAYCLOSETIME : 0; + return nextdelayclose; + +} + +#endif /* DELAY_CLOSE */ + +#if defined(OPER_KLINE) || defined(LOCOP_KLINE) || \ + defined(OPER_TKLINE) || defined(LOCOP_TKLINE) +void check_klines(void) +{ + Reg aClient *cptr; + int kflag, i; + char *reason; + + kline_added=0; + + for (i = highest_fd ; i>=0; i--) + { + + if (!(cptr = local[i]) || IsListening(cptr) || IsLog(cptr) || + IsHeld(cptr)) + continue; +#ifdef ILINE_FLAGS + if (IsKlineExempt(cptr)) + { + continue; + } +#endif + if ( IsPerson(cptr) ) + { + kflag = find_kill(cptr, 1, &reason); + } + else + { + kflag = 0; + reason = NULL; + } + + if (kflag && IsPerson(cptr)) + { + char buf[100]; + + sendto_flag(SCH_NOTICE, + "Kill line active for %s", + get_client_name(cptr, FALSE)); + cptr->exitc = EXITC_KLINE; + if (reason) + sprintf(buf, "Kill line active: %.80s", + reason); + (void)exit_client(cptr, cptr, &me, (reason) ? + buf : "Kill line active"); + } + } + + return; +} +#endif static time_t check_pings(currenttime) @@ -354,7 +505,6 @@ if (!(cptr = local[i]) || IsListening(cptr) || IsLog(cptr) || IsHeld(cptr)) continue; - /* * K and R lines once per minute, max. This is the max. * granularity in K-lines anyway (with time field). @@ -365,7 +515,11 @@ #endif /* TIMEDKLINES */ rehashed) { - if (IsPerson(cptr)) + if (IsPerson(cptr) +#ifdef ILINE_FLAGS + && !IsKlineExempt(cptr) +#endif + ) { kflag = find_kill(cptr, rehashed, &reason); #ifdef R_LINES_OFTEN @@ -656,6 +810,12 @@ ROOT_PATH); exit(5); } + if (chdir("/") != 0) + { + perror("chdir"); + (void)fprintf(stderr, "%s: Cannot chdir to /\n", IRCD_PATH); + exit(5); + } #endif /*CHROOTDIR*/ #ifdef ZIP_LINKS @@ -680,7 +840,9 @@ bzero((char *)&me, sizeof(me)); version = make_version(); /* Generate readable version string */ - +#ifdef SEND_ISUPPORT + isupport = make_isupport(); /* generate 005 numeric */ +#endif /* ** All command line parameters have the syntax "-fstring" ** or "-f string" (e.g. the space is optional). String may @@ -804,7 +966,6 @@ } #endif -#if !defined(CHROOTDIR) (void)setuid((uid_t)euid); # if defined(IRC_UID) && defined(IRC_GID) if ((int)getuid() == 0) @@ -817,7 +978,6 @@ (void)setuid(IRC_UID); } # endif -#endif /*CHROOTDIR/UID/GID*/ #if defined(USE_IAUTH) if ((bootopt & BOOT_NOIAUTH) == 0) @@ -862,8 +1022,8 @@ timeofday = time(NULL); #ifdef CACHED_MOTD motd = NULL; - read_motd(IRCDMOTD_PATH); #endif + read_motd(IRCDMOTD_PATH); inithashtables(); initlists(); initclass(); @@ -873,6 +1033,7 @@ timeofday = time(NULL); (void)init_sys(); logfiles_open(); + init_ssl(); #ifdef USE_SYSLOG openlog(mybasename(myargv[0]), LOG_PID|LOG_NDELAY, LOG_FACILITY); @@ -908,9 +1069,10 @@ if (!find_me()) exit(-1); } - + initialconf = 0; dbuf_init(); setup_me(&me); + rehash_ssl(); check_class(); ircd_writetune(tunefile); if (bootopt & BOOT_INETD) @@ -984,7 +1146,11 @@ ** active C lines, this call to Tryconnections is ** made once only; it will return 0. - avalon */ +#ifdef OPER_SET + if (iconf.aconnect && nextconnect && timeofday >= nextconnect) +#else if (nextconnect && timeofday >= nextconnect) +#endif nextconnect = try_connections(timeofday); /* ** Every once in a while, hunt channel structures that @@ -1066,6 +1232,19 @@ rehashed = 0; } +#ifdef DELAY_CLOSE + if (nextdelayclose && (timeofday >= nextdelayclose)) + { + nextdelayclose = delay_close(-1,NULL); + } +#endif + +#if defined(OPER_KLINE) || defined(LOCOP_KLINE) || \ + defined(OPER_TKLINE) || defined(LOCOP_TKLINE) + if (kline_added) + check_klines(); +#endif + if (dorestart) restart("Caught SIGINT"); if (dorehash) diff -ru --new-file irc2.10.3p3/ircd/ircd_ext.h irc2.10.3p3+sd7/ircd/ircd_ext.h --- irc2.10.3p3/ircd/ircd_ext.h Fri Feb 12 06:00:47 1999 +++ irc2.10.3p3+sd7/ircd/ircd_ext.h Mon Feb 3 14:31:07 2003 @@ -27,6 +27,7 @@ extern aClient me; extern aClient *client; extern istat_t istat; +extern iconf_t iconf; extern char **myargv; extern int rehashed; extern int portnum; @@ -41,6 +42,10 @@ extern time_t nextping; extern time_t nextdnscheck; extern time_t nextexpire; +extern int initialconf; +#ifdef DELAY_CLOSE +extern time_t nextdelayclose; +#endif #endif /* IRCD_C */ /* External definitions for global functions. @@ -59,4 +64,7 @@ EXTERN void server_reboot(); EXTERN void ircd_writetune __P((char *filename)); EXTERN void ircd_readtune __P((char *filename)); +#ifdef DELAY_CLOSE +EXTERN time_t delay_close __P((int fd,char *reason)); +#endif #undef EXTERN diff -ru --new-file irc2.10.3p3/ircd/list.c irc2.10.3p3+sd7/ircd/list.c --- irc2.10.3p3/ircd/list.c Mon May 7 00:36:55 2001 +++ irc2.10.3p3+sd7/ircd/list.c Mon Feb 3 14:31:07 2003 @@ -121,6 +121,10 @@ cptr->info = DefInfo; if (size == CLIENT_LOCAL_SIZE) { +#ifdef USE_SSL + cptr->ssl = NULL; + cptr->handshake = 0; +#endif cptr->since = cptr->lasttime = cptr->firsttime = timeofday; cptr->confs = NULL; cptr->sockhost[0] = '\0'; @@ -147,6 +151,13 @@ istat.is_auth -= 1; MyFree(cptr->auth); } + if (cptr->hopcount == 0) + { + if (cptr->reason) + MyFree(cptr->reason); + } + if (MyConnect(cptr)) + free_ssl(cptr); MyFree((char *)cptr); } @@ -190,6 +201,7 @@ if (!serv) { serv = (aServer *)MyMalloc(sizeof(aServer)); + memset(serv,0,sizeof(aServer)); #ifdef DEBUGMODE servs.inuse++; #endif @@ -201,8 +213,11 @@ serv->up = NULL; serv->refcnt = 1; serv->nexts = NULL; +#ifdef SERVER_MAP + serv->down = NULL; +#endif cptr->serv = serv; - + bzero((void *)serv->usercnt,3*sizeof(int)); for (sp = svrtop; sp; spp = sp, sp = sp->nexts) if (spp && ((spp->ltok) + 1 < sp->ltok)) break; @@ -309,6 +324,10 @@ cptr, cptr ? cptr->name : "", buf); #endif } + if (serv->up && serv->up != ME) + { + MyFree((char *)serv->up); + } MyFree((char *)serv); } } @@ -547,6 +566,12 @@ aconf->status = CONF_ILLEGAL; aconf->pref = -1; aconf->hold = time(NULL); +#ifdef SPOOF + aconf->spoof = NULL; +#endif +#ifdef USE_SSL + aconf->cert = NULL; +#endif Class(aconf) = NULL; return (aconf); } @@ -584,6 +609,14 @@ bzero(aconf->passwd, strlen(aconf->passwd)); if (aconf->ping) MyFree((char *)aconf->ping); +#ifdef SPOOF + if (aconf->spoof) + MyFree(aconf->spoof); +#endif +#ifdef USE_SSL + if (aconf->cert) + MyFree(aconf->cert); +#endif MyFree(aconf->passwd); MyFree(aconf->name); MyFree((char *)aconf); diff -ru --new-file irc2.10.3p3/ircd/s_auth.c irc2.10.3p3+sd7/ircd/s_auth.c --- irc2.10.3p3/ircd/s_auth.c Fri May 4 22:34:52 2001 +++ irc2.10.3p3+sd7/ircd/s_auth.c Mon Feb 3 14:31:07 2003 @@ -272,15 +272,15 @@ } iauth_stats = (aExtData *) MyMalloc(sizeof(aExtData)); - iauth_stats->line = MyMalloc(60); + iauth_stats->line = MyMalloc(80); sprintf(iauth_stats->line, "iauth modules statistics (%s)", myctime(timeofday)); iauth_stats->next = (aExtData *) MyMalloc(sizeof(aExtData)); - iauth_stats->next->line = MyMalloc(60); + iauth_stats->next->line = MyMalloc(80); sprintf(iauth_stats->next->line, - "spawned: %d, current options: %X (%.11s)", + "spawned: %d, current options: %X (%.20s)", iauth_spawn, iauth_options, (iauth_version) ? iauth_version : "???"); iauth_stats->next->next = NULL; @@ -440,6 +440,13 @@ ** yet: we don't even know if this is a server ** or a user connection! */ + int i; + char *reason; + reason = strchr(start,'#'); + if (reason) + { + cptr->reason = mystrdup(reason+1); + } if (start[0] == 'K') cptr->exitc = EXITC_AREF; else diff -ru --new-file irc2.10.3p3/ircd/s_bsd.c irc2.10.3p3+sd7/ircd/s_bsd.c --- irc2.10.3p3/ircd/s_bsd.c Sat Jun 30 23:18:55 2001 +++ irc2.10.3p3+sd7/ircd/s_bsd.c Mon Feb 3 14:31:07 2003 @@ -314,7 +314,6 @@ #endif if (inetport(cptr, aconf->host, aconf->name, aconf->port)) cptr->fd = -2; - if (cptr->fd >= 0) { cptr->confs = make_link(); @@ -328,7 +327,32 @@ free_client(cptr); return 0; } - +#ifdef DELAY_ACCEPT +void activate_delayed_listeners() +{ + aConfItem *aconf = NULL; + int pcnt = 0; + + for (aconf = conf; aconf; aconf = aconf->next) + { + if (!(aconf->status & CONF_LISTEN_PORT) + || (conf->status & CONF_ILLEGAL)) + { + continue; + } + if (!(aconf->status & CONF_ACTIVE)) + { + aconf->status |= CONF_ACTIVE; + pcnt++; + add_listener(aconf); + } + } + if (pcnt) + { + sendto_flag(SCH_NOTICE,"Activating delayed listening ports"); + } +} +#endif #ifdef UNIXPORT /* * unixport @@ -1055,7 +1079,40 @@ "Lost C-Line for %s", get_client_name(cptr,FALSE)); return -1; } - if (!BadPtr(aconf->passwd)) + if (!BadPtr(aconf->passwd)) { +#ifdef USE_SSL + /* shall we use ssl ? */ + if (UseSSL(Class(aconf)) == 1) { + int ret; + struct sockaddr tmp; + int tl = sizeof(tmp); + /* we need to do that, because of buggy openssl + which segfaults on dead socket ;-( */ + if (getpeername(cptr->fd, &tmp, &tl)) { + sendto_flag(SCH_ERROR, + "Failed ssl connection to %s: dead socket (connection refused ?)", + get_client_name(cptr, TRUE)); + return -1; + } + if (!aconf->cert) { + sendto_flag(SCH_NOTICE, + "Using default cert for %s", + get_client_name(cptr, TRUE)); + } + ret = ssl_server_connect(cptr, aconf->cert); + if (ret <= 0) { + sendto_flag(SCH_ERROR, + "Failed ssl connection to %s", + get_client_name(cptr, TRUE)); + return -1; + } + sendto_flag(SCH_NOTICE, + "Server ssl connection to %s established sucesfully", + get_client_name(cptr, TRUE)); + } else { + cptr->handshake = 1; + } +#endif #ifndef ZIP_LINKS sendto_one(cptr, "PASS %s %s IRC|%s %s", aconf->passwd, pass_version, serveropts, @@ -1066,6 +1123,7 @@ (bootopt & BOOT_STRICTPROT) ? "P" : "", (aconf->status == CONF_ZCONNECT_SERVER) ? "Z" : ""); #endif + } aconf = find_conf(cptr->confs, cptr->name, CONF_NOCONNECT_SERVER); if (!aconf) @@ -1146,6 +1204,7 @@ bcopy((char *)&cptr->ip, (char *)&sin.SIN_ADDR, sizeof(cptr->ip)); bcopy((char *)&cptr->ip, (char *)&acptr->ip, sizeof(cptr->ip)); +// acptr->handshake = 3; if (connect(acptr->fd, (SAP)&sin, sizeof(sin)) < 0 && errno != EINPROGRESS) { @@ -1154,7 +1213,8 @@ MyFree((char *)acptr); return -1; } - +// if (!errno) +// acptr->handshake = 0; acptr->status = STAT_RECONNECT; if (acptr->fd > highest_fd) highest_fd = acptr->fd; @@ -1297,8 +1357,21 @@ } del_fd(i, &fdall); local[i] = NULL; - (void)close(i); - +#ifdef DELAY_CLOSE + if (cptr->user && (cptr->user->flags & FLAGS_BADBOY)) + { + delay_close(i,cptr->buffer); + if (!nextdelayclose) + { + nextdelayclose = timeofday + DELAYCLOSETIME; + } + } + else +#endif + { + (void)close(i); + } + cptr->fd = -2; DBufClear(&cptr->sendQ); DBufClear(&cptr->recvQ); @@ -1465,6 +1538,47 @@ return; } +/* + * set_blocking - Set the client connection into non-blocking mode. + * If your system doesn't support this, you're screwed, ircd will run like + * crap. + * returns true (1) if successful, false (0) otherwise + */ +int set_blocking(int fd) +{ + /* + * NOTE: consult ALL your relevant manual pages *BEFORE* changing + * these ioctl's. There are quite a few variations on them, + * as can be seen by the PCS one. They are *NOT* all the same. + * Heed this well. - Avalon. + */ + /* This portion of code might also apply to NeXT. -LynX */ +#ifdef NBLOCK_SYSV + int res = 0; + + if (ioctl(fd, FIONBIO, &res) == -1) + return 0; + +#else /* !NBLOCK_SYSV */ + int nonb = 0; + int res; + +#ifdef NBLOCK_POSIX + nonb |= O_NONBLOCK; +#endif +#ifdef NBLOCK_BSD + nonb |= O_NDELAY; +#endif + + res = fcntl(fd, F_GETFL, 0); + if (!(res&nonb)) return 0; + if (-1 == res || fcntl(fd, F_SETFL, res ^ nonb) == -1) + return 0; +#endif /* !NBLOCK_SYSV */ + return 1; +} + + #ifdef CLONE_CHECK /* * check_clones @@ -1557,15 +1671,23 @@ report_error("Failed in connecting to %s :%s", cptr); add_con_refuse: + (void)close(fd); +add_con_delay_refuse: ircstp->is_ref++; acptr->fd = -2; free_client(acptr); - (void)close(fd); return NULL; } /* don't want to add "Failed in connecting to" here.. */ if (aconf && IsIllegal(aconf)) goto add_con_refuse; +#ifdef DELAY_ACCEPT + /* we are not accepting connections because of split */ + if (aconf && (aconf->status & CONF_DELAY) && (iconf.caccept < 2)) + { + goto add_con_refuse; + } +#endif /* Copy ascii address to 'sockhost' just in case. Then we * have something valid to put into error messages... */ @@ -1607,10 +1729,15 @@ (acptr->hostp) ? acptr->hostp->h_name : acptr->sockhost); del_queries((char *)acptr); +#ifdef DELAY_CLOSE + delay_close(fd,"ERROR :Too rapid connections from your host"); + goto add_con_delay_refuse; +#else (void)send(fd, "ERROR :Too rapid connections from your host\r\n", 46, 0); goto add_con_refuse; +#endif } #endif acptr->fd = fd; @@ -1843,8 +1970,12 @@ #ifdef INET6 length = recvfrom(cptr->fd, readbuf, sizeof(readbuf), 0, 0, 0); #else +#ifdef USE_SSL + length = safe_read(cptr, readbuf, sizeof(readbuf)); +#else length = recv(cptr->fd, readbuf, sizeof(readbuf), 0); #endif +#endif #if defined(DEBUGMODE) && defined(DEBUG_READ) if (length > 0) Debug((DEBUG_READ, @@ -1896,8 +2027,11 @@ if (length && dbuf_put(&cptr->recvQ, readbuf, length) < 0) return exit_client(cptr, cptr, &me, "dbuf_put fail"); - if (IsPerson(cptr) && - DBufLength(&cptr->recvQ) > CLIENT_FLOOD) + if (IsPerson(cptr) +#ifdef CAN_FLOOD + && !CanFlood(cptr) +#endif + && DBufLength(&cptr->recvQ) > CLIENT_FLOOD) { cptr->exitc = EXITC_FLOOD; return exit_client(cptr, cptr, &me, "Excess Flood"); @@ -2438,6 +2572,7 @@ (void)set_sock_opts(cptr->fd, cptr); (void)signal(SIGALRM, dummy); (void)alarm(4); +// cptr->handshake = 3; if (connect(cptr->fd, (SAP)svp, len) < 0 && errno != EINPROGRESS) { i = errno; /* other system calls may eat errno */ @@ -2455,6 +2590,8 @@ errno = ETIMEDOUT; return -1; } +// if (!errno) +// cptr->handshake = 0; (void)alarm(0); /* Attach config entries to client here rather than in diff -ru --new-file irc2.10.3p3/ircd/s_bsd_ext.h irc2.10.3p3+sd7/ircd/s_bsd_ext.h --- irc2.10.3p3/ircd/s_bsd_ext.h Fri Feb 5 01:50:21 1999 +++ irc2.10.3p3+sd7/ircd/s_bsd_ext.h Mon Feb 3 14:31:07 2003 @@ -54,6 +54,7 @@ EXTERN void close_connection __P((aClient *cptr)); EXTERN int get_sockerr __P((aClient *cptr)); EXTERN void set_non_blocking __P((int fd, aClient *cptr)); +EXTERN int set_blocking __P((int fd)); EXTERN aClient *add_connection __P((aClient *cptr, int fd)); EXTERN int read_message __P((time_t delay, FdAry *fdp, int ro)); EXTERN int connect_server __P((aConfItem *aconf, aClient *by, @@ -61,6 +62,9 @@ EXTERN void get_my_name __P((aClient *cptr, char *name, int len)); EXTERN int setup_ping __P((aConfItem *aconf)); EXTERN void send_ping __P((aConfItem *aconf)); +#ifdef DELAY_ACCEPT +EXTERN void activate_delayed_listeners(); +#endif #if defined(ENABLE_SUMMON) || defined(ENABLE_USERS) EXTERN int utmp_open(); EXTERN int utmp_read __P((int fd, char *name, char *line, char *host, diff -ru --new-file irc2.10.3p3/ircd/s_conf.c irc2.10.3p3+sd7/ircd/s_conf.c --- irc2.10.3p3/ircd/s_conf.c Fri Jul 6 01:08:58 2001 +++ irc2.10.3p3+sd7/ircd/s_conf.c Mon Feb 3 14:31:07 2003 @@ -51,6 +51,7 @@ static char rcsid[] = "@(#)$Id: s_conf.c,v 1.42.2.15 2001/07/05 22:08:58 chopin Exp $"; #endif +#include #include "os.h" #include "s_defines.h" #define S_CONF_C @@ -63,6 +64,21 @@ aConfItem *conf = NULL; aConfItem *kconf = NULL; +#ifdef RECOVER +extern char * ltoid(unsigned); +extern char md5me[RECOVER_SMDLEN]; +void md_server_name(char *buf, char *a, char *b) +{ + char mdbuf[16]; + MD5_CTX md5; + MD5_Init(&md5); + if (a) MD5_Update(&md5, a, strlen(a)); + if (b) MD5_Update(&md5, b, strlen(b)); + MD5_Final(mdbuf, &md5); + memcpy(buf, ltoid(*((time_t *) mdbuf)), RECOVER_SMDLEN); +} +#endif + /* * remove all conf entries from the client except those which match * the status field mask. @@ -161,6 +177,38 @@ return -1; } +#ifdef SPOOF +/* this replaces '%'-s in spoofed hostnames by md5 bytes of real host|ip */ +static void do_spoof(char *host, char *spoof) +{ + char mdbuf[16]; + int mdp[32], i; + + if ((!spoof) || (!*spoof)) + return; + + MD5(host, strlen(host), mdbuf); + for (i = 0; i < 32; i++) { + if (!(i&1)) { + mdp[i] = (mdbuf[i >> 1] >> 4) & 0xf; + } else { + mdp[i] = mdbuf[i >> 1] & 0xf; + } + } + + i = 0; + do { + if (*spoof == '%') { + *host++ = 'a' + mdp[i % 32]; + i++; + } else { + *host++ = *spoof; + } + } while (*spoof++); + *host = 0; +} +#endif + /* * find the first (best) I line to attach. */ @@ -177,9 +225,13 @@ for (aconf = conf; aconf; aconf = aconf->next) { - if ((aconf->status != CONF_CLIENT) && - (aconf->status != CONF_RCLIENT)) + Debug((DEBUG_DNS, "ya %s %s", aconf->name, aconf->host)); + if (IsIllegal(aconf)) continue; + + if (!(aconf->status & (CONF_CLIENT | CONF_RCLIENT))) + continue; + Debug((DEBUG_DNS, "client => name = %s host = %s", aconf->name, aconf->host)); if (aconf->port && aconf->port != cptr->acpt->port) continue; if (!aconf->host || !aconf->name) @@ -229,9 +281,46 @@ attach_iline: if (aconf->status & CONF_RCLIENT) SetRestricted(cptr); +#ifdef ILINE_FLAGS + if (aconf->status & CONF_EXEMPT) + { + cptr->user->flags |= FLAGS_EXEMPT; + } + if (aconf->status & CONF_FLOOD) + { + cptr->user->flags |= FLAGS_FLOOD; + } + if (!hp && (aconf->status & CONF_RNODNS)) + { + SetRestricted(cptr); + } + if (aconf->status & CONF_DOT) + { + cptr->user->flags |= FLAGS_DOT; + } +#ifdef RECOVER + if (aconf->status & CONF_IMMORTAL) + { + cptr->user->flags |= FLAGS_IMMORTAL; + } +#endif +#endif get_sockhost(cptr, uhost); if ((i = attach_conf(cptr, aconf)) < -1) find_bounce(cptr, ConfClass(aconf), -1); + +#ifdef USE_SSL + cptr->forcessl = UseSSL(Class(aconf)); +#endif + +#ifdef SPOOF + do_spoof(cptr->sockhost, aconf->spoof); + if ((aconf->spoof) && (*aconf->spoof)) +#if defined(OPERS_WATCHING_USERS) + cptr->real_ip = cptr->ip; +#endif + inetaton("1.3.3.7", &cptr->ip); +#endif return i; } find_bounce(cptr, 0, -2); @@ -271,6 +360,7 @@ aConfItem *aconf; { Reg Link **lp, *tmp; + aConfItem **aconf2,*aconf3; lp = &(cptr->confs); @@ -291,7 +381,23 @@ } } if (aconf && !--aconf->clients && IsIllegal(aconf)) - free_conf(aconf); + { + /* Remove the conf entry from the Conf linked list */ + for (aconf2 = &conf; (aconf3 = *aconf2); ) + { + if (aconf3 == aconf) + { + *aconf2 = aconf3->next; + aconf3->next = NULL; + free_conf(aconf); + + } + else + { + aconf2 = &aconf3->next; + } + } + } tmp = *lp; *lp = tmp->next; free_link(tmp); @@ -329,7 +435,7 @@ aClient *cptr; { Reg Link *lp; - + if (is_attached(aconf, cptr)) return 1; if (IsIllegal(aconf)) @@ -342,9 +448,10 @@ return -3; /* Use this for printing error message */ } if ((aconf->status & (CONF_CLIENT | CONF_RCLIENT))) - { + { int hcnt = 0, ucnt = 0; - + int ghcnt = 0, gucnt = 0; + Reg anUser *user = NULL; /* check on local/global limits per host and per user@host */ /* @@ -352,7 +459,64 @@ ** host check is done on the IP address. ** user check is done on the IDENT reply. */ - if (ConfMaxHLocal(aconf) > 0 || ConfMaxUHLocal(aconf) > 0) { + if (ConfMaxHLocal(aconf) > 0 || ConfMaxUHLocal(aconf) > 0 || + ConfMaxHGlobal(aconf) > 0 || ConfMaxUHGlobal(aconf) > 0 ) + { + for ((user = hash_find_hostname(cptr->sockhost,NULL));user;user=user->hnext) + { + if (!mycmp(cptr->sockhost,user->host)) + { + ghcnt++; + if (MyConnect(user->bcptr)) + { + hcnt++; + if (!mycmp(user->bcptr->auth,cptr->auth)) + { + ucnt++; + gucnt++; + } + } + else + { + if (!mycmp(user->username,cptr->user->username)) + { + gucnt++; + } + } + if (ConfMaxUHLocal(aconf) > 0 && + ucnt >= ConfMaxUHLocal(aconf)) + { + return -5; + } + + if (ConfMaxHLocal(aconf) > 0 && + hcnt >= ConfMaxHLocal(aconf)) + { + return -4; + } + if (ConfMaxUHGlobal(aconf) > 0 && + gucnt >= ConfMaxUHGlobal(aconf)) + { + return -7; + } + if (ConfMaxHGlobal(aconf) > 0 && + ghcnt >= ConfMaxHGlobal(aconf)) + { + return -6; + } + } + } + } +#ifndef NO_EXTENSIVE_LOCAL_LIMIT_CHECK + /* Part of old cpu intensive code which is checking user's + * ip against all all other local clients. Needed only when + * client changes it's hostname between connects. + * Won't be needed on pure 2.11 net -- jv + */ + + /* now, check local IP too */ + if (ConfMaxHLocal(aconf) > 0 || ConfMaxUHLocal(aconf) > 0) + { Reg aClient *acptr; Reg int i; @@ -374,38 +538,8 @@ ucnt >= ConfMaxUHLocal(aconf)) return -5; /* for error message */ } - /* - ** Global limits - ** host check is done on the hostname (IP if unresolved) - ** user check is done on username - */ - if (ConfMaxHGlobal(aconf) > 0 || ConfMaxUHGlobal(aconf) > 0) - { - Reg aClient *acptr; - Reg int ghcnt = hcnt, gucnt = ucnt; - - for (acptr = client; acptr; acptr = acptr->next) - { - if (!IsPerson(acptr)) - continue; - if (MyConnect(acptr) && - (ConfMaxHLocal(aconf) > 0 || - ConfMaxUHLocal(aconf) > 0)) - continue; - if (!strcmp(cptr->sockhost, acptr->user->host)) - { - if (ConfMaxHGlobal(aconf) > 0 && - ++ghcnt >= ConfMaxHGlobal(aconf)) - return -6; - if (ConfMaxUHGlobal(aconf) > 0 && - !strcmp(cptr->user->username, - acptr->user->username) && - (++gucnt >=ConfMaxUHGlobal(aconf))) - return -7; - } - } - } - } +#endif + } lp = make_link(); istat.is_conflink++; @@ -570,7 +704,6 @@ #endif ); - for (tmp = conf; tmp; tmp = tmp->next) { if (!(tmp->status & (CONF_OPS)) || !tmp->name || !tmp->host || @@ -582,14 +715,37 @@ */ if (match(tmp->host, userhost) && match(tmp->host, userip) && (!strchr(tmp->host, '/') - || match_ipmask(tmp->host, cptr))) + || match_ipmask(tmp->host, cptr))) { continue; - if (tmp->clients < MaxLinks(Class(tmp))) + } + if (tmp->clients < MaxLinks(Class(tmp))) { return tmp; + } } return NULL; } +aConfItem *get_ssl_line(void) +{ + Reg aConfItem *tmp; + char *p; + + for (tmp = conf; tmp; tmp = tmp->next) { + if (tmp->status & CONF_SSL) { + if (tmp->host) { + for (p = tmp->host; *p; p++) + if (*p == '^') *p = ':'; + } + if (tmp->passwd) { + for (p = tmp->passwd; *p; p++) + if (*p == '^') *p = ':'; + } + return tmp; + } + } + return NULL; +} + aConfItem *find_conf_name(name, statmask) char *name; @@ -713,12 +869,20 @@ if (!BadPtr(bconf->host) && mycmp(bconf->host, aconf->host)) continue; +#ifdef DELAY_ACCEPT + /* ignore ->passwd field */ + if (!(aconf->status & CONF_LISTEN_PORT)) + { +#endif if ((BadPtr(bconf->passwd) && !BadPtr(aconf->passwd)) || (BadPtr(aconf->passwd) && !BadPtr(bconf->passwd))) continue; if (!BadPtr(bconf->passwd) && mycmp(bconf->passwd, aconf->passwd)) continue; +#ifdef DELAY_ACCEPT + } +#endif if ((BadPtr(bconf->name) && !BadPtr(aconf->name)) || (BadPtr(aconf->name) && !BadPtr(bconf->name))) @@ -730,8 +894,7 @@ return bconf; } -/* - * rehash +/* rehash * * Actual REHASH service routine. Called with sig == 0 if it has been called * as a result of an operator issuing this command, else assume it has been @@ -831,18 +994,18 @@ * flush out deleted I and P lines although still in use. */ for (tmp = &conf; (tmp2 = *tmp); ) - if (!(tmp2->status & CONF_ILLEGAL)) + if (!(tmp2->status & CONF_ILLEGAL) || tmp2->clients) tmp = &tmp2->next; else { *tmp = tmp2->next; tmp2->next = NULL; - if (!tmp2->clients) - free_conf(tmp2); + free_conf(tmp2); } #ifdef CACHED_MOTD read_motd(IRCDMOTD_PATH); #endif + rehash_ssl(); rehashed = 1; return ret; } @@ -974,7 +1137,7 @@ {'\\', '\\'}, { 0, 0}}; Reg char *tmp, *s; int fd, i; - char line[512], c[80], *tmp2 = NULL, *tmp3 = NULL, *tmp4 = NULL; + char line[512], c[80], *tmp2 = NULL, *tmp3 = NULL, *tmp4 = NULL, *tmp5 = NULL; int ccount = 0, ncount = 0; aConfItem *aconf = NULL; @@ -1040,7 +1203,7 @@ if (tmp2) MyFree(tmp2); - tmp3 = tmp4 = NULL; + tmp3 = tmp4 = tmp5 = NULL; tmp = getfield(line); if (!tmp) continue; @@ -1141,6 +1304,10 @@ case 'y': aconf->status = CONF_CLASS; break; + case 'X': + case 'x': + aconf->status = CONF_SSL; + break; default: Debug((DEBUG_ERROR, "Error in config file: %s", line)); break; @@ -1173,7 +1340,50 @@ DupString(aconf->passwd, tmp); if ((tmp = getfield(NULL)) == NULL) break; - DupString(aconf->name, tmp); +#ifdef ILINE_FLAGS + if (aconf->status & (CONF_CLIENT | CONF_RCLIENT)) + { + /* parse i-line flags using more + sophisticated (and more obfuscated) + way -sd */ + static unsigned int conf_tab[] = + { CONF_EXEMPT, CONF_RNODNS +#ifdef CAN_FLOOD + , CONF_FLOOD +#endif +#ifdef USE_SSL + , CONF_DOT +#endif +#ifdef RECOVER + , CONF_IMMORTAL +#endif + }; + + static char *p, char_tab[] = "<+" +#ifdef CAN_FLOOD + "|" +#endif +#ifdef USE_SSL + "." +#endif +#ifdef RECOVER + "^" +#endif + ; + while (*tmp && (p = index(char_tab, *tmp))) { + aconf->status |= conf_tab[p-char_tab]; + Debug((DEBUG_DNS, "Parsing I-flag '%c'", *tmp)); + tmp++; + + } + Debug((DEBUG_DNS, "Rest of I-Line = %s\n", tmp)); + DupString(aconf->name, tmp); + } + else +#endif + { + DupString(aconf->name, tmp); + } if ((tmp = getfield(NULL)) == NULL) break; aconf->port = 0; @@ -1190,7 +1400,11 @@ /* the following are only used for Y: */ if ((tmp3 = getfield(NULL)) == NULL) break; - tmp4 = getfield(NULL); + if ((tmp4 = getfield(NULL)) == NULL) + break; +#ifdef USE_SSL + tmp5 = getfield(NULL); +#endif break; } istat.is_confmem += aconf->host ? strlen(aconf->host)+1 : 0; @@ -1218,7 +1432,11 @@ atoi(index(tmp3, '.') + 1) : 1, tmp4 ? atoi(tmp4) : 1, (tmp4 && index(tmp4, '.')) ? - atoi(index(tmp4, '.') + 1) : 1); + atoi(index(tmp4, '.') + 1) : 1 +#ifdef USE_SSL + ,tmp5 ? atoi(tmp5) : 0 +#endif + ); continue; } /* @@ -1232,26 +1450,95 @@ if (MaxLinks(Class(aconf)) < 0) Class(aconf) = find_class(0); } - if (aconf->status & (CONF_LISTEN_PORT|CONF_CLIENT)) +#ifdef DELAY_ACCEPT + if (aconf->status & (CONF_LISTEN_PORT)) + { + if (aconf->passwd && strchr(aconf->passwd,'D')) + { + aconf->status |= CONF_DELAY; + } + if (aconf->passwd && strchr(aconf->passwd,'S')) + { + aconf->status |= CONF_SERVERONLY; + /* feature, remove delay if serveronly */ + aconf->status &= ~CONF_DELAY; + } + } +#endif + + if (aconf->status & (CONF_LISTEN_PORT|CONF_CLIENT|CONF_RCLIENT)) { - aConfItem *bconf; + aConfItem *bconf = NULL; if ((bconf = find_conf_entry(aconf, aconf->status))) { delist_conf(bconf); bconf->status &= ~CONF_ILLEGAL; - if (aconf->status == CONF_CLIENT) - { + if (aconf->status & (CONF_CLIENT | CONF_RCLIENT)) { +#ifdef ILINE_FLAGS + /* a bit of bitmagic, *ahem* -sd */ + bconf->status &= ~CONF_ILINE_FLAGS; + bconf->status |= aconf->status & CONF_ILINE_FLAGS; +#endif bconf->class->links -= bconf->clients; bconf->class = aconf->class; bconf->class->links += bconf->clients; } +#ifdef DELAY_ACCEPT + if (aconf->status & CONF_LISTEN_PORT) + { + if (aconf->status & CONF_DELAY) + { + bconf->status &= ~CONF_SERVERONLY; + bconf->status |= CONF_DELAY; + } + else + { + bconf->status &= ~CONF_DELAY; + } + if (aconf->status & CONF_SERVERONLY) + { + bconf->status &= ~CONF_DELAY; + bconf->status |= CONF_SERVERONLY; + } + else + { + bconf->status &= ~CONF_SERVERONLY; + } + } +#endif + free_conf(aconf); aconf = bconf; } - else if (aconf->host && - aconf->status == CONF_LISTEN_PORT) - (void)add_listener(aconf); + + if (aconf->host && + aconf->status & CONF_LISTEN_PORT) + { +#ifdef DELAY_ACCEPT + if (aconf->status & CONF_DELAY) + { + /* we have Delayed ports and we + * are starting, don't bind them. + */ + if (initialconf) + iconf.caccept = 1; + } + if (!((iconf.caccept < 2) && + (aconf->status & CONF_DELAY))) + { + aconf->status |= CONF_ACTIVE; + } + + if (aconf->status & CONF_ACTIVE) +#endif + { + if (!bconf) + { + add_listener(aconf); + } + } + } } if (aconf->status & CONF_SERVICE) aconf->port &= SERVICE_MASK_ALL; @@ -1296,7 +1583,13 @@ MyFree(tmp2); tmp2 = NULL; } - +#ifdef USE_SSL + if (tmp3) { + DupString(aconf->cert, tmp3); + MyFree(tmp3); + tmp3 = NULL; + } +#endif } /* ** Name cannot be changed after the startup. @@ -1312,12 +1605,29 @@ MyFree(me.info); me.info = MyMalloc(REALLEN+1); strncpyzt(me.info, aconf->name, REALLEN+1); +#ifdef NAMECHANGE_HACK + /* you must be very careful when you're going + to change this. at least squit all servers + before changeing. -sd */ if (ME[0] == '\0' && aconf->host[0]) +#endif + { strncpyzt(ME, aconf->host, sizeof(ME)); + } +#ifdef RECOVER + md_server_name(md5me, me.name, me.info); + sendto_flag(SCH_NOTICE, "md5me = '%3s'", md5me); +#endif if (aconf->port) setup_ping(aconf); } +#ifdef SPOOF + if ((tmp3) && (aconf->status & (CONF_CLIENT|CONF_RCLIENT))) { + DupString(aconf->spoof, tmp3); + } +#endif + (void)collapse(aconf->host); (void)collapse(aconf->name); Debug((DEBUG_NOTICE, diff -ru --new-file irc2.10.3p3/ircd/s_conf_ext.h irc2.10.3p3+sd7/ircd/s_conf_ext.h --- irc2.10.3p3/ircd/s_conf_ext.h Fri Feb 9 13:35:34 2001 +++ irc2.10.3p3+sd7/ircd/s_conf_ext.h Mon Feb 3 14:31:07 2003 @@ -67,4 +67,9 @@ # ifdef INET6 EXTERN char *ipv6_convert __P((char *orig)); # endif + +#ifdef USE_SSL +EXTERN aConfItem *get_ssl_line __P((void)); +#endif + #undef EXTERN diff -ru --new-file irc2.10.3p3/ircd/s_debug.c irc2.10.3p3+sd7/ircd/s_debug.c --- irc2.10.3p3/ircd/s_debug.c Fri Oct 19 21:44:27 2001 +++ irc2.10.3p3+sd7/ircd/s_debug.c Mon Feb 3 14:31:07 2003 @@ -36,6 +36,9 @@ #ifndef NO_IDENT 'a', #endif +#ifdef MIN_CHANOP_SERV +'B', +#endif #ifdef CHROOTDIR 'c', #endif @@ -88,6 +91,9 @@ 'K', # endif #endif +#ifdef FAILED_OPERLOG +'l', +#endif #ifdef LEAST_IDLE 'L', #endif @@ -123,6 +129,9 @@ #endif #ifdef OPER_REMOTE 't', +#ifdef TOPICWHOTIME +'T', +#endif #endif #ifndef NO_PREFIX 'u', @@ -148,8 +157,116 @@ #ifdef INET6 '6', #endif +'@', '\0'}; +/* + * Option string. Must be before #ifdef DEBUGMODE. + * spaces are not allowed. + */ +char cropts[] = { +#ifdef EXTRA_STATISTICS +'E', +#endif +#ifdef FAILED_OPERLOG +'F', +#endif +#ifdef LOG_IP +'I', +#endif +#ifdef OPER_KLINE +'K', +#endif +#ifdef LOCOP_KLINE +'k', +#endif +#ifdef OPER_TKLINE +'T', +#endif +#ifdef LOCOP_TKLINE +'t', +#endif +#ifdef RESTRICT_USERNAMES +'u', +#endif +'\0'}; + +char flopts[] = { +#ifdef CLIENTS_CHANNEL +'C', +#endif +'\0'}; + +char scopts[] = { +#ifdef EXTRA_STATISTICS +'C', +#endif +#ifdef FAILED_OPERLOG +'f', +#endif +#ifdef OPER_KLINE +# ifdef LOCOP_KLINE +'K', +# else +'k', +# endif +#endif +#ifdef LOCAL_REJECTIONS_ONLY +'r', +#endif +#ifdef TOPICWHOTIME +'t', +#endif +'\0' }; + +char jvopts[] = { +#ifdef NO_EXTENSIVE_LOCAL_LIMIT_CHECK +'L', +#endif +#ifdef STATS_F +'F', +#endif +#ifdef WHOIS_SIGNON_TIME +'s', +#endif +#ifdef NO_OPER_TRYAGAIN +'N', +#endif +#ifdef DELAY_ACCEPT +'d', +#endif +#ifdef DELAY_CLOSE +'D', +#endif +#ifdef SEND_ISUPPORT +'5', +#endif +#ifdef STATS_QMARK +'?', +#endif +#ifdef SERVER_MAP +'M', +#endif +#ifdef LIST_ALIS_NOTE +'A', +#endif +#ifdef SPLIT_HANDLE +'S', +#endif +#ifdef OPER_SET +'o', +#endif +#ifdef ILINE_FLAGS +'I', +#endif +#ifdef IAUTH_VERBOSE_REJECTS +'v', +#endif +#ifdef LOG_IRCNAME +'i', +#endif +'\0' +}; #ifdef DEBUGMODE static char debugbuf[2*READBUF_SIZE]; /* needs to be big.. */ @@ -358,6 +475,26 @@ -1, -1 #endif ); + sendto_one(cptr, ":%s %d %s :Sc:%s", ME, RPL_STATSDEFINE, nick, + scopts); +#ifdef EXTRA_STATISTICS + sendto_one(cptr, ":%s %d %s :Cr:%s %d/%d/%d/%d/%d/%d Fl:%s", + ME, RPL_STATSDEFINE, nick, cropts, + istat.is_m_users, istat.is_m_myclnt, + istat.is_m_service, istat.is_m_myservice, + istat.is_m_serv, istat.is_m_myserv,flopts); +#else + sendto_one(cptr, ":%s %d %s :Cr:%s Fl:%s", + ME, RPL_STATSDEFINE, nick, cropts,flopts); +#endif + sendto_one(cptr, ":%s %d %s :jv:%s Split Servers: %d (%d) Users: %d", + ME, RPL_STATSDEFINE,nick,jvopts, +#ifdef SPLIT_HANDLE + SPLIT_SERV,istat.is_eobservers,SPLIT_USERS +#else + -1,-1,-1 +#endif + ); } void count_memory(cptr, nick, debug) diff -ru --new-file irc2.10.3p3/ircd/s_err.c irc2.10.3p3+sd7/ircd/s_err.c --- irc2.10.3p3/ircd/s_err.c Sat Feb 10 21:11:06 2001 +++ irc2.10.3p3+sd7/ircd/s_err.c Mon Feb 3 14:31:07 2003 @@ -40,8 +40,32 @@ /* 001 */ { RPL_WELCOME, ":Welcome to the Internet Relay Network %s" }, /* 002 */ { RPL_YOURHOST, ":Your host is %s, running version %s" }, /* 003 */ { RPL_CREATED, ":This server was created %s" }, -/* 004 */ { RPL_MYINFO, "%s %s aoOirw abeiIklmnoOpqrstv" }, +/* 004 */ { RPL_MYINFO, "%s %s%s aoOirw abeiIklmnoOpqrstv" }, +#ifdef SEND_ISUPPORT +/* 005 */ //{ RPL_ISUPPORT, "MAP PREFIX=(ov)@+ MODES=3 CHANTYPES=#&!+ MAXCHANNELS=%d NICKLEN=%d TOPICLEN=%d KICKLEN=%d NETWORK=%s CHANMODES=beI,k,l,imnpstaqr :are supported by this server" }, +/* 005 */ { RPL_ISUPPORT, "%s :are supported by this server" }, +#else /* 005 */ { RPL_BOUNCE, ":Try server %s, port %d" }, +#endif +/* 006 */ { 0, (char *)NULL }, +/* 007 */ { 0, (char *)NULL }, +/* 008 */ { 0, (char *)NULL }, +/* 009 */ { 0, (char *)NULL }, +#ifdef SEND_ISUPPORT +/* 010 */ { RPL_BOUNCE, "%s %d :Please use this Server/Port instead" }, +#else +/* 010 */ { 0, (char *)NULL }, +#endif +/* 011 */ { 0, (char *)NULL }, +/* 012 */ { 0, (char *)NULL }, +/* 013 */ { 0, (char *)NULL }, +#ifdef SERVER_MAP +/* 014 */ { 0, (char *)NULL }, +/* 015 */ { RPL_MAP, ":%s" }, +/* 016 */ { 0, (char *)NULL }, +/* 017 */ { RPL_MAPEND, ":End of /MAP" }, +/* 018 */ { RPL_MAPSTART, ":%-53s | %s" }, +#endif { 0, (char *)NULL } }; @@ -183,7 +207,11 @@ /* 314 */ { RPL_WHOWASUSER, "%s %s %s * :%s" }, /* 315 */ { RPL_ENDOFWHO, "%s :End of WHO list." }, /* 316 */ { RPL_WHOISCHANOP, (char *)NULL }, +#ifdef WHOIS_SIGNON_TIME +/* 317 */ { RPL_WHOISIDLE, "%s %ld %ld :seconds idle, signon time" }, +#else /* 317 */ { RPL_WHOISIDLE, "%s %ld :seconds idle" }, +#endif /* 318 */ { RPL_ENDOFWHOIS, "%s :End of WHOIS list." }, /* 319 */ { RPL_WHOISCHANNELS, "%s :%s" }, { 0, (char *)NULL }, @@ -199,7 +227,11 @@ { 0, (char *)NULL }, /* 331 */ { RPL_NOTOPIC, "%s :No topic is set." }, /* 332 */ { RPL_TOPIC, "%s :%s" }, +#ifdef TOPICWHOTIME +/* 333 */ { RPL_TOPICWHOTIME, "%s %s %lu" }, +#else { 0, (char *)NULL }, +#endif { 0, (char *)NULL }, { 0, (char *)NULL }, { 0, (char *)NULL }, @@ -217,7 +249,7 @@ /* 348 */ { RPL_EXCEPTLIST, "%s %s" }, /* 349 */ { RPL_ENDOFEXCEPTLIST, "%s :End of Channel Exception List" }, { 0, (char *)NULL }, -/* 351 */ { RPL_VERSION, "%s.%s %s :%s" }, +/* 351 */ { RPL_VERSION, "%s%s.%s %s :%s" }, /* 352 */ { RPL_WHOREPLY, "%s %s %s %s %s %s :%d %s" }, /* 353 */ { RPL_NAMREPLY, "%s" }, { 0, (char *)NULL }, @@ -247,7 +279,8 @@ { 0, (char *)NULL }, { 0, (char *)NULL }, { 0, (char *)NULL }, -/* 381 */ { RPL_YOUREOPER, ":You are now an IRC Operator" }, +/* 381 */ { RPL_YOUREOPER, ":You are now known as an IRC supermouse\ + ~(,,^>." }, /* 382 */ { RPL_REHASHING, "%s :Rehashing" }, /* 383 */ { RPL_YOURESERVICE, ":You are service %s" }, /* 384 */ { RPL_MYPORTIS, "%d :Port to local server is\r\n" }, @@ -293,7 +326,7 @@ /* 217 */ { RPL_STATSQLINE, "%c %s %s %s %d %d" }, /* 218 */ { RPL_STATSYLINE, "%c %d %d %d %d %ld %d.%d %d.%d" }, /* 219 */ { RPL_ENDOFSTATS, "%c :End of STATS report" }, - { 0, (char *)NULL }, +/* 220 */ { RPL_STATSPLINE, "%c %d %s %d :%s %s" }, /* 221 */ { RPL_UMODEIS, "%s" }, { 0, (char *)NULL }, { 0, (char *)NULL }, @@ -338,7 +371,13 @@ /* 261 */ { RPL_TRACELOG, "File %s %d" }, /* 262 */ { RPL_TRACEEND, "%s %s.%s :End of TRACE" }, /* 263 */ { RPL_TRYAGAIN, "%s :Please wait a while and try again." }, +#ifdef EXTRA_STATISTICS + { 0, (char *)NULL }, +/* 265 */ { RPL_LOCALUSERS, ":Current local users: %d Max: %d" }, +/* 266 */ { RPL_GLOBALUSERS, ":Current global users: %d Max: %d" } +#else { 0, (char *)NULL } +#endif }; char *err_str(numeric, to) diff -ru --new-file irc2.10.3p3/ircd/s_externs.h irc2.10.3p3+sd7/ircd/s_externs.h --- irc2.10.3p3/ircd/s_externs.h Wed May 6 02:30:20 1998 +++ irc2.10.3p3+sd7/ircd/s_externs.h Mon Feb 3 14:31:07 2003 @@ -51,3 +51,4 @@ #include "support_ext.h" #include "version_ext.h" #include "whowas_ext.h" +#include "s_ssl.h" diff -ru --new-file irc2.10.3p3/ircd/s_id.c irc2.10.3p3+sd7/ircd/s_id.c --- irc2.10.3p3/ircd/s_id.c Sun May 13 22:27:14 2001 +++ irc2.10.3p3+sd7/ircd/s_id.c Mon Feb 3 14:31:07 2003 @@ -63,9 +63,8 @@ -1, -1, -1, -1, -1, -1, -1 }; /* ltoid: base 10 -> base 36 conversion */ -static char * -ltoid(l) -time_t l; +char * ltoid(l) +unsigned int l; { static char idrpl[CHIDLEN+1]; char c = CHIDLEN-1; diff -ru --new-file irc2.10.3p3/ircd/s_misc.c irc2.10.3p3+sd7/ircd/s_misc.c --- irc2.10.3p3/ircd/s_misc.c Fri Oct 19 21:44:27 2001 +++ irc2.10.3p3+sd7/ircd/s_misc.c Mon Feb 3 14:31:07 2003 @@ -370,7 +370,11 @@ { if (sptr->flags & FLAGS_KILLED) { +#ifdef LOCAL_REJECTIONS_ONLY + sendto_flag(SCH_NOTICE, "Killed: %s.", +#else sendto_flag(SCH_LOCAL, "Killed: %s.", +#endif get_client_name(sptr, TRUE)); sptr->exitc = EXITC_KILL; } @@ -386,6 +390,11 @@ sendto_flog(sptr, NULL, sptr->user->username, sptr->user->host); # endif +#ifdef CLIENTS_CHANNEL + sendto_flag(SCH_CLIENTS, "Client exiting: %s was %s from %s reason: %s", + sptr->name,sptr->user->username,sptr->user->host,comment); + +#endif } else if (sptr->exitc != EXITC_REF && sptr->exitc != EXITC_AREF) { @@ -408,16 +417,30 @@ istat.is_myservice--; else istat.is_unknown--; - - if (cptr != NULL && sptr != cptr) - sendto_one(sptr, "ERROR :Closing Link: %s %s (%s)", - get_client_name(sptr,FALSE), - cptr->name, comment); - else - sendto_one(sptr, "ERROR :Closing Link: %s (%s)", - get_client_name(sptr,FALSE), comment); - - if (sptr->auth != sptr->username) +#ifdef DELAY_CLOSE + if (cptr && cptr->user && (cptr->user->flags + & FLAGS_BADBOY)) + { + SPRINTF(cptr->buffer, "ERROR :Closing Link: %s (%s)", + get_client_name(sptr,FALSE), comment); + } + else +#endif + { + if (cptr != NULL && sptr != cptr) + { + sendto_one(sptr, "ERROR :Closing Link: %s %s (%s)", + get_client_name(sptr,FALSE), + cptr->name, comment); + } + else + { + sendto_one(sptr, "ERROR :Closing Link: %s (%s)", + get_client_name(sptr,FALSE), comment); + + } + } + if (sptr->auth != sptr->username) { istat.is_authmem -= strlen(sptr->auth) + 1; istat.is_auth -= 1; @@ -504,6 +527,15 @@ } } } /* If (IsServer(sptr)) */ +#ifdef SPLIT_HANDLE + if ((istat.is_user[0] + istat.is_user[1]) < SPLIT_USERS || istat.is_eobservers < SPLIT_SERV) + { + if (!iconf.split) + { + check_split(); + } + } +#endif } /* if (MyConnect(sptr) || (sptr->flags & FLAGS_HELD)) */ if (IsServer(sptr) && GotDependantClient(sptr)) @@ -531,6 +563,16 @@ acptr->flags |= flags; exit_one_client(cptr, acptr, &me, comment1); } +#ifdef SPLIT_HANDLE + if ((istat.is_user[0] + istat.is_user[1]) < SPLIT_USERS || istat.is_eobservers < SPLIT_SERV) + { + if (!iconf.split) + { + check_split(); + } + } +#endif + } /* @@ -604,13 +646,65 @@ "ERROR: tried to exit me! : %s", comment); return; /* ...must *never* exit self!! */ } - else if (IsServer(sptr)) { + else if (IsServer(sptr)) + { + Link *lpu,**tmp; + aClient *auptr; + int dcnt = 0; + + /* ** Old sendto_serv_but_one() call removed because we now ** need to send different names to different servers ** (domain name matching) */ istat.is_serv--; +#ifdef SPLIT_HANDLE + if (!IsBurst(sptr)) + { + istat.is_eobservers--; + } +#endif + /* we have also remove the server from ->down */ + auptr = find_client(sptr->serv->up,NULL); + /* hmm.. if it doesn't exist, it means it squitted before */ + if (auptr) + { + lpu = auptr->serv->down; + if (lpu) + { + dcnt = --lpu->flags; + } + for (tmp = &(auptr->serv->down); (lpu = *tmp); tmp = &lpu->next) + { + if (lpu->value.cptr == sptr) + { + *tmp = lpu->next; + free_link(lpu); + break; + } + } + if (auptr->serv->down) + { + auptr->serv->down->flags = dcnt; + } + } + /* and free my downlinks. The squit code is SOOO broken btw */ + if (sptr->serv->down) + { + Link *lp2; + lp2 = sptr->serv->down; + while (lp2) + { + lpu = lp2; + lp2 = lp2->next; + free_link(lpu); + } + sptr->serv->down = NULL; + } +#ifdef EXTRA_STATISTICS + save_server_max(sptr->name,sptr->serv->usermax); +#endif for (i = fdas.highest; i >= 0; i--) { Reg aConfItem *aconf; @@ -696,11 +790,21 @@ if (sptr->user) { if (IsInvisible(sptr)) + { istat.is_user[1]--; - else - istat.is_user[0]--; + sptr->user->servp->usercnt[1]--; + } + else + { + sptr->user->servp->usercnt[0]--; + istat.is_user[0]--; + } + if (IsAnOper(sptr)) + { istat.is_oper--; + sptr->user->servp->usercnt[2]--; + } sendto_common_channels(sptr, ":%s QUIT :%s", sptr->name, comment); @@ -745,6 +849,8 @@ add_history(sptr, (sptr == cptr) ? &me : NULL); #endif off_history(sptr); + del_from_hostname_hash_table(sptr->user->host,sptr->user); + } } else if (sptr->name[0] && IsService(sptr)) @@ -825,16 +931,33 @@ istat.is_serv = 1; istat.is_remc = 1; /* don't ask me why, I forgot. */ bzero((char *)&ircst, sizeof(ircst)); + + bzero((char *)&iconf, sizeof(iconf)); + iconf.aconnect = 1; + iconf.split = 1; +#ifdef DELAY_ACCEPT + iconf.caccept = 2; +#endif } +#ifdef EXTRA_STATISTICS +void tstats(cptr, name, level) +aClient *cptr; +char *name; +int level; +#else void tstats(cptr, name) aClient *cptr; char *name; +#endif { Reg aClient *acptr; Reg int i; Reg struct stats *sp; struct stats tmp; +#ifdef EXTRA_STATISTICS + Reg time_t now; +#endif sp = &tmp; bcopy((char *)ircstp, (char *)sp, sizeof(*sp)); @@ -884,6 +1007,173 @@ sp->is_ni++; } +#ifdef EXTRA_STATISTICS + switch (level) { + case 2: now = timeofday - me.since; + if (now == 0) + now = 1; + + sendto_one(cptr, + ":%s %d %s :------------------------------------------------------", + ME, RPL_STATSDEBUG, name); + sendto_one(cptr, + ":%s %d %s :Current uptime: %4d day%s, %2d:%02d:%02d%s %10d s", + ME, RPL_STATSDEBUG, name, now/86400, ( now/86400 == 1 ? "" : "s"), + (now/3600)%24, (now/60)%60, now%60, ( now/86400 == 1 ? " " : ""), now); + sendto_one(cptr, + ":%s %d %s :------------------------------------------------------", + ME, RPL_STATSDEBUG, name); + sendto_one(cptr, + ":%s %d %s :Connected Current Highest Average Total NetHigh", + ME, RPL_STATSDEBUG, name); + sendto_one(cptr, + ":%s %d %s :Clients: %6u %8u %8.1f %8u %8u", + ME, RPL_STATSDEBUG, name, istat.is_myclnt, istat.is_m_myclnt, + (float )((double ) sp->is_cti / (double ) (now)), sp->is_cl, + istat.is_m_users); + if (istat.is_m_myservice != 0) + sendto_one(cptr, + ":%s %d %s :Services: %6u %8u %8u", + ME, RPL_STATSDEBUG, name, istat.is_myservice, + istat.is_m_myservice, istat.is_m_service); + sendto_one(cptr, + ":%s %d %s :Servers: %6u %8u %8.1f %8u %8u", + ME, RPL_STATSDEBUG, name, istat.is_myserv, istat.is_m_myserv, + ((float ) sp->is_sti / (float ) (now)), sp->is_sv, istat.is_m_serv); + sendto_one(cptr, + ":%s %d %s :------------------------------------------------------", + ME, RPL_STATSDEBUG, name); + sendto_one(cptr, + ":%s %d %s :Duration Average Total", + ME, RPL_STATSDEBUG, name); + sendto_one(cptr, + ":%s %d %s :Clients: %4d:%02d:%02d %12lu s", + ME, RPL_STATSDEBUG, name, + ((sp->is_cti / (sp->is_cl ? sp->is_cl : 1))/3600), + (((sp->is_cti / (sp->is_cl ? sp->is_cl : 1))/60)%60), + ((sp->is_cti / (sp->is_cl ? sp->is_cl : 1))%60), sp->is_cti); + sendto_one(cptr, + ":%s %d %s :Servers: %4d:%02d:%02d %12lu s", + ME, RPL_STATSDEBUG, name, + ((sp->is_sti / (sp->is_sv ? sp->is_sv : 1))/3600), + (((sp->is_sti / (sp->is_sv ? sp->is_sv : 1))/60)%60), + ((sp->is_sti / (sp->is_sv ? sp->is_sv : 1))%60), sp->is_sti); + sendto_one(cptr, + ":%s %d %s :------------------------------------------------------", + ME, RPL_STATSDEBUG, name); + sendto_one(cptr, + ":%s %d %s :Data received Average Rate Total", + ME, RPL_STATSDEBUG, name); + sendto_one(cptr, + ":%s %d %s :Clients: %8lu Kb %6.2f Kb/s %10lu Kb", + ME, RPL_STATSDEBUG, name, (sp->is_ckr / ( sp->is_cl ? sp->is_cl : 1 )), + ((double ) sp->is_ckr / (double ) (now)), sp->is_ckr); + sendto_one(cptr, + ":%s %d %s :Servers: %8lu Kb %6.2f Kb/s %10lu Kb", + ME, RPL_STATSDEBUG, name, + ( sp->is_skr / ( sp->is_sv ? sp->is_sv : 1 )), + (float )((double ) sp->is_skr / (double ) (now)), sp->is_skr); + sendto_one(cptr, + ":%s %d %s :UDP: %8u", + ME, RPL_STATSDEBUG, name, sp->is_udpok); + sendto_one(cptr, + ":%s %d %s :------------------------------------------------------", + ME, RPL_STATSDEBUG, name); + sendto_one(cptr, + ":%s %d %s :Data sent Average Rate Total", + ME, RPL_STATSDEBUG, name); + sendto_one(cptr, + ":%s %d %s :Clients: %8lu Kb %6.2f Kb/s %10lu Kb", + ME, RPL_STATSDEBUG, name, (sp->is_cks / (sp->is_cl ? sp->is_cl : 1)), + (float )((double ) sp->is_cks / (double ) (now)), sp->is_cks); + sendto_one(cptr, + ":%s %d %s :Servers: %8lu Kb %6.2f Kb/s %10lu Kb", + ME, RPL_STATSDEBUG, name, (sp->is_sks / (sp->is_sv ? sp->is_sv : 1)), + (float )((double ) sp->is_sks / (double ) (now)), sp->is_sks); + sendto_one(cptr, + ":%s %d %s :------------------------------------------------------", + ME, RPL_STATSDEBUG, name); + return; + + case 1: sendto_one(cptr, + ":%s %d %s :------------------------------------------------------", + ME, RPL_STATSDEBUG, name); +#if !defined(USE_IAUTH) + sendto_one(cptr, + ":%s %d %s :Authorization fails: %8lu", + ME, RPL_STATSDEBUG, name, sp->is_abad); + sendto_one(cptr, + ":%s %d %s :Authorization successes: %8lu", + ME, RPL_STATSDEBUG, name, sp->is_asuc); +#endif + sendto_one(cptr, + ":%s %d %s :Connections accepted: %8lu", + ME, RPL_STATSDEBUG, name, sp->is_ac); + sendto_one(cptr, + ":%s %d %s :Connections refused: %8lu", + ME, RPL_STATSDEBUG, name, sp->is_ref); + sendto_one(cptr, + ":%s %d %s :Local connections made: %8lu", + ME, RPL_STATSDEBUG, name, sp->is_loc); + sendto_one(cptr, + ":%s %d %s :------------------------------------------------------", + ME, RPL_STATSDEBUG, name); + sendto_one(cptr, + ":%s %d %s :Fakes: %8lu", + ME, RPL_STATSDEBUG, name, sp->is_fake); + sendto_one(cptr, + ":%s %d %s :Nick Collisions: %8lu", + ME, RPL_STATSDEBUG, name, sp->is_kill); + sendto_one(cptr, + ":%s %d %s :Unknown connections dropped: %8lu", + ME, RPL_STATSDEBUG, name, sp->is_ni); + sendto_one(cptr, + ":%s %d %s :Users without servers: %8lu", + ME, RPL_STATSDEBUG, name, sp->is_nosrv); + sendto_one(cptr, + ":%s %d %s :Empty messages: %8lu", + ME, RPL_STATSDEBUG, name, sp->is_empt); + sendto_one(cptr, + ":%s %d %s :Numerics seen: %8lu", + ME, RPL_STATSDEBUG, name, sp->is_num); + sendto_one(cptr, + ":%s %d %s :Unknown commands: %8lu", + ME, RPL_STATSDEBUG, name, sp->is_unco); + sendto_one(cptr, + ":%s %d %s :Unknown prefixes: %8lu", + ME, RPL_STATSDEBUG, name, sp->is_unpf); + sendto_one(cptr, + ":%s %d %s :Wrong directions: %8lu", + ME, RPL_STATSDEBUG, name, sp->is_wrdi); + sendto_one(cptr, + ":%s %d %s :------------------------------------------------------", + ME, RPL_STATSDEBUG, name); + sendto_one(cptr, + ":%s %d %s :Elapsed time Minimum Average Maximum Limit", + ME, RPL_STATSDEBUG, name); + sendto_one(cptr, + ":%s %d %s :Nick Delay: %8lu %8lu %8lu %8lu", + ME, RPL_STATSDEBUG, name, sp->is_wwmt, + (u_int) (sp->is_wwt / (sp->is_wwcnt ? sp->is_wwcnt : 1 )), + sp->is_wwMt, KILLCHASETIMELIMIT); + sendto_one(cptr, + ":%s %d %s :Whowas: %8lu %8lu %8lu %8lu", + ME, RPL_STATSDEBUG, name, sp->is_lkmt, + (u_int) (sp->is_lkt / (sp->is_lkcnt ? sp->is_lkcnt : 1)), + sp->is_lkMt, DELAYCHASETIMELIMIT); + sendto_one(cptr, + ":%s %d %s :------------------------------------------------------", + ME, RPL_STATSDEBUG, name); +#if defined(USE_IAUTH) + report_iauth_stats(cptr, name); + sendto_one(cptr, + ":%s %d %s :------------------------------------------------------", + ME, RPL_STATSDEBUG, name); +#endif + return; + } +#endif + sendto_one(cptr, ":%s %d %s :accepts %lu refused %lu", ME, RPL_STATSDEBUG, name, sp->is_ac, sp->is_ref); sendto_one(cptr, ":%s %d %s :unknown: commands %lu prefixes %lu", @@ -931,6 +1221,13 @@ sp->is_ckr, sp->is_cbr, sp->is_skr, sp->is_sbr); sendto_one(cptr, ":%s %d %s :time connected %lu %lu", ME, RPL_STATSDEBUG, name, sp->is_cti, sp->is_sti); +#ifdef DELAY_CLOSE + if (IsAnOper(cptr)) + { + sendto_one(cptr, ":%s %d %s :delay closed %lu", + ME,RPL_STATSDEBUG, name, istat.is_delayclosed); + } +#endif #if defined(USE_IAUTH) report_iauth_stats(cptr, name); #endif @@ -986,3 +1283,339 @@ close(fd); } #endif + + +#if defined(OPER_KLINE) || defined(LOCOP_KLINE) +int m_kline(cptr,sptr,parc,parv) +aClient *cptr, *sptr; +int parc; +char *parv[]; +{ + +#if defined(OPER_KLINE) && defined(LOCOP_KLINE) + if (!MyClient(sptr) || !IsAnOper(sptr)) +#else +# if defined(OPER_KLINE) + if (!MyClient(sptr) || !IsOper(sptr)) +# else + if (!MyClient(sptr) || !IsLocOp(sptr)) +# endif +#endif + { + sendto_one(sptr, err_str(ERR_NOPRIVILEGES, parv[0]), me.name, + parv[0]); + return 0; + } + + return m_dokline(cptr,sptr,parc,parv,1); +} +#endif + + +#if defined(OPER_TKLINE) || defined(LOCOP_TKLINE) +int m_tkline(cptr,sptr,parc,parv) +aClient *cptr, *sptr; +int parc; +char *parv[]; +{ + +#if defined(OPER_TKLINE) && defined(LOCOP_TKLINE) + if (!MyClient(sptr) || !IsAnOper(sptr)) +#else +# if defined(OPER_TKLINE) + if (!MyClient(sptr) || !IsOper(sptr)) +# else + if (!MyClient(sptr) || !IsLocOp(sptr)) +# endif +#endif + { + sendto_one(sptr, err_str(ERR_NOPRIVILEGES, parv[0]), me.name, + parv[0]); + return 0; + } + + return m_dokline(cptr,sptr,parc,parv,0); +} +#endif + + +#if defined(OPER_KLINE) || defined(LOCOP_KLINE) || \ + defined(OPER_TKLINE) || defined(LOCOP_TKLINE) +extern int kline_added; + +int m_dokline(cptr, sptr, parc, parv, perm) +aClient *cptr, *sptr; +int parc; +char *parv[]; +int perm; +{ + aConfItem *aconf; + aClient *acptr; + int out, i; + char buffer[1024]; + char *user, *host; + char kline_reason[256]; + time_t current_time; + + if (parc < 3) + { + sendto_one(sptr, ":%s NOTICE %s :Not enough parameters", + me.name, parv[0]); + return 0; + } + + if (match("*@*", parv[1])) + { + sendto_one(sptr, + ":%s NOTICE %s :Sorry but \"%s\" needs to be of the format\ + of user@host", me.name, parv[0], parv[1]); + return 0; + } + + user = parv[1]; + while (*user) + { + if ((*user == ' ') || (*user =='#') || +#ifdef INET6 + (*user == '%') +#else + (*user == ':') +#endif + ) + break; + user++; + } + + if (*user && (*user != ' ')) + { + sendto_one(sptr, + ":%s NOTICE %s :The user@host may not contain '%c'", + me.name, parv[0], *user); + return 0; + } + + host = strchr(parv[1], '@'); + *(host++) = '\0'; + + if ((user = strchr(host, ' ')) != NULL) + *user = '\0'; + user = parv[1]; + + if (!match(user, "dummyuser") && !match(host, "dumm.ystring.xx")) + { + sendto_one(sptr, + ":%s NOTICE %s :Sorry can not %skline *@*", + me.name, parv[0], ( perm ? "" : "t" )); + return 0; + } + + kline_reason[0] = '\0'; + if (isdigit(*parv[2])) + { + sendto_one(sptr, + ":%s NOTICE %s :The %skline reason may not start\ + with a digit", + me.name, parv[0], ( perm ? "" : "t" )); + return 0; + } + + for (i = 2; i < parc; i++) + { + if (strlen(parv[i]) + strlen(kline_reason) + 2 < 256) + { + strcat(kline_reason, parv[i]); + strcat(kline_reason, "\240"); + } + } + kline_reason[strlen(kline_reason) - 1] = '\0'; + + for (i = strlen(kline_reason) - 1; i >= 0; i--) + { + if ((kline_reason[i] == '#') || +#ifdef INET6 + (kline_reason[i] == '%') +#else + (kline_reason[i] == ':') +#endif + ) + { + sendto_one(sptr, + ":%s NOTICE %s :The %skline reason may not\ + contain '%c'", + me.name, parv[0], ( perm ? "" : "t" ), + kline_reason[i]); + return 0; + } + } + + aconf = make_conf(); + aconf->status = CONF_KILL; + DupString(aconf->host, host); + DupString(aconf->passwd, kline_reason); + DupString(aconf->name, user); + aconf->port = 0; + Class(aconf) = find_class(0); + aconf->next = kconf; + kconf = aconf; + aconf = NULL; + + kline_added = 1; + rehashed = 1; + + if (perm) + { + if ((out = open(KLINE_FILE, O_WRONLY|O_APPEND))==-1) + { + sendto_one(sptr, + ":%s NOTICE %s :Problem opening server configfile", + me.name, parv[0]); + return 0; + } + + time(¤t_time); + + sprintf(buffer, "# Added by %s (%s@%s) on %s", + sptr->name, sptr->user->username, sptr->user->host, + asctime(localtime(¤t_time))); + if (write(out, buffer, strlen(buffer)) <= 0) + { + sendto_one(sptr, + ":%s NOTICE %s :Problem writing to the configfile", + me.name, parv[0]); + close(out); + return 0; + } + +#ifdef INET6 + sprintf(buffer, "K%%%s%%%s%%%s%%\n\n", host, kline_reason, user); +#else + sprintf(buffer, "K:%s:%s:%s:\n\n", host, kline_reason, user); +#endif + if (write(out, buffer, strlen(buffer)) <= 0) + { + sendto_one(sptr, + ":%s NOTICE %s :Problem writing to the configfile", + me.name, parv[0]); + close(out); + return 0; + } + close(out); + } + + sendto_flag(SCH_LOCAL, "%s added a %skline for %s@%s with reason: %s", + parv[0], ( perm ? "" : "t" ), user, host, kline_reason); + sendto_one(sptr, + ":%s NOTICE %s :Added %skline for %s@%s%s with reason: %s", + me.name, parv[0], ( perm ? "" : "t" ), user, host, + ( perm ? " to the server configfile" : "" ), kline_reason); +#if defined(USE_SYSLOG) && defined(SYSLOG_KLINE) + syslog(LOG_INFO, "%s!%s@%s %skline %s@%s (%s)", + sptr->name, sptr->user->username, sptr->user->host, + ( perm ? "" : "t" ), user, host, kline_reason); +#endif + + + return 0; +} +#endif + +#ifdef EXTRA_STATISTICS +static Link *saved_servers = NULL; +void save_server_max(server,clients) +char *server; +int clients; +{ + Link *lp; + char *servername; + + for (lp = saved_servers; lp ; lp = lp->next) + { + if (!mycmp(lp->value.cp,server)) + { + sendto_flag(SCH_ERROR,"Tried to save server's user maximum for already saved server"); + return; + } + } + + servername = mystrdup(server); + lp = make_link(); + lp->value.cp = servername; + lp->flags = clients; + lp->next = saved_servers; + saved_servers = lp; +} + + +int restore_server_max(server) +char *server; +{ + Link *lp, **curr; + int users = 0; + + for (curr = &saved_servers ; (lp = *curr); curr = &lp->next) + { + if (!mycmp(lp->value.cp,server)) + { + users = lp->flags; + *curr = lp->next; + free_link(lp); + break; + } + } + return users; +} +#endif + +#ifdef SPLIT_HANDLE +void check_split() +{ + if (istat.is_eobservers < SPLIT_SERV || + (istat.is_user[0] + istat.is_user[1] < SPLIT_USERS)) + { + if (!iconf.split) + { + sendto_flag(SCH_NOTICE,"Network split detected, split mode activated"); + } + iconf.split = 1; + } + else + { + if (iconf.split) + { + sendto_flag(SCH_NOTICE,"Network rejoined, split mode deactivated"); +#ifdef DELAY_ACCEPT + if (iconf.caccept == 1) + { + activate_delayed_listeners(); + iconf.caccept = 2; + } +#endif + } + iconf.split = 0; + + } + +} +void bubble_eob(sptr) +aClient *sptr; +{ + aClient *acptr = sptr; + char *up = sptr->serv->up; + while (up && mycmp(up,me.name)) + { + up = acptr->serv->up; + acptr = find_server(up,NULL); + if (!acptr) + { + sendto_flag(SCH_ERROR,"Unknown uplink %s while bubbling EOB ?!",up); + break; + } + if (IsBurst(acptr)) + { + ClearBurst(acptr); + istat.is_eobservers++; + sendto_flag(SCH_DEBUG,"EOB from %s (bubbled)",up); + } + } +} +#endif diff -ru --new-file irc2.10.3p3/ircd/s_misc_ext.h irc2.10.3p3+sd7/ircd/s_misc_ext.h --- irc2.10.3p3/ircd/s_misc_ext.h Mon Aug 3 17:09:23 1998 +++ irc2.10.3p3+sd7/ircd/s_misc_ext.h Mon Feb 3 14:31:07 2003 @@ -51,8 +51,27 @@ char *comment)); EXTERN void checklist(); EXTERN void initstats(); +#ifdef EXTRA_STATISTICS +EXTERN void tstats __P((aClient *cptr, char *name, int level)); +#else EXTERN void tstats __P((aClient *cptr, char *name)); +#endif #ifdef CACHED_MOTD EXTERN void read_motd __P((char *filename)); #endif /* CACHED_MOTD */ +#if defined(OPER_KLINE) || defined(LOCOP_KLINE) +EXTERN int m_kline __P((aClient *cptr, aClient *sptr, int parc, char *parv[])); +#endif +#if defined(OPER_TKLINE) || defined(LOCOP_TKLINE) +EXTERN int m_tkline __P((aClient *cptr, aClient *sptr, int parc, + char *parv[])); +#endif +#ifdef EXTRA_STATISTICS +EXTERN void save_server_max __P((char *server,int clients)); +EXTERN int restore_server_max __P((char *server)); +#endif +#ifdef SPLIT_HANDLE +EXTERN void check_split(); +EXTERN void bubble_eob __P((aClient *sptr)); +#endif #undef EXTERN diff -ru --new-file irc2.10.3p3/ircd/s_numeric.c irc2.10.3p3+sd7/ircd/s_numeric.c --- irc2.10.3p3/ircd/s_numeric.c Sun Dec 13 01:48:17 1998 +++ irc2.10.3p3+sd7/ircd/s_numeric.c Mon Feb 3 14:31:07 2003 @@ -82,7 +82,8 @@ } for (; (nick = strtoken(&p, parv[1], ",")); parv[1] = NULL) { - if ((acptr = find_client(nick, (aClient *)NULL))) + if ((acptr = find_client(nick, (aClient *)NULL)) || + (acptr = find_server(nick, NULL))) { /* ** Drop to bit bucket if for me... @@ -96,11 +97,27 @@ ** - Avalon */ if (IsMe(acptr) || acptr->from == cptr) + { +#ifdef SPLIT_HANDLE + if (IsServer(sptr) && IsBurst(sptr) && + numeric == ERR_NOSUCHSERVER) + { /* we got EOB-emulation reply */ + ClearBurst(sptr); + sendto_flag(SCH_DEBUG,"End of burst from %s (emulated)",sptr->name); + istat.is_eobservers++; + bubble_eob(sptr); + check_split(); + } + else +#endif + { sendto_flag(SCH_NUM, "From %s for %s: %s %d %s %s.", get_client_name(cptr, TRUE), acptr->name, sptr->name, numeric, nick, buffer); + } + } else if (IsPerson(acptr) || IsServer(acptr) || IsService(acptr)) sendto_prefix_one(acptr, sptr,":%s %d %s%s", diff -ru --new-file irc2.10.3p3/ircd/s_serv.c irc2.10.3p3+sd7/ircd/s_serv.c --- irc2.10.3p3/ircd/s_serv.c Sat Oct 20 00:09:10 2001 +++ irc2.10.3p3+sd7/ircd/s_serv.c Mon Feb 3 14:31:07 2003 @@ -92,6 +92,10 @@ ** non-NULL pointers. */ +#ifdef RECOVER +extern char md5me[RECOVER_SMDLEN]; +#endif + /* ** m_version ** parv[0] = sender prefix @@ -104,7 +108,7 @@ { if (hunt_server(cptr,sptr,":%s VERSION :%s",1,parc,parv)==HUNTED_ISME) sendto_one(sptr, rpl_str(RPL_VERSION, parv[0]), - version, debugmode, ME, serveropts); + version, APPEND_VERSION, debugmode, ME, serveropts); return 2; } @@ -435,7 +439,21 @@ get_client_name(cptr, TRUE)); return 2; } - + +#ifdef RECOVER + { + char buf[RECOVER_SMDLEN]; + md_server_name(buf, host, info); + if (!memcmp(buf, md5me, RECOVER_SMDLEN)) { + sendto_one(sptr, "ERROR :Server name hash conflict - try change server hostname/realname", + host, me, buf); + sendto_flag(SCH_ERROR, "Server name hash conflict %s/%s == %s/%s (%s)", + host, info, me.name, me.info, buf); + return exit_client(cptr, cptr, &me, "Server name hash conflict"); + } + } +#endif + /* *WHEN* can it be that "cptr != sptr" ????? --msa */ /* When SERVER command (like now) has prefix. -avalon */ @@ -500,7 +518,11 @@ /* A server can only be introduced by another server. */ if (!IsServer(sptr)) { - sendto_flag(SCH_LOCAL, +#ifdef LOCAL_REJECTIONS_ONLY + sendto_flag(SCH_NOTICE, +#else + sendto_flag(SCH_LOCAL, +#endif "Squitting %s brought by %s (introduced by %s)", host, get_client_name(cptr, FALSE), sptr->name); @@ -588,11 +610,38 @@ if (acptr->info != DefInfo) MyFree(acptr->info); acptr->info = mystrdup(info); - acptr->serv->up = sptr->name; + acptr->serv->up = mystrdup(sptr->name); acptr->serv->stok = token; acptr->serv->snum = find_server_num(acptr->name); SetServer(acptr); istat.is_serv++; +#ifdef EXTRA_STATISTICS + /* + ** Keep track of the highest number of connected + ** servers (hostmasks) to this network. + **/ + if (istat.is_serv > istat.is_m_serv) + istat.is_m_serv = istat.is_serv; + acptr->serv->usermax = restore_server_max(acptr->name); +#endif +#ifdef SPLIT_HANDLE + SetBurst(acptr); + sendto_one(cptr,":%s PING %s :%s",my_name_for_link(ME,cptr->serv->nline->port), + my_name_for_link(ME,cptr->serv->nline->port), + acptr->name); +#endif + /* add server to downlink list */ + { + Link *lp; + + lp = make_link(); + bzero((char *)lp, sizeof(Link)); + lp->value.cptr = acptr; + lp->next = sptr->serv->down; + /* we keep number of downlinks in flags */ + lp->flags = sptr->serv->down ? sptr->serv->down->flags + 1 : 1; + sptr->serv->down = lp; + } add_client_to_list(acptr); (void)add_to_client_hash_table(acptr->name, acptr); (void)add_to_server_hash_table(acptr->serv, cptr); @@ -840,16 +889,50 @@ ** code is more neat this way... --msa */ SetServer(cptr); +#ifdef SPLIT_HANDLE + SetBurst(cptr); +#endif istat.is_unknown--; istat.is_serv++; +#ifdef EXTRA_STATISTICS + /* + ** Keep track of the highest number of connected + ** servers to this network. + **/ + if (istat.is_serv > istat.is_m_serv) + istat.is_m_serv = istat.is_serv; +#endif istat.is_myserv++; +#ifdef EXTRA_STATISTICS + /* + ** Keep track of the highest number of servers which + ** this server has had connected simultaniously. + */ + if (istat.is_myserv > istat.is_m_myserv) + istat.is_m_myserv = istat.is_myserv; +#endif + +#ifdef SERVER_MAP + /* add server to downlink list */ + { + Link *lp; + + lp = make_link(); + bzero((char *)lp, sizeof(Link)); + lp->value.cptr = cptr; + lp->next = me.serv->down; + /* we keep number of downlinks in flags */ + lp->flags = me.serv->down ? me.serv->down->flags + 1 : 1; + me.serv->down = lp; + } +#endif nextping = timeofday; sendto_flag(SCH_NOTICE, "Link with %s established. (%X%s)", inpath, cptr->hopcount, (cptr->flags & FLAGS_ZIP) ? "z" : ""); (void)add_to_client_hash_table(cptr->name, cptr); /* doesnt duplicate cptr->serv if allocted this struct already */ (void)make_server(cptr); - cptr->serv->up = me.name; + cptr->serv->up = mystrdup(me.name); cptr->serv->nline = aconf; cptr->serv->version = cptr->hopcount; /* temporary location */ cptr->hopcount = 1; /* local server connection */ @@ -860,6 +943,9 @@ Debug((DEBUG_NOTICE, "Server link established with %s V%X %d", cptr->name, cptr->serv->version, cptr->serv->stok)); add_fd(cptr->fd, &fdas); +#ifdef EXTRA_STATISTICS + cptr->serv->usermax = restore_server_max(cptr->name); +#endif #ifdef USE_SERVICES check_services_butone(SERVICE_WANT_SERVER, cptr->name, cptr, ":%s SERVER %s %d %s :%s", ME, cptr->name, @@ -987,7 +1073,10 @@ send_channel_modes(cptr, chptr); } } - +#ifdef SPLIT_HANDLE + /* send PING- emulate EOB */ + sendto_one(cptr,":%s PING %s %s",my_name_for_link(ME, aconf->port),my_name_for_link(ME, aconf->port),cptr->name); +#endif cptr->flags &= ~FLAGS_CBURST; #ifdef ZIP_LINKS /* @@ -1062,7 +1151,11 @@ { char **text = infotext; - if (IsServer(cptr) && check_link(cptr)) + if ( +#ifdef NO_OPER_TRYAGAIN + !IsOper(sptr) && +#endif + IsServer(cptr) && check_link(cptr)) { sendto_one(sptr, rpl_str(RPL_TRYAGAIN, parv[0]), "INFO"); @@ -1287,7 +1380,6 @@ { CONF_DENY, RPL_STATSDLINE, 'D'}, { 0, 0, 0} }; - static void report_configured_links(sptr, to, mask) aClient *sptr; char *to; @@ -1295,6 +1387,9 @@ { static char null[] = ""; aConfItem *tmp; +#ifdef ILINE_FLAGS + char nmbuf[HOSTLEN*2]; +#endif int *p, port; char c, *host, *pass, *name; @@ -1303,14 +1398,61 @@ if (tmp->status & mask) { for (p = &report_array[0][0]; *p; p += 3) - if (*p == tmp->status) + if ((*p & tmp->status) && !(*p & CONF_ILLEGAL)) break; if (!*p) continue; c = (char)*(p+2); host = BadPtr(tmp->host) ? null : tmp->host; pass = BadPtr(tmp->passwd) ? NULL : tmp->passwd; - name = BadPtr(tmp->name) ? null : tmp->name; +#ifdef ILINE_FLAGS + if ((tmp->status & (CONF_CLIENT | CONF_RCLIENT)) && + tmp->status & (CONF_EXEMPT|CONF_RNODNS)) + { + if ((tmp->status & CONF_EXEMPT) && + tmp->status & CONF_RNODNS) + { + if (BadPtr(tmp->name)) + { + name = ""; + } + else + { + sprintf(nmbuf,"+<%s",tmp->name); + name = nmbuf; + } + } + else if (tmp->status & CONF_EXEMPT) + { + if (BadPtr(tmp->name)) + { + name = ""; + } + else + { + sprintf(nmbuf,"<%s",tmp->name); + name = nmbuf; + } + + } + else + { + if (BadPtr(tmp->name)) + { + name = ""; + } + else + { + sprintf(nmbuf,"+%s",tmp->name); + name = nmbuf; + } + } + } + else +#endif + { + name = BadPtr(tmp->name) ? null : tmp->name; + } port = (int)tmp->port; /* * On K/V lines the passwd contents can be @@ -1352,7 +1494,162 @@ } return; } +#ifdef STATS_F +static void report_fd(sptr,acptr,to) +aClient *sptr, *acptr; +char *to; +{ + static char locip[100], *ret; + int s; + + if (IsMe(acptr) || !acptr->acpt || !IsRegistered(acptr)) + return; + ret = +#ifdef INET6 + inetntop(AF_INET6, + (char *)&acptr->acpt->ip, + mydummy, MYDUMMY_SIZE), +#else + inetntoa((char *)&acptr->acpt->ip); +#endif + s = strlen(ret) + 1; + memcpy(locip, ret, s < sizeof(locip) ? s : sizeof(locip)); + locip[sizeof(locip) - 1] = 0; + sendto_one(sptr,":%s %d %s %d %s %d %s %d %s %s %d" +#ifdef USE_SSL +" %s" +#endif + , + ME,RPL_STATSLINKINFO,to, + acptr->fd, + locip, + acptr->acpt->port, +#ifdef INET6 + inetntop(AF_INET6, + (char *)&acptr->ip, + mydummy, MYDUMMY_SIZE), +#else +#if defined(OPERS_WATCHING_USERS) && defined(SPOOF) + inetntoa((char *)&acptr->real_ip), +#else + inetntoa((char *)&acptr->ip), +#endif +#endif + acptr->port,acptr->name, + acptr->user ? acptr->user->username : acptr->auth, + acptr->user ? timeofday - acptr->user->last : -1 +#ifdef USE_SSL + ,acptr->ssl ? "|| ssl" : "|| non-ssl" +#endif + ); +} +#endif /* STATS_F */ +#ifdef STATS_QMARK +/* show quick info about connected servers */ +static void report_myservers(sptr,to) +aClient *sptr; +char *to; +{ + int i; + int timeconnected; + aClient *acptr; + aServer *asptr; + int users = 0, servers = 0; + + for (i = fdas.highest; i >= 0; i--) + { + if (!(acptr = local[fdas.fd[i]])) + { + continue; + } + + if (IsMe(acptr) || !IsServer(acptr)) + { + continue; + } + users = 0; + servers = 0; + + timeconnected = timeofday - acptr->firsttime; +#ifdef HUB + for (asptr = svrtop;asptr;asptr = asptr->nexts) + { + if (asptr->bcptr->from == acptr) + { + servers++; + users += asptr->usercnt[0]; + users += asptr->usercnt[1]; + } + } +#else /* !HUB */ + servers = istat.is_serv - 1; + users = istat.is_user[0] + istat.is_user[1]; + users -= istat.is_myclnt; +#endif + sendto_one(sptr,":%s %d %s : %s (%d, %02d:%02d:%02d) %dS %dC %ldkB sent %ldkB recv %ldkB sq%s", + ME,RPL_STATSDEBUG,to,acptr->name, + timeconnected / 86400,(timeconnected % 86400) / 3600, + (timeconnected % 3600)/60, + timeconnected % 60,servers,users,acptr->sendK,acptr->receiveK,(int) ( + (int)DBufLength(&acptr->sendQ) / 1024), +#ifdef SPLIT_HANDLE + IsBurst(acptr) ? " BURST" : "" +#else + "" +#endif + ); + } +} +#endif +#ifdef DELAY_ACCEPT +static void report_listeners(sptr,to) +aClient *sptr; +char *to; +{ + aConfItem *tmp; + int active,comma; + for (tmp = conf; tmp; tmp = tmp->next) + { + if (!(tmp->status & CONF_LISTEN_PORT)) + { + continue; + } + /* this SUUUUX, we need some nice list of all listeners! + * - jv + */ + if (tmp->status & CONF_ACTIVE) + { + active = 1; + } + else + { + active = 0; + } + *buf = 0; + comma = 0; + if (tmp->status & CONF_DELAY) + { + strcat(buf,"delay"); + comma = 1; + } + + if (tmp->status & CONF_SERVERONLY) + { + if (comma) + { + strcat(buf,","); + } + strcat(buf,"server-only"); + } + + sendto_one(sptr,":%s %d %s :%d %s %s",ME,RPL_STATSDEFINE,to, + tmp->port,active ? "active" : "inactive",buf); + + } +} + +#endif int m_stats(cptr, sptr, parc, parv) aClient *cptr, *sptr; int parc; @@ -1369,7 +1666,12 @@ if (IsServer(cptr) && (stat != 'd' && stat != 'p' && stat != 'q' && stat != 's' && stat != 'u' && stat != 'v') && + +#ifndef NO_OPER_TRYAGAIN !((stat == 'o' || stat == 'c') && IsOper(sptr))) +#else + !IsOper(sptr)) +#endif { if (check_link(cptr)) { @@ -1390,14 +1692,35 @@ 2, parc, parv) != HUNTED_ISME) return 5; } - name = (parc > 2) ? parv[2] : ME; cm = (parc > 3) ? parv[3]: name; doall = !match(name, ME) && !match(cm, ME); wilds = index(cm, '*') || index(cm, '?'); + + /* no stats, just dumb client */ + if (parv[1] && !mycmp(parv[1],ME)) + { + return 2; + } + +#ifdef CLIENTS_CHANNEL + if (stat && (sptr->user)) { + sendto_flag(SCH_CLIENTS,"Stats %c by %s from %s on %s", + stat,sptr->name,sptr->user->username,sptr->user->host); + } +#endif switch (stat) { +#ifdef STATS_F + case 'f' : case 'F' : /* send FD list */ + if (!IsOper(sptr) || !MyConnect(sptr)) + { + stat = '*'; + break; + } + stat = 'f'; +#endif case 'L' : case 'l' : /* * send info about connections which match, or all if the @@ -1411,6 +1734,13 @@ { if (!(acptr = local[i])) continue; +#ifdef STATS_F + if (stat == 'f') + { + report_fd(sptr, acptr, parv[0]); + continue; + } +#endif if (IsPerson(acptr) && !(MyConnect(sptr) && IsAnOper(sptr)) && acptr != sptr) continue; @@ -1429,7 +1759,12 @@ else { if ((acptr = find_client(cm, NULL))) - sendto_one(cptr, Lformat, ME, +#ifdef STATS_F + if (stat == 'f') + report_fd(sptr, acptr, parv[0]); + else +#endif + sendto_one(cptr, Lformat, ME, RPL_STATSLINKINFO, parv[0], get_client_name(acptr, isupper(stat)), (int)DBufLength(&acptr->sendQ), @@ -1461,6 +1796,12 @@ CONF_HUB|CONF_LEAF|CONF_DENY); break; case 'I' : case 'i' : /* I (and i) conf lines */ +#ifdef STATS_I_OPERONLY + if (!IsOper(sptr)) { + stat = '*'; + break; + } +#endif report_configured_links(cptr, parv[0], CONF_CLIENT|CONF_RCLIENT); break; @@ -1479,7 +1820,17 @@ case 'o' : case 'O' : /* O (and o) lines */ report_configured_links(cptr, parv[0], CONF_OPS); break; +#ifdef DELAY_ACCEPT + case 'P' : /* port listing */ + if (IsAnOper(sptr)) + { + report_listeners(sptr,parv[0]); + break; + } + case 'p' : /* ircd ping stats */ +#else case 'p' : case 'P' : /* ircd ping stats */ +#endif report_ping(sptr, parv[0]); break; case 'Q' : case 'q' : /* Q lines */ @@ -1491,8 +1842,24 @@ case 'S' : case 's' : /* S lines */ report_configured_links(cptr, parv[0], CONF_SERVICE); break; +#ifdef EXTRA_STATISTICS + case 'T' : /* various statistics for operators only */ + if (MyOper(sptr)) { + tstats(cptr, parv[0], 2); + break; + } + case 't' : /* various statistics for operators only */ + if (MyOper(sptr)) { + tstats(cptr, parv[0], 1); + break; + } + + /* various statistics */ + tstats(cptr, parv[0], 0); +#else case 'T' : case 't' : /* various statistics */ tstats(cptr, parv[0]); +#endif break; case 'U' : case 'u' : /* uptime */ { @@ -1523,6 +1890,11 @@ case 'z' : /* memory use */ count_memory(cptr, parv[0], 0); break; +#ifdef STATS_QMARK + case '?' : + report_myservers(sptr,parv[0]); + break; +#endif default : stat = '*'; break; @@ -1641,122 +2013,118 @@ int parc; char *parv[]; { - int s_count = 0, /* server */ - c_count = 0, /* client (visible) */ - u_count = 0, /* unknown */ - i_count = 0, /* invisible client */ - o_count = 0, /* oparator */ - v_count = 0; /* service */ - int m_client = 0, /* my clients */ - m_server = 0, /* my server links */ - m_service = 0; /* my services */ - aClient *acptr; - + int s_count = 0, /* server */ + c_count = 0, /* visible client */ + u_count = 0, /* unknown */ + i_count = 0, /* invisible client */ + o_count = 0, /* operator */ + v_count = 0; /* service */ + int m_client = 0, /* my clients */ + m_server = 0, /* my server links */ + m_service = 0; /* my services */ + int mask_max = 0; /* max of given mask */ + if (parc > 2) if (hunt_server(cptr, sptr, ":%s LUSERS %s :%s", 2, parc, parv) != HUNTED_ISME) return 3; if (parc == 1 || !MyConnect(sptr)) - { - sendto_one(sptr, rpl_str(RPL_LUSERCLIENT, parv[0]), - istat.is_user[0] + istat.is_user[1], - istat.is_service, istat.is_serv); - if (istat.is_oper) - sendto_one(sptr, rpl_str(RPL_LUSEROP, parv[0]), - istat.is_oper); - if (istat.is_unknown > 0) - sendto_one(sptr, rpl_str(RPL_LUSERUNKNOWN, parv[0]), - istat.is_unknown); - if (istat.is_chan) - sendto_one(sptr, rpl_str(RPL_LUSERCHANNELS, parv[0]), - istat.is_chan); - sendto_one(sptr, rpl_str(RPL_LUSERME, parv[0]), - istat.is_myclnt, istat.is_myservice, - istat.is_myserv); - return 2; - } - (void)collapse(parv[1]); - for (acptr = client; acptr; acptr = acptr->next) - { - if (!IsServer(acptr) && acptr->user) - { - if (match(parv[1], acptr->user->server)) - continue; - } - else - if (match(parv[1], acptr->name)) - continue; + { + s_count = istat.is_serv; + c_count = istat.is_user[0]; + i_count = istat.is_user[1]; + u_count = istat.is_unknown; + o_count = istat.is_oper; + v_count = istat.is_service; + m_client = istat.is_myclnt; + m_server = istat.is_myserv; + m_service = istat.is_myservice; +#ifdef EXTRA_STATISTICS + mask_max = istat.is_m_users; +#endif + } + else + { + aClient *acptr; + aServer *asptr; + aService *svcp; + + (void)collapse(parv[1]); + + /* LUSERS */ + for (asptr = svrtop;asptr;asptr = asptr->nexts) + { + if (!match(parv[1],asptr->bcptr->name)) + { + s_count++; + + c_count += asptr->usercnt[0]; + i_count += asptr->usercnt[1]; + o_count += asptr->usercnt[2]; + /* not exact probably, but oh well... */ +#ifdef EXTRA_STATISTICS + mask_max += asptr->usermax; +#endif + if (IsMe(asptr->bcptr)) + { + m_client = istat.is_myclnt; + m_server = istat.is_myserv; + m_service = istat.is_myservice; + u_count = istat.is_unknown; - switch (acptr->status) + } + } + } + + /* Count services, but only if we found some matching server + * before (to prevent wrong matches on masks like *irc*). - jv + */ + if (s_count) { - case STAT_SERVER: - if (MyConnect(acptr)) - m_server++; - /* flow thru */ - case STAT_ME: - s_count++; - break; - case STAT_SERVICE: - if (MyConnect(acptr)) - m_service++; - v_count++; - break; - case STAT_CLIENT: - if (IsOper(acptr)) - o_count++; -#ifdef SHOW_INVISIBLE_LUSERS - if (MyConnect(acptr)) - m_client++; - if (!IsInvisible(acptr)) - c_count++; - else - i_count++; -#else - if (MyConnect(acptr)) - { - if (IsInvisible(acptr)) - { - if (IsAnOper(sptr)) - m_client++; - } - else - m_client++; - } - if (!IsInvisible(acptr)) - c_count++; - else - i_count++; -#endif - break; - default: - u_count++; - break; - } - } -#ifndef SHOW_INVISIBLE_LUSERS - if (IsAnOper(sptr) && i_count) + for (svcp = svctop;svcp;svcp = svcp->nexts) + { + if (!match(parv[1],svcp->servp->bcptr->name)) + { + v_count++; + } + } + } + } + +#ifndef SHOW_INVISIBLE_LUSERS + if (!IsOper(sptr)) + { + i_count = 0; + } #endif sendto_one(sptr, rpl_str(RPL_LUSERCLIENT, parv[0]), c_count + i_count, v_count, s_count); -#ifndef SHOW_INVISIBLE_LUSERS - else - sendto_one(sptr, rpl_str(RPL_LUSERCLIENT, parv[0]), - c_count, v_count, s_count); -#endif if (o_count) + { sendto_one(sptr, rpl_str(RPL_LUSEROP, parv[0]), o_count); - if (u_count > 0) + } + if (u_count) + { sendto_one(sptr, rpl_str(RPL_LUSERUNKNOWN, parv[0]), u_count); - if ((c_count = count_channels(sptr))>0) - sendto_one(sptr, rpl_str(RPL_LUSERCHANNELS, parv[0]), - count_channels(sptr)); + } + sendto_one(sptr, rpl_str(RPL_LUSERCHANNELS, parv[0]),istat.is_chan); sendto_one(sptr, rpl_str(RPL_LUSERME, parv[0]), m_client, m_service, m_server); +#ifdef EXTRA_STATISTICS + if (m_client) + { + sendto_one(sptr, rpl_str(RPL_LOCALUSERS, parv[0]), + istat.is_myclnt, istat.is_m_myclnt); + } + sendto_one(sptr, rpl_str(RPL_GLOBALUSERS, parv[0]), + c_count + i_count, mask_max); +#endif + return 2; } - + /*********************************************************************** * m_connect() - Added by Jto 11 Feb 1989 ***********************************************************************/ @@ -1787,7 +2155,7 @@ 3,parc,parv) != HUNTED_ISME) return 1; - if (parc < 3 || *parv[1] == '\0') + if (parc < 2 || *parv[1] == '\0') { sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS, parv[0]), "CONNECT"); @@ -1830,18 +2198,34 @@ ** from there, then use the precompiled default. */ tmpport = port = aconf->port; - if ((port = atoi(parv[2])) <= 0) - { + + if (parc > 2) + { + port = atoi(parv[2]); + } + if (parc < 3 || !port) + { + if (tmpport < 0) + { + port = 0 - port; + } + else + { + port = tmpport; + } + + if (!port) + { + sendto_one(sptr, ":%s NOTICE %s :Connect: missing port number", + ME, parv[0]); + return 0; + } + } + if (port < 0) + { sendto_one(sptr, "NOTICE %s :Connect: Illegal port number", parv[0]); - return 0; - } - else if (port <= 0) - { - sendto_one(sptr, ":%s NOTICE %s :Connect: missing port number", - ME, parv[0]); - return 0; - } + } /* ** Notify all operators about remote connect requests */ @@ -1991,6 +2375,14 @@ #ifdef USE_SYSLOG syslog(LOG_INFO, "REHASH From %s\n", get_client_name(sptr, FALSE)); #endif +#ifdef DELAY_CLOSE + if (parc >1 && parv[1] && *parv[1] == 'd') + { + delay_close(-2,NULL); + sendto_flag(SCH_NOTICE, + "%s is forcing closing of delay closed sockets", parv[0]); + } +#endif return rehash(cptr, sptr, (parc > 1) ? ((*parv[1] == 'q')?2:0) : 0); } #endif @@ -2038,171 +2430,236 @@ } #endif -/* -** m_trace -** parv[0] = sender prefix -** parv[1] = servername -*/ -int m_trace(cptr, sptr, parc, parv) -aClient *cptr, *sptr; -int parc; -char *parv[]; +void trace_one(to,sptr,acptr) +char *to; +aClient *sptr,*acptr; { - Reg int i; - Reg aClient *acptr; - aClass *cltmp; - char *tname; - int doall, link_s[MAXCONNECTIONS], link_u[MAXCONNECTIONS]; - int wilds, dow; - - if (parc > 1) - tname = parv[1]; - else - tname = ME; - - switch (hunt_server(cptr, sptr, ":%s TRACE :%s", 1, parc, parv)) - { - case HUNTED_PASS: /* note: gets here only if parv[1] exists */ - { - aClient *ac2ptr; + char *name; + int class; - ac2ptr = next_client(client, parv[1]); - sendto_one(sptr, rpl_str(RPL_TRACELINK, parv[0]), - version, debugmode, tname, ac2ptr->from->name, - ac2ptr->from->serv->version, - (ac2ptr->from->flags & FLAGS_ZIP) ? "z" : "", - timeofday - ac2ptr->from->firsttime, - (int)DBufLength(&ac2ptr->from->sendQ), - (int)DBufLength(&sptr->from->sendQ)); - return 5; - } - case HUNTED_ISME: - break; - default: - return 1; - } - - doall = (parv[1] && (parc > 1)) ? !match(tname, ME): TRUE; - wilds = !parv[1] || index(tname, '*') || index(tname, '?'); - dow = wilds || doall; - - if (doall) { - for (i = 0; i < MAXCONNECTIONS; i++) - link_s[i] = 0, link_u[i] = 0; - for (acptr = client; acptr; acptr = acptr->next) -#ifdef SHOW_INVISIBLE_LUSERS - if (IsPerson(acptr)) - link_u[acptr->from->fd]++; -#else - if (IsPerson(acptr) && - (!IsInvisible(acptr) || IsOper(sptr))) - link_u[acptr->from->fd]++; -#endif - else if (IsServer(acptr)) - link_s[acptr->from->fd]++; - } - - /* report all direct connections */ + name = get_client_name(acptr,FALSE); + class = get_client_class(acptr); - for (i = 0; i <= highest_fd; i++) - { - char *name; - int class; - - if (!(acptr = local[i])) /* Local Connection? */ - continue; - if (IsPerson(acptr) && IsInvisible(acptr) && dow && - !(MyConnect(sptr) && IsAnOper(sptr)) && - !IsAnOper(acptr) && (acptr != sptr)) - continue; - if (!doall && wilds && match(tname, acptr->name)) - continue; - if (!dow && mycmp(tname, acptr->name)) - continue; - name = get_client_name(acptr,FALSE); - class = get_client_class(acptr); - - switch(acptr->status) - { + switch (acptr->status) + { case STAT_CONNECTING: sendto_one(sptr, rpl_str(RPL_TRACECONNECTING, - parv[0]), class, name); - break; + to), class, name); + break; + case STAT_HANDSHAKE: - sendto_one(sptr, rpl_str(RPL_TRACEHANDSHAKE, parv[0]), - class, name); + sendto_one(sptr, rpl_str(RPL_TRACEHANDSHAKE, to), + class, name); break; + case STAT_ME: break; + case STAT_UNKNOWN: - if (IsAnOper(sptr) || (MyPerson(sptr) && SendWallops(sptr))) - sendto_one(sptr, - rpl_str(RPL_TRACEUNKNOWN, parv[0]), + sendto_one(sptr,rpl_str(RPL_TRACEUNKNOWN, to), class, name); break; + case STAT_CLIENT: - /* Only opers see users if there is a wildcard - * but anyone can see all the opers. - */ if (IsAnOper(acptr)) - sendto_one(sptr, - rpl_str(RPL_TRACEOPERATOR, parv[0]), - class, name); - else if (!dow || (MyConnect(sptr) && IsAnOper(sptr))) - sendto_one(sptr, - rpl_str(RPL_TRACEUSER, parv[0]), - class, name); + { + sendto_one(sptr,rpl_str(RPL_TRACEOPERATOR, + to),class, name); + } + else + { + sendto_one(sptr,rpl_str(RPL_TRACEUSER, + to),class, name); + } + break; + case STAT_SERVER: + { + /* we need to count servers/users behind this link */ + int servers = 0, users = 0; + aServer *asptr; + aClient *next; +#ifdef HUB + for (asptr = svrtop;asptr;asptr = asptr->nexts) + { + if (asptr->bcptr->from == acptr) + { + servers++; + users += asptr->usercnt[0]; +#ifdef SHOW_INVISIBLE_LUSERS + users += asptr->usercnt[1]; +#endif + } + } +#else /* !HUB */ + /* we can have only one server linked */ + servers = istat.is_serv - 1; + users = istat.is_user[0]; +#ifdef SHOW_INVISIBLE_LUSERS + users += istat.is_user[1]; + users -= istat.is_myclnt; +#else + users -= me.usercnt[0]; +#endif +#endif /* HUB */ + if (acptr->serv->user) - sendto_one(sptr, rpl_str(RPL_TRACESERVER, - parv[0]), class, link_s[i], - link_u[i], name, acptr->serv->by, - acptr->serv->user->username, - acptr->serv->user->host, - acptr->serv->version, - (acptr->flags & FLAGS_ZIP) ?"z":""); + { + sendto_one(sptr, rpl_str(RPL_TRACESERVER, + to), class, servers, users, name, + acptr->serv->by, acptr->serv->user->username, + acptr->serv->user->host, acptr->serv->version, + (acptr->flags & FLAGS_ZIP) ?"z":""); + } else + { sendto_one(sptr, rpl_str(RPL_TRACESERVER, - parv[0]), class, link_s[i], - link_u[i], name, - *(acptr->serv->by) ? - acptr->serv->by : "*", "*", ME, - acptr->serv->version, - (acptr->flags & FLAGS_ZIP) ?"z":""); break; + to), class, servers, users, name, + *(acptr->serv->by) ? acptr->serv->by : "*", "*", + ME, acptr->serv->version, + (acptr->flags & FLAGS_ZIP) ?"z":""); + } + break; + } case STAT_RECONNECT: - sendto_one(sptr, rpl_str(RPL_TRACERECONNECT, parv[0]), - class, name); + sendto_one(sptr, rpl_str(RPL_TRACERECONNECT, to), + class, name); break; + case STAT_SERVICE: - sendto_one(sptr, rpl_str(RPL_TRACESERVICE, parv[0]), - class, name, acptr->service->type, - acptr->service->wants); + sendto_one(sptr, rpl_str(RPL_TRACESERVICE, to), + class, name, acptr->service->type, + acptr->service->wants); break; + case STAT_LOG: - sendto_one(sptr, rpl_str(RPL_TRACELOG, parv[0]), - ME, acptr->port); + sendto_one(sptr, rpl_str(RPL_TRACELOG, to), + ME, acptr->port); break; + default: /* ...we actually shouldn't come here... --msa */ - sendto_one(sptr, rpl_str(RPL_TRACENEWTYPE, parv[0]), - name); - break; - } - } + sendto_one(sptr, rpl_str(RPL_TRACENEWTYPE, to), + name); + break; + } +} - /* - * Add these lines to summarize the above which can get rather long - * and messy when done remotely - Avalon - */ - if (IsPerson(sptr) && SendWallops(sptr)) - for (cltmp = FirstClass(); doall && cltmp; cltmp = NextClass(cltmp)) - if (Links(cltmp) > 0) - sendto_one(sptr, rpl_str(RPL_TRACECLASS, parv[0]), - Class(cltmp), Links(cltmp)); - sendto_one(sptr, rpl_str(RPL_TRACEEND, parv[0]), tname, version, +/* + * m_trace + * parv[0] = sender prefix + * parv[1] = traced nick/server/service + */ +int m_trace(cptr, sptr, parc, parv) +aClient *cptr, *sptr; +int parc; +char *parv[]; +{ + aClient *acptr; + int maskedserv = 0; + int i = 0; + + if (parc > 1) + { + /* wildcards now allowed only in server/service names */ + acptr = find_matching_client(parv[1],NULL); + if (!acptr) + { + sendto_one(sptr, err_str(ERR_NOSUCHSERVER, + parv[0]), parv[1]); + return 1; + } + if (IsServer(acptr)) + { + if (!match(acptr->name,parv[1])) + { + /* if we are tracing masked server, + * we have to send parv[1], not acptr->name + */ + maskedserv = 1; + } + } + } + else + { + acptr = &me; + } + if (!IsMe(acptr)) + { + if (!MyConnect(acptr) || IsServer(acptr)) + { +#ifdef RESTRICT_RESTRICTED + if (MyConnect(sptr) && IsRestricted(sptr)) + { + sendto_one(sptr,err_str(ERR_RESTRICTED,parv[0])); + return 5; + } +#endif + if (acptr->from == cptr) + { /* eek ?! */ + return 1; + } + /* passthru */ + sendto_one(sptr, rpl_str(RPL_TRACELINK, parv[0]), + version, debugmode, (maskedserv) ? parv[1] : acptr->name, acptr->from->name, + acptr->from->serv->version, + (acptr->from->flags & FLAGS_ZIP) ? "z" : "", + timeofday - acptr->from->firsttime, + (int)DBufLength(&acptr->from->sendQ), + (int)DBufLength(&sptr->from->sendQ)); + sendto_one(acptr,":%s TRACE :%s",sptr->name, (maskedserv) ? parv[1] : acptr->name); + return 5; + } + else + { + /* tracing something local */ + trace_one(parv[0],sptr,acptr); + } + } + else + { + /* well, report everything */ + aClient *a2cptr; + + for (i = 0; i <= highest_fd; i++) + { + if (!(a2cptr = local[i])) + { + continue; + } + if (IsMe(a2cptr)) + { + continue; + } + if (IsPerson(a2cptr) && !(a2cptr == sptr || IsAnOper(a2cptr) || + (IsAnOper(sptr) && MyConnect(sptr))) ) + { + continue; + } + if (IsUnknown(a2cptr) && !((IsAnOper(sptr) || MyClient(sptr)) + && SendWallops(sptr)) ) + { + continue; + } + trace_one(parv[0],sptr,a2cptr); + } + if (IsPerson(sptr) && SendWallops(sptr)) + { + aClass *cltmp; + for (cltmp = FirstClass(); cltmp; cltmp = NextClass(cltmp)) + { + if (Links(cltmp) > 0) + { + sendto_one(sptr, rpl_str(RPL_TRACECLASS, parv[0]), + Class(cltmp), Links(cltmp)); + } + } + } + } + sendto_one(sptr, rpl_str(RPL_TRACEEND, parv[0]), acptr->name, version, debugmode); return 2; - } +} /* ** m_motd @@ -2225,7 +2682,11 @@ struct tm *tm; #endif - if (check_link(cptr)) + if ( +#ifdef NO_OPER_TRYAGAIN + !IsOper(sptr) && +#endif + check_link(cptr)) { sendto_one(sptr, rpl_str(RPL_TRYAGAIN, parv[0]), "MOTD"); return 5; @@ -2345,6 +2806,293 @@ return 0; } #endif +#ifdef SERVER_MAP +static void dump_map(sptr,root,pbuf) +aClient *sptr; +aClient *root; +char *pbuf; +{ + Link *lp; + int cnt,i = 0; + int len; + int pad = 53; /* at which position we add stats */ + int users,max; + aClient *acptr; + + *pbuf= '\0'; + strcat(pbuf,root->name); + len = strlen(buf); + buf[len] = ' '; + if (len < pad ) + { + for (i = len+1 ; i < pad ; i++) + { + buf[i] = '-'; + } + } + if (IsMe(root)) + { + max = istat.is_m_myclnt; + } + else + { + max = root->serv->usermax; + } + users = root->serv->usercnt[0] + root->serv->usercnt[1]; + SPRINTF(buf + pad ," | %5d %4.1f %5d",users, 100 * (float) users / + (float) (istat.is_user[0] + istat.is_user[1]), + max); + + sendto_one(sptr,rpl_str(RPL_MAP,sptr->name),buf); + + i = 1; + if ((lp = root->serv->down)) + { + cnt = lp->flags; + if (cnt) + { + if (pbuf > buf + 3) + { + pbuf[-2] = ' '; + if (pbuf[-3] == '`') + { + pbuf[-3] = ' '; + } + } + } + } + + for (; lp; lp = lp->next) + { + *pbuf = ' '; + if (i < cnt) + { + *(pbuf + 1) = '|'; + } + else + { + *(pbuf + 1) = '`'; + } + + *(pbuf + 2) = '-'; + *(pbuf + 3) = ' '; + acptr = lp->value.cptr; + dump_map(sptr,acptr,pbuf+4); + i++; + } + +} +/* based on ircu's m_map and kreynet's format */ +int m_map(cptr, sptr, parc, parv) +aClient *cptr, *sptr; +int parc; +char *parv[]; +{ +sendto_one(sptr,rpl_str(RPL_MAPSTART,parv[0]),"Server name","Users % Max"); + dump_map(sptr,&me,buf,0); + sendto_one(sptr,rpl_str(RPL_MAPEND,parv[0])); + return 2; +} +#endif +#ifdef OPER_SET +static char *def_values[] = +{ + "OFF", + "ON", + NULL +}; +static char *caccept_values[] = +{ + "OFF", + "SPLIT", + "ON", + NULL +}; +static struct Set_Message set_msgtab[] = +{ + {"ACONNECT",&iconf.aconnect,def_values}, +#ifdef DELAY_ACCEPT + {"CACCEPT",&iconf.caccept,caccept_values}, +#endif + {NULL,NULL,NULL} +}; +static void set_action(option,value) +char *option; +int value; +{ + if (!mycmp(option,"ACONNECT")) + { + if (value == 1) + { + nextconnect = timeofday; + } + } +#ifdef DELAY_ACCEPT + else if (!mycmp(option,"CACCEPT")) + { + if (value == 2) + { + activate_delayed_listeners(); + } + } +#endif +} +int m_set(cptr, sptr, parc, parv) +aClient *cptr, *sptr; +int parc; +char *parv[]; +{ + + struct Set_Message *mptr; + int val,i = 0; + char *endptr; + char **valstr; + char obuf[BUFSIZE]; + + obuf[0] = 0; + + /* query for values */ + if (parc < 2) + { + for (mptr = set_msgtab; mptr->cmd; mptr++) + { + sendto_one(sptr,":%s NOTICE %s :Value of %s is %s",ME,parv[0], + mptr->cmd, mptr->values[*(mptr->value)]); + } + + return 1; + } + + /* query for one value */ + if (parc == 2) + { + for (mptr = set_msgtab; mptr->cmd; mptr++) + { + if (mycmp(parv[1],mptr->cmd)) + { + continue; + } + + sendto_one(sptr,":%s NOTICE %s :Value of %s is %s",ME,parv[0], + mptr->cmd, mptr->values[*(mptr->value)]); + return 1; + } + sendto_one(sptr,":%s NOTICE %s :Unknown option %s",ME,parv[0],parv[1]); + + return 1; + } + /* setting value */ + for (mptr = set_msgtab; mptr->cmd; mptr++) + { + if (!mycmp(parv[1],mptr->cmd)) + { + break; + } + } + if (!mptr->cmd) + { + sendto_one(sptr,":%s NOTICE %s :Unknown option %s",ME,parv[0],parv[1]); + return 1; + } + val = strtol(parv[2],&endptr,10); + + if (endptr != parv[2]) + { + /* ha! a number! */ + if (mptr->values) + { /* value has symbolical names */ + i = 0; + for (valstr = mptr->values; *valstr; valstr++) + { + if (i == val) + { + break; + } + strcat(obuf,*valstr); + strcat(obuf," "); + i++; + } + if (!*valstr) + { + sendto_one(sptr,":%s NOTICE %s :Uknown value %d for option %d, avaible values are %s", + ME,parv[0],val,mptr->cmd,obuf); + return 1; + + } + if (*(mptr->value) == i) + { + sendto_one(sptr,":%s NOTICE %s :Value of %s was already set to %s", + ME,parv[0],mptr->cmd,*valstr); + return 1; + + } + + *(mptr->value) = val; + sendto_one(sptr,":%s NOTICE %s :Value of %s set to %s", + ME,parv[0],mptr->cmd,*valstr); + sendto_flag(SCH_NOTICE,"%s changed value of %s to %s", + parv[0],mptr->cmd,*valstr); + set_action(mptr->cmd,val); + return 1; + } + else + { /* numeric only */ + if (*(mptr->value) == val) + { + sendto_one(sptr, ":%s NOTICE %s :Value of %s was already set to %d", + ME,parv[0],mptr->cmd,val); + + return 1; + } + *(mptr->value) = val; + sendto_one(sptr, ":%s NOTICE %s :Value of %s set to %d", + ME,parv[0],mptr->cmd,val); + sendto_flag(SCH_NOTICE,"%s changed value of %s to %d", + parv[0],mptr->cmd,val); + + set_action(mptr->cmd,val); + return 1; + } + } + else + { + i = 0; + for (valstr = mptr->values; *valstr; valstr++) + { + if (!mycmp(parv[2],*valstr)) + { /* found value */ + break; + } + i++; + strcat(obuf,*valstr); + strcat(obuf," "); + } + if (!*valstr) + { + sendto_one(sptr,":%s NOTICE %s :Unknown value for %s, avaible options are %s", + ME,parv[0],mptr->cmd,obuf); + return 1; + } + if (*(mptr->value) == i) + { + sendto_one(sptr, ":%s NOTICE %s :Value of %s was already set to %d", + ME,parv[0],mptr->cmd,val); + return 1; + } + + *(mptr->value) = i; + sendto_one(sptr, ":%s NOTICE %s :Value of %s set to %s", + ME,parv[0],mptr->cmd,*valstr); + sendto_flag(SCH_NOTICE,"%s changed value of %s to %s", + parv[0],mptr->cmd,*valstr); + + set_action(mptr->cmd,i); + return 1; + + } + +} +#endif /* ** storing server names in User structures is a real waste, @@ -2453,3 +3201,4 @@ ircstp->is_cklno++; return -1; } + diff -ru --new-file irc2.10.3p3/ircd/s_serv_ext.h irc2.10.3p3+sd7/ircd/s_serv_ext.h --- irc2.10.3p3/ircd/s_serv_ext.h Wed Sep 3 20:46:04 1997 +++ irc2.10.3p3+sd7/ircd/s_serv_ext.h Mon Feb 3 14:31:07 2003 @@ -69,4 +69,10 @@ #if defined(OPER_DIE) || defined(LOCOP_DIE) EXTERN int m_die __P((aClient *cptr, aClient *sptr, int parc, char *parv[])); #endif /* OPER_DIE || LOCOP_DIE */ +#ifdef SERVER_MAP +EXTERN int m_map __P((aClient *cptr, aClient *sptr, int parc, char *parv[])); +#endif +#ifdef OPER_SET +EXTERN int m_set __P((aClient *cptr, aClient *sptr, int parc, char *parv[])); +#endif #undef EXTERN diff -ru --new-file irc2.10.3p3/ircd/s_service.c irc2.10.3p3+sd7/ircd/s_service.c --- irc2.10.3p3/ircd/s_service.c Mon May 14 07:12:32 2001 +++ irc2.10.3p3+sd7/ircd/s_service.c Mon Feb 3 14:31:07 2003 @@ -435,15 +435,32 @@ sptr->name); sendto_one(sptr, rpl_str(RPL_YOURHOST, sptr->name), get_client_name(&me, FALSE), version); - sendto_one(sptr, rpl_str(RPL_MYINFO, sptr->name), ME, version); + sendto_one(sptr, rpl_str(RPL_MYINFO, sptr->name), ME, version, + APPEND_VERSION); sendto_flag(SCH_NOTICE, "Service %s connected", get_client_name(sptr, TRUE)); istat.is_unknown--; istat.is_myservice++; +#ifdef EXTRA_STATISTICS + /* + ** Keep track of maximum number of simultanious + ** services to this server. + */ + if (istat.is_myservice > istat.is_m_myservice) + istat.is_m_myservice = istat.is_myservice; +#endif } #endif istat.is_service++; +#ifdef EXTRA_STATISTICS + /* + ** Keep track of maximum number of services + ** simultaniously connected to this network. + */ + if (istat.is_service > istat.is_m_service) + istat.is_m_service = istat.is_service; +#endif svc = make_service(sptr); SetService(sptr); svc->servp = sp; diff -ru --new-file irc2.10.3p3/ircd/s_ssl.c irc2.10.3p3+sd7/ircd/s_ssl.c --- irc2.10.3p3/ircd/s_ssl.c Thu Jan 1 02:00:00 1970 +++ irc2.10.3p3+sd7/ircd/s_ssl.c Tue Feb 4 19:02:38 2003 @@ -0,0 +1,285 @@ +/* + * $Id: s_ssl.c, transparent ssl routines for accepting/reading/writing + * from/to ssl/non-ssl connections. written in jan 2003 by sd@hysteria.sk, + * this file is public domain. + */ + +#include "os.h" +#include "s_defines.h" +#include "s_externs.h" + +#include + +#ifdef USE_SSL +#ifndef min +#define min(x,y) (((x)>(y))?(y):(x)) +#endif + +SSL_CTX *ircdctx = NULL; + +/* + * initializes ssl + */ +void init_ssl(void) +{ + SSL_library_init(); + SSLeay_add_ssl_algorithms(); + SSL_load_error_strings(); +} + +/* + * rehash/reload the ssl cert/key + */ +void rehash_ssl(void) +{ + char certf[128] = "cert.pem"; + char keyf[128] = "key.pem"; + aConfItem *ssl = get_ssl_line(); + + if (ircdctx) { + SSL_CTX_free(ircdctx); + } + + if ((ssl) && (ssl->name)) + sscanf(ssl->name, "%s %s", certf, keyf); + + ircdctx = SSL_CTX_new(SSLv23_method()); + if (ircdctx) { + if ((SSL_CTX_use_certificate_file(ircdctx, certf, + SSL_FILETYPE_PEM) <= 0) || + (SSL_CTX_use_PrivateKey_file(ircdctx, keyf, + SSL_FILETYPE_PEM) <= 0) || + (!SSL_CTX_check_private_key(ircdctx))) { + SSL_CTX_free(ircdctx); + ircdctx = NULL; + sendto_flag(SCH_ERROR, "Can't initialize ssl key/cert. ssl disabled."); + return; + } + } + SSL_CTX_set_quiet_shutdown(ircdctx, 1); + sendto_flag(SCH_NOTICE, "Server key/cert loaded. ssl enabled."); +} + +/* + * does accept() ssl handshake on _first_ read, or just returns + * read bytes if it was not ssl at all ;-) this allows us to sit + * with ssl on one port. + */ +static int do_handshake(aClient *cptr, char *buf, int buflen) +{ + int ret; + /* didn't initialized ssl on client yet ? */ + if (!cptr->ssl) { + if (ircdctx) + cptr->ssl = SSL_new(ircdctx); + if ((!cptr->ssl) || + (!SSL_set_fd(cptr->ssl, cptr->fd))) { + if (cptr->ssl) + SSL_free(cptr->ssl); + cptr->ssl = NULL; + cptr->handshake = 1; +#ifndef ONLY_SSL + errno = EAGAIN; + return -1; +#else + cptr->handshake = 2; + errno = ENOMEM; + return -1; +#endif + } + } + + /* ok, ssl struct should be set up ok, + try to SSL_accept the conn */ + errno = 0; + ret = SSL_accept(cptr->ssl); + if (ret <= 0) { + if (ret < 0) + ret = SSL_get_error(cptr->ssl, ret); + /* interrupts caused by non-blocking io/alarm */ + if (((ret == SSL_ERROR_WANT_READ) || + (ret == SSL_ERROR_WANT_WRITE) || + (ret == SSL_ERROR_SYSCALL)) + && ((errno == EAGAIN) || (errno == EWOULDBLOCK))) { + return -1; + } else { + +#ifndef ONLY_SSL + int i; + cptr->handshake = 1; + /* protocol error - fall back to normal connection */ + i = min(cptr->ssl->packet_length, buflen); + if (i > 0) + memcpy(buf, cptr->ssl->packet, i); + else { + cptr->handshake = 2; + errno = EIO; + i = -1; + } + SSL_free(cptr->ssl); + cptr->ssl = NULL; + return i; +#else + cptr->handshake = 2; + errno = EIO; + return -1; +#endif + } + } + cptr->handshake = 1; + errno = EAGAIN; + return -1; +} + +/* + * does normal/ssl read, depending on situation + * it establishes ssl connection _transparently_ + */ +int safe_read(aClient *cptr, char *buf, int len) +{ + int ret; + + if (cptr->handshake == 2) { + errno = EIO; + return -1; + } + +#ifndef ONLY_SSL + /* handshake passed - _nonencrypted_ connection */ + if ((cptr->handshake) && (!cptr->ssl)) { + return recv(cptr->fd, buf, len, 0); + } +#endif + + /* no handshake ? time for accept. */ + if (!cptr->handshake) + return do_handshake(cptr, buf, len); + + /* we've handshake and we have ssl */ + ret = SSL_read(cptr->ssl, buf, len); + if (ret >= 0) + return ret; + + if (ret < 0) { + ret = SSL_get_error(cptr->ssl, ret); + if (((ret == SSL_ERROR_WANT_READ) || + (ret == SSL_ERROR_WANT_WRITE) || + (ret == SSL_ERROR_SYSCALL)) + && ((errno == EAGAIN) || (errno == EWOULDBLOCK))) + return -1; + } + + cptr->handshake = 2; + if (!errno) { + errno = EIO; + return 0; + } + return -1; +} + +/* + * does ssl/clear write to client's socket, both must be + * _established_ before. + */ +int safe_write(aClient *cptr, char *buf, int len) +{ + int ret; + + if (cptr->handshake == 2) + return len; + + if (!cptr->handshake) { + return do_handshake(cptr, NULL, 0); + } + +#ifndef ONLY_SSL + if ((!cptr->ssl) && (cptr->handshake)) { + return send(cptr->fd, buf, len, 0); + } +#endif + + ret = SSL_write(cptr->ssl, buf, len); + if (ret >= 0) + return ret; + if (ret < 0) { + ret = SSL_get_error(cptr->ssl, ret); + if (((ret == SSL_ERROR_WANT_READ) || + (ret == SSL_ERROR_WANT_WRITE) || + (ret == SSL_ERROR_SYSCALL)) + && ((errno == EAGAIN) || (errno == EWOULDBLOCK))) + return -1; + } + + cptr->handshake = 2; + if (!errno) { + errno = EIO; + return 0; + } + return -1; +} + + +void free_ssl(aClient *cptr) +{ + if (cptr->ssl) { + SSL_shutdown(cptr->ssl); + SSL_free(cptr->ssl); + cptr->ssl = NULL; + } +} + +/* + * establish "connect" ssl session, f.e. when connecting + * to server uplink. + */ +int ssl_server_connect(aClient *cptr, char *cert) +{ + int err; + SSL_CTX *ctx = ircdctx; + + if (!cptr) + return -1; + + /* if custom certificate, set it */ + if ((cert) && (*cert)) { + ctx = SSL_CTX_new(SSLv23_method()); + if (!ctx) + return -1; + if (SSL_CTX_use_certificate_file(ircdctx, cert, + SSL_FILETYPE_PEM) <= 0) { + sendto_flag(SCH_ERROR, "Failed loading certificate file for %s", + get_client_name(cptr, TRUE)); + return -1; + } + } + + if (!ctx) + return -1; + + cptr->ssl = SSL_new(ctx); + if (ircdctx != ctx) + SSL_CTX_free(ctx); + if (!cptr->ssl) + return -1; + if (!SSL_set_fd(cptr->ssl, cptr->fd)) { + SSL_free(cptr->ssl); + cptr->ssl = NULL; + cptr->handshake = 2; + return -1; + } + + /* XXX this needs to be fixed XXX */ + set_blocking(cptr->fd); + err = SSL_connect(cptr->ssl); + set_non_blocking(cptr->fd, cptr); + + if (err <= 0) { + SSL_free(cptr->ssl); + cptr->ssl = NULL; + cptr->handshake = 2; + return err; + } + cptr->handshake = 1; + return 1; +} +#endif diff -ru --new-file irc2.10.3p3/ircd/s_ssl.h irc2.10.3p3+sd7/ircd/s_ssl.h --- irc2.10.3p3/ircd/s_ssl.h Thu Jan 1 02:00:00 1970 +++ irc2.10.3p3+sd7/ircd/s_ssl.h Mon Feb 3 14:31:07 2003 @@ -0,0 +1,24 @@ +/* + * $Id: s_ssl.h, transparent ssl routines for accepting/reading/writing + * from/to ssl/non-ssl connections. written in jan 2003 by sd@hysteria.sk, + * this file is public domain. + */ + +#ifndef S_SSL_H +#define S_SSL_H + +#include "os.h" + +#ifdef USE_SSL + +extern SSL_CTX *ircdctx; +extern void init_ssl(void); +extern void rehash_ssl(void); +extern int safe_read(aClient *cptr, char *buf, int len); +extern int safe_write(aClient *cptr, char *buf, int len); +extern void free_ssl(aClient *cptr); +extern int ssl_server_connect(aClient *cptr, char *cert); + +#endif + +#endif diff -ru --new-file irc2.10.3p3/ircd/s_user.c irc2.10.3p3+sd7/ircd/s_user.c --- irc2.10.3p3/ircd/s_user.c Fri Oct 19 16:56:55 2001 +++ irc2.10.3p3+sd7/ircd/s_user.c Wed Feb 5 18:39:53 2003 @@ -39,6 +39,14 @@ FLAGS_WALLOP, 'w', FLAGS_RESTRICTED, 'r', FLAGS_AWAY, 'a', +#ifdef ILINE_FLAGS +#ifdef CAN_FLOOD + FLAGS_FLOOD, 'F', +#endif +#ifdef RECOVER + FLAGS_IMMORTAL, 'I', +#endif +#endif 0, 0 }; /* @@ -99,6 +107,99 @@ */ /* + * ok. this is ideal place for doing stupid things, like recovering + * of our user when nick-collided off the net. + * + * so, assume that someone nick-collided us, all neighbour servers + * purged our client (they got a kill) or will do in near future. + * + * so what we may do? first, choose not-so-easy-to-collide nick, + * based on server name (unique in whole net) and recovered nick + * serial no. then send to *local* clients, including collided one + * a nick change. to remote servers, we'll just re-introduce + * this "new" client and join him back to his channels and + * give him +o/+v, if had any. this finally stops nick-collision + * abuse in order to make some channel opless making channel + * history to do not work (=hacking ops later) + * + * this may break some things: + * first, client do not exist for the rest of the network + * for a while, so our user may miss some messages sent to + * channel during recovery, although he thinks that nothing + * happened. + * second, nick change forced by server may confuse some + * irc client software. + * + * note that this nick recovery works together with servers + * not having it at all. + * -sd + */ + +#ifdef RECOVER +static time_t nickcounter = 0; +extern char md5me[RECOVER_SMDLEN]; +extern char *ltoid(unsigned); + +static int recover_him(aClient *cptr) +{ + char newnick[NICKLEN+1]; + aClient *acptr; + aConfItem *aconf; + int i; + static char pbuf[4096]; + + cptr->flags &= ~FLAGS_KILLED; + + /* construct new random nick, possibility + of existence on network is *very* unlikely: + 012345678 + 0 - random number 0-9 + 123 - md5 of server host/info + 45678 - collided nick serial no. + */ + memset(newnick, 0, NICKLEN+1); + newnick[0] = '0' + (rand() % 10); + memcpy(newnick + 1, md5me, RECOVER_SMDLEN); + /* ugh! */ + memcpy(newnick + RECOVER_SMDLEN + 1, ltoid(nickcounter++), + (NICKLEN - (RECOVER_SMDLEN + 1))>5?5:(NICKLEN - (RECOVER_SMDLEN + 1))); + + + send_umode(NULL, cptr, 0, SEND_UMODES, pbuf); + + /* spread the word to local users */ + sendto_common_channels(cptr, ":%s NICK :%s", cptr->name, newnick); + del_from_client_hash_table(cptr->name, cptr); + strcpy(cptr->name, newnick); + add_to_client_hash_table(newnick, cptr); + + /* ok, and now re-introduce user to the rest of the world */ + for (i = fdas.highest; i >= 0; i--) { + if ((acptr = local[fdas.fd[i]]) == cptr || IsMe(acptr)) + continue; + if ((aconf = acptr->serv->nline) && + !match(my_name_for_link(ME, aconf->port), + cptr->user->server)) { + sendto_one(acptr, "NICK %s %d %s %s %s %s :%s", + newnick, cptr->hopcount+1, + cptr->user->username, cptr->user->host, + me.serv->tok, (*pbuf) ? pbuf : "+", + cptr->info); + } else { + sendto_one(acptr, "NICK %s %d %s %s %s %s :%s", + newnick, cptr->hopcount+1, + cptr->user->username, cptr->user->host, + cptr->user->servp->tok, + (*pbuf) ? pbuf : "+", cptr->info); + } + send_user_joins(acptr, cptr); + } + + return 0; +} +#endif + +/* ** next_client ** Local function to find the next matching client. The search ** can be continued from the specified client entry. Normal @@ -108,6 +209,8 @@ ** HandleMatchingClient; ** */ + + aClient *next_client(next, ch) Reg aClient *next; /* First client to check */ Reg char *ch; /* search string (may include wilds) */ @@ -324,6 +427,12 @@ (IsUnixSocket(cptr)) ? me.sockhost : ((cptr->hostp) ? cptr->hostp->h_name : cptr->sockhost)); #endif +#ifdef DELAY_CLOSE + if (cptr->user) + { + cptr->user->flags |= FLAGS_BADBOY; + } +#endif return exit_client(cptr, cptr, &me, longm); } @@ -363,6 +472,9 @@ #ifndef NO_PREFIX char prefix; #endif +#ifdef RESTRICT_USERNAMES + char *hptr; +#endif int i; user->last = timeofday; @@ -372,7 +484,6 @@ if (MyConnect(sptr)) { char *reason = NULL; - #if defined(USE_IAUTH) static time_t last = 0; static u_int count = 0; @@ -449,6 +560,7 @@ ** + i line with ident ** = i line with OTHER type ident ** - i line, no ident + ** . I/i line, no ssl */ if (!(sptr->flags & FLAGS_GOTID)) prefix = '~'; @@ -482,14 +594,68 @@ strncpyzt(user->username, username, USERLEN+1); #endif + if (sptr->exitc == EXITC_AREF || sptr->exitc == EXITC_AREFQ) { + char *showres = NULL; + if (sptr->reason) + { + showres = strchr(sptr->reason,' '); + if (showres) + { + *showres = '\0'; + } + } if (sptr->exitc == EXITC_AREF) - sendto_flag(SCH_LOCAL, - "Denied connection from %s.", + { + if (showres) + { + sendto_flag(SCH_LOCAL, + "Denied connection from %s. (%s)", + get_client_host(sptr),sptr->reason); + *showres = ' '; + } + else + sendto_flag(SCH_LOCAL, + "Denied connection from %s. ", get_client_host(sptr)); - return ereject_user(cptr, " Denied ","Denied access"); + + } + if (showres && !*(showres+1)) + { + showres = NULL; + } + return ereject_user(cptr, " Denied ",showres ? showres+1 : "Denied access"); } +#ifdef USE_SSL + /* damn, must be all of those crazy rejections right here ? -sd */ + switch (cptr->forcessl) { + case 1: /* force ssl */ + if (!cptr->ssl) + return ereject_user(cptr, " usessl ", + "Your class of users *must* use ssl."); + break; + case 2: /* deny ssl */ + if (cptr->ssl) + return ereject_user(cptr, " nossl ", + "Your class of users are not allowed to use ssl."); + break; + default:; + } +#endif +#ifdef DELAY_ACCEPT + /* well, this is not exactly the correct place for this + * check, but oh well.. -jv */ + { + aConfItem *bconf; + bconf = sptr->acpt->confs->value.aconf; + if (bconf->status & CONF_SERVERONLY) + { + sendto_flag(SCH_LOCAL,"User connection to server-only port from %s",get_client_host(sptr)); + return ereject_user(cptr, " serveronly ", "This port is avaible for servers only."); + } + } +#endif if ((i = check_client(sptr))) { struct msg_set { char *shortm; char *longm; }; @@ -514,7 +680,6 @@ return ereject_user(cptr, exit_msg[i].shortm, exit_msg[i].longm); } - #ifndef NO_PREFIX if (IsRestricted(sptr)) { @@ -532,6 +697,23 @@ } #endif +#ifdef SSL_PREFIX + /* for users which can select between ssl/non-ssl + put a dot ('.') in prefix for those w/o ssl */ + + if ((!sptr->ssl) && (ircdctx) && (!sptr->forcessl) + +#ifdef ILINE_FLAGS + && (user->flags & FLAGS_DOT) +#endif + ) { + strncpyzt(buf2, user->username, USERLEN+1); + *user->username = '.'; + strncpy(user->username + 1, buf2, USERLEN); + } +#endif + + aconf = sptr->confs->value.aconf; if (IsUnixSocket(sptr)) strncpyzt(user->host, me.sockhost, HOSTLEN+1); @@ -546,10 +728,38 @@ return exit_client(cptr, sptr, &me, "Bad Password"); } bzero(sptr->passwd, sizeof(sptr->passwd)); +#ifdef RESTRICT_USERNAMES + /* + * Do not allow special characters in the username. + */ + hptr = user->username; +#ifdef SSL_PREFIX + if (*hptr == '.') + hptr++; +#endif +#ifndef NO_PREFIX + if (prefix) + hptr++; +#endif + while (*hptr && isvaliduser(*hptr)) + hptr++; + if (*hptr) { + ircstp->is_ref++; + sendto_flag(SCH_LOCAL, "Invalid username: %s@%s.", + sptr->user->username, sptr->sockhost); + return exit_client(cptr, sptr, &me, + "Invalid username"); + } +#endif /* * following block for the benefit of time-dependent K:-lines */ +#ifdef ILINE_FLAGS + if (!IsKlineExempt(sptr) && find_kill(sptr, 1, &reason)) + +#else if (find_kill(sptr, 1, &reason)) +#endif { /*char buf[100];*/ @@ -582,6 +792,21 @@ return exit_client(cptr, sptr, &me , "R-lined"); } #endif + +#ifdef CLIENTS_CHANNEL + sendto_flag(SCH_CLIENTS,"Client connecting: %s is %s from %s [%s] named %s", + nick,user->username,user->host, +#ifdef INET6 + inetntop(AF_INET6, + (char *)&sptr->ip, + mydummy, MYDUMMY_SIZE), +#else + inetntoa((char *)&sptr->ip), +#endif + + sptr->info); +#endif + if (oldstatus == STAT_MASTER && MyConnect(sptr)) (void)m_oper(&me, sptr, 1, parv); /* *user->tok = '1'; @@ -629,13 +854,72 @@ (*buf) ? buf : "+", sptr->info); } /* for(my-leaf-servers) */ if (IsInvisible(sptr)) /* Can be initialized in m_user() */ + { istat.is_user[1]++; /* Local and server defaults +i */ + user->servp->usercnt[1]++; + } else + { istat.is_user[0]++; + user->servp->usercnt[0]++; + + } +#ifdef SPLIT_HANDLE + if (istat.is_user[1] + istat.is_user[0] >= SPLIT_USERS) + { + check_split(); + } +#endif +#ifdef EXTRA_STATISTICS + /* + ** Keep track of maximum number of global users. + */ + if ((istat.is_user[1] + istat.is_user[0]) > istat.is_m_users) { + istat.is_m_users = istat.is_user[1] + istat.is_user[0]; + if ((istat.is_m_users % 1000) == 0) + sendto_flag(SCH_NOTICE, + "New highest global client connection: %d", + istat.is_m_users); + } + if (user->servp->usercnt[0] + user->servp->usercnt[1] > user->servp->usermax) + { + user->servp->usermax = user->servp->usercnt[0] + user->servp->usercnt[1]; + } +#endif if (MyConnect(sptr)) { istat.is_unknown--; istat.is_myclnt++; +#ifdef EXTRA_STATISTICS + /* + ** Inform of highest client connection. + */ + if (istat.is_myclnt > istat.is_m_myclnt) { + istat.is_m_myclnt = istat.is_myclnt; + if ((istat.is_m_myclnt % 10) == 0) + sendto_flag(SCH_NOTICE, + "New highest local client connection: %d", + istat.is_m_myclnt); + } + /* + ** Small cludge to try and warn of some fast clonebots. + */ + if ((istat.is_myclnt % 10) == 0) { + if (istat.is_myclnt > istat.is_last_cnt) { + if (istat.is_last_cnt_t == 0) + istat.is_last_cnt_t = me.since; + + sendto_flag(SCH_NOTICE, + "Local increase from %d to %d clients in %d second%s", + (istat.is_myclnt - 10),istat.is_myclnt, + (timeofday - istat.is_last_cnt_t), + ((timeofday - istat.is_last_cnt_t == 1) ? "" + : "s")); + } + istat.is_last_cnt_t = timeofday; + istat.is_last_cnt = istat.is_myclnt; + } +#endif sprintf(buf, "%s!%s@%s", nick, user->username, user->host); sptr->exitc = EXITC_REG; sendto_one(sptr, rpl_str(RPL_WELCOME, nick), buf); @@ -644,14 +928,59 @@ get_client_name(&me, FALSE), version); sendto_one(sptr, rpl_str(RPL_CREATED, nick), creation); sendto_one(sptr, rpl_str(RPL_MYINFO, parv[0]), - ME, version); + ME, version, APPEND_VERSION); +#ifdef SEND_ISUPPORT + sendto_one(sptr, rpl_str(RPL_ISUPPORT, parv[0]), + isupport); +#endif (void)m_lusers(sptr, sptr, 1, parv); (void)m_motd(sptr, sptr, 1, parv); if (IsRestricted(sptr)) sendto_one(sptr, err_str(ERR_RESTRICTED, nick)); send_umode(sptr, sptr, 0, ALL_UMODES, buf); +#ifdef SPLIT_HANDLE + if (iconf.split) + { + sendto_one(sptr,":%s NOTICE %s :Server is currently in split-mode. You will NOT get channel operator status on new channels.",ME,nick); + } +#endif +#ifdef DELAY_ACCEPT + if (iconf.caccept < 2) + { + sendto_one(sptr,":%s NOTICE %s :Server is currently in delay-accept mode. Users can't connect.",ME,nick); + } +#endif + +#ifdef USE_SSL +#ifdef SSL_NOTICE + { + aConfItem *tmp = get_ssl_line(); + if (tmp && +#ifdef ILINE_FLAGS + user->flags & FLAGS_DOT +#endif + ) { + int bits; + char *proto, *name; + + if ((tmp->host) && (*tmp->host) && (sptr->ssl)) { + proto = SSL_get_cipher_version(sptr->ssl); + name = (char *) SSL_get_cipher_name(sptr->ssl); + bits = SSL_get_cipher_bits(sptr->ssl, NULL); + sendto_one(sptr, ":%s NOTICE %s :%s (protocol: %s, cipher: %s/%d)" + , ME, nick, tmp->host, proto, name, bits); + } + if ((tmp->passwd) && (*tmp->passwd) && (!sptr->ssl)) { + sendto_one(sptr, ":%s NOTICE %s :%s", ME, nick, + tmp->passwd); + } + } + } +#endif +#endif nextping = timeofday; } + #ifdef USE_SERVICES #if 0 check_services_butone(SERVICE_WANT_NICK, user->server, NULL, @@ -668,6 +997,7 @@ send_umode(NULL, sptr, 0, ALL_UMODES, buf); check_services_num(sptr, buf); #endif + add_to_hostname_hash_table(user->host,user); return 1; } @@ -887,8 +1217,11 @@ ** The client indicated by 'acptr' is dead meat, give at least some ** indication of the reason why we are just dropping it cold. */ - sendto_one(acptr, err_str(ERR_NICKCOLLISION, acptr->name), - acptr->name, user, host); +#ifndef RECOVER + if (!(MyConnect(acptr) && IsImmortal(acptr))) + sendto_one(acptr, err_str(ERR_NICKCOLLISION, acptr->name), + acptr->name, user, host); +#endif /* ** This seemingly obscure test (sptr == cptr) differentiates ** between "NICK new" (TRUE) and ":old NICK new" (FALSE) forms. @@ -918,6 +1251,10 @@ ** the other info would be lost */ get_client_name(cptr, FALSE)); +#ifdef RECOVER + if (MyConnect(acptr) && IsImmortal(acptr)) + return recover_him(acptr); +#endif acptr->flags |= FLAGS_KILLED; return exit_client(NULL, acptr, &me, "Nick collision"); } @@ -943,8 +1280,18 @@ ME, acptr->name, ME, acptr->user->username, acptr->user->host, acptr->from->name, user, host, cptr->name, sptr->name); - acptr->flags |= FLAGS_KILLED; - (void)exit_client(NULL, acptr, &me, "Nick collision(new)"); +#ifdef RECOVER + if (MyConnect(acptr) && IsImmortal(acptr)) + recover_him(acptr); + else { +#endif + acptr->flags |= FLAGS_KILLED; + (void)exit_client(NULL, acptr, &me, "Nick collision(new)"); +#ifdef RECOVER + } + if (MyConnect(sptr) && IsImmortal(sptr)) + return recover_him(sptr); +#endif sptr->flags |= FLAGS_KILLED; return exit_client(cptr, sptr, &me, "Nick collision(old)"); @@ -1004,6 +1351,13 @@ ** on that channel. Propagate notice to other servers. */ sendto_common_channels(sptr, ":%s NICK :%s", parv[0], nick); +#ifdef CLIENTS_CHANNEL + if (MyConnect(sptr) && IsRegisteredUser(sptr)) { + sendto_flag(SCH_CLIENTS,"Nick change %s to %s for %s from %s", + parv[0],nick,sptr->user->username,sptr->user->host); + } +#endif + if (sptr->user) /* should always be true.. */ { add_history(sptr, sptr); @@ -1357,7 +1711,7 @@ who_one(sptr, lp->value.cptr, chptr, lp); } } - else if (lp = find_user_link(chptr->members, sptr)) + else if ((lp = find_user_link(chptr->members, sptr))) who_one(sptr, lp->value.cptr, chptr, lp); } @@ -1365,73 +1719,92 @@ ** who_find ** lists all (matching) users. ** CPU intensive, but what can be done? +** +** Reduced CPU load - 05/2001 */ static void who_find(sptr, mask, oper) aClient *sptr; char *mask; int oper; { - aChannel *chptr, *ch2ptr; - Link *lp; - int member; - int showperson, isinvis; - aClient *acptr; - + Reg Link *lp,*lp2; + int myoper = 0; + Reg aClient *acptr; + aChannel *chptr = NULL; + if (MyConnect(sptr) && IsAnOper(sptr)) + { + myoper = 1; + } + + /* first, show INvisible matching users on common channels */ + for (lp = sptr->user->channel; lp ;lp = lp->next) + { + chptr = lp->value.chptr; + if (IsAnonymous(chptr)) + continue; + for (lp2 = chptr->members; lp2 ;lp2 = lp2->next) + { + acptr = lp2->value.cptr; + + if (!IsInvisible(acptr) || (acptr->flags & FLAGS_HIDDEN)) + { + continue; + } + + if (oper && !IsAnOper(acptr)) + { + continue; + } + + acptr->flags |= FLAGS_HIDDEN; + if (!mask || + match(mask, acptr->name) == 0 || + match(mask, acptr->user->username) == 0 || + match(mask, acptr->user->host) == 0 || + match(mask, acptr->user->server) == 0 || + match(mask, acptr->info) == 0) + who_one(sptr, acptr, chptr, NULL); + + } + } + + /* second, show all matching visible clients */ for (acptr = client; acptr; acptr = acptr->next) { - ch2ptr = NULL; if (!IsPerson(acptr)) continue; + + /* clear the flag */ + if (acptr->flags & FLAGS_HIDDEN) + { + acptr->flags &= ~FLAGS_HIDDEN; + continue; + } + + /* allow local opers to see matching clients on _LOCAL_ server */ + if (IsInvisible(acptr) && !(MyConnect(acptr) && myoper)) + { + continue; + } + /* we wanted only opers */ if (oper && !IsAnOper(acptr)) + { continue; - showperson = 0; - /* - * Show user if they are on the same channel, or not - * invisible and on a non secret channel (if any). - * Do this before brute force match on all relevant - * fields since these are less cpu intensive (I - * hope :-) and should provide better/more shortcuts - * -avalon - */ - isinvis = IsInvisible(acptr); - for (lp = acptr->user->channel; lp; lp = lp->next) - { - chptr = lp->value.chptr; - if (IsAnonymous(chptr)) - continue; - member = IsMember(sptr, chptr); - if (isinvis && !member) - continue; - if (member || (!isinvis && PubChannel(chptr))) - { - showperson = 1; - if (!IsAnonymous(chptr) || - acptr != sptr) - { - ch2ptr = chptr; - break; - } - } - if (HiddenChannel(chptr) && - !SecretChannel(chptr) && !isinvis) - showperson = 1; - } - if (!acptr->user->channel && !isinvis) - showperson = 1; + } + /* - ** This is brute force solution, not efficient...? ;( + ** This is brute force solution, not efficient...? ;( ** Show entry, if no mask or any of the fields match ** the mask. --msa */ - if (showperson && - (!mask || + if (!mask || match(mask, acptr->name) == 0 || match(mask, acptr->user->username) == 0 || match(mask, acptr->user->host) == 0 || match(mask, acptr->user->server) == 0 || - match(mask, acptr->info) == 0)) - who_one(sptr, acptr, ch2ptr, NULL); + match(mask, acptr->info) == 0) + who_one(sptr, acptr, NULL, NULL); } } @@ -1465,7 +1838,7 @@ for (p = NULL, mask = strtoken(&p, parv[1], ","); mask && penalty <= MAXPENALTY; mask = strtoken(&p, NULL, ",")) - { + { channame = NULL; penalty += 1; @@ -1477,12 +1850,11 @@ /* I think it's useless --Beeth */ clean_channelname(mask); #endif - /* simplify mask */ (void)collapse(mask); /* - ** We can never have here !mask + ** We can never have here !mask ** or *mask == '\0', since it would be equal ** to parc == 1, that is 'WHO' and/or would not ** pass through above for loop. @@ -1557,6 +1929,7 @@ ** All nice chances lost above. ** We must hog our server with that. */ + who_find(sptr, mask, oper); penalty += MAXPENALTY; } @@ -1649,7 +2022,11 @@ if (acptr->user && MyConnect(acptr)) sendto_one(sptr, rpl_str(RPL_WHOISIDLE, sptr->name), +#ifdef WHOIS_SIGNON_TIME + name, timeofday - user->last,acptr->firsttime); +#else name, timeofday - user->last); +#endif } /* @@ -1956,6 +2333,9 @@ char *inpath = get_client_name(cptr,FALSE); char *user, *path, *killer; int chasing = 0; + + sendto_flag(SCH_NOTICE, "cptr = %s, sptr = %s, sender prefix = %s, victim = %s, path = %s", + cptr->name, sptr->name, parv[0], parv[1], parv[2]); if (parc < 2 || *parv[1] == '\0') { @@ -2086,15 +2466,6 @@ #endif /* - ** Tell the victim she/he has been zapped, but *only* if - ** the victim is on current server--no sense in sending the - ** notification chasing the above kill, it won't get far - ** anyway (as this user don't exist there any more either) - */ - if (MyConnect(acptr)) - sendto_prefix_one(acptr, sptr,":%s KILL %s :%s!%s", - parv[0], acptr->name, inpath, path); - /* ** Set FLAGS_KILLED. This prevents exit_one_client from sending ** the unnecessary QUIT for this. (This flag should never be ** set in any other place) @@ -2107,7 +2478,8 @@ } else { - if ((killer = index(path, ' '))) + char *collide, *tmp = index(path, ' '); + if ((killer = tmp)) { while (killer > path && *killer != '!') killer--; @@ -2117,7 +2489,35 @@ else killer = path; SPRINTF(buf2, "Killed (%s)", killer); +#ifdef RECOVER + /* detect if kill was generated by nick + collision - remote server even doesn't bother + sending us some reliable info regarding + to kill, so we're guessing this + when 3rd word equals to '<-' + i.e. nickname collision kill path -sd */ + + if (IsImmortal(acptr) && (tmp) && + (MyConnect(acptr)) && (IsServer(cptr))) { + collide = index(tmp + 1, ' '); + if ((collide) && (!memcmp(collide, " <- ", 4))) { + /* eeek! */ + return recover_him(acptr); + } + } +#endif } + + /* + ** Tell the victim she/he has been zapped, but *only* if + ** the victim is on current server--no sense in sending the + ** notification chasing the above kill, it won't get far + ** anyway (as this user don't exist there any more either) + */ + if (MyConnect(acptr)) + sendto_prefix_one(acptr, sptr,":%s KILL %s :%s!%s", + parv[0], acptr->name, inpath, path); + return exit_client(cptr, acptr, sptr, buf2); } @@ -2278,10 +2678,35 @@ cptr->flags &= ~FLAGS_PINGSENT; sptr->flags &= ~FLAGS_PINGSENT; - if (!BadPtr(destination) && mycmp(destination, ME) != 0) +#ifdef SPLIT_HANDLE + if (IsServer(cptr) && IsServer(sptr) && (BadPtr(destination) || !match(destination,ME))) + { + if (IsBurst(sptr)) + { + ClearBurst(sptr); + istat.is_eobservers++; + if (MyConnect(sptr)) + { + sendto_flag(SCH_NOTICE,"End of burst from %s. Lasted %d seconds.", + cptr->name,timeofday - cptr->firsttime); + } + else + { + sendto_flag(SCH_DEBUG,"EOB from %s (PONG)",sptr->name); + } + bubble_eob(sptr); + if (iconf.split) + { + check_split(); + } + } + } +#endif + if (!BadPtr(destination) && match(destination, ME) != 0) { if ((acptr = find_client(destination, NULL)) || - (acptr = find_server(destination, NULL))) { + (acptr = find_server(destination, NULL))) + { if (!(MyClient(sptr) && mycmp(origin, sptr->name))) sendto_one(acptr,":%s PONG %s %s", parv[0], origin, destination); @@ -2450,12 +2875,59 @@ parv[0], IsOper(sptr) ? 'O' : 'o'); #endif if (IsAnOper(sptr)) + { istat.is_oper++; + sptr->user->servp->usercnt[2]++; + } } else { (void)detach_conf(sptr, aconf); sendto_one(sptr,err_str(ERR_PASSWDMISMATCH, parv[0])); +#ifdef FAILED_OPERLOG + sendto_flag(SCH_NOTICE, "FAILED OPER %s attempt by %s!%s@%s", + name, parv[0], sptr->user->username, sptr->user->host); +# if defined(USE_SYSLOG) && defined(SYSLOG_OPER) + syslog(LOG_INFO, "FAILED OPER %s attempt by %s!%s@%s [%s@%s]", + name, parv[0], sptr->user->username, sptr->user->host, + sptr->auth, IsUnixSocket(sptr) ? sptr->sockhost : +#ifdef INET6 + inet_ntop(AF_INET6, (char *)&sptr->ip, mydummy, MYDUMMY_SIZE)); +#else + + inetntoa((char *)&sptr->ip)); +#endif +# endif +# ifdef FNAME_OPERLOG + { + int logfile; + + (void)alarm(3); + if (IsPerson(sptr) && + (logfile = open(FNAME_OPERLOG, O_WRONLY|O_APPEND)) != -1) + { + (void)alarm(0); + SPRINTF(buf, "%s FAILED OPER %s attempt by %s!%s@%s [%s@%s]\n", + myctime(timeofday), name, parv[0], sptr->user->username, + sptr->user->host, sptr->auth, IsUnixSocket(sptr) ? + sptr->sockhost : +#ifdef INET6 + inetntop(AF_INET6, (char *)&sptr->ip, mydummy, + MYDUMMY_SIZE)); + +#else + inetntoa((char *)&sptr->ip)); +#endif + (void)alarm(3); + (void)write(logfile, buf, strlen(buf)); + (void)alarm(0); + (void)close(logfile); + } + (void)alarm(0); + } +# endif +#endif + } return 3; } @@ -2723,6 +3195,18 @@ ":%s AWAY :", parv[0]); #endif default : +#ifdef CAN_FLOOD + if (!IsOper(sptr) && MyConnect(sptr)) + { + if (*m == 'F') + { + sendto_one(sptr, err_str( + ERR_UMODEUNKNOWNFLAG, parv[0]), + *m); + continue; + } + } +#endif for (s = user_modes; (flag = *s); s += 2) if (*m == (char)(*(s+1))) { @@ -2768,11 +3252,15 @@ { istat.is_user[1]--; istat.is_user[0]++; + sptr->user->servp->usercnt[1]--; + sptr->user->servp->usercnt[0]++; } if (IsInvisible(sptr) && !(setflags & FLAGS_INVISIBLE)) { istat.is_user[1]++; istat.is_user[0]--; + sptr->user->servp->usercnt[1]++; + sptr->user->servp->usercnt[0]--; } send_umode_out(cptr, sptr, setflags); } @@ -2781,6 +3269,7 @@ if (IsOper(sptr) && !(setflags & FLAGS_OPER)) { istat.is_oper++; + sptr->user->servp->usercnt[2]++; #ifdef USE_SERVICES check_services_butone(SERVICE_WANT_OPER, sptr->user->server, sptr, ":%s MODE %s :+o", parv[0], @@ -2790,6 +3279,7 @@ else if (!IsOper(sptr) && (setflags & FLAGS_OPER)) { istat.is_oper--; + sptr->user->servp->usercnt[2]--; #ifdef USE_SERVICES check_services_butone(SERVICE_WANT_OPER, sptr->user->server, sptr, ":%s MODE %s :-o", parv[0], @@ -2799,6 +3289,7 @@ else if (MyConnect(sptr) && !IsLocOp(sptr) && (setflags & FLAGS_LOCOP)) { istat.is_oper--; + sptr->user->servp->usercnt[2]--; #ifdef USE_SERVICES check_services_butone(SERVICE_WANT_OPER, sptr->user->server, sptr, ":%s MODE %s :-O", parv[0], diff -ru --new-file irc2.10.3p3/ircd/version.c.SH.in irc2.10.3p3+sd7/ircd/version.c.SH.in --- irc2.10.3p3/ircd/version.c.SH.in Thu Jul 22 01:59:54 1999 +++ irc2.10.3p3+sd7/ircd/version.c.SH.in Mon Feb 3 14:31:07 2003 @@ -63,6 +63,7 @@ char *generation = "$generation"; char *creation = "$creation"; char *version; /* Filled by make_version() */ +char *isupport; /* Filled by make_isupport() */ char *pass_version = PATCHLEVEL; char *infotext[] = @@ -108,6 +109,12 @@ "", "[$sumsserv] [$sumchan] [$sumsbsd] [$sumsuser]", "[$sumhash] [$sumsmisc] [$sumircd]", + "", + "This server has been patched by hemp patch, revision 2002080901.", + "See http://jv.irc.cz/irc/ for more information about this patch.", + "", + "This server uses sd5 privacy/enchacement patch, look at", + "http://irc.hysteria.sk/patches for more information.", 0, }; !SUB!THIS! diff -ru --new-file irc2.10.3p3/ircd/version_ext.h irc2.10.3p3+sd7/ircd/version_ext.h --- irc2.10.3p3/ircd/version_ext.h Wed Sep 3 20:46:08 1997 +++ irc2.10.3p3+sd7/ircd/version_ext.h Mon Feb 3 14:31:07 2003 @@ -27,6 +27,7 @@ extern char *generation; extern char *creation; extern char *version; +extern char *isupport; extern char *pass_version; extern char *infotext[]; #endif /* VERSION_C */ diff -ru --new-file irc2.10.3p3/support/Makefile.in irc2.10.3p3+sd7/support/Makefile.in --- irc2.10.3p3/support/Makefile.in Fri Feb 9 15:47:07 2001 +++ irc2.10.3p3+sd7/support/Makefile.in Mon Feb 3 14:31:07 2003 @@ -41,7 +41,7 @@ # linker flags LDFLAGS = @LDFLAGS@ # required libraries, except zlib and curses/termcap -LIBS = @LIBS@ +LIBS = @LIBS@ -lssl -lcrypto MATHLIBS = @MATHLIBS@ # zlib, eventually ZLIBS = @IRC_ZLIB_LIBRARY@ @@ -153,11 +153,11 @@ SERVER_OBJS = channel.o class.o hash.o ircd.o list.o res.o s_auth.o \ s_bsd.o s_conf.o s_debug.o s_err.o s_id.o s_misc.o s_numeric.o \ s_serv.o s_service.o s_user.o s_zip.o whowas.o \ - res_init.o res_comp.o res_mkquery.o + res_init.o res_comp.o res_mkquery.o s_ssl.o IAUTH_COMMON_OBJS = clsupport.o clmatch.o # This is a little evil IAUTH_OBJS = iauth.o a_conf.o a_io.o a_log.o \ - mod_lhex.o mod_pipe.o mod_rfc931.o mod_socks.o + mod_lhex.o mod_pipe.o mod_rfc931.o mod_socks.o mod_webproxy.o IAUTH = iauth CHKCONF_COMMON_OBJS = match.o @@ -398,6 +398,9 @@ s_conf.o: ../ircd/s_conf.c setup.h config.h $(CC) $(S_CFLAGS) -DIRCDMOTD_PATH="\"$(IRCDMOTD_PATH)\"" -DIRCDM4_PATH="\"$(IRCDM4_PATH)\"" -c -o $@ ../ircd/s_conf.c +s_ssl.o: ../ircd/s_ssl.c setup.h config.h + $(CC) $(S_CFLAGS) -DIRCDMOTD_PATH="\"$(IRCDMOTD_PATH)\"" -DIRCDM4_PATH="\"$(IRCDM4_PATH)\"" -c -o $@ ../ircd/s_ssl.c + s_debug.o: ../ircd/s_debug.c setup.h config.h $(CC) $(S_CFLAGS) -c -o $@ ../ircd/s_debug.c @@ -408,7 +411,8 @@ $(CC) $(S_CFLAGS) -c -o $@ ../ircd/s_id.c s_misc.o: ../ircd/s_misc.c setup.h config.h - $(CC) $(S_CFLAGS) -DFNAME_USERLOG="\"$(FNAME_USERLOG)\"" -DFNAME_CONNLOG="\"$(FNAME_CONNLOG)\"" -c -o $@ ../ircd/s_misc.c + $(CC) $(S_CFLAGS) -DFNAME_USERLOG="\"$(FNAME_USERLOG)\"" \ + -DIRCDCONF_PATH="\"$(IRCDCONF_PATH)\"" -DFNAME_CONNLOG="\"$(FNAME_CONNLOG)\"" -c -o $@ ../ircd/s_misc.c s_numeric.o: ../ircd/s_numeric.c setup.h config.h $(CC) $(S_CFLAGS) -c -o $@ ../ircd/s_numeric.c @@ -464,6 +468,9 @@ mod_socks.o: ../iauth/mod_socks.c config.h setup.h $(CC) $(A_CFLAGS) -c -o $@ ../iauth/mod_socks.c +mod_webproxy.o: ../iauth/mod_webproxy.c config.h setup.h + $(CC) $(A_CFLAGS) -c -o $@ ../iauth/mod_webproxy.c -Wall + chkconf.o: ../ircd/chkconf.c setup.h config.h $(CC) $(CC_CFLAGS) -DCHKCONF_COMPILE -DIRCDCONF_PATH="\"$(IRCDCONF_PATH)\"" -DIRCDM4_PATH="\"$(IRCDM4_PATH)\"" -c -o $@ ../ircd/chkconf.c diff -ru --new-file irc2.10.3p3/support/config.h.dist irc2.10.3p3+sd7/support/config.h.dist --- irc2.10.3p3/support/config.h.dist Sat Oct 20 00:51:15 2001 +++ irc2.10.3p3+sd7/support/config.h.dist Mon Feb 3 14:31:07 2003 @@ -17,70 +17,131 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/*** start of +sd5 privacy patch *****************************************/ +/* allow only irc operators to see I/i: lines server configuration */ +#define STATS_I_OPERONLY + +/* allow server-info change on-the-fly */ +#define NAMECHANGE_HACK + +/* +F users can flood server - | iline flag */ +#define CAN_FLOOD + +/* recover nicks from collision + * the way it is working is simple: + * when we'll see that someone else is introducing us + * same nick, we'll normally kill him *BUT* + * if we receive server kill (most times a nick collision) + * we'll do not tell to local users what happened, + * they'll see nick change and other servers reintroduced + * client with random nick. + * to enable this, user *must* set 'I' umode flag to himself + * or must exist under i-line with flag '^' (will get +I from server) + */ +#define RECOVER +#ifdef RECOVER +/* do not change this unless you do not know what this means ;-) */ +#define RECOVER_SMDLEN 3 +#endif + /* - * ircdwatch configuration options. + * allow spoofing/masking hostnames in I: lines + * fe: + * I:*@*::::10:%%%%.irc.hysteria.sk -> users becomes .irc.hysteria.sk, + * is md5 of ip|host, can be up to 32 %'s replaced, then hash repeats + * + * I:*@127.0.0.1::::10:hysteria.sk -> just spoofs all users to hysteria.sk + * + * WARNING: O, K, R etc lines follow _spoofed_ hosts ;-) + * because host ip-s is always '1.3.3.7', k/r/o-line-ing on ip basis + * doesn't work for now. */ +#define SPOOF +/* + * allow use of ssl + * in ircd.conf you must specify: + * X:::/path/to/certfile /path/to/keyfile + * ssl/non-ssl client are handled transparently, so one port + * can be for both types. + * + * note that behaviour of use of ssl can be set in Y:, as 7th + * field, 0 - autodetect, 1 - ssl only, 2 - plaintext only + * so 0 means that users can connect both types, 1 they + * can use only ssl, 2 they're not allowed to use ssl. + * + * to distinguish ssl and non-ssl users in ssl-type 0 class, + * you may use ILINE_FLAGS and put '.' in name field of I: + * and define SSL_PREFIX, server will then start to put for + * non-ssled users '.' in their username prefix. + * + * if you want to connect to server using ssl, create + * server class with ssl type of '1' and use this in C/N + * line. you can even specify cert file of remote server + * as last field of C: line. + */ + +#ifdef SPOOF +/* private feature - let opers know about users ip in statistics + STATS_F below must be defined to make this work! */ +#define OPERS_WATCHING_USERS +#endif +#define USE_SSL + +#ifdef USE_SSL +#undef ONLY_SSL /* if defined, *only* ssl clients is accepted */ +#define SSL_NOTICE /* notice for users in autodetect (0) ssl class */ +#define SSL_PREFIX /* prefix users with dot in autodetect (0) ssl class */ +#endif + +#define APPEND_VERSION "+hemp+sd7" +/*** end of +sd5 privacy patch *******************************************/ + + +/* ircdwatch configuration options ***************************************/ /* how often (in seconds) should we check that ircd runs? */ #define IRCDWATCH_POLLING_INTERVAL 30 -/* - * should we check for config file changes and HUP the server - * if a change is detected? - */ +/* should we check for config file changes and HUP the server + * if a change is detected? */ #undef IRCDWATCH_HUP_ON_CONFIG_CHANGE -/* - * although you may not want to log ircd-messages to syslog you +/* although you may not want to log ircd-messages to syslog you * may want to log when ircdwatch reloads the config or when - * ircd croaks and ircdwatch has to restart it - */ + * ircd croaks and ircdwatch has to restart it */ #define IRCDWATCH_USE_SYSLOG #ifdef IRCDWATCH_USE_SYSLOG # define IRCDWATCH_SYSLOG_IDENT "ircdwatch" # define IRCDWATCH_SYSLOG_OPTIONS (LOG_PID) # define IRCDWATCH_SYSLOG_FACILITY LOG_DAEMON #endif +/* end of ircdwatch configuration options ********************************/ -/* - * irc[d] configuration options. - * - * Most of the following defines are related to the server, - * some apply to the client. - * - */ +/* irc[d] configuration options ******************************************/ -/* - * If you don't want the server to keep reading the MOTD file from the disk, +/* If you don't want the server to keep reading the MOTD file from the disk, * define CACHED_MOTD. The server will store the MOTD in memory, and only - * read it again from the disk when rehashing if the file has changed. - */ + * read it again from the disk when rehashing if the file has changed. */ #define CACHED_MOTD -/* CHROOTDIR - * - * Define for value added security if you are a rooter. +/* Define for value added security if you are a rooter. * * CPATH, MPATH, LPATH, PPATH, TPATH, QPATH, OPATH, * FNAME_USERLOG, FNAME_OPERLOG, FNAME_CONNLOG, FNAME_AUTHLOG * must have RPATH as root directory! Set them in Makefile * - * You may want to define IRC_UID and IRC_GID - */ + * You may want to define IRC_UID and IRC_GID */ #undef CHROOTDIR #if defined(CHROOTDIR) #define ROOT_PATH "/where/to/change/root/dir" #endif -/* ENABLE_SUMMON - * - * The SUMMON command requires the ircd to be run as group tty in order +/* The SUMMON command requires the ircd to be run as group tty in order * to work properly in many cases. If you are on a machine where it * won't work, or simply don't want local users to be summoned, undefine - * this. - */ + * this. */ #undef ENABLE_SUMMON /* local summon */ #undef ENABLE_USERS /* enables local /users (same as who/finger output) */ @@ -88,16 +149,14 @@ * * As defined this will show the correct invisible count for anyone who does * LUSERS on your server. On a large net this doesnt mean much, but on a - * small net it might be an advantage to undefine it. - */ + * small net it might be an advantage to undefine it. */ #define SHOW_INVISIBLE_LUSERS /* NO_DEFAULT_INVISIBLE * * When defined, your users will not automatically be attributed with user * mode "i" (i == invisible). Invisibility means people dont showup in - * WHO or NAMES unless they are on the same channel as you. - */ + * WHO or NAMES unless they are on the same channel as you. */ #undef NO_DEFAULT_INVISIBLE /* OPER_KILL @@ -118,17 +177,47 @@ * if 'OPER_x' is undefined so you can't give local operators more rights * than global ones. */ -#undef OPER_KILL +#define OPER_KILL #define OPER_REHASH -#undef OPER_RESTART +#define OPER_RESTART #define OPER_DIE -#undef OPER_REMOTE +#define OPER_REMOTE #undef LOCOP_REHASH #undef LOCOP_RESTART #undef LOCOP_DIE +#define OPER_KLINE /* global oper can/cannot on-line pernament /kline */ +#undef LOCOP_KLINE /* local oper can/cannot on-line pernament /kline */ +#define OPER_TKLINE +#undef LOCOP_TKLINE +#define LOCOP_SJOIN +#define LOCOP_SMODE +#define LOCOP_SNAMES +#define LOCOP_SCLEAN -/* - * Maximum number of network connections your server will allow. This should +#ifdef OPER_KILL +#undef LOCAL_KILL_ONLY /* allow to kill localy only */ +#endif + + +/* (informational) channel where soper usage gets sent to. + * #define it to a value, i.e. "#soper-usage", if you want it, + * #undef if you don't. + */ +#define SOPERCHAN "#soper-usage" + +/* define to have (partial-logging) channel that traps all server mode + changes */ +#define SMODE_CHAN +#undef LOCOP_SMODE_CHAN + +/* define to have the SJOIN, SMODE, SNAMES, SCLEAN commands available */ +#define SOPER_SJOIN +#define SOPER_SMODE +#define SOPER_SNAMES +#define SOPER_SCLEAN + + +/* Maximum number of network connections your server will allow. This should * never exceed max. number of open file descrpitors and wont increase this. * Should remain LOW as possible. Most sites will usually have under 50 or so * connections. @@ -136,9 +225,8 @@ * over 2 or more servers. * 1 server = 1 connection, 1 user = 1 connection. * This should be at *least* 4: 2 listen ports (1 tcp, 1 udp) - * 1 dns port, 1 client - */ -#define MAXCONNECTIONS 50 + * 1 dns port, 1 client */ +#define MAXCONNECTIONS 1024 /* MAXIMUM LINKS * @@ -164,38 +252,30 @@ * lines. Then you will only connect to one of the Americans. * * This value is only used if you don't have server classes defined, and - * a server is in class 0 (the default class if none is set). - * - */ -#define MAXIMUM_LINKS 1 + * a server is in class 0 (the default class if none is set). */ +#define MAXIMUM_LINKS 5 -/* - * A pure non-routing leaf server can undefine HUB for best performance. +/* A pure non-routing leaf server can undefine HUB for best performance. * If your server is running as a a HUB Server then define this. * A HUB Server has many servers connect to it at the same as opposed - * to a leaf which just has 1 server (typically the uplink). - */ -/* #define HUB */ + * to a leaf which just has 1 server (typically the uplink). */ +#define HUB #ifdef HUB -/* - * MAXSERVERS is the maximum number of servers that will be linked +/* MAXSERVERS is the maximum number of servers that will be linked * to your server at the same time. This number is not a limit, - * it is used to allocate memory when ircd is started. - */ -# define MAXSERVERS 3 + * it is used to allocate memory when ircd is started. */ +# define MAXSERVERS 5 #else # define MAXSERVERS 1 #endif -/* - * If you want to use timed klines, set it to frequence in seconds, +/* If you want to use timed klines, set it to frequence in seconds, * how often to check if client is to be removed; usually 60 seconds * (smallest granularity you can get in K:line anyway). * - * Advised not to use it ;-) --Beeth - */ -#undef TIMEDKLINES + * Advised not to use it ;-) --Beeth */ +#define TIMEDKLINES 60 /* R_LINES: The conf file now allows the existence of R lines, or * restrict lines. These allow more freedom in the ability to restrict @@ -229,7 +309,7 @@ * starts up the server with a new conf file that has some extra * O-lines. So don't use this unless you're debugging. */ -#undef CMDLINE_CONFIG /* allow conf-file to be specified on command line */ +#define CMDLINE_CONFIG /* allow conf-file to be specified on command line */ /* * To use m4 as a preprocessor on the ircd.conf file, define M4_PREPROC. @@ -311,11 +391,6 @@ #undef IRC_UID #undef IRC_GID -#ifdef notdef -#define IRC_UID 65534 /* eg for what to do to enable this feature */ -#define IRC_GID 65534 -#endif - /* * CLIENT_FLOOD * @@ -323,7 +398,7 @@ * send to the server without processing before disconnecting the client for * flooding it. Values greater than 8000 make no difference to the server. */ -#define CLIENT_FLOOD 1000 +#define CLIENT_FLOOD 8000 /* Remote query flood protection. */ #define CHREPLLEN 8192 @@ -337,7 +412,7 @@ * services are not fully implemented yet, so don't use it unless you really * know what you are doing. */ -#undef USE_SERVICES +#define USE_SERVICES /* * Define the following to make the delay for nicks random. @@ -370,7 +445,7 @@ * NOTE: Undefining this leads to a significant increase in CPU usage if * you reject client which keeps connecting. */ -#define SLOW_ACCEPT +#undef SLOW_ACCEPT /* * Defining this will make the server check for rapid connections from a single @@ -381,33 +456,187 @@ * * IMPORTANT: This **MUST** defined if SLOW_ACCEPT is NOT defined */ -#undef CLONE_CHECK +#define CLONE_CHECK -/* STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP */ -/* STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP */ -/* STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP */ -/* You shouldn't change anything below this line, unless absolutely needed. */ +/* + * Disclaimer: The following part concerns the Cr-patches. By defining this + * you will end up with "no warranty" whatsoever - use at your + * own risk. + * The Cr patch does not compromize the anonymity and does + * not affect users integrity in any way. The new features will + * only provide extra functionality and statistics for local + * IRC operators. + */ +#define RESTRICT_USERNAMES -#ifdef OPER_KILL -/* LOCAL_KILL_ONLY +/* + * Define this if you want to allow online K-lining (permanent) for + * regular and local operators. + */ + +/* + * Define this if you want to allow online K-lining to memory only + * which is removed after rehashing the configuration file or by + * restarting the server. + */ + +/* + * Define this if you want (t)kline requests to go to syslog + * Note that you must also have USE_SYSLOG defined otherwise + * it won't work + * this is a part of patch f2 by fantomas + */ +#define SYSLOG_KLINE + +/* + * This will give some extra statistics, such as highest usercount, + * connection duration and local client incrementation. * - * To be used, OPER_KILL must be defined. - * LOCAL_KILL_ONLY restricts KILLs to clients which are connected to the - * server the Operator is connected to (ie lets them deal with local - * problem users or 'ghost' clients + * Note: will also show local/global max in /lusers - jv */ -#define LOCAL_KILL_ONLY -#endif +#define EXTRA_STATISTICS + +/* CrXXe8 related stuff follows. It makes the TKLINE/KLINE servernotice + * show the k-linereason too and does two cosmetical corrections to the + * "Local increase..." and the RPL_YOUREOPER servernotices. Also it + * doesn't suppress iauth statistics for opers using stats t. + * + * Define this to show and log failed /oper attempts too! + * Define LOG_IP for logging [ident@remoteip#remoteport,localip#localport]. + */ +#define RESTRICT_USERNAMES + +#undef FAILED_OPERLOG +#undef LOG_IP + +/* Fl4 related stuff follows - so far, the only stuff retained from Fl3c + * for Fl4 is the &clients channel ; this is because the TKLINE/KLINE code + * from Fl3c is also present in the Cr15 code. + */ + +/* define this to enable an extra local channel '&clients', which only + * IRC operators may join. Notification of nick-changes, connects, exits, + * and requests for server statistics will be sent to this channel. + * Some people regard this as a breach of privacy, hence (unlike Fl3c) + * it is turned off by default. + * f2 - easy clients merged - jv + */ +#define CLIENTS_CHANNEL + + + +/* + * Define this to see when a channel topic was set and who it was set by. + */ +#define TOPICWHOTIME + +/* + * Define this if you want msgs normally sent to &local moved to ¬ices + * - EXCEPT unauth/rejection/too many connection notices. The reasoning + * behind this is if you want to see local information except the annoying + * and resource wasting unauths and rejections.. + */ +#define LOCAL_REJECTIONS_ONLY + + +/* +jv patch defines follows */ + +/* New stats - F show FDs and remote&local ports (local oper only) + */ +#define STATS_F + +/* show signon time of local clients in whois */ +#define WHOIS_SIGNON_TIME + +/* no RPL_TRYAGAIN for opers - i think it's right and doesn't add + * privileges for opers, just allows them to administrate net better. + */ +#define NO_OPER_TRYAGAIN +/* If you want to notify users that doing /LIST is bad and they should + use ALIS instead, define this. Notice is sent BEFORE any output. + */ + +// #define LIST_ALIS_NOTE "Usage of /list for listing all channels is deprecated. Please use \"/squery alis help\" instead." + +/* If you want to send server IS_SUPPORT upon connect and along with + VERSION reply. Also moves redirect numerics from 5 to 10. + also define Networkname. + */ +#define SEND_ISUPPORT +#define NETWORKNAME "IRCNet" + +/* support for /MAP a'la ircu. */ +#define SERVER_MAP + +/* quick info about connected servers */ +#define STATS_QMARK + +/* define if you want to set some values - delay accept mode, disable/enable autoconnects */ +#define OPER_SET + +/* wait with closing sockets of rejected clients, in seconds */ +#define DELAY_CLOSE +#define DELAYCLOSETIME 3 + +/* Split handling - replaces QPI + * works as follows: + * PINGs all servers behind the link and waits for PONG. + * Note: somehow unreliable with current 8000) || (CLIENT_FLOOD < 512) -error CLIENT_FLOOD needs redefining. +#warning "CLIENT_FLOOD w/ weird value" # endif #else -error CLIENT_FLOOD undefined +#define CLIENT_FLOOD 8000 #endif #if defined(ZIP_LINKS) -# if (ZIP_MINIMUM > ZIP_MAXIMUM) +#if (ZIP_MINIMUM > ZIP_MAXIMUM) error ZIP_MINIMUM needs redefining. # endif #endif @@ -559,10 +789,13 @@ #if ! USE_POLL # if (MAXCONNECTIONS > FD_SETSIZE) -error FD_SETSIZE must be bigger than MAXCONNECTIONS +#warning "FD_SETSIZE must be bigger than MAXCONNECTIONS" +#undef MAXCONNECTIONS +#define MAXCONNECTIONS (FD_SETSIZE-5) # endif #endif + /* ** buffer used for iauth-ircd communication ** very big servers might consider increasing it @@ -584,7 +817,8 @@ ** */ #if defined(R_LINES_OFTEN) && !defined(TIMEDKLINES) -error TIMEDKLINES must be defined for R_LINES_OFTEN to work (are you sure you need them?) +#define TIMEDKLINES 60 +#warning "TIMEDKLINES must be defined for R_LINES_OFTEN to work (are you sure you need them?)" #endif /* @@ -592,3 +826,8 @@ */ #define NOWRITEALARM 1 + +#if defined(DELAY_ACCEPT) && !defined(SPLIT_HANDLE) +#warning "DELAY_ACCEPT requires SPLIT_HANDLE defined." +#define SPLIT_HANDLE +#endif diff -ru --new-file irc2.10.3p3/support/iauth.conf irc2.10.3p3+sd7/support/iauth.conf --- irc2.10.3p3/support/iauth.conf Mon Jul 5 01:15:43 1999 +++ irc2.10.3p3+sd7/support/iauth.conf Mon Feb 3 14:31:07 2003 @@ -14,5 +14,10 @@ module rfc931 # Check and reject open SOCKS proxies -#module socks -# option = reject,paranoid +module socks + option = reject,paranoid + timeout = 5 + +module webproxy + option = log,reject,ports=3128;8080 + timeout = 10 diff -ru --new-file irc2.10.3p3/support/tkconf.h.dist irc2.10.3p3+sd7/support/tkconf.h.dist --- irc2.10.3p3/support/tkconf.h.dist Sun Feb 21 02:33:47 1999 +++ irc2.10.3p3+sd7/support/tkconf.h.dist Mon Feb 3 14:31:07 2003 @@ -28,8 +28,8 @@ #undef TKSERV_DEBUG /* The name of the ircd config file backup (suffix after CPATH) */ -#define TKSERV_IRCD_CONFIG_BAK CPATH".tkserv" +#define TKSERV_IRCD_CONFIG_BAK TKSERV_IRCD_CONF".tkserv" /* The name of the ircd temp config file (suffix after CPATH) */ -#define TKSERV_IRCD_CONFIG_TMP CPATH".tmp" +#define TKSERV_IRCD_CONFIG_TMP TKSERV_IRCD_CONF".tmp"