ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/send.c
Revision: 3215
Committed: Tue Mar 25 19:23:15 2014 UTC (11 years, 5 months ago) by michael
Content type: text/x-csrc
File size: 26104 byte(s)
Log Message:
- Fixed some comments; cleaned up style here and there

File Contents

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

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision