1 /*
2  *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3  *
4  *  Copyright (c) 1997-2021 ircd-hybrid development team
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 2 of the License, or
9  *  (at your option) 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19  *  USA
20  */
21 
22 /*! \file send.c
23  * \brief Functions for sending messages.
24  * \version $Id: send.c 9858 2021-01-01 04:43:42Z michael $
25  */
26 
27 #include "stdinc.h"
28 #include "list.h"
29 #include "send.h"
30 #include "channel.h"
31 #include "client.h"
32 #include "dbuf.h"
33 #include "irc_string.h"
34 #include "ircd.h"
35 #include "s_bsd.h"
36 #include "server_capab.h"
37 #include "conf_class.h"
38 #include "log.h"
39 
40 
41 static uintmax_t current_serial;
42 
43 
44 /* send_format()
45  *
46  * inputs
47  *		- buffer
48  *		- format pattern to use
49  *		- var args
50  * output	- number of bytes formatted output
51  * side effects	- modifies sendbuf
52  */
53 static void
send_format(struct dbuf_block * buffer,const char * pattern,va_list args)54 send_format(struct dbuf_block *buffer, const char *pattern, va_list args)
55 {
56   /*
57    * from rfc1459
58    *
59    * IRC messages are always lines of characters terminated with a CR-LF
60    * (Carriage Return - Line Feed) pair, and these messages shall not
61    * exceed 512 characters in length,  counting all characters
62    * including the trailing CR-LF.
63    * Thus, there are 510 characters maximum allowed
64    * for the command and its parameters.  There is no provision for
65    * continuation message lines.  See section 7 for more details about
66    * current implementations.
67    */
68   dbuf_put_args(buffer, pattern, args);
69 
70   if (buffer->size > IRCD_BUFSIZE - 2)
71     buffer->size = IRCD_BUFSIZE - 2;
72 
73   buffer->data[buffer->size++] = '\r';
74   buffer->data[buffer->size++] = '\n';
75 }
76 
77 /*
78  ** send_message
79  **      Internal utility which appends given buffer to the sockets
80  **      sendq.
81  */
82 static void
send_message(struct Client * to,struct dbuf_block * buffer)83 send_message(struct Client *to, struct dbuf_block *buffer)
84 {
85   assert(!IsMe(to));
86   assert(to != &me);
87   assert(MyConnect(to));
88 
89   if (dbuf_length(&to->connection->buf_sendq) + buffer->size > get_sendq(&to->connection->confs))
90   {
91     if (IsServer(to))
92       sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
93                            "Max SendQ limit exceeded for %s: %zu > %u",
94                            client_get_name(to, HIDE_IP),
95                            (dbuf_length(&to->connection->buf_sendq) + buffer->size),
96                            get_sendq(&to->connection->confs));
97 
98     if (IsClient(to))
99       AddFlag(to, FLAGS_SENDQEX);
100 
101     dead_link_on_write(to, 0);
102     return;
103   }
104 
105   dbuf_add(&to->connection->buf_sendq, buffer);
106 
107   /*
108    * Update statistics. The following is slightly incorrect because
109    * it counts messages even if queued, but bytes only really sent.
110    * Queued bytes get updated in send_queued_write().
111    */
112   ++to->connection->send.messages;
113   ++me.connection->send.messages;
114 
115   send_queued_write(to);
116 }
117 
118 /* send_message_remote()
119  *
120  * inputs	- pointer to client from message is being sent
121  * 		- pointer to client to send to
122  *		- pointer to buffer
123  * output	- none
124  * side effects	- Despite the function name, this only sends to directly
125  *		  connected clients.
126  *
127  */
128 static void
send_message_remote(struct Client * to,const struct Client * from,struct dbuf_block * buffer)129 send_message_remote(struct Client *to, const struct Client *from, struct dbuf_block *buffer)
130 {
131   assert(MyConnect(to));
132   assert(IsServer(to));
133   assert(!IsMe(to));
134   assert(to->from == to);
135 
136   if (to == from->from)
137     sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE, "Send message to %s dropped from %s (Fake Dir)",
138                          to->name, from->name);
139   else
140     send_message(to, buffer);
141 }
142 
143 /*
144  ** sendq_unblocked
145  **      Called when a socket is ready for writing.
146  */
147 void
sendq_unblocked(fde_t * F,void * data)148 sendq_unblocked(fde_t *F, void *data)
149 {
150   struct Client *const client = data;
151 
152   assert(client);
153   assert(client->connection);
154   assert(client->connection->fd);
155   assert(client->connection->fd == F);
156 
157   DelFlag(client, FLAGS_BLOCKED);
158   send_queued_write(client);
159 }
160 
161 /*
162  ** send_queued_write
163  **      This is called when there is a chance that some output would
164  **      be possible. This attempts to empty the send queue as far as
165  **      possible, and then if any data is left, a write is rescheduled.
166  */
167 void
send_queued_write(struct Client * to)168 send_queued_write(struct Client *to)
169 {
170   ssize_t retlen;
171 
172   /*
173    * Once socket is marked dead, we cannot start writing to it,
174    * even if the error is removed...
175    */
176   if (IsDead(to) || HasFlag(to, FLAGS_BLOCKED))
177     return;  /* no use calling send() now */
178 
179   /* Next, lets try to write some data */
180   while (dbuf_length(&to->connection->buf_sendq))
181   {
182     bool want_read = false;
183     const struct dbuf_block *first = to->connection->buf_sendq.blocks.head->data;
184 
185     if (tls_isusing(&to->connection->fd->tls))
186     {
187       retlen = tls_write(&to->connection->fd->tls, first->data + to->connection->buf_sendq.pos,
188                                                    first->size - to->connection->buf_sendq.pos, &want_read);
189 
190       if (want_read == true)
191         return;  /* Retry later, don't register for write events */
192     }
193     else
194       retlen = send(to->connection->fd->fd, first->data + to->connection->buf_sendq.pos,
195                                             first->size - to->connection->buf_sendq.pos, 0);
196 
197     if (retlen <= 0)
198     {
199       if (retlen < 0 && comm_ignore_errno(errno) == true)
200       {
201         AddFlag(to, FLAGS_BLOCKED);
202         /* We have a non-fatal error, reschedule a write */
203         comm_setselect(to->connection->fd, COMM_SELECT_WRITE, sendq_unblocked, to, 0);
204       }
205       else
206         dead_link_on_write(to, errno);
207       return;
208     }
209 
210     dbuf_delete(&to->connection->buf_sendq, retlen);
211 
212     /* We have some data written .. update counters */
213     to->connection->send.bytes += retlen;
214     me.connection->send.bytes += retlen;
215   }
216 }
217 
218 /* sendto_one()
219  *
220  * inputs	- pointer to destination client
221  *		- var args message
222  * output	- NONE
223  * side effects	- send message to single client
224  */
225 void
sendto_one(struct Client * to,const char * pattern,...)226 sendto_one(struct Client *to, const char *pattern, ...)
227 {
228   va_list args;
229 
230   if (IsDead(to->from))
231     return;  /* This socket has already been marked as dead */
232 
233   va_start(args, pattern);
234 
235   struct dbuf_block *buffer = dbuf_alloc();
236   send_format(buffer, pattern, args);
237 
238   va_end(args);
239 
240   send_message(to->from, buffer);
241 
242   dbuf_ref_free(buffer);
243 }
244 
245 void
sendto_one_numeric(struct Client * to,const struct Client * from,enum irc_numerics numeric,...)246 sendto_one_numeric(struct Client *to, const struct Client *from, enum irc_numerics numeric, ...)
247 {
248   va_list args;
249 
250   if (IsDead(to->from))
251     return;  /* This socket has already been marked as dead */
252 
253   const char *dest = ID_or_name(to, to);
254   if (EmptyString(dest))
255     dest = "*";
256 
257   struct dbuf_block *buffer = dbuf_alloc();
258   dbuf_put_fmt(buffer, ":%s %03d %s ", ID_or_name(from, to), numeric & ~SND_EXPLICIT, dest);
259 
260   va_start(args, numeric);
261 
262   const char *numstr;
263   if (numeric & SND_EXPLICIT)
264     numstr = va_arg(args, const char *);
265   else
266     numstr = numeric_form(numeric);
267 
268   send_format(buffer, numstr, args);
269   va_end(args);
270 
271   send_message(to->from, buffer);
272 
273   dbuf_ref_free(buffer);
274 }
275 
276 void
sendto_one_notice(struct Client * to,const struct Client * from,const char * pattern,...)277 sendto_one_notice(struct Client *to, const struct Client *from, const char *pattern, ...)
278 {
279   va_list args;
280 
281   if (IsDead(to->from))
282     return;  /* This socket has already been marked as dead */
283 
284   const char *dest = ID_or_name(to, to);
285   if (EmptyString(dest))
286     dest = "*";
287 
288   struct dbuf_block *buffer = dbuf_alloc();
289   dbuf_put_fmt(buffer, ":%s NOTICE %s ", ID_or_name(from, to), dest);
290 
291   va_start(args, pattern);
292   send_format(buffer, pattern, args);
293   va_end(args);
294 
295   send_message(to->from, buffer);
296 
297   dbuf_ref_free(buffer);
298 }
299 
300 /* sendto_channel_butone()
301  *
302  * inputs	- pointer to client(server) to NOT send message to
303  *		- pointer to client that is sending this message
304  *		- pointer to channel being sent to
305  *		- vargs message
306  * output	- NONE
307  * side effects	- message as given is sent to given channel members.
308  *
309  * WARNING - +D clients are ignored
310  */
311 void
sendto_channel_butone(struct Client * one,const struct Client * from,struct Channel * channel,unsigned int type,const char * pattern,...)312 sendto_channel_butone(struct Client *one, const struct Client *from,
313                       struct Channel *channel, unsigned int type,
314                       const char *pattern, ...)
315 {
316   va_list args_l, args_r;
317   dlink_node *node;
318   struct dbuf_block *buffer_l = dbuf_alloc();
319   struct dbuf_block *buffer_r = dbuf_alloc();
320 
321   if (IsClient(from))
322     dbuf_put_fmt(buffer_l, ":%s!%s@%s ", from->name, from->username, from->host);
323   else
324     dbuf_put_fmt(buffer_l, ":%s ", from->name);
325 
326   dbuf_put_fmt(buffer_r, ":%s ", from->id);
327 
328   va_start(args_l, pattern);
329   va_start(args_r, pattern);
330   send_format(buffer_l, pattern, args_l);
331   send_format(buffer_r, pattern, args_r);
332   va_end(args_l);
333   va_end(args_r);
334 
335   ++current_serial;
336 
337   DLINK_FOREACH(node, channel->members.head)
338   {
339     struct ChannelMember *member = node->data;
340     struct Client *target = member->client;
341 
342     assert(IsClient(target));
343 
344     if (IsDead(target->from))
345       continue;
346 
347     if (one && (target->from == one->from))
348       continue;
349 
350     if (type && (member->flags & type) == 0)
351       continue;
352 
353     if (HasUMode(target, UMODE_DEAF))
354       continue;
355 
356     if (MyConnect(target))
357       send_message(target, buffer_l);
358     else if (target->from->connection->serial != current_serial)
359       send_message_remote(target->from, from, buffer_r);
360 
361     target->from->connection->serial = current_serial;
362   }
363 
364   dbuf_ref_free(buffer_l);
365   dbuf_ref_free(buffer_r);
366 }
367 
368 /* sendto_server()
369  *
370  * inputs       - pointer to client to NOT send to
371  *              - pointer to channel
372  *              - capabs or'd together which must ALL be present
373  *              - capabs or'd together which must ALL NOT be present
374  *              - printf style format string
375  *              - args to format string
376  * output       - NONE
377  * side effects - Send a message to all connected servers, except the
378  *                client 'one' (if non-NULL), as long as the servers
379  *                support ALL capabs in 'capab', and NO capabs in 'nocapab'.
380  *
381  * This function was written in an attempt to merge together the other
382  * billion sendto_*serv*() functions, which sprung up with capabs,
383  * lazylinks, uids, etc.
384  * -davidt
385  */
386 void
sendto_server(const struct Client * one,const unsigned int capab,const unsigned int nocapab,const char * format,...)387 sendto_server(const struct Client *one,
388               const unsigned int capab,
389               const unsigned int nocapab,
390               const char *format, ...)
391 {
392   va_list args;
393   dlink_node *node;
394   struct dbuf_block *buffer = dbuf_alloc();
395 
396   va_start(args, format);
397   send_format(buffer, format, args);
398   va_end(args);
399 
400   DLINK_FOREACH(node, local_server_list.head)
401   {
402     struct Client *client = node->data;
403 
404     /* If dead already skip */
405     if (IsDead(client))
406       continue;
407 
408     /* check against 'one' */
409     if (one && (client == one->from))
410       continue;
411 
412     /* check we have required capabs */
413     if (IsCapable(client, capab) != capab)
414       continue;
415 
416     /* check we don't have any forbidden capabs */
417     if (IsCapable(client, nocapab))
418       continue;
419 
420     send_message(client, buffer);
421   }
422 
423   dbuf_ref_free(buffer);
424 }
425 
426 /* sendto_common_channels_local()
427  *
428  * inputs	- pointer to client
429  *		- pattern to send
430  * output	- NONE
431  * side effects	- Sends a message to all people on local server who are
432  * 		  in same channel with user.
433  *		  used by m_nick.c and exit_one_client.
434  */
435 void
sendto_common_channels_local(struct Client * user,bool touser,unsigned int poscap,unsigned int negcap,const char * pattern,...)436 sendto_common_channels_local(struct Client *user, bool touser, unsigned int poscap,
437                              unsigned int negcap, const char *pattern, ...)
438 {
439   va_list args;
440   dlink_node *node, *node2;
441   struct dbuf_block *buffer = dbuf_alloc();
442 
443   va_start(args, pattern);
444   send_format(buffer, pattern, args);
445   va_end(args);
446 
447   ++current_serial;
448 
449   DLINK_FOREACH(node, user->channel.head)
450   {
451     struct ChannelMember *member = node->data;
452     struct Channel *channel = member->channel;
453 
454     DLINK_FOREACH(node2, channel->members_local.head)
455     {
456       struct ChannelMember *member2 = node2->data;
457       struct Client *target = member2->client;
458 
459       if (IsDead(target))
460         continue;
461 
462       if (target == user)
463         continue;
464 
465       if (target->connection->serial == current_serial)
466         continue;
467 
468       if (poscap && HasCap(target, poscap) != poscap)
469         continue;
470 
471       if (negcap && HasCap(target, negcap))
472         continue;
473 
474       target->connection->serial = current_serial;
475       send_message(target, buffer);
476     }
477   }
478 
479   if (touser == true && MyConnect(user) && !IsDead(user))
480     if (HasCap(user, poscap) == poscap)
481       send_message(user, buffer);
482 
483   dbuf_ref_free(buffer);
484 }
485 
486 /*! \brief Send a message to members of a channel that are locally connected to this server.
487  * \param one      Client to skip; can be NULL
488  * \param channel    Destination channel
489  * \param status   Channel member status flags clients must have
490  * \param poscap   Positive client capabilities flags (CAP)
491  * \param negcap   Negative client capabilities flags (CAP)
492  * \param pattern  Format string for command arguments
493  */
494 void
sendto_channel_local(const struct Client * one,struct Channel * channel,unsigned int status,unsigned int poscap,unsigned int negcap,const char * pattern,...)495 sendto_channel_local(const struct Client *one, struct Channel *channel, unsigned int status,
496                      unsigned int poscap, unsigned int negcap, const char *pattern, ...)
497 {
498   va_list args;
499   dlink_node *node;
500   struct dbuf_block *buffer = dbuf_alloc();
501 
502   va_start(args, pattern);
503   send_format(buffer, pattern, args);
504   va_end(args);
505 
506   DLINK_FOREACH(node, channel->members_local.head)
507   {
508     struct ChannelMember *member = node->data;
509     struct Client *target = member->client;
510 
511     if (IsDead(target))
512       continue;
513 
514     if (one && (target == one->from))
515       continue;
516 
517     if (status && (member->flags & status) == 0)
518       continue;
519 
520     if (poscap && HasCap(target, poscap) != poscap)
521       continue;
522 
523     if (negcap && HasCap(target, negcap))
524       continue;
525 
526     send_message(target, buffer);
527   }
528 
529   dbuf_ref_free(buffer);
530 }
531 
532 /*
533  ** match_it() and sendto_match_butone() ARE only used
534  ** to send a msg to all ppl on servers/hosts that match a specified mask
535  ** (used for enhanced PRIVMSGs) for opers
536  **
537  ** addition -- Armin, 8jun90 (gruner@informatik.tu-muenchen.de)
538  **
539  */
540 
541 /* match_it()
542  *
543  * inputs	- client pointer to match on
544  *		- actual mask to match
545  *		- what to match on, HOST or SERVER
546  * output	- 1 or 0 if match or not
547  * side effects	- NONE
548  */
549 static bool
match_it(const struct Client * one,const char * mask,unsigned int what)550 match_it(const struct Client *one, const char *mask, unsigned int what)
551 {
552   if (what == MATCH_HOST)
553     return match(mask, one->host) == 0;
554 
555   return match(mask, one->servptr->name) == 0;
556 }
557 
558 /* sendto_match_butone()
559  *
560  * Send to all clients which match the mask in a way defined on 'what';
561  * either by user hostname or user servername.
562  *
563  * ugh. ONLY used by m_message.c to send an "oper magic" message. ugh.
564  */
565 void
sendto_match_butone(const struct Client * one,const struct Client * from,const char * mask,int what,const char * pattern,...)566 sendto_match_butone(const struct Client *one, const struct Client *from,
567                     const char *mask, int what, const char *pattern, ...)
568 {
569   va_list args_l, args_r;
570   dlink_node *node;
571   struct dbuf_block *buffer_l = dbuf_alloc();
572   struct dbuf_block *buffer_r = dbuf_alloc();
573 
574   dbuf_put_fmt(buffer_l, ":%s!%s@%s ", from->name, from->username, from->host);
575   dbuf_put_fmt(buffer_r, ":%s ", from->id);
576 
577   va_start(args_l, pattern);
578   va_start(args_r, pattern);
579   send_format(buffer_l, pattern, args_l);
580   send_format(buffer_r, pattern, args_r);
581   va_end(args_l);
582   va_end(args_r);
583 
584   /* Scan the local clients */
585   DLINK_FOREACH(node, local_client_list.head)
586   {
587     struct Client *client = node->data;
588 
589     if (IsDead(client))
590       continue;
591 
592     if (one && (client == one->from))
593       continue;
594 
595     if (match_it(client, mask, what) == false)
596       continue;
597 
598     send_message(client, buffer_l);
599   }
600 
601   /* Now scan servers */
602   DLINK_FOREACH(node, local_server_list.head)
603   {
604     struct Client *client = node->data;
605 
606     /*
607      * The old code looped through every client on the network for each
608      * server to check if the server (client) has at least 1 client
609      * matching the mask, using something like:
610      *
611      * for (target = GlobalClientList; target; target = target->next)
612      *        if (IsRegisteredUser(target) &&
613      *                        match_it(target, mask, what) &&
614      *                        (target->from == client))
615      *   vsendto_prefix_one(client, from, pattern, args);
616      *
617      * That way, we wouldn't send the message to a server who didn't have
618      * a matching client. However, on a network such as EFNet, that code
619      * would have looped through about 50 servers, and in each loop, loop
620      * through about 50k clients as well, calling match() in each nested
621      * loop. That is a very bad thing cpu wise - just send the message to
622      * every connected server and let that server deal with it.
623      * -wnder
624      */
625     if (IsDead(client))
626       continue;
627 
628     if (one && (client == one->from))
629       continue;
630 
631     send_message_remote(client, from, buffer_r);
632   }
633 
634   dbuf_ref_free(buffer_l);
635   dbuf_ref_free(buffer_r);
636 }
637 
638 /* sendto_match_servs()
639  *
640  * inputs       - source client
641  *              - mask to send to
642  *              - capab needed
643  *              - data
644  * outputs	- none
645  * side effects	- data sent to servers matching with capab
646  */
647 void
sendto_match_servs(const struct Client * source_p,const char * mask,unsigned int capab,const char * pattern,...)648 sendto_match_servs(const struct Client *source_p, const char *mask, unsigned int capab,
649                    const char *pattern, ...)
650 {
651   va_list args;
652   dlink_node *node;
653   struct dbuf_block *buffer = dbuf_alloc();
654 
655   dbuf_put_fmt(buffer, ":%s ", source_p->id);
656 
657   va_start(args, pattern);
658   send_format(buffer, pattern, args);
659   va_end(args);
660 
661   ++current_serial;
662 
663   DLINK_FOREACH(node, global_server_list.head)
664   {
665     struct Client *target = node->data;
666 
667     if (IsDead(target->from))
668       continue;
669 
670     /* Do not attempt to send to ourselves ... */
671     if (IsMe(target))
672       continue;
673 
674     /* ... or the source */
675     if (target->from == source_p->from)
676       continue;
677 
678     if (target->from->connection->serial == current_serial)
679       continue;
680 
681     if (IsCapable(target->from, capab) != capab)
682       continue;
683 
684     if (match(mask, target->name))
685       continue;
686 
687     target->from->connection->serial = current_serial;
688     send_message_remote(target->from, source_p, buffer);
689   }
690 
691   dbuf_ref_free(buffer);
692 }
693 
694 /* sendto_anywhere()
695  *
696  * inputs	- pointer to dest client
697  * 		- pointer to from client
698  * 		- varags
699  * output	- NONE
700  * side effects	- less efficient than sendto_remote and sendto_one
701  * 		  but useful when one does not know where target "lives"
702  */
703 void
sendto_anywhere(struct Client * to,const struct Client * from,const char * command,const char * pattern,...)704 sendto_anywhere(struct Client *to, const struct Client *from,
705                 const char *command,
706                 const char *pattern, ...)
707 {
708   va_list args;
709 
710   if (IsDead(to->from))
711     return;
712 
713   struct dbuf_block *buffer = dbuf_alloc();
714   if (MyClient(to) && IsClient(from))
715     dbuf_put_fmt(buffer, ":%s!%s@%s %s %s ", from->name, from->username,
716                  from->host, command, to->name);
717   else
718     dbuf_put_fmt(buffer, ":%s %s %s ", ID_or_name(from, to),
719                  command, ID_or_name(to, to));
720 
721   va_start(args, pattern);
722   send_format(buffer, pattern, args);
723   va_end(args);
724 
725   if (MyConnect(to))
726     send_message(to, buffer);
727   else
728     send_message_remote(to->from, from, buffer);
729 
730   dbuf_ref_free(buffer);
731 }
732 
733 /* sendto_realops_flags()
734  *
735  * inputs	- flag types of messages to show to real opers
736  *		- flag indicating opers/admins
737  *		- var args input message
738  * output	- NONE
739  * side effects	- Send to *local* ops only but NOT +s nonopers.
740  */
741 void
sendto_realops_flags(unsigned int flags,int level,int type,const char * pattern,...)742 sendto_realops_flags(unsigned int flags, int level, int type, const char *pattern, ...)
743 {
744   va_list args;
745   dlink_node *node;
746   const char *ntype = "???";
747 
748   switch (type)
749   {
750     case SEND_NOTICE:
751       ntype = "Notice";
752       break;
753     case SEND_GLOBAL:
754       ntype = "Global";
755       break;
756     case SEND_LOCOPS:
757       ntype = "LocOps";
758       break;
759     default:
760       assert(0);
761   }
762 
763   struct dbuf_block *buffer = dbuf_alloc();
764   dbuf_put_fmt(buffer, ":%s NOTICE * :*** %s -- ", me.name, ntype);
765 
766   va_start(args, pattern);
767   send_format(buffer, pattern, args);
768   va_end(args);
769 
770   DLINK_FOREACH(node, oper_list.head)
771   {
772     struct Client *client = node->data;
773     assert(HasUMode(client, UMODE_OPER));
774 
775     if (IsDead(client))
776       continue;
777 
778     /*
779      * If we're sending it to opers and they're an admin, skip.
780      * If we're sending it to admins, and they're not, skip.
781      */
782     if (((level == L_ADMIN) && !HasUMode(client, UMODE_ADMIN)) ||
783         ((level == L_OPER) && HasUMode(client, UMODE_ADMIN)))
784       continue;
785 
786     if (!HasUMode(client, flags))
787       continue;
788 
789     send_message(client, buffer);
790   }
791 
792   dbuf_ref_free(buffer);
793 }
794 
795 /* ts_warn()
796  *
797  * inputs       - var args message
798  * output       - NONE
799  * side effects - Call sendto_realops_flags, with some flood checking
800  *                (at most 5 warnings every 5 seconds)
801  */
802 void
sendto_realops_flags_ratelimited(uintmax_t * rate,const char * pattern,...)803 sendto_realops_flags_ratelimited(uintmax_t *rate, const char *pattern, ...)
804 {
805   va_list args;
806   char buffer[IRCD_BUFSIZE];
807 
808   if ((event_base->time.sec_monotonic - *rate) < 20)
809     return;
810 
811   *rate = event_base->time.sec_monotonic;
812 
813   va_start(args, pattern);
814   vsnprintf(buffer, sizeof(buffer), pattern, args);
815   va_end(args);
816 
817   sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE, "%s", buffer);
818   ilog(LOG_TYPE_IRCD, "%s", buffer);
819 }
820 
821 /* sendto_wallops_flags()
822  *
823  * inputs       - flag types of messages to show to real opers
824  *              - client sending request
825  *              - var args input message
826  * output       - NONE
827  * side effects - Send a wallops to local opers
828  */
829 void
sendto_wallops_flags(unsigned int flags,const struct Client * source_p,const char * pattern,...)830 sendto_wallops_flags(unsigned int flags, const struct Client *source_p,
831                      const char *pattern, ...)
832 {
833   va_list args;
834   dlink_node *node;
835   struct dbuf_block *buffer = dbuf_alloc();
836 
837   if (IsClient(source_p))
838     dbuf_put_fmt(buffer, ":%s!%s@%s WALLOPS :", source_p->name, source_p->username, source_p->host);
839   else
840     dbuf_put_fmt(buffer, ":%s WALLOPS :", source_p->name);
841 
842   va_start(args, pattern);
843   send_format(buffer, pattern, args);
844   va_end(args);
845 
846   DLINK_FOREACH(node, oper_list.head)
847   {
848     struct Client *client = node->data;
849     assert(client->umodes & UMODE_OPER);
850 
851     if (IsDead(client))
852       continue;
853 
854     if (!HasUMode(client, flags))
855       continue;
856 
857     send_message(client, buffer);
858   }
859 
860   dbuf_ref_free(buffer);
861 }
862