| Commit message (Expand) | Author | Age | Files | Lines |
| * | 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/modules | Aaron Jones | 2026-03-11 | 2 | -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: e2a499f | Ryan Schmidt | 2026-01-27 | 1 | -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
| Aaron Jones | 2026-01-27 | 1 | -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
| Ryan Schmidt | 2026-01-22 | 1 | -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.
| Ryan Schmidt | 2026-01-21 | 1 | -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.
| Ryan Schmidt | 2026-01-21 | 1 | -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
| Ryan Schmidt | 2026-01-21 | 9 | -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. | Ryan Schmidt | 2026-01-11 | 1 | -20/+18 |
| * | Fix memory leak in sendto_match_servs (#465)•••Free the msgbuf cache after we're done. | Ryan Schmidt | 2025-10-23 | 1 | -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.
| Andreas Rammhold | 2025-10-13 | 1 | -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. | Ryan Schmidt | 2025-10-11 | 1 | -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)
``` | Val Lorentz | 2025-10-11 | 2 | -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
| Ryan Schmidt | 2025-10-10 | 1 | -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.
| Ryan Schmidt | 2025-10-10 | 1 | -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.
| Ryan Schmidt | 2025-10-10 | 2 | -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().
| Ryan Schmidt | 2025-10-10 | 3 | -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.
| Ryan Schmidt | 2025-10-10 | 1 | -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.
| Ryan Schmidt | 2025-10-10 | 1 | -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.
| Ryan Schmidt | 2025-10-10 | 2 | -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.
| Ryan Schmidt | 2025-10-10 | 1 | -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.
| Ryan Schmidt | 2025-10-10 | 1 | -0/+7 |
| * | fix: remove cruft and fix msgbuf_parse | Raito Bezarius | 2025-10-10 | 2 | -3/+1 |
| * | msgbuf: duplicate the string during partial parse and constify line | Raito Bezarius | 2025-10-10 | 1 | -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
| Raito Bezarius | 2025-10-10 | 5 | -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.
| Raito Bezarius | 2025-10-10 | 3 | -0/+43 |
| * | isupport: add CLIENTTAGDENY | Raito Bezarius | 2025-10-10 | 1 | -0/+11 |
| * | Propagate server-time implicitly (ugh) | Ed Kellett | 2025-10-10 | 1 | -0/+8 |
| * | send: Make cap masks respect CAP_STAG for servers | Ed Kellett | 2025-10-10 | 1 | -19/+20 |
| * | msgbuf: Add msgbuf_get_tag | Ed Kellett | 2025-10-10 | 1 | -0/+13 |
| * | Add STAG server cap | Ed Kellett | 2025-10-10 | 1 | -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> | Aaron Jones | 2025-02-25 | 1 | -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 PINGSENT | Eric Mertens | 2025-01-29 | 1 | -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.
| Doug Freed | 2024-06-15 | 1 | -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.
| Doug Freed | 2024-06-15 | 2 | -89/+51 |
| * | Remove WebSocket support | Aaron Jones | 2024-06-12 | 7 | -641/+8 |
| * | Fix small typo•••authdd -> authd | Firepup650 | 2024-04-13 | 1 | -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.
| Aaron Jones | 2023-11-08 | 2 | -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.
| Aaron Jones | 2023-11-07 | 2 | -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
| Doug Freed | 2023-11-06 | 2 | -5/+13 |
| * | Replace free with rb_free | Eric Mertens | 2023-11-06 | 1 | -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>
| Ed Kellett | 2023-11-06 | 1 | -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
| Doug Freed | 2023-07-01 | 1 | -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.
| Doug Freed | 2023-07-01 | 1 | -0/+3 |
| * | support RSFNC indicating type of FNC (e.g. FORCE vs REGAIN) (#406) | Jess Porter | 2023-07-01 | 1 | -0/+2 |
| * | Warn opers about unresponsive servers | David Schultz | 2023-06-13 | 3 | -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.
| Doug Freed | 2023-01-23 | 1 | -2/+2 |
| * | ircd/authproc.c: avoid crash on lack of any configured DNSBLs•••Fixes fbc97166a6e455f5cccf
Closes #396
| Aaron Jones | 2023-01-11 | 1 | -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: @Unit193 | Aaron Jones | 2023-01-11 | 2 | -16/+32 |
| * | CHGHOST when only case changes (#384) | Jess Porter | 2022-11-09 | 1 | -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(). | Aaron Jones | 2022-11-06 | 1 | -2/+2 |