aboutsummaryrefslogtreecommitdiffstats
path: root/ircd
Commit message (Expand)AuthorAgeFilesLines
* Tidy up module loading code•••The existing code had several defects: - Core module file names were hardcoded, while autoloaded non- core module filenames were not. Code that loaded core modules had a different but in some places duplicated structure to the code that loaded autoloaded modules. - Module loading for autoloaded modules happened in dentry order, making it unpredictable from one server to the next, or even across instances of `make install` on the same server. - Module loading for autoloaded modules did not verify that the dentry was a file before trying to load it. - An IRCd start (or a conftest) only printed lines about loading modules mentioned in the configuration file. - The configuration file was parsed before loading core and autoloaded modules, meaning any modules specified in the configuration file would be loaded first. - Once a module was loaded, it was added to the head of the module list, making MODLIST show them in reverse loaded order (newest (re)loaded modules at the top of the list). These are addressed as follows: - We now scan the core and autoload module directories and use this to determine which modules to load. - We now sort the dentries according to their filename before iterating them to load them, making module load order finally deterministic. - We now test if a dentry is actually a file before trying to load it. - We now print a message to the console (if running in foreground or conftest mode) when loading any module, including core and autoloaded modules. - The message printed to the console now has the IRCd module directory prefix stripped from it if it matches. - The configuration file is now parsed after loading core and autoload modules. - The modules are added to the module list in the order that they are loaded. This now makes MODLIST show the order that modules were (re)loaded in. Modifications to two modules are part of this effort: - The autoload module `m_alias` relied upon the alias dict not being NULL when loaded, but this is only the case after the configuration file has been parsed. The module already had a "rehash" hook to destroy all existing aliases and create new ones, so we can just make the module do nothing on load (remove its modinit function) and change it to use the "conf_read_end" hook instead of the "rehash" hook, and it will still create aliases after the configuration file is subsequently parsed. With this modification, there are now no in-tree consumers of the "rehash" hook. - The autoload module `m_services` iterated `service_list` upon loading it, which will now be empty (a no-op) since the module is loaded before configuration file is parsed. This module too handles the configuration file being parsed with a "conf_read_end" hook and takes the appropriate action, so we can just remove this code from its modinit function. All other modules' modinit functions have been audited for behaviour like this; there was nothing of note. amdj/modulesGravatar Aaron Jones2026-03-112-68/+135
* parse: fix crash•••The incoming_client and incoming_message globals were not properly cleared after processing a numeric command. Ensure they are cleared by not returning early after setting those global values. Fixes: e2a499fGravatar Ryan Schmidt2026-01-271-3/+3
* ircd/newconf.c: conf_set_general_hidden_caps: fix order of operations•••We should increment the number of capabilities to allocate space for after freeing any existing capabilities, in order to prevent the loop that frees them from overwriting the number. Reported-By: Ryan Schmidt Gravatar Aaron Jones2026-01-271-6/+10
* Pass msgbuf to PART's privmsg_channel hook and propagate PART tags•••The privmsg_channel hook gained a new msgbuf member which was uninitialized in m_part. Properly pass the msgbuf to that parameter and propagate any tags set by the hook to downstream servers. This requires introducing sendto_server_tags(), and I refactored sendto_server() to call the same helper internal method as sendto_server_tags(). I took the opportunity to update the method to use msgbuf instead of linebuf directly (meaning sendto_server() now calls outbound_msgbuf). Fixes #484 Gravatar Ryan Schmidt2026-01-221-17/+66
* Batch updates•••The extension example_module was extended to introduce a new client-initiated batch type named test. This is primarily done to ease testing of the client-initiated portions of m_batch, but also serves as a useful sketch for how a module can register its own client-initiated batch types. The definition of struct BatchHandler was slightly modified to use a callback function to determine if nesting is allowed. The callback can additionally set a custom error message if desired when returning false. The len and messages list in struct Batch no longer include the start message, so a len of 0 indicates an empty batch. Because the start message is still allocated and saved off, adjust anything that impacts a client's pending_batch_lines by 1 to account for the implicit additional message. Empty batches now trigger the relevant batch handler. If a handler wants to no-op on empty batches, it can do so but this allows additional flexibility for handlers to still do something upon receiving empty client-initiated batches. Gravatar Ryan Schmidt2026-01-211-8/+9
* Include AWAY and status MODEs in netjoin batches•••AWAY is burst to away-notify clients and status MODEs (+o and +v) are burst to all clients on the channel. Excluding these from the batch means that clients may opt to process these before the batch completes, then get confused because they have no records of those nicknames existing or being members of the channel. Including both in the netjoin batch solves these concerns, although the netjoin batch spec is silent on whether we're allowed to put non-JOIN commands in that batch. Gravatar Ryan Schmidt2026-01-211-3/+3
* Add batch support•••- Add "batch" client capability - Support sending netsplit/netjoin batches - Support receiving BATCH from clients and remote servers - Support for modules to define supported batch types for incoming batches - Add "message_handler" hook to override the handler for a particular incoming message - Add technical and user-facing documentation for batches - Add some more sendto_* overloads that support tags which were missing from the initial message-tags implementation but turned out to be needed Gravatar Ryan Schmidt2026-01-219-104/+413
* Propagate tags in numerics from linked servers (#477)•••Previously, we handled numerics before running the message_tags hook or setting the incoming_message and incoming_client globals, which meant that tags received from linked servers would never be passed along to clients. Now do both of those things before passing the numeric along so we can propagate message tags in numerics. This will, among other things, mean server-time now works with numerics and solves an issue with implementing labeled-response in the future.Gravatar Ryan Schmidt2026-01-111-20/+18
* Fix memory leak in sendto_match_servs (#465)•••Free the msgbuf cache after we're done.Gravatar Ryan Schmidt2025-10-231-0/+2
* Remote the `compressed` server flag•••This is a follow-up to 81531536aac9adb585c5a17b448aa0496bf68ebd where the ziplinks feature had been ripped out. Unfortunately the value of the `compressed` flag had been set to `0` instead of `-1`, or removed entirely. This led to resetting a connect blocks flags being reset whenever the `compressed` flag was being set. When you'd set the flags (in this order) `topicburst, compressed, ssl` you'd end up with just the `ssl` flag as setting `compressed` would reset all of the flag back to zero (newconf.c:439) as set_modes_from_table excepts `-1` to be passed as not-found / invalid flag value. With this (trivial) patch the log will contain a helpful line telling operators that the `compressed` flag is unknown. It doesn't fail config parsing/rehashing: > Warning -- unknown flag compressed. Gravatar Andreas Rammhold2025-10-131-1/+0
* Fix CLIENTTAGDENY when there are no allowed tags (#461)•••The buffer was uninitialized and would produce garbage data. Ensure that the buffer is an empty string when there are no allowed client tags.Gravatar Ryan Schmidt2025-10-111-0/+1
* Revert "msgbuf: duplicate the string during partial parse and constify line" ...•••This reverts commit 5b253939da8f6b0a44ce6787ed12e26450ac6a63 to fix a memory leak: ``` ==825564== 818 bytes in 4 blocks are definitely lost in loss record 616 of 648 ==825564== at 0x4844818: malloc (vg_replace_malloc.c:446) ==825564== by 0x49CD7A9: strdup (strdup.c:42) ==825564== by 0x4888A2E: msgbuf_partial_parse (msgbuf.c:143) ==825564== by 0x489DA84: build_msgbuf (send.c:276) ==825564== by 0x489DA84: sendto_one_numeric (send.c:431) ==825564== by 0x48A3CD7: show_isupport (supported.c:181) ==825564== by 0x489A9F2: user_welcome (s_user.c:1433) ==825564== by 0x489B114: register_local_user (s_user.c:718) ==825564== by 0x488FC08: handle_command (parse.c:310) ==825564== by 0x488FC08: parse (parse.c:224) ==825564== by 0x488EEF8: parse_client_queued.part.0 (packet.c:67) ==825564== by 0x488F084: parse_client_queued (packet.c:49) ==825564== by 0x488F084: read_packet (packet.c:306) ==825564== by 0x4B3C47B: rb_select_epoll (epoll.c:199) ==825564== by 0x4B3716F: rb_select (commio.c:2038) ==825564== [...] ==825564== ==825564== 3,012 bytes in 15 blocks are definitely lost in loss record 627 of 648 ==825564== at 0x4844818: malloc (vg_replace_malloc.c:446) ==825564== by 0x49CD7A9: strdup (strdup.c:42) ==825564== by 0x4888A2E: msgbuf_partial_parse (msgbuf.c:143) ==825564== by 0x489D3CE: build_msgbuf (send.c:276) ==825564== by 0x489D3CE: sendto_realops_snomask (send.c:1431) ==825564== by 0x4887C0D: load_a_module (modules.c:712) ==825564== by 0x488801D: load_core_modules (modules.c:257) ==825564== by 0x488124A: solanum_main (ircd.c:664) ==825564== by 0x494DCA7: (below main) (libc_start_call_main.h:58) ```Gravatar Val Lorentz2025-10-112-3/+3
* Address review comments•••- Remove static qualifier from a string that didn't need it - Add some tests for trailing params with a leading colon as data to ensure they are parsed/unparsed correctly Gravatar Ryan Schmidt2025-10-101-1/+1
* Ensure duplicate tags only use the final value•••Per spec, individual tag keys MUST only be used once per message, and implementations SHOULD disregard all but the final occurrence of a tag key. As such, iterate over the user-provided tags in reverse order and automatically discard tags that we have already approved. Also, require that a client giving us a +typing tag has negotiated the message-tags capability themselves. Gravatar Ryan Schmidt2025-10-101-2/+7
* Fix typing module decl and send 417 in more cases•••The typing module declaration had a copy/paste error that has now been corrected, and we now send 417 ERR_INPUTTOOLONG in cases where parsing the line into a MsgBuf fails because it overflowed the 8191+512 byte buffer while processing tags or the message origin. Gravatar Ryan Schmidt2025-10-102-5/+8
* Address review comments•••Correctly sent ERR_INPUTTOOLONG if the incoming tags portion from a client is too long. The previous calculation did not take into account the fact we added null terminators after every tag key and value. Since msgbuf_parse is used for both server and client input, we expose the length of the original tags portion of the buffer in the MsgBuf struct rather than abort msgbuf_parse if it is too long, since the only time truncation is explicitly not allowed is for incoming tags from client messages. Additionally, make join_sep functional in format_client_tags(). Gravatar Ryan Schmidt2025-10-103-28/+32
* ircd/send.c: Better support for outbound tags•••There are now sendto_* functions that take explicit tags to pass to the outgoing MsgBuf, in addition to any hook functions that listen to outbound_msgbuf to add tags of their own. The outbound_msgbuf hook function now receives a fully-parsed line, meaning it will have a defined parameters array and (sometimes) origin. Hook functions can make use of this to read message context when determining whether to add tags, and can also manipulate the outbound MsgBuf as it will be unparsed back into an IRC line after hooks have executed to be sent off. Previously, only the tags portion was used and outbound_msgbuf had no capability to examine or manipulate the rest of the outgoing message. These functions also make use of the new MsgBuf caching layer that takes a local and remote source. For functions that receive a static source as part of the format pattern, NULL is used so that the cache inherits the source from the parsed line. In some cases, a sendto function may produce completely different messages depending on the situation (e.g. sendto_channel_opmod which behaves differently depending on if the remote server supports EOPMOD or not, and if not, whether or not the target channel is +m). In such cases, separate MsgBuf caches with separate MsgBufs were used. The outbound_msgbuf hook is only executed once however, and all tags are copied over to the other MsgBufs. This allows things like msgid to be stable regardless of which variation is being sent out to which client. Internal static functions beginning with underscores were renamed to be sendto_*_internal instead. Identifiers with leading underscores in file scope are reserved by the C standard, and their usage here was undefined behavior. Gravatar Ryan Schmidt2025-10-101-370/+487
* Cleanup areas impacted by client tags•••With the new TAGMSG support in m_message, filter now receives TAGMSG but would choke on processing them due to not having a mapping from that message type to a command name. Right now, no filtering is done on tag contents because there is currently no tags that we support that take arbitrary user-defined data (and thus would require filtering). This fact does not change in the course of this patchset. The client_tags code to register client tags for the CLIENTTAGSDENY ISUPPORT message had some general formatting cleanup as well as a fix for a segfault when removing support for a client tag if that client tag was the last one being removed (causing the src and dest for strcpy to be the same pointer) as well as a bugfix for the strcmp check that would've caused it to overwrite the wrong client tag entry. Gravatar Ryan Schmidt2025-10-101-13/+8
* Refactor message_tag hook•••The original hook was defined in the (now-removed) cap_message_tag module. This new hook lives deeper down in parse.c so that it fires on all incoming tags for all incoming messages. The hook was renamed from client_tag_accept to message_tag to denote that it is used for all tags, including tags coming from server connections, and not just tags with a client-only prefix. The hook data contains two non-const fields for the capmask and approval status. Since incoming tags lack a capmask entirely, this allows hook functions that wish to keep the tag around to specify the capmask used for propagating the tag to other clients and servers. The approval status can take one of three forms: approve the tag, drop the tag from the message (but still process other tags and run the command handler), or drop the entire message (not processing any other tags and not running any command handlers). It is expected when a hook function drops the message that they'll send appropriate feedback to the client, however the nature of that feedback will likely vary by hook function so no default message is given to a client if their message is dropped. The incoming_message global defined previously with cap_server_time now holds the MsgBuf with the updated/sanitized list of tags rather than the raw values specified by the client. Additionally, cap_server_time makes use of this new hook to propagate the time tag into function callbacks that support tag propagation. The implicit propagation still exists since the majority of function callbacks do not support explicit tag propagation, and that fact will not change in the course of this patchset. Gravatar Ryan Schmidt2025-10-102-4/+51
* Update MsgBuf for better tags support•••Note: Future commits within this PR update call sites to leverage these changes. I opted to keep each individual commit smaller to make them easier to review in series. When parsing a line into a MsgBuf, we now keep track of whether the final parameter had a leading colon or not, so that we can roundtrip unparse it with said colon even if the final parameter lacks a space or otherwise doesn't require the leading colon. solanum sends multiple such messages and clients may be coded to expect colons in various situations, so adding this roundtrip support maintains backwards compatibility for when all outbound messages get parsed into MsgBuf and then unparsed before being sent off. The MsgBuf cache now keeps track of two messages: one with a "local" source and one with a "remote" source. Many send functions, e.g. the sendto_channel family, use ids for the sender when sending remotely but use the hostmask or server name for local sends. When forcing outbound messages into a parse/unparse loop we can no longer just ad-hoc assemble strings together like the current linebuf code does, so instead we cache both variants to avoid needless string formatting operations in tight send loops. Unparsing tags from a MsgBuf now enforces that the server tags and client tags portions do not exceed 4094 bytes each, and that server tags always come before client tags. Excess data is truncated. Gravatar Ryan Schmidt2025-10-101-88/+144
* Increase tags to 8191 bytes and max count to 30•••If we receive an incoming message from a client that has over 4094 bytes of tag data (not including leading '@' or trailing ' '), reject the message with ERR_INPUTTOOLONG (417) per the message-tags spec. Similarly, give the same numeric if the client specifies the new maximum of 30 tags, since we can't distinguish between a client that gives us 30 tags and one that gives us more than 30. The spec says we are not allowed to truncate tags at all, and having 30 means we could have potentially truncated the incoming tag data. Gravatar Ryan Schmidt2025-10-101-0/+7
* fix: remove cruft and fix msgbuf_parseGravatar Raito Bezarius2025-10-102-3/+1
* msgbuf: duplicate the string during partial parse and constify lineGravatar Raito Bezarius2025-10-101-2/+2
* message-tags: facility to manipulate client-tags•••It provides for hook facilities to client-only tags: - messages can be dropped silently ; - messages can be edited ; - messages can be stripped from a client-only tag Gravatar Raito Bezarius2025-10-105-30/+96
* m_message: proper tag propagation•••This introduces an handler to accept or not the propagation of a tag. Basic sketch API is provided for modules to hook for providing their own policy for specific tag propagation. Gravatar Raito Bezarius2025-10-103-0/+43
* isupport: add CLIENTTAGDENYGravatar Raito Bezarius2025-10-101-0/+11
* Propagate server-time implicitly (ugh)Gravatar Ed Kellett2025-10-101-0/+8
* send: Make cap masks respect CAP_STAG for serversGravatar Ed Kellett2025-10-101-19/+20
* msgbuf: Add msgbuf_get_tagGravatar Ed Kellett2025-10-101-0/+13
* Add STAG server capGravatar Ed Kellett2025-10-101-0/+2
* GitHub CI Workflow: Bump OS and compiler versions (#447)•••* GitHub CI Workflow: Bump OS and compiler versions * CI: fix for clang 18/19 - Don't enable -Werror during the execution of ./configure and drop -Wunused-value from --enable-warnings - librb/src/crypt.c: remove old-style function decls - rb_dictionary: define type of arguments, fix callees - rb_radixtree: fix spurious out-of-bounds diagnostic Co-authored-by: Doug Freed <dwfreed@mtu.edu>Gravatar Aaron Jones2025-02-251-2/+2
* Don't set the oper flags on client (#443)•••Remove unused OPER_FLAGS logic in favor new priv system. It had rotted over time and was overlapping with PINGSENTGravatar Eric Mertens2025-01-291-3/+0
* s_user: reject invalid usernames before anything else•••This way invalid characters in usernames only appear in this snote, and all other rejection snotes will always have clean usernames. Gravatar Doug Freed2024-06-151-26/+26
* s_user: sanitize username early•••This ensures we don't allow [ in usernames anywhere. This also adds the tilde early, which simplifies a lot of things, and fixes an issue with username K-Lines on IsNoTilde users. Gravatar Doug Freed2024-06-152-89/+51
* Remove WebSocket supportGravatar Aaron Jones2024-06-127-641/+8
* Fix small typo•••authdd -> authdGravatar Firepup6502024-04-131-1/+1
* extensions/invite_notify: make the NOTICE optional, configurable•••This adds a configuration option that determines whether the NOTICE is sent to clients that do not support the IRCv3 invite-notify capability. Requested by LiberaChat MGM. Gravatar Aaron Jones2023-11-082-1/+3
* ircd/listener: return a fatal TLS alert for early rejected TLS clients•••This is in furtherance of commit 3fdf26aa19628d5e12a3 which added functionality to reply with a TLS record layer alert for D-Lined TLS clients. It turns out that there are other plaintext error messages in this same function that should receive the same treatment. Also move another error string to a variable and use a compile-time optimised-out strlen for it too, to use the same approach as an existing error string. Finally, use a different alert (internal_error) for the case where IRCd is simply unable to accept more connections. Gravatar Aaron Jones2023-11-072-19/+46
* client: refactor del_all_accepts to allow skipping own accept list•••This allows reusing this function for other uses that just need to remove this client from others' accept lists on nick change and not have duplicates of this code everywhere Gravatar Doug Freed2023-11-062-5/+13
* Replace free with rb_freeGravatar Eric Mertens2023-11-061-1/+1
* Delay rehashing until we're not processing events•••Fixes crash introduced by 0ab6dbbc651ddd1c26cb7baa6e6cf86890a4abd2. It's probably a regression since it defeats a system designed to stop this from happening, but I didn't dig through the history. rehash() closes listeners. If we happen to get a single epoll() result that wants to first rehash and then accept a connection, the epoll info will point to a freed rb_fde_t. Other selectors should have similar problems, but we didn't investigate that. rb_fde_ts are normally batched up and freed outside the event processing, but as of the above commit close_listeners() screws that up by closing pending FDs immediately in order to create new listeners. I think it might be a bit better to revert this behaviour and simply not close listeners if we are going to open new ones over them, but have opted for the smallest reasonable change I can think of. Helped-by: Eric Mertens <emertens@gmail.com> Gravatar Ed Kellett2023-11-061-9/+26
* modules: quietly succeed at loading a module if already loaded•••This allows explicitly loading a module in the config so it's available for later config items that might need it, and skips the double load when main loads all modules, which would cause errors Gravatar Doug Freed2023-07-011-0/+4
* modules: clear module list and mod paths in init•••If main is called more than once (like in tests), everything is reinitialized except the loaded module list and module paths, so clear them too so that modules are loaded again and the path list is correct. Gravatar Doug Freed2023-07-011-0/+3
* support RSFNC indicating type of FNC (e.g. FORCE vs REGAIN) (#406)Gravatar Jess Porter2023-07-011-0/+2
* Warn opers about unresponsive serversGravatar David Schultz2023-06-133-0/+39
* chmode: convert bants to a proper serial•••This way it increments for every change. It need not be a timestamp, as its actual value is not important. This fixes an issue where a ban could be set, hit, and cleared all in the same second, and the affected client would still be cached as banned because the bants hadn't actually changed. Gravatar Doug Freed2023-01-231-2/+2
* ircd/authproc.c: avoid crash on lack of any configured DNSBLs•••Fixes fbc97166a6e455f5cccf Closes #396 Gravatar Aaron Jones2023-01-111-6/+9
* authd: fix crash/restart breaking DNSBL lookups (#394)•••authd child processes are only told about configured DNSBLs when the configuration is being parsed. This is bad, because when authd crashes or is killed, IRCd will restart it, but will not tell it about any configured DNSBLs until IRCd is next rehashed. We already have a dictionary that stores configured DNSBLs (for hit statistics for `STATS n'), so store the additional needed fields in that structure, and loop over that dictionary's entries when authd is restarted, sending the fields just as if the configuration were being reloaded. Reported-By: @Unit193Gravatar Aaron Jones2023-01-112-16/+32
* CHGHOST when only case changes (#384)Gravatar Jess Porter2022-11-091-1/+1
* timeout_dead_authd_clients(): fix memory leak and order of operations (#385)•••Ensure we deallocate the nodes created by the first loop, and zero out the authd data after removing them from the authd clients dict. The authd_abort_client() function already does the latter, so just call that instead of authd_free_client().Gravatar Aaron Jones2022-11-061-2/+2