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); }
void dostatus(void) { int i = 0; int n; putchar('\n'); printf("Namespace: "); if (cmd_namespace != NULL) printf("%s\n", cmd_namespace); else { if (pmnsfile == NULL) printf("(default)\n"); else printf("%s\n", pmnsfile); } if (myPmdaName == NULL || connmode == NO_CONN) printf("PMDA: none\n"); else { printf("PMDA: %s\n", myPmdaName); printf("Connection: "); switch (connmode) { case CONN_DSO: printf("dso\n"); printf("DSO Interface Version: %d\n", dispatch.comm.pmda_interface); printf("PMDA PMAPI Version: %d\n", dispatch.comm.pmapi_version); break; case CONN_DAEMON: printf("daemon\n"); printf("PMDA PMAPI Version: "); i = __pmVersionIPC(infd); if (i == UNKNOWN_VERSION) printf("unknown!\n"); else printf("%d\n", i); break; default: printf("unknown!\n"); break; } } printf("Debug options: "); n = 0; for (i = 0; i < num_debug; i++) { if (*(debug_map[i].options)) n++; } if (n == num_debug) printf("(all)"); else if (n == 0) printf("(none)"); else { n = 0; for (i = 0; i < num_debug; i++) { if (*(debug_map[i].options)) { if (n == 0) n = 1; else putchar(' '); printf("%s", debug_map[i].name); } } } putchar('\n'); printf("Timer: "); if (timer == 0) printf("off\n"); else printf("on\n"); printf("Getdesc: "); if (get_desc == 0) printf("off\n"); else printf("on\n"); putchar('\n'); __pmDumpProfile(stdout, PM_INDOM_NULL, profile); putchar('\n'); }
/* * sendstatus */ static int sendstatus(void) { int rv; int end; int version; static int firsttime = 1; static char *tzlogger; struct timeval now; if (firsttime) { tzlogger = __pmTimezone(); firsttime = 0; } if ((version = __pmVersionIPC(clientfd)) < 0) return version; if (version >= LOG_PDU_VERSION2) { __pmLoggerStatus ls; if ((ls.ls_state = logctl.l_state) == PM_LOG_STATE_NEW) ls.ls_start.tv_sec = ls.ls_start.tv_usec = 0; else memcpy(&ls.ls_start, &logctl.l_label.ill_start, sizeof(ls.ls_start)); memcpy(&ls.ls_last, &last_stamp, sizeof(ls.ls_last)); __pmtimevalNow(&now); ls.ls_timenow.tv_sec = (__int32_t)now.tv_sec; ls.ls_timenow.tv_usec = (__int32_t)now.tv_usec; ls.ls_vol = logctl.l_curvol; ls.ls_size = ftell(logctl.l_mfp); assert(ls.ls_size >= 0); /* be careful of buffer size mismatches when copying strings */ end = sizeof(ls.ls_hostname) - 1; strncpy(ls.ls_hostname, logctl.l_label.ill_hostname, end); ls.ls_hostname[end] = '\0'; /* BTW, that string should equal pmcd_host[]. */ /* NB: FQDN cleanup: there is no such thing as 'the fully qualified domain name' of a server: it may have several or none; the set may have changed since the time the log archive was collected. Now that we store the then-current pmcd.hostname in the ill_hostname (and thus get it reported in ls_hostname), we could pass something else informative in the ls_fqdn slot. Namely, pmcd_host_conn[], which is the access path pmlogger's using to get to the pmcd. */ end = sizeof(ls.ls_fqdn) - 1; strncpy(ls.ls_fqdn, pmcd_host_conn, end); ls.ls_fqdn[end] = '\0'; end = sizeof(ls.ls_tz) - 1; strncpy(ls.ls_tz, logctl.l_label.ill_tz, end); ls.ls_tz[end] = '\0'; end = sizeof(ls.ls_tzlogger) - 1; if (tzlogger != NULL) strncpy(ls.ls_tzlogger, tzlogger, end); else end = 0; ls.ls_tzlogger[end] = '\0'; rv = __pmSendLogStatus(clientfd, &ls); } else rv = PM_ERR_IPC; return rv; }
int __pmConnectPMCD(pmHostSpec *hosts, int nhosts, int ctxflags, __pmHashCtl *attrs) { int sts = -1; int fd = -1; /* Fd for socket connection to pmcd */ int *ports; int nports; int portIx; int version = -1; int proxyport; pmHostSpec *proxyhost; static int first_time = 1; static pmHostSpec proxy; PM_INIT_LOCKS(); PM_LOCK(__pmLock_libpcp); if (first_time) { /* * One-trip check for use of pmproxy(1) in lieu of pmcd(1), * and to extract the optional environment variables ... * PMCD_PORT, PMPROXY_HOST and PMPROXY_PORT. * We also check for the presense of a certificate database * and load it up if either a user or system (global) DB is * found. */ first_time = 0; load_pmcd_ports(); load_proxy_hostspec(&proxy); } if (hosts[0].nports == 0) { nports = global_nports; ports = global_portlist; } else { nports = hosts[0].nports; ports = hosts[0].ports; } if (proxy.name == NULL && nhosts == 1) { const char *name = (const char *)hosts[0].name; /* * no proxy, connecting directly to pmcd */ PM_UNLOCK(__pmLock_libpcp); sts = -1; /* Try connecting via the local unix domain socket, if requested and supported. */ if (nports == PM_HOST_SPEC_NPORTS_LOCAL || nports == PM_HOST_SPEC_NPORTS_UNIX) { #if defined(HAVE_STRUCT_SOCKADDR_UN) if ((fd = __pmAuxConnectPMCDUnixSocket(name)) >= 0) { if ((sts = __pmConnectHandshake(fd, name, ctxflags, attrs)) < 0) { __pmCloseSocket(fd); } else sts = fd; portIx = -1; /* no port */ } #endif /* * If the connection failed, or is not supported, and the protocol was 'local:', * then try connecting to localhost via the default port(s). */ if (sts < 0) { if (nports == PM_HOST_SPEC_NPORTS_LOCAL) { name = "localhost"; nports = global_nports; ports = global_portlist; sts = -1; /* keep trying */ } else sts = -2; /* no more connection attempts. */ } } /* If still not connected, try via the given host name and ports, if requested. */ if (sts == -1) { for (portIx = 0; portIx < nports; portIx++) { if ((fd = __pmAuxConnectPMCDPort(name, ports[portIx])) >= 0) { if ((sts = __pmConnectHandshake(fd, name, ctxflags, attrs)) < 0) { __pmCloseSocket(fd); } else /* success */ break; } else sts = fd; } } if (sts < 0) { #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_CONTEXT) { char errmsg[PM_MAXERRMSGLEN]; fprintf(stderr, "__pmConnectPMCD(%s): pmcd connection port=", hosts[0].name); for (portIx = 0; portIx < nports; portIx++) { if (portIx == 0) fprintf(stderr, "%d", ports[portIx]); else fprintf(stderr, ",%d", ports[portIx]); } fprintf(stderr, " failed: %s\n", pmErrStr_r(sts, errmsg, sizeof(errmsg))); } #endif return sts; } #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_CONTEXT) { if (portIx >= 0) { fprintf(stderr, "__pmConnectPMCD(%s): pmcd connection port=%d fd=%d PDU version=%u\n", hosts[0].name, ports[portIx], fd, __pmVersionIPC(fd)); } else { fprintf(stderr, "__pmConnectPMCD(%s): pmcd connection path=%s fd=%d PDU version=%u\n", hosts[0].name, name, fd, __pmVersionIPC(fd)); } __pmPrintIPC(); } #endif return fd; } /* * connecting to pmproxy, and then to pmcd ... not a direct * connection to pmcd */ proxyhost = (nhosts > 1) ? &hosts[1] : &proxy; proxyport = (proxyhost->nports > 0) ? proxyhost->ports[0] : PROXY_PORT; for (portIx = 0; portIx < nports; portIx++) { fd = __pmAuxConnectPMCDPort(proxyhost->name, proxyport); if (fd < 0) { #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_CONTEXT) { char errmsg[PM_MAXERRMSGLEN]; fprintf(stderr, "__pmConnectPMCD(%s): proxy to %s port=%d failed: %s \n", hosts[0].name, proxyhost->name, proxyport, pmErrStr_r(-neterror(), errmsg, sizeof(errmsg))); } #endif PM_UNLOCK(__pmLock_libpcp); return fd; } if ((sts = version = negotiate_proxy(fd, hosts[0].name, ports[portIx])) < 0) __pmCloseSocket(fd); else if ((sts = __pmConnectHandshake(fd, proxyhost->name, ctxflags, attrs)) < 0) __pmCloseSocket(fd); else /* success */ break; } if (sts < 0) { #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_CONTEXT) { char errmsg[PM_MAXERRMSGLEN]; fprintf(stderr, "__pmConnectPMCD(%s): proxy connection to %s port=", hosts[0].name, proxyhost->name); for (portIx = 0; portIx < nports; portIx++) { if (portIx == 0) fprintf(stderr, "%d", ports[portIx]); else fprintf(stderr, ",%d", ports[portIx]); } fprintf(stderr, " failed: %s\n", pmErrStr_r(sts, errmsg, sizeof(errmsg))); } #endif PM_UNLOCK(__pmLock_libpcp); return sts; } #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_CONTEXT) { fprintf(stderr, "__pmConnectPMCD(%s): proxy connection host=%s port=%d fd=%d version=%d\n", hosts[0].name, proxyhost->name, ports[portIx], fd, version); } #endif PM_UNLOCK(__pmLock_libpcp); return fd; }
/* * Determine which clients (if any) have sent data to the server and handle it * as required. */ void HandleClientInput(__pmFdSet *fdsPtr) { int sts; int i; __pmPDU *pb; __pmPDUHdr *php; ClientInfo *cp; for (i = 0; i < nClients; i++) { int pinpdu; if (!client[i].status.connected || !__pmFD_ISSET(client[i].fd, fdsPtr)) continue; cp = &client[i]; this_client_id = i; pinpdu = sts = __pmGetPDU(cp->fd, LIMIT_SIZE, _pmcd_timeout, &pb); if (sts > 0) { pmcd_trace(TR_RECV_PDU, cp->fd, sts, (int)((__psint_t)pb & 0xffffffff)); } else { CleanupClient(cp, sts); continue; } php = (__pmPDUHdr *)pb; if (__pmVersionIPC(cp->fd) == UNKNOWN_VERSION && php->type != PDU_CREDS) { /* old V1 client protocol, no longer supported */ sts = PM_ERR_IPC; CleanupClient(cp, sts); __pmUnpinPDUBuf(pb); continue; } if (pmDebug & DBG_TRACE_APPL0) ShowClients(stderr); switch (php->type) { case PDU_PROFILE: sts = (cp->denyOps & PMCD_OP_FETCH) ? PM_ERR_PERMISSION : DoProfile(cp, pb); break; case PDU_FETCH: sts = (cp->denyOps & PMCD_OP_FETCH) ? PM_ERR_PERMISSION : DoFetch(cp, pb); break; case PDU_INSTANCE_REQ: sts = (cp->denyOps & PMCD_OP_FETCH) ? PM_ERR_PERMISSION : DoInstance(cp, pb); break; case PDU_DESC_REQ: sts = (cp->denyOps & PMCD_OP_FETCH) ? PM_ERR_PERMISSION : DoDesc(cp, pb); break; case PDU_TEXT_REQ: sts = (cp->denyOps & PMCD_OP_FETCH) ? PM_ERR_PERMISSION : DoText(cp, pb); break; case PDU_RESULT: sts = (cp->denyOps & PMCD_OP_STORE) ? PM_ERR_PERMISSION : DoStore(cp, pb); break; case PDU_PMNS_IDS: sts = (cp->denyOps & PMCD_OP_FETCH) ? PM_ERR_PERMISSION : DoPMNSIDs(cp, pb); break; case PDU_PMNS_NAMES: sts = (cp->denyOps & PMCD_OP_FETCH) ? PM_ERR_PERMISSION : DoPMNSNames(cp, pb); break; case PDU_PMNS_CHILD: sts = (cp->denyOps & PMCD_OP_FETCH) ? PM_ERR_PERMISSION : DoPMNSChild(cp, pb); break; case PDU_PMNS_TRAVERSE: sts = (cp->denyOps & PMCD_OP_FETCH) ? PM_ERR_PERMISSION : DoPMNSTraverse(cp, pb); break; case PDU_CREDS: sts = DoCreds(cp, pb); break; default: sts = PM_ERR_IPC; } if (sts < 0) { if (pmDebug & DBG_TRACE_APPL0) fprintf(stderr, "PDU: %s client[%d]: %s\n", __pmPDUTypeStr(php->type), i, pmErrStr(sts)); /* Make sure client still alive before sending. */ if (cp->status.connected) { pmcd_trace(TR_XMIT_PDU, cp->fd, PDU_ERROR, sts); sts = __pmSendError(cp->fd, FROM_ANON, sts); if (sts < 0) __pmNotifyErr(LOG_ERR, "HandleClientInput: " "error sending Error PDU to client[%d] %s\n", i, pmErrStr(sts)); } } if (pinpdu > 0) __pmUnpinPDUBuf(pb); } }