ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/send.c
Revision: 3311
Committed: Tue Apr 15 12:10:36 2014 UTC (12 years, 5 months ago) by michael
Content type: text/x-csrc
File size: 26017 byte(s)
Error occurred while calculating annotation data.
Log Message:
- Undo -r3215 for now

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 && (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 && (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))
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
534 DLINK_FOREACH(uptr, chptr->members.head)
535 {
536 ms = uptr->data;
537 target_p = ms->client_p;
538
539 if (!MyConnect(target_p) || target_p == user || IsDefunct(target_p) ||
540 target_p->localClient->serial == current_serial)
541 continue;
542
543 if (HasCap(target_p, cap) != cap)
544 continue;
545
546 target_p->localClient->serial = current_serial;
547 send_message(target_p, buffer);
548 }
549 }
550
551 if (touser && MyConnect(user) && !IsDead(user) &&
552 user->localClient->serial != current_serial)
553 if (HasCap(user, cap) == cap)
554 send_message(user, buffer);
555
556 dbuf_ref_free(buffer);
557 }
558
559 /* sendto_channel_local()
560 *
561 * inputs - member status mask, e.g. CHFL_CHANOP | CHFL_VOICE
562 * - whether to ignore +D clients (YES/NO)
563 * - pointer to channel to send to
564 * - var args pattern
565 * output - NONE
566 * side effects - Send a message to all members of a channel that are
567 * locally connected to this server.
568 */
569 void
570 sendto_channel_local(unsigned int type, int nodeaf, struct Channel *chptr,
571 const char *pattern, ...)
572 {
573 va_list args;
574 dlink_node *ptr = NULL;
575 struct dbuf_block *buffer;
576
577 buffer = dbuf_alloc();
578
579 va_start(args, pattern);
580 send_format(buffer, pattern, args);
581 va_end(args);
582
583 DLINK_FOREACH(ptr, chptr->members.head)
584 {
585 struct Membership *ms = ptr->data;
586 struct Client *target_p = ms->client_p;
587
588 if (type && (ms->flags & type) == 0)
589 continue;
590
591 if (!MyConnect(target_p) || IsDefunct(target_p) ||
592 (nodeaf && HasUMode(target_p, UMODE_DEAF)))
593 continue;
594
595 send_message(target_p, buffer);
596 }
597
598 dbuf_ref_free(buffer);
599 }
600
601 /* sendto_channel_local_butone()
602 *
603 * inputs - pointer to client to NOT send message to
604 * - member status mask, e.g. CHFL_CHANOP | CHFL_VOICE
605 * - pointer to channel to send to
606 * - var args pattern
607 * output - NONE
608 * side effects - Send a message to all members of a channel that are
609 * locally connected to this server except one.
610 *
611 * WARNING - +D clients are omitted
612 */
613 void
614 sendto_channel_local_butone(struct Client *one, unsigned int type, unsigned int cap,
615 struct Channel *chptr, const char *pattern, ...)
616 {
617 va_list args;
618 dlink_node *ptr = NULL;
619 struct dbuf_block *buffer;
620
621 buffer = dbuf_alloc();
622
623 va_start(args, pattern);
624 send_format(buffer, pattern, args);
625 va_end(args);
626
627 DLINK_FOREACH(ptr, chptr->members.head)
628 {
629 struct Membership *ms = ptr->data;
630 struct Client *target_p = ms->client_p;
631
632 if (type && (ms->flags & type) == 0)
633 continue;
634
635 if (!MyConnect(target_p) || (one && target_p == one->from))
636 continue;
637
638 if (IsDefunct(target_p) || HasUMode(target_p, UMODE_DEAF))
639 continue;
640
641 if (HasCap(target_p, cap) != cap)
642 continue;
643
644 send_message(target_p, buffer);
645 }
646
647 dbuf_ref_free(buffer);
648 }
649
650 /*
651 ** match_it() and sendto_match_butone() ARE only used
652 ** to send a msg to all ppl on servers/hosts that match a specified mask
653 ** (used for enhanced PRIVMSGs) for opers
654 **
655 ** addition -- Armin, 8jun90 (gruner@informatik.tu-muenchen.de)
656 **
657 */
658
659 /* match_it()
660 *
661 * inputs - client pointer to match on
662 * - actual mask to match
663 * - what to match on, HOST or SERVER
664 * output - 1 or 0 if match or not
665 * side effects - NONE
666 */
667 static int
668 match_it(const struct Client *one, const char *mask, unsigned int what)
669 {
670 if (what == MATCH_HOST)
671 return !match(mask, one->host);
672
673 return !match(mask, one->servptr->name);
674 }
675
676 /* sendto_match_butone()
677 *
678 * Send to all clients which match the mask in a way defined on 'what';
679 * either by user hostname or user servername.
680 *
681 * ugh. ONLY used by m_message.c to send an "oper magic" message. ugh.
682 */
683 void
684 sendto_match_butone(struct Client *one, struct Client *from, const char *mask,
685 int what, const char *pattern, ...)
686 {
687 va_list alocal, aremote;
688 dlink_node *ptr = NULL, *ptr_next = NULL;
689 struct dbuf_block *local_buf, *remote_buf;
690
691 local_buf = dbuf_alloc(), remote_buf = dbuf_alloc();
692
693 dbuf_put_fmt(local_buf, ":%s!%s@%s ", from->name, from->username, from->host);
694 dbuf_put_fmt(remote_buf, ":%s ", from->id);
695
696 va_start(alocal, pattern);
697 va_start(aremote, pattern);
698 send_format(local_buf, pattern, alocal);
699 send_format(remote_buf, pattern, aremote);
700 va_end(aremote);
701 va_end(alocal);
702
703 /* scan the local clients */
704 DLINK_FOREACH(ptr, local_client_list.head)
705 {
706 struct Client *client_p = ptr->data;
707
708 if ((!one || client_p != one->from) && !IsDefunct(client_p) &&
709 match_it(client_p, mask, what))
710 send_message(client_p, local_buf);
711 }
712
713 /* Now scan servers */
714 DLINK_FOREACH_SAFE(ptr, ptr_next, serv_list.head)
715 {
716 struct Client *client_p = ptr->data;
717
718 /*
719 * The old code looped through every client on the
720 * network for each server to check if the
721 * server (client_p) has at least 1 client matching
722 * the mask, using something like:
723 *
724 * for (target_p = GlobalClientList; target_p; target_p = target_p->next)
725 * if (IsRegisteredUser(target_p) &&
726 * match_it(target_p, mask, what) &&
727 * (target_p->from == client_p))
728 * vsendto_prefix_one(client_p, from, pattern, args);
729 *
730 * That way, we wouldn't send the message to
731 * a server who didn't have a matching client.
732 * However, on a network such as EFNet, that
733 * code would have looped through about 50
734 * servers, and in each loop, loop through
735 * about 50k clients as well, calling match()
736 * in each nested loop. That is a very bad
737 * thing cpu wise - just send the message
738 * to every connected server and let that
739 * server deal with it.
740 * -wnder
741 */
742 if ((!one || client_p != one->from) && !IsDefunct(client_p))
743 send_message_remote(client_p, from, remote_buf);
744 }
745
746 dbuf_ref_free(local_buf);
747 dbuf_ref_free(remote_buf);
748 }
749
750 /* sendto_match_servs()
751 *
752 * inputs - source client
753 * - mask to send to
754 * - capab needed
755 * - data
756 * outputs - none
757 * side effects - data sent to servers matching with capab
758 */
759 void
760 sendto_match_servs(struct Client *source_p, const char *mask, unsigned int cap,
761 const char *pattern, ...)
762 {
763 va_list args;
764 dlink_node *ptr = NULL;
765 struct dbuf_block *buff_suid;
766
767 buff_suid = dbuf_alloc();
768
769 va_start(args, pattern);
770 dbuf_put_fmt(buff_suid, ":%s ", source_p->id);
771 dbuf_put_args(buff_suid, pattern, args);
772 va_end(args);
773
774 ++current_serial;
775
776 DLINK_FOREACH(ptr, global_serv_list.head)
777 {
778 struct Client *target_p = ptr->data;
779
780 /* Do not attempt to send to ourselves, or the source */
781 if (IsMe(target_p) || target_p->from == source_p->from)
782 continue;
783
784 if (target_p->from->localClient->serial == current_serial)
785 continue;
786
787 if (!match(mask, target_p->name))
788 {
789 /*
790 * if we set the serial here, then we'll never do a
791 * match() again, if !IsCapable()
792 */
793 target_p->from->localClient->serial = current_serial;
794
795 if (!IsCapable(target_p->from, cap))
796 continue;
797
798 send_message_remote(target_p->from, source_p, buff_suid);
799 }
800 }
801
802 dbuf_ref_free(buff_suid);
803 }
804
805 /* sendto_anywhere()
806 *
807 * inputs - pointer to dest client
808 * - pointer to from client
809 * - varags
810 * output - NONE
811 * side effects - less efficient than sendto_remote and sendto_one
812 * but useful when one does not know where target "lives"
813 */
814 void
815 sendto_anywhere(struct Client *to, struct Client *from,
816 const char *command,
817 const char *pattern, ...)
818 {
819 va_list args;
820 struct dbuf_block *buffer = NULL;
821
822 if (IsDead(to->from))
823 return;
824
825 buffer = dbuf_alloc();
826
827 if (MyClient(to) && IsClient(from))
828 dbuf_put_fmt(buffer, ":%s!%s@%s %s %s ", from->name, from->username,
829 from->host, command, to->name);
830 else
831 dbuf_put_fmt(buffer, ":%s %s %s ", ID_or_name(from, to),
832 command, ID_or_name(to, to));
833
834 va_start(args, pattern);
835 send_format(buffer, pattern, args);
836 va_end(args);
837
838 if (MyClient(to))
839 send_message(to, buffer);
840 else
841 send_message_remote(to, from, buffer);
842
843 dbuf_ref_free(buffer);
844 }
845
846 /* sendto_realops_flags()
847 *
848 * inputs - flag types of messages to show to real opers
849 * - flag indicating opers/admins
850 * - var args input message
851 * output - NONE
852 * side effects - Send to *local* ops only but NOT +s nonopers.
853 */
854 void
855 sendto_realops_flags(unsigned int flags, int level, int type, const char *pattern, ...)
856 {
857 const char *ntype = NULL;
858 dlink_node *ptr = NULL;
859 char nbuf[IRCD_BUFSIZE] = "";
860 va_list args;
861
862 va_start(args, pattern);
863 vsnprintf(nbuf, sizeof(nbuf), pattern, args);
864 va_end(args);
865
866 switch (type)
867 {
868 case SEND_NOTICE:
869 ntype = "Notice";
870 break;
871 case SEND_GLOBAL:
872 ntype = "Global";
873 break;
874 case SEND_LOCOPS:
875 ntype = "LocOps";
876 break;
877 default:
878 assert(0);
879 }
880
881 DLINK_FOREACH(ptr, oper_list.head)
882 {
883 struct Client *client_p = ptr->data;
884 assert(HasUMode(client_p, UMODE_OPER));
885
886 /*
887 * If we're sending it to opers and they're an admin, skip.
888 * If we're sending it to admins, and they're not, skip.
889 */
890 if (((level == L_ADMIN) && !HasUMode(client_p, UMODE_ADMIN)) ||
891 ((level == L_OPER) && HasUMode(client_p, UMODE_ADMIN)))
892 continue;
893
894 if (HasUMode(client_p, flags))
895 sendto_one(client_p, ":%s NOTICE %s :*** %s -- %s",
896 me.name, client_p->name, ntype, nbuf);
897 }
898 }
899
900 /* ts_warn()
901 *
902 * inputs - var args message
903 * output - NONE
904 * side effects - Call sendto_realops_flags, with some flood checking
905 * (at most 5 warnings every 5 seconds)
906 */
907 void
908 sendto_realops_flags_ratelimited(const char *pattern, ...)
909 {
910 va_list args;
911 char buffer[IRCD_BUFSIZE] = "";
912 static time_t last = 0;
913 static int warnings = 0;
914
915 /*
916 ** if we're running with TS_WARNINGS enabled and someone does
917 ** something silly like (remotely) connecting a nonTS server,
918 ** we'll get a ton of warnings, so we make sure we don't send
919 ** more than 5 every 5 seconds. -orabidoo
920 */
921
922 if (CurrentTime - last < 5)
923 {
924 if (++warnings > 5)
925 return;
926 }
927 else
928 {
929 last = CurrentTime;
930 warnings = 0;
931 }
932
933 va_start(args, pattern);
934 vsnprintf(buffer, sizeof(buffer), pattern, args);
935 va_end(args);
936
937 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE, "%s", buffer);
938 ilog(LOG_TYPE_IRCD, "%s", buffer);
939 }
940
941 /* sendto_wallops_flags()
942 *
943 * inputs - flag types of messages to show to real opers
944 * - client sending request
945 * - var args input message
946 * output - NONE
947 * side effects - Send a wallops to local opers
948 */
949 void
950 sendto_wallops_flags(unsigned int flags, struct Client *source_p,
951 const char *pattern, ...)
952 {
953 dlink_node *ptr = NULL;
954 va_list args;
955 struct dbuf_block *buffer;
956
957 buffer = dbuf_alloc();
958
959 if (IsClient(source_p))
960 dbuf_put_fmt(buffer, ":%s!%s@%s WALLOPS :", source_p->name, source_p->username, source_p->host);
961 else
962 dbuf_put_fmt(buffer, ":%s WALLOPS :", source_p->name);
963
964 va_start(args, pattern);
965 send_format(buffer, pattern, args);
966 va_end(args);
967
968 DLINK_FOREACH(ptr, oper_list.head)
969 {
970 struct Client *client_p = ptr->data;
971 assert(client_p->umodes & UMODE_OPER);
972
973 if (HasUMode(client_p, flags) && !IsDefunct(client_p))
974 send_message(client_p, buffer);
975 }
976
977 dbuf_ref_free(buffer);
978 }

Properties

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