static int negotiate_proxy(int fd, const char *hostname, int port) { char buf[MY_BUFLEN]; char *bp; int ok = 0; /* * version negotiation (converse to pmproxy logic) * __pmSend my client version message * __pmRecv server version message * __pmSend hostname and port */ if (__pmSend(fd, MY_VERSION, strlen(MY_VERSION), 0) != strlen(MY_VERSION)) { char errmsg[PM_MAXERRMSGLEN]; __pmNotifyErr(LOG_WARNING, "__pmConnectPMCD: send version string to pmproxy failed: %s\n", pmErrStr_r(-neterror(), errmsg, sizeof(errmsg))); return PM_ERR_IPC; } for (bp = buf; bp < &buf[MY_BUFLEN]; bp++) { if (__pmRecv(fd, bp, 1, 0) != 1) { *bp = '\0'; bp = &buf[MY_BUFLEN]; break; } if (*bp == '\n' || *bp == '\r') { *bp = '\0'; break; } } if (bp < &buf[MY_BUFLEN]) { if (strcmp(buf, "pmproxy-server 1") == 0) ok = 1; } if (!ok) { __pmNotifyErr(LOG_WARNING, "__pmConnectPMCD: bad version string from pmproxy: \"%s\"\n", buf); return PM_ERR_IPC; } snprintf(buf, sizeof(buf), "%s %d\n", hostname, port); if (__pmSend(fd, buf, strlen(buf), 0) != strlen(buf)) { char errmsg[PM_MAXERRMSGLEN]; __pmNotifyErr(LOG_WARNING, "__pmConnectPMCD: send hostname+port string to pmproxy failed: %s'\n", pmErrStr_r(-neterror(), errmsg, sizeof(errmsg))); return PM_ERR_IPC; } return ok; }
int __pmXmitPDU(int fd, __pmPDU *pdubuf) { int socketipc = __pmSocketIPC(fd); int off = 0; int len; __pmPDUHdr *php = (__pmPDUHdr *)pdubuf; __pmIgnoreSignalPIPE(); #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_PDU) { int j; char *p; int jend = PM_PDU_SIZE(php->len); char strbuf[20]; /* clear the padding bytes, lest they contain garbage */ p = (char *)pdubuf + php->len; while (p < (char *)pdubuf + jend*sizeof(__pmPDU)) *p++ = '~'; /* buffer end */ if (mypid == -1) mypid = (int)getpid(); fprintf(stderr, "[%d]pmXmitPDU: %s fd=%d len=%d", mypid, __pmPDUTypeStr_r(php->type, strbuf, sizeof(strbuf)), fd, php->len); for (j = 0; j < jend; j++) { if ((j % 8) == 0) fprintf(stderr, "\n%03d: ", j); fprintf(stderr, "%8x ", pdubuf[j]); } putc('\n', stderr); } #endif len = php->len; php->len = htonl(php->len); php->from = htonl(php->from); php->type = htonl(php->type); while (off < len) { char *p = (char *)pdubuf; int n; p += off; n = socketipc ? __pmSend(fd, p, len-off, 0) : write(fd, p, len-off); if (n < 0) break; off += n; } php->len = ntohl(php->len); php->from = ntohl(php->from); php->type = ntohl(php->type); if (off != len) { if (socketipc) { if (__pmSocketClosed()) return PM_ERR_IPC; return neterror() ? -neterror() : PM_ERR_IPC; } return oserror() ? -oserror() : PM_ERR_IPC; } __pmOverrideLastFd(fd); if (php->type >= PDU_START && php->type <= PDU_FINISH) __pmPDUCntOut[php->type-PDU_START]++; return off; }
static int http_client_get(http_client *cp) { char buf[BUFSIZ]; char host[MAXHOSTNAMELEN]; char *bp = &buf[0], *url = cp->url; http_parser_url *up = &cp->parser_url; const char *path, *agent, *version, *protocol; size_t hostlen, len = 0, length; int sts; /* sanitize request parameters */ if ((agent = cp->user_agent) == NULL) agent = pmProgname; if ((version = cp->agent_vers) == NULL) version = "1.0"; if ((path = url + up->field_data[UF_PATH].off) == NULL || up->field_data[UF_PATH].off == 0 || strchr(path, '/') == NULL){ path = "/"; /* assume root-level request */ } hostlen = up->field_data[UF_HOST].len; strncpy(host, url + up->field_data[UF_HOST].off, hostlen); host[hostlen] = '\0'; // strncpy(host, "localhost", sizeof("localhost")); // host[sizeof("localhost")] = '\0'; // strncpy(path, "/containers/8d70f8a47a6b6e515fb8e40d31da7928de70e883c235ba16b132e6a3b4f8267d/json", sizeof("/containers/8d70f8a47a6b6e515fb8e40d31da7928de70e883c235ba16b132e6a3b4f8267d/json")); // __pmNotifyErr(LOG_DEBUG, "hit here: %s", cp->type_buffer); protocol = url + up->field_data[UF_SCHEMA].off; length = up->field_data[UF_SCHEMA].len; /* prepare and send a GET request */ if (length == sizeof(HTTP)-1 && strncmp(protocol, UNIX, length) == 0) { len += snprintf(bp+len, sizeof(buf)-len, "GET %s HTTP/%s\r\n", cp->type_buffer, http_versionstr(cp->http_version)); len += snprintf(bp+len, sizeof(buf)-len, "Host: %s\r\n", "localhost"); } else { len += snprintf(bp+len, sizeof(buf)-len, "GET %s HTTP/%s\r\n", path, http_versionstr(cp->http_version)); len += snprintf(bp+len, sizeof(buf)-len, "Host: %s\r\n", host); } len += snprintf(bp+len, sizeof(buf)-len, "User-Agent: %s/%s\r\n", agent, version); /* establish persistent connections (default in HTTP/1.1 onward) */ if (cp->http_version < PV_HTTP_1_1) len += snprintf(bp+len, sizeof(buf)-len, "Connection: keep-alive\r\n"); len += snprintf(bp+len, sizeof(buf)-len, "\r\n"); buf[BUFSIZ-1] = '\0'; if ((pmDebug & DBG_TRACE_HTTP) && (pmDebug & DBG_TRACE_DESPERATE)) fprintf(stderr, "Sending HTTP request:\n\n%s\n", buf); if ((sts = __pmSend(cp->fd, buf, len, 0)) < 0) { if (__pmSocketClosed()) { sts = 1; } else { cp->error_code = sts; sts = -1; } http_client_disconnect(cp); } else { sts = 0; } if (pmDebug & DBG_TRACE_HTTP) fprintf(stderr, "http_client_get sts=%d\n", sts); return sts; }
/* 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]; }