1 /************************************************************************
2 * IRC - Internet Relay Chat, ircd/s_bsd.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 /* -- Jto -- 07 Jul 1990
22 * Added jlp@hamblin.byu.edu's debugtty fix
23 */
24
25 /* -- Armin -- Jun 18 1990
26 * Added setdtablesize() for more socket connections
27 * (sequent OS Dynix only) -- maybe select()-call must be changed ...
28 */
29
30 /* -- Jto -- 13 May 1990
31 * Added several fixes from msa:
32 * Better error messages
33 * Changes in check_access
34 * Added SO_REUSEADDR fix from zessel@informatik.uni-kl.de
35 */
36
37 #ifndef lint
38 static const volatile char rcsid[] = "@(#)$Id: s_bsd.c,v 1.187 2010/08/13 19:58:46 bif Exp $";
39 #endif
40
41 #include "os.h"
42 #include "s_defines.h"
43 #define S_BSD_C
44 #include "s_externs.h"
45 #undef S_BSD_C
46
47 #ifndef IN_LOOPBACKNET
48 #define IN_LOOPBACKNET 0x7f
49 #endif
50
51 aClient *local[MAXCONNECTIONS];
52 FdAry fdas, fdall;
53 int highest_fd = 0, readcalls = 0, udpfd = -1, resfd = -1, adfd = -1;
54 time_t timeofday;
55 static struct SOCKADDR_IN mysk;
56 static void polludp(void);
57
58 static struct SOCKADDR *connect_inet (aConfItem *, aClient *, int *);
59 static int completed_connection (aClient *);
60 static int check_init (aClient *, char *);
61 static int check_ping (char *, int);
62 static void do_dns_async (void);
63 static int set_sock_opts (int, aClient *);
64 #ifdef UNIXPORT
65 static struct SOCKADDR *connect_unix (aConfItem *, aClient *, int *);
66 static aClient *add_unixconnection (aClient *, int);
67 static char unixpath[256];
68 #endif
69 static char readbuf[READBUF_SIZE];
70
71 #define CFLAG (CONF_CONNECT_SERVER|CONF_ZCONNECT_SERVER)
72 #define NFLAG CONF_NOCONNECT_SERVER
73
74 /*
75 * Try and find the correct name to use with getrlimit() for setting the max.
76 * number of files allowed to be open by this process.
77 */
78 #ifdef RLIMIT_FDMAX
79 # define RLIMIT_FD_MAX RLIMIT_FDMAX
80 #else
81 # ifdef RLIMIT_NOFILE
82 # define RLIMIT_FD_MAX RLIMIT_NOFILE
83 # else
84 # ifdef RLIMIT_OPEN_MAX
85 # define RLIMIT_FD_MAX RLIMIT_OPEN_MAX
86 # else
87 # undef RLIMIT_FD_MAX
88 # endif
89 # endif
90 #endif
91
92 /*
93 ** add_local_domain()
94 ** Add the domain to hostname, if it is missing
95 ** (as suggested by eps@TOASTER.SFSU.EDU)
96 ** Note: size is the max we can append to hname!
97 */
98
add_local_domain(char * hname,size_t size)99 void add_local_domain(char *hname, size_t size)
100 {
101 #ifdef RES_INIT
102 /* some return plain hostname with ending dot, whoops. */
103 if (hname[strlen(hname)-1] == '.')
104 {
105 hname[strlen(hname)-1] = '\0';
106 size++;
107 }
108 /* try to fix up unqualified names */
109 if (!index(hname, '.'))
110 {
111 if (!(ircd_res.options & RES_INIT))
112 {
113 Debug((DEBUG_DNS,"ircd_res_init()"));
114 ircd_res_init();
115 }
116 /* Enough space in hname to append defdname? */
117 /* "2" is dot and ending \0 */
118 if (ircd_res.defdname[0] &&
119 strlen(ircd_res.defdname) + 2 <= size)
120 {
121 /* no need for strncat with above check */
122 (void)strcat(hname, ".");
123 (void)strcat(hname, ircd_res.defdname);
124 }
125 }
126 #endif
127 return;
128 }
129
130 /*
131 ** Cannot use perror() within daemon. stderr is closed in
132 ** ircd and cannot be used. And, worse yet, it might have
133 ** been reassigned to a normal connection...
134 */
135
136 /*
137 ** report_error
138 ** This a replacement for perror(). Record error to log and
139 ** also send a copy to all *LOCAL* opers online.
140 **
141 ** text is a *format* string for outputting error. It must
142 ** contain only two '%s', the first will be replaced
143 ** by the sockhost from the cptr, and the latter will
144 ** by strerror(errno).
145 **
146 ** cptr if not NULL, is the *LOCAL* client associated with
147 ** the error.
148 */
report_error(char * text,aClient * cptr)149 void report_error(char *text, aClient *cptr)
150 {
151 Reg int errtmp = errno; /* debug may change 'errno' */
152 Reg char *host;
153 int err;
154 SOCK_LEN_TYPE len = sizeof(err);
155 char fmbuf[BUFSIZE+1];
156 aClient *bysptr = NULL;
157
158 extern char *strerror(int);
159
160 host = (cptr) ? get_client_name(cptr, FALSE) : "";
161
162 Debug((DEBUG_ERROR, text, host, strerror(errtmp)));
163
164 /*
165 * Get the *real* error from the socket (well try to anyway..).
166 * This may only work when SO_DEBUG is enabled but its worth the
167 * gamble anyway.
168 */
169 #ifdef SO_ERROR
170 if (cptr && !IsMe(cptr) && cptr->fd >= 0)
171 if (!GETSOCKOPT(cptr->fd, SOL_SOCKET, SO_ERROR, &err, &len))
172 if (err)
173 errtmp = err;
174 #endif
175 sendto_flag(SCH_ERROR, text, host, strerror(errtmp));
176 if (cptr && (IsConnecting(cptr) || IsHandshake(cptr)) &&
177 cptr->serv && cptr->serv->byuid[0])
178 {
179 bysptr = find_uid(cptr->serv->byuid, NULL);
180 if (bysptr && !MyConnect(bysptr))
181 {
182 fmbuf[0] = '\0';
183 strcpy(fmbuf, ":%s NOTICE %s :");
184 strncat(fmbuf, text, BUFSIZE-strlen(fmbuf));
185 sendto_one(bysptr, fmbuf, ME, bysptr->name,
186 host, strerror(errtmp));
187 }
188 }
189 #ifdef USE_SYSLOG
190 syslog(LOG_WARNING, text, host, strerror(errtmp));
191 #endif
192 if (serverbooting)
193 {
194 fprintf(stderr,text,host,strerror(errtmp));
195 fprintf(stderr,"\n");
196 }
197 return;
198 }
199
200 /*
201 * inetport
202 *
203 * Create a socket in the AF_INET domain, bind it to the port given in
204 * 'port' and listen to it. If 'ip' has a value, use it as vif to listen.
205 * Connections are accepted to this socket depending on the IP# mask given
206 * by 'ipmask'. Returns the fd of the socket created or -1 on error.
207 */
inetport(aClient * cptr,char * ip,char * ipmask,int port,int dolisten)208 int inetport(aClient *cptr, char *ip, char *ipmask, int port, int dolisten)
209 {
210 static struct SOCKADDR_IN server;
211 int ad[4];
212 SOCK_LEN_TYPE len = sizeof(server);
213 char ipname[20];
214
215 /* broken config? why allow such broken line to live?
216 ** XXX: fix initconf()? --B. */
217 if (!ipmask)
218 {
219 sendto_flag(SCH_ERROR, "Invalid P-line");
220 return -1;
221 }
222 ad[0] = ad[1] = ad[2] = ad[3] = 0;
223
224 /*
225 * do it this way because building ip# from separate values for each
226 * byte requires endian knowledge or some nasty messing. Also means
227 * easy conversion of "*" to 0.0.0.0 or 134.* to 134.0.0.0 :-)
228 */
229 (void)sscanf(ipmask, "%d.%d.%d.%d", &ad[0], &ad[1], &ad[2], &ad[3]);
230 if (ad[0]>>8 || ad[1]>>8 || ad[2]>>8 || ad[3]>>8)
231 {
232 sendto_flag(SCH_ERROR, "Invalid ipmask %s", ipmask);
233 return -1;
234 }
235 (void)sprintf(ipname, "%d.%d.%d.%d", ad[0], ad[1], ad[2], ad[3]);
236
237 (void)sprintf(cptr->sockhost, "%-.42s.%u", ip ? ip : ME,
238 (unsigned int)port);
239 DupString(cptr->auth, ipname);
240 /*
241 * At first, open a new socket
242 */
243 if (cptr->fd == -1)
244 cptr->fd = socket(AFINET, SOCK_STREAM, 0);
245 if (cptr->fd < 0)
246 {
247 report_error("opening stream socket %s:%s", cptr);
248 return -1;
249 }
250 else if (cptr->fd >= MAXCLIENTS)
251 {
252 sendto_flag(SCH_ERROR,
253 "No more connections allowed (%s)", cptr->name);
254 (void)close(cptr->fd);
255 return -1;
256 }
257 (void)set_sock_opts(cptr->fd, cptr);
258 #if defined (__CYGWIN32__)
259 /* Can anyone explain why setting nonblock here works and does not
260 ** in add_listener after we return from inetport()? --B. */
261 (void)set_non_blocking(cptr->fd, cptr);
262 #endif
263 /*
264 * Bind a port to listen for new connections if port is non-null,
265 * else assume it is already open and try get something from it.
266 */
267 if (port)
268 {
269 server.SIN_FAMILY = AFINET;
270 #ifdef INET6
271 if (!ip || (!isxdigit(*ip) && *ip != ':'))
272 server.sin6_addr = in6addr_any;
273 else
274 if(!inetpton(AF_INET6, ip, server.sin6_addr.s6_addr))
275 bcopy(minus_one, server.sin6_addr.s6_addr,
276 IN6ADDRSZ);
277 #else
278 if (!ip || !isdigit(*ip))
279 server.sin_addr.s_addr = INADDR_ANY;
280 else
281 server.sin_addr.s_addr = inetaddr(ip);
282 #endif
283 server.SIN_PORT = htons(port);
284 /*
285 * Try 10 times to bind the socket with an interval of 20
286 * seconds. Do this so we don't have to keep trying manually
287 * to bind. Why ? Because a port that has closed often lingers
288 * around for a short time.
289 * This used to be the case. Now it no longer is.
290 * Could cause the server to hang for too long - avalon
291 */
292 if (bind(cptr->fd, (SAP)&server, sizeof(server)) == -1)
293 {
294 report_error("binding stream socket %s:%s", cptr);
295 (void)close(cptr->fd);
296 return -1;
297 }
298 }
299
300 if (getsockname(cptr->fd, (struct SOCKADDR *)&server, &len))
301 {
302 report_error("getsockname failed for %s:%s",cptr);
303 (void)close(cptr->fd);
304 return -1;
305 }
306
307 if (cptr == &me) /* KLUDGE to get it work... */
308 {
309 char buf[1024];
310
311 (void)sprintf(buf, replies[RPL_MYPORTIS], ME, "*",
312 ntohs(server.SIN_PORT));
313 (void)write(0, buf, strlen(buf));
314 }
315
316 if (cptr->fd > highest_fd)
317 highest_fd = cptr->fd;
318 #ifdef INET6
319 bcopy(server.sin6_addr.s6_addr, cptr->ip.s6_addr, IN6ADDRSZ);
320 #else
321 cptr->ip.s_addr = server.sin_addr.s_addr; /* broken on linux at least*/
322 #endif
323 cptr->port = port;
324 local[cptr->fd] = cptr;
325 if (dolisten)
326 {
327 listen(cptr->fd, LISTENQUEUE);
328 }
329
330 return 0;
331 }
332
333 /*
334 * add_listener
335 *
336 * Create a new client which is essentially the stub like 'me' to be used
337 * for a socket that is passive (listen'ing for connections to be accepted).
338 */
add_listener(aConfItem * aconf)339 int add_listener(aConfItem *aconf)
340 {
341 aClient *cptr;
342
343 cptr = make_client(NULL);
344 cptr->flags = FLAGS_LISTEN;
345 cptr->acpt = cptr;
346 cptr->from = cptr;
347 cptr->firsttime = time(NULL);
348 cptr->name = ME;
349 SetMe(cptr);
350
351
352 cptr->confs = make_link();
353 cptr->confs->next = NULL;
354 cptr->confs->value.aconf = aconf;
355
356 open_listener(cptr);
357 /* Add to linked list */
358 if (ListenerLL)
359 {
360 ListenerLL->prev = cptr;
361 }
362 cptr->next = ListenerLL;
363 cptr->prev = NULL;
364 ListenerLL = cptr;
365
366 return 0;
367 }
368
369 #ifdef UNIXPORT
370 /*
371 * unixport
372 *
373 * Create a socket and bind it to a filename which is comprised of the path
374 * (directory where file is placed) and port (actual filename created).
375 * Set directory permissions as rwxr-xr-x so other users can connect to the
376 * file which is 'forced' to rwxrwxrwx (different OS's have different need of
377 * modes so users can connect to the socket).
378 */
unixport(aClient * cptr,char * path,int port)379 int unixport(aClient *cptr, char *path, int port)
380 {
381 struct sockaddr_un un;
382 struct stat buf;
383
384 if ((cptr->fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
385 {
386 report_error("error opening unix domain socket %s:%s", cptr);
387 return -1;
388 }
389 else if (cptr->fd >= MAXCLIENTS)
390 {
391 sendto_flag(SCH_ERROR,
392 "No more connections allowed (%s)", path);
393 (void)close(cptr->fd);
394 return -1;
395 }
396
397 un.sun_family = AF_UNIX;
398 (void)mkdir(path, 0755);
399 sprintf(unixpath, "%s/%d", path, port);
400 get_sockhost(cptr, unixpath);
401 if (stat(unixpath, &buf)==0)
402 {
403 report_error("unix domain socket %s:%s", cptr);
404 (void)close(cptr->fd);
405 return -1;
406 }
407 strncpyzt(un.sun_path, unixpath, sizeof(un.sun_path));
408 errno = 0;
409
410 if (bind(cptr->fd, (SAP)&un, strlen(unixpath)+2) == -1)
411 {
412 report_error("error binding unix socket %s:%s", cptr);
413 (void)close(cptr->fd);
414 return -1;
415 }
416 if (cptr->fd > highest_fd)
417 highest_fd = cptr->fd;
418 (void)listen(cptr->fd, LISTENQUEUE);
419 (void)chmod(path, 0755);
420 (void)chmod(unixpath, 0777);
421 SetUnixSock(cptr);
422 cptr->port = 0;
423 local[cptr->fd] = cptr;
424
425 return 0;
426 }
427 #endif
428
429 /*
430 * close_listeners
431 *
432 * Close and free all clients which are marked as having their socket open
433 * and in a state where they can accept connections. Unix sockets have
434 * the path to the socket unlinked for cleanliness.
435 */
close_listeners(void)436 void close_listeners(void)
437 {
438 aClient *acptr, *bcptr;
439 aConfItem *aconf;
440
441 /*
442 * close all 'extra' listening ports we have and unlink the file
443 * name if it was a unix socket.
444 */
445 for (acptr = ListenerLL; acptr; acptr = bcptr)
446 {
447 aconf = acptr->confs->value.aconf;
448 bcptr = acptr->next; /* might get deleted by close_connection
449 */
450
451 if (IsIllegal(aconf))
452 {
453 #ifdef UNIXPORT
454 if (IsUnixSocket(acptr))
455 {
456 sprintf(unixpath, "%s/%d",
457 aconf->host, aconf->port);
458 (void)unlink(unixpath);
459 }
460 #endif
461 if (aconf->clients > 0)
462 {
463 close_client_fd(acptr);
464 }
465 else
466 {
467 close_connection(acptr);
468 }
469 }
470 }
471 }
472
473 /* Opens listening socket on given listener */
open_listener(aClient * cptr)474 void open_listener(aClient *cptr)
475 {
476 aConfItem *aconf;
477 int dolisten = 1;
478
479 aconf = cptr->confs->value.aconf;
480
481 if (!IsListener(cptr) || cptr->fd > 0)
482 {
483 return;
484 }
485
486 #ifdef UNIXPORT
487 if (*aconf->host == '/')
488 {
489 if (unixport(cptr, aconf->host, aconf->port))
490 {
491 cptr->fd = -1;
492 }
493 }
494 else
495 #endif
496 {
497 if (IsConfDelayed(aconf) && !firstrejoindone)
498 {
499 dolisten = 0;
500 SetListenerInactive(cptr);
501 }
502 if (inetport(cptr, aconf->host, aconf->name, aconf->port,
503 dolisten))
504 {
505 /* to allow further inetport calls */
506 cptr->fd = -1;
507 }
508 }
509
510 if (cptr->fd >= 0)
511 {
512 add_fd(cptr->fd, &fdas);
513 add_fd(cptr->fd, &fdall);
514 set_non_blocking(cptr->fd, cptr);
515 }
516 }
517
518 /* Reopens listening sockets on all listeners */
reopen_listeners(void)519 void reopen_listeners(void)
520 {
521 aClient *acptr;
522 aConfItem *aconf;
523 for (acptr = ListenerLL; acptr; acptr = acptr->next)
524 {
525 aconf = acptr->confs->value.aconf;
526 if (!IsIllegal(aconf) && acptr->fd < 0)
527 {
528 open_listener(acptr);
529 }
530 }
531 }
532
activate_delayed_listeners(void)533 void activate_delayed_listeners(void)
534 {
535 int cnt = 0;
536 aClient *acptr;
537
538 for (acptr = ListenerLL; acptr; acptr = acptr->next)
539 {
540 if (IsListenerInactive(acptr))
541 {
542 listen(acptr->fd, LISTENQUEUE);
543 ClearListenerInactive(acptr);
544 cnt++;
545 }
546 }
547
548 if (cnt > 0)
549 {
550 sendto_flag(SCH_NOTICE, "%d listeners activated", cnt);
551 }
552 }
553
start_iauth(int rcvdsig)554 void start_iauth(int rcvdsig)
555 {
556 #if defined(USE_IAUTH)
557 static time_t last = 0;
558 static char first = 1;
559 int sp[2], fd, val;
560 static pid_t iauth_pid = 0;
561
562 if ((bootopt & BOOT_NOIAUTH) != 0)
563 return;
564 if (rcvdsig == 2)
565 {
566 sendto_flag(SCH_AUTH, "Killing iauth...");
567 if (iauth_pid)
568 kill(iauth_pid, SIGTERM);
569 iauth_pid = 0;
570 }
571 else
572 if (adfd >= 0)
573 {
574 if (rcvdsig)
575 sendto_flag(SCH_AUTH,
576 "iauth is already running, restart canceled");
577 return;
578 }
579 if ((time(NULL) - last) > 90 || rcvdsig)
580 {
581 sendto_flag(SCH_AUTH, "Starting iauth...");
582 last = time(NULL);
583 read_iauth(); /* to reset olen */
584 iauth_spawn += 1;
585 }
586 else
587 return;
588 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) < 0)
589 {
590 sendto_flag(SCH_ERROR, "socketpair() failed!");
591 sendto_flag(SCH_AUTH, "Failed to restart iauth!");
592 }
593 adfd = sp[0];
594 set_non_blocking(sp[0], NULL);
595 set_non_blocking(sp[1], NULL); /* less to worry about in iauth */
596 val = IAUTH_BUFFER;
597 if (setsockopt(sp[0], SOL_SOCKET, SO_SNDBUF, (void *) &val,
598 sizeof(val)) < 0)
599 sendto_flag(SCH_AUTH,
600 "IAUTH_BUFFER too big for sp0 sndbuf, using default");
601 if (setsockopt(sp[1], SOL_SOCKET, SO_SNDBUF, (void *) &val,
602 sizeof(val)) < 0)
603 sendto_flag(SCH_AUTH,
604 "IAUTH_BUFFER too big for sp1 sndbuf, using default");
605 if (setsockopt(sp[0], SOL_SOCKET, SO_RCVBUF, (void *) &val,
606 sizeof(val)) < 0)
607 sendto_flag(SCH_AUTH,
608 "IAUTH_BUFFER too big for sp0 rcvbuf, using default");
609 if (setsockopt(sp[1], SOL_SOCKET, SO_RCVBUF, (void *) &val,
610 sizeof(val)) < 0)
611 sendto_flag(SCH_AUTH,
612 "IAUTH_BUFFER too big for sp1 rcvbuf, using default");
613 switch ((iauth_pid = vfork()))
614 {
615 case -1:
616 sendto_flag(SCH_ERROR, "vfork() failed!");
617 sendto_flag(SCH_AUTH, "Failed to restart iauth!");
618 close(sp[0]); close(sp[1]);
619 adfd = -1;
620 return;
621 case 0:
622 for (fd = 0; fd < MAXCONNECTIONS; fd++)
623 if (fd != sp[1])
624 (void)close(fd);
625 if (sp[1] != 0)
626 {
627 (void)dup2(sp[1], 0);
628 close(sp[1]);
629 }
630 if (execl(IAUTH_PATH, IAUTH, NULL) < 0)
631 _exit(-1); /* should really not happen.. */
632 default:
633 close(sp[1]);
634 }
635
636 if (first)
637 first = 0;
638 else
639 {
640 int i;
641 aClient *cptr;
642 char abuf[BUFSIZ]; /* size of abuf in vsendto_iauth */
643 /* 20 is biggest possible ending "%d O\n\0", which means
644 ** 16-digit fd -- very unlikely :> */
645 char *e = abuf + BUFSIZ - 20;
646 char *s = abuf;
647
648 /* Build abuf to send big buffer once (or twice) to iauth,
649 ** which goes faster than many consecutive small writes.
650 ** BitKoenig claims it saves metadata overhead on Linux and
651 ** does not harm other systems --B. */
652 for (i = 0; i <= highest_fd; i++)
653 {
654 if (!(cptr = local[i]))
655 continue;
656 if (IsServer(cptr) || IsService(cptr))
657 continue;
658
659 /* if not enough room in abuf, send whatever we have
660 ** now and start writing from begin of abuf again. */
661 if (s > e)
662 {
663 /* sendto_iauth() appends "\n", so we
664 ** remove last one */
665 *(s - 1) = '\0';
666 sendto_iauth(abuf);
667 s = abuf;
668 }
669 /* A little trick: we sprintf onto s and move s (which
670 ** points inside abuf) forward, at the end of s (number
671 ** of bytes returned by sprintf). This makes s always
672 ** point to the end of things written on abuf, which
673 ** allows both next sprintf at the end (no strcat!) and
674 ** removing last \n when needed. */
675 s += sprintf(s, "%d O\n", i);
676 }
677 /* send the rest */
678 if (s != abuf)
679 {
680 *(s - 1) = '\0';
681 sendto_iauth(abuf);
682 }
683 }
684 #endif
685 }
686
687 /*
688 * init_sys
689 */
init_sys(void)690 void init_sys(void)
691 {
692 Reg int fd;
693
694 #ifdef RLIMIT_FD_MAX
695 struct rlimit limit;
696
697 if (!getrlimit(RLIMIT_FD_MAX, &limit))
698 {
699 if (limit.rlim_max < MAXCONNECTIONS)
700 {
701 (void)fprintf(stderr, "ircd fd table is too big\n");
702 (void)fprintf(stderr, "Hard Limit: %d IRC max: %d\n",
703 (int) limit.rlim_max, MAXCONNECTIONS);
704 (void)fprintf(stderr,
705 "Fix MAXCONNECTIONS and recompile.\n");
706 exit(-1);
707 }
708 limit.rlim_cur = limit.rlim_max; /* make soft limit the max */
709 if (setrlimit(RLIMIT_FD_MAX, &limit) == -1)
710 {
711 (void)fprintf(stderr, "error setting max fd's to %d\n",
712 (int) limit.rlim_cur);
713 exit(-1);
714 }
715 }
716 /* Let's assume that if it has define for fd limit, then
717 it can do core limits, too. --B. */
718 if (!getrlimit(RLIMIT_CORE, &limit))
719 {
720 limit.rlim_cur = limit.rlim_max;
721 if (limit.rlim_cur != RLIM_INFINITY)
722 {
723 (void)fprintf(stderr, "warning: max core"
724 " is not unlimited\n");
725 }
726 if (setrlimit(RLIMIT_CORE, &limit) == -1)
727 {
728 (void)fprintf(stderr, "error setting max core to %d\n",
729 (int) limit.rlim_cur);
730 exit(-1);
731 }
732 }
733 #endif
734 #if !defined(USE_POLL)
735 # ifdef sequent
736 # ifndef DYNIXPTX
737 int fd_limit;
738
739 fd_limit = setdtablesize(MAXCONNECTIONS + 1);
740 if (fd_limit < MAXCONNECTIONS)
741 {
742 (void)fprintf(stderr,"ircd fd table too big\n");
743 (void)fprintf(stderr,"Hard Limit: %d IRC max: %d\n",
744 fd_limit, MAXCONNECTIONS);
745 (void)fprintf(stderr,"Fix MAXCONNECTIONS\n");
746 exit(-1);
747 }
748 # endif
749 # endif
750 #endif /* USE_POLL */
751
752 #if defined(PCS) || defined(DYNIXPTX) || defined(SVR3)
753 char logbuf[BUFSIZ];
754
755 (void)setvbuf(stderr,logbuf,_IOLBF,sizeof(logbuf));
756 #else
757 # if defined(HPUX)
758 (void)setvbuf(stderr, NULL, _IOLBF, 0);
759 # else
760 # if !defined(SVR4)
761 (void)setlinebuf(stderr);
762 # endif
763 # endif
764 #endif
765
766 bzero((char *)&fdas, sizeof(fdas));
767 bzero((char *)&fdall, sizeof(fdall));
768 fdas.highest = fdall.highest = -1;
769 /* we need stderr open, don't close() it, daemonize() will do it */
770 /* after ircdwatch restarts ircd, we no longer have stderr, FIXME */
771 local[0] = local[1] = local[2] = NULL;
772 for (fd = 3; fd < MAXCONNECTIONS; fd++)
773 {
774 local[fd] = NULL;
775 (void)close(fd);
776 }
777 }
778
daemonize(void)779 void daemonize(void)
780 {
781 #ifdef TIOCNOTTY
782 int fd;
783 #endif
784
785 if (bootopt & BOOT_TTY) /* debugging is going to a tty */
786 goto init_dgram;
787
788 (void)fclose(stdout);
789 (void)close(1);
790
791 if (!(bootopt & BOOT_DEBUG))
792 {
793 (void)fclose(stderr);
794 (void)close(2);
795 }
796
797 if (((bootopt & BOOT_CONSOLE) || isatty(0)) &&
798 !(bootopt & BOOT_INETD))
799 {
800 if (fork())
801 exit(0);
802 #ifdef TIOCNOTTY
803 if ((fd = open("/dev/tty", O_RDWR)) >= 0)
804 {
805 (void)ioctl(fd, TIOCNOTTY, (char *)NULL);
806 (void)close(fd);
807 }
808 #endif
809 #if defined(HPUX) || defined(SVR4) || defined(DYNIXPTX) || \
810 defined(_POSIX_SOURCE) || defined(SGI)
811 (void)setsid();
812 #elif defined (__CYGWIN32__) || defined(__APPLE__)
813 (void)setpgrp();
814 #else
815 (void)setpgrp(0, (int)getpid());
816 #endif
817 (void)fclose(stdin);
818 (void)close(0);
819 }
820 init_dgram:
821 resfd = init_resolver(0x1f);
822
823 start_iauth(0);
824
825 }
826
827
write_pidfile(void)828 void write_pidfile(void)
829 {
830 int fd;
831 char buff[20];
832 (void)truncate(IRCDPID_PATH, 0);
833 if ((fd = open(IRCDPID_PATH, O_CREAT|O_WRONLY, 0600))>=0)
834 {
835 bzero(buff, sizeof(buff));
836 (void)sprintf(buff,"%5d\n", (int)getpid());
837 if (write(fd, buff, strlen(buff)) == -1)
838 {
839 Debug((DEBUG_NOTICE,"Error writing to pid file %s",
840 IRCDPID_PATH));
841 }
842 (void)close(fd);
843 return;
844 }
845 # ifdef DEBUGMODE
846 else
847 Debug((DEBUG_NOTICE,"Error opening pid file %s",
848 IRCDPID_PATH));
849 # endif
850 }
851
852 /*
853 * Initialize the various name strings used to store hostnames. This is set
854 * from either the server's sockhost (if client fd is a tty or localhost)
855 * or from the ip# converted into a string. 0 = success, -1 = fail.
856 */
check_init(aClient * cptr,char * sockn)857 static int check_init(aClient *cptr, char *sockn)
858 {
859 struct SOCKADDR_IN sk;
860 SOCK_LEN_TYPE len = sizeof(struct SOCKADDR_IN);
861
862 #ifdef UNIXPORT
863 if (IsUnixSocket(cptr))
864 {
865 strncpyzt(sockn, cptr->acpt->sockhost, HOSTLEN+1);
866 get_sockhost(cptr, sockn);
867 return 0;
868 }
869 #endif
870
871 /* If descriptor is a tty, special checking... */
872 if (isatty(cptr->fd))
873 {
874 strncpyzt(sockn, me.sockhost, HOSTLEN);
875 bzero((char *)&sk, sizeof(struct SOCKADDR_IN));
876 }
877 else if (getpeername(cptr->fd, (SAP)&sk, &len) == -1)
878 {
879 report_error("connect failure: %s %s", cptr);
880 return -1;
881 }
882 #ifdef INET6
883 inetntop(AF_INET6, (char *)&sk.sin6_addr, sockn, INET6_ADDRSTRLEN);
884 Debug((DEBUG_DNS,"sockn %x",sockn));
885 Debug((DEBUG_DNS,"sockn %s",sockn));
886 #else
887 (void)strcpy(sockn, (char *)inetntoa((char *)&sk.sin_addr));
888 #endif
889 bcopy((char *)&sk.SIN_ADDR, (char *)&cptr->ip, sizeof(struct IN_ADDR));
890 cptr->port = ntohs(sk.SIN_PORT);
891
892 return 0;
893 }
894
895 /*
896 * Ordinary client access check. Look for conf lines which have the same
897 * status as the flags passed.
898 * 0 = Success
899 * -1 = Bad socket.
900 * -2 = Access denied
901 */
check_client(aClient * cptr)902 int check_client(aClient *cptr)
903 {
904 char sockname[HOSTLEN+1];
905 Reg struct hostent *hp = NULL;
906 Reg int i;
907
908 #ifdef INET6
909 Debug((DEBUG_DNS, "ch_cl: check access for %s[%s]",
910 cptr->name, inet_ntop(AF_INET6, (char *)&cptr->ip, ipv6string,
911 sizeof(ipv6string))));
912 #else
913 Debug((DEBUG_DNS, "ch_cl: check access for %s[%s]",
914 cptr->name, inetntoa((char *)&cptr->ip)));
915 #endif
916
917 if (check_init(cptr, sockname))
918 return -1;
919
920 #ifdef UNIXPORT
921 if (!IsUnixSocket(cptr))
922 #endif
923 hp = cptr->hostp;
924 /*
925 * Verify that the host to ip mapping is correct both ways and that
926 * the ip#(s) for the socket is listed for the host.
927 */
928 if (hp)
929 {
930 for (i = 0; hp->h_addr_list[i]; i++)
931 if (!bcmp(hp->h_addr_list[i], (char *)&cptr->ip,
932 sizeof(struct IN_ADDR)))
933 break;
934 if (!hp->h_addr_list[i])
935 {
936 #ifdef INET6
937 sendto_flag(SCH_ERROR,
938 "IP# Mismatch: %s != %s[%08x%08x%08x%08x]",
939 inetntop(AF_INET6, (char *)&cptr->ip,
940 ipv6string,sizeof(ipv6string)), hp->h_name,
941 ((unsigned long *)hp->h_addr)[0],
942 ((unsigned long *)hp->h_addr)[1],
943 ((unsigned long *)hp->h_addr)[2],
944 ((unsigned long *)hp->h_addr)[3]);
945 #else
946 sendto_flag(SCH_ERROR, "IP# Mismatch: %s != %s[%08x]",
947 inetntoa((char *)&cptr->ip), hp->h_name,
948 *((unsigned long *)hp->h_addr));
949 #endif
950 hp = NULL;
951 cptr->hostp = NULL;
952 }
953 }
954
955 if ((i = attach_Iline(cptr, hp, sockname)))
956 {
957 Debug((DEBUG_DNS,"ch_cl: access denied: %s[%s]",
958 cptr->name, sockname));
959 return i;
960 }
961
962 Debug((DEBUG_DNS, "ch_cl: access ok: %s[%s]",
963 cptr->name, sockname));
964
965 #ifdef NO_OPER_REMOTE
966 if (
967 #ifdef UNIXPORT
968 IsUnixSocket(cptr) ||
969 #endif
970 #ifdef INET6
971 IN6_IS_ADDR_LOOPBACK(&cptr->ip) ||
972 /* If s6_addr32 was standard, we could just compare them,
973 * not memcmp. --B. */
974 !memcmp(cptr->ip.s6_addr, mysk.sin6_addr.s6_addr, 16)
975 #else
976 inetnetof(cptr->ip) == IN_LOOPBACKNET ||
977 cptr->ip.S_ADDR == mysk.SIN_ADDR.S_ADDR
978 #endif
979 )
980 {
981 ircstp->is_loc++;
982 cptr->flags |= FLAGS_LOCAL;
983 }
984 #endif /* NO_OPER_REMOTE */
985 return 0;
986 }
987
988 /*
989 * check_server_init(), check_server()
990 * check access for a server given its name (passed in cptr struct).
991 * Must check for all C/N lines which have a name which matches the
992 * name given and a host which matches. A host alias which is the
993 * same as the server name is also acceptable in the host field of a
994 * C/N line.
995 * 0 = Success
996 * -1 = Access denied
997 * -2 = Bad socket.
998 */
check_server_init(aClient * cptr)999 int check_server_init(aClient *cptr)
1000 {
1001 Reg char *name;
1002 Reg aConfItem *c_conf = NULL, *n_conf = NULL;
1003 struct hostent *hp = NULL;
1004 Link *lp;
1005
1006 name = cptr->name;
1007 Debug((DEBUG_DNS, "sv_cl: check access for %s[%s]",
1008 name, cptr->sockhost));
1009
1010 if (IsUnknown(cptr) && !attach_confs(cptr, name, CFLAG|NFLAG))
1011 {
1012 Debug((DEBUG_DNS,"No C/N lines for %s", name));
1013 return -1;
1014 }
1015 lp = cptr->confs;
1016 /*
1017 * We initiated this connection so the client should have a C and N
1018 * line already attached after passing through the connec_server()
1019 * function earlier.
1020 */
1021 if (IsConnecting(cptr) || IsHandshake(cptr))
1022 {
1023 c_conf = find_conf(lp, name, CFLAG);
1024 n_conf = find_conf(lp, name, NFLAG);
1025 if (!c_conf || !n_conf)
1026 {
1027 sendto_flag(SCH_ERROR, "Connecting Error: %s[%s]",
1028 name, cptr->sockhost);
1029 det_confs_butmask(cptr, 0);
1030 return -1;
1031 }
1032 }
1033 #ifdef UNIXPORT
1034 if (IsUnixSocket(cptr))
1035 {
1036 if (!c_conf)
1037 c_conf = find_conf(lp, name, CFLAG);
1038 if (!n_conf)
1039 n_conf = find_conf(lp, name, NFLAG);
1040 }
1041 #endif
1042
1043 /*
1044 ** If the servername is a hostname, either an alias (CNAME) or
1045 ** real name, then check with it as the host. Use gethostbyname()
1046 ** to check for servername as hostname.
1047 */
1048 if (!cptr->hostp
1049 #ifdef UNIXPORT
1050 && !IsUnixSocket(cptr)
1051 #endif
1052 )
1053 {
1054 Reg aConfItem *aconf;
1055
1056 aconf = count_cnlines(lp);
1057 if (aconf)
1058 {
1059 Reg char *s;
1060 Link lin;
1061
1062 /*
1063 ** Do a lookup for the CONF line *only* and not
1064 ** the server connection else we get stuck in a
1065 ** nasty state since it takes a SERVER message to
1066 ** get us here and we can't interrupt that very
1067 ** well.
1068 */
1069 lin.value.aconf = aconf;
1070 lin.flags = ASYNC_CONF;
1071 nextdnscheck = 1;
1072 if ((s = index(aconf->host, '@')))
1073 s++;
1074 else
1075 s = aconf->host;
1076 Debug((DEBUG_DNS,"sv_ci:cache lookup (%s)",s));
1077 hp = gethost_byname(s, &lin);
1078 }
1079 }
1080 return check_server(cptr, hp, c_conf, n_conf);
1081 }
1082
check_server(aClient * cptr,struct hostent * hp,aConfItem * c_conf,aConfItem * n_conf)1083 int check_server(aClient *cptr, struct hostent *hp,
1084 aConfItem *c_conf, aConfItem *n_conf)
1085 {
1086 Reg char *name;
1087 char abuff[HOSTLEN+USERLEN+2];
1088 char sockname[HOSTLEN+1], fullname[HOSTLEN+1];
1089 Link *lp = cptr->confs;
1090 int i;
1091
1092 if (check_init(cptr, sockname))
1093 return -2;
1094
1095 check_serverback:
1096 if (hp)
1097 {
1098 for (i = 0; hp->h_addr_list[i]; i++)
1099 if (!bcmp(hp->h_addr_list[i], (char *)&cptr->ip,
1100 sizeof(struct IN_ADDR)))
1101 break;
1102 if (!hp->h_addr_list[i])
1103 {
1104 #ifdef INET6
1105 sendto_flag(SCH_ERROR,
1106 "IP# Mismatch: %s != %s[%08x%08x%08x%08x]",
1107 inetntop(AF_INET6, (char *)&cptr->ip,
1108 ipv6string, sizeof(ipv6string)),hp->h_name,
1109 ((unsigned long *)hp->h_addr)[0],
1110 ((unsigned long *)hp->h_addr)[1],
1111 ((unsigned long *)hp->h_addr)[2],
1112 ((unsigned long *)hp->h_addr)[3]);
1113 #else
1114 sendto_flag(SCH_ERROR, "IP# Mismatch: %s != %s[%08x]",
1115 inetntoa((char *)&cptr->ip), hp->h_name,
1116 *((unsigned long *)hp->h_addr));
1117 #endif
1118 hp = NULL;
1119 }
1120 }
1121 else if (cptr->hostp)
1122 {
1123 hp = cptr->hostp;
1124 goto check_serverback;
1125 }
1126
1127 if (hp)
1128 /*
1129 * if we are missing a C or N line from above, search for
1130 * it under all known hostnames we have for this ip#.
1131 */
1132 for (i=0,name = hp->h_name; name ; name = hp->h_aliases[i++])
1133 {
1134 strncpyzt(fullname, name, sizeof(fullname));
1135 add_local_domain(fullname, HOSTLEN-strlen(fullname));
1136 Debug((DEBUG_DNS, "sv_cl: gethostbyaddr: %s->%s",
1137 sockname, fullname));
1138 sprintf(abuff, "%s@%s", cptr->username, fullname);
1139 if (!c_conf)
1140 c_conf = find_conf_host(lp, abuff, CFLAG);
1141 if (!n_conf)
1142 n_conf = find_conf_host(lp, abuff, NFLAG);
1143 if (c_conf && n_conf)
1144 {
1145 get_sockhost(cptr, fullname);
1146 break;
1147 }
1148 }
1149 name = cptr->name;
1150
1151 /*
1152 * Check for C and N lines with the hostname portion the ip number
1153 * of the host the server runs on. This also checks the case where
1154 * there is a server connecting from 'localhost'.
1155 */
1156 if (IsUnknown(cptr) && (!c_conf || !n_conf))
1157 {
1158 sprintf(abuff, "%s@%s", cptr->username, sockname);
1159 if (!c_conf)
1160 c_conf = find_conf_host(lp, abuff, CFLAG);
1161 if (!n_conf)
1162 n_conf = find_conf_host(lp, abuff, NFLAG);
1163 }
1164 /*
1165 * Attach by IP# only if all other checks have failed.
1166 * It is quite possible to get here with the strange things that can
1167 * happen when using DNS in the way the irc server does. -avalon
1168 */
1169 if (!hp)
1170 {
1171 if (!c_conf)
1172 c_conf = find_conf_ip(lp, (char *)&cptr->ip,
1173 cptr->username, CFLAG);
1174 if (!n_conf)
1175 n_conf = find_conf_ip(lp, (char *)&cptr->ip,
1176 cptr->username, NFLAG);
1177 }
1178 else
1179 for (i = 0; hp->h_addr_list[i]; i++)
1180 {
1181 if (!c_conf)
1182 c_conf = find_conf_ip(lp, hp->h_addr_list[i],
1183 cptr->username, CFLAG);
1184 if (!n_conf)
1185 n_conf = find_conf_ip(lp, hp->h_addr_list[i],
1186 cptr->username, NFLAG);
1187 }
1188 /*
1189 * detach all conf lines that got attached by attach_confs()
1190 */
1191 det_confs_butmask(cptr, 0);
1192 /*
1193 * if no C or no N lines, then deny access
1194 */
1195 if (!c_conf || !n_conf)
1196 {
1197 get_sockhost(cptr, sockname);
1198 Debug((DEBUG_DNS, "sv_cl: access denied: %s[%s@%s] c %x n %x",
1199 name, cptr->auth, cptr->sockhost,
1200 c_conf, n_conf));
1201 return -1;
1202 }
1203 /*
1204 * attach the C and N lines to the client structure for later use.
1205 */
1206 (void)attach_confs(cptr, name, CONF_HUB|CONF_LEAF);
1207 (void)attach_conf(cptr, n_conf);
1208 (void)attach_conf(cptr, c_conf);
1209 if (IsIllegal(n_conf) || IsIllegal(c_conf))
1210 {
1211 sendto_flag(SCH_DEBUG, "Illegal class!");
1212 return -2;
1213 }
1214 if (!n_conf->host || !c_conf->host)
1215 {
1216 sendto_flag(SCH_DEBUG, "Null host in class!");
1217 return -2;
1218 }
1219
1220 if (
1221 #ifdef INET6
1222 AND16(c_conf->ipnum.s6_addr) == 255
1223 #else
1224 c_conf->ipnum.s_addr == -1
1225 #endif
1226 #ifdef UNIXPORT
1227 && !IsUnixSocket(cptr)
1228 #endif
1229 )
1230 {
1231 bcopy((char *)&cptr->ip, (char *)&c_conf->ipnum,
1232 sizeof(struct IN_ADDR));
1233 }
1234 #ifdef UNIXPORT
1235 if (!IsUnixSocket(cptr))
1236 #endif
1237 get_sockhost(cptr, c_conf->host);
1238
1239 Debug((DEBUG_DNS,"sv_cl: access ok: %s[%s]",
1240 name, cptr->sockhost));
1241 return 0;
1242 }
1243
1244 /*
1245 ** completed_connection
1246 ** Complete non-blocking connect()-sequence. Check access and
1247 ** terminate connection, if trouble detected.
1248 **
1249 ** Return TRUE, if successfully completed
1250 ** FALSE, if failed and ClientExit
1251 */
completed_connection(aClient * cptr)1252 static int completed_connection(aClient *cptr)
1253 {
1254 aConfItem *aconf;
1255
1256 SetHandshake(cptr);
1257
1258 aconf = find_conf(cptr->confs, cptr->name, CFLAG);
1259 if (!aconf)
1260 {
1261 sendto_flag(SCH_NOTICE,
1262 "Lost C-Line for %s", get_client_name(cptr,FALSE));
1263 return -1;
1264 }
1265 if (!BadPtr(aconf->passwd))
1266 sendto_one(cptr, "PASS %s %s IRC|%s %s%s%s", aconf->passwd,
1267 pass_version, serveropts,
1268 (bootopt & BOOT_STRICTPROT) ? "P" : "",
1269 #ifdef JAPANESE
1270 "j",
1271 #else
1272 "",
1273 #endif
1274 #ifdef ZIP_LINKS
1275 (aconf->status == CONF_ZCONNECT_SERVER) ? "Z" :
1276 #endif
1277 ""
1278 );
1279
1280 aconf = find_conf(cptr->confs, cptr->name, CONF_NOCONNECT_SERVER);
1281 if (!aconf)
1282 {
1283 sendto_flag(SCH_NOTICE,
1284 "Lost N-Line for %s", get_client_name(cptr,FALSE));
1285 return -1;
1286 }
1287 sendto_one(cptr, "SERVER %s 1 %s :%s",
1288 my_name_for_link(ME, aconf->port), me.serv->sid, me.info);
1289 if (!IsDead(cptr))
1290 {
1291 start_auth(cptr);
1292 #if defined(USE_IAUTH)
1293 /*
1294 ** This could become a bug.. but I don't think iauth needs the
1295 ** hostname/aliases in this case. -kalt
1296 */
1297 sendto_iauth("%d d", cptr->fd);
1298 #endif
1299 }
1300
1301 return (IsDead(cptr)) ? -1 : 0;
1302 }
1303
1304 /*
1305 * Closes FD in aClient structures.
1306 */
close_client_fd(aClient * cptr)1307 void close_client_fd(aClient *cptr)
1308 {
1309 int i;
1310
1311 #ifdef SO_LINGER
1312 struct linger sockling;
1313
1314 sockling.l_onoff = 0;
1315 #endif
1316
1317 if (cptr->authfd >= 0)
1318 {
1319 #ifdef SO_LINGER
1320 if (cptr->exitc == EXITC_PING)
1321 if (SETSOCKOPT(cptr->authfd, SOL_SOCKET, SO_LINGER,
1322 &sockling, sockling))
1323 report_error("setsockopt(SO_LINGER) %s:%s",
1324 cptr);
1325 #endif
1326 (void)close(cptr->authfd);
1327
1328 cptr->authfd = -1;
1329 }
1330
1331 if ((i = cptr->fd) >= 0)
1332 {
1333 flush_connections(i);
1334 if (IsServer(cptr) || IsListener(cptr))
1335 {
1336 del_fd(i, &fdas);
1337 #ifdef ZIP_LINKS
1338 /*
1339 ** the connection might have zip data (even if
1340 ** FLAGS_ZIP is not set)
1341 */
1342 zip_free(cptr);
1343 #endif
1344 }
1345 else if (IsClient(cptr))
1346 {
1347 #ifdef SO_LINGER
1348 if (cptr->exitc == EXITC_PING)
1349 if (SETSOCKOPT(i, SOL_SOCKET, SO_LINGER,
1350 &sockling, sockling))
1351 report_error("setsockopt(SO_LINGER) %s:%s",
1352 cptr);
1353 #endif
1354 }
1355 del_fd(i, &fdall);
1356 local[i] = NULL;
1357 (void)close(i);
1358
1359 cptr->fd = -1;
1360 DBufClear(&cptr->sendQ);
1361 DBufClear(&cptr->recvQ);
1362 bzero(cptr->passwd, sizeof(cptr->passwd));
1363 }
1364 }
1365
1366 /*
1367 ** close_connection
1368 ** Close the physical connection. This function must make
1369 ** MyConnect(cptr) == FALSE, and set cptr->from == NULL.
1370 */
close_connection(aClient * cptr)1371 void close_connection(aClient *cptr)
1372 {
1373 aConfItem *aconf;
1374
1375 if (IsServer(cptr))
1376 {
1377 ircstp->is_sv++;
1378 ircstp->is_sbs += cptr->sendB;
1379 ircstp->is_sbr += cptr->receiveB;
1380 ircstp->is_sti += timeofday - cptr->firsttime;
1381 }
1382 else if (IsClient(cptr))
1383 {
1384 ircstp->is_cl++;
1385 ircstp->is_cbs += cptr->sendB;
1386 ircstp->is_cbr += cptr->receiveB;
1387 ircstp->is_cti += timeofday - cptr->firsttime;
1388 }
1389 else
1390 {
1391 ircstp->is_ni++;
1392 }
1393
1394 /*
1395 * remove outstanding DNS queries.
1396 */
1397 del_queries((char *)cptr);
1398 /*
1399 * If the server connection has been up for a long amount of time,
1400 * schedule a 'quick' reconnect, else reset the next-connect cycle.
1401 */
1402 if (IsServer(cptr) &&
1403 (aconf = find_conf_exact(cptr->name, cptr->username,
1404 cptr->sockhost, CFLAG)))
1405 {
1406 /*
1407 * Reschedule a faster reconnect, if this was a automatically
1408 * connected configuration entry. (Note that if we have had
1409 * a rehash in between, the status has been changed to
1410 * CONF_ILLEGAL). But only do this if it was a "good" link.
1411 */
1412 aconf->hold = timeofday;
1413 aconf->hold += (aconf->hold - cptr->since > HANGONGOODLINK) ?
1414 HANGONRETRYDELAY : ConfConFreq(aconf);
1415 /* nextconnect could be 0 */
1416 if (nextconnect > aconf->hold || nextconnect == 0)
1417 {
1418 nextconnect = aconf->hold;
1419 }
1420 }
1421
1422 if (nextconnect == 0 && (IsHandshake(cptr) || IsConnecting(cptr)))
1423 {
1424 nextconnect = timeofday + HANGONRETRYDELAY;
1425 }
1426
1427 if (cptr->fd >= 0)
1428 {
1429 #if defined(USE_IAUTH)
1430 if (!IsListener(cptr) && !IsConnecting(cptr))
1431 {
1432 /* iauth doesn't know about listening FD nor
1433 * cancelled outgoing connections.
1434 */
1435 sendto_iauth("%d D", cptr->fd);
1436 }
1437 #endif
1438 /*
1439 * clean up extra sockets from P-lines which have been
1440 * discarded.
1441 */
1442 if ((cptr->acpt != &me) && !(IsListener(cptr)))
1443 {
1444 aconf = cptr->acpt->confs->value.aconf;
1445
1446 if (aconf->clients > 0)
1447 {
1448 aconf->clients--;
1449 }
1450
1451 if (!aconf->clients && IsIllegal(aconf))
1452 {
1453 close_connection(cptr->acpt);
1454 }
1455 }
1456 }
1457
1458 close_client_fd(cptr);
1459
1460 /* Remove from Listener Linked list */
1461 if (IsListener(cptr) && cptr->confs && cptr->confs->value.aconf &&
1462 IsIllegal(cptr->confs->value.aconf) &&
1463 cptr->confs->value.aconf->clients <= 0)
1464 {
1465 if (cptr->prev)
1466 {
1467 cptr->prev->next = cptr->next;
1468 }
1469 else
1470 {
1471 /* we were 1st */
1472 ListenerLL = cptr->next;
1473 }
1474 if (cptr->next)
1475 {
1476 cptr->next->prev = cptr->prev;
1477 }
1478 }
1479
1480 det_confs_butmask(cptr, 0);
1481 cptr->from = NULL; /* ...this should catch them! >:) --msa */
1482 return;
1483 }
1484
1485 /*
1486 ** set_sock_opts
1487 */
set_sock_opts(int fd,aClient * cptr)1488 static int set_sock_opts(int fd, aClient *cptr)
1489 {
1490 int opt, ret = 0;
1491 #ifdef SO_REUSEADDR
1492 opt = 1;
1493 if (SETSOCKOPT(fd, SOL_SOCKET, SO_REUSEADDR, &opt, opt) < 0)
1494 report_error("setsockopt(SO_REUSEADDR) %s:%s", cptr);
1495 #endif
1496 #if defined(SO_DEBUG) && defined(DEBUGMODE) && 0
1497 /* Solaris 2.x with SO_DEBUG writes to syslog by default */
1498 #if !defined(SOLARIS_2) || defined(USE_SYSLOG)
1499 opt = 1;
1500 if (SETSOCKOPT(fd, SOL_SOCKET, SO_DEBUG, &opt, opt) < 0)
1501 report_error("setsockopt(SO_DEBUG) %s:%s", cptr);
1502 #endif /* SOLARIS_2 */
1503 #endif
1504 #if defined(SO_USELOOPBACK) && !defined(__CYGWIN32__)
1505 opt = 1;
1506 if (SETSOCKOPT(fd, SOL_SOCKET, SO_USELOOPBACK, &opt, opt) < 0)
1507 report_error("setsockopt(SO_USELOOPBACK) %s:%s", cptr);
1508 #endif
1509 #ifdef SO_RCVBUF
1510 opt = 8192;
1511 if (SETSOCKOPT(fd, SOL_SOCKET, SO_RCVBUF, &opt, opt) < 0)
1512 report_error("setsockopt(SO_RCVBUF) %s:%s", cptr);
1513 #endif
1514 #ifdef SO_SNDBUF
1515 # ifdef _SEQUENT_
1516 /* seems that Sequent freezes up if the receving buffer is a different size
1517 * to the sending buffer (maybe a tcp window problem too).
1518 */
1519 # endif
1520 opt = 8192;
1521 if (SETSOCKOPT(fd, SOL_SOCKET, SO_SNDBUF, &opt, opt) < 0)
1522 report_error("setsockopt(SO_SNDBUF) %s:%s", cptr);
1523 # ifdef SO_SNDLOWAT
1524 /*
1525 * Setting the low water mark should improve performence by avoiding
1526 * early returns from select()/poll(). It shouldn't delay sending
1527 * data, provided that io_loop() combines read_message() and
1528 * flush_fdary/connections() calls properly. -kalt
1529 * This call isn't always implemented, even when defined.. so be quiet
1530 * about errors. -kalt
1531 */
1532 opt = 8192;
1533 SETSOCKOPT(fd, SOL_SOCKET, SO_SNDLOWAT, &opt, opt);
1534 # endif
1535 #endif
1536 #if defined(IP_OPTIONS) && defined(IPPROTO_IP) && !defined(AIX) && \
1537 !defined(INET6)
1538 /*
1539 * Mainly to turn off and alert us to source routing, here.
1540 * Method borrowed from Wietse Venema's TCP wrapper.
1541 */
1542 {
1543 if (!IsListener(cptr)
1544 #ifdef UNIXPORT
1545 && !IsUnixSocket(cptr)
1546 #endif
1547 )
1548 {
1549 u_char opbuf[256], *t = opbuf;
1550 char *s = readbuf;
1551
1552 opt = sizeof(opbuf);
1553 if (GETSOCKOPT(fd, IPPROTO_IP, IP_OPTIONS, t, &opt) == -1)
1554 report_error("getsockopt(IP_OPTIONS) %s:%s", cptr);
1555 else if (opt > 0)
1556 {
1557 for (; opt > 0; opt--, s+= 3)
1558 (void)sprintf(s, " %02x", *t++);
1559 *s = '\0';
1560 sendto_flag(SCH_NOTICE,
1561 "Connection %s with IP opts%s",
1562 get_client_name(cptr, TRUE), readbuf);
1563 Debug((DEBUG_NOTICE,
1564 "Connection %s with IP opts%s",
1565 get_client_name(cptr, TRUE), readbuf));
1566 ret = -1;
1567 }
1568 }
1569 }
1570 #endif
1571 return ret;
1572 }
1573
get_sockerr(aClient * cptr)1574 int get_sockerr(aClient *cptr)
1575 {
1576 int errtmp = errno, err = 0;
1577 SOCK_LEN_TYPE len = sizeof(err);
1578
1579 #ifdef SO_ERROR
1580 if (cptr->fd >= 0)
1581 if (!GETSOCKOPT(cptr->fd, SOL_SOCKET, SO_ERROR, &err, &len))
1582 if (err)
1583 errtmp = err;
1584 #endif
1585 return errtmp;
1586 }
1587
1588 /*
1589 ** set_non_blocking
1590 ** Set the client connection into non-blocking mode. If your
1591 ** system doesn't support this, you can make this a dummy
1592 ** function (and get all the old problems that plagued the
1593 ** blocking version of IRC--not a problem if you are a
1594 ** lightly loaded node...)
1595 */
set_non_blocking(int fd,aClient * cptr)1596 void set_non_blocking(int fd, aClient *cptr)
1597 {
1598 int res, nonb = 0;
1599
1600 /*
1601 ** NOTE: consult ALL your relevant manual pages *BEFORE* changing
1602 ** these ioctl's. There are quite a few variations on them,
1603 ** as can be seen by the PCS one. They are *NOT* all the same.
1604 ** Heed this well. - Avalon.
1605 */
1606 #ifdef NBLOCK_POSIX
1607 nonb |= O_NONBLOCK;
1608 #endif
1609 #ifdef NBLOCK_BSD
1610 nonb |= O_NDELAY;
1611 #endif
1612 #ifdef NBLOCK_SYSV
1613 /* This portion of code might also apply to NeXT. -LynX */
1614 res = 1;
1615
1616 if (ioctl (fd, FIONBIO, &res) < 0)
1617 report_error("ioctl(fd,FIONBIO) failed for %s:%s", cptr);
1618 #else
1619 if ((res = fcntl(fd, F_GETFL, 0)) == -1)
1620 report_error("fcntl(fd, F_GETFL) failed for %s:%s",cptr);
1621 else if (fcntl(fd, F_SETFL, res | nonb) == -1)
1622 report_error("fcntl(fd, F_SETL, nonb) failed for %s:%s",cptr);
1623 #endif
1624 return;
1625 }
1626
1627 #ifdef CLONE_CHECK
1628 /*
1629 * check_clones
1630 * adapted by jecete 4 IRC Ptnet
1631 */
check_clones(aClient * cptr)1632 static int check_clones(aClient *cptr)
1633 {
1634 struct abacklog {
1635 struct IN_ADDR ip;
1636 time_t PT;
1637 struct abacklog *next;
1638 };
1639 static struct abacklog *backlog = NULL;
1640 register struct abacklog **blscn = &backlog,
1641 *blptr;
1642 register int count = 0;
1643
1644 /* First, ditch old entries */
1645 while (*blscn != NULL)
1646 {
1647 if ((*blscn)->PT+CLONE_PERIOD < timeofday)
1648 {
1649 blptr= *blscn;
1650 *blscn=blptr->next;
1651 MyFree(blptr);
1652 }
1653 else
1654 blscn = &(*blscn)->next;
1655 }
1656 /* Now add new item to the list */
1657 blptr = (struct abacklog *) MyMalloc(sizeof(struct abacklog));
1658 #ifdef INET6
1659 bcopy(cptr->ip.s6_addr, blptr->ip.s6_addr, IN6ADDRSZ);
1660 #else
1661 blptr->ip.s_addr = cptr->ip.s_addr;
1662 #endif
1663 blptr->PT = timeofday;
1664 blptr->next = backlog;
1665 backlog = blptr;
1666
1667 /* Count the number of entries from the same host */
1668 blptr = backlog;
1669 while (blptr != NULL)
1670 {
1671 #ifdef INET6
1672 if (bcmp(blptr->ip.s6_addr, cptr->ip.s6_addr, IN6ADDRSZ) == 0)
1673 #else
1674 if (blptr->ip.s_addr == cptr->ip.s_addr)
1675 #endif
1676 count++;
1677 blptr = blptr->next;
1678 }
1679 return (count);
1680 }
1681 #endif
1682
1683 /* moved from inner blocks of add_connection to get rid of gotos */
add_connection_refuse(int fd,aClient * acptr,int delay)1684 void add_connection_refuse(int fd, aClient *acptr, int delay)
1685 {
1686 #if !defined(DELAY_CLOSE)
1687 delay = 0;
1688 #endif
1689 if (!delay)
1690 {
1691 (void)close(fd);
1692 }
1693 ircstp->is_ref++;
1694 acptr->fd = -2;
1695 free_client(acptr);
1696 }
1697
1698 /*
1699 * Creates a client which has just connected to us on the given fd.
1700 * The sockhost field is initialized with the ip# of the host.
1701 * The client is added to the linked list of clients but isnt added to any
1702 * hash tables yet since it doesnt have a name.
1703 */
add_connection(aClient * cptr,int fd)1704 aClient *add_connection(aClient *cptr, int fd)
1705 {
1706 Link lin;
1707 aClient *acptr;
1708 aConfItem *aconf = NULL;
1709 acptr = make_client(NULL);
1710
1711 aconf = cptr->confs->value.aconf;
1712 acptr->acpt = cptr;
1713
1714 /* Removed preliminary access check. Full check is performed in
1715 * m_server and m_user instead. Also connection time out help to
1716 * get rid of unwanted connections.
1717 */
1718 if (isatty(fd)) /* If descriptor is a tty, special checking... */
1719 get_sockhost(acptr, cptr->sockhost);
1720 else
1721 {
1722 struct SOCKADDR_IN addr;
1723 SOCK_LEN_TYPE len = sizeof(struct SOCKADDR_IN);
1724
1725 if (getpeername(fd, (SAP)&addr, &len) == -1)
1726 {
1727 #if defined(linux)
1728 if (errno != ENOTCONN)
1729 #endif
1730 report_error("Failed in connecting to %s :%s",
1731 cptr);
1732 add_connection_refuse(fd, acptr, 0);
1733 return NULL;
1734 }
1735 /* don't want to add "Failed in connecting to" here.. */
1736 if (aconf && IsIllegal(aconf))
1737 {
1738 add_connection_refuse(fd, acptr, 0);
1739 return NULL;
1740 }
1741 /* Copy ascii address to 'sockhost' just in case. Then we
1742 * have something valid to put into error messages...
1743 */
1744 #ifdef INET6
1745 inetntop(AF_INET6, (char *)&addr.sin6_addr, ipv6string,
1746 sizeof(ipv6string));
1747 get_sockhost(acptr, (char *)ipv6string);
1748 #else
1749 get_sockhost(acptr, (char *)inetntoa((char *)&addr.sin_addr));
1750 #endif
1751 bcopy ((char *)&addr.SIN_ADDR, (char *)&acptr->ip,
1752 sizeof(struct IN_ADDR));
1753 acptr->port = ntohs(addr.SIN_PORT);
1754
1755 #ifdef CLONE_CHECK
1756 if (check_clones(acptr) > CLONE_MAX)
1757 {
1758 sendto_flag(SCH_LOCAL, "Rejecting connection from %s.",
1759 acptr->sockhost);
1760 acptr->exitc = EXITC_CLONE;
1761 sendto_flog(acptr, EXITC_CLONE, "", acptr->sockhost);
1762 #ifdef DELAY_CLOSE
1763 nextdelayclose = delay_close(fd);
1764 #else
1765 (void)send(fd, "ERROR :Too rapid connections from your "
1766 "host\r\n", 46, 0);
1767 #endif
1768 /* If DELAY_CLOSE is not defined, delay will
1769 ** be changed to 0 inside. --B. */
1770 add_connection_refuse(fd, acptr, 1);
1771 return NULL;
1772 }
1773 #endif
1774 lin.flags = ASYNC_CLIENT;
1775 lin.value.cptr = acptr;
1776 lin.next = NULL;
1777 #ifdef INET6
1778 Debug((DEBUG_DNS, "lookup %s",
1779 inet_ntop(AF_INET6, (char *)&addr.sin6_addr,
1780 ipv6string, sizeof(ipv6string))));
1781 #else
1782 Debug((DEBUG_DNS, "lookup %s",
1783 inetntoa((char *)&addr.sin_addr)));
1784 #endif
1785 acptr->hostp = gethost_byaddr((char *)&acptr->ip, &lin);
1786 if (!acptr->hostp)
1787 SetDNS(acptr);
1788 nextdnscheck = 1;
1789 }
1790
1791 acptr->fd = fd;
1792 set_non_blocking(acptr->fd, acptr);
1793 if (set_sock_opts(acptr->fd, acptr) == -1)
1794 {
1795 add_connection_refuse(fd, acptr, 0);
1796 return NULL;
1797 }
1798 if (aconf)
1799 aconf->clients++;
1800 if (fd > highest_fd)
1801 highest_fd = fd;
1802 local[fd] = acptr;
1803 add_fd(fd, &fdall);
1804 add_client_to_list(acptr);
1805 start_auth(acptr);
1806 #if defined(USE_IAUTH)
1807 if (!isatty(fd) && !DoingDNS(acptr))
1808 {
1809 int i = 0;
1810
1811 while (acptr->hostp->h_aliases[i])
1812 sendto_iauth("%d A %s", acptr->fd,
1813 acptr->hostp->h_aliases[i++]);
1814 if (acptr->hostp->h_name)
1815 sendto_iauth("%d N %s",acptr->fd,acptr->hostp->h_name);
1816 else if (acptr->hostp->h_aliases[0])
1817 sendto_iauth("%d n", acptr->fd);
1818 }
1819 #endif
1820 return acptr;
1821 }
1822
1823 #ifdef UNIXPORT
add_unixconnection(aClient * cptr,int fd)1824 static aClient *add_unixconnection(aClient *cptr, int fd)
1825 {
1826 aClient *acptr;
1827 aConfItem *aconf = NULL;
1828
1829 acptr = make_client(NULL);
1830
1831 /* Copy ascii address to 'sockhost' just in case. Then we
1832 * have something valid to put into error messages...
1833 */
1834 get_sockhost(acptr, me.sockhost);
1835 aconf = cptr->confs->value.aconf;
1836 if (aconf)
1837 {
1838 if (IsIllegal(aconf))
1839 {
1840 ircstp->is_ref++;
1841 acptr->fd = -2;
1842 free_client(acptr);
1843 (void)close(fd);
1844 return NULL;
1845 }
1846 else
1847 aconf->clients++;
1848 }
1849 acptr->fd = fd;
1850 if (fd > highest_fd)
1851 highest_fd = fd;
1852 local[fd] = acptr;
1853 add_fd(fd, &fdall);
1854 acptr->acpt = cptr;
1855 SetUnixSock(acptr);
1856 bcopy((char *)&me.ip, (char *)&acptr->ip, sizeof(struct IN_ADDR));
1857
1858 add_client_to_list(acptr);
1859 set_non_blocking(acptr->fd, acptr);
1860 (void)set_sock_opts(acptr->fd, acptr);
1861 # if defined(USE_IAUTH)
1862 /*
1863 ** iauth protocol and iauth itself should be extended to alllow
1864 ** dealing with this type of connection.
1865 */
1866 sendto_iauth("%d O", acptr->fd);
1867 SetDoneXAuth(acptr);
1868 # endif
1869 return acptr;
1870 }
1871 #endif
1872
1873 /*
1874 ** read_listener
1875 **
1876 ** Accept incoming connections, extracted from read_message() 98/12 -kalt
1877 ** Up to LISTENER_MAXACCEPT connections will be accepted in one run.
1878 */
read_listener(aClient * cptr)1879 static void read_listener(aClient *cptr)
1880 {
1881 int fdnew, max = LISTENER_MAXACCEPT;
1882 aClient *acptr;
1883
1884 while (max--)
1885 {
1886 /*
1887 ** There may be many reasons for error return, but in otherwise
1888 ** correctly working environment the probable cause is running
1889 ** out of file descriptors (EMFILE, ENFILE or others?). The
1890 ** man pages for accept don't seem to list these as possible,
1891 ** although it's obvious that it may happen here.
1892 ** Thus no specific errors are tested at this point, just
1893 ** assume that connections cannot be accepted until some old
1894 ** is closed first.
1895 */
1896 if ((fdnew = accept(cptr->fd, NULL, NULL)) < 0)
1897 {
1898 if (errno != EWOULDBLOCK)
1899 report_error("Cannot accept connection %s:%s",
1900 cptr);
1901 break;
1902 }
1903 ircstp->is_ac++;
1904 if (fdnew >= MAXCLIENTS)
1905 {
1906 ircstp->is_ref++;
1907 sendto_flag(SCH_ERROR, "All connections in use. (%s)",
1908 get_client_name(cptr, TRUE));
1909 find_bounce(NULL, 0, fdnew);
1910 (void)send(fdnew, "ERROR :All connections in use\r\n",
1911 32, 0);
1912 (void)close(fdnew);
1913 continue;
1914 }
1915
1916 /* Can cptr->confs->value.aconf be NULL? --B. */
1917 if ((iconf.caccept == 0 ||
1918 (iconf.caccept == 2 && iconf.split == 1))
1919 && cptr->confs->value.aconf != NULL
1920 && IsConfDelayed(cptr->confs->value.aconf))
1921 {
1922 /* Should we bother sendto_flag(SCH_ERROR...? --B. */
1923 #ifdef CACCEPT_DELAYED_CLOSE
1924 nextdelayclose = delay_close(fdnew);
1925 ircstp->is_ref++;
1926 #else
1927 (void)send(fdnew, "ERROR :All client connections are "
1928 "temporarily refused.\r\n", 56, 0);
1929 (void)close(fdnew);
1930 #endif
1931 continue;
1932 }
1933
1934 #ifdef UNIXPORT
1935 if (IsUnixSocket(cptr))
1936 acptr = add_unixconnection(cptr, fdnew);
1937 else
1938 #endif
1939 acptr = add_connection(cptr, fdnew);
1940
1941 if (acptr == NULL)
1942 {
1943 continue;
1944 }
1945 nextping = timeofday; /* isn't this abusive? -kalt */
1946 istat.is_unknown++;
1947
1948 /* Notice on connect. */
1949 sendto_one(acptr, replies[RPL_HELLO], ME, HELLO_MSG);
1950 }
1951 }
1952
1953 /*
1954 ** client_packet
1955 **
1956 ** Process data from receive buffer to client.
1957 ** Extracted from read_packet() 960804/291p3/Vesa
1958 */
client_packet(aClient * cptr)1959 static int client_packet(aClient *cptr)
1960 {
1961 Reg int dolen = 0;
1962
1963 while (DBufLength(&cptr->recvQ) && !NoNewLine(cptr) &&
1964 ((cptr->status < STAT_UNKNOWN) ||
1965 (cptr->since - timeofday < MAXPENALTY)))
1966 {
1967 /*
1968 ** If it has become registered as a Service or Server
1969 ** then skip the per-message parsing below.
1970 */
1971 if (IsService(cptr) || IsServer(cptr))
1972 {
1973 dolen = dbuf_get(&cptr->recvQ, readbuf,
1974 sizeof(readbuf));
1975 if (dolen <= 0)
1976 break;
1977 dolen = dopacket(cptr, readbuf, dolen);
1978 if (dolen == 2 && cptr->since == cptr->lasttime)
1979 cptr->since += 5;
1980 if (dolen)
1981 return dolen;
1982 break;
1983 }
1984 dolen = dbuf_getmsg(&cptr->recvQ, readbuf,
1985 sizeof(readbuf));
1986 /*
1987 ** Devious looking...whats it do ? well..if a client
1988 ** sends a *long* message without any CR or LF, then
1989 ** dbuf_getmsg fails and we pull it out using this
1990 ** loop which just gets the next 512 bytes and then
1991 ** deletes the rest of the buffer contents.
1992 ** -avalon
1993 */
1994 while (dolen <= 0)
1995 {
1996 if (dolen < 0)
1997 return exit_client(cptr, cptr, &me,
1998 "dbuf_getmsg fail");
1999 if (DBufLength(&cptr->recvQ) < 510)
2000 { /* hmm? */
2001 cptr->flags |= FLAGS_NONL;
2002 break;
2003 }
2004 dolen = dbuf_get(&cptr->recvQ, readbuf, 511);
2005 if (dolen > 0 && DBufLength(&cptr->recvQ))
2006 DBufClear(&cptr->recvQ);
2007 }
2008
2009 /* Is it okay not to test for other return values? -krys */
2010 if (dolen > 0 &&
2011 (dopacket(cptr, readbuf, dolen) == FLUSH_BUFFER))
2012 return FLUSH_BUFFER;
2013 }
2014 return 1;
2015 }
2016
2017 /*
2018 ** read_packet
2019 **
2020 ** Read a 'packet' of data from a connection and process it. Read in 8k
2021 ** chunks to give a better performance rating (for server connections).
2022 ** Do some tricky stuff for client connections to make sure they don't do
2023 ** any flooding >:-) -avalon
2024 */
read_packet(aClient * cptr,int msg_ready)2025 static int read_packet(aClient *cptr, int msg_ready)
2026 {
2027 Reg int length = 0, done;
2028
2029 if (msg_ready &&
2030 !(IsPerson(cptr) && DBufLength(&cptr->recvQ) > 6090))
2031 {
2032 errno = 0;
2033 #ifdef INET6
2034 length = recvfrom(cptr->fd, readbuf, sizeof(readbuf), 0, 0, 0);
2035 #else
2036 length = recv(cptr->fd, readbuf, sizeof(readbuf), 0);
2037 #endif
2038 #if defined(DEBUGMODE) && defined(DEBUG_READ)
2039 if (length > 0)
2040 Debug((DEBUG_READ,
2041 "recv = %d bytes from %d[%s]:[%*.*s]\n",
2042 length, cptr->fd, cptr->name, length, length,
2043 readbuf));
2044 #endif
2045
2046 Debug((DEBUG_DEBUG, "Received %d(%d-%s) bytes from %d %s",
2047 length, errno, strerror(errno),
2048 cptr->fd, get_client_name(cptr, TRUE)));
2049 cptr->lasttime = timeofday;
2050 if (cptr->lasttime > cptr->since)
2051 cptr->since = cptr->lasttime;
2052 cptr->flags &= ~(FLAGS_PINGSENT|FLAGS_NONL);
2053 /*
2054 * If not ready, fake it so it isnt closed
2055 */
2056 if (length == -1 &&
2057 ((errno == EWOULDBLOCK) || (errno == EAGAIN)))
2058 return 1;
2059 if (length <= 0)
2060 return length;
2061 }
2062 else if (msg_ready)
2063 return exit_client(cptr, cptr, &me, "EOF From Client");
2064
2065 /*
2066 ** For server connections, we process as many as we can without
2067 ** worrying about the time of day or anything :)
2068 */
2069 if (IsServer(cptr) || IsConnecting(cptr) || IsHandshake(cptr) ||
2070 IsService(cptr))
2071 {
2072 if (length > 0)
2073 {
2074 done = dopacket(cptr, readbuf, length);
2075 if (done && done != 2)
2076 return done;
2077 }
2078 }
2079 else
2080 {
2081 /*
2082 ** Before we even think of parsing what we just read, stick
2083 ** it on the end of the receive queue and do it when its
2084 ** turn comes around.
2085 */
2086 /* why no poolsize increase here like in send? --B. */
2087 if (length && dbuf_put(&cptr->recvQ, readbuf, length) < 0)
2088 return exit_client(cptr, cptr, &me, "dbuf_put fail");
2089
2090 if (IsPerson(cptr) &&
2091 DBufLength(&cptr->recvQ) > CLIENT_FLOOD
2092 && !is_allowed(cptr, ACL_CANFLOOD))
2093 {
2094 cptr->exitc = EXITC_FLOOD;
2095 return exit_client(cptr, cptr, &me, "Excess Flood");
2096 }
2097
2098 return client_packet(cptr);
2099 }
2100 return 1;
2101 }
2102
2103
2104 /*
2105 * Check all connections for new connections and input data that is to be
2106 * processed. Also check for connections with data queued and whether we can
2107 * write it out.
2108 *
2109 * Don't ever use ZERO for delay, unless you mean to poll and then
2110 * you have to have sleep/wait somewhere else in the code.--msa
2111 * Actually, ZERO is NOT ZERO anymore.. see below -kalt
2112 */
read_message(time_t delay,FdAry * fdp,int ro)2113 int read_message(time_t delay, FdAry *fdp, int ro)
2114 {
2115 #if !defined(USE_POLL)
2116 # define SET_READ_EVENT( thisfd ) FD_SET( thisfd, &read_set)
2117 # define SET_WRITE_EVENT( thisfd ) FD_SET( thisfd, &write_set)
2118 # define CLR_READ_EVENT( thisfd ) FD_CLR( thisfd, &read_set)
2119 # define CLR_WRITE_EVENT( thisfd ) FD_CLR( thisfd, &write_set)
2120 # define TST_READ_EVENT( thisfd ) FD_ISSET( thisfd, &read_set)
2121 # define TST_WRITE_EVENT( thisfd ) FD_ISSET( thisfd, &write_set)
2122
2123 fd_set read_set, write_set;
2124 int highfd = -1;
2125 #else
2126 /* most of the following use pfd */
2127 # define POLLSETREADFLAGS (POLLIN|POLLRDNORM)
2128 # define POLLREADFLAGS (POLLSETREADFLAGS|POLLHUP|POLLERR)
2129 # define POLLSETWRITEFLAGS (POLLOUT|POLLWRNORM)
2130 # define POLLWRITEFLAGS (POLLOUT|POLLWRNORM|POLLHUP|POLLERR)
2131
2132 # define SET_READ_EVENT( thisfd ){ CHECK_PFD( thisfd );\
2133 pfd->events |= POLLSETREADFLAGS;}
2134 # define SET_WRITE_EVENT( thisfd ){ CHECK_PFD( thisfd );\
2135 pfd->events |= POLLSETWRITEFLAGS;}
2136
2137 # define CLR_READ_EVENT( thisfd ) pfd->revents &= ~POLLSETREADFLAGS
2138 # define CLR_WRITE_EVENT( thisfd ) pfd->revents &= ~POLLSETWRITEFLAGS
2139 # define TST_READ_EVENT( thisfd ) pfd->revents & POLLREADFLAGS
2140 # define TST_WRITE_EVENT( thisfd ) pfd->revents & POLLWRITEFLAGS
2141
2142 # define CHECK_PFD( thisfd ) \
2143 if ( pfd->fd != thisfd ) { \
2144 pfd = &poll_fdarray[nbr_pfds++];\
2145 pfd->fd = thisfd; \
2146 pfd->events = 0; \
2147 pfd->revents = 0; \
2148 }
2149
2150 struct pollfd poll_fdarray[MAXCONNECTIONS];
2151 struct pollfd * pfd = poll_fdarray;
2152 struct pollfd * res_pfd = NULL;
2153 struct pollfd * udp_pfd = NULL;
2154 struct pollfd * ad_pfd = NULL;
2155 aClient * authclnts[MAXCONNECTIONS]; /* mapping of auth fds to client ptrs */
2156 int nbr_pfds = 0;
2157 #endif
2158
2159 aClient *cptr;
2160 int nfds, ret = 0;
2161 struct timeval wait;
2162 time_t delay2 = delay;
2163 int res, length, fd, i;
2164 int auth;
2165 int write_err = 0;
2166
2167 for (res = 0;;)
2168 {
2169 #if !defined(USE_POLL)
2170 FD_ZERO(&read_set);
2171 FD_ZERO(&write_set);
2172 #else
2173 /* set up such that CHECK_FD works */
2174 nbr_pfds = 0;
2175 pfd = poll_fdarray;
2176 pfd->fd = -1;
2177 res_pfd = NULL;
2178 udp_pfd = NULL;
2179 ad_pfd = NULL;
2180 #endif /* USE_POLL */
2181 auth = 0;
2182
2183 #if defined(USE_POLL)
2184 if ( auth == 0 )
2185 bzero((char *) authclnts, sizeof( authclnts ));
2186 #endif
2187 for (i = fdp->highest; i >= 0; i--)
2188 {
2189 fd = fdp->fd[i];
2190 if (!(cptr = local[fd]))
2191 continue;
2192 Debug((DEBUG_L11, "fd %d cptr %#x %d %#x %s",
2193 fd, cptr, cptr->status, cptr->flags,
2194 get_client_name(cptr,TRUE)));
2195 /* authentication fd's */
2196 if (DoingAuth(cptr))
2197 {
2198 auth++;
2199 SET_READ_EVENT(cptr->authfd);
2200 Debug((DEBUG_NOTICE,"auth on %x %d", cptr,
2201 fd));
2202 if (cptr->flags & FLAGS_WRAUTH)
2203 SET_WRITE_EVENT(cptr->authfd);
2204 #if defined(USE_POLL)
2205 authclnts[cptr->authfd] = cptr;
2206 #else
2207 if (cptr->authfd > highfd)
2208 highfd = cptr->authfd;
2209 #endif
2210 }
2211 /*
2212 ** if any of these is true, data won't be parsed
2213 ** so no need to check for anything!
2214 */
2215 #if defined(USE_IAUTH)
2216 if (DoingDNS(cptr) || DoingAuth(cptr) ||
2217 WaitingXAuth(cptr) ||
2218 (DoingXAuth(cptr) &&
2219 !(iauth_options & XOPT_EARLYPARSE)))
2220 #else
2221 if (DoingDNS(cptr) || DoingAuth(cptr))
2222 #endif
2223 continue;
2224 #if !defined(USE_POLL)
2225 if (fd > highfd)
2226 highfd = fd;
2227 #endif
2228 if (IsListener(cptr))
2229 {
2230 if (
2231 #ifdef LISTENER_DELAY
2232 /* Checking for new connections is only
2233 ** done up to once per LD seconds. */
2234 timeofday >= cptr->lasttime +
2235 LISTENER_DELAY &&
2236 #endif
2237 ro == 0)
2238 {
2239 SET_READ_EVENT( fd );
2240 }
2241 else if (delay2 > 1)
2242 delay2 = 1;
2243 continue;
2244 }
2245
2246 /*
2247 ** This is very approximate, it should take
2248 ** cptr->since into account. -kalt
2249 */
2250 if (DBufLength(&cptr->recvQ) && delay2 > 2)
2251 delay2 = 1;
2252
2253 if (IsRegisteredUser(cptr))
2254 {
2255 if (cptr->since - timeofday < MAXPENALTY+1)
2256 SET_READ_EVENT( fd );
2257 }
2258 else if (DBufLength(&cptr->recvQ) < 4088)
2259 SET_READ_EVENT( fd );
2260
2261 /*
2262 ** If we have anything in the sendQ, check if there is
2263 ** room to write data.
2264 */
2265 if (DBufLength(&cptr->sendQ) ||
2266 #ifdef ZIP_LINKS
2267 ((cptr->flags & FLAGS_ZIP) &&
2268 (cptr->zip->outcount > 0)) ||
2269 #endif
2270 IsConnecting(cptr))
2271 {
2272 if (IsServer(cptr) || IsConnecting(cptr) ||
2273 ro == 0)
2274 {
2275 SET_WRITE_EVENT(fd);
2276 }
2277 }
2278 }
2279
2280 if (udpfd >= 0)
2281 {
2282 SET_READ_EVENT(udpfd);
2283 #if !defined(USE_POLL)
2284 if (udpfd > highfd)
2285 highfd = udpfd;
2286 #else
2287 udp_pfd = pfd;
2288 #endif
2289 }
2290 if (resfd >= 0)
2291 {
2292 SET_READ_EVENT(resfd);
2293 #if !defined(USE_POLL)
2294 if (resfd > highfd)
2295 highfd = resfd;
2296 #else
2297 res_pfd = pfd;
2298 #endif
2299 }
2300 #if defined(USE_IAUTH)
2301 if (adfd >= 0)
2302 {
2303 SET_READ_EVENT(adfd);
2304 # if ! USE_POLL
2305 if (adfd > highfd)
2306 highfd = adfd;
2307 # else
2308 ad_pfd = pfd;
2309 # endif
2310 }
2311 #endif
2312 Debug((DEBUG_L11, "udpfd %d resfd %d adfd %d", udpfd, resfd,
2313 adfd));
2314 #if !defined(USE_POLL)
2315 Debug((DEBUG_L11, "highfd %d", highfd));
2316 #endif
2317
2318 wait.tv_sec = MIN(delay2, delay);
2319 wait.tv_usec = (delay == 0) ? 200000 : 0;
2320 #if !defined(USE_POLL)
2321 nfds = select(highfd + 1, (SELECT_FDSET_TYPE *)&read_set,
2322 (SELECT_FDSET_TYPE *)&write_set, 0, &wait);
2323 #else
2324 nfds = poll( poll_fdarray, nbr_pfds,
2325 wait.tv_sec * 1000 + wait.tv_usec/1000 );
2326 #endif
2327 ret = nfds;
2328 if (nfds == -1 && errno == EINTR)
2329 return -1;
2330 else if (nfds >= 0)
2331 break;
2332 #if !defined(USE_POLL)
2333 report_error("select %s:%s", &me);
2334 #else
2335 report_error("poll %s:%s", &me);
2336 #endif
2337 res++;
2338 if (res > 5)
2339 restart("too many select()/poll() errors");
2340 sleep(10);
2341 timeofday = time(NULL);
2342 } /* for(res=0;;) */
2343
2344 timeofday = time(NULL);
2345 if (nfds > 0 &&
2346 #if !defined(USE_POLL)
2347 resfd >= 0 &&
2348 #else
2349 (pfd = res_pfd) &&
2350 #endif
2351 TST_READ_EVENT(resfd))
2352 {
2353 CLR_READ_EVENT(resfd);
2354 nfds--;
2355 do_dns_async();
2356 }
2357 if (nfds > 0 &&
2358 #if !defined(USE_POLL)
2359 udpfd >= 0 &&
2360 #else
2361 (pfd = udp_pfd) &&
2362 #endif
2363 TST_READ_EVENT(udpfd))
2364 {
2365 CLR_READ_EVENT(udpfd);
2366 nfds--;
2367 polludp();
2368 }
2369 #if defined(USE_IAUTH)
2370 if (nfds > 0 &&
2371 # if ! USE_POLL
2372 adfd >= 0 &&
2373 # else
2374 (pfd = ad_pfd) &&
2375 # endif
2376 TST_READ_EVENT(adfd))
2377 {
2378 CLR_READ_EVENT(adfd);
2379 nfds--;
2380 read_iauth();
2381 }
2382 #endif
2383
2384 #if !defined(USE_POLL)
2385 for (i = fdp->highest; i >= 0; i--)
2386 #else
2387 for (pfd = poll_fdarray, i = 0; i < nbr_pfds; i++, pfd++ )
2388 #endif
2389 {
2390 #if !defined(USE_POLL)
2391 fd = fdp->fd[i];
2392 if (!(cptr = local[fd]))
2393 continue;
2394 #else
2395 fd = pfd->fd;
2396 if ((cptr = authclnts[fd]))
2397 {
2398 #endif
2399 /*
2400 * check for the auth fd's
2401 */
2402 if (auth > 0 && nfds > 0
2403 #if !defined(USE_POLL)
2404 && cptr->authfd >= 0
2405 #endif
2406 )
2407 {
2408 auth--;
2409 if (TST_WRITE_EVENT(cptr->authfd))
2410 {
2411 nfds--;
2412 send_authports(cptr);
2413 }
2414 else if (TST_READ_EVENT(cptr->authfd))
2415 {
2416 nfds--;
2417 read_authports(cptr);
2418 }
2419 continue;
2420 }
2421 #if defined(USE_POLL)
2422 }
2423 fd = pfd->fd;
2424 if (!(cptr = local[fd]))
2425 continue;
2426 #else
2427 fd = cptr->fd;
2428 #endif
2429 /*
2430 * accept connections
2431 */
2432 if (TST_READ_EVENT(fd) && IsListener(cptr) &&
2433 !IsListenerInactive(cptr))
2434 {
2435 CLR_READ_EVENT(fd);
2436 cptr->lasttime = timeofday;
2437 read_listener(cptr);
2438 continue;
2439 }
2440 if (IsMe(cptr))
2441 continue;
2442 if (TST_WRITE_EVENT(fd))
2443 {
2444 write_err = 0;
2445 /*
2446 ** ...room for writing, empty some queue then...
2447 */
2448 if (IsConnecting(cptr))
2449 write_err = completed_connection(cptr);
2450 if (!write_err)
2451 (void)send_queued(cptr);
2452 if (IsDead(cptr) || write_err)
2453 {
2454 deadsocket:
2455 if (TST_READ_EVENT(fd))
2456 CLR_READ_EVENT(fd);
2457 if (cptr->exitc == EXITC_SENDQ)
2458 {
2459 (void)exit_client(cptr,cptr,&me,
2460 "Max SendQ exceeded");
2461 }
2462 else
2463 {
2464 /* Keep (primary) error or it will not
2465 * be possible to discriminate socket
2466 * error from mbuf error. --B. */
2467 if (cptr->exitc == EXITC_REG)
2468 cptr->exitc = EXITC_ERROR;
2469 (void)exit_client(cptr, cptr, &me,
2470 strerror(get_sockerr(cptr)));
2471 }
2472 continue;
2473 }
2474 }
2475 length = 1; /* for fall through case */
2476 if (!NoNewLine(cptr) || TST_READ_EVENT(fd))
2477 {
2478 if (!DoingAuth(cptr))
2479 length = read_packet(cptr, TST_READ_EVENT(fd));
2480 }
2481 readcalls++;
2482 if (length == FLUSH_BUFFER)
2483 continue;
2484 else if (length > 0)
2485 flush_connections(cptr->fd);
2486 if (IsDead(cptr))
2487 goto deadsocket;
2488 if (length > 0)
2489 continue;
2490
2491 /* Ghost! Unknown users are tagged in parse() since 2.9.
2492 * Let's not drop the uplink but just the ghost's message.
2493 */
2494 if (length == -3)
2495 continue;
2496
2497 /*
2498 ** NB: This following section has been modified to *expect*
2499 ** cptr to be valid (ie if (length == FLUSH_BUFFER) is
2500 ** above and stays there). - avalon 24/9/94
2501 */
2502 /*
2503 ** ...hmm, with non-blocking sockets we might get
2504 ** here from quite valid reasons, although.. why
2505 ** would select report "data available" when there
2506 ** wasn't... so, this must be an error anyway... --msa
2507 ** actually, EOF occurs when read() returns 0 and
2508 ** in due course, select() returns that fd as ready
2509 ** for reading even though it ends up being an EOF. -avalon
2510 */
2511 Debug((DEBUG_ERROR, "READ ERROR: fd = %d %d %d",
2512 cptr->fd, errno, length));
2513
2514 if (IsServer(cptr) || IsHandshake(cptr))
2515 {
2516 int timeconnected = timeofday - cptr->firsttime;
2517
2518 if (length == 0)
2519 sendto_flag(SCH_NOTICE,
2520 "Server %s closed the connection (%d, %2d:%02d:%02d)",
2521 get_client_name(cptr, FALSE),
2522 timeconnected / 86400,
2523 (timeconnected % 86400) / 3600,
2524 (timeconnected % 3600)/60,
2525 timeconnected % 60);
2526 else /* this must be for -1 */
2527 {
2528 report_error("Lost connection to %s:%s",cptr);
2529 sendto_flag(SCH_NOTICE,
2530 "%s had been connected for %d, %2d:%02d:%02d",
2531 get_client_name(cptr, FALSE),
2532 timeconnected / 86400,
2533 (timeconnected % 86400) / 3600,
2534 (timeconnected % 3600)/60,
2535 timeconnected % 60);
2536 }
2537 }
2538 (void)exit_client(cptr, cptr, &me, length >= 0 ?
2539 "EOF From client" :
2540 strerror(get_sockerr(cptr)));
2541 } /* for(i) */
2542 return ret;
2543 }
2544
2545 /*
2546 * connect_server
2547 */
2548 int connect_server(aConfItem *aconf, aClient *by, struct hostent *hp)
2549 {
2550 Reg struct SOCKADDR *svp;
2551 Reg aClient *cptr, *c2ptr;
2552 Reg char *s;
2553 int i, len;
2554
2555 #ifdef INET6
2556 Debug((DEBUG_NOTICE,"Connect to %s[%s] @%s",
2557 aconf->name, aconf->host,
2558 inet_ntop(AF_INET6, (char *)&aconf->ipnum, ipv6string,
2559 sizeof(ipv6string))));
2560 #else
2561 Debug((DEBUG_NOTICE,"Connect to %s[%s] @%s",
2562 aconf->name, aconf->host,
2563 inetntoa((char *)&aconf->ipnum)));
2564 #endif
2565
2566 if ((c2ptr = find_server(aconf->name, NULL)))
2567 {
2568 sendto_flag(SCH_NOTICE, "Server %s already present from %s",
2569 aconf->name, get_client_name(c2ptr, TRUE));
2570 if (by && IsPerson(by) && !MyClient(by))
2571 sendto_one(by,
2572 ":%s NOTICE %s :Server %s already present from %s",
2573 ME, by->name, aconf->name,
2574 get_client_name(c2ptr, TRUE));
2575 return -1;
2576 }
2577
2578 /*
2579 * If we don't know the IP# for this host and it is a hostname and
2580 * not a ip# string, then try and find the appropriate host record.
2581 */
2582 if (!aconf->ipnum.S_ADDR && *aconf->host != '/')
2583 {
2584 Link lin;
2585
2586 lin.flags = ASYNC_CONNECT;
2587 lin.value.aconf = aconf;
2588 nextdnscheck = 1;
2589 s = (char *)index(aconf->host, '@');
2590 s++; /* should NEVER be NULL */
2591 #ifdef INET6
2592 if (!inetpton(AF_INET6, s, aconf->ipnum.s6_addr))
2593 #else
2594 if ((aconf->ipnum.s_addr = inetaddr(s)) == -1)
2595 #endif
2596 {
2597 #ifdef INET6
2598 bzero(aconf->ipnum.s6_addr, IN6ADDRSZ);
2599 #else
2600 aconf->ipnum.s_addr = 0;
2601 #endif
2602 hp = gethost_byname(s, &lin);
2603 Debug((DEBUG_NOTICE, "co_sv: hp %x ac %x na %s ho %s",
2604 hp, aconf, aconf->name, s));
2605 if (!hp)
2606 return 0;
2607 bcopy(hp->h_addr, (char *)&aconf->ipnum,
2608 sizeof(struct IN_ADDR));
2609 }
2610 }
2611 cptr = make_client(NULL);
2612 if ((make_server(cptr))==NULL)
2613 {
2614 free_client(cptr);
2615 return -1;
2616 }
2617 cptr->hostp = hp;
2618 /*
2619 * Copy these in so we have something for error detection.
2620 */
2621 strncpyzt(cptr->serv->namebuf, aconf->name, sizeof(cptr->serv->namebuf));
2622 strncpyzt(cptr->sockhost, aconf->host, HOSTLEN+1);
2623
2624 #ifdef UNIXPORT
2625 if (*aconf->host == '/') /* (/ starts a 2), Unix domain -- dl*/
2626 svp = connect_unix(aconf, cptr, &len);
2627 else
2628 #endif
2629 svp = connect_inet(aconf, cptr, &len);
2630
2631 if (!svp)
2632 {
2633 free_server:
2634 if (cptr->fd >= 0)
2635 (void)close(cptr->fd);
2636 cptr->fd = -2;
2637 /* make_server() sets ->bcptr, clear it now or free_server()
2638 ** complains. --B. */
2639 cptr->serv->bcptr = NULL;
2640 free_server(cptr->serv);
2641 free_client(cptr);
2642 return -1;
2643 }
2644
2645 set_non_blocking(cptr->fd, cptr);
2646 (void)set_sock_opts(cptr->fd, cptr);
2647 (void)signal(SIGALRM, dummy);
2648 (void)alarm(4);
2649 if (connect(cptr->fd, (SAP)svp, len) < 0 && errno != EINPROGRESS)
2650 {
2651 i = errno; /* other system calls may eat errno */
2652 (void)alarm(0);
2653 report_error("Connect to host %s failed: %s",cptr);
2654 if (by && IsPerson(by) && !MyClient(by))
2655 sendto_one(by,
2656 ":%s NOTICE %s :Connect to host %s failed.",
2657 ME, by->name, cptr->name);
2658 errno = i;
2659 if (errno == EINTR)
2660 errno = ETIMEDOUT;
2661 goto free_server;
2662 }
2663 (void)alarm(0);
2664
2665 /* Attach config entries to client here rather than in
2666 * completed_connection. This to avoid null pointer references
2667 * when name returned by gethostbyaddr matches no C lines
2668 * (could happen in 2.6.1a when host and servername differ).
2669 * No need to check access and do gethostbyaddr calls.
2670 * There must at least be one as we got here C line... meLazy
2671 */
2672 (void)attach_confs_host(cptr, aconf->host, CFLAG|NFLAG);
2673
2674 if (!find_conf_host(cptr->confs, aconf->host, NFLAG) ||
2675 !find_conf_host(cptr->confs, aconf->host, CFLAG))
2676 {
2677 sendto_flag(SCH_NOTICE,
2678 "Host %s is not enabled for connecting:no C/N-line",
2679 aconf->host);
2680 if (by && IsPerson(by) && !MyClient(by))
2681 sendto_one(by,
2682 ":%s NOTICE %s :Connect to host %s failed.",
2683 ME, by->name, cptr->name);
2684 det_confs_butmask(cptr, 0);
2685 goto free_server;
2686 }
2687 /*
2688 ** The socket has been connected or connect is in progress.
2689 */
2690 if (by && IsPerson(by))
2691 {
2692 (void)strcpy(cptr->serv->by, by->name);
2693 if (by->user)
2694 {
2695 strcpy(cptr->serv->byuid, by->user->uid);
2696 }
2697 cptr->serv->user = by->user;
2698 by->user->refcnt++;
2699 }
2700 else
2701 (void)strcpy(cptr->serv->by, "AutoConn.");
2702 cptr->serv->up = &me;
2703 cptr->serv->maskedby = cptr;
2704 cptr->serv->nline = aconf;
2705 if (cptr->fd > highest_fd)
2706 highest_fd = cptr->fd;
2707 add_fd(cptr->fd, &fdall);
2708 local[cptr->fd] = cptr;
2709 cptr->acpt = &me;
2710 SetConnecting(cptr);
2711
2712 get_sockhost(cptr, aconf->host);
2713 add_client_to_list(cptr);
2714 nextping = timeofday;
2715 istat.is_unknown++;
2716
2717 return 0;
2718 }
2719
2720 static struct SOCKADDR *connect_inet(aConfItem *aconf, aClient *cptr,
2721 int *lenp)
2722 {
2723 static struct SOCKADDR_IN server;
2724 struct SOCKADDR_IN outip;
2725
2726 Reg struct hostent *hp;
2727 aClient *acptr;
2728 int i;
2729
2730 /*
2731 * Might as well get sockhost from here, the connection is attempted
2732 * with it so if it fails its useless.
2733 */
2734 cptr->fd = socket(AFINET, SOCK_STREAM, 0);
2735 if (cptr->fd >= MAXCLIENTS)
2736 {
2737 sendto_flag(SCH_NOTICE,
2738 "No more connections allowed (%s)", cptr->name);
2739 return NULL;
2740 }
2741 bzero((char *)&server, sizeof(server));
2742 server.SIN_FAMILY = AFINET;
2743 get_sockhost(cptr, aconf->host);
2744
2745 if (!BadPtr(aconf->source_ip))
2746 {
2747 memset(&outip, 0, sizeof(outip));
2748 outip.SIN_PORT = 0;
2749 outip.SIN_FAMILY = AFINET;
2750 #ifdef INET6
2751 if (!inetpton(AF_INET6, aconf->source_ip, outip.sin6_addr.s6_addr))
2752 #else
2753 if ((outip.sin_addr.s_addr = inetaddr(aconf->source_ip)) == -1)
2754 #endif
2755 {
2756 sendto_flag(SCH_ERROR, "Invalid source IP (%s) in C:line",
2757 aconf->source_ip);
2758 memcpy(&outip, &mysk, sizeof(mysk));
2759 }
2760 }
2761 else
2762 {
2763 memcpy(&outip, &mysk, sizeof(mysk));
2764 }
2765 if (cptr->fd == -1)
2766 {
2767 report_error("opening stream socket to server %s:%s", cptr);
2768 return NULL;
2769 }
2770 /*
2771 ** Bind to a local IP# (with unknown port - let unix decide) so
2772 ** we have some chance of knowing the IP# that gets used for a host
2773 ** with more than one IP#.
2774 ** With VIFs, M:line defines outgoing IP# and initialises mysk.
2775 */
2776 if (bind(cptr->fd, (SAP)&outip, sizeof(outip)) == -1)
2777 {
2778 report_error("error binding to local port for %s:%s", cptr);
2779 return NULL;
2780 }
2781 /*
2782 * By this point we should know the IP# of the host listed in the
2783 * conf line, whether as a result of the hostname lookup or the ip#
2784 * being present instead. If we don't know it, then the connect fails.
2785 */
2786 #ifdef INET6
2787 if (isdigit(*aconf->host) && (AND16(aconf->ipnum.s6_addr) == 255))
2788 if (!inetpton(AF_INET6, aconf->host,aconf->ipnum.s6_addr))
2789 bcopy(minus_one, aconf->ipnum.s6_addr, IN6ADDRSZ);
2790 if (AND16(aconf->ipnum.s6_addr) == 255)
2791 #else
2792 if (isdigit(*aconf->host) && (aconf->ipnum.s_addr == -1))
2793 aconf->ipnum.s_addr = inetaddr(aconf->host);
2794 if (aconf->ipnum.s_addr == -1)
2795 #endif
2796 {
2797 hp = cptr->hostp;
2798 if (!hp)
2799 {
2800 Debug((DEBUG_FATAL, "%s: unknown host", aconf->host));
2801 return NULL;
2802 }
2803 bcopy(hp->h_addr, (char *)&aconf->ipnum,
2804 sizeof(struct IN_ADDR));
2805 }
2806 bcopy((char *)&aconf->ipnum, (char *)&server.SIN_ADDR,
2807 sizeof(struct IN_ADDR));
2808 bcopy((char *)&aconf->ipnum, (char *)&cptr->ip,
2809 sizeof(struct IN_ADDR));
2810 cptr->port = (aconf->port > 0) ? aconf->port : portnum;
2811 server.SIN_PORT = htons(cptr->port);
2812 /*
2813 * Look for a duplicate IP#,port pair among already open connections
2814 * (This caters for unestablished connections).
2815 */
2816 for (i = highest_fd; i >= 0; i--)
2817 if ((acptr = local[i]) &&
2818 !bcmp((char *)&cptr->ip, (char *)&acptr->ip,
2819 sizeof(cptr->ip)) && server.SIN_PORT == acptr->port)
2820 return NULL;
2821 *lenp = sizeof(server);
2822 return (struct SOCKADDR *)&server;
2823 }
2824
2825 #ifdef UNIXPORT
2826 /* connect_unix
2827 *
2828 * Build a socket structure for cptr so that it can connet to the unix
2829 * socket defined by the conf structure aconf.
2830 */
2831 static struct SOCKADDR *connect_unix(aConfItem *aconf, aClient *cptr,
2832 int *lenp)
2833 {
2834 static struct sockaddr_un sock;
2835
2836 if ((cptr->fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
2837 {
2838 report_error("Unix domain connect to host %s failed: %s", cptr);
2839 return NULL;
2840 }
2841 else if (cptr->fd >= MAXCLIENTS)
2842 {
2843 sendto_flag(SCH_NOTICE,
2844 "No more connections allowed (%s)", cptr->name);
2845 return NULL;
2846 }
2847
2848 get_sockhost(cptr, aconf->host);
2849 strncpyzt(sock.sun_path, aconf->host + 2, sizeof(sock.sun_path));
2850 sock.sun_family = AF_UNIX;
2851 *lenp = strlen(sock.sun_path) + 2;
2852
2853 SetUnixSock(cptr);
2854 return (struct sockaddr *)&sock;
2855 }
2856 #endif
2857
2858 /*
2859 * The following section of code performs summoning of users to irc.
2860 */
2861 #if defined(ENABLE_SUMMON) || defined(USERS_SHOWS_UTMP)
2862 int utmp_open(void)
2863 {
2864 #ifdef O_NOCTTY
2865 return (open(UTMP, O_RDONLY|O_NOCTTY));
2866 #else
2867 return (open(UTMP, O_RDONLY));
2868 #endif
2869 }
2870
2871 int utmp_read(int fd, char *name, char *line, char *host, int hlen)
2872 {
2873 struct utmp ut;
2874 while (read(fd, (char *)&ut, sizeof (struct utmp))
2875 == sizeof (struct utmp))
2876 {
2877 strncpyzt(name, ut.ut_name, 9);
2878 strncpyzt(line, ut.ut_line, 10);
2879 #ifdef USER_PROCESS
2880 # if defined(HPUX) || defined(AIX)
2881 strncpyzt(host,(ut.ut_host[0]) ? (ut.ut_host) : ME, 16);
2882 # else
2883 strncpyzt(host, ME, 9);
2884 # endif
2885 if (ut.ut_type == USER_PROCESS)
2886 return 0;
2887 #else
2888 strncpyzt(host, (ut.ut_host[0]) ? (ut.ut_host) : ME,
2889 hlen);
2890 if (ut.ut_name[0])
2891 return 0;
2892 #endif
2893 }
2894 return -1;
2895 }
2896
2897 int utmp_close(int fd)
2898 {
2899 return(close(fd));
2900 }
2901
2902 #ifdef ENABLE_SUMMON
2903 void summon(aClient *who, char *namebuf, char *linebuf, char *chname)
2904 {
2905 static char wrerr[] = "NOTICE %s :Write error. Couldn't summon.";
2906 int fd;
2907 char line[512];
2908 struct tm *tp;
2909
2910 tp = localtime(&timeofday);
2911 if (strlen(linebuf) > (size_t) 9)
2912 {
2913 sendto_one(who,"NOTICE %s :Serious fault in SUMMON.",
2914 who->name);
2915 sendto_one(who,
2916 "NOTICE %s :linebuf too long. Inform Administrator",
2917 who->name);
2918 return;
2919 }
2920 /*
2921 * Following line added to prevent cracking to e.g. /dev/kmem if
2922 * UTMP is for some silly reason writable to everyone...
2923 */
2924 if ((linebuf[0] != 't' || linebuf[1] != 't' || linebuf[2] != 'y')
2925 && (linebuf[0] != 'c' || linebuf[1] != 'o' || linebuf[2] != 'n')
2926 && (linebuf[0] != 'p' || linebuf[1] != 't' || linebuf[2] != 's')
2927 #ifdef HPUX
2928 && (linebuf[0] != 'p' || linebuf[1] != 't' || linebuf[2] != 'y' ||
2929 linebuf[3] != '/')
2930 #endif
2931 )
2932 {
2933 sendto_one(who,
2934 "NOTICE %s :Looks like mere mortal souls are trying to",
2935 who->name);
2936 sendto_one(who,"NOTICE %s :enter the twilight zone... ",
2937 who->name);
2938 Debug((0, "%s (%s@%s, nick %s, %s)",
2939 "FATAL: major security hack. Notify Administrator !",
2940 who->username, who->user->host,
2941 who->name, who->info));
2942 return;
2943 }
2944
2945 sprintf(line,"/dev/%s", linebuf);
2946 (void)alarm(5);
2947 #ifdef O_NOCTTY
2948 if ((fd = open(line, O_WRONLY | O_NDELAY | O_NOCTTY)) == -1)
2949 #else
2950 if ((fd = open(line, O_WRONLY | O_NDELAY)) == -1)
2951 #endif
2952 {
2953 (void)alarm(0);
2954 sendto_one(who,
2955 "NOTICE %s :%s seems to have disabled summoning...",
2956 who->name, namebuf);
2957 return;
2958 }
2959 #if !defined(O_NOCTTY) && defined(TIOCNOTTY)
2960 (void)ioctl(fd, TIOCNOTTY, NULL);
2961 #endif
2962 (void)alarm(0);
2963 (void)sprintf(line,"\n\r\007Message from IRC_Daemon@%s at %d:%02d\n\r",
2964 ME, tp->tm_hour, tp->tm_min);
2965 if (write(fd, line, strlen(line)) != strlen(line))
2966 {
2967 (void)alarm(0);
2968 (void)close(fd);
2969 sendto_one(who, wrerr, who->name);
2970 return;
2971 }
2972 (void)alarm(0);
2973 (void)strcpy(line, "ircd: You are being summoned to Internet Relay \
2974 Chat on\n\r");
2975 (void)alarm(5);
2976 if (write(fd, line, strlen(line)) != strlen(line))
2977 {
2978 (void)alarm(0);
2979 (void)close(fd);
2980 sendto_one(who, wrerr, who->name);
2981 return;
2982 }
2983 (void)alarm(0);
2984 sprintf(line, "ircd: Channel %s, by %s@%s (%s) %s\n\r", chname,
2985 who->user->username, who->user->host, who->name, who->info);
2986 (void)alarm(5);
2987 if (write(fd, line, strlen(line)) != strlen(line))
2988 {
2989 (void)alarm(0);
2990 (void)close(fd);
2991 sendto_one(who, wrerr, who->name);
2992 return;
2993 }
2994 (void)alarm(0);
2995 (void)strcpy(line,"ircd: Respond with irc\n\r");
2996 (void)alarm(5);
2997 if (write(fd, line, strlen(line)) != strlen(line))
2998 {
2999 (void)alarm(0);
3000 (void)close(fd);
3001 sendto_one(who, wrerr, who->name);
3002 return;
3003 }
3004 (void)close(fd);
3005 (void)alarm(0);
3006 sendto_one(who, replies[RPL_SUMMONING], ME, BadTo(who->name), namebuf);
3007 return;
3008 }
3009 # endif
3010 #endif /* ENABLE_SUMMON */
3011
3012 /*
3013 ** find the real hostname for the host running the server (or one which
3014 ** matches the server's name) and its primary IP#. Hostname is stored
3015 ** in the client structure passed as a pointer.
3016 */
3017 void get_my_name(aClient *cptr, char *name, int len)
3018 {
3019 static char tmp[HOSTLEN+1];
3020 struct hostent *hp;
3021 char *cname = cptr->name;
3022 aConfItem *aconf;
3023 #ifdef HAVE_GETIPNODEBYNAME
3024 int error_num1, error_num2;
3025 struct hostent *hp1, *hp2;
3026 #endif
3027
3028 /*
3029 ** Setup local socket structure to use for binding to.
3030 */
3031 bzero((char *)&mysk, sizeof(mysk));
3032 mysk.SIN_FAMILY = AFINET;
3033 mysk.SIN_PORT = 0;
3034
3035 if ((aconf = find_me())->passwd && isdigit(*aconf->passwd))
3036 #ifdef INET6
3037 if(!inetpton(AF_INET6, aconf->passwd, mysk.sin6_addr.s6_addr))
3038 bcopy(minus_one, mysk.sin6_addr.s6_addr, IN6ADDRSZ);
3039 #else
3040 mysk.sin_addr.s_addr = inetaddr(aconf->passwd);
3041 #endif
3042
3043 if (gethostname(name, len) == -1)
3044 return;
3045 name[len] = '\0';
3046
3047 add_local_domain(name, len - strlen(name));
3048
3049 /*
3050 ** If hostname gives another name than cname, then check if there is
3051 ** a CNAME record for cname pointing to hostname. If so accept
3052 ** cname as our name. meLazy
3053 */
3054 if (BadPtr(cname))
3055 return;
3056 #ifdef HAVE_GETIPNODEBYNAME
3057 hp1 = getipnodebyname(cname, AF_INET6, AI_DEFAULT, &error_num1);
3058 hp2 = getipnodebyname(name, AF_INET6, AI_DEFAULT, &error_num2);
3059 if (! error_num1) hp=hp1; else hp=hp2;
3060 if ((! error_num1) || (! error_num2))
3061 #else
3062 if ((hp = gethostbyname(cname)) || (hp = gethostbyname(name)))
3063 #endif
3064 {
3065 char *hname;
3066 int i = 0;
3067
3068 for (hname = hp->h_name; hname; hname = hp->h_aliases[i++])
3069 {
3070 strncpyzt(tmp, hname, sizeof(tmp));
3071 add_local_domain(tmp, sizeof(tmp) - strlen(tmp));
3072
3073 /*
3074 ** Copy the matching name over and store the
3075 ** 'primary' IP# as 'myip' which is used
3076 ** later for making the right one is used
3077 ** for connecting to other hosts.
3078 */
3079 if (!mycmp(ME, tmp))
3080 break;
3081 }
3082 if (mycmp(ME, tmp))
3083 strncpyzt(name, hp->h_name, len);
3084 else
3085 strncpyzt(name, tmp, len);
3086 #if 0
3087 /* If someone puts IP in M:, fine, use it as outgoing ip, but using
3088 resolved M: name for outgoing ip is... troublesome. It can resolve to IP of
3089 some other host or 127.0.0.1 (in which case we'd be getting strange errors
3090 from connect()); if left empty, OS will decide itself what IP to use;
3091 if someone wants to control this, use M: or C: adequate fields. --B. */
3092 if (BadPtr(aconf->passwd))
3093 bcopy(hp->h_addr, (char *)&mysk.SIN_ADDR,
3094 sizeof(struct IN_ADDR));
3095 #endif
3096 Debug((DEBUG_DEBUG,"local name is %s",
3097 get_client_name(&me,TRUE)));
3098 }
3099 #ifdef HAVE_GETIPNODEBYNAME
3100 freehostent(hp1);
3101 freehostent(hp2);
3102 #endif
3103 return;
3104 }
3105
3106 /*
3107 ** setup a UDP socket and listen for incoming packets
3108 */
3109 int setup_ping(aConfItem *aconf)
3110 {
3111 struct SOCKADDR_IN from;
3112 int on = 1;
3113
3114 if (udpfd != -1)
3115 return udpfd;
3116 bzero((char *)&from, sizeof(from));
3117 if (aconf->passwd && isdigit(*aconf->passwd))
3118 #ifdef INET6
3119 {
3120 if (!inetpton(AF_INET6, aconf->passwd,from.sin6_addr.s6_addr))
3121 bcopy(minus_one, from.sin6_addr.s6_addr, IN6ADDRSZ);
3122 }
3123 #else
3124 from.sin_addr.s_addr = inetaddr(aconf->passwd);
3125 #endif
3126 else
3127 #ifdef INET6
3128 from.SIN_ADDR = in6addr_any;
3129 #else
3130 from.sin_addr.s_addr = htonl(INADDR_ANY); /* hmmpf */
3131 #endif
3132 from.SIN_PORT = htons((u_short) aconf->port);
3133 from.SIN_FAMILY = AFINET;
3134
3135 if ((udpfd = socket(AFINET, SOCK_DGRAM, 0)) == -1)
3136 {
3137 Debug((DEBUG_ERROR, "socket udp : %s", strerror(errno)));
3138 return -1;
3139 }
3140 if (SETSOCKOPT(udpfd, SOL_SOCKET, SO_REUSEADDR, &on, on) == -1)
3141 {
3142 #ifdef USE_SYSLOG
3143 syslog(LOG_ERR, "setsockopt udp fd %d : %m", udpfd);
3144 #endif
3145 Debug((DEBUG_ERROR, "setsockopt so_reuseaddr : %s",
3146 strerror(errno)));
3147 (void)close(udpfd);
3148 return udpfd = -1;
3149 }
3150 on = 0;
3151 (void) SETSOCKOPT(udpfd, SOL_SOCKET, SO_BROADCAST, &on, on);
3152 if (bind(udpfd, (SAP)&from, sizeof(from))==-1)
3153 {
3154 #ifdef USE_SYSLOG
3155 syslog(LOG_ERR, "bind udp.%d fd %d : %m",
3156 ntohs(from.SIN_PORT), udpfd);
3157 #endif
3158 Debug((DEBUG_ERROR, "bind : %s", strerror(errno)));
3159 (void)close(udpfd);
3160 return udpfd = -1;
3161 }
3162 if (fcntl(udpfd, F_SETFL, FNDELAY)==-1)
3163 {
3164 Debug((DEBUG_ERROR, "fcntl fndelay : %s", strerror(errno)));
3165 (void)close(udpfd);
3166 return udpfd = -1;
3167 }
3168 Debug((DEBUG_INFO, "udpfd = %d, port %d", udpfd,ntohs(from.SIN_PORT)));
3169 return udpfd;
3170 }
3171
3172
3173 void send_ping(aConfItem *aconf)
3174 {
3175 Ping pi;
3176 struct SOCKADDR_IN sin;
3177 aCPing *cp = aconf->ping;
3178
3179 #ifdef INET6
3180 if (!aconf->ipnum.s6_addr || AND16(aconf->ipnum.s6_addr) == 255 || !cp->port)
3181 #else
3182 if (!aconf->ipnum.s_addr || aconf->ipnum.s_addr == -1 || !cp->port)
3183 #endif
3184 return;
3185 if (aconf->class->conFreq == 0) /* avoid flooding */
3186 return;
3187 pi.pi_cp = aconf;
3188 pi.pi_id = htonl(PING_CPING);
3189 pi.pi_seq = cp->lseq++;
3190 cp->seq++;
3191 /*
3192 * Only recognise stats from the last 20 minutes as significant...
3193 * Try and fake sliding along a "window" here.
3194 */
3195 if (cp->seq > 1 && cp->seq * aconf->class->conFreq > 1200)
3196 {
3197 if (cp->recvd)
3198 {
3199 cp->ping -= (cp->ping / cp->recvd);
3200 if (cp->recvd == cp->seq)
3201 cp->recvd--;
3202 }
3203 else
3204 cp->ping = 0;
3205 cp->seq--;
3206 }
3207
3208 bzero((char *)&sin, sizeof(sin));
3209 #ifdef INET6
3210 bcopy(aconf->ipnum.s6_addr, sin.sin6_addr.s6_addr, IN6ADDRSZ);
3211 #else
3212 sin.sin_addr.s_addr = aconf->ipnum.s_addr;
3213 #endif
3214 sin.SIN_PORT = htons(cp->port);
3215 sin.SIN_FAMILY = AFINET;
3216 (void)gettimeofday(&pi.pi_tv, NULL);
3217 #ifdef INET6
3218 Debug((DEBUG_SEND,"Send ping to %s,%d fd %d, %d bytes",
3219 inet_ntop(AF_INET6, (char *)&aconf->ipnum, ipv6string, sizeof(ipv6string)),
3220 cp->port, udpfd, sizeof(pi)));
3221 #else
3222 Debug((DEBUG_SEND,"Send ping to %s,%d fd %d, %d bytes",
3223 inetntoa((char *)&aconf->ipnum),
3224 cp->port, udpfd, sizeof(pi)));
3225 #endif
3226 (void)sendto(udpfd, (char *)&pi, sizeof(pi), 0,(SAP)&sin,sizeof(sin));
3227 }
3228
3229 static int check_ping(char *buf, int len)
3230 {
3231 Ping pi;
3232 aConfItem *aconf;
3233 struct timeval tv;
3234 double d;
3235 aCPing *cp = NULL;
3236 u_long rtt;
3237
3238 (void)gettimeofday(&tv, NULL);
3239
3240 if (len < sizeof(pi) + 8)
3241 return -1;
3242
3243 bcopy(buf, (char *)&pi, sizeof(pi)); /* ensure nice byte align. */
3244
3245 for (aconf = conf; aconf; aconf = aconf->next)
3246 if (pi.pi_cp == aconf && (cp = aconf->ping))
3247 break;
3248 if (!aconf || match(aconf->name, buf + sizeof(pi)))
3249 return -1;
3250
3251 cp->recvd++;
3252 cp->lrecvd++;
3253 rtt = ((tv.tv_sec - pi.pi_tv.tv_sec) * 1000 +
3254 (tv.tv_usec - pi.pi_tv.tv_usec) / 1000);
3255 cp->ping += rtt;
3256 cp->rtt += rtt;
3257 if (cp->rtt > 1000000)
3258 {
3259 cp->ping = (cp->rtt /= cp->lrecvd);
3260 cp->recvd = cp->lrecvd = 1;
3261 cp->seq = cp->lseq = 1;
3262 }
3263 d = (double)cp->recvd / (double)cp->seq;
3264 d = pow(d, (double)20.0);
3265 d = (double)cp->ping / (double)cp->recvd / d;
3266 if (d > 10000.0)
3267 d = 10000.0;
3268 aconf->pref = (int) (d * 100.0);
3269
3270 return 0;
3271 }
3272
3273 /*
3274 * max # of pings set to 15/sec.
3275 */
3276 static void polludp(void)
3277 {
3278 static time_t last = 0;
3279 static int cnt = 0, mlen = 0, lasterr = 0;
3280 Reg char *s;
3281 struct SOCKADDR_IN from;
3282 Ping pi;
3283 int n;
3284 SOCK_LEN_TYPE fromlen = sizeof(from);
3285
3286 /*
3287 * find max length of data area of packet.
3288 */
3289 if (!mlen)
3290 {
3291 mlen = sizeof(readbuf) - strlen(ME) - strlen(version);
3292 mlen -= 6;
3293 if (mlen < 0)
3294 mlen = 0;
3295 }
3296 Debug((DEBUG_DEBUG,"udp poll"));
3297
3298 memset(&from, 0, fromlen);
3299 n = recvfrom(udpfd, readbuf, mlen, 0, (SAP)&from, &fromlen);
3300 if (n == -1)
3301 {
3302 ircstp->is_udperr++;
3303 if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
3304 return;
3305 else
3306 {
3307 #if 0
3308 /* seems to create more confusion than it's worth */
3309 char buf[100];
3310
3311 sprintf(buf, "udp port recvfrom() from %s to %%s: %%s",
3312 #ifdef INET6
3313 from.sin6_addr.s6_addr
3314 #else
3315 from.sin_addr.s_addr
3316 #endif
3317 == 0 ? "unknown" :
3318 #ifdef INET6
3319 inetntop(AF_INET6, (char *)&from.sin6_addr,
3320 ipv6string, sizeof(ipv6string))
3321 #else
3322 inetntoa((char *)&from.sin_addr)
3323 #endif
3324 );
3325 report_error(buf, &me);
3326 #endif /* confusion */
3327 return;
3328 }
3329 }
3330
3331 if (timeofday == last)
3332 {
3333 if (++cnt > 14)
3334 {
3335 if (timeofday > lasterr + 30)
3336 {
3337 sendto_flag(SCH_NOTICE,
3338 "udp packet dropped: %d bytes from %s.%d",
3339 #ifdef INET6
3340 n, inetntop(AF_INET6,
3341 (char *)&from.sin6_addr, ipv6string,
3342 sizeof(ipv6string)),
3343 #else
3344 n,inetntoa((char *)&from.sin_addr),
3345 #endif
3346 ntohs(from.SIN_PORT));
3347 lasterr = timeofday;
3348 }
3349 ircstp->is_udpdrop++;
3350 return;
3351 }
3352 }
3353 else
3354 cnt = 0, last = timeofday;
3355
3356 #ifdef INET6
3357 Debug((DEBUG_NOTICE, "udp (%d) %d bytes from %s,%d", cnt, n,
3358 inet_ntop(AF_INET6, (char *)&from.sin6_addr, ipv6string,
3359 sizeof(ipv6string)),
3360 ntohs(from.SIN_PORT)));
3361 #else
3362 Debug((DEBUG_NOTICE, "udp (%d) %d bytes from %s,%d", cnt, n,
3363 inetntoa((char *)&from.sin_addr),
3364 ntohs(from.SIN_PORT)));
3365 #endif
3366
3367 readbuf[n] = '\0';
3368 ircstp->is_udpok++;
3369 if (n < 8)
3370 return;
3371
3372 bcopy(s = readbuf, (char *)&pi, MIN(n, sizeof(pi)));
3373 pi.pi_id = ntohl(pi.pi_id);
3374 Debug((DEBUG_INFO, "\tpi_id %#x pi_seq %d pi_cp %#x",
3375 pi.pi_id, pi.pi_seq, pi.pi_cp));
3376
3377 if ((pi.pi_id == (PING_CPING|PING_REPLY) ||
3378 pi.pi_id == (PING_CPING|(PING_REPLY << 24))) && n >= sizeof(pi))
3379 {
3380 check_ping(s, n);
3381 return;
3382 }
3383 else if (pi.pi_id & PING_REPLY)
3384 return;
3385 /*
3386 * attach my name and version for the reply
3387 */
3388 pi.pi_id |= PING_REPLY;
3389 pi.pi_id = htonl(pi.pi_id);
3390 bcopy((char *)&pi, s, MIN(n, sizeof(pi)));
3391 s += n;
3392 (void)strcpy(s, ME);
3393 s += strlen(s)+1;
3394 (void)strcpy(s, version);
3395 s += strlen(s);
3396 (void)sendto(udpfd, readbuf, s-readbuf, 0, (SAP)&from ,sizeof(from));
3397 return;
3398 }
3399
3400 /*
3401 * do_dns_async
3402 *
3403 * Called when the fd returned from init_resolver() has been selected for
3404 * reading.
3405 */
3406 static void do_dns_async(void)
3407 {
3408 static Link ln;
3409 aClient *cptr;
3410 aConfItem *aconf;
3411 struct hostent *hp;
3412 int bytes, pkts;
3413
3414 pkts = 0;
3415
3416 do {
3417 ln.flags = -1;
3418 hp = get_res((char *)&ln);
3419
3420 Debug((DEBUG_DNS,"%#x = get_res(%d,%#x)", hp, ln.flags,
3421 ln.value.cptr));
3422
3423 switch (ln.flags)
3424 {
3425 case ASYNC_NONE :
3426 /*
3427 * no reply was processed that was outstanding or
3428 * had a client still waiting.
3429 */
3430 break;
3431 case ASYNC_CLIENT :
3432 if ((cptr = ln.value.cptr))
3433 {
3434 del_queries((char *)cptr);
3435 ClearDNS(cptr);
3436 cptr->hostp = hp;
3437 #if defined(USE_IAUTH)
3438 if (hp)
3439 {
3440 int i = 0;
3441
3442 while (hp->h_aliases[i])
3443 sendto_iauth("%d A %s",
3444 cptr->fd,
3445 hp->h_aliases[i++]);
3446 if (hp->h_name)
3447 sendto_iauth("%d N %s",
3448 cptr->fd, hp->h_name);
3449 else if (hp->h_aliases[0])
3450 sendto_iauth("%d n", cptr->fd);
3451 }
3452 else
3453 sendto_iauth("%d d", cptr->fd);
3454 if (iauth_options & XOPT_EXTWAIT)
3455 cptr->lasttime = timeofday;
3456 #endif
3457 }
3458 break;
3459 case ASYNC_CONNECT :
3460 aconf = ln.value.aconf;
3461 if (hp && aconf)
3462 {
3463 bcopy(hp->h_addr, (char *)&aconf->ipnum,
3464 sizeof(struct IN_ADDR));
3465 (void)connect_server(aconf, NULL, hp);
3466 }
3467 else
3468 sendto_flag(SCH_ERROR,
3469 "Connect to %s failed: host lookup",
3470 (aconf) ? aconf->host : "unknown");
3471 break;
3472 case ASYNC_CONF :
3473 aconf = ln.value.aconf;
3474 if (hp && aconf)
3475 bcopy(hp->h_addr, (char *)&aconf->ipnum,
3476 sizeof(struct IN_ADDR));
3477 break;
3478 default :
3479 break;
3480 }
3481 pkts++;
3482 if (ioctl(resfd, FIONREAD, &bytes) == -1)
3483 bytes = 0;
3484 } while ((bytes > 0) && (pkts < 10));
3485 }
3486
3487 #ifdef DELAY_CLOSE
3488 /*
3489 * Delaying close(2) on too rapid connections reduces cpu
3490 * and bandwidth usage. Not mentioning disk space, if you
3491 * log such crap.
3492 *
3493 * Based on Ari `DLR' Heikkinen <aheikin@dlr.pspt.fi> irce0.9.1
3494 * by Piotr `Beeth' Kucharski <chopin@42.pl>
3495 *
3496 * Note: calling with fd == -2 closes all delayed fds.
3497 */
3498
3499 time_t delay_close(int fd)
3500 {
3501 struct fdlog
3502 {
3503 struct fdlog *next;
3504 int fd;
3505 time_t time;
3506 };
3507 static struct fdlog *first = NULL, *last = NULL;
3508 struct fdlog *next = first, *tmp;
3509 int tmpdel = 0;
3510
3511 if (fd == -2)
3512 {
3513 /* special case used in m_close() -- close all! */
3514 tmpdel = istat.is_delayclosewait;
3515 }
3516 else
3517 /* Make sure we don't delay close() on too many fds. If we have
3518 * kept more than half (possibly) available fds for clients
3519 * waiting to be closed, release quarter oldest of them.
3520 * >>1, >>2 are faster equivalents of /2, /4 --B. */
3521 if (istat.is_delayclosewait > (MAXCLIENTS-istat.is_localc) >> 1)
3522 {
3523 tmpdel = istat.is_delayclosewait >> 2;
3524 }
3525
3526 while ((tmp = next))
3527 {
3528 if (tmp->time < timeofday || tmpdel-- > 0)
3529 {
3530 next = tmp->next;
3531 (void)send(fd, "ERROR :Too rapid connections "
3532 "from your host\r\n", 46, 0);
3533 close(tmp->fd);
3534 MyFree(tmp);
3535 istat.is_delayclosewait--;
3536 if (!next)
3537 {
3538 last = NULL;
3539 }
3540 first = next;
3541 }
3542 else
3543 {
3544 /* This linked list has entries chronologically
3545 * sorted, so if tmp is not old enough, all next
3546 * would also be not old enough to close. */
3547 break;
3548 }
3549 }
3550
3551 if (fd >= 0)
3552 {
3553 /* set socket in nonblocking state (just in case) */
3554 set_non_blocking(fd, NULL);
3555
3556 /* disallow further receives */
3557 shutdown(fd, SHUT_RD);
3558
3559 /* create a new entry with fd and time of close */
3560 tmp = (struct fdlog *)MyMalloc(sizeof(*tmp));
3561 tmp->next = NULL;
3562 tmp->fd = fd;
3563 tmp->time = timeofday + DELAY_CLOSE;
3564 istat.is_delayclosewait++;
3565 istat.is_delayclose++;
3566
3567 /* then add it to the list */
3568 if (last)
3569 {
3570 last->next = tmp;
3571 last = tmp;
3572 }
3573 else
3574 {
3575 first = last = tmp;
3576 }
3577 }
3578
3579 return first ? first->time : 0;
3580 }
3581 #endif
3582