ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/send.c
Revision: 3135
Committed: Mon Mar 10 21:11:25 2014 UTC (11 years, 5 months ago) by michael
Content type: text/x-csrc
File size: 27867 byte(s)
Log Message:
- Server now no longer accepts TS5 links

File Contents

# User Rev Content
1 adx 30 /*
2 michael 2916 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 adx 30 *
4 michael 2916 * Copyright (c) 1997-2014 ircd-hybrid development team
5 adx 30 *
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 michael 2916 /*! \file send.c
23     * \brief Functions for sending messages.
24     * \version $Id$
25     */
26    
27 adx 30 #include "stdinc.h"
28 michael 1011 #include "list.h"
29 adx 30 #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 michael 1309 #include "conf.h"
40     #include "log.h"
41 adx 30 #include "memory.h"
42     #include "packet.h"
43    
44    
45 michael 1078 static unsigned int current_serial = 0;
46 adx 30
47    
48     /* send_format()
49     *
50 michael 3120 * inputs
51     * - buffer
52 adx 30 * - format pattern to use
53     * - var args
54     * output - number of bytes formatted output
55     * side effects - modifies sendbuf
56     */
57 michael 3107 static void
58     send_format(struct dbuf_block *buffer, const char *pattern, va_list args)
59 adx 30 {
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 michael 2638 * exceed 512 characters in length, counting all characters
66 adx 30 * 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 michael 3107 dbuf_put_args(buffer, pattern, args);
73 adx 30
74 michael 3107 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 adx 30 }
80    
81     /*
82     ** send_message
83     ** Internal utility which appends given buffer to the sockets
84     ** sendq.
85     */
86     static void
87 michael 3107 send_message(struct Client *to, struct dbuf_block *buf)
88 adx 30 {
89 michael 439 assert(!IsMe(to));
90 michael 438 assert(to != &me);
91 adx 30
92 michael 3107 if (dbuf_length(&to->localClient->buf_sendq) + buf->size > get_sendq(&to->localClient->confs))
93 adx 30 {
94     if (IsServer(to))
95 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
96 michael 1761 "Max SendQ limit exceeded for %s: %lu > %u",
97 adx 30 get_client_name(to, HIDE_IP),
98 michael 3107 (unsigned long)(dbuf_length(&to->localClient->buf_sendq) + buf->size),
99 michael 1632 get_sendq(&to->localClient->confs));
100 adx 30 if (IsClient(to))
101     SetSendQExceeded(to);
102     dead_link_on_write(to, 0);
103     return;
104     }
105 michael 2638
106 michael 3107 dbuf_add(&to->localClient->buf_sendq, buf);
107 adx 30
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 michael 2881 send_queued_write(to);
117 adx 30 }
118    
119     /* send_message_remote()
120     *
121     * inputs - pointer to client from message is being sent
122     * - pointer to client to send to
123 michael 3120 * - pointer to buffer
124 adx 30 * output - none
125     * side effects - Despite the function name, this only sends to directly
126     * connected clients.
127 michael 2916 *
128 adx 30 */
129     static void
130 michael 3107 send_message_remote(struct Client *to, struct Client *from, struct dbuf_block *buf)
131 adx 30 {
132 michael 3112 to = to->from;
133 michael 2793
134 adx 30 if (!MyConnect(to))
135     {
136 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
137 michael 2638 "Server send message to %s [%s] dropped from %s(Not local server)",
138     to->name, to->from->name, from->name);
139 adx 30 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 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
150 adx 30 "Send message to %s [%s] dropped from %s(Fake Dir)",
151     to->name, to->from->name, from->name);
152     return;
153     }
154    
155 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
156 adx 30 "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 michael 3135 sendto_server(NULL, NOCAPS, NOCAPS,
162 adx 30 ":%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 michael 1219 AddFlag(to, FLAGS_KILLED);
167 adx 30
168     if (IsClient(from))
169 michael 3109 sendto_one_numeric(from, &me, ERR_GHOSTEDCLIENT, to->name,
170     to->username, to->host, to->from);
171 adx 30
172     exit_client(to, &me, "Ghosted client");
173     return;
174 michael 2638 }
175 adx 30
176 michael 3107 send_message(to, buf);
177 adx 30 }
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 michael 2881 assert(fd == &client_p->localClient->fd);
187     send_queued_write(client_p);
188 adx 30 }
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 michael 2638 int retlen = 0;
200 adx 30
201     /*
202     ** Once socket is marked dead, we cannot start writing to it,
203     ** even if the error is removed...
204     */
205 michael 2881 if (IsDead(to))
206 adx 30 return; /* no use calling send() now */
207    
208     /* Next, lets try to write some data */
209 michael 3113 if (dbuf_length(&to->localClient->buf_sendq))
210 adx 30 {
211 michael 2638 do
212     {
213 michael 3113 struct dbuf_block *first = to->localClient->buf_sendq.blocks.head->data;
214 adx 30
215     #ifdef HAVE_LIBCRYPTO
216     if (to->localClient->fd.ssl)
217     {
218 michael 3113 retlen = SSL_write(to->localClient->fd.ssl, first->data + to->localClient->buf_sendq.pos, first->size - to->localClient->buf_sendq.pos);
219 adx 30
220     /* translate openssl error codes, sigh */
221 michael 2638 if (retlen < 0)
222     {
223     switch (SSL_get_error(to->localClient->fd.ssl, retlen))
224     {
225 adx 30 case SSL_ERROR_WANT_READ:
226 michael 2638 return; /* retry later, don't register for write events */
227     case SSL_ERROR_WANT_WRITE:
228     errno = EWOULDBLOCK;
229 adx 30 case SSL_ERROR_SYSCALL:
230 michael 2638 break;
231 michael 430 case SSL_ERROR_SSL:
232     if (errno == EAGAIN)
233     break;
234 adx 30 default:
235 michael 2638 retlen = errno = 0; /* either an SSL-specific error or EOF */
236     }
237     }
238 adx 30 }
239     else
240     #endif
241 michael 3113 retlen = send(to->localClient->fd.fd, first->data + to->localClient->buf_sendq.pos, first->size - to->localClient->buf_sendq.pos, 0);
242 adx 30
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 michael 3113 comm_setselect(&to->localClient->fd, COMM_SELECT_WRITE,
257     (PF *)sendq_unblocked, to, 0);
258 adx 30 }
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 michael 2638 send_queued_write(ptr->data);
283 adx 30
284     DLINK_FOREACH(ptr, unknown_list.head)
285 michael 2638 send_queued_write(ptr->data);
286 adx 30
287     DLINK_FOREACH(ptr, local_client_list.head)
288 michael 2638 send_queued_write(ptr->data);
289 adx 30
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 michael 3107 struct dbuf_block *buffer;
310 adx 30
311 michael 3112 to = to->from;
312    
313 adx 30 if (IsDead(to))
314 michael 3107 return; /* This socket has already been marked as dead */
315 adx 30
316 michael 3107 buffer = dbuf_alloc();
317    
318 adx 30 va_start(args, pattern);
319 michael 3107 send_format(buffer, pattern, args);
320 adx 30 va_end(args);
321    
322 michael 3107 send_message(to, buffer);
323    
324     dbuf_ref_free(buffer);
325 adx 30 }
326    
327 michael 3109 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 michael 3112 to = to->from;
335    
336 michael 3109 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 michael 3113 dbuf_put_fmt(buffer, ":%s %03d %s ", ID_or_name(from, to), numeric, dest);
346 michael 3109
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 michael 3110 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 michael 3112 to = to->from;
364    
365 michael 3110 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 michael 3113 dbuf_put_fmt(buffer, ":%s NOTICE %s ", ID_or_name(from, to), dest);
375 michael 3110
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 adx 30 /* 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 michael 1479 struct Channel *chptr, unsigned int type,
399 adx 30 const char *pattern, ...)
400     {
401 adx 285 va_list alocal, aremote, auid;
402 michael 3107 struct dbuf_block *local_buf, *remote_buf, *uid_buf;
403 michael 1078 dlink_node *ptr = NULL, *ptr_next = NULL;
404 adx 30
405 michael 3107 local_buf = dbuf_alloc(), remote_buf = dbuf_alloc(), uid_buf = dbuf_alloc();
406    
407 adx 30 if (IsServer(from))
408 michael 3113 dbuf_put_fmt(local_buf, ":%s ", from->name);
409 adx 30 else
410 michael 3113 dbuf_put_fmt(local_buf, ":%s!%s@%s ", from->name, from->username, from->host);
411 adx 30
412 michael 3113 dbuf_put_fmt(remote_buf, ":%s ", from->name);
413     dbuf_put_fmt(uid_buf, ":%s ", ID(from));
414 michael 3107
415 adx 285 va_start(alocal, pattern);
416     va_start(aremote, pattern);
417     va_start(auid, pattern);
418 michael 3107 send_format(local_buf, pattern, alocal);
419     send_format(remote_buf, pattern, aremote);
420     send_format(uid_buf, pattern, auid);
421 adx 285 va_end(auid);
422     va_end(aremote);
423     va_end(alocal);
424 adx 30
425     ++current_serial;
426    
427     DLINK_FOREACH_SAFE(ptr, ptr_next, chptr->members.head)
428     {
429 michael 1479 struct Membership *ms = ptr->data;
430     struct Client *target_p = ms->client_p;
431 adx 30
432 michael 1078 assert(IsClient(target_p));
433    
434 michael 1219 if (IsDefunct(target_p) || HasUMode(target_p, UMODE_DEAF) || target_p->from == one)
435 adx 30 continue;
436    
437 michael 1479 if (type != 0 && (ms->flags & type) == 0)
438     continue;
439    
440 michael 1078 if (MyConnect(target_p))
441 michael 3103 send_message(target_p, local_buf);
442     else if (target_p->from->localClient->serial != current_serial)
443     send_message_remote(target_p->from, from, remote_buf);
444     target_p->from->localClient->serial = current_serial;
445 adx 30 }
446 michael 3107
447     dbuf_ref_free(local_buf);
448     dbuf_ref_free(remote_buf);
449     dbuf_ref_free(uid_buf);
450 adx 30 }
451    
452     /* sendto_server()
453 michael 2916 *
454 adx 30 * inputs - pointer to client to NOT send to
455 db 939 * - pointer to channel
456 adx 30 * - caps or'd together which must ALL be present
457     * - caps or'd together which must ALL NOT be present
458     * - printf style format string
459     * - args to format string
460     * output - NONE
461     * side effects - Send a message to all connected servers, except the
462     * client 'one' (if non-NULL), as long as the servers
463     * support ALL capabs in 'caps', and NO capabs in 'nocaps'.
464 michael 2916 *
465 adx 30 * This function was written in an attempt to merge together the other
466     * billion sendto_*serv*() functions, which sprung up with capabs,
467     * lazylinks, uids, etc.
468     * -davidt
469     */
470 michael 2638 void
471 michael 1474 sendto_server(struct Client *one,
472 michael 1015 const unsigned int caps,
473     const unsigned int nocaps,
474 adx 30 const char *format, ...)
475     {
476     va_list args;
477 michael 885 dlink_node *ptr = NULL;
478 michael 3107 struct dbuf_block *buffer;
479 adx 30
480 michael 3107 buffer = dbuf_alloc();
481    
482 adx 30 va_start(args, format);
483 michael 3107 send_format(buffer, format, args);
484 adx 30 va_end(args);
485    
486     DLINK_FOREACH(ptr, serv_list.head)
487     {
488 michael 885 struct Client *client_p = ptr->data;
489 adx 30
490     /* If dead already skip */
491     if (IsDead(client_p))
492     continue;
493     /* check against 'one' */
494     if (one != NULL && (client_p == one->from))
495     continue;
496     /* check we have required capabs */
497     if ((client_p->localClient->caps & caps) != caps)
498     continue;
499     /* check we don't have any forbidden capabs */
500     if ((client_p->localClient->caps & nocaps) != 0)
501     continue;
502    
503 michael 3107 send_message(client_p, buffer);
504 adx 30 }
505 michael 3107
506     dbuf_ref_free(buffer);
507 adx 30 }
508    
509     /* sendto_common_channels_local()
510     *
511     * inputs - pointer to client
512     * - pattern to send
513     * output - NONE
514     * side effects - Sends a message to all people on local server who are
515 michael 2916 * in same channel with user.
516 adx 30 * used by m_nick.c and exit_one_client.
517     */
518     void
519 michael 1734 sendto_common_channels_local(struct Client *user, int touser, unsigned int cap,
520 adx 30 const char *pattern, ...)
521     {
522     va_list args;
523     dlink_node *uptr;
524     dlink_node *cptr;
525     struct Channel *chptr;
526     struct Membership *ms;
527     struct Client *target_p;
528 michael 3107 struct dbuf_block *buffer;
529 adx 30
530 michael 3107 buffer = dbuf_alloc();
531    
532 adx 30 va_start(args, pattern);
533 michael 3107 send_format(buffer, pattern, args);
534 adx 30 va_end(args);
535    
536     ++current_serial;
537    
538     DLINK_FOREACH(cptr, user->channel.head)
539     {
540 michael 2638 chptr = ((struct Membership *)cptr->data)->chptr;
541 adx 30 assert(chptr != NULL);
542    
543 michael 572 DLINK_FOREACH(uptr, chptr->members.head)
544 adx 30 {
545     ms = uptr->data;
546     target_p = ms->client_p;
547     assert(target_p != NULL);
548    
549 michael 572 if (!MyConnect(target_p) || target_p == user || IsDefunct(target_p) ||
550 michael 1078 target_p->localClient->serial == current_serial)
551 adx 30 continue;
552    
553 michael 1734 if (HasCap(target_p, cap) != cap)
554     continue;
555    
556 michael 1078 target_p->localClient->serial = current_serial;
557 michael 3107 send_message(target_p, buffer);
558 adx 30 }
559     }
560    
561     if (touser && MyConnect(user) && !IsDead(user) &&
562 michael 1078 user->localClient->serial != current_serial)
563 michael 1844 if (HasCap(user, cap) == cap)
564 michael 3107 send_message(user, buffer);
565    
566     dbuf_ref_free(buffer);
567 adx 30 }
568    
569     /* sendto_channel_local()
570     *
571     * inputs - member status mask, e.g. CHFL_CHANOP | CHFL_VOICE
572     * - whether to ignore +D clients (YES/NO)
573     * - pointer to channel to send to
574     * - var args pattern
575     * output - NONE
576     * side effects - Send a message to all members of a channel that are
577     * locally connected to this server.
578     */
579     void
580 michael 2543 sendto_channel_local(unsigned int type, int nodeaf, struct Channel *chptr,
581 adx 30 const char *pattern, ...)
582     {
583     va_list args;
584 michael 2638 dlink_node *ptr = NULL;
585 michael 3107 struct dbuf_block *buffer;
586 adx 30
587 michael 3107 buffer = dbuf_alloc();
588    
589 adx 30 va_start(args, pattern);
590 michael 3107 send_format(buffer, pattern, args);
591 adx 30 va_end(args);
592    
593 michael 572 DLINK_FOREACH(ptr, chptr->members.head)
594 adx 30 {
595 michael 2638 struct Membership *ms = ptr->data;
596     struct Client *target_p = ms->client_p;
597 adx 30
598     if (type != 0 && (ms->flags & type) == 0)
599     continue;
600    
601 michael 572 if (!MyConnect(target_p) || IsDefunct(target_p) ||
602 michael 1219 (nodeaf && HasUMode(target_p, UMODE_DEAF)))
603 adx 30 continue;
604    
605 michael 3107 send_message(target_p, buffer);
606 adx 30 }
607 michael 3107
608     dbuf_ref_free(buffer);
609 adx 30 }
610    
611     /* sendto_channel_local_butone()
612     *
613     * inputs - pointer to client to NOT send message to
614     * - member status mask, e.g. CHFL_CHANOP | CHFL_VOICE
615     * - pointer to channel to send to
616     * - var args pattern
617     * output - NONE
618     * side effects - Send a message to all members of a channel that are
619     * locally connected to this server except one.
620     *
621     * WARNING - +D clients are omitted
622     */
623 michael 2638 void
624 michael 2543 sendto_channel_local_butone(struct Client *one, unsigned int type, unsigned int cap,
625 michael 2638 struct Channel *chptr, const char *pattern, ...)
626 adx 30 {
627     va_list args;
628 michael 2638 dlink_node *ptr = NULL;
629 michael 3107 struct dbuf_block *buffer;
630 adx 30
631 michael 3107 buffer = dbuf_alloc();
632    
633 michael 2638 va_start(args, pattern);
634 michael 3107 send_format(buffer, pattern, args);
635 adx 30 va_end(args);
636    
637 michael 2638 DLINK_FOREACH(ptr, chptr->members.head)
638     {
639     struct Membership *ms = ptr->data;
640     struct Client *target_p = ms->client_p;
641 adx 30
642     if (type != 0 && (ms->flags & type) == 0)
643     continue;
644    
645 michael 572 if (!MyConnect(target_p) || target_p == one ||
646 michael 1219 IsDefunct(target_p) || HasUMode(target_p, UMODE_DEAF))
647 adx 30 continue;
648 michael 1734
649     if (HasCap(target_p, cap) != cap)
650 michael 2638 continue;
651    
652 michael 3107 send_message(target_p, buffer);
653 adx 30 }
654 michael 3107
655     dbuf_ref_free(buffer);
656 adx 30 }
657    
658     /*
659     ** match_it() and sendto_match_butone() ARE only used
660     ** to send a msg to all ppl on servers/hosts that match a specified mask
661     ** (used for enhanced PRIVMSGs) for opers
662     **
663     ** addition -- Armin, 8jun90 (gruner@informatik.tu-muenchen.de)
664     **
665     */
666    
667     /* match_it()
668     *
669     * inputs - client pointer to match on
670     * - actual mask to match
671     * - what to match on, HOST or SERVER
672     * output - 1 or 0 if match or not
673     * side effects - NONE
674     */
675     static int
676 michael 2867 match_it(const struct Client *one, const char *mask, unsigned int what)
677 adx 30 {
678     if (what == MATCH_HOST)
679 michael 1652 return !match(mask, one->host);
680 adx 30
681 michael 1652 return !match(mask, one->servptr->name);
682 adx 30 }
683    
684     /* sendto_match_butone()
685     *
686     * Send to all clients which match the mask in a way defined on 'what';
687     * either by user hostname or user servername.
688     *
689     * ugh. ONLY used by m_message.c to send an "oper magic" message. ugh.
690     */
691     void
692     sendto_match_butone(struct Client *one, struct Client *from, char *mask,
693     int what, const char *pattern, ...)
694     {
695 adx 285 va_list alocal, aremote;
696 michael 3107 dlink_node *ptr = NULL, *ptr_next = NULL;
697     struct dbuf_block *local_buf, *remote_buf;
698 adx 30
699 michael 3107 local_buf = dbuf_alloc(), remote_buf = dbuf_alloc();
700    
701 michael 3113 dbuf_put_fmt(local_buf, ":%s!%s@%s ", from->name, from->username, from->host);
702     dbuf_put_fmt(remote_buf, ":%s ", from->name);
703 michael 3107
704 adx 285 va_start(alocal, pattern);
705     va_start(aremote, pattern);
706 michael 3107 send_format(local_buf, pattern, alocal);
707     send_format(remote_buf, pattern, aremote);
708 adx 285 va_end(aremote);
709     va_end(alocal);
710 adx 30
711     /* scan the local clients */
712     DLINK_FOREACH(ptr, local_client_list.head)
713     {
714 michael 3107 struct Client *client_p = ptr->data;
715 adx 30
716     if (client_p != one && !IsDefunct(client_p) &&
717     match_it(client_p, mask, what))
718 michael 3107 send_message(client_p, local_buf);
719 adx 30 }
720    
721     /* Now scan servers */
722     DLINK_FOREACH_SAFE(ptr, ptr_next, serv_list.head)
723     {
724 michael 3107 struct Client *client_p = ptr->data;
725 adx 30
726     /*
727     * The old code looped through every client on the
728     * network for each server to check if the
729     * server (client_p) has at least 1 client matching
730     * the mask, using something like:
731     *
732     * for (target_p = GlobalClientList; target_p; target_p = target_p->next)
733     * if (IsRegisteredUser(target_p) &&
734     * match_it(target_p, mask, what) &&
735     * (target_p->from == client_p))
736     * vsendto_prefix_one(client_p, from, pattern, args);
737     *
738     * That way, we wouldn't send the message to
739     * a server who didn't have a matching client.
740     * However, on a network such as EFNet, that
741     * code would have looped through about 50
742     * servers, and in each loop, loop through
743     * about 50k clients as well, calling match()
744     * in each nested loop. That is a very bad
745     * thing cpu wise - just send the message
746     * to every connected server and let that
747     * server deal with it.
748     * -wnder
749     */
750     if (client_p != one && !IsDefunct(client_p))
751 michael 3107 send_message_remote(client_p, from, remote_buf);
752 adx 30 }
753 michael 3107
754     dbuf_ref_free(local_buf);
755     dbuf_ref_free(remote_buf);
756 adx 30 }
757    
758     /* sendto_match_servs()
759     *
760     * inputs - source client
761     * - mask to send to
762     * - capab needed
763     * - data
764     * outputs - none
765     * side effects - data sent to servers matching with capab
766     */
767     void
768 michael 2543 sendto_match_servs(struct Client *source_p, const char *mask, unsigned int cap,
769 adx 30 const char *pattern, ...)
770     {
771     va_list args;
772 michael 2638 dlink_node *ptr = NULL;
773 michael 3135 struct dbuf_block *buff_suid;
774 adx 30
775 michael 3135 buff_suid = dbuf_alloc();
776 michael 3107
777 adx 30 va_start(args, pattern);
778 michael 3113 dbuf_put_fmt(buff_suid, ":%s ", ID(source_p));
779 michael 3107 dbuf_put_args(buff_suid, pattern, args);
780 adx 30 va_end(args);
781    
782 michael 948 ++current_serial;
783 adx 30
784     DLINK_FOREACH(ptr, global_serv_list.head)
785     {
786 michael 2638 struct Client *target_p = ptr->data;
787 adx 30
788     /* Do not attempt to send to ourselves, or the source */
789     if (IsMe(target_p) || target_p->from == source_p->from)
790     continue;
791    
792 michael 1078 if (target_p->from->localClient->serial == current_serial)
793 adx 30 continue;
794    
795 michael 1652 if (!match(mask, target_p->name))
796 adx 30 {
797     /*
798     * if we set the serial here, then we'll never do a
799     * match() again, if !IsCapable()
800     */
801 michael 1078 target_p->from->localClient->serial = current_serial;
802 adx 30
803     if (!IsCapable(target_p->from, cap))
804     continue;
805    
806 michael 3135 send_message_remote(target_p->from, source_p, buff_suid);
807 adx 30 }
808     }
809 michael 3107
810     dbuf_ref_free(buff_suid);
811 adx 30 }
812    
813     /* sendto_anywhere()
814     *
815     * inputs - pointer to dest client
816     * - pointer to from client
817     * - varags
818     * output - NONE
819     * side effects - less efficient than sendto_remote and sendto_one
820     * but useful when one does not know where target "lives"
821     */
822     void
823     sendto_anywhere(struct Client *to, struct Client *from,
824 michael 2793 const char *command,
825 adx 30 const char *pattern, ...)
826     {
827     va_list args;
828 michael 3107 struct dbuf_block *buffer;
829 adx 30
830 michael 2793 if (IsDead(to->from))
831 adx 30 return;
832    
833 michael 3107 buffer = dbuf_alloc();
834    
835 adx 30 if (MyClient(to))
836     {
837     if (IsServer(from))
838 michael 3113 dbuf_put_fmt(buffer, ":%s %s %s ", from->name, command, to->name);
839 adx 30 else
840 michael 3113 dbuf_put_fmt(buffer, ":%s!%s@%s %s %s ", from->name, from->username, from->host, command, to->name);
841 adx 30 }
842 michael 2634 else
843 michael 3113 dbuf_put_fmt(buffer, ":%s %s %s ", ID_or_name(from, to), command, ID_or_name(to, to));
844 adx 30
845     va_start(args, pattern);
846 michael 3107 send_format(buffer, pattern, args);
847 adx 30 va_end(args);
848    
849 michael 2518 if (MyClient(to))
850 michael 3107 send_message(to, buffer);
851 adx 30 else
852 michael 3107 send_message_remote(to, from, buffer);
853    
854     dbuf_ref_free(buffer);
855 adx 30 }
856    
857     /* sendto_realops_flags()
858     *
859     * inputs - flag types of messages to show to real opers
860     * - flag indicating opers/admins
861     * - var args input message
862     * output - NONE
863     * side effects - Send to *local* ops only but NOT +s nonopers.
864     */
865     void
866 michael 1618 sendto_realops_flags(unsigned int flags, int level, int type, const char *pattern, ...)
867 adx 30 {
868 michael 1618 const char *ntype = NULL;
869 michael 1078 dlink_node *ptr = NULL;
870 adx 30 char nbuf[IRCD_BUFSIZE];
871     va_list args;
872    
873     va_start(args, pattern);
874 michael 1618 vsnprintf(nbuf, sizeof(nbuf), pattern, args);
875 adx 30 va_end(args);
876    
877 michael 1618 switch (type)
878 adx 30 {
879 michael 1618 case SEND_NOTICE:
880     ntype = "Notice";
881     break;
882     case SEND_GLOBAL:
883     ntype = "Global";
884     break;
885     case SEND_LOCOPS:
886     ntype = "LocOps";
887     break;
888     default:
889     assert(0);
890 adx 30 }
891    
892 michael 1206 DLINK_FOREACH(ptr, oper_list.head)
893     {
894     struct Client *client_p = ptr->data;
895 michael 1618 assert(HasUMode(client_p, UMODE_OPER));
896 michael 1206
897 michael 1618 /*
898     * If we're sending it to opers and they're an admin, skip.
899     * If we're sending it to admins, and they're not, skip.
900 michael 1206 */
901 michael 1219 if (((level == L_ADMIN) && !HasUMode(client_p, UMODE_ADMIN)) ||
902 michael 2638 ((level == L_OPER) && HasUMode(client_p, UMODE_ADMIN)))
903 michael 1206 continue;
904    
905 michael 1219 if (HasUMode(client_p, flags))
906 michael 1618 sendto_one(client_p, ":%s NOTICE %s :*** %s -- %s",
907     me.name, client_p->name, ntype, nbuf);
908 michael 1206 }
909     }
910    
911 adx 30 /* sendto_wallops_flags()
912     *
913     * inputs - flag types of messages to show to real opers
914     * - client sending request
915     * - var args input message
916     * output - NONE
917     * side effects - Send a wallops to local opers
918     */
919     void
920     sendto_wallops_flags(unsigned int flags, struct Client *source_p,
921     const char *pattern, ...)
922     {
923 michael 1078 dlink_node *ptr = NULL;
924 adx 30 va_list args;
925 michael 3107 struct dbuf_block *buffer;
926 adx 30
927 michael 3107 buffer = dbuf_alloc();
928    
929 adx 30 if (IsClient(source_p))
930 michael 3113 dbuf_put_fmt(buffer, ":%s!%s@%s WALLOPS :", source_p->name, source_p->username, source_p->host);
931 adx 30 else
932 michael 3113 dbuf_put_fmt(buffer, ":%s WALLOPS :", source_p->name);
933 adx 30
934     va_start(args, pattern);
935 michael 3107 send_format(buffer, pattern, args);
936 adx 30 va_end(args);
937    
938     DLINK_FOREACH(ptr, oper_list.head)
939     {
940 michael 1078 struct Client *client_p = ptr->data;
941 adx 30 assert(client_p->umodes & UMODE_OPER);
942    
943 michael 1219 if (HasUMode(client_p, flags) && !IsDefunct(client_p))
944 michael 3107 send_message(client_p, buffer);
945 adx 30 }
946 michael 3107
947     dbuf_ref_free(buffer);
948 adx 30 }
949    
950     /* ts_warn()
951     *
952     * inputs - var args message
953     * output - NONE
954     * side effects - Call sendto_realops_flags, with some flood checking
955     * (at most 5 warnings every 5 seconds)
956     */
957     void
958 michael 3078 sendto_realops_flags_ratelimited(const char *pattern, ...)
959 adx 30 {
960     va_list args;
961 michael 1078 char buffer[IRCD_BUFSIZE];
962 adx 30 static time_t last = 0;
963     static int warnings = 0;
964    
965     /*
966     ** if we're running with TS_WARNINGS enabled and someone does
967     ** something silly like (remotely) connecting a nonTS server,
968     ** we'll get a ton of warnings, so we make sure we don't send
969     ** more than 5 every 5 seconds. -orabidoo
970     */
971    
972     if (CurrentTime - last < 5)
973     {
974     if (++warnings > 5)
975     return;
976     }
977     else
978     {
979     last = CurrentTime;
980     warnings = 0;
981     }
982    
983     va_start(args, pattern);
984 michael 1086 vsnprintf(buffer, sizeof(buffer), pattern, args);
985 adx 30 va_end(args);
986    
987 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE, "%s", buffer);
988 michael 1247 ilog(LOG_TYPE_IRCD, "%s", buffer);
989 adx 30 }
990    
991     /* kill_client()
992     *
993     * inputs - client to send kill towards
994     * - pointer to client to kill
995     * - reason for kill
996     * output - NONE
997     * side effects - NONE
998     */
999     void
1000     kill_client(struct Client *client_p, struct Client *diedie,
1001     const char *pattern, ...)
1002     {
1003     va_list args;
1004 michael 3107 struct dbuf_block *buffer;
1005 adx 30
1006 michael 3120 client_p = client_p->from;
1007    
1008 adx 30 if (IsDead(client_p))
1009     return;
1010    
1011 michael 3107 buffer = dbuf_alloc();
1012 adx 30
1013 michael 3113 dbuf_put_fmt(buffer, ":%s KILL %s :",
1014     ID_or_name(&me, client_p),
1015     ID_or_name(diedie, client_p));
1016 michael 3107
1017 adx 30 va_start(args, pattern);
1018 michael 3107 send_format(buffer, pattern, args);
1019 adx 30 va_end(args);
1020    
1021 michael 3107 send_message(client_p, buffer);
1022    
1023     dbuf_ref_free(buffer);
1024 adx 30 }
1025    
1026     /* kill_client_ll_serv_butone()
1027     *
1028     * inputs - pointer to client to not send to
1029     * - pointer to client to kill
1030     * output - NONE
1031     * side effects - Send a KILL for the given client
1032     * message to all connected servers
1033     * except the client 'one'. Also deal with
1034     * client being unknown to leaf, as in lazylink...
1035     */
1036     void
1037 michael 2565 kill_client_serv_butone(struct Client *one, struct Client *source_p,
1038     const char *pattern, ...)
1039 adx 30 {
1040     va_list args;
1041 michael 885 dlink_node *ptr = NULL;
1042 michael 3135 struct dbuf_block *uid_buffer = dbuf_alloc();
1043 adx 30
1044 adx 285 va_start(args, pattern);
1045 michael 3135 dbuf_put_fmt(uid_buffer, ":%s KILL %s :", ID(&me), ID(source_p));
1046     send_format(uid_buffer, pattern, args);
1047 adx 30 va_end(args);
1048    
1049     DLINK_FOREACH(ptr, serv_list.head)
1050     {
1051 michael 885 struct Client *client_p = ptr->data;
1052 adx 30
1053     if (one != NULL && (client_p == one->from))
1054     continue;
1055     if (IsDefunct(client_p))
1056     continue;
1057    
1058 michael 3135 send_message(client_p, uid_buffer);
1059 adx 30 }
1060 michael 3107
1061     dbuf_ref_free(uid_buffer);
1062 michael 2638 }

Properties

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