[IRC-Dev CVS] [CVS] Module ircd-ircdev: Change committed
Brought to you by:
zolty
From: Toni G. <zo...@us...> - 2003-11-12 05:39:45
|
CVSROOT : /cvsroot/irc-dev Module : ircd-ircdev Commit time: 2003-11-11 21:36:31 UTC Modified files: ChangeLog ChangeLog.es configure configure.in include/channel.h include/client.h include/handlers.h include/ircd_features.h include/numeric.h include/patchlevel.h include/res.h include/s_user.h include/struct.h include/whocmds.h ircd/Makefile.in ircd/channel.c ircd/gline.c ircd/ircd.c ircd/ircd_features.c ircd/ircd_log.c ircd/ircd_relay.c ircd/ircd_snprintf.c ircd/jupe.c ircd/listener.c ircd/m_account.c ircd/m_burst.c ircd/m_destruct.c ircd/m_join.c ircd/m_kick.c ircd/m_links.c ircd/m_map.c ircd/m_mode.c ircd/m_names.c ircd/m_nick.c ircd/m_opmode.c ircd/m_part.c ircd/m_ping.c ircd/m_userhost.c ircd/m_userip.c ircd/m_who.c ircd/m_whois.c ircd/parse.c ircd/s_auth.c ircd/s_bsd.c ircd/s_debug.c ircd/s_err.c ircd/s_misc.c ircd/s_serv.c ircd/s_stats.c ircd/s_user.c ircd/uping.c ircd/whocmds.c Added files: include/destruct_event.h include/ircd_tea.h ircd/destruct_event.c ircd/ircd_tea.c Log message: Author: zoltan <zo...@ir...> Log message: 2003-11-11 Toni Garcia <zo...@ir...> 1.0.alpha6 * Se incluye la encriptacion TEA en el ircd. * Se separa el codigo especial de Undernet con defines. * Sincronizacion con algunos parches del u2.10.12. * Sincronizacion con u2.10.11.06. ---------------------- diff included ---------------------- Index: ircd-ircdev/ChangeLog diff -u ircd-ircdev/ChangeLog:1.6 ircd-ircdev/ChangeLog:1.7 --- ircd-ircdev/ChangeLog:1.6 Sun Nov 2 10:34:46 2003 +++ ircd-ircdev/ChangeLog Tue Nov 11 13:36:21 2003 @@ -1,10 +1,16 @@ # # ChangeLog for ircd-ircdev # -# $Id: ChangeLog,v 1.6 2003/11/02 18:34:46 zolty Exp $ +# $Id: ChangeLog,v 1.7 2003/11/11 21:36:21 zolty Exp $ # # Insert new changes at beginning of the change list. # +2003-11-11 Toni Garcia <zo...@ir...> 1.0.alpha6 + * Includes TEA encryptation. + * Separates Undernet special code with defines. + * Synchronization with some patches of u2.10.12. + * Synchronization with u2.10.11.06. + 2003-11-02 Toni Garcia <zo...@ir...> 1.0.alpha5 * Check lex and yacc (configure.in). * Fix bison bug (ircd_parser.y). Index: ircd-ircdev/ChangeLog.es diff -u ircd-ircdev/ChangeLog.es:1.6 ircd-ircdev/ChangeLog.es:1.7 --- ircd-ircdev/ChangeLog.es:1.6 Sun Nov 2 10:34:46 2003 +++ ircd-ircdev/ChangeLog.es Tue Nov 11 13:36:21 2003 @@ -1,10 +1,16 @@ # # Log de Cambios para ircd-ircdev # -# $Id: ChangeLog.es,v 1.6 2003/11/02 18:34:46 zolty Exp $ +# $Id: ChangeLog.es,v 1.7 2003/11/11 21:36:21 zolty Exp $ # # Insertar los nuevos cambios al principio de esta lista de cambios. # +2003-11-11 Toni Garcia <zo...@ir...> 1.0.alpha6 + * Se incluye la encriptacion TEA en el ircd. + * Se separa el codigo especial de Undernet con defines. + * Sincronizacion con algunos parches del u2.10.12. + * Sincronizacion con u2.10.11.06. + 2003-11-02 Toni Garcia <zo...@ir...> 1.0.alpha5 * Chequeo de lex y yacc en el configure.in. * Fix de un bug de bison (ircd_parser.y). Index: ircd-ircdev/configure diff -u ircd-ircdev/configure:1.5 ircd-ircdev/configure:1.6 --- ircd-ircdev/configure:1.5 Sun Nov 2 10:34:47 2003 +++ ircd-ircdev/configure Tue Nov 11 13:36:21 2003 @@ -3055,117 +3055,6 @@ -echo "$as_me:$LINENO: checking for library containing res_mkquery" >&5 -echo $ECHO_N "checking for library containing res_mkquery... $ECHO_C" >&6 -if test "${ac_cv_search_res_mkquery+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_func_search_save_LIBS=$LIBS -ac_cv_search_res_mkquery=no -cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char res_mkquery (); -int -main () -{ -res_mkquery (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_search_res_mkquery="none required" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext -if test "$ac_cv_search_res_mkquery" = no; then - for ac_lib in resolv; do - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char res_mkquery (); -int -main () -{ -res_mkquery (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_search_res_mkquery="-l$ac_lib" -break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext - done -fi -LIBS=$ac_func_search_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_search_res_mkquery" >&5 -echo "${ECHO_T}$ac_cv_search_res_mkquery" >&6 -if test "$ac_cv_search_res_mkquery" != no; then - test "$ac_cv_search_res_mkquery" = "none required" || LIBS="$ac_cv_search_res_mkquery $LIBS" - -else - { { echo "$as_me:$LINENO: error: Unable to find library containing res_mkquery()" >&5 -echo "$as_me: error: Unable to find library containing res_mkquery()" >&2;} - { (exit 1); exit 1; }; } -fi - - ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -7487,11 +7376,6 @@ echo "$as_me:$LINENO: result: Linux ($host) found." >&5 echo "${ECHO_T}Linux ($host) found." >&6 unet_poll_syscall=yes -# if test x"$ac_cv_header_sys_epoll_h" = xyes; then -# unet_poll_syscall=no -# else -# unet_poll_syscall=yes -# fi OSDEP_C=os_linux.c ;; @@ -9558,25 +9442,45 @@ echo "IRC-Dev ircd is now hopefully configured for your system." echo "" echo " Host system: $host_os" -echo " Prefix: $prefix" +echo " Engines supported:" +if test x"$unet_cv_enable_epoll" = xyes; then +echo " epoll()" +fi +if test x"$unet_cv_enable_kqueue" = xyes; then +echo " kqueue()" +fi +if test x"$unet_cv_enable_devpoll" = xyes; then +echo " /dev/poll" +fi +if test x"$unet_cv_enable_poll" = xyes; then +echo " poll()" +fi +echo "" echo " Asserts: $unet_cv_enable_asserts" echo " Warnings: $unet_cv_enable_warnings" echo " Debug: $unet_cv_enable_debug" echo " Profile: $unet_cv_enable_profile" echo " Pedantic: $unet_cv_enable_pedantic" +echo " Inlines: $unet_cv_enable_inlines" +echo " Debugging symbols: $unet_cv_enable_symbols" echo " ADNS: $unet_cv_enable_adns" -echo " Owner/mode: $unet_cv_with_owner.$unet_cv_with_group ($unet_cv_with_mode)" -echo " Chroot: $unet_cv_with_chroot" echo "" -echo " Domain: $unet_cv_with_domain" -echo " Binaries path: $prefix/bin" +echo " Prefix: $prefix" +echo " Binaries path: $unet_bindir" echo " IRCD Binary: $unet_spath" +echo " Lib path: $unet_libdir" echo " Data path: $unet_cv_with_dpath" -echo " Config path: $unet_cv_with_cpath" -echo " Log path: $unet_cv_with_lpath" +echo " Config file: $unet_cpath" +echo " Debug log file: $unet_lpath" +echo " Owner/mode: $unet_cv_with_owner.$unet_cv_with_group ($unet_cv_with_mode)" +echo " Chroot: $unet_cv_with_chroot" +echo "" echo " Maximum connections: $unet_cv_with_maxcon" +echo " Domain: $unet_cv_with_domain" +#echo " IRC Environment: DDB (Distributed DataBase)" +#echo " IRC Environment: Services (Ex TerraIRCU)" +#echo " IRC Environment: Undernet" +#echo " IRC Environment: None (BUG, mail to zo...@ir...)" echo "" -echo " poll() engine: $unet_cv_enable_poll" -echo " epoll() engine: $unet_cv_enable_epoll" -echo " kqueue() engine: $unet_cv_enable_kqueue" -echo " /dev/poll engine: $unet_cv_enable_devpoll" + + Index: ircd-ircdev/configure.in diff -u ircd-ircdev/configure.in:1.5 ircd-ircdev/configure.in:1.6 --- ircd-ircdev/configure.in:1.5 Sun Nov 2 10:34:47 2003 +++ ircd-ircdev/configure.in Tue Nov 11 13:36:21 2003 @@ -19,7 +19,7 @@ dnl along with this program; if not, write to the Free Software dnl Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. dnl -dnl $Id: configure.in,v 1.5 2003/11/02 18:34:47 zolty Exp $ +dnl $Id: configure.in,v 1.6 2003/11/11 21:36:21 zolty Exp $ dnl Make sure we are in the correct directory (someone could have run dnl 'configure' with a wrong '--srcdir'). @@ -106,11 +106,6 @@ dnl Do all the checks necessary to figure out -lnsl / -lsocket stuff AC_LIBRARY_NET -dnl Look for res_mkquery. Done after AC_LIBRARY_NET in case res_mkquery -dnl is in one of those libraries somewhere. -AC_SEARCH_LIBS(res_mkquery, resolv, , -[AC_MSG_ERROR([Unable to find library containing res_mkquery()])]) - dnl Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS(poll.h sys/devpoll.h sys/event.h sys/epoll.h) @@ -156,11 +151,6 @@ *-linux*) AC_MSG_RESULT([Linux ($host) found.]) unet_poll_syscall=yes -# if test x"$ac_cv_header_sys_epoll_h" = xyes; then -# unet_poll_syscall=no -# else -# unet_poll_syscall=yes -# fi OSDEP_C=os_linux.c ;; @@ -719,25 +709,45 @@ echo "IRC-Dev ircd is now hopefully configured for your system." echo "" echo " Host system: $host_os" -echo " Prefix: $prefix" +echo " Engines supported:" +if test x"$unet_cv_enable_epoll" = xyes; then +echo " epoll()" +fi +if test x"$unet_cv_enable_kqueue" = xyes; then +echo " kqueue()" +fi +if test x"$unet_cv_enable_devpoll" = xyes; then +echo " /dev/poll" +fi +if test x"$unet_cv_enable_poll" = xyes; then +echo " poll()" +fi +echo "" echo " Asserts: $unet_cv_enable_asserts" echo " Warnings: $unet_cv_enable_warnings" echo " Debug: $unet_cv_enable_debug" echo " Profile: $unet_cv_enable_profile" echo " Pedantic: $unet_cv_enable_pedantic" +echo " Inlines: $unet_cv_enable_inlines" +echo " Debugging symbols: $unet_cv_enable_symbols" echo " ADNS: $unet_cv_enable_adns" -echo " Owner/mode: $unet_cv_with_owner.$unet_cv_with_group ($unet_cv_with_mode)" -echo " Chroot: $unet_cv_with_chroot" echo "" -echo " Domain: $unet_cv_with_domain" -echo " Binaries path: $prefix/bin" +echo " Prefix: $prefix" +echo " Binaries path: $unet_bindir" echo " IRCD Binary: $unet_spath" +echo " Lib path: $unet_libdir" echo " Data path: $unet_cv_with_dpath" -echo " Config path: $unet_cv_with_cpath" -echo " Log path: $unet_cv_with_lpath" +echo " Config file: $unet_cpath" +echo " Debug log file: $unet_lpath" +echo " Owner/mode: $unet_cv_with_owner.$unet_cv_with_group ($unet_cv_with_mode)" +echo " Chroot: $unet_cv_with_chroot" +echo "" echo " Maximum connections: $unet_cv_with_maxcon" +echo " Domain: $unet_cv_with_domain" +#echo " IRC Environment: DDB (Distributed DataBase)" +#echo " IRC Environment: Services (Ex TerraIRCU)" +#echo " IRC Environment: Undernet" +#echo " IRC Environment: None (BUG, mail to zo...@ir...)" echo "" -echo " poll() engine: $unet_cv_enable_poll" -echo " epoll() engine: $unet_cv_enable_epoll" -echo " kqueue() engine: $unet_cv_enable_kqueue" -echo " /dev/poll engine: $unet_cv_enable_devpoll" + + Index: ircd-ircdev/include/channel.h diff -u ircd-ircdev/include/channel.h:1.2 ircd-ircdev/include/channel.h:1.3 --- ircd-ircdev/include/channel.h:1.2 Sat Nov 1 09:19:35 2003 +++ ircd-ircdev/include/channel.h Tue Nov 11 13:36:21 2003 @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Id: channel.h,v 1.2 2003/11/01 17:19:35 zolty Exp $ + * $Id: channel.h,v 1.3 2003/11/11 21:36:21 zolty Exp $ */ #ifndef INCLUDED_channel_h #define INCLUDED_channel_h @@ -40,6 +40,9 @@ #define MODEBUFLEN 200 #define KEYLEN 23 +#if defined(UNDERNET) +#define PASSLEN 23 +#endif #define CHANNELLEN 200 #define MAXJOINARGS 15 /* number of slots for join buffer */ @@ -67,6 +70,11 @@ #define CHFL_BANNED 0x1000 /* Channel member is banned */ #define CHFL_SILENCE_IPMASK 0x2000 /* silence mask is an IP-number mask */ #define CHFL_USER_PARTING 0x4000 /* User is already parting that channel */ +#if defined(UNDERNET) +#define CHFL_BURST_ALREADY_OPPED 0x08000 /* In oob BURST, but was already joined and opped */ +#define CHFL_BURST_ALREADY_VOICED 0x10000 /* In oob BURST, but was already joined and voiced */ +#define CHFL_CHANNEL_MANAGER 0x20000 /* Set when creating channel or using Apass */ +#endif #define CHFL_OVERLAP (CHFL_CHANOP | CHFL_VOICE) #define CHFL_BANVALIDMASK (CHFL_BANVALID | CHFL_BANNED) @@ -90,18 +98,31 @@ #define MODE_SAVE 0x20000 /* save this mode-with-arg 'til later */ #define MODE_FREE 0x40000 /* string needs to be passed to MyFree() */ #define MODE_BURSTADDED 0x80000 /* channel was created by a BURST */ +#if defined(UNDERNET) +#define MODE_UPASS 0x100000 +#define MODE_APASS 0x200000 +#endif /* * mode flags which take another parameter (With PARAmeterS) */ #define MODE_WPARAS (MODE_CHANOP|MODE_VOICE|MODE_BAN|MODE_KEY|MODE_LIMIT) +#if defined(UNDERNET) +#define infochanmodes feature_bool(FEAT_OPLEVELS) ? "Abiklmnopstuvr" : "biklmnopstvr" +#define infochanmodeswithparams feature_bool(FEAT_OPLEVELS) ? "Abklouv" : "bklov" +#else +#define infochanmodes "biklmnopstvr" +#define infochanmodeswithparams "bklov" +#endif + #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) || find_channel_member((v),(c))) +#define ShowChannel(v,c) (PubChannel(c) || find_channel_member((v),(c)) || \ + (IsAnOper(v) && HasPriv(v, PRIV_LIST_CHAN))) #define PubChannel(x) ((!x) || ((x)->mode.mode & \ (MODE_PRIVATE | MODE_SECRET)) == 0) #define is_listed(x) ((x)->mode.mode & MODE_LISTED) @@ -170,18 +191,32 @@ struct Membership* next_channel; struct Membership* prev_channel; unsigned int status; +#if defined(UNDERNET) + unsigned short oplevel; +#endif }; +#if defined(UNDERNET) +#define MAXOPLEVELDIGITS 3 +#define MAXOPLEVEL 999 +#endif + #define IsZombie(x) ((x)->status & CHFL_ZOMBIE) #define IsDeopped(x) ((x)->status & CHFL_DEOPPED) #define IsBanned(x) ((x)->status & CHFL_BANNED) #define IsBanValid(x) ((x)->status & CHFL_BANVALID) #define IsChanOp(x) ((x)->status & CHFL_CHANOP) +#if defined(UNDERNET) +#define OpLevel(x) ((x)->oplevel) +#endif #define HasVoice(x) ((x)->status & CHFL_VOICE) #define IsServOpOk(x) ((x)->status & CHFL_SERVOPOK) #define IsBurstJoined(x) ((x)->status & CHFL_BURST_JOINED) #define IsVoicedOrOpped(x) ((x)->status & CHFL_VOICED_OR_OPPED) #define IsUserParting(x) ((x)->status & CHFL_USER_PARTING) +#if defined(UNDERNET) +#define IsChannelManager(x) ((x)->status & CHFL_CHANNEL_MANAGER) +#endif #define SetBanned(x) ((x)->status |= CHFL_BANNED) #define SetBanValid(x) ((x)->status |= CHFL_BANVALID) @@ -190,6 +225,10 @@ #define SetBurstJoined(x) ((x)->status |= CHFL_BURST_JOINED) #define SetZombie(x) ((x)->status |= CHFL_ZOMBIE) #define SetUserParting(x) ((x)->status |= CHFL_USER_PARTING) +#if defined(UNDERNET) +#define SetChannelManager(x) ((x)->status |= CHFL_CHANNEL_MANAGER) +#define SetOpLevel(x, v) (void)((x)->oplevel = (v)) +#endif #define ClearBanned(x) ((x)->status &= ~CHFL_BANNED) #define ClearBanValid(x) ((x)->status &= ~CHFL_BANVALID) @@ -202,12 +241,17 @@ unsigned int mode; unsigned int limit; char key[KEYLEN + 1]; +#if defined(UNDERNET) + char upass[PASSLEN + 1]; + char apass[PASSLEN + 1]; +#endif }; struct Channel { struct Channel* next; struct Channel* prev; struct Channel* hnext; + struct DestructEvent* destruct_event; time_t creationtime; time_t topic_time; unsigned int users; @@ -294,7 +338,7 @@ */ extern void clean_channelname(char* name); extern void channel_modes(struct Client *cptr, char *mbuf, char *pbuf, - int buflen, struct Channel *chptr); + int buflen, struct Channel *chptr, struct Membership *member); extern int set_mode(struct Client* cptr, struct Client* sptr, struct Channel* chptr, int parc, char* parv[], char* mbuf, char* pbuf, char* npbuf, int* badop); @@ -305,9 +349,10 @@ extern struct Membership* find_member_link(struct Channel * chptr, const struct Client* cptr); extern int sub1_from_channel(struct Channel* chptr); +extern int destruct_channel(struct Channel* chptr); extern int can_join(struct Client *sptr, struct Channel *chptr, char *key); extern void add_user_to_channel(struct Channel* chptr, struct Client* who, - unsigned int flags); + unsigned int flags, int oplevel); extern void cancel_mode(struct Client *sptr, struct Channel *chptr, char m, const char *param, int *count); extern void add_token_to_sendbuf(char *token, size_t *sblenp, int *firstp, @@ -336,7 +381,12 @@ extern int is_chan_op(struct Client *cptr, struct Channel *chptr); extern int is_zombie(struct Client *cptr, struct Channel *chptr); extern int has_voice(struct Client *cptr, struct Channel *chptr); -extern int IsInvited(struct Client* cptr, struct Channel* chptr); +/* + NOTE: pointer is compared, and not dereferenced, called by + add_target with a void*, since targets could be anything, + this function can't make any assumptions that it has a channel +*/ +extern int IsInvited(struct Client* cptr, const void* chptr); extern void send_channel_modes(struct Client *cptr, struct Channel *chptr); extern char *pretty_mask(char *mask); extern void del_invite(struct Client *cptr, struct Channel *chptr); @@ -361,7 +411,8 @@ extern int mode_parse(struct ModeBuf *mbuf, struct Client *cptr, struct Client *sptr, struct Channel *chptr, - int parc, char *parv[], unsigned int flags); + int parc, char *parv[], unsigned int flags, + struct Membership* member); #define MODE_PARSE_SET 0x01 /* actually set channel modes */ #define MODE_PARSE_STRICT 0x02 /* +m +n +t style not supported */ Index: ircd-ircdev/include/client.h diff -u ircd-ircdev/include/client.h:1.2 ircd-ircdev/include/client.h:1.3 --- ircd-ircdev/include/client.h:1.2 Sat Nov 1 16:47:33 2003 +++ ircd-ircdev/include/client.h Tue Nov 11 13:36:21 2003 @@ -18,7 +18,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * - * $Id: client.h,v 1.2 2003/11/02 00:47:33 zolty Exp $ + * $Id: client.h,v 1.3 2003/11/11 21:36:21 zolty Exp $ */ #ifndef INCLUDED_client_h #define INCLUDED_client_h @@ -81,6 +81,8 @@ #define FLAGSET_SET(set, flag) (set).bits[FLAGSET_INDEX(flag)] |= FLAGSET_MASK(flag) #define FLAGSET_CLEAR(set, flag) (set).bits[FLAGSET_INDEX(flag)] &= ~FLAGSET_MASK(flag) +#define infousermodes "dioswkgx" + enum Priv { PRIV_CHAN_LIMIT, /* no channel limit on oper */ PRIV_MODE_LCHAN, /* oper can mode local chans */ @@ -110,6 +112,7 @@ PRIV_DISPLAY, /* "Is an oper" displayed */ PRIV_SEE_OPERS, /* display hidden opers */ PRIV_WIDE_GLINE, /* oper can set wider G-lines */ + PRIV_LIST_CHAN, /* oper can list secret channels */ PRIV_FORCE_OPMODE, /* oper can override a Q-line */ PRIV_FORCE_LOCAL_OPMODE,/* oper can override a local channel Q-line */ PRIV_LAST_PRIV /* must be the same as the last priv */ @@ -146,7 +149,9 @@ FLAG_CHSERV, /* Disallow KICK or MODE -o on the user; don't display channels in /whois */ FLAG_DEBUG, /* send global debug/anti-hack info */ +#if defined(UNDERNET) FLAG_ACCOUNT, /* account name has been set */ +#endif FLAG_HIDDENHOST, /* user's host is hidden */ FLAG_LAST_FLAG, FLAG_LOCAL_UMODES = FLAG_LOCOP, /* First local mode flag */ @@ -424,12 +429,18 @@ #define SendWallops(x) HasFlag(x, FLAG_WALLOP) #define IsHub(x) HasFlag(x, FLAG_HUB) #define IsService(x) HasFlag(x, FLAG_SERVICE) +#if defined(UNDERNET) #define IsAccount(x) HasFlag(x, FLAG_ACCOUNT) +#endif #define IsHiddenHost(x) HasFlag(x, FLAG_HIDDENHOST) #define IsPingSent(x) HasFlag(x, FLAG_PINGSENT) #define IsPrivileged(x) (IsAnOper(x) || IsServer(x)) +#if !defined(UNDERNET) +#define HasHiddenHost(x) (IsHiddenHost(x)) +#else #define HasHiddenHost(x) (IsAccount(x) && IsHiddenHost(x)) +#endif #define SetAccess(x) SetFlag(x, FLAG_CHKACCESS) #define SetBurst(x) SetFlag(x, FLAG_BURST) @@ -448,9 +459,14 @@ #define SetServNotice(x) SetFlag(x, FLAG_SERVNOTICE) #define SetHub(x) SetFlag(x, FLAG_HUB) #define SetService(x) SetFlag(x, FLAG_SERVICE) +#if defined(UNDERNET) #define SetAccount(x) SetFlag(x, FLAG_ACCOUNT) +#endif #define SetHiddenHost(x) SetFlag(x, FLAG_HIDDENHOST) #define SetPingSent(x) SetFlag(x, FLAG_PINGSENT) + +#define SeeOper(sptr,acptr) (IsAnOper(acptr) && (HasPriv(acptr, PRIV_DISPLAY) \ + || HasPriv(sptr, PRIV_SEE_OPERS))) #define ClearAccess(x) ClrFlag(x, FLAG_CHKACCESS) #define ClearBurst(x) ClrFlag(x, FLAG_BURST) Index: ircd-ircdev/include/destruct_event.h diff -u /dev/null ircd-ircdev/include/destruct_event.h:1.1 --- /dev/null Tue Nov 11 13:36:32 2003 +++ ircd-ircdev/include/destruct_event.h Tue Nov 11 13:36:21 2003 @@ -0,0 +1,36 @@ +#ifndef INCLUDED_destruct_event_h +#define INCLUDED_destruct_event_h +/* + * IRC - Internet Relay Chat, include/destruct_event.h + * Copyright (C) 2002 Carlo Wood <ca...@al...> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, 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: destruct_event.h,v 1.1 2003/11/11 21:36:21 zolty Exp $ + */ + +#ifndef INCLUDED_config_h +#include "config.h" +#endif +#ifndef INCLUDED_channel_h +#include "channel.h" +#endif + +extern void schedule_destruct_event_1m(struct Channel* chptr); +extern void schedule_destruct_event_48h(struct Channel* chptr); +extern void remove_destruct_event(struct Channel* chptr); +extern void exec_expired_destruct_events(struct Event* ev); + +#endif /* INCLUDED_destruct_event_h */ Index: ircd-ircdev/include/handlers.h diff -u ircd-ircdev/include/handlers.h:1.2 ircd-ircdev/include/handlers.h:1.3 --- ircd-ircdev/include/handlers.h:1.2 Tue Oct 7 11:52:17 2003 +++ ircd-ircdev/include/handlers.h Tue Nov 11 13:36:21 2003 @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Id: handlers.h,v 1.2 2003/10/07 18:52:17 zolty Exp $ + * $Id: handlers.h,v 1.3 2003/11/11 21:36:21 zolty Exp $ */ #ifndef INCLUDED_handlers_h #define INCLUDED_handlers_h @@ -184,7 +184,9 @@ /* * Server commands */ +#if defined(UNDERNET) extern int ms_account(struct Client*, struct Client*, int, char*[]); +#endif extern int ms_admin(struct Client*, struct Client*, int, char*[]); extern int ms_asll(struct Client*, struct Client*, int, char*[]); extern int ms_away(struct Client*, struct Client*, int, char*[]); Index: ircd-ircdev/include/ircd_features.h diff -u ircd-ircdev/include/ircd_features.h:1.3 ircd-ircdev/include/ircd_features.h:1.4 --- ircd-ircdev/include/ircd_features.h:1.3 Sat Nov 1 07:26:45 2003 +++ ircd-ircdev/include/ircd_features.h Tue Nov 11 13:36:21 2003 @@ -18,7 +18,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Id: ircd_features.h,v 1.3 2003/11/01 15:26:45 zolty Exp $ + * $Id: ircd_features.h,v 1.4 2003/11/11 21:36:21 zolty Exp $ */ struct Client; @@ -49,6 +49,9 @@ FEAT_HIDDEN_IP, FEAT_AUTOHIDE, FEAT_CONNEXIT_NOTICES, +#if defined(UNDERNET) + FEAT_OPLEVELS, +#endif FEAT_LOCAL_CHANNELS, /* features that probably should not be touched */ @@ -92,6 +95,7 @@ FEAT_UNLIMIT_OPER_QUERY, FEAT_LOCAL_KILL_ONLY, FEAT_CONFIG_OPERCMDS, + FEAT_LIST_CHAN, /* features that affect global opers on this server */ FEAT_OPER_KILL, @@ -111,6 +115,7 @@ FEAT_OPER_SET, FEAT_OPERS_SEE_IN_SECRET_CHANNELS, FEAT_OPER_WIDE_GLINE, + FEAT_OPER_LIST_CHAN, /* features that affect local opers on this server */ FEAT_LOCOP_KILL, @@ -125,6 +130,7 @@ FEAT_LOCOP_SET, FEAT_LOCOP_SEE_IN_SECRET_CHANNELS, FEAT_LOCOP_WIDE_GLINE, + FEAT_LOCOP_LIST_CHAN, /* HEAD_IN_SAND Features */ FEAT_HIS_SNOTICES, Index: ircd-ircdev/include/ircd_tea.h diff -u /dev/null ircd-ircdev/include/ircd_tea.h:1.1 --- /dev/null Tue Nov 11 13:36:32 2003 +++ ircd-ircdev/include/ircd_tea.h Tue Nov 11 13:36:21 2003 @@ -0,0 +1,30 @@ +/* + * IRC - Internet Relay Chat, ircd/ircd_tea.h + * + * See file AUTHORS in IRC package for additional names of + * the programmers. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id: ircd_tea.h,v 1.1 2003/11/11 21:36:21 zolty Exp $ + */ +#ifndef INCLUDED_ircd_tea_h +#define INCLUDED_ircd_tea_h + +extern void ircd_tea(unsigned int v[], unsigned int k[], unsigned int x[]); +extern void ircd_untea(unsigned int v[], unsigned int k[], unsigned int x[]); + +#endif /* INCLUDED_ircd_tea_h */ + Index: ircd-ircdev/include/numeric.h diff -u ircd-ircdev/include/numeric.h:1.2 ircd-ircdev/include/numeric.h:1.3 --- ircd-ircdev/include/numeric.h:1.2 Tue Oct 7 11:52:18 2003 +++ ircd-ircdev/include/numeric.h Tue Nov 11 13:36:21 2003 @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Id: numeric.h,v 1.2 2003/10/07 18:52:18 zolty Exp $ + * $Id: numeric.h,v 1.3 2003/11/11 21:36:21 zolty Exp $ */ #ifndef INCLUDED_numeric_h #define INCLUDED_numeric_h @@ -63,6 +63,9 @@ #define RPL_MAP 15 /* Undernet extension */ #define RPL_MAPMORE 16 /* Undernet extension */ #define RPL_MAPEND 17 /* Undernet extension */ +#if defined(UNDERNET) +#define RPL_APASSWARN 30 /* Undernet extension */ +#endif /* RPL_YOURID 42 IRCnet extension */ /* RPL_ATTEMPTINGJUNC 50 aircd extension */ /* RPL_ATTEMPTINGREROUTE 51 aircd extension */ @@ -449,6 +452,13 @@ ERR_WHOLIMEXCEED 523 dalnet */ #define ERR_QUARANTINED 524 /* Undernet extension -Vampire */ +#if defined(UNDERNET) +#define ERR_NOTLOWEROPLEVEL 550 /* Undernet extension */ +#define ERR_NOTMANAGER 551 /* Undernet extension */ +#define ERR_CHANSECURED 552 /* Undernet extension */ +#define ERR_UPASSSET 553 /* Undernet extension */ +#define ERR_UPASSNOTSET 554 /* Undernet extension */ +#endif #define RPL_LOGON 600 /* Dalnet extension */ #define RPL_LOGOFF 601 /* Dalnet extension */ Index: ircd-ircdev/include/patchlevel.h diff -u ircd-ircdev/include/patchlevel.h:1.6 ircd-ircdev/include/patchlevel.h:1.7 --- ircd-ircdev/include/patchlevel.h:1.6 Sun Nov 2 10:34:47 2003 +++ ircd-ircdev/include/patchlevel.h Tue Nov 11 13:36:21 2003 @@ -15,10 +15,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Id: patchlevel.h,v 1.6 2003/11/02 18:34:47 zolty Exp $ + * $Id: patchlevel.h,v 1.7 2003/11/11 21:36:21 zolty Exp $ * */ -#define PATCHLEVEL ".alpha5" +#define PATCHLEVEL ".alpha6" #define RELEASE "1.0" Index: ircd-ircdev/include/res.h diff -u ircd-ircdev/include/res.h:1.2 ircd-ircdev/include/res.h:1.3 --- ircd-ircdev/include/res.h:1.2 Sat Nov 1 16:47:33 2003 +++ ircd-ircdev/include/res.h Tue Nov 11 13:36:21 2003 @@ -1,7 +1,7 @@ /* * irc2.7.2/ircd/res.h (C)opyright 1992 Darren Reed. * - * $Id: res.h,v 1.2 2003/11/02 00:47:33 zolty Exp $ + * $Id: res.h,v 1.3 2003/11/11 21:36:21 zolty Exp $ */ #ifndef INCLUDED_res_h #define INCLUDED_res_h @@ -16,7 +16,7 @@ struct DNSQuery { void* vptr; /* pointer used by callback to identify request */ - void (*callback)(void* vptr, struct hostent* reply); /* callback to call */ + void (*callback)(void* vptr, struct hostent* he); /* callback to call */ }; extern int ResolverFileDescriptor; /* GLOBAL - file descriptor (s_bsd.c) */ Index: ircd-ircdev/include/s_user.h diff -u ircd-ircdev/include/s_user.h:1.1.1.1 ircd-ircdev/include/s_user.h:1.2 --- ircd-ircdev/include/s_user.h:1.1.1.1 Mon Sep 8 03:34:28 2003 +++ ircd-ircdev/include/s_user.h Tue Nov 11 13:36:21 2003 @@ -1,7 +1,7 @@ /* * s_user.h * - * $Id: s_user.h,v 1.1.1.1 2003/09/08 10:34:28 zolty Exp $ + * $Id: s_user.h,v 1.2 2003/11/11 21:36:21 zolty Exp $ */ #ifndef INCLUDED_s_user_h #define INCLUDED_s_user_h @@ -77,7 +77,7 @@ InfoFormatter fmt); extern int add_silence(struct Client* sptr, const char* mask); -extern int hide_hostmask(struct Client *cptr, unsigned int flag); +extern int hide_hostmask(struct Client *cptr, unsigned int flags); extern int set_user_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv[]); extern int is_silenced(struct Client *sptr, struct Client *acptr); Index: ircd-ircdev/include/struct.h diff -u ircd-ircdev/include/struct.h:1.2 ircd-ircdev/include/struct.h:1.3 --- ircd-ircdev/include/struct.h:1.2 Tue Oct 7 11:52:18 2003 +++ ircd-ircdev/include/struct.h Tue Nov 11 13:36:21 2003 @@ -18,7 +18,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Id: struct.h,v 1.2 2003/10/07 18:52:18 zolty Exp $ + * $Id: struct.h,v 1.3 2003/11/11 21:36:21 zolty Exp $ */ #ifndef INCLUDED_struct_h #define INCLUDED_struct_h @@ -77,7 +77,9 @@ char username[USERLEN + 1]; char host[HOSTLEN + 1]; char realhost[HOSTLEN + 1]; +#if defined(UNDERNET) char account[ACCOUNTLEN + 1]; +#endif }; #endif /* INCLUDED_struct_h */ Index: ircd-ircdev/include/whocmds.h diff -u ircd-ircdev/include/whocmds.h:1.1.1.1 ircd-ircdev/include/whocmds.h:1.2 --- ircd-ircdev/include/whocmds.h:1.1.1.1 Mon Sep 8 03:34:28 2003 +++ ircd-ircdev/include/whocmds.h Tue Nov 11 13:36:21 2003 @@ -1,7 +1,7 @@ /* * whocmds.h * - * $Id: whocmds.h,v 1.1.1.1 2003/09/08 10:34:28 zolty Exp $ + * $Id: whocmds.h,v 1.2 2003/11/11 21:36:21 zolty Exp $ */ #ifndef INCLUDED_whocmds_h #define INCLUDED_whocmds_h @@ -36,15 +36,22 @@ #define WHO_FIELD_DIS 256 #define WHO_FIELD_REN 512 #define WHO_FIELD_IDL 1024 +#if defined(UNDERNET) #define WHO_FIELD_ACC 2048 +#endif #define WHO_FIELD_DEF ( WHO_FIELD_NIC | WHO_FIELD_UID | WHO_FIELD_HOS | WHO_FIELD_SER ) #define IS_VISIBLE_USER(s,ac) ((s==ac) || (!IsInvisible(ac))) -#define SEE_LUSER(s, ac, b) (IS_VISIBLE_USER(s, ac) || ((b & WHOSELECT_EXTRA) && MyConnect(ac) && (HasPriv((s), PRIV_SHOW_INVIS) || HasPriv((s), PRIV_SHOW_ALL_INVIS)))) - -#define SEE_USER(s, ac, b) (SEE_LUSER(s, ac, b) || ((b & WHOSELECT_EXTRA) && HasPriv((s), PRIV_SHOW_ALL_INVIS))) +#define SEE_LUSER(s, ac, b) (IS_VISIBLE_USER(s, ac) || \ + ((b & WHOSELECT_EXTRA) && MyConnect(ac) && \ + (HasPriv((s), PRIV_SHOW_INVIS) || \ + HasPriv((s), PRIV_SHOW_ALL_INVIS)))) + +#define SEE_USER(s, ac, b) (SEE_LUSER(s, ac, b) || \ + ((b & WHOSELECT_EXTRA) && \ + HasPriv((s), PRIV_SHOW_ALL_INVIS))) #define SHOW_MORE(sptr, counter) (HasPriv(sptr, PRIV_UNLIMIT_QUERY) || (!(counter-- < 0)) ) Index: ircd-ircdev/ircd/Makefile.in diff -u ircd-ircdev/ircd/Makefile.in:1.6 ircd-ircdev/ircd/Makefile.in:1.7 --- ircd-ircdev/ircd/Makefile.in:1.6 Sun Nov 2 10:34:47 2003 +++ ircd-ircdev/ircd/Makefile.in Tue Nov 11 13:36:21 2003 @@ -58,7 +58,8 @@ CC = @CC@ CFLAGS = @CFLAGS@ -CPPFLAGS = -I. -I.. -I${top_srcdir}/include -I${top_srcdir}/libs/adns/src @CPPFLAGS@ +CPPFLAGS = -I. -I.. -I${top_srcdir}/include @CPPFLAGS@ +#CPPFLAGS = -I. -I.. -I${top_srcdir}/include -I${top_srcdir}/libs/adns/src @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ @@ -91,6 +92,7 @@ client.c \ crule.c \ dbuf.c \ + destruct_event.c \ fda.c \ fileio.c \ gline.c \ @@ -105,6 +107,7 @@ ircd_signal.c \ ircd_snprintf.c \ ircd_string.c \ + ircd_tea.c \ ircd_xopen.c \ jupe.c \ lex.yy.c \ Index: ircd-ircdev/ircd/channel.c diff -u ircd-ircdev/ircd/channel.c:1.2 ircd-ircdev/ircd/channel.c:1.3 --- ircd-ircdev/ircd/channel.c:1.2 Sat Nov 1 09:19:36 2003 +++ ircd-ircdev/ircd/channel.c Tue Nov 11 13:36:21 2003 @@ -17,12 +17,13 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Id: channel.c,v 1.2 2003/11/01 17:19:36 zolty Exp $ + * $Id: channel.c,v 1.3 2003/11/11 21:36:21 zolty Exp $ */ #include "config.h" #include "channel.h" #include "client.h" +#include "destruct_event.h" #include "hash.h" #include "ircd.h" #include "ircd_alloc.h" @@ -185,14 +186,17 @@ /* * Subtract one user from channel i (and free channel * block, if channel became empty). + * + * defined(UNDERNET) + * Returns: true (1) if channel still has members. + * false (0) if the channel is now empty. + * !defined(UNDERNET) * Returns: true (1) if channel still exists * false (0) if the channel was destroyed + * !defined(UNDERNET) */ int sub1_from_channel(struct Channel* chptr) { - struct SLink *tmp; - struct SLink *obtmp; - if (chptr->users > 1) /* Can be 0, called for an empty channel too */ { assert(0 != chptr->members); @@ -200,6 +204,46 @@ return 1; } +#if defined(UNDERNET) + chptr->users = 0; + + /* + * Also channels without Apass set need to be kept alive, + * otherwise Bad Guys(tm) would be able to takeover + * existing channels too easily, and then set an Apass! + * However, if a channel without Apass becomes empty + * then we try to be kind to them and remove possible + * limiting modes. + */ + chptr->mode.mode &= ~MODE_INVITEONLY; + chptr->mode.limit = 0; + /* + * We do NOT reset a possible key or bans because when + * the 'channel owners' can't get in because of a key + * or ban then apparently there was a fight/takeover + * on the channel and we want them to contact IRC opers + * who then will educate them on the use of Apass/upass. + */ + + if (feature_bool(FEAT_OPLEVELS)) { + if (TStime() - chptr->creationtime < 172800) /* Channel younger than 48 hours? */ + schedule_destruct_event_1m(chptr); /* Get rid of it in approximately 4-5 minutes */ + else + schedule_destruct_event_48h(chptr); /* Get rid of it in approximately 48 hours */ + } else + destruct_channel(chptr); +#else + destruct_channel(chptr); +#endif + + return 0; +} + +int destruct_channel(struct Channel* chptr) +{ + struct SLink *tmp; + struct SLink *obtmp; + assert(0 == chptr->members); /* Channel became (or was) empty: Remove channel */ @@ -425,6 +469,7 @@ s = make_nick_user_host(nu_host, cli_name(cptr), (cli_user(cptr))->username, (cli_user(cptr))->host); +#if defined(UNDERNET) if (IsAccount(cptr)) { if (HasHiddenHost(cptr)) sr = make_nick_user_host(nu_realhost, cli_name(cptr), @@ -438,6 +483,7 @@ tmphost); } } +#endif /* defined(UNDERNET) */ for (tmp = chptr->banlist; tmp; tmp = tmp->next) { if ((tmp->flags & CHFL_BAN_IPMASK)) { @@ -473,7 +519,7 @@ * chain. */ void add_user_to_channel(struct Channel* chptr, struct Client* who, - unsigned int flags) + unsigned int flags, int oplevel) { assert(0 != chptr); assert(0 != who); @@ -492,6 +538,9 @@ member->user = who; member->channel = chptr; member->status = flags; +#if defined(UNDERNET) + member->oplevel = oplevel; +#endif member->next_member = chptr->members; if (member->next_member) @@ -505,6 +554,8 @@ member->prev_channel = 0; (cli_user(who))->channel = member; + if (chptr->destruct_event) + remove_destruct_event(chptr); ++chptr->users; ++((cli_user(who))->joined); } @@ -621,6 +672,12 @@ { assert(0 != member); +#if defined(UNDERNET) + /* Discourage using the Apass to get op. They should use the upass. */ + if (IsChannelManager(member) && *member->channel->mode.upass) + return 0; +#endif + if (IsVoicedOrOpped(member)) return 1; /* @@ -651,10 +708,16 @@ member = find_channel_member(cptr, chptr); - /* You can't speak if your off channel and +n (no external messages) or +m (moderated). */ + /* + * You can't speak if you're off channel, and it is +n (no external messages) + * or +m (moderated). + */ if (!member) { - if ((chptr->mode.mode & (MODE_NOPRIVMSGS|MODE_MODERATED)) || - ((chptr->mode.mode & MODE_REGONLY) && !IsAccount(cptr))) + if ((chptr->mode.mode & (MODE_NOPRIVMSGS|MODE_MODERATED)) +#if defined(UNDERNET) + || ((chptr->mode.mode & MODE_REGONLY) && !IsAccount(cptr)) +#endif + ) return 0; else return !is_banned(cptr, chptr, NULL); @@ -686,8 +749,10 @@ * with the parameters in pbuf. */ void channel_modes(struct Client *cptr, char *mbuf, char *pbuf, int buflen, - struct Channel *chptr) + struct Channel *chptr, struct Membership *member) { + int previous_parameter = 0; + assert(0 != mbuf); assert(0 != pbuf); assert(0 != chptr); @@ -710,6 +775,7 @@ if (chptr->mode.limit) { *mbuf++ = 'l'; ircd_snprintf(0, pbuf, buflen, "%u", chptr->mode.limit); + previous_parameter = 1; } if (*chptr->mode.key) { @@ -720,17 +786,51 @@ strcat(pbuf, chptr->mode.key); } else strcat(pbuf, "*"); + previous_parameter = 1; + } +#if defined(UNDERNET) + if (*chptr->mode.apass) { + *mbuf++ = 'A'; + if (previous_parameter) + strcat(pbuf, " "); + if (IsServer(cptr)) { + strcat(pbuf, chptr->mode.apass); + } else + strcat(pbuf, "*"); + previous_parameter = 1; + } + if (*chptr->mode.upass) { + *mbuf++ = 'u'; + if (previous_parameter) + strcat(pbuf, " "); + if (IsServer(cptr) || (member && IsChanOp(member) && OpLevel(member) == 0)) { + strcat(pbuf, chptr->mode.upass); + } else + strcat(pbuf, "*"); } +#endif /* UNDERNET */ *mbuf = '\0'; } +#if defined(UNDERNET) +int compare_member_oplevel(const void *mp1, const void *mp2) +{ + struct Membership const* member1 = *(struct Membership const**)mp1; + struct Membership const* member2 = *(struct Membership const**)mp2; + if (member1->oplevel == member2->oplevel) + return 0; + return (member1->oplevel < member2->oplevel) ? -1 : 1; +} +#endif /* UNDERNET */ + /* * send "cptr" a full list of the modes for channel chptr. */ void send_channel_modes(struct Client *cptr, struct Channel *chptr) { + /* The order in which modes are generated is now mandatory */ static unsigned int current_flags[4] = - { 0, CHFL_CHANOP | CHFL_VOICE, CHFL_VOICE, CHFL_CHANOP }; + { 0, CHFL_VOICE, CHFL_CHANOP, CHFL_CHANOP | CHFL_VOICE }; int first = 1; int full = 1; int flag_cnt = 0; @@ -741,6 +841,12 @@ char modebuf[MODEBUFLEN]; char parabuf[MODEBUFLEN]; struct MsgBuf *mb; +#if defined(UNDERNET) + int number_of_ops = 0; + int opped_members_index = 0; + struct Membership** opped_members = NULL; + int last_oplevel = 0; +#endif assert(0 != cptr); assert(0 != chptr); @@ -752,7 +858,7 @@ lp2 = chptr->banlist; *modebuf = *parabuf = '\0'; - channel_modes(cptr, modebuf, parabuf, sizeof(parabuf), chptr); + channel_modes(cptr, modebuf, parabuf, sizeof(parabuf), chptr, 0); for (first = 1; full; first = 0) /* Loop for multiple messages */ { @@ -764,7 +870,7 @@ mb = msgq_make(&me, "%C " TOK_BURST " %H %Tu", &me, chptr, chptr->creationtime); - if (first && modebuf[1]) /* Add simple modes (iklmnpst) + if (first && modebuf[1]) /* Add simple modes (Aiklmnpstu) if first message */ { /* prefix: "<Y> B <channel> <TS>[ <modes>[ <params>]]" */ @@ -777,14 +883,134 @@ /* * Attach nicks, comma seperated " nick[:modes],nick[:modes],..." * + * First find all opless members. + * + * defined(UNDERNET) + * Run 2 times over all members, to group the members with + * and without voice together. + * Then run 2 times over all opped members (which are ordered + * by op-level) to also group voice and non-voice together. + * + * !defined(UNDERNET) * Run 4 times over all members, to group the members with the * same mode together */ - for (first = 1; flag_cnt < 4; - member = chptr->members, new_mode = 1, flag_cnt++) +#if defined(UNDERNET) + for (first = 1; flag_cnt < 4; new_mode = 1, flag_cnt++) { + while(member) + { + if (flag_cnt < 2 && IsChanOp(member)) + { + /* + * The first loop (to find all non-voice/op), we count the ops. + * The second loop (to find all voiced non-ops), store the ops + * in a dynamic array. + */ + if (flag_cnt == 0) + ++number_of_ops; + else + opped_members[opped_members_index++] = member; + } + /* Only handle the members with the flags that we are interested in. */ + if ((member->status & CHFL_VOICED_OR_OPPED) == current_flags[flag_cnt]) + { + if (msgq_bufleft(mb) < NUMNICKLEN + 3 + MAXOPLEVELDIGITS) + /* The 3 + MAXOPLEVELDIGITS is a possible ",:v999". */ + { + full = 1; /* Make sure we continue after + sending it so far */ + /* Ensure the new BURST line contains the current + * ":mode", except when there is no mode yet. */ + new_mode = (flag_cnt > 0) ? 1 : 0; + break; /* Do not add this member to this message */ + } + msgq_append(&me, mb, "%c%C", first ? ' ' : ',', member->user); + first = 0; /* From now on, use commas to add new nicks */ + + /* + * Do we have a nick with a new mode ? + * Or are we starting a new BURST line? + */ + if (new_mode) + { + /* + * This means we are at the _first_ member that has only + * voice, or the first member that has only ops, or the + * first member that has voice and ops (so we get here + * at most three times, plus once for every start of + * a continued BURST line where only these modes is current. + * In the two cases where the current mode includes ops, + * we need to add the _absolute_ value of the oplevel to the mode. + */ + char tbuf[3 + MAXOPLEVELDIGITS] = ":"; + int loc = 1; + + if (HasVoice(member)) /* flag_cnt == 1 or 3 */ + tbuf[loc++] = 'v'; + if (IsChanOp(member)) /* flag_cnt == 2 or 3 */ + { + /* append the absolute value of the oplevel */ + loc += ircd_snprintf(0, tbuf + loc, sizeof(tbuf) - loc, "%u", member->oplevel); + last_oplevel = member->oplevel; + } + tbuf[loc] = '\0'; + msgq_append(&me, mb, tbuf); + new_mode = 0; + } + else if (flag_cnt > 1 && last_oplevel != member->oplevel) + { + /* + * This can't be the first member of a (continued) BURST + * message because then either flag_cnt == 0 or new_mode == 1 + * Now we need to append the incremental value of the oplevel. + */ + char tbuf[2 + MAXOPLEVELDIGITS]; + ircd_snprintf(0, tbuf, sizeof(tbuf), ":%u", member->oplevel - last_oplevel); + last_oplevel = member->oplevel; + msgq_append(&me, mb, tbuf); + } + } + /* Go to the next `member'. */ + if (flag_cnt < 2) + member = member->next_member; + else + member = opped_members[++opped_members_index]; + } + if (full) + break; + + /* Point `member' at the start of the list again. */ + if (flag_cnt == 0) + { + member = chptr->members; + /* Now, after one loop, we know the number of ops and can + * allocate the dynamic array with pointer to the ops. */ + opped_members = (struct Membership**) + MyMalloc((number_of_ops + 1) * sizeof(struct Membership*)); + opped_members[number_of_ops] = NULL; /* Needed for loop termination */ + } + else + { + /* At the end of the second loop, sort the opped members with + * increasing op-level, so that we will output them in the + * correct order (and all op-level increments stay positive) */ + if (flag_cnt == 1) + qsort(opped_members, number_of_ops, + sizeof(struct Membership*), compare_member_oplevel); + /* The third and fourth loop run only over the opped members. */ + member = opped_members[(opped_members_index = 0)]; + } + + } /* loop over 0,+v,+o,+ov */ + +#else /* !UNDERNET */ + for (first = 1; flag_cnt < 4; + member = chptr->members, new_mode = 1, flag_cnt++) + { for (; member; member = member->next_member) { + if ((member->status & CHFL_VOICED_OR_OPPED) != current_flags[flag_cnt]) continue; /* Skip members with different flags */ @@ -819,10 +1045,12 @@ msgq_append(&me, mb, tbuf); } } + member = member->next_member; } if (full) break; } +#endif /* UNDERNET */ if (!full) { @@ -848,6 +1076,12 @@ msgq_clean(mb); } /* Continue when there was something that didn't fit (full==1) */ + +#if defined(UNDERNET) + if (opped_members) + MyFree(opped_members); +#endif + } /* @@ -1024,8 +1258,10 @@ if (chptr->mode.limit && chptr->users >= chptr->mode.limit) return overrideJoin + ERR_CHANNELISFULL; +#if defined(UNDERNET) if ((chptr->mode.mode & MODE_REGONLY) && !IsAccount(sptr)) return overrideJoin + ERR_NEEDREGGEDNICK; +#endif if (is_banned(sptr, chptr, NULL)) return overrideJoin + ERR_BANNEDFROMCHAN; @@ -1172,7 +1408,8 @@ { for (; chptr; chptr = chptr->next) { - if (!cli_user(cptr)) + if (!cli_user(cptr) || (!(HasPriv(cptr, PRIV_LIST_CHAN) && IsAnOper(cptr)) && + SecretChannel(chptr) && !find_channel_member(cptr, chptr))) continue; if (chptr->users > args->min_users && chptr->users < args->max_users && chptr->creationtime > args->min_time && @@ -1220,7 +1457,7 @@ * via 'a', or on server 'B' via either 'b' or 'c', or on server D via 'd'. * * a) On server A : set CHFL_ZOMBIE for `who' (lp) and pass on the KICK. - * Remove the user immedeately when no users are left on the channel. + * Remove the user immediately when no users are left on the channel. * b) On server B : remove the user (who/lp) from the channel, send a * PART upstream (to A) and pass on the KICK. * c) KICKed by `client'; On server B : remove the user (who/lp) from the @@ -1309,7 +1546,7 @@ * of course, str2 is not NULL) */ static void -build_string(char *strptr, int *strptr_i, char *str1, char *str2, char c) +build_string(char *strptr, int *strptr_i, const char *str1, const char *str2, char c) { if (c) strptr[(*strptr_i)++] = c; @@ -1345,6 +1582,10 @@ /* MODE_KEY, 'k', */ /* MODE_BAN, 'b', */ /* MODE_LIMIT, 'l', */ +#if defined(UNDERNET) +/* MODE_APASS, 'A', */ +/* MODE_UPASS, 'u', */ +#endif 0x0, 0x0 }; int i; @@ -1419,13 +1660,34 @@ bufptr[(*bufptr_i)++] = MB_TYPE(mbuf, i) & MODE_CHANOP ? 'o' : 'v'; totalbuflen -= IRCD_MAX(5, tmp) + 1; } +#if defined(UNDERNET) + } else if (MB_TYPE(mbuf, i) & (MODE_BAN | MODE_APASS | MODE_UPASS)) { +#else } else if (MB_TYPE(mbuf, i) & MODE_BAN) { +#endif tmp = strlen(MB_STRING(mbuf, i)); if ((totalbuflen - tmp) <= 0) /* don't overflow buffer */ MB_TYPE(mbuf, i) |= MODE_SAVE; /* save for later */ else { +#if defined(UNDERNET) + char mode_char; + switch(MB_TYPE(mbuf, i) & (MODE_BAN | MODE_APASS | MODE_UPASS)) + { + case MODE_APASS: + mode_char = 'A'; + break; + case MODE_UPASS: + mode_char = 'u'; + break; + default: + mode_char = 'b'; + break; + } + bufptr[(*bufptr_i)++] = mode_char; +#else bufptr[(*bufptr_i)++] = 'b'; +#endif totalbuflen -= tmp + 1; } } else if (MB_TYPE(mbuf, i) & MODE_KEY) { @@ -1492,6 +1754,12 @@ build_string(strptr, strptr_i, mbuf->mb_dest & MODEBUF_DEST_NOKEY ? "*" : MB_STRING(mbuf, i), 0, ' '); +#if defined(UNDERNET) + /* deal with invisible passwords */ + else if (MB_TYPE(mbuf, i) & (MODE_APASS | MODE_UPASS)) + build_string(strptr, strptr_i, "*", 0, ' '); +#endif + /* * deal with limit; note we cannot include the limit parameter if we're * removing it @@ -1575,7 +1843,11 @@ build_string(strptr, strptr_i, NumNick(MB_CLIENT(mbuf, i)), ' '); /* deal with modes that take strings */ +#if defined(UNDERNET) + else if (MB_TYPE(mbuf, i) & (MODE_KEY | MODE_BAN | MODE_APASS | MODE_UPASS)) +#else else if (MB_TYPE(mbuf, i) & (MODE_KEY | MODE_BAN)) +#endif build_string(strptr, strptr_i, MB_STRING(mbuf, i), 0, ' '); /* @@ -1676,6 +1948,9 @@ assert(0 != chan); assert(0 != dest); + if (IsLocalChannel(chan->chname)) + dest &= ~MODEBUF_DEST_SERVER; + mbuf->mb_add = 0; mbuf->mb_rem = 0; mbuf->mb_source = source; @@ -1803,6 +2078,10 @@ MODE_INVITEONLY, 'i', MODE_NOPRIVMSGS, 'n', MODE_KEY, 'k', +#if defined(UNDERNET) + MODE_APASS, 'A', + MODE_UPASS, 'u', +#endif /* MODE_BAN, 'b', */ MODE_LIMIT, 'l', MODE_REGONLY, 'r', @@ -1812,6 +2091,9 @@ int i, bufpos = 0, len; int *flag_p; char *key = 0, limitbuf[20]; +#if defined(UNDERNET) + char *apass = 0, *upass = 0; +#endif assert(0 != mbuf); assert(0 != buf); @@ -1822,12 +2104,22 @@ for (i = 0; i < mbuf->mb_count; i++) { /* find keys and limits */ if (MB_TYPE(mbuf, i) & MODE_ADD) { +#if defined(UNDERNET) + add |= MB_TYPE(mbuf, i) & (MODE_KEY | MODE_LIMIT | MODE_APASS | MODE_UPASS); +#else add |= MB_TYPE(mbuf, i) & (MODE_KEY | MODE_LIMIT); +#endif if (MB_TYPE(mbuf, i) & MODE_KEY) /* keep strings */ key = MB_STRING(mbuf, i); else if (MB_TYPE(mbuf, i) & MODE_LIMIT) ircd_snprintf(0, limitbuf, sizeof(limitbuf), "%u", MB_UINT(mbuf, i)); +#if defined(UNDERNET) + else if (MB_TYPE(mbuf, i) & MODE_UPASS) + upass = MB_STRING(mbuf, i); + else if (MB_TYPE(mbuf, i) & MODE_APASS) + apass = MB_STRING(mbuf, i); +#endif } } @@ -1845,6 +2137,12 @@ build_string(buf, &bufpos, key, 0, ' '); else if (buf[i] == 'l') build_string(buf, &bufpos, limitbuf, 0, ' '); +#if defined(UNDERNET) + else if (buf[i] == 'u') + build_string(buf, &bufpos, upass, 0, ' '); + else if (buf[i] == 'A') + build_string(buf, &bufpos, apass, 0, ' '); +#endif } buf[bufpos] = '\0'; @@ -1880,12 +2178,17 @@ #define DONE_BANLIST 0x04 /* We've sent the ban list */ #define DONE_NOTOPER 0x08 /* We've sent a "Not oper" error */ #define DONE_BANCLEAN 0x10 /* We've cleaned bans... */ +#if defined(UNDERNET) +#define DONE_UPASS 0x20 /* We've set user pass */ +#define DONE_APASS 0x40 /* We've set admin pass */ +#endif struct ParseState { struct ModeBuf *mbuf; struct Client *cptr; struct Client *sptr; struct Channel *chptr; + struct Membership *member; int parc; char **parv; unsigned int flags; @@ -2023,7 +2326,7 @@ /* clean up the key string */ s = t_str; - while (*++s > ' ' && *s != ':' && --t_len) + while (*s > ' ' && *s != ':' && --t_len) s++; *s = '\0'; @@ -2074,6 +2377,233 @@ } } +#if defined(UNDERNET) +/* + * Helper function to convert user passes + */ +static void +mode_parse_upass(struct ParseState *state, int *flag_p) +{ + char *t_str, *s; + int t_len; + + if (MyUser(state->sptr) && state->max_args <= 0) /* drop if too many args */ + return; + + if (state->parc <= 0) { /* warn if not enough args */ + if (MyUser(state->sptr)) + need_more_params(state->sptr, state->dir == MODE_ADD ? "MODE +u" : + "MODE -u"); + return; + } + + t_str = state->parv[state->args_used++]; /* grab arg */ + state->parc--; + state->max_args--; + + /* If they're not an oper, they can't change modes */ + if (state->flags & (MODE_PARSE_NOTOPER | MODE_PARSE_NOTMEMBER)) { + send_notoper(state); + return; + } + + /* If they are not the channel manager, they are not allowed to change it */ + if (MyUser(state->sptr) && !IsChannelManager(state->member)) { + if (*state->chptr->mode.apass) { + send_reply(state->sptr, ERR_NOTMANAGER, state->chptr->chname, + "Use /JOIN", state->chptr->chname, "<AdminPass>."); + } else { + send_reply(state->sptr, ERR_NOTMANAGER, state->chptr->chname, + "Re-create the channel. The channel must be *empty* for", + TStime() - state->chptr->creationtime >= 171000 ? "48 contiguous hours" : "a minute or two", + "before it can be recreated."); + } + return; + } + + if (state->done & DONE_UPASS) /* allow upass to be set only once */ + return; + state->done |= DONE_UPASS; + + t_len = PASSLEN + 1; + + /* clean up the upass string */ + s = t_str; + while (*s > ' ' && *s != ':' && --t_len) + s++; + *s = '\0'; + + if (!*t_str) { /* warn if empty */ + if (MyUser(state->sptr)) + need_more_params(state->sptr, state->dir == MODE_ADD ? "MODE +u" : + "MODE -u"); + return; + } + + if (!state->mbuf) + return; + + if (!(state->flags & MODE_PARSE_FORCE)) + /* can't add the upass while apass is not set */ + if (state->dir == MODE_ADD && !*state->chptr->mode.apass) { + send_reply(state->sptr, ERR_UPASSNOTSET, state->chptr->chname, state->chptr->chname); + return; + } + /* can't add a upass if one is set, nor can one remove the wrong upass */ + if ((state->dir == MODE_ADD && *state->chptr->mode.upass) || + (state->dir == MODE_DEL && + ircd_strcmp(state->chptr->mode.upass, t_str))) { + send_reply(state->sptr, ERR_KEYSET, state->chptr->chname); + return; + } + + if (!(state->flags & MODE_PARSE_WIPEOUT) && state->dir == MODE_ADD && + !ircd_strcmp(state->chptr->mode.upass, t_str)) + return; /* no upass change */ + + if (state->flags & MODE_PARSE_BOUNCE) { + if (*state->chptr->mode.upass) /* reset old upass */ + modebuf_mode_string(state->mbuf, MODE_DEL | flag_p[0], + state->chptr->mode.upass, 0); + else /* remove new bogus upass */ + modebuf_mode_string(state->mbuf, MODE_ADD | flag_p[0], t_str, 0); + } else /* send new upass */ + modebuf_mode_string(state->mbuf, state->dir | flag_p[0], t_str, 0); + + if (state->flags & MODE_PARSE_SET) { + if (state->dir == MODE_ADD) /* set the new upass */ + ircd_strncpy(state->chptr->mode.upass, t_str, PASSLEN); + else /* remove the old upass */ + *state->chptr->mode.upass = '\0'; + } +} + +/* + * Helper function to convert admin passes + */ +static void +mode_parse_apass(struct ParseState *state, int *flag_p) +{ + char *t_str, *s; + int t_len; + + if (MyUser(state->sptr) && state->max_args <= 0) /* drop if too many args */ + return; + + if (state->parc <= 0) { /* warn if not enough args */ + if (MyUser(state->sptr)) + need_more_params(state->sptr, state->dir == MODE_ADD ? "MODE +A" : + "MODE -A"); + return; + } + + t_str = state->parv[state->args_used++]; /* grab arg */ + state->parc--; + state->max_args--; + + /* If they're not an oper, they can't change modes */ + if (state->flags & (MODE_PARSE_NOTOPER | MODE_PARSE_NOTMEMBER)) { + send_notoper(state); + return; + } + + /* Don't allow to change the Apass if the channel is older than 48 hours. */ + if (TStime() - state->chptr->creationtime >= 172800 && !IsAnOper(state->sptr)) { + send_reply(state->sptr, ERR_CHANSECURED, state->chptr->chname); + return; + } + + /* If they are not the channel manager, they are not allowed to change it */ + if (MyUser(state->sptr) && !IsChannelManager(state->member)) { + if (*state->chptr->mode.apass) { + send_reply(state->sptr, ERR_NOTMANAGER, state->chptr->chname, + "Use /JOIN", state->chptr->chname, "<AdminPass>."); + } else { + send_reply(state->sptr, ERR_NOTMANAGER, state->chptr->chname, + "Re-create the channel. The channel must be *empty* for", + "at least a whole minute", "before it can be recreated."); + } + return; + } + + if (state->done & DONE_APASS) /* allow apass to be set only once */ + return; + state->done |= DONE_APASS; + + t_len = PASSLEN + 1; + + /* clean up the apass string */ + s = t_str; + while (*s > ' ' && *s != ':' && --t_len) + s++; + *s = '\0'; + + if (!*t_str) { /* warn if empty */ + if (MyUser(state->sptr)) + need_more_params(state->sptr, state->dir == MODE_ADD ? "MODE +A" : + "MODE -A"); + return; + } + + if (!state->mbuf) + return; + + if (!(state->flags & MODE_PARSE_FORCE)) { + ... [truncated message content] |