static void tcp_close_pending_connection (TCP_FD *pp) { int r; if (tmr_active (&pp->timer)) tmr_stop (&pp->timer); ctrc_printd (TCPS_ID, TCPS_CLOSE_PEND, &pp->fd, sizeof (pp->fd)); sock_fd_remove_socket (pp->fd); r = close (pp->fd); trace_server ("close", r, pp->fd); if (r) perror ("tcp_close_pending_connection: close()"); pp->fd = 0; tcp_pending_free (pp); }
/* handle remote trace request * * <source numeric> TRACE/TR <target> <target server numeric> * * cargv[0] = target * as given by source, can be a nick or a server (may contain wildcards) * cargv[1] = target server numeric * */ int handletracemsg(void *source, int cargc, char **cargv) { nick *snick; /* struct nick for source nick */ nick *tnick; /* struct nick for target nick */ nick **lnick; /* struct nick for looping local users */ int c; /* loop variable */ int opers = 0; /* number of operators */ int users = 0; /* number of users */ int servers = 0; /* number of servers */ int doall, wilds, dow; /* determine what to show */ char *sourcenum = (char *)source; /* source user numeric */ char *target; /* target parameter - as given by the source user */ /* check parameters */ if (cargc < 2) { miscreply_needmoreparams(sourcenum, "TRACE"); return CMD_OK; } /* get the parameters */ target = cargv[0]; /* find source user */ if (!(snick = miscreply_finduser(sourcenum, "TRACE"))) return CMD_OK; /* doall, wilds, dow */ doall = match2strings(target, myserver->content); wilds = strchr(target, '*') || strchr(target, '?'); dow = wilds || doall; /* find target user */ if ((tnick = getnickbynick(target))) { /* my user */ if (mylongnum == homeserver(tnick->numeric)) trace_user(sourcenum, tnick); } /* source user is an operator */ else if (IsOper(snick)) { /* show servers */ servers = trace_server(sourcenum, target, doall); /* do all or wilds */ if (dow) { /* loop over all local users */ lnick = servernicks[mylongnum]; for (c = 0; c < serverlist[mylongnum].maxusernum; c++) { if (lnick[c] == NULL) /* no user */ continue; /* target is invisible (mode +i), target is not an operator */ if (IsInvisible(lnick[c]) && dow && !IsOper(lnick[c])) continue; /* dont show all, do wildcards and no match */ if (!doall && wilds && !match2strings(target, lnick[c]->nick)) continue; if (IsOper(lnick[c])) opers++; else users++; trace_user(sourcenum, lnick[c]); } /* * class has no meaning here, * but showing the total count for users/opers/servers might be useful anyway * * 209 RPL_TRACECLASS "source 209 target Class class count" * "irc.netsplit.net 209 foobar Class users 2" */ if (users) irc_send("%s 209 %s Class users %d", getmynumeric(), sourcenum, users); if (opers) irc_send("%s 209 %s Class opers %d", getmynumeric(), sourcenum, opers); if (servers) irc_send("%s 209 %s Class servers %d", getmynumeric(), sourcenum, servers); } } /* * 262 RPL_TRACEEND "source 262 target :End of TRACE" * "irc.netsplit.net 262 foobar :End of TRACE" */ irc_send("%s 262 %s :End of TRACE", getmynumeric(), sourcenum); return CMD_OK; }
static void tcp_server_accept (SOCKET fd, short revents, void *arg) { IP_CX *scxp = (IP_CX *) arg; TCP_FD *pp; struct sockaddr_in peer_addr; #ifdef DDS_IPV6 struct sockaddr_in6 peer_addr_v6; #endif struct sockaddr *caddr; socklen_t size; uint32_t a4; int r; trace_poll_events (fd, revents, arg); memset (&scxp->dst_addr, 0, sizeof (scxp->dst_addr)); if (scxp->locator->locator.kind == LOCATOR_KIND_TCPv4) { peer_addr.sin_family = AF_INET; caddr = (struct sockaddr *) &peer_addr; size = sizeof (struct sockaddr_in); } #ifdef DDS_IPV6 else if (scxp->locator->locator.kind == LOCATOR_KIND_TCPv6) { peer_addr_v6.sin6_family = AF_INET6; caddr = (struct sockaddr *) &peer_addr_v6; size = sizeof (struct sockaddr_in6); } #endif else { warn_printf ("TCP(S): unknown address family!"); return; } #ifdef TCP_ACCEPT_DELAY_MS usleep (TCP_ACCEPT_DELAY_MS * 1000); #endif r = accept (fd, caddr, &size); ctrc_begind (TCPS_ID, TCPS_SERVER_EV, &fd, sizeof (fd)); ctrc_contd (&revents, sizeof (revents)); ctrc_contd (caddr, size); ctrc_contd (&r, sizeof (r)); ctrc_endd (); trace_server ("accept", r, fd); if (r < 0) { perror ("tcp_server_accept: accept()"); log_printf (RTPS_ID, 0, "tcp_server_accept: accept() failed - errno = %d.\r\n", ERRNO); return; } #ifdef DDS_TCP_NODELAY sock_set_tcp_nodelay (r); #endif /* Create a new pending TCP connection. */ pp = xmalloc (sizeof (TCP_FD)); if (!pp) { ctrc_printd (TCPS_ID, TCPS_FD_NOMEM, &r, sizeof (r)); close (r); /* bad reuse of variable in error case */ trace_server ("close", 0, r); log_printf (RTPS_ID, 0, "TCP(S): allocation failure!\r\n"); return; } memset (pp, 0, sizeof (TCP_FD)); pp->fd = r; if (scxp->locator->locator.kind == LOCATOR_KIND_TCPv4) { a4 = ntohl (peer_addr.sin_addr.s_addr); memset (pp->dst_addr, 0, 12); pp->dst_addr [12] = a4 >> 24; pp->dst_addr [13] = (a4 >> 16) & 0xff; pp->dst_addr [14] = (a4 >> 8) & 0xff; pp->dst_addr [15] = a4 & 0xff; pp->dst_port = ntohs (peer_addr.sin_port); }
static int tcp_do_connect (TCP_CON_REQ_ST *p) { TCP_CON_LIST_ST *hp; TCP_DATA *dp; struct sockaddr_in sa_v4; #ifdef DDS_IPV6 struct sockaddr_in6 sa_v6; #endif struct sockaddr *sa; socklen_t len; unsigned family; short events; int fd, r, err; #ifdef __APPLE__ int yes = 1; #endif trc_con1 ("tcp_do_connect(cp=%p);\r\n", (void *) p); do { /* No connect() in progress currently! */ hp = p->head; if ((hp->locator.kind & LOCATOR_KINDS_IPv4) != 0) { sa_v4.sin_family = family = AF_INET; sa_v4.sin_port = htons (hp->locator.port); sa = (struct sockaddr *) &sa_v4; len = sizeof (sa_v4); sa_v4.sin_addr.s_addr = htonl ((hp->locator.address [12] << 24) | (hp->locator.address [13] << 16) | (hp->locator.address [14] << 8) | hp->locator.address [15]); ctrc_printd (TCPS_ID, TCPS_DO_CON, hp->locator.address + 12, 4); } #ifdef DDS_IPV6 else if ((hp->locator.kind & LOCATOR_KINDS_IPv6) != 0) { sa_v6.sin6_family = family = AF_INET6; memcpy (sa_v6.sin6_addr.s6_addr, hp->locator.address, 16); sa_v6.sin6_port = htons (hp->locator.port); sa = (struct sockaddr *) &sa_v6; len = sizeof (sa_v6); ctrc_printd (TCPS_ID, TCPS_DO_CON, hp->locator.address, 16); } #endif else { log_printf (RTPS_ID, 0, "tcp_do_connect: invalid locator kind!\r\n"); return (-2); } dp = xmalloc (sizeof (TCP_DATA)); if (!dp) { warn_printf ("tcp_connect: out of memory for TCP context!"); return (-2); } dp->send_msg = dp->recv_msg = NULL; fd = socket (family, SOCK_STREAM, IPPROTO_TCP); trace_client ("socket", fd, -1); if (fd < 0) { xfree (dp); /*perror ("tcp_do_connect: socket()");*/ log_printf (RTPS_ID, 0, "tcp_do_connect: socket() failed - errno = %d.\r\n", ERRNO); return (-2); } p->cxp->fd = fd; p->cxp->fd_owner = 1; p->cxp->sproto = dp; #ifdef __APPLE__ /* MSG_NOSIGNAL does not exist for Apple OS, but a equivalent socket option is available */ if (setsockopt (fd, SOL_SOCKET, SO_NOSIGPIPE, &yes, sizeof (yes)) < 0) perror ("tcp_do_connect: setsockopt()"); #endif #ifdef DDS_TCP_NODELAY sock_set_tcp_nodelay (fd); #endif sock_set_socket_nonblocking (fd); events = POLLIN | POLLPRI | POLLHUP | POLLNVAL; for (;;) { r = connect (fd, sa, len); ctrc_begind (TCPS_ID, TCPS_SYS_CON, &fd, sizeof (fd)); ctrc_contd (&r, sizeof (r)); ctrc_endd (); trace_client ("connect", r, fd); if (r == -1) { err = ERRNO; if (err == EINTR) continue; if (err != EINPROGRESS) { ctrc_printd (TCPS_ID, TCPS_CON_ERR, &fd, sizeof (fd)); /*perror ("tcp_do_connect: connect()");*/ log_printf (RTPS_ID, 0, "tcp_do_connect: connect() failed - errno = %d.\r\n", err); close (fd); trace_server ("close", r, fd); p->cxp->cx_state = CXS_WRETRY; p->cxp->fd = 0; p->cxp->fd_owner = 0; } else { log_printf (RTPS_ID, 0, "TCP: connecting to server [%d] ...\r\n", fd); p->cxp->cx_state = CXS_CONNECT; sock_fd_add_socket (fd, events | POLLOUT, tcp_wait_connect_complete, p, "DDS.TCP-C"); ctrc_printd (TCPS_ID, TCPS_CON_WAIT, &fd, sizeof (fd)); return (-1); } } else { log_printf (RTPS_ID, 0, "TCP: connected to server [%d]\r\n", fd); p->cxp->cx_state = CXS_OPEN; ctrc_printd (TCPS_ID, TCPS_CON_OK, &fd, sizeof (fd)); sock_fd_add_socket (fd, events, tcp_socket_activity, p->cxp, "DDS.TCP-C"); } break; } p = tcp_clear_pending_connect (p); } while (p); return (r); }