ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/send.c
Revision: 3312
Committed: Tue Apr 15 12:13:07 2014 UTC (11 years, 4 months ago) by michael
Content type: text/x-csrc
File size: 26118 byte(s)
Log Message:
- Readded FLAGS_BLOCKED

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

Properties

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