Beispiel #1
0
int
structs_fixedarray_decode(const struct structs_type *type, const u_char *code,
	size_t cmax, void *data, char *ebuf, size_t emax)
{
	const struct structs_type *const etype = type->args[0].v;
	const u_int length = type->args[2].i;
	const u_int bitslen = NUM_BYTES(length);
	const u_char *bits;
	int clen = 0;
	u_int i;

	/* Make sure it's really a fixedarray type */
	if (type->tclass != STRUCTS_TYPE_FIXEDARRAY) {
		errno = EINVAL;
		return (-1);
	}

	/* Get bits array */
	if (cmax < bitslen) {
		strlcpy(ebuf, "encoded array is truncated", emax);
		errno = EINVAL;
		return (-1);
	}
	bits = code;
	code += bitslen;
	cmax -= bitslen;
	clen += bitslen;

	/* Decode elements */
	for (i = 0; i < length; i++) {
		void *const edata = (char *)data + (i * etype->size);
		int eclen;

		/* If element not present, assign it the default value */
		if ((bits[i / 8] & (1 << (i % 8))) == 0) {
			if (structs_init(etype, NULL, edata) == -1)
				goto fail;
			continue;
		}

		/* Decode element */
		if ((eclen = (*etype->decode)(etype,
		    code, cmax, edata, ebuf, emax)) == -1)
			goto fail;

		/* Go to next encoded element */
		code += eclen;
		cmax -= eclen;
		clen += eclen;
		continue;

		/* Un-do work done so far */
fail:		while (i-- > 0) {
			structs_free(etype, NULL,
			    (char *)data + (i * etype->size));
		}
		return (-1);
	}

	/* Done */
	return (clen);
}
Beispiel #2
0
int
structs_array_decode(const struct structs_type *type, const u_char *code,
	size_t cmax, void *data, char *ebuf, size_t emax)
{
	const struct structs_type *const etype = type->args[0].v;
	const char *const mtype = type->args[1].v;
	struct structs_array *const ary = data;
	const u_char *bits;
	u_int32_t elength;
	u_int bitslen;
	int clen;
	u_int i;

	/* Make sure it's really an array type */
	if (type->tclass != STRUCTS_TYPE_ARRAY) {
		errno = EINVAL;
		return (-1);
	}

	/* Get number of elements */
	if (cmax < 4)
		goto truncated;
	memcpy(&elength, code, 4);
	ary->length = ntohl(elength);
	code += 4;
	cmax -= 4;
	clen = 4;

	/* Get bits array */
	bitslen = NUM_BYTES(ary->length);
	if (cmax < bitslen) {
truncated:	strlcpy(ebuf, "encoded array is truncated", emax);
		errno = EINVAL;
		return (-1);
	}
	bits = code;
	code += bitslen;
	cmax -= bitslen;
	clen += bitslen;

	/* Allocate array elements */
	if ((ary->elems = MALLOC(mtype, ary->length * etype->size)) == NULL)
		return (-1);

	/* Decode elements */
	for (i = 0; i < ary->length; i++) {
		void *const edata = (char *)ary->elems + (i * etype->size);
		int eclen;

		/* If element not present, assign it the default value */
		if ((bits[i / 8] & (1 << (i % 8))) == 0) {
			if (structs_init(etype, NULL, edata) == -1)
				goto fail;
			continue;
		}

		/* Decode element */
		if ((eclen = (*etype->decode)(etype,
		    code, cmax, edata, ebuf, emax)) == -1)
			goto fail;

		/* Go to next encoded element */
		code += eclen;
		cmax -= eclen;
		clen += eclen;
		continue;

		/* Un-do work done so far */
fail:		while (i-- > 0) {
			structs_free(etype, NULL,
			    (char *)ary->elems + (i * etype->size));
		}
		FREE(mtype, ary->elems);
		return (-1);
	}

	/* Done */
	return (clen);
}
Beispiel #3
0
int
structs_fixedarray_encode(const struct structs_type *type, const char *mtype,
	struct structs_data *code, const void *data)
{
	const struct structs_type *const etype = type->args[0].v;
	const u_int length = type->args[2].i;
	const u_int bitslen = NUM_BYTES(length);
	struct structs_data *ecodes;
	u_char *bits;
	void *delem;
	u_int tlen;
	int r = -1;
	u_int i;

	/* Make sure it's really a fixedarray type */
	if (type->tclass != STRUCTS_TYPE_FIXEDARRAY) {
		errno = EINVAL;
		return (-1);
	}

	/* Get the default value for an element */
	if ((delem = MALLOC(TYPED_MEM_TEMP, etype->size)) == NULL)
		return (-1);
	if (structs_init(etype, NULL, delem) == -1)
		goto fail1;

	/* Create bit array. Each bit indicates an element that is present. */
	if ((bits = MALLOC(TYPED_MEM_TEMP, bitslen)) == NULL)
		goto fail2;
	memset(bits, 0, bitslen);
	tlen = bitslen;

	/* Create array of individual encodings, one per element */
	if ((ecodes = MALLOC(TYPED_MEM_TEMP, length * sizeof(*ecodes))) == NULL)
		goto fail3;
	for (i = 0; i < length; i++) {
		const void *const elem = (char *)data + (i * etype->size);
		struct structs_data *const ecode = &ecodes[i];

		/* Check for default value, leave out if same as */
		if ((*etype->equal)(etype, elem, delem) == 1) {
			memset(ecode, 0, sizeof(*ecode));
			continue;
		}
		bits[i / 8] |= (1 << (i % 8));

		/* Encode element */
		if ((*etype->encode)(etype, TYPED_MEM_TEMP, ecode, elem) == -1)
			goto fail4;
		tlen += ecode->length;
	}

	/* Allocate final encoded region */
	if ((code->data = MALLOC(mtype, tlen)) == NULL)
		goto fail4;

	/* Copy bits array */
	memcpy(code->data, bits, bitslen);
	code->length = bitslen;

	/* Copy encoded elements */
	for (i = 0; i < length; i++) {
		struct structs_data *const ecode = &ecodes[i];

		memcpy(code->data + code->length, ecode->data, ecode->length);
		code->length += ecode->length;
	}

	/* OK */
	r = 0;

	/* Clean up and exit */
fail4:	while (i-- > 0)
		FREE(TYPED_MEM_TEMP, ecodes[i].data);
	FREE(TYPED_MEM_TEMP, ecodes);
fail3:	FREE(TYPED_MEM_TEMP, bits);
fail2:	structs_free(etype, NULL, delem);
fail1:	FREE(TYPED_MEM_TEMP, delem);
	return (r);
}
/*
 * Same as http_xml_send_xmlrpc() but with user-defined URL path.
 */
int
http_xml_send_xmlrpc2(struct http_client *client,
	struct in_addr ip, u_int16_t port, int https,
	const char *username, const char *password, const char *urlpath,
	const char *methodName, u_int nparams,
	const struct structs_type **ptypes, const void **pdatas,
	const struct structs_type *rep_type, void *rep,
	struct xmlrpc_compact_fault *faultp, structs_xmllog_t *rlogger)
{
	const struct structs_type *const xreq_type
	    = &structs_type_xmlrpc_request;
	const struct structs_type *const xrep_type
	    = &structs_type_xmlrpc_response;
	const struct structs_type *const ftype
	    = &structs_type_xmlrpc_compact_fault;
	struct http_xml_send_xmlrpc_ctx *ctx;
	struct xmlrpc_compact_fault fault;
	char ebuf[128];
	int ret = -1;
	int r;

	/* Get context */
	if ((ctx = MALLOC(MEM_TYPE, sizeof(*ctx))) == NULL) {
		alogf(LOG_ERR, "%s: %m", "malloc");
		return (-1);
	}
	memset(ctx, 0, sizeof(*ctx));
	pthread_cleanup_push(http_xml_send_xmlrpc_cleanup, ctx);

	/* Build XML-RPC request and reply */
	if ((ctx->xreq = structs_xmlrpc_build_request(MEM_TYPE,
	    methodName, nparams, ptypes, pdatas)) == NULL) {
		alogf(LOG_ERR, "%s: %m", "structs_xmlrpc_build_request");
		goto fail;
	}
	if ((ctx->xrep = MALLOC(MEM_TYPE, xrep_type->size)) == NULL) {
		alogf(LOG_ERR, "%s: %m", "malloc");
		goto fail;
	}
	if (structs_init(xrep_type, NULL, ctx->xrep) == -1) {
		alogf(LOG_ERR, "%s: %m", "structs_init");
		FREE(MEM_TYPE, ctx->xrep);
		ctx->xrep = NULL;
		goto fail;
	}

#ifdef XML_RPC_DEBUG
	printf("%s: sending this XML-RPC request:\n", __FUNCTION__);
	(void)structs_xml_output(xreq_type, XML_RPC_REQUEST_TAG,
	    NULL, ctx->xreq, stdout, NULL, 0);
#endif

	/* Send request and get reply; note: we could get canceled here. */
	r = http_xml_send(client, ip, port, https, urlpath,
	    username, password, XML_RPC_REQUEST_TAG, NULL, xreq_type,
	    ctx->xreq, STRUCTS_XML_FULL, XML_RPC_REPLY_TAG, NULL, NULL,
	    xrep_type, ctx->xrep, 0, rlogger);

#ifdef XML_RPC_DEBUG
	printf("%s: got this XML-RPC reply (error=%s):\n",
	    __FUNCTION__, r == -1 ? strerror(errno) : "none");
	(void)structs_xml_output(xrep_type, XML_RPC_REPLY_TAG,
	    NULL, ctx->xrep, stdout, NULL, 0);
#endif

	/* Check error */
	if (r == -1)
		goto fail;

	/* Check for fault */
	if (structs_init(ftype, NULL, &fault) == -1) {
		alogf(LOG_ERR, "%s: %m", "structs_init");
		goto fail;
	}
	if (structs_xmlrpc2struct(xrep_type, ctx->xrep,
	    "fault.value", ftype, &fault, NULL, NULL, 0) == 0) {
		if (faultp != NULL)
			*faultp = fault;
		else
			structs_free(ftype, NULL, &fault);
		ret = -2;			/* -2 indicates fault */
		goto fail;
	}
	structs_free(ftype, NULL, &fault);

	/* Extract response (if desired) */
	if (rep != NULL) {
		if (rep_type != NULL) {		/* return compact type */
			if (structs_xmlrpc2struct(xrep_type, ctx->xrep,
			    "params.0.value", rep_type, rep, NULL, ebuf,
			    sizeof(ebuf)) == -1) {
				(*rlogger)(LOG_ERR, "error decoding XML-RPC"
				    " response: %s", ebuf);
				goto fail;
			}
		} else {			/* return exploded type */
			if (structs_get(&structs_type_xmlrpc_value,
			    "params.0.value", ctx->xrep, rep) == -1) {
				alogf(LOG_ERR, "structs_get: %m%s", "");
				goto fail;
			}
		}
	}

	/* OK */
	ret = 0;

fail:;
	/* Done */
	pthread_cleanup_pop(1);
	return (ret);
}