]> jfr.im git - irc.git/blame - software/ircd/www.irc.org/ftp/irc/org/irc2.11.2p3/common/send.c
init
[irc.git] / software / ircd / www.irc.org / ftp / irc / org / irc2.11.2p3 / common / send.c
CommitLineData
3bd189cb
JR
1/*
2 * IRC - Internet Relay Chat, common/send.c
3 * Copyright (C) 1990 Jarkko Oikarinen and
4 * University of Oulu, Computing Center
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 1, or (at your option)
9 * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21#ifndef lint
22static const volatile char rcsid[] = "@(#)$Id: send.c,v 1.108 2008/06/08 17:17:10 chopin Exp $";
23#endif
24
25#include "os.h"
26#include "s_defines.h"
27#define SEND_C
28#include "s_externs.h"
29#undef SEND_C
30
31static char sendbuf[2048];
32
33
34static void vsendto_prefix_one(aClient *, aClient *, char *, va_list);
35static char psendbuf[2048];
36static int sentalong[MAXCONNECTIONS];
37
38/*
39** dead_link
40** An error has been detected. The link *must* be closed,
41** but *cannot* call ExitClient (m_bye) from here.
42** Instead, mark it with FLAGS_DEADSOCK. This should
43** generate ExitClient from the main loop.
44**
45** The notice is skipped for "uninteresting" cases,
46** like Persons and yet unknown connections...
47*/
48static int dead_link(aClient *to, char *pattern, ...)
49{
50 char notice[BUFSIZE];
51 va_list va;
52
53 va_start(va, pattern);
54 vsprintf(notice, pattern, va);
55 va_end(va);
56
57 SetDead(to);
58 /*
59 * If because of BUFFERPOOL problem then clean dbufs now so that
60 * notices don't hurt operators below.
61 */
62 DBufClear(&to->recvQ);
63 DBufClear(&to->sendQ);
64 if (!IsPerson(to) && !IsUnknown(to) && !(to->flags & FLAGS_CLOSING))
65 sendto_flag(SCH_ERROR, notice);
66 Debug((DEBUG_ERROR, notice));
67 return -1;
68}
69
70/*
71** flush_fdary
72** Used to empty all output buffers for connections in fdary.
73*/
74void flush_fdary(FdAry *fdp)
75{
76 int i;
77 aClient *cptr;
78
79 for (i = 0; i <= fdp->highest; i++)
80 {
81 if (!(cptr = local[fdp->fd[i]]))
82 continue;
83 if (!IsRegistered(cptr)) /* is this needed?? -kalt */
84 continue;
85 if (DBufLength(&cptr->sendQ) > 0)
86 (void)send_queued(cptr);
87 }
88}
89
90/*
91** flush_connections
92** Used to empty all output buffers for all connections. Should only
93** be called once per scan of connections. There should be a select in
94** here perhaps but that means either forcing a timeout or doing a poll.
95** When flushing, all we do is empty the obuffer array for each local
96** client and try to send it. if we can't send it, it goes into the sendQ
97** -avalon
98*/
99void flush_connections(int fd)
100{
101 Reg int i;
102 Reg aClient *cptr;
103
104 if (fd == me.fd)
105 {
106 for (i = highest_fd; i >= 0; i--)
107 if ((cptr = local[i]) && DBufLength(&cptr->sendQ) > 0)
108 (void)send_queued(cptr);
109 }
110 else if (fd >= 0 && (cptr = local[fd]) && DBufLength(&cptr->sendQ) > 0)
111 (void)send_queued(cptr);
112}
113
114/*
115** send_message
116** Internal utility which delivers one message buffer to the
117** socket. Takes care of the error handling and buffering, if
118** needed.
119** if ZIP_LINKS is defined, the message will eventually be compressed,
120** anything stored in the sendQ is compressed.
121**
122** If msg is a null pointer, we are flushing connection
123*/
124int send_message(aClient *to, char *msg, int len)
125{
126 int i;
127
128 Debug((DEBUG_SEND,"Sending %s %d [%s] ", to->name, to->fd, msg));
129
130 if (to->from)
131 to = to->from;
132 if (to->fd < 0)
133 {
134 Debug((DEBUG_ERROR,
135 "Local socket %s with negative fd... AARGH!",
136 to->name));
137 }
138 if (IsMe(to))
139 {
140 sendto_flag(SCH_ERROR, "Trying to send to myself! [%s]", msg);
141 return 0;
142 }
143 if (IsDead(to))
144 return 0; /* This socket has already been marked as dead */
145 if (DBufLength(&to->sendQ) > (i=get_sendq(to, CBurst(to))))
146 {
147 to->exitc = EXITC_SENDQ;
148 if (IsService(to) || IsServer(to))
149 {
150 return dead_link(to,
151 "Max SendQ limit exceeded for %s: %d > %d",
152 get_client_name(to, FALSE),
153 DBufLength(&to->sendQ), i);
154 }
155 return dead_link(to, "Max Sendq exceeded");
156 }
157# ifdef ZIP_LINKS
158 /*
159 ** data is first stored in to->zip->outbuf until
160 ** it's big enough to be compressed and stored in the sendq.
161 ** send_queued is then responsible to never let the sendQ
162 ** be empty and to->zip->outbuf not empty.
163 */
164 if (to->flags & FLAGS_ZIP)
165 msg = zip_buffer(to, msg, &len, 0);
166
167# endif /* ZIP_LINKS */
168tryagain:
169 if (len && (i = dbuf_put(&to->sendQ, msg, len)) < 0)
170 {
171 if (i == -2 /* Poolsize was exceeded. */
172#ifdef POOLSIZE_LIMITED
173 /*
174 ** Defining this retains old ircd behaviour (will
175 ** allow client quit with buffer allocation error
176 ** as a result of poolsize starvation). As it may
177 ** happen to all clients on a big channel without
178 ** their fault, I think this is not right.
179 ** In the long run it should not matter (poolsize
180 ** or memory usage-wise), because if client lacks
181 ** the poolsize, the poolsize is too small anyway
182 ** and next netburst would probably make it grow.
183 ** IMO increasing poolsize with no limits is good
184 ** for clients -- hence this is not defined. --B.
185 */
186 && CBurst(to)
187#endif
188 )
189 {
190 /* Anyway, 10% increase. */
191 poolsize *= 1.1;
192 sendto_flag(SCH_NOTICE,
193 "New poolsize %u. (reached)",
194 poolsize);
195 istat.is_dbufmore++;
196 goto tryagain;
197 }
198 else
199 {
200 to->exitc = EXITC_MBUF;
201 return dead_link(to,
202 "Buffer allocation error for %s",
203 get_client_name(to, FALSE));
204 }
205 }
206 /*
207 ** Update statistics. The following is slightly incorrect
208 ** because it counts messages even if queued, but bytes
209 ** only really sent. Queued bytes get updated in SendQueued.
210 */
211 to->sendM += 1;
212 me.sendM += 1;
213 if (to->acpt != &me)
214 to->acpt->sendM += 1;
215 /*
216 ** This little bit is to stop the sendQ from growing too large when
217 ** there is no need for it to. Thus we call send_queued() every time
218 ** 2k has been added to the queue since the last non-fatal write.
219 ** Also stops us from deliberately building a large sendQ and then
220 ** trying to flood that link with data (possible during the net
221 ** relinking done by servers with a large load).
222 */
223 if (DBufLength(&to->sendQ)/1024 > to->lastsq)
224 send_queued(to);
225 return 0;
226}
227
228/*
229** send_queued
230** This function is called from the main select-loop (or whatever)
231** when there is a chance the some output would be possible. This
232** attempts to empty the send queue as far as possible...
233*/
234int send_queued(aClient *to)
235{
236 char *msg;
237 int len, rlen, more = 0;
238 aClient *bysptr = NULL;
239
240 /*
241 ** Once socket is marked dead, we cannot start writing to it,
242 ** even if the error is removed...
243 */
244 if (IsDead(to))
245 {
246 /*
247 ** Actually, we should *NEVER* get here--something is
248 ** not working correct if send_queued is called for a
249 ** dead socket... --msa
250 */
251 return -1;
252 }
253#ifdef ZIP_LINKS
254 /*
255 ** Here, we must make sure than nothing will be left in to->zip->outbuf
256 ** This buffer needs to be compressed and sent if all the sendQ is sent
257 */
258 if ((to->flags & FLAGS_ZIP) && to->zip->outcount)
259 {
260 if (DBufLength(&to->sendQ) > 0)
261 more = 1;
262 else
263 {
264 msg = zip_buffer(to, NULL, &len, 1);
265
266 if (len == -1)
267 return dead_link(to,
268 "fatal error in zip_buffer()");
269
270 if (dbuf_put(&to->sendQ, msg, len) < 0)
271 {
272 to->exitc = EXITC_MBUF;
273 return dead_link(to,
274 "Buffer allocation error for %s",
275 get_client_name(to, FALSE));
276 }
277 }
278 }
279#endif
280 while (DBufLength(&to->sendQ) > 0 || more)
281 {
282 msg = dbuf_map(&to->sendQ, &len);
283 /* Returns always len > 0 */
284 if ((rlen = deliver_it(to, msg, len)) < 0)
285 {
286 if ( (IsConnecting(to) || IsHandshake(to))
287 && to->serv && to->serv->byuid[0])
288 {
289 bysptr = find_uid(to->serv->byuid, NULL);
290 if (bysptr && !MyConnect(bysptr))
291 {
292 sendto_one(bysptr, ":%s NOTICE %s :"
293 "Write error (%s) to %s, closing link",
294 ME, bysptr->name, strerror(-rlen),
295 to->name);
296 }
297 }
298 return dead_link(to,
299 "Write error (%s) to %s, closing link",
300 strerror(-rlen), get_client_name(to, FALSE));
301 }
302 (void)dbuf_delete(&to->sendQ, rlen);
303 to->lastsq = DBufLength(&to->sendQ)/1024;
304 if (rlen < len) /* ..or should I continue until rlen==0? */
305 break;
306
307#ifdef ZIP_LINKS
308 if (DBufLength(&to->sendQ) == 0 && more)
309 {
310 /*
311 ** The sendQ is now empty, compress what's left
312 ** uncompressed and try to send it too
313 */
314 more = 0;
315 msg = zip_buffer(to, NULL, &len, 1);
316
317 if (len == -1)
318 return dead_link(to,
319 "fatal error in zip_buffer()");
320
321 if (dbuf_put(&to->sendQ, msg, len) < 0)
322 {
323 to->exitc = EXITC_MBUF;
324 return dead_link(to,
325 "Buffer allocation error for %s",
326 get_client_name(to, FALSE));
327 }
328 }
329#endif
330 }
331
332 return (IsDead(to)) ? -1 : 0;
333}
334
335
336static anUser ausr;
337static aClient anon;
338
339void initanonymous(void)
340{
341 memset(&ausr, 0, sizeof(anUser));
342 strcpy(ausr.username, "anonymous");
343 strcpy(ausr.uid, "0ANONYM");
344 strcpy(ausr.host, "anonymous.");
345 ausr.server = "anonymous.";
346
347 memset(&anon, 0, sizeof(aClient));
348 anon.user = &ausr;
349 anon.from = &anon;
350 anon.fd = -2;
351 anon.status = STAT_CLIENT;
352 anon.name = anon.namebuf;
353 strcpy(anon.namebuf, "anonymous");
354 strcpy(anon.username, "anonymous");
355 anon.info = "anonymous identity hider";
356 anon.exitc = EXITC_UNDEF;
357}
358
359/*
360 * sendprep: takes care of building the string according to format & args
361 */
362static int vsendprep(char *pattern, va_list va)
363{
364 int len;
365
366 Debug((DEBUG_L10, "sendprep(%s)", pattern));
367 len = vsprintf(sendbuf, pattern, va);
368 if (len > 510)
369#ifdef IRCII_KLUDGE
370 len = 511;
371#else
372 len = 510;
373 sendbuf[len++] = '\r';
374#endif
375 sendbuf[len++] = '\n';
376 sendbuf[len] = '\0';
377 return len;
378}
379
380/*
381 * sendpreprep: takes care of building the string according to format & args,
382 * and of adding a complete prefix if necessary
383 */
384static int vsendpreprep(aClient *to, aClient *from, char *pattern, va_list va)
385{
386 int len;
387
388 Debug((DEBUG_L10, "sendpreprep(%#x(%s),%#x(%s),%s)",
389 to, to->name, from, from->name, pattern));
390 if (to && from && MyClient(to) && IsPerson(from) &&
391 !strncmp(pattern, ":%s", 3))
392 {
393 char *par = va_arg(va, char *);
394
395 if (from == &anon || !mycmp(par, from->name))
396 {
397 len = sprintf(psendbuf, ":%s!%s@%s", from->name,
398 from->user->username, from->user->host);
399 }
400 else
401 {
402 len = sprintf(psendbuf, ":%s", par);
403 }
404
405 len += vsprintf(psendbuf+len, pattern+3, va);
406 }
407 else
408 len = vsprintf(psendbuf, pattern, va);
409
410 if (len > 510)
411#ifdef IRCII_KLUDGE
412 len = 511;
413#else
414 len = 510;
415 psendbuf[len++] = '\r';
416#endif
417 psendbuf[len++] = '\n';
418 psendbuf[len] = '\0';
419 return len;
420}
421
422/*
423** send message to single client
424*/
425int vsendto_one(aClient *to, char *pattern, va_list va)
426{
427 int len;
428
429 len = vsendprep(pattern, va);
430
431 (void)send_message(to, sendbuf, len);
432 return len;
433}
434
435int sendto_one(aClient *to, char *pattern, ...)
436{
437 int len;
438 va_list va;
439 va_start(va, pattern);
440 len = vsendto_one(to, pattern, va);
441 va_end(va);
442 return len;
443}
444
445/*
446 * sendto_channel_butone
447 *
448 * Send a message to all members of a channel that are connected to this
449 * server except client 'one'.
450 */
451void sendto_channel_butone(aClient *one, aClient *from, aChannel *chptr,
452 char *pattern, ...)
453{
454 Reg Link *lp;
455 Reg aClient *acptr, *lfrm = from;
456 int len1, len2 = 0;
457
458 if (IsAnonymous(chptr) && IsClient(from))
459 {
460 lfrm = &anon;
461 }
462
463 if (one != from && MyConnect(from) && IsRegisteredUser(from))
464 {
465 /* useless junk? */ /* who said that and why? --B. */
466 va_list va;
467 va_start(va, pattern);
468 vsendto_prefix_one(from, from, pattern, va);
469 va_end(va);
470 }
471
472 {
473 va_list va;
474 va_start(va, pattern);
475 len1 = vsendprep(pattern, va);
476 va_end(va);
477 }
478
479
480 for (lp = chptr->clist; lp; lp = lp->next)
481 {
482 acptr = lp->value.cptr;
483 if (acptr->from == one || IsMe(acptr))
484 continue; /* ...was the one I should skip */
485 if (MyConnect(acptr) && IsRegisteredUser(acptr))
486 {
487 if (!len2)
488 {
489 va_list va;
490 va_start(va, pattern);
491 len2 = vsendpreprep(acptr, lfrm, pattern, va);
492 va_end(va);
493 }
494
495 if (acptr != from)
496 (void)send_message(acptr, psendbuf, len2);
497 }
498 else
499 (void)send_message(acptr, sendbuf, len1);
500 }
501 return;
502}
503
504/*
505 * sendto_server_butone
506 *
507 * Send a message to all connected servers except the client 'one'.
508 */
509void sendto_serv_butone(aClient *one, char *pattern, ...)
510{
511 Reg int i, len=0;
512 Reg aClient *cptr;
513
514 for (i = fdas.highest; i >= 0; i--)
515 if ((cptr = local[fdas.fd[i]]) &&
516 (!one || cptr != one->from) && !IsMe(cptr)) {
517 if (!len)
518 {
519 va_list va;
520 va_start(va, pattern);
521 len = vsendprep(pattern, va);
522 va_end(va);
523 }
524 (void)send_message(cptr, sendbuf, len);
525 }
526 return;
527}
528
529int sendto_serv_v(aClient *one, int ver, char *pattern, ...)
530{
531 Reg int i, len=0, rc=0;
532 Reg aClient *cptr;
533
534 for (i = fdas.highest; i >= 0; i--)
535 {
536 if ((cptr = local[fdas.fd[i]]) &&
537 (!one || cptr != one->from) && !IsMe(cptr))
538 {
539#if 0
540/* We're not using it for now, so just save some cpu.
541** Revive once we need it --B. */
542 if ((cptr->serv->version & ver) == 0)
543 {
544 rc = 1;
545 continue;
546 }
547#endif
548 if (!len)
549 {
550 va_list va;
551 va_start(va, pattern);
552 len = vsendprep(pattern, va);
553 va_end(va);
554 }
555 (void)send_message(cptr, sendbuf, len);
556 }
557 }
558
559 return rc;
560}
561
562#if 0
563/* We're not using it for now, so just save some cpu.
564** Revive once we need it --B. */
565int sendto_serv_notv(aClient *one, int ver, char *pattern, ...)
566{
567 Reg int i, len=0, rc=0;
568 Reg aClient *cptr;
569
570 for (i = fdas.highest; i >= 0; i--)
571 {
572 if ((cptr = local[fdas.fd[i]]) &&
573 (!one || cptr != one->from) && !IsMe(cptr))
574 {
575 if ((cptr->serv->version & ver) == 0)
576 {
577 if (!len)
578 {
579 va_list va;
580 va_start(va, pattern);
581 len = vsendprep(pattern, va);
582 va_end(va);
583 }
584
585 (void)send_message(cptr, sendbuf, len);
586 }
587 else
588 {
589 rc = 1;
590 }
591 }
592 }
593
594 return rc;
595}
596#endif
597
598/*
599 * sendto_common_channels()
600 *
601 * Sends a message to all people (inclusing user) on local server who are
602 * in same channel with user, except for channels set Quiet or Anonymous
603 * The calling procedure must take the necessary steps for such channels.
604 */
605void sendto_common_channels(aClient *user, char *pattern, ...)
606{
607 Reg int i;
608 Reg aClient *cptr;
609 Reg Link *channels, *lp;
610 int len = 0;
611
612/* This is kind of funky, but should work. The first part below
613 is optimized for HUB servers or servers with few clients on
614 them. The second part is optimized for bigger client servers
615 where looping through the whole client list is bad. I'm not
616 really certain of the point at which each function equals
617 out...but I do know the 2nd part will help big client servers
618 fairly well... - Comstud 97/04/24
619*/
620
621 if (highest_fd < 50) /* This part optimized for HUB servers... */
622 {
623 if (MyConnect(user))
624 {
625 va_list va;
626 va_start(va, pattern);
627 len = vsendpreprep(user, user, pattern, va);
628 va_end(va);
629 (void)send_message(user, psendbuf, len);
630 }
631 for (i = 0; i <= highest_fd; i++)
632 {
633 if (!(cptr = local[i]) || IsServer(cptr) ||
634 user == cptr || !user->user)
635 continue;
636 for (lp = user->user->channel; lp; lp = lp->next)
637 {
638 if (!IsMember(cptr, lp->value.chptr))
639 continue;
640 if (IsAnonymous(lp->value.chptr))
641 continue;
642 if (!IsQuiet(lp->value.chptr))
643 {
644#ifndef DEBUGMODE
645 if (!len) /* This saves little cpu,
646 but breaks the debug code.. */
647#endif
648 {
649 va_list va;
650 va_start(va, pattern);
651 len = vsendpreprep(cptr, user, pattern, va);
652 va_end(va);
653 }
654 (void)send_message(cptr, psendbuf,
655 len);
656 break;
657 }
658 }
659 }
660 }
661 else
662 {
663 /* This part optimized for client servers */
664 bzero((char *)&sentalong[0], sizeof(int) * MAXCONNECTIONS);
665 if (MyConnect(user))
666 {
667 va_list va;
668 va_start(va, pattern);
669 len = vsendpreprep(user, user, pattern, va);
670 va_end(va);
671 (void)send_message(user, psendbuf, len);
672 sentalong[user->fd] = 1;
673 }
674 if (!user->user)
675 return;
676 for (channels=user->user->channel; channels;
677 channels=channels->next)
678 {
679 if (IsQuiet(channels->value.chptr))
680 continue;
681 if (IsAnonymous(channels->value.chptr))
682 continue;
683 for (lp=channels->value.chptr->clist;lp;
684 lp=lp->next)
685 {
686 cptr = lp->value.cptr;
687 if (user == cptr)
688 continue;
689 if (!cptr->user || sentalong[cptr->fd])
690 continue;
691 sentalong[cptr->fd]++;
692#ifndef DEBUGMODE
693 if (!len) /* This saves little cpu,
694 but breaks the debug code.. */
695#endif
696 {
697 va_list va;
698 va_start(va, pattern);
699 len = vsendpreprep(cptr, user, pattern, va);
700 va_end(va);
701 }
702 (void)send_message(cptr, psendbuf, len);
703 }
704 }
705 }
706 return;
707}
708
709/*
710 * sendto_channel_butserv
711 *
712 * Send a message to all members of a channel that are connected to this
713 * server.
714 */
715void sendto_channel_butserv(aChannel *chptr, aClient *from, char *pattern, ...)
716{
717 Reg Link *lp;
718 Reg aClient *acptr, *lfrm = from;
719 int len = 0;
720
721 if (MyClient(from))
722 { /* Always send to the client itself */
723 va_list va;
724 va_start(va, pattern);
725 vsendto_prefix_one(from, from, pattern, va);
726 va_end(va);
727 if (IsQuiet(chptr)) /* Really shut up.. */
728 return;
729 }
730 if (IsAnonymous(chptr) && IsClient(from))
731 {
732 lfrm = &anon;
733 }
734
735 for (lp = chptr->clist; lp; lp = lp->next)
736 if (MyClient(acptr = lp->value.cptr) && acptr != from)
737 {
738 if (!len)
739 {
740 va_list va;
741 va_start(va, pattern);
742 len = vsendpreprep(acptr, lfrm, pattern, va);
743 va_end(va);
744 }
745 (void)send_message(acptr, psendbuf, len);
746 }
747
748 return;
749}
750
751/*
752** send a msg to all ppl on servers/hosts that match a specified mask
753** (used for enhanced PRIVMSGs)
754**
755** addition -- Armin, 8jun90 (gruner@informatik.tu-muenchen.de)
756*/
757
758static int match_it(aClient *one, char *mask, int what)
759{
760 switch (what)
761 {
762 case MATCH_HOST:
763 return (match(mask, one->user->host)==0);
764 case MATCH_SERVER:
765 default:
766 return (match(mask, one->user->server)==0);
767 }
768}
769
770/*
771 * sendto_match_servs
772 *
773 * send to all servers which match the mask at the end of a channel name
774 * (if there is a mask present) or to all if no mask.
775 */
776void sendto_match_servs(aChannel *chptr, aClient *from, char *format, ...)
777{
778 Reg int i, len=0;
779 Reg aClient *cptr;
780 char *mask;
781
782 if (chptr)
783 {
784 if (*chptr->chname == '&')
785 return;
786 if ((mask = get_channelmask(chptr->chname)))
787 mask++;
788 }
789 else
790 mask = (char *)NULL;
791
792 for (i = fdas.highest; i >= 0; i--)
793 {
794 if (!(cptr = local[fdas.fd[i]]) || (cptr == from) ||
795 IsMe(cptr))
796 continue;
797 if (!BadPtr(mask) && match(mask, cptr->name))
798 continue;
799#ifdef JAPANESE
800 if (!jp_valid(cptr, chptr, 0))
801 continue;
802#endif
803 if (!len)
804 {
805 va_list va;
806 va_start(va, format);
807 len = vsendprep(format, va);
808 va_end(va);
809 }
810 (void)send_message(cptr, sendbuf, len);
811 }
812}
813
814int sendto_match_servs_v(aChannel *chptr, aClient *from, int ver,
815 char *format, ...)
816{
817 Reg int i, len=0, rc=0;
818 Reg aClient *cptr;
819 char *mask;
820
821 if (chptr)
822 {
823 if (*chptr->chname == '&')
824 return 0;
825 if ((mask = get_channelmask(chptr->chname)))
826 mask++;
827 }
828 else
829 mask = (char *)NULL;
830
831 for (i = fdas.highest; i >= 0; i--)
832 {
833 if (!(cptr = local[fdas.fd[i]]) || (cptr == from) ||
834 IsMe(cptr))
835 continue;
836 if (!BadPtr(mask) && match(mask, cptr->name))
837 continue;
838#ifdef JAPANESE
839 if (!jp_valid(cptr, chptr, 0))
840 continue;
841#endif
842
843#if 0
844/* We're not using it for now, so just save some cpu.
845** Revive once we need it --B. */
846 if ((ver & cptr->serv->version) == 0)
847 {
848 rc = 1;
849 continue;
850 }
851#endif
852 if (!len)
853 {
854 va_list va;
855 va_start(va, format);
856 len = vsendprep(format, va);
857 va_end(va);
858 }
859 (void)send_message(cptr, sendbuf, len);
860 }
861 return rc;
862}
863
864#if 0
865/* We're not using it for now, so just save some cpu.
866** Revive once we need it --B. */
867int sendto_match_servs_notv(aChannel *chptr, aClient *from, int ver,
868 char *format, ...)
869{
870 Reg int i, len=0, rc=0;
871 Reg aClient *cptr;
872 char *mask;
873
874 if (chptr)
875 {
876 if (*chptr->chname == '&')
877 return 0;
878 if ((mask = get_channelmask(chptr->chname)))
879 mask++;
880 }
881 else
882 mask = (char *)NULL;
883
884 for (i = fdas.highest; i >= 0; i--)
885 {
886 if (!(cptr = local[fdas.fd[i]]) || (cptr == from) ||
887 IsMe(cptr))
888 continue;
889 if (!BadPtr(mask) && match(mask, cptr->name))
890 continue;
891#ifdef JAPANESE
892 if (!jp_valid(cptr, chptr, 0))
893 continue;
894#endif
895 if ((ver & cptr->serv->version) != 0)
896 {
897 rc = 1;
898 continue;
899 }
900 if (!len)
901 {
902 va_list va;
903 va_start(va, format);
904 len = vsendprep(format, va);
905 va_end(va);
906 }
907 (void)send_message(cptr, sendbuf, len);
908 }
909 return rc;
910}
911#endif
912
913/*
914 * sendto_match_butone
915 *
916 * Send to all clients which match the mask in a way defined on 'what';
917 * either by user hostname or user servername.
918 */
919void sendto_match_butone(aClient *one, aClient *from, char *mask, int what,
920 char *pattern, ...)
921{
922 int i;
923 aClient *cptr,
924 *srch;
925
926 for (i = 0; i <= highest_fd; i++)
927 {
928 if (!(cptr = local[i]))
929 continue; /* that clients are not mine */
930 if (cptr == one) /* must skip the origin !! */
931 continue;
932 if (IsServer(cptr))
933 {
934 /*
935 ** we can save some CPU here by not searching the
936 ** entire list of users since it is ordered!
937 ** original idea/code from pht.
938 ** it could be made better by looping on the list of
939 ** servers to avoid non matching blocks in the list
940 ** (srch->from != cptr), but then again I never
941 ** bothered to worry or optimize this routine -kalt
942 */
943 for (srch = cptr->prev; srch; srch = srch->prev)
944 {
945 if (!IsRegisteredUser(srch))
946 continue;
947 if (srch->from == cptr &&
948 match_it(srch, mask, what))
949 break;
950 }
951 if (srch == NULL)
952 continue;
953 }
954 /* my client, does he match ? */
955 else if (!(IsRegisteredUser(cptr) &&
956 match_it(cptr, mask, what)))
957 {
958 continue;
959 }
960 /* this frame have tricked me many times ;) and it's only
961 ** frame for having va declared ;) --Beeth */
962 {
963 va_list va;
964 va_start(va, pattern);
965 vsendto_prefix_one(cptr, from, pattern, va);
966 va_end(va);
967 }
968
969 }
970 return;
971}
972
973/*
974** sendto_ops_butone
975** Send message to all operators.
976** one - client not to send message to
977** from- client which message is from *NEVER* NULL!!
978*/
979void sendto_ops_butone(aClient *one, char *from, char *pattern, ...)
980{
981 va_list va;
982 char buf[BUFSIZE];
983
984 va_start(va, pattern);
985 vsprintf(buf, pattern, va);
986 va_end(va);
987 sendto_serv_butone(one, ":%s WALLOPS :%s", from, buf);
988 sendto_flag(SCH_WALLOP, "!%s! %s", from, buf);
989
990 return;
991}
992
993/*
994 * to - destination client
995 * from - client which message is from
996 *
997 * NOTE: NEITHER OF THESE SHOULD *EVER* BE NULL!!
998 * -avalon
999 */
1000void sendto_prefix_one(aClient *to, aClient *from, char *pattern, ...)
1001{
1002 int len;
1003
1004 va_list va;
1005 va_start(va, pattern);
1006 len = vsendpreprep(to, from, pattern, va);
1007 va_end(va);
1008 send_message(to, psendbuf, len);
1009 return;
1010}
1011
1012static void vsendto_prefix_one(aClient *to, aClient *from, char *pattern,
1013 va_list va)
1014{
1015 int len;
1016
1017 len = vsendpreprep(to, from, pattern, va);
1018 send_message(to, psendbuf, len);
1019 return;
1020}
1021
1022
1023/*
1024 * sends a message to a server-owned channel
1025 */
1026static SChan svchans[SCH_MAX] = {
1027 { SCH_ERROR, "&ERRORS", NULL, -2},
1028 { SCH_NOTICE, "&NOTICES", NULL, -2},
1029 { SCH_KILL, "&KILLS", NULL, -2},
1030 { SCH_CHAN, "&CHANNEL", NULL, -2},
1031 { SCH_NUM, "&NUMERICS", NULL, -2},
1032 { SCH_SERVER, "&SERVERS", NULL, -2},
1033 { SCH_HASH, "&HASH", NULL, -2},
1034 { SCH_LOCAL, "&LOCAL", NULL, -2},
1035 { SCH_SERVICE, "&SERVICES", NULL, -2},
1036 { SCH_DEBUG, "&DEBUG", NULL, -2},
1037 { SCH_AUTH, "&AUTH", NULL, -2},
1038 { SCH_SAVE, "&SAVE", NULL, -2},
1039 { SCH_WALLOP, "&WALLOPS", NULL, -2},
1040#ifdef CLIENTS_CHANNEL
1041 { SCH_CLIENT, "&CLIENTS", NULL, -2},
1042#endif
1043 { SCH_OPER, "&OPER", NULL, -2},
1044};
1045
1046
1047void setup_svchans(void)
1048{
1049 int i;
1050 SChan *shptr;
1051
1052#ifdef LOG_SERVER_CHANNELS
1053 /* They're here, as they need to be done only once per server run,
1054 ** to determine if we want given channel logged. --B. */
1055# ifdef LOG_SCH_ERROR
1056 (svchans+SCH_ERROR)->fd = -1;
1057# endif
1058# ifdef LOG_SCH_NOTICE
1059 (svchans+SCH_NOTICE)->fd = -1;
1060# endif
1061# ifdef LOG_SCH_KILL
1062 (svchans+SCH_KILL)->fd = -1;
1063# endif
1064# ifdef LOG_SCH_CHAN
1065 (svchans+SCH_CHAN)->fd = -1;
1066# endif
1067# ifdef LOG_SCH_NUM
1068 (svchans+SCH_NUM)->fd = -1;
1069# endif
1070# ifdef LOG_SCH_SERVER
1071 (svchans+SCH_SERVER)->fd = -1;
1072# endif
1073# ifdef LOG_SCH_HASH
1074 (svchans+SCH_HASH)->fd = -1;
1075# endif
1076# ifdef LOG_SCH_LOCAL
1077 (svchans+SCH_LOCAL)->fd = -1;
1078# endif
1079# ifdef LOG_SCH_SERVICE
1080 (svchans+SCH_SERVICE)->fd = -1;
1081# endif
1082# ifdef LOG_SCH_DEBUG
1083 (svchans+SCH_DEBUG)->fd = -1;
1084# endif
1085# ifdef LOG_SCH_AUTH
1086 (svchans+SCH_AUTH)->fd = -1;
1087# endif
1088# ifdef LOG_SCH_SAVE
1089 (svchans+SCH_SAVE)->fd = -1;
1090# endif
1091# ifdef LOG_SCH_WALLOP
1092 (svchans+SCH_WALLOP)->fd = -1;
1093# endif
1094# ifdef CLIENTS_CHANNEL
1095# ifdef LOG_SCH_CLIENT
1096 (svchans+SCH_CLIENT)->fd = -1;
1097# endif
1098# endif
1099# ifdef LOG_SCH_OPER
1100 (svchans+SCH_OPER)->fd = -1;
1101# endif
1102#endif
1103 for (i = SCH_MAX - 1, shptr = svchans + i; i >= 0; i--, shptr--)
1104 shptr->svc_ptr = find_channel(shptr->svc_chname, NULL);
1105}
1106
1107void sendto_flag(u_int chan, char *pattern, ...)
1108{
1109 Reg aChannel *chptr = NULL;
1110 SChan *shptr;
1111 char nbuf[1024];
1112
1113 if (chan >= SCH_MAX)
1114 chan = SCH_NOTICE;
1115 shptr = svchans + chan;
1116
1117 if ((chptr = shptr->svc_ptr))
1118 {
1119 {
1120 va_list va;
1121 va_start(va, pattern);
1122 (void)vsprintf(nbuf, pattern, va);
1123 va_end(va);
1124 }
1125 sendto_channel_butserv(chptr, &me, ":%s NOTICE %s :%s", ME, chptr->chname, nbuf);
1126
1127#ifdef USE_SERVICES
1128 switch (chan)
1129 {
1130 case SCH_ERROR:
1131 check_services_butone(SERVICE_WANT_ERRORS, NULL, &me,
1132 "&ERRORS :%s", nbuf);
1133 break;
1134 case SCH_NOTICE:
1135 check_services_butone(SERVICE_WANT_NOTICES, NULL, &me,
1136 "&NOTICES :%s", nbuf);
1137 break;
1138 case SCH_LOCAL:
1139 check_services_butone(SERVICE_WANT_LOCAL, NULL, &me,
1140 "&LOCAL :%s", nbuf);
1141 break;
1142 case SCH_NUM:
1143 check_services_butone(SERVICE_WANT_NUMERICS, NULL, &me,
1144 "&NUMERICS :%s", nbuf);
1145 break;
1146#ifdef CLIENTS_CHANNEL
1147 case SCH_CLIENT:
1148 check_services_butone(SERVICE_WANT_CLIENTS, NULL, &me,
1149 "&CLIENTS :%s", nbuf);
1150 break;
1151#endif
1152 }
1153#endif
1154 }
1155#ifdef LOG_SERVER_CHANNELS
1156 if ((svchans+chan)->fd >= 0)
1157 {
1158 char lbuf[1024];
1159 int len;
1160
1161 len = sprintf(lbuf, "%u %s\n", (u_int)timeofday, nbuf);
1162 (void)write((svchans+chan)->fd, lbuf, len);
1163 }
1164#endif
1165 return;
1166}
1167
1168static int userlog = -1;
1169static int connlog = -1;
1170
1171void logfiles_open(void)
1172{
1173#ifdef LOG_SERVER_CHANNELS
1174 int i;
1175 SChan *shptr;
1176 char fname[BUFSIZE];
1177
1178 for (i = SCH_MAX - 1, shptr = svchans + i; i >= 0; i--, shptr--)
1179 {
1180 if (shptr->fd == -2)
1181 {
1182 /* We don't want this channel logged. */
1183 continue;
1184 }
1185
1186 sprintf(fname, "%s.%s", FNAME_SCH_PREFIX, shptr->svc_chname+1);
1187 shptr->fd = open(fname, O_WRONLY|O_APPEND|O_NDELAY
1188#ifdef LOGFILES_ALWAYS_CREATE
1189 |O_CREAT, S_IRUSR|S_IWUSR
1190#endif
1191 );
1192 /* Better safe than sorry. */
1193 if (shptr->fd >= 0)
1194 {
1195 local[shptr->fd] = NULL;
1196 }
1197 }
1198#endif
1199#ifdef FNAME_USERLOG
1200 userlog = open(FNAME_USERLOG, O_WRONLY|O_APPEND|O_NDELAY
1201# ifdef LOGFILES_ALWAYS_CREATE
1202 |O_CREAT, S_IRUSR|S_IWUSR
1203# endif
1204 );
1205 /* Better safe than sorry. */
1206 if (userlog >= 0)
1207 {
1208 local[userlog] = NULL;
1209 }
1210#else
1211 userlog = -1;
1212#endif
1213#ifdef FNAME_CONNLOG
1214 connlog = open(FNAME_CONNLOG, O_WRONLY|O_APPEND|O_NDELAY
1215# ifdef LOGFILES_ALWAYS_CREATE
1216 |O_CREAT, S_IRUSR|S_IWUSR
1217# endif
1218 );
1219 if (connlog >= 0)
1220 {
1221 local[connlog] = NULL;
1222 }
1223#else
1224 connlog = -1;
1225#endif
1226}
1227
1228void logfiles_close(void)
1229{
1230#ifdef LOG_SERVER_CHANNELS
1231 int i;
1232 SChan *shptr;
1233
1234 for (i = SCH_MAX - 1, shptr = svchans + i; i >= 0; i--, shptr--)
1235 {
1236 if (shptr->fd >= 0)
1237 {
1238 (void)close(shptr->fd);
1239 }
1240 }
1241#endif
1242#ifdef FNAME_USERLOG
1243 if (userlog != -1)
1244 {
1245 (void)close(userlog);
1246 userlog = -1;
1247 }
1248#endif
1249#ifdef FNAME_CONNLOG
1250 if (connlog != -1)
1251 {
1252 (void)close(connlog);
1253 connlog = -1;
1254 }
1255#endif
1256}
1257
1258/*
1259 * sendto_flog
1260 * cptr used for firsttime, auth, exitc, send/receive M/B
1261 * msg exit code
1262 * username sometimes can't get it from cptr
1263 * hostname i.e.
1264 */
1265void sendto_flog(aClient *cptr, char msg, char *username, char *hostname)
1266{
1267 /*
1268 ** One day we will rewrite linebuf to malloc()s, but for now
1269 ** we are lazy. The longest linebuf I saw during last year
1270 ** was 216. Max auth reply can be 1024, see rfc931_work() and
1271 ** if iauth is disabled, read_authports() makes it max 513.
1272 ** And the rest... just count, I got 154 --Beeth
1273 */
1274 char linebuf[1500];
1275 int linebuflen;
1276 /*
1277 ** This is a potential buffer overflow.
1278 ** I mean, when you manage to keep ircd
1279 ** running for almost 12 years ;-) --B.
1280 */
1281#ifdef LOG_OLDFORMAT
1282 char buf[12];
1283#endif
1284 int logfile;
1285
1286 /*
1287 ** EXITC_REG == 0 means registered client quitting, so it goes to
1288 ** userlog; otherwise it's rejection and goes to connlog --Beeth.
1289 */
1290 logfile = (msg == EXITC_REG ? userlog : connlog);
1291
1292#if !defined(USE_SERVICES) && !( defined(USE_SYSLOG) && \
1293 (defined(SYSLOG_USERS) || defined(SYSLOG_CONN)) )
1294 if (logfile == -1)
1295 {
1296 return;
1297 }
1298#endif
1299#ifdef LOG_OLDFORMAT
1300 if (msg == EXITC_REG)
1301 {
1302 time_t duration;
1303
1304 duration = timeofday - cptr->firsttime + 1;
1305 (void)sprintf(buf, "%3d:%02d:%02d",
1306 (int) (duration / 3600),
1307 (int) ((duration % 3600) / 60),
1308 (int) (duration % 60));
1309 }
1310 else
1311 {
1312 char *anyptr;
1313
1314 switch(msg)
1315 {
1316 case EXITC_GHMAX: anyptr="G IP max"; break;
1317 case EXITC_GUHMAX: anyptr="G u@h max"; break;
1318 case EXITC_LHMAX: anyptr="L IP max"; break;
1319 case EXITC_LUHMAX: anyptr="L u@h max"; break;
1320 case EXITC_AREF:
1321 case EXITC_AREFQ: anyptr=" Denied "; break;
1322 case EXITC_KLINE: anyptr=" K lined "; break;
1323 case EXITC_CLONE: anyptr=" ?Clone? "; break;
1324 case EXITC_YLINEMAX: anyptr=" max "; break;
1325 case EXITC_NOILINE: anyptr=" No Auth "; break;
1326 case EXITC_AUTHFAIL: anyptr="No iauth!"; break;
1327 case EXITC_AUTHTOUT: anyptr="iauth t/o"; break;
1328 case EXITC_FAILURE: anyptr=" Failure "; break;
1329 default: anyptr=" Unknown ";
1330 }
1331 (void)sprintf(buf, "%s", anyptr);
1332 }
1333 linebuflen = sprintf(linebuf,
1334 "%s (%s): %s@%s [%s] %c %lu %luKb %lu %luKb ",
1335 myctime(cptr->firsttime), buf,
1336 username[0] ? username : "<none>", hostname,
1337 cptr->auth ? cptr->auth : "<none>",
1338 cptr->exitc, cptr->sendM, (long)(cptr->sendB>>10),
1339 cptr->receiveM, (long)(cptr->receiveB>>10));
1340#else
1341 /*
1342 ** This is the content of loglines.
1343 */
1344 linebuflen = sprintf(linebuf,
1345 "%c %d %d %s %s %s %s %d %s %lu %llu %lu %llu ",
1346 /* exit code as defined in common/struct_def.h; some common:
1347 * '0' normal exit, '-' unregistered client quit, 'k' k-lined,
1348 * 'K' killed, 'X' x-lined, 'Y' max clients limit of Y-line,
1349 * 'L' local @host limit, 'l' local user@host limit, 'P' ping
1350 * timeout, 'Q' send queue exceeded, 'E' socket error */
1351 cptr->exitc,
1352 /* signon unix time */
1353 (u_int) cptr->firsttime,
1354 /* signoff unix time */
1355 (u_int) timeofday,
1356 /* username (if ident is not working, it's from USER cmd) */
1357 username,
1358 /* hmm, let me take an educated guess... a hostname? */
1359 hostname,
1360 /* ident, if available */
1361 cptr->auth ? cptr->auth : "?",
1362 /* client IP */
1363 cptr->user ? cptr->user->sip :
1364#ifdef INET6
1365 inetntop(AF_INET6, (char *)&cptr->ip, ipv6string, sizeof(ipv6string)),
1366#else
1367 inetntoa((char *)&cptr->ip),
1368#endif
1369 /* client (remote) port */
1370 cptr->port,
1371 /* server sockhost (IP plus port or unix socket path) */
1372 cptr->acpt ? cptr->acpt->sockhost : "?",
1373 /* messages and bytes sent to client */
1374 cptr->sendM, cptr->sendB,
1375 /* messages and bytes received from client */
1376 cptr->receiveM, cptr->receiveB);
1377#endif /* LOG_OLDFORMAT */
1378#if defined(USE_SYSLOG) && (defined(SYSLOG_USERS) || defined(SYSLOG_CONN))
1379 if (msg == EXITC_REG)
1380 {
1381# ifdef SYSLOG_USERS
1382 syslog(LOG_NOTICE, "%s", linebuf);
1383# endif
1384 }
1385 else
1386 {
1387# ifdef SYSLOG_CONN
1388 syslog(LOG_NOTICE, "%s", linebuf);
1389# endif
1390 }
1391#endif /* USE_SYSLOG */
1392
1393#ifdef USE_SERVICES
1394 if (msg == EXITC_REG)
1395 {
1396 check_services_butone(SERVICE_WANT_USERLOG, NULL, &me,
1397 "USERLOG :%s", linebuf);
1398 }
1399 else
1400 {
1401 check_services_butone(SERVICE_WANT_CONNLOG, NULL, &me,
1402 "CONNLOG :%s", linebuf);
1403 }
1404#endif
1405 if (logfile != -1)
1406 {
1407 linebuf[linebuflen-1] = '\n';
1408 (void)write(logfile, linebuf, linebuflen);
1409 }
1410}