ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/send.c
Revision: 3113
Committed: Thu Mar 6 22:19:29 2014 UTC (11 years, 5 months ago) by michael
Content type: text/x-csrc
File size: 28945 byte(s)
Log Message:
- Update dbuf.h, dbuf.c

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

Properties

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