static void nvlist_report_missing(int type, const char *name) { PJDLOG_ABORT("Element '%s' of type %s doesn't exist.", name, nvpair_type_string(type)); }
static void adreq_fill(struct adreq *adreq, uint8_t cmd, const unsigned char *data, size_t size) { static uint64_t seq = 1; PJDLOG_ASSERT(size <= ADIST_BUF_SIZE); switch (cmd) { case ADIST_CMD_OPEN: case ADIST_CMD_CLOSE: PJDLOG_ASSERT(data != NULL && size == 0); size = strlen(data) + 1; break; case ADIST_CMD_APPEND: PJDLOG_ASSERT(data != NULL && size > 0); break; case ADIST_CMD_KEEPALIVE: case ADIST_CMD_ERROR: PJDLOG_ASSERT(data == NULL && size == 0); break; default: PJDLOG_ABORT("Invalid command (%hhu).", cmd); } adreq->adr_cmd = cmd; adreq->adr_seq = seq++; adreq->adr_datasize = size; /* Don't copy if data is already in out buffer. */ if (data != NULL && data != adreq->adr_data) bcopy(data, adreq->adr_data, size); }
static void tls_remote_address(const void *ctx, char *addr, size_t size) { const struct tls_ctx *tlsctx = ctx; PJDLOG_ASSERT(tlsctx != NULL); PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC); PJDLOG_ASSERT(tlsctx->tls_wait_called); switch (tlsctx->tls_side) { case TLS_SIDE_CLIENT: PJDLOG_ASSERT(tlsctx->tls_sock != NULL); PJDLOG_VERIFY(strlcpy(addr, "tls://N/A", size) < size); break; case TLS_SIDE_SERVER_WORK: PJDLOG_ASSERT(tlsctx->tls_sock != NULL); PJDLOG_VERIFY(strlcpy(addr, tlsctx->tls_raddr, size) < size); break; case TLS_SIDE_SERVER_LISTEN: PJDLOG_ASSERT(tlsctx->tls_tcp != NULL); proto_remote_address(tlsctx->tls_tcp, addr, size); PJDLOG_ASSERT(strncmp(addr, "tcp://", 6) == 0); /* Replace tcp:// prefix with tls:// */ bcopy("tls://", addr, 6); break; default: PJDLOG_ABORT("Invalid side (%d).", tlsctx->tls_side); } }
/* * Dump content of nvlist. */ static void nvlist_xdump(const nvlist_t *nvl, int fd, int level) { nvpair_t *nvp; PJDLOG_ASSERT(level < 3); if (nvlist_error(nvl) != 0) { dprintf(fd, "%*serror: %d\n", level * 4, "", nvlist_error(nvl)); return; } for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; nvp = nvlist_next_nvpair(nvl, nvp)) { dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp), nvpair_type_string(nvpair_type(nvp))); switch (nvpair_type(nvp)) { case NV_TYPE_NULL: dprintf(fd, " null\n"); break; case NV_TYPE_BOOL: dprintf(fd, " %s\n", nvpair_get_bool(nvp) ? "TRUE" : "FALSE"); break; case NV_TYPE_NUMBER: dprintf(fd, " %ju (%jd) (0x%jx)\n", (uintmax_t)nvpair_get_number(nvp), (intmax_t)nvpair_get_number(nvp), (uintmax_t)nvpair_get_number(nvp)); break; case NV_TYPE_STRING: dprintf(fd, " [%s]\n", nvpair_get_string(nvp)); break; case NV_TYPE_NVLIST: dprintf(fd, "\n"); nvlist_xdump(nvpair_get_nvlist(nvp), fd, level + 1); break; case NV_TYPE_DESCRIPTOR: dprintf(fd, " %d\n", nvpair_get_descriptor(nvp)); break; case NV_TYPE_BINARY: { const unsigned char *binary; unsigned int ii; size_t size; binary = nvpair_get_binary(nvp, &size); dprintf(fd, " %zu ", size); for (ii = 0; ii < size; ii++) dprintf(fd, "%02hhx", binary[ii]); dprintf(fd, "\n"); break; } default: PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp)); } } }
static void nvlist_report_missing(int type, const char *namefmt, va_list nameap) { char *name; vasprintf(&name, namefmt, nameap); PJDLOG_ABORT("Element '%s' of type %s doesn't exist.", name != NULL ? name : "N/A", nvpair_type_string(type)); }
/* * Thread sends requests back to primary node. */ static void * send_thread(void *arg) { struct hast_resource *res = arg; struct nv *nvout; struct hio *hio; void *data; size_t length; for (;;) { pjdlog_debug(2, "send: Taking request."); QUEUE_TAKE(send, hio); reqlog(LOG_DEBUG, 2, -1, hio, "send: (%p) Got request: ", hio); nvout = nv_alloc(); /* Copy sequence number. */ nv_add_uint64(nvout, hio->hio_seq, "seq"); switch (hio->hio_cmd) { case HIO_READ: if (hio->hio_error == 0) { data = hio->hio_data; length = hio->hio_length; break; } /* * We send no data in case of an error. */ /* FALLTHROUGH */ case HIO_DELETE: case HIO_FLUSH: case HIO_WRITE: data = NULL; length = 0; break; default: PJDLOG_ABORT("Unexpected command (cmd=%hhu).", hio->hio_cmd); } if (hio->hio_error != 0) nv_add_int16(nvout, hio->hio_error, "error"); if (hast_proto_send(res, res->hr_remoteout, nvout, data, length) < 0) { secondary_exit(EX_TEMPFAIL, "Unable to send reply."); } nv_free(nvout); pjdlog_debug(2, "send: (%p) Moving request to the free queue.", hio); hio_clear(hio); QUEUE_INSERT(free, hio); } /* NOTREACHED */ return (NULL); }
static void casper_message(const cap_channel_t *capcas, struct service *service) { const char *cmd; nvlist_t *nvl; nvl = cap_recv_nvlist(capcas); if (nvl == NULL) pjdlog_exit(1, "Unable to receive message from Casper"); cmd = nvlist_get_string(nvl, "cmd"); if (strcmp(cmd, "connection") == 0) casper_message_connection(service, nvl); else PJDLOG_ABORT("Unknown command from Casper: %s.", cmd); }
nvpair_t * nvpair_clone(const nvpair_t *nvp) { nvpair_t *newnvp; const char *name; const void *data; size_t datasize; NVPAIR_ASSERT(nvp); name = nvpair_name(nvp); switch (nvpair_type(nvp)) { case NV_TYPE_NULL: newnvp = nvpair_create_null(name); break; case NV_TYPE_BOOL: newnvp = nvpair_create_bool(name, nvpair_get_bool(nvp)); break; case NV_TYPE_NUMBER: newnvp = nvpair_create_number(name, nvpair_get_number(nvp)); break; case NV_TYPE_STRING: newnvp = nvpair_create_string(name, nvpair_get_string(nvp)); break; case NV_TYPE_NVLIST: newnvp = nvpair_create_nvlist(name, nvpair_get_nvlist(nvp)); break; #ifndef _KERNEL case NV_TYPE_DESCRIPTOR: newnvp = nvpair_create_descriptor(name, nvpair_get_descriptor(nvp)); break; #endif case NV_TYPE_BINARY: data = nvpair_get_binary(nvp, &datasize); newnvp = nvpair_create_binary(name, data, datasize); break; default: PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp)); } return (newnvp); }
static int sp_descriptor(const void *ctx) { const struct sp_ctx *spctx = ctx; PJDLOG_ASSERT(spctx != NULL); PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); PJDLOG_ASSERT(spctx->sp_side == SP_SIDE_CLIENT || spctx->sp_side == SP_SIDE_SERVER); switch (spctx->sp_side) { case SP_SIDE_CLIENT: PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); return (spctx->sp_fd[0]); case SP_SIDE_SERVER: PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); return (spctx->sp_fd[1]); } PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); }
static bool pwd_allowed_user(const nvlist_t *limits, const char *uname, uid_t uid) { const char *name; void *cookie; int type; if (limits == NULL) return (true); /* * If no limit was set on allowed users, then all users are allowed. */ if (!nvlist_exists_nvlist(limits, "users")) return (true); limits = nvlist_get_nvlist(limits, "users"); cookie = NULL; while ((name = nvlist_next(limits, &type, &cookie)) != NULL) { switch (type) { case NV_TYPE_NUMBER: if (uid != (uid_t)-1 && nvlist_get_number(limits, name) == (uint64_t)uid) { return (true); } break; case NV_TYPE_STRING: if (uname != NULL && strcmp(nvlist_get_string(limits, name), uname) == 0) { return (true); } break; default: PJDLOG_ABORT("Unexpected type %d.", type); } } return (false); }
static int tls_descriptor(const void *ctx) { const struct tls_ctx *tlsctx = ctx; PJDLOG_ASSERT(tlsctx != NULL); PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC); switch (tlsctx->tls_side) { case TLS_SIDE_CLIENT: case TLS_SIDE_SERVER_WORK: PJDLOG_ASSERT(tlsctx->tls_sock != NULL); return (proto_descriptor(tlsctx->tls_sock)); case TLS_SIDE_SERVER_LISTEN: PJDLOG_ASSERT(tlsctx->tls_tcp != NULL); return (proto_descriptor(tlsctx->tls_tcp)); default: PJDLOG_ABORT("Invalid side (%d).", tlsctx->tls_side); } }
static int sp_send(void *ctx, const unsigned char *data, size_t size, int fd) { struct sp_ctx *spctx = ctx; int sock; PJDLOG_ASSERT(spctx != NULL); PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); switch (spctx->sp_side) { case SP_SIDE_UNDEF: /* * If the first operation done by the caller is proto_send(), * we assume this is the client. */ /* FALLTHROUGH */ spctx->sp_side = SP_SIDE_CLIENT; /* Close other end. */ close(spctx->sp_fd[1]); spctx->sp_fd[1] = -1; case SP_SIDE_CLIENT: PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); sock = spctx->sp_fd[0]; break; case SP_SIDE_SERVER: PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); sock = spctx->sp_fd[1]; break; default: PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); } /* Someone is just trying to decide about side. */ if (data == NULL) return (0); return (proto_common_send(sock, data, size, fd)); }
static void sp_close(void *ctx) { struct sp_ctx *spctx = ctx; PJDLOG_ASSERT(spctx != NULL); PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); switch (spctx->sp_side) { case SP_SIDE_UNDEF: PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); close(spctx->sp_fd[0]); spctx->sp_fd[0] = -1; PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); close(spctx->sp_fd[1]); spctx->sp_fd[1] = -1; break; case SP_SIDE_CLIENT: PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); close(spctx->sp_fd[0]); spctx->sp_fd[0] = -1; PJDLOG_ASSERT(spctx->sp_fd[1] == -1); break; case SP_SIDE_SERVER: PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); close(spctx->sp_fd[1]); spctx->sp_fd[1] = -1; PJDLOG_ASSERT(spctx->sp_fd[0] == -1); break; default: PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); } spctx->sp_magic = 0; free(spctx); }
/* * Validate correctness of the entire nv structure and all its elements. * If extrap is not NULL, store number of extra bytes at the end of the buffer. */ int nv_validate(struct nv *nv, size_t *extrap) { struct nvhdr *nvh; unsigned char *data, *ptr; size_t dsize, size, vsize; int error; if (nv == NULL) { errno = ENOMEM; return (-1); } NV_CHECK(nv); PJDLOG_ASSERT(nv->nv_error == 0); /* TODO: Check that names are unique? */ error = 0; ptr = ebuf_data(nv->nv_ebuf, &size); while (size > 0) { /* * Zeros at the end of the buffer are acceptable. */ if (ptr[0] == '\0') break; /* * Minimum size at this point is size of nvhdr structure, one * character long name plus terminating '\0'. */ if (size < sizeof(*nvh) + 2) { error = EINVAL; break; } nvh = (struct nvhdr *)ptr; if (size < NVH_HSIZE(nvh)) { error = EINVAL; break; } if (nvh->nvh_name[nvh->nvh_namesize - 1] != '\0') { error = EINVAL; break; } if (strlen(nvh->nvh_name) != (size_t)(nvh->nvh_namesize - 1)) { error = EINVAL; break; } if ((nvh->nvh_type & NV_TYPE_MASK) < NV_TYPE_FIRST || (nvh->nvh_type & NV_TYPE_MASK) > NV_TYPE_LAST) { error = EINVAL; break; } dsize = NVH_DSIZE(nvh); if (dsize == 0) { error = EINVAL; break; } if (size < NVH_SIZE(nvh)) { error = EINVAL; break; } vsize = 0; switch (nvh->nvh_type & NV_TYPE_MASK) { case NV_TYPE_INT8: case NV_TYPE_UINT8: if (vsize == 0) vsize = 1; /* FALLTHROUGH */ case NV_TYPE_INT16: case NV_TYPE_UINT16: if (vsize == 0) vsize = 2; /* FALLTHROUGH */ case NV_TYPE_INT32: case NV_TYPE_UINT32: if (vsize == 0) vsize = 4; /* FALLTHROUGH */ case NV_TYPE_INT64: case NV_TYPE_UINT64: if (vsize == 0) vsize = 8; if (dsize != vsize) { error = EINVAL; break; } break; case NV_TYPE_INT8_ARRAY: case NV_TYPE_UINT8_ARRAY: break; case NV_TYPE_INT16_ARRAY: case NV_TYPE_UINT16_ARRAY: if (vsize == 0) vsize = 2; /* FALLTHROUGH */ case NV_TYPE_INT32_ARRAY: case NV_TYPE_UINT32_ARRAY: if (vsize == 0) vsize = 4; /* FALLTHROUGH */ case NV_TYPE_INT64_ARRAY: case NV_TYPE_UINT64_ARRAY: if (vsize == 0) vsize = 8; if ((dsize % vsize) != 0) { error = EINVAL; break; } break; case NV_TYPE_STRING: data = NVH_DATA(nvh); if (data[dsize - 1] != '\0') { error = EINVAL; break; } if (strlen((char *)data) != dsize - 1) { error = EINVAL; break; } break; default: PJDLOG_ABORT("invalid condition"); } if (error != 0) break; ptr += NVH_SIZE(nvh); size -= NVH_SIZE(nvh); } if (error != 0) { errno = error; if (nv->nv_error == 0) nv->nv_error = error; return (-1); } if (extrap != NULL) *extrap = size; return (0); }
static void nv_swap(struct nvhdr *nvh, bool tohost) { unsigned char *data, *end, *p; size_t vsize; data = NVH_DATA(nvh); if (tohost) { if ((nvh->nvh_type & NV_ORDER_MASK) == NV_ORDER_HOST) return; nvh->nvh_dsize = le32toh(nvh->nvh_dsize); end = data + nvh->nvh_dsize; nvh->nvh_type &= ~NV_ORDER_MASK; nvh->nvh_type |= NV_ORDER_HOST; } else { if ((nvh->nvh_type & NV_ORDER_MASK) == NV_ORDER_NETWORK) return; end = data + nvh->nvh_dsize; nvh->nvh_dsize = htole32(nvh->nvh_dsize); nvh->nvh_type &= ~NV_ORDER_MASK; nvh->nvh_type |= NV_ORDER_NETWORK; } vsize = 0; switch (nvh->nvh_type & NV_TYPE_MASK) { case NV_TYPE_INT8: case NV_TYPE_UINT8: case NV_TYPE_INT8_ARRAY: case NV_TYPE_UINT8_ARRAY: break; case NV_TYPE_INT16: case NV_TYPE_UINT16: case NV_TYPE_INT16_ARRAY: case NV_TYPE_UINT16_ARRAY: if (vsize == 0) vsize = 2; /* FALLTHROUGH */ case NV_TYPE_INT32: case NV_TYPE_UINT32: case NV_TYPE_INT32_ARRAY: case NV_TYPE_UINT32_ARRAY: if (vsize == 0) vsize = 4; /* FALLTHROUGH */ case NV_TYPE_INT64: case NV_TYPE_UINT64: case NV_TYPE_INT64_ARRAY: case NV_TYPE_UINT64_ARRAY: if (vsize == 0) vsize = 8; for (p = data; p < end; p += vsize) { if (tohost) { switch (vsize) { case 2: *(uint16_t *)(void *)p = le16toh(*(uint16_t *)(void *)p); break; case 4: *(uint32_t *)(void *)p = le32toh(*(uint32_t *)(void *)p); break; case 8: *(uint64_t *)(void *)p = le64toh(*(uint64_t *)(void *)p); break; default: PJDLOG_ABORT("invalid condition"); } } else { switch (vsize) { case 2: *(uint16_t *)(void *)p = htole16(*(uint16_t *)(void *)p); break; case 4: *(uint32_t *)(void *)p = htole32(*(uint32_t *)(void *)p); break; case 8: *(uint64_t *)(void *)p = htole64(*(uint64_t *)(void *)p); break; default: PJDLOG_ABORT("invalid condition"); } } } break; case NV_TYPE_STRING: break; default: PJDLOG_ABORT("unrecognized type"); } }
/* * Thread reads from or writes to local component and also handles DELETE and * FLUSH requests. */ static void * disk_thread(void *arg) { struct hast_resource *res = arg; struct hio *hio; ssize_t ret; bool clear_activemap, logerror; clear_activemap = true; for (;;) { pjdlog_debug(2, "disk: Taking request."); QUEUE_TAKE(disk, hio); while (clear_activemap) { unsigned char *map; size_t mapsize; /* * When first request is received, it means that primary * already received our activemap, merged it and stored * locally. We can now safely clear our activemap. */ mapsize = activemap_calc_ondisk_size(res->hr_local_mediasize - METADATA_SIZE, res->hr_extentsize, res->hr_local_sectorsize); map = calloc(1, mapsize); if (map == NULL) { pjdlog_warning("Unable to allocate memory to clear local activemap."); break; } if (pwrite(res->hr_localfd, map, mapsize, METADATA_SIZE) != (ssize_t)mapsize) { pjdlog_errno(LOG_WARNING, "Unable to store cleared activemap"); free(map); break; } free(map); clear_activemap = false; pjdlog_debug(1, "Local activemap cleared."); break; } reqlog(LOG_DEBUG, 2, -1, hio, "disk: (%p) Got request: ", hio); logerror = true; /* Handle the actual request. */ switch (hio->hio_cmd) { case HIO_READ: ret = pread(res->hr_localfd, hio->hio_data, hio->hio_length, hio->hio_offset + res->hr_localoff); if (ret < 0) hio->hio_error = errno; else if (ret != (int64_t)hio->hio_length) hio->hio_error = EIO; else hio->hio_error = 0; break; case HIO_WRITE: ret = pwrite(res->hr_localfd, hio->hio_data, hio->hio_length, hio->hio_offset + res->hr_localoff); if (ret < 0) hio->hio_error = errno; else if (ret != (int64_t)hio->hio_length) hio->hio_error = EIO; else hio->hio_error = 0; break; case HIO_DELETE: ret = g_delete(res->hr_localfd, hio->hio_offset + res->hr_localoff, hio->hio_length); if (ret < 0) hio->hio_error = errno; else hio->hio_error = 0; break; case HIO_FLUSH: if (!res->hr_localflush) { ret = -1; hio->hio_error = EOPNOTSUPP; logerror = false; break; } ret = g_flush(res->hr_localfd); if (ret < 0) { if (errno == EOPNOTSUPP) res->hr_localflush = false; hio->hio_error = errno; } else { hio->hio_error = 0; } break; default: PJDLOG_ABORT("Unexpected command (cmd=%hhu).", hio->hio_cmd); } if (logerror && hio->hio_error != 0) { reqlog(LOG_ERR, 0, hio->hio_error, hio, "Request failed: "); } pjdlog_debug(2, "disk: (%p) Moving request to the send queue.", hio); QUEUE_INSERT(send, hio); } /* NOTREACHED */ return (NULL); }
/* * Dump content of nvlist. */ void nvlist_dump(const nvlist_t *nvl, int fd) { const nvlist_t *tmpnvl; nvpair_t *nvp, *tmpnvp; void *cookie; int level; level = 0; if (nvlist_dump_error_check(nvl, fd, level)) return; nvp = nvlist_first_nvpair(nvl); while (nvp != NULL) { dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp), nvpair_type_string(nvpair_type(nvp))); switch (nvpair_type(nvp)) { case NV_TYPE_NULL: dprintf(fd, " null\n"); break; case NV_TYPE_BOOL: dprintf(fd, " %s\n", nvpair_get_bool(nvp) ? "TRUE" : "FALSE"); break; case NV_TYPE_NUMBER: dprintf(fd, " %ju (%jd) (0x%jx)\n", (uintmax_t)nvpair_get_number(nvp), (intmax_t)nvpair_get_number(nvp), (uintmax_t)nvpair_get_number(nvp)); break; case NV_TYPE_STRING: dprintf(fd, " [%s]\n", nvpair_get_string(nvp)); break; case NV_TYPE_NVLIST: dprintf(fd, "\n"); tmpnvl = nvpair_get_nvlist(nvp); if (nvlist_dump_error_check(tmpnvl, fd, level + 1)) break; tmpnvp = nvlist_first_nvpair(tmpnvl); if (tmpnvp != NULL) { nvl = tmpnvl; nvp = tmpnvp; level++; continue; } break; case NV_TYPE_DESCRIPTOR: dprintf(fd, " %d\n", nvpair_get_descriptor(nvp)); break; case NV_TYPE_BINARY: { const unsigned char *binary; unsigned int ii; size_t size; binary = nvpair_get_binary(nvp, &size); dprintf(fd, " %zu ", size); for (ii = 0; ii < size; ii++) dprintf(fd, "%02hhx", binary[ii]); dprintf(fd, "\n"); break; } case NV_TYPE_BOOL_ARRAY: { const bool *value; unsigned int ii; size_t nitems; value = nvpair_get_bool_array(nvp, &nitems); dprintf(fd, " [ "); for (ii = 0; ii < nitems; ii++) { dprintf(fd, "%s", value[ii] ? "TRUE" : "FALSE"); if (ii != nitems - 1) dprintf(fd, ", "); } dprintf(fd, " ]\n"); break; } case NV_TYPE_STRING_ARRAY: { const char * const *value; unsigned int ii; size_t nitems; value = nvpair_get_string_array(nvp, &nitems); dprintf(fd, " [ "); for (ii = 0; ii < nitems; ii++) { if (value[ii] == NULL) dprintf(fd, "NULL"); else dprintf(fd, "\"%s\"", value[ii]); if (ii != nitems - 1) dprintf(fd, ", "); } dprintf(fd, " ]\n"); break; } case NV_TYPE_NUMBER_ARRAY: { const uint64_t *value; unsigned int ii; size_t nitems; value = nvpair_get_number_array(nvp, &nitems); dprintf(fd, " [ "); for (ii = 0; ii < nitems; ii++) { dprintf(fd, "%ju (%jd) (0x%jx)", value[ii], value[ii], value[ii]); if (ii != nitems - 1) dprintf(fd, ", "); } dprintf(fd, " ]\n"); break; } case NV_TYPE_DESCRIPTOR_ARRAY: { const int *value; unsigned int ii; size_t nitems; value = nvpair_get_descriptor_array(nvp, &nitems); dprintf(fd, " [ "); for (ii = 0; ii < nitems; ii++) { dprintf(fd, "%d", value[ii]); if (ii != nitems - 1) dprintf(fd, ", "); } dprintf(fd, " ]\n"); break; } case NV_TYPE_NVLIST_ARRAY: { const nvlist_t * const *value; unsigned int ii; size_t nitems; value = nvpair_get_nvlist_array(nvp, &nitems); dprintf(fd, " %zu\n", nitems); tmpnvl = NULL; tmpnvp = NULL; for (ii = 0; ii < nitems; ii++) { if (nvlist_dump_error_check(value[ii], fd, level + 1)) { break; } if (tmpnvl == NULL) { tmpnvp = nvlist_first_nvpair(value[ii]); if (tmpnvp != NULL) { tmpnvl = value[ii]; } else { dprintf(fd, "%*s,\n", (level + 1) * 4, ""); } } } if (tmpnvp != NULL) { nvl = tmpnvl; nvp = tmpnvp; level++; continue; } break; } default: PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp)); } while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) { do { cookie = NULL; if (nvlist_in_array(nvl)) dprintf(fd, "%*s,\n", level * 4, ""); nvl = nvlist_get_pararr(nvl, &cookie); if (nvl == NULL) return; if (nvlist_in_array(nvl) && cookie == NULL) { nvp = nvlist_first_nvpair(nvl); } else { nvp = cookie; level--; } } while (nvp == NULL); if (nvlist_in_array(nvl) && cookie == NULL) break; } } }
static void * nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep) { unsigned char *buf, *ptr; size_t left, size; const nvlist_t *tmpnvl; nvpair_t *nvp, *tmpnvp; void *cookie; NVLIST_ASSERT(nvl); if (nvl->nvl_error != 0) { ERRNO_SET(nvl->nvl_error); return (NULL); } size = nvlist_size(nvl); buf = nv_malloc(size); if (buf == NULL) return (NULL); ptr = buf; left = size; ptr = nvlist_pack_header(nvl, ptr, &left); nvp = nvlist_first_nvpair(nvl); while (nvp != NULL) { NVPAIR_ASSERT(nvp); nvpair_init_datasize(nvp); ptr = nvpair_pack_header(nvp, ptr, &left); if (ptr == NULL) goto fail; switch (nvpair_type(nvp)) { case NV_TYPE_NULL: ptr = nvpair_pack_null(nvp, ptr, &left); break; case NV_TYPE_BOOL: ptr = nvpair_pack_bool(nvp, ptr, &left); break; case NV_TYPE_NUMBER: ptr = nvpair_pack_number(nvp, ptr, &left); break; case NV_TYPE_STRING: ptr = nvpair_pack_string(nvp, ptr, &left); break; case NV_TYPE_NVLIST: tmpnvl = nvpair_get_nvlist(nvp); ptr = nvlist_pack_header(tmpnvl, ptr, &left); if (ptr == NULL) goto fail; tmpnvp = nvlist_first_nvpair(tmpnvl); if (tmpnvp != NULL) { nvl = tmpnvl; nvp = tmpnvp; continue; } ptr = nvpair_pack_nvlist_up(ptr, &left); break; #ifndef _KERNEL case NV_TYPE_DESCRIPTOR: ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, &left); break; case NV_TYPE_DESCRIPTOR_ARRAY: ptr = nvpair_pack_descriptor_array(nvp, ptr, fdidxp, &left); break; #endif case NV_TYPE_BINARY: ptr = nvpair_pack_binary(nvp, ptr, &left); break; case NV_TYPE_BOOL_ARRAY: ptr = nvpair_pack_bool_array(nvp, ptr, &left); break; case NV_TYPE_NUMBER_ARRAY: ptr = nvpair_pack_number_array(nvp, ptr, &left); break; case NV_TYPE_STRING_ARRAY: ptr = nvpair_pack_string_array(nvp, ptr, &left); break; case NV_TYPE_NVLIST_ARRAY: { const nvlist_t * const * value; size_t nitems; unsigned int ii; tmpnvl = NULL; value = nvpair_get_nvlist_array(nvp, &nitems); for (ii = 0; ii < nitems; ii++) { ptr = nvlist_pack_header(value[ii], ptr, &left); if (ptr == NULL) goto out; tmpnvp = nvlist_first_nvpair(value[ii]); if (tmpnvp != NULL) { tmpnvl = value[ii]; break; } ptr = nvpair_pack_nvlist_array_next(ptr, &left); if (ptr == NULL) goto out; } if (tmpnvl != NULL) { nvl = tmpnvl; nvp = tmpnvp; continue; } break; } default: PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp)); } if (ptr == NULL) goto fail; while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) { do { cookie = NULL; if (nvlist_in_array(nvl)) { ptr = nvpair_pack_nvlist_array_next(ptr, &left); if (ptr == NULL) goto fail; } nvl = nvlist_get_pararr(nvl, &cookie); if (nvl == NULL) goto out; if (nvlist_in_array(nvl) && cookie == NULL) { nvp = nvlist_first_nvpair(nvl); ptr = nvlist_pack_header(nvl, ptr, &left); if (ptr == NULL) goto fail; } else if (nvpair_type((nvpair_t *)cookie) != NV_TYPE_NVLIST_ARRAY) { ptr = nvpair_pack_nvlist_up(ptr, &left); if (ptr == NULL) goto fail; nvp = cookie; } else { nvp = cookie; } } while (nvp == NULL); if (nvlist_in_array(nvl) && cookie == NULL) break; } } out: if (sizep != NULL) *sizep = size; return (buf); fail: nv_free(buf); return (NULL); }
/* * Thread receives requests from the primary node. */ static void * recv_thread(void *arg) { struct hast_resource *res = arg; struct hio *hio; struct nv *nv; for (;;) { pjdlog_debug(2, "recv: Taking free request."); QUEUE_TAKE(free, hio); pjdlog_debug(2, "recv: (%p) Got request.", hio); if (hast_proto_recv_hdr(res->hr_remotein, &nv) < 0) { secondary_exit(EX_TEMPFAIL, "Unable to receive request header"); } if (requnpack(res, hio, nv) != 0) { nv_free(nv); pjdlog_debug(2, "recv: (%p) Moving request to the send queue.", hio); QUEUE_INSERT(send, hio); continue; } switch (hio->hio_cmd) { case HIO_READ: res->hr_stat_read++; break; case HIO_WRITE: res->hr_stat_write++; break; case HIO_DELETE: res->hr_stat_delete++; break; case HIO_FLUSH: res->hr_stat_flush++; break; case HIO_KEEPALIVE: break; default: PJDLOG_ABORT("Unexpected command (cmd=%hhu).", hio->hio_cmd); } reqlog(LOG_DEBUG, 2, -1, hio, "recv: (%p) Got request header: ", hio); if (hio->hio_cmd == HIO_KEEPALIVE) { nv_free(nv); pjdlog_debug(2, "recv: (%p) Moving request to the free queue.", hio); hio_clear(hio); QUEUE_INSERT(free, hio); continue; } else if (hio->hio_cmd == HIO_WRITE) { if (hast_proto_recv_data(res, res->hr_remotein, nv, hio->hio_data, MAXPHYS) < 0) { secondary_exit(EX_TEMPFAIL, "Unable to receive request data"); } } nv_free(nv); pjdlog_debug(2, "recv: (%p) Moving request to the disk queue.", hio); QUEUE_INSERT(disk, hio); } /* NOTREACHED */ return (NULL); }
static void * nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep) { unsigned char *buf, *ptr; size_t left, size; const nvlist_t *tmpnvl; nvpair_t *nvp, *tmpnvp; void *cookie; NVLIST_ASSERT(nvl); if (nvl->nvl_error != 0) { ERRNO_SET(nvl->nvl_error); return (NULL); } size = nvlist_size(nvl); buf = nv_malloc(size); if (buf == NULL) return (NULL); ptr = buf; left = size; ptr = nvlist_pack_header(nvl, ptr, &left); nvp = nvlist_first_nvpair(nvl); while (nvp != NULL) { NVPAIR_ASSERT(nvp); nvpair_init_datasize(nvp); ptr = nvpair_pack_header(nvp, ptr, &left); if (ptr == NULL) { nv_free(buf); return (NULL); } switch (nvpair_type(nvp)) { case NV_TYPE_NULL: ptr = nvpair_pack_null(nvp, ptr, &left); break; case NV_TYPE_BOOL: ptr = nvpair_pack_bool(nvp, ptr, &left); break; case NV_TYPE_NUMBER: ptr = nvpair_pack_number(nvp, ptr, &left); break; case NV_TYPE_STRING: ptr = nvpair_pack_string(nvp, ptr, &left); break; case NV_TYPE_NVLIST: tmpnvl = nvpair_get_nvlist(nvp); ptr = nvlist_pack_header(tmpnvl, ptr, &left); if (ptr == NULL) goto out; tmpnvp = nvlist_first_nvpair(tmpnvl); if (tmpnvp != NULL) { nvl = tmpnvl; nvp = tmpnvp; continue; } ptr = nvpair_pack_nvlist_up(ptr, &left); break; #ifndef _KERNEL case NV_TYPE_DESCRIPTOR: ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, &left); break; #endif case NV_TYPE_BINARY: ptr = nvpair_pack_binary(nvp, ptr, &left); break; default: PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp)); } if (ptr == NULL) { nv_free(buf); return (NULL); } while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) { cookie = NULL; nvl = nvlist_get_parent(nvl, &cookie); if (nvl == NULL) goto out; nvp = cookie; ptr = nvpair_pack_nvlist_up(ptr, &left); if (ptr == NULL) goto out; } } out: if (sizep != NULL) *sizep = size; return (buf); }
static nvlist_t * nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds, int flags) { const unsigned char *ptr; nvlist_t *nvl, *retnvl, *tmpnvl; nvpair_t *nvp; size_t left; bool isbe; PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0); left = size; ptr = buf; tmpnvl = NULL; nvl = retnvl = nvlist_create(0); if (nvl == NULL) goto failed; ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left); if (ptr == NULL) goto failed; if (nvl->nvl_flags != flags) { ERRNO_SET(EILSEQ); goto failed; } while (left > 0) { ptr = nvpair_unpack(isbe, ptr, &left, &nvp); if (ptr == NULL) goto failed; switch (nvpair_type(nvp)) { case NV_TYPE_NULL: ptr = nvpair_unpack_null(isbe, nvp, ptr, &left); break; case NV_TYPE_BOOL: ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left); break; case NV_TYPE_NUMBER: ptr = nvpair_unpack_number(isbe, nvp, ptr, &left); break; case NV_TYPE_STRING: ptr = nvpair_unpack_string(isbe, nvp, ptr, &left); break; case NV_TYPE_NVLIST: ptr = nvpair_unpack_nvlist(isbe, nvp, ptr, &left, nfds, &tmpnvl); nvlist_set_parent(tmpnvl, nvp); break; #ifndef _KERNEL case NV_TYPE_DESCRIPTOR: ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left, fds, nfds); break; #endif case NV_TYPE_BINARY: ptr = nvpair_unpack_binary(isbe, nvp, ptr, &left); break; case NV_TYPE_NVLIST_UP: if (nvl->nvl_parent == NULL) goto failed; nvl = nvpair_nvlist(nvl->nvl_parent); nvpair_free_structure(nvp); continue; default: PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp)); } if (ptr == NULL) goto failed; nvlist_move_nvpair(nvl, nvp); if (tmpnvl != NULL) { nvl = tmpnvl; tmpnvl = NULL; } } return (retnvl); failed: nvlist_destroy(retnvl); return (NULL); }
/* * Dump content of nvlist. */ void nvlist_dump(const nvlist_t *nvl, int fd) { const nvlist_t *tmpnvl; nvpair_t *nvp, *tmpnvp; void *cookie; int level; level = 0; if (nvlist_dump_error_check(nvl, fd, level)) return; nvp = nvlist_first_nvpair(nvl); while (nvp != NULL) { dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp), nvpair_type_string(nvpair_type(nvp))); switch (nvpair_type(nvp)) { case NV_TYPE_NULL: dprintf(fd, " null\n"); break; case NV_TYPE_BOOL: dprintf(fd, " %s\n", nvpair_get_bool(nvp) ? "TRUE" : "FALSE"); break; case NV_TYPE_NUMBER: dprintf(fd, " %ju (%jd) (0x%jx)\n", (uintmax_t)nvpair_get_number(nvp), (intmax_t)nvpair_get_number(nvp), (uintmax_t)nvpair_get_number(nvp)); break; case NV_TYPE_STRING: dprintf(fd, " [%s]\n", nvpair_get_string(nvp)); break; case NV_TYPE_NVLIST: dprintf(fd, "\n"); tmpnvl = nvpair_get_nvlist(nvp); if (nvlist_dump_error_check(tmpnvl, fd, level + 1)) break; tmpnvp = nvlist_first_nvpair(tmpnvl); if (tmpnvp != NULL) { nvl = tmpnvl; nvp = tmpnvp; level++; continue; } break; case NV_TYPE_DESCRIPTOR: dprintf(fd, " %d\n", nvpair_get_descriptor(nvp)); break; case NV_TYPE_BINARY: { const unsigned char *binary; unsigned int ii; size_t size; binary = nvpair_get_binary(nvp, &size); dprintf(fd, " %zu ", size); for (ii = 0; ii < size; ii++) dprintf(fd, "%02hhx", binary[ii]); dprintf(fd, "\n"); break; } default: PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp)); } while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) { cookie = NULL; nvl = nvlist_get_parent(nvl, &cookie); if (nvl == NULL) return; nvp = cookie; level--; } } }
int service_start(const char *name, int sock, service_limit_func_t *limitfunc, service_command_func_t *commandfunc, int argc, char *argv[]) { struct service *service; struct service_connection *sconn, *sconntmp; fd_set fds; int maxfd, nfds, serrno; assert(argc == 2); pjdlog_init(PJDLOG_MODE_STD); pjdlog_debug_set(atoi(argv[1])); service = service_alloc(name, limitfunc, commandfunc); if (service == NULL) return (errno); if (service_connection_add(service, sock, NULL) == NULL) { serrno = errno; service_free(service); return (serrno); } for (;;) { FD_ZERO(&fds); maxfd = -1; for (sconn = service_connection_first(service); sconn != NULL; sconn = service_connection_next(sconn)) { maxfd = fd_add(&fds, maxfd, service_connection_get_sock(sconn)); } PJDLOG_ASSERT(maxfd >= 0); PJDLOG_ASSERT(maxfd + 1 <= (int)FD_SETSIZE); nfds = select(maxfd + 1, &fds, NULL, NULL, NULL); if (nfds < 0) { if (errno != EINTR) pjdlog_errno(LOG_ERR, "select() failed"); continue; } else if (nfds == 0) { /* Timeout. */ PJDLOG_ABORT("select() timeout"); continue; } for (sconn = service_connection_first(service); sconn != NULL; sconn = sconntmp) { /* * Prepare for connection to be removed from the list * on failure. */ sconntmp = service_connection_next(sconn); if (FD_ISSET(service_connection_get_sock(sconn), &fds)) service_message(service, sconn); } if (service_connection_first(service) == NULL) { /* * No connections left, exiting. */ break; } } return (0); }
/* * Thread receives requests from the primary node. */ static void * recv_thread(void *arg) { struct hast_resource *res = arg; struct hio *hio, *mshio; struct nv *nv; for (;;) { pjdlog_debug(2, "recv: Taking free request."); QUEUE_TAKE(free, hio); pjdlog_debug(2, "recv: (%p) Got request.", hio); if (hast_proto_recv_hdr(res->hr_remotein, &nv) == -1) { secondary_exit(EX_TEMPFAIL, "Unable to receive request header"); } if (requnpack(res, hio, nv) != 0) { nv_free(nv); pjdlog_debug(2, "recv: (%p) Moving request to the send queue.", hio); QUEUE_INSERT(send, hio); continue; } switch (hio->hio_cmd) { case HIO_READ: res->hr_stat_read++; break; case HIO_WRITE: res->hr_stat_write++; break; case HIO_DELETE: res->hr_stat_delete++; break; case HIO_FLUSH: res->hr_stat_flush++; break; case HIO_KEEPALIVE: break; default: PJDLOG_ABORT("Unexpected command (cmd=%hhu).", hio->hio_cmd); } reqlog(LOG_DEBUG, 2, -1, hio, "recv: (%p) Got request header: ", hio); if (hio->hio_cmd == HIO_KEEPALIVE) { nv_free(nv); pjdlog_debug(2, "recv: (%p) Moving request to the free queue.", hio); hio_clear(hio); QUEUE_INSERT(free, hio); continue; } else if (hio->hio_cmd == HIO_WRITE) { if (hast_proto_recv_data(res, res->hr_remotein, nv, hio->hio_data, MAXPHYS) == -1) { secondary_exit(EX_TEMPFAIL, "Unable to receive request data"); } if (hio->hio_memsync) { /* * For memsync requests we expect two replies. * Clone the hio so we can handle both of them. */ pjdlog_debug(2, "recv: Taking free request."); QUEUE_TAKE(free, mshio); pjdlog_debug(2, "recv: (%p) Got request.", mshio); hio_copy(hio, mshio); mshio->hio_error = 0; /* * We want to keep 'memsync' tag only on the * request going onto send queue (mshio). */ hio->hio_memsync = false; pjdlog_debug(2, "recv: (%p) Moving memsync request to the send queue.", mshio); QUEUE_INSERT(send, mshio); } } nv_free(nv); pjdlog_debug(2, "recv: (%p) Moving request to the disk queue.", hio); QUEUE_INSERT(disk, hio); } /* NOTREACHED */ return (NULL); }
/* * Dump content of the nv structure. */ void nv_dump(struct nv *nv) { struct nvhdr *nvh; unsigned char *data, *ptr; size_t dsize, size; unsigned int ii; bool swap; if (nv_validate(nv, NULL) == -1) { printf("error: %d\n", errno); return; } NV_CHECK(nv); PJDLOG_ASSERT(nv->nv_error == 0); ptr = ebuf_data(nv->nv_ebuf, &size); while (size > 0) { PJDLOG_ASSERT(size >= sizeof(*nvh) + 2); nvh = (struct nvhdr *)ptr; PJDLOG_ASSERT(size >= NVH_SIZE(nvh)); swap = ((nvh->nvh_type & NV_ORDER_MASK) == NV_ORDER_NETWORK); dsize = NVH_DSIZE(nvh); data = NVH_DATA(nvh); printf(" %s", nvh->nvh_name); switch (nvh->nvh_type & NV_TYPE_MASK) { case NV_TYPE_INT8: printf("(int8): %jd", (intmax_t)(*(int8_t *)data)); break; case NV_TYPE_UINT8: printf("(uint8): %ju", (uintmax_t)(*(uint8_t *)data)); break; case NV_TYPE_INT16: printf("(int16): %jd", swap ? (intmax_t)le16toh(*(int16_t *)(void *)data) : (intmax_t)*(int16_t *)(void *)data); break; case NV_TYPE_UINT16: printf("(uint16): %ju", swap ? (uintmax_t)le16toh(*(uint16_t *)(void *)data) : (uintmax_t)*(uint16_t *)(void *)data); break; case NV_TYPE_INT32: printf("(int32): %jd", swap ? (intmax_t)le32toh(*(int32_t *)(void *)data) : (intmax_t)*(int32_t *)(void *)data); break; case NV_TYPE_UINT32: printf("(uint32): %ju", swap ? (uintmax_t)le32toh(*(uint32_t *)(void *)data) : (uintmax_t)*(uint32_t *)(void *)data); break; case NV_TYPE_INT64: printf("(int64): %jd", swap ? (intmax_t)le64toh(*(int64_t *)(void *)data) : (intmax_t)*(int64_t *)(void *)data); break; case NV_TYPE_UINT64: printf("(uint64): %ju", swap ? (uintmax_t)le64toh(*(uint64_t *)(void *)data) : (uintmax_t)*(uint64_t *)(void *)data); break; case NV_TYPE_INT8_ARRAY: printf("(int8 array):"); for (ii = 0; ii < dsize; ii++) printf(" %jd", (intmax_t)((int8_t *)data)[ii]); break; case NV_TYPE_UINT8_ARRAY: printf("(uint8 array):"); for (ii = 0; ii < dsize; ii++) printf(" %ju", (uintmax_t)((uint8_t *)data)[ii]); break; case NV_TYPE_INT16_ARRAY: printf("(int16 array):"); for (ii = 0; ii < dsize / 2; ii++) { printf(" %jd", swap ? (intmax_t)le16toh(((int16_t *)(void *)data)[ii]) : (intmax_t)((int16_t *)(void *)data)[ii]); } break; case NV_TYPE_UINT16_ARRAY: printf("(uint16 array):"); for (ii = 0; ii < dsize / 2; ii++) { printf(" %ju", swap ? (uintmax_t)le16toh(((uint16_t *)(void *)data)[ii]) : (uintmax_t)((uint16_t *)(void *)data)[ii]); } break; case NV_TYPE_INT32_ARRAY: printf("(int32 array):"); for (ii = 0; ii < dsize / 4; ii++) { printf(" %jd", swap ? (intmax_t)le32toh(((int32_t *)(void *)data)[ii]) : (intmax_t)((int32_t *)(void *)data)[ii]); } break; case NV_TYPE_UINT32_ARRAY: printf("(uint32 array):"); for (ii = 0; ii < dsize / 4; ii++) { printf(" %ju", swap ? (uintmax_t)le32toh(((uint32_t *)(void *)data)[ii]) : (uintmax_t)((uint32_t *)(void *)data)[ii]); } break; case NV_TYPE_INT64_ARRAY: printf("(int64 array):"); for (ii = 0; ii < dsize / 8; ii++) { printf(" %ju", swap ? (uintmax_t)le64toh(((uint64_t *)(void *)data)[ii]) : (uintmax_t)((uint64_t *)(void *)data)[ii]); } break; case NV_TYPE_UINT64_ARRAY: printf("(uint64 array):"); for (ii = 0; ii < dsize / 8; ii++) { printf(" %ju", swap ? (uintmax_t)le64toh(((uint64_t *)(void *)data)[ii]) : (uintmax_t)((uint64_t *)(void *)data)[ii]); } break; case NV_TYPE_STRING: printf("(string): %s", (char *)data); break; default: PJDLOG_ABORT("invalid condition"); } printf("\n"); ptr += NVH_SIZE(nvh); size -= NVH_SIZE(nvh); } }
static int tls_accept(void *ctx, void **newctxp) { struct tls_ctx *tlsctx = ctx; struct tls_ctx *newtlsctx; struct proto_conn *sock, *tcp; pid_t pid; int error; PJDLOG_ASSERT(tlsctx != NULL); PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC); PJDLOG_ASSERT(tlsctx->tls_side == TLS_SIDE_SERVER_LISTEN); if (proto_connect(NULL, "socketpair://", -1, &sock) == -1) return (errno); /* Accept TCP connection. */ if (proto_accept(tlsctx->tls_tcp, &tcp) == -1) { error = errno; proto_close(sock); return (error); } pid = fork(); switch (pid) { case -1: /* Failure. */ error = errno; proto_close(sock); return (error); case 0: /* Child. */ pjdlog_prefix_set("[TLS sandbox] (server) "); #ifdef HAVE_SETPROCTITLE setproctitle("[TLS sandbox] (server) "); #endif /* Close listen socket. */ proto_close(tlsctx->tls_tcp); tls_call_exec_server(sock, tcp); /* NOTREACHED */ PJDLOG_ABORT("Unreachable."); default: /* Parent. */ newtlsctx = calloc(1, sizeof(*tlsctx)); if (newtlsctx == NULL) { error = errno; proto_close(sock); proto_close(tcp); (void)kill(pid, SIGKILL); return (error); } proto_local_address(tcp, newtlsctx->tls_laddr, sizeof(newtlsctx->tls_laddr)); PJDLOG_ASSERT(strncmp(newtlsctx->tls_laddr, "tcp://", 6) == 0); bcopy("tls://", newtlsctx->tls_laddr, 6); *strrchr(newtlsctx->tls_laddr, ':') = '\0'; proto_remote_address(tcp, newtlsctx->tls_raddr, sizeof(newtlsctx->tls_raddr)); PJDLOG_ASSERT(strncmp(newtlsctx->tls_raddr, "tcp://", 6) == 0); bcopy("tls://", newtlsctx->tls_raddr, 6); *strrchr(newtlsctx->tls_raddr, ':') = '\0'; proto_close(tcp); proto_recv(sock, NULL, 0); newtlsctx->tls_sock = sock; newtlsctx->tls_tcp = NULL; newtlsctx->tls_wait_called = true; newtlsctx->tls_side = TLS_SIDE_SERVER_WORK; newtlsctx->tls_magic = TLS_CTX_MAGIC; *newctxp = newtlsctx; return (0); } }