ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/send.c
Revision: 3136
Committed: Tue Mar 11 18:24:03 2014 UTC (11 years, 5 months ago) by michael
Content type: text/x-csrc
File size: 27670 byte(s)
Log Message:
- Various fixes to previous ts5 removal changes

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->name, 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, &me, "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 ", ID(from));
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) || target_p->from == one)
432 continue;
433
434 if (type != 0 && (ms->flags & type) == 0)
435 continue;
436
437 if (MyConnect(target_p))
438 send_message(target_p, local_buf);
439 else if (target_p->from->localClient->serial != current_serial)
440 send_message_remote(target_p->from, from, remote_buf);
441 target_p->from->localClient->serial = current_serial;
442 }
443
444 dbuf_ref_free(local_buf);
445 dbuf_ref_free(remote_buf);
446 }
447
448 /* sendto_server()
449 *
450 * inputs - pointer to client to NOT send to
451 * - pointer to channel
452 * - caps or'd together which must ALL be present
453 * - caps or'd together which must ALL NOT be present
454 * - printf style format string
455 * - args to format string
456 * output - NONE
457 * side effects - Send a message to all connected servers, except the
458 * client 'one' (if non-NULL), as long as the servers
459 * support ALL capabs in 'caps', and NO capabs in 'nocaps'.
460 *
461 * This function was written in an attempt to merge together the other
462 * billion sendto_*serv*() functions, which sprung up with capabs,
463 * lazylinks, uids, etc.
464 * -davidt
465 */
466 void
467 sendto_server(struct Client *one,
468 const unsigned int caps,
469 const unsigned int nocaps,
470 const char *format, ...)
471 {
472 va_list args;
473 dlink_node *ptr = NULL;
474 struct dbuf_block *buffer;
475
476 buffer = dbuf_alloc();
477
478 va_start(args, format);
479 send_format(buffer, format, args);
480 va_end(args);
481
482 DLINK_FOREACH(ptr, serv_list.head)
483 {
484 struct Client *client_p = ptr->data;
485
486 /* If dead already skip */
487 if (IsDead(client_p))
488 continue;
489 /* check against 'one' */
490 if (one != NULL && (client_p == one->from))
491 continue;
492 /* check we have required capabs */
493 if ((client_p->localClient->caps & caps) != caps)
494 continue;
495 /* check we don't have any forbidden capabs */
496 if ((client_p->localClient->caps & nocaps) != 0)
497 continue;
498
499 send_message(client_p, buffer);
500 }
501
502 dbuf_ref_free(buffer);
503 }
504
505 /* sendto_common_channels_local()
506 *
507 * inputs - pointer to client
508 * - pattern to send
509 * output - NONE
510 * side effects - Sends a message to all people on local server who are
511 * in same channel with user.
512 * used by m_nick.c and exit_one_client.
513 */
514 void
515 sendto_common_channels_local(struct Client *user, int touser, unsigned int cap,
516 const char *pattern, ...)
517 {
518 va_list args;
519 dlink_node *uptr;
520 dlink_node *cptr;
521 struct Channel *chptr;
522 struct Membership *ms;
523 struct Client *target_p;
524 struct dbuf_block *buffer;
525
526 buffer = dbuf_alloc();
527
528 va_start(args, pattern);
529 send_format(buffer, pattern, args);
530 va_end(args);
531
532 ++current_serial;
533
534 DLINK_FOREACH(cptr, user->channel.head)
535 {
536 chptr = ((struct Membership *)cptr->data)->chptr;
537 assert(chptr != NULL);
538
539 DLINK_FOREACH(uptr, chptr->members.head)
540 {
541 ms = uptr->data;
542 target_p = ms->client_p;
543 assert(target_p != NULL);
544
545 if (!MyConnect(target_p) || target_p == user || IsDefunct(target_p) ||
546 target_p->localClient->serial == current_serial)
547 continue;
548
549 if (HasCap(target_p, cap) != cap)
550 continue;
551
552 target_p->localClient->serial = current_serial;
553 send_message(target_p, buffer);
554 }
555 }
556
557 if (touser && MyConnect(user) && !IsDead(user) &&
558 user->localClient->serial != current_serial)
559 if (HasCap(user, cap) == cap)
560 send_message(user, buffer);
561
562 dbuf_ref_free(buffer);
563 }
564
565 /* sendto_channel_local()
566 *
567 * inputs - member status mask, e.g. CHFL_CHANOP | CHFL_VOICE
568 * - whether to ignore +D clients (YES/NO)
569 * - pointer to channel to send to
570 * - var args pattern
571 * output - NONE
572 * side effects - Send a message to all members of a channel that are
573 * locally connected to this server.
574 */
575 void
576 sendto_channel_local(unsigned int type, int nodeaf, struct Channel *chptr,
577 const char *pattern, ...)
578 {
579 va_list args;
580 dlink_node *ptr = NULL;
581 struct dbuf_block *buffer;
582
583 buffer = dbuf_alloc();
584
585 va_start(args, pattern);
586 send_format(buffer, pattern, args);
587 va_end(args);
588
589 DLINK_FOREACH(ptr, chptr->members.head)
590 {
591 struct Membership *ms = ptr->data;
592 struct Client *target_p = ms->client_p;
593
594 if (type != 0 && (ms->flags & type) == 0)
595 continue;
596
597 if (!MyConnect(target_p) || IsDefunct(target_p) ||
598 (nodeaf && HasUMode(target_p, UMODE_DEAF)))
599 continue;
600
601 send_message(target_p, buffer);
602 }
603
604 dbuf_ref_free(buffer);
605 }
606
607 /* sendto_channel_local_butone()
608 *
609 * inputs - pointer to client to NOT send message to
610 * - member status mask, e.g. CHFL_CHANOP | CHFL_VOICE
611 * - pointer to channel to send to
612 * - var args pattern
613 * output - NONE
614 * side effects - Send a message to all members of a channel that are
615 * locally connected to this server except one.
616 *
617 * WARNING - +D clients are omitted
618 */
619 void
620 sendto_channel_local_butone(struct Client *one, unsigned int type, unsigned int cap,
621 struct Channel *chptr, const char *pattern, ...)
622 {
623 va_list args;
624 dlink_node *ptr = NULL;
625 struct dbuf_block *buffer;
626
627 buffer = dbuf_alloc();
628
629 va_start(args, pattern);
630 send_format(buffer, pattern, args);
631 va_end(args);
632
633 DLINK_FOREACH(ptr, chptr->members.head)
634 {
635 struct Membership *ms = ptr->data;
636 struct Client *target_p = ms->client_p;
637
638 if (type != 0 && (ms->flags & type) == 0)
639 continue;
640
641 if (!MyConnect(target_p) || target_p == one ||
642 IsDefunct(target_p) || HasUMode(target_p, UMODE_DEAF))
643 continue;
644
645 if (HasCap(target_p, cap) != cap)
646 continue;
647
648 send_message(target_p, buffer);
649 }
650
651 dbuf_ref_free(buffer);
652 }
653
654 /*
655 ** match_it() and sendto_match_butone() ARE only used
656 ** to send a msg to all ppl on servers/hosts that match a specified mask
657 ** (used for enhanced PRIVMSGs) for opers
658 **
659 ** addition -- Armin, 8jun90 (gruner@informatik.tu-muenchen.de)
660 **
661 */
662
663 /* match_it()
664 *
665 * inputs - client pointer to match on
666 * - actual mask to match
667 * - what to match on, HOST or SERVER
668 * output - 1 or 0 if match or not
669 * side effects - NONE
670 */
671 static int
672 match_it(const struct Client *one, const char *mask, unsigned int what)
673 {
674 if (what == MATCH_HOST)
675 return !match(mask, one->host);
676
677 return !match(mask, one->servptr->name);
678 }
679
680 /* sendto_match_butone()
681 *
682 * Send to all clients which match the mask in a way defined on 'what';
683 * either by user hostname or user servername.
684 *
685 * ugh. ONLY used by m_message.c to send an "oper magic" message. ugh.
686 */
687 void
688 sendto_match_butone(struct Client *one, struct Client *from, char *mask,
689 int what, const char *pattern, ...)
690 {
691 va_list alocal, aremote;
692 dlink_node *ptr = NULL, *ptr_next = NULL;
693 struct dbuf_block *local_buf, *remote_buf;
694
695 local_buf = dbuf_alloc(), remote_buf = dbuf_alloc();
696
697 dbuf_put_fmt(local_buf, ":%s!%s@%s ", from->name, from->username, from->host);
698 dbuf_put_fmt(remote_buf, ":%s ", ID(from));
699
700 va_start(alocal, pattern);
701 va_start(aremote, pattern);
702 send_format(local_buf, pattern, alocal);
703 send_format(remote_buf, pattern, aremote);
704 va_end(aremote);
705 va_end(alocal);
706
707 /* scan the local clients */
708 DLINK_FOREACH(ptr, local_client_list.head)
709 {
710 struct Client *client_p = ptr->data;
711
712 if (client_p != one && !IsDefunct(client_p) &&
713 match_it(client_p, mask, what))
714 send_message(client_p, local_buf);
715 }
716
717 /* Now scan servers */
718 DLINK_FOREACH_SAFE(ptr, ptr_next, serv_list.head)
719 {
720 struct Client *client_p = ptr->data;
721
722 /*
723 * The old code looped through every client on the
724 * network for each server to check if the
725 * server (client_p) has at least 1 client matching
726 * the mask, using something like:
727 *
728 * for (target_p = GlobalClientList; target_p; target_p = target_p->next)
729 * if (IsRegisteredUser(target_p) &&
730 * match_it(target_p, mask, what) &&
731 * (target_p->from == client_p))
732 * vsendto_prefix_one(client_p, from, pattern, args);
733 *
734 * That way, we wouldn't send the message to
735 * a server who didn't have a matching client.
736 * However, on a network such as EFNet, that
737 * code would have looped through about 50
738 * servers, and in each loop, loop through
739 * about 50k clients as well, calling match()
740 * in each nested loop. That is a very bad
741 * thing cpu wise - just send the message
742 * to every connected server and let that
743 * server deal with it.
744 * -wnder
745 */
746 if (client_p != one && !IsDefunct(client_p))
747 send_message_remote(client_p, from, remote_buf);
748 }
749
750 dbuf_ref_free(local_buf);
751 dbuf_ref_free(remote_buf);
752 }
753
754 /* sendto_match_servs()
755 *
756 * inputs - source client
757 * - mask to send to
758 * - capab needed
759 * - data
760 * outputs - none
761 * side effects - data sent to servers matching with capab
762 */
763 void
764 sendto_match_servs(struct Client *source_p, const char *mask, unsigned int cap,
765 const char *pattern, ...)
766 {
767 va_list args;
768 dlink_node *ptr = NULL;
769 struct dbuf_block *buff_suid;
770
771 buff_suid = dbuf_alloc();
772
773 va_start(args, pattern);
774 dbuf_put_fmt(buff_suid, ":%s ", ID(source_p));
775 dbuf_put_args(buff_suid, pattern, args);
776 va_end(args);
777
778 ++current_serial;
779
780 DLINK_FOREACH(ptr, global_serv_list.head)
781 {
782 struct Client *target_p = ptr->data;
783
784 /* Do not attempt to send to ourselves, or the source */
785 if (IsMe(target_p) || target_p->from == source_p->from)
786 continue;
787
788 if (target_p->from->localClient->serial == current_serial)
789 continue;
790
791 if (!match(mask, target_p->name))
792 {
793 /*
794 * if we set the serial here, then we'll never do a
795 * match() again, if !IsCapable()
796 */
797 target_p->from->localClient->serial = current_serial;
798
799 if (!IsCapable(target_p->from, cap))
800 continue;
801
802 send_message_remote(target_p->from, source_p, buff_suid);
803 }
804 }
805
806 dbuf_ref_free(buff_suid);
807 }
808
809 /* sendto_anywhere()
810 *
811 * inputs - pointer to dest client
812 * - pointer to from client
813 * - varags
814 * output - NONE
815 * side effects - less efficient than sendto_remote and sendto_one
816 * but useful when one does not know where target "lives"
817 */
818 void
819 sendto_anywhere(struct Client *to, struct Client *from,
820 const char *command,
821 const char *pattern, ...)
822 {
823 va_list args;
824 struct dbuf_block *buffer;
825
826 if (IsDead(to->from))
827 return;
828
829 buffer = dbuf_alloc();
830
831 if (MyClient(to))
832 {
833 if (IsServer(from))
834 dbuf_put_fmt(buffer, ":%s %s %s ", from->name, command, to->name);
835 else
836 dbuf_put_fmt(buffer, ":%s!%s@%s %s %s ", from->name, from->username, from->host, command, to->name);
837 }
838 else
839 dbuf_put_fmt(buffer, ":%s %s %s ", ID_or_name(from, to), command, ID_or_name(to, to));
840
841 va_start(args, pattern);
842 send_format(buffer, pattern, args);
843 va_end(args);
844
845 if (MyClient(to))
846 send_message(to, buffer);
847 else
848 send_message_remote(to, from, buffer);
849
850 dbuf_ref_free(buffer);
851 }
852
853 /* sendto_realops_flags()
854 *
855 * inputs - flag types of messages to show to real opers
856 * - flag indicating opers/admins
857 * - var args input message
858 * output - NONE
859 * side effects - Send to *local* ops only but NOT +s nonopers.
860 */
861 void
862 sendto_realops_flags(unsigned int flags, int level, int type, const char *pattern, ...)
863 {
864 const char *ntype = NULL;
865 dlink_node *ptr = NULL;
866 char nbuf[IRCD_BUFSIZE];
867 va_list args;
868
869 va_start(args, pattern);
870 vsnprintf(nbuf, sizeof(nbuf), pattern, args);
871 va_end(args);
872
873 switch (type)
874 {
875 case SEND_NOTICE:
876 ntype = "Notice";
877 break;
878 case SEND_GLOBAL:
879 ntype = "Global";
880 break;
881 case SEND_LOCOPS:
882 ntype = "LocOps";
883 break;
884 default:
885 assert(0);
886 }
887
888 DLINK_FOREACH(ptr, oper_list.head)
889 {
890 struct Client *client_p = ptr->data;
891 assert(HasUMode(client_p, UMODE_OPER));
892
893 /*
894 * If we're sending it to opers and they're an admin, skip.
895 * If we're sending it to admins, and they're not, skip.
896 */
897 if (((level == L_ADMIN) && !HasUMode(client_p, UMODE_ADMIN)) ||
898 ((level == L_OPER) && HasUMode(client_p, UMODE_ADMIN)))
899 continue;
900
901 if (HasUMode(client_p, flags))
902 sendto_one(client_p, ":%s NOTICE %s :*** %s -- %s",
903 me.name, client_p->name, ntype, nbuf);
904 }
905 }
906
907 /* sendto_wallops_flags()
908 *
909 * inputs - flag types of messages to show to real opers
910 * - client sending request
911 * - var args input message
912 * output - NONE
913 * side effects - Send a wallops to local opers
914 */
915 void
916 sendto_wallops_flags(unsigned int flags, struct Client *source_p,
917 const char *pattern, ...)
918 {
919 dlink_node *ptr = NULL;
920 va_list args;
921 struct dbuf_block *buffer;
922
923 buffer = dbuf_alloc();
924
925 if (IsClient(source_p))
926 dbuf_put_fmt(buffer, ":%s!%s@%s WALLOPS :", source_p->name, source_p->username, source_p->host);
927 else
928 dbuf_put_fmt(buffer, ":%s WALLOPS :", source_p->name);
929
930 va_start(args, pattern);
931 send_format(buffer, pattern, args);
932 va_end(args);
933
934 DLINK_FOREACH(ptr, oper_list.head)
935 {
936 struct Client *client_p = ptr->data;
937 assert(client_p->umodes & UMODE_OPER);
938
939 if (HasUMode(client_p, flags) && !IsDefunct(client_p))
940 send_message(client_p, buffer);
941 }
942
943 dbuf_ref_free(buffer);
944 }
945
946 /* ts_warn()
947 *
948 * inputs - var args message
949 * output - NONE
950 * side effects - Call sendto_realops_flags, with some flood checking
951 * (at most 5 warnings every 5 seconds)
952 */
953 void
954 sendto_realops_flags_ratelimited(const char *pattern, ...)
955 {
956 va_list args;
957 char buffer[IRCD_BUFSIZE];
958 static time_t last = 0;
959 static int warnings = 0;
960
961 /*
962 ** if we're running with TS_WARNINGS enabled and someone does
963 ** something silly like (remotely) connecting a nonTS server,
964 ** we'll get a ton of warnings, so we make sure we don't send
965 ** more than 5 every 5 seconds. -orabidoo
966 */
967
968 if (CurrentTime - last < 5)
969 {
970 if (++warnings > 5)
971 return;
972 }
973 else
974 {
975 last = CurrentTime;
976 warnings = 0;
977 }
978
979 va_start(args, pattern);
980 vsnprintf(buffer, sizeof(buffer), pattern, args);
981 va_end(args);
982
983 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE, "%s", buffer);
984 ilog(LOG_TYPE_IRCD, "%s", buffer);
985 }
986
987 /* kill_client()
988 *
989 * inputs - client to send kill towards
990 * - pointer to client to kill
991 * - reason for kill
992 * output - NONE
993 * side effects - NONE
994 */
995 void
996 kill_client(struct Client *client_p, struct Client *diedie,
997 const char *pattern, ...)
998 {
999 va_list args;
1000 struct dbuf_block *buffer;
1001
1002 client_p = client_p->from;
1003
1004 if (IsDead(client_p))
1005 return;
1006
1007 buffer = dbuf_alloc();
1008
1009 dbuf_put_fmt(buffer, ":%s KILL %s :",
1010 ID_or_name(&me, client_p),
1011 ID_or_name(diedie, client_p));
1012
1013 va_start(args, pattern);
1014 send_format(buffer, pattern, args);
1015 va_end(args);
1016
1017 send_message(client_p, buffer);
1018
1019 dbuf_ref_free(buffer);
1020 }
1021
1022 /* kill_client_serv_butone()
1023 *
1024 * inputs - pointer to client to not send to
1025 * - pointer to client to kill
1026 * output - NONE
1027 * side effects - Send a KILL for the given client
1028 * message to all connected servers
1029 * except the client 'one'. Also deal with
1030 * client being unknown to leaf, as in lazylink...
1031 */
1032 void
1033 kill_client_serv_butone(struct Client *one, struct Client *source_p,
1034 const char *pattern, ...)
1035 {
1036 va_list args;
1037 dlink_node *ptr = NULL;
1038 struct dbuf_block *uid_buffer = dbuf_alloc();
1039
1040 va_start(args, pattern);
1041 dbuf_put_fmt(uid_buffer, ":%s KILL %s :", ID(&me), ID(source_p));
1042 send_format(uid_buffer, pattern, args);
1043 va_end(args);
1044
1045 DLINK_FOREACH(ptr, serv_list.head)
1046 {
1047 struct Client *client_p = ptr->data;
1048
1049 if (one != NULL && (client_p == one->from))
1050 continue;
1051 if (IsDefunct(client_p))
1052 continue;
1053
1054 send_message(client_p, uid_buffer);
1055 }
1056
1057 dbuf_ref_free(uid_buffer);
1058 }

Properties

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