ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/send.c
Revision: 3120
Committed: Fri Mar 7 21:52:54 2014 UTC (11 years, 5 months ago) by michael
Content type: text/x-csrc
File size: 28826 byte(s)
Log Message:
- Missed some of the parv[0] removal changes. Fixed.

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

Properties

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