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