X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=ircd%2Fuping.c;h=62b69560db348c636e148f2f967d99e487746c6f;hb=refs%2Fheads%2Fupstream;hp=b12fdcb2b1466dcc0dcbefe265ada908f6756ddc;hpb=263c649848b2b25a097134227a7b89d868cb2e1e;p=ircu2.10.12-pk.git diff --git a/ircd/uping.c b/ircd/uping.c index b12fdcb..62b6956 100644 --- a/ircd/uping.c +++ b/ircd/uping.c @@ -15,21 +15,26 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * $Id$ */ +/** @file + * @brief UDP ping implementation. + * @version $Id$ + */ +#include "config.h" + #include "uping.h" #include "client.h" #include "ircd.h" #include "ircd_alloc.h" +#include "ircd_events.h" #include "ircd_log.h" #include "ircd_osdep.h" #include "ircd_string.h" #include "match.h" +#include "msg.h" #include "numeric.h" #include "numnicks.h" -#include "res.h" -#include "s_bsd.h" /* vserv */ +#include "s_bsd.h" /* VirtualHost */ #include "s_conf.h" #include "s_debug.h" #include "s_misc.h" @@ -37,8 +42,7 @@ #include "send.h" #include "sys.h" -#include -#include +/* #include -- Now using assert in ircd_log.h */ #include #include #include @@ -48,27 +52,22 @@ #include #include -#define UPINGTIMEOUT 60 /* Timeout waiting for ping responses */ - -#ifndef INADDR_NONE -#define INADDR_NONE 0xffffffff -#endif - -static void ping_server(struct UPing*); +#define UPINGTIMEOUT 60 /**< Timeout waiting for ping responses */ -static struct UPing* pingList = 0; -int UPingListener = -1; /* UDP listener socket for upings */ +static struct UPing* pingList = 0; /**< Linked list of UPing structs */ +static struct Socket upingSock_v4; /**< Socket struct for IPv4 upings */ +static struct Socket upingSock_v6; /**< Socket struct for IPv6 upings */ -/* - * pings_begin - iterator function for ping list +/** Start iteration of uping list. + * @return Start of uping list. */ struct UPing* uping_begin(void) { return pingList; } -/* - * pings_erase - removes ping struct from ping list +/** Removes \a p from uping list. + * @param[in,out] p UPing to remove from list. */ static void uping_erase(struct UPing* p) { @@ -76,8 +75,8 @@ static void uping_erase(struct UPing* p) struct UPing* last = 0; assert(0 != p); - - for (it = pingList; it; last = it = it->next) { + + for (it = pingList; it; last = it, it = it->next) { if (p == it) { if (last) last->next = p->next; @@ -88,210 +87,230 @@ static void uping_erase(struct UPing* p) } } -/* - * uping_dns_callback - this gets called when the resolver either - * succeeds or fails to locate the servers address. - * If the dns query failed hp will be 0, otherwise it - * will contain the stuff a hostent normally contains. +/** Callback for uping listener socket. + * Reads a uping from the socket and respond, but not more than 10 + * times per second. + * @param[in] ev I/O event for uping socket. */ -static void uping_dns_callback(void* v, struct DNSReply* r) +static void uping_echo_callback(struct Event* ev) { - struct UPing* ping = (struct UPing*) v; - assert(valid_ptr((void*)ping, sizeof(struct UPing))); + struct Socket *sock; + struct irc_sockaddr from; + unsigned int len = 0; + static time_t last = 0; + static int counter = 0; + char buf[BUFSIZE + 1]; - if (r) { - memcpy(&ping->sin.sin_addr, r->hp->h_addr, sizeof(struct in_addr)); - ping_server(ping); - } - else - { - sendto_ops("UDP ping to %s failed: host lookup", ping->name); - end_ping(ping); - } -} + assert(ev_type(ev) == ET_READ || ev_type(ev) == ET_ERROR); + sock = ev_socket(ev); + assert(sock == &upingSock_v4 || sock == &upingSock_v6); + Debug((DEBUG_DEBUG, "UPING: uping_echo")); -/* - * Setup a UDP socket and listen for incoming packets + if (IO_SUCCESS != os_recvfrom_nonb(s_fd(sock), buf, BUFSIZE, &len, &from)) + return; + /* + * count em even if we're getting flooded so we can tell we're getting + * flooded. + */ + ++ServerStats->uping_recv; + if (len < 19) + return; + else if (CurrentTime != last) { + counter = 0; + last = CurrentTime; + } else if (++counter > 10) + return; + os_sendto_nonb(s_fd(sock), buf, len, NULL, 0, &from); +} + +/** Initialize a UDP socket for upings. + * @returns 0 on success, -1 on error. */ int uping_init(void) { - struct sockaddr_in from; + struct irc_sockaddr from; int fd; - memset(&from, 0, sizeof(from)); -#ifdef VIRTUAL_HOST - from.sin_addr = vserv.sin_addr; -#else - from.sin_addr.s_addr = htonl(INADDR_ANY); -#endif - from.sin_port = htons(atoi(UDP_PORT)); - from.sin_family = AF_INET; + memcpy(&from, &VirtualHost_v4, sizeof(from)); + from.port = atoi(UDP_PORT); - if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { - Debug((DEBUG_ERROR, "UPING: UDP listener socket call failed: %s", strerror(errno))); + fd = os_socket(&from, SOCK_DGRAM, "IPv4 uping listener", AF_INET); + if (fd < 0) return -1; - } - if (!os_set_reuseaddr(fd)) { - ircd_log(L_ERROR, "UPING: setsockopt UDP listener: fd %d", fd); - Debug((DEBUG_ERROR, "UPING: set reuseaddr on UDP listener failed: %s", strerror(errno))); + if (!socket_add(&upingSock_v4, uping_echo_callback, 0, SS_DATAGRAM, + SOCK_EVENT_READABLE, fd)) { + Debug((DEBUG_ERROR, "UPING: Unable to queue fd to event system")); close(fd); return -1; } - if (bind(fd, (struct sockaddr*) &from, sizeof(from)) == -1) { - ircd_log(L_ERROR, "UPING: bind UDP listener %d fd %d", htons(from.sin_port), fd); - Debug((DEBUG_ERROR, "UPING: bind on UDP listener failed : %s", strerror(errno))); - close(fd); + +#ifdef AF_INET6 + memcpy(&from, &VirtualHost_v6, sizeof(from)); + from.port = atoi(UDP_PORT); + + fd = os_socket(&from, SOCK_DGRAM, "IPv6 uping listener", AF_INET6); + if (fd < 0) return -1; - } - if (!os_set_nonblocking(fd)) { - Debug((DEBUG_ERROR, "UPING: set non-blocking: %s", strerror(errno))); + if (!socket_add(&upingSock_v6, uping_echo_callback, 0, SS_DATAGRAM, + SOCK_EVENT_READABLE, fd)) { + Debug((DEBUG_ERROR, "UPING: Unable to queue fd to event system")); close(fd); return -1; } - return fd; +#endif + + return 0; } -/* - * max # of pings set to 15/sec. +/** Callback for socket activity on an outbound uping socket. + * @param[in] ev I/O event for socket. */ -void polludp(int udpfd) +static void uping_read_callback(struct Event* ev) { - struct sockaddr_in from; - unsigned int len = 0; - static time_t last = 0; - static int counter = 0; - char buf[BUFSIZE + 1]; + struct UPing *pptr; - Debug((DEBUG_DEBUG, "UPING: poll")); + assert(0 != ev_socket(ev)); + assert(0 != s_data(ev_socket(ev))); - if (IO_SUCCESS != os_recvfrom_nonb(udpfd, buf, BUFSIZE, &len, &from)) - return; - /* - * count em even if we're getting flooded so we can tell we're getting - * flooded. - */ - ++ServerStats->uping_recv; - if (CurrentTime == last) { - if (++counter > 10) - return; - } - else { - counter = 0; - last = CurrentTime; + pptr = (struct UPing*) s_data(ev_socket(ev)); + + Debug((DEBUG_SEND, "uping_read_callback called, %p (%d)", pptr, + ev_type(ev))); + + if (ev_type(ev) == ET_DESTROY) { /* being destroyed */ + pptr->freeable &= ~UPING_PENDING_SOCKET; + + if (!pptr->freeable) + MyFree(pptr); /* done with it, finally */ + } else { + assert(ev_type(ev) == ET_READ || ev_type(ev) == ET_ERROR); + + uping_read(pptr); /* read uping response */ } - if (len < 19) - return; - sendto(udpfd, buf, len, 0, (struct sockaddr *)&from, sizeof(from)); } - -/* - * start_ping +/** Timer callback to send another outbound uping. + * @param[in] ev Event for uping timer. */ -static void start_ping(struct UPing* pptr) +static void uping_sender_callback(struct Event* ev) { - assert(valid_ptr((void*) pptr, sizeof(struct UPing))); - - if (MyUser(pptr->client) || Protocol(pptr->client->from) < 10) { - sendto_one(pptr->client, - ":%s NOTICE %s :Sending %d ping%s to %s[%s] port %d", - me.name, pptr->client->name, pptr->count, - (pptr->count == 1) ? "" : "s", pptr->name, - ircd_ntoa((const char*) &pptr->sin.sin_addr), ntohs(pptr->sin.sin_port)); - } - else - { - sendto_one(pptr->client, - "%s NOTICE %s%s :Sending %d ping%s to %s[%s] port %d", - NumServ(&me), NumNick(pptr->client), pptr->count, - (pptr->count == 1) ? "" : "s", pptr->name, - ircd_ntoa((const char*) &pptr->sin.sin_addr), ntohs(pptr->sin.sin_port)); + struct UPing *pptr; + + assert(0 != ev_timer(ev)); + assert(0 != t_data(ev_timer(ev))); + + pptr = (struct UPing*) t_data(ev_timer(ev)); + + Debug((DEBUG_SEND, "uping_sender_callback called, %p (%d)", pptr, + ev_type(ev))); + + if (ev_type(ev) == ET_DESTROY) { /* being destroyed */ + pptr->freeable &= ~UPING_PENDING_SENDER; + + if (!pptr->freeable) + MyFree(pptr); /* done with it, finally */ + } else { + assert(ev_type(ev) == ET_EXPIRE); + + pptr->lastsent = CurrentTime; /* store last ping time */ + uping_send(pptr); /* send a ping */ + + if (pptr->sent == pptr->count) /* done sending pings, don't send more */ + timer_del(ev_timer(ev)); } - pptr->timeout = CurrentTime + UPINGTIMEOUT; - pptr->active = 1; } -/* - * ping_server - get the server host address if not valid - * then call start_ping +/** Timer callback to stop upings. + * @param[in] ev Event for uping expiration. */ -static void ping_server(struct UPing* pptr) +static void uping_killer_callback(struct Event* ev) { - if (INADDR_NONE == pptr->sin.sin_addr.s_addr) { - char *s; - - if ((s = strchr(pptr->name, '@'))) - ++s; - else - s = pptr->name; - - if (INADDR_NONE == (pptr->sin.sin_addr.s_addr = inet_addr(s))) { - struct DNSQuery query; - struct DNSReply* rpl; - - query.vptr = (void*) pptr; - query.callback = uping_dns_callback; - if (0 == (rpl = gethost_byname(s, &query))) - return; - memcpy(&pptr->sin.sin_addr, rpl->hp->h_addr, sizeof(struct in_addr)); - } + struct UPing *pptr; + + assert(0 != ev_timer(ev)); + assert(0 != t_data(ev_timer(ev))); + + pptr = (struct UPing*) t_data(ev_timer(ev)); + + Debug((DEBUG_SEND, "uping_killer_callback called, %p (%d)", pptr, + ev_type(ev))); + + if (ev_type(ev) == ET_DESTROY) { /* being destroyed */ + pptr->freeable &= ~UPING_PENDING_KILLER; + + if (!pptr->freeable) + MyFree(pptr); /* done with it, finally */ + } else { + assert(ev_type(ev) == ET_EXPIRE); + + uping_end(pptr); /* kill the uping, kill the uping! */ } - start_ping(pptr); } +/** Start a uping. + * This sets up the timers, UPing flags, and sends a notice to the + * requesting client. + */ +static void uping_start(struct UPing* pptr) +{ + assert(0 != pptr); + + timer_add(timer_init(&pptr->sender), uping_sender_callback, (void*) pptr, + TT_PERIODIC, 1); + timer_add(timer_init(&pptr->killer), uping_killer_callback, (void*) pptr, + TT_RELATIVE, UPINGTIMEOUT); + pptr->freeable |= UPING_PENDING_SENDER | UPING_PENDING_KILLER; -/* - * send_ping - * + sendcmdto_one(&me, CMD_NOTICE, pptr->client, "%C :Sending %d ping%s to %s", + pptr->client, pptr->count, (pptr->count == 1) ? "" : "s", + pptr->name); + pptr->active = 1; +} + +/** Send a uping to another server. + * @param[in] pptr Descriptor for uping. */ -void send_ping(struct UPing* pptr) +void uping_send(struct UPing* pptr) { struct timeval tv; char buf[BUFSIZE + 1]; assert(0 != pptr); + if (pptr->sent == pptr->count) + return; memset(buf, 0, sizeof(buf)); gettimeofday(&tv, NULL); - sprintf(buf, " %10lu%c%6lu", tv.tv_sec, '\0', tv.tv_usec); + sprintf(buf, " %10lu%c%6lu", (unsigned long)tv.tv_sec, '\0', (unsigned long)tv.tv_usec); Debug((DEBUG_SEND, "send_ping: sending [%s %s] to %s.%d on %d", buf, &buf[12], - ircd_ntoa((const char*) &pptr->sin.sin_addr), ntohs(pptr->sin.sin_port), + ircd_ntoa(&pptr->addr.addr), pptr->addr.port, pptr->fd)); - if (sendto(pptr->fd, buf, BUFSIZE, 0, (struct sockaddr*) &pptr->sin, - sizeof(struct sockaddr_in)) != BUFSIZE) + if (os_sendto_nonb(pptr->fd, buf, BUFSIZE, NULL, 0, &pptr->addr) != IO_SUCCESS) { - int err = errno; + const char* msg = strerror(errno); + if (!msg) + msg = "Unknown error"; if (pptr->client) - { - if (MyUser(pptr->client) -#ifndef NO_PROTOCOL9 - || (IsServer(pptr->client->from) && Protocol(pptr->client->from) < 10) -#endif - ) - sendto_one(pptr->client, ":%s NOTICE %s :UPING: sendto() failed: %s", - me.name, pptr->client->name, strerror(errno)); - else - sendto_one(pptr->client, "%s NOTICE %s%s :UPING: sendto() failed: %s", - NumServ(&me), NumNick(pptr->client), strerror(errno)); - } - Debug((DEBUG_DEBUG, "UPING: send_ping: sendto failed on %d: %s", pptr->fd, strerror(err))); - end_ping(pptr); + sendcmdto_one(&me, CMD_NOTICE, pptr->client, "%C :UPING: send failed: " + "%s", pptr->client, msg); + Debug((DEBUG_DEBUG, "UPING: send_ping: sendto failed on %d: %s", pptr->fd, msg)); + uping_end(pptr); return; } ++pptr->sent; } -/* - * read_ping +/** Read the response from an outbound uping. + * @param[in] pptr UPing to check. */ -void read_ping(struct UPing* pptr) +void uping_read(struct UPing* pptr) { - struct sockaddr_in sin; + struct irc_sockaddr sin; struct timeval tv; unsigned int len; unsigned int pingtime; @@ -307,302 +326,159 @@ void read_ping(struct UPing* pptr) if (IO_BLOCKED == ior) return; else if (IO_FAILURE == ior) { - int err = errno; - if (MyUser(pptr->client) -#ifndef NO_PROTOCOL9 - || (IsServer(pptr->client->from) && Protocol(pptr->client->from) < 10) -#endif - ) - sendto_one(pptr->client, ":%s NOTICE %s :UPING: recvfrom: %s", - me.name, pptr->client->name, strerror(err)); - else - sendto_one(pptr->client, "%s NOTICE %s%s :UPING: recvfrom: %s", - NumServ(&me), NumNick(pptr->client), strerror(err)); - Debug((DEBUG_SEND, "UPING: read_ping: recvfrom: %d", err)); - end_ping(pptr); + const char* msg = strerror(errno); + if (!msg) + msg = "Unknown error"; + sendcmdto_one(&me, CMD_NOTICE, pptr->client, "%C :UPING: receive error: " + "%s", pptr->client, msg); + uping_end(pptr); return; - } + } if (len < 19) return; /* Broken packet */ ++pptr->received; + + buf[len] = 0; pingtime = (tv.tv_sec - atol(&buf[1])) * 1000 + (tv.tv_usec - atol(buf + strlen(buf) + 1)) / 1000; pptr->ms_ave += pingtime; - if (!(pptr->ms_min) || (pptr->ms_min > pingtime)) + if (!pptr->ms_min || pptr->ms_min > pingtime) pptr->ms_min = pingtime; if (pingtime > pptr->ms_max) pptr->ms_max = pingtime; - - pptr->timeout = CurrentTime + UPINGTIMEOUT; - Debug((DEBUG_SEND, "read_ping: %d bytes, ti %lu: [%s %s] %lu ms", - len, pptr->timeout, buf, (buf + strlen(buf) + 1), pingtime)); + timer_chg(&pptr->killer, TT_RELATIVE, UPINGTIMEOUT); s = pptr->buf + strlen(pptr->buf); sprintf(s, " %u", pingtime); if (pptr->received == pptr->count) - end_ping(pptr); + uping_end(pptr); return; } - -/* - * m_uping -- by Run - * - * parv[0] = sender prefix - * parv[1] = pinged server - * parv[2] = port - * parv[3] = hunted server - * parv[4] = number of requested pings +/** Start sending upings to a server. + * @param[in] sptr Client requesting the upings. + * @param[in] aconf ConfItem containing the address to ping. + * @param[in] port Port number to ping. + * @param[in] count Number of times to ping (should be at least 20). + * @return Zero. */ -int m_uping(struct Client* cptr, struct Client *sptr, int parc, char *parv[]) +int uping_server(struct Client* sptr, struct ConfItem* aconf, int port, int count) { - struct ConfItem *aconf; - int port; int fd; - struct UPing* pptr = 0; + int family = 0; + struct UPing* pptr; + struct irc_sockaddr *local; - if (!IsPrivileged(sptr)) - { - sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); - return -1; - } + assert(0 != sptr); + assert(0 != aconf); - if (parc < 2) - { - sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "UPING"); + if (!irc_in_addr_valid(&aconf->address.addr)) { + sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :UPING: Host lookup failed for " + "%s", sptr, aconf->name); return 0; } - if (MyUser(sptr)) - { - if (parc == 2) - { - parv[parc++] = UDP_PORT; - parv[parc++] = me.name; - parv[parc++] = "5"; - } - else if (parc == 3) - { - if (IsDigit(*parv[2])) - parv[parc++] = me.name; - else - { - parv[parc++] = parv[2]; - parv[2] = UDP_PORT; - } - parv[parc++] = "5"; - } - else if (parc == 4) - { - if (IsDigit(*parv[2])) - { - if (IsDigit(*parv[3])) - { - parv[parc++] = parv[3]; - parv[3] = me.name; - } - else - parv[parc++] = "5"; - } - else - { - parv[parc++] = parv[3]; - parv[3] = parv[2]; - parv[2] = UDP_PORT; - } - } - } - if (hunt_server(1, cptr, sptr, - ":%s UPING %s %s %s %s", 3, parc, parv) != HUNTED_ISME) - return 0; - - if (BadPtr(parv[4]) || atoi(parv[4]) <= 0) - { - if (MyUser(sptr) || Protocol(cptr) < 10) - sendto_one(sptr, ":%s NOTICE %s :UPING: Illegal number of packets: %s", - me.name, parv[0], parv[4]); - else - sendto_one(sptr, "%s NOTICE %s%s :UPING: Illegal number of packets: %s", - NumServ(&me), NumNick(sptr), parv[4]); - return 0; - } + if (IsUPing(sptr)) + uping_cancel(sptr, sptr); /* Cancel previous ping request */ - /* Check if a CONNECT would be possible at all (adapted from m_connect) */ - for (aconf = GlobalConfList; aconf; aconf = aconf->next) - { - if (aconf->status == CONF_SERVER && - match(parv[1], aconf->name) == 0) - break; + if (irc_in_addr_is_ipv4(&aconf->address.addr)) { + local = &VirtualHost_v4; + family = AF_INET; + } else { + local = &VirtualHost_v6; } - if (!aconf) - { - for (aconf = GlobalConfList; aconf; aconf = aconf->next) - { - if (aconf->status == CONF_SERVER && - (match(parv[1], aconf->host) == 0 || - match(parv[1], strchr(aconf->host, '@') + 1) == 0)) - break; - } - } - if (!aconf) - { - if (MyUser(sptr) || Protocol(cptr) < 10) - sendto_one(sptr, ":%s NOTICE %s :UPING: Host %s not listed in ircd.conf", - me.name, parv[0], parv[1]); - else - sendto_one(sptr, - "%s NOTICE %s%s :UPING: Host %s not listed in ircd.conf", - NumServ(&me), NumNick(sptr), parv[1]); + fd = os_socket(local, SOCK_DGRAM, "Outbound uping socket", family); + if (fd < 0) return 0; - } - if (IsUPing(sptr)) - cancel_ping(sptr, sptr); /* Cancel previous ping request */ - - /* - * Determine port: First user supplied, then default : 7007 - */ - if (BadPtr(parv[2]) || (port = atoi(parv[2])) <= 0) - port = atoi(UDP_PORT); - - if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { - int err = errno; - sendto_ops("m_uping: socket: %s", (err != EMFILE) - ? strerror(err) : "No more sockets"); - if (MyUser(sptr) || Protocol(cptr) < 10) - sendto_one(sptr, - ":%s NOTICE %s :UPING: Unable to create udp ping socket", - me.name, parv[0]); - else - sendto_one(sptr, - "%s NOTICE %s%s :UPING: Unable to create udp ping socket", - NumServ(&me), NumNick(sptr)); - ircd_log(L_ERROR, "UPING: Unable to create UDP socket"); - return 0; - } + pptr = (struct UPing*) MyMalloc(sizeof(struct UPing)); + assert(0 != pptr); + memset(pptr, 0, sizeof(struct UPing)); - if (!os_set_nonblocking(fd)) { - if (MyUser(sptr) || Protocol(cptr) < 10) - sendto_one(sptr, ":%s NOTICE %s :UPING: Can't set fd non-blocking", - me.name, parv[0]); - else - sendto_one(sptr, "%s NOTICE %s%s :UPING: Can't set fd non-blocking", - NumServ(&me), NumNick(sptr)); + if (!socket_add(&pptr->socket, uping_read_callback, (void*) pptr, + SS_DATAGRAM, SOCK_EVENT_READABLE, fd)) { + sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :UPING: Can't queue fd for " + "reading", sptr); close(fd); + MyFree(pptr); return 0; } - pptr = (struct UPing*) MyMalloc(sizeof(struct UPing)); - assert(0 != pptr); - memset(pptr, 0, sizeof(struct UPing)); - pptr->fd = fd; - pptr->sin.sin_port = htons(port); - pptr->sin.sin_addr.s_addr = aconf->ipnum.s_addr; - pptr->sin.sin_family = AF_INET; - pptr->count = IRCD_MIN(20, atoi(parv[4])); - strcpy(pptr->name, aconf->host); - pptr->client = sptr; - pptr->index = -1; + pptr->fd = fd; + memcpy(&pptr->addr.addr, &aconf->address.addr, sizeof(pptr->addr.addr)); + pptr->addr.port = port; + pptr->count = IRCD_MIN(20, count); + pptr->client = sptr; + pptr->freeable = UPING_PENDING_SOCKET; + strcpy(pptr->name, aconf->name); pptr->next = pingList; - pingList = pptr; + pingList = pptr; SetUPing(sptr); - ping_server(pptr); + uping_start(pptr); return 0; } -void end_ping(struct UPing* pptr) +/** Clean up a UPing structure, reporting results to the requester. + * @param[in,out] pptr UPing results. + */ +void uping_end(struct UPing* pptr) { - Debug((DEBUG_DEBUG, "end_ping: %p", pptr)); - delete_resolver_queries((void*) pptr); - if (pptr->client) - { - if (MyUser(pptr->client) - || (IsServer(pptr->client->from) && Protocol(pptr->client->from) < 10)) - { - if (pptr->lastsent) /* Started at all ? */ - { - if (0 < pptr->received) /* Received any pings at all? */ - { - sendto_one(pptr->client, ":%s NOTICE %s :UPING %s%s", - me.name, pptr->client->name, pptr->name, pptr->buf); - /* XXX - warning long unsigned int format, unsigned int arg (7, 8, 9) */ - sendto_one(pptr->client, - ":%s NOTICE %s :UPING Stats: sent %d recvd %d ; " - "min/avg/max = %1lu/%1lu/%1lu ms", - me.name, pptr->client->name, pptr->sent, - pptr->received, pptr->ms_min, - (2 * pptr->ms_ave) / (2 * pptr->received), - pptr->ms_max); - } - else - sendto_one(pptr->client, - ":%s NOTICE %s :UPING: no response from %s within %d seconds", - me.name, pptr->client->name, pptr->name, - UPINGTIMEOUT); - } - else - sendto_one(pptr->client, - ":%s NOTICE %s :UPING: Could not start ping to %s %d", - me.name, pptr->client->name, pptr->name, ntohs(pptr->sin.sin_port)); - } - else - { - if (pptr->lastsent) /* Started at all ? */ - { - if (0 < pptr->received) /* Received any pings at all? */ - { - sendto_one(pptr->client, "%s NOTICE %s%s :UPING %s%s", - NumServ(&me), NumNick(pptr->client), pptr->name, pptr->buf); - /* XXX - warning: long unsigned int format, unsigned int arg(9, 10, 11) */ - sendto_one(pptr->client, - "%s NOTICE %s%s :UPING Stats: sent %d recvd %d ; " - "min/avg/max = %1lu/%1lu/%1lu ms", - NumServ(&me), NumNick(pptr->client), pptr->sent, - pptr->received, pptr->ms_min, - (2 * pptr->ms_ave) / (2 * pptr->received), - pptr->ms_max); - } - else - sendto_one(pptr->client, - "%s NOTICE %s%s :UPING: no response from %s within %d seconds", - NumServ(&me), NumNick(pptr->client), pptr->name, - UPINGTIMEOUT); - } - else - sendto_one(pptr->client, - "%s NOTICE %s%s :UPING: Could not start ping to %s %d", - NumServ(&me), NumNick(pptr->client), pptr->name, - ntohs(pptr->sin.sin_port)); - } + Debug((DEBUG_DEBUG, "uping_end: %p", pptr)); + + if (pptr->client) { + if (pptr->lastsent) { + if (0 < pptr->received) { + sendcmdto_one(&me, CMD_NOTICE, pptr->client, "%C :UPING %s%s", + pptr->client, pptr->name, pptr->buf); + sendcmdto_one(&me, CMD_NOTICE, pptr->client, "%C :UPING Stats: " + "sent %d recvd %d ; min/avg/max = %u/%u/%u ms", + pptr->client, pptr->sent, pptr->received, pptr->ms_min, + (2 * pptr->ms_ave) / (2 * pptr->received), pptr->ms_max); + } else + sendcmdto_one(&me, CMD_NOTICE, pptr->client, "%C :UPING: no response " + "from %s within %d seconds", pptr->client, pptr->name, + UPINGTIMEOUT); + } else + sendcmdto_one(&me, CMD_NOTICE, pptr->client, "%C :UPING: Could not " + "start ping to %s", pptr->client, pptr->name); } + close(pptr->fd); pptr->fd = -1; uping_erase(pptr); if (pptr->client) ClearUPing(pptr->client); - MyFree(pptr); + if (pptr->freeable & UPING_PENDING_SOCKET) + socket_del(&pptr->socket); + if (pptr->freeable & UPING_PENDING_SENDER) + timer_del(&pptr->sender); + if (pptr->freeable & UPING_PENDING_KILLER) + timer_del(&pptr->killer); } -void cancel_ping(struct Client *sptr, struct Client* acptr) +/** Change notifications for any upings by \a sptr. + * @param[in] sptr Client to stop notifying. + * @param[in] acptr New client to notify (or NULL). + */ +void uping_cancel(struct Client *sptr, struct Client* acptr) { struct UPing* ping; struct UPing* ping_next; - Debug((DEBUG_DEBUG, "UPING: cancelling uping for %s", sptr->name)); + Debug((DEBUG_DEBUG, "UPING: canceling uping for %s", cli_name(sptr))); for (ping = pingList; ping; ping = ping_next) { ping_next = ping->next; if (sptr == ping->client) { ping->client = acptr; - end_ping(ping); + uping_end(ping); } } ClearUPing(sptr); } -