ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/send.c
Revision: 3110
Committed: Thu Mar 6 20:33:17 2014 UTC (11 years, 5 months ago) by michael
Content type: text/x-csrc
File size: 28873 byte(s)
Log Message:
- Added sendto_one_notice()

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

Properties

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