static void authsenderr(aClient *cptr) { ircstp->is_abad++; (void)close(cptr->authfd); if (cptr->authfd == highest_fd) while (!local[highest_fd]) highest_fd--; cptr->authfd = -1; cptr->flags &= ~(FLAGS_AUTH|FLAGS_WRAUTH); #ifdef SHOW_HEADERS send(cptr->fd, REPORT_FAIL_ID, R_fail_id, 0); #endif if (!DoingDNS(cptr)) SetAccess(cptr); return; }
void check_client_fd(aClient *cptr) { if (DoingAuth(cptr)) { unsigned int fdflags = get_fd_flags(cptr->authfd); if(!(fdflags & FDF_WANTREAD)) set_fd_flags(cptr->authfd, FDF_WANTREAD); if((cptr->flags & FLAGS_WRAUTH) && !(fdflags & FDF_WANTWRITE)) set_fd_flags(cptr->authfd, FDF_WANTWRITE); else if(!(cptr->flags & FLAGS_WRAUTH) && (fdflags & FDF_WANTWRITE)) unset_fd_flags(cptr->authfd, FDF_WANTWRITE); return; } if (DoingDNS(cptr)) return; set_fd_flags(cptr->fd, FDF_WANTREAD); }
static time_t check_pings(time_t currenttime) { #ifdef TIMEDKLINES static time_t lkill = 0; #endif Reg aClient *cptr; Reg int kflag = 0; aClient *bysptr = NULL; int ping = 0, i; time_t oldest = 0, timeout; char *reason = NULL; for (i = highest_fd; i >= 0; i--) { if (!(cptr = local[i]) || IsListener(cptr)) continue; #ifdef TIMEDKLINES kflag = 0; reason = NULL; /* ** Once per TIMEDKLINES seconds. ** (1 minute is minimum resolution in K-line field) */ if ((currenttime - lkill > TIMEDKLINES) && IsPerson(cptr) && !IsKlineExempt(cptr)) { kflag = find_kill(cptr, 1, &reason); } #endif ping = IsRegistered(cptr) ? cptr->ping : ACCEPTTIMEOUT; Debug((DEBUG_DEBUG, "c(%s) %d p %d k %d a %d", cptr->name, cptr->status, ping, kflag, currenttime - cptr->lasttime)); /* * Ok, so goto's are ugly and can be avoided here but this code * is already indented enough so I think its justified. -avalon */ if (!kflag && IsRegistered(cptr) && (ping >= currenttime - cptr->lasttime)) goto ping_timeout; /* * If the server hasnt talked to us in 2*ping seconds * and it has a ping time, then close its connection. * If the client is a user and a KILL line was found * to be active, close this connection too. */ if (kflag || ((currenttime - cptr->lasttime) >= (2 * ping) && (cptr->flags & FLAGS_PINGSENT)) || (!IsRegistered(cptr) && (currenttime - cptr->firsttime) >= ping)) { if (!IsRegistered(cptr) && (DoingDNS(cptr) || DoingAuth(cptr) || DoingXAuth(cptr))) { if (cptr->authfd >= 0) { (void)close(cptr->authfd); cptr->authfd = -1; cptr->count = 0; *cptr->buffer = '\0'; } Debug((DEBUG_NOTICE, "%s/%c%s timeout %s", (DoingDNS(cptr)) ? "DNS" : "dns", (DoingXAuth(cptr)) ? "X" : "x", (DoingAuth(cptr)) ? "AUTH" : "auth", get_client_name(cptr,TRUE))); del_queries((char *)cptr); ClearAuth(cptr); #if defined(USE_IAUTH) if (DoingDNS(cptr) || DoingXAuth(cptr)) { if (DoingDNS(cptr) && (iauth_options & XOPT_EXTWAIT)) { /* iauth wants more time */ sendto_iauth("%d d", cptr->fd); ClearDNS(cptr); cptr->lasttime = currenttime; continue; } if (DoingXAuth(cptr) && (iauth_options & XOPT_NOTIMEOUT)) { cptr->exitc = EXITC_AUTHTOUT; sendto_iauth("%d T", cptr->fd); exit_client(cptr, cptr, &me, "Authentication Timeout"); continue; } sendto_iauth("%d T", cptr->fd); SetDoneXAuth(cptr); } #endif ClearDNS(cptr); ClearXAuth(cptr); ClearWXAuth(cptr); cptr->firsttime = currenttime; cptr->lasttime = currenttime; continue; } if (IsServer(cptr) || IsConnecting(cptr) || IsHandshake(cptr)) { if (cptr->serv && cptr->serv->byuid[0]) { bysptr = find_uid(cptr->serv->byuid, NULL); } /* we are interested only in *remote* opers */ if (bysptr && !MyConnect(bysptr)) { sendto_one(bysptr, ":%s NOTICE %s :" "No response from %s, closing" " link", ME, bysptr->name, get_client_name(cptr, FALSE)); } sendto_flag(SCH_NOTICE, "No response from %s closing link", get_client_name(cptr, FALSE)); } /* * this is used for KILL lines with time restrictions * on them - send a message to the user being killed * first. */ if (kflag && IsPerson(cptr)) { char buf[100]; sendto_flag(SCH_NOTICE, "Kill line active for %s", get_client_name(cptr, FALSE)); cptr->exitc = EXITC_KLINE; if (!BadPtr(reason)) sprintf(buf, "Kill line active: %.80s", reason); (void)exit_client(cptr, cptr, &me, (reason) ? buf : "Kill line active"); } else { cptr->exitc = EXITC_PING; (void)exit_client(cptr, cptr, &me, "Ping timeout"); } continue; } else if (IsRegistered(cptr) && (cptr->flags & FLAGS_PINGSENT) == 0) { /* * if we havent PINGed the connection and we havent * heard from it in a while, PING it to make sure * it is still alive. */ cptr->flags |= FLAGS_PINGSENT; /* not nice but does the job */ cptr->lasttime = currenttime - ping; sendto_one(cptr, "PING :%s", me.name); } ping_timeout: timeout = cptr->lasttime + ping; while (timeout <= currenttime) timeout += ping; if (timeout < oldest || !oldest) oldest = timeout; } #ifdef TIMEDKLINES if (currenttime - lkill > 60) lkill = currenttime; #endif if (!oldest || oldest < currenttime) oldest = currenttime + PINGFREQUENCY; if (oldest < currenttime + 30) oldest += 30; Debug((DEBUG_NOTICE,"Next check_ping() call at: %s, %d %d %d", myctime(oldest), ping, oldest, currenttime)); return (oldest); }
/* * start_auth * * Flag the client to show that an attempt to contact the ident server on * the client's host. The connect and subsequently the socket are all put * into 'non-blocking' mode. Should the connect or any later phase of the * identifing process fail, it is aborted and the user is given a username * of "unknown". */ void start_auth(aClient *cptr) { struct sockaddr_in sock; struct sockaddr_in localaddr; int locallen; Debug((DEBUG_NOTICE,"start_auth(%x) fd %d status %d", cptr, cptr->fd, cptr->status)); if ((cptr->authfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { #ifdef USE_SYSLOG syslog(LOG_ERR, "Unable to create auth socket for %s:%m", get_client_name(cptr,TRUE)); #endif if (!DoingDNS(cptr)) SetAccess(cptr); ircstp->is_abad++; return; } if (cptr->authfd >= MAXCONNECTIONS) { sendto_ops("Can't allocate fd for auth on %s", get_client_name(cptr, TRUE)); (void)close(cptr->authfd); return; } #ifdef SHOW_HEADERS send(cptr->fd, REPORT_DO_ID, R_do_id, 0); #endif set_non_blocking(cptr->authfd, cptr); /* get the local address of the client and bind to that to * make the auth request. This used to be done only for * ifdef VIRTTUAL_HOST, but needs to be done for all clients * since the ident request must originate from that same address-- * and machines with multiple IP addresses are common now */ locallen = sizeof(struct sockaddr_in); bzero(&localaddr, locallen); getsockname(cptr->fd, (struct sockaddr *)&localaddr, &locallen); localaddr.sin_port = htons(0); if (bind(cptr->authfd, (struct sockaddr *)&localaddr, sizeof(localaddr)) == -1) { report_error("binding auth stream socket %s:%s", cptr); (void)close(cptr->fd); return; } bcopy((char *)&cptr->ip, (char *)&sock.sin_addr, sizeof(struct in_addr)); sock.sin_port = htons(113); sock.sin_family = AF_INET; /* (void)alarm((unsigned)4);*/ if (connect(cptr->authfd, (struct sockaddr *)&sock, sizeof(sock)) == -1 && errno != EINPROGRESS) { ircstp->is_abad++; /* * No error report from this... */ /* (void)alarm((unsigned)0);*/ (void)close(cptr->authfd); cptr->authfd = -1; if (!DoingDNS(cptr)) SetAccess(cptr); #ifdef SHOW_HEADERS send(cptr->fd, REPORT_FAIL_ID, R_fail_id, 0); #endif return; } /* (void)alarm((unsigned)0);*/ cptr->flags |= (FLAGS_WRAUTH|FLAGS_AUTH); if (cptr->authfd > highest_fd) highest_fd = cptr->authfd; return; }
/* * read_authports * * read the reply (if any) from the ident server we connected to. * The actual read processing here is pretty weak - no handling of the reply * if it is fragmented by IP. * * This is really broken and needs to be rewritten. Somehow len is nonzero * on failed connects() on Solaris (and maybe others?). I relocated the * REPORT_FIN_ID to hide the problem. --Rodder * */ void read_authports(aClient *cptr) { Reg char *s, *t; Reg int len; char ruser[USERLEN+1], tuser[USERLEN+1]; u_short remp = 0, locp = 0; *ruser = '******'; Debug((DEBUG_NOTICE,"read_authports(%x) fd %d authfd %d stat %d", cptr, cptr->fd, cptr->authfd, cptr->status)); /* * Nasty. Cant allow any other reads from client fd while we're * waiting on the authfd to return a full valid string. Use the * client's input buffer to buffer the authd reply. * Oh. this is needed because an authd reply may come back in more * than 1 read! -avalon */ if ((len = read(cptr->authfd, cptr->buffer + cptr->count, sizeof(cptr->buffer) - 1 - cptr->count)) >= 0) { cptr->count += len; cptr->buffer[cptr->count] = '\0'; } if ((len > 0) && (cptr->count != sizeof(cptr->buffer) - 1) && (sscanf(cptr->buffer, "%hd , %hd : USERID : %*[^:]: %10s", &remp, &locp, tuser) == 3) && (s = strrchr(cptr->buffer, ':'))) { for (++s, t = ruser; *s && (t < ruser + sizeof(ruser)); s++) if (!isspace(*s) && *s != ':' && *s != '@') *t++ = *s; *t = '\0'; Debug((DEBUG_INFO,"auth reply ok")); } else if(len != 0) /* then its < 0 an error */ { /* sendto_realops("This is the infamous fdlist.c bug. congrats."); */ *ruser = '******'; } (void)close(cptr->authfd); if (cptr->authfd == highest_fd) while (!local[highest_fd]) highest_fd--; cptr->count = 0; cptr->authfd = -1; ClearAuth(cptr); if (!DoingDNS(cptr)) SetAccess(cptr); if (len > 0) Debug((DEBUG_INFO,"ident reply: [%s]", cptr->buffer)); if (!locp || !remp || !*ruser) { ircstp->is_abad++; (void)strcpy(cptr->username, "unknown"); return; } #ifdef SHOW_HEADERS else send(cptr->fd, REPORT_FIN_ID, R_fin_id, 0); #endif ircstp->is_asuc++; strncpyzt(cptr->username, ruser, USERLEN+1); cptr->flags |= FLAGS_GOTID; Debug((DEBUG_INFO, "got username [%s]", ruser)); return; }
static time_t check_pings(time_t currenttime) { aClient *cptr; aConfItem *aconf = (aConfItem *) NULL; int killflag, zkillflag, ping = 0, i; time_t oldest = 0; /* timeout removed, see EXPLANATION below */ char *reason, *ktype, fbuf[512]; char *errtxt = "No response from %s, closing link"; for (i = 0; i <= highest_fd; i++) { if (!(cptr = local[i]) || IsMe(cptr) || IsLog(cptr)) continue; /* Note: No need to notify opers here. It's * already done when "FLAGS_DEADSOCKET" is set. */ if (cptr->flags & FLAGS_DEADSOCKET) { (void) exit_client(cptr, cptr, &me, (cptr->flags & FLAGS_SENDQEX) ? "SendQ exceeded" : "Dead socket"); i--; continue; } killflag = NO; zkillflag = NO; if (rehashed) { if (zline_in_progress) { if (IsPerson(cptr)) { if ((aconf = find_zkill(cptr))) zkillflag = YES; } } else { if(IsPerson(cptr)) { if((aconf = find_kill(cptr))) killflag = YES; } } } /* Added a bit of code here to differentiate * between K and Z-lines. -ThemBones */ if (zkillflag || killflag) { ktype = zkillflag ? "Z-lined" : ((aconf->status == CONF_KILL) ? "K-lined" : "Autokilled"); if (killflag) { sendto_ops("%s active for %s", (aconf->status == CONF_KILL) ? "K-line" : "Autokill", get_client_name(cptr, FALSE)); reason = aconf->passwd ? aconf->passwd : ktype; } else { /* its a Z line */ sendto_ops("Z-line active for %s", get_client_name(cptr, FALSE)); reason = aconf->passwd ? aconf->passwd : "Z-lined"; } sendto_one(cptr, err_str(ERR_YOUREBANNEDCREEP), me.name, cptr->name, ktype); ircsprintf(fbuf, "%s: %s", ktype, reason); (void) exit_client(cptr, cptr, &me, fbuf); i--; /* subtract out this fd so we check it again.. */ continue; } if (IsRegistered(cptr)) ping = cptr->pingval; else ping = CONNECTTIMEOUT; /* * Ok, so goto's are ugly and can be avoided here but this code * is already indented enough so I think its justified. -avalon * * justified by what? laziness? <g> * If the client pingtime is fine (ie, not larger than the client ping) * skip over all the checks below. - lucas */ if (ping < (currenttime - cptr->lasttime)) { /* * If the server hasnt talked to us in 2*ping seconds and it has * a ping time, then close its connection. If the client is a * user and a KILL line was found to be active, close this * connection too. */ if (((cptr->flags & FLAGS_PINGSENT) && ((currenttime - cptr->lasttime) >= (2 * ping))) || ((!IsRegistered(cptr) && (currenttime - cptr->since) >= ping))) { if (!IsRegistered(cptr) && (DoingDNS(cptr) || DoingAuth(cptr))) { if (cptr->authfd >= 0) { (void) close(cptr->authfd); cptr->authfd = -1; cptr->count = 0; *cptr->buffer = '\0'; } #ifdef SHOW_HEADERS if (DoingDNS(cptr)) ssl_send(cptr, REPORT_FAIL_DNS, R_fail_dns, 0); if (DoingAuth(cptr)) ssl_send(cptr, REPORT_FAIL_ID, R_fail_id, 0); #endif Debug((DEBUG_NOTICE, "DNS/AUTH timeout %s", get_client_name(cptr, TRUE))); del_queries((char *) cptr); ClearAuth(cptr); ClearDNS(cptr); SetAccess(cptr); cptr->since = currenttime; continue; } if (IsServer(cptr) || IsConnecting(cptr) || IsHandshake(cptr)) { ircsprintf(fbuf, "from %s: %s", me.name, errtxt); sendto_gnotice(fbuf, get_client_name(cptr, HIDEME)); ircsprintf(fbuf, ":%s GNOTICE :%s", me.name, errtxt); sendto_serv_butone(cptr, fbuf, get_client_name(cptr, HIDEME)); } (void) exit_client(cptr, cptr, &me, "Ping timeout"); i--; /* subtract out this fd so we check it again.. */ continue; } /* don't send pings during a burst, as we send them already. */ else if (!(cptr->flags & (FLAGS_PINGSENT|FLAGS_BURST))) { /* * if we havent PINGed the connection and we havent heard from * it in a while, PING it to make sure it is still alive. */ cptr->flags |= FLAGS_PINGSENT; /* * not nice but does the job */ cptr->lasttime = currenttime - ping; sendto_one(cptr, "PING :%s", me.name); } } /* see EXPLANATION below * * timeout = cptr->lasttime + ping; * while (timeout <= currenttime) * timeout += ping; * if (timeout < oldest || !oldest) * oldest = timeout; */ /* * Check UNKNOWN connections - if they have been in this state * for > 100s, close them. */ if (IsUnknown(cptr)) if (cptr->firsttime ? ((timeofday - cptr->firsttime) > 100) : 0) (void) exit_client(cptr, cptr, &me, "Connection Timed Out"); } rehashed = 0; zline_in_progress = 0; /* EXPLANATION * on a server with a large volume of clients, at any given point * there may be a client which needs to be pinged the next second, * or even right away (a second may have passed while running * check_pings). Preserving CPU time is more important than * pinging clients out at exact times, IMO. Therefore, I am going to make * check_pings always return currenttime + 9. This means that it may take * a user up to 9 seconds more than pingfreq to timeout. Oh well. * Plus, the number is 9 to 'stagger' our check_pings calls out over * time, to avoid doing it and the other tasks ircd does at the same time * all the time (which are usually done on intervals of 5 seconds or so). * - lucas * * if (!oldest || oldest < currenttime) * oldest = currenttime + PINGFREQUENCY; */ oldest = currenttime + 9; Debug((DEBUG_NOTICE, "Next check_ping() call at: %s, %d %d %d", myctime(oldest), ping, oldest, currenttime)); return oldest; }
static time_t check_pings(time_t currenttime) { register aClient *cptr; /* current local cptr being examined */ aConfItem *aconf = (aConfItem *)NULL; int ping = 0; /* ping time value from client */ int i; /* used to index through fd/cptr's */ time_t oldest = 0; /* next ping time */ time_t timeout; /* found necessary ping time */ char *reason; /* pointer to reason string */ int die_index=0; /* index into list */ char ping_time_out_buffer[64]; /* blech that should be a define */ /* of dying clients */ dying_clients[0] = (aClient *)NULL; /* mark first one empty */ /* * I re-wrote the way klines are handled. Instead of rescanning * the local[] array and calling exit_client() right away, I * mark the client thats dying by placing a pointer to its aClient * into dying_clients[]. When I have examined all in local[], * I then examine the dying_clients[] for aClient's to exit. * This saves the rescan on k-lines, also greatly simplifies the code, * * Jan 28, 1998 * -Dianora */ for (i = 0; i <= highest_fd; i++) { if (!(cptr = local[i]) || IsMe(cptr) || IsLog(cptr)) continue; /* and go examine next fd/cptr */ /* ** Note: No need to notify opers here. It's ** already done when "FLAGS_DEADSOCKET" is set. */ if (cptr->flags & FLAGS_DEADSOCKET) { /* N.B. EVERY single time dying_clients[] is set * it must be followed by an immediate continue, * to prevent this cptr from being marked again for exit. * If you don't, you could cause exit_client() to be called twice * for the same cptr. i.e. bad news * -Dianora */ dying_clients[die_index] = cptr; dying_clients_reason[die_index++] = ((cptr->flags & FLAGS_SENDQEX) ? "SendQ exceeded" : "Dead socket"); dying_clients[die_index] = (aClient *)NULL; continue; /* and go examine next fd/cptr */ } if (rehashed) { if(dline_in_progress) { if(IsPerson(cptr)) { if( (aconf = find_dkill(cptr)) ) /* if there is a returned aConfItem then kill it */ { sendto_ops("D-line active for %s", get_client_name(cptr, FALSE)); dying_clients[die_index] = cptr; #ifdef KLINE_WITH_REASON reason = aconf->passwd ? aconf->passwd : "D-lined"; dying_clients_reason[die_index++] = reason; #else dying_clients_reason[die_index++] = "D-lined"; #endif dying_clients[die_index] = (aClient *)NULL; sendto_one(cptr, err_str(ERR_YOUREBANNEDCREEP), me.name, cptr->name, reason); continue; /* and go examine next fd/cptr */ } } } else { if(IsPerson(cptr)) { #ifdef GLINES if( (aconf = find_gkill(cptr)) ) { sendto_ops("G-line active for %s", get_client_name(cptr, FALSE)); dying_clients[die_index] = cptr; #ifdef KLINE_WITH_REASON reason = aconf->passwd ? aconf->passwd : "G-lined"; dying_clients_reason[die_index++] = reason; #else dying_clients_reason[die_index++] = "G-lined"; #endif dying_clients[die_index] = (aClient *)NULL; sendto_one(cptr, err_str(ERR_YOUREBANNEDCREEP), me.name, cptr->name, reason); continue; /* and go examine next fd/cptr */ } else #endif if((aconf = find_kill(cptr))) /* if there is a returned aConfItem.. then kill it */ { sendto_ops("K-line active for %s", get_client_name(cptr, FALSE)); dying_clients[die_index] = cptr; #ifdef KLINE_WITH_REASON #ifdef K_COMMENT_ONLY reason = aconf->passwd ? aconf->passwd : "K-lined"; #else reason = (BadPtr(aconf->passwd) || !is_comment(aconf->passwd)) ? "K-lined" : aconf->passwd; #endif dying_clients_reason[die_index++] = reason; #else dying_clients_reason[die_index++] = "K-lined"; #endif dying_clients[die_index] = (aClient *)NULL; sendto_one(cptr, err_str(ERR_YOUREBANNEDCREEP), me.name, cptr->name, reason); continue; /* and go examine next fd/cptr */ } } } } #ifdef IDLE_CHECK if (IsPerson(cptr)) { if( !IsElined(cptr) && ((timeofday - cptr->user->last) > idle_time)) { aConfItem *aconf; dying_clients[die_index] = cptr; dying_clients_reason[die_index++] = "idle exceeder"; dying_clients[die_index] = (aClient *)NULL; aconf = make_conf(); aconf->status = CONF_KILL; DupString(aconf->host, cptr->user->host); DupString(aconf->passwd, "idle exceeder" ); DupString(aconf->name, cptr->user->username); aconf->port = 0; aconf->hold = timeofday + 60; add_temp_kline(aconf); sendto_ops("Idle exceeder %s temp k-lining", get_client_name(cptr,FALSE)); continue; /* and go examine next fd/cptr */ } } #endif #ifdef REJECT_HOLD if (IsRejectHeld(cptr)) { if( timeofday > (cptr->firsttime + REJECT_HOLD_TIME) ) { dying_clients[die_index] = cptr; dying_clients_reason[die_index++] = "reject held client"; dying_clients[die_index] = (aClient *)NULL; continue; /* and go examine next fd/cptr */ } } #endif #if defined(R_LINES) && defined(R_LINES_OFTEN) /* * this is used for KILL lines with time restrictions * on them - send a message to the user being killed * first. * *** Moved up above -taner *** * * Moved here, no more rflag -Dianora */ if (IsPerson(cptr) && find_restrict(cptr)) { sendto_ops("Restricting %s, closing link.", get_client_name(cptr,FALSE)); dying_clients[die_index] = cptr; dying_clients_reason[die_index++] = "you have been R-lined"; dying_clients[die_index] = (aClient *)NULL; continue; /* and go examine next fd/cptr */ } #endif if (!IsRegistered(cptr)) ping = CONNECTTIMEOUT; else ping = get_client_ping(cptr); /* * Ok, so goto's are ugly and can be avoided here but this code * is already indented enough so I think its justified. -avalon */ /* if (!rflag && (ping >= currenttime - cptr->lasttime)) goto ping_timeout; */ /* * *sigh* I think not -Dianora */ if (ping < (currenttime - cptr->lasttime)) { /* * If the server hasnt talked to us in 2*ping seconds * and it has a ping time, then close its connection. * If the client is a user and a KILL line was found * to be active, close this connection too. */ if (((currenttime - cptr->lasttime) >= (2 * ping) && (cptr->flags & FLAGS_PINGSENT)) || ((!IsRegistered(cptr) && (currenttime - cptr->since) >= ping))) { if (!IsRegistered(cptr) && (DoingDNS(cptr) || DoingAuth(cptr))) { if (cptr->authfd >= 0) { (void)close(cptr->authfd); cptr->authfd = -1; cptr->count = 0; *cptr->buffer = '\0'; } #ifdef SHOW_HEADERS if (DoingDNS(cptr)) send(cptr->fd, REPORT_FAIL_DNS, R_fail_dns, 0); else send(cptr->fd, REPORT_FAIL_ID, R_fail_id, 0); #endif Debug((DEBUG_NOTICE,"DNS/AUTH timeout %s", get_client_name(cptr,TRUE))); del_queries((char *)cptr); ClearAuth(cptr); ClearDNS(cptr); SetAccess(cptr); cptr->since = currenttime; continue; } if (IsServer(cptr) || IsConnecting(cptr) || IsHandshake(cptr)) { sendto_ops("No response from %s, closing link", get_client_name(cptr, FALSE)); } /* * this is used for KILL lines with time restrictions * on them - send a messgae to the user being killed * first. * *** Moved up above -taner *** */ cptr->flags2 |= FLAGS2_PING_TIMEOUT; dying_clients[die_index++] = cptr; /* the reason is taken care of at exit time */ /* dying_clients_reason[die_index++] = "Ping timeout"; */ dying_clients[die_index] = (aClient *)NULL; /* * need to start loop over because the close can * affect the ordering of the local[] array.- avalon * ** Not if you do it right - Dianora */ continue; } else if ((cptr->flags & FLAGS_PINGSENT) == 0) { /* * if we havent PINGed the connection and we havent * heard from it in a while, PING it to make sure * it is still alive. */ cptr->flags |= FLAGS_PINGSENT; /* not nice but does the job */ cptr->lasttime = currenttime - ping; sendto_one(cptr, "PING :%s", me.name); } } /* ping_timeout: */ timeout = cptr->lasttime + ping; while (timeout <= currenttime) timeout += ping; if (timeout < oldest || !oldest) oldest = timeout; /* * Check UNKNOWN connections - if they have been in this state * for > 100s, close them. */ if (IsUnknown(cptr)) { if (cptr->firsttime ? ((timeofday - cptr->firsttime) > 100) : 0) { dying_clients[die_index] = cptr; dying_clients_reason[die_index++] = "Connection Timed Out"; dying_clients[die_index] = (aClient *)NULL; continue; } } } /* Now exit clients marked for exit above. * it doesn't matter if local[] gets re-arranged now * * -Dianora */ for(die_index = 0; (cptr = dying_clients[die_index]); die_index++) { if(cptr->flags2 & FLAGS2_PING_TIMEOUT) { (void)ircsprintf(ping_time_out_buffer, "Ping timeout: %d seconds", currenttime - cptr->lasttime); (void)exit_client(cptr, cptr, &me, ping_time_out_buffer ); } else (void)exit_client(cptr, cptr, &me, dying_clients_reason[die_index]); } rehashed = 0; dline_in_progress = 0; if (!oldest || oldest < currenttime) oldest = currenttime + PINGFREQUENCY; Debug((DEBUG_NOTICE,"Next check_ping() call at: %s, %d %d %d", myctime(oldest), ping, oldest, currenttime)); return (oldest); }