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

Properties

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