12264Sjacobs /*
22264Sjacobs * CDDL HEADER START
32264Sjacobs *
42264Sjacobs * The contents of this file are subject to the terms of the
52264Sjacobs * Common Development and Distribution License (the "License").
62264Sjacobs * You may not use this file except in compliance with the License.
72264Sjacobs *
82264Sjacobs * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92264Sjacobs * or http://www.opensolaris.org/os/licensing.
102264Sjacobs * See the License for the specific language governing permissions
112264Sjacobs * and limitations under the License.
122264Sjacobs *
132264Sjacobs * When distributing Covered Code, include this CDDL HEADER in each
142264Sjacobs * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152264Sjacobs * If applicable, add the following below this CDDL HEADER, with the
162264Sjacobs * fields enclosed by brackets "[]" replaced with your own identifying
172264Sjacobs * information: Portions Copyright [yyyy] [name of copyright owner]
182264Sjacobs *
192264Sjacobs * CDDL HEADER END
202264Sjacobs */
212264Sjacobs
222264Sjacobs /*
23*4030Sjacobs * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
242264Sjacobs * Use is subject to license terms.
252264Sjacobs *
262264Sjacobs */
272264Sjacobs
282264Sjacobs /* $Id: read.c 146 2006-03-24 00:26:54Z njacobs $ */
292264Sjacobs
302264Sjacobs #pragma ident "%Z%%M% %I% %E% SMI"
312264Sjacobs
322264Sjacobs #include <stdio.h>
332264Sjacobs #include <stdlib.h>
342264Sjacobs #include <alloca.h>
352264Sjacobs #include <string.h>
362264Sjacobs #include <stdarg.h>
372264Sjacobs #include <sys/types.h>
382264Sjacobs #include <netinet/in.h>
392264Sjacobs #include <inttypes.h>
402264Sjacobs
412264Sjacobs #include <papi.h>
422264Sjacobs #include <ipp.h>
432264Sjacobs
442264Sjacobs
452264Sjacobs #define _ipp_tag_string(id) ipp_tag_string((id), buf, sizeof (buf))
462264Sjacobs
472264Sjacobs static papi_status_t
read_name_with_language(ipp_reader_t iread,void * fd,papi_attribute_t *** message)482264Sjacobs read_name_with_language(ipp_reader_t iread, void *fd,
492264Sjacobs papi_attribute_t ***message)
502264Sjacobs {
512264Sjacobs char *string;
522264Sjacobs uint16_t size;
532264Sjacobs
542264Sjacobs /* read the language */
552264Sjacobs if (iread(fd, &size, 2) != 2) {
562264Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST,
572264Sjacobs "read failed: lang len\n");
582264Sjacobs return (PAPI_BAD_REQUEST);
592264Sjacobs }
602264Sjacobs size = (uint16_t)ntohs(size);
612264Sjacobs
622264Sjacobs if ((string = alloca(size + 1)) == NULL) {
632264Sjacobs ipp_set_status(message, PAPI_TEMPORARY_ERROR,
642264Sjacobs "Memory allocation failed");
652264Sjacobs return (PAPI_TEMPORARY_ERROR);
662264Sjacobs }
672264Sjacobs if (iread(fd, string, size) != size) {
682264Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST,
692264Sjacobs "read failed: lang\n");
702264Sjacobs return (PAPI_BAD_REQUEST);
712264Sjacobs }
722264Sjacobs
732264Sjacobs /* read the text */
742264Sjacobs if (iread(fd, &size, 2) != 2) {
752264Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST,
762264Sjacobs "read failed: text len\n");
772264Sjacobs return (PAPI_BAD_REQUEST);
782264Sjacobs }
792264Sjacobs size = (uint16_t)ntohs(size);
802264Sjacobs
812264Sjacobs if ((string = alloca(size + 1)) == NULL) {
822264Sjacobs ipp_set_status(message, PAPI_TEMPORARY_ERROR,
832264Sjacobs "Memory allocation failed");
842264Sjacobs return (PAPI_TEMPORARY_ERROR);
852264Sjacobs }
862264Sjacobs if (iread(fd, string, size) != size) {
872264Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST,
882264Sjacobs "read failed: text\n");
892264Sjacobs return (PAPI_BAD_REQUEST);
902264Sjacobs }
912264Sjacobs
922264Sjacobs return (PAPI_OK);
932264Sjacobs }
942264Sjacobs
952264Sjacobs
962264Sjacobs static struct {
972264Sjacobs int8_t ipp_type;
982264Sjacobs int8_t size;
992264Sjacobs } type_info[] = {
1002264Sjacobs { VTAG_INTEGER, 4 },
1012264Sjacobs { VTAG_ENUM, 4 },
1022264Sjacobs { VTAG_BOOLEAN, 1 },
1032264Sjacobs { VTAG_RANGE_OF_INTEGER, 8 },
1042264Sjacobs { VTAG_RESOLUTION, 9 },
1052264Sjacobs { VTAG_DATE_TIME, 11 },
1062264Sjacobs { DTAG_MIN, 0 }
1072264Sjacobs };
1082264Sjacobs
1092264Sjacobs /* verify that the IPP type and size are compatible */
1102264Sjacobs static int
validate_length(int8_t type,int8_t size)1112264Sjacobs validate_length(int8_t type, int8_t size)
1122264Sjacobs {
1132264Sjacobs int i;
1142264Sjacobs
1152264Sjacobs for (i = 0; type_info[i].ipp_type != DTAG_MIN; i++)
1162264Sjacobs if (type_info[i].ipp_type == type)
1172264Sjacobs return ((type_info[i].size == size) ? 0 : -1);
1182264Sjacobs return (0);
1192264Sjacobs }
1202264Sjacobs
1212264Sjacobs /* convert tyep IPP type to a type that is marginally compatible */
1222264Sjacobs static int8_t
base_type(int8_t i)1232264Sjacobs base_type(int8_t i)
1242264Sjacobs {
1252264Sjacobs switch (i) {
1262264Sjacobs case VTAG_ENUM:
1272264Sjacobs case VTAG_INTEGER:
1282264Sjacobs return (VTAG_INTEGER);
1292264Sjacobs case VTAG_URI:
1302264Sjacobs case VTAG_OCTET_STRING:
1312264Sjacobs case VTAG_TEXT_WITHOUT_LANGUAGE:
1322264Sjacobs case VTAG_URI_SCHEME:
1332264Sjacobs case VTAG_CHARSET:
1342264Sjacobs case VTAG_NATURAL_LANGUAGE:
1352264Sjacobs case VTAG_MIME_MEDIA_TYPE:
1362264Sjacobs case VTAG_NAME_WITHOUT_LANGUAGE:
1372264Sjacobs case VTAG_KEYWORD:
1382264Sjacobs return (VTAG_TEXT_WITHOUT_LANGUAGE);
1392264Sjacobs case VTAG_BOOLEAN:
1402264Sjacobs case VTAG_RANGE_OF_INTEGER:
1412264Sjacobs case VTAG_DATE_TIME:
1422264Sjacobs case VTAG_RESOLUTION:
1432264Sjacobs default:
1442264Sjacobs return (i);
1452264Sjacobs }
1462264Sjacobs }
1472264Sjacobs
1482264Sjacobs /* verify that the IPP type is correct for the named attribute */
1492264Sjacobs static papi_status_t
validate_type(char * name,int8_t type)1502264Sjacobs validate_type(char *name, int8_t type)
1512264Sjacobs {
1522264Sjacobs int8_t t = name_to_ipp_type(name);
1532264Sjacobs
1542264Sjacobs if (t == 0) /* The attribute is not defined in the RFC */
1552264Sjacobs return (PAPI_NOT_FOUND);
1562264Sjacobs else if (t == type) /* The supplied type matched the RFC type */
1572264Sjacobs return (PAPI_OK);
1582264Sjacobs else { /* The supplied type doesn't match the RFC */
1592264Sjacobs if (base_type(t) == base_type(type))
1602264Sjacobs return (PAPI_OK);
1612264Sjacobs
1622264Sjacobs return (PAPI_CONFLICT);
1632264Sjacobs }
1642264Sjacobs }
1652264Sjacobs
1662264Sjacobs /* verify that the IPP value is within specification for the named attribute */
1672264Sjacobs static int
validate_value(papi_attribute_t *** message,char * name,int8_t type,...)1682264Sjacobs validate_value(papi_attribute_t ***message, char *name, int8_t type, ...)
1692264Sjacobs {
1702264Sjacobs #define within(a, b, c) ((b >= a) && (b <= c))
1712264Sjacobs va_list ap;
1722264Sjacobs int rc = -1;
1732264Sjacobs int min = min_val_len(type, name),
1742264Sjacobs max = max_val_len(type, name);
1752264Sjacobs char buf[64]; /* For _ipp_<...>_string() */
1762264Sjacobs
1772264Sjacobs va_start(ap, type);
1782264Sjacobs switch (type) {
1792264Sjacobs case VTAG_ENUM:
1802264Sjacobs case VTAG_INTEGER: {
1812264Sjacobs int32_t i = (int32_t)va_arg(ap, int32_t);
1822264Sjacobs
1832264Sjacobs if (within(min, i, max))
1842264Sjacobs rc = 0;
1852264Sjacobs else
1862264Sjacobs ipp_set_status(message, PAPI_BAD_ARGUMENT,
1872264Sjacobs "%s(%s): %d: out of range (%d - %d)", name,
1882264Sjacobs _ipp_tag_string(type), i, min, max);
1892264Sjacobs }
1902264Sjacobs break;
1912264Sjacobs case VTAG_BOOLEAN: {
1922264Sjacobs int8_t v = (int8_t)va_arg(ap, int);
1932264Sjacobs
1942264Sjacobs if (within(0, v, 1))
1952264Sjacobs rc = 0;
1962264Sjacobs else
1972264Sjacobs ipp_set_status(message, PAPI_BAD_ARGUMENT,
1982264Sjacobs "%s(%s): %d: out of range (0 - 1)", name,
1992264Sjacobs _ipp_tag_string(type), v);
2002264Sjacobs }
2012264Sjacobs break;
2022264Sjacobs case VTAG_RANGE_OF_INTEGER: {
2032264Sjacobs int32_t lower = (int32_t)va_arg(ap, int32_t);
2042264Sjacobs int32_t upper = (int32_t)va_arg(ap, int32_t);
2052264Sjacobs
2062264Sjacobs if (within(min, lower, max) &&
2072264Sjacobs within(min, upper, max))
2082264Sjacobs rc = 0;
2092264Sjacobs else
2102264Sjacobs ipp_set_status(message, PAPI_BAD_ARGUMENT,
2112264Sjacobs "%s(%s): %d - %d: out of range (%d - %d)", name,
2122264Sjacobs _ipp_tag_string(type), lower, upper, min, max);
2132264Sjacobs }
2142264Sjacobs break;
2152264Sjacobs case VTAG_URI:
2162264Sjacobs case VTAG_OCTET_STRING:
2172264Sjacobs case VTAG_TEXT_WITHOUT_LANGUAGE:
2182264Sjacobs case VTAG_URI_SCHEME:
2192264Sjacobs case VTAG_CHARSET:
2202264Sjacobs case VTAG_NATURAL_LANGUAGE:
2212264Sjacobs case VTAG_MIME_MEDIA_TYPE:
2222264Sjacobs case VTAG_NAME_WITHOUT_LANGUAGE: {
2232264Sjacobs char *v = (char *)va_arg(ap, char *);
2242264Sjacobs
2252264Sjacobs if (strlen(v) < max)
2262264Sjacobs rc = 0;
2272264Sjacobs else
2282264Sjacobs ipp_set_status(message, PAPI_BAD_ARGUMENT,
2292264Sjacobs "%s(%s): %s: too long (max length: %d)", name,
2302264Sjacobs _ipp_tag_string(type), v, max);
2312264Sjacobs }
2322264Sjacobs break;
2332264Sjacobs case VTAG_KEYWORD: {
2342264Sjacobs char *v = (char *)va_arg(ap, char *);
2352264Sjacobs
2362264Sjacobs if (strlen(v) >= max)
2372264Sjacobs ipp_set_status(message, PAPI_BAD_ARGUMENT,
2382264Sjacobs "%s(%s): %s: too long (max length: %d)", name,
2392264Sjacobs _ipp_tag_string(type), v, max);
2402264Sjacobs else if (is_keyword(v) == 0)
2412264Sjacobs ipp_set_status(message, PAPI_BAD_ARGUMENT,
2422264Sjacobs "%s(%s): %s: invalid keyword", name,
2432264Sjacobs _ipp_tag_string(type), v);
2442264Sjacobs else
2452264Sjacobs rc = 0;
2462264Sjacobs }
2472264Sjacobs break;
2482264Sjacobs case VTAG_DATE_TIME:
2492264Sjacobs case VTAG_RESOLUTION:
2502264Sjacobs default:
2512264Sjacobs rc = 0;
2522264Sjacobs }
2532264Sjacobs va_end(ap);
2542264Sjacobs
2552264Sjacobs return (rc);
2562264Sjacobs #undef within
2572264Sjacobs }
2582264Sjacobs
2592264Sjacobs /*
2602264Sjacobs * read_attr_group() reads in enough of the message data to parse an entire
2612264Sjacobs * attribute group. Since to determine that the group is finished you have to
2622264Sjacobs * read the character that determines the type of the next group, this function
2632264Sjacobs * must return that character, in order that our caller knows how to call us for
2642264Sjacobs * the next group. Thus type is used both as an input parameter (the type of
2652264Sjacobs * attribute group to read in) and an output parameter (the type of the next
2662264Sjacobs * attribute group).
2672264Sjacobs */
2682264Sjacobs
2692264Sjacobs static papi_status_t
ipp_read_attribute_group(ipp_reader_t iread,void * fd,int8_t * type,papi_attribute_t *** message)2702264Sjacobs ipp_read_attribute_group(ipp_reader_t iread, void *fd, int8_t *type,
2712264Sjacobs papi_attribute_t ***message)
2722264Sjacobs {
2732264Sjacobs int8_t value_tag;
2742264Sjacobs uint16_t name_length, value_length;
2752264Sjacobs papi_attribute_t **attributes = NULL;
2762264Sjacobs char *name = NULL;
2772264Sjacobs int i;
2782264Sjacobs char buf[64]; /* For _ipp_<...>_string() */
2792264Sjacobs
2802264Sjacobs /*
2812264Sjacobs * RFC2910 3.3 says we need to handle `An expected but missing
2822264Sjacobs * "begin-attribute-group-tag" field. How?
2832264Sjacobs */
2842264Sjacobs if (*type > DTAG_MAX) {
2852264Sjacobs /* Scream bloody murder, or assign a new type? */
2862264Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST,
2872264Sjacobs "Bad attribute group tag 0x%.2hx (%s)",
2882264Sjacobs *type, _ipp_tag_string(*type));
2892264Sjacobs return (PAPI_BAD_REQUEST);
2902264Sjacobs }
2912264Sjacobs
2922264Sjacobs /* This loops through *values* not *attributes*! */
2932264Sjacobs for (i = 0; ; i++) {
2942264Sjacobs papi_status_t valid = PAPI_OK;
2952264Sjacobs if (iread(fd, &value_tag, 1) != 1) {
2962264Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST,
2972264Sjacobs "bad read: value tag\n");
2982264Sjacobs return (PAPI_BAD_REQUEST);
2992264Sjacobs }
3002264Sjacobs /* are we done with this group ? */
3012264Sjacobs if (value_tag <= DTAG_MAX)
3022264Sjacobs break;
3032264Sjacobs
3042264Sjacobs if (iread(fd, &name_length, 2) != 2) {
3052264Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST,
3062264Sjacobs "bad read: name length\n");
3072264Sjacobs return (PAPI_BAD_REQUEST);
3082264Sjacobs }
3092264Sjacobs name_length = (uint16_t)ntohs(name_length);
3102264Sjacobs
3112264Sjacobs /* Not just another value for the previous attribute */
3122264Sjacobs if (name_length != 0) {
3132264Sjacobs if ((name = alloca(name_length + 1)) == NULL) {
3142264Sjacobs ipp_set_status(message, PAPI_TEMPORARY_ERROR,
3152264Sjacobs "alloca(): failed\n");
3162264Sjacobs return (PAPI_TEMPORARY_ERROR);
3172264Sjacobs }
3182264Sjacobs (void) memset(name, 0, name_length + 1);
3192264Sjacobs
3202264Sjacobs if (iread(fd, name, name_length) != name_length) {
3212264Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST,
3222264Sjacobs "bad read: name\n");
3232264Sjacobs return (PAPI_BAD_REQUEST);
3242264Sjacobs }
3252264Sjacobs }
3262264Sjacobs
3272264Sjacobs valid = validate_type(name, value_tag);
3282264Sjacobs if ((valid != PAPI_OK) && (valid != PAPI_NOT_FOUND))
3292264Sjacobs ipp_set_status(message, valid, "%s(%s): %s", name,
3302264Sjacobs _ipp_tag_string(value_tag),
3312264Sjacobs papiStatusString(valid));
3322264Sjacobs
3332264Sjacobs if (iread(fd, &value_length, 2) != 2) {
3342264Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST,
3352264Sjacobs "bad read: value length\n");
3362264Sjacobs return (PAPI_BAD_REQUEST);
3372264Sjacobs }
3382264Sjacobs value_length = (uint16_t)ntohs(value_length);
3392264Sjacobs
3402264Sjacobs if (validate_length(value_tag, value_length) < 0) {
3412264Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST,
3422264Sjacobs "Bad value length (%d) for type %s",
3432264Sjacobs value_length, _ipp_tag_string(value_tag));
3442264Sjacobs return (PAPI_BAD_REQUEST);
3452264Sjacobs }
3462264Sjacobs
3472264Sjacobs switch (value_tag) {
3482264Sjacobs case VTAG_INTEGER:
3492264Sjacobs case VTAG_ENUM: {
3502264Sjacobs int32_t v;
3512264Sjacobs
3522264Sjacobs if (iread(fd, &v, value_length) != value_length) {
3532264Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST,
3542264Sjacobs "bad read: int/enum\n");
3552264Sjacobs return (PAPI_BAD_REQUEST);
3562264Sjacobs }
3572264Sjacobs v = (int32_t)ntohl(v);
3582264Sjacobs (void) validate_value(message, name, value_tag, v);
3592264Sjacobs papiAttributeListAddInteger(&attributes,
3602264Sjacobs PAPI_ATTR_APPEND, name, v);
3612264Sjacobs
3622264Sjacobs }
3632264Sjacobs break;
3642264Sjacobs case VTAG_BOOLEAN: {
3652264Sjacobs int8_t v;
3662264Sjacobs
3672264Sjacobs if (iread(fd, &v, value_length) != value_length) {
3682264Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST,
3692264Sjacobs "bad read: boolean\n");
3702264Sjacobs return (PAPI_BAD_REQUEST);
3712264Sjacobs }
3722264Sjacobs (void) validate_value(message, name, value_tag, v);
3732264Sjacobs papiAttributeListAddBoolean(&attributes,
3742264Sjacobs PAPI_ATTR_APPEND, name, v);
3752264Sjacobs }
3762264Sjacobs break;
3772264Sjacobs case VTAG_RANGE_OF_INTEGER: {
3782264Sjacobs int32_t min, max;
3792264Sjacobs
3802264Sjacobs if (iread(fd, &min, 4) != 4) {
3812264Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST,
3822264Sjacobs "bad read: min\n");
3832264Sjacobs return (PAPI_BAD_REQUEST);
3842264Sjacobs }
3852264Sjacobs if (iread(fd, &max, 4) != 4) {
3862264Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST,
3872264Sjacobs "bad read: max\n");
3882264Sjacobs return (PAPI_BAD_REQUEST);
3892264Sjacobs }
3902264Sjacobs min = (int32_t)ntohl(min);
3912264Sjacobs max = (int32_t)ntohl(max);
3922264Sjacobs (void) validate_value(message, name, value_tag,
3932264Sjacobs min, max);
3942264Sjacobs papiAttributeListAddRange(&attributes, PAPI_ATTR_APPEND,
3952264Sjacobs name, min, max);
3962264Sjacobs }
3972264Sjacobs break;
3982264Sjacobs case VTAG_RESOLUTION: {
3992264Sjacobs int32_t x, y;
4002264Sjacobs int8_t units;
4012264Sjacobs
4022264Sjacobs if (iread(fd, &x, 4) != 4) {
4032264Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST,
4042264Sjacobs "bad read: x\n");
4052264Sjacobs return (PAPI_BAD_REQUEST);
4062264Sjacobs }
4072264Sjacobs if (iread(fd, &y, 4) != 4) {
4082264Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST,
4092264Sjacobs "bad read: y\n");
4102264Sjacobs return (PAPI_BAD_REQUEST);
4112264Sjacobs }
4122264Sjacobs if (iread(fd, &units, 1) != 1) {
4132264Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST,
4142264Sjacobs "bad read: units\n");
4152264Sjacobs return (PAPI_BAD_REQUEST);
4162264Sjacobs }
4172264Sjacobs x = (int32_t)ntohl(x);
4182264Sjacobs y = (int32_t)ntohl(y);
4192264Sjacobs papiAttributeListAddResolution(&attributes,
4202264Sjacobs PAPI_ATTR_APPEND, name, x, y,
4212264Sjacobs (papi_resolution_unit_t)units);
4222264Sjacobs }
4232264Sjacobs break;
4242264Sjacobs case VTAG_DATE_TIME: {
4252264Sjacobs struct tm tm;
4262264Sjacobs time_t v;
4272264Sjacobs int8_t c;
4282264Sjacobs uint16_t s;
4292264Sjacobs
4302264Sjacobs (void) memset(&tm, 0, sizeof (tm));
4312264Sjacobs if (iread(fd, &s, 2) != 2) {
4322264Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST,
4332264Sjacobs "bad read: year\n");
4342264Sjacobs return (PAPI_BAD_REQUEST);
4352264Sjacobs }
4362264Sjacobs tm.tm_year = (uint16_t)ntohs(s) - 1900;
4372264Sjacobs if (iread(fd, &c, 1) != 1) {
4382264Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST,
4392264Sjacobs "bad read: month\n");
4402264Sjacobs return (PAPI_BAD_REQUEST);
4412264Sjacobs }
4422264Sjacobs tm.tm_mon = c - 1;
4432264Sjacobs if (iread(fd, &c, 1) != 1) {
4442264Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST,
4452264Sjacobs "bad read: day\n");
4462264Sjacobs return (PAPI_BAD_REQUEST);
4472264Sjacobs }
4482264Sjacobs tm.tm_mday = c;
4492264Sjacobs if (iread(fd, &c, 1) != 1) {
4502264Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST,
4512264Sjacobs "bad read: hour\n");
4522264Sjacobs return (PAPI_BAD_REQUEST);
4532264Sjacobs }
4542264Sjacobs tm.tm_hour = c;
4552264Sjacobs if (iread(fd, &c, 1) != 1) {
4562264Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST,
4572264Sjacobs "bad read: minutes\n");
4582264Sjacobs return (PAPI_BAD_REQUEST);
4592264Sjacobs }
4602264Sjacobs tm.tm_min = c;
4612264Sjacobs if (iread(fd, &c, 1) != 1) {
4622264Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST,
4632264Sjacobs "bad read: seconds\n");
4642264Sjacobs return (PAPI_BAD_REQUEST);
4652264Sjacobs }
4662264Sjacobs tm.tm_sec = c;
4672264Sjacobs if (iread(fd, &c, 1) != 1) {
4682264Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST,
4692264Sjacobs "bad read: decisec\n");
4702264Sjacobs return (PAPI_BAD_REQUEST);
4712264Sjacobs }
4722264Sjacobs /* tm.deciseconds = c; */
4732264Sjacobs if (iread(fd, &c, 1) != 1) {
4742264Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST,
4752264Sjacobs "bad read: utc_dir\n");
4762264Sjacobs return (PAPI_BAD_REQUEST);
4772264Sjacobs }
4782264Sjacobs /* tm.utc_dir = c; */
4792264Sjacobs if (iread(fd, &c, 1) != 1) {
4802264Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST,
4812264Sjacobs "bad read: utc_hour\n");
4822264Sjacobs return (PAPI_BAD_REQUEST);
4832264Sjacobs }
4842264Sjacobs /* tm.utc_hours = c; */
4852264Sjacobs if (iread(fd, &c, 1) != 1) {
4862264Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST,
4872264Sjacobs "bad read: utc_min\n");
4882264Sjacobs return (PAPI_BAD_REQUEST);
4892264Sjacobs }
4902264Sjacobs /* tm.utc_minutes = c; */
4912264Sjacobs
4922264Sjacobs v = mktime(&tm);
4932264Sjacobs
4942264Sjacobs (void) validate_value(message, name, value_tag, v);
4952264Sjacobs papiAttributeListAddDatetime(&attributes,
4962264Sjacobs PAPI_ATTR_APPEND, name, v);
4972264Sjacobs }
4982264Sjacobs break;
4992264Sjacobs case VTAG_NAME_WITH_LANGUAGE:
5002264Sjacobs case VTAG_TEXT_WITH_LANGUAGE:
5012264Sjacobs /*
5022264Sjacobs * we are dropping this because we don't support
5032264Sjacobs * name with language at this time.
5042264Sjacobs */
5052264Sjacobs (void) read_name_with_language(iread, fd, message);
5062264Sjacobs break;
5072264Sjacobs case VTAG_NAME_WITHOUT_LANGUAGE:
5082264Sjacobs case VTAG_TEXT_WITHOUT_LANGUAGE:
5092264Sjacobs case VTAG_URI:
5102264Sjacobs case VTAG_KEYWORD:
5112264Sjacobs case VTAG_CHARSET: {
5122264Sjacobs char *v;
5132264Sjacobs
5142264Sjacobs if ((v = calloc(1, value_length + 1)) == NULL) {
5152264Sjacobs ipp_set_status(message, PAPI_TEMPORARY_ERROR,
5162264Sjacobs "calloc(): failed\n");
5172264Sjacobs return (PAPI_TEMPORARY_ERROR);
5182264Sjacobs }
5192264Sjacobs #ifdef NOTDEF
5202264Sjacobs if (iread(fd, v, value_length) != value_length) {
5212264Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST,
5222264Sjacobs "bad read: stringy\n");
5232264Sjacobs return (PAPI_BAD_REQUEST);
5242264Sjacobs }
5252264Sjacobs #else
5262264Sjacobs {
5272264Sjacobs int rc, i = value_length;
5282264Sjacobs char *p = v;
5292264Sjacobs
5302264Sjacobs while ((rc = iread(fd, p, i)) != i) {
5312264Sjacobs if (rc <= 0) {
5322264Sjacobs ipp_set_status(message,
5332264Sjacobs PAPI_BAD_REQUEST,
5342264Sjacobs "bad read: stringy\n");
5352264Sjacobs return (PAPI_BAD_REQUEST);
5362264Sjacobs }
5372264Sjacobs i -= rc;
5382264Sjacobs p += rc;
5392264Sjacobs }
5402264Sjacobs }
5412264Sjacobs #endif
5422264Sjacobs (void) validate_value(message, name, value_tag, v);
5432264Sjacobs papiAttributeListAddString(&attributes,
5442264Sjacobs PAPI_ATTR_APPEND, name, v);
5452264Sjacobs }
5462264Sjacobs break;
5472264Sjacobs case VTAG_UNKNOWN:
5482264Sjacobs case VTAG_NOVALUE:
5492264Sjacobs case VTAG_UNSUPPORTED:
5502264Sjacobs papiAttributeListAddValue(&attributes, PAPI_ATTR_EXCL,
5512264Sjacobs name, PAPI_COLLECTION, NULL);
5522264Sjacobs break;
5532264Sjacobs default: {
5542264Sjacobs char *v;
5552264Sjacobs
5562264Sjacobs if ((v = calloc(1, value_length + 1)) == NULL) {
5572264Sjacobs ipp_set_status(message, PAPI_TEMPORARY_ERROR,
5582264Sjacobs "calloc(): failed\n");
5592264Sjacobs return (PAPI_TEMPORARY_ERROR);
5602264Sjacobs }
5612264Sjacobs if (iread(fd, v, value_length) != value_length) {
5622264Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST,
5632264Sjacobs "bad read: other\n");
5642264Sjacobs return (PAPI_BAD_REQUEST);
5652264Sjacobs }
5662264Sjacobs papiAttributeListAddString(&attributes,
5672264Sjacobs PAPI_ATTR_APPEND, name, v);
5682264Sjacobs }
5692264Sjacobs break;
5702264Sjacobs }
5712264Sjacobs }
5722264Sjacobs
5732264Sjacobs if (attributes != NULL) {
5742264Sjacobs char name[32];
5752264Sjacobs
5762264Sjacobs (void) ipp_tag_string(*type, name, sizeof (name));
5772264Sjacobs papiAttributeListAddCollection(message, PAPI_ATTR_APPEND, name,
5782264Sjacobs attributes);
5792264Sjacobs }
5802264Sjacobs
5812264Sjacobs *type = value_tag;
5822264Sjacobs
5832264Sjacobs return (PAPI_OK);
5842264Sjacobs }
5852264Sjacobs
5862264Sjacobs
5872264Sjacobs static papi_status_t
ipp_read_header(ipp_reader_t iread,void * fd,papi_attribute_t *** message,char type)5882264Sjacobs ipp_read_header(ipp_reader_t iread, void *fd, papi_attribute_t ***message,
5892264Sjacobs char type)
5902264Sjacobs {
5912264Sjacobs char *attr_name = "status-code"; /* default to a response */
5922264Sjacobs char buf[8];
5932264Sjacobs int8_t c;
5942264Sjacobs uint16_t s;
5952264Sjacobs int32_t i;
5962264Sjacobs
5972264Sjacobs if ((iread == NULL) || (fd == NULL) || (message == NULL))
5982264Sjacobs return (PAPI_BAD_ARGUMENT);
5992264Sjacobs
6002264Sjacobs /*
6012264Sjacobs * Apache 1.X uses the buffer supplied to it's read call to read in
6022264Sjacobs * the chunk size when chunking is used. This causes problems
6032264Sjacobs * reading the header a piece at a time, because we don't have
6042264Sjacobs * enough room to read in the chunk size prior to reading the
6052264Sjacobs * chunk.
6062264Sjacobs */
6072264Sjacobs
6082264Sjacobs if (iread(fd, buf, 8) != 8)
6092264Sjacobs return (PAPI_BAD_REQUEST);
6102264Sjacobs
6112264Sjacobs c = buf[0];
6122264Sjacobs (void) papiAttributeListAddInteger(message, PAPI_ATTR_REPLACE,
6132264Sjacobs "version-major", c);
6142264Sjacobs
6152264Sjacobs c = buf[1];
6162264Sjacobs (void) papiAttributeListAddInteger(message, PAPI_ATTR_REPLACE,
6172264Sjacobs "version-minor", c);
6182264Sjacobs
6192264Sjacobs memcpy(&s, &buf[2], 2);
6202264Sjacobs s = (uint16_t)ntohs(s);
6212264Sjacobs if (type == IPP_TYPE_REQUEST)
6222264Sjacobs attr_name = "operation-id";
6232264Sjacobs (void) papiAttributeListAddInteger(message, PAPI_ATTR_REPLACE,
6242264Sjacobs attr_name, s);
6252264Sjacobs
626*4030Sjacobs memcpy(&i, &buf[4], 4);
6272264Sjacobs i = (uint32_t)ntohl(i);
6282264Sjacobs (void) papiAttributeListAddInteger(message, PAPI_ATTR_REPLACE,
6292264Sjacobs "request-id", i);
6302264Sjacobs
6312264Sjacobs return (PAPI_OK);
6322264Sjacobs }
6332264Sjacobs
6342264Sjacobs static papi_status_t
ipp_read_attribute_groups(ipp_reader_t iread,void * fd,papi_attribute_t *** message)6352264Sjacobs ipp_read_attribute_groups(ipp_reader_t iread, void *fd,
6362264Sjacobs papi_attribute_t ***message)
6372264Sjacobs {
6382264Sjacobs papi_status_t result = PAPI_OK;
6392264Sjacobs int8_t tag;
6402264Sjacobs
6412264Sjacobs /* start reading the attribute groups */
6422264Sjacobs if (iread(fd, &tag, 1) != 1) /* prime the pump */
6432264Sjacobs return (PAPI_BAD_REQUEST);
6442264Sjacobs
6452264Sjacobs while ((tag != DTAG_END_OF_ATTRIBUTES) && (result == PAPI_OK)) {
6462264Sjacobs result = ipp_read_attribute_group(iread, fd, &tag, message);
6472264Sjacobs }
6482264Sjacobs
6492264Sjacobs return (result);
6502264Sjacobs }
6512264Sjacobs
6522264Sjacobs papi_status_t
ipp_read_message(ipp_reader_t iread,void * fd,papi_attribute_t *** message,char type)6532264Sjacobs ipp_read_message(ipp_reader_t iread, void *fd, papi_attribute_t ***message,
6542264Sjacobs char type)
6552264Sjacobs {
6562264Sjacobs papi_status_t result = PAPI_OK;
6572264Sjacobs
6582264Sjacobs if ((iread == NULL) || (fd == NULL) || (message == NULL))
6592264Sjacobs return (PAPI_BAD_ARGUMENT);
6602264Sjacobs
6612264Sjacobs result = ipp_read_header(iread, fd, message, type);
6622264Sjacobs if (result == PAPI_OK)
6632264Sjacobs result = ipp_read_attribute_groups(iread, fd, message);
6642264Sjacobs
6652264Sjacobs return (result);
6662264Sjacobs }
667