ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/send.c
Revision: 3186
Committed: Thu Mar 20 18:09:34 2014 UTC (11 years, 5 months ago) by michael
Content type: text/x-csrc
File size: 26103 byte(s)
Log Message:
- Get rid of the ID() macro

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

Properties

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