unrealircd

- supernets unrealircd source & configuration
git clone git://git.acid.vegas/unrealircd.git
Log | Files | Refs | Archive | README | LICENSE

send.c (37874B)

      1 /*
      2  *   Unreal Internet Relay Chat Daemon, src/send.c
      3  *   Copyright (C) 1990 Jarkko Oikarinen and
      4  *		      University of Oulu, Computing Center
      5  *
      6  *   This program is free software; you can redistribute it and/or modify
      7  *   it under the terms of the GNU General Public License as published by
      8  *   the Free Software Foundation; either version 1, or (at your option)
      9  *   any later version.
     10  *
     11  *   This program is distributed in the hope that it will be useful,
     12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14  *   GNU General Public License for more details.
     15  *
     16  *   You should have received a copy of the GNU General Public License
     17  *   along with this program; if not, write to the Free Software
     18  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     19  */
     20 
     21 /* send.c 2.32 2/28/94 (C) 1988 University of Oulu, Computing Center and Jarkko Oikarinen */
     22 
     23 /** @file
     24  * @brief The sending functions to users, channels, servers.
     25  */
     26 
     27 #include "unrealircd.h"
     28 
     29 /* Some forward declarions are needed */
     30 void vsendto_one(Client *to, MessageTag *mtags, const char *pattern, va_list vl);
     31 void vsendto_prefix_one(Client *to, Client *from, MessageTag *mtags, const char *pattern, va_list vl) __attribute__((format(printf,4,0)));
     32 static int vmakebuf_local_withprefix(char *buf, size_t buflen, Client *from, const char *pattern, va_list vl) __attribute__((format(printf,4,0)));
     33 
     34 #define ADD_CRLF(buf, len) { if (len > 510) len = 510; \
     35                              buf[len++] = '\r'; buf[len++] = '\n'; buf[len] = '\0'; } while(0)
     36 
     37 /* These are two local (static) buffers used by the various send functions */
     38 static char sendbuf[2048];
     39 static char sendbuf2[MAXLINELENGTH];
     40 
     41 /** This is used to ensure no duplicate messages are sent
     42  * to the same server uplink/direction. In send functions
     43  * that deliver to multiple users or servers the value is
     44  * increased by 1 and then for each delivery in the loop
     45  * it is checked if to->direction->local->serial == current_serial
     46  * and if so, sending is skipped.
     47  */
     48 MODVAR int  current_serial;
     49 
     50 /** Mark the socket as "dead".
     51  * This is used when exit_client() cannot be used from the
     52  * current code because doing so would be (too) unexpected.
     53  * The socket is closed later in the main loop.
     54  * NOTE: this function is becoming less important, now that
     55  *       exit_client() will not actively free the client.
     56  *       Still, sometimes we need to use dead_socket()
     57  *       since we don't want to be doing IsDead() checks after
     58  *       each and every sendto...().
     59  * @param to		Client to mark as dead
     60  * @param notice	The quit reason to use
     61  */
     62 int dead_socket(Client *to, const char *notice)
     63 {
     64 	DBufClear(&to->local->recvQ);
     65 	DBufClear(&to->local->sendQ);
     66 
     67 	if (IsDeadSocket(to))
     68 		return -1; /* already pending to be closed */
     69 
     70 	SetDeadSocket(to);
     71 
     72 	/* We may get here because of the 'CPR' in check_deadsockets().
     73 	 * In which case, we return -1 as well.
     74 	 */
     75 	if (to->local->error_str)
     76 		return -1; /* don't overwrite & don't send multiple times */
     77 	
     78 	if (!IsUser(to) && !IsUnknown(to) && !IsRPC(to) && !IsControl(to) && !IsClosing(to))
     79 	{
     80 		/* Looks like a duplicate error message to me?
     81 		 * If so, remove it here.
     82 		 */
     83 		unreal_log(ULOG_ERROR, "link", "LINK_CLOSING", to,
     84 		           "Link to server $client.details closed: $reason",
     85 		           log_data_string("reason", notice));
     86 	}
     87 	safe_strdup(to->local->error_str, notice);
     88 	return -1;
     89 }
     90 
     91 /** This is a callback function from the event loop.
     92  * All it does is call send_queued().
     93  */
     94 void send_queued_cb(int fd, int revents, void *data)
     95 {
     96 	Client *to = data;
     97 
     98 	if (IsDeadSocket(to))
     99 		return;
    100 
    101 	send_queued(to);
    102 }
    103 
    104 /** This function is called when queued data might be ready to be
    105  * sent to the client. It is called from the event loop and also
    106  * a couple of other places (such as when closing the connection).
    107  */
    108 int send_queued(Client *to)
    109 {
    110 	int  len, rlen;
    111 	dbufbuf *block;
    112 	int want_read;
    113 
    114 	/* We NEVER write to dead sockets. */
    115 	if (IsDeadSocket(to))
    116 		return -1;
    117 
    118 	while (DBufLength(&to->local->sendQ) > 0)
    119 	{
    120 		block = container_of(to->local->sendQ.dbuf_list.next, dbufbuf, dbuf_node);
    121 		len = block->size;
    122 
    123 		/* Deliver it and check for fatal error.. */
    124 		if ((rlen = deliver_it(to, block->data, len, &want_read)) < 0)
    125 		{
    126 			char buf[256];
    127 			snprintf(buf, 256, "Write error: %s", STRERROR(ERRNO));
    128 			return dead_socket(to, buf);
    129 		}
    130 		dbuf_delete(&to->local->sendQ, rlen);
    131 		if (want_read)
    132 		{
    133 			/* SSL_write indicated that it cannot write data at this
    134 			 * time and needs to READ data first. Let's stop talking
    135 			 * to the user and ask to notify us when there's data
    136 			 * to read.
    137 			 */
    138 			fd_setselect(to->local->fd, FD_SELECT_READ, send_queued_cb, to);
    139 			fd_setselect(to->local->fd, FD_SELECT_WRITE, NULL, to);
    140 			break;
    141 		}
    142 		/* Restore handling of reads towards read_packet(), since
    143 		 * it may be overwritten in an earlier call to send_queued(),
    144 		 * to handle reads by send_queued_cb(), see directly above.
    145 		 */
    146 		fd_setselect(to->local->fd, FD_SELECT_READ, read_packet, to);
    147 		if (rlen < len)
    148 		{
    149 			/* incomplete write due to EWOULDBLOCK, reschedule */
    150 			fd_setselect(to->local->fd, FD_SELECT_WRITE, send_queued_cb, to);
    151 			break;
    152 		}
    153 	}
    154 	
    155 	/* Nothing left to write, stop asking for write-ready notification. */
    156 	if ((DBufLength(&to->local->sendQ) == 0) && (to->local->fd >= 0))
    157 		fd_setselect(to->local->fd, FD_SELECT_WRITE, NULL, to);
    158 
    159 	return (IsDeadSocket(to)) ? -1 : 0;
    160 }
    161 
    162 /** Mark "to" with "there is data to be send" */
    163 void mark_data_to_send(Client *to)
    164 {
    165 	if (!IsDeadSocket(to) && (to->local->fd >= 0) && (DBufLength(&to->local->sendQ) > 0))
    166 	{
    167 		fd_setselect(to->local->fd, FD_SELECT_WRITE, send_queued_cb, to);
    168 	}
    169 }
    170 
    171 /** Send data to clients, servers, channels, IRCOps, etc.
    172  * There are a lot of send functions. The most commonly functions
    173  * are: sendto_one() to send to an individual user,
    174  * sendnumeric() to send a numeric to an individual user
    175  * and sendto_channel() to send a message to a channel.
    176  * @defgroup SendFunctions Send functions
    177  * @{
    178  */
    179 
    180 /** Send a message to a single client.
    181  * This function is used quite a lot, after sendnumeric() it is the most-used send function.
    182  * @param to		The client to send to
    183  * @param mtags		Any message tags associated with this message (can be NULL)
    184  * @param pattern	The format string / pattern to use.
    185  * @param ...		Format string parameters.
    186  * @section sendto_one_examples Examples
    187  * @subsection sendto_one_mode_r Send "MODE -r"
    188  * This will send the `:serv.er.name MODE yournick -r` message.
    189  * Note that it will send only this message to illustrate the sendto_one() function.
    190  * It does *not* set anyone actually -r.
    191  * @code
    192  * sendto_one(client, NULL, ":%s MODE %s :-r", me.name, client->name);
    193  * @endcode
    194  */
    195 void sendto_one(Client *to, MessageTag *mtags, FORMAT_STRING(const char *pattern), ...)
    196 {
    197 	va_list vl;
    198 	va_start(vl, pattern);
    199 	vsendto_one(to, mtags, pattern, vl);
    200 	va_end(vl);
    201 }
    202 
    203 /** Send a message to a single client - va_list variant.
    204  * This function is similar to sendto_one() except that it
    205  * doesn't use varargs but uses a va_list instead.
    206  * Generally this function is NOT used outside send.c, so not by modules.
    207  * @param to		The client to send to
    208  * @param mtags		Any message tags associated with this message (can be NULL)
    209  * @param pattern	The format string / pattern to use.
    210  * @param vl		Format string parameters.
    211  */
    212 void vsendto_one(Client *to, MessageTag *mtags, const char *pattern, va_list vl)
    213 {
    214 	const char *mtags_str = mtags ? mtags_to_string(mtags, to) : NULL;
    215 
    216 	/* Need to ignore -Wformat-nonliteral here */
    217 #if defined(__GNUC__)
    218 #pragma GCC diagnostic push
    219 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
    220 #endif
    221 	ircvsnprintf(sendbuf, sizeof(sendbuf)-3, pattern, vl);
    222 #if defined(__GNUC__)
    223 #pragma GCC diagnostic pop
    224 #endif
    225 
    226 	if (BadPtr(mtags_str))
    227 	{
    228 		/* Simple message without message tags */
    229 		sendbufto_one(to, sendbuf, 0);
    230 	} else {
    231 		/* Message tags need to be prepended */
    232 		snprintf(sendbuf2, sizeof(sendbuf2)-3, "@%s %s", mtags_str, sendbuf);
    233 		sendbufto_one(to, sendbuf2, 0);
    234 	}
    235 }
    236 
    237 
    238 /** Send a line buffer to the client.
    239  * This function is used (usually indirectly) for pretty much all
    240  * cases where a line needs to be sent to a client.
    241  * @param to    The client to which the buffer should be send.
    242  * @param msg   The message.
    243  * @param quick Normally set to 0, see the notes.
    244  * @note
    245  * - Neither 'to' or 'msg' may be NULL.
    246  * - If quick is set to 0 then the length is calculated,
    247  *   the string is cut off at 510 bytes if needed, and
    248  *   CR+LF is added if needed.
    249  *   If quick is >0 then it is assumed the message already
    250  *   is within boundaries and passed all safety checks and
    251  *   contains CR+LF at the end. This if, for example, used in
    252  *   channel broadcasts to save some CPU cycles. It is NOT
    253  *   recommended as normal usage since you need to be very
    254  *   careful to take everything into account, including side-
    255  *   effects not mentioned here.
    256  */
    257 void sendbufto_one(Client *to, char *msg, unsigned int quick)
    258 {
    259 	int len;
    260 	Hook *h;
    261 	Client *intended_to = to;
    262 	
    263 	if (to->direction)
    264 		to = to->direction;
    265 	if (IsDeadSocket(to))
    266 		return;		/* This socket has already
    267 				   been marked as dead */
    268 	if (to->local->fd < 0)
    269 	{
    270 		/* This is normal when 'to' was being closed (via exit_client
    271 		 *  and close_connection) --Run
    272 		 */
    273 		return;
    274 	}
    275 
    276 	/* Unless 'quick' is set, we do some safety checks,
    277 	 * cut the string off at the appropriate place and add
    278 	 * CR+LF if needed (nearly always).
    279 	 */
    280 	if (!quick)
    281 	{
    282 		char *p = msg;
    283 		if (*msg == '@')
    284 		{
    285 			/* The message includes one or more message tags:
    286 			 * Spec-wise the rules allow about 8K for message tags
    287 			 * (MAXTAGSIZE) and then 512 bytes for
    288 			 * the remainder of the message (BUFSIZE).
    289 			 */
    290 			p = strchr(msg+1, ' ');
    291 			if (!p)
    292 			{
    293 				unreal_log(ULOG_WARNING, "send", "SENDBUFTO_ONE_MALFORMED_MSG", to,
    294 				           "Malformed message to $client: $buf",
    295 				           log_data_string("buf", msg));
    296 				return;
    297 			}
    298 			if (p - msg > MAXTAGSIZE)
    299 			{
    300 				unreal_log(ULOG_WARNING, "send", "SENDBUFTO_ONE_OVERSIZED_MSG", to,
    301 				           "Oversized message to $client (length $length): $buf",
    302 				           log_data_integer("length", p - msg),
    303 				           log_data_string("buf", msg));
    304 				return;
    305 			}
    306 			p++; /* skip space character */
    307 		}
    308 		len = strlen(p);
    309 		if (!len || (p[len - 1] != '\n'))
    310 		{
    311 			if (len > 510)
    312 				len = 510;
    313 			p[len++] = '\r';
    314 			p[len++] = '\n';
    315 			p[len] = '\0';
    316 		}
    317 		len = strlen(msg); /* (note: we could use pointer jugling to avoid a strlen here) */
    318 	} else {
    319 		len = quick;
    320 	}
    321 
    322 	if (len >= MAXLINELENGTH)
    323 	{
    324 		unreal_log(ULOG_WARNING, "send", "SENDBUFTO_ONE_OVERSIZED_MSG2", to,
    325 			   "Oversized message to $client (length $length): $buf",
    326 			   log_data_integer("length", len),
    327 			   log_data_string("buf", msg));
    328 #ifdef DEBUGMODE
    329 		abort();
    330 #else
    331 		return;
    332 #endif
    333 	}
    334 
    335 	if (IsMe(to))
    336 	{
    337 		char tmp_msg[500];
    338 
    339 		strlcpy(tmp_msg, msg, sizeof(tmp_msg));
    340 		stripcrlf(tmp_msg);
    341 		unreal_log(ULOG_WARNING, "send", "SENDBUFTO_ONE_ME_MESSAGE", to,
    342 			   "Trying to send data to myself: $buf",
    343 			   log_data_string("buf", tmp_msg));
    344 		return;
    345 	}
    346 
    347 	for (h = Hooks[HOOKTYPE_PACKET]; h; h = h->next)
    348 	{
    349 		(*(h->func.intfunc))(&me, to, intended_to, &msg, &len);
    350 		if (!msg)
    351 			return;
    352 	}
    353 
    354 #if defined(RAWCMDLOGGING)
    355 	{
    356 		char copy[512], *p;
    357 		strlcpy(copy, msg, len > sizeof(copy) ? sizeof(copy) : len);
    358 		p = strchr(copy, '\n');
    359 		if (p) *p = '\0';
    360 		p = strchr(copy, '\r');
    361 		if (p) *p = '\0';
    362 		unreal_log(ULOG_INFO, "rawtraffic", "TRAFFIC_OUT", to,
    363 		           "-> $client: $data",
    364 		           log_data_string("data", copy));
    365 	}
    366 #endif
    367 
    368 	if (DBufLength(&to->local->sendQ) > get_sendq(to))
    369 	{
    370 		unreal_log(ULOG_INFO, "flood", "SENDQ_EXCEEDED", to,
    371 		           "Flood of queued data to $client.details [$client.ip] exceeds class::sendq ($sendq > $class_sendq) (Too much data queued to be sent to this client)",
    372 		           log_data_integer("sendq", DBufLength(&to->local->sendQ)),
    373 		           log_data_integer("class_sendq", get_sendq(to)));
    374 		dead_socket(to, "Max SendQ exceeded");
    375 		return;
    376 	}
    377 
    378 	dbuf_put(&to->local->sendQ, msg, len);
    379 
    380 	/*
    381 	 * Update statistics. The following is slightly incorrect
    382 	 * because it counts messages even if queued, but bytes
    383 	 * only really sent. Queued bytes get updated in SendQueued.
    384 	 */
    385 	// FIXME: something is wrong here, I think we do double counts, either in message or in traffic, I forgot.. CHECK !!!!
    386 	to->local->traffic.messages_sent++;
    387 	me.local->traffic.messages_sent++;
    388 
    389 	/* Previously we ran send_queued() here directly, but that is
    390 	 * a bad idea, CPU-wise. So now we just mark the client indicating
    391 	 * that there is data to send.
    392 	 */
    393 	if (IsControl(to))
    394 		send_queued(to); /* send this one ASAP */
    395 	else
    396 		mark_data_to_send(to);
    397 }
    398 
    399 /** A single function to send data to a channel.
    400  * Previously there were 6 different functions to send channel data,
    401  * now there is 1 single function. This also means that you most
    402  * likely will pass NULL or 0 as some parameters.
    403  * @param channel       The channel to send to
    404  * @param from          The source of the message
    405  * @param skip          The client to skip (can be NULL).
    406  *                      Note that if you specify a remote link then
    407  *                      you usually mean xyz->direction and not xyz.
    408  * @param member_modes  Require any of the member_modes to be set (eg: "o"), or NULL to skip this check.
    409  * @param clicap      Client capability the recipient should have
    410  *                    (this only works for local clients, we will
    411  *                     always send the message to remote clients and
    412  *                     assume the server there will handle it)
    413  * @param sendflags   Determines whether to send the message to local/remote users
    414  * @param mtags       The message tags to attach to this message
    415  * @param pattern     The pattern (eg: ":%s PRIVMSG %s :%s")
    416  * @param ...         The parameters for the pattern.
    417  * @note For all channel messages, it is important to attach the correct
    418  *       message tags (mtags) via a new_message() call, as can be seen
    419  *       in the example.
    420  * @section sendto_channel_examples Examples
    421  * @subsection sendto_channel_privmsg Send a PRIVMSG to a channel
    422  * This command will send the message "Hello everyone!!!" to the channel when executed.
    423  * @code
    424  * CMD_FUNC(cmd_sayhello)
    425  * {
    426  *     MessageTag *mtags = NULL;
    427  *     Channel *channel = NULL;
    428  *     if ((parc < 2) || BadPtr(parv[1]))
    429  *     {
    430  *         sendnumeric(client, ERR_NEEDMOREPARAMS, "SAYHELLO");
    431  *         return;
    432  *     }
    433  *     channel = find_channel(parv[1]);
    434  *     if (!channel)
    435  *     {
    436  *         sendnumeric(client, ERR_NOSUCHCHANNEL, parv[1]);
    437  *         return;
    438  *     }
    439  *     new_message(client, recv_mtags, &mtags);
    440  *     sendto_channel(channel, client, client->direction, NULL, 0,
    441  *                    SEND_LOCAL|SEND_REMOTE, mtags,
    442  *                    ":%s PRIVMSG %s :Hello everyone!!!",
    443  *                    client->name, channel->name);
    444  *     free_message_tags(mtags);
    445  * }
    446  * @endcode
    447  */
    448 void sendto_channel(Channel *channel, Client *from, Client *skip,
    449                     char *member_modes, long clicap, int sendflags,
    450                     MessageTag *mtags,
    451                     FORMAT_STRING(const char *pattern), ...)
    452 {
    453 	va_list vl;
    454 	Member *lp;
    455 	Client *acptr;
    456 	char member_modes_ext[64];
    457 
    458 	if (member_modes)
    459 	{
    460 		channel_member_modes_generate_equal_or_greater(member_modes, member_modes_ext, sizeof(member_modes_ext));
    461 		member_modes = member_modes_ext;
    462 	}
    463 
    464 	++current_serial;
    465 	for (lp = channel->members; lp; lp = lp->next)
    466 	{
    467 		acptr = lp->client;
    468 
    469 		/* Skip sending to 'skip' */
    470 		if ((acptr == skip) || (acptr->direction == skip))
    471 			continue;
    472 		/* Don't send to deaf clients (unless 'senddeaf' is set) */
    473 		if (IsDeaf(acptr) && (sendflags & SKIP_DEAF))
    474 			continue;
    475 		/* Don't send to NOCTCP clients */
    476 		if (has_user_mode(acptr, 'T') && (sendflags & SKIP_CTCP))
    477 			continue;
    478 		/* Now deal with 'member_modes' (if not NULL) */
    479 		if (member_modes && !check_channel_access_member(lp, member_modes))
    480 			continue;
    481 		/* Now deal with 'clicap' (if non-zero) */
    482 		if (clicap && MyUser(acptr) && ((clicap & CAP_INVERT) ? HasCapabilityFast(acptr, clicap) : !HasCapabilityFast(acptr, clicap)))
    483 			continue;
    484 
    485 		if (MyUser(acptr))
    486 		{
    487 			/* Local client */
    488 			if (sendflags & SEND_LOCAL)
    489 			{
    490 				va_start(vl, pattern);
    491 				vsendto_prefix_one(acptr, from, mtags, pattern, vl);
    492 				va_end(vl);
    493 			}
    494 		}
    495 		else
    496 		{
    497 			/* Remote client */
    498 			if (sendflags & SEND_REMOTE)
    499 			{
    500 				/* Message already sent to remote link? */
    501 				if (acptr->direction->local->serial != current_serial)
    502 				{
    503 					va_start(vl, pattern);
    504 					vsendto_prefix_one(acptr, from, mtags, pattern, vl);
    505 					va_end(vl);
    506 
    507 					acptr->direction->local->serial = current_serial;
    508 				}
    509 			}
    510 		}
    511 	}
    512 
    513 	if (sendflags & SEND_REMOTE)
    514 	{
    515 		/* For the remaining uplinks that we have not sent a message to yet...
    516 		 * broadcast-channel-messages=never: don't send it to them
    517 		 * broadcast-channel-messages=always: always send it to them
    518 		 * broadcast-channel-messages=auto: send it to them if the channel is set +H (history)
    519 		 */
    520 
    521 		if ((iConf.broadcast_channel_messages == BROADCAST_CHANNEL_MESSAGES_ALWAYS) ||
    522 		    ((iConf.broadcast_channel_messages == BROADCAST_CHANNEL_MESSAGES_AUTO) && has_channel_mode(channel, 'H')))
    523 		{
    524 			list_for_each_entry(acptr, &server_list, special_node)
    525 			{
    526 				if ((acptr == skip) || (acptr->direction == skip))
    527 					continue; /* still obey this rule.. */
    528 				if (acptr->direction->local->serial != current_serial)
    529 				{
    530 					va_start(vl, pattern);
    531 					vsendto_prefix_one(acptr, from, mtags, pattern, vl);
    532 					va_end(vl);
    533 
    534 					acptr->direction->local->serial = current_serial;
    535 				}
    536 			}
    537 		}
    538 	}
    539 }
    540 
    541 /** Send a message to a server, taking into account server options if needed.
    542  * @param one		The client to skip (can be NULL)
    543  * @param servercaps	Server capabilities which must be present (OR'd together, if multiple)
    544  * @param noservercaps	Server capabilities which must NOT be present (OR'd together, if multiple)
    545  * @param mtags		The message tags to attach to this message.
    546  * @param format	The format string / pattern, such as ":%s NICK %s".
    547  * @param ...		The parameters for the format string
    548  */
    549 void sendto_server(Client *one, unsigned long servercaps, unsigned long noservercaps, MessageTag *mtags, FORMAT_STRING(const char *format), ...)
    550 {
    551 	Client *acptr;
    552 
    553 	/* noone to send to.. */
    554 	if (list_empty(&server_list))
    555 		return;
    556 
    557 	list_for_each_entry(acptr, &server_list, special_node)
    558 	{
    559 		va_list vl;
    560 
    561 		if (one && acptr == one->direction)
    562 			continue;
    563 
    564 		if (servercaps && !CHECKSERVERPROTO(acptr, servercaps))
    565 			continue;
    566 
    567 		if (noservercaps && CHECKSERVERPROTO(acptr, noservercaps))
    568 			continue;
    569 
    570 		va_start(vl, format);
    571 		vsendto_one(acptr, mtags, format, vl);
    572 		va_end(vl);
    573 	}
    574 }
    575 
    576 /** Send a message to all local users on all channels where
    577  * the user 'user' is on.
    578  * This is used for events such as a nick change and quit.
    579  * @param user        The user and source of the message.
    580  * @param skip        The client to skip (can be NULL)
    581  * @param clicap      Client capability the recipient should have
    582  *                    (this only works for local clients, we will
    583  *                     always send the message to remote clients and
    584  *                     assume the server there will handle it)
    585  * @param mtags       The message tags to attach to this message.
    586  * @param pattern     The pattern (eg: ":%s NICK %s").
    587  * @param ...         The parameters for the pattern.
    588  */
    589 void sendto_local_common_channels(Client *user, Client *skip, long clicap, MessageTag *mtags, FORMAT_STRING(const char *pattern), ...)
    590 {
    591 	va_list vl;
    592 	Membership *channels;
    593 	Member *users;
    594 	Client *acptr;
    595 
    596 	/* We now create the buffer _before_ we send it to the clients. -- Syzop */
    597 	*sendbuf = '\0';
    598 	va_start(vl, pattern);
    599 	vmakebuf_local_withprefix(sendbuf, sizeof sendbuf, user, pattern, vl);
    600 	va_end(vl);
    601 
    602 	++current_serial;
    603 
    604 	if (user->user)
    605 	{
    606 		for (channels = user->user->channel; channels; channels = channels->next)
    607 		{
    608 			for (users = channels->channel->members; users; users = users->next)
    609 			{
    610 				acptr = users->client;
    611 
    612 				if (!MyConnect(acptr))
    613 					continue; /* only process local clients */
    614 
    615 				if (acptr->local->serial == current_serial)
    616 					continue; /* message already sent to this client */
    617 
    618 				if (clicap && ((clicap & CAP_INVERT) ? HasCapabilityFast(acptr, clicap) : !HasCapabilityFast(acptr, clicap)))
    619 					continue; /* client does not have the specified capability */
    620 
    621 				if (acptr == skip)
    622 					continue; /* the one to skip */
    623 
    624 				if (!user_can_see_member(acptr, user, channels->channel))
    625 					continue; /* the sending user (quit'ing or nick changing) is 'invisible' -- skip */
    626 
    627 				acptr->local->serial = current_serial;
    628 				sendto_one(acptr, mtags, "%s", sendbuf);
    629 			}
    630 		}
    631 	}
    632 }
    633 
    634 /** Send a QUIT message to all local users on all channels where
    635  * the user 'user' is on.
    636  * This is used for events such as a nick change and quit.
    637  * @param user        The user and source of the message.
    638  * @param skip        The client to skip (can be NULL)
    639  * @param clicap      Client capability the recipient should have
    640  *                    (this only works for local clients, we will
    641  *                     always send the message to remote clients and
    642  *                     assume the server there will handle it)
    643  * @param mtags       The message tags to attach to this message.
    644  * @param pattern     The pattern (eg: ":%s NICK %s").
    645  * @param ...         The parameters for the pattern.
    646  */
    647 void quit_sendto_local_common_channels(Client *user, MessageTag *mtags, const char *reason)
    648 {
    649 	va_list vl;
    650 	Membership *channels;
    651 	Member *users;
    652 	Client *acptr;
    653 	char sender[512];
    654 	MessageTag *m;
    655 	const char *real_quit_reason = NULL;
    656 
    657 	m = find_mtag(mtags, "unrealircd.org/real-quit-reason");
    658 	if (m && m->value)
    659 		real_quit_reason = m->value;
    660 
    661 	if (IsUser(user))
    662 	{
    663 		snprintf(sender, sizeof(sender), "%s!%s@%s",
    664 		         user->name, user->user->username, GetHost(user));
    665 	} else {
    666 		strlcpy(sender, user->name, sizeof(sender));
    667 	}
    668 
    669 	++current_serial;
    670 
    671 	if (user->user)
    672 	{
    673 		for (channels = user->user->channel; channels; channels = channels->next)
    674 		{
    675 			for (users = channels->channel->members; users; users = users->next)
    676 			{
    677 				acptr = users->client;
    678 
    679 				if (!MyConnect(acptr))
    680 					continue; /* only process local clients */
    681 
    682 				if (acptr->local->serial == current_serial)
    683 					continue; /* message already sent to this client */
    684 
    685 				if (!user_can_see_member(acptr, user, channels->channel))
    686 					continue; /* the sending user (QUITing) is 'invisible' -- skip */
    687 
    688 				acptr->local->serial = current_serial;
    689 				if (!reason)
    690 					sendto_one(acptr, mtags, ":%s QUIT", sender);
    691 				else if (!IsOper(acptr) || !real_quit_reason)
    692 					sendto_one(acptr, mtags, ":%s QUIT :%s", sender, reason);
    693 				else
    694 					sendto_one(acptr, mtags, ":%s QUIT :%s", sender, real_quit_reason);
    695 			}
    696 		}
    697 	}
    698 }
    699 
    700 /*
    701 ** send a msg to all ppl on servers/hosts that match a specified mask
    702 ** (used for enhanced PRIVMSGs)
    703 **
    704 ** addition -- Armin, 8jun90 (gruner@informatik.tu-muenchen.de)
    705 */
    706 
    707 static int match_it(Client *one, const char *mask, int what)
    708 {
    709 	switch (what)
    710 	{
    711 		case MATCH_HOST:
    712 			return match_simple(mask, one->user->realhost);
    713 		case MATCH_SERVER:
    714 		default:
    715 			return match_simple(mask, one->user->server);
    716 	}
    717 }
    718 
    719 /** Send to all clients which match the mask.
    720  * This function is rarely used.
    721  * @param one		The client to skip
    722  * @param from		The sender
    723  * @param mask		The mask
    724  * @param what		One of MATCH_HOST or MATCH_SERVER
    725  * @param mtags		Message tags associated with the message
    726  * @param pattern	Format string
    727  * @param ...		Parameters to the format string
    728  */
    729 void sendto_match_butone(Client *one, Client *from, const char *mask, int what,
    730                          MessageTag *mtags, FORMAT_STRING(const char *pattern), ...)
    731 {
    732 	va_list vl;
    733 	Client *acptr;
    734 	char cansendlocal, cansendglobal;
    735 
    736 	if (MyConnect(from))
    737 	{
    738 		cansendlocal = (ValidatePermissionsForPath("chat:notice:local",from,NULL,NULL,NULL)) ? 1 : 0;
    739 		cansendglobal = (ValidatePermissionsForPath("chat:notice:global",from,NULL,NULL,NULL)) ? 1 : 0;
    740 	}
    741 	else
    742 		cansendlocal = cansendglobal = 1;
    743 
    744 	/* To servers... */
    745 	if (cansendglobal)
    746 	{
    747 		char buf[512];
    748 
    749 		va_start(vl, pattern);
    750 		ircvsnprintf(buf, sizeof(buf), pattern, vl);
    751 		va_end(vl);
    752 
    753 		sendto_server(one, 0, 0, mtags, "%s", buf);
    754 	}
    755 
    756 	/* To local clients... */
    757 	if (cansendlocal)
    758 	{
    759 		list_for_each_entry(acptr, &lclient_list, lclient_node)
    760 		{
    761 			if (!IsMe(acptr) && (acptr != one) && IsUser(acptr) && match_it(acptr, mask, what))
    762 			{
    763 				va_start(vl, pattern);
    764 				vsendto_prefix_one(acptr, from, mtags, pattern, vl);
    765 				va_end(vl);
    766 			}
    767 		}
    768 	}
    769 }
    770 
    771 /** Send a message to all locally connected users with specified user mode.
    772  * @param umodes	The umode that the recipient should have set (one of UMODE_)
    773  * @param pattern	The format string / pattern to use.
    774  * @param ...		Format string parameters.
    775  */
    776 void sendto_umode(int umodes, FORMAT_STRING(const char *pattern), ...)
    777 {
    778 	va_list vl;
    779 	Client *acptr;
    780 	char nbuf[1024];
    781 
    782 	list_for_each_entry(acptr, &lclient_list, lclient_node)
    783 		if (IsUser(acptr) && (acptr->umodes & umodes) == umodes)
    784 		{
    785 			ircsnprintf(nbuf, sizeof(nbuf), ":%s NOTICE %s :", me.name, acptr->name);
    786 			strlcat(nbuf, pattern, sizeof nbuf);
    787 
    788 			va_start(vl, pattern);
    789 			vsendto_one(acptr, NULL, nbuf, vl);
    790 			va_end(vl);
    791 		}
    792 }
    793 
    794 /** Send a message to all users with specified user mode (local & remote users).
    795  * @param umodes	The umode that the recipient should have set (one of UMODE_*)
    796  * @param pattern	The format string / pattern to use.
    797  * @param ...		Format string parameters.
    798  */
    799 void sendto_umode_global(int umodes, FORMAT_STRING(const char *pattern), ...)
    800 {
    801 	va_list vl;
    802 	Client *acptr;
    803 	Umode *um;
    804 	char nbuf[1024];
    805 	char modestr[128];
    806 	char *p;
    807 
    808 	/* Convert 'umodes' (int) to 'modestr' (string) */
    809 	get_usermode_string_raw_r(umodes, modestr, sizeof(modestr));
    810 
    811 	list_for_each_entry(acptr, &lclient_list, lclient_node)
    812 	{
    813 		if (IsUser(acptr) && (acptr->umodes & umodes) == umodes)
    814 		{
    815 			ircsnprintf(nbuf, sizeof(nbuf), ":%s NOTICE %s :", me.name, acptr->name);
    816 			strlcat(nbuf, pattern, sizeof nbuf);
    817 
    818 			va_start(vl, pattern);
    819 			vsendto_one(acptr, NULL, nbuf, vl);
    820 			va_end(vl);
    821 		} else
    822 		if (IsServer(acptr) && *modestr)
    823 		{
    824 			snprintf(nbuf, sizeof(nbuf), ":%s SENDUMODE %s :%s", me.id, modestr, pattern);
    825 			va_start(vl, pattern);
    826 			vsendto_one(acptr, NULL, nbuf, vl);
    827 			va_end(vl);
    828 		}
    829 	}
    830 }
    831 
    832 /** Send CAP DEL and CAP NEW notification to clients supporting it.
    833  * This function is mostly meant to be used by the CAP and SASL modules.
    834  * @param add		Whether the CAP token is added (1) or removed (0)
    835  * @param token		The CAP token
    836  */
    837 void send_cap_notify(int add, const char *token)
    838 {
    839 	Client *client;
    840 	ClientCapability *clicap = ClientCapabilityFindReal(token);
    841 	long CAP_NOTIFY = ClientCapabilityBit("cap-notify");
    842 
    843 	list_for_each_entry(client, &lclient_list, lclient_node)
    844 	{
    845 		if (HasCapabilityFast(client, CAP_NOTIFY))
    846 		{
    847 			if (add)
    848 			{
    849 				const char *args = NULL;
    850 				if (clicap)
    851 				{
    852 					if (clicap->visible && !clicap->visible(client))
    853 						continue; /* invisible CAP, so don't announce it */
    854 					if (clicap->parameter && (client->local->cap_protocol >= 302))
    855 						args = clicap->parameter(client);
    856 				}
    857 				if (!args)
    858 				{
    859 					sendto_one(client, NULL, ":%s CAP %s NEW :%s",
    860 						me.name, (*client->name ? client->name : "*"), token);
    861 				} else {
    862 					sendto_one(client, NULL, ":%s CAP %s NEW :%s=%s",
    863 						me.name, (*client->name ? client->name : "*"), token, args);
    864 				}
    865 			} else {
    866 				sendto_one(client, NULL, ":%s CAP %s DEL :%s",
    867 					me.name, (*client->name ? client->name : "*"), token);
    868 			}
    869 		}
    870 	}
    871 }
    872 
    873 /* Prepare buffer based on format string and 'from' for LOCAL delivery.
    874  * The prefix (:<something>) will be expanded to :nick!user@host if 'from'
    875  * is a person, taking into account the rules for hidden/cloaked host.
    876  * NOTE: Do not send this prepared buffer to remote clients or servers,
    877  *       they do not want or need the expanded prefix. In that case, simply
    878  *       use ircvsnprintf() directly.
    879  */
    880 static int vmakebuf_local_withprefix(char *buf, size_t buflen, Client *from, const char *pattern, va_list vl)
    881 {
    882 	int len;
    883 
    884 	/* This expands the ":%s " part of the pattern
    885 	 * into ":nick!user@host ".
    886 	 * In case of a non-person (server) it doesn't do
    887 	 * anything since no expansion is needed.
    888 	 */
    889 	if (from && from->user && !strncmp(pattern, ":%s ", 4))
    890 	{
    891 		va_arg(vl, char *); /* eat first parameter */
    892 
    893 		*buf = ':';
    894 		strlcpy(buf+1, from->name, buflen-1);
    895 
    896 		if (IsUser(from))
    897 		{
    898 			char *username = from->user->username;
    899 			char *host = GetHost(from);
    900 
    901 			if (*username)
    902 			{
    903 				strlcat(buf, "!", buflen);
    904 				strlcat(buf, username, buflen);
    905 			}
    906 			if (*host)
    907 			{
    908 				strlcat(buf, "@", buflen);
    909 				strlcat(buf, host, buflen);
    910 			}
    911 		}
    912 		/* Now build the remaining string */
    913 #if defined(__GNUC__)
    914 #pragma GCC diagnostic push
    915 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
    916 #endif
    917 		ircvsnprintf(buf + strlen(buf), buflen - strlen(buf), &pattern[3], vl);
    918 #if defined(__GNUC__)
    919 #pragma GCC diagnostic pop
    920 #endif
    921 	}
    922 	else
    923 	{
    924 		ircvsnprintf(buf, buflen, pattern, vl);
    925 	}
    926 
    927 	len = strlen(buf);
    928 	ADD_CRLF(buf, len);
    929 	return len;
    930 }
    931 
    932 /** Send a message to a client, expand the sender prefix.
    933  * This is similar to sendto_one() except that it will expand the source part :%s
    934  * to :nick!user@host if needed, while with sendto_one() it will be :nick.
    935  * @param to		The client to send to
    936  * @param mtags		Any message tags associated with this message (can be NULL)
    937  * @param pattern	The format string / pattern to use.
    938  * @param ...		Format string parameters.
    939  */
    940 void sendto_prefix_one(Client *to, Client *from, MessageTag *mtags, FORMAT_STRING(const char *pattern), ...)
    941 {
    942 	va_list vl;
    943 	va_start(vl, pattern);
    944 	vsendto_prefix_one(to, from, mtags, pattern, vl);
    945 	va_end(vl);
    946 }
    947 
    948 /** Send a message to a single client, expand the sender prefix - va_list variant.
    949  * This is similar to vsendto_one() except that it will expand the source part :%s
    950  * to :nick!user@host if needed, while with sendto_one() it will be :nick.
    951  * This function is also similar to sendto_prefix_one(), but this is the va_list
    952  * variant.
    953  * @param to		The client to send to
    954  * @param mtags		Any message tags associated with this message (can be NULL)
    955  * @param pattern	The format string / pattern to use.
    956  * @param ...		Format string parameters.
    957  */
    958 void vsendto_prefix_one(Client *to, Client *from, MessageTag *mtags, const char *pattern, va_list vl)
    959 {
    960 	const char *mtags_str = mtags ? mtags_to_string(mtags, to) : NULL;
    961 
    962 	if (to && from && MyUser(to) && from->user)
    963 		vmakebuf_local_withprefix(sendbuf, sizeof(sendbuf)-3, from, pattern, vl);
    964 	else
    965 		ircvsnprintf(sendbuf, sizeof(sendbuf)-3, pattern, vl);
    966 
    967 	if (BadPtr(mtags_str))
    968 	{
    969 		/* Simple message without message tags */
    970 		sendbufto_one(to, sendbuf, 0);
    971 	} else {
    972 		/* Message tags need to be prepended */
    973 		snprintf(sendbuf2, sizeof(sendbuf2)-3, "@%s %s", mtags_str, sendbuf);
    974 		sendbufto_one(to, sendbuf2, 0);
    975 	}
    976 }
    977 
    978 /** Introduce user to all other servers, except the one to skip.
    979  * @param one    Server to skip (can be NULL)
    980  * @param client Client to introduce
    981  * @param umodes User modes of client
    982  */
    983 void sendto_serv_butone_nickcmd(Client *one, MessageTag *mtags, Client *client, const char *umodes)
    984 {
    985 	Client *acptr;
    986 
    987 	list_for_each_entry(acptr, &server_list, special_node)
    988 	{
    989 		if (one && acptr == one->direction)
    990 			continue;
    991 		
    992 		sendto_one_nickcmd(acptr, mtags, client, umodes);
    993 	}
    994 }
    995 
    996 /** Introduce user to a server.
    997  * @param server  Server to send to (locally connected!)
    998  * @param client  Client to introduce
    999  * @param umodes  User modes of client
   1000  */
   1001 void sendto_one_nickcmd(Client *server, MessageTag *mtags, Client *client, const char *umodes)
   1002 {
   1003 	char *vhost;
   1004 	char mtags_generated = 0;
   1005 
   1006 	if (!*umodes)
   1007 		umodes = "+";
   1008 
   1009 	if (SupportVHP(server))
   1010 	{
   1011 		if (IsHidden(client))
   1012 			vhost = client->user->virthost;
   1013 		else
   1014 			vhost = client->user->realhost;
   1015 	}
   1016 	else
   1017 	{
   1018 		if (IsHidden(client) && client->umodes & UMODE_SETHOST)
   1019 			vhost = client->user->virthost;
   1020 		else
   1021 			vhost = "*";
   1022 	}
   1023 
   1024 	if (mtags == NULL)
   1025 	{
   1026 		moddata_add_s2s_mtags(client, &mtags);
   1027 		mtags_generated = 1;
   1028 	}
   1029 
   1030 	sendto_one(server, mtags,
   1031 		":%s UID %s %d %lld %s %s %s %s %s %s %s %s :%s",
   1032 		client->uplink->id, client->name, client->hopcount,
   1033 		(long long)client->lastnick,
   1034 		client->user->username, client->user->realhost, client->id,
   1035 		client->user->account, umodes, vhost, getcloak(client),
   1036 		encode_ip(client->ip), client->info);
   1037 
   1038 	if (mtags_generated)
   1039 		safe_free_message_tags(mtags);
   1040 }
   1041 
   1042 /* sidenote: sendnotice() and sendtxtnumeric() assume no client or server
   1043  * has a % in their nick, which is a safe assumption since % is illegal.
   1044  */
   1045  
   1046 /** Send a server notice to a client.
   1047  * @param to		The client to send to
   1048  * @param pattern	The format string / pattern to use.
   1049  * @param ...		Format string parameters.
   1050  */
   1051 void sendnotice(Client *to, FORMAT_STRING(const char *pattern), ...)
   1052 {
   1053 	static char realpattern[1024];
   1054 	va_list vl;
   1055 	char *name = *to->name ? to->name : "*";
   1056 
   1057 	ircsnprintf(realpattern, sizeof(realpattern), ":%s NOTICE %s :%s", me.name, name, pattern);
   1058 
   1059 	va_start(vl, pattern);
   1060 	vsendto_one(to, NULL, realpattern, vl);
   1061 	va_end(vl);
   1062 }
   1063 
   1064 /** Send MultiLine list as a notice, one for each line.
   1065  * @param client	The client to send to
   1066  * @param m		The MultiLine list.
   1067  */
   1068 void sendnotice_multiline(Client *client, MultiLine *m)
   1069 {
   1070 	for (; m; m = m->next)
   1071 		sendnotice(client, "%s", m->line);
   1072 }
   1073 
   1074 /** Send numeric message to a client - format to user specific needs.
   1075  * This will ignore the numeric definition of src/numeric.c and always send ":me.name numeric clientname "
   1076  * followed by the pattern and format string you choose.
   1077  * @param to		The recipient
   1078  * @param mtags     NULL, or NULL-terminated array of message tags
   1079  * @param numeric	The numeric, one of RPL_* or ERR_*, see src/numeric.c
   1080  * @param pattern	The format string / pattern to use.
   1081  * @param ...		Format string parameters.
   1082  * @note Don't forget to add a colon if you need it (eg `:%%s`), this is a common mistake.
   1083  */
   1084 void sendtaggednumericfmt(Client *to, MessageTag *mtags, int numeric, FORMAT_STRING(const char *pattern), ...)
   1085 {
   1086 	va_list vl;
   1087 	char realpattern[512];
   1088 
   1089 	snprintf(realpattern, sizeof(realpattern), ":%s %.3d %s %s", me.name, numeric, to->name[0] ? to->name : "*", pattern);
   1090 
   1091 	va_start(vl, pattern);
   1092 	vsendto_one(to, mtags, realpattern, vl);
   1093 	va_end(vl);
   1094 }
   1095 
   1096 /** Send text numeric message to a client (RPL_TEXT).
   1097  * Because this generic output numeric is commonly used it got a special function for it.
   1098  * @param to		The recipient
   1099  * @param numeric	The numeric, one of RPL_* or ERR_*, see src/numeric.c
   1100  * @param pattern	The format string / pattern to use.
   1101  * @param ...		Format string parameters.
   1102  * @note Don't forget to add a colon if you need it (eg `:%%s`), this is a common mistake.
   1103  */
   1104 void sendtxtnumeric(Client *to, FORMAT_STRING(const char *pattern), ...)
   1105 {
   1106 	static char realpattern[1024];
   1107 	va_list vl;
   1108 
   1109 	ircsnprintf(realpattern, sizeof(realpattern), ":%s %d %s :%s", me.name, RPL_TEXT, to->name, pattern);
   1110 
   1111 	va_start(vl, pattern);
   1112 	vsendto_one(to, NULL, realpattern, vl);
   1113 	va_end(vl);
   1114 }
   1115 
   1116 /** Build buffer in order to send a numeric message to a client - rarely used.
   1117  * @param buf		The buffer that should be used
   1118  * @param buflen	The size of the buffer
   1119  * @param to		The recipient
   1120  * @param numeric	The numeric, one of RPL_* or ERR_*, see src/numeric.c
   1121  * @param pattern	The format string / pattern to use.
   1122  * @param ...		Format string parameters.
   1123  */
   1124 void buildnumericfmt(char *buf, size_t buflen, Client *to, int numeric, FORMAT_STRING(const char *pattern), ...)
   1125 {
   1126 	va_list vl;
   1127 	char realpattern[512];
   1128 
   1129 	snprintf(realpattern, sizeof(realpattern), ":%s %.3d %s %s", me.name, numeric, to->name[0] ? to->name : "*", pattern);
   1130 
   1131 	va_start(vl, pattern);
   1132 	/* Need to ignore -Wformat-nonliteral here */
   1133 #if defined(__GNUC__)
   1134 #pragma GCC diagnostic push
   1135 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
   1136 #endif
   1137 	vsnprintf(buf, buflen, realpattern, vl);
   1138 #if defined(__GNUC__)
   1139 #pragma GCC diagnostic pop
   1140 #endif
   1141 	va_end(vl);
   1142 }
   1143 
   1144 void add_nvplist_numeric_fmt(NameValuePrioList **lst, int priority, const char *name, Client *to, int numeric, FORMAT_STRING(const char *pattern), ...)
   1145 {
   1146 	va_list vl;
   1147 	char realpattern[512], buf[512];
   1148 
   1149 	snprintf(realpattern, sizeof(realpattern), ":%s %.3d %s %s", me.name, numeric, to->name[0] ? to->name : "*", pattern);
   1150 
   1151 	va_start(vl, pattern);
   1152 	/* Need to ignore -Wformat-nonliteral here */
   1153 #if defined(__GNUC__)
   1154 #pragma GCC diagnostic push
   1155 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
   1156 #endif
   1157 	vsnprintf(buf, sizeof(buf), realpattern, vl);
   1158 #if defined(__GNUC__)
   1159 #pragma GCC diagnostic pop
   1160 #endif
   1161 	va_end(vl);
   1162 
   1163 	add_nvplist(lst, priority, name, buf);
   1164 }
   1165 
   1166 /* Send raw data directly to socket, bypassing everything.
   1167  * Looks like an interesting function to call? NO! STOP!
   1168  * Don't use this function. It may only be used by the initial
   1169  * Z-Line check via the codepath to banned_client().
   1170  * YOU SHOULD NEVER USE THIS FUNCTION.
   1171  * If you want to send raw data (without formatting) to a client
   1172  * then have a look at sendbufto_one() instead.
   1173  *
   1174  * Side-effects:
   1175  * Too many to list here. Only in the early accept code the
   1176  * "if's" and side-effects are under control.
   1177  *
   1178  * By the way, did I already mention that you SHOULD NOT USE THIS
   1179  * FUNCTION? ;)
   1180  */
   1181 void send_raw_direct(Client *user, FORMAT_STRING(const char *pattern), ...)
   1182 {
   1183 	va_list vl;
   1184 	int sendlen;
   1185 
   1186 	*sendbuf = '\0';
   1187 	va_start(vl, pattern);
   1188 	sendlen = vmakebuf_local_withprefix(sendbuf, sizeof(sendbuf), user, pattern, vl);
   1189 	va_end(vl);
   1190 	(void)send(user->local->fd, sendbuf, sendlen, 0);
   1191 }
   1192 
   1193 /** @} */