ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/send.c
Revision: 2916
Committed: Sat Jan 25 21:09:18 2014 UTC (11 years, 7 months ago) by michael
Content type: text/x-csrc
File size: 30727 byte(s)
Log Message:
- Clean up all files in include/ (fixed indentation, removed whitespaces/tabs)
- Fixed copyright years

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

Properties

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