ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/send.c
Revision: 1206
Committed: Wed Aug 24 21:41:23 2011 UTC (14 years ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/send.c
File size: 32843 byte(s)
Log Message:
- Implement GLOBOPS
- remove debugging code from parse.c

File Contents

# User Rev Content
1 adx 30 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * send.c: Functions for sending messages.
4     *
5     * Copyright (C) 2002 by the past and present ircd coders, and others.
6     *
7     * This program is free software; you can redistribute it and/or modify
8     * it under the terms of the GNU General Public License as published by
9     * the Free Software Foundation; either version 2 of the License, or
10     * (at your option) any later version.
11     *
12     * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20     * USA
21     *
22 knight 31 * $Id$
23 adx 30 */
24    
25     #include "stdinc.h"
26 michael 1011 #include "list.h"
27 adx 30 #include "send.h"
28     #include "channel.h"
29     #include "client.h"
30     #include "common.h"
31     #include "dbuf.h"
32     #include "irc_string.h"
33     #include "ircd.h"
34     #include "handlers.h"
35     #include "numeric.h"
36     #include "fdlist.h"
37     #include "s_bsd.h"
38     #include "s_serv.h"
39     #include "sprintf_irc.h"
40     #include "s_conf.h"
41     #include "s_log.h"
42     #include "memory.h"
43     #include "hook.h"
44     #include "packet.h"
45    
46    
47     struct Callback *iosend_cb = NULL;
48     struct Callback *iosendctrl_cb = NULL;
49 michael 1078 static unsigned int current_serial = 0;
50 adx 30
51    
52     /* send_format()
53     *
54     * inputs - buffer to format into
55     * - size of the buffer
56     * - format pattern to use
57     * - var args
58     * output - number of bytes formatted output
59     * side effects - modifies sendbuf
60     */
61     static inline int
62     send_format(char *lsendbuf, int bufsize, const char *pattern, va_list args)
63     {
64     int len;
65    
66     /*
67     * from rfc1459
68     *
69     * IRC messages are always lines of characters terminated with a CR-LF
70     * (Carriage Return - Line Feed) pair, and these messages shall not
71     * exceed 512 characters in length, counting all characters
72     * including the trailing CR-LF.
73     * Thus, there are 510 characters maximum allowed
74     * for the command and its parameters. There is no provision for
75     * continuation message lines. See section 7 for more details about
76     * current implementations.
77     */
78     len = vsnprintf(lsendbuf, bufsize - 1, pattern, args);
79     if (len > bufsize - 2)
80     len = bufsize - 2; /* required by some versions of vsnprintf */
81    
82     lsendbuf[len++] = '\r';
83     lsendbuf[len++] = '\n';
84 michael 1078 return len;
85 adx 30 }
86    
87     /*
88 adx 163 * iosend_default - append a packet to the client's sendq.
89     */
90     void *
91     iosend_default(va_list args)
92     {
93     struct Client *to = va_arg(args, struct Client *);
94     int length = va_arg(args, int);
95     char *buf = va_arg(args, char *);
96    
97     dbuf_put(&to->localClient->buf_sendq, buf, length);
98     return NULL;
99     }
100    
101     /*
102 adx 30 ** send_message
103     ** Internal utility which appends given buffer to the sockets
104     ** sendq.
105     */
106     static void
107     send_message(struct Client *to, char *buf, int len)
108     {
109 michael 439 assert(!IsMe(to));
110 michael 438 assert(to != &me);
111 adx 30
112     if (dbuf_length(&to->localClient->buf_sendq) + len > get_sendq(to))
113     {
114     if (IsServer(to))
115     sendto_realops_flags(UMODE_ALL, L_ALL,
116     "Max SendQ limit exceeded for %s: %lu > %lu",
117     get_client_name(to, HIDE_IP),
118     (unsigned long)(dbuf_length(&to->localClient->buf_sendq) + len),
119     get_sendq(to));
120     if (IsClient(to))
121     SetSendQExceeded(to);
122     dead_link_on_write(to, 0);
123     return;
124     }
125    
126 adx 163 execute_callback(iosend_cb, to, len, buf);
127 adx 30
128     /*
129     ** Update statistics. The following is slightly incorrect
130     ** because it counts messages even if queued, but bytes
131     ** only really sent. Queued bytes get updated in SendQueued.
132     */
133     ++to->localClient->send.messages;
134     ++me.localClient->send.messages;
135    
136     if (dbuf_length(&to->localClient->buf_sendq) >
137     (IsServer(to) ? (unsigned int) 1024 : (unsigned int) 4096))
138     send_queued_write(to);
139     }
140    
141     /* send_message_remote()
142     *
143     * inputs - pointer to client from message is being sent
144     * - pointer to client to send to
145     * - pointer to preformatted buffer
146     * - length of input buffer
147     * output - none
148     * side effects - Despite the function name, this only sends to directly
149     * connected clients.
150     *
151     */
152     static void
153     send_message_remote(struct Client *to, struct Client *from,
154     char *buf, int len)
155     {
156     if (!MyConnect(to))
157     {
158     sendto_realops_flags(UMODE_ALL, L_ALL,
159     "server send message to %s [%s] dropped from %s(Not local server)",
160     to->name, to->from->name, from->name);
161     return;
162     }
163    
164     /* Optimize by checking if (from && to) before everything */
165     /* we set to->from up there.. */
166    
167     if (!MyClient(from) && IsClient(to) && (to == from->from))
168     {
169     if (IsServer(from))
170     {
171     sendto_realops_flags(UMODE_ALL, L_ALL,
172     "Send message to %s [%s] dropped from %s(Fake Dir)",
173     to->name, to->from->name, from->name);
174     return;
175     }
176    
177     sendto_realops_flags(UMODE_ALL, L_ALL,
178     "Ghosted: %s[%s@%s] from %s[%s@%s] (%s)",
179     to->name, to->username, to->host,
180     from->name, from->username, from->host,
181     to->from->name);
182    
183 michael 885 sendto_server(NULL, NULL, CAP_TS6, NOCAPS,
184 adx 30 ":%s KILL %s :%s (%s[%s@%s] Ghosted %s)",
185     me.id, to->name, me.name, to->name,
186     to->username, to->host, to->from->name);
187 michael 885 sendto_server(NULL, NULL, NOCAPS, CAP_TS6,
188 adx 30 ":%s KILL %s :%s (%s[%s@%s] Ghosted %s)",
189     me.name, to->name, me.name, to->name,
190     to->username, to->host, to->from->name);
191    
192     SetKilled(to);
193    
194     if (IsClient(from))
195     sendto_one(from, form_str(ERR_GHOSTEDCLIENT),
196     me.name, from->name, to->name, to->username,
197     to->host, to->from);
198    
199     exit_client(to, &me, "Ghosted client");
200    
201     return;
202     }
203    
204     send_message(to, buf, len);
205     }
206    
207     /*
208     ** sendq_unblocked
209     ** Called when a socket is ready for writing.
210     */
211     void
212     sendq_unblocked(fde_t *fd, struct Client *client_p)
213     {
214     ClearSendqBlocked(client_p);
215     /* let send_queued_write be executed by send_queued_all */
216    
217     #ifdef HAVE_LIBCRYPTO
218     if (fd->flags.pending_read)
219     {
220     fd->flags.pending_read = 0;
221     read_packet(fd, client_p);
222     }
223     #endif
224     }
225    
226     /*
227     ** slinkq_unblocked
228     ** Called when a server control socket is ready for writing.
229     */
230     static void
231     slinkq_unblocked(fde_t *fd, struct Client *client_p)
232     {
233     ClearSlinkqBlocked(client_p);
234     send_queued_slink_write(client_p);
235     }
236    
237     /*
238     ** send_queued_write
239     ** This is called when there is a chance that some output would
240     ** be possible. This attempts to empty the send queue as far as
241     ** possible, and then if any data is left, a write is rescheduled.
242     */
243     void
244     send_queued_write(struct Client *to)
245     {
246     int retlen;
247     struct dbuf_block *first;
248    
249     /*
250     ** Once socket is marked dead, we cannot start writing to it,
251     ** even if the error is removed...
252     */
253     if (IsDead(to) || IsSendqBlocked(to))
254     return; /* no use calling send() now */
255    
256     /* Next, lets try to write some data */
257    
258     if (dbuf_length(&to->localClient->buf_sendq))
259     {
260     do {
261     first = to->localClient->buf_sendq.blocks.head->data;
262    
263     #ifdef HAVE_LIBCRYPTO
264     if (to->localClient->fd.ssl)
265     {
266     retlen = SSL_write(to->localClient->fd.ssl, first->data, first->size);
267    
268     /* translate openssl error codes, sigh */
269     if (retlen < 0)
270     switch (SSL_get_error(to->localClient->fd.ssl, retlen))
271     {
272     case SSL_ERROR_WANT_READ:
273     return; /* retry later, don't register for write events */
274    
275     case SSL_ERROR_WANT_WRITE:
276     errno = EWOULDBLOCK;
277     case SSL_ERROR_SYSCALL:
278     break;
279 michael 430 case SSL_ERROR_SSL:
280     if (errno == EAGAIN)
281     break;
282 adx 30 default:
283     retlen = errno = 0; /* either an SSL-specific error or EOF */
284     }
285     }
286     else
287     #endif
288     retlen = send(to->localClient->fd.fd, first->data, first->size, 0);
289    
290     if (retlen <= 0)
291     break;
292    
293     dbuf_delete(&to->localClient->buf_sendq, retlen);
294    
295     /* We have some data written .. update counters */
296     to->localClient->send.bytes += retlen;
297     me.localClient->send.bytes += retlen;
298     } while (dbuf_length(&to->localClient->buf_sendq));
299    
300     if ((retlen < 0) && (ignoreErrno(errno)))
301     {
302     /* we have a non-fatal error, reschedule a write */
303     SetSendqBlocked(to);
304     comm_setselect(&to->localClient->fd, COMM_SELECT_WRITE,
305     (PF *)sendq_unblocked, (void *)to, 0);
306     }
307     else if (retlen <= 0)
308     {
309     dead_link_on_write(to, errno);
310     return;
311     }
312     }
313     }
314    
315     /*
316     ** send_queued_slink_write
317     ** This is called when there is a chance the some output would
318     ** be possible. This attempts to empty the send queue as far as
319     ** possible, and then if any data is left, a write is rescheduled.
320     */
321     void
322     send_queued_slink_write(struct Client *to)
323     {
324     int retlen;
325    
326     /*
327     ** Once socket is marked dead, we cannot start writing to it,
328     ** even if the error is removed...
329     */
330     if (IsDead(to) || IsSlinkqBlocked(to))
331     return; /* no use calling send() now */
332    
333     /* Next, lets try to write some data */
334     if (to->localClient->slinkq != NULL)
335     {
336     retlen = send(to->localClient->ctrlfd.fd,
337     to->localClient->slinkq + to->localClient->slinkq_ofs,
338     to->localClient->slinkq_len, 0);
339     if (retlen < 0)
340     {
341     /* If we have a fatal error */
342     if (!ignoreErrno(errno))
343     {
344     dead_link_on_write(to, errno);
345     return;
346     }
347     }
348     else if (retlen == 0)
349     {
350     /* 0 bytes is an EOF .. */
351     dead_link_on_write(to, 0);
352     return;
353     }
354     else
355     {
356     execute_callback(iosendctrl_cb, to, retlen,
357     to->localClient->slinkq + to->localClient->slinkq_ofs);
358     to->localClient->slinkq_len -= retlen;
359    
360     assert(to->localClient->slinkq_len >= 0);
361     if (to->localClient->slinkq_len)
362     to->localClient->slinkq_ofs += retlen;
363     else
364     {
365     to->localClient->slinkq_ofs = 0;
366     MyFree(to->localClient->slinkq);
367     to->localClient->slinkq = NULL;
368     }
369     }
370    
371     /* Finally, if we have any more data, reschedule a write */
372     if (to->localClient->slinkq_len)
373     {
374     SetSlinkqBlocked(to);
375     comm_setselect(&to->localClient->ctrlfd, COMM_SELECT_WRITE,
376     (PF *)slinkq_unblocked, (void *)to, 0);
377     }
378     }
379     }
380    
381     /* send_queued_all()
382     *
383     * input - NONE
384     * output - NONE
385     * side effects - try to flush sendq of each client
386     */
387     void
388     send_queued_all(void)
389     {
390     dlink_node *ptr;
391    
392     /* Servers are processed first, mainly because this can generate
393     * a notice to opers, which is to be delivered by this function.
394     */
395     DLINK_FOREACH(ptr, serv_list.head)
396     send_queued_write((struct Client *) ptr->data);
397    
398     DLINK_FOREACH(ptr, unknown_list.head)
399     send_queued_write((struct Client *) ptr->data);
400    
401     DLINK_FOREACH(ptr, local_client_list.head)
402     send_queued_write((struct Client *) ptr->data);
403    
404     /* NOTE: This can still put clients on aborted_list; unfortunately,
405     * exit_aborted_clients takes precedence over send_queued_all,
406     * because exiting clients can generate server/oper traffic.
407     * The easiest approach is dealing with aborted clients in the next I/O lap.
408     * -adx
409     */
410     }
411    
412     /* sendto_one()
413     *
414     * inputs - pointer to destination client
415     * - var args message
416     * output - NONE
417     * side effects - send message to single client
418     */
419     void
420     sendto_one(struct Client *to, const char *pattern, ...)
421     {
422     va_list args;
423     char buffer[IRCD_BUFSIZE];
424     int len;
425    
426     if (to->from != NULL)
427     to = to->from;
428     if (IsDead(to))
429     return; /* This socket has already been marked as dead */
430    
431     va_start(args, pattern);
432     len = send_format(buffer, IRCD_BUFSIZE, pattern, args);
433     va_end(args);
434    
435     send_message(to, buffer, len);
436     }
437    
438     /* sendto_channel_butone()
439     *
440     * inputs - pointer to client(server) to NOT send message to
441     * - pointer to client that is sending this message
442     * - pointer to channel being sent to
443     * - vargs message
444     * output - NONE
445     * side effects - message as given is sent to given channel members.
446     *
447     * WARNING - +D clients are ignored
448     */
449     void
450     sendto_channel_butone(struct Client *one, struct Client *from,
451     struct Channel *chptr, const char *command,
452     const char *pattern, ...)
453     {
454 adx 285 va_list alocal, aremote, auid;
455 adx 30 char local_buf[IRCD_BUFSIZE];
456     char remote_buf[IRCD_BUFSIZE];
457     char uid_buf[IRCD_BUFSIZE];
458     int local_len, remote_len, uid_len;
459 michael 1078 dlink_node *ptr = NULL, *ptr_next = NULL;
460 adx 30
461     if (IsServer(from))
462     local_len = ircsprintf(local_buf, ":%s %s %s ",
463     from->name, command, chptr->chname);
464     else
465     local_len = ircsprintf(local_buf, ":%s!%s@%s %s %s ",
466     from->name, from->username, from->host,
467     command, chptr->chname);
468     remote_len = ircsprintf(remote_buf, ":%s %s %s ",
469     from->name, command, chptr->chname);
470     uid_len = ircsprintf(uid_buf, ":%s %s %s ",
471     ID(from), command, chptr->chname);
472    
473 adx 285 va_start(alocal, pattern);
474     va_start(aremote, pattern);
475     va_start(auid, pattern);
476 adx 30 local_len += send_format(&local_buf[local_len], IRCD_BUFSIZE - local_len,
477 adx 285 pattern, alocal);
478 adx 30 remote_len += send_format(&remote_buf[remote_len], IRCD_BUFSIZE - remote_len,
479 adx 285 pattern, aremote);
480 adx 30 uid_len += send_format(&uid_buf[uid_len], IRCD_BUFSIZE - uid_len, pattern,
481 adx 285 auid);
482     va_end(auid);
483     va_end(aremote);
484     va_end(alocal);
485 adx 30
486     ++current_serial;
487    
488     DLINK_FOREACH_SAFE(ptr, ptr_next, chptr->members.head)
489     {
490 michael 1078 struct Client *target_p = ((struct Membership *)ptr->data)->client_p;
491 adx 30
492 michael 1078 assert(IsClient(target_p));
493    
494 adx 30 if (IsDefunct(target_p) || IsDeaf(target_p) || target_p->from == one)
495     continue;
496    
497 michael 1078 if (MyConnect(target_p))
498 adx 30 {
499 michael 1078 if (target_p->localClient->serial != current_serial)
500 adx 30 {
501     send_message(target_p, local_buf, local_len);
502 michael 1078 target_p->localClient->serial = current_serial;
503 adx 30 }
504     }
505     else
506     {
507     /* Now check whether a message has been sent to this
508     * remote link already
509     */
510 michael 1078 if (target_p->from->localClient->serial != current_serial)
511 adx 30 {
512     if (IsCapable(target_p->from, CAP_TS6))
513     send_message_remote(target_p->from, from, uid_buf, uid_len);
514     else
515     send_message_remote(target_p->from, from, remote_buf, remote_len);
516 michael 1078 target_p->from->localClient->serial = current_serial;
517 adx 30 }
518     }
519     }
520     }
521    
522     /* sendto_server()
523     *
524     * inputs - pointer to client to NOT send to
525 db 939 * - pointer to channel
526 adx 30 * - caps or'd together which must ALL be present
527     * - caps or'd together which must ALL NOT be present
528     * - printf style format string
529     * - args to format string
530     * output - NONE
531     * side effects - Send a message to all connected servers, except the
532     * client 'one' (if non-NULL), as long as the servers
533     * support ALL capabs in 'caps', and NO capabs in 'nocaps'.
534     *
535     * This function was written in an attempt to merge together the other
536     * billion sendto_*serv*() functions, which sprung up with capabs,
537     * lazylinks, uids, etc.
538     * -davidt
539     */
540     void
541 michael 1015 sendto_server(struct Client *one, const struct Channel *chptr,
542     const unsigned int caps,
543     const unsigned int nocaps,
544 adx 30 const char *format, ...)
545     {
546     va_list args;
547 michael 885 dlink_node *ptr = NULL;
548 adx 30 char buffer[IRCD_BUFSIZE];
549 michael 885 int len = 0;
550 adx 30
551 michael 885 if (chptr && chptr->chname[0] != '#')
552     return;
553 adx 30
554     va_start(args, format);
555     len = send_format(buffer, IRCD_BUFSIZE, format, args);
556     va_end(args);
557    
558     DLINK_FOREACH(ptr, serv_list.head)
559     {
560 michael 885 struct Client *client_p = ptr->data;
561 adx 30
562     /* If dead already skip */
563     if (IsDead(client_p))
564     continue;
565     /* check against 'one' */
566     if (one != NULL && (client_p == one->from))
567     continue;
568     /* check we have required capabs */
569     if ((client_p->localClient->caps & caps) != caps)
570     continue;
571     /* check we don't have any forbidden capabs */
572     if ((client_p->localClient->caps & nocaps) != 0)
573     continue;
574    
575     send_message(client_p, buffer, len);
576     }
577     }
578    
579     /* sendto_common_channels_local()
580     *
581     * inputs - pointer to client
582     * - pattern to send
583     * output - NONE
584     * side effects - Sends a message to all people on local server who are
585     * in same channel with user.
586     * used by m_nick.c and exit_one_client.
587     */
588     void
589     sendto_common_channels_local(struct Client *user, int touser,
590     const char *pattern, ...)
591     {
592     va_list args;
593     dlink_node *uptr;
594     dlink_node *cptr;
595     struct Channel *chptr;
596     struct Membership *ms;
597     struct Client *target_p;
598     char buffer[IRCD_BUFSIZE];
599     int len;
600    
601     va_start(args, pattern);
602     len = send_format(buffer, IRCD_BUFSIZE, pattern, args);
603     va_end(args);
604    
605     ++current_serial;
606    
607     DLINK_FOREACH(cptr, user->channel.head)
608     {
609     chptr = ((struct Membership *) cptr->data)->chptr;
610     assert(chptr != NULL);
611    
612 michael 572 DLINK_FOREACH(uptr, chptr->members.head)
613 adx 30 {
614     ms = uptr->data;
615     target_p = ms->client_p;
616     assert(target_p != NULL);
617    
618 michael 572 if (!MyConnect(target_p) || target_p == user || IsDefunct(target_p) ||
619 michael 1078 target_p->localClient->serial == current_serial)
620 adx 30 continue;
621    
622 michael 1078 target_p->localClient->serial = current_serial;
623 adx 30 send_message(target_p, buffer, len);
624     }
625     }
626    
627     if (touser && MyConnect(user) && !IsDead(user) &&
628 michael 1078 user->localClient->serial != current_serial)
629 adx 30 send_message(user, buffer, len);
630     }
631    
632     /* sendto_channel_local()
633     *
634     * inputs - member status mask, e.g. CHFL_CHANOP | CHFL_VOICE
635     * - whether to ignore +D clients (YES/NO)
636     * - pointer to channel to send to
637     * - var args pattern
638     * output - NONE
639     * side effects - Send a message to all members of a channel that are
640     * locally connected to this server.
641     */
642     void
643     sendto_channel_local(int type, int nodeaf, struct Channel *chptr,
644     const char *pattern, ...)
645     {
646     va_list args;
647     char buffer[IRCD_BUFSIZE];
648     int len;
649     dlink_node *ptr;
650     struct Membership *ms;
651     struct Client *target_p;
652    
653     va_start(args, pattern);
654     len = send_format(buffer, IRCD_BUFSIZE, pattern, args);
655     va_end(args);
656    
657 michael 572 DLINK_FOREACH(ptr, chptr->members.head)
658 adx 30 {
659     ms = ptr->data;
660     target_p = ms->client_p;
661    
662     if (type != 0 && (ms->flags & type) == 0)
663     continue;
664    
665 michael 572 if (!MyConnect(target_p) || IsDefunct(target_p) ||
666     (nodeaf && IsDeaf(target_p)))
667 adx 30 continue;
668    
669     send_message(target_p, buffer, len);
670     }
671     }
672    
673     /* sendto_channel_local_butone()
674     *
675     * inputs - pointer to client to NOT send message to
676     * - member status mask, e.g. CHFL_CHANOP | CHFL_VOICE
677     * - pointer to channel to send to
678     * - var args pattern
679     * output - NONE
680     * side effects - Send a message to all members of a channel that are
681     * locally connected to this server except one.
682     *
683     * WARNING - +D clients are omitted
684     */
685     void
686     sendto_channel_local_butone(struct Client *one, int type,
687     struct Channel *chptr, const char *pattern, ...)
688     {
689     va_list args;
690     char buffer[IRCD_BUFSIZE];
691     int len;
692     struct Client *target_p;
693     struct Membership *ms;
694     dlink_node *ptr;
695    
696     va_start(args, pattern);
697     len = send_format(buffer, IRCD_BUFSIZE, pattern, args);
698     va_end(args);
699    
700 michael 572 DLINK_FOREACH(ptr, chptr->members.head)
701 adx 30 {
702     ms = ptr->data;
703     target_p = ms->client_p;
704    
705     if (type != 0 && (ms->flags & type) == 0)
706     continue;
707    
708 michael 572 if (!MyConnect(target_p) || target_p == one ||
709     IsDefunct(target_p) || IsDeaf(target_p))
710 adx 30 continue;
711     send_message(target_p, buffer, len);
712     }
713     }
714    
715    
716     /* sendto_channel_remote()
717     *
718     * inputs - Client not to send towards
719     * - Client from whom message is from
720     * - member status mask, e.g. CHFL_CHANOP | CHFL_VOICE
721     * - pointer to channel to send to
722     * - var args pattern
723     * output - NONE
724     * side effects - Send a message to all members of a channel that are
725     * remote to this server.
726     */
727     void
728 michael 1015 sendto_channel_remote(struct Client *one, struct Client *from, int type,
729     const unsigned int caps, const unsigned int nocaps,
730     struct Channel *chptr, const char *pattern, ...)
731 adx 30 {
732     va_list args;
733     char buffer[IRCD_BUFSIZE];
734     int len;
735     dlink_node *ptr;
736     struct Client *target_p;
737     struct Membership *ms;
738    
739     va_start(args, pattern);
740     len = send_format(buffer, IRCD_BUFSIZE, pattern, args);
741     va_end(args);
742    
743 db 189 ++current_serial;
744    
745 adx 30 DLINK_FOREACH(ptr, chptr->members.head)
746     {
747     ms = ptr->data;
748     target_p = ms->client_p;
749    
750     if (type != 0 && (ms->flags & type) == 0)
751     continue;
752    
753     if (MyConnect(target_p))
754     continue;
755     target_p = target_p->from;
756    
757     if (target_p == one->from ||
758     ((target_p->from->localClient->caps & caps) != caps) ||
759     ((target_p->from->localClient->caps & nocaps) != 0))
760     continue;
761 michael 1078 if (target_p->from->localClient->serial != current_serial)
762 db 189 {
763     send_message(target_p, buffer, len);
764 michael 1078 target_p->from->localClient->serial = current_serial;
765 db 189 }
766 adx 30 }
767     }
768    
769     /*
770     ** match_it() and sendto_match_butone() ARE only used
771     ** to send a msg to all ppl on servers/hosts that match a specified mask
772     ** (used for enhanced PRIVMSGs) for opers
773     **
774     ** addition -- Armin, 8jun90 (gruner@informatik.tu-muenchen.de)
775     **
776     */
777    
778     /* match_it()
779     *
780     * inputs - client pointer to match on
781     * - actual mask to match
782     * - what to match on, HOST or SERVER
783     * output - 1 or 0 if match or not
784     * side effects - NONE
785     */
786     static int
787     match_it(const struct Client *one, const char *mask, int what)
788     {
789     if (what == MATCH_HOST)
790 michael 1078 return match(mask, one->host);
791 adx 30
792 michael 1078 return match(mask, one->servptr->name);
793 adx 30 }
794    
795     /* sendto_match_butone()
796     *
797     * Send to all clients which match the mask in a way defined on 'what';
798     * either by user hostname or user servername.
799     *
800     * ugh. ONLY used by m_message.c to send an "oper magic" message. ugh.
801     */
802     void
803     sendto_match_butone(struct Client *one, struct Client *from, char *mask,
804     int what, const char *pattern, ...)
805     {
806 adx 285 va_list alocal, aremote;
807 adx 30 struct Client *client_p;
808     dlink_node *ptr, *ptr_next;
809     char local_buf[IRCD_BUFSIZE], remote_buf[IRCD_BUFSIZE];
810     int local_len = ircsprintf(local_buf, ":%s!%s@%s ", from->name,
811     from->username, from->host);
812     int remote_len = ircsprintf(remote_buf, ":%s ", from->name);
813    
814 adx 285 va_start(alocal, pattern);
815     va_start(aremote, pattern);
816 adx 30 local_len += send_format(&local_buf[local_len], IRCD_BUFSIZE - local_len,
817 adx 285 pattern, alocal);
818 adx 30 remote_len += send_format(&remote_buf[remote_len], IRCD_BUFSIZE - remote_len,
819 adx 285 pattern, aremote);
820     va_end(aremote);
821     va_end(alocal);
822 adx 30
823     /* scan the local clients */
824     DLINK_FOREACH(ptr, local_client_list.head)
825     {
826     client_p = ptr->data;
827    
828     if (client_p != one && !IsDefunct(client_p) &&
829     match_it(client_p, mask, what))
830     send_message(client_p, local_buf, local_len);
831     }
832    
833     /* Now scan servers */
834     DLINK_FOREACH_SAFE(ptr, ptr_next, serv_list.head)
835     {
836     client_p = ptr->data;
837    
838     /*
839     * The old code looped through every client on the
840     * network for each server to check if the
841     * server (client_p) has at least 1 client matching
842     * the mask, using something like:
843     *
844     * for (target_p = GlobalClientList; target_p; target_p = target_p->next)
845     * if (IsRegisteredUser(target_p) &&
846     * match_it(target_p, mask, what) &&
847     * (target_p->from == client_p))
848     * vsendto_prefix_one(client_p, from, pattern, args);
849     *
850     * That way, we wouldn't send the message to
851     * a server who didn't have a matching client.
852     * However, on a network such as EFNet, that
853     * code would have looped through about 50
854     * servers, and in each loop, loop through
855     * about 50k clients as well, calling match()
856     * in each nested loop. That is a very bad
857     * thing cpu wise - just send the message
858     * to every connected server and let that
859     * server deal with it.
860     * -wnder
861     */
862     if (client_p != one && !IsDefunct(client_p))
863     send_message_remote(client_p, from, remote_buf, remote_len);
864     }
865     }
866    
867     /* sendto_match_servs()
868     *
869     * inputs - source client
870     * - mask to send to
871     * - capab needed
872     * - data
873     * outputs - none
874     * side effects - data sent to servers matching with capab
875     */
876     void
877     sendto_match_servs(struct Client *source_p, const char *mask, int cap,
878     const char *pattern, ...)
879     {
880     va_list args;
881     struct Client *target_p;
882     dlink_node *ptr;
883     char buffer[IRCD_BUFSIZE];
884     int found = 0;
885    
886     va_start(args, pattern);
887     vsnprintf(buffer, sizeof(buffer), pattern, args);
888     va_end(args);
889    
890 michael 948 ++current_serial;
891 adx 30
892     DLINK_FOREACH(ptr, global_serv_list.head)
893     {
894     target_p = ptr->data;
895    
896     /* Do not attempt to send to ourselves, or the source */
897     if (IsMe(target_p) || target_p->from == source_p->from)
898     continue;
899    
900 michael 1078 if (target_p->from->localClient->serial == current_serial)
901 adx 30 continue;
902    
903     if (match(mask, target_p->name))
904     {
905     /*
906     * if we set the serial here, then we'll never do a
907     * match() again, if !IsCapable()
908     */
909 michael 1078 target_p->from->localClient->serial = current_serial;
910 adx 30 found++;
911    
912     if (!IsCapable(target_p->from, cap))
913     continue;
914    
915     sendto_anywhere(target_p, source_p, "%s", buffer);
916     }
917     }
918     }
919    
920     /* sendto_anywhere()
921     *
922     * inputs - pointer to dest client
923     * - pointer to from client
924     * - varags
925     * output - NONE
926     * side effects - less efficient than sendto_remote and sendto_one
927     * but useful when one does not know where target "lives"
928     */
929     void
930     sendto_anywhere(struct Client *to, struct Client *from,
931     const char *pattern, ...)
932     {
933     va_list args;
934     char buffer[IRCD_BUFSIZE];
935     int len;
936     struct Client *send_to = (to->from != NULL ? to->from : to);
937    
938     if (IsDead(send_to))
939     return;
940    
941     if (MyClient(to))
942     {
943     if (IsServer(from))
944     {
945     if (IsCapable(to, CAP_TS6) && HasID(from))
946     len = ircsprintf(buffer, ":%s ", from->id);
947     else
948     len = ircsprintf(buffer, ":%s ", from->name);
949     }
950     else
951     len = ircsprintf(buffer, ":%s!%s@%s ",
952     from->name, from->username, from->host);
953     }
954     else len = ircsprintf(buffer, ":%s ", ID_or_name(from, send_to));
955    
956     va_start(args, pattern);
957     len += send_format(&buffer[len], IRCD_BUFSIZE - len, pattern, args);
958     va_end(args);
959    
960     if(MyClient(to))
961     send_message(send_to, buffer, len);
962     else
963     send_message_remote(send_to, from, buffer, len);
964     }
965    
966     /* sendto_realops_flags()
967     *
968     * inputs - flag types of messages to show to real opers
969     * - flag indicating opers/admins
970     * - var args input message
971     * output - NONE
972     * side effects - Send to *local* ops only but NOT +s nonopers.
973     */
974     void
975     sendto_realops_flags(unsigned int flags, int level, const char *pattern, ...)
976     {
977 michael 1078 dlink_node *ptr = NULL;
978 adx 30 char nbuf[IRCD_BUFSIZE];
979     va_list args;
980    
981     va_start(args, pattern);
982     vsnprintf(nbuf, IRCD_BUFSIZE, pattern, args);
983     va_end(args);
984    
985     DLINK_FOREACH(ptr, oper_list.head)
986     {
987 michael 1078 struct Client *client_p = ptr->data;
988 adx 30 assert(client_p->umodes & UMODE_OPER);
989    
990     /* If we're sending it to opers and theyre an admin, skip.
991     * If we're sending it to admins, and theyre not, skip.
992     */
993     if (((level == L_ADMIN) && !IsAdmin(client_p)) ||
994     ((level == L_OPER) && IsAdmin(client_p)))
995     continue;
996    
997     if (client_p->umodes & flags)
998     sendto_one(client_p, ":%s NOTICE %s :*** Notice -- %s",
999     me.name, client_p->name, nbuf);
1000     }
1001     }
1002    
1003 michael 1206 void
1004     sendto_globops_flags(unsigned int flags, int level, const char *pattern, ...)
1005     {
1006     dlink_node *ptr = NULL;
1007     char nbuf[IRCD_BUFSIZE];
1008     va_list args;
1009    
1010     va_start(args, pattern);
1011     vsnprintf(nbuf, IRCD_BUFSIZE, pattern, args);
1012     va_end(args);
1013    
1014     DLINK_FOREACH(ptr, oper_list.head)
1015     {
1016     struct Client *client_p = ptr->data;
1017     assert(client_p->umodes & UMODE_OPER);
1018    
1019     /* If we're sending it to opers and theyre an admin, skip.
1020     * If we're sending it to admins, and theyre not, skip.
1021     */
1022     if (((level == L_ADMIN) && !IsAdmin(client_p)) ||
1023     ((level == L_OPER) && IsAdmin(client_p)))
1024     continue;
1025    
1026     if (client_p->umodes & flags)
1027     sendto_one(client_p, ":%s NOTICE %s :*** Global -- %s",
1028     me.name, client_p->name, nbuf);
1029     }
1030     }
1031    
1032 adx 30 /* sendto_wallops_flags()
1033     *
1034     * inputs - flag types of messages to show to real opers
1035     * - client sending request
1036     * - var args input message
1037     * output - NONE
1038     * side effects - Send a wallops to local opers
1039     */
1040     void
1041     sendto_wallops_flags(unsigned int flags, struct Client *source_p,
1042     const char *pattern, ...)
1043     {
1044 michael 1078 dlink_node *ptr = NULL;
1045 adx 30 va_list args;
1046     char buffer[IRCD_BUFSIZE];
1047     int len;
1048    
1049     if (IsClient(source_p))
1050     len = ircsprintf(buffer, ":%s!%s@%s WALLOPS :",
1051     source_p->name, source_p->username, source_p->host);
1052     else
1053     len = ircsprintf(buffer, ":%s WALLOPS :", source_p->name);
1054    
1055     va_start(args, pattern);
1056     len += send_format(&buffer[len], IRCD_BUFSIZE - len, pattern, args);
1057     va_end(args);
1058    
1059     DLINK_FOREACH(ptr, oper_list.head)
1060     {
1061 michael 1078 struct Client *client_p = ptr->data;
1062 adx 30 assert(client_p->umodes & UMODE_OPER);
1063    
1064     if ((client_p->umodes & flags) && !IsDefunct(client_p))
1065     send_message(client_p, buffer, len);
1066     }
1067     }
1068    
1069     /* ts_warn()
1070     *
1071     * inputs - var args message
1072     * output - NONE
1073     * side effects - Call sendto_realops_flags, with some flood checking
1074     * (at most 5 warnings every 5 seconds)
1075     */
1076     void
1077     ts_warn(const char *pattern, ...)
1078     {
1079     va_list args;
1080 michael 1078 char buffer[IRCD_BUFSIZE];
1081 adx 30 static time_t last = 0;
1082     static int warnings = 0;
1083    
1084     /*
1085     ** if we're running with TS_WARNINGS enabled and someone does
1086     ** something silly like (remotely) connecting a nonTS server,
1087     ** we'll get a ton of warnings, so we make sure we don't send
1088     ** more than 5 every 5 seconds. -orabidoo
1089     */
1090    
1091     if (CurrentTime - last < 5)
1092     {
1093     if (++warnings > 5)
1094     return;
1095     }
1096     else
1097     {
1098     last = CurrentTime;
1099     warnings = 0;
1100     }
1101    
1102     va_start(args, pattern);
1103 michael 1086 vsnprintf(buffer, sizeof(buffer), pattern, args);
1104 adx 30 va_end(args);
1105    
1106     sendto_realops_flags(UMODE_ALL, L_ALL, "%s", buffer);
1107     ilog(L_CRIT, "%s", buffer);
1108     }
1109    
1110     /* kill_client()
1111     *
1112     * inputs - client to send kill towards
1113     * - pointer to client to kill
1114     * - reason for kill
1115     * output - NONE
1116     * side effects - NONE
1117     */
1118     void
1119     kill_client(struct Client *client_p, struct Client *diedie,
1120     const char *pattern, ...)
1121     {
1122     va_list args;
1123     char buffer[IRCD_BUFSIZE];
1124     int len;
1125    
1126     if (client_p->from != NULL)
1127     client_p = client_p->from;
1128     if (IsDead(client_p))
1129     return;
1130    
1131     len = ircsprintf(buffer, ":%s KILL %s :", ID_or_name(&me, client_p->from),
1132     ID_or_name(diedie, client_p));
1133    
1134     va_start(args, pattern);
1135     len += send_format(&buffer[len], IRCD_BUFSIZE - len, pattern, args);
1136     va_end(args);
1137    
1138     send_message(client_p, buffer, len);
1139     }
1140    
1141     /* kill_client_ll_serv_butone()
1142     *
1143     * inputs - pointer to client to not send to
1144     * - pointer to client to kill
1145     * output - NONE
1146     * side effects - Send a KILL for the given client
1147     * message to all connected servers
1148     * except the client 'one'. Also deal with
1149     * client being unknown to leaf, as in lazylink...
1150     */
1151     void
1152     kill_client_ll_serv_butone(struct Client *one, struct Client *source_p,
1153     const char *pattern, ...)
1154     {
1155     va_list args;
1156     int have_uid = 0;
1157 michael 885 dlink_node *ptr = NULL;
1158 adx 30 char buf_uid[IRCD_BUFSIZE], buf_nick[IRCD_BUFSIZE];
1159 michael 885 int len_uid = 0, len_nick = 0;
1160 adx 30
1161 michael 1115 if (HasID(source_p))
1162 adx 30 {
1163     have_uid = 1;
1164 adx 285 va_start(args, pattern);
1165 adx 30 len_uid = ircsprintf(buf_uid, ":%s KILL %s :", me.id, ID(source_p));
1166     len_uid += send_format(&buf_uid[len_uid], IRCD_BUFSIZE - len_uid, pattern,
1167     args);
1168 adx 285 va_end(args);
1169 adx 30 }
1170 adx 285
1171     va_start(args, pattern);
1172 adx 30 len_nick = ircsprintf(buf_nick, ":%s KILL %s :", me.name, source_p->name);
1173     len_nick += send_format(&buf_nick[len_nick], IRCD_BUFSIZE - len_nick, pattern,
1174     args);
1175     va_end(args);
1176    
1177     DLINK_FOREACH(ptr, serv_list.head)
1178     {
1179 michael 885 struct Client *client_p = ptr->data;
1180 adx 30
1181     if (one != NULL && (client_p == one->from))
1182     continue;
1183     if (IsDefunct(client_p))
1184     continue;
1185    
1186 michael 885 if (have_uid && IsCapable(client_p, CAP_TS6))
1187     send_message(client_p, buf_uid, len_uid);
1188     else
1189     send_message(client_p, buf_nick, len_nick);
1190 adx 30 }
1191     }

Properties

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