From 4440a86cfa359b8e40a484a2cd46d33db5455d8a Mon Sep 17 00:00:00 2001 From: Jonas Gunz Date: Mon, 25 May 2020 20:09:04 +0200 Subject: Initial --- common/bsd.c | 192 ++ common/bsd_ext.h | 41 + common/class_def.h | 58 + common/common_def.h | 88 + common/dbuf.c | 532 ++++ common/dbuf_def.h | 96 + common/dbuf_ext.h | 49 + common/match.c | 314 +++ common/match_ext.h | 43 + common/msg_def.h | 77 + common/numeric_def.h | 337 +++ common/os.h | 765 ++++++ common/packet.c | 197 ++ common/packet_ext.h | 32 + common/parse.c | 786 ++++++ common/parse_ext.h | 56 + common/patchlevel.h | 22 + common/send.c | 1555 +++++++++++ common/send_ext.h | 82 + common/struct_def.h | 832 ++++++ common/support.c | 1190 +++++++++ common/support_def.h | 28 + common/support_ext.h | 80 + configure | 50 + contrib/README | 21 + contrib/RULES | 24 + contrib/antispoof.README | 56 + contrib/antispoof.diff | 484 ++++ contrib/ircdwatch/README | 56 + contrib/ircdwatch/ircdwatch.8 | 50 + contrib/ircdwatch/ircdwatch.c | 499 ++++ contrib/mkpasswd/README | 64 + contrib/mkpasswd/crypter | 55 + contrib/mkpasswd/mkpasswd.c | 44 + contrib/mod_passwd/README | 30 + contrib/mod_passwd/mod_passwd.c | 171 ++ contrib/tkserv/CHANGES | 37 + contrib/tkserv/CREDITS | 60 + contrib/tkserv/INSTALL | 20 + contrib/tkserv/README | 290 +++ contrib/tkserv/proto.h | 24 + contrib/tkserv/tkserv.access.example | 10 + contrib/tkserv/tkserv.c | 1022 ++++++++ doc/2.10-New | 18 + doc/2.9-New | 60 + doc/Authors | 180 ++ doc/BUGS | 13 + doc/ChangeLog | 1956 ++++++++++++++ doc/Etiquette | 84 + doc/INSTALL.appendix | 86 + doc/INSTALL.info | 1759 +++++++++++++ doc/INSTALL.sgml | 1388 ++++++++++ doc/INSTALL.txt | 1716 +++++++++++++ doc/Juped/Advertisement | 39 + doc/Juped/ChangeLog.common | 91 + doc/Juped/ChangeLog.doc | 90 + doc/Juped/ChangeLog.include | 85 + doc/Juped/ChangeLog.irc | 77 + doc/Juped/ChangeLog.ircd | 458 ++++ doc/Juped/INSTALL | 1167 +++++++++ doc/Juped/US-Admin/Networking | 156 ++ doc/LICENSE | 249 ++ doc/Makefile | 39 + doc/Nets/Europe/CoordEBIC | 86 + doc/Nets/Europe/IRCNO | 171 ++ doc/Nets/Europe/InfoEBIC | 48 + doc/Nets/Europe/RulesEBIC | 90 + doc/Nets/Europe/links.eu | 70 + doc/Nets/Europe/rules | 55 + doc/Nets/IRCNet | 17 + doc/README | 40 + doc/RELEASE_LOG | 23 + doc/RELEASE_NOTES | 120 + doc/SERVICE.sgml | 285 +++ doc/SERVICE.txt | 330 +++ doc/alt-irc-faq | 293 +++ doc/example.conf | 531 ++++ doc/iauth-internals.txt | 350 +++ doc/iauth.8 | 54 + doc/iauth.conf.5 | 159 ++ doc/irc.1 | 85 + doc/ircd.8 | 202 ++ doc/m4macros | 48 + iauth/a_conf.c | 548 ++++ iauth/a_conf_def.h | 56 + iauth/a_conf_ext.h | 43 + iauth/a_defines.h | 39 + iauth/a_externs.h | 34 + iauth/a_io.c | 831 ++++++ iauth/a_io_ext.h | 50 + iauth/a_log.c | 123 + iauth/a_log_def.h | 41 + iauth/a_log_ext.h | 46 + iauth/a_struct_def.h | 72 + iauth/iauth.c | 226 ++ iauth/mod_lhex.c | 318 +++ iauth/mod_lhex_ext.h | 28 + iauth/mod_pipe.c | 217 ++ iauth/mod_pipe_ext.h | 28 + iauth/mod_rfc931.c | 368 +++ iauth/mod_rfc931_ext.h | 45 + iauth/mod_socks.c | 632 +++++ iauth/mod_socks_ext.h | 28 + irc/c_bsd.c | 149 ++ irc/c_bsd_ext.h | 39 + irc/c_conf.c | 95 + irc/c_conf_ext.h | 38 + irc/c_debug.c | 61 + irc/c_debug_ext.h | 49 + irc/c_defines.h | 35 + irc/c_externs.h | 44 + irc/c_msg.c | 407 +++ irc/c_msg_ext.h | 76 + irc/c_numeric.c | 413 +++ irc/c_numeric_ext.h | 39 + irc/c_version.c | 46 + irc/c_version_ext.h | 32 + irc/ctcp.c | 50 + irc/ctcp_ext.h | 33 + irc/edit.c | 411 +++ irc/edit_ext.h | 55 + irc/help.c | 228 ++ irc/help_def.h | 23 + irc/help_ext.h | 40 + irc/ignore.c | 141 + irc/ignore_ext.h | 43 + irc/irc.c | 908 +++++++ irc/irc_def.h | 29 + irc/irc_ext.h | 84 + irc/screen.c | 287 +++ irc/screen_ext.h | 56 + irc/str.c | 84 + irc/str_ext.h | 39 + irc/swear.c | 216 ++ irc/swear_ext.h | 53 + ircd/buildm4 | 98 + ircd/channel.c | 3396 ++++++++++++++++++++++++ ircd/channel_def.h | 29 + ircd/channel_ext.h | 64 + ircd/chkconf.c | 745 ++++++ ircd/class.c | 256 ++ ircd/class_ext.h | 49 + ircd/hash.c | 940 +++++++ ircd/hash_def.h | 32 + ircd/hash_ext.h | 52 + ircd/ircd.c | 1287 ++++++++++ ircd/ircd_ext.h | 62 + ircd/list.c | 685 +++++ ircd/list2.c | 515 ++++ ircd/list_ext.h | 66 + ircd/nameser_def.h | 330 +++ ircd/res.c | 1697 ++++++++++++ ircd/res_comp.c | 929 +++++++ ircd/res_comp_ext.h | 44 + ircd/res_def.h | 59 + ircd/res_ext.h | 41 + ircd/res_init.c | 642 +++++ ircd/res_init_ext.h | 39 + ircd/res_mkquery.c | 178 ++ ircd/res_mkquery_ext.h | 35 + ircd/resolv_def.h | 220 ++ ircd/s_auth.c | 804 ++++++ ircd/s_auth_ext.h | 52 + ircd/s_bsd.c | 3243 +++++++++++++++++++++++ ircd/s_bsd_ext.h | 77 + ircd/s_conf.c | 1684 ++++++++++++ ircd/s_conf_ext.h | 66 + ircd/s_debug.c | 668 +++++ ircd/s_debug_ext.h | 45 + ircd/s_defines.h | 41 + ircd/s_err.c | 436 ++++ ircd/s_err_ext.h | 33 + ircd/s_externs.h | 53 + ircd/s_id.c | 208 ++ ircd/s_id_ext.h | 43 + ircd/s_misc.c | 998 ++++++++ ircd/s_misc_ext.h | 58 + ircd/s_numeric.c | 127 + ircd/s_numeric_ext.h | 33 + ircd/s_serv.c | 2489 ++++++++++++++++++ ircd/s_serv_ext.h | 72 + ircd/s_service.c | 708 ++++++ ircd/s_service_ext.h | 58 + ircd/s_user.c | 2869 +++++++++++++++++++++ ircd/s_user_ext.h | 60 + ircd/s_zip.c | 261 ++ ircd/s_zip_ext.h | 38 + ircd/service_def.h | 54 + ircd/sys_def.h | 31 + ircd/version.c.SH.in | 113 + ircd/version_ext.h | 32 + ircd/whowas.c | 464 ++++ ircd/whowas_def.h | 34 + ircd/whowas_ext.h | 47 + support/Makefile.in | 488 ++++ support/acconfig.h | 101 + support/config.guess | 954 +++++++ support/config.h.dist | 555 ++++ support/config.sub | 955 +++++++ support/configure | 4671 ++++++++++++++++++++++++++++++++++ support/configure.in | 1519 +++++++++++ support/iauth.conf | 18 + support/install-sh | 253 ++ support/mkdirhier | 70 + support/setup.h.in | 413 +++ support/sums.in | 39 + support/tkconf.h.dist | 35 + 207 files changed, 69923 insertions(+) create mode 100644 common/bsd.c create mode 100644 common/bsd_ext.h create mode 100644 common/class_def.h create mode 100644 common/common_def.h create mode 100644 common/dbuf.c create mode 100644 common/dbuf_def.h create mode 100644 common/dbuf_ext.h create mode 100644 common/match.c create mode 100644 common/match_ext.h create mode 100644 common/msg_def.h create mode 100644 common/numeric_def.h create mode 100644 common/os.h create mode 100644 common/packet.c create mode 100644 common/packet_ext.h create mode 100644 common/parse.c create mode 100644 common/parse_ext.h create mode 100644 common/patchlevel.h create mode 100644 common/send.c create mode 100644 common/send_ext.h create mode 100644 common/struct_def.h create mode 100644 common/support.c create mode 100644 common/support_def.h create mode 100644 common/support_ext.h create mode 100755 configure create mode 100644 contrib/README create mode 100644 contrib/RULES create mode 100644 contrib/antispoof.README create mode 100644 contrib/antispoof.diff create mode 100644 contrib/ircdwatch/README create mode 100644 contrib/ircdwatch/ircdwatch.8 create mode 100644 contrib/ircdwatch/ircdwatch.c create mode 100644 contrib/mkpasswd/README create mode 100755 contrib/mkpasswd/crypter create mode 100644 contrib/mkpasswd/mkpasswd.c create mode 100644 contrib/mod_passwd/README create mode 100644 contrib/mod_passwd/mod_passwd.c create mode 100644 contrib/tkserv/CHANGES create mode 100644 contrib/tkserv/CREDITS create mode 100644 contrib/tkserv/INSTALL create mode 100644 contrib/tkserv/README create mode 100644 contrib/tkserv/proto.h create mode 100644 contrib/tkserv/tkserv.access.example create mode 100644 contrib/tkserv/tkserv.c create mode 100644 doc/2.10-New create mode 100644 doc/2.9-New create mode 100644 doc/Authors create mode 100644 doc/BUGS create mode 100644 doc/ChangeLog create mode 100644 doc/Etiquette create mode 100644 doc/INSTALL.appendix create mode 100644 doc/INSTALL.info create mode 100644 doc/INSTALL.sgml create mode 100644 doc/INSTALL.txt create mode 100644 doc/Juped/Advertisement create mode 100644 doc/Juped/ChangeLog.common create mode 100644 doc/Juped/ChangeLog.doc create mode 100644 doc/Juped/ChangeLog.include create mode 100644 doc/Juped/ChangeLog.irc create mode 100644 doc/Juped/ChangeLog.ircd create mode 100644 doc/Juped/INSTALL create mode 100644 doc/Juped/US-Admin/Networking create mode 100644 doc/LICENSE create mode 100644 doc/Makefile create mode 100644 doc/Nets/Europe/CoordEBIC create mode 100644 doc/Nets/Europe/IRCNO create mode 100644 doc/Nets/Europe/InfoEBIC create mode 100644 doc/Nets/Europe/RulesEBIC create mode 100644 doc/Nets/Europe/links.eu create mode 100644 doc/Nets/Europe/rules create mode 100644 doc/Nets/IRCNet create mode 100644 doc/README create mode 100644 doc/RELEASE_LOG create mode 100644 doc/RELEASE_NOTES create mode 100644 doc/SERVICE.sgml create mode 100644 doc/SERVICE.txt create mode 100644 doc/alt-irc-faq create mode 100644 doc/example.conf create mode 100644 doc/iauth-internals.txt create mode 100644 doc/iauth.8 create mode 100644 doc/iauth.conf.5 create mode 100644 doc/irc.1 create mode 100644 doc/ircd.8 create mode 100644 doc/m4macros create mode 100644 iauth/a_conf.c create mode 100644 iauth/a_conf_def.h create mode 100644 iauth/a_conf_ext.h create mode 100644 iauth/a_defines.h create mode 100644 iauth/a_externs.h create mode 100644 iauth/a_io.c create mode 100644 iauth/a_io_ext.h create mode 100644 iauth/a_log.c create mode 100644 iauth/a_log_def.h create mode 100644 iauth/a_log_ext.h create mode 100644 iauth/a_struct_def.h create mode 100644 iauth/iauth.c create mode 100644 iauth/mod_lhex.c create mode 100644 iauth/mod_lhex_ext.h create mode 100644 iauth/mod_pipe.c create mode 100644 iauth/mod_pipe_ext.h create mode 100644 iauth/mod_rfc931.c create mode 100644 iauth/mod_rfc931_ext.h create mode 100644 iauth/mod_socks.c create mode 100644 iauth/mod_socks_ext.h create mode 100644 irc/c_bsd.c create mode 100644 irc/c_bsd_ext.h create mode 100644 irc/c_conf.c create mode 100644 irc/c_conf_ext.h create mode 100644 irc/c_debug.c create mode 100644 irc/c_debug_ext.h create mode 100644 irc/c_defines.h create mode 100644 irc/c_externs.h create mode 100644 irc/c_msg.c create mode 100644 irc/c_msg_ext.h create mode 100644 irc/c_numeric.c create mode 100644 irc/c_numeric_ext.h create mode 100644 irc/c_version.c create mode 100644 irc/c_version_ext.h create mode 100644 irc/ctcp.c create mode 100644 irc/ctcp_ext.h create mode 100644 irc/edit.c create mode 100644 irc/edit_ext.h create mode 100644 irc/help.c create mode 100644 irc/help_def.h create mode 100644 irc/help_ext.h create mode 100644 irc/ignore.c create mode 100644 irc/ignore_ext.h create mode 100644 irc/irc.c create mode 100644 irc/irc_def.h create mode 100644 irc/irc_ext.h create mode 100644 irc/screen.c create mode 100644 irc/screen_ext.h create mode 100644 irc/str.c create mode 100644 irc/str_ext.h create mode 100644 irc/swear.c create mode 100644 irc/swear_ext.h create mode 100755 ircd/buildm4 create mode 100644 ircd/channel.c create mode 100644 ircd/channel_def.h create mode 100644 ircd/channel_ext.h create mode 100644 ircd/chkconf.c create mode 100644 ircd/class.c create mode 100644 ircd/class_ext.h create mode 100644 ircd/hash.c create mode 100644 ircd/hash_def.h create mode 100644 ircd/hash_ext.h create mode 100644 ircd/ircd.c create mode 100644 ircd/ircd_ext.h create mode 100644 ircd/list.c create mode 100644 ircd/list2.c create mode 100644 ircd/list_ext.h create mode 100644 ircd/nameser_def.h create mode 100644 ircd/res.c create mode 100644 ircd/res_comp.c create mode 100644 ircd/res_comp_ext.h create mode 100644 ircd/res_def.h create mode 100644 ircd/res_ext.h create mode 100644 ircd/res_init.c create mode 100644 ircd/res_init_ext.h create mode 100644 ircd/res_mkquery.c create mode 100644 ircd/res_mkquery_ext.h create mode 100644 ircd/resolv_def.h create mode 100644 ircd/s_auth.c create mode 100644 ircd/s_auth_ext.h create mode 100644 ircd/s_bsd.c create mode 100644 ircd/s_bsd_ext.h create mode 100644 ircd/s_conf.c create mode 100644 ircd/s_conf_ext.h create mode 100644 ircd/s_debug.c create mode 100644 ircd/s_debug_ext.h create mode 100644 ircd/s_defines.h create mode 100644 ircd/s_err.c create mode 100644 ircd/s_err_ext.h create mode 100644 ircd/s_externs.h create mode 100644 ircd/s_id.c create mode 100644 ircd/s_id_ext.h create mode 100644 ircd/s_misc.c create mode 100644 ircd/s_misc_ext.h create mode 100644 ircd/s_numeric.c create mode 100644 ircd/s_numeric_ext.h create mode 100644 ircd/s_serv.c create mode 100644 ircd/s_serv_ext.h create mode 100644 ircd/s_service.c create mode 100644 ircd/s_service_ext.h create mode 100644 ircd/s_user.c create mode 100644 ircd/s_user_ext.h create mode 100644 ircd/s_zip.c create mode 100644 ircd/s_zip_ext.h create mode 100644 ircd/service_def.h create mode 100644 ircd/sys_def.h create mode 100644 ircd/version.c.SH.in create mode 100644 ircd/version_ext.h create mode 100644 ircd/whowas.c create mode 100644 ircd/whowas_def.h create mode 100644 ircd/whowas_ext.h create mode 100644 support/Makefile.in create mode 100644 support/acconfig.h create mode 100755 support/config.guess create mode 100644 support/config.h.dist create mode 100644 support/config.sub create mode 100755 support/configure create mode 100644 support/configure.in create mode 100644 support/iauth.conf create mode 100755 support/install-sh create mode 100755 support/mkdirhier create mode 100644 support/setup.h.in create mode 100644 support/sums.in create mode 100644 support/tkconf.h.dist diff --git a/common/bsd.c b/common/bsd.c new file mode 100644 index 0000000..69b66e7 --- /dev/null +++ b/common/bsd.c @@ -0,0 +1,192 @@ +/************************************************************************ + * IRC - Internet Relay Chat, common/bsd.c + * Copyright (C) 1990 Jarkko Oikarinen and + * University of Oulu, Computing Center + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef lint +static char rcsid[] = "@(#)$Id: bsd.c,v 1.3 1998/12/13 00:02:33 kalt Exp $"; +#endif + +#include "os.h" +#ifndef CLIENT_COMPILE +# include "s_defines.h" +#else +# include "c_defines.h" +#endif +#define BSD_C +#ifndef CLIENT_COMPILE +# include "s_externs.h" +#else +# include "c_externs.h" +#endif +#undef BSD_C + +#ifdef DEBUGMODE +int writecalls = 0, writeb[10] = {0,0,0,0,0,0,0,0,0,0}; +#endif +RETSIGTYPE dummy(s) +int s; +{ +#ifndef HAVE_RELIABLE_SIGNALS + (void)signal(SIGALRM, dummy); + (void)signal(SIGPIPE, dummy); +# ifndef HPUX /* Only 9k/800 series require this, but don't know how to.. */ +# ifdef SIGWINCH + (void)signal(SIGWINCH, dummy); +# endif +# endif +#else +# if POSIX_SIGNALS + struct sigaction act; + + act.sa_handler = dummy; + act.sa_flags = 0; + (void)sigemptyset(&act.sa_mask); + (void)sigaddset(&act.sa_mask, SIGALRM); + (void)sigaddset(&act.sa_mask, SIGPIPE); +# ifdef SIGWINCH + (void)sigaddset(&act.sa_mask, SIGWINCH); +# endif + (void)sigaction(SIGALRM, &act, (struct sigaction *)NULL); + (void)sigaction(SIGPIPE, &act, (struct sigaction *)NULL); +# ifdef SIGWINCH + (void)sigaction(SIGWINCH, &act, (struct sigaction *)NULL); +# endif +# endif +#endif +} + + +/* +** deliver_it +** Attempt to send a sequence of bytes to the connection. +** Returns +** +** < 0 Some fatal error occurred, (but not EWOULDBLOCK). +** This return is a request to close the socket and +** clean up the link. +** +** >= 0 No real error occurred, returns the number of +** bytes actually transferred. EWOULDBLOCK and other +** possibly similar conditions should be mapped to +** zero return. Upper level routine will have to +** decide what to do with those unwritten bytes... +** +** *NOTE* alarm calls have been preserved, so this should +** work equally well whether blocking or non-blocking +** mode is used... +*/ +int deliver_it(cptr, str, len) +aClient *cptr; +int len; +char *str; + { + int retval; + aClient *acpt = cptr->acpt; + +#ifdef DEBUGMODE + writecalls++; +#endif +#ifndef NOWRITEALARM + (void)alarm(WRITEWAITDELAY); +#endif +#ifdef INET6 + retval = sendto(cptr->fd, str, len, 0, 0, 0); +#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 + ** all is Ok, if the 'write' just returns '0' instead of an + ** error and errno=EWOULDBLOCK. + ** + ** ...now, would this work on VMS too? --msa + */ + if (retval < 0 && (errno == EWOULDBLOCK || errno == EAGAIN || +#ifdef EMSGSIZE + errno == EMSGSIZE || +#endif + errno == ENOBUFS)) + { + retval = 0; + cptr->flags |= FLAGS_BLOCKED; + } + else if (retval > 0) + cptr->flags &= ~FLAGS_BLOCKED; + +#ifndef NOWRITEALARM + (void )alarm(0); +#endif +#ifdef DEBUGMODE + if (retval < 0) { + writeb[0]++; + Debug((DEBUG_ERROR,"write error (%s) to %s", + sys_errlist[errno], cptr->name)); +#ifndef CLIENT_COMPILE + hold_server(cptr); +#endif + } else if (retval == 0) + writeb[1]++; + else if (retval < 16) + writeb[2]++; + else if (retval < 32) + writeb[3]++; + else if (retval < 64) + writeb[4]++; + else if (retval < 128) + writeb[5]++; + else if (retval < 256) + writeb[6]++; + else if (retval < 512) + writeb[7]++; + else if (retval < 1024) + writeb[8]++; + else + writeb[9]++; +#endif + if (retval > 0) + { +#if defined(DEBUGMODE) && defined(DEBUG_WRITE) + Debug((DEBUG_WRITE, "send = %d bytes to %d[%s]:[%*.*s]\n", + retval, cptr->fd, cptr->name, retval, retval, str)); +#endif + cptr->sendB += retval; + me.sendB += retval; + if (cptr->sendB > 1023) + { + cptr->sendK += (cptr->sendB >> 10); + cptr->sendB &= 0x03ff; /* 2^10 = 1024, 3ff = 1023 */ + } + if (acpt != &me) + { + acpt->sendB += retval; + if (acpt->sendB > 1023) + { + acpt->sendK += (acpt->sendB >> 10); + acpt->sendB &= 0x03ff; + } + } + else if (me.sendB > 1023) + { + me.sendK += (me.sendB >> 10); + me.sendB &= 0x03ff; + } + } + return(retval); +} diff --git a/common/bsd_ext.h b/common/bsd_ext.h new file mode 100644 index 0000000..e1ec689 --- /dev/null +++ b/common/bsd_ext.h @@ -0,0 +1,41 @@ +/************************************************************************ + * IRC - Internet Relay Chat, common/bsd_ext.h + * Copyright (C) 1997 Alain Nissen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* This file contains external definitions for global variables and functions + defined in common/bsd.c. + */ + +/* External definitions for global variables. + */ +#ifndef BSD_C +#ifdef DEBUGMODE +extern int writecalls, writeb[]; +#endif /* DEBUGMODE */ +#endif /* BSD_C */ + +/* External definitions for global functions. + */ +#ifndef BSD_C +#define EXTERN extern +#else /* BSD_C */ +#define EXTERN +#endif /* BSD_C */ +EXTERN RETSIGTYPE dummy __P((int s)); +EXTERN int deliver_it __P((aClient *cptr, char *str, int len)); +#undef EXTERN diff --git a/common/class_def.h b/common/class_def.h new file mode 100644 index 0000000..743b672 --- /dev/null +++ b/common/class_def.h @@ -0,0 +1,58 @@ +/************************************************************************ + * IRC - Internet Relay Chat, common/class_def.h + * Copyright (C) 1990 Darren Reed + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +typedef struct Class { + int class; + int conFreq; + int pingFreq; + int maxLinks; + long maxSendq; + int maxHLocal; + int maxUHLocal; + int maxHGlobal; + int maxUHGlobal; + int links; + struct Class *next; +} aClass; + +#define Class(x) ((x)->class) +#define ConFreq(x) ((x)->conFreq) +#define PingFreq(x) ((x)->pingFreq) +#define MaxLinks(x) ((x)->maxLinks) +#define MaxSendq(x) ((x)->maxSendq) +#define MaxHLocal(x) ((x)->maxHLocal) +#define MaxUHLocal(x) ((x)->maxUHLocal) +#define MaxHGlobal(x) ((x)->maxHGlobal) +#define MaxUHGlobal(x) ((x)->maxUHGlobal) +#define Links(x) ((x)->links) +#define IncSendq(x) MaxSendq(x) = (int)((float)MaxSendq(x) * 1.1) + +#define ConfLinks(x) (Class(x)->links) +#define ConfMaxLinks(x) (Class(x)->maxLinks) +#define ConfClass(x) (Class(x)->class) +#define ConfConFreq(x) (Class(x)->conFreq) +#define ConfPingFreq(x) (Class(x)->pingFreq) +#define ConfSendq(x) (Class(x)->maxSendq) +#define ConfMaxHLocal(x) (Class(x)->maxHLocal) +#define ConfMaxUHLocal(x) (Class(x)->maxUHLocal) +#define ConfMaxHGlobal(x) (Class(x)->maxHGlobal) +#define ConfMaxUHGlobal(x) (Class(x)->maxUHGlobal) + +#define FirstClass() classes +#define NextClass(x) ((x)->next) diff --git a/common/common_def.h b/common/common_def.h new file mode 100644 index 0000000..dff2150 --- /dev/null +++ b/common/common_def.h @@ -0,0 +1,88 @@ +/************************************************************************ + * IRC - Internet Relay Chat, common/common_def.h + * Copyright (C) 1990 Armin Gruner + * + * 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. + */ + +#ifdef SPRINTF +#undef SPRINTF +#endif +#if ! USE_STDARG +#define SPRINTF (void) irc_sprintf +#else +#define SPRINTF (void) sprintf +#endif + +#define DupString(x,y) do {x = (char *)MyMalloc(strlen((char *)y) + 1);\ + (void)strcpy((char *)x, (char *)y);\ + } while(0) + +#undef tolower +#define tolower(c) (tolowertab[(u_char)(c)]) + +#undef toupper +#define toupper(c) (touppertab[(u_char)(c)]) + +#undef isalpha +#undef isdigit +#undef isxdigit +#undef isalnum +#undef isprint +#undef isascii +#undef isgraph +#undef ispunct +#undef islower +#undef isupper +#undef isspace + +#define PRINT 1 +#define CNTRL 2 +#define ALPHA 4 +#define PUNCT 8 +#define DIGIT 16 +#define SPACE 32 + +#define isalpha(c) (char_atribs[(u_char)(c)]&ALPHA) +#define isspace(c) (char_atribs[(u_char)(c)]&SPACE) +#define islower(c) ((char_atribs[(u_char)(c)]&ALPHA) && \ + ((u_char)(c) > (u_char)0x5f)) +#define isupper(c) ((char_atribs[(u_char)(c)]&ALPHA) && \ + ((u_char)(c) < (u_char)0x60)) +#define isdigit(c) (char_atribs[(u_char)(c)]&DIGIT) +#define isxdigit(c) (isdigit(c) || \ + ((u_char)'a' <= (u_char)(c) && \ + (u_char)(c) <= (u_char)'f') || \ + ((u_char)'A' <= (u_char)(c) && \ + (u_char)(c) <= (u_char)'F')) +#define isalnum(c) (char_atribs[(u_char)(c)]&(DIGIT|ALPHA)) +#define isprint(c) (char_atribs[(u_char)(c)]&PRINT) +#define isascii(c) (/*((u_char)(c) >= (u_char)'\0') &&*/ \ + ((u_char)(c) <= (u_char)0x7f)) +#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 DEBUGMODE +# define Debug(x) debug x +# define DO_DEBUG_MALLOC +#else +# define Debug(x) ; +# define LOGFILE "/dev/null" +#endif + +#if defined(CHKCONF_COMPILE) || defined(CLIENT_COMPILE) +#undef ZIP_LINKS +#endif diff --git a/common/dbuf.c b/common/dbuf.c new file mode 100644 index 0000000..fbb8d97 --- /dev/null +++ b/common/dbuf.c @@ -0,0 +1,532 @@ +/************************************************************************ + * IRC - Internet Relay Chat, common/dbuf.c + * Copyright (C) 1990 Markku Savela + * + * 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: dbuf.c,v 1.8 1997/09/03 17:45:13 kalt Exp $"; +#endif + +/* +** For documentation of the *global* functions implemented here, +** see the header file (dbuf.h). +** +*/ + +#include "os.h" +#ifndef CLIENT_COMPILE +# include "s_defines.h" +#else +# include "c_defines.h" +#endif +#define DBUF_C +#ifndef CLIENT_COMPILE +# include "s_externs.h" +#else +# include "c_externs.h" +#endif +#undef DBUF_C + +#undef VALLOC + +#if !defined(VALLOC) && !defined(valloc) +#define valloc malloc +#endif + +#ifdef CLIENT_COMPILE +/* kind of ugly, eh? */ +u_int dbufalloc = 0; +#endif + +u_int poolsize = (BUFFERPOOL > 1500000) ? BUFFERPOOL : 1500000; +dbufbuf *freelist = NULL; + +/* dbuf_init--initialize a stretch of memory as dbufs. + Doing this early on should save virtual memory if not real memory.. + at the very least, we get more control over what the server is doing + + mika@cs.caltech.edu 6/24/95 +*/ + +void dbuf_init() +{ + dbufbuf *dbp; + int i = 0, nb; + + nb = poolsize / sizeof(dbufbuf); + freelist = (dbufbuf *)valloc(nb * sizeof(dbufbuf)); + if (!freelist) + return; /* screw this if it doesn't work */ + dbp = freelist; +#ifndef CLIENT_COMPILE + for( ; i < (nb - 1); i++, dbp++, istat.is_dbufnow++) +#else + for( ; i < (nb - 1); i++, dbp++) +#endif + dbp->next = (dbp + 1); + dbp->next = NULL; +#ifndef CLIENT_COMPILE + istat.is_dbufnow++; + istat.is_dbuf = istat.is_dbufnow; +#endif +} + +/* +** dbuf_alloc - allocates a dbufbuf structure either from freelist or +** creates a new one. +** Return: 0 on success, -1 on fatal alloc error, -2 on pool exceeding +*/ +static int dbuf_alloc(dbptr) +dbufbuf **dbptr; +{ +#if defined(VALLOC) && !defined(DEBUGMODE) + Reg dbufbuf *db2ptr; + Reg int num; +#endif + +#ifndef CLIENT_COMPILE + if (istat.is_dbufuse++ == istat.is_dbufmax) + istat.is_dbufmax = istat.is_dbufuse; +#else + dbufalloc++; +#endif + if ((*dbptr = freelist)) + { + freelist = freelist->next; + return 0; + } +#ifndef CLIENT_COMPILE + if (istat.is_dbufuse * DBUFSIZ > poolsize) +#else + if (dbufalloc * DBUFSIZ > poolsize) +#endif + { +#ifndef CLIENT_COMPILE + istat.is_dbufuse--; +#else + dbufalloc--; +#endif + return -2; /* Not fatal, go back and increase poolsize */ + } + +#if defined(_SC_PAGE_SIZE) && !defined(_SC_PAGESIZE) +#define _SC_PAGESIZE _SC_PAGE_SIZE +#endif +#if defined(VALLOC) && !defined(DEBUGMODE) +# if defined(SOL20) || defined(_SC_PAGESIZE) + num = sysconf(_SC_PAGESIZE)/sizeof(dbufbuf); +# else + num = getpagesize()/sizeof(dbufbuf); +# endif + if (num < 0) + num = 1; + +#ifndef CLIENT_COMPILE + istat.is_dbufnow += num; +#endif + + *dbptr = (dbufbuf *)valloc(num*sizeof(dbufbuf)); + if (!*dbptr) + return -1; + + num--; + for (db2ptr = *dbptr; num; num--) + { + db2ptr = (dbufbuf *)((char *)db2ptr + sizeof(dbufbuf)); + db2ptr->next = freelist; + freelist = db2ptr; + } + return 0; +#else +#ifndef CLIENT_COMPILE + istat.is_dbufnow++; +#endif + if (!(*dbptr = (dbufbuf *)MyMalloc(sizeof(dbufbuf)))) + return -1; + return 0; +#endif +} +/* +** dbuf_free - return a dbufbuf structure to the freelist +*/ +static void dbuf_free(ptr) +Reg dbufbuf *ptr; +{ +#ifndef CLIENT_COMPILE + istat.is_dbufuse--; +#else + dbufalloc--; +#endif + ptr->next = freelist; + freelist = ptr; +} +/* +** This is called when malloc fails. Scrap the whole content +** of dynamic buffer and return -1. (malloc errors are FATAL, +** there is no reason to continue this buffer...). After this +** the "dbuf" has consistent EMPTY status... ;) +*/ +int dbuf_malloc_error(dyn) +dbuf *dyn; + { + dbufbuf *p; + + dyn->length = 0; + dyn->offset = 0; + while ((p = dyn->head) != NULL) + { + dyn->head = p->next; + dbuf_free(p); + } +#ifdef DBUF_TAIL + dyn->tail = dyn->head; +#endif + return -1; + } + + +/* +** dbuf_put +** Append the number of bytes to the buffer, allocating more +** memory as needed. Bytes are copied into internal buffers +** from users buffer. +** +** returns > 0, if operation successfull +** < 0, if failed (due memory allocation problem) +*/ +int dbuf_put(dyn, buf, length) +dbuf *dyn; /* Dynamic buffer header */ +char *buf; /* Pointer to data to be stored */ +int length; /* Number of bytes to store */ +{ + Reg dbufbuf **h; + dbufbuf *d; +#ifdef DBUF_TAIL + dbufbuf *dtail; + Reg int off; +#else + Reg int nbr, off; +#endif + Reg int chunk, i, dlength; + + dlength = dyn->length; + + off = (dyn->offset + dyn->length) % DBUFSIZ; +#ifdef DBUF_TAIL + dtail = dyn->tail; + if (!dyn->length) + h = &(dyn->head); + else + { + if (off) + h = &(dyn->tail); + else + h = &(dyn->tail->next); + } +#else + /* + ** Locate the last non-empty buffer. If the last buffer is + ** full, the loop will terminate with 'd==NULL'. This loop + ** assumes that the 'dyn->length' field is correctly + ** maintained, as it should--no other check really needed. + */ + nbr = (dyn->offset + dyn->length) / DBUFSIZ; + for (h = &(dyn->head); (d = *h) && --nbr >= 0; h = &(d->next)); +#endif + /* + ** Append users data to buffer, allocating buffers as needed + */ + chunk = DBUFSIZ - off; + dyn->length += length; + for ( ;length > 0; h = &(d->next)) + { + if ((d = *h) == NULL) + { + if ((i = dbuf_alloc(&d))) + { + if (i == -1) /* out of memory, cleanup */ + /* modifies dyn->tail */ + dbuf_malloc_error(dyn); + else + /* If we run out of bufferpool, visit upper + * level to increase it and retry. -Vesa + */ + { + /* + ** Cancel this dbuf_put as well, + ** since it is incomplete. -krys + */ + dyn->length = dlength; +#ifdef DBUF_TAIL + dyn->tail = dtail; +#endif + } + return i; + } +#ifdef DBUF_TAIL + dyn->tail = d; +#endif + *h = d; + d->next = NULL; + } + if (chunk > length) + chunk = length; + bcopy(buf, d->data + off, chunk); + length -= chunk; + buf += chunk; + off = 0; + chunk = DBUFSIZ; + } + return 1; + } + + +/* +** dbuf_map, dbuf_delete +** These functions are meant to be used in pairs and offer +** a more efficient way of emptying the buffer than the +** normal 'dbuf_get' would allow--less copying needed. +** +** map returns a pointer to a largest contiguous section +** of bytes in front of the buffer, the length of the +** section is placed into the indicated "long int" +** variable. Returns NULL *and* zero length, if the +** buffer is empty. +** +** delete removes the specified number of bytes from the +** front of the buffer releasing any memory used for them. +** +** Example use (ignoring empty condition here ;) +** +** buf = dbuf_map(&dyn, &count); +** +** dbuf_delete(&dyn, N); +** +** Note: delete can be used alone, there is no real binding +** between map and delete functions... +*/ +char *dbuf_map(dyn,length) +dbuf *dyn; /* Dynamic buffer header */ +int *length; /* Return number of bytes accessible */ + { + if (dyn->head == NULL) + { +#ifdef DBUF_TAIL + dyn->tail = NULL; +#endif + *length = 0; + return NULL; + } + *length = DBUFSIZ - dyn->offset; + if (*length > dyn->length) + *length = dyn->length; + return (dyn->head->data + dyn->offset); + } + +int dbuf_delete(dyn,length) +dbuf *dyn; /* Dynamic buffer header */ +int length; /* Number of bytes to delete */ + { + dbufbuf *d; + int chunk; + + if (length > dyn->length) + length = dyn->length; + chunk = DBUFSIZ - dyn->offset; + while (length > 0) + { + if (chunk > length) + chunk = length; + length -= chunk; + dyn->offset += chunk; + dyn->length -= chunk; + if (dyn->offset == DBUFSIZ || dyn->length == 0) + { + if ((d = dyn->head)) + { /* What did I do? A memory leak.. ? */ + dyn->head = d->next; + dbuf_free(d); + } + dyn->offset = 0; + } + chunk = DBUFSIZ; + } + if (dyn->head == (dbufbuf *)NULL) +#ifdef DBUF_TAIL + { + dyn->tail = NULL; +#endif + dyn->length = 0; +#ifdef DBUF_TAIL + } +#endif + return 0; + } + +/* +** dbuf_get +** Remove number of bytes from the buffer, releasing dynamic +** memory, if applicaple. Bytes are copied from internal buffers +** to users buffer. +** +** returns the number of bytes actually copied to users buffer, +** if >= 0, any value less than the size of the users +** buffer indicates the dbuf became empty by this operation. +** +** Return 0 indicates that buffer was already empty. +** +** Negative return values indicate some unspecified +** error condition, rather fatal... +*/ +int dbuf_get(dyn, buf, length) +dbuf *dyn; /* Dynamic buffer header */ +char *buf; /* Pointer to buffer to receive the data */ +int length; /* Max amount of bytes that can be received */ + { + int moved = 0; + int chunk; + char *b; + + while (length > 0 && (b = dbuf_map(dyn, &chunk)) != NULL) + { + if (chunk > length) + chunk = length; + bcopy(b, buf, (int)chunk); + (void)dbuf_delete(dyn, chunk); + buf += chunk; + length -= chunk; + moved += chunk; + } + return moved; + } + +/* +int dbuf_copy(dyn, buf, length) +dbuf *dyn; +register char *buf; +int length; +{ + register dbufbuf *d = dyn->head; + register char *s; + register int chunk, len = length, dlen = dyn->length; + + s = d->data + dyn->offset; + chunk = MIN(DBUFSIZ - dyn->offset, dlen); + + while (len > 0) + { + if (chunk > dlen) + chunk = dlen; + if (chunk > len) + chunk = len; + + bcopy(s, buf, chunk); + buf += chunk; + len -= chunk; + dlen -= chunk; + + if (dlen > 0 && (d = d->next)) + { + chunk = DBUFSIZ; + s = d->data; + } + else + break; + } + return length - len; +} +*/ + +/* +** dbuf_getmsg +** +** Check the buffers to see if there is a string which is terminted with +** either a \r or \n prsent. If so, copy as much as possible (determined by +** length) into buf and return the amount copied - else return 0. +*/ +int dbuf_getmsg(dyn, buf, length) +dbuf *dyn; +char *buf; +register int length; +{ + dbufbuf *d; + register char *s; + register int dlen; + register int i; + int copy; + +getmsg_init: + d = dyn->head; + dlen = dyn->length; + i = DBUFSIZ - dyn->offset; + if (i <= 0) + return -1; + copy = 0; + if (d && dlen) + s = dyn->offset + d->data; + else + return 0; + + if (i > dlen) + i = dlen; + while (length > 0 && dlen > 0) + { + dlen--; + if (*s == '\n' || *s == '\r') + { + copy = dyn->length - dlen; + /* + ** Shortcut this case here to save time elsewhere. + ** -avalon + */ + if (copy == 1) + { + (void)dbuf_delete(dyn, 1); + goto getmsg_init; + } + break; + } + length--; + if (!--i) + { + if ((d = d->next)) + { + s = d->data; + i = MIN(DBUFSIZ, dlen); + } + } + else + s++; + } + + if (copy <= 0) + return 0; + + /* + ** copy as much of the message as wanted into parse buffer + */ + i = dbuf_get(dyn, buf, MIN(copy, length)); + /* + ** and delete the rest of it! + */ + if (copy - i > 0) + (void)dbuf_delete(dyn, copy - i); + if (i >= 0) + *(buf+i) = '\0'; /* mark end of messsage */ + + return i; +} diff --git a/common/dbuf_def.h b/common/dbuf_def.h new file mode 100644 index 0000000..1295d2d --- /dev/null +++ b/common/dbuf_def.h @@ -0,0 +1,96 @@ +/************************************************************************ + * IRC - Internet Relay Chat, common/dbuf_def.h + * Copyright (C) 1990 Markku Savela + * + * 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. + */ + +#define DBUF_TAIL + +/* +** dbuf is a collection of functions which can be used to +** maintain a dynamic buffering of a byte stream. +** Functions allocate and release memory dynamically as +** required [Actually, there is nothing that prevents +** this package maintaining the buffer on disk, either] +*/ + +/* +** These structure definitions are only here to be used +** as a whole, *DO NOT EVER REFER TO THESE FIELDS INSIDE +** THE STRUCTURES*! It must be possible to change the internal +** implementation of this package without changing the +** interface. +*/ +#if !defined(_SEQUENT_) +typedef struct dbuf + { + u_int length; /* Current number of bytes stored */ + u_int offset; /* Offset to the first byte */ + struct dbufbuf *head; /* First data buffer, if length > 0 */ +#ifdef DBUF_TAIL + /* added by mnystrom@mit.edu: */ + struct dbufbuf *tail; /* last data buffer, if length > 0 */ +#endif + } dbuf; +#else +typedef struct dbuf + { + uint length; /* Current number of bytes stored */ + uint offset; /* Offset to the first byte */ + struct dbufbuf *head; /* First data buffer, if length > 0 */ +#ifdef DBUF_TAIL + /* added by mnystrom@mit.edu: */ + struct dbufbuf *tail; /* last data buffer, if length > 0 */ +#endif + } dbuf; +#endif +/* +** And this 'dbufbuf' should never be referenced outside the +** implementation of 'dbuf'--would be "hidden" if C had such +** keyword... +** If it was possible, this would compile to be exactly 1 memory +** page in size. 2048 bytes seems to be the most common size, so +** as long as a pointer is 4 bytes, we get 2032 bytes for buffer +** data after we take away a bit for malloc to play with. -avalon +*/ +typedef struct dbufbuf + { + struct dbufbuf *next; /* Next data buffer, NULL if this is last */ + char data[2032]; /* Actual data stored here */ + } dbufbuf; + +/* +** DBufLength +** Return the current number of bytes stored into the buffer. +** (One should use this instead of referencing the internal +** length field explicitly...) +*/ +#define DBufLength(dyn) ((dyn)->length) + +/* +** DBufClear +** Scratch the current content of the buffer. Release all +** allocated buffers and make it empty. +*/ +#define DBufClear(dyn) dbuf_delete((dyn),DBufLength(dyn)) + +/* This is a dangerous define because a broken compiler will set DBUFSIZ +** to 4, which will work but will be very inefficient. However, there +** are other places where the code breaks badly if this is screwed +** up, so... -- Wumpus +*/ + +#define DBUFSIZ sizeof(((dbufbuf *)0)->data) diff --git a/common/dbuf_ext.h b/common/dbuf_ext.h new file mode 100644 index 0000000..da0a659 --- /dev/null +++ b/common/dbuf_ext.h @@ -0,0 +1,49 @@ +/************************************************************************ + * IRC - Internet Relay Chat, common/dbuf_ext.h + * Copyright (C) 1997 Alain Nissen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* This file contains external definitions for global variables and functions + defined in common/dbuf.c. + */ + +/* External definitions for global variables. + */ +#ifndef DBUF_C +#ifdef CLIENT_COMPILE +extern u_int dbufalloc; +#endif +extern u_int poolsize; +extern dbufbuf *freelist; +#endif /* DBUF_C */ + +/* External definitions for global functions. + */ +#ifndef DBUF_C +#define EXTERN extern +#else /* DBUF_C */ +#define EXTERN +#endif /* DBUF_C */ +EXTERN void dbuf_init(); +EXTERN int dbuf_malloc_error __P((dbuf *dyn)); +EXTERN int dbuf_put __P((dbuf *dyn, char *buf, int length)); +EXTERN char *dbuf_map __P((dbuf *dyn, int *length)); +EXTERN int dbuf_delete __P((dbuf *dyn, int length)); +EXTERN int dbuf_get __P((dbuf *dyn, char *buf, int length)); +EXTERN int dbuf_copy __P((dbuf *dyn, register char *buf, int length)); +EXTERN int dbuf_getmsg __P((dbuf *dyn, char *buf, register int length)); +#undef EXTERN diff --git a/common/match.c b/common/match.c new file mode 100644 index 0000000..ad2bda6 --- /dev/null +++ b/common/match.c @@ -0,0 +1,314 @@ +/************************************************************************ + * IRC - Internet Relay Chat, common/match.c + * Copyright (C) 1990 Jarkko Oikarinen + * + * 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: match.c,v 1.5 1999/02/05 22:00:25 kalt Exp $"; +#endif + +#include "os.h" +#ifndef CLIENT_COMPILE +# include "s_defines.h" +#else +# include "c_defines.h" +#endif +#define MATCH_C +#ifndef CLIENT_COMPILE +# include "s_externs.h" +#else +# include "c_externs.h" +#endif +#undef MATCH_C + +unsigned char tolowertab[] = + { 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, + 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, + 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, + 0x1e, 0x1f, + ' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')', + '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + ':', ';', '<', '=', '>', '?', + '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', + 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', + '_', + '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', + 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', + 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, + 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, + 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, + 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, + 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, + 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, + 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, + 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff }; + +unsigned char touppertab[] = + { 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, + 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, + 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, + 0x1e, 0x1f, + ' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')', + '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + ':', ';', '<', '=', '>', '?', + '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', + 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', + 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', + 0x5f, + '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', + 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', + 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', + 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, + 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, + 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, + 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, + 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, + 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, + 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, + 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff }; + +unsigned char char_atribs[] = { +/* 0-7 */ CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, +/* 8-12 */ CNTRL, CNTRL|SPACE, CNTRL|SPACE, CNTRL|SPACE, CNTRL|SPACE, +/* 13-15 */ CNTRL|SPACE, CNTRL, CNTRL, +/* 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, +/* 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, +/* 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, +/* a0-af */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/* b0-bf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/* c0-cf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/* d0-df */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/* e0-ef */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/* f0-ff */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + +#define MAX_ITERATIONS 512 +/* +** Compare if a given string (name) matches the given +** mask (which can contain wild cards: '*' - match any +** number of chars, '?' - match any single character. +** +** return 0, if match +** 1, if no match +*/ + +/* +** match() +** Iterative matching function, rather than recursive. +** Written by Douglas A Lewis (dalewis@acsu.buffalo.edu) +*/ + +int match(mask, name) +char *mask, *name; +{ + Reg u_char *m = (u_char *)mask, *n = (u_char *)name; + char *ma = mask, *na = name; + int wild = 0, q = 0, calls = 0; + + while (1) + { +#ifdef MAX_ITERATIONS + if (calls++ > MAX_ITERATIONS) + break; +#endif + + if (*m == '*') + { + while (*m == '*') + m++; + wild = 1; + ma = (char *)m; + na = (char *)n; + } + + if (!*m) + { + if (!*n) + return 0; + for (m--; (m > (u_char *)mask) && (*m == '?'); m--) + ; + if ((m > (u_char *)mask) && (*m == '*') && + (m[-1] != '\\')) + return 0; + if (!wild) + return 1; + m = (u_char *)ma; + n = (u_char *)++na; + } + else if (!*n) + return 1; + if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?'))) + { + m++; + q = 1; + } + else + q = 0; + + if ((tolower(*m) != tolower(*n)) && ((*m != '?') || q)) + { + if (!wild) + return 1; + m = (u_char *)ma; + n = (u_char *)++na; + } + else + { + if (*m) + m++; + if (*n) + n++; + } + } + + return 1; +} + + +/* +** collapse a pattern string into minimal components. +** This particular version is "in place", so that it changes the pattern +** which is to be reduced to a "minimal" size. +*/ +char *collapse(pattern) +char *pattern; +{ + Reg char *s = pattern, *s1, *t; + + if (BadPtr(pattern)) + return pattern; + /* + * Collapse all \** into \*, \*[?]+\** into \*[?]+ + */ + for (; *s; s++) + if (*s == '\\') + if (!*(s + 1)) + break; + else + s++; + else if (*s == '*') + { + if (*(t = s1 = s + 1) == '*') + while (*t == '*') + t++; + else if (*t == '?') + for (t++, s1++; *t == '*' || *t == '?'; t++) + if (*t == '?') + *s1++ = *t; + while ((*s1++ = *t++)) + ; + } + return pattern; +} + + +/* +** Case insensitive comparison of two NULL terminated strings. +** +** returns 0, if s1 equal to s2 +** <0, if s1 lexicographically less than s2 +** >0, if s1 lexicographically greater than s2 +*/ +int mycmp(s1, s2) +char *s1; +char *s2; + { + Reg unsigned char *str1 = (unsigned char *)s1; + Reg unsigned char *str2 = (unsigned char *)s2; + Reg int res; + + while ((res = toupper(*str1) - toupper(*str2)) == 0) + { + if (*str1 == '\0') + return 0; + str1++; + str2++; + } + return (res); + } + + +int myncmp(str1, str2, n) +char *str1; +char *str2; +int n; + { + Reg unsigned char *s1 = (unsigned char *)str1; + Reg unsigned char *s2 = (unsigned char *)str2; + Reg int res; + + while ((res = toupper(*s1) - toupper(*s2)) == 0) + { + s1++; s2++; n--; + if (n == 0 || (*s1 == '\0' && *s2 == '\0')) + return 0; + } + return (res); + } diff --git a/common/match_ext.h b/common/match_ext.h new file mode 100644 index 0000000..4953bcf --- /dev/null +++ b/common/match_ext.h @@ -0,0 +1,43 @@ +/************************************************************************ + * IRC - Internet Relay Chat, common/match_ext.h + * Copyright (C) 1997 Alain Nissen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* This file contains external definitions for global variables and functions + defined in common/match.c. + */ + +/* External definitions for global variables. + */ +#ifndef MATCH_C +extern unsigned char tolowertab[]; +extern unsigned char touppertab[]; +extern unsigned char char_atribs[]; +#endif /* MATCH_C */ + +/* External definitions for global functions. + */ +#ifndef MATCH_C +#define EXTERN extern +#else /* MATCH_C */ +#define EXTERN +#endif /* MATCH_C */ +EXTERN int match __P((char *mask, char *name)); +EXTERN char *collapse __P((char *pattern)); +EXTERN int mycmp __P((char *s1, char *s2)); +EXTERN int myncmp __P((char *str1, char *str2, int n)); +#undef EXTERN diff --git a/common/msg_def.h b/common/msg_def.h new file mode 100644 index 0000000..9d6096d --- /dev/null +++ b/common/msg_def.h @@ -0,0 +1,77 @@ +/************************************************************************ + * IRC - Internet Relay Chat, common/msg_def.h + * Copyright (C) 1990 Jarkko Oikarinen and + * University of Oulu, Computing Center + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#define MSG_PRIVATE "PRIVMSG" /* PRIV */ +#define MSG_WHO "WHO" /* WHO -> WHOC */ +#define MSG_WHOIS "WHOIS" /* WHOI */ +#define MSG_WHOWAS "WHOWAS" /* WHOW */ +#define MSG_USER "USER" /* USER */ +#define MSG_NICK "NICK" /* NICK */ +#define MSG_SERVER "SERVER" /* SERV */ +#define MSG_LIST "LIST" /* LIST */ +#define MSG_TOPIC "TOPIC" /* TOPI */ +#define MSG_INVITE "INVITE" /* INVI */ +#define MSG_VERSION "VERSION" /* VERS */ +#define MSG_QUIT "QUIT" /* QUIT */ +#define MSG_SQUIT "SQUIT" /* SQUI */ +#define MSG_KILL "KILL" /* KILL */ +#define MSG_INFO "INFO" /* INFO */ +#define MSG_LINKS "LINKS" /* LINK */ +#define MSG_SUMMON "SUMMON" /* SUMM */ +#define MSG_STATS "STATS" /* STAT */ +#define MSG_USERS "USERS" /* USER -> USRS */ +#define MSG_HELP "HELP" /* HELP */ +#define MSG_ERROR "ERROR" /* ERRO */ +#define MSG_AWAY "AWAY" /* AWAY */ +#define MSG_CONNECT "CONNECT" /* CONN */ +#define MSG_PING "PING" /* PING */ +#define MSG_PONG "PONG" /* PONG */ +#define MSG_OPER "OPER" /* OPER */ +#define MSG_PASS "PASS" /* PASS */ +#define MSG_WALLOPS "WALLOPS" /* WALL */ +#define MSG_TIME "TIME" /* TIME */ +#define MSG_NAMES "NAMES" /* NAME */ +#define MSG_ADMIN "ADMIN" /* ADMI */ +#define MSG_TRACE "TRACE" /* TRAC */ +#define MSG_NOTICE "NOTICE" /* NOTI */ +#define MSG_JOIN "JOIN" /* JOIN */ +#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_UMODE "UMODE" /* UMOD */ +#define MSG_KICK "KICK" /* KICK */ +#define MSG_RECONECT "RECONNECT" /* RECONNECT -> RECO */ +#define MSG_SERVICE "SERVICE" /* SERV -> SRVI */ +#define MSG_USERHOST "USERHOST" /* USER -> USRH */ +#define MSG_ISON "ISON" /* ISON */ +#define MSG_NOTE "NOTE" /* NOTE */ +#define MSG_SQUERY "SQUERY" /* SQUE */ +#define MSG_SERVLIST "SERVLIST" /* SERV -> SLIS */ +#define MSG_SERVSET "SERVSET" /* SERV -> SSET */ +#define MSG_REHASH "REHASH" /* REHA */ +#define MSG_RESTART "RESTART" /* REST */ +#define MSG_CLOSE "CLOSE" /* CLOS */ +#define MSG_DIE "DIE" +#define MSG_HASH "HAZH" /* HASH */ +#define MSG_DNS "DNS" /* DNS -> DNSS */ + +#define MAXPARA 15 diff --git a/common/numeric_def.h b/common/numeric_def.h new file mode 100644 index 0000000..c1b095c --- /dev/null +++ b/common/numeric_def.h @@ -0,0 +1,337 @@ +/************************************************************************ + * IRC - Internet Relay Chat, common/numeric_def.h + * Copyright (C) 1990 Jarkko Oikarinen + * + * 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. + */ + +/* + * -- Avalon -- 1 Sep 1992 + * + * Added RPL_TRACELOG, RPL_STATSOLINE + */ + +/* + * -- Avalon -- 13 Aug 1992 + * + * Added ERR_BADCHANNELKEY, ERR_KEYSET + */ + +/* + * -- Avalon -- 10 Aug 1992 + * + * Added RPL_SUMMONING + */ + +/* + * -- Avalon -- 5 Jul 1992 + * + * Added ERR_NICKCOLLISION + */ + +/* + * -- Avalon -- 14 Jul 1992 + * + * Added RPL_UNAWAY, RPL_NOWAWAY, ERR_NOORIGIN, ERR_FILEERROR, ERR_NOLOGIN, + * ERR_SUMMONDISABLED, ERR_USERSDISABLED, RPL_USERSSTART, RPL_USERS, + * RPL_ENDOFUSERS, RPL_NOUSERS + */ + +/* + * -- Avalon -- 12 Jul 1992 + * + * Added RPL_CLOSING RPL_CLOSEEND + */ + +/* + * -- Avalon -- 10-11 Jul 1992 + * + * Added RPL_MOTD, RPL_MOTDSTART, RPL_ENDOFMOTD, ERR_NOMOTD, + * RPL_INFO, RPL_INFOSTART, RPL_ENDOFINFO, ERR_CANTKILLSERVER, + * RPL_LUSERCLIENT, RPL_LUSEROP, RPL_LUSERUNKNOWN, RPL_LUSERCHAN, RPL_LUSERME, + * RPL_STATSUPTIME, RPL_ADMINLOC1, RPL_ADMINLOC2, RPL_ADMINME, + * RPL_ADMINEMAIL, ERR_NOADMININFO + */ + +/* + * -- Avalon -- 28 Jun 1992 + * + * Added ERR_BADCHANMASK and RPL_ENDOFWHOWAS + */ + +/* + * -- Avalon -- 13 May 1992 + * + * Added RPL_STATSLLINE + */ + +/* + * -- Avalon -- 12 Jan 1992 + * + * Added RPL_TRACELINK + */ + +/* + * -- Wumpus -- 30 Nov 1991 + * + * It's very important that you never change what a numeric means -- + * you can delete old ones (maybe) and add new ones, but never ever + * take a number and make it suddenly mean something else, or change + * an old number just for the hell of it. + */ + +/* + * -- avalon -- 19 Nov 1991 + * Added ERR_USERSDONTMATCH + * + * -- avalon -- 06 Nov 1991 + * Added RPL_BANLIST, RPL_BANLISTEND, ERR_BANNEDFROMCHAN + * + * -- avalon -- 15 Oct 1991 + * Added RPL_TRACEs (201-209) + * Added RPL_STATSs (211-219) + */ + +/* -- Jto -- 16 Jun 1990 + * A couple of new numerics added... + */ + +/* -- Jto -- 03 Jun 1990 + * Added ERR_YOUWILLBEBANNED and Check defines (sigh, had to put 'em here..) + * Added ERR_UNKNOWNMODE... + * Added ERR_CANNOTSENDTOCHAN... + */ + +/* + * Reserve numerics 000-099 for server-client connections where the client + * is local to the server. If any server is passed a numeric in this range + * from another server then it is remapped to 100-199. -avalon + */ +#define RPL_WELCOME 001 +#define RPL_YOURHOST 002 +#define RPL_CREATED 003 +#define RPL_MYINFO 004 +#define RPL_BOUNCE 005 + +/* + * Errors are in the range from 400-599 currently and are grouped by what + * commands they come from. + */ +#define ERR_NOSUCHNICK 401 +#define ERR_NOSUCHSERVER 402 +#define ERR_NOSUCHCHANNEL 403 +#define ERR_CANNOTSENDTOCHAN 404 +#define ERR_TOOMANYCHANNELS 405 +#define ERR_WASNOSUCHNICK 406 +#define ERR_TOOMANYTARGETS 407 +#define ERR_NOSUCHSERVICE 408 +#define ERR_NOORIGIN 409 + +#define ERR_NORECIPIENT 411 +#define ERR_NOTEXTTOSEND 412 +#define ERR_NOTOPLEVEL 413 +#define ERR_WILDTOPLEVEL 414 +#define ERR_BADMASK 415 +#define ERR_TOOMANYMATCHES 416 + +#define ERR_UNKNOWNCOMMAND 421 +#define ERR_NOMOTD 422 +#define ERR_NOADMININFO 423 +#define ERR_FILEERROR 424 + +#define ERR_NONICKNAMEGIVEN 431 +#define ERR_ERRONEUSNICKNAME 432 +#define ERR_NICKNAMEINUSE 433 +#define ERR_SERVICENAMEINUSE 434 +#define ERR_SERVICECONFUSED 435 +#define ERR_NICKCOLLISION 436 +#define ERR_UNAVAILRESOURCE 437 +/* #define ERR_DEAD 438 reserved for later use -krys */ + +#define ERR_USERNOTINCHANNEL 441 +#define ERR_NOTONCHANNEL 442 +#define ERR_USERONCHANNEL 443 +#define ERR_NOLOGIN 444 +#define ERR_SUMMONDISABLED 445 +#define ERR_USERSDISABLED 446 + +#define ERR_NOTREGISTERED 451 + +#define ERR_NEEDMOREPARAMS 461 +#define ERR_ALREADYREGISTRED 462 +#define ERR_NOPERMFORHOST 463 +#define ERR_PASSWDMISMATCH 464 +#define ERR_YOUREBANNEDCREEP 465 +#define ERR_YOUWILLBEBANNED 466 +#define ERR_KEYSET 467 + +#define ERR_CHANNELISFULL 471 +#define ERR_UNKNOWNMODE 472 +#define ERR_INVITEONLYCHAN 473 +#define ERR_BANNEDFROMCHAN 474 +#define ERR_BADCHANNELKEY 475 +#define ERR_BADCHANMASK 476 +#define ERR_NOCHANMODES 477 +#define ERR_BANLISTFULL 478 + +#define ERR_NOPRIVILEGES 481 +#define ERR_CHANOPRIVSNEEDED 482 +#define ERR_CANTKILLSERVER 483 +#define ERR_RESTRICTED 484 +#define ERR_UNIQOPRIVSNEEDED 485 + +#define ERR_NOOPERHOST 491 +#define ERR_NOSERVICEHOST 492 + +#define ERR_UMODEUNKNOWNFLAG 501 +#define ERR_USERSDONTMATCH 502 + +/* + * Numberic replies from server commands. + * These are currently in the range 200-399. + */ +#define RPL_NONE 300 +#define RPL_AWAY 301 +#define RPL_USERHOST 302 +#define RPL_ISON 303 +#define RPL_TEXT 304 +#define RPL_UNAWAY 305 +#define RPL_NOWAWAY 306 + +#define RPL_WHOISUSER 311 +#define RPL_WHOISSERVER 312 +#define RPL_WHOISOPERATOR 313 + +#define RPL_WHOWASUSER 314 +/* rpl_endofwho below (315) */ +#define RPL_ENDOFWHOWAS 369 + +#define RPL_WHOISCHANOP 316 /* redundant and not needed but reserved */ +#define RPL_WHOISIDLE 317 + +#define RPL_ENDOFWHOIS 318 +#define RPL_WHOISCHANNELS 319 + +#define RPL_LISTSTART 321 +#define RPL_LIST 322 +#define RPL_LISTEND 323 +#define RPL_CHANNELMODEIS 324 +#define RPL_UNIQOPIS 325 + +#define RPL_NOTOPIC 331 +#define RPL_TOPIC 332 + +#define RPL_INVITING 341 +#define RPL_SUMMONING 342 + +#define RPL_INVITELIST 346 +#define RPL_ENDOFINVITELIST 347 + +#define RPL_EXCEPTLIST 348 +#define RPL_ENDOFEXCEPTLIST 349 + +#define RPL_VERSION 351 + +#define RPL_WHOREPLY 352 +#define RPL_ENDOFWHO 315 +#define RPL_NAMREPLY 353 +#define RPL_ENDOFNAMES 366 + +#define RPL_KILLDONE 361 +#define RPL_CLOSING 362 +#define RPL_CLOSEEND 363 +#define RPL_LINKS 364 +#define RPL_ENDOFLINKS 365 +/* rpl_endofnames above (366) */ +#define RPL_BANLIST 367 +#define RPL_ENDOFBANLIST 368 +/* rpl_endofwhowas above (369) */ + +#define RPL_INFO 371 +#define RPL_MOTD 372 +#define RPL_INFOSTART 373 +#define RPL_ENDOFINFO 374 +#define RPL_MOTDSTART 375 +#define RPL_ENDOFMOTD 376 + +#define RPL_YOUREOPER 381 +#define RPL_REHASHING 382 +#define RPL_YOURESERVICE 383 +#define RPL_MYPORTIS 384 +#define RPL_NOTOPERANYMORE 385 + +#define RPL_TIME 391 +#define RPL_USERSSTART 392 +#define RPL_USERS 393 +#define RPL_ENDOFUSERS 394 +#define RPL_NOUSERS 395 + +#define RPL_TRACELINK 200 +#define RPL_TRACECONNECTING 201 +#define RPL_TRACEHANDSHAKE 202 +#define RPL_TRACEUNKNOWN 203 +#define RPL_TRACEOPERATOR 204 +#define RPL_TRACEUSER 205 +#define RPL_TRACESERVER 206 +#define RPL_TRACESERVICE 207 +#define RPL_TRACENEWTYPE 208 +#define RPL_TRACECLASS 209 +#define RPL_TRACERECONNECT 210 + +#define RPL_STATSLINKINFO 211 +#define RPL_STATSCOMMANDS 212 +#define RPL_STATSCLINE 213 +#define RPL_STATSNLINE 214 +#define RPL_STATSILINE 215 +#define RPL_STATSKLINE 216 +#define RPL_STATSQLINE 217 +#define RPL_STATSYLINE 218 +#define RPL_ENDOFSTATS 219 + +#define RPL_UMODEIS 221 + +#define RPL_SERVICEINFO 231 +#define RPL_ENDOFSERVICES 232 +#define RPL_SERVICE 233 +#define RPL_SERVLIST 234 +#define RPL_SERVLISTEND 235 + +#define RPL_STATSIAUTH 239 +#define RPL_STATSVLINE 240 +#define RPL_STATSLLINE 241 +#define RPL_STATSUPTIME 242 +#define RPL_STATSOLINE 243 +#define RPL_STATSHLINE 244 +#define RPL_STATSSLINE 245 +#define RPL_STATSPING 246 +#define RPL_STATSBLINE 247 +#define RPL_STATSDEFINE 248 +#define RPL_STATSDEBUG 249 +#define RPL_STATSDLINE 250 + +#define RPL_LUSERCLIENT 251 +#define RPL_LUSEROP 252 +#define RPL_LUSERUNKNOWN 253 +#define RPL_LUSERCHANNELS 254 +#define RPL_LUSERME 255 +#define RPL_ADMINME 256 +#define RPL_ADMINLOC1 257 +#define RPL_ADMINLOC2 258 +#define RPL_ADMINEMAIL 259 + +#define RPL_TRACELOG 261 +#define RPL_TRACEEND 262 +#define RPL_TRYAGAIN 263 + diff --git a/common/os.h b/common/os.h new file mode 100644 index 0000000..a556764 --- /dev/null +++ b/common/os.h @@ -0,0 +1,765 @@ +/************************************************************************ + * IRC - Internet Relay Chat, include/os.h + * Copyright (C) 1997 Alain Nissen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* This file contains the various system-relative "#include" lines needed for + getting all system types, macros, external variables and functions defined. + + This file also contains definitions of types, constants, macros, external + variables and functions that are missing in the include files of some OS, + or need to be redefined for various reasons. + */ + +#include "setup.h" + +#if HAVE_STDIO_H +# include +#endif + +#if HAVE_STDLIB_H +# include +#endif + +#if HAVE_SYS_TYPES_H +# include +#endif + +#if HAVE_SYS_BITYPES_H +# include +#endif + +#if HAVE_STDDEF_H +# include +#endif + +#if USE_STDARG +# include +#endif + +#if HAVE_UNISTD_H +# include +#endif + +#if HAVE_CTYPE_H +# include +#endif + +#if HAVE_MEMORY_H +# include +#endif + +#if HAVE_VFORK_H +# include +#endif + +#if HAVE_ERRNO_H +# include +#endif + +#if HAVE_SYS_ERRNO_H +# include +#endif + +#if HAVE_SYS_SYSCALL_H +# include +#endif + +#if HAVE_PWD_H +# include +#endif + +#if HAVE_MATH_H +# include +#endif + +#if HAVE_UTMP_H +# include +#endif + +#if HAVE_FCNTL_H +# include +#endif + +#if HAVE_SIGNAL_H +# include +#endif + +#if HAVE_SYS_WAIT_H +# include +#endif + +#if HAVE_SYS_IOCTL_H +# include +#endif + +#if HAVE_SYS_FILE_H +# include +#endif + +#if HAVE_SYS_FILIO_H +# include +#endif + +#if HAVE_SYS_SOCKET_H +# include +#endif + +#if HAVE_SYS_STAT_H +# include +#endif + +#if HAVE_SYS_SELECT_H +# include +#endif + +#if HAVE_SYS_POLL_H +# if linux +/* Linux is just soooo broken */ +# define _GNU_SOURCE 1 +# endif +# include +# if linux && !defined(POLLRDNORM) +/* Linux 2.1.xx supports poll(), header files are not upto date yet */ +# define POLLRDNORM 0x0040 +# endif +#endif + +#if HAVE_STROPTS_H +# include +#endif + +#if HAVE_NETDB_H +# if BAD___CONST_NETDB_H +# ifndef __const +# define __const +# include +# undef __const +# else +# include +# endif +# else +# include +# endif +#endif + +#if HAVE_NETINET_IN_H +# include +#endif + +#if HAVE_SYS_UN_H +# include +#endif + +#if HAVE_ARPA_INET_H +# include +#endif + +#if HAVE_SYS_PARAM_H +# include +#endif + +#if HAVE_SYS_SYSLOG_H +# include +#else +# if HAVE_SYSLOG_H +# include +# endif +#endif + +#if HAVE_STRING_H +# include +#else +# if HAVE_STRINGS_H +# include +# endif +#endif + +#if TIME_WITH_SYS_TIME +# include +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif + +#if HAVE_SYS_RESOURCE_H +# include +#endif + +#if HAVE_SYS_TIMES_H +# include +#endif + +#if HAVE_NETINET_IN_SYSTM_H +# include +#endif + +#if HAVE_NETINFO_NI_H +# include +#endif + +#if USE_ZLIB && !defined(CLIENT_COMPILE) && !defined(CHKCONF_COMPILE) && \ + !defined(CONTRIB_COMPILE) +# include +#endif + +#if defined(INET6) && defined(CLIENT_COMPILE) +# if (defined(linux) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__osf__)) && \ + HAVE_RESOLV_H +# include +# endif +# if HAVE_ARPA_NAMESER_H +# include +# endif +#endif + +#if defined(HAVE_DLFCN_H) +# include +#endif + +#if (defined(__FreeBSD__) ||\ + defined(__OpenBSD__) ||\ + defined(__NetBSD__) ) && !defined(__ELF__) +# define DLSYM_NEEDS_UNDERSCORE +#endif + +/* Some special include files for a special OS. :) + */ + +#ifdef ISC +# include +# include +# include +# include +#endif + +/* Definition of __P for handling possible prototype-syntax problems. + */ + +#ifdef __P +# undef __P +#endif +#if __STDC__ +# define __P(x) x +#else +# define __P(x) () +#endif + +/* Some additional system-relative defines that make the code easier. + * + * Note. In fact, the C code should never use system-specific tests; as you + * know, numerous people worked on it in the past, so now it is + * difficult for me to know why such tests are used in the code. But I + * still hope this part of the include file will be cleaned up in + * further releases. -- Alain.Nissen@ulg.ac.be + */ + +#if defined(ultrix) || defined(__ultrix) || defined(__ultrix__) +# ifdef ULTRIX +# undef ULTRIX +# endif +# define ULTRIX +#endif + +#if defined(aix) || defined(_AIX) +# ifdef AIX +# undef AIX +# endif +# define AIX +#endif + +#if defined(sgi) || defined(__sgi) || defined(__sgi__) +# ifdef SGI +# undef SGI +# endif +# define SGI +#endif + +#ifdef NeXT +# ifdef NEXT +# undef NEXT +# endif +# define NEXT +#endif + +#if defined(hpux) || defined(__hpux) +# ifdef HPUX +# undef HPUX +# endif +# define HPUX +#endif + +#if defined(_SVR4) || defined(__SVR4) || defined(__SVR4__) || defined(__svr4__) +# ifdef SVR4 +# undef SVR4 +# endif +# define SVR4 +#endif + +#ifdef __osf__ +# ifdef OSF +# undef OSF +# endif +# define OSF +# ifndef BSD +# define BSD 1 +# endif +#endif + +#if defined(sequent) || defined(__sequent) || defined(__sequent) +# ifdef _SEQUENT_ +# undef _SEQUENT_ +# endif +# define _SEQUENT_ +# undef BSD +# define SYSV +# define DYNIXPTX +#endif + +#if defined(mips) || defined(PCS) +#undef SYSV +#endif + +#ifdef MIPS +#undef BSD +#define BSD 1 /* mips only works in bsd43 environment */ +#endif + +#define Reg register + +/* Strings and memory functions portability problems. + */ + +#if HAVE_MEMCMP && MEMCMP_BROKEN +# define memcmp irc_memcmp +#endif + +#if HAVE_STRCHR +# ifdef index +# undef index +# endif +# define index strchr +#endif + +#if HAVE_STRRCHR +# ifdef rindex +# undef rindex +# endif +# define rindex strrchr +#endif + +#if ! HAVE_STRCHR && HAVE_INDEX +# ifdef strchr +# undef strchr +# endif +# define strchr index +#endif + +#if ! HAVE_STRRCHR && HAVE_RINDEX +# ifdef strrchr +# undef strrchr +# endif +# define strrchr rindex +#endif + +#if HAVE_MEMCMP +# ifdef bcmp +# undef bcmp +# endif +# define bcmp memcmp +#endif + +#if HAVE_MEMSET +# ifdef bzero +# undef bzero +# endif +# define bzero(a,b) memset((a),0,(b)) +#endif + +#if HAVE_MEMMOVE +# ifdef bcopy +# undef bcopy +# endif +# define bcopy(a,b,c) memmove((b),(a),(c)) +#endif + +#if ! HAVE_MEMCMP && HAVE_BCMP +# ifdef memcmp +# undef memcmp +# endif +# define memcmp bcmp +#endif + +#if ! HAVE_MEMCPY && HAVE_BCOPY +# ifdef memcpy +# undef memcpy +# endif +# define memcpy(d,s,n) bcopy((s),(d),(n)) +#endif + +#define strcasecmp mycmp +#define strncasecmp myncmp + +/* inet_ntoa(), inet_aton(), inet_addr() and inet_netof() portability + * problems. + * + * The undefs and prototypes are "needed" because of the way Paul Vixie + * majorly screws up system's include files with Bind. In this case, it's + * Bind 8.x installing /usr[/local]/include/arpa/inet.h -krys + */ + +#if HAVE_INET_NTOA +# ifdef inet_ntoa +# undef inet_ntoa +extern char *inet_ntoa __P((struct in_addr in)); +# endif +# define inetntoa(x) inet_ntoa(*(struct in_addr *)(x)) +#endif +#if HAVE_INET_ATON +# ifdef inet_aton +# undef inet_aton +extern int inet_aton __P((const char *cp, struct in_addr *addr)); +# endif +# define inetaton inet_aton +#endif +#if HAVE_INET_ADDR +# ifdef inet_addr +# undef inet_addr +extern unsigned long int inet_addr __P((const char *cp)); +# endif +# define inetaddr inet_addr +#endif +#if HAVE_INET_NETOF +# ifdef inet_netof +# undef inet_netof +extern int inet_netof __P((struct in_addr in)); +# endif +# define inetnetof inet_netof +#endif +#if ! HAVE_ARPA_INET_H +extern unsigned long int inet_addr __P((const char *cp)); +extern int inet_aton __P((const char *cp, struct in_addr *addr)); +extern int inet_netof __P((struct in_addr in)); +extern char *inet_ntoa __P((struct in_addr in)); +#endif + +/* Signals portability problems. + */ + +#ifdef HPUX +# ifndef SIGWINCH /*pre 9.0*/ +# define SIGWINCH SIGWINDOW +# endif +#endif + +#if BSD_RELIABLE_SIGNALS || POSIX_SIGNALS +#define HAVE_RELIABLE_SIGNALS +#endif + +/* Curses/Termcap portability problems (client only). + */ + +#ifdef CLIENT_COMPILE +#if USE_NCURSES || USE_CURSESX || USE_CURSES +# define DOCURSES +# if USE_CURSESX && HAVE_CURSESX_H +# include +# endif +# if (USE_NCURSES || USE_CURSES) && HAVE_CURSES_H +# if HAVE_NCURSES_H +# include +# else +# include +# endif +# endif +#else +# undef DOCURSES +#endif /* USE_NCURSES || ... */ + +#if USE_TERMCAP +# define DOTERMCAP +# if HAVE_SGTTY_H +# include +# endif +#else +# undef DOTERMCAP +#endif /* USE_TERMCAP */ +#endif /* CLIENT_COMPILE */ + +/* ctime portability problems. + */ + +#if defined(HPUX) && __STDC__ +# define ctime(x) (ctime((const time_t *)(x))) +#endif + +/* getsockopt portability problems. + */ + +#ifdef apollo +# undef IP_OPTIONS /* Defined in /usr/include/netinet/in.h but doesn't work */ +#endif + +/* setlinebuf portability problems. + */ + +#if defined(HPUX) && !defined(SYSV) && !defined(SVR4) || defined(__CYGWIN32__) +# define setlinebuf(x) (setvbuf((x), NULL, _IOLBF, BUFSIZ)) +#endif + + +/* gethostbyname portability problems. + */ + +#if SOLARIS_2_0_2_1_2_2 +/* + * On Solaris 2.0, 2.1 and 2.2 (SunOS 5.0, 5.1 and 5.2) systems, + * gethostbyname() has a bug, it always returns null in h->aliases. + * Workaround: use the undocumented __switch_gethostbyname(...). + */ +extern struct hostent *__switch_gethostbyname __P((const char *name)); +#define gethostbyname __switch_gethostbyname +#endif + +#if SOLARIS_2_3 +/* + * On Solaris 2.3 (SunOS 5.3) systems, gethostbyname() has a bug, it always + * returns null in h->aliases. Workaround: use the undocumented + * _switch_gethostbyname_r(...). + */ +extern struct hostent *_switch_gethostbyname_r __P((const char *name, + struct hostent *hp, + char *buf, int size, + int *h_errno)); +#define gethostbyname solaris_gethostbyname +#endif + +/* Resolver portability problems. + */ + +#ifdef __m88k__ +# define __BIND_RES_TEXT +#endif + +#ifndef NETDB_INTERNAL /* defined in latest BIND's */ +# define NETDB_INTERNAL -1 /* but not in every vendors' */ +#endif + +/* getrusage portability problems. + */ + +#if defined(HPUX) && ! HAVE_GETRUSAGE +# define getrusage(a,b) (syscall(SYS_GETRUSAGE, (a), (b))) +# define HAVE_GETRUSAGE 1 +#endif + +/* select portability problems - some systems do not define FD_... macros; on + * some systems (for example HPUX), select uses an int * instead of an + * fd_set * for its 2nd, 3rd and 4th arguments. + * + * Note. This test should be more portable and put in configure ... but I've + * no idea on how to build a test for configure that will guess if the + * system uses int * or fd_set * inside select(). If you've some idea, + * please tell it to me. :) -- Alain.Nissen@ulg.ac.be + */ + +#if ! USE_POLL +# ifndef FD_ZERO +# define FD_ZERO(set) (((set)->fds_bits[0]) = 0) +# define FD_SET(s1, set) (((set)->fds_bits[0]) |= 1 << (s1)) +# define FD_ISSET(s1, set) (((set)->fds_bits[0]) & (1 << (s1))) +# define FD_SETSIZE 30 +# endif /* FD_ZERO */ +# if defined(HPUX) && (! defined(_XPG4_EXTENDED) || (defined(_XPG4_EXTENDED) && defined(__INCLUDE_FROM_TIME_H) && !defined(_XOPEN_SOURCE_EXTENDED))) +# define SELECT_FDSET_TYPE int +# else +# define SELECT_FDSET_TYPE fd_set +# endif +#else /* should not be here - due to irc/c_bsd.c that does not support poll */ +# define SELECT_FDSET_TYPE fd_set +#endif /* USE_POLL */ + +/* POSIX.1 portability problems - HAVE_SYS_WAIT_H is defined + * only if is compatible with POSIX.1 - if not included, a + * prototype must be supplied for wait (wait3 and waitpid are unused here). + */ + +#if ! HAVE_SYS_WAIT_H +# if USE_UNION_WAIT +extern pid_t wait __P((union wait *)); +# else +extern pid_t wait __P((int *)); +# endif +#endif + +/* portability problems - X/Open SPEC 1170 specifies that + * the length parameter of socket operations must be a size_t + * (resp. size_t *), instead of an int (resp. int *); the problem is that + * only a few systems (for example AIX 4.2) follow this specification; others + * systems still use int (resp. int *), which is not always equal to size_t + * (resp. size_t *). + * + * Note. This test should be more portable and put in configure ... but I've + * no idea on how to build a test for configure that will guess if the + * system uses size_t or int for their socket operations. If you've some + * idea, please tell it to me. :) -- Alain.Nissen@ulg.ac.be + */ + +#if defined(AIX) && defined(_XOPEN_SOURCE_EXTENDED) && _XOPEN_SOURCE_EXTENDED +# define SOCK_LEN_TYPE size_t +#else +# define SOCK_LEN_TYPE int +#endif + +/* Stupid typo in AIX 3.2's . + */ + +#if AIX_3_2 +# ifdef _IO +# undef _IO +# endif +# define _IO(x,y) (IOC_VOID|((x)<<8)|(y)) +#endif + +/* These macros may be broken. + */ + +#if STAT_MACROS_BROKEN +# ifdef S_ISFIFO +# undef S_ISFIFO +# endif +# define S_ISFIFO(m) (((m)&(_S_IFMT)) == (_S_IFIFO)) +# ifdef S_ISDIR +# undef S_ISDIR +# endif +# define S_ISDIR(m) (((m)&(_S_IFMT)) == (_S_IFDIR)) +# ifdef S_ISCHR +# undef S_ISCHR +# endif +# define S_ISCHR(m) (((m)&(_S_IFMT)) == (_S_IFCHR)) +# ifdef S_ISBLK +# undef S_ISBLK +# endif +# define S_ISBLK(m) (((m)&(_S_IFMT)) == (_S_IFBLK)) +# ifdef S_ISREG +# undef S_ISREG +# endif +# define S_ISREG(m) (((m)&(_S_IFMT)) == (_S_IFREG)) +#endif + +/* These constants may be missing. + */ + +#ifndef NULL +#define NULL 0 +#endif +#ifdef FALSE +#undef FALSE +#endif +#define FALSE (0) +#ifdef TRUE +#undef TRUE +#endif +#define TRUE (!FALSE) + +/* These macros may be missing. + */ + +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +/* These external may be missing. + */ + +#if ! SYS_ERRLIST_DECLARED +extern char *sys_errlist[]; +#endif + +#if ! SYS_NERR_DECLARED +extern int sys_nerr; +#endif + +#if ! ERRNO_DECLARED +extern int errno; +#endif + +#if ! H_ERRNO_DECLARED +extern int h_errno; +#endif + +/* + * IPv4 or IPv6 structures? + */ + +#ifdef INET6 + +# define AND16(x) ((x)[0]&(x)[1]&(x)[2]&(x)[3]&(x)[4]&(x)[5]&(x)[6]&(x)[7]&(x)[8]&(x)[9]&(x)[10]&(x)[11]&(x)[12]&(x)[13]&(x)[14]&(x)[15]) +static unsigned char minus_one[]={ 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 0}; +# define WHOSTENTP(x) ((x)[0]|(x)[1]|(x)[2]|(x)[3]|(x)[4]|(x)[5]|(x)[6]|(x)[7]|(x)[8]|(x)[9]|(x)[10]|(x)[11]|(x)[12]|(x)[13]|(x)[14]|(x)[15]) + +# define AFINET AF_INET6 +# define SOCKADDR_IN sockaddr_in6 +# define SOCKADDR sockaddr +# define SIN_FAMILY sin6_family +# define SIN_PORT sin6_port +# define SIN_ADDR sin6_addr +# define S_ADDR s6_addr +# define IN_ADDR in6_addr + +# ifndef uint32_t +# define uint32_t __u32 +# endif + +# define MYDUMMY_SIZE 128 +char mydummy[MYDUMMY_SIZE]; +char mydummy2[MYDUMMY_SIZE]; + +# if defined(linux) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(bsdi) +# ifndef s6_laddr +# define s6_laddr s6_addr32 +# endif +# endif + +# if defined(linux) +static const struct in6_addr in6addr_any={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0}; +# endif + +# define IRCDCONF_DELIMITER '%' + +#else +# define AFINET AF_INET +# define SOCKADDR_IN sockaddr_in +# define SOCKADDR sockaddr +# define SIN_FAMILY sin_family +# define SIN_PORT sin_port +# define SIN_ADDR sin_addr +# define S_ADDR s_addr +# define IN_ADDR in_addr + +# define WHOSTENTP(x) (x) +# define IRCDCONF_DELIMITER ':' +#endif diff --git a/common/packet.c b/common/packet.c new file mode 100644 index 0000000..75bc2e6 --- /dev/null +++ b/common/packet.c @@ -0,0 +1,197 @@ +/************************************************************************ + * IRC - Internet Relay Chat, common/packet.c + * Copyright (C) 1990 Jarkko Oikarinen and + * University of Oulu, Computing Center + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef lint +static char rcsid[] = "@(#)$Id: packet.c,v 1.8 1999/04/19 22:26:22 kalt Exp $"; +#endif + +#include "os.h" +#ifndef CLIENT_COMPILE +# include "s_defines.h" +#else +# include "c_defines.h" +#endif +#define PACKET_C +#ifndef CLIENT_COMPILE +# include "s_externs.h" +#else +# include "c_externs.h" +#endif +#undef PACKET_C + +/* +** dopacket +** cptr - pointer to client structure for which the buffer data +** applies. +** buffer - pointr to the buffer containing the newly read data +** length - number of valid bytes of data in the buffer +** +** The buffer might be partially or totally zipped. +** At the beginning of the compressed flow, it is possible that +** an uncompressed ERROR message will be found. This occurs when +** the connection fails on the other server before switching +** to compressed mode. +** +** Note: +** It is implicitly assumed that dopacket is called only +** with cptr of "local" variation, which contains all the +** necessary fields (buffer etc..) +*/ +int dopacket(cptr, buffer, length) +Reg aClient *cptr; +char *buffer; +Reg int length; +{ + Reg char *ch1; + Reg char *ch2, *bufptr; + aClient *acpt = cptr->acpt; + int r = 1; +#ifdef ZIP_LINKS + int unzipped = 0; +#endif + + me.receiveB += length; /* Update bytes received */ + cptr->receiveB += length; + if (cptr->receiveB > 1023) + { + cptr->receiveK += (cptr->receiveB >> 10); + cptr->receiveB &= 0x03ff; /* 2^10 = 1024, 3ff = 1023 */ + } + if (acpt != &me) + { + acpt->receiveB += length; + if (acpt->receiveB > 1023) + { + acpt->receiveK += (acpt->receiveB >> 10); + acpt->receiveB &= 0x03ff; + } + } + else if (me.receiveB > 1023) + { + me.receiveK += (me.receiveB >> 10); + me.receiveB &= 0x03ff; + } + + bufptr = cptr->buffer; + ch1 = bufptr + cptr->count; + ch2 = buffer; + +#ifdef ZIP_LINKS + while ((length > 0 && ch2) || ((cptr->flags & FLAGS_ZIP) && + (cptr->zip->in->avail_in || + !unzipped))) +#else + while (length > 0 && ch2) +#endif + { + Reg char c; + +#ifdef ZIP_LINKS + if (cptr->flags & FLAGS_ZIPSTART) + { + /* + ** beginning of server connection, the buffer + ** contained PASS/SERVER and is now zipped! + ** Ignore the '\n' that should be here. + */ + if (*ch2 == '\n') /* also check \r ? */ + { + ch2++; + length--; + cptr->flags &= ~FLAGS_ZIPSTART; + } + if (length == 0) + return 1; + } + + if ((cptr->flags & FLAGS_ZIP) && !(unzipped && length)) + { + /* uncompressed buffer first */ + unzipped = length; /* length is register, store + temp in unzipped */ + ch2 = unzip_packet(cptr, ch2, &unzipped); + length = unzipped; + unzipped = 1; + if (length == -1) + return exit_client(cptr, cptr, &me, + "fatal error in unzip_packet()"); + if (length == 0 || *ch2 == '\0') + break; + } +#endif + length--; + c = (*ch1 = *ch2++); + /* + * Yuck. Stuck. To make sure we stay backward compatible, + * we must assume that either CR or LF terminates the message + * and not CR-LF. By allowing CR or LF (alone) into the body + * of messages, backward compatibility is lost and major + * problems will arise. - Avalon + */ + if ((c <= '\r') && (c == '\n' || c == '\r')) + { + if (ch1 == bufptr) + continue; /* Skip extra LF/CR's */ + *ch1 = '\0'; + me.receiveM += 1; /* Update messages received */ + cptr->receiveM += 1; + if (cptr->acpt != &me) + cptr->acpt->receiveM += 1; + cptr->count = 0; /* ...just in case parse returns with + ** FLUSH_BUFFER without removing the + ** structure pointed by cptr... --msa + */ + if ((r = parse(cptr, bufptr, ch1)) == + FLUSH_BUFFER) + /* + ** FLUSH_BUFFER means actually that cptr + ** structure *does* not exist anymore!!! --msa + */ + return FLUSH_BUFFER; +#ifndef CLIENT_COMPILE + /* + ** Socket is dead so exit (which always returns with + ** FLUSH_BUFFER here). - avalon + */ + if (cptr->flags & FLAGS_DEADSOCKET) + { + if (cptr->exitc == EXITC_REG) + cptr->exitc = EXITC_DEAD; + return exit_client(cptr, cptr, &me, + "Dead Socket"); + } + /* + ** Something is wrong, really wrong, and nothing + ** else should be allowed to be parsed! + ** This covers a bug which is somewhere else, + ** since no decent server would send such thing + ** as an unknown command. -krys + */ + if (IsServer(cptr) && (cptr->flags & FLAGS_UNKCMD)) + break; +#endif + ch1 = bufptr; + } + else if (ch1 < bufptr + (sizeof(cptr->buffer)-1)) + ch1++; /* There is always room for the null */ + } + cptr->count = ch1 - bufptr; + return r; +} diff --git a/common/packet_ext.h b/common/packet_ext.h new file mode 100644 index 0000000..9493fc8 --- /dev/null +++ b/common/packet_ext.h @@ -0,0 +1,32 @@ +/************************************************************************ + * IRC - Internet Relay Chat, common/packet_ext.h + * Copyright (C) 1997 Alain Nissen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* This file contains external definitions for global variables and functions + defined in common/packet.c. + */ + +/* External definitions for global functions. + */ +#ifndef PACKET_C +#define EXTERN extern +#else /* PACKET_C */ +#define EXTERN +#endif /* PACKET_C */ +EXTERN int dopacket __P((Reg aClient *cptr, char *buffer, Reg int length)); +#undef EXTERN diff --git a/common/parse.c b/common/parse.c new file mode 100644 index 0000000..9bb496c --- /dev/null +++ b/common/parse.c @@ -0,0 +1,786 @@ +/************************************************************************ + * IRC - Internet Relay Chat, common/parse.c + * Copyright (C) 1990 Jarkko Oikarinen and + * University of Oulu, Computing Center + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef lint +static char rcsid[] = "@(#)$Id: parse.c,v 1.25 1999/04/14 17:29:36 kalt Exp $"; +#endif + +#include "os.h" +#ifndef CLIENT_COMPILE +# include "s_defines.h" +#else +# include "c_defines.h" +#endif +#define PARSE_C +#ifndef CLIENT_COMPILE +# include "s_externs.h" +#else +# include "c_externs.h" +#endif +#undef PARSE_C + +struct Message msgtab[] = { + { MSG_PRIVATE, m_private, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L}, +#ifndef CLIENT_COMPILE + { MSG_NJOIN, m_njoin, MAXPARA, MSG_LAG|MSG_NOU, 0, 0, 0L}, +#endif + { MSG_JOIN, m_join, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L}, + { MSG_MODE, m_mode, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L}, + { 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}, + { MSG_NOTICE, m_notice, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L}, + { MSG_KICK, m_kick, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L}, + { MSG_SERVER, m_server, MAXPARA, MSG_LAG|MSG_NOU, 0, 0, 0L}, +#ifndef CLIENT_COMPILE + { MSG_TRACE, m_trace, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L}, +#endif + { MSG_TOPIC, m_topic, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L}, + { MSG_INVITE, m_invite, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L}, + { MSG_WALLOPS, m_wallops, MAXPARA, MSG_LAG|MSG_REG|MSG_NOU, 0, 0, 0L}, + { MSG_PING, m_ping, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L}, + { MSG_PONG, m_pong, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L}, + { MSG_ERROR, m_error, MAXPARA, MSG_LAG|MSG_REG|MSG_NOU, 0, 0, 0L}, +#ifdef OPER_KILL + { MSG_KILL, m_kill, MAXPARA, MSG_LAG|MSG_REG|MSG_OP|MSG_LOP, 0,0, 0L}, +#else + { MSG_KILL, m_kill, MAXPARA, MSG_LAG|MSG_REG|MSG_NOU, 0, 0, 0L}, +#endif +#ifndef CLIENT_COMPILE + { 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}, + { MSG_ISON, m_ison, 1, MSG_LAG|MSG_REG, 0, 0, 0L}, + { MSG_SQUIT, m_squit, MAXPARA, MSG_LAG|MSG_REG|MSG_OP|MSG_LOP, 0,0, 0L}, + { MSG_WHOIS, m_whois, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L}, + { MSG_WHO, m_who, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L}, + { 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}, + { 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}, + { MSG_TIME, m_time, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L}, + { MSG_OPER, m_oper, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L}, + { MSG_CONNECT, m_connect, MAXPARA, + MSG_LAG|MSG_REGU|MSG_OP|MSG_LOP, 0, 0, 0L}, + { MSG_VERSION, m_version, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L}, + { MSG_STATS, m_stats, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L}, + { MSG_LINKS, m_links, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L}, + { MSG_ADMIN, m_admin, MAXPARA, MSG_LAG, 0, 0, 0L}, + { MSG_USERS, m_users, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L}, + { MSG_SUMMON, m_summon, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L}, + { MSG_HELP, m_help, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L}, + { MSG_INFO, m_info, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L}, + { MSG_MOTD, m_motd, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L}, + { MSG_CLOSE, m_close, MAXPARA, MSG_LAG|MSG_REGU|MSG_OP, 0, 0, 0L}, + { MSG_RECONECT,m_reconnect,MAXPARA, MSG_LAG|MSG_NOU, 0, 0, 0L}, + { MSG_SERVICE, m_service, MAXPARA, MSG_LAG|MSG_NOU, 0, 0, 0L}, +#ifdef USE_SERVICES + { MSG_SERVSET, m_servset, MAXPARA, MSG_LAG|MSG_SVC, 0, 0, 0L}, +#endif + { MSG_SQUERY, m_squery, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L}, + { MSG_SERVLIST,m_servlist, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L}, + { MSG_HASH, m_hash, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L}, + { MSG_DNS, m_dns, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L}, +#ifdef OPER_REHASH + { MSG_REHASH, m_rehash, MAXPARA, MSG_REGU|MSG_OP +# ifdef LOCOP_REHASH + |MSG_LOP +# endif + , 0, 0, 0L}, +#endif +#ifdef OPER_RESTART + { MSG_RESTART, m_restart, MAXPARA, MSG_REGU|MSG_OP +# ifdef LOCOP_RESTART + |MSG_LOP +# endif + , 0, 0, 0L}, +#endif +#ifdef OPER_DIE + { MSG_DIE, m_die, MAXPARA, MSG_REGU|MSG_OP +# ifdef LOCOP_DIE + |MSG_LOP +# endif + , 0, 0, 0L}, +#endif +#endif /* !CLIENT_COMPILE */ + { (char *) 0, (int (*)()) 0, 0, 0, 0, 0, 0L} +}; + +/* + * NOTE: parse() should not be called recursively by other functions! + */ +static char *para[MAXPARA+1]; + +#ifdef CLIENT_COMPILE +static char sender[NICKLEN+USERLEN+HOSTLEN+3]; +char userhost[USERLEN+HOSTLEN+2]; +#define timeofday time(NULL) +#else +static char sender[HOSTLEN+1]; +static int cancel_clients __P((aClient *, aClient *, char *)); +static void remove_unknown __P((aClient *, char *)); +#endif + +/* +** Find a client (server or user) by name. +** +** *Note* +** Semantics of this function has been changed from +** the old. 'name' is now assumed to be a null terminated +** string and the search is the for server and user. +*/ +#ifndef CLIENT_COMPILE +aClient *find_client(name, cptr) +char *name; +Reg aClient *cptr; + { + aClient *acptr = cptr; + + if (name && *name) + acptr = hash_find_client(name, cptr); + + return acptr; + } + +aClient *find_service(name, cptr) +char *name; +Reg aClient *cptr; + { + aClient *acptr = cptr; + + if (index(name, '@')) + acptr = hash_find_client(name, cptr); + return acptr; + } + +#else /* CLIENT_COMPILE */ + +aClient *find_client(name, cptr) +char *name; +aClient *cptr; + { + Reg aClient *c2ptr = cptr; + + if (!name || !*name) + return c2ptr; + + for (c2ptr = client; c2ptr; c2ptr = c2ptr->next) + if (mycmp(name, c2ptr->name) == 0) + return c2ptr; + return cptr; + } +#endif /* CLIENT_COMPILE */ + +/* +** Find a user@host (server or user). +** +** *Note* +** Semantics of this function has been changed from +** the old. 'name' is now assumed to be a null terminated +** string and the search is the for server and user. +*/ +aClient *find_userhost(user, host, cptr, count) +char *user, *host; +aClient *cptr; +int *count; + { + Reg aClient *c2ptr; + Reg aClient *res = cptr; + + *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; + } + } + return res; + } + +/* +** Find server by name. +** +** This implementation assumes that server and user names +** are unique, no user can have a server name and vice versa. +** One should maintain separate lists for users and servers, +** if this restriction is removed. +** +** *Note* +** Semantics of this function has been changed from +** the old. 'name' is now assumed to be a null terminated +** string. +*/ +#ifndef CLIENT_COMPILE +/* +** Find a server from hash table, given its name +*/ +aClient *find_server(name, cptr) +char *name; +Reg aClient *cptr; +{ + aClient *acptr = cptr; + + if (name && *name) + acptr = hash_find_server(name, cptr); + return acptr; +} + +/* +** Given a server name, find the server mask behind which the server +** is hidden. +*/ +aClient *find_mask(name, cptr) +char *name; +aClient *cptr; +{ + static char servermask[HOSTLEN+1]; + Reg aClient *c2ptr = cptr; + Reg char *mask = servermask; + + if (!name || !*name) + return c2ptr; + if ((c2ptr = hash_find_server(name, cptr))) + return (c2ptr); + if (index(name, '*')) + return c2ptr; + strcpy (servermask, name); + while (*mask) + { + if (*(mask+1) == '.') + { + *mask = '*'; + if ((c2ptr = hash_find_server(mask, cptr))) + return (c2ptr); + } + mask++; + } + return (c2ptr ? c2ptr : cptr); +} + +/* +** Find a server from hash table, given its token +*/ +aServer *find_tokserver(token, cptr, c2ptr) +int token; +aClient *cptr, *c2ptr; +{ + return hash_find_stoken(token, cptr, c2ptr); +} + +/* +** Find a server, given its name (which might contain *'s, in which case +** the first match will be return [not the best one]) +*/ +aClient *find_name(name, cptr) +char *name; +aClient *cptr; +{ + Reg aClient *c2ptr = cptr; + Reg aServer *sp = NULL; + + if (!name || !*name) + return c2ptr; + + if ((c2ptr = hash_find_server(name, cptr))) + return (c2ptr); + if (!index(name, '*')) + return c2ptr; + for (sp = svrtop; sp; sp = sp->nexts) + { + /* + ** A server present in the list necessarily has a non NULL + ** bcptr pointer. + */ + if (match(name, sp->bcptr->name) == 0) + break; + if (index(sp->bcptr->name, '*')) + if (match(sp->bcptr->name, name) == 0) + break; + } + return (sp ? sp->bcptr : cptr); +} +#else +aClient *find_server(name, cptr) +char *name; +aClient *cptr; +{ + Reg aClient *c2ptr = cptr; + + if (!name || !*name) + return c2ptr; + + for (c2ptr = client; c2ptr; c2ptr = c2ptr->next) + { + if (!IsServer(c2ptr) && !IsMe(c2ptr)) + continue; + if (match(c2ptr->name, name) == 0 || + match(name, c2ptr->name) == 0) + break; + } + return (c2ptr ? c2ptr : cptr); +} +#endif /* CLIENT_COMPILE */ + +/* +** Find person by (nick)name. +*/ +aClient *find_person(name, cptr) +char *name; +aClient *cptr; + { + Reg aClient *c2ptr = cptr; + + c2ptr = find_client(name, c2ptr); + + if (c2ptr && IsClient(c2ptr) && c2ptr->user) + return c2ptr; + else + return cptr; + } + +/* + * parse a buffer. + * Return values: + * errors: -3 for unknown origin/sender, -2 for FLUSH_BUFFER, -1 for bad cptr + * + * NOTE: parse() should not be called recusively by any other fucntions! + */ +int parse(cptr, buffer, bufend) +aClient *cptr; +char *buffer, *bufend; + { + Reg aClient *from = cptr; + Reg char *ch, *s; + Reg int len, i, numeric = 0, paramcount; + Reg struct Message *mptr = NULL; + int ret; + +#ifndef CLIENT_COMPILE + Debug((DEBUG_DEBUG, "Parsing %s: %s", + get_client_name(cptr, FALSE), buffer)); + if (IsDead(cptr)) + return -1; +#endif + + s = sender; + *s = '\0'; + for (ch = buffer; *ch == ' '; ch++) + ; + para[0] = from->name; + if (*ch == ':') + { + /* + ** Copy the prefix to 'sender' assuming it terminates + ** with SPACE (or NULL, which is an error, though). + */ + for (++ch, i = 0; *ch && *ch != ' '; ++ch ) + if (s < (sender + sizeof(sender)-1)) + *s++ = *ch; /* leave room for NULL */ + *s = '\0'; +#ifdef CLIENT_COMPILE + if ((s = index(sender, '!'))) + { + *s++ = '\0'; + strncpyzt(userhost, s, sizeof(userhost)); + } + else if ((s = index(sender, '@'))) + { + *s++ = '\0'; + strncpyzt(userhost, s, sizeof(userhost)); + } +#endif + /* + ** Actually, only messages coming from servers can have + ** the prefix--prefix silently ignored, if coming from + ** a user client... + ** + ** ...sigh, the current release "v2.2PL1" generates also + ** null prefixes, at least to NOTIFY messages (e.g. it + ** puts "sptr->nickname" as prefix from server structures + ** where it's null--the following will handle this case + ** as "no prefix" at all --msa (": NOTICE nick ...") + */ + if (*sender && IsServer(cptr)) + { + from = find_client(sender, (aClient *) NULL); + if (!from || + /* + ** I really believe that the followin line is + ** useless. What a waste, especially with 2.9 + ** hostmasks.. at least the test on from->name + ** will make it a bit better. -krys + */ + (*from->name == '*' && match(from->name, sender))) + from = find_server(sender, (aClient *)NULL); +#ifndef CLIENT_COMPILE + /* Is there svc@server prefix ever? -Vesa */ + /* every time a service talks -krys */ + if (!from && index(sender, '@')) + from = find_service(sender, (aClient *)NULL); + if (!from) + from = find_mask(sender, (aClient *) NULL); +#endif + + para[0] = sender; + + /* Hmm! If the client corresponding to the + * prefix is not found--what is the correct + * action??? Now, I will ignore the message + * (old IRC just let it through as if the + * prefix just wasn't there...) --msa + * Since 2.9 we pick them up and .. --Vesa + */ + if (!from) + { + Debug((DEBUG_ERROR, + "Unknown prefix (%s)(%s) from (%s)", + sender, buffer, cptr->name)); + ircstp->is_unpf++; +#ifndef CLIENT_COMPILE + remove_unknown(cptr, sender); +#endif + return -3; /* Grab it in read_message() */ + } + if (from->from != cptr) + { + ircstp->is_wrdi++; + Debug((DEBUG_ERROR, + "Message (%s) coming from (%s)", + buffer, cptr->name)); +#ifndef CLIENT_COMPILE + return cancel_clients(cptr, from, buffer); +#else + return -1; +#endif + } + } + while (*ch == ' ') + ch++; + } + if (*ch == '\0') + { + ircstp->is_empt++; + Debug((DEBUG_NOTICE, "Empty message from host %s:%s", + cptr->name, from->name)); + return -1; + } + /* + ** Extract the command code from the packet. Point s to the end + ** of the command code and calculate the length using pointer + ** arithmetic. Note: only need length for numerics and *all* + ** numerics must have paramters and thus a space after the command + ** code. -avalon + */ + s = (char *)index(ch, ' '); /* s -> End of the command code */ + len = (s) ? (s - ch) : 0; + if (len == 3 && + isdigit(*ch) && isdigit(*(ch + 1)) && isdigit(*(ch + 2))) + { + numeric = (*ch - '0') * 100 + (*(ch + 1) - '0') * 10 + + (*(ch + 2) - '0'); + paramcount = MAXPARA; + ircstp->is_num++; + } + else + { + if (s) + *s++ = '\0'; + for (mptr = msgtab; mptr->cmd; mptr++) + if (mycmp(mptr->cmd, ch) == 0) + break; + + if (!mptr->cmd) + { + /* + ** Note: Give error message *only* to recognized + ** persons. It's a nightmare situation to have + ** two programs sending "Unknown command"'s or + ** equivalent to each other at full blast.... + ** If it has got to person state, it at least + ** seems to be well behaving. Perhaps this message + ** should never be generated, though... --msa + ** Hm, when is the buffer empty -- if a command + ** code has been found ?? -Armin + */ + if (buffer[0] != '\0') + { + cptr->flags |= FLAGS_UNKCMD; + if (IsPerson(from)) + sendto_one(from, + ":%s %d %s %s :Unknown command", + me.name, ERR_UNKNOWNCOMMAND, + from->name, ch); +#ifdef CLIENT_COMPILE + Debug((DEBUG_ERROR,"Unknown (%s) from %s[%s]", + ch, cptr->name, cptr->sockhost)); +#else + else if (IsServer(cptr)) + sendto_flag(SCH_ERROR, + "Unknown command from %s:%s", + get_client_name(cptr, TRUE), ch); + Debug((DEBUG_ERROR,"Unknown (%s) from %s", + ch, get_client_name(cptr, TRUE))); +#endif + } + ircstp->is_unco++; + return -1; + } + paramcount = mptr->parameters; + i = bufend - ((s) ? s : ch); + mptr->bytes += i; +#ifndef CLIENT_COMPILE + if ((mptr->flags & MSG_LAG) && + !(IsServer(cptr) || IsService(cptr))) + { /* Flood control partly migrated into penalty */ + if (bootopt & BOOT_PROT) + cptr->since += (1 + i / 100); + else + cptr->since = timeofday; + /* Allow only 1 msg per 2 seconds + * (on average) to prevent dumping. + * to keep the response rate up, + * bursts of up to 5 msgs are allowed + * -SRB + */ + } +#endif + } + /* + ** Must the following loop really be so devious? On + ** surface it splits the message to parameters from + ** blank spaces. But, if paramcount has been reached, + ** the rest of the message goes into this last parameter + ** (about same effect as ":" has...) --msa + */ + + /* Note initially true: s==NULL || *(s-1) == '\0' !! */ + +#ifdef CLIENT_COMPILE + if (me.user) + para[0] = sender; +#endif + i = 0; + if (s) + { + if (paramcount > MAXPARA) + paramcount = MAXPARA; + for (;;) + { + /* + ** Never "FRANCE " again!! ;-) Clean + ** out *all* blanks.. --msa + */ + while (*s == ' ') + *s++ = '\0'; + + if (*s == '\0') + break; + if (*s == ':') + { + /* + ** The rest is single parameter--can + ** include blanks also. + */ + para[++i] = s + 1; + break; + } + para[++i] = s; + if (i >= paramcount-1) + break; + for (; *s != ' ' && *s; s++) + ; + } + } + para[++i] = NULL; /* at worst, ++i is paramcount (MAXPARA) */ + if (mptr == NULL) + return (do_numeric(numeric, cptr, from, i, para)); + mptr->count++; + if (!MyConnect(from)) + mptr->rcount++; + if (IsRegisteredUser(cptr) && +#ifdef IDLE_FROM_MSG + mptr->func == m_private) +#else + mptr->func != m_ping && mptr->func != m_pong) +#endif + from->user->last = timeofday; + Debug((DEBUG_DEBUG, "Function: %#x = %s parc %d parv %#x", + mptr->func, mptr->cmd, i, para)); +#ifndef CLIENT_COMPILE + if ((mptr->flags & MSG_REGU) && check_registered_user(from)) + return -1; + if ((mptr->flags & MSG_SVC) && check_registered_service(from)) + return -1; + if ((mptr->flags & MSG_REG) && check_registered(from)) + return -1; + if ((mptr->flags & MSG_NOU) && (MyPerson(from) || MyService(from))) + { + sendto_one(from, err_str(ERR_ALREADYREGISTRED, para[0])); + return-1; + } + if (MyConnect(from) && !IsServer(from) && + (mptr->flags & (MSG_LOP|MSG_OP)) && + !((mptr->flags & MSG_OP) && (IsOper(from))) && + !((mptr->flags & MSG_LOP) && (IsLocOp(from)))) + { + sendto_one(from, err_str(ERR_NOPRIVILEGES, para[0])); + return -1; + } +#endif + /* + ** ALL m_functions return now UNIFORMLY: + ** -2 old FLUSH_BUFFER return value (unchanged). + ** -1 if parsing of a protocol message leads in a syntactic/semantic + ** error and NO penalty scoring should be applied. + ** >=0 if protocol message processing was successful. The return + ** value indicates the penalty score. + */ + ret = (*mptr->func)(cptr, from, i, para); + +#ifndef CLIENT_COMPILE + /* + ** Add penalty score for sucessfully parsed command if issued by + ** a LOCAL user client. + */ + if ((ret > 0) && IsRegisteredUser(cptr) && (bootopt & BOOT_PROT)) + { + 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; +} + +/* + * field breakup for ircd.conf file. + */ +char *getfield(irc_newline) +char *irc_newline; +{ + static char *line = NULL; + char *end, *field; + + if (irc_newline) + line = irc_newline; + if (line == NULL) + return(NULL); + + field = line; + if ((end = (char *)index(line, IRCDCONF_DELIMITER)) == NULL) + { + line = NULL; + if ((end = (char *)index(field,'\n')) == NULL) + end = field + strlen(field); + } + else + line = end + 1; + *end = '\0'; + return(field); +} + +#ifndef CLIENT_COMPILE +static int cancel_clients(cptr, sptr, cmd) +aClient *cptr, *sptr; +char *cmd; +{ + /* + * kill all possible points that are causing confusion here, + * I'm not sure I've got this all right... + * - avalon + */ + sendto_flag(SCH_NOTICE, "Message (%s) for %s[%s!%s@%s] from %s", + cmd, sptr->name, sptr->from->name, sptr->from->username, + sptr->from->sockhost, get_client_name(cptr, TRUE)); + /* + * Incorrect prefix for a server from some connection. If it is a + * client trying to be annoying, just QUIT them, if it is a server + * then the same deal. + */ + if (IsServer(sptr) || IsMe(sptr)) + { + sendto_flag(SCH_NOTICE, "Dropping server %s",cptr->name); + return exit_client(cptr, cptr, &me, "Fake Direction"); + } + /* + * Ok, someone is trying to impose as a client and things are + * confused. If we got the wrong prefix from a server, send out a + * kill, else just exit the lame client. + */ + if (IsServer(cptr)) + { + sendto_serv_butone(NULL, ":%s KILL %s :%s (%s[%s] != %s)", + me.name, sptr->name, me.name, + sptr->name, sptr->from->name, + get_client_name(cptr, TRUE)); + sptr->flags |= FLAGS_KILLED; + return exit_client(cptr, sptr, &me, "Fake Prefix"); + } + return exit_client(cptr, cptr, &me, "Fake prefix"); +} + +static void remove_unknown(cptr, sender) +aClient *cptr; +char *sender; +{ + if (!IsRegistered(cptr) || IsClient(cptr)) + return; + /* + * Not from a server so don't need to worry about it. + */ + if (!IsServer(cptr)) + return; + /* + * squit if it is a server because it means something is really + * wrong. + */ + if (index(sender, '.') /* <- buggy, it could be a service! */ + && !index(sender, '@')) /* better.. */ + { + sendto_flag(SCH_LOCAL, "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)); + } + else + /* + * Do kill if it came from a server because it means there is a ghost + * user on the other server which needs to be removed. -avalon + * it can simply be caused by lag (among other things), so just + * drop it if it is not a server. -krys + * services aren't prone to collisions, so lag shouldn't be responsible + * 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.", + sender, get_client_name(cptr, FALSE)); +} +#endif diff --git a/common/parse_ext.h b/common/parse_ext.h new file mode 100644 index 0000000..6fdd118 --- /dev/null +++ b/common/parse_ext.h @@ -0,0 +1,56 @@ +/************************************************************************ + * IRC - Internet Relay Chat, common/parse_ext.h + * Copyright (C) 1997 Alain Nissen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* This file contains external definitions for global variables and functions + defined in common/parse.c. + */ + +/* External definitions for global variables. + */ +#ifndef PARSE_C +#ifdef CLIENT_COMPILE +extern char userhost[]; +#endif /* CLIENT_COMPILE */ +extern struct Message msgtab[]; +#endif /* PARSE_C */ + +/* External definitions for global functions. + */ +#ifndef PARSE_C +#define EXTERN extern +#else /* PARSE_C */ +#define EXTERN +#endif /* PARSE_C */ +#ifndef CLIENT_COMPILE +EXTERN aClient *find_client __P((char *name, Reg aClient *cptr)); +EXTERN aClient *find_service __P((char *name, Reg aClient *cptr)); +EXTERN aClient *find_server __P((char *name, Reg aClient *cptr)); +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)); +#else /* CLIENT_COMPILE */ +EXTERN aClient *find_client __P((char *name, aClient *cptr)); +EXTERN aClient *find_server __P((char *name, aClient *cptr)); +#endif /* CLIENT_COMPILE */ +EXTERN aClient *find_userhost __P((char *user, char *host, aClient *cptr, + int *count)); +EXTERN aClient *find_person __P((char *name, aClient *cptr)); +EXTERN int parse __P((aClient *cptr, char *buffer, char *bufend)); +EXTERN char *getfield __P((char *irc_newline)); +#undef EXTERN diff --git a/common/patchlevel.h b/common/patchlevel.h new file mode 100644 index 0000000..6b84548 --- /dev/null +++ b/common/patchlevel.h @@ -0,0 +1,22 @@ +/************************************************************************ + * IRC - Internet Relay Chat, common/patchlevel.h + * + * 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 PATCHLEVEL +#define PATCHLEVEL "0210030000" /* for server identification */ +#define DEVLEVEL 'b' +#endif diff --git a/common/send.c b/common/send.c new file mode 100644 index 0000000..c61e3e5 --- /dev/null +++ b/common/send.c @@ -0,0 +1,1555 @@ +/* + * IRC - Internet Relay Chat, common/send.c + * Copyright (C) 1990 Jarkko Oikarinen and + * University of Oulu, Computing Center + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef lint +static char rcsid[] = "@(#)$Id: send.c,v 1.39 1999/07/21 22:57:40 kalt Exp $"; +#endif + +#include "os.h" +#ifndef CLIENT_COMPILE +# include "s_defines.h" +#else +# include "c_defines.h" +#endif +#define SEND_C +#ifndef CLIENT_COMPILE +# include "s_externs.h" +#else +# include "c_externs.h" +#endif +#undef SEND_C + +static char sendbuf[2048]; +static int send_message __P((aClient *, char *, int)); + +#if USE_STDARG +static void vsendto_prefix_one(aClient *, aClient *, char *, va_list); +#endif + + +#ifndef CLIENT_COMPILE +static char psendbuf[2048]; +static int sentalong[MAXCONNECTIONS]; +#endif + +/* +** dead_link +** An error has been detected. The link *must* be closed, +** but *cannot* call ExitClient (m_bye) from here. +** Instead, mark it with FLAGS_DEADSOCKET. This should +** generate ExitClient from the main loop. +** +** If 'notice' is not NULL, it is assumed to be a format +** for a message to local opers. It can contain only one +** '%s', which will be replaced by the sockhost field of +** the failing link. +** +** Also, the notice is skipped for "uninteresting" cases, +** like Persons and yet unknown connections... +*/ +static int dead_link(to, notice) +aClient *to; +char *notice; +{ + if (IsHeld(to)) + return -1; + to->flags |= FLAGS_DEADSOCKET; + /* + * If because of BUFFERPOOL problem then clean dbufs now so that + * notices don't hurt operators below. + */ + DBufClear(&to->recvQ); + DBufClear(&to->sendQ); +#ifndef CLIENT_COMPILE + if (!IsPerson(to) && !IsUnknown(to) && !(to->flags & FLAGS_CLOSING)) + sendto_flag(SCH_ERROR, notice, get_client_name(to, FALSE)); + Debug((DEBUG_ERROR, notice, get_client_name(to, FALSE))); +#endif + return -1; +} + +#ifndef CLIENT_COMPILE +/* +** flush_fdary +** Used to empty all output buffers for connections in fdary. +*/ +void flush_fdary(fdp) +FdAry *fdp; +{ + int i; + aClient *cptr; + + for (i = 0; i <= fdp->highest; i++) + { + if (!(cptr = local[fdp->fd[i]])) + continue; + if (!IsRegistered(cptr)) /* is this needed?? -kalt */ + continue; + if (DBufLength(&cptr->sendQ) > 0) + (void)send_queued(cptr); + } +} + +/* +** flush_connections +** Used to empty all output buffers for all connections. Should only +** be called once per scan of connections. There should be a select in +** here perhaps but that means either forcing a timeout or doing a poll. +** When flushing, all we do is empty the obuffer array for each local +** client and try to send it. if we can't send it, it goes into the sendQ +** -avalon +*/ +void flush_connections(fd) +int fd; +{ + Reg int i; + Reg aClient *cptr; + + if (fd == me.fd) + { + for (i = highest_fd; i >= 0; i--) + if ((cptr = local[i]) && DBufLength(&cptr->sendQ) > 0) + (void)send_queued(cptr); + } + else if (fd >= 0 && (cptr = local[fd]) && DBufLength(&cptr->sendQ) > 0) + (void)send_queued(cptr); +} +#endif + +/* +** send_message +** Internal utility which delivers one message buffer to the +** socket. Takes care of the error handling and buffering, if +** needed. +** if ZIP_LINKS is defined, the message will eventually be compressed, +** anything stored in the sendQ is compressed. +*/ +static int send_message(to, msg, len) +aClient *to; +char *msg; /* if msg is a null pointer, we are flushing connection */ +int len; +#if !defined(CLIENT_COMPILE) +{ + int i; + + Debug((DEBUG_SEND,"Sending %s %d [%s] ", to->name, to->fd, msg)); + + if (to->from) + to = to->from; + if (to->fd < 0) + { + Debug((DEBUG_ERROR, + "Local socket %s with negative fd... AARGH!", + to->name)); + } + if (IsMe(to)) + { + sendto_flag(SCH_ERROR, "Trying to send to myself! [%s]", msg); + return 0; + } + if (IsDead(to)) + return 0; /* This socket has already been marked as dead */ + if (DBufLength(&to->sendQ) > get_sendq(to)) + { +# ifdef HUB + if (CBurst(to)) + { + aConfItem *aconf = to->serv->nline; + + poolsize -= MaxSendq(aconf->class) >> 1; + IncSendq(aconf->class); + poolsize += MaxSendq(aconf->class) >> 1; + sendto_flag(SCH_NOTICE, + "New poolsize %d. (sendq adjusted)", + poolsize); + istat.is_dbufmore++; + } + else if (IsServer(to) || IsService(to)) + sendto_flag(SCH_ERROR, + "Max SendQ limit exceeded for %s: %d > %d", + get_client_name(to, FALSE), + DBufLength(&to->sendQ), get_sendq(to)); + if (!CBurst(to)) + { + to->exitc = EXITC_SENDQ; + return dead_link(to, "Max Sendq exceeded"); + } +# else /* HUB */ + if (IsService(to) || IsServer(to)) + sendto_flag(SCH_ERROR, + "Max SendQ limit exceeded for %s: %d > %d", + get_client_name(to, FALSE), + DBufLength(&to->sendQ), get_sendq(to)); + to->exitc = EXITC_SENDQ; + return dead_link(to, "Max Sendq exceeded"); +# endif /* HUB */ + } + else + { +tryagain: +# ifdef ZIP_LINKS + /* + ** data is first stored in to->zip->outbuf until + ** it's big enough to be compressed and stored in the sendq. + ** send_queued is then responsible to never let the sendQ + ** be empty and to->zip->outbuf not empty. + */ + if (to->flags & FLAGS_ZIP) + msg = zip_buffer(to, msg, &len, 0); + + if (len && (i = dbuf_put(&to->sendQ, msg, len)) < 0) +# else /* ZIP_LINKS */ + if ((i = dbuf_put(&to->sendQ, msg, len)) < 0) +# endif /* ZIP_LINKS */ + if (i == -2 && CBurst(to)) + { /* poolsize was exceeded while connect burst */ + aConfItem *aconf = to->serv->nline; + + poolsize -= MaxSendq(aconf->class) >> 1; + IncSendq(aconf->class); + poolsize += MaxSendq(aconf->class) >> 1; + sendto_flag(SCH_NOTICE, + "New poolsize %d. (reached)", + poolsize); + istat.is_dbufmore++; + goto tryagain; + } + else + { + to->exitc = EXITC_MBUF; + return dead_link(to, + "Buffer allocation error for %s"); + } + } + /* + ** Update statistics. The following is slightly incorrect + ** because it counts messages even if queued, but bytes + ** only really sent. Queued bytes get updated in SendQueued. + */ + to->sendM += 1; + me.sendM += 1; + if (to->acpt != &me) + to->acpt->sendM += 1; + /* + ** This little bit is to stop the sendQ from growing too large when + ** there is no need for it to. Thus we call send_queued() every time + ** 2k has been added to the queue since the last non-fatal write. + ** Also stops us from deliberately building a large sendQ and then + ** trying to flood that link with data (possible during the net + ** relinking done by servers with a large load). + */ + if (DBufLength(&to->sendQ)/1024 > to->lastsq) + send_queued(to); + return 0; +} +#else /* CLIENT_COMPILE */ +{ + int rlen = 0, i; + + Debug((DEBUG_SEND,"Sending %s %d [%s] ", to->name, to->fd, msg)); + + if (to->from) + to = to->from; + if (to->fd < 0) + { + Debug((DEBUG_ERROR, + "Local socket %s with negative fd... AARGH!", + to->name)); + } + if (IsDead(to)) + return 0; /* This socket has already been marked as dead */ + + if ((rlen = deliver_it(to, msg, len)) < 0 && rlen < len) + return dead_link(to,"Write error to %s, closing link"); + /* + ** Update statistics. The following is slightly incorrect + ** because it counts messages even if queued, but bytes + ** only really sent. Queued bytes get updated in SendQueued. + */ + to->sendM += 1; + me.sendM += 1; + if (to->acpt != &me) + to->acpt->sendM += 1; + return 0; +} +#endif + +/* +** send_queued +** This function is called from the main select-loop (or whatever) +** when there is a chance the some output would be possible. This +** attempts to empty the send queue as far as possible... +*/ +int send_queued(to) +aClient *to; +{ + char *msg; + int len, rlen, more = 0; + + /* + ** Once socket is marked dead, we cannot start writing to it, + ** even if the error is removed... + */ + if (IsDead(to)) + { + /* + ** Actually, we should *NEVER* get here--something is + ** not working correct if send_queued is called for a + ** dead socket... --msa + */ + return -1; + } +#ifdef ZIP_LINKS + /* + ** Here, we must make sure than nothing will be left in to->zip->outbuf + ** This buffer needs to be compressed and sent if all the sendQ is sent + */ + if ((to->flags & FLAGS_ZIP) && to->zip->outcount) + { + if (DBufLength(&to->sendQ) > 0) + more = 1; + else + { + msg = zip_buffer(to, NULL, &len, 1); + + if (len == -1) + return dead_link(to, + "fatal error in zip_buffer()"); + + if (dbuf_put(&to->sendQ, msg, len) < 0) + { + to->exitc = EXITC_MBUF; + return dead_link(to, + "Buffer allocation error for %s"); + } + } + } +#endif + while (DBufLength(&to->sendQ) > 0 || more) + { + msg = dbuf_map(&to->sendQ, &len); + /* Returns always len > 0 */ + if ((rlen = deliver_it(to, msg, len)) < 0) + return dead_link(to,"Write error to %s, closing link"); + (void)dbuf_delete(&to->sendQ, rlen); + to->lastsq = DBufLength(&to->sendQ)/1024; + if (rlen < len) /* ..or should I continue until rlen==0? */ + break; + +#ifdef ZIP_LINKS + if (DBufLength(&to->sendQ) == 0 && more) + { + /* + ** The sendQ is now empty, compress what's left + ** uncompressed and try to send it too + */ + more = 0; + msg = zip_buffer(to, NULL, &len, 1); + + if (len == -1) + return dead_link(to, + "fatal error in zip_buffer()"); + + if (dbuf_put(&to->sendQ, msg, len) < 0) + { + to->exitc = EXITC_MBUF; + return dead_link(to, + "Buffer allocation error for %s"); + } + } +#endif + } + + return (IsDead(to)) ? -1 : 0; +} + + +#ifndef CLIENT_COMPILE +static anUser ausr = { NULL, NULL, NULL, NULL, 0, 0, 0, 0, NULL, + NULL, "anonymous", "anonymous.", "anonymous."}; + +static aClient anon = { NULL, NULL, NULL, &ausr, NULL, NULL, 0, 0,/*flags*/ + &anon, -2, 0, STAT_CLIENT, "anonymous", "anonymous", + "anonymous identity hider", 0, "", +# ifdef ZIP_LINKS + NULL, +# endif + 0, {0, 0, NULL }, {0, 0, NULL }, + 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, 0, NULL, 0 +# if defined(__STDC__) /* hack around union{} initialization -Vesa */ + ,{0}, NULL, "", "" +# endif + }; +#endif + +/* + * + */ +#if ! USE_STDARG +static int sendprep(pattern, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11) +char *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *p11; +#else +static int vsendprep(char *pattern, va_list va) +#endif +{ + int len; + + Debug((DEBUG_L10, "sendprep(%s)", pattern)); +#if ! USE_STDARG + len = irc_sprintf(sendbuf, pattern, p1, p2, p3, p4, p5, p6, + p7, p8, p9, p10, p11); + if (len == -1) + len = strlen(sendbuf); +#else + len = vsprintf(sendbuf, pattern, va); +#endif + if (len > 510) +#ifdef IRCII_KLUDGE + len = 511; +#else + len = 510; + sendbuf[len++] = '\r'; +#endif + sendbuf[len++] = '\n'; + sendbuf[len] = '\0'; + return len; +} + +#ifndef CLIENT_COMPILE +#if ! USE_STDARG +static int sendpreprep(to, from, pattern, + p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11) +aClient *to, *from; +char *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *p11; +{ + static char sender[HOSTLEN+NICKLEN+USERLEN+5]; + Reg anUser *user; + char *par; + int flag = 0, len; + + Debug((DEBUG_L10, "sendpreprep(%#x(%s),%#x(%s),%s)", + to, to->name, from, from->name, pattern)); + par = p1; + if (to && from && MyClient(to) && IsPerson(from) && + !mycmp(par, from->name)) + { + user = from->user; + (void)strcpy(sender, from->name); + if (user) + { + if (*user->username) + { + (void)strcat(sender, "!"); + (void)strcat(sender, user->username); + } + if (*user->host && !MyConnect(from)) + { + (void)strcat(sender, "@"); + (void)strcat(sender, user->host); + flag = 1; + } + } + /* + ** flag is used instead of index(sender, '@') for speed and + ** also since username/nick may have had a '@' in them. -avalon + */ + if (!flag && MyConnect(from) && *user->host) + { + (void)strcat(sender, "@"); + if (IsUnixSocket(from)) + (void)strcat(sender, user->host); + else + (void)strcat(sender, from->sockhost); + } + par = sender; + } + len = irc_sprintf(psendbuf, pattern, par, p2, p3, p4, p5, p6, + p7, p8, p9, p10, p11); + if (len == -1) + len = strlen(psendbuf); + if (len > 510) +#ifdef IRCII_KLUDGE + len = 511; +#else + len = 510; + psendbuf[len++] = '\r'; +#endif + psendbuf[len++] = '\n'; + psendbuf[len] = '\0'; + return len; +} + +#else /* USE_STDARG */ + +static int vsendpreprep(aClient *to, aClient *from, char *pattern, va_list va) +{ + Reg anUser *user; + int flag = 0, len; + + Debug((DEBUG_L10, "sendpreprep(%#x(%s),%#x(%s),%s)", + to, to->name, from, from->name, pattern)); + if (to && from && MyClient(to) && IsPerson(from) && + !strncmp(pattern, ":%s", 3)) + { + char *par = va_arg(va, char *); + if (from == &anon || !mycmp(par, from->name)) + { + user = from->user; + (void)strcpy(psendbuf, ":"); + (void)strcat(psendbuf, from->name); + if (user) + { + if (*user->username) + { + (void)strcat(psendbuf, "!"); + (void)strcat(psendbuf, user->username); + } + if (*user->host && !MyConnect(from)) + { + (void)strcat(psendbuf, "@"); + (void)strcat(psendbuf, user->host); + flag = 1; + } + } + /* + ** flag is used instead of index(newpat, '@') for speed and + ** also since username/nick may have had a '@' in them. -avalon + */ + if (!flag && MyConnect(from) && *user->host) + { + (void)strcat(psendbuf, "@"); + if (IsUnixSocket(from)) + (void)strcat(psendbuf, user->host); + else + (void)strcat(psendbuf, from->sockhost); + } + } + else + { + (void)strcpy(psendbuf, ":"); + (void)strcat(psendbuf, par); + } + + len = strlen(psendbuf); + len += vsprintf(psendbuf+len, pattern+3, va); + } + else + len = vsprintf(psendbuf, pattern, va); + + if (len > 510) +#ifdef IRCII_KLUDGE + len = 511; +#else + len = 510; + psendbuf[len++] = '\r'; +#endif + psendbuf[len++] = '\n'; + psendbuf[len] = '\0'; + return len; +} +#endif /* USE_STDARG */ +#endif /* CLIENT_COMPILE */ + +/* +** send message to single client +*/ +#if ! USE_STDARG +int sendto_one(to, pattern, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11) +aClient *to; +char *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *p11; +#else +int vsendto_one(aClient *to, char *pattern, va_list va) +#endif +{ + int len; + +#if ! USE_STDARG + len = sendprep(pattern, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); +#else + len = vsendprep(pattern, va); +#endif + + (void)send_message(to, sendbuf, len); + return len; +} + +#if USE_STDARG +int sendto_one(aClient *to, char *pattern, ...) +{ + int len; + va_list va; + va_start(va, pattern); + len = vsendto_one(to, pattern, va); + va_end(va); + return len; +} +#endif + +#ifndef CLIENT_COMPILE +#if ! USE_STDARG +/*VARARGS*/ +void sendto_channel_butone(one, from, chptr, pattern, + p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11) +aClient *one, *from; +aChannel *chptr; +char *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *p11; +#else +void sendto_channel_butone(aClient *one, aClient *from, aChannel *chptr, char *pattern, ...) +#endif +{ + Reg Link *lp; + Reg aClient *acptr, *lfrm = from; + int len1, len2 = 0; + + if (IsAnonymous(chptr) && IsClient(from)) + { +#if ! USE_STDARG + if (p1 && *p1 && !mycmp(p1, from->name)) + p1 = anon.name; +#endif + lfrm = &anon; + } + + if (one != from && MyConnect(from) && IsRegisteredUser(from)) + { + /* useless junk? */ +#if ! USE_STDARG + sendto_prefix_one(from, from, pattern, p1, p2, p3, p4, + p5, p6, p7, p8, p9, p10, p11); +#else + va_list va; + va_start(va, pattern); + vsendto_prefix_one(from, from, pattern, va); + va_end(va); +#endif + } + +#if ! USE_STDARG + len1 = sendprep(pattern, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); +#else + { + va_list va; + va_start(va, pattern); + len1 = vsendprep(pattern, va); + va_end(va); + } +#endif + + + for (lp = chptr->clist; lp; lp = lp->next) + { + acptr = lp->value.cptr; + if (acptr->from == one || IsMe(acptr)) + continue; /* ...was the one I should skip */ + if (MyConnect(acptr) && IsRegisteredUser(acptr)) + { + if (!len2) + { +#if ! USE_STDARG + len2 = sendpreprep(acptr, lfrm, pattern, p1, + p2, p3, p4, p5, p6, p7, p8, + p9, p10, p11); +#else + va_list va; + va_start(va, pattern); + len2 = vsendpreprep(acptr, lfrm, pattern, va); + va_end(va); +#endif + } + + if (acptr != from) + (void)send_message(acptr, psendbuf, len2); + } + else + (void)send_message(acptr, sendbuf, len1); + } + return; +} + +/* + * sendto_server_butone + * + * Send a message to all connected servers except the client 'one'. + */ +#if ! USE_STDARG +/*VARARGS*/ +void sendto_serv_butone(one, pattern, p1, p2, p3, p4,p5,p6,p7,p8,p9,p10,p11) +aClient *one; +char *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *p11; +#else +void sendto_serv_butone(aClient *one, char *pattern, ...) +#endif +{ + Reg int i, len=0; + Reg aClient *cptr; + + for (i = fdas.highest; i >= 0; i--) + if ((cptr = local[fdas.fd[i]]) && + (!one || cptr != one->from) && !IsMe(cptr)) { + if (!len) + { +#if ! USE_STDARG + len = sendprep(pattern, p1, p2, p3, p4, p5, + p6, p7, p8, p9, p10, p11); +#else + va_list va; + va_start(va, pattern); + len = vsendprep(pattern, va); + va_end(va); +#endif + } + (void)send_message(cptr, sendbuf, len); + } + return; +} + +#if ! USE_STDARG +int +sendto_serv_v(one, ver, pattern, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11) +aClient *one; +int ver; +char *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *p11; +#else +int +sendto_serv_v(aClient *one, int ver, char *pattern, ...) +#endif +{ + Reg int i, len=0, rc=0; + Reg aClient *cptr; + + for (i = fdas.highest; i >= 0; i--) + if ((cptr = local[fdas.fd[i]]) && + (!one || cptr != one->from) && !IsMe(cptr)) + if (cptr->serv->version & ver) + { + if (!len) + { +#if ! USE_STDARG + len = sendprep(pattern, p1, p2, p3, p4, + p5, p6, p7, p8, p9, p10, + p11); +#else + va_list va; + va_start(va, pattern); + len = vsendprep(pattern, va); + va_end(va); +#endif + } + (void)send_message(cptr, sendbuf, len); + } + else + rc = 1; + return rc; +} + +#if ! USE_STDARG +int +sendto_serv_notv(one, ver, pattern, p1, p2, p3, p4, p5, p6, p7, p8, p9,p10,p11) +aClient *one; +int ver; +char *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *p11; +#else +int +sendto_serv_notv(aClient *one, int ver, char *pattern, ...) +#endif +{ + Reg int i, len=0, rc=0; + Reg aClient *cptr; + + for (i = fdas.highest; i >= 0; i--) + if ((cptr = local[fdas.fd[i]]) && + (!one || cptr != one->from) && !IsMe(cptr)) + if ((cptr->serv->version & ver) == 0) + { + if (!len) + { +#if ! USE_STDARG + len = sendprep(pattern, p1, p2, p3, p4, + p5, p6, p7, p8, p9, p10, + p11); +#else + va_list va; + va_start(va, pattern); + len = vsendprep(pattern, va); + va_end(va); +#endif + } + (void)send_message(cptr, sendbuf, len); + } + else + rc = 1; + return rc; +} + +/* + * sendto_common_channels() + * + * Sends a message to all people (inclusing user) on local server who are + * in same channel with user, except for channels set Quiet or Anonymous + * The calling procedure must take the necessary steps for such channels. + */ +#if ! USE_STDARG +/*VARARGS*/ +void sendto_common_channels(user,pattern,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11) +aClient *user; +char *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *p11; +#else +void sendto_common_channels(aClient *user, char *pattern, ...) +#endif +{ + Reg int i; + Reg aClient *cptr; + Reg Link *channels, *lp; + int len = 0; + +/* This is kind of funky, but should work. The first part below + is optimized for HUB servers or servers with few clients on + them. The second part is optimized for bigger client servers + where looping through the whole client list is bad. I'm not + really certain of the point at which each function equals + out...but I do know the 2nd part will help big client servers + fairly well... - Comstud 97/04/24 +*/ + + if (highest_fd < 50) /* This part optimized for HUB servers... */ + { + if (MyConnect(user)) + { +#if ! USE_STDARG + len = sendpreprep(user, user, pattern, + p1, p2, p3, p4, p5, p6, p7, p8, p9, p10,p11); + +#else + va_list va; + va_start(va, pattern); + len = vsendpreprep(user, user, pattern, va); + va_end(va); +#endif + (void)send_message(user, psendbuf, len); + } + for (i = 0; i <= highest_fd; i++) + { + if (!(cptr = local[i]) || IsServer(cptr) || + user == cptr || !user->user) + continue; + for (lp = user->user->channel; lp; lp = lp->next) + { + if (!IsMember(cptr, lp->value.chptr)) + continue; + if (IsAnonymous(lp->value.chptr)) + continue; + if (!IsQuiet(lp->value.chptr)) + { +#ifndef DEBUGMODE + if (!len) /* This saves little cpu, + but breaks the debug code.. */ +#endif + { +#if ! USE_STDARG + len = sendpreprep(cptr, user, pattern, + p1, p2, p3, p4, p5, + p6, p7, p8, p9, p10, + p11); +#else + va_list va; + va_start(va, pattern); + len = vsendpreprep(cptr, user, pattern, va); + va_end(va); +#endif + } + (void)send_message(cptr, psendbuf, + len); + break; + } + } + } + } + else + { + /* This part optimized for client servers */ + bzero((char *)&sentalong[0], sizeof(int) * MAXCONNECTIONS); + if (MyConnect(user)) + { +#if ! USE_STDARG + len = sendpreprep(user, user, pattern, p1, p2, p3, p4, + p5, p6, p7, p8, p9, p10, p11); +#else + va_list va; + va_start(va, pattern); + len = vsendpreprep(user, user, pattern, va); + va_end(va); +#endif + (void)send_message(user, psendbuf, len); + sentalong[user->fd] = 1; + } + if (!user->user) + return; + for (channels=user->user->channel; channels; + channels=channels->next) + { + if (IsQuiet(channels->value.chptr)) + continue; + if (IsAnonymous(channels->value.chptr)) + continue; + for (lp=channels->value.chptr->members;lp; + lp=lp->next) + { + cptr = lp->value.cptr; + if (user == cptr) + continue; + if (!MyConnect(cptr) || sentalong[cptr->fd]) + continue; + sentalong[cptr->fd]++; +#ifndef DEBUGMODE + if (!len) /* This saves little cpu, + but breaks the debug code.. */ +#endif + { +#if ! USE_STDARG + len = sendpreprep(cptr, user, pattern, + p1, p2, p3, p4, p5, + p6, p7, p8, p9, p10, + p11); +#else + va_list va; + va_start(va, pattern); + len = vsendpreprep(cptr, user, pattern, va); + va_end(va); +#endif + } + (void)send_message(cptr, psendbuf, len); + } + } + } + return; +} + +/* + * sendto_channel_butserv + * + * Send a message to all members of a channel that are connected to this + * server. + */ +#if ! USE_STDARG +/*VARARGS*/ +void sendto_channel_butserv(chptr, from, pattern, p1, p2, p3, + p4, p5, p6, p7, p8, p9, p10, p11) +aChannel *chptr; +aClient *from; +char *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *p11; +#else +void sendto_channel_butserv(aChannel *chptr, aClient *from, char *pattern, ...) +#endif +{ + Reg Link *lp; + Reg aClient *acptr, *lfrm = from; + int len = 0; + + if (MyClient(from)) + { /* Always send to the client itself */ +#if ! USE_STDARG + sendto_prefix_one(from, from, pattern, p1, p2, p3, p4, + p5, p6, p7, p8, p9, p10, p11); +#else + va_list va; + va_start(va, pattern); + vsendto_prefix_one(from, from, pattern, va); + va_end(va); +#endif + if (IsQuiet(chptr)) /* Really shut up.. */ + return; + } + if (IsAnonymous(chptr) && IsClient(from)) + { +#if ! USE_STDARG + if (p1 && *p1 && !mycmp(p1, from->name)) + p1 = anon.name; +#endif + lfrm = &anon; + } + + for (lp = chptr->members; lp; lp = lp->next) + if (MyClient(acptr = lp->value.cptr) && acptr != from) + { + if (!len) + { +#if ! USE_STDARG + len = sendpreprep(acptr, lfrm, pattern, p1, p2, + p3, p4, p5, p6, p7, p8, p9, + p10, p11); +#else + va_list va; + va_start(va, pattern); + len = vsendpreprep(acptr, lfrm, pattern, va); + va_end(va); +#endif + } + (void)send_message(acptr, psendbuf, len); + } + + return; +} + +/* +** send a msg to all ppl on servers/hosts that match a specified mask +** (used for enhanced PRIVMSGs) +** +** addition -- Armin, 8jun90 (gruner@informatik.tu-muenchen.de) +*/ + +static int match_it(one, mask, what) +aClient *one; +char *mask; +int what; +{ + switch (what) + { + case MATCH_HOST: + return (match(mask, one->user->host)==0); + case MATCH_SERVER: + default: + return (match(mask, one->user->server)==0); + } +} + +/* + * sendto_match_servs + * + * send to all servers which match the mask at the end of a channel name + * (if there is a mask present) or to all if no mask. + */ +#if ! USE_STDARG +/*VARARGS*/ +void sendto_match_servs(chptr, from, format, p1, p2, p3, p4, p5, p6, p7, + p8, p9, p10, p11) +aChannel *chptr; +aClient *from; +char *format, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *p11; +#else +void sendto_match_servs(aChannel *chptr, aClient *from, char *format, ...) +#endif +{ + Reg int i, len=0; + Reg aClient *cptr; + char *mask; + + if (chptr) + { + if (*chptr->chname == '&') + return; + if ((mask = (char *)rindex(chptr->chname, ':'))) + mask++; + } + else + mask = (char *)NULL; + + for (i = fdas.highest; i >= 0; i--) + { + if (!(cptr = local[fdas.fd[i]]) || (cptr == from) || + IsMe(cptr)) + continue; + if (!BadPtr(mask) && match(mask, cptr->name)) + continue; + if (chptr && + *chptr->chname == '!' && !(cptr->serv->version & SV_NJOIN)) + continue; + if (!len) + { +#if ! USE_STDARG + len = sendprep(format, p1, p2, p3, p4, p5, p6, p7, + p8, p9, p10, p11); +#else + va_list va; + va_start(va, format); + len = vsendprep(format, va); + va_end(va); +#endif + } + (void)send_message(cptr, sendbuf, len); + } +} + +#if ! USE_STDARG +/*VARARGS*/ +int +sendto_match_servs_v(chptr, from, ver, format, p1, p2, p3, p4, p5, p6, + p7, p8, p9, p10, p11) +aChannel *chptr; +aClient *from; +char *format, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *p11; +int ver; +#else +int +sendto_match_servs_v(aChannel *chptr, aClient *from, int ver, + char *format, ...) +#endif +{ + Reg int i, len=0, rc=0; + Reg aClient *cptr; + char *mask; + + if (chptr) + { + if (*chptr->chname == '&') + return 0; + if ((mask = (char *)rindex(chptr->chname, ':'))) + mask++; + } + else + mask = (char *)NULL; + + for (i = fdas.highest; i >= 0; i--) + { + if (!(cptr = local[fdas.fd[i]]) || (cptr == from) || + IsMe(cptr)) + continue; + if (!BadPtr(mask) && match(mask, cptr->name)) + continue; + if (chptr && + *chptr->chname == '!' && !(cptr->serv->version & SV_NJOIN)) + continue; + if ((ver & cptr->serv->version) == 0) + { + rc = 1; + continue; + } + if (!len) + { +#if ! USE_STDARG + len = sendprep(format, p1, p2, p3, p4, p5, p6, p7, + p8, p9, p10, p11); +#else + va_list va; + va_start(va, format); + len = vsendprep(format, va); + va_end(va); +#endif + } + (void)send_message(cptr, sendbuf, len); + } + return rc; +} + +#if ! USE_STDARG +/*VARARGS*/ +int +sendto_match_servs_notv(chptr, from, ver, format, p1, p2, p3, p4, p5, + p6, p7, p8, p9, p10, p11) +aChannel *chptr; +aClient *from; +char *format, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *p11; +int ver; +#else +int +sendto_match_servs_notv(aChannel *chptr, aClient *from, int ver, + char *format, ...) +#endif +{ + Reg int i, len=0, rc=0; + Reg aClient *cptr; + char *mask; + + if (chptr) + { + if (*chptr->chname == '&') + return 0; + if ((mask = (char *)rindex(chptr->chname, ':'))) + mask++; + } + else + mask = (char *)NULL; + + for (i = fdas.highest; i >= 0; i--) + { + if (!(cptr = local[fdas.fd[i]]) || (cptr == from) || + IsMe(cptr)) + continue; + if (!BadPtr(mask) && match(mask, cptr->name)) + continue; + if (chptr && + *chptr->chname == '!' && !(cptr->serv->version & SV_NJOIN)) + continue; + if ((ver & cptr->serv->version) != 0) + { + rc = 1; + continue; + } + if (!len) + { +#if ! USE_STDARG + len = sendprep(format, p1, p2, p3, p4, p5, p6, p7, + p8, p9, p10, p11); +#else + va_list va; + va_start(va, format); + len = vsendprep(format, va); + va_end(va); +#endif + } + (void)send_message(cptr, sendbuf, len); + } + return rc; +} + +/* + * sendto_match_butone + * + * Send to all clients which match the mask in a way defined on 'what'; + * either by user hostname or user servername. + */ +/*VARARGS*/ +#if ! USE_STDARG +void sendto_match_butone(one, from, mask, what, pattern, + p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11) +aClient *one, *from; +int what; +char *mask, *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9,*p10,*p11; +#else +void sendto_match_butone(aClient *one, aClient *from, char *mask, int what, char *pattern, ...) + +#endif +{ + int i; + aClient *cptr, + *srch; + + for (i = 0; i <= highest_fd; i++) + { + if (!(cptr = local[i])) + continue; /* that clients are not mine */ + if (cptr == one) /* must skip the origin !! */ + continue; + if (IsServer(cptr)) + { + /* + ** we can save some CPU here by not searching the + ** entire list of users since it is ordered! + ** original idea/code from pht. + ** it could be made better by looping on the list of + ** servers to avoid non matching blocks in the list + ** (srch->from != cptr), but then again I never + ** bothered to worry or optimize this routine -kalt + */ + for (srch = cptr->prev; srch; srch = srch->prev) + { + if (!IsRegisteredUser(srch)) + continue; + if (srch->from == cptr && + match_it(srch, mask, what)) + break; + } + if (srch == NULL) + continue; + } + /* my client, does he match ? */ + else if (!(IsRegisteredUser(cptr) && + match_it(cptr, mask, what))) + continue; +#if ! USE_STDARG + sendto_prefix_one(cptr, from, pattern, + p1, p2, p3, p4, p5, p6, p7, p8, p9, p10,p11); +#else + { + va_list va; + va_start(va, pattern); + vsendto_prefix_one(cptr, from, pattern, va); + va_end(va); + } +#endif + + } + return; +} + +/* +** sendto_ops_butone +** Send message to all operators. +** one - client not to send message to +** from- client which message is from *NEVER* NULL!! +*/ +#if ! USE_STDARG +/*VARARGS*/ +void sendto_ops_butone(one, from, pattern, + p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11) +aClient *one, *from; +char *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *p11; +#else +void sendto_ops_butone(aClient *one, aClient *from, char *pattern, ...) +#endif +{ + Reg int i; + Reg aClient *cptr; + + bzero((char *)&sentalong[0], sizeof(int) * MAXCONNECTIONS); + for (cptr = client; cptr; cptr = cptr->next) + { + if (IsService(cptr) || !IsRegistered(cptr)) + continue; + if ((IsPerson(cptr) && !SendWallops(cptr)) || IsMe(cptr)) + continue; + if (MyClient(cptr) && !(IsServer(from) || IsMe(from))) + continue; + i = cptr->from->fd; /* find connection oper is on */ + if (sentalong[i]) /* sent message along it already ? */ + continue; + if (cptr->from == one) + continue; /* ...was the one I should skip */ + sentalong[i] = 1; +#if ! USE_STDARG + sendto_prefix_one(cptr->from, from, pattern, + p1, p2, p3, p4, p5, p6, p7, p8, p9, p10,p11); +#else + { + va_list va; + va_start(va, pattern); + vsendto_prefix_one(cptr->from, from, pattern, va); + va_end(va); + } +#endif + } + return; +} + +/* + * to - destination client + * from - client which message is from + * + * NOTE: NEITHER OF THESE SHOULD *EVER* BE NULL!! + * -avalon + */ +#if ! USE_STDARG +/*VARARGS*/ +void sendto_prefix_one(to, from, pattern, + p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11) +Reg aClient *to; +Reg aClient *from; +char *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *p11; +#else +void sendto_prefix_one(aClient *to, aClient *from, char *pattern, ...) +#endif +{ + int len; + +#if ! USE_STDARG + len = sendpreprep(to, from, pattern, p1, p2, p3, p4, p5, p6, p7, p8, + p9, p10, p11); +#else + va_list va; + va_start(va, pattern); + len = vsendpreprep(to, from, pattern, va); + va_end(va); +#endif + send_message(to, psendbuf, len); + return; +} + +#if USE_STDARG +static void vsendto_prefix_one(aClient *to, aClient *from, char *pattern, va_list va) +{ + int len; + + len = vsendpreprep(to, from, pattern, va); + send_message(to, psendbuf, len); + return; +} +#endif + + +/* + * sends a message to a server-owned channel + */ +static SChan svchans[SCH_MAX] = { + { SCH_ERROR, "&ERRORS", NULL }, + { SCH_NOTICE, "&NOTICES", NULL }, + { SCH_KILL, "&KILLS", NULL }, + { SCH_CHAN, "&CHANNEL", NULL }, + { SCH_NUM, "&NUMERICS", NULL }, + { SCH_SERVER, "&SERVERS", NULL }, + { SCH_HASH, "&HASH", NULL }, + { SCH_LOCAL, "&LOCAL", NULL }, + { SCH_SERVICE, "&SERVICES", NULL }, + { SCH_DEBUG, "&DEBUG", NULL }, + { SCH_AUTH, "&AUTH", NULL }, +}; + + +void setup_svchans() +{ + int i; + SChan *shptr; + + for (i = SCH_MAX, shptr = svchans + (i - 1); i > 0; i--, shptr--) + shptr->svc_ptr = find_channel(shptr->svc_chname, NULL); +} + +#if ! USE_STDARG +void sendto_flag(chan, pattern, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10,p11) +u_int chan; +char *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *p11; +#else +void sendto_flag(u_int chan, char *pattern, ...) +#endif +{ + Reg aChannel *chptr = NULL; + SChan *shptr; + char nbuf[1024]; + + if (chan < 1 || chan > SCH_MAX) + chan = SCH_NOTICE; + shptr = svchans + (chan - 1); + + if ((chptr = shptr->svc_ptr)) + { +#if ! USE_STDARG + (void)sprintf(nbuf, pattern, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); +#else + { + va_list va; + va_start(va, pattern); + (void)vsprintf(nbuf, pattern, va); + va_end(va); + } +#endif + sendto_channel_butserv(chptr, &me, ":%s NOTICE %s :%s", ME, chptr->chname, nbuf); + +#ifdef USE_SERVICES + switch (chan) + { + case SCH_ERROR: + check_services_butone(SERVICE_WANT_ERRORS, NULL, &me, + "&ERRORS :%s", nbuf); + break; + case SCH_NOTICE: + check_services_butone(SERVICE_WANT_NOTICES, NULL, &me, + "&NOTICES :%s", nbuf); + break; + case SCH_LOCAL: + check_services_butone(SERVICE_WANT_LOCAL, NULL, &me, + "&LOCAL :%s", nbuf); + break; + case SCH_NUM: + check_services_butone(SERVICE_WANT_NUMERICS, NULL, &me, + "&NUMERICS :%s", nbuf); + break; + } +#endif + } + + return; +} + +/* + * sendto_flog + * cptr used for firsttime, auth, exitc, send/received M/K + * msg replaces duration if duration is 0 + * duration only used if non 0 + * username can't get it from cptr + * hostname i.e. + */ +void sendto_flog(cptr, msg, duration, username, hostname) +aClient *cptr; +char *msg, *username, *hostname; +time_t duration; +{ + char linebuf[1024]; /* auth reply might be long.. */ + int logfile; + +#ifdef USE_SERVICES + if (duration) + { + (void)sprintf(linebuf, + "%s (%3d:%02d:%02d): %s@%s [%s] %c %lu %luKb %lu %luKb\n", + myctime(cptr->firsttime), + (int) (duration / 3600), + (int) ((duration % 3600) / 60), + (int) (duration % 60), + username, hostname, cptr->auth, + cptr->exitc, cptr->sendM, cptr->sendK, + cptr->receiveM, cptr->receiveK); + check_services_butone(SERVICE_WANT_USERLOG, NULL, &me, + "USERLOG :%s", linebuf); + } + else + { + (void)sprintf(linebuf, + "%s (%s): %s@%s [%s] %c %lu %luKb %lu %luKb\n", + myctime(cptr->firsttime), msg, username, + hostname, cptr->auth, + cptr->exitc, cptr->sendM, cptr->sendK, + cptr->receiveM, cptr->receiveK); + check_services_butone(SERVICE_WANT_CONNLOG, NULL, &me, + "CONNLOG :%s", linebuf); + } +#endif + /* + * This conditional makes the logfile active only after + * it's been created, thus logging can be turned off by + * removing the file. + * + * stop NFS hangs...most systems should be able to + * file in 3 seconds. -avalon (curtesy of wumpus) + */ + (void)alarm(3); + if ( +#ifdef FNAME_USERLOG + (duration && + (logfile = open(FNAME_USERLOG, O_WRONLY|O_APPEND)) != -1) +# ifdef FNAME_CONNLOG + || +# endif +#endif +#ifdef FNAME_CONNLOG + (!duration && + (logfile = open(FNAME_CONNLOG, O_WRONLY|O_APPEND)) != -1) +#else +# ifndef FNAME_USERLOG + 0 +# endif +#endif + ) + { + (void)alarm(0); +#ifndef USE_SERVICES + if (duration) + (void)sprintf(linebuf, + "%s (%3d:%02d:%02d): %s@%s [%s] %c %lu %luKb %lu %luKb\n", + myctime(cptr->firsttime), + (int) (duration / 3600), + (int) ((duration % 3600) / 60), + (int) (duration % 60), + username, hostname, cptr->auth, + cptr->exitc, cptr->sendM, cptr->sendK, + cptr->receiveM, cptr->receiveK); + else + (void)sprintf(linebuf, + "%s (%s): %s@%s [%s] %c %lu %luKb %lu %luKb\n", + myctime(cptr->firsttime), msg, username, + hostname, cptr->auth, + cptr->exitc, cptr->sendM, cptr->sendK, + cptr->receiveM, cptr->receiveK); +#endif + (void)alarm(3); + (void)write(logfile, linebuf, strlen(linebuf)); + (void)alarm(0); + (void)close(logfile); + } + (void)alarm(0); +} +#endif /* CLIENT_COMPILE */ diff --git a/common/send_ext.h b/common/send_ext.h new file mode 100644 index 0000000..7f0d409 --- /dev/null +++ b/common/send_ext.h @@ -0,0 +1,82 @@ +/************************************************************************ + * IRC - Internet Relay Chat, common/send_ext.h + * Copyright (C) 1997 Alain Nissen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* This file contains external definitions for global variables and functions + defined in common/send.c. + */ + +/* External definitions for global functions. + */ +#ifndef SEND_C +#define EXTERN extern +#else /* SEND_C */ +#define EXTERN +#endif /* SEND_C */ +EXTERN int send_queued __P((aClient *to)); +#if ! USE_STDARG +EXTERN int sendto_one(); +#else /* USE_STDARG */ +EXTERN int vsendto_one (aClient *to, char *pattern, va_list va); +EXTERN int sendto_one (aClient *to, char *pattern, ...); +#endif /* USE_STDARG */ +#ifndef CLIENT_COMPILE +EXTERN void flush_connections __P((int fd)); +EXTERN void flush_fdary __P((FdAry *)); +EXTERN void setup_svchans(); +EXTERN void sendto_flog __P((aClient *cptr, char *msg, time_t duration, + char *username, char *hostname)); +#if ! USE_STDARG +EXTERN void sendto_channel_butone(); +EXTERN void sendto_serv_butone(); +EXTERN int sendto_serv_v(); +EXTERN int sendto_serv_notv(); +EXTERN void sendto_common_channels(); +EXTERN void sendto_channel_butserv(); +EXTERN void sendto_match_servs(); +EXTERN int sendto_match_servs_v(); +EXTERN int sendto_match_servs_notv(); +EXTERN void sendto_match_butone(); +EXTERN void sendto_ops_butone(); +EXTERN void sendto_prefix_one(); +EXTERN void sendto_flag(); +#else /* USE_STDARG */ +EXTERN void sendto_channel_butone (aClient *one, aClient *from, + aChannel *chptr, char *pattern, ...); +EXTERN void sendto_serv_butone (aClient *one, char *pattern, ...); +EXTERN int sendto_serv_v (aClient *one, int ver, char *pattern, ...); +EXTERN int sendto_serv_notv (aClient *one, int ver, char *pattern, ...); +EXTERN void sendto_common_channels (aClient *user, char *pattern, ...); +EXTERN void sendto_channel_butserv (aChannel *chptr, aClient *from, + char *pattern, ...); +EXTERN void sendto_match_servs (aChannel *chptr, aClient *from, + char *format, ...); +EXTERN int sendto_match_servs_v (aChannel *chptr, aClient *from, int ver, + char *format, ...); +EXTERN int sendto_match_servs_notv (aChannel *chptr, aClient *from, int ver, + char *format, ...); +EXTERN void sendto_match_butone (aClient *one, aClient *from, char *mask, + int what, char *pattern, ...); +EXTERN void sendto_ops_butone (aClient *one, aClient *from, char *pattern, + ...); +EXTERN void sendto_prefix_one (aClient *to, aClient *from, char *pattern, + ...); +EXTERN void sendto_flag (u_int chan, char *pattern, ...); +#endif /* USE_STDARG */ +#endif /* CLIENT_COMPILE */ +#undef EXTERN diff --git a/common/struct_def.h b/common/struct_def.h new file mode 100644 index 0000000..720a531 --- /dev/null +++ b/common/struct_def.h @@ -0,0 +1,832 @@ +/************************************************************************ + * IRC - Internet Relay Chat, common/struct_def.h + * Copyright (C) 1990 Jarkko Oikarinen and + * University of Oulu, Computing Center + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +typedef struct ConfItem aConfItem; +typedef struct Client aClient; +typedef struct Channel aChannel; +typedef struct User anUser; +typedef struct Server aServer; +typedef struct Service aService; +typedef struct SLink Link; +typedef struct SMode Mode; +typedef struct fdarray FdAry; +typedef struct CPing aCPing; +typedef struct Zdata aZdata; +#if defined(CACHED_MOTD) +typedef struct LineItem aMotd; +#endif +#if defined(USE_IAUTH) +typedef struct LineItem aExtCf; +typedef struct LineItem aExtData; +#endif + +#define HOSTLEN 63 /* Length of hostname. Updated to */ + /* comply with RFC1123 */ + +#define NICKLEN 9 /* 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 BUFSIZE 512 /* WARNING: *DONT* CHANGE THIS!!!! */ +#define MAXRECIPIENTS 20 +#define MAXBANS 30 +#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 ! */ + +/* + * Make up some numbers which should reflect average leaf server connect + * queue max size. + * queue=(<# of channels> * + * <# of users>) * 2 + * pool= * + */ +#define QUEUELEN (((MAXCONNECTIONS / 10) * (CHANNELLEN + BANLEN + 16) +\ + (HOSTLEN * 4 + REALLEN + NICKLEN + USERLEN + 24) *\ + (MAXCONNECTIONS / 2)) * 2) + +#define BUFFERPOOL (DBUFSIZ * MAXCONNECTIONS * 2) + \ + (QUEUELEN * MAXSERVERS) + +#define USERHOST_REPLYLEN (NICKLEN+HOSTLEN+USERLEN+5) + +/* +** 'offsetof' is defined in ANSI-C. The following definition +** is not absolutely portable (I have been told), but so far +** it has worked on all machines I have needed it. The type +** should be size_t but... --msa +*/ +#ifndef offsetof +#define offsetof(t,m) (int)((&((t *)0L)->m)) +#endif + +#define elementsof(x) (sizeof(x)/sizeof(x[0])) + +/* +** flags for bootup options (command line flags) +*/ +#define BOOT_CONSOLE 0x001 +#define BOOT_QUICK 0x002 +#define BOOT_DEBUG 0x004 +#define BOOT_INETD 0x008 +#define BOOT_TTY 0x010 +#define BOOT_OPER 0x020 +#define BOOT_AUTODIE 0x040 +#define BOOT_BADTUNE 0x080 +#define BOOT_PROT 0x100 +#define BOOT_STRICTPROT 0x200 +#define BOOT_NOIAUTH 0x400 + +#define STAT_RECONNECT -7 /* Reconnect attempt for server connections */ +#define STAT_LOG -6 /* logfile for -x */ +#define STAT_MASTER -5 /* Local ircd master before identification */ +#define STAT_CONNECTING -4 +#define STAT_HANDSHAKE -3 +#define STAT_UNKNOWN -2 +#define STAT_ME -1 +#define STAT_SERVER 0 +#define STAT_CLIENT 1 +#define STAT_SERVICE 2 + +/* + * status macros. + */ +#define IsRegisteredUser(x) ((x)->status == STAT_CLIENT && (x)->user) +#define IsRegistered(x) ((x)->status >= STAT_SERVER || \ + (x)->status == STAT_ME) +#define IsConnecting(x) ((x)->status == STAT_CONNECTING) +#define IsHandshake(x) ((x)->status == STAT_HANDSHAKE) +#define IsMe(x) ((x)->status == STAT_ME) +#define IsUnknown(x) ((x)->status == STAT_UNKNOWN || \ + (x)->status == STAT_MASTER) +#define IsServer(x) ((x)->status == STAT_SERVER) +#define IsClient(x) ((x)->status == STAT_CLIENT) +#define IsLog(x) ((x)->status == STAT_LOG) +#define IsService(x) ((x)->status == STAT_SERVICE && (x)->service) +#define IsReconnect(x) ((x)->status == STAT_RECONNECT) + +#define SetMaster(x) ((x)->status = STAT_MASTER) +#define SetConnecting(x) ((x)->status = STAT_CONNECTING) +#define SetHandshake(x) ((x)->status = STAT_HANDSHAKE) +#define SetMe(x) ((x)->status = STAT_ME) +#define SetUnknown(x) ((x)->status = STAT_UNKNOWN) +#define SetServer(x) ((x)->status = STAT_SERVER) +#define SetClient(x) ((x)->status = STAT_CLIENT) +#define SetLog(x) ((x)->status = STAT_LOG) +#define SetService(x) ((x)->status = STAT_SERVICE) + +#define FLAGS_PINGSENT 0x0001 /* Unreplied ping sent */ +#define FLAGS_DEADSOCKET 0x0002 /* Local socket is dead--Exiting soon */ +#define FLAGS_KILLED 0x0004 /* Prevents "QUIT" from being sent for this */ +#define FLAGS_BLOCKED 0x0008 /* socket is in a blocked condition [unused] */ +#define FLAGS_UNIX 0x0010 /* socket is in the unix domain, not inet */ +#define FLAGS_CLOSING 0x0020 /* set when closing to suppress errors */ +#define FLAGS_LISTEN 0x0040 /* used to mark clients which we listen() on */ +#define FLAGS_XAUTHDONE 0x0080 /* iauth is finished with this client */ +#define FLAGS_DOINGDNS 0x0100 /* client is waiting for a DNS response */ +#define FLAGS_AUTH 0x0200 /* client is waiting on rfc931 response */ +#define FLAGS_WRAUTH 0x0400 /* set if we havent writen to ident server */ +#define FLAGS_LOCAL 0x0800 /* set for local clients */ +#define FLAGS_GOTID 0x1000 /* successful ident lookup achieved */ +#define FLAGS_XAUTH 0x2000 /* waiting on external authentication */ +#define FLAGS_WXAUTH 0x4000 /* same as above, but also prevent parsing */ +#define FLAGS_NONL 0x8000 /* No \n in buffer */ +#define FLAGS_CBURST 0x10000 /* set to mark connection burst being sent */ +#define FLAGS_RILINE 0x20000 /* Restricted i-line [unused?] */ +#define FLAGS_QUIT 0x40000 /* QUIT :comment shows it's not a split */ +#define FLAGS_SPLIT 0x80000 /* client QUITting because of a netsplit */ +#define FLAGS_HIDDEN 0x100000 /* netsplit is behind a hostmask */ +#define FLAGS_UNKCMD 0x200000 /* has sent an unknown command */ +#define FLAGS_ZIP 0x400000 /* link is zipped */ +#define FLAGS_ZIPRQ 0x800000 /* zip requested */ +#define FLAGS_ZIPSTART 0x1000000 /* start of zip (ignore any CRLF) */ +#define FLAGS_HELD 0x8000000 /* connection held and reconnect try */ + +#define FLAGS_OPER 0x0001 /* Operator */ +#define FLAGS_LOCOP 0x0002 /* Local operator -- SRB */ +#define FLAGS_WALLOP 0x0004 /* send wallops to them */ +#define FLAGS_INVISIBLE 0x0008 /* makes user invisible */ +#define FLAGS_RESTRICTED 0x0010 /* Restricted user */ +#define FLAGS_AWAY 0x0020 /* user is away */ + +#define SEND_UMODES (FLAGS_INVISIBLE|FLAGS_OPER|FLAGS_WALLOP|FLAGS_AWAY) +#define ALL_UMODES (SEND_UMODES|FLAGS_LOCOP|FLAGS_RESTRICTED) + +/* + * flags macros. + */ +#define IsOper(x) ((x)->user && (x)->user->flags & FLAGS_OPER) +#define IsLocOp(x) ((x)->user && (x)->user->flags & FLAGS_LOCOP) +#define IsInvisible(x) ((x)->user->flags & FLAGS_INVISIBLE) +#define IsRestricted(x) ((x)->user && \ + (x)->user->flags & FLAGS_RESTRICTED) +#define IsAnOper(x) ((x)->user && \ + (x)->user->flags & (FLAGS_OPER|FLAGS_LOCOP)) +#define IsPerson(x) ((x)->user && IsClient(x)) +#define IsPrivileged(x) (IsServer(x) || IsAnOper(x)) +#define SendWallops(x) ((x)->user->flags & FLAGS_WALLOP) +#define IsUnixSocket(x) ((x)->flags & FLAGS_UNIX) +#define IsListening(x) ((x)->flags & FLAGS_LISTEN) +#define IsLocal(x) (MyConnect(x) && (x)->flags & FLAGS_LOCAL) +#define IsDead(x) ((x)->flags & FLAGS_DEADSOCKET) +#define IsHeld(x) ((x)->flags & FLAGS_HELD) +#define CBurst(x) ((x)->flags & FLAGS_CBURST) + +#define SetOper(x) ((x)->user->flags |= FLAGS_OPER) +#define SetLocOp(x) ((x)->user->flags |= FLAGS_LOCOP) +#define SetInvisible(x) ((x)->user->flags |= FLAGS_INVISIBLE) +#define SetRestricted(x) ((x)->user->flags |= FLAGS_RESTRICTED) +#define SetWallops(x) ((x)->user->flags |= FLAGS_WALLOP) +#define SetUnixSock(x) ((x)->flags |= FLAGS_UNIX) +#define SetDNS(x) ((x)->flags |= FLAGS_DOINGDNS) +#define SetDoneXAuth(x) ((x)->flags |= FLAGS_XAUTHDONE) +#define DoingDNS(x) ((x)->flags & FLAGS_DOINGDNS) +#define DoingAuth(x) ((x)->flags & FLAGS_AUTH) +#define DoingXAuth(x) ((x)->flags & FLAGS_XAUTH) +#define WaitingXAuth(x) ((x)->flags & FLAGS_WXAUTH) +#define DoneXAuth(x) ((x)->flags & FLAGS_XAUTHDONE) +#define NoNewLine(x) ((x)->flags & FLAGS_NONL) + +#define ClearOper(x) ((x)->user->flags &= ~FLAGS_OPER) +#define ClearInvisible(x) ((x)->user->flags &= ~FLAGS_INVISIBLE) +#define ClearRestricted(x) ((x)->user->flags &= ~FLAGS_RESTRICTED) +#define ClearWallops(x) ((x)->user->flags &= ~FLAGS_WALLOP) +#define ClearDNS(x) ((x)->flags &= ~FLAGS_DOINGDNS) +#define ClearAuth(x) ((x)->flags &= ~FLAGS_AUTH) +#define ClearXAuth(x) ((x)->flags &= ~FLAGS_XAUTH) +#define ClearWXAuth(x) ((x)->flags &= ~FLAGS_WXAUTH) + +/* + * defined debugging levels + */ +#define DEBUG_FATAL 0 +#define DEBUG_ERROR 1 /* report_error() and other errors that are found */ +#define DEBUG_READ 2 +#define DEBUG_WRITE 2 +#define DEBUG_NOTICE 3 +#define DEBUG_DNS 4 /* used by all DNS related routines - a *lot* */ +#define DEBUG_INFO 5 /* general usful info */ +#define DEBUG_NUM 6 /* numerics */ +#define DEBUG_SEND 7 /* everything that is sent out */ +#define DEBUG_DEBUG 8 /* anything to do with debugging, ie unimportant :) */ +#define DEBUG_MALLOC 9 /* malloc/free calls */ +#define DEBUG_LIST 10 /* debug list use */ +#define DEBUG_L10 10 +#define DEBUG_L11 11 + +/* + * defines for curses in client + */ +#define DUMMY_TERM 0 +#define CURSES_TERM 1 +#define TERMCAP_TERM 2 + +struct CPing { + u_short port; /* port to send pings to */ + u_long rtt; /* average RTT */ + u_long ping; + u_long seq; /* # sent still in the "window" */ + u_long lseq; /* sequence # of last sent */ + u_long recvd; /* # received still in the "window" */ + u_long lrecvd; /* # received */ +}; + +struct ConfItem { + u_int status; /* If CONF_ILLEGAL, delete when no clients */ + int clients; /* Number of *LOCAL* clients using this */ + struct IN_ADDR ipnum; /* ip number of host field */ + char *host; + char *passwd; + char *name; + int port; + u_int pref; /* preference value */ + struct CPing *ping; + time_t hold; /* Hold action until this time (calendar time) */ +#ifndef VMSP + aClass *class; /* Class of connection */ +#endif + struct ConfItem *next; +}; + +#define CONF_ILLEGAL 0x80000000 +#define CONF_MATCH 0x40000000 +#define CONF_QUARANTINED_SERVER 0x000001 +#define CONF_CLIENT 0x000002 +#define CONF_RCLIENT 0x000004 +#define CONF_CONNECT_SERVER 0x000008 +#define CONF_NOCONNECT_SERVER 0x000010 +#define CONF_ZCONNECT_SERVER 0x000020 +#define CONF_LOCOP 0x000040 +#define CONF_OPERATOR 0x000080 +#define CONF_ME 0x000100 +#define CONF_KILL 0x000200 +#define CONF_ADMIN 0x000400 +#ifdef R_LINES +#define CONF_RESTRICT 0x000800 +#endif +#define CONF_CLASS 0x001000 +#define CONF_SERVICE 0x002000 +#define CONF_LEAF 0x004000 +#define CONF_LISTEN_PORT 0x008000 +#define CONF_HUB 0x010000 +#define CONF_VER 0x020000 +#define CONF_BOUNCE 0x040000 +#define CONF_OTHERKILL 0x080000 +#define CONF_DENY 0x100000 + +#define CONF_OPS (CONF_OPERATOR | CONF_LOCOP) +#define CONF_SERVER_MASK (CONF_CONNECT_SERVER | CONF_NOCONNECT_SERVER |\ + CONF_ZCONNECT_SERVER) +#define CONF_CLIENT_MASK (CONF_CLIENT | CONF_RCLIENT | CONF_SERVICE | CONF_OPS | \ + CONF_SERVER_MASK) + +#define IsIllegal(x) ((x)->status & CONF_ILLEGAL) + +typedef struct { + u_long pi_id; + u_long pi_seq; + struct timeval pi_tv; + aConfItem *pi_cp; +} Ping; + + +#define PING_REPLY 0x01 +#define PING_CPING 0x02 + +#ifdef ZIP_LINKS +/* the minimum amount of data needed to trigger compression */ +# define ZIP_MINIMUM 4096 + +/* the maximum amount of data to be compressed (can actually be a bit more) */ +# define ZIP_MAXIMUM 8192 /* WARNING: *DON'T* CHANGE THIS!!!! */ + +struct Zdata { + z_stream *in; /* input zip stream data */ + z_stream *out; /* output zip stream data */ + char outbuf[ZIP_MAXIMUM]; /* outgoing (unzipped) buffer */ + int outcount; /* size of outbuf content */ +}; +#endif + +struct LineItem +{ + char *line; + struct LineItem *next; +}; + +/* + * Client structures + */ +struct User { + Link *channel; /* chain of channel pointer blocks */ + Link *invited; /* chain of invite pointer blocks */ + Link *uwas; /* chain of whowas pointer blocks */ + char *away; /* pointer to away message */ + time_t last; /* "idle" time */ + int refcnt; /* Number of times this block is referenced + ** from aClient (field user), aServer (field + ** by) and whowas array (field ww_user). + */ + int joined; /* number of channels joined */ + int flags; /* user modes */ + struct Server *servp; + /* + ** In a perfect world the 'server' name + ** should not be needed, a pointer to the + ** client describing the server is enough. + ** Unfortunately, in reality, server may + ** not yet be in links while USER is + ** introduced... --msa + */ + aClient *bcptr; + char username[USERLEN+1]; + char host[HOSTLEN+1]; + char *server; +}; + +struct Server { + anUser *user; /* who activated this connection */ + char *up; /* uplink for this server */ + aConfItem *nline; /* N-line pointer for this server */ + int version; /* version id for local client */ + int snum; + int stok, + ltok; + int refcnt; /* Number of times this block is referenced + ** from anUser (field servp), aService (field + ** servp) and aClient (field serv) + */ + struct Server *nexts, *prevs, *shnext; + aClient *bcptr; + char by[NICKLEN+1]; + char tok[5]; + time_t lastload; /* penalty like counters, see s_serv.c + ** should be in the local part, but.. + */ +}; + +struct Service { + int wants; + int type; + char *server; + aServer *servp; + struct Service *nexts, *prevs; + aClient *bcptr; + char dist[HOSTLEN+1]; +}; + +struct Client { + struct Client *next,*prev, *hnext; + anUser *user; /* ...defined, if this is a User */ + aServer *serv; /* ...defined, if this is a server */ + aService *service; + u_int hashv; /* raw hash value */ + long flags; /* client flags */ + aClient *from; /* == self, if Local Client, *NEVER* NULL! */ + int fd; /* >= 0, for local clients */ + int hopcount; /* number of servers to this 0 = local */ + short status; /* Client type */ + char name[HOSTLEN+1]; /* Unique name of the client, nick or host */ + char username[USERLEN+1]; /* username here now for auth stuff */ + char *info; /* Free form additional client information */ + /* + ** The following fields are allocated only for local clients + ** (directly connected to *this* server with a socket. + ** The first of them *MUST* be the "count"--it is the field + ** to which the allocation is tied to! *Never* refer to + ** these fields, if (from != self). + */ + int count; /* Amount of data in buffer */ + char buffer[BUFSIZE]; /* Incoming message buffer */ +#ifdef ZIP_LINKS + aZdata *zip; /* zip data */ +#endif + short lastsq; /* # of 2k blocks when sendqueued called last*/ + dbuf sendQ; /* Outgoing message queue--if socket full */ + dbuf recvQ; /* Hold for data incoming yet to be parsed */ + long sendM; /* Statistics: protocol messages send */ + long sendK; /* Statistics: total k-bytes send */ + long receiveM; /* Statistics: protocol messages received */ + long receiveK; /* Statistics: total k-bytes received */ + u_short sendB; /* counters to count upto 1-k lots of bytes */ + u_short receiveB; /* sent and received. */ + time_t lasttime; /* last time we received data */ + time_t firsttime; /* time client was created */ + time_t since; /* last time we parsed something */ + aClient *acpt; /* listening client which we accepted from */ + Link *confs; /* Configuration record associated */ + int authfd; /* fd for rfc931 authentication */ + char *auth; + u_short port; /* and the remote port# too :-) */ + struct IN_ADDR ip; /* keep real ip# too */ + 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 exitc; +}; + +#define CLIENT_LOCAL_SIZE sizeof(aClient) +#define CLIENT_REMOTE_SIZE offsetof(aClient,count) + +/* + * statistics structures + */ +struct stats { + u_int is_cl; /* number of client connections */ + u_int is_sv; /* number of server connections */ + u_int is_ni; /* connection but no idea who it was + * (can be a P: line that has been removed -krys) */ + u_short is_cbs; /* bytes sent to clients */ + u_short is_cbr; /* bytes received to clients */ + u_short is_sbs; /* bytes sent to servers */ + u_short is_sbr; /* bytes received to servers */ + u_long is_cks; /* k-bytes sent to clients */ + u_long is_ckr; /* k-bytes received to clients */ + u_long is_sks; /* k-bytes sent to servers */ + u_long is_skr; /* k-bytes received to servers */ + time_t is_cti; /* time spent connected by clients */ + time_t is_sti; /* time spent connected by servers */ + u_int is_ac; /* connections accepted */ + u_int is_ref; /* accepts refused */ + u_int is_unco; /* unknown commands */ + u_int is_wrdi; /* command going in wrong direction */ + u_int is_unpf; /* unknown prefix */ + u_int is_empt; /* empty message */ + u_int is_num; /* numeric message */ + u_int is_kill; /* number of kills generated on collisions */ + u_int is_fake; /* MODE 'fakes' */ + u_int is_asuc; /* successful auth requests */ + u_int is_abad; /* bad auth requests */ + u_int is_udpok; /* packets recv'd on udp port */ + u_int is_udperr; /* packets recvfrom errors on udp port */ + u_int is_udpdrop; /* packets recv'd but dropped on udp port */ + u_int is_loc; /* local connections made */ + u_int is_nosrv; /* user without server */ + u_long is_wwcnt; /* number of nicks overwritten in whowas[] */ + u_long is_wwt; /* sum of elapsed time on when overwriting whowas[]*/ + u_long is_wwMt; /* max elapsed time on when overwriting whowas[] */ + u_long is_wwmt; /* min elapsed time on when overwriting whowas[] */ + u_long is_lkcnt; /* number of nicks overwritten in locked[] */ + u_long is_lkt; /* sum of elapsed time on when overwriting locked[]*/ + u_long is_lkMt; /* max elapsed time on when overwriting locked[] */ + u_long is_lkmt; /* min elapsed time on when overwriting locked[] */ + u_int is_ckl; /* calls to check_link() */ + u_int is_cklQ; /* rejected: SendQ too high */ + u_int is_ckly; /* rejected: link too young */ + u_int is_cklno; /* rejected: "flood" */ + u_int is_cklok; /* accepted */ + u_int is_cklq; /* accepted early */ +}; + +/* mode structure for channels */ + +struct SMode { + u_int mode; + int limit; + char key[KEYLEN+1]; +}; + +/* Message table structure */ + +struct Message { + char *cmd; + int (* func)(); + int parameters; + u_int flags; + /* bit 0 set means that this command is allowed to be used + * only on the average of once per 2 seconds -SRB */ + u_int count; /* total count */ + u_int rcount; /* remote count */ + u_long bytes; +}; + +#define MSG_LAG 0x0001 +#define MSG_NOU 0x0002 /* Not available to users */ +#define MSG_SVC 0x0004 /* Services only */ +#define MSG_NOUK 0x0008 /* Not available to unknowns */ +#define MSG_REG 0x0010 /* Must be registered */ +#define MSG_REGU 0x0020 /* Must be a registered user */ +/*#define MSG_PP 0x0040*/ +/*#define MSG_FRZ 0x0080*/ +#define MSG_OP 0x0100 /* opers only */ +#define MSG_LOP 0x0200 /* locops only */ + +/* fd array structure */ + +struct fdarray { + int fd[MAXCONNECTIONS]; + int highest; +}; + +/* general link structure used for chains */ + +struct SLink { + struct SLink *next; + union { + aClient *cptr; + aChannel *chptr; + aConfItem *aconf; + char *cp; + int i; + } value; + int flags; +}; + +/* channel structure */ + +struct Channel { + struct Channel *nextch, *prevch, *hnextch; + u_int hashv; /* raw hash value */ + Mode mode; + char topic[TOPICLEN+1]; + int users; /* current membership total */ + Link *members; /* channel members */ + Link *invites; /* outstanding invitations */ + Link *mlist; /* list of extended modes: +b/+e/+I */ + Link *clist; /* list of connections which are members */ + time_t history; /* channel history (aka channel delay) */ + time_t reop; /* server reop stamp for !channels */ + char chname[1]; +}; + +/* +** Channel Related macros follow +*/ + +/* Channel related flags */ + +#define CHFL_UNIQOP 0x0001 /* Channel creator */ +#define CHFL_CHANOP 0x0002 /* Channel operator */ +#define CHFL_VOICE 0x0004 /* the power to speak */ +#define CHFL_BAN 0x0008 /* ban channel flag */ +#define CHFL_EXCEPTION 0x0010 /* exception channel flag */ +#define CHFL_INVITE 0x0020 /* invite channel flag */ + +/* Channel Visibility macros */ + +#define MODE_UNIQOP CHFL_UNIQOP +#define MODE_CHANOP CHFL_CHANOP +#define MODE_VOICE CHFL_VOICE +#define MODE_PRIVATE 0x0008 +#define MODE_SECRET 0x0010 +#define MODE_MODERATED 0x0020 +#define MODE_TOPICLIMIT 0x0040 +#define MODE_INVITEONLY 0x0080 +#define MODE_NOPRIVMSGS 0x0100 +#define MODE_KEY 0x0200 +#define MODE_BAN 0x0400 +#define MODE_LIMIT 0x0800 +#define MODE_ANONYMOUS 0x1000 +#define MODE_QUIET 0x2000 +#define MODE_EXCEPTION 0x4000 +#define MODE_INVITE 0x8000 +#define MODE_REOP 0x10000 +#define MODE_FLAGS 0x1ffff +/* + * mode flags which take another parameter (With PARAmeterS) + */ +#define MODE_WPARAS (MODE_UNIQOP|MODE_CHANOP|MODE_VOICE|MODE_BAN|MODE_KEY\ + |MODE_LIMIT|MODE_INVITE|MODE_EXCEPTION) +/* + * Undefined here, these are used in conjunction with the above modes in + * the source. +#define MODE_DEL 0x40000000 +#define MODE_ADD 0x80000000 + */ + +#define HoldChannel(x) (!(x)) +/* name invisible */ +#define SecretChannel(x) ((x) && ((x)->mode.mode & MODE_SECRET)) +/* channel not shown but names are */ +#define HiddenChannel(x) ((x) && ((x)->mode.mode & MODE_PRIVATE)) +/* channel visible */ +#define ShowChannel(v,c) (PubChannel(c) || IsMember((v),(c))) +#define IsAnonymous(c) ((c) && ((c)->mode.mode & MODE_ANONYMOUS)) +#define PubChannel(x) ((!x) || ((x)->mode.mode &\ + (MODE_PRIVATE | MODE_SECRET)) == 0) + +/* +#define IsMember(u, c) (assert(*(c)->chname != '\0'), find_user_link((c)->members, u) ? 1 : 0) +#define IsMember(u, c) (find_user_link((c)->members, u) ? 1 : 0) +*/ +#define IsMember(u, c) (u && (u)->user && \ + find_channel_link((u)->user->channel, c) ? 1 : 0) +#ifdef CLIENT_COMPILE +# define IsChannelName(n) ((n) && (*(n) == '#' || *(n) == '&' ||\ + *(n) == '+' || *(n) == '!')) +#else +# define IsChannelName(n) ((n) && (*(n) == '#' || *(n) == '&' ||\ + *(n) == '+' || \ + (*(n) == '!' && cid_ok(n)))) +#endif +#define IsQuiet(x) ((x)->mode.mode & MODE_QUIET) +#define UseModes(n) ((n) && (*(n) == '#' || *(n) == '&' || \ + *(n) == '!')) + +/* Misc macros */ + +#define BadPtr(x) (!(x) || (*(x) == '\0')) + +#define isvalid(c) (((c) >= 'A' && (c) <= '~') || isdigit(c) || (c) == '-') + +#define MyConnect(x) ((x)->fd >= 0) +#define MyClient(x) (MyConnect(x) && IsClient(x)) +#define MyPerson(x) (MyConnect(x) && IsPerson(x)) +#define MyOper(x) (MyConnect(x) && IsOper(x)) +#define MyService(x) (MyConnect(x) && IsService(x)) +#define ME me.name + +#define GotDependantClient(x) (x->prev && \ + ((IsRegisteredUser(x->prev) && \ + x->prev->user->servp == x->serv) || \ + (IsService(x->prev) && \ + x->prev->service->servp == x->serv))) + +typedef struct { + u_long is_user[2]; /* users, non[0] invis and invis[1] */ + u_long is_serv; /* servers */ + u_long is_service; /* services */ + u_long is_chan; /* channels */ + u_long is_chanmem; + u_long is_chanusers; /* channels users */ + u_long is_hchan; /* channels in history */ + u_long is_hchanmem; + u_long is_cchan; /* channels in cache */ + u_long is_cchanmem; + u_long is_away; /* away sets */ + u_long is_awaymem; + u_long is_oper; /* opers */ + u_long is_bans; /* bans */ + u_long is_banmem; + u_long is_invite; /* invites */ + u_long is_class; /* classes */ + u_long is_conf; /* conf lines */ + u_long is_confmem; + u_long is_conflink; /* attached conf lines */ + u_long is_myclnt; /* local clients */ + u_long is_myserv; /* local servers */ + u_long is_myservice; /* local services */ + u_long is_unknown; /* unknown (local) connections */ + u_long is_wwusers; /* users kept for whowas[] */ + u_long is_wwaways; /* aways in users in whowas[] */ + u_long is_wwawaysmem; + u_long is_wwuwas; /* uwas links */ + u_long is_localc; /* local items (serv+service+client+..) */ + u_long is_remc; /* remote clients */ + u_long is_users; /* user structs */ + u_long is_useri; /* user invites */ + u_long is_userc; /* user links to channels */ + u_long is_auth; /* OTHER ident reply block */ + u_long is_authmem; + u_int is_dbuf; /* number of dbuf allocated (originally) */ + u_int is_dbufnow; /* number of dbuf allocated */ + u_int is_dbufuse; /* number of dbuf in use */ + 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*/ +} istat_t; + +/* String manipulation macros */ + +/* strncopynt --> strncpyzt to avoid confusion, sematics changed + N must be now the number of bytes in the array --msa */ +#define strncpyzt(x, y, N) do{(void)strncpy(x,y,N);x[N-1]='\0';}while(0) +#define StrEq(x,y) (!strcmp((x),(y))) + +/* used in SetMode() in channel.c and m_umode() in s_msg.c */ + +#define MODE_NULL 0 +#define MODE_ADD 0x40000000 +#define MODE_DEL 0x20000000 + +/* return values for hunt_server() */ + +#define HUNTED_NOSUCH (-1) /* if the hunted server is not found */ +#define HUNTED_ISME 0 /* if this server should execute the command */ +#define HUNTED_PASS 1 /* if message passed onwards successfully */ + +/* used when sending to #mask or $mask */ + +#define MATCH_SERVER 1 +#define MATCH_HOST 2 + +/* used for sendto_serv */ + +#define SV_OLD 0x0000 +#define SV_29 0x0001 /* useless, but preserved for coherence */ +#define SV_NJOIN 0x0002 /* server understands the NJOIN command */ +#define SV_NMODE 0x0004 /* server knows new MODEs (+e/+I) */ +#define SV_NCHAN 0x0008 /* server knows new channels -????name */ + /* ! SV_NJOIN implies ! SV_NCHAN */ +#define SV_2_10 (SV_29|SV_NJOIN|SV_NMODE|SV_NCHAN) +#define SV_OLDSQUIT 0x1000 /* server uses OLD SQUIT logic */ + +/* used for sendto_flag */ + +typedef struct { + int svc_chan; + char *svc_chname; + struct Channel *svc_ptr; +} SChan; + +#define SCH_ERROR 1 +#define SCH_NOTICE 2 +#define SCH_KILL 3 +#define SCH_CHAN 4 +#define SCH_NUM 5 +#define SCH_SERVER 6 +#define SCH_HASH 7 +#define SCH_LOCAL 8 +#define SCH_SERVICE 9 +#define SCH_DEBUG 10 +#define SCH_AUTH 11 +#define SCH_MAX 11 + +/* used for async dns values */ + +#define ASYNC_NONE (-1) +#define ASYNC_CLIENT 0 +#define ASYNC_CONNECT 1 +#define ASYNC_CONF 2 +#define ASYNC_SERVER 3 + +/* Client exit codes for log file */ +#define EXITC_UNDEF '-' /* unregistered client */ +#define EXITC_REG '0' /* normal exit */ +#define EXITC_DIE 'd' /* server died */ +#define EXITC_DEAD 'D' /* socket died */ +#define EXITC_ERROR 'E' /* socket error */ +#define EXITC_FLOOD 'F' /* client flooding */ +#define EXITC_KLINE 'k' /* K-lined */ +#define EXITC_KILL 'K' /* KILLed */ +#define EXITC_MBUF 'M' /* mem alloc error */ +#define EXITC_PING 'P' /* ping timeout */ +#define EXITC_SENDQ 'Q' /* send queue exceeded */ +#define EXITC_RLINE 'r' /* R-lined */ +#define EXITC_REF 'R' /* Refused */ +#define EXITC_AREF 'U' /* Unauthorized by iauth */ +#define EXITC_AREFQ 'u' /* Unauthorized by iauth, be quiet */ +#define EXITC_AUTHFAIL 'A' /* Authentication failure (iauth problem) */ +#define EXITC_AUTHTOUT 'a' /* Authentication time out */ + +/* eXternal authentication slave OPTions */ +#define XOPT_REQUIRED 0x01 /* require authentication be done by iauth */ +#define XOPT_NOTIMEOUT 0x02 /* disallow iauth time outs */ +#define XOPT_EXTWAIT 0x10 /* extend registration ping timeout */ +#define XOPT_EARLYPARSE 0x20 /* allow early parsing and send USER/PASS + information to iauth */ + +/* misc defines */ + +#define FLUSH_BUFFER -2 +#define UTMP "/etc/utmp" +#define COMMA "," + +#define SAP struct SOCKADDR * + +/* IRC client structures */ + +#ifdef CLIENT_COMPILE +typedef struct Ignore { + char user[NICKLEN+1]; + char from[USERLEN+HOSTLEN+2]; + int flags; + struct Ignore *next; +} anIgnore; + +#define IGNORE_PRIVATE 1 +#define IGNORE_PUBLIC 2 +#define IGNORE_TOTAL 3 + +#define HEADERLEN 200 + +#endif /* CLIENT_COMPILE */ diff --git a/common/support.c b/common/support.c new file mode 100644 index 0000000..f90e6b0 --- /dev/null +++ b/common/support.c @@ -0,0 +1,1190 @@ +/************************************************************************ + * IRC - Internet Relay Chat, common/support.c + * Copyright (C) 1990, 1991 Armin Gruner + * + * 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: support.c,v 1.17 1999/06/25 15:36:16 kalt Exp $"; +#endif + +#include "os.h" +#ifndef CLIENT_COMPILE +# include "s_defines.h" +#else +# include "c_defines.h" +#endif +#define SUPPORT_C +#ifndef CLIENT_COMPILE +# include "s_externs.h" +#else +# include "c_externs.h" +#endif +#undef SUPPORT_C + +char *mystrdup(s) +char *s; +{ + /* Portable strdup(), contributed by mrg, thanks! -roy */ + + char *t; + + t = (char *) MyMalloc(strlen(s) + 1); + if (t) + return ((char *)strcpy(t, s)); + return NULL; +} + +#if ! HAVE_STRTOKEN +/* +** strtoken.c -- walk through a string of tokens, using a set +** of separators +** argv 9/90 +*/ + +char *strtoken(save, str, fs) +char **save; +char *str, *fs; +{ + char *pos = *save; /* keep last position across calls */ + Reg char *tmp; + + if (str) + pos = str; /* new string scan */ + + while (pos && *pos && index(fs, *pos) != NULL) + pos++; /* skip leading separators */ + + if (!pos || !*pos) + return (pos = *save = NULL); /* string contains only sep's */ + + tmp = pos; /* now, keep position of the token */ + + while (*pos && index(fs, *pos) == NULL) + pos++; /* skip content of the token */ + + if (*pos) + *pos++ = '\0'; /* remove first sep after the token */ + else + pos = NULL; /* end of string */ + + *save = pos; + return(tmp); +} +#endif /* HAVE_STRTOKEN */ + +#if ! HAVE_STRTOK +/* +** NOT encouraged to use! +*/ + +char *strtok(str, fs) +char *str, *fs; +{ + static char *pos; + + return strtoken(&pos, str, fs); +} + +#endif /* HAVE_STRTOK */ + +#if ! HAVE_STRERROR +/* +** strerror - return an appropriate system error string to a given errno +** +** argv 11/90 +*/ + +char *strerror(err_no) +int err_no; +{ + static char buff[40]; + char *errp; + + errp = (err_no > sys_nerr ? (char *)NULL : sys_errlist[err_no]); + + if (errp == (char *)NULL) + { + errp = buff; + SPRINTF(errp, "Unknown Error %d", err_no); + } + return errp; +} + +#endif /* HAVE_STRERROR */ + +/** + ** myctime() + ** This is like standard ctime()-function, but it zaps away + ** the newline from the end of that string. Also, it takes + ** the time value as parameter, instead of pointer to it. + ** Note that it is necessary to copy the string to alternate + ** buffer (who knows how ctime() implements it, maybe it statically + ** has newline there and never 'refreshes' it -- zapping that + ** might break things in other places...) + ** + **/ + +char *myctime(value) +time_t value; +{ + static char buf[28]; + Reg char *p; + + (void)strcpy(buf, ctime(&value)); + if ((p = (char *)index(buf, '\n')) != NULL) + *p = '\0'; + + return buf; +} + +/* +** mybasename() +** removes path from a filename +*/ +char * +mybasename(path) +char *path; +{ + char *lastslash; + + if (lastslash = rindex(path, '/')) + return lastslash + 1; + return path; +} + +#ifdef INET6 +/* + * inetntop: return the : notation of a given IPv6 internet number. + * make sure the compressed representation (rfc 1884) isn't used. + */ +char *inetntop(af, in, out, the_size) +int af; +const void *in; +char *out; +size_t the_size; +{ + static char local_dummy[MYDUMMY_SIZE]; + + inet_ntop(af, in, local_dummy, the_size); + if (strstr(local_dummy, "::")) + { + char cnt = 0, *cp = local_dummy, *op = out; + + while (*cp) + { + if (*cp == ':') + cnt += 1; + if (*cp++ == '.') + { + cnt += 1; + break; + } + } + cp = local_dummy; + while (*cp) + { + *op++ = *cp++; + if (*(cp-1) == ':' && *cp == ':') + { + if ((cp-1) == local_dummy) + { + op--; + *op++ = '0'; + *op++ = ':'; + } + + *op++ = '0'; + while (cnt++ < 7) + { + *op++ = ':'; + *op++ = '0'; + } + } + } + if (*(op-1)==':') *op++ = '0'; + *op = '\0'; + Debug((DEBUG_DNS,"Expanding `%s' -> `%s'", local_dummy, + out)); + } + else + bcopy(local_dummy, out, 64); + return out; +} +#endif + +#if ! HAVE_INET_NTOA +/* +** inetntoa -- changed name to remove collision possibility and +** so behaviour is gaurunteed to take a pointer arg. +** -avalon 23/11/92 +** inet_ntoa -- returned the dotted notation of a given +** internet number (some ULTRIX don't have this) +** argv 11/90). +** inet_ntoa -- its broken on some Ultrix/Dynix too. -avalon +*/ + +char *inetntoa(in) +char *in; +{ + static char buf[16]; + Reg u_char *s = (u_char *)in; + Reg int a,b,c,d; + + a = (int)*s++; + b = (int)*s++; + c = (int)*s++; + d = (int)*s; + (void)sprintf(buf, "%d.%d.%d.%d", a,b,c,d ); + + return buf; +} +#endif + +#if ! HAVE_INET_NETOF +/* +** inet_netof -- return the net portion of an internet number +** argv 11/90 +*/ +int inetnetof(in) +struct in_addr in; +{ + register u_long i = ntohl(in.s_addr); + + if (IN_CLASSA(i)) + return (((i)&IN_CLASSA_NET) >> IN_CLASSA_NSHIFT); + else if (IN_CLASSB(i)) + return (((i)&IN_CLASSB_NET) >> IN_CLASSB_NSHIFT); + else + return (((i)&IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); +} +#endif + +#if ! HAVE_INET_ADDR +# ifndef INADDR_NONE +# define INADDR_NONE 0xffffffff +# endif +/* + * Ascii internet address interpretation routine. + * The value returned is in network order. + */ +u_long +inetaddr(cp) + register const char *cp; +{ + struct in_addr val; + + if (inetaton(cp, &val)) + return (val.s_addr); + return (INADDR_NONE); +} +#endif + +#if ! HAVE_INET_ATON +/* + * Check whether "cp" is a valid ascii representation + * of an Internet address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * This replaces inet_addr, the return value from which + * cannot distinguish between failure and a local broadcast address. + */ +int +inetaton(cp, addr) + register const char *cp; + struct in_addr *addr; +{ + register u_long val; + register int base, n; + register char c; + u_int parts[4]; + register u_int *pp = parts; + + c = *cp; + for (;;) { + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, isdigit=decimal. + */ + if (!isdigit(c)) + return (0); + val = 0; base = 10; + if (c == '0') { + c = *++cp; + if (c == 'x' || c == 'X') + base = 16, c = *++cp; + else + base = 8; + } + for (;;) { + if (isascii(c) && isdigit(c)) { + val = (val * base) + (c - '0'); + c = *++cp; + } else if (base == 16 && isascii(c) && isxdigit(c)) { + val = (val << 4) | + (c + 10 - (islower(c) ? 'a' : 'A')); + c = *++cp; + } else + break; + } + if (c == '.') { + /* + * Internet format: + * a.b.c.d + * a.b.c (with c treated as 16 bits) + * a.b (with b treated as 24 bits) + */ + if (pp >= parts + 3) + return (0); + *pp++ = val; + c = *++cp; + } else + break; + } + /* + * Check for trailing characters. + */ + if (c != '\0' && (!isascii(c) || !isspace(c))) + return (0); + /* + * Concoct the address according to + * the number of parts specified. + */ + n = pp - parts + 1; + switch (n) { + + case 0: + return (0); /* initial nondigit */ + + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if (val > 0xffffff) + return (0); + val |= parts[0] << 24; + break; + + case 3: /* a.b.c -- 8.8.16 bits */ + if (val > 0xffff) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /* a.b.c.d -- 8.8.8.8 bits */ + if (val > 0xff) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + } + if (addr) + addr->s_addr = htonl(val); + return (1); +} +#endif + +#if defined(DEBUGMODE) && !defined(CLIENT_COMPILE) +void dumpcore(msg, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11) +char *msg, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *p11; +{ + static time_t lastd = 0; + static int dumps = 0; + char corename[12]; + time_t now; + int p; + + now = time(NULL); + + if (!lastd) + lastd = now; + else if (now - lastd < 60 && dumps > 2) + (void)s_die(0); + if (now - lastd > 60) + { + lastd = now; + dumps = 1; + } + else + dumps++; + p = getpid(); + if (fork()>0) { + kill(p, 3); + kill(p, 9); + } + write_pidfile(); + SPRINTF(corename, "core.%d", p); + (void)rename("core", corename); + Debug((DEBUG_FATAL, "Dumped core : core.%d", p)); + sendto_flag(SCH_ERROR, "Dumped core : core.%d", p); + Debug((DEBUG_FATAL, msg, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10,p11)); + sendto_flag(SCH_ERROR, msg, p1, p2, p3, p4, p5, p6, p7, p8,p9,p10,p11); + (void)s_die(0); +} +#endif + +#if defined(DEBUGMODE) && !defined(CLIENT_COMPILE) && defined(DO_DEBUG_MALLOC) + +static char *marray[100000]; +static int mindex = 0; + +#define SZ_EX (sizeof(char *) + sizeof(size_t) + 4) +#define SZ_CHST (sizeof(char *) + sizeof(size_t)) +#define SZ_CH (sizeof(char *)) +#define SZ_ST (sizeof(size_t)) + +char *MyMalloc(x) +size_t x; +{ + register int i; + register char **s; + char *ret; + + ret = (char *)malloc(x + (size_t)SZ_EX); + + if (!ret) + { +# ifndef CLIENT_COMPILE + outofmemory(); +# else + perror("malloc"); + exit(-1); +# endif + } + bzero(ret, (int)x + SZ_EX); + bcopy((char *)&ret, ret, SZ_CH); + bcopy((char *)&x, ret + SZ_ST, SZ_ST); + bcopy("VAVA", ret + SZ_CHST + (int)x, 4); + Debug((DEBUG_MALLOC, "MyMalloc(%ld) = %#x", x, ret + SZ_CHST)); + for(i = 0, s = marray; *s && i < mindex; i++, s++) + ; + if (i < 100000) + { + *s = ret; + if (i == mindex) + mindex++; + } + return ret + SZ_CHST; + } + +char *MyRealloc(x, y) +char *x; +size_t y; + { + register int l; + register char **s; + char *ret, *cp; + size_t i; + int k; + + if (x != NULL) + { + x -= SZ_CHST; + bcopy(x, (char *)&cp, SZ_CH); + bcopy(x + SZ_CH, (char *)&i, SZ_ST); + bcopy(x + (int)i + SZ_CHST, (char *)&k, 4); + if (bcmp((char *)&k, "VAVA", 4) || (x != cp)) + dumpcore("MyRealloc %#x %d %d %#x %#x", x, y, i, cp, k); + } + ret = (char *)realloc(x, y + (size_t)SZ_EX); + + if (!ret) + { +# ifndef CLIENT_COMPILE + outofmemory(); +# else + perror("realloc"); + exit(-1); +# endif + } + bcopy((char *)&ret, ret, SZ_CH); + bcopy((char *)&y, ret + SZ_CH, SZ_ST); + bcopy("VAVA", ret + SZ_CHST + (int)y, 4); + Debug((DEBUG_NOTICE, "MyRealloc(%#x,%ld) = %#x", x, y, ret + SZ_CHST)); + for(l = 0, s = marray; *s != x && l < mindex; l++, s++) + ; + if (l < mindex) + *s = NULL; + else if (l == mindex) + Debug((DEBUG_MALLOC, "%#x !found", x)); + for(l = 0, s = marray; *s && l < mindex; l++,s++) + ; + if (l < 100000) + { + *s = ret; + if (l == mindex) + mindex++; + } + return ret + SZ_CHST; + } + +void MyFree(x) +char *x; +{ + size_t i; + char *j; + u_char k[4]; + register int l; + register char **s; + + if (!x) + return; + x -= SZ_CHST; + + bcopy(x, (char *)&j, SZ_CH); + bcopy(x + SZ_CH, (char *)&i, SZ_ST); + bcopy(x + SZ_CHST + (int)i, (char *)k, 4); + + if (bcmp((char *)k, "VAVA", 4) || (j != x)) + dumpcore("MyFree %#x %ld %#x %#x", x, i, j, + (k[3]<<24) | (k[2]<<16) | (k[1]<<8) | k[0]); + + Debug((DEBUG_MALLOC, "MyFree(%#x)",x + SZ_CHST)); +#undef free + (void)free(x); +#define free(x) MyFree(x) + + for (l = 0, s = marray; *s != x && l < mindex; l++, s++) + ; + if (l < mindex) + *s = NULL; + else if (l == mindex) + Debug((DEBUG_MALLOC, "%#x !found", x)); +} +#else +char *MyMalloc(x) +size_t x; +{ + char *ret = (char *)malloc(x); + + if (!ret) + { +# ifndef CLIENT_COMPILE + outofmemory(); +# else + perror("malloc"); + exit(-1); +# endif + } + return ret; +} + +char *MyRealloc(x, y) +char *x; +size_t y; + { + char *ret = (char *)realloc(x, y); + + if (!ret) + { +# ifndef CLIENT_COMPILE + outofmemory(); +# else + perror("realloc"); + exit(-1); +# endif + } + return ret; + } +#endif + + +/* +** read a string terminated by \r or \n in from a fd +** +** Created: Sat Dec 12 06:29:58 EST 1992 by avalon +** Returns: +** 0 - EOF +** -1 - error on read +** >0 - number of bytes returned (<=num) +** After opening a fd, it is necessary to init dgets() by calling it as +** dgets(x,y,0); +** to mark the buffer as being empty. +*/ +int dgets(fd, buf, num) +int fd, num; +char *buf; +{ + static char dgbuf[8192]; + static char *head = dgbuf, *tail = dgbuf; + register char *s, *t; + register int n, nr; + + /* + ** Sanity checks. + */ + if (head == tail) + *head = '\0'; + if (!num) + { + head = tail = dgbuf; + *head = '\0'; + return 0; + } + if (num > sizeof(dgbuf) - 1) + num = sizeof(dgbuf) - 1; +dgetsagain: + if (head > dgbuf) + { + for (nr = tail - head, s = head, t = dgbuf; nr > 0; nr--) + *t++ = *s++; + tail = t; + head = dgbuf; + } + /* + ** check input buffer for EOL and if present return string. + */ + if (head < tail && + ((s = index(head, '\n')) || (s = index(head, '\r'))) && s < tail) + { + n = MIN(s - head + 1, num); /* at least 1 byte */ +dgetsreturnbuf: + bcopy(head, buf, n); + head += n; + if (head == tail) + head = tail = dgbuf; + return n; + } + + if (tail - head >= num) /* dgets buf is big enough */ + { + n = num; + goto dgetsreturnbuf; + } + + n = sizeof(dgbuf) - (tail - dgbuf) - 1; + nr = read(fd, tail, n); + if (nr == -1) + { + head = tail = dgbuf; + return -1; + } + if (!nr) + { + if (tail > head) + { + n = MIN(tail - head, num); + goto dgetsreturnbuf; + } + head = tail = dgbuf; + return 0; + } + tail += nr; + *tail = '\0'; + for (t = head; (s = index(t, '\n')); ) + { + if ((s > head) && (s > dgbuf)) + { + t = s-1; + for (nr = 0; *t == '\\'; nr++) + t--; + if (nr & 1) + { + t = s+1; + s--; + nr = tail - t; + while (nr--) + *s++ = *t++; + tail -= 2; + *tail = '\0'; + } + else + s++; + } + else + s++; + t = s; + } + *tail = '\0'; + goto dgetsagain; +} + +#if ! USE_STDARG +/* + * By Mika + */ +int irc_sprintf(outp, formp, + i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11) +char *outp; +char *formp; +char *i0, *i1, *i2, *i3, *i4, *i5, *i6, *i7, *i8, *i9, *i10, *i11; +{ + /* rp for Reading, wp for Writing, fp for the Format string */ + /* we could hack this if we know the format of the stack */ + char *inp[12]; + Reg char *rp, *fp, *wp, **pp = inp; + Reg char f; + Reg long myi; + int i; + + inp[0] = i0; + inp[1] = i1; + inp[2] = i2; + inp[3] = i3; + inp[4] = i4; + inp[5] = i5; + inp[6] = i6; + inp[7] = i7; + inp[8] = i8; + inp[9] = i9; + inp[10] = i10; + inp[11] = i11; + + /* + * just scan the format string and puke out whatever is necessary + * along the way... + */ + + for (i = 0, wp = outp, fp = formp; (f = *fp++); ) + if (f != '%') + *wp++ = f; + else + switch (*fp++) + { + /* put the most common case at the top */ + /* copy a string */ + case 's': + for (rp = *pp++; (*wp++ = *rp++); ) + ; + --wp; + /* get the next parameter */ + break; + /* + * reject range for params to this mean that the + * param must be within 100-999 and this +ve int + */ + case 'd': + case 'u': + myi = (long)*pp++; + if ((myi < 100) || (myi > 999)) + { + (void)sprintf(outp, formp, i0, i1, i2, + i3, i4, i5, i6, i7, i8, + i9, i10, i11); + return -1; + } + + *wp++ = (char)(myi / 100 + (int) '0'); + myi %= 100; + *wp++ = (char)(myi / 10 + (int) '0'); + myi %= 10; + *wp++ = (char)(myi + (int) '0'); + break; + case 'c': + *wp++ = (char)(long)*pp++; + break; + case '%': + *wp++ = '%'; + break; + default : + (void)sprintf(outp, formp, i0, i1, i2, i3, i4, + i5, i6, i7, i8, i9, i10, i11); + return -1; + } + *wp = '\0'; + return wp - outp; +} +#endif + +/* + * Make 'readable' version string. + */ +char *make_version() +{ + int ve, re, mi, dv, pl; + char ver[15]; + + sscanf(PATCHLEVEL, "%2d%2d%2d%2d%2d", &ve, &re, &mi, &dv, &pl); + /* version & revision */ + sprintf(ver, "%d.%d", ve, (mi == 99) ? re + 1 : re); + if (mi == 99) mi = -1; + /* minor revision */ + sprintf(ver + strlen(ver), ".%d", dv ? mi+1 : mi); + if (dv) /* alpha/beta, note how visual patchlevel is raised above */ + sprintf(ver + strlen(ver), "%c%d", DEVLEVEL, dv); + if (pl) /* patchlevel */ + sprintf(ver + strlen(ver), "p%d", pl); + return mystrdup(ver); +} + +#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 + * doesn't have it. -krys + * Replacement version from Dave Miller. + */ +int truncate(path, length) +const char *path; +off_t length; +{ + int fd, res; + fd = open(path, O_WRONLY); + if (fd == -1) + return -1; + res = ftruncate(fd, length); + close(fd); + return res; +} +#endif /* HAVE_TRUNCATE */ + +#if SOLARIS_2_3 +/* + * On Solaris 2.3 (SunOS 5.3) systems, gethostbyname() has a bug, it always + * returns null in h->aliases. Workaround: use the undocumented + * _switch_gethostbyname_r(...). + */ +#define HBUFSIZE 4096 + +struct hostent *solaris_gethostbyname(name) + const char *name; +{ + static struct hostent hp; + static char buf[HBUFSIZE]; + + return _switch_gethostbyname_r(name, &hp, buf, sizeof(buf), &h_errno); +} +#endif /* SOLARIS_2_3 */ + +#if HAVE_MEMCMP && MEMCMP_BROKEN +/* + * Some OS may have a memcmp that is not 8-bit clean. + * + * Copyright (C) 1991, 1993, 1995 Free Software Foundation, Inc. + * Contributed by Torbjorn Granlund (tege@sics.se). + * + * NOTE: The canonical source of this part of the file is maintained with the + * GNU C Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. + */ + +/* Type to use for aligned memory operations. + This should normally be the biggest type supported by a single load + and store. Must be an unsigned type. */ +#define op_t unsigned long int +#define OPSIZ (sizeof(op_t)) + +/* Threshold value for when to enter the unrolled loops. */ +#define OP_T_THRES 16 + +/* Type to use for unaligned operations. */ +typedef unsigned char byte; + +#if ! WORDS_BIGENDIAN +#define MERGE(w0, sh_1, w1, sh_2) (((w0) >> (sh_1)) | ((w1) << (sh_2))) +#else +#define MERGE(w0, sh_1, w1, sh_2) (((w0) << (sh_1)) | ((w1) >> (sh_2))) +#endif + +#if WORDS_BIGENDIAN +#define CMP_LT_OR_GT(a, b) ((a) > (b) ? 1 : -1) +#else +#define CMP_LT_OR_GT(a, b) memcmp_bytes ((a), (b)) +#endif + +/* BE VERY CAREFUL IF YOU CHANGE THIS CODE! */ + +/* The strategy of this memcmp is: + + 1. Compare bytes until one of the block pointers is aligned. + + 2. Compare using memcmp_common_alignment or + memcmp_not_common_alignment, regarding the alignment of the other + block after the initial byte operations. The maximum number of + full words (of type op_t) are compared in this way. + + 3. Compare the few remaining bytes. */ + +#if ! WORDS_BIGENDIAN +/* memcmp_bytes -- Compare A and B bytewise in the byte order of the machine. + A and B are known to be different. + This is needed only on little-endian machines. */ +#ifdef __GNUC__ +__inline +#endif +static int +memcmp_bytes (a, b) + op_t a, b; +{ + long int srcp1 = (long int) &a; + long int srcp2 = (long int) &b; + op_t a0, b0; + + do + { + a0 = ((byte *) srcp1)[0]; + b0 = ((byte *) srcp2)[0]; + srcp1 += 1; + srcp2 += 1; + } + while (a0 == b0); + return a0 - b0; +} +#endif + +/* memcmp_common_alignment -- Compare blocks at SRCP1 and SRCP2 with LEN `op_t' + objects (not LEN bytes!). Both SRCP1 and SRCP2 should be aligned for + memory operations on `op_t's. */ +#ifdef __GNUC__ +__inline +#endif +static int +memcmp_common_alignment (srcp1, srcp2, len) + long int srcp1; + long int srcp2; + size_t len; +{ + op_t a0, a1; + op_t b0, b1; + + switch (len % 4) + { + case 2: + a0 = ((op_t *) srcp1)[0]; + b0 = ((op_t *) srcp2)[0]; + srcp1 -= 2 * OPSIZ; + srcp2 -= 2 * OPSIZ; + len += 2; + goto do1; + case 3: + a1 = ((op_t *) srcp1)[0]; + b1 = ((op_t *) srcp2)[0]; + srcp1 -= OPSIZ; + srcp2 -= OPSIZ; + len += 1; + goto do2; + case 0: + if (OP_T_THRES <= 3 * OPSIZ && len == 0) + return 0; + a0 = ((op_t *) srcp1)[0]; + b0 = ((op_t *) srcp2)[0]; + goto do3; + case 1: + a1 = ((op_t *) srcp1)[0]; + b1 = ((op_t *) srcp2)[0]; + srcp1 += OPSIZ; + srcp2 += OPSIZ; + len -= 1; + if (OP_T_THRES <= 3 * OPSIZ && len == 0) + goto do0; + /* Fall through. */ + } + + do + { + a0 = ((op_t *) srcp1)[0]; + b0 = ((op_t *) srcp2)[0]; + if (a1 != b1) + return CMP_LT_OR_GT (a1, b1); + + do3: + a1 = ((op_t *) srcp1)[1]; + b1 = ((op_t *) srcp2)[1]; + if (a0 != b0) + return CMP_LT_OR_GT (a0, b0); + + do2: + a0 = ((op_t *) srcp1)[2]; + b0 = ((op_t *) srcp2)[2]; + if (a1 != b1) + return CMP_LT_OR_GT (a1, b1); + + do1: + a1 = ((op_t *) srcp1)[3]; + b1 = ((op_t *) srcp2)[3]; + if (a0 != b0) + return CMP_LT_OR_GT (a0, b0); + + srcp1 += 4 * OPSIZ; + srcp2 += 4 * OPSIZ; + len -= 4; + } + while (len != 0); + + /* This is the right position for do0. Please don't move + it into the loop. */ + do0: + if (a1 != b1) + return CMP_LT_OR_GT (a1, b1); + return 0; +} + +/* memcmp_not_common_alignment -- Compare blocks at SRCP1 and SRCP2 with LEN + `op_t' objects (not LEN bytes!). SRCP2 should be aligned for memory + operations on `op_t', but SRCP1 *should be unaligned*. */ +#ifdef __GNUC__ +__inline +#endif +static int +memcmp_not_common_alignment (srcp1, srcp2, len) + long int srcp1; + long int srcp2; + size_t len; +{ + op_t a0, a1, a2, a3; + op_t b0, b1, b2, b3; + op_t x; + int shl, shr; + + /* Calculate how to shift a word read at the memory operation + aligned srcp1 to make it aligned for comparison. */ + + shl = 8 * (srcp1 % OPSIZ); + shr = 8 * OPSIZ - shl; + + /* Make SRCP1 aligned by rounding it down to the beginning of the `op_t' + it points in the middle of. */ + srcp1 &= -OPSIZ; + + switch (len % 4) + { + case 2: + a1 = ((op_t *) srcp1)[0]; + a2 = ((op_t *) srcp1)[1]; + b2 = ((op_t *) srcp2)[0]; + srcp1 -= 1 * OPSIZ; + srcp2 -= 2 * OPSIZ; + len += 2; + goto do1; + case 3: + a0 = ((op_t *) srcp1)[0]; + a1 = ((op_t *) srcp1)[1]; + b1 = ((op_t *) srcp2)[0]; + srcp2 -= 1 * OPSIZ; + len += 1; + goto do2; + case 0: + if (OP_T_THRES <= 3 * OPSIZ && len == 0) + return 0; + a3 = ((op_t *) srcp1)[0]; + a0 = ((op_t *) srcp1)[1]; + b0 = ((op_t *) srcp2)[0]; + srcp1 += 1 * OPSIZ; + goto do3; + case 1: + a2 = ((op_t *) srcp1)[0]; + a3 = ((op_t *) srcp1)[1]; + b3 = ((op_t *) srcp2)[0]; + srcp1 += 2 * OPSIZ; + srcp2 += 1 * OPSIZ; + len -= 1; + if (OP_T_THRES <= 3 * OPSIZ && len == 0) + goto do0; + /* Fall through. */ + } + + do + { + a0 = ((op_t *) srcp1)[0]; + b0 = ((op_t *) srcp2)[0]; + x = MERGE(a2, shl, a3, shr); + if (x != b3) + return CMP_LT_OR_GT (x, b3); + + do3: + a1 = ((op_t *) srcp1)[1]; + b1 = ((op_t *) srcp2)[1]; + x = MERGE(a3, shl, a0, shr); + if (x != b0) + return CMP_LT_OR_GT (x, b0); + + do2: + a2 = ((op_t *) srcp1)[2]; + b2 = ((op_t *) srcp2)[2]; + x = MERGE(a0, shl, a1, shr); + if (x != b1) + return CMP_LT_OR_GT (x, b1); + + do1: + a3 = ((op_t *) srcp1)[3]; + b3 = ((op_t *) srcp2)[3]; + x = MERGE(a1, shl, a2, shr); + if (x != b2) + return CMP_LT_OR_GT (x, b2); + + srcp1 += 4 * OPSIZ; + srcp2 += 4 * OPSIZ; + len -= 4; + } + while (len != 0); + + /* This is the right position for do0. Please don't move + it into the loop. */ + do0: + x = MERGE(a2, shl, a3, shr); + if (x != b3) + return CMP_LT_OR_GT (x, b3); + return 0; +} + +int +irc_memcmp (s1, s2, len) + const __ptr_t s1; + const __ptr_t s2; + size_t len; +{ + op_t a0; + op_t b0; + long int srcp1 = (long int) s1; + long int srcp2 = (long int) s2; + op_t res; + + if (len >= OP_T_THRES) + { + /* There are at least some bytes to compare. No need to test + for LEN == 0 in this alignment loop. */ + while (srcp2 % OPSIZ != 0) + { + a0 = ((byte *) srcp1)[0]; + b0 = ((byte *) srcp2)[0]; + srcp1 += 1; + srcp2 += 1; + res = a0 - b0; + if (res != 0) + return res; + len -= 1; + } + + /* SRCP2 is now aligned for memory operations on `op_t'. + SRCP1 alignment determines if we can do a simple, + aligned compare or need to shuffle bits. */ + + if (srcp1 % OPSIZ == 0) + res = memcmp_common_alignment (srcp1, srcp2, len / OPSIZ); + else + res = memcmp_not_common_alignment (srcp1, srcp2, len / OPSIZ); + if (res != 0) + return res; + + /* Number of bytes remaining in the interval [0..OPSIZ-1]. */ + srcp1 += len & -OPSIZ; + srcp2 += len & -OPSIZ; + len %= OPSIZ; + } + + /* There are just a few bytes to compare. Use byte memory operations. */ + while (len != 0) + { + a0 = ((byte *) srcp1)[0]; + b0 = ((byte *) srcp2)[0]; + srcp1 += 1; + srcp2 += 1; + res = a0 - b0; + if (res != 0) + return res; + len -= 1; + } + + return 0; +} +#endif /* HAVE_MEMCMP && MEMCMP_BROKEN */ diff --git a/common/support_def.h b/common/support_def.h new file mode 100644 index 0000000..500e88f --- /dev/null +++ b/common/support_def.h @@ -0,0 +1,28 @@ +/************************************************************************ + * IRC - Internet Relay Chat, common/support_def.h + * Copyright (C) 1991, 1993, 1995 Free Software Foundation, Inc. + * Contributed by Torbjorn Granlund (tege@sics.se). + * + * 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. + */ + +#ifdef __ptr_t +#undef __ptr_t +#endif +#if defined (__STDC__) && __STDC__ +#define __ptr_t void * +#else +#define __ptr_t char * +#endif diff --git a/common/support_ext.h b/common/support_ext.h new file mode 100644 index 0000000..6e81d18 --- /dev/null +++ b/common/support_ext.h @@ -0,0 +1,80 @@ +/************************************************************************ + * IRC - Internet Relay Chat, common/support_ext.h + * Copyright (C) 1997 Alain Nissen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* This file contains external definitions for global variables and functions + defined in common/support.c. + */ + +/* External definitions for global functions. + */ +#ifndef SUPPORT_C +#define EXTERN extern +#else /* SUPPORT_C */ +#define EXTERN +#endif /* SUPPORT_C */ +EXTERN char *mystrdup __P((char *s)); +#if ! HAVE_STRTOKEN +EXTERN char *strtoken __P((char **save, char *str, char *fs)); +#endif /* HAVE_STRTOKEN */ +#if ! HAVE_STRTOK +EXTERN char *strtok __P((char *str, char *fs)); +#endif /* HAVE_STRTOK */ +#if ! HAVE_STRERROR +EXTERN char *strerror __P((int err_no)); +#endif /* HAVE_STRERROR */ +EXTERN char *myctime __P((time_t value)); +EXTERN char *mybasename __P((char *)); +#ifdef INET6 +EXTERN char *inetntop(int af, const void *in, char *local_dummy, size_t the_size); +#endif +#if ! HAVE_INET_NTOA +EXTERN char *inetntoa __P((char *in)); +#endif /* HAVE_INET_NTOA */ +#if ! HAVE_INET_NETOF +EXTERN int inetnetof __P((struct in_addr in)); +#endif /* HAVE_INET_NETOF */ +#if ! HAVE_INET_ADDR +EXTERN u_long inetaddr __P((register const char *cp)); +#endif /* HAVE_INET_ADDR */ +#if ! HAVE_INET_ATON +EXTERN int inetaton __P((register const char *cp, struct in_addr *addr)); +#endif /* HAVE_INET_ATON */ +#if defined(DEBUGMODE) && !defined(CLIENT_COMPILE) +EXTERN void dumpcore (); +#endif /* DEBUGMODE && !CLIENT_COMPILE */ +#if defined(DEBUGMODE) && !defined(CLIENT_COMPILE) && defined(DO_DEBUG_MALLOC) +EXTERN char *MyMalloc __P((size_t x)); +EXTERN char *MyRealloc __P((char *x, size_t y)); +EXTERN void MyFree __P((char *x)); +#else /* DEBUGMODE && !CLIENT_COMPILE && !DO_DEBUG_MALLOC */ +EXTERN char *MyMalloc __P((size_t x)); +EXTERN char *MyRealloc __P((char *x, size_t y)); +#endif /* DEBUGMODE && !CLIENT_COMPILE && !DO_DEBUG_MALLOC */ +#if ! USE_STDARG +EXTERN int irc_sprintf(); +#endif /* USE_STDARG */ +EXTERN int dgets __P((int fd, char *buf, int num)); +EXTERN char *make_version(); +#if SOLARIS_2_3 +EXTERN struct hostent *solaris_gethostbyname __P((const char *name)); +#endif /* SOLARIS_2_3 */ +#if HAVE_MEMCMP && MEMCMP_BROKEN +EXTERN int irc_memcmp __P((const __ptr_t s1, const __ptr_t s2, size_t len)); +#endif /* HAVE_MEMCMP && MEMCMP_BROKEN */ +#undef EXTERN diff --git a/configure b/configure new file mode 100755 index 0000000..6ea0218 --- /dev/null +++ b/configure @@ -0,0 +1,50 @@ +#! /bin/sh + +quick_fwd= +for arg +do + case "$arg" in + -help | --help | --hel | --he) + quick_fwd=yes + break ;; + -version | --version | --versio | --versi | --vers) + quick_fwd=yes + break ;; + *) + break ;; + esac +done +if test "x$quick_fwd" = xyes +then + support/configure $* +else + echo "retrieving the system name, type and OS release..." + rev=`support/config.guess` + if test "${rev}" # test for no output + then + echo " your system seems to be ${rev}." + if test ! -d "${rev}" + then + echo "creating directory ${rev}..." + mkdir "${rev}" + fi + cd "${rev}" + echo "now working in directory ${rev}..." + cp -p ../support/configure . + if test ! -f config.h + then + echo "copying config.h from config.h.dist..." + cp -p ../support/config.h.dist config.h + fi + ./configure $* + if test $? = 0 + then + echo "Have you read doc/README? (I hope so)" + echo "Next cd ${rev}, edit \"config.h\" and \"Makefile\"," + echo "run \"make all\" to build and \"make install\" to install." + fi + else + echo Failed to determine your host type, giving up. + echo Perhaps you should specify it manually. + fi +fi diff --git a/contrib/README b/contrib/README new file mode 100644 index 0000000..7d62989 --- /dev/null +++ b/contrib/README @@ -0,0 +1,21 @@ +$Id: README,v 1.6 1999/03/13 23:06:15 kalt Exp $ + +This directory contains ircd related contributions. Most of them fall + in one of the following categories: + * small side utility + * code sample + * service + +Each contribution lives in its own directory under contrib/ and has a +README file. For those which need to be compiled, this can be done in +the same directory as you compiled irc and/or ircd. + +If you want to submit a package for this directory, see the RULES file. + +--- + +mkpasswd utility to crypt a password. +ircdwatch utility to keep ircd running (eventually restarting it). +tkserv stupid toy to manage "temporary" klines. +mod_passwd example of DSM module for iauth +antispoof.diff diff file to add extra code to ircd to prevent TCP spoofing diff --git a/contrib/RULES b/contrib/RULES new file mode 100644 index 0000000..f3de2a1 --- /dev/null +++ b/contrib/RULES @@ -0,0 +1,24 @@ +$Id: RULES,v 1.2 1998/11/09 20:07:12 kalt Exp $ + +This file describes how to prepare a package for inclusion +in the contrib/ directory. The goal is to have a consistent +setup for all contributions, making it easy to install any +of them. + +* each package must have a README file (at least) explaining + what it is about. +* a man page would be nice ;-) + +* packages are stored in contrib/ + +* C programs: + * If possible, use the same coding style as in the + rest of the package. + * They need to be portable + * They should use "setup.h" or "os.h" + * If needed, they may have a *.h file generated by configure + * They are to be compiled from within the same + directory as irc/ircd, using the same Makefile + + +* questions, submissions should be sent to ircd-dev@irc.org diff --git a/contrib/antispoof.README b/contrib/antispoof.README new file mode 100644 index 0000000..fd1d5a7 --- /dev/null +++ b/contrib/antispoof.README @@ -0,0 +1,56 @@ +The nospoof patch was adapted from the nospoof5 patch in use on Undernet +servers. It should NOT be needed unless you're running ircd on a really +old OS which doesn't have a patch against TCP spoofing. Note that this +patch should be applied BEFORE running ./configure -- this is very +important, and the usual cause of any problems encountered. + +When a client connects to the server, they are sent a PING with a random +number (please do not confuse this with a CTCP PING -- they're very +different things). Until the client responds with a PONG and the correct +random number, it is not registered with the server and cannot do +anything. + +Please note that this does break the RFC. However, it has been tested +with most popular clients and is in common use on large IRC networks +currently. The only reported client to have problems is Homer (for +the Macintosh). + +To cater for possibly broken clients, a message is also sent to clients +on connect of the form: + +*** If your client freezes here, type /QUOTE PONG 12345678 or /PONG 12345678 + +Because of this, it is a good idea to increase the allowed timeout on +connections since the user might have to manually PONG the server with +the ugly number (although hopefully they only need to cut'n'paste). + +If the client PONGs with the wrong number, another message is sent to +the client directing the user what to type. In addition, if the +connection does end up timing out due to no PONG, a message is sent to +the user explaining the client may not be compatible, and lists where +compatible clients for all the major platforms can be found. + +The random number sequence is based on an md5 series. I didn't write it. +Someone else did. It's included because many have a dud random() in their +libc (this applies to more people than you think). It is seeded on a +#define value in config.h - YOU MUST CHANGE THIS FROM THE DEFAULT OR YOU +CAN STILL BE SPOOFED. If you still find that you get spoofed, try +changing this value again and recompiling. + +KNOWN BUGS: + + - There is a known bug whereby the host provided by the client's + USER sequence is not checked for validity until after the PONG + reply (and registration takes place). This allows a form of + "spoofing" to take place, with the client showing under /whois + lookups with a fake hostname. At this stage the client can't + actually issue commands to the server though, and the hostmask + is corrected to what it should be upon the PONG being received + (and the client properly registered). + + - The random number generator isn't 64-bit clean. On 64-bit + machines, a 64-bit random number is generated, but I'm not + convinced all 64-bits are random. At least 32 bits are + however, so this isn't a problem. + + - Andrew (earthpig@yoyo.cc.monash.edu.au) diff --git a/contrib/antispoof.diff b/contrib/antispoof.diff new file mode 100644 index 0000000..b02832f --- /dev/null +++ b/contrib/antispoof.diff @@ -0,0 +1,484 @@ +diff -urN irc-cvs/common/numeric_def.h irc-cvs-nospoof/common/numeric_def.h +--- irc-cvs/common/numeric_def.h Wed Jan 20 12:28:46 1999 ++++ irc-cvs-nospoof/common/numeric_def.h Tue Mar 16 12:45:56 1999 +@@ -198,6 +198,10 @@ + #define ERR_UMODEUNKNOWNFLAG 501 + #define ERR_USERSDONTMATCH 502 + ++#if defined(NOSPOOF) ++#define ERR_BADPING 513 ++#endif ++ + /* + * Numberic replies from server commands. + * These are currently in the range 200-399. +diff -urN irc-cvs/common/parse.c irc-cvs-nospoof/common/parse.c +--- irc-cvs/common/parse.c Tue Dec 29 02:44:57 1998 ++++ irc-cvs-nospoof/common/parse.c Tue Mar 16 12:45:56 1999 +@@ -56,7 +56,11 @@ + { MSG_INVITE, m_invite, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L}, + { MSG_WALLOPS, m_wallops, MAXPARA, MSG_LAG|MSG_REG|MSG_NOU, 0, 0, 0L}, + { MSG_PING, m_ping, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L}, ++#if defined(NOSPOOF) ++ { MSG_PONG, m_pong, MAXPARA, MSG_LAG, 0, 0, 0L}, ++#else + { MSG_PONG, m_pong, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L}, ++#endif + { MSG_ERROR, m_error, MAXPARA, MSG_LAG|MSG_REG|MSG_NOU, 0, 0, 0L}, + #ifdef OPER_KILL + { MSG_KILL, m_kill, MAXPARA, MSG_LAG|MSG_REG|MSG_OP|MSG_LOP, 0,0, 0L}, +diff -urN irc-cvs/common/send.c irc-cvs-nospoof/common/send.c +--- irc-cvs/common/send.c Fri Feb 5 10:26:35 1999 ++++ irc-cvs-nospoof/common/send.c Tue Mar 16 12:45:56 1999 +@@ -392,6 +392,9 @@ + NULL, + # endif + 0, {0, 0, NULL }, {0, 0, NULL }, ++#if defined(NOSPOOF) ++ -1, ++#endif + 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, 0, NULL, 0 + # if defined(__STDC__) /* hack around union{} initialization -Vesa */ + ,{0}, NULL, "", "" +diff -urN irc-cvs/common/struct_def.h irc-cvs-nospoof/common/struct_def.h +--- irc-cvs/common/struct_def.h Sun Mar 14 11:59:54 1999 ++++ irc-cvs-nospoof/common/struct_def.h Tue Mar 16 12:45:56 1999 +@@ -432,6 +432,9 @@ + short lastsq; /* # of 2k blocks when sendqueued called last*/ + dbuf sendQ; /* Outgoing message queue--if socket full */ + dbuf recvQ; /* Hold for data incoming yet to be parsed */ ++#if defined(NOSPOOF) ++ u_long cookie; /* Random cookie local clients must PONG */ ++#endif + long sendM; /* Statistics: protocol messages send */ + long sendK; /* Statistics: total k-bytes send */ + long receiveM; /* Statistics: protocol messages received */ +diff -urN irc-cvs/ircd/ircd.c irc-cvs-nospoof/ircd/ircd.c +--- irc-cvs/ircd/ircd.c Sun Mar 14 11:59:58 1999 ++++ irc-cvs-nospoof/ircd/ircd.c Tue Mar 16 12:45:56 1999 +@@ -493,6 +493,22 @@ + else + { + cptr->exitc = EXITC_PING; ++#if defined(NOSPOOF) ++ if((!IsRegistered(cptr)) && (cptr->name) && ++ (cptr->username)) ++ { ++ sendto_one(cptr, ++ ":%s %d %s :Your client may not be compatible with this server.", ++ me.name, ERR_BADPING, cptr->name); ++ /* Someone suggest a better ++ * place? :) - Earthpig ++ */ ++ sendto_one(cptr, ++ ":%s %d %s :Compatible clients are available at " ++ "ftp://yoyo.cc.monash.edu.au/pub/irc/clients/", ++ me.name, ERR_BADPING, cptr->name); ++ } ++#endif + (void)exit_client(cptr, cptr, &me, + "Ping timeout"); + } +diff -urN irc-cvs/ircd/list.c irc-cvs-nospoof/ircd/list.c +--- irc-cvs/ircd/list.c Tue Dec 29 02:44:57 1998 ++++ irc-cvs-nospoof/ircd/list.c Tue Mar 16 12:45:56 1999 +@@ -146,6 +146,9 @@ + if (size == CLIENT_LOCAL_SIZE) + { + cptr->since = cptr->lasttime = cptr->firsttime = timeofday; ++#if defined(NOSPOOF) ++ cptr->cookie = 0; ++#endif + cptr->confs = NULL; + cptr->sockhost[0] = '\0'; + cptr->buffer[0] = '\0'; +diff -urN irc-cvs/ircd/random.c irc-cvs-nospoof/ircd/random.c +--- irc-cvs/ircd/random.c Thu Jan 1 10:00:00 1970 ++++ irc-cvs-nospoof/ircd/random.c Tue Mar 16 12:45:56 1999 +@@ -0,0 +1,162 @@ ++/************************************************************************ ++ * IRC - Internet Relay Chat, ircd/random.c ++ * ++ * 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include "os.h" ++#include "s_defines.h" ++ ++#ifdef NOSPOOF ++ ++char localkey[8] = RANDOM_SEED; ++ ++/* ++ * MD5 transform algorithm, taken from code written by Colin Plumb, ++ * and put into the public domain ++ * ++ * Kev: Taken from Ted T'so's /dev/random random.c code and modified to ++ * be slightly simpler. That code is released under a BSD-style copyright ++ * OR under the terms of the GNU Public License, which should be included ++ * at the top of this source file. ++ * ++ * record: Cleaned up to work with ircd. RANDOM_TOKEN is defined in ++ * setup.h by the make script; if people start to "guess" your cookies, ++ * consider recompiling your server with a different random token. ++ */ ++ ++/* The four core functions - F1 is optimized somewhat */ ++ ++#define F1(x, y, z) (z ^ (x & (y ^ z))) ++#define F2(x, y, z) F1(z, x, y) ++#define F3(x, y, z) (x ^ y ^ z) ++#define F4(x, y, z) (y ^ (x | ~z)) ++ ++/* This is the central step in the MD5 algorithm. */ ++#define MD5STEP(f, w, x, y, z, data, s) \ ++ ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) ++ ++/* ++ * The core of the MD5 algorithm, this alters an existing MD5 hash to ++ * reflect the addition of 16 longwords of new data. MD5Update blocks ++ * the data and converts bytes into longwords for this routine. ++ * ++ * original comment left in; this used to be called MD5Transform and took ++ * two arguments; I've internalized those arguments, creating the character ++ * array "localkey," which should contain 8 bytes of data. The function also ++ * originally returned nothing; now it returns an unsigned long that is the ++ * random number. It appears to be reallyrandom, so... -Kev ++ * ++ * I don't really know what this does. I tried to figure it out and got ++ * a headache. If you know what's good for you, you'll leave this stuff ++ * for the smart people and do something else. -record ++ */ ++unsigned long ircrandom(void) ++{ ++ unsigned long a, b, c, d; ++ unsigned char in[16]; ++ struct timeval tv; ++ ++ (void)gettimeofday(&tv, NULL); ++ ++ (void)memcpy((void *)in, (void *)localkey, 8); ++ (void)memcpy((void *)(in+8), (void *)&tv.tv_sec, 4); ++ (void)memcpy((void *)(in+12), (void *)&tv.tv_usec, 4); ++ ++ a = 0x67452301; ++ b = 0xefcdab89; ++ c = 0x98badcfe; ++ d = 0x10325476; ++ ++ MD5STEP(F1, a, b, c, d, (long)in[ 0]+0xd76aa478, 7); ++ MD5STEP(F1, d, a, b, c, (long)in[ 1]+0xe8c7b756, 12); ++ MD5STEP(F1, c, d, a, b, (long)in[ 2]+0x242070db, 17); ++ MD5STEP(F1, b, c, d, a, (long)in[ 3]+0xc1bdceee, 22); ++ MD5STEP(F1, a, b, c, d, (long)in[ 4]+0xf57c0faf, 7); ++ MD5STEP(F1, d, a, b, c, (long)in[ 5]+0x4787c62a, 12); ++ MD5STEP(F1, c, d, a, b, (long)in[ 6]+0xa8304613, 17); ++ MD5STEP(F1, b, c, d, a, (long)in[ 7]+0xfd469501, 22); ++ MD5STEP(F1, a, b, c, d, (long)in[ 8]+0x698098d8, 7); ++ MD5STEP(F1, d, a, b, c, (long)in[ 9]+0x8b44f7af, 12); ++ MD5STEP(F1, c, d, a, b, (long)in[10]+0xffff5bb1, 17); ++ MD5STEP(F1, b, c, d, a, (long)in[11]+0x895cd7be, 22); ++ MD5STEP(F1, a, b, c, d, (long)in[12]+0x6b901122, 7); ++ MD5STEP(F1, d, a, b, c, (long)in[13]+0xfd987193, 12); ++ MD5STEP(F1, c, d, a, b, (long)in[14]+0xa679438e, 17); ++ MD5STEP(F1, b, c, d, a, (long)in[15]+0x49b40821, 22); ++ ++ MD5STEP(F2, a, b, c, d, (long)in[ 1]+0xf61e2562, 5); ++ MD5STEP(F2, d, a, b, c, (long)in[ 6]+0xc040b340, 9); ++ MD5STEP(F2, c, d, a, b, (long)in[11]+0x265e5a51, 14); ++ MD5STEP(F2, b, c, d, a, (long)in[ 0]+0xe9b6c7aa, 20); ++ MD5STEP(F2, a, b, c, d, (long)in[ 5]+0xd62f105d, 5); ++ MD5STEP(F2, d, a, b, c, (long)in[10]+0x02441453, 9); ++ MD5STEP(F2, c, d, a, b, (long)in[15]+0xd8a1e681, 14); ++ MD5STEP(F2, b, c, d, a, (long)in[ 4]+0xe7d3fbc8, 20); ++ MD5STEP(F2, a, b, c, d, (long)in[ 9]+0x21e1cde6, 5); ++ MD5STEP(F2, d, a, b, c, (long)in[14]+0xc33707d6, 9); ++ MD5STEP(F2, c, d, a, b, (long)in[ 3]+0xf4d50d87, 14); ++ MD5STEP(F2, b, c, d, a, (long)in[ 8]+0x455a14ed, 20); ++ MD5STEP(F2, a, b, c, d, (long)in[13]+0xa9e3e905, 5); ++ MD5STEP(F2, d, a, b, c, (long)in[ 2]+0xfcefa3f8, 9); ++ MD5STEP(F2, c, d, a, b, (long)in[ 7]+0x676f02d9, 14); ++ MD5STEP(F2, b, c, d, a, (long)in[12]+0x8d2a4c8a, 20); ++ ++ MD5STEP(F3, a, b, c, d, (long)in[ 5]+0xfffa3942, 4); ++ MD5STEP(F3, d, a, b, c, (long)in[ 8]+0x8771f681, 11); ++ MD5STEP(F3, c, d, a, b, (long)in[11]+0x6d9d6122, 16); ++ MD5STEP(F3, b, c, d, a, (long)in[14]+0xfde5380c, 23); ++ MD5STEP(F3, a, b, c, d, (long)in[ 1]+0xa4beea44, 4); ++ MD5STEP(F3, d, a, b, c, (long)in[ 4]+0x4bdecfa9, 11); ++ MD5STEP(F3, c, d, a, b, (long)in[ 7]+0xf6bb4b60, 16); ++ MD5STEP(F3, b, c, d, a, (long)in[10]+0xbebfbc70, 23); ++ MD5STEP(F3, a, b, c, d, (long)in[13]+0x289b7ec6, 4); ++ MD5STEP(F3, d, a, b, c, (long)in[ 0]+0xeaa127fa, 11); ++ MD5STEP(F3, c, d, a, b, (long)in[ 3]+0xd4ef3085, 16); ++ MD5STEP(F3, b, c, d, a, (long)in[ 6]+0x04881d05, 23); ++ MD5STEP(F3, a, b, c, d, (long)in[ 9]+0xd9d4d039, 4); ++ MD5STEP(F3, d, a, b, c, (long)in[12]+0xe6db99e5, 11); ++ MD5STEP(F3, c, d, a, b, (long)in[15]+0x1fa27cf8, 16); ++ MD5STEP(F3, b, c, d, a, (long)in[ 2]+0xc4ac5665, 23); ++ ++ MD5STEP(F4, a, b, c, d, (long)in[ 0]+0xf4292244, 6); ++ MD5STEP(F4, d, a, b, c, (long)in[ 7]+0x432aff97, 10); ++ MD5STEP(F4, c, d, a, b, (long)in[14]+0xab9423a7, 15); ++ MD5STEP(F4, b, c, d, a, (long)in[ 5]+0xfc93a039, 21); ++ MD5STEP(F4, a, b, c, d, (long)in[12]+0x655b59c3, 6); ++ MD5STEP(F4, d, a, b, c, (long)in[ 3]+0x8f0ccc92, 10); ++ MD5STEP(F4, c, d, a, b, (long)in[10]+0xffeff47d, 15); ++ MD5STEP(F4, b, c, d, a, (long)in[ 1]+0x85845dd1, 21); ++ MD5STEP(F4, a, b, c, d, (long)in[ 8]+0x6fa87e4f, 6); ++ MD5STEP(F4, d, a, b, c, (long)in[15]+0xfe2ce6e0, 10); ++ MD5STEP(F4, c, d, a, b, (long)in[ 6]+0xa3014314, 15); ++ MD5STEP(F4, b, c, d, a, (long)in[13]+0x4e0811a1, 21); ++ MD5STEP(F4, a, b, c, d, (long)in[ 4]+0xf7537e82, 6); ++ MD5STEP(F4, d, a, b, c, (long)in[11]+0xbd3af235, 10); ++ MD5STEP(F4, c, d, a, b, (long)in[ 2]+0x2ad7d2bb, 15); ++ MD5STEP(F4, b, c, d, a, (long)in[ 9]+0xeb86d391, 21); ++ ++ /* ++ * we have 4 unsigned longs generated by the above sequence; this scrambles ++ * them together so that if there is any pattern, it will be obscured. ++ */ ++ return (a ^ b ^ c ^ d); ++} ++ ++#endif +diff -urN irc-cvs/ircd/s_debug.c irc-cvs-nospoof/ircd/s_debug.c +--- irc-cvs/ircd/s_debug.c Fri Feb 5 10:44:16 1999 ++++ irc-cvs-nospoof/ircd/s_debug.c Tue Mar 16 12:45:56 1999 +@@ -148,6 +148,9 @@ + #ifdef INET6 + '6', + #endif ++#if defined(NOSPOOF) ++'*', ++#endif + '\0'}; + + #ifdef DEBUGMODE +@@ -344,7 +347,7 @@ + sendto_one(cptr, ":%s %d %s :BS:%d MXR:%d MXB:%d MXBL:%d PY:%d", + ME, RPL_STATSDEFINE, nick, BUFSIZE, MAXRECIPIENTS, MAXBANS, + MAXBANLENGTH, MAXPENALTY); +- sendto_one(cptr, ":%s %d %s :ZL:%d CM:%d CP:%d", ++ sendto_one(cptr, ":%s %d %s :ZL:%d CM:%d CP:%d NS:%s", + ME, RPL_STATSDEFINE, nick, + #ifdef ZIP_LINKS + ZIP_LEVEL, +@@ -352,9 +355,14 @@ + -1, + #endif + #ifdef CLONE_CHECK +- CLONE_MAX, CLONE_PERIOD ++ CLONE_MAX, CLONE_PERIOD, ++#else ++ -1, -1, ++#endif ++#if defined(NOSPOOF) ++ "yes" + #else +- -1, -1 ++ "no" + #endif + ); + } +diff -urN irc-cvs/ircd/s_err.c irc-cvs-nospoof/ircd/s_err.c +--- irc-cvs/ircd/s_err.c Sun Feb 28 02:45:29 1999 ++++ irc-cvs-nospoof/ircd/s_err.c Tue Mar 16 12:45:56 1999 +@@ -162,6 +162,19 @@ + { 0, (char *)NULL }, + /* 501 */ { ERR_UMODEUNKNOWNFLAG, ":Unknown MODE flag" }, + /* 502 */ { ERR_USERSDONTMATCH, ":Can't change mode for other users" }, ++#if defined(NOSPOOF) ++ { 0, (char *)NULL }, ++ { 0, (char *)NULL }, ++ { 0, (char *)NULL }, ++ { 0, (char *)NULL }, ++ { 0, (char *)NULL }, ++ { 0, (char *)NULL }, ++ { 0, (char *)NULL }, ++ { 0, (char *)NULL }, ++ { 0, (char *)NULL }, ++ { 0, (char *)NULL }, ++/* 513 */ { ERR_BADPING, (char *)NULL }, ++#endif + { 0, (char *)NULL } + }; + +diff -urN irc-cvs/ircd/s_user.c irc-cvs-nospoof/ircd/s_user.c +--- irc-cvs/ircd/s_user.c Tue Mar 16 12:32:51 1999 ++++ irc-cvs-nospoof/ircd/s_user.c Tue Mar 16 12:51:41 1999 +@@ -335,9 +335,9 @@ + + /* + ** register_user +-** This function is called when both NICK and USER messages +-** have been accepted for the client, in whatever order. Only +-** after this the USER message is propagated. ++** This function is called when both NICK and USER [and maybe PONG] ++** messages have been accepted for the client, in whatever order. ++** Only after this the USER message is propagated. + ** + ** NICK's must be propagated at once when received, although + ** it would be better to delay them too until full info is +@@ -1007,9 +1007,30 @@ + + /* This had to be copied here to avoid problems.. */ + (void)strcpy(sptr->name, nick); ++#if defined(NOSPOOF) ++ /* If the client hasn't gotten a cookie-ping yet, ++ choose a cookie and send it. -record!jegelhof@cloud9.net */ ++ ++ if (!sptr->cookie) ++ { ++ while((!sptr->cookie) || (sptr->cookie==-1)) ++ sptr->cookie=(ircrandom()); ++ sendto_one(cptr, "PING :%lu", sptr->cookie); ++ sendto_one(sptr, ++ ":%s %d %s :If your client freezes here, type /QUOTE PONG %lu " ++ "or /PONG %lu ", ++ me.name, ERR_BADPING, sptr->name, ++ sptr->cookie, sptr->cookie); ++ } ++ ++ if ((sptr->user) && (sptr->cookie==-1)) ++ { ++#else + if (sptr->user) ++#endif + /* +- ** USER already received, now we have NICK. ++ ** USER [and possibly PONG] already received, ++ ** now we have NICK. + ** *NOTE* For servers "NICK" *must* precede the + ** user message (giving USER before NICK is possible + ** only for local client connection!). register_user +@@ -1020,6 +1041,9 @@ + sptr->user->username) + == FLUSH_BUFFER) + return FLUSH_BUFFER; ++#if defined(NOSPOOF) ++ } ++#endif + } + /* + ** Finally set new nick name. +@@ -1849,7 +1873,12 @@ + if (strlen(realname) > REALLEN) + realname[REALLEN] = '\0'; + sptr->info = mystrdup(realname); +- if (sptr->name[0]) /* NICK already received, now we have USER... */ ++ if ((sptr->name[0]) ++#if defined(NOSPOOF) ++ && (!MyConnect(sptr) || (sptr->cookie==-1)) ++#endif ++ ) ++ /* NICK already received, now we have USER... */ + { + if ((parc == 6) && IsServer(cptr)) /* internal m_user() */ + { +@@ -2222,7 +2251,32 @@ + aClient *acptr; + char *origin, *destination; + +- if (parc < 2 || *parv[1] == '\0') ++#if defined(NOSPOOF) ++ /* Check to see if this is a PONG :cookie reply from an ++ unregistered user. If so, process it. -record */ ++ ++ if((!IsRegistered(sptr)) && (sptr->cookie!=0) && ++ (sptr->cookie!=-1) && (parc>1)) ++ { ++ if(strtoul(parv[parc-1],NULL,10)==sptr->cookie) ++ { ++ sptr->cookie=-1; ++ if((sptr->user) && (sptr->name[0])) ++ /* NICK and USER OK */ ++ return register_user(cptr, sptr, sptr->name, ++ sptr->user->username); ++ } ++ else ++ sendto_one(sptr, ++ ":%s %d %s :To connect, type /QUOTE PONG %lu or /PONG %lu", ++ me.name, ERR_BADPING, sptr->name, ++ sptr->cookie, sptr->cookie); ++ ++ return 1; ++ } ++#endif ++ ++ if (parc < 2 || *parv[1] == '\0') + { + sendto_one(sptr, err_str(ERR_NOORIGIN, parv[0])); + return 1; +diff -urN irc-cvs/support/Makefile.in irc-cvs-nospoof/support/Makefile.in +--- irc-cvs/support/Makefile.in Fri Mar 12 20:06:00 1999 ++++ irc-cvs-nospoof/support/Makefile.in Tue Mar 16 12:47:37 1999 +@@ -153,7 +153,7 @@ + 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 random.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 \ +@@ -431,6 +431,9 @@ + + res_mkquery.o: ../ircd/res_mkquery.c setup.h config.h + $(CC) $(S_CFLAGS) -c -o $@ ../ircd/res_mkquery.c ++ ++random.o: ../ircd/random.c setup.h config.h ++ $(CC) $(S_CFLAGS) -c -o $@ ../ircd/random.c + + iauth.o: ../iauth/iauth.c config.h setup.h + $(CC) $(A_CFLAGS) -c -o $@ ../iauth/iauth.c +diff -urN irc-cvs/support/config.h.dist irc-cvs-nospoof/support/config.h.dist +--- irc-cvs/support/config.h.dist Mon Feb 22 10:41:32 1999 ++++ irc-cvs-nospoof/support/config.h.dist Tue Mar 16 12:45:57 1999 +@@ -374,6 +374,30 @@ + */ + #undef CLONE_CHECK + ++/* Define this to turn on code that enables a PING/PONG cookies sequence ++ * whenever a client connects. The purpose of this is to prevent IP ++ * spoofing (normally based on predicting TCP/IP sequence numbers). ++ * This breaks the RFC slightly, but so far only one (old) client has ++ * been encountered that breaks. There's a small overhead if you define ++ * it, but it's essential for older BSD-based (or any other) TCP/IP ++ * stacks with predictable sequence numbers. ++ */ ++ ++#undef NOSPOOF ++ ++/* Random number generator seed -- used for cookies if NOSPOOF is ++ * defined. ++ * ++ * Set this to an 8 character random text string. ++ * Do _NOT_ use the default text. ++ * If people are able to defeat the IP-spoofing protection on your ++ * server, please consider changing this value and recompiling. ++ */ ++ ++#if defined(NOSPOOF) ++#define RANDOM_SEED "ChangeMe" ++#endif ++ + /* 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 */ diff --git a/contrib/ircdwatch/README b/contrib/ircdwatch/README new file mode 100644 index 0000000..80653bd --- /dev/null +++ b/contrib/ircdwatch/README @@ -0,0 +1,56 @@ +$Id: README,v 1.5 1998/11/09 22:56:34 borud Exp $ + +DESCRIPTION +=========== + ircdwatch is a daemon that regularly checks to see if ircd is running. + if ircd should die or somehow stop running, ircdwatch will respawn the + ircd daemon. if desirable, ircdwatch can be configured to check if + the ircd configuration file is changed and send a SIGHUP to the ircd + daemon which then causes the daemon to reload the configuration + file. + + the ircdwatch program itself is also used as sort of a remote + control depending on what command line arguments you feed it. you + can use it to start ircd and stop ircd and ircdwatch. + +OPTIONS +======= + if you invoke ircdwatch without any command line arguments it will + either daemonize itself and become a daemon, or it will exit if it + detects that an ircdwatch daemon is already running. + + for using the ircdwatch program as a remote control the following + command line options are available: + + --kill + stop both ircdwatch and ircd + + --rest + stop ircdwatch but leave ircd running + + --help + list command line arguments + + +COMPILE TIME CONFIGURATION +========================== + you configure ircdwatch by editing config.h in the directory where + you build ircd. the configuration parameters available for + ircdwatch are those starting with the prefix "IRCDWATCH_". please + refer to the config.h file for more information on the parameter + settings. most of the defaults should be okay if you want to use + ircdwatch though. + + +ADMINISTRATIVIA +=============== + ircdwatch was written by Bjorn Borud and is + Copyright (C) 1998 Bjorn Borud + + the program is released under the GNU General Public License + + the current maintainer can be reached at: + + please report bugs to + improvements are welcome. + diff --git a/contrib/ircdwatch/ircdwatch.8 b/contrib/ircdwatch/ircdwatch.8 new file mode 100644 index 0000000..cc944b1 --- /dev/null +++ b/contrib/ircdwatch/ircdwatch.8 @@ -0,0 +1,50 @@ +.\" @(#)$Id: ircdwatch.8,v 1.1 1998/06/12 22:57:40 kalt Exp $ +.TH IRCDWATCH 8 "$Date: 1998/06/12 22:57:40 $" +.SH NAME +ircdwatch \- Daemon for monitoring ircd and ircd.conf +.SH SYNOPSIS +.hy 0 +.IP \fBircdwatch\fP +[ +.BI \-\-kill +] [ +.BI \-\-rest +] [ +.BI \-\-help +] +.SH DESCRIPTION +.LP +\fIircdwatch\fP is a daemon that periodically checks that the +\fIircd\fP daemon is running, restarting it of necessary. This +daemon can also be configured (at compile time) to check for +changes to the \fIircd\fP configuration file and make \fIircd\fP +reload its configuration file by sending it a SIGHUP signal. +.LP +Given command line arguments \fIircdwatch\fP will serve as a remote +control for stopping both \fIircdwatch\fP and \fIircd\fP or just +\fIircdwatch\fP. + +.SH OPTIONS +.TP +.B \-\-kill +Stop both \fIircd\fP and \fIircdwatch\fP +.TP +.B \-\-rest +Stop \fIircdwatch\fP but leave \fIircd\fP running +.TP +.B \-\-help +List command line arguments +.SH COPYRIGHT +Copyright (C) 1998 Bjorn Borud, +.LP +.RE +.SH FILES + "ircd.conf" + "ircd.pid" + "ircdwatch.pid" +.SH "SEE ALSO" +ircd(8) +.SH BUGS +There may be some portability issues. Report bugs to +.SH AUTHOR +Bjorn Borud, diff --git a/contrib/ircdwatch/ircdwatch.c b/contrib/ircdwatch/ircdwatch.c new file mode 100644 index 0000000..c384578 --- /dev/null +++ b/contrib/ircdwatch/ircdwatch.c @@ -0,0 +1,499 @@ +/* + * Copyright (C) 1998 Bjorn Borud + * + * 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: ircdwatch.c,v 1.3 1999/02/21 00:33:44 kalt Exp $"; +#endif + +#include +#include /* atol() */ +#include /* fork() exec() */ +#include +#include /* stat() */ +#include +#include +#include /* strncmp() */ +#include + +#include "os.h" +#include "config.h" + +/* + * Try and find the correct name to use with getrlimit() for setting + * the max. number of files allowed to be open by this process. + * (borrowed from ircd/s_bsd.c) + */ +#ifdef RLIMIT_FDMAX +# define RLIMIT_FD_MAX RLIMIT_FDMAX +#else +# ifdef RLIMIT_NOFILE +# define RLIMIT_FD_MAX RLIMIT_NOFILE +# else +# ifdef RLIMIT_OPEN_MAX +# define RLIMIT_FD_MAX RLIMIT_OPEN_MAX +# else +# undef RLIMIT_FD_MAX +# endif +# endif +#endif + +#define PID_LEN 7 /* overkill, but hey */ +#define MAX_OPEN_FILEDESCRIPTORS_WILD_GUESS 256 + +static int want_to_quit = 0; + +void finalize(int i) +{ +#ifdef IRCDWATCH_USE_SYSLOG + syslog(LOG_NOTICE, "ircdwatch daemon exiting"); + closelog(); +#endif + exit(i); +} + +int daemonize(void) +{ + pid_t pid; + int i; + int open_max; + +#ifdef RLIMIT_FD_MAX + struct rlimit rlim; + + if (getrlimit(RLIMIT_FD_MAX, &rlim) != 0) { + perror("getrlimit"); + finalize(1); + } + + /* if we get a lame answer we just take a wild guess */ + if (rlim.rlim_max == 0) { + open_max = MAX_OPEN_FILEDESCRIPTORS_WILD_GUESS; + } + + open_max = rlim.rlim_max; + +#else + + /* no RLIMIT_FD_MAX? take a wild guess */ + open_max = MAX_OPEN_FILEDESCRIPTORS_WILD_GUESS; + +#endif + + pid = fork(); + if (pid < 0) { + perror("fork"); + exit(1); + } + + /* parent process dies */ + if (pid != 0) { + exit(0); + } + + setsid(); + umask(0); + + /* close file descriptors */ + for (i=0; i < open_max; i++) { + close(i); + } + + return(0); +} + +static void sig_handler (int signo) +{ + if (signo == SIGHUP) { + want_to_quit = 1; + return; + } + + if (signo == SIGALRM) { + +#ifndef POSIX_SIGNALS + (void)signal(SIGALRM, &sig_handler); +#endif; + + return; + } +} + + +void set_up_signals(void) +{ +#ifdef POSIX_SIGNALS + struct sigaction act; + + act.sa_handler = sig_handler; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + + if (sigaction(SIGHUP, &act, NULL) < 0) { + perror("sigaction"); + } + + if (sigaction(SIGALRM, &act, NULL) < 0) { + perror("sigaction"); + } +#else + (void)signal(SIGHUP, &sig_handler); + (void)signal(SIGALRM, &sig_handler); +#endif + + /* ignore it if child processes die */ + signal(SIGCHLD, SIG_IGN); +} + +int write_my_pid(void) +{ + FILE *f; + + f = fopen(IRCDWATCH_PID_FILENAME, "w"); + if (f == NULL) { + return(-1); + } + + fprintf(f, "%d\n", getpid()); + fclose(f); + + return(0); +} + + +int file_modified(char *s) +{ + struct stat st; + + if (stat(s, &st) < 0) { + return(-1); + } + return(st.st_ctime); +} + + +int spawn (char *cmd) +{ + pid_t pid; + + pid = fork(); + + if (pid == -1) { +#ifdef IRCDWATCH_USE_SYSLOG + syslog(LOG_ERR, "spawn() unable to fork, errno=%d", errno); +#endif + return(-1); + } + + if (pid == 0) { + execl("/bin/sh", "sh", "-c", cmd, (char *) NULL); + _exit(127); + } + return(0); +} + +int read_pid(char *pid_filename) +{ + FILE *f; + char pidbuf[PID_LEN]; + pid_t pid; + + f = fopen(pid_filename, "r"); + if (f == NULL) { +#ifdef IRCDWATCH_USE_SYSLOG + syslog(LOG_ERR, "unable to fopen() %s: %s", pid_filename, strerror(errno)); +#endif + return(-1); + } + + if (fgets(pidbuf, PID_LEN, f) != NULL) { + pid = atol(pidbuf); + } else { +#ifdef IRCDWATCH_USE_SYSLOG + syslog(LOG_ERR, "fgets() %s: %s", pid_filename, strerror(errno)); +#endif + fclose(f); + return(-1); + } + + fclose(f); + return(pid); +} + +int file_exists (char *s) +{ + struct stat st; + if ((stat(s, &st) < 0) && (errno == ENOENT)) { + return(0); + } + return(1); +} + +/* yeah, I'll get around to these in some later version */ + +int file_readable (char *s) +{ + return(access(s, R_OK) == 0); +} + +int file_writable (char *s) +{ + return(access(s, W_OK) == 0); +} + +int file_executable (char *s) +{ + int rc; + rc = (access(IRCD_PATH, X_OK) == 0); + return rc; +} + +int verify_pid(int pid) +{ + int res; + + res = kill(pid, 0); + if (res < 0 && errno == EPERM) { + fprintf(stderr, "Not process owner\n"); + exit(1); + } + + return(res == 0); +} + +int ircdwatch_running () { + int pid; + + if (file_exists(IRCDWATCH_PID_FILENAME)) { + pid = read_pid(IRCDWATCH_PID_FILENAME); + if (pid > 0) { + return(verify_pid(pid) == 1); + } else { + return(-1); + } + } + return(0); +} + +int ircd_running () { + int pid; + + if (file_exists(IRCDPID_PATH)) { + pid = read_pid(IRCDPID_PATH); + if (pid > 0) { + return(verify_pid(pid) == 1); + } else { + return(-1); + } + } + return(0); +} + +void hup_ircd () +{ + int pid; + int res; + + if (file_exists(IRCDPID_PATH)) { + pid = read_pid(IRCDPID_PATH); + if (pid > 0) { + res = kill(pid, SIGHUP); + if (res < 0 && errno == EPERM) { +#ifdef IRCDWATCH_USE_SYSLOG + syslog(LOG_ERR, "not allowed to send SIGHUP to ircd"); +#endif + finalize(1); + } + } + } +} + + +void daemon_run () +{ + int i; + int last_config_time = 0; + + /* is ircdwatch already running? */ + i = ircdwatch_running(); + if (i == -1) { + /* unable to open pid file. wrong user? */ + fprintf(stderr, "ircdwatch pid file exists but is unreadable\n"); + exit(1); + } else if (i) { + fprintf(stderr, "ircdwatch is already running\n"); + exit(0); + } + + /* is ircd running? */ + i = ircd_running(); + if (i == -1) { + /* unable to open pid file. wrong user? */ + fprintf(stderr, "ircdwatch pid file exists but is unreadable\n"); + exit(1); + } else if (!i) { + fprintf(stderr, "ircd not running. attempting to start ircd...\n"); + if (file_exists(IRCD_PATH)) { + if (file_executable(IRCD_PATH)) { + spawn(IRCD_PATH); + } else { + fprintf(stderr, "%s not executable\n", IRCD_PATH); + exit(1); + } + } else { + fprintf(stderr, "%s does not exist\n", IRCD_PATH); + exit(1); + } + } + + set_up_signals(); + closelog(); + /* daemonize(); */ + +#ifdef IRCDWATCH_USE_SYSLOG + openlog(IRCDWATCH_SYSLOG_IDENT, + IRCDWATCH_SYSLOG_OPTIONS, + IRCDWATCH_SYSLOG_FACILITY); + + syslog(LOG_NOTICE, "starting ircdwatch daemon"); +#endif + + alarm(IRCDWATCH_POLLING_INTERVAL); + pause(); + + while (!want_to_quit) { + if (! ircd_running() ) { + +#ifdef IRCDWATCH_USE_SYSLOG + syslog(LOG_ERR, "spawning %s", IRCD_PATH); +#endif + + spawn(IRCD_PATH); + } + +#ifdef IRCDWATCH_HUP_ON_CONFIG_CHANGE + i = file_modified(IRCDCONF_PATH); + if (i != -1) { + + if (last_config_time == 0) { + last_config_time = i; + } + + else if (i > last_config_time) { + last_config_time = i; + hup_ircd(); + +#ifdef IRCDWATCH_USE_SYSLOG + syslog(LOG_NOTICE, "config change, HUPing ircd"); +#endif + + } + } +#endif + + alarm(IRCDWATCH_POLLING_INTERVAL); + pause(); + } + return; +} + +void kill_ircd () +{ + int pid; + int res; + + if (file_exists(IRCDPID_PATH)) { + pid = read_pid(IRCDPID_PATH); + if (pid > 0) { + res = kill(pid, SIGTERM); + if (res < 0) { + perror("ircd kill"); + finalize(1); + } else { + fprintf(stderr, "killed ircd\n"); + } + } + } else { + fprintf(stderr, "File %s does not exist\n", IRCDPID_PATH); + } +} + +void kill_ircdwatch () +{ + int pid; + int res; + + if (file_exists(IRCDWATCH_PID_FILENAME)) { + pid = read_pid(IRCDWATCH_PID_FILENAME); + if (pid > 0) { + res = kill(pid, SIGHUP); + if (res < 0) { + perror("ircdwatch kill"); + finalize(1); + } else { + fprintf(stderr, "Sent HUP to ircdwatch. it will die soon...\n"); + } + } + } else { + fprintf(stderr, "File %s does not exist\n", IRCDWATCH_PID_FILENAME); + } +} + + +void usage (void) +{ + fprintf(stderr,"\n\ +Usage:\n\ + ircdwatch [--kill | --rest | --help]\n\ +\n\ + --kill, stop both ircdwatch and ircd\n\ + --rest, stop ircdwatch but let ircd alone\n\ + --help, display this text\n\ +\n\ +%s\n", rcsid); +} + +int +main (int argc, char **argv) { + int i; + +#ifdef IRCDWATCH_USE_SYSLOG + openlog(IRCDWATCH_SYSLOG_IDENT, + IRCDWATCH_SYSLOG_OPTIONS, + IRCDWATCH_SYSLOG_FACILITY); +#endif + + if (argc > 1) { + if (strncmp(argv[1], "--rest", 6) == 0) { + kill_ircdwatch(); + exit(0); + } + + if (strncmp(argv[1], "--kill", 6) == 0) { + kill_ircdwatch(); + kill_ircd(); + exit(0); + } + + usage(); + exit(0); + } + + daemon_run(); + finalize(0); +} diff --git a/contrib/mkpasswd/README b/contrib/mkpasswd/README new file mode 100644 index 0000000..a2bb420 --- /dev/null +++ b/contrib/mkpasswd/README @@ -0,0 +1,64 @@ +/************************************************************************ + * IRC - Internet Relay Chat, ircd/crypt/README + * Copyright (C) 1991 Nelson Minar + * + * 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. + * + * $Id: README,v 1.1 1998/04/07 21:20:59 kalt Exp $ + * + */ + +The change implemented here is that the operator password in irc.conf +is no longer stored in plaintext form, but is encrypted the same way +that user passwords are encrypted on normal UNIX systems. Ie, instead +of having + + O:*:goodboy:Nelson + +in your ircd.conf file, you have + + O:*:sCnvYRmbFJ7oI:Nelson + +You still type "/oper Nelson goodboy" to become operator. However, if +someone gets ahold of your irc.conf file, they can no longer figure +out what the password is from reading it. There are still other +security holes, namely server-server passwords, but this closes one +obvious problem. + +So how do you generate these icky looking strings for passwords? +There's a simple program called mkpasswd to do that for you. Just run +mkpasswd, and at the prompt type in your plaintext password. It will +spit out the encrypted password, which you should then just copy into +the irc.conf file. This should be done only when adding new passwords +to your irc.conf file. To change over your irc.conf file to use +encrypted passwords, define CRYPT_OPER_PASSWORD in config.h. You will +need to recompile your server if you already compiled it with this +feature disabled. Once compiled, edit the Makefile in this directory +and chang "IRCDCONF" to your irc.conf file. Then "make install" in this +directory to replace all the operator passwords in your irc.conf file +with the encrypted format. + +Choose your passwords carefully. Do not choose something in a +dictionary, make sure its at least 5 characters. Anything past 8 +characters is ignored. + +One thing to note about crypt() passwords - for every plaintext, there +are 4096 different passwords. Some valid encryptions of "goodboy" +include t1Ub2RhRQHd4g sCnvYRmbFJ7oI and Xr4Z.Kg5tcdy6. The first +two characters (the "salt") determine which of the 4096 passwords +you will get. mkpasswd chooses the salt randomly, or alternately +will let you specify one on the command line. + +see also - crypt(3) diff --git a/contrib/mkpasswd/crypter b/contrib/mkpasswd/crypter new file mode 100755 index 0000000..4851620 --- /dev/null +++ b/contrib/mkpasswd/crypter @@ -0,0 +1,55 @@ +#!/usr/local/bin/perl +#************************************************************************ +#* IRC - Internet Relay Chat, ircd/crypt/crypter +#* Copyright (C) 1991 Sean Batt +#* +#* 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. +#* +#* $Id: crypter,v 1.1 1998/04/07 21:21:00 kalt Exp $ +#* +#*/ + +#From Sean Batt sean@coombs.anu.edu.au +# +#Temporary output file +# +$tmpfile = "/tmp/ircd.conf.tmp"; + +# +#Original ircd.conf file +# +$ircdconf = @ARGV[0]; + +print "crypting ",$ircdconf,"\n"; +@saltset = ('a' .. 'z', 'A' .. 'Z', '0' .. '9', '.', '/'); + +umask(0077); +open ($ircdout, ">/tmp/ircd.conf.tmp") || die "open $!"; + +while ($text = <>) { +#if its not an "O" line we can ignore it + $text =~ /^o/i || print ($ircdout $text) && next; + chop($text); + @oline = split(':', $text); + $salt = $saltset[rand(time)%64].$saltset[(rand(time)>>6)%64]; + $oline[2] = crypt(@oline[2], $salt); + print ($ircdout join(':',@oline)."\n"); +} +close ($ircdout); +close ($ircdin); +print "/bin/cp ",$tmpfile," ",$ircdconf,"\n"; +(fork()==0) ? exec("/bin/cp", $tmpfile, $ircdconf) : wait; + +#unlink($tmpfile); diff --git a/contrib/mkpasswd/mkpasswd.c b/contrib/mkpasswd/mkpasswd.c new file mode 100644 index 0000000..8ea8413 --- /dev/null +++ b/contrib/mkpasswd/mkpasswd.c @@ -0,0 +1,44 @@ +/* simple password generator by Nelson Minar (minar@reed.edu) + * copyright 1991, all rights reserved. + * You can use this code as long as my name stays with it. + */ + +#include +#include +#include + +#ifndef lint +static char rcsid[] = "@(#)$Id: mkpasswd.c,v 1.1 1998/04/07 21:21:00 kalt Exp $"; +#endif + +extern char *getpass(); + +int main(argc, argv) +int argc; +char *argv[]; +{ + static char saltChars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./"; + char salt[3]; + char * plaintext; + int i; + + if (argc < 2) { + srandom(time(0)); /* may not be the BEST salt, but its close */ + salt[0] = saltChars[random() % 64]; + salt[1] = saltChars[random() % 64]; + salt[2] = 0; + } + else { + salt[0] = argv[1][0]; + salt[1] = argv[1][1]; + salt[2] = '\0'; + if ((strchr(saltChars, salt[0]) == NULL) || (strchr(saltChars, salt[1]) == NULL)) + fprintf(stderr, "illegal salt %s\n", salt), exit(1); + } + + plaintext = getpass("plaintext: "); + + printf("%s\n", crypt(plaintext, salt)); + return 0; +} + diff --git a/contrib/mod_passwd/README b/contrib/mod_passwd/README new file mode 100644 index 0000000..6aa2352 --- /dev/null +++ b/contrib/mod_passwd/README @@ -0,0 +1,30 @@ +$Id: README,v 1.1 1999/03/13 23:06:15 kalt Exp $ + +This is an example module for the authentication program (iauth) used by +the IRC server. + +* This module demonstrates how a module can access and use the PASS and + USER information provided by users. It is *NOT* a finished product. In + particular, the actual password validation is not implemented. + +* This module also demonstrates how a DSM module should be written. You'll + note that it is completely identical to ordinary modules, except for one + extra function: "passwd_load()" + +To be used, this module needs to be compiled from the normal compilation +directory. It should be linked as a dynamic library. Methods vary +depending on the compiler and platform. + +$ gcc -c -g -I../iauth -I../common -I. ../contrib/mod_passwd/mod_passwd.c +$ ld -Bshareable mod_passwd.o -o mod_passwd.so +$ ls -l mod_passwd.so +-rwxr--r-- 1 kalt staff 26932 Mar 13 17:59 mod_passwd.so +$ + +To be used by iauth, add the following lines to the iauth.conf file: + + extinfo + shared passwd /path/to/mod_passwd.so + module passwd + +See iauth.conf(5) for more information on configuring iauth. diff --git a/contrib/mod_passwd/mod_passwd.c b/contrib/mod_passwd/mod_passwd.c new file mode 100644 index 0000000..817a722 --- /dev/null +++ b/contrib/mod_passwd/mod_passwd.c @@ -0,0 +1,171 @@ +/************************************************************************ + * IRC - Internet Relay Chat, mod_passwd.c + * Copyright (C) 1999 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_passwd.c,v 1.1 1999/03/13 23:06:15 kalt Exp $"; +#endif + +#include "os.h" +#include "a_defines.h" +#include "a_externs.h" + +/* + * passwd_init + * + * This procedure is called when a particular module is loaded. + * Returns NULL if everything went fine, + * an error message otherwise. + */ +char * +passwd_init(self) +AnInstance *self; +{ + return NULL; +} + +/* + * passwd_release + * + * This procedure is called when a particular module is unloaded. + */ +void +passwd_release(self) +AnInstance *self; +{ +} + +/* + * passwd_stats + * + * This procedure is called regularly to update statistics sent to ircd. + */ +void +passwd_stats(self) +AnInstance *self; +{ +} + +/* + * passwd_start + * + * This procedure is called to start an authentication. + * Returns 0 if everything went fine, + * +1 if still waiting for some data (username, password).. + * -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. passwd_clean + * will NOT be called) + */ +int +passwd_start(cl) +u_int cl; +{ + if (cldata[cl].authuser && + cldata[cl].authfrom < cldata[cl].instance->in) + { + /* + ** another instance preceding this one in the configuration + ** has already authenticated the user, no need to bother + ** doing anything here then. (the other takes precedence) + */ + return -1; + } + if ((cldata[cl].state & A_GOTU) == 0) + /* haven't received username/password pair from ircd yet */ + return 1; + if ((cldata[cl].state & A_GOTP) == 0) + { + /* no password to check -> reject user! */ + cldata[cl].state |= A_DENY; + sendto_ircd("K %d %s %u ", cl, cldata[cl].itsip, + cldata[cl].itsport); + return -1; /* done */ + } + /* + ** + ** + ** INSERT FUNCTION TO CHECK PASSWORD VALIDITY + ** + ** + */ + /* if failure, see above */ + /* if success: */ + cldata[cl].state |= A_UNIX; + if (cldata[cl].authuser) + free(cldata[cl].authuser); + cldata[cl].authuser = mystrdup(cldata[cl].user); + cldata[cl].authfrom = cldata[cl].instance->in; + sendto_ircd("U %d %s %u %s", cl, cldata[cl].itsip, cldata[cl].itsport, + cldata[cl].authuser); + return -1; /* done */ +} + +/* + * passwd_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 +passwd_work(cl) +u_int cl; +{ + return -1; +} + +/* + * passwd_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 +passwd_clean(cl) +u_int cl; +{ +} + +/* + * passwd_timeout + * + * This procedure is called whenever the timeout set by the module is + * reached. + * + * Returns 0 if things are okay, -1 if authentication was aborted. + */ +int +passwd_timeout(cl) +u_int cl; +{ +} + +static aModule Module_passwd = + { "passwd", passwd_init, passwd_release, passwd_stats, + passwd_start, passwd_work, passwd_timeout, passwd_clean }; + +aModule * +passwd_load() +{ + return &Module_passwd; +} diff --git a/contrib/tkserv/CHANGES b/contrib/tkserv/CHANGES new file mode 100644 index 0000000..e983ded --- /dev/null +++ b/contrib/tkserv/CHANGES @@ -0,0 +1,37 @@ +1.0.0b8 : Ported TkServ to C. +1.0.0b8 : It is now possible to QUIT the service via SQUERY. +1.0.0b9 : Added default expiration if no time value was specified (koopal) +1.0.0b9 : It is now possible to remove existing tklines "manually" (koopal) +1.0.0b10: the pwd of the service went to the cmd line (koopal) +1.0.0 : Official release of TkServ +1.0.1 : Applied some fixes to make TkServ work under BSDI (primetime) +1.0.1 : no address of a local var is returned anymore :) (primetime) +1.0.2 : Added forgotten tkserv.access.example to the package (primetime) +1.0.2 : IP masks (x.x.x.*) are now also be recognized as IPs (primetime) +1.0.2 : hostnames are now also possible in the restriction field (primetime) +1.0.3 : DEBUGGING is now functional and displays all service<->server + traffic to the standard output +1.0.3 : TkServ should now also compile under Irix (Szern) +1.0.3 : IP restrictions are now also possible in the access file + - wildcards are allowed (Szern) +1.0.3 : Wildcards do now also work in the oper u@h field of the access + file (Szern) +1.0.3 : Replaced FNM_CASEFOLD by FNM_NOESCAPE +1.0.4 : ':' is not allowed anymore in the TKLINE cmd line (Eumel) +1.0.4 : Fixed lame bug which kept tklines active altho already expired (Eumel) +1.0.5 : TkServ should now also compile under Redhat Linux. (Tero) +1.0.5 : a few changes for ircd/contrib compliancy +1.0.5 : the semantics for the access file have changed (check out README) +1.0.5 : it is now possible to disallow tklining of specific hosts (tumble) +1.0.6 : Added leading colons for the /squery commands (tumble) +1.0.6 : Added a hint concerning the distribution to the README +1.0.6 : it's now possible to decide whether a user needs to be opered or + not when accessing TkServ +1.0.7 : TkServ won't crash anymore if a bad lifetime is given (Tero) +1.0.8 : A few changes to make TkServ fit better into ircd/contrib. +1.0.8 : TkServ now sends out a hint when it receives an unknown cmd + (Fusion & viha) +1.0.9 : renamed the function logf due to a conflict in *BSD? (Virginie) +1.0.9 : General rename of some tkserv functions +1.2 : Password migration from cmd line to conf file (Earthpig) +1.2 : TkServ now daemonizes itself. (Earthpig) diff --git a/contrib/tkserv/CREDITS b/contrib/tkserv/CREDITS new file mode 100644 index 0000000..617fb16 --- /dev/null +++ b/contrib/tkserv/CREDITS @@ -0,0 +1,60 @@ +Thanks to the following people, who have contributed in one way or another +to the development of TkServ: + +- Andre 'koopal' Koopal + + beta testing + + default expiration + + removal of tklines before expiration (manual removal) + + password migration from config.h to cmd line + +- Asu 'primetime' Pala + + fix for BSDI + + IP recognition bug + + forgotten tkserv.access.example file + + hostnames in the restriction field of the access file + +- 'Szern' + + fix for Irix + + IPs in the restriction field + + wildcards in the u@h oper field of the access file + +- Michael 'Eumel' Neumayer + + colons are not allowed anymore outside the password parameter + + expired tklines do now get removed really automatically + +- Tero 'Tero' Saari + + RedHat Linux cludge + + no crashes anymore when a bad lifetime is given + +- Andrew ´Earthpig´ Snare + + password back to conf file (more secure) + + automatic daemonization + +- 'tumble' + + possibility to explicitly disallow specific hosts from getting tklined + + leading colons for the /squery commands in the README + +- Kristian 'Fusion' Bergmann & 'viha' + + Sending out of a hint when an unknown command is received + +- 'Virginie' + + rename of the logf function because of conflict under *BSD? + +- 'jbn' + + expiration of tklines / default expiration + +- The EPIC Software Labs + + for their nice ircII-EPIC client from which i took some networking + stuff, see http://www.snafu.de/~kl/epic/index.html for more about + epic + +- Kai 'Oswald' Seidler + + for his NoteServ, on which TkServ is based and which has helped me a + lot in making TkServ, see http://oswald.pages.de for more + +- Christophe 'syrk' Kalt and Vesa 'Vesa' Ruokonen + + for giving me the impulse to this kind of service :) + + +And finally thanks to all the Linux people out there for contributing +to the world's best OS! :-) diff --git a/contrib/tkserv/INSTALL b/contrib/tkserv/INSTALL new file mode 100644 index 0000000..9bc69bd --- /dev/null +++ b/contrib/tkserv/INSTALL @@ -0,0 +1,20 @@ +How to install TkServ +--------------------- + +Yes, there isn't any configure yet. That's why the compilation on some +machines could be difficult because you may have to include one or two +libraries by hand. I'll try to create a configure file in the future. + +Up to now, i've only compiled TkServ on Linux, Solaris and Irix. I hope you +won't get into trouble when trying to compile on another OS. But everyone +should be running Linux anyway. :-) + +So here we go: + +1. Unpack and untar the archive. (which you might already have done :) +2. RTFM. :-> +3. run "./configure" (if you haven't already done so) +3. Edit the tkconf.h file. +4. "make tkserv" + +Good luck, Kasi diff --git a/contrib/tkserv/README b/contrib/tkserv/README new file mode 100644 index 0000000..a7b7c47 --- /dev/null +++ b/contrib/tkserv/README @@ -0,0 +1,290 @@ +Welcome to TkServ ! +=+=+=+=+=+=+=+=+=+= + +This program is released under the GNU General Public License. +A copy of this license is included in the distribution. + +I) Introduction +--------------- + +TkServ is a so-called temporary k-line service. + +[If you don't know what a service is, consult the documentation which comes +along with the irc2.10.x package (if you don't know services, you shouldn't +be reading this anyway ;).] + +This is what TkServ does - roughly: On request, it adds a given k-line +pattern to the server's k-line list and (sooner or later, see below) then +removes it. The adding/removing is done via the ircd.conf file. + +The purpose/advantages of a temporary k-line service: + + - it facilitates the process of k-lining users + - added k-lines disappear automatically (see below) + - it allows _also_ remote users (only if they are listed in the access + file of the service - see below) to temp k-line users on the respective + server + - it allows people to specify a duration for each tkline + - it is more effective than /kill but practically as easy to use + - it could therefore act as a replacement for the /kill command - which in + fact is more or less its longtime goal... + + +II) Security concerns +--------------------- + +Of course, when allowing remote "access" to the ircd.conf file, the main +concern of most admins is security. Therefore, here's a list of the +procedures used by TkServ to ensure that only authorized users may add +temporary k-lines to the server's conf file [origin == the person who is +sending a request]: + +- the origin's user@host has to match one of the u@h's in the tkserv.access + file (case sensitive!) +- the origin has always to specify a password which has to match the + password that belongs to the corresponding user@host in the access file + (case sensitive!) +- the origin has to be opered, if you want to +- it is possible to allow an authorized user to only tkline given hostnames + or TLDs + +Especially the third point equals to strong security, because: Could you +imagine any cracker who has gained O: on some server, wasting his time on +trying to get access to a remote server's temp k-line list instead of +playing around with his O: ? See, neither could i. ;-) + + +III) Installation +----------------- + +A) Precondition + + The only thing you need in order to run TkServ is an "ircd.conf" file, + an "ircd.pid" file and an IRC server which has been compiled with + USE_SERVICES #define'd in the config.h file (!). + +B) Editing the configuration file (config.h) + + You have to change the following entries in the config file: + + TKSERV_ADMIN_NAME (your real name) + TKSERV_ADMIN_CONTACT (mail address) + TKSERV_ADMIN_OTHER (your nick, for example) + + TKSERV_NAME (the name of the service appearing on /SERVLIST) + TKSERV_DESC (a neato description :) + TKSERV_DIST (the distribution of the service) + +| A few words to the distribution of the service. Here are the pros & +| contras of a global TkServ from my point of view: +| +| [contra] It makes the /servlist become unnecessarily big and less handy +| [contra] You can detect also local services by /trace'ing a server +| [contra] You can access a local TkServ by setting up a special client +| on the concerned server (maybe with a special I: line) +| +| [pro] A global TkServ is more comfortable to use for remote users. +| [pro] If you want to see which server is running one (for e.g. to +| request access to it), you do only have to do a /servlist. + + TKSERV_PATH (the abs. path to your ircd.conf, no trailing slash please!) + TKSERV_LOGFILE (the abs. path to your tkserv logfile, no trailing slash) + TKSERV_ACCESSFILE (the abs. path to your tkserv access file, ditto) + + TKSERV_DEBUG (for debugging only, displayes traffic to standard output) + +C) Compiling the source + +TkServ will be compiled along with the irc server. + +D) Setting up the access file: tkserv.access + + If anyone should be authorized to use TkServ on your server, he/she has + to figure in the access file. The format of it is: + +| [!][] +| +| Which means: +| [!] [] +| +| A '!' before the u@h means that the specified user doesn't need to be +| opered when accessing TkServ. Before the FQDN/IP, it means that the user +| is not allowed to tkline that given FQDN/IP. See below. +| +| Examples: +| (1) foo@bar.com foo-pass +| (2) some@user.on.the.net some.passw1 *.net,207.128.* +| another@user.foo.com Akfdsv.df *netcom.com,*.ca +| you@get.the.picture.org ditto. *.org,dialup*.lamer.net,194.44.44.* +| oper@dialup*.dialup.net pwd1.2 *dialup.net,145.44.*,*.fr +| (3) !luser@doesnt.need.to.be.opered.org bleh !elite.org,*.org +| (4) !~luser@no.ident.no.oper.com yo *.com +| +| (1) Any oper who is running identd and whose userhost equals to +| foo@bar.com can tkline everyone if supplied password equals +| foo-pass. +| (2) Any oper with identd whose u@h equals to some@user.on.the.net +| can tkline everyone whose TLD is ".net" or who is IRCing within +| the IP subnet 207.128.*, if correct password is given. +| (3) Any luser (no need to be opered) whose u@h/passwd equals can tkline +| everyone whose TLD is ".org" except the host "elite.org" +| ("*@elite.org"). +| +| Generally, you should be aware of the fact that if you put something +| in the FQDN/IP field, then you automatically restrict the access. +| Therefore, you must then also indicate all the allowed FQDNs/IPs. +| +| The access routines are pretty flexible. So pay attention in what order +| you allow/disallow what. :) +| +| Other examples: +| !foo@bar.com foo-pass !*.net,*.com,!*.com +| some@user.on.the.net some.passw1 *.net,207.128.*,!127.0.0.* +| another@user.foo.com Akfdsv.df *netcom.com,!*trends.ca,*.ca +| +| Notice that if you allow "*.de" and after it you forbid "blah.de", +| this won't work. The oper will still be able to tkline blah.de since +| "*.de" appears before "!blah.de" in the access field. +| +| Are we confused, yet? ;-) + + For some other examples, refer to the tkserv.access.example file, which + is included in the package. + + The u@h field for the user can also contain wildcards, as you can see. + +| If you specify an FQDN (or several of them in a comma-separated +| list), the concerned user will only be allowed to tkline users from +| that FQDN(s). Everything is done via 'wildcard-matching' (if any). +| I.e. that "home.blah.de" matches only "*@home.blah.de". If you want +| to allow a whole TLD, you have to do this by putting "*.tld" in the +| access field. + +! An empty FQDN/IP field means that the concerned user can tkline everyone. ! + [Except *@* that is.] + +E) Setting up the S: line in your ircd.conf file + + If you're not yet familiar with S: lines, consult the documentation of + the ircd package. + + S::::33554432: + + is the FQDN from which the service will connect to the server. + + The service type 33554432 is mandatory! Currently, TkServ will refuse + any other service type. [Actually, it won't, but it's good to think that + it will... ;-] + + The service class should refer to an existing class (according to the + documentation :). + +F) Starting TkServ + + The command line syntax of TkServ looks like this: + + tkserv + or + tkserv + + Example: + + tkserv localhost 6667 my-serv.pass + + Where is the address of your IRC server, the port to + which TkServ will connect and the password for the service. + +G) Adding temp k-klines (TKLINE) + + Provided that TkServ recognizes you, you can add temporary k-lines via + the TKLINE command, which has three different variants: + + (1) :TKLINE + (2) :TKLINE + (3) :TKLINE -1 + + (1) adds a tkline for with an expire time of hours and + with the reason . + (2) adds a tkline for with the default expire time (2 hours) and + with the reason . + (3) removes any existing tklines found for . + + Examples: + + (1) :TKLINE my.pass 5 lamer@lamers.org dont flood + (2) :TKLINE blah. *@foo.com stop spamming + (3) :TKLINE my.pass -1 lamer@lamers.org + + must be > 0 and < 168. + +| [If your client doesn't support SQUERY, the entire cmd line has to be: +| "/quote squery :tkline ...". If it does support it, +| then "/squery tkline ..." should do it.] +| +| [And yes, ircII-EPIC4 supports SQUERY and SERVLIST! ;-)] +| +| If a non-opered user tries to use TKLINE without having a matching entry +| in the access file, he gets "Only IRC-Operators may use this command" as +| an error message. This is not correct anymore, but i didn't bother to +| change it (since it may prevent kids from playing around with TkServ :). + +H) Online help/info + +TkServ does also have a little online help which is accessible via +"/squery help". + +I) Quitting the service + +To make TkServ quit IRC you have to send him the following SQUERY: + +QUIT + +Where corresponds to password that you indicated at startup. +Be aware that anyone who knows that password can make your TkServ quit. + +J) Debugging + +If you #define TKSERV_DEBUG in the config.h file, everything which is sent +to the server from the service and from the server to the service will be +displayed to the standard output. + + +IV) Misc, or what goes where + +TkServ will create the following permanent files in your ircd directory: + +ircd.conf.tkserv (backup of the ircd.conf file) +tkserv.log (TkServ's log file) + +The latter will contain most of the error messages (in case something goes +wrong - what we all don't hope ;) as well as logs of successful TKLINE +requests. + +The tkserv.access file has to be in the directory specified in the config.h +file. If no tkserv.access file is found, no one will be able to add temp +k-lines. + +Now and then you should zero your TkServ logfile because this won't happen +by itself. =) + + +V) Credits + +See the CREDITS file. + + +VI) Bugs, comments, suggestions... + +Send everything to kl@snafu.de or to Kasi@IRC. + + +VII) The TkServ-mailinglist + +There's now a mailinglist for TkServ out there. It is used for general +announcements (bugs, new releases, etc.) concerning TkServ. Since it's a +read-only mailinglist, it doesn't have much traffic. You can subscribe to +it by sending a mail to tkserv@kl.Snafu.DE with "subscribe" in the subject +or in the body of the mail. + + +Enjoy, -Kasi diff --git a/contrib/tkserv/proto.h b/contrib/tkserv/proto.h new file mode 100644 index 0000000..edf23b7 --- /dev/null +++ b/contrib/tkserv/proto.h @@ -0,0 +1,24 @@ +void sendto_server(char *buf, ...); +void sendto_user(char *text, ...); +void process_server_output(char *line); +void parse_server_output(char *buffer); +int server_output(int fd, char *buffer); + +void service_pong(void); +void service_notice(char **args); +void service_squery(char **args); +int service_userhost(char *args); +void squery_help(char **args); +void squery_tkline(char **args); +void squery_quit(char **args); + +void sendlog(char *text, ...); +char *ts(void); + +int is_opered(void); +int is_authorized(char *pwd, char *host); + +void exec_cmd(char *cmd, ...); +int add_tkline(char *host, char *user, char *reason, int lifetime); +int check_tklines(char *host, char *user, int lifetime); +void rehash(int what); diff --git a/contrib/tkserv/tkserv.access.example b/contrib/tkserv/tkserv.access.example new file mode 100644 index 0000000..4269c93 --- /dev/null +++ b/contrib/tkserv/tkserv.access.example @@ -0,0 +1,10 @@ +foo@bar.com foo.pass *netcom.com,*.net +someone@SomeOrg.org aldkf.23 eleet.org,165.55.45.* +~blah@ppp*.blah.de igh.pass +user@users.Online.net ukuk.ua1 +some@ip*.user.com blah 204.85.*,194.55.43.* +you.get@the.picture.com pass ppp*.lame.com,*.org,dialin*.whitehouse.gov,*.net,*.uk +disallow@something.com bleh !*.de,!*.fr,*.net,*.org,*.com,!195.144.45.* +disallow@another.host.fr yo !hugo.fr,!admin.irc.fr,*.fr,*.ca,195.55.66.* +!luser@who.doesnt.need.to.be.opered.de yeh *.de + diff --git a/contrib/tkserv/tkserv.c b/contrib/tkserv/tkserv.c new file mode 100644 index 0000000..92f281d --- /dev/null +++ b/contrib/tkserv/tkserv.c @@ -0,0 +1,1022 @@ +/* +** Powered by Linux. :-) +** +** Copyright (c) 1998 Kaspar 'Kasi' Landsberg, +** +** File : tkserv.c v1.2 +** Author : Kaspar 'Kasi' Landsberg, +** Desc. : Temporary K-line Service. +** For further info see the README file. +** Location : http://www.snafu.de/~kl/tkserv +** Usage : tkserv +** E.g. : tkserv localhost 6667 +** +** This program is distributed under the GNU General Public License 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 details. +** +** Note: The C version of this service is based on parts of the +** ircII-EPIC IRC client by the EPIC Software Labs and on +** the NoteServ service by Kai 'Oswald' Seidler - see +** http://oswald.pages.de for more about NoteServ. +** Thanks to both. =) +** +** PS: Casting rules the world! (doh) +*/ + +#include "os.h" +#undef strcasecmp +#include "config.h" +#include "tkconf.h" +#include "proto.h" + +/* Max. kill reason length */ +#define TKS_MAXKILLREASON 128 + +/* Used max. length for an absolute Unix path */ +#define TKS_MAXPATH 128 + +/* Max. buffer length (don't change this?) */ +#define TKS_MAXBUFFER 8192 + +/* don't change this either(?) */ +#define TKS_MAXARGS 250 + +/* The version information */ +#define TKS_VERSION "Hello, i'm TkServ v1.2." + +static char *nuh; +FILE *tks_logf; +int fd = -1, tklined = 0; + +/* +** Returns the current time in a formated way. +** Yes, "ts" stands for "time stamp". I know, +** this hurts, but i couldn't find any better +** description. ;-> +*/ +char *tks_ts(void) +{ + static char tempus[256]; + time_t now; + struct tm *loctime; + + /* Get the current time */ + now = time(NULL); + + /* Convert it to local time representation */ + loctime = localtime(&now); + + strftime(tempus, 256, "@%H:%M %m/%d", loctime); + + return(tempus); +} + +/* logging routine, with timestamps */ +void tks_log(char *text, ...) +{ + char txt[TKS_MAXBUFFER]; + va_list va; + + tks_logf = fopen(TKSERV_LOGFILE, "a"); + va_start(va, text); + vsprintf(txt, text, va); + + if (tks_logf != NULL) + fprintf(tks_logf, "%s %s\n", txt, tks_ts()); + else + { + perror(TKSERV_LOGFILE); + va_end(va); + return; + } + + va_end(va); + fclose(tks_logf); +} + +/* an optimized system() function */ +void exec_cmd(char *cmd, ...) +{ + char command[TKS_MAXBUFFER]; + va_list va; + + va_start(va, cmd); + vsprintf(command, cmd, va); + system(command); + va_end(va); +} + +/* sends a string (<= TKS_MAXBUFFER) to the server */ +void sendto_server(char *buf, ...) +{ + char buffer[TKS_MAXBUFFER]; + va_list va; + + va_start(va, buf); + vsprintf(buffer, buf, va); + write(fd, buffer, strlen(buffer)); + va_end(va); + +#ifdef TKSERV_DEBUG + printf("%s", buffer); +#endif +} + +/* sends a NOTICE to the SQUERY origin */ +void sendto_user(char *text, ...) +{ + char *nick, *ch; + char txt[TKS_MAXBUFFER]; + va_list va; + + nick = (char *) strdup(nuh); + ch = (char *) strchr(nick, '!'); + *ch = '\0'; + + va_start(va, text); + vsprintf(txt, text, va); + sendto_server("NOTICE %s :%s\n", nick, txt); + va_end(va); +} + +void process_server_output(char *line) +{ + char *ptr; + static char *args[TKS_MAXARGS]; + int i, argc = 0; + + while ((ptr = (char *) strchr(line, ' ')) && argc < TKS_MAXARGS) + { + args[argc] = line; + argc++; + *ptr = '\0'; + line = ptr + 1; + } + + args[argc] = line; + + for (i = argc + 1; i < TKS_MAXARGS; i++) + args[i] = ""; + + /* + ** After successfull registering, backup the ircd.conf file + ** and set the perms of the log file -- the easy way :) + */ + if ((*args[0] == ':') && (!strcmp(args[1], "SERVSET"))) + { + chmod(TKSERV_ACCESSFILE, S_IRUSR | S_IWRITE); + chmod(TKSERV_LOGFILE, S_IRUSR | S_IWRITE); + exec_cmd("cp "CPATH" "TKSERV_IRCD_CONFIG_BAK); + tks_log("Registration successful."); + } + + /* We do only react upon PINGs, SQUERYs and &NOTICES */ + if (!strcmp(args[0], "PING")) + service_pong(); + + if ((*args[0] == ':') && (!strcmp(args[1], "SQUERY"))) + service_squery(args); + + if (!strcmp(args[0], "&NOTICES")) + service_notice(args); +} + +/* reformats the server output */ +void parse_server_output(char *buffer) +{ + char *ch, buf[TKS_MAXBUFFER]; + static char tmp[TKS_MAXBUFFER]; + + /* server sent an empty line, so just return */ + if (!buffer && !*buffer) + return; + + while ((ch = (char *) strchr(buffer, '\n'))) + { + *ch = '\0'; + + if (*(ch - 1) == '\r') + *(ch - 1) == '\0'; + + sprintf(buf, "%s%s", tmp, buffer); + *tmp = '\0'; + process_server_output(buf); + buffer = ch + 1; + } + + if (*buffer) + strcpy(tmp, buffer); +} + +/* reads and returns output from the server */ +int server_output(int fd, char *buffer) +{ + int n = read(fd, buffer, TKS_MAXBUFFER); + buffer[n] = '\0'; + +#ifdef TKSERV_DEBUG + printf("%s", buffer); +#endif + + return(n); +} + +/* is the origin of the /squery opered? */ +int is_opered(void) +{ + char *nick, *ch, *token, *u_num, *userh; + char buffer[TKS_MAXBUFFER]; + + nick = (char *) strdup(nuh); + ch = (char *) strchr(nick, '!'); + *ch = '\0'; + sendto_server("USERHOST %s\n", nick); + + /* get the USERHOST reply (hopefully) */ + server_output(fd, buffer); + + token = (char *) strtok(buffer, " "); + token = (char *) strtok(NULL, " "); + u_num = (char *) strdup(token); + token = (char *) strtok(NULL, " "); + token = (char *) strtok(NULL, " "); + userh = (char *) strdup(token); + + /* if we got the USERHOST reply, perform the check */ + if (!strcmp(u_num, "302")) + { + char *ch; + ch = (char *) strchr(userh, '=') - 1; + + /* is the origin opered? */ + if (*ch == '*') + { + char *old_uh, *new_uh, *ch; + + old_uh = (char *) (strchr(nuh, '!') + 1); + new_uh = (char *) (strchr(userh, '=') + 2); + + if (ch = (char *) strchr(new_uh, '\r')) + *ch = '\0'; + + /* Does the u@h of the USERHOST reply correspond to the u@h of our origin? */ + if (!strcmp(old_uh, new_uh)) + return(1); + else + /* + ** race condition == we sent a USERHOST request and got the USERHHOST reply, + ** but this reply doesn't correspond to our origin of the SQUERY -- + ** this should never happen (but never say never ;) + */ + sendto_user("A race condition has occured -- please try again."); + } + } + else + /* + ** race condition == we sent a USERHOST request but the next message from + ** the server was not a USERHOST reply (usually due to lag) + */ + sendto_user("A race condition has occured -- please try again (and ignore the following error message)."); + + return(0); +} + +/* +** Look for an entry in the access file and +** see if the origin needs to be opered +*/ +int must_be_opered() +{ + FILE *fp; + + /* if the access file exists, check for auth */ + if ((fp = fopen(TKSERV_ACCESSFILE, "r")) != NULL) + { + char buffer[TKS_MAXBUFFER]; + char *access_uh, *token, *uh; + + while (fgets(buffer, TKS_MAXBUFFER, fp)) + { + uh = (char *) (strchr(nuh, '!') + 1); + token = (char *) strtok(buffer, " "); + + if (token) + access_uh = (char *) strdup(token); + + /* check for access file corruption */ + if (!access_uh) + { + tks_log("Corrupt access file. RTFM. :-)"); + + return(0); + } + + /* do we need an oper? */ + if (*access_uh == '!') + { + if (!fnmatch((char *) (strchr(access_uh, '!') + 1), uh, 0)) + return(0); + } + } + } + else + tks_log("%s not found.", TKSERV_ACCESSFILE); + + return(1); +} + +/* check whether origin is authorized to use the service */ +int is_authorized(char *pwd, char *host) +{ + FILE *fp; + + /* if the access file exists, check for authorization */ + if ((fp = fopen(TKSERV_ACCESSFILE, "r")) != NULL) + { + char buffer[TKS_MAXBUFFER]; + char *access_uh, *access_pwd; + char *token, *uh, *ch, *tlds = NULL; + + while (fgets(buffer, TKS_MAXBUFFER, fp)) + { + uh = (char *) (strchr(nuh, '!') + 1); + token = (char *) strtok(buffer, " "); + + if (token) + access_uh = (char *) strdup(token); + + if (*access_uh == '!') + access_uh = (char *) (strchr(access_uh, '!') + 1); + + token = (char *) strtok(NULL, " "); + + if (token) + access_pwd = (char *) strdup(token); + + token = (char *) strtok(NULL, " "); + + if (token) + tlds = (char *) strdup(token); + else + if (ch = (char *) strchr(access_pwd, '\n')) + *ch = '\0'; + + /* check for access file corruption */ + if (!access_uh || !access_pwd) + { + tks_log("Corrupt access file. RTFM. :-)"); + + return(0); + } + + /* check uh, pass and TLD */ + if (!fnmatch(access_uh, uh, 0)) + if (!strcmp(pwd, access_pwd)) + if (!tlds) + return(1); + else + { + char *token, *ch; + + /* blah */ + if (ch = (char *) strchr(tlds, '\n')) + *ch = '\0'; + + token = (char *) strtok(tlds, ","); + + /* '!' negates the given host/domain -> not allowed to tkline */ + if (*token == '!') + { + if (!fnmatch(((char *) strchr(token, '!') + 1), host, 0)) + { + sendto_user("You are not allowed to tkline \"%s\",", host); + return(0); + } + } + else if (!fnmatch(token, host, 0)) + return(1); + + /* walk thru the list */ + while (token = (char *) strtok(NULL, ",")) + { + if (*token == '!') + { + if (!fnmatch((char *) (strchr(token, '!') + 1), host, 0)) + { + sendto_user("You are not allowed to tkline \"%s\",", host); + return(0); + } + } + else if (!fnmatch(token, host, 0)) + return(1); + } + + sendto_user("You are not allowed to tkline \"%s\".", host); + } + } + + } + else + tks_log("%s not found.", TKSERV_ACCESSFILE); + + return(0); +} + +/*************** ircd.conf section ****************/ + +/* Appends new tklines to the ircd.conf file */ +int add_tkline(char *host, char *user, char *reason, int lifetime) +{ + FILE *iconf; + + if (iconf = fopen(CPATH, "a")) + { + time_t now; + + now = time(NULL); + fprintf(iconf, "K:%s:%s:%s:0 # %d %u tkserv\n", + host, reason, user, lifetime, now); + fclose(iconf); + rehash(1); + tks_log("K:%s:%s:%s:0 added for %d hour(s) by %s.", + host, reason, user, lifetime, nuh); + + return(1); + } + else + tks_log("Couldn't write to "CPATH); + + return(0); +} + +/* Check for expired tklines in the ircd.conf file */ +int check_tklines(char *host, char *user, int lifetime) +{ + FILE *iconf, *iconf_tmp; + + if ((iconf = fopen(CPATH, "r")) && (iconf_tmp = fopen(TKSERV_IRCD_CONFIG_TMP, "w"))) + { + int count = 0, found = 0; + time_t now; + char buffer[TKS_MAXBUFFER]; + char buf_tmp[TKS_MAXBUFFER]; + + /* just in case... */ + chmod(TKSERV_IRCD_CONFIG_TMP, S_IRUSR | S_IWRITE); + + now = time(NULL); + + while (fgets(buffer, TKS_MAXBUFFER, iconf)) + { + if ((*buffer != 'K') || (!strstr(buffer, "tkserv"))) + fprintf(iconf_tmp, buffer); + else + { + /* + ** If lifetime has a value of -1, look for matching + ** tklines and remove them. Otherwise, perform + ** the expiration check. + */ + if (lifetime == -1) + { + char *token; + char buf[TKS_MAXBUFFER]; + + strcpy(buf, buffer); + token = (char *) strtok(buf, ":"); + token = (char *) strtok(NULL, ":"); + + if (!strcasecmp(token, host)) + { + token = (char *) strtok(NULL, ":"); + token = (char *) strtok(NULL, ":"); + + if (!strcasecmp(token, user)) + { + count++; + found = 1; + } + else + fprintf(iconf_tmp, buffer); + } + else + fprintf(iconf_tmp, buffer); + } + else + { + char *ch, *token; + char buf[TKS_MAXBUFFER]; + unsigned long int lifetime, then; + + strcpy(buf, buffer); + ch = (char *) strrchr(buf, '#'); + token = (char *) strtok(ch, " "); + token = (char *) strtok(NULL, " "); + lifetime = strtoul(token, NULL, 0); + token = (char *) strtok(NULL, " "); + then = strtoul(token, NULL, 0); + + if (!(((now - then) / (60 * 60)) >= lifetime)) + fprintf(iconf_tmp, buffer); + else + found = 1; + } + } + } + + fclose(iconf); + fclose(iconf_tmp); + exec_cmd("cp %s %s", TKSERV_IRCD_CONFIG_TMP,CPATH); + unlink(TKSERV_IRCD_CONFIG_TMP); + + if (found) + rehash(-1); + + return(count); + } + else + tks_log("Error while checking for expired tklines..."); +} + +/* reloads the ircd.conf file -- the easy way */ +void rehash(int what) +{ + exec_cmd("kill -HUP `cat "PPATH"`"); + + if (what != -1) + tklined = what; +} + +/*************** end of ircd.conf section **************/ + +/*************** The service command section *************/ + +/* On PING, send PONG and check for expired tklines */ +void service_pong(void) +{ + sendto_server("PONG %s\n", TKSERV_NAME); + check_tklines(NULL, NULL, 0); +} + +/* +** If we get a rehash, tell the origin that the tklines are active/removed +** and check for expired tklines... +*/ +void service_notice(char **args) +{ + if ((!strcmp(args[4], "reloading") && (!strcmp(args[5], TKSERV_IRCD_CONF))) || + (!strcmp(args[3], "rehashing") && (!strcmp(args[4], "Server")))) + { + if (tklined) + { + sendto_user("TK-line%s.", (tklined > 1) ? "(s) removed" : " active"); + tklined = 0; + } + } +} + +/* parse the received SQUERY */ +void service_squery(char **args) +{ + char *cmd, *ch; + + nuh = (char *) strdup(args[0] + 1); + cmd = (char *) strdup(args[3] + 1); + + if (ch = (char *) strchr(cmd, '\r')) + *ch = '\0'; + + if (!strcasecmp(cmd, "admin")) + { + sendto_user(TKSERV_ADMIN_NAME); + sendto_user(TKSERV_ADMIN_CONTACT); + sendto_user(TKSERV_ADMIN_OTHER); + } + + else if (!strcasecmp(cmd, "help")) + squery_help(args); + + else if (!strcasecmp(cmd, "info")) + { + sendto_user("This service is featuring temporary k-lines."); + sendto_user("It's available at http://www.snafu.de/~kl/tkserv."); + } + + else if (!strcasecmp(cmd, "quit")) + squery_quit(args); + + else if (!strcasecmp(cmd, "tkline")) + squery_tkline(args); + + else if (!strcasecmp(cmd, "version")) + sendto_user(TKS_VERSION); + + else + sendto_user("Unknown command. Try HELP."); +} + +/* SQUERY HELP */ +void squery_help(char **args) +{ + char *ch, *help_about; + + help_about = args[4]; + + if (help_about && *help_about) + { + if (ch = (char *) strchr(help_about, '\r')) + *ch = '\0'; + + if (!strcasecmp(help_about, "admin")) + sendto_user("ADMIN shows you the administrative info for this service."); + + if (!strcasecmp(help_about, "help")) + sendto_user("HELP shows you the help text for ."); + + if (!strcasecmp(help_about, "info")) + sendto_user("INFO shows you a short description about this service."); + + if (!strcasecmp(help_about, "tkline")) + { + sendto_user("TKLINE adds a temporary entry to the server's k-line list."); + sendto_user("TKLINE is a privileged command."); + } + + if (!strcasecmp(help_about, "version")) + sendto_user("VERSION shows you the version information of this service."); + } + else + { + sendto_user("Available commands:"); + sendto_user("HELP, INFO, VERSION, ADMIN, TKLINE."); + sendto_user("Send HELP for further help."); + } +} + +/* SQUERY TKLINE */ +void squery_tkline(char **args) +{ + int lifetime, i; + char *passwd, *pattern, *host, *ch, *user = "*"; + char reason[TKS_MAXKILLREASON]; + + /* Before we go thru all this, make sure we don't waste our time... */ + if (must_be_opered()) + { + if (!is_opered()) + { + sendto_user("Only IRC-Operators may use this command."); + return; + } + } + + i = 5; + + while (args[i] && *args[i]) + { + if (strchr(args[i], ':')) + { + sendto_user("Colons are only allowed in the password."); + return; + } + + i++; + } + + if (args[5] && *args[5]) + { + if (isdigit(*args[5]) || (*args[5] == '-')) + lifetime = atoi(args[5]); + else + { + sendto_user("The lifetime may only contain digits."); + return; + } + } + else + { + sendto_user("Usage: TKLINE [] "); + return; + } + + /* TKLINE */ + if ((lifetime > 0) && !(args[7] && *args[7])) + { + sendto_user("Usage: TKLINE "); + return; + } + + /* TKLINE (default expiration) */ + if ((lifetime == 0) && !(args[6] && *args[6])) + { + sendto_user("Usage: TKLINE "); + return; + } + + /* TKLINE -1 (removal of tklines) */ + if ((lifetime == -1) && !(args[6] && *args[6])) + { + sendto_user("Usage: TKLINE -1 "); + return; + } + + if ((lifetime >= 768) || (lifetime < -1)) + { + sendto_user(" must be greater than 0 and less than 768."); + return; + } + + /* I don't want to get confused, so all this may be a bit redundant */ + + if (lifetime > 0) + { + passwd = args[4]; + pattern = args[6]; + strcpy(reason, args[7]); + i = 8; + + /* I know... */ + while(args[i] && *args[i]) + { + strncat(reason, " ", TKS_MAXKILLREASON - strlen(reason) - 1); + strncat(reason, args[i], TKS_MAXKILLREASON - strlen(reason) - 1); + i++; + } + + if (ch = (char *) strchr(reason, '\r')) + *ch = '\0'; + } + + if (lifetime == 0) + { + if (!(strchr(args[5], '@') || strchr(args[5], '*') || + strchr(args[5], '.'))) + { + sendto_user(" must be greater than 0."); + return; + } + + passwd = args[4]; + lifetime = 2; /* Default lifetime */ + pattern = args[5]; + strcpy(reason, args[6]); + i = 7; + + while(args[i] && *args[i]) + { + strncat(reason, " ", TKS_MAXKILLREASON - strlen(reason) - 1); + strncat(reason, args[i], TKS_MAXKILLREASON - strlen(reason) - 1); + i++; + } + + if (ch = (char *) strchr(reason, '\r')) + *ch = '\0'; + } + + if (lifetime == -1) + { + passwd = args[4]; + pattern = args[6]; + + if (ch = (char *) strchr(pattern, '\r')) + *ch = '\0'; + } + + + /* Don't allow "*@*" and "*" in the pattern */ + if (!strcmp(pattern, "*@*") || !strcmp(pattern, "*")) + { + sendto_user("The pattern \"%s\" is not allowed.", pattern); + tks_log("%s tried to tkline/untkline \"%s\".", nuh, pattern); + return; + } + + /* Split the pattern up into username and hostname */ + if (ch = (char *) strchr(pattern, '@')) + { + host = (char *) (strchr(pattern, '@') + 1); + user = pattern; + *ch = '\0'; + } + else /* user defaults to "*" */ + host = pattern; + + /* + ** Make sure there's a dot in the hostname. + ** The reason for this being that i "need" a dot + ** later on and that i don't want to perform + ** extra checks whether it's there or not... + ** Call this lazyness, but it also makes the service faster. ;-) + */ + if (!strchr(host, '.')) + { + sendto_user("The hostname must contain at least one dot."); + return; + } + + if (!is_authorized(passwd, host)) + { + sendto_user("Authorization failed."); + return; + } + + if (lifetime == -1) + { + int i; + + i = check_tklines(host, user, lifetime); + sendto_user("%d tkline%sfor \"%s@%s\" found.", i, + (i > 1) ? "s " : " ", user, host); + + if (i > 0) + rehash(2); + } + else + if (!add_tkline(host, user, reason, lifetime)) + sendto_user("Error while trying to edit the "CPATH" file."); +} + +/* SQUERY QUIT +** Each time we receive a QUIT via SQUERY we check whether +** the supplied password matches the one in the conf file or not. +** If not, an error is sent out. If yes, we close the connection to +** the server. +*/ +void squery_quit(char **args) +{ + char *ch; + + if (ch = (char *) strchr(args[4], '\r')) + *ch = '\0'; + + if (!strcmp(args[4], TKSERV_PASSWORD)) + { + tks_log("Got QUIT from %s. Terminating.", nuh); + sendto_server("QUIT :Linux makes the world go round. :)\n"); + } + else + { + sendto_user("I refuse to QUIT. Have a look at the log to see why."); + tks_log("Got QUIT from %s with wrong password. Continuing.", nuh); + } +} + +/**************** End of service command section ***************/ + +int main(int argc, char *argv[]) +{ + + char *host, *port, buffer[TKS_MAXBUFFER], last_buf[TKS_MAXBUFFER]; + char tmp[TKS_MAXPATH]; + + int is_unix = (argv[1] && *argv[1] == '/'); + int sock_type = (is_unix) ? AF_UNIX : AF_INET; + int proto_type = SOCK_STREAM; + int eof = 0; + + struct in_addr LocalHostAddr; + struct sockaddr_in server; + struct sockaddr_in localaddr; + struct hostent *hp; + struct timeval timeout; + + fd_set read_set; + fd_set write_set; + + if ((is_unix) && (argc != 2)) + { + fprintf(stderr, "Usage: %s \n", argv[0]); + fprintf(stderr, " %s \n", argv[0]); + exit(1); + } + else if (argc != 3) + { + fprintf(stderr, "Usage: %s \n", argv[0]); + fprintf(stderr, " %s \n", argv[0]); + exit(1); + } + + if (!strcmp(TKSERV_DIST, "*")) + { + printf("Your service has a global distribution. Please make sure that\n"); + printf("you read the part about the service distribution in the README.\n"); + } + + tks_log("Welcome to TkServ. Lean back and enjoy the show..."); + + if ((fd = socket(sock_type, proto_type, 0)) < 0) + { + perror("socket"); + exit(1); + } + + /* copy the args into something more documentable */ + host = argv[1]; + + if (!is_unix) + port = argv[2]; + + /* Unix domain socket */ + if (is_unix) + { + struct sockaddr_un name; + memset(&name, 0, sizeof(struct sockaddr_un)); + name.sun_family = AF_UNIX; + strcpy(name.sun_path, host); + + if (connect(fd, (struct sockaddr *) &name, strlen(name.sun_path) + 2) == -1) + { + perror("connect"); + close(fd); + exit(1); + } + } + + memset(&localaddr, 0, sizeof(struct sockaddr_in)); + localaddr.sin_family = AF_INET; + localaddr.sin_addr = LocalHostAddr; + localaddr.sin_port = 0; + + if (bind(fd, (struct sockaddr *) &localaddr, sizeof(localaddr))) + { + perror("bind"); + close(fd); + exit(1); + } + + memset(&server, 0, sizeof(struct sockaddr_in)); + memset(&LocalHostAddr, 0, sizeof(LocalHostAddr)); + + if (!(hp = gethostbyname(host))) + { + perror("resolv"); + close(fd); + exit(1); + } + + memmove(&(server.sin_addr), hp->h_addr, hp->h_length); + memmove((void *) &LocalHostAddr, hp->h_addr, sizeof(LocalHostAddr)); + server.sin_family = AF_INET; + server.sin_port = htons(atoi(port)); + + if (connect(fd, (struct sockaddr *) &server, sizeof(server)) == -1) + { + perror("connect"); + exit(1); + } + + /* register the service with SERVICE_WANT_NOTICE */ + sendto_server("PASS %s\n", TKSERV_PASSWORD); + sendto_server("SERVICE %s localhost %s 33554432 0 :%s\n", TKSERV_NAME, TKSERV_DIST, TKSERV_DESC); + sendto_server("SERVSET 33619968\n"); + + timeout.tv_usec = 1000; + timeout.tv_sec = 10; + + /* daemonization... i'm sure it's not complete */ + switch (fork()) + { + case -1: + perror("fork()"); + exit(3); + case 0: + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); + if (setsid() == -1) + exit(4); + break; + default: + return 0; + } + + /* listen for server output and parse it */ + while (!eof) + { + FD_ZERO(&read_set); + FD_ZERO(&write_set); + FD_SET(fd, &read_set); + + if (select(FD_SETSIZE, &read_set, &write_set, NULL, &timeout) == -1) + { + perror("select"); + } + + if (!server_output(fd, buffer)) + { + printf("Connection closed.\n"); + printf("Last server output was: %s\n", last_buf); + eof = 1; + } + + strcpy(last_buf, buffer); + parse_server_output(buffer); + } + + close(fd); + + exit(0); +} +/* eof */ diff --git a/doc/2.10-New b/doc/2.10-New new file mode 100644 index 0000000..8903783 --- /dev/null +++ b/doc/2.10-New @@ -0,0 +1,18 @@ + * +a (away) user mode + This user mode is used to propagate users' away status between + servers. + + * added channel mode +e (exceptions to bans). + * added channel mode +I (invitations). + * invites can now be used to override channel bans and limit. + * banned users cannot speak on channel without +o/+v. + * ! channels introduced (can't be collided); + A quite detailed technical description can be found on the web: + http://www.stealth.net/~kalt/irc/channel.html + + * NJOIN for 2.10 <-> 2.10 communication on connect bursts instead of + the combined JOIN/MODE introduced by 2.9 (and now deprecated) + + * a slave process is now used to authenticate incoming connections. + The slave's modular design makes it easy to add new authentication + modules. diff --git a/doc/2.9-New b/doc/2.9-New new file mode 100644 index 0000000..17d78e2 --- /dev/null +++ b/doc/2.9-New @@ -0,0 +1,60 @@ + * +a (anonymous) channel mode + + This channel mode is only allowed on &local channels. + + * +s user mode removed; + * &KILLS, &NOTICES, &ERRORS, &CHANNEL, &HASH, &NUMERICS, &SERVERS + channels created and used by the server for server notices + (comments on what goes where please) and dividing notices up this + way was better than using more user modes (they default to the + server being on them and +amnt); + + &KILLS : server and oper KILLS + &NOTICES : warnings and notices + &ERRORS : server errors + &LOCAL : notices concerning local clients. + &CHANNEL : fake modes + &HASH : hash tables growth + &NUMERICS : numerics received by the server + &SERVERS : servers joining and leaving the net + + * + channels reintroduced (can't have modes); + * Config doesn't prompt for cc/includes/libs; + * M-line doesn't define port, PORTNUM removed from config.h (must use + P-lines or use inetd); + * BIND 4.9.2 libresolv stuff included; + * USERHOST will return as many id's as requested. + * RECONNECT to pickup error'd sserver-server links (not activated) + * chooses next bigger prime for hash table sizes rather than + needing exact primes + * hash tables grow to suit rather than being static in size + * adaptive growth of sendq (suggested by msa) + * Server parameter in USER message tokenised betweem 2.9 servers + * whowas tables grow to suit rather than being static in size + * NICK+USER+UMODE combined into NICK for 2.9 <-> 2.9 communication + * MODE +ov and JOIN combined into JOIN for 2.9 <-> 2.9 communication + on connect bursts + * QUIT removed when possible for 2.9 <-> 2.9 communication on split + * autoconf'iscated ircd. + * userlog has single character appended to show cause of quit. + * i lines (user mode +r) + + i lined users have a restricted access: They are forbidden + MODE, KICK and TOPIC on #channels. They don't get channel + operator status when creating a #channel, and cannot + change their nickname once connected. + + * enhanced nick delay to prevent collisions + + The nickname of users splitting away is locked for 15 minutes, + and cannot be used by local clients. + + * channel history to prevent op riding + + A user with channel operator status on #foo splitting away + means that no local user can re-create the channel #foo during + the next 15 minutes. It doesn't stop users from using #foo as + as the channel is not empty. + +Some transition documentation from 2.8 to 2.9 version can be found in + http://www.irc.org/~irc/server/ diff --git a/doc/Authors b/doc/Authors new file mode 100644 index 0000000..07f8ee0 --- /dev/null +++ b/doc/Authors @@ -0,0 +1,180 @@ +/************************************************************************ + * IRC - Internet Relay Chat, doc/AUTHORS + * Copyright (C) 1990 + * + * AUTHORS FILE: + * This file attempts to remember all contributors to the IRC + * developement. Names can be only added this file, no name + * should ever be removed. This file must be included into all + * distributions of IRC and derived works. + * + * 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. + */ + +The email addresses listed in here may or may not be up to date. + +IRC was conceived of and written by Jarkko Oikarinen . +IRC was originally written in University of Oulu, Computing Center. +Jan 1991 - IRC 2.6 jto@tolsun.oulu.fi + - Multiple Channels and protocol changes + +Contributions were made by a cast of dozens, including the following: + +Markku Jarvinen : Emacs-like editing facility for the client + +Kimmo Suominen : HP-UX port + +Jeff Trim : enhancements and advice + +Vijay Subramaniam : advice and ruthless publicity + +Karl Kleinpaste : user's manual + +Greg Lindahl : AUTOMATON code, the Wumpus GM automaton, +myriad bug fixes + +Bill Wisner : numerous bug fixes and code +enhancements + +Tom Davis and Tim Russell : +VMS modifications + +Markku Savela : advice, support, and being the +incentive to do some of our *own* coding. :) + +Tom Hopkins : bug fixes, quarantine lines, +consolidation of various patches. + +Christopher Davis : EFnet/Anet gateway coding, +many automata ;), documentation fixing. + +Helen Rose : documentation updating, and fixing. + +Tom Hinds : emacs client updating. + +Tim Miller : various server and client-breaking +features. + +Darren Reed : various bug fixes and enhancements. +Introduced nickname and channelname hash tables into the server. + +The version 2.2 release was coordinated by Mike Bolotski +. + +The version 2.4 release was coordinated by Markku Savela and +Chelsea Ashley Dyerman + +The version 2.5.2 release was coordinated by Christopher Davis, Helen Rose, +and Tom Hopkins. + +The versions 2.6.2, 2.7, 2.8 and 2.9 releases were coordinated by Darren Reed. + +Contributions for the 2.8 release from the following people: +Matthew Green +Chuck Kane +Matt Lyle +Vesa Ruokonen + +Markku Savela / April 1990 +Fixed various bugs in 2.2PL1 release server (2.2msa.4) and changed +sockets to use non-blocking mode (2.2msa.9). [I have absolutely +nothing to do with clients :-] + +Chelsea Ashley Dyerman / April 1990 +Rewrote the Makefiles, restructuring of source tree. Added libIrcd.a to +the Makefile macros, numerous reformatting of server text messages, and +added mkversion.sh to keep track of compilation statistics. Numerous +bug fixes and enhancements, and co-coordinator of the 2.4 release. + +jarlek@ifi.uio.no added mail functions to irc. + +Armin Gruner / May, June 1990: +* Patched KILL-line feature for ircd.conf, works now. + Enhancement: Time intervals can be specified in passwd-field. + Result: KILL-Line is only active during these intervals +* Patched PRIVMSG handling, now OPER can specify masks for sending + private messages, advantage: msg to all at a specified server or host. +* Little tests on irc 2.5 alpha, fixed some little typos in client code. + Change: common/debug.c has been moved to ircd/s_debug.c, and a + irc/c_debug.c has been created, for the benefit that wrong server msg + are displayed if client does not recognize them. (strange, if a server + sends an 'unknown command', isn't it?) + +Tom Hopkins / September, October 1990: +* Patched msa's K lines for servers (Q lines). +* Consolidated several patches, including Stealth's logging patch. +* Fixed several minor bugs. +* Has done lots of other stuff that I can't seem to remember, but he + always works on code, so he has to have done alot more than three + lines worth. :) + +Various modifications, bugreports, cleanups and testing by: + +Hugo Calendar +Bo Adler +Michael Sandrof +Jon Solomon +Jan Peterson +Nathan Glasser +Helen Rose +Mike Pelletier +Basalat Ali Raja +Eric P. Scott +Dan Goodwin +Noah Friedman + +The 2.9 release brought many improvements to the protocol: adaptive growth +of sendq, hash tables, whowas table, extended NICK syntax, server tokens, +extended JOIN syntax, restricted usermode, nick and channel delay, +suppression of server-server QUITs during splits, suppression of usermode s.. + +Contributions for the 2.9 release from the following people: +Vesa Ruokonen : V configuration lines, many bug fixes. +Christophe Kalt : nick and channel delay, suppressed QUITs +during netsplits, many bug fixes. + +The versions 2.9.3, 2.9.4, 2.9.5 releases were coordinated by Christophe Kalt. + +Christophe Kalt : server link compression using zlib, added +B configuration lines, extended IP bans and K lines to work on resolved hosts, +finished service code, virtual IP support. + +Various modifications, bugreports, cleanups and testing by: + +Chris Behrens +Helmut Springer +Magnus Tjernstrom +Olivier Galibert : service code testing +Alain Nissen : source tree restructuration, many +portability issues, new configure.in +Roar Thronæs added IPv6 support + +The versions 2.10 releases were coordinated by Christophe Kalt. + +Christophe Kalt : added channel modes e and I, designed and +implemented !channels, brought away status back to life, added NJOIN message, +made invitation override bans, wrote iauth. + +Various modifications, bugreports, cleanups and testing by: + +Helmut Springer +Michael 'Eumel' Neumayer +Kurt Roeckx cleaned up the compression code, among many things +Roar Thronæs for more IPv6 work +Piotr Kucharski for his work on the anti socks module +Michal Svoboda removed useless anUser linked list + +Thanks go to those persons not mentioned here who have added their advice, +opinions, and code to IRC. diff --git a/doc/BUGS b/doc/BUGS new file mode 100644 index 0000000..32e914f --- /dev/null +++ b/doc/BUGS @@ -0,0 +1,13 @@ +# @(#)$Id: BUGS,v 1.14 1999/03/07 22:59:31 kalt Exp $ + +The list is probably not as scary as it once was. +Anyone with some free time is welcome to fix those =) + +* The server still occasionnally crashes because of some bug + in the hash tables. (Vesa already fixed this bug several + times but it keeps crashing :^) + +* RECONNECT is still in some unknown state. (and deactivated + for various reasons) + +* The operator count showed by /LUSERS becomes incorrect (negative). diff --git a/doc/ChangeLog b/doc/ChangeLog new file mode 100644 index 0000000..9869542 --- /dev/null +++ b/doc/ChangeLog @@ -0,0 +1,1956 @@ +2.10.3 + +1999-08-13 Christophe Kalt + + * channel.c/match_modeid(): logic fix (reported by Michal Svoboda). + + * os.h: added YET ANOTHER KLUDGE for linux and poll(). + + * ircd.c: assume "-s" option in CYGWIN environment. + + * configure.in: update for CYGWIN environment. + +1999-08-13 Piotr Kucharski + + * mod_socks.c/socks_read(): allow more methods in socks5 check. + +1999-08-01 Piotr Kucharski + + * ircd.c/bad_command(): -d command line option no longer exists, + while -s was added. + +1999-07-28 Christophe Kalt + + * struct_def.h: IsChannelName() macro cannot use cid_ok() for the + client. + + * channel.c/m_njoin(): inverse condition prevented modes from + being sent to users and 2.9 servers. + +1999-07-27 Piotr Kucharski + + * s_id.c/cid_ok(): quite unfortunate typo which made joining + !channels impossible (from Michal Svoboda). + +1999-07-25 Christophe Kalt + + * channel.c: sanity checks to drop modes on +channels even when + received from servers (from Michal Svoboda). + + * struct_def.h, channel.c, s_id.c: added checks to ensure !name + validity (from Michal Svoboda). + +1999-07-23 Christophe Kalt + + * s_bsd.c/inetport(): fixed test for IPv6 (from KIKUCHI Takahiro). + + * ircd.c: + * better casting for sbrk() for OSF 4.0. + * setup_me(): fixed syntax for IPv6. + +1999-07-21 Piotr Kucharski + + * channel.c/set_mode(): send ERR_UNKNOWNMODE to 'mode O' issued + on non-!channels. + +1999-07-21 Christophe Kalt + + * s_misc.c/exit_one_client(): generate fake PARTs for users + quitting anonymous channels. + + * send.c/sendto_common_channels(): skip anonymous channels. + + * Makefile.in: ircdwatch needs clsupport.o which needs clmatch.o. + + * channel.c: added notices to warn users about +a channels. + +1999-07-20 Kurt Roeckx + + * channel.c: + * m_njoin: send +v for uniqops in the right case + * send_channel_members: send +v inside njoin for ops too + * m_invite: send back numerics if the channel doesn't exist + +1999-07-18 Piotr Kucharski + + * channel.c/set_mode(), m_kick(): send ERR_NOTONCHANNEL, not + ERR_CHANOPRIVSNEEDED, thus disable stealth secret channel probing; + furthermore, use rather sptr->name, not parv[0] in sending errors; + +1999-07-17 Christophe Kalt + + * ircd.c/setup_me(), s_bsd.c: fixed that really old bug about the + I line format to match connections received on the loopback + interface (from Eugene L. Vorokov). + + * configure.in: fixed previous changes about poll() (reported by + KIKUCHI Takahiro). + +1999-07-17 Kurt Roeckx + + * s_user.c/m_kill(): killer could end up < path + +1999-07-14 Christophe Kalt + + * configure.in, os.h: use ncurses.h (from KIKUCHI Takahiro). + + * configure.in: SunOS has poll(), but we don't want to use it + (reported by KIKUCHI Takahiro). + + * mod_lhex.c: replaced strtoul() with sscanf(). + +1999-07-11 Christophe Kalt + + * a_defines.h was missing support_def.h (from KIKUCHI Takahiro). + + * Makefile.in: ircdwatch.c uses strerror(), needs clsupport.o + (from KIKUCHI Takahiro). + + * config.h.dist, ircd.c, s_debug.c: renamed CONNECTTIMEOUT to + ACCEPTTIMEOUT, and changed from 30 to 90. + +1999-07-11 Piotr Kucharski + + * mod_socks.c: + * socks_write(): a typo made iauth allow open proxies and + caused a lot of BADPROTO warnings (from KIKUCHI Takahiro). + * socks_init(): buffer overflow with tmpbuf[] being too + small to hold too many iauth options (also from Takahiro). + +1999-07-09 Christophe Kalt + + * configure.in, os.h, s_bsd.c: IPv6 updates (from KIKUCHI Takahiro). + +1999-07-05 Christophe Kalt + + * s_bsd.c/read_message(): can't use iauth_options when USE_IAUTH + is undefined. + +1999-07-05 Piotr Kucharski + + * channel.c/m_invite(): invite to :-channels was sometimes + lost with no error. + +1999-07-04 Christophe Kalt + + * a_conf_def.h, a_conf.c, a_io.c: added the "timeout" option. + + * mod_socks.c: added PROXY_BADPROTO & OPT_PROTOCOL to + differentiate between unexpected and bad protocol. + + * s_id.c: fixed alphabet_id[] (noted by Michal Svoboda), and + rewrote some code. + +1999-07-04 Piotr Kucharski + + * s_user.c/m_nick(): fix performance bug introduced in code + preventing insidious collisions + + * mod_socks.c/socks_open_proxy(): now reports in logs versions + of open proxies found + +1999-07-02 Kurt Roeckx + + * configure.in, Makefile.in: Added -I for inet6. + +1999-07-02 Christophe Kalt + + * res.c/proc_answer(): portability fix from hybrid6. + + * send.c/sendto_match_butone(): finally looked closely at why this + was sending $*.mask to the wrong servers, fixed. + + * struct_def.h, send.c/sendto_match_butone(), list_ext.h, + list.c/make_client(), ircd.c/setup_me(), s_misc.c/exit_client(), + s_serv.c, s_service.c/m_service(), s_user.c/m_user(): removed old + code conditional to NO_USRTOP being undefined. + + * s_user.c: + * m_nick(): new delay on nicks to prevent insidious + collisions (from Piotr Kucharski). + * m_private(): dropped restrictions on mass msg/notices. + + * s_auth.c/read_authports(): can't call set_clean_username with + ->auth pointing to ->username (from Piotr Kucharski). + + * mod_socks.c: couple typos. + + * a_conf.c/conf_read(): ->popt wasn't initialized. + +1999-06-27 Christophe Kalt + + * s_misc.c/exit_one_client(): made BETTER_NDELAY a little more + friendly (from Piotr Kucharski). + + * a_io.c/sendto_ircd(): added error output in write error notice. + + * hash.c/hash_channel_name(): added shortname parameter to disable + guess and fix bug (From Q). + + * channel.c/m_join(): reject local user join for duplicates. + + * mod_socks.c: more options, less bugs (from Piotr Kucharski). + + * s_user.c: + * m_nick(): kill nicks introduced by server if parc != 8 + instead of simply sending a notice. + * register_user(): static variable wasn't declared as such. + + * ircd.c, s_serv.c: used mybasename(); + + * support_ext.h, support.c: added mybasename(); + +1999-06-20 Christophe Kalt + + * mod_socks.c: added code to allow checks for v5 as well as v4, + depending on configuration (from Piotr Kucharski). + + * configure.in, ircd.c/ircd_writetune(), s_serv.c/m_rehash(): use + basename, and check if it needs libgen. + + * channel.c/m_njoin(): simple optimization resulting from change + to sendto_match_servs_notv() below. + + * send_ext.h, send.c: sendto_serv_{not,}v and + sendto_match_servs_{not,}v now return an integer. + +1999-06-16 Christophe Kalt + + * iauth.c/main(): send version to ircd upon startup. + + * mod_rfc931.c/rfc931_work(): removed checks on weird chars, let + ircd deal with this. + + * s_auth.c: + * start_auth(): abort if getpeername() fails (problem + reported by Wolfgang Scherer). + * added set_clean_username(), used in read_iauth() and + read_authports(). + * read_iauth(): added o message (a->i). + * read_iauth(): added V message (a->i). + + * struct_def.h, s_serv.c: added SV_OLDSQUIT, and made m_squit() + smarter (ugh, it's a kludge). + +1999-06-07 Christophe Kalt + + * s_user.c: + * m_nick(): added notice to warn of NICK messages coming + from servers with parc != 8. + * register_user(): fixed unaccurate notices about iauth. + + * config.h.dist: increased HANGONRETRYDELAY & HANGONGOODLINK values. + +1999-06-06 Christophe Kalt + + * struct_def.h, send.c/sendto_match_butone(), list_ext.h, + list.c/make_client(), ircd.c/setup_me(), s_misc.c/exit_client(), + s_serv.c, s_service.c/m_service(), s_user.c/m_user(): added + reorder_client_list() and NO_USRTOP defines. This reduces memory + usage (Original code from Michal Svoboda). + + * channel.c/reop_channel(): desynched could be caused by server + reops (channel mode +r) (reported by Thomas Kuiper). + +1999-05-01 Christophe Kalt + + * s_conf_ext.h, s_conf.c, s_serv.c: added a new list for K/k lines + only as an easy way to improve overall performance. + + * service_def.h: updated SERVICE_MASK_ALL. + +1999-04-19 Christophe Kalt + + * channel.c/m_njoin(): need to use sendto_match_servs*(); duh! + + * send_ext.h, send.c: added sendto_match_servs_notv(). + + * s_serv.c/m_squit(): fixed logic in previous change. + + * packet.c/dopacket(): fixed uncompression code. + +1999-04-15 Christophe Kalt + + * service_def.h, channel.c/m_topic(), s_service.c/m_servset(): + added SERVICE_WANT_TOPIC. + + * s_serv.c/m_squit(): fixed serious and old bug that caused + servers to be removed from memory (but not dependants!!!) while + squit is going upstream. + + * s_debug.c/send_usage(): divide by zero bugfix (reported by Aaron + Campbell). + + * channel.c/m_njoin(): ignore channels with an invalid mask. + + * common/parse.c: extended MSG_NOU to include services. + +1999-04-10 Christophe Kalt + + * Makefile.in, a_conf_def.h, a_externs.h, a_conf.c, mod_lhex_ext.h, + mod_lhex.c: New module (from Andrew Snare). + + * s_debug.c: increased size of debugbuf[] to avoid overflows (from + Eugene L. Vorokov). + + * send.c/send_message(): catch more unlikely errors (from Eugene + L. Vorokov). + + * s_bsd.c/set_sock_opts(): silently ignore errors for SO_SNDLOWAT. + + * common/os.h: FreeBSD portability (from KIKUCHI Takahiro). + + * s_bsd.c/read_message(): + * debug notice format bugfix (from Q). + * INET6 fix (from KIKUCHI Takahiro). + + * s_conf.c: + * initconf(): allow service type to be in hex in the + configuration (from Thomas Kuiper). + * find_conf_flags(): case sensitivity fix (from Q). + +1999-03-19 Christophe Kalt + + * mod_socks.c/socks_work(): closed proxies would get rejected on + first attempt and accepted later as the "closed" status was in the + cache. + + * s_user.c/register_user(): fixed iauth failure notice timing bug. + +1999-03-13 Christophe Kalt + + * struct_def.h, ircd.c, s_auth.c, s_bsd.c, s_user_ext.h, s_user.c, + a_struct_def.h, iauth.c, a_conf.c, a_io.c: added XOPT_EARLYPARSE, + `P' message for iauth, `extinfo' option for iauth. + + * a_io.c/next_io(): if xxx_start() returns 1, count module as left. + +1999-03-11 Christophe Kalt + + * chkconf.c: + * finally shut off MyFree() redefinition warning. + * fixed undefined behaviour with ++ operator (effet de bord). + + * a_io.c/init_io(): bzero bugfix (reported by Tomas Edwardsson). + + * a_conf_def.h, a_conf.c: + * conf_err(): send conf errors to ircd as well. + * conf_match(): extended iauth.conf syntax for hostname + and IP matching. + * added conf_ipmask() to allow use of a.b.c.d/z format for IP. + + * configure.in: use "cc -Ae" on HPUX (reported by Jens Riecken). + + * ircd.c/main(): iauth's presence needs to be checked before + setting up the signal handlers. + +1999-03-09 Christophe Kalt + + * a_struct_def.h, a_conf_ext.h, a_conf_def.h, a_conf.c, a_io.c, + mod_pipe.c, mod_rfc931.c, mod_socks.c: rewrote next_io() and + conf_match() to use new more flexible logic. + + * os.h, a_conf.c, iauth.c, configure.in, Makefile.in, acconfig.h: + added DSM support. + +1999-03-08 Christophe Kalt + + * struct_def.h, a_conf.c, a_conf_ext.h, iauth.c, ircd.c, s_auth.c, + s_auth_ext.h, s_bsd.c, s_user.c, s_user_exit.c: added + XOPT_{REQUIRED,NOTIMEOUT,EXTWAIT}, added iauth_spawn counter; + removed iauth_required variable. + + * struct_def.h, s_auth.c, s_user.c: added FLAGS_DONEXAUTH to get + rid of the approximation from yesterday. + + * s_bsd.c/read_message(): use CLR_READ_EVENT() before modifying fd. + +1999-03-07 Christophe Kalt + + * res_comp.c: added missing prototypes. + + * struct_def.h, a_conf.c, a_conf_ext.h, iauth.c, s_auth_ext.h, + s_auth.c, s_user.c: added option to reject new user connections if + iauth is dead (approximate!). + + * struct_def.h, ircd.c, res.c, s_auth.c, s_bsd.c: removed all + references to {Set,Clear,Do}Access macros (unused for a LONG time). + + * ircd.c: + * check_pings(): fixed "immediate ping timeout" bug. + * main(): check for iauth's presence after changing [ug]id. + + * s_bsd.c/do_dns_async(): notify iauth when no PTR record is found. + + * Makefile.in: fix for M4 file path (Matthew Sullivan). + +1999-03-04 Christophe Kalt + + * ircd.c/io_loop(), s_bsd.c/start_iauth(): keep trying to restart + iauth (up to once every 90 seconds) to avoid being iauth-less. + + * struct_def.h, mod_socks.c, s_auth.c, s_user.c: added new message + type from iauth to ircd to allow denying connections without any + message sent to &AUTH; used by the socks module. + +1999-02-22 Christophe Kalt + + * s_err.c: RPL_TRACESERVICE changed to show values in hexadecimal + (from Thomas Kuiper). + + * s_service.c/m_service(): fixed error message. + +1999-02-20 Christophe Kalt + + * configure, configure.in, Makefile.in, config.h.dist, buildm4, + send.c, ircd.c, s_bsd.c, s_conf.c, s_misc.c, s_serv.c, s_user.c, + chkconf.c, a_conf.c, a_log.c: paths overhaul. + + * c_msg_ext.h, c_msg.c: fixed m_server() prototype. + +1999-02-19 Kurt Roeckx + + * packet.c/dopacket(), s_bsd.c/read_packet(): bugfix. + +1999-02-18 Christophe Kalt + + * res.c/proc_answer(): fixed T_PTR processing (problem reported by + Michal Svoboda). + + * channel.c: + * del_modeid(): bugfix when called with NULL. + * can_join(): readability (from Q). + + * s_serv.c/check_version(): + * removed code about 2.10.0[ab]*. + * never used NJOIN with 0209* servers (bugfix). + + * s_err.c: removed extraneous %s in RPL_UNIQOPIS. + +1999-02-09 Kurt Roeckx + + * hash.c/hash_find_channels(): cleanup. + + * ircd.c/main(), ircd_ext.h: various cleanups. + + * res_comp_ext.h: added prototype for ircd_getshort(). + + * s_bsd.c/read_message(): typo fix (=! -> !=). + + * s_conf.c/attach_conf(): stops detecting listen sockets as + clients from same IP address. + + * s_err.c: removed / from replies. + + * s_serv.c/m_links(): removed unused variable. + + * s_user.c/who_channel(): removed unused variables. + +1999-02-05 Christophe Kalt + + * match.c/match(): removed predictable if's (from Tero Jänkä). + + * s_serv.c/m_server_estab(): flush_connections() called once + during burst. + + * s_debug.c: updated. + + * ircd.c/io_loop(), s_bsd.c/read_message(), s_bsd_ext.h, config.h: + new logic inspired from irce, removed PREFER_SERVER. + + * s_bsd.c: + * added read_listeners(). + * set_sock_opts() now sets SO_SNDLOWAT. + * add_connection() now sends a message to client being + reject by the anti-clone crap. + + * send.c: added flush_fdary() function. + + * common_def.h, config.h, send.c: removed SENDQ_ALWAYS define, + simplified code for when it was undefined as it is only used by + the client now. + +2.10.2 + +1999-02-03 Christophe Kalt + + * mod_rfc931.c/rfc931_work(): get rid of any \n in replies. + + * a_io.c/parse_ircd(): when receiving a "DNS timeout" message, + inform ircd if we're already done (otherwise, it keeps waiting + until timeout). + + * s_bsd.c/completed_connection(): tell iauth not to wait for DNS + information for servers we connect to. + + * s_auth.c/read_iauth(): + * fixed "Garbage" notices to &AUTH. + * send E message to iauth when parsing garbage. + +1999-01-28 Christophe Kalt + + * s_serv.c/m_server_estab(): added notices to &DEBUG. + + * struct_def.h, s_auth.c: renamed MotdItem to LineItem and moved + around some defines. + + * s_bsd_ext.h: added missing ';' for utmp_open() definition. + + * channel.c/m_list(): !shortname now reports +p/+s channels (but + still hides member count and topic for +s channels). + + * match.c/match(): rearranged if test to suppress harmless read + overflow errors (reported by Insure++). + + * s_user.c/m_nick(): lp needs to be initialized (reported by Insure++). + + * hash.c/hash_find_channels(): bugfix (spottoed by Q). + + * mod_rfc931.c/rfc931_init(): fix for a silly bug (from Piotr). + +1999-01-19 Christophe Kalt + + * resolv_def.h, res_comp.c, res_init.c: updated (BIND 4.9.7-REL). + + * packet.c/dopacket(): don't call unzip_packet() without data at + beginning of connection only! (from Q). + + * numeric_def.h, s_err.c, channel.c: added numerics RPL_UNIQOPIS + (325), ERR_BANLISTFULL (478) and ERR_UNIQOPPRIVSNEEDED (485). + + * channel.c: + * m_njoin(): missing return value (reported by Insure++). + * m_mode(): use ERR_RESTRICTED for restricted clients. + * m_join(): it's now possible to create !!#foo if #foo exists. + * m_list(): now works for !shortname. + + * hash_ext.h, hash.c: added hash_find_channels(). + + * configure.in, os.h: + * update for autoconf 2.13. + * let's trust autoconf to decide to use poll() or not. + + * s_bsd.c: sendto_flags() doesn't exist, it's sendto_flag(). + + * mod_rfc931.c: + * stats weren't initialized. + * added undocumented "protocol" option (it's boring!). + + * mod_socks.c: + * fixed never occuring memory leak. + * improved stats (from Piotr Kucharski). + + * s_user_ext.h, s_user.c, s_service.c: added a parameter to + do_nick_name() [UID]. + +1999-01-12 Christophe Kalt + + * a_log_def.h, mod_pipe_ext.h, a_externs.h, mod_pipe.c, a_conf.c: + finally wrote the pipe module. + + * struct_def.h, a_conf_def.h, a_io_ext.h, iauth.c, mod_rfc931.c, + mod_socks.c, s_auth.c, s_auth_ext.h, s_misc.c: iauth now sends + statistics to ircd, shown by /stats t. + + * a_conf_def.h, a_conf.c, a_log_def.h, mod_socks.c: SOCKS module + overhaul: added caching, rewrote code to use v4 instead of v5, and + to be smarter (Based on work from Piotr Kucharski). + + * s_user.c: do_nick_name() now rejects "anonymous". + + * packet.c/dopacket(): don't call unzip_packet() without data. + + * channel.c: extension to del_modeid() from Kaspar Landsberg. + + * s_bsd.c: don't call dopacket() again for compressed links just + because the output buffer was filled up. + +1998-12-31 Christophe Kalt + + * ircd.c: removed extraneous flush_connections() call in io_loop(). + + * ircd.c, s_bsd.c, list.c, list_ext.h: removed unused 'active' code. + + * struct_def.h, parse.c: removed various unused aClient fields. + +1998-12-24 Christophe Kalt + + * s_service.c: using FLAGS_CBURST for services has too many + implications; reverted. + + * struct_def.h, s_bsd.c, s_zip.c: removed requirement for + inflate() to never fill up the uncompression output buffer, an + unlikely situation which is now dealt with. (mostly from Q). + +1998-12-21 Christophe Kalt + + + * s_user.c: + * [RFC] suppressed an error reply for notices in m_message(). + * server notices to +n channels were failing. (Reported by Q). + + * a_defines.h: INET6 fix for OSF (from Roar Thronæs). + + * os.h: INET6 fix for OSF (from Roar Thronæs). + + * channel.c: added check against 'duplicate joins' in m_njoin(). + +1998-12-14 Christophe Kalt + + * channel.c: + * yet another +a/+r fix in set_mode(). + * send_channel_modes() would occasionnally send duplicate + bans. (Reported by Robert Martin-Legene ) + + * iauth.c, a_io.c: added nonexistant INET6 code. + + * os.h, nameser_def.h, resolv_def.h: OSF portability fix from Roar + Thronæs. + + * s_auth.c: added missing INET6 code. (Roar Thronæs) + +1998-09-25 Christophe Kalt + + * configure.in: Check for IPv6 system type and update $LIBS (from + KIKUCHI Takahiro ) + + * bsd.c, os.h, parse.c, struct_def.h, support.c, support_ext.h, + c_bsd.c, c_version.c, c_version_ext.h, irc.c, swear.c, channel.c, + chkconf.c, ircd.c, nameser_def.h, res.c, res_def.h, res_init.c, + resolv_def.h, s_auth.c, s_bsd.c, s_conf.c, s_debug.c, s_misc.c, + s_serv.c, s_user.c, acconfig.h, configure.in: merged 2.9.5+IPv6. + +1998-04-12 Christophe Kalt + + * configure.in, s_debug.c: vsyslog() isn't necessarely available + even if USE_STDARG is defined. (Digital Unix) + +1998-04-04 Christophe Kalt + + * c_version_ext.h, c_version.c, irc.c, swear.c: Digital Unix 4.0B + port (Roar Thronæs ) + +1998-12-12 Christophe Kalt + + * channel.c: +a/+r fix for !channels. + +1998-11-20 Christophe Kalt + + * irc.c: allocate me.info (fix by Helmut Franzke ). + +2.10.1 + +1998-11-12 Christophe Kalt + + * Doc references to @stealth.net changed to @irc.org. + + * s_serv.c: report_ping() now sends some extra info to &DEBUG. + + * s_bsd.c: send_ping() window set to 20 minutes (instead of 10), + and never close it. + +1998-11-03 Christophe Kalt + + * s_serv.c: changed m_trace() to only show unknowns to opers and + local clients. + + * a_io.c: fd remap processing bugfix (from Q@ping.be). + + * s_bsd.c: fixed ircd/iauth problem with servers ircd connects to. + +1998-10-31 Christophe Kalt + + * parse.c: reordered msgtab[]. + + * s_serv.c: added more restrictions to m_links(), m_stats() [t], + m_motd() and m_lusers() for remote clients. (*sigh*) + + * channel.c: fixed count_channels() not to count empty channels. + +1998-10-28 Christophe Kalt + + * s_user.c: optimized m_whois() (pointed out by several people). + + * s_user.c, channel.c: channel creator flag is now removed on -o. + + * channel.c: + * !channel creation is now done with !! rather than !#. + * fixed channel counters (affects /lusers & /stats z). + * m_njoin(): simple optimization. + +Sat Oct 10 18:55:38 1998 Christophe Kalt + + * a_io.c: don't TST_* if cldata[i].?fd <= 0 in loop_io(). + + * ircd.s, s_auth.c, s_bsd.c, s_bsd_ext.h: always attempt to + restart iauth in start_iauth() after receiving a SIGUSR1. + + * s_service.c: reverted part of last change. + + * s_user.c: last change introduced a bug. (typo, reported by N. Aust) + + * channel.c: fixed match_modeid() to handle remote clients + properly now that it's used from can_send(). + +Thu Oct 8 18:33:50 1998 Christophe Kalt + + * configure.in: always compile with -g flag, and never strip. + + * channel.c: + * renamed sub1_from_channel() to free_channel(). + * always send modes for empty channels during netjoin. + * fixed old (2.9.x) memory leak in collect_channel_garbage(). + + * s_id.c: + * linked list corruption bugfix in collect_chid(). + * added logic to avoid excessive caching in cache_chid(). + + * s_service.c: stdarg bugfix in check_service_butone (from O.G.). + +Sun Sep 27 15:12:53 1998 Christophe Kalt + + * s_user.c: prefix bugfix (reported by mrg). + +2.10.0p1 + +Fri Sep 25 22:21:06 1998 Christophe Kalt + + * channel.c: check for +r mode before calling reop_channel(). + +2.10.0 + +Wed Sep 23 19:55:14 1998 Christophe Kalt + + * configure.in, os.h: don't trust poll() to work if it exists. + + * channel.c: + * removed FULLV2_10 ifdef's + * don't send empty NJOIN in m_njoin() (Reported by Beeth). + + * channel.c, s_debug.c, config.h.dist: removed MIRC_KLUDGE. + + * chkconf.c: added warning about old V line format. + + * config.h.dist: OPER_DIE is now defined by default. + + * s_user.c: reverted last change, and hostnames are now truncated. + + * os.h: preprocessor syntax fix. + + * s_conf.c: stupid typo in match_ipmask(). + + * s_auth.c: added a new debugging notice. + + * s_debug.c: flags update. + + * ircd.c: + * added some debugging info in restart notice. + * changed strdup() in mystrdup() (from Andrew Snare). + +Sun Sep 20 15:22:25 1998 Christophe Kalt + + * os.h, configure.in: configure now checks for poll() existence to + decide if it should be used. + + * res_init.c, s_conf.c: strncpy() bugfixes (from Q). + + * s_auth.c, mod_rfc931.c: '[' is no longer allowed in ident replies. + + * channel.c: don't let chanops set +a on !channels. + + * a_io.c: (weirdbug)fix. + + * s_err.c: numeric 004 update. + + * s_user.c: connections rejected by iauth are now shown as K-lined + in &LOCAL. + + * s_bsd.c: new PASS syntax (Q). + +Sun Sep 13 20:32:08 1998 Christophe Kalt + + * config.h.dist, ircd.c: removed MYNAME. + + * Makefile.in, config.h.dist: SPATH/APATH cleanup. + + * parse.c: ABW fix (Leon Brouwers and purify). + +Sat Sep 12 18:53:39 1998 Christophe Kalt + + * ircd.c, s_bsd.c: SIGCHLD handling code to avoid zombies. + + * s_bsd.c: + * udpfd used in place of adfd in in read_message(). + * silently deal with linux accept() way of life. + + * a_io.c: loop_io() bugfix for select() systems. + + * ircd.c: + * me.info from ircd.conf was overridden in setup_me(). + * server_reboot() created a zombie. + + * s_user.c: allow servers to speak on channels (reported by Q). + + * channel.c: + * NJOIN bugfix related to unique ops (reported by Q). + * removed old core from msa. + + * various little cleanups. + + * res.c: buffer overflow fix. (thanks to Leon Brouwers + and purify) + +Tue Sep 8 21:23:27 1998 Christophe Kalt + + * s_user.c: user mode +a propagation bugfix. + + * ircd.c: die immediately if no listener exists after reading the conf. + + * send_ext.h, send.c, channel.c: backward compatibility fix for eI + channel modes (added sendto_match_servs_v()). + +Mon Sep 7 18:03:34 1998 Christophe Kalt + + * s_bsd.c: inversed test for -s in start_iauth(). + + * channel.c: + * keys starting with ':' don't propagate correctly. + * m_njoin() didn't send modes properly to clients. + + * s_serv.c: + * slightly changed the PASS syntax again. + * 2.10 alphas didn't recognize peers as such (reported by Q). + +Sun Aug 23 22:16:40 1998 Christophe Kalt + + * struct_def.h, ircd.c, list.c, list_ext.h, s_conf.c, s_serv.c, + s_service.c, s_user.c: aClient's info is now dynamically allocated + to overcome server handshake limitations. + +Sat Aug 22 15:20:10 1998 Christophe Kalt + + * channel.c: fixed ^G bug (only triggered in channel creation) + + * struct_def.h, channel.c, s_err.c, s_user.c: AWAY is back. + +Sun Aug 16 16:01:15 1998 Christophe Kalt + + * ircd.c:, s_bsd.c: added -s switch. + +Sat Aug 8 14:21:20 1998 Christophe Kalt + + * s_serv.c: Roger's diff broke compression. (reported by Andre Koopal) + + * Makefile.in: iauth didn't know where to find zlib.h (reported + by delta) + + * a_log.c: typos in parameter names (reported by delta). + +Fri Aug 7 23:54:10 1998 Christophe Kalt + + * mod_rfc931.c: added sanity check on replies. + +Fri Aug 7 00:03:45 1998 Christophe Kalt + + * mod_rfc931.c: read RFC 1413 and fixed the reply parser. + + * numeric_def.h, s_err.c, s_auth_ext.h, s_auth.c, s_serv.c: added + /stats a to show iauth's configuation. + + * s_auth.c, a_*.[ch], mod_*.c: + * SIGUSR2 will cause iauth to close and reopen log file(s). + * worked around delayed messages from the iauth caused by + ircd's fd remapping habit. + * reduced memory usage by dynamically allocating `inbuffer'. + * added G message (a->i). + * added E message (i->a) and cleaned up errors messages in + parse_ircd(). + * added a/A messages (a->i) to transmist configuration. + * revisited next_io() and hopefully fixed the logic. + + * ircd.c, res.c, s_auth.c, s_auth_ext.h, s_bsd.c, s_user.c: + * stdarg'ized sendto_iauth(). + * iauth is now automatically restarted. + * fixed bcopy() length in read_iauth(). + * added notices to track the "" username bug. + +Tue Aug 4 21:43:53 1998 Christophe Kalt + + * a_io.c: numerous bug fixes.. + + * mod_rfc931.c: fix to prevent crash when receiving data from + broken ident servers. + + * a_conf.c, a_conf_def.h, a_externs.h, a_log_def.h: added module + `socks'. (Based on a 2.9.5 diff from Jonathan Chapman) + + * a_log.c: added timestamps to `auth' log. + + * s_misc.c: EXITC_AREF is a special case like EXITC_REF. + + * parse.c: penalty bugfix. + + * ircd.c, s_auth.c, s_bsd.c, s_bsd_ext.h: + * cleaned up iauth startup procedure, added start_iauth() + which is called upon SIGUSR1. + * various fixes in read_iauth(). + +Sun Aug 2 18:34:20 1998 Christophe Kalt + + * s_mist_ext.h, s_misc.c, support_ext.h, support.c: moved + myctime() from s_misc.c to support.c. + + * s_bsd.c, a_io.c: added `R' message from ircd to iauth. + + * s_serv.c: updated check_version() not to use NJOIN with 2.9.5 links. + + * parse.c: restricted SQUERY to users. + + * channel.c: + * m_njoin(): conversion bugfix (Reported by Q). + * added FULLV2_10 #if's. + + * struct_def.h, channel.c, s_err.c, s_misc.c: added channel mode `r'. + + * send.c: reference to NULL pointer in sendto_match_servs() + (Reported by Core). + + * sys_def.c, chkconf.c: MyFree() redefinitions (from Core). + + * Makefile.in: "make install-server" path problems. + +Sun Jul 19 15:32:48 1998 Christophe Kalt + + * s_conf.c, ircd.c: unitialized K line comment in check_pings(). + + * channel.c: + * beI modes to multiple channels were corrupted. + * mode parameters starting with : don't propagate correctly. + * !channel creation propagation was broken (reported by Eumel). + + * send.c, struct_def.h, channel.s, res.c, ircd.c, s_auth.c, + s_auth_ext.h, s_bsd.c, s_bsd_ext.h, s_conf.c, s_user.c, + Makefile.in, config.h.dist: added iauth. + +Fri Jun 12 19:00:03 1998 Christophe Kalt + + * ircd.c: fix for inetd support (from Jonathan Chapman + ). + + * parse.c, s_debug.c: more LOCOP_* fixes (from Michael Neumayer). + + * s_user.c: oper counter bugfix (from Magnus Tjernstrom). + + * channel.c: + * fixed join #a,#b,.. desynch bug (reported by viha@vip.fi). + * fixed netjoin +p/+s desynch problem (same). + +Sun May 31 14:18:41 1998 Christophe Kalt + + * send.c, channel.c: '-' leftovers (Michael Neumayer ). + +Mon May 25 15:13:51 1998 Christophe Kalt + + * struct_def.h, channel.c, hash.c, s_misc.c: changed new channels + prefix to ! (instead of -). + + * parse.c: undefining LOCOP_* had no effect (reported by Eumel). + + * s_service.c: SERVICE_WANT_OPER burst fix (from Jonathan Chapman). + + * s_bsd.c: SO_LINGER patch (from Andrew Snare ). + + * configure.in: better logic for --resconf. + + * channel.c: + * m_invite() fix for &channels. + * add_modeid() always used RPL_BANLIST. + * bIe modes coming from a server were rejected + add_modeid() if another mode with the same pattern existed. + + * c_debug_ext.h, c_debug.c, chkconf.c, s_misc.c, s_zip.c: fixes + for DEBUGMODE (from Andrew Snare & Magnus + Tjernstrom ) + + * hash.c: bigger_prime() useless optimization from Magnus :-) + +Tue May 5 19:26:25 1998 Christophe Kalt + + * config.h.dist, Makefile.in, struct_def.h, s_externs.h, send.c, + channel.c, hash.c, s_debug.c, s_err.c, s_misc.c, s_serv.c, + s_user.c: implemented new channels. + + * struct_def.h, parse.c, channel.c, ircd.c, s_debug.c, s_misc.c, + s_serv.c, s_user.c, whowas.c, config.h.dist: replaced BIG_NET #define. + +Fri Apr 24 20:30:21 1998 Christophe Kalt + + * irc.c: missing refresh() (from Dave Hill ). + + * s_conf.c, s_service.c: portability fixes from Avalon. + + * channel.c, s_user.c: adapted undernet's Bquiet. + +Sun Apr 5 17:50:08 1998 Christophe Kalt + + * configure, configure.in, config.h.dist: added --logdir option. + + * s_serv.c: + * moved user wallops from #wallops to +wallops. + * stricter m_server() check for unregistered users. + + * send.c: wallops were sent to services and unregistered clients. + +Sat Apr 4 19:05:26 1998 Christophe Kalt + + * struct_def.h, packet.c, s_bsd.c: (never triggered) link + compression bugfix (Roger Espel Llima ). + + * config.h.dist, ircd.c, s_debug.c: added PREFER_SERVER #define. + + * s_user.c: + * m_oper() notice bug fix (Michael 'Eumel' Neumayer). + * completely disabled AWAY. + + * struct_def.h, parse.c, channel.c, ircd.c, s_debug.c, s_misc.c, + s_serv.c, s_user.c, whowas.c, config.h.dist: added BIG_NET #define. + + * s_misc.c; Y2K fix. + +Tue Mar 31 18:52:41 1998 Christophe Kalt + + * s_serv.c: removed now obsolete USE_NJOIN. + + * numeric_def.h, struct_def.h, channel.c, s_debug.c, s_err.c, + s_serv.c: added channel modes +e (EFnet's exceptions to bans) and + +I (invitations); raised MAXBANS (should be renamed) to 30. + + * support.c: extended make_version(). + + * channel.c: + * notify user when a ban is rejected because "redundant". + * /invite (from chanop) now overrides bans & limit. + + * s_debug.c, s_serv.c: /stats r no longer restricted to DEBUGMODE. + + * s_bsd.c: getrlimit()/setrlimit() is now used regardless of + poll() availibility. + +Sun Mar 22 14:01:24 1998 Christophe Kalt + + * channel.c: MIRC_KLUDGE sent bogus modes on channel creation. + + * os.h, support.c, s_bsd.c: CYGWIN32 cleanup from Dave Miller. + + * s_user.c: hunt_server() cleanup. + + * s_conf.c: match_ipmask() choked on a.b.c.d/z (reported by Helmut + Springer ). + +2.9.5 + +Tue Feb 17 21:25:02 1998 Christophe Kalt + + * s_bsd.c: w32 doesn't have a working fork(). + + * ircd.c: deal with "getpwuid(getuid())" returning NULL. + + * configure.in, os.h, support.c: use our own truncate() when + needed (CYGWIN32), and CYGWIN32 portability. (Thanks to Dave + Miller ). + + * config.guess: update. + + * s_user.c: broadcast restriction wasn't right (Yegg). + + * send.c, ircd.c: removed noisy debugging notices. + +Sat Feb 7 09:21:52 1998 Christophe Kalt + + * s_user.c: + * oper log is now more verbose. + * broadcast messages/notices are now less restricted. + + * hash.c: nitpicking (from Magnus Tjernstrom). + + * configure.in: quoting cleanup (from Alain). + + * send_ext.h, s_debug.h: STDARG prototyping cleanup (from Alain). + +Fri Jan 23 17:39:17 1998 Christophe Kalt + + * os.h: linux 2.1 implements poll() but the header files are a + mess (what did you expect?), kludge to get it work (from Vesa). + + * channel.c: fixes related to MIRC_KLUDGE. + + * s_conf.c: + * find_kill() fix and cleanup (mostly from Vesa). + * find_bounce() stricter check and fix (from Vesa). + + * parse.c: m_njoin() is only used by the server. + +Fri Jan 23 17:38:36 1998 Christophe Kalt + + * channel.c: + * buffer overflow fix. + * bugfix from Avalon. + * join/invite were propagated for &channels. (reported by DLR) + * invite/kick were propagated beyond masks. (reported by DLR) + * multiple kicks could desynch channels. + + * s_user.c: stricter check on unregistered NICK changes (Avalon). + + * hash.c: hash_find_server() didn't handle z.stealth.net (1 + letter) masked by *.stealth.net (DLR). + + * msg_def.h, struct_def.h, channel_ext.h, parse.c, channel.c, + s_serv.c: added send_channel_members() and m_njoin(). + + * send_ext.h, send.c: added sendto_serv_notv(). + + * buidm4: yet another m4 booboo. (fix from Mario) + +Wed Jan 7 11:40:59 1998 Christophe Kalt + + * s_user.c: strncpy() lameness. + + * s_conf.c: added match_ipmask() (from Vesa). + + * configure.in, send_ext.h: "checking for working stdarg" always + failed because of a quoting problem. + +Thu Dec 18 21:48:18 1997 Christophe Kalt + + * channel.c: abusive usage of /names now forbidden. + + * class.c: imposed a minimum of 60 seconds for connect frequencies. + + * struct_def.h, s_misc.c, s_serv.c: check_link() tuning and statistics. + +Tue Dec 16 17:12:16 1997 Christophe Kalt + + * s_conf.c: finished D lines. + + * numeric_def.h, struct_def.h, list.c, s_err.c, s_serv.c: added + check_link() to prevent server links from being flooded by replies + to user requests. + + * s_bsd.c: try to prevent the server from flooding with UDP pings. + + * channel.c: #foo:*.tld modes were always sent during the burst. + +Wed Nov 12 21:02:15 1997 Christophe Kalt + + * struct_def.h, s_conf_ext.h, s_conf.c, ircd.c, chkconf.c, + numeric_def.h, s_err.c , s_serv.c: added D configuration + lines. (/stats h) + + * send.c, s_service.c: allocate more dbufs during a service burst + if needed. + + * channel.c: cosmetics, and fixed the use of MAXPENALTY in m_kick(). + + * s_debug.c: too many parameters in a call to sendto_one(). + +2.9.4 + +Sat Oct 18 09:37:33 1997 Christophe Kalt + + * setup.h.in, configure.in: (Alain Nissen) + * additional header files checked. + * non-blocking system test fixed. + + * os.h: curses/termcap stuff is now only used for the client (AN). + + * swear_ext.h, swear.c: portability issues (Alain Nissen). + + * c_bsd.c, s_bsd.c, os.h: SELECT_FDSET_TYPE (defined in os.h) used + as pointer type in select() calls; HPUX compilation problem + fixed. (Alain Nissen) + + * buildm4: typo & missing quote. (again!) + +Fri Oct 10 23:48:25 1997 Christophe Kalt + + * s_serv.c: improved m_die() and m_restart() in case a service is + used for user log. + + * os.h, acconfig.h, configure.in, res.c, s_bsd.c: (Alain Nissen) + * kludge to deal with broken hostent declaration in + netdb.h on some linux systems. + * test for sigaction & sigset functions added back; signal + implementation test fixed. + + * s_conf.c: + * more explicit K line message when reason specified in + ircd.conf. + * extended I lines syntax. + + * s_service_ext.h, s_service.c, s_misc.c: faster split handling is + possible now that 2.8.x protocol is history. + + * channel.c: + * m_join() was unefficient on net joins. + * MIRC_KLUDGE would never show +ov modes. + + * s_user.c: + * services can now send to channels (if the modes allow it). + * prefixes for restricted connections were gone. + + * buildm4: missing quote. + +2.9.4b + +Wed Oct 1 21:57:45 1997 Christophe Kalt + + * chkconf.c: added knowledge of B lines. + + * s_debug.c: more info on dbufs for better tuning. + + * channel.c: bans on IP are now matched against resolving clients. + + * s_conf.c: K lines on IP can now be matched against resolving clients. + + * buildm4: update for Y and K line macros, and added macros for + B,V,i and k lines (Mario Holbe). + + * s_conf.c: Y global limit per host didn't work. + +Wed Sep 24 18:25:45 1997 Christophe Kalt + + * acconfig.h, configure.in, setup.h.in, resolv_def.h, res_init.c: + added --resconf=FILE option to configure (Alain Nissen). + + * s_conf.c: fixed bug with Y limits. + +Tue Sep 23 11:36:30 1997 Christophe Kalt + + * common_def.h: added CHKCONF_COMPILE statement. + + * bsd_ext.h: incorrect declaration for writeb. + + * support_ext.h, support.c: dumpcore() was broken. + + * class_def.h, class_ext.h, class.c, s_conf.c, s_err.c: it's now + possible to combine a limit per host and per user@host for the + same class. + + * s_user.c: + * RPL_ENDOFWHO wasn't correct. + * who_find() / m_whois() didn't always respect +a mode. + * @ restriction in username could be bypassed. + * unlikely but nonetheless possible ghost generation. + + * ircd.c: setgid() was called after setuid() (reported by Nicole + Haywood ) + + * parse.c: avoid a match() call if possible. + +Sun Sep 14 19:44:27 1997 Christophe Kalt + + * ircd.c: redundant/useless code commented out. + + * struct_def.h, parse.c, s_err.c, s_serv.c: `stats m' is more verbose. + + * os.h, Makefile.in: zlib.h was missing from includes. + + * s_user.c: 2 fixes (a NULL pointer, and a non reinitialized one). + +Thu Sep 11 21:43:20 1997 Christophe Kalt + + * class_def.h, class_ext.h, class.c, s_bsd.c, s_conf.c, s_err.c, + s_user.c: added 2 fields to Y lines and implemented [u@]h global + limits. + + * service_def.h, channel.c, s_service.c: added SERVICE_WANT_VCHANNEL. + + * channel.c: server channels now have a topic. + + * s_conf.c: negative class numbers are now forbidden. + + * s_conf_ext.h, s_conf.c, s_bsd.c: new B lines format. + +Sun Sep 7 20:02:50 1997 Christophe Kalt + + * s_conf.c: B lines now catch "unauthorized connections". + + * s_user.c: m_who() limit wasn't coded. fixed this and rewrote + m_who() because recursivity and penalty don't go together. + + * s_err.c: REPL_SERVLIST type field is now in hexa. + + * service_def.h, send.c, s_misc.c, s_user.c: extended services + capabilities so they can do logging. + + * s_serv.c, s_user.c: added MD5 support for crypt() (from Urvos Juvan). + + * res.c: hostnames containing * or ? are now rejected. + + * s_conf.c: service type field stripped from optional bits (in S + lines). + + * s_serv.c: server token wasn't sent to services in m_server_estab(). + + * s_service.c: SERVICE_WANT_PREFIX wasn't honored by m_squery(). + + * struct_def.h, parse.c, s_serv.c, s_user.c: + * added MyService() macro and updated several tests. + * next_client() was ignoring services. + +Tue Aug 19 08:38:54 1997 Christophe Kalt + + * channel.c: m_names() could still have a truncated reply. + + * more cleaning from Alain.Nissen@ulg.ac.be: + + * struct_def.h, bsd.c, s_bsd.c: removed references to "pyr". + * res_comp.c: removed res_getshort() [never used]. + * removed all references to VMS. + +Mon Aug 11 13:34:15 1997 Christophe Kalt + + * The following changes are from Alain.Nissen@ulg.ac.be + + * all files (in short): + * include/ was removed. + * all .c have a corresponding _ext.h to declare external + variables and functions. + * [sc]_externs.h are #includes *_ext.h. + * [sc]_defines.h are #includes *_def.h. + * all .c have the same list of #include. + * os.h has all system #includes and portability tests. + + * Also, several bug and portability fixes: + + * c_bsd.c: move renamed in tcap_move (portability). + * c_msg.c: + * added test on DOCURSES before including it. + * various casts. + * edit.c: + * return type of suspend_irc() changed to RETSIGTYPE. + * added int argument to suspend_irc(). + * use of signal(SIGTSTP,...) now depends on + whether the signal exists rather than the OS. + * help.c: helplist rewritten properly. + * irc.c: + * strdup() replaced with mystrdup(). + * do_log() takes 2 arguments. + * return type of quit_intr() changed to RETSIGTYPE. + * added int argument to quit_intr(). + * screen.c: such a mess + * LINES is only present under curses. + * idem for refresh(). + * clear_to_eol() is supposed to take 2 arguments, + but what are they? + * swear.c: added to clients targets + * channel.c: delch renamed in del_ch. + * chkconf.c, parse.c: newline renamed in irc_newline. + * ircd.c: s_monitor(), s_die(), s_rehash(), s_restart() + return type changed from VOIDSIG to RETSIGTYPE. + * res.c: now using SOCK_LEN_TYPE. + * res_comp.c, res_init.c: various portability changes. + * s_auth.c: now using SOCK_LEN_TYPE. + * s_bsd.c: now using SOCK_LEN_TYPE. + * s_conf.c: several portability fixes. + * s_err.c: local_replies[] and local_replies[] rewritten. + * s_service.c: changed test on USE_STDARG. + * bsd.c: + * return type for dummy() is now RETSIGTYPE. + * dummy() now takes one int argument. + * dbuf.c: removed unused DBUF_INIT. + * support.c: + * many changes concerning #if tests. + * added solaris_gethostbyname() to use instead of + Solaris 2.3 broken gethostbyname(). + * added irc_memcmp() to use if system's memcmp() + is broken. + * nameser.h: now using WORDS_BIGENDIAN. + * configure.in: + * simpler solaris 2.x detection when looking for zlib. + * added test for cursesX. + * added check for sys_errlist definition in sys/errno.h + * and more... + * Makefile.in: CFLAGS split in S_CFLAGS, C_CFLAGS and + CC_CFLAGS (ircd, irc, chkconf). + +Fri Aug 8 10:51:24 1997 Christophe Kalt + + * channel.c: m_names() behaviour wasn't consistent with m_who() + concerning +p channels (Michael 'Eumel' Neumayer). + + * configure.in: minor changes (Alain Nissen). + + * s_user.c: missing argument to err_str() (Kai Seidler). + + * config.h.dist, h.h, struct.h, common.c, channel.c, s_bsd.c, + s_debug.c, s_err.c, s_misc.c, s_serv.c, s_service.c, s_user.c: + removed support for 2.8 protocol. + + * config.h.dist, msg.h, channel.c, note.c, s_bsd.c, s_debug.c, + s_misd.c, s_user.c: removed NOTE. + + * s_bsd.c: wrong argument to bzero(). + + * Makefile.in, buildm4: rev.sh replaced by config.guess and + buildm4 wasn't ran by `make install-server'. + +2.9.3 + +Wed Jul 23 11:23:30 1997 Christophe Kalt + + * res.c: queries were never resent when reaching timeout (C. Behrens). + + * acconfig.h, configure.in: better sys_errlist test (A. Nissen). + + * version.c.SH.in: portability (A. Nissen). + + * acconfig.h, configure.in, common.h, config.h.dist: AIX cleanup + and optimization flags (A. Nissen). + + * configure.in: typo. + +Thu Jul 17 23:04:48 1997 Christophe Kalt + + * c_numeric.c, irc.c: fixes from Vesa. + + * send.c: buffer overflow fix. + + * h.h, res_init.c: portability fixes. + +Wed Jul 16 21:35:50 1997 Christophe Kalt + + * s_serv.c: m_die() referenced data after freeing it. + + * support.c, res.c: silly changes to make purify happier. + + * s_bsd.c: fixed memory corruption problem. + + * s_user.c: m_whois() voice flag changed back to + (from !). + + * h.h, support.c, configure.in: reverted back: use inet_* if + present, use our own inet* if not. Our functions must be + different to avoid some crazy clash when bind 8.x is on installed + the system. Should we teach configure.in about -lbind? + +Tue Jul 15 00:18:01 1997 Christophe Kalt + + * inet_addr.c moved to support.c, renamed functions (inet_addr, + inet_aton, inet_ntoa, inet_netof) to avoid clashes; always used + even if the system has it. + + * New configure and Makefile from Alain Nissen. (many many files + changed, removed, created, rewritten) + + * buildm4: update (Mario Holbe). + + * struct.h, s_bsd.c: fixed the P line rehash bug(?). + + * h.h, ircd.c: let's be nice to SunOS' cc. + +Mon Jun 30 21:41:11 1997 Christophe Kalt + + * dbuf.c, send.c: earlier changes broke the client. + + * config.h.dist, struct.h, dbuf.h, dbuf.c: new magic formula to + compute BUFFERPOOL. Added MAXSERVERS for this purpose. + + * s_serv.c: buffer overflow (Chris Behrens). + +Thu Jun 26 19:18:24 1997 Christophe Kalt + + * struct.h, channel.c, hash.c, parse.c, send.c, s_misc.c, + s_service.c: + * cleanup. + * added &SERVICES. + + * s_bsd.c: wrong buffer size given to getsockopt(). + +Thu Jun 19 18:35:37 1997 Christophe Kalt + + * h.h, struct.h, s_debug.c, send.c, dbuf.c: + * dbuf stats. + * send_message() #ifndef SENDQ_ALWAYS was not uptodate, + tried to bring it back up to date. + + * res.c: fixed possible buffer overflow. + + * h.h, s_debug.c, send.c: fixes for STDARG (Olivier Galibert) + + * ircd.c: server_reboot() would crash when called because of "out + of memory". + +Mon Jun 9 20:49:55 1997 Christophe Kalt + + * config.h.dist, h.h, struct.h, send.c, ircd.c, list.c, s_debug.c, + s_serv.c, s_user.c: removed #define KRYS, it is now always `defined'. + + * config.h.dist, h.h, common.h, service.h, sys.h, configure.in, + send.c, support.c, s_auth.c, s_service.c, s_debug.c, s_conf.c: + removed references to varargs, added support for stdargs. + It is controlled by #define USE_STDARG set by configure. (adapted + from Olivier Galibert) + + * ircd.c: CHROOT is really called CHROOTDIR. + + * s_user.c: + * extended m_message() to accept n!u@h as recipient. + * removed notice for bogus PONG. + + * s_serv.c: /SQUIT now requires 2 arguments from opers. + +Sun Jun 1 16:57:39 1997 Christophe Kalt + + * dbuf.h, dbuf.c: #define DBUF_TAIL is back. + + * s_conf.c: fixed B lines behaviour, port number is now mandatory. + + * send.c: missing arg to dead_link(). (Olivier Galibert) + + * s_serv.c, numeric.h, s_err.c: added /stats B to see B lines (and + fixed /stats V reply). + + * service.h, channel.c, s_misc.c, s_service.c, s_serv.c, s_user.c: + * numerous bugfixes related to local services (if + USE_SERVICES is defined). + * extended services option to allow 2.9 NICK syntax, and + let them see tokens if they want. (adapted from O.Galibert) + +Wed May 21 21:17:51 1997 Christophe Kalt + + * channel.c, s_service.c, service.h: finished service code (whee). + + * s_serv.c: services were incorrectly sent during burst. + + * s_bsd.c: ident MUST be done before anything else is read from a + client. + +Thu May 15 16:27:13 1997 Christophe Kalt + + * struct.h, s_conf.h, s_serv.c: created k: lines to be able to + deny access based on OTHER ident replies. + + * s_user.c: changed 001 reply to return n!u@h (more zen). + + * s_serv.c: + * if A: is bogus, trash it and complain instead of crashing. + * get_client_name() is non-reentrant. *sigh* + +Wed May 7 22:11:04 1997 Christophe Kalt + + * s_user.c: nick chasing kill bug fix. (Chris Behrens) + + * h.h, ircd.c, s_conf.c, s_user.c: K-lined users now exit + displaying the Kline comment, if any. + + * s_conf.c: fixed notice ERR_YOUWILLBEBANNED, and don't disconnect + then. + + * inet.h, nameser.h, resolv.h, inet_addr.c, portability.h, res.c, + res_comp.c, res_init.c, res_mkquery.c: updated. (BIND 4.9.5-P1) + + * channel.c: notice for service could use free'ed memory. + +Sun Apr 27 16:40:08 1997 Christophe Kalt + + * send.c: fixed couple buglets (added by Chris Behrens :^). + + * s_user.c: removed dummy m_note() which was unused and buggy, and + would let any oper _broadcast_ NOTE queries to the net. + + * m_note.c: Modified m_note() in note.c not to send any NOTE + commands to other servers. + + This is lame, someone help me and port note to be a service. + Then, I'll finally take it out of the server !! :-) + +Thu Apr 24 18:51:25 1997 Christophe Kalt + + * send.c: better (faster) sendto_common_channel() (from Chris Behrens). + + * s_serv.c: fixed connected burst for services with hostmasks. + + * s_user.c: fixed origin check in m_pong(). + + * res.c: added a check on hostnames. (From Darren Reed) + +Sun Apr 20 20:30:21 1997 Christophe Kalt + + * s_conf.c: find_bounce() had an inversed test. (how could it work + when I tested it??) + + * s_serv.c: SERVER message would occasionnally (and incorrectly) + be dropped. + + * s_misc.c: simple optimization in exit_client(). + + * s_service.c, s_serv.c: things looked wrong, SERVICE syntax + inchorent. Minor memory leak. + + * s_bsd.c, s_misc.c: various "typos" fixed. (UDP & non POLL) + + * send.c, h.h: removed sendto_all_butone(). (unused) + +Tue Apr 15 19:41:32 1997 Christophe Kalt + + * sock.h: added a check to make sure FD_SETSIZE is big enough. + + * s_bsd.c, struct.h, s_misc.c: added more UDP stats. + + * s_bsd.c: fixed udp_pfd/res_pfd mess, and cleaned the code. (whee) + + * h.h, struct.h, numeric.h, s_err.c, s_conf.c, s_bsd.c: added B lines. + + * channel.c: defining USE_SERVICE would cause buffer corruption + when propagating channel modes to servers. (Found by Michael Neumayer) + +Wed Apr 2 15:25:54 1997 Christophe Kalt + + * list.c, s_serv.c: added some error notices for users without server. + + * s_bsd.c: fixed UDP port binding when no IP is given. + + * configure.in: add -cckr to CFLAGS on SGI when using cc(1) + +Thu Mar 27 19:03:09 1997 Christophe Kalt + + * h.h, send.c, s_bsd.c, s_user.c, s_serv.c: amount of transferred + data added to file logs. + + * config.h.dist: define SVR4 if __svr4__ is there. + + * packet.c: drop server sending an unknown command. + + * s_user.c: changed m_who() for better performance (from Chris + Behrens), also put a limit on its number of arguments. + + * h.h, struct.h, list.c: better IsMember (from Chris Behrens). + + * s_serv.c: don't let a user introduce a new server. + +Fri Mar 21 19:53:36 1997 Christophe Kalt + + * h.h, struct.h, ircd.c, s_conf.c, s_misc.c, s_serv.c, + config.h.dist: server can now cache the MOTD in memory (from Chris + Behrens). See CACHED_MOTD #define. + + * service.h, channel.c, s_serv.c, s_service.c, s_user.c: additions + for services. + + * s_misc.c: added missing parameter for check_service_butone(). + + * INSTALL completed and converted to sgml + + * s_serv.c: MyRealloc(NULL, size) isn't portable. + +Tue Mar 18 17:59:26 1997 Christophe Kalt + + * 2.9.3b10 + + * channel.c, hash.c, res.c, s_serv.c, s_service.c, s_user.c, + whowas.c: penalties tuned again. (added Volker Paulsen's anti SPAM + hack). + + * s_err.c, s_serv.c: minor changes to RPL_STATS* + + * s_bsd.c: authclnts[] was not always initialized. + + * ircd.c: buffer in ircd_readtune() lacked initialization. + + * s_service.c: fixed buffer overflow. + + * send.c, support.c: # of arguments cleanup. + + * list.c, res.c, s_service.c: casts to suppress warnings. + + * h.h, dbuf.c: bufalloc, dbufblocks, poolsize now + unsigned. (some checks might be needed, poolsize can really get + big). + + * s_misc.c: removed duplicate code in exit_client(). + + * parse.c: + + * Added more notices when generating SQUITs for unknown + servers. + * removed bogus else. + +Fri Feb 28 09:34:36 1997 Christophe Kalt + + * s_err.c, s_serv.c: Added 2 more fields to RPL_TRACELINK. + +Thu Feb 27 14:50:37 1997 Christophe Kalt + + * s_serv.c: /connect by servername didn't work for c lines (from Eumel) + +Wed Feb 26 16:48:36 1997 Christophe Kalt + + * s_bsd.c: removed (old) redundant code concerning VIF. + + * config.h.dist: CLONE_MAX and CLONE_PERIOD could be undefined. + + * common.c: match() cleanup. + +Thu Feb 13 17:27:53 1997 Christophe Kalt + + * res.c, res_init.c, res_mkquery.c, ircd.c, s_bsd.c: renamed + res_init() to ircd_res_init() to avoid conflict (ULTRIX). + + * hash.c, struct.c: cleanup of hashing functions. + + * match.c, parse.c, send.c, common.h, channel.c, hash.c, s_bsd.c, + s_misc.c, s_serv.c, s_service.c, s_user.c, note.c, ignore.c: + + * _match() changed to match() and the check for maximum + "recursion" slightly changed. + * match() and matches() removed (stubs from when match + was recursive?). + * All occurrences of matches() changed to match(). + * this saves one function call per match. + + * send.c: Added 2 parameters to sendto_serv_butone(). + + * s_err.c, s_serv.c: Added one field to RPL_TRACELINK. + +Sun Jan 26 20:02:34 EET 1997 Vesa Ruokonen (ruokonen@aapo.it.lut.fi) + + * 2.9.3b8 + + * support.c, h.h, list.c: gcc -Wall cleanups. + * h.h, struct.h, chkconf.c, s_conf.c, s_serv.c: + created V:lines for checking connecting client parameters. + passed as PASS command parameters. A matching V:line. + refuses the connection (version number & compile flags). + * struct.h, channel.c, s_debug.c: + penalty threshold used for limiting KICK params. + * struct.h: initial QUEUELEN calculation tuned. (->BUFFERPOOL). + * c_msg.c: more verbose m_pong(). + * channel.c, s_serv.c, s_user.c, whowas.c: + penalties tuned for commands generating global bcast. + * hash.c: converted multiplication to hashtable lookup to speed. + up function calls. (from Core) + * ircd.c, s_bsd.c: added truncation for non-appended writes. (_root_) + * s_user.c: prefix for voice capability in channel list of WHOIS reply + changed from '+' to '!'. + * s_user.c: drop PONGs with bad origin. + store connection parameters from PASS temporarily to info + field in contstant locations. + * s_user.c: m_umode() fixed (from Core). + +Wed Jan 15 14:42:43 1997 Christophe Kalt + + * s_bsd.c: + + * mysk was initialized by empty password in M line. + +Tue Jan 14 24:62:34 EET 1997 Vesa Ruokonen (ruokonen@aapo.it.lut.fi) + + * parse.c, channel.c, s_user.c: cleanup of find_functions(), + _nickserv replaced by _service. + * h.h, : setup_ping() takes aConfItem pointer as parameter now. + * sys.h: #elif expanded to #else #if for compability + * s_bsd.c: inetport(P:line) changed to support VIFs better. + More info about listening ports into /stats l. + UDP ping is initialized from M:line, not anymore from P:line. + * s_numeric.c: cleanups in numeric processing. + * Makefile.in, Makefile.irc, Makefile.ircd: makedepend fix + * configure.in: zlib check moved to end, as it can interfere + other checks when libs aren't in default paths. + +Mon Jan 13 09:11:04 1997 Christophe Kalt + + * ircd.c: + + * made the display of version (flag -v) more verbose. + + * regenerated configure (with autoconf 2.12; thanks digital). + + * s_user.c: + + * fixed, and extended KILL reasons for `standard' + collisions. (both victims u@h are now shown). + + * send.c: + + * fixed the logic when sending mass message/notice to a + server mask. + + * configure.in, Makefile.in: + + * fixed detection & use of zlib using the environment + variable ZLIB_HOME (from Vesa). + +Thu Jan 9 13:09:36 1997 Christophe Kalt + + * struct.h, ircd.c: + + * added -b command line switch to let the server start + even if the ircd.tune file is corrupted (mostly from + Magnus Tjernstrom). + + * s_conf.c: + + * udp listen was setup even if port was defined to be 0. + +Wed Jan 8 12:35:03 1997 Christophe Kalt + + * h.h, s_bsd.c, s_conf.c: + + * port field in M configuration line is used again, now to + define on which port the server will listen for UDP pings. + + * hash.c: + + * restricted commands to opers (from Vesa). + + * send.c: + + * sendto_match_butone() had a broken behaviour, + brought back the old (2.8.21) behaviour. + + * s_bsd.c: + + * fixed negociation of compression for outgoing + connections. + + * moved the "rejected connection" notice to &LOCAL. + + * SLOW_ACCEPT #ifdef's changed to #ifndef's to get what + one should expect from the define name ! + + * made inetport() more readable, and added check on empty + string parameter (from Vesa). + + * highfd isn't defined when _DO_POLL_ is defined, so don't + use it in debug notices (from Vesa). + + * break changed to continue because ??? (from Vesa). + + * s_user.c: + + * fixed KILL notice sent on nick collision (was using + ident reply for remote clients). + + * allowed oper!user@host.foo to send global message/notice + to #*.foo + + * s_serv.c, s_user.c, s_bsd.c, s_debug.c: + + * changed the PASS command semantic (from Vesa). + +Fri Jan 3 14:47:52 1997 Christophe Kalt + + * s_bsd.c: + + * completed virtual hosts support (M line). + + * config.h.dist: + + * AIX has poll(), use it. + +Mon Dec 30 15:08:20 1996 Christophe Kalt + + * s_bsd.c, h.h: + + * added support for virtual hosts (P line). + +Wed Dec 18 12:08:29 1996 Christophe Kalt + + * bsd.c: + + * fixed read_message() bugs resulting from the merge. + + * channel.c: + + * limited the number of possible kicks to MAXMODEPARAMS. + +Mon Dec 16 09:36:54 1996 Christophe Kalt + + * list.c: + + * don't free serv->user too early. + + * removed duplicated(?) away memory count. + +Fri Dec 13 10:28:43 1996 Christophe Kalt - Hmm, Friday the 13th! + + * config.h.dist, s_auth.c, s_user.c, s_debug.c: + + * minor tuning. + +Thu Dec 12 10:34:47 1996 Christophe Kalt + + * struct.h, s_auth.c, s_debug.c: + + * added memory usage stats for ident replies. + + * send.c, s_auth.c, s_misc.c: + + * fixed boundaries problems with long ident replies. + +Wed Dec 11 17:42:29 1996 Christophe Kalt + + * struct.h, send.c, s_auth.c, s_bsd.c, list.c, s_conf.c, s_misc.c, + s_user.c: + + * added auth field to struct Client to eventually store + long `OTHER' ident replies. It is only used in logs, and + notices (not in matches against configuration lines). + + * config.h.dist: + + * added #define SLOW_ACCEPT (default). + + * added #define CLONE_CHECK (default). + + * s_bsd.c: + + * fixed config line reference counter. + + * added CLONE_CHECK code (check_clones() from + pgoncalves@mail.telepac.pt (Pedro Goncalves)). + + * added SLOW_ACCEPT (previous behaviour) code. + + * merged the 2 versions of read_message(), fixing some + (buggy) difference between them. + + * merged two for() in read_message(). + + +Mon Dec 2 11:02:54 1996 Christophe Kalt + + * s_user.c: + + * changed error notice + + * send.c: + + * #*.mask messages now propagated to other servers. + + * s_service.c: + + * added missing else. + + * config.h.dist, s_debug.c, channel.c: + + * removed all references to V28PlusOnly + * made NoV28Link defined by default + +Wed Nov 27 18:09:42 1996 Christophe Kalt + + * struct.h, class.c, ircd.c, s_bsd.c, s_conf.c, s_serv.c: + + * added lowercase c config line + +Tue Oct 1 22:29:31 1996 Christophe Kalt + + * added config.h to dependancies in Makefile.ircd + + * config.h.dist, h.h, struct.h, packet.c, send.c, ircd.c, s_bsd.c, + s_debug.c, s_serv.c, s_user.c, s_err.c, list.c, Makefile.ircd, + configure.in: + + * added #define ZIP_LINKS and s_zip.c. + * made configure look for the zlib (-lgz). + * implemented server-server zlib compression. diff --git a/doc/Etiquette b/doc/Etiquette new file mode 100644 index 0000000..b531954 --- /dev/null +++ b/doc/Etiquette @@ -0,0 +1,84 @@ +/************************************************************************ + * IRC - Internet Relay Chat, doc/etiquette + * Copyright (C) 1990, Lea Viljanen and Ari Husa + * + * 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. + */ + +HOW TO BEHAVE ON IRC + +Authors: Lea Viljanen (LadyBug) viljanen@kreeta.helsinki.fi + Ari Husa (luru) so-luru@tolsun.oulu.fi +Revised, March 1994: Helen Rose (Trillian) hrose@kei.com + +1) Language + + The most widely understood and spoken language on IRC is English. +However! As IRC is used in many different countries, English is by +no means the only language. If you want to speak some other language +than English (for example with your friends), go to a separate channel +and set the topic (with /topic) to indicate that. For example + /topic #channelname Finnish only! +would mean that this channel would be reserved for Finnish discussion. +On the other hand, you should check the topic (with /list command) +before you move to a channel to see if there are any restrictions about +language. + On a channel not restricted by /topic, please speak a language +everybody can understand. If you want to do otherwise, change channels +and set the topic accordingly. + + +2) Hello/Goodbye + + It's not necessary to greet everybody on a channel personally. +Usually one "Hello" or equivalent is enough. And don't expect everybody +to greet you back. On a channel with 20 people that would mean one +screenful of hellos. It's sensible not to greet, in order not to be rude +to the rest of the channel. If you must say hello, do it with a private /msg. +The same applies to goodbyes. + + +3) Discussion + + When you come to a new channel it's advised you to listen +for a while to get an impression of what's discussed. Please feel free +to join in, but do not try to force your topic into the discussion +if that doesn't come naturally. + + +4) {}|[]\ + + IRC has quite a lot of people from Scandinavian countries, +the above characters are letters in their alphabet. This +has been explained on IRC about a thousand and one times, so +read the following, do not ask it on IRC: + + { is an A with 2 dots over it + } is an A with a small circle above it + | is either an O with 2 dots over it or an O with a dash (/) through it + [, ], and \ are the preceding three letters in upper case. + + There are a lot of people from Japan as well, who use Kanji characters +which may look quite exotic as well. As I don't know Kanji I don't +even try to explain any of the characters. + +5) ATTENTION! + + Remember, people on IRC form their opinions about you only by +your actions, writings and comments on IRC. So think before you type. +Do not "dump" to a channel or user (send large amounts of unwanted +information). This is likely to get you /kicked off the channel or +/killed off from irc. Dumping causes network 'burps', connections going +down because servers cannot handle the large amount of traffic any more. diff --git a/doc/INSTALL.appendix b/doc/INSTALL.appendix new file mode 100644 index 0000000..beeb57a --- /dev/null +++ b/doc/INSTALL.appendix @@ -0,0 +1,86 @@ +Appendix A: Difference between IP addresses and hostnames + + + There are 2 different types of INTERNET addresses, NAME addresses and + NUMERIC addresses. NAME addresses look like ENGLISH words (and indeed + they are ENGLISH words that refer to a given host). A NAME address looks + like "tolsun.oulu.fi" - and that particular address refers to the machine + named TOLSUN in Finland. It is a UNIQUE address because no other machine + in the world has its NAME address the same as "tolsun.oulu.fi". Anytime + you say "telnet tolsun.oulu.fi" - you would always connect to TOLSUN in + Finland. NUMERIC addresses refer to those addresses that are made up of + NUMBERS for example "128.214.5.6" is the NUMERIC address for TOLSUN. This + address is also UNIQUE in that no other machine in the world will be use + those NUMERIC numbers. The NUMERIC address is usually more reliable than + the NAME address because not all sites can recognize and translate the + NAME address into it's numeric counterpart. NUMERIC always seems to work + best, but use a NAME address when you can because it is easier to tell + what host you are connected to. + + + Every Unix machine has a file called "/etc/hosts" on it. This file + contains NAME and NUMERIC addresses. When you supply IRC with a NAME + address it will at first try to find it in /etc/hosts, and then (if it's + really smart), use the local Domain Name Server (DNS) to find the NUMERIC + address for the host you want to connect to. Thus if you plan to use NAME + addresses keep in mind that on SOME sites the entry for the TARGET machine + must be found in /etc/hosts or the NAME address will fail. A typical + entry in /etc/hosts looks like this: + + 130.253.1.15 orion.cair.du.edu orion.du.edu orion # BSD 4.3 + + This particular example is the Host ORION at the University of Denver. + Notice that on the far left is the NUMERIC Address for orion. The + next few ENGLISH words are the NAME addresses that can be used for orion, + "orion.cair.du.edu", "orion.du.edu", "orion". ALL of these NAME addresses + will return the NUMERIC address "130.253.1.15" which IRC will use to + connect to the TARGET UNIX. (when I say TARGET UNIX I am refering to the + UNIX you want to connect to for IRC). Any futher questions about + /etc/hosts should be directed to "man hosts". + + +Appendix B: Enabling Summon Messages + + +-----------------------------------------------------------------------+ + | E N A B L I N G / S U M M O N M E S S A G E S | + +-----------------------------------------------------------------------+ + + *NOTE* You must have ROOT or special access to the GROUP tty ('/dev') + to do this. If you want to allow users around the world to summon + users at your site to irc, then you should make sure that summon works. + + The "IRCD" program needs access to the GROUP of '/dev'. This + directory is where user TTY's are stored (as UNIX treats each Terminal + as a FILE!) IRCD needs GROUP ACCESS to /dev so that users can be + SUMMONED to the program by others users that are *in* the program. + This allows people from other Universities around the world to SUMMON + your users to IRC so that they can chat with them. Berkeley, SUN, HP-UX + and most of the newer versions of UNIX check to see if a USER is + accepting MESSAGES via the GROUP access rights on their TTY listing + in the /dev directory. For example an entry in '/dev' looks like this: + + (Unix Path on BSD 4.3 UNIX is: /dev/ttyp0) + + crw------- 1 jtrim 20, 0 Apr 29 10:35 ttyp0 + + You will note that 'jtrim' OWNS this terminal and can READ/WRITE to this + terminal as well (which makes sense because I am ENTERING DATA and + RECEIVEING DATA back from the UNIX). I logged into this particular + UNIX on "April 29th" at "10:35am" and my TTY is "ttyp0". But further + of *note* is that I do not have my MESSAGES ON! (mesg n) -- This is + how my terminal would look with MESSAGES ON (mesg y): + + crw--w---- 1 jtrim 20, 0 Apr 29 10:35 ttyp0 + + With my MESSAGES ON (mesg y) I can receive TALK(1) requests, use the + UNIX WRITE(1) command and other commands that allow users to talk + to one another. In IRC this would also allow me to get IRC /SUMMON + messages. To set up the "IRCD" program to work with /SUMMON type + the following: (using ROOT or an account that has access to '/dev'). + + % chgrp tty ircd + % chmod 6111 ircd + + The above commands read: "Give IRCD access to GROUP tty (which is /dev) + and then when ANYONE runs the IRCD allow SETUID and SETGID priviliges + so that they can use the /SUMMON command. diff --git a/doc/INSTALL.info b/doc/INSTALL.info new file mode 100644 index 0000000..c74be27 --- /dev/null +++ b/doc/INSTALL.info @@ -0,0 +1,1759 @@ +This is Info file INSTALL.info, produced by Makeinfo-1.55 from the +input file /tmp/sgml2info3035tmp2. + + \input texinfo + + +File: INSTALL.info, Node: Top, Next: Installing IRC-, Prev: (DIR), Up: (DIR) + +Installing IRC - The Internet Relay Chat Program +************************************************ + + SGML version by Christophe Kalt + $Id: INSTALL.info,v 1.38 1999/08/13 17:22:12 kalt Exp $ + + This document describes how to install, and configure IRC 2.10.3. + +* Menu: + +* Installing IRC-:: +* The config-h file:: +* Editing the Makefile and compiling:: +* The ircd-conf file:: +* Related resources:: +* Reporting a bug:: + + +File: INSTALL.info, Node: Installing IRC-, Next: The config-h file, Prev: Top, Up: Top + +Installing IRC- +*************** + +* Menu: + +* The configure script:: +* Notes for Cygwin32 users:: +* Notes concerning IPv6 support:: + + +File: INSTALL.info, Node: The configure script, Next: Notes for Cygwin32 users, Up: Installing IRC- + +The configure script +==================== + + This package uses a GNU configure script for its configuration. You +simply need to untar the distribution and run the "configure" script. +This will run configure which will probe your system for any +peculiarities it has and setup the Makefile and a file of default +#define's ($arch/setup.h). + + There are a few options to "configure" to help it out, or change the +default behaviour: +`--prefix=DIR' + changes the default directory into which ircd will install using + "make install". This defaults to /usr/local + +`--sbindir=DIR' + changes the default directory where the system admin executable + files will go. It is important to set this properly. (default is + prefix/sbin) + +`--logdir=DIR' + changes the default directory where the irc log files will go. + (default is prefix/var/log/ircd) + +`--sysconfdir=DIR' + changes the default directory where the irc server configuration + files will go. (default is prefix/etc) + +`--localstatedir=DIR' + changes the default directory where the irc server state files + will go. (default is prefix/var/run) + +`--resconf=FILE' + defines the file to be used by ircd to initialize its resolver. + (default is /etc/resolv.conf) + +`--zlib-include=DIR' + specifies in which directory the include file from the zlib is + located. + +`--zlib-library=DIR' + specifies in which directory the zlib library is located. + +`--zlib-prefix=DIR' + specifies the prefix for zlib location. It overrides the 2 + previous options. (The include directory is supposed to be in + prefix/include, and the library in prefix/lib). + +`--with-zlib' + is the default. "configure" looks on your system to find the + zlib. If found, ircd will be linked using it. This does NOT mean + you can use server link compression, for this you also need to + define ZIP_LINKS (see section below). + +`--without-zlib' + tells "configure" not to look for the zlib. Defining this will + keep you from using server link compression. + +`--enable-ip6' + Enable IPv6 support (See notes below) + +`--enable-dsm' + Enable Dynamically Shared Modules support for iauth + + +File: INSTALL.info, Node: Notes for Cygwin32 users, Next: Notes concerning IPv6 support, Prev: The configure script, Up: Installing IRC- + +Notes for Cygwin32 users +======================== + + The daemon of 2.10.3 release compiles properly on W32 systems which +have the GNU-Win32 environment () setup. At the time of the release, +tests were made using the version b20.1 of the Cygwin32 library. + + When compiling on such system, you want to make sure that you have +carefully followed the Cygwin32 installation notes. In particular, you +will need to make sure that the following files exist: `/bin/cp.exe', +`/bin/mv.exe', `/bin/rm.exe' and `/bin/sh.exe'. + + Also, the IRC server needs a `resolv.conf' file in order to +initialize the resolver. This file can be anywhere (see configure +options), and is typically in `/etc' on UNIX systems. + + Finally, iauth is automatically disabled. Even though the iauth +program compiles properly, extra work is required to have a working +communication channel between the IRC server and the iauth program. + + +File: INSTALL.info, Node: Notes concerning IPv6 support, Prev: Notes for Cygwin32 users, Up: Installing IRC- + +Notes concerning IPv6 support +============================= + + The only part of the software that doesn't use IPv6 is the server +internal resolver. It relies on the name servers defined in +"/etc/resolv.conf" to be IPv4 addresses. + + This version was tested on the following IPv6 systems: BSD/OS+KAME, +Digital Unix, FreeBSD+KAME, Linux, NetBSD+INRIA. + + Because IPv6 numeric addresses contain ":" characters, `the +separator for the server configuration file was changed to "%"'. + + +File: INSTALL.info, Node: The config-h file, Next: Editing the Makefile and compiling, Prev: Installing IRC-, Up: Top + +The config-h file +***************** + + The second step consists of defining options before the compilation. +This is done by editing the "config.h" file and changing the various +#DEFINE's. + +* Menu: + +* Define what type of UNIX your machine uses-:: +* DEBUGMODE:: +* CPATH MPATH LPATH PPATH TPATH QPATH OPATH:: +* CACHED_MOTD:: +* CHROOTDIR:: +* ENABLE_SUMMON ENABLE_USERS:: +* SHOW_INVISIBLE_LUSERS NO_DEFAULT_INVISIBLE:: +* OPER_KILL OPER_REHASH OPER_RESTART LOCAL_KILL_ONLY:: +* ZIP_LINKS ZIP_LEVEL:: +* SLOW_ACCEPT:: +* CLONE_CHECK:: +* Other #define's:: + + +File: INSTALL.info, Node: Define what type of UNIX your machine uses-, Next: DEBUGMODE, Up: The config-h file + +Define what type of UNIX your machine uses- +=========================================== + + Pick the machine type which best describes your machine and change +the #undef to #define (if needed).Some flavours of Unix require no +#define and in such cases all others should be #undef'd. + + +File: INSTALL.info, Node: DEBUGMODE, Next: CPATH MPATH LPATH PPATH TPATH QPATH OPATH, Prev: Define what type of UNIX your machine uses-, Up: The config-h file + +DEBUGMODE +========= + + Define DEBUGMODE if you want to see the ircd debugging information +as the daemon is running. Normally this function will be undefined as +ircd produces a considerable amount of output. DEBUGMODE must be +defined for either of -t or -x command line options to work. Defining +this induces a large overhead for the server as it does a large amount +of self diagnostics whilst running. + + `This should only be defined for test purposes, and never used on a +production server.' + + +File: INSTALL.info, Node: CPATH MPATH LPATH PPATH TPATH QPATH OPATH, Next: CACHED_MOTD, Prev: DEBUGMODE, Up: The config-h file + +CPATH MPATH LPATH PPATH TPATH QPATH OPATH +========================================= + + Define CPATH to be the directory path to the "ircd.conf" file. This +path is usually /usr/local/lib/ircd/ircd.conf. The format of this file +will be discussed later. + + The LPATH #define should be set to "/dev/null" unless you plan to +debug the ircd program. Note that the logfile grows very quickly. + + Define MPATH to be the path to the "motd" (message of the day) file +for the server. Keep in mind this is automatically displayed whenever +anyone signs on to your server. + + The PPATH is optional, but if defined, should point to a file which +either doesn't exist (but is creatable) or a previously used PPATH +file. It is used for storing the server's PID so a ps(1) isn't +necessary. + + Define QPATH to be the directory path to the "iauth.conf" file. This +path is usually /usr/local/lib/ircd/iauth.conf. The format of this +file is described by a manual page. + + The OPATH #define should be set to "/dev/null" unless you plan to +debug the iauth program. Note that the logfile grows very quickly. + + +File: INSTALL.info, Node: CACHED_MOTD, Next: CHROOTDIR, Prev: CPATH MPATH LPATH PPATH TPATH QPATH OPATH, Up: The config-h file + +CACHED_MOTD +=========== + + The server sends the "motd" to every client connecting. Every time, +it reads it from the disk. This is quite intensive and can be +undesirable for busy servers. + + Defining CACHED_MOTD will make the server store the "motd" in +memory, and only read it again from the disk when rehashing if the file +has changed. + + +File: INSTALL.info, Node: CHROOTDIR, Next: ENABLE_SUMMON ENABLE_USERS, Prev: CACHED_MOTD, Up: The config-h file + +CHROOTDIR +========= + + To use the CHROOTDIR feature, make sure it is #define'd and that the +server is being run as root. The server will chroot to the directory +name provded by "IRCDDIR" (in Makefile). + + +File: INSTALL.info, Node: ENABLE_SUMMON ENABLE_USERS, Next: SHOW_INVISIBLE_LUSERS NO_DEFAULT_INVISIBLE, Prev: CHROOTDIR, Up: The config-h file + +ENABLE_SUMMON ENABLE_USERS +========================== + + For security conscious server admins, they may wish to leave +ENABLE_USERS undefined, disabling the USERS command which can be used +to glean information the same as finger can. ENABLE_SUMMON toggles +whether the server will attempt to summon local users to irc by writing +a message similar to that from talk(1) to a user's tty. + + +File: INSTALL.info, Node: SHOW_INVISIBLE_LUSERS NO_DEFAULT_INVISIBLE, Next: OPER_KILL OPER_REHASH OPER_RESTART LOCAL_KILL_ONLY, Prev: ENABLE_SUMMON ENABLE_USERS, Up: The config-h file + +SHOW_INVISIBLE_LUSERS NO_DEFAULT_INVISIBLE +========================================== + + On large IRC networks, the number of invisible users is likely to be +large and reporting that number cause no pain. To aid and effect this, +SHOW_INVISIBLE_LUSERS is provided to cause the LUSERS command to report +the number of invisible users to all people and not just operators. The +NO_DEFAULT_INVISIBLE define is used to toggle whether clients are +automatically made invisible when they register. + + +File: INSTALL.info, Node: OPER_KILL OPER_REHASH OPER_RESTART LOCAL_KILL_ONLY, Next: ZIP_LINKS ZIP_LEVEL, Prev: SHOW_INVISIBLE_LUSERS NO_DEFAULT_INVISIBLE, Up: The config-h file + +OPER_KILL OPER_REHASH OPER_RESTART LOCAL_KILL_ONLY +================================================== + + The three operator only commands, KILL, REHASH and RESTART, may all +be disabled to ensure that an operator who does not have the correct +privilidges does not have the power to cause untoward things to occur. +To further curb the actions of guest operators, LOCAL_KILL_ONLY can be +defined to only allow locally connected clients to be KILLed. + + +File: INSTALL.info, Node: ZIP_LINKS ZIP_LEVEL, Next: SLOW_ACCEPT, Prev: OPER_KILL OPER_REHASH OPER_RESTART LOCAL_KILL_ONLY, Up: The config-h file + +ZIP_LINKS ZIP_LEVEL +=================== + + As of the 2.9.3 version of the server, server-server connections may +be compressed using the zlib. In order to compile the server with this +feature, you MUST have the zlib package (version 1.0 or higher) already +compiled and define ZIP_LINKS in the config.h file. Compression use for +server-server connections is separately configured in the ircd.conf +file for each server-server link. ZIP_LEVEL allows you to control the +compression level that will be used. Values above 5 will noticeably +increase the CPU used by the server. + + The zlib package may be found at . The data format used by the zlib +library is described by RFCs (Request for Comments) 1950 to 1952 in the +files (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip +format). These documents are also available in other formats from + + +File: INSTALL.info, Node: SLOW_ACCEPT, Next: CLONE_CHECK, Prev: ZIP_LINKS ZIP_LEVEL, Up: The config-h file + +SLOW_ACCEPT +=========== + + This option is defined by default and is needed on some OSes. It +creates an artificial delay in processing incoming connections. On a +given port, no more than 1 connection per 2 seconds will be processed. + + Undefining this will let the server process connections as fast as +it can which can cause problems on some OSes (such as SunOS) and be +abused (fast massive join of clonebots..), for these reasons, if you +decide to undefine SLOW_ACCEPT you MUST define CLONE_CHECK. + + +File: INSTALL.info, Node: CLONE_CHECK, Next: Other #define's, Prev: SLOW_ACCEPT, Up: The config-h file + +CLONE_CHECK +=========== + + This option acts as a wrapper, by checking incoming connections +early before starting ident query. By default, the server will not +accept more than 2 connections from the same host within 10 seconds. + + +File: INSTALL.info, Node: Other #define's, Prev: CLONE_CHECK, Up: The config-h file + +Other #define's +=============== + + The rest of the user changable #define's should be pretty much self +explanatory in the config.h file. It is *NOT* recommended that any of +the file undef the line with "STOP STOP" in it be changed. + + +File: INSTALL.info, Node: Editing the Makefile and compiling, Next: The ircd-conf file, Prev: The config-h file, Up: Top + +Editing the Makefile and compiling +********************************** + + This package now uses GNU autoconf to probe your system and generate +the correct Makefile. However you need to edit it to specify specific +information, such as "prefix", "irc_mode", "ircd_mode" and "ircd_dir". + + Now to build the package, type "make all". If everything goes will, +you can then install it by typing "make install". + + If you have trouble compiling ircd, copy Makefile.in to Makefile and +edit Makefile as appropriate. + + +File: INSTALL.info, Node: The ircd-conf file, Next: Related resources, Prev: Editing the Makefile and compiling, Up: Top + +The ircd-conf file +****************** + + After installing the ircd and irc programs, edit the ircd.conf file +as per the instructions in this section and install it in the location +you specified in the config.h file. There is a sample conf file called +example.conf in the doc/ directory. + + Appendix A (See INSTALL.appendix) describes the differences between +IP addresses and host names. If you are unfamiliar with this, you +should probably scan through it before proceeding. + + The ircd.conf file contains various records that specify +configuration options. The record types are as follows: + 1. Machine information (M) + + 2. Administrative info (A) + + 3. Port connections (P) + + 4. Connection Classes (Y) + + 5. Client connections (I,i) + + 6. Operator privileges (O) + + 7. Restrict lines (R) + + 8. Excluded accounts (K,k) + + 9. Server connections (C,c,N) + + 10. Deny auto-connections (D) + + 11. Hub connections (H) + + 12. Leaf connections (L) + + 13. Version limitations (V) + + 14. Excluded machines (Q) + + 15. Service connections (S) + + 16. Bounce server (B) + + 17. Default local server (U) + + Except for types "M" and "A", you are allowed to have multiple +records of the same type. In some cases, you can have concurrent +records. `It is important to note that the last matching record will +be used'. This is especially useful when setting up I records (client +connections). + +* Menu: + +* Machine information:: +* Administrative info:: +* Port connections:: +* Connection Classes:: +* Client connections:: +* Operator priviliges:: +* Restrict connections:: +* Excluded accounts:: +* Server connections:: +* Deny auto-connections:: +* Hub connections:: +* Leaf connections:: +* Version limitations:: +* Excluded machines:: +* Service connections:: +* Bounce server:: +* Default local server (for local clients) `*OBSOLETED*':: + + +File: INSTALL.info, Node: Machine information, Next: Administrative info, Up: The ircd-conf file + +Machine information +=================== + +`Introduction' + IRC needs to know a few things about your UNIX site, and the "M" + command specifies this information for IRC. The fomat of this + command is: + +`Format' + M:::: + +`M' + "M" specifies a Machine description line + +`Server NAME' + The name of YOUR server adding any Internet DOMAINNAME that might + also be present. If this hostname can be resolved, the IP# found + will be used to for outgoing connections. Otherwise the default + interface address of the host is used. The server name may not be + FQDN of another host. (This means all outgoing connections will + be done from the same IP#, even if your host has several IP#). + +`YOUR Internet IP#' + If the machine on which you run the server has several IP + addresses, you can define which IP# to use for outgoing + connections. This overrides overrides the "Server NAME". + + See Also the "Port Connections" section. + +`Geographic Location' + Geographic Location is used to say WHERE YOUR SERVER is, and gives + people in other parts of the world a good idea of where you are! + If your server is in the USA, it is usually best to say: + , USA. Like for Denver I say: "Denver Colorado, USA". + Finnish sites (like tolsun.oulu.fi generally say something like + "Oulu, Finland". + +`Port' + Defines the port on which your server will listen for UDP pings + from other servers. This should be the port were other servers + are set to autoconnect. (Also see the port field description in + connect lines). + +`Example:' + M:tolsun.oulu.fi::Oulu, Finland:6667: + + This line reads: My Host's name is "tolsun.oulu.fi" and my site is + located in "Oulu, Finland". + + M:orion.cair.du.edu::Denver Colorado, USA:6667: + + This line reads: My Hosts name is "orion.cair.du.edu" and my site + is located in "Denver Colorado, USA". + + +File: INSTALL.info, Node: Administrative info, Next: Port connections, Prev: Machine information, Up: The ircd-conf file + +Administrative info +=================== + +`Introduction' + The "A" line is used for administrative information about a site. + The e-mail address of the person running the server should be + included here in case problems arise. + +`Format' + A::::: + +`A' + This specifies an Admin record. + +`Your Name & Location' + Use this field to say tell your FULL NAME and where in the world + your machine is. Be sure to add your City, State/Province and + Country. + +`Your Electronix Mailing Addr' + Use this field to specify your Electronic Mailing Address + preferably your Internet Mailing Address. If you have a UUCP or + ARAPnet address - please add that as well. Be sure to add any + extra DOMAIN information that is needed, for example "mail + jtrim@orion" probably won't work as a mail address to me if you + happen to be in Alaska. But "mail jtrim@orion.cair.du.edu" would + work because you know that "orion" is part of the DOMAIN + "cair.du.edu". So be sure to add your DOMAINNAMES to your mailing + addresses. + +`Other' + This is really an OTHER field - you can add what you want here. + +`Example' + (the line is just one line in the confuration file, here it is cut + into two lines to make it clearer to read): + + A:Jeff Trim - Denver Colorado, USA:INET jtrim@orion.cair.du.edu + UUCP {hao,isis}!udenva!jtrim:Terve! Heippa! Have you said hello + in Finnish today?;):: + + Would look like this when printed out with the /admin command: + + Jeff Trim - Denver Colorado, USA INET jtrim@orion.cair.du.edu + UUCP {hao,isis}!udenva!jtrim Terve! Hei! Heippa! Have you said + hello in Finnish today? ;) + + Note that the A record cannot be split across multiple lines; it + will typically be longer than 80 characters and will therefore + wrap around the screen. + + +File: INSTALL.info, Node: Port connections, Next: Connection Classes, Prev: Administrative info, Up: The ircd-conf file + +Port connections +================ + +`Introduction' + The port line adds flexibility to the server's ability to accept + connections. By use of this line in the ircd.conf file, it is easy + to setup both Unix Domain ports for the server to accept + connections on as well as extra internet ports. + +`Format' + P::<*>::: + P::<*>:<*>:: + + * Internet Ports + `Internet IP#' + If the host on which the server runs has several IP + addresses, you can define for which IP address connections + will be accepted. If no is defined here, server will bind to + all interfaces (INADDR_ANY). See also MACHINE CONFIGURATION + section to properly configure outgoing connections. + + P:192.168.1.194:::6664: + + `Internet IP# Mask' + This defines where connections may come from and be accepted. + The IP mask uses either *'s or 0's as wildcards. The + following two lines are the same: + + P:::128.2.*:6664: P:::128.2.0.0:6664: + + The incoming isn't matched against the mask, rather the ip# + string is decoded and compared segment by segment. Thus + + P:::128.2*.1.2:6664: + + will not match 128.20.1.2. + + `Port' + The port number field tells the server which port number it + should listen on for incoming connections. + + * Unix Socket Ports. + `Directory' + The path set in this field should be the directory name in + which to create the unix socket for later listening to. The + server will attempt to create the directory before creating + the unix socket. + + `Port' + The port field when used in combination with a pathname in a + P-line is the filename created in the directory set in the + first field. + + `Example' + P:/tmp/.ircd:::6667: + + Creates a unix socket in the /tmp/.ircd directory called + "6667". The unix socket (file) must be a numerical. + +`Note' + You need at least one P line. + + +File: INSTALL.info, Node: Connection Classes, Next: Client connections, Prev: Port connections, Up: The ircd-conf file + +Connection Classes +================== + +`Introduction' + To enable more efficient use of MAXIMUM_LINKS, connection classes + were implemented. All clients belong to a connection class. + + Each line for a server should have the same number as the sixth + field. If it is absent, the server deaults it to 0, using the + defaults from the config.h file. + + To define a connection class, you need to include a Y: line in the + ircd.conf file. This enables you to define the ping frequency, + connection frequency (for servers) and maximum number of links + that class should have. + + Currently, the Y: line `MUST' appear in the ircd.conf file + `BEFORE' it is used in any other way. + +`Format' + Y::::::: + +`Y' + This specifies a Class record. + +`Class' + This is the class number which gains the following attributes and + should match that which is on the end of the C/c/N/I/O/S line. + +`Ping Frequency' + This field defines how long the server will let the connection + remain "silent" before sending a PING message to make sure it is + still alive. Unless you are sure of what you are doing, use the + default value which is in your config.h file. + +`Connect Frequency' + By changing this number, you change how often your server checks + to see if it can connect to this server. If you want to check very + occasionally, use a large value, but if it is an important + connection, you might want a smaller value so that you connect to + it as soon as possible. + +`Max Links' + This field defines the maximum number of links this class will + allow from automatic connections (C lines). Using /CONNECT + overrides this feature. Also defines the maximum number of users + in this class for I/O lines per I/O line. + +`SendQ' + This field defines the "SendQ" value for this class. If this + field is not present, the default (from config.h) is assigned. + +`Local limit' + This field is used to limit the number of local concurrent + connections. The format is . + * x: defines the maximum number of clients from the same host + (IP) will be allowed. + + * y: defines the maximum number of clients from the same + user@host (IP) will be allowed. Read note below. + + Only x or y may be set, any unset value defaults to zero. + +`Global limit' + This field has the same use as the "Local limit" field. But, the + connection counts are done for all clients present on the net + instead of only counting local clients. + +`Note' + leaving any of the fields (except SendQ) out means their value is + 0 (ZERO)!! The SendQ field default value is dynamically + determined. + +`Note' + If you plan to use the local user@host limit, please read the + following very carefully. The "user" value is the ident reply for + the connection. If no reply was given then it defaults to + "unknown" and thus the effective limit will be per host, not per + user@host. Also, some ident servers return encrypted data which + changes for every connection making the limit void. + +`Note' + Only the local limitation is accurate. + +`Note' + If you define a gobal limit, you should also define a local limit + (same or lower) as it won't take more CPU and will make the global + limit more accurate. + +`Note' + The local and global limits only affect users (I lines), not + servers nor services. + +`Example' + Y:23:120:300:5:100000:0:0: (server class) + + This defines class 23 to allow 5 auto-connections, which are + checked every 300 seconds. The connection is allowed to remain + silent for 120 seconds before a PING is sent. NOTE: fields 3 & 4 + are in seconds. The SendQ is set to 100000 bytes. + + Another feature of connection class is the ability to do automatic + routing by using the class as a "priority". If you are connected + to a server which has a class lower than one of the servers that + is "behind" it, the server will disconnect the lower class one and + schedule a "new" connection for the higher class server. + + Y:1:60:0:50:20000:2:5: (client class) + + In case of a client class, the fields are interpreted a bit + differently. This class (number 1) can be used by up to 50 users. + The connections are allowed to remain silent for 60 seconds + before a PING is set. The SendQ is set to 20000 bytes. A new + connection in this class will only be allowed if there aren't more + than 2 other local connections from the same IP address, or more + than 5 other connections on the net from the same hostname. + + Y:2:60:0:50:20000:2.1:5: (client class) + + In case of a client class, the fields are interpreted a bit + differently. This class (number 1) can be used by up to 50 users. + The connections are allowed to remain silent for 60 seconds + before a PING is set. The SendQ is set to 20000 bytes. A new + connection in this class will only be allowed if there aren't more + than 2 other local connections from the same IP address, 1 other + local connection from the same user from the same IP address, or + more than 5 other connections on the net from the same hostname. + + +File: INSTALL.info, Node: Client connections, Next: Operator priviliges, Prev: Connection Classes, Up: The ircd-conf file + +Client connections +================== + + How to let clients connect to your IRCD. +`Introduction' + A client is a program that connects to the ircd daemon (ircd). + There are clients written in C, GNU Emacs Lisp and many other + languages. The "irc" program is the C client. Each person that + talks via IRC is running their own client. + + The ircd.conf files contains entries that specify which clients + are allowed to connect to your irc daemon. Obviously you want to + allow your own machine's clients to connect. You may want to + allow clients from other sites to connect. These remote clients + will use your server as a connection point. All messages sent by + these clients will pass through your machine. + +`Format' + I::::: + i::::: + +`TARGET Host Addr' + Specifies the IP address(es) of the machine(s) that are allowed to + connect. If "user@" prefixes the actual IP address the server + will require that the remote username returned by the ident server + be the same as the one given before the "@". Wildcards are + permitted unless using a bitmask (e.g. 1.2.3.0/24). + +`Password' + The password that must be given by the client to be allowed on the + server. + +`TARGET Host NAME' + Specifies the host name(s) of the machines allowed to connect to + the server. If "user@" prefixes the actual IP address the server + will require that the remote username returned by the ident server + be the same as the one given before the "@". Wildcards are + permitted. + + This field can be empty, it then has a special meaning. See Below. + +`Port' + Specifies the port number for which this configuration line is + valid. An empty field, or "0" matches all ports. + +`Class' + This field should refer to an existing class. Connections classes + are usefull to limit the number of users allowed on the server. + +`Note' + The server first checks if the client hostname (or any aliases) + matches the `TARGET Host NAME' field. If a match is found, the + client is accepted. If not, the server checks if the IP address + of the client matches the `TARGET Host Addr' field. The matching + field is used to set the name of the client: for example, if the + client matches the `TARGET Host Addr' field, it will show on IRC + with a numerical address (even if this address is resolvable). If + the `TARGET Host NAME' field is empty, then the host name is + always used (when available). + +`Examples' + For example, if you were installing IRC on tolsun.oulu.fi and you + wanted to allow examples sake let us assume you were making this + file for tolsun and you wanted to let your own clients to connect + to your server, you would add this entry to the file: + + I:x::tolsun.oulu.fi::1 + + If you wanted to let remote clients connect, you could add the + following lines: + + I:x::*.du.edu::1 + + Allow any clients from machines whose names end in ".du.edu" to + connect with no password. + + I:128.214.6.100::nic.funet.fi::1 + + Allow clients from a machine with that IP number to connect. + Numeric match is enough, name is not required anymore. + + I:x:secret:*.tut.fi::1 + + Allow clients from machines matching "*.tut.fi" to connect with + the password "secret". + + I:*::*::1 + + Allow anyone from anywhere to connect your server. + + This is the easiest way, but it also allows people to for example + dump files to your server, or connect 1000 (or how many open + sockets per process your OS allows) clients to your machine and + take your network ports. Of course the same things can be done by + simply telnetting to your machine's SMTP port (for example). + + I:x::*.fi:6667:1 + + Allow clients from machines matching "*.fi" to connect on the port + 6667. + + I:135.11.35.*::*.net::1 + + Allows clients from machines which host name matches "*.net" or + which IP address matches "135.11.35.*" to connect to the server. + If the host name does not match "*.net" then the IP address is + used for these clients, even if the host name is known. + + I:135.11.35.*::::1 + + Allows clients from machines which IP address matches + "135.11.35.*" to connect to the server. If the host name is + known, is it used as address for these clients. + +`NEW!!!' + As of the 2.7.2d version of the server, the server is able to + accept connections on multiple ports. I-lines are required for + each P-line to allow connections to be accepted. For unix sockets, + this means either adding I:/path/port::/path/port or some variation + (wildcards are recognised here). For internet ports, there must be + an I-line which allows the host access as normal, but the port + field of the I-line must match that of the port of the socket + accepting the connectiion. A port number of 0 is a wildcard + (matches all ports). + +`NEW!!!' + As of the 2.9.1 version of the server, i lines are introduced. + They work the same way as I lines, but the clients matching an i + line will have a restricted connection. (no nick/mode change, no + kick). Such users will have their username prefixed by +, = or - + depending on the ident reply. + + +File: INSTALL.info, Node: Operator priviliges, Next: Restrict connections, Prev: Client connections, Up: The ircd-conf file + +Operator priviliges +=================== + + How to become the IRC administrator on your site +`Introduction' + To become an IRC Administrator, IRC must know who is authorized to + become an operator and what their "Nickname" and "Password" is. + +`Format' + O::::: + +`O' + Speficies Operator record. If you use capital letter ("O") in it, + it specifies a global operator. Small letter ("o") specifies a + local operator. Local operator has basically the same rights + except global operator with some restrictions. + +`TARGET Host NAME' + Tells IRC which host you have the privileges FROM. This means + that you should be logged into this host when you ask for the + priviliges. If you specify "tolsun.oulu.fi" then IRC will expect + your CLIENT to be connected at "tolsun.oulu.fi" - when you ask for + OPERATOR privileges from "tolsun.oulu.fi". You cannot be logged in + at any other host and be able to use your OPERATOR privileges at + tolsun, only when you are connected at TOLSUN will this work - + this is a safeguard against unauthorized sites. + +`Password' + If your AUTHORIZATION Password - this is the password that let's + IRC know you are who you say you are! Never tell anyone your + password and always keep the "ircd.conf" file protected from all + of the other users. + +`Nickname' + The Nickname you usually go by - but you can make this what you + want. + +`Port' + Unused. + +`Class' + The class field should refer to an existing class (preferably + having a lower number than that for the relevant I-line) and + determines the maximum number of simultaneous uses of the O-line + allowable through the max. links field in the Y-line. + +`Example' + O:orion.cair.du.edu:pyunxc:Jeff::1 + + There is an OPERATOR at "orion.cair.du.edu" that can get Operator + priviliges if he specifies a password of "pyunxc" and uses a + NICKNAME of "Jeff". + + +File: INSTALL.info, Node: Restrict connections, Next: Excluded accounts, Prev: Operator priviliges, Up: The ircd-conf file + +Restrict connections +==================== + + Let an external program decide if a client should be allowed or not. +`Introduction' + R lines provide a convenient way to handle user access to the + server with an external program. The outside program given three + parameters: the client's username (set by the USER command), the + client's hostname, and the client's ident reply ("unknown" if + none). + + It is expected to return a reply line where the first word is + either "Y" or "N" meaning `Yes Let them in" or "No don't let them + in". If the first word begins with neither "Y" or "N" the default + is to let the person on. + +`Format' + R:::::: + +`R' + This specifies a restrict record. + +`Target Host Name' + In this field you specify the Hostname that the user is connecting + from. If you wanted to restrict connects to IRC from + "orion.cair.du.edu" then you would want to enter + "orion.cair.du.edu". + +`Program' + This is the external program to run to know if the user is allowed + on your server. + +`User' + The Username of the user you want removed from IRC. For example + "root". + + +File: INSTALL.info, Node: Excluded accounts, Next: Server connections, Prev: Restrict connections, Up: The ircd-conf file + +Excluded accounts +================= + + Remove an errant user from IRC on your site. +`Introduction' + Obviously it is hoped that you wouldn't have to use this command. + Unfortunately sometimes a user can become unmanageable and this is + your only recourse - the KILL USER command. THIS COMMAND ONLY + AFFECTS YOUR SERVER - If this user can connect to another SERVER + somewhere else in the IRC-Network then you would have to talk to + the administrator on that site to disable his access from that + IRCD Server as well. + +`Format' + K::