void kore_accesslog(struct http_request *req) { struct kore_log_packet logpacket; logpacket.addrtype = req->owner->addrtype; if (logpacket.addrtype == AF_INET) { memcpy(logpacket.addr, &(req->owner->addr.ipv4.sin_addr), sizeof(req->owner->addr.ipv4.sin_addr)); } else { memcpy(logpacket.addr, &(req->owner->addr.ipv6.sin6_addr), sizeof(req->owner->addr.ipv6.sin6_addr)); } logpacket.status = req->status; logpacket.method = req->method; logpacket.worker_id = worker->id; logpacket.worker_cpu = worker->cpu; logpacket.time_req = req->total; if (kore_strlcpy(logpacket.host, req->host, sizeof(logpacket.host)) >= sizeof(logpacket.host)) kore_log(LOG_NOTICE, "kore_accesslog: host truncated"); if (kore_strlcpy(logpacket.path, req->path, sizeof(logpacket.path)) >= sizeof(logpacket.path)) kore_log(LOG_NOTICE, "kore_accesslog: path truncated"); if (req->agent != NULL) { if (kore_strlcpy(logpacket.agent, req->agent, sizeof(logpacket.agent)) >= sizeof(logpacket.agent)) kore_log(LOG_NOTICE, "kore_accesslog: agent truncated"); } else { (void)kore_strlcpy(logpacket.agent, "unknown", sizeof(logpacket.agent)); } #if !defined(KORE_NO_TLS) memset(logpacket.cn, '\0', sizeof(logpacket.cn)); if (req->owner->cert != NULL) { if (X509_GET_CN(req->owner->cert, logpacket.cn, sizeof(logpacket.cn)) == -1) { kore_log(LOG_WARNING, "client cert without a CN?"); } } #endif kore_msg_send(KORE_MSG_PARENT, KORE_MSG_ACCESSLOG, &logpacket, sizeof(logpacket)); }
void kore_accesslog(struct http_request *req) { ssize_t len; struct kore_log_packet logpacket; logpacket.addrtype = req->owner->addrtype; if (logpacket.addrtype == AF_INET) { memcpy(logpacket.addr, &(req->owner->addr.ipv4.sin_addr), sizeof(req->owner->addr.ipv4.sin_addr)); } else { memcpy(logpacket.addr, &(req->owner->addr.ipv6.sin6_addr), sizeof(req->owner->addr.ipv6.sin6_addr)); } logpacket.status = req->status; logpacket.method = req->method; logpacket.worker_id = worker->id; logpacket.worker_cpu = worker->cpu; logpacket.time_req = req->total; kore_strlcpy(logpacket.host, req->host, sizeof(logpacket.host)); kore_strlcpy(logpacket.path, req->path, sizeof(logpacket.path)); if (req->agent != NULL) { kore_strlcpy(logpacket.agent, req->agent, sizeof(logpacket.agent)); } else { kore_strlcpy(logpacket.agent, "unknown", sizeof(logpacket.agent)); } memset(logpacket.cn, '\0', sizeof(logpacket.cn)); #if !defined(KORE_BENCHMARK) if (req->owner->cert != NULL) { if (X509_GET_CN(req->owner->cert, logpacket.cn, sizeof(logpacket.cn)) == -1) { kore_log(LOG_WARNING, "client cert without a CN?"); } } #endif len = send(accesslog_fd[1], &logpacket, sizeof(logpacket), 0); if (len == -1) { kore_log(LOG_WARNING, "kore_accesslog(): send(): %s", errno_s); } else if (len != sizeof(logpacket)) { kore_log(LOG_WARNING, "short accesslog packet sent"); } }
void kore_accesslog(struct http_request *req) { struct timespec ts; struct tm *tm; u_int64_t now; struct kore_alog_header *hdr; size_t avail; time_t curtime; int len, attempts; char addr[INET6_ADDRSTRLEN]; const char *ptr, *method, *cn, *referer; switch (req->method) { case HTTP_METHOD_GET: method = "GET"; break; case HTTP_METHOD_POST: method = "POST"; break; case HTTP_METHOD_PUT: method = "PUT"; break; case HTTP_METHOD_DELETE: method = "DELETE"; break; case HTTP_METHOD_HEAD: method = "HEAD"; break; case HTTP_METHOD_PATCH: method = "PATCH"; break; default: method = "UNKNOWN"; break; } if (req->referer != NULL) referer = req->referer; else referer = "-"; cn = "-"; #if !defined(KORE_NO_TLS) if (req->owner->cert != NULL) { if (X509_GET_CN(req->owner->cert, cnbuf, sizeof(cnbuf)) != -1) cn = cnbuf; } #endif switch (req->owner->family) { case AF_INET: ptr = inet_ntop(req->owner->family, &(req->owner->addr.ipv4.sin_addr), addr, sizeof(addr)); break; case AF_INET6: ptr = inet_ntop(req->owner->family, &(req->owner->addr.ipv6.sin6_addr), addr, sizeof(addr)); break; case AF_UNIX: ptr = NULL; break; default: fatal("unknown family %d", req->owner->family); } if (ptr == NULL) { addr[0] = '-'; addr[1] = '\0'; } now = kore_time_ms(); if ((now - time_cache) >= 1000) { time(&curtime); tm = localtime(&curtime); (void)strftime(tbuf, sizeof(tbuf), "%d/%b/%Y:%H:%M:%S %z", tm); time_cache = now; } attempts = 0; ts.tv_sec = 0; ts.tv_nsec = 1000000; for (;;) { if (attempts++ > 1000) { if (getppid() == 1) { if (kill(worker->pid, SIGQUIT) == -1) fatal("failed to shutdown"); return; } attempts = 0; } accesslog_lock(worker); avail = KORE_ACCESSLOG_BUFLEN - worker->lb.offset; if (avail < sizeof(*hdr) + LOG_ENTRY_MINSIZE_GUESS) { accesslog_unlock(worker); nanosleep(&ts, NULL); continue; } hdr = (struct kore_alog_header *) (worker->lb.buf + worker->lb.offset); worker->lb.offset += sizeof(*hdr); len = snprintf(worker->lb.buf + worker->lb.offset, avail, "%s - %s [%s] \"%s %s HTTP/1.1\" %d %zu \"%s\" \"%s\"\n", addr, cn, tbuf, method, req->path, req->status, req->content_length, referer, req->agent); if (len == -1) fatal("failed to create log entry"); if ((size_t)len >= avail) { worker->lb.offset -= sizeof(*hdr); accesslog_unlock(worker); nanosleep(&ts, NULL); continue; } if ((size_t)len > USHRT_MAX) { kore_log(LOG_WARNING, "log entry length exceeds limit (%d)", len); worker->lb.offset -= sizeof(*hdr); break; } hdr->loglen = len; hdr->domain = req->hdlr->dom->id; worker->lb.offset += (size_t)len; break; } accesslog_unlock(worker); }