ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/send.c
Revision: 3164
Committed: Sat Mar 15 20:19:15 2014 UTC (11 years, 5 months ago) by michael
Content type: text/x-csrc
File size: 27693 byte(s)
Log Message:
- More client_p removal cleanups
- parse.c:handle_command: now no longer drop servers if the right
  amount of parameters isn't given

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

Properties

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