void CleanupClient(ClientInfo *cp, int sts) { char *caddr; int i, msg; int force; force = pmDebug & DBG_TRACE_APPL0; if (sts != 0 || force) { /* for access violations, only print the message if this host hasn't * been dinged for an access violation since startup or reconfiguration */ if (sts == PM_ERR_PERMISSION || sts == PM_ERR_CONNLIMIT) { if ( (msg = AddBadHost(cp->addr)) ) { caddr = __pmSockAddrToString(cp->addr); fprintf(stderr, "access violation from host %s\n", caddr); free(caddr); } } else msg = 0; if (msg || force) { for (i = 0; i < nClients; i++) { if (cp == &client[i]) break; } fprintf(stderr, "endclient client[%d]: (fd %d) %s (%d)\n", i, cp->fd, pmErrStr(sts), sts); } } /* If the client is being cleaned up because its connection was refused * don't do this because it hasn't actually contributed to the connection * count */ if (sts != PM_ERR_PERMISSION && sts != PM_ERR_CONNLIMIT) __pmAccDelClient(cp->addr); pmcd_trace(TR_DEL_CLIENT, cp->fd, sts, 0); DeleteClient(cp); if (maxClientFd < maxReqPortFd) maxClientFd = maxReqPortFd; for (i = 0; i < nAgents; i++) if (agent[i].profClient == cp) agent[i].profClient = NULL; }
void ShowClients(FILE *f) { int i; char *sbuf; char *hostName; fprintf(f, " fd client connection from ipc ver operations denied\n"); fprintf(f, " == ======================================== ======= =================\n"); for (i = 0; i < nClients; i++) { if (client[i].status.connected == 0) continue; fprintf(f, " %3d ", client[i].fd); hostName = __pmGetNameInfo(client[i].addr); if (hostName == NULL) { sbuf = __pmSockAddrToString(client[i].addr); fprintf(f, "%s", sbuf); free(sbuf); } else { fprintf(f, "%-40.40s", hostName); free(hostName); } fprintf(f, " %7d", __pmVersionIPC(client[i].fd)); if (client[i].denyOps != 0) { fprintf(f, " "); if (client[i].denyOps & PMCD_OP_FETCH) fprintf(f, "fetch "); if (client[i].denyOps & PMCD_OP_STORE) fprintf(f, "store "); } fputc('\n', f); } fputc('\n', f); }
/* Establish a new socket connection to a client */ ClientInfo * AcceptNewClient(int reqfd) { int i; int fd; __pmSockLen addrlen; int ok = 0; char buf[MY_BUFLEN]; char *bp; char *endp; char *abufp; i = NewClient(); addrlen = __pmSockAddrSize(); fd = __pmAccept(reqfd, client[i].addr, &addrlen); if (fd == -1) { __pmNotifyErr(LOG_ERR, "AcceptNewClient(%d) __pmAccept failed: %s", reqfd, netstrerror()); Shutdown(); exit(1); } __pmSetSocketIPC(fd); if (fd > maxSockFd) maxSockFd = fd; __pmFD_SET(fd, &sockFds); client[i].fd = fd; client[i].pmcd_fd = -1; client[i].status.connected = 1; client[i].status.allowed = 0; client[i].pmcd_hostname = NULL; /* * version negotiation (converse to negotiate_proxy() logic in * libpcp * * __pmRecv client version message * __pmSend my server version message * __pmRecv pmcd hostname and pmcd port */ for (bp = buf; bp < &buf[MY_BUFLEN]; bp++) { if (__pmRecv(fd, bp, 1, 0) != 1) { *bp = '\0'; /* null terminate what we have */ bp = &buf[MY_BUFLEN]; /* flag error */ break; } /* end of line means no more ... */ if (*bp == '\n' || *bp == '\r') { *bp = '\0'; break; } } if (bp < &buf[MY_BUFLEN]) { /* looks OK so far ... is this a version we can support? */ if (strcmp(buf, "pmproxy-client 1") == 0) { client[i].version = 1; ok = 1; } } if (!ok) { #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_CONTEXT) { abufp = __pmSockAddrToString(client[i].addr); __pmNotifyErr(LOG_INFO, "Bad version string from client at %s", abufp); free(abufp); fprintf(stderr, "AcceptNewClient: bad version string was \""); for (bp = buf; *bp && bp < &buf[MY_BUFLEN]; bp++) fputc(*bp & 0xff, stderr); fprintf(stderr, "\"\n"); } #endif DeleteClient(&client[i]); return NULL; } if (__pmSend(fd, MY_VERSION, strlen(MY_VERSION), 0) != strlen(MY_VERSION)) { abufp = __pmSockAddrToString(client[i].addr); __pmNotifyErr(LOG_WARNING, "AcceptNewClient: failed to send version " "string (%s) to client at %s\n", MY_VERSION, abufp); free(abufp); DeleteClient(&client[i]); return NULL; } for (bp = buf; bp < &buf[MY_BUFLEN]; bp++) { if (__pmRecv(fd, bp, 1, 0) != 1) { *bp = '\0'; /* null terminate what we have */ bp = &buf[MY_BUFLEN]; /* flag error */ break; } /* end of line means no more ... */ if (*bp == '\n' || *bp == '\r') { *bp = '\0'; break; } } if (bp < &buf[MY_BUFLEN]) { /* looks OK so far ... get hostname and port */ for (bp = buf; *bp && *bp != ' '; bp++) ; if (bp != buf) { *bp = '\0'; client[i].pmcd_hostname = strdup(buf); if (client[i].pmcd_hostname == NULL) __pmNoMem("PMCD.hostname", strlen(buf), PM_FATAL_ERR); bp++; client[i].pmcd_port = (int)strtoul(bp, &endp, 10); if (*endp != '\0') { abufp = __pmSockAddrToString(client[i].addr); __pmNotifyErr(LOG_WARNING, "AcceptNewClient: bad pmcd port " "\"%s\" from client at %s", bp, abufp); free(abufp); DeleteClient(&client[i]); return NULL; } } /* error, fall through */ } if (client[i].pmcd_hostname == NULL) { abufp = __pmSockAddrToString(client[i].addr); __pmNotifyErr(LOG_WARNING, "AcceptNewClient: failed to get PMCD " "hostname (%s) from client at %s", buf, abufp); free(abufp); DeleteClient(&client[i]); return NULL; } #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_CONTEXT) { /* * note error message gets appended to once pmcd connection is * made in ClientLoop() */ abufp = __pmSockAddrToString(client[i].addr); fprintf(stderr, "AcceptNewClient [%d] fd=%d from %s to %s (port %s)", i, fd, abufp, client[i].pmcd_hostname, bp); free(abufp); } #endif return &client[i]; }