You do not have permission to edit this page, for the following reasons:
Free text:
ports: 6667, 6697 (SSL) IPv4 & IPv6! Cool features: Create a new #channel, get a free +q! [[File:Larry.png|thumb]] ===Modules=== {| class="wikitable" |+ !Name !Function |- |certificate-refresh |Automatically reload SSL/TLS certificate when the underlying certificate on the filesystem has changed. |- |hyb-statsconn |RPL_STATSCONN to new clients and LUSERS, like Hybrid/Ratbox |- |no-services-plus-q |Channel creator is automatically given +q/~ |} ====/src/modules/third/certificate-refresh.c==== automatically reload your SSL/TLS certificates when they are changed on the filesystem, no need for a cron job. <syntaxhighlight lang="c"> /* License: GPLv2 * Author: clrx */ #include "unrealircd.h" ModuleHeader MOD_HEADER = { "third/certificate-refresh", /* name */ "1.0.0", /* version */ "Certificate Refresh: Automatically checks SSL/TLS certificates for changes, and reloads SSL/TLS if the certificate has been updated.", /* description */ "clrx", /* author */ "unrealircd-5", /* do not change this, it indicates module API version */ }; /*** <<<MODULE MANAGER START>>> module { // Documentation, as displayed in './unrealircd module info nameofmodule', and possibly at other places: documentation "https://www.example.org/"; // This is displayed in './unrealircd module info ..' and also if compilation of the module fails: troubleshooting "In case of problems, check the FAQ at ... or e-mail me at ..."; min-unrealircd-version "5.*"; max-unrealircd-version "5.*"; post-install-text { "The module is installed. Now all you need to do is add a loadmodule line:"; "loadmodule \"third/certificate-refresh\";"; "And /REHASH the IRCd."; "The module does not need any other configuration."; } } *** <<<MODULE MANAGER END>>> */ #define _MCRF_USE_REINIT_SSL (UNREAL_VERSION_GENERATION == 5 && UNREAL_VERSION_MAJOR == 2 && UNREAL_VERSION_MINOR < 1) #define _MCRF_TIMEOUT 43200000 /* 12 hours, in milliseconds. */ typedef struct mCRF_Watch_File mCRF_Watch_File; struct mCRF_Watch_File { char *path; time_t last_modified; mCRF_Watch_File *next; }; /* Forward Declarations. */ EVENT(mCRF_timeout); EVENT(mCRF_setup_files); time_t mCRF_get_cert_time(const char *path); mCRF_Watch_File *mCRF_add_watch_file(const char *path); mCRF_Watch_File *mCRF_find_watch_file(const char *path); static mCRF_Watch_File *watched_files; EVENT(mCRF_timeout) { TLSOptions *tls_options; int needReload = 0; mCRF_Watch_File *wptr; for (wptr = watched_files; wptr; wptr = wptr->next) { time_t ts_curr = mCRF_get_cert_time(wptr->path); if (ts_curr != wptr->last_modified) { needReload = 1; wptr->last_modified = ts_curr; } } if (needReload) { sendto_snomask(SNO_SNOTICE, "*** [third/certificate-refresh]: Server TLS certificate(s) updated, reloading certificates."); #if _MCRF_USE_REINIT_SSL reinit_ssl(NULL); #else reinit_tls(); #endif } } EVENT(mCRF_setup_files) { ConfigItem_listen *lptr; ConfigItem_sni *sptr; TLSOptions *tls_options = get_tls_options_for_client(&me); if (tls_options) mCRF_add_watch_file(tls_options->certificate_file); for (lptr = conf_listen; lptr; lptr = lptr->next) { tls_options = lptr->tls_options; if (tls_options) mCRF_add_watch_file(tls_options->certificate_file); } for (sptr = conf_sni; sptr; sptr = sptr->next) { mCRF_add_watch_file(sptr->tls_options->certificate_file); } } time_t mCRF_get_cert_time(const char *path) { time_t r = 0; struct stat st; if (!stat(path, &st)) { r = st.st_mtime; } return r; } mCRF_Watch_File *mCRF_add_watch_file(const char *path) { mCRF_Watch_File *wptr; if (path == NULL) return NULL; wptr = mCRF_find_watch_file(path); if (wptr) return wptr; wptr = safe_alloc(sizeof(mCRF_Watch_File)); memset(wptr, 0, sizeof(mCRF_Watch_File)); wptr->path = our_strdup(path); wptr->last_modified = mCRF_get_cert_time(wptr->path); if (watched_files == NULL) { watched_files = wptr; } else { mCRF_Watch_File *tmp, *prv; tmp = watched_files; while (tmp != NULL) { prv = tmp; tmp = tmp->next; } prv->next = wptr; } return wptr; } mCRF_Watch_File *mCRF_find_watch_file(const char *path) { mCRF_Watch_File *wptr; for (wptr = watched_files; wptr; wptr = wptr->next) { if (smycmp(path, wptr->path) == 0) return wptr; } return NULL; } MOD_INIT() { EventAdd(modinfo->handle, "mCRF_timeout", mCRF_timeout, NULL, _MCRF_TIMEOUT, 0); EventAdd(modinfo->handle, "mCRF_setup_files", mCRF_setup_files, NULL, 5 * 1000, 1); return MOD_SUCCESS; } MOD_UNLOAD() { mCRF_Watch_File *wptr, *wptri; for (wptr = watched_files; wptr; wptr = wptri) { wptri = wptr->next; safe_free(wptr->path); safe_free(wptr); } return MOD_SUCCESS; } MOD_TEST() { return MOD_SUCCESS; } MOD_LOAD() { return MOD_SUCCESS; } </syntaxhighlight>'''/src/modules/third/hyb-statsconn.c''' Shows RPL_STATSCONN upon client connection and when LUSERS is called. Doesn't add a lot of value otherwise, but I like how it shows how many actual IRC clients (as opposed to all accept()s in /STATS T) have connected to the server during the current run. I named it hybrid-statsconn since that is the first time I remember seeing this information, but I don't know where this numeric really came from. Oh well :) [22:56:45] * There are 6 users and 410 invisible on 147 servers [22:56:45] * 129 operator(s) online [22:56:45] * 218 channels formed [22:56:45] * I have 4 clients and 1 servers [22:56:45] * Current local users 4, max 6 [22:56:45] * Current global users 416, max 1000001 [22:56:45] * Highest connection count: 7 (6 clients) (26 connections received) (These were the stats after running for about two weeks without a reboot in the round robin) <syntaxhighlight lang="c"> /* License: GPLv2 * Author: clrx */ #include "unrealircd.h" ModuleHeader MOD_HEADER = { "third/hyb-statsconn", /* name */ "1.0.0", /* version */ "Hyb-StatsConn: Shows RPL_STATSCONN", /* description */ "clrx", /* author */ "unrealircd-5", /* do not change this, it indicates module API version */ }; #define RPL_STATSCONN_MESSAGE ":Highest connection count: %d (%d clients) (%ld connections received)" int m_hyb_statsconn_hook_welcome(Client *acptr, int after_numeric); int m_hyb_statsconn_hook_local_server_connect(Client *acptr); int m_hyb_statsconn_rehash_complete(void); CMD_OVERRIDE_FUNC(m_hyb_statsconn_override); void m_hyb_statsconn_show_statsconn(Client *acptr); static long totalrestartcount = 0; /* Keep track of our handle in order to reinstall the override after each rehash. */ Module *myHandle; MOD_TEST() { return MOD_SUCCESS; } MOD_INIT() { /* Must mark as permanent, or else we will lose our count. */ ModuleSetOptions(modinfo->handle, MOD_OPT_PERM, 1); myHandle = modinfo->handle; HookAdd(modinfo->handle, HOOKTYPE_SERVER_CONNECT, 0, m_hyb_statsconn_hook_local_server_connect); HookAdd(modinfo->handle, HOOKTYPE_WELCOME, 0, m_hyb_statsconn_hook_welcome); /* Even if the module is marked as permanent, /REHASH will unload the CommandOverride. So, if we rehash, we need to reload the Override. */ HookAdd(modinfo->handle, HOOKTYPE_REHASH_COMPLETE, 999, m_hyb_statsconn_rehash_complete); return MOD_SUCCESS; } MOD_LOAD() { /* Install override on first startup, only run once due to permanent module. */ m_hyb_statsconn_rehash_complete(); return MOD_SUCCESS; } MOD_UNLOAD() { return MOD_SUCCESS; } CMD_OVERRIDE_FUNC(m_hyb_statsconn_override) { CallCommandOverride(ovr, client, recv_mtags, parc, parv); /* This is recommended per the Unreal wiki. It's probably unnecessary as at this time * lusers does not offer a way to kill the client, and sendbufto_one also checks for a * dead socket. But it doesn't hurt anything and provides future proofing incase * other innovations are invented! */ if (IsDead(client)) return; if (parc > 1) { Client *target = find_server(parv[1], NULL); if (target != &me) return; } m_hyb_statsconn_show_statsconn(client); } int m_hyb_statsconn_rehash_complete(void) { /* re-install override after each rehash */ CommandOverrideAdd(myHandle, "LUSERS", m_hyb_statsconn_override); return HOOK_CONTINUE; } int m_hyb_statsconn_hook_local_server_connect(Client *acptr) { /* Only care about local clients, but hooked in for all servers per API. Only increment * if client is a local server. */ if (MyConnect(acptr) && IsServer(acptr)) totalrestartcount = totalrestartcount + 1; return HOOK_CONTINUE; } int m_hyb_statsconn_hook_welcome(Client *acptr, int after_numeric) { /* Is HOOK_WELCOME called for new servers? Don't know, don't care, be safe. */ if (!IsUser(acptr)) return HOOK_CONTINUE; if (after_numeric == RPL_GLOBALUSERS) { /*I haven't read the Unreal source code close enough to know if this is really necessary, but it doesn't hurt anything. */ if (MyUser(acptr)) totalrestartcount = totalrestartcount + 1; m_hyb_statsconn_show_statsconn(acptr); } return HOOK_CONTINUE; } void m_hyb_statsconn_show_statsconn(Client *acptr) { int l_max_connection_count = max_connection_count; char flatmap = (FLAT_MAP && !ValidatePermissionsForPath("server:info:lusers",acptr,NULL,NULL,NULL)) ? 1 : 0; /* If we have a low number of users, the numbers won't make sense. */ if (l_max_connection_count < (irccounts.me_max + irccounts.me_servers)) l_max_connection_count = irccounts.me_max + irccounts.me_servers; if (flatmap) l_max_connection_count = irccounts.me_max; sendnumericfmt(acptr, RPL_STATSCONN, RPL_STATSCONN_MESSAGE, l_max_connection_count, irccounts.me_max, totalrestartcount); } </syntaxhighlight>'''/src/modules/third/no-services-plus-q.c''' Adds +q to the user who creates the channel. Not super useful but InspIRCd used to have a feature like this - especially useful if you do not have services like PissNet. Very simple, possibly a better way to accomplish this but it works for me. <syntaxhighlight lang="c"> /* License: GPLv2 or whatever. * Author: clrx */ #include "unrealircd.h" ModuleHeader MOD_HEADER = { "third/no-services-plus-q", /* name */ "1.0.0", /* version */ "NoServicesPlusQ: First user to join channel gets +q(~), useful if your network does not have services.", /* description */ "clrx", /* author */ "unrealircd-5", /* do not change this, it indicates module API version */ }; int nosvs_local_join(Client *acptr, Channel *channel, MessageTag *mtags, char *parv[]); MOD_TEST() { return MOD_SUCCESS; } MOD_INIT() { #ifdef PREFIX_AQ HookAdd(modinfo->handle, HOOKTYPE_LOCAL_JOIN, 0, nosvs_local_join); #endif return MOD_SUCCESS; } MOD_LOAD() { return MOD_SUCCESS; } MOD_UNLOAD() { return MOD_SUCCESS; } int nosvs_local_join(Client *acptr, Channel *channel, MessageTag *mtags, char *parv[]) { if (channel->users == 1 && !has_channel_mode(channel, 'P')) { char *lparv[] = { "+q", acptr->name, NULL }; do_mode(channel, &me, mtags, 2, lparv, 0, 0); } return HOOK_CONTINUE; } </syntaxhighlight>