1355b4669Sjacobs /* 2355b4669Sjacobs * CDDL HEADER START 3355b4669Sjacobs * 4355b4669Sjacobs * The contents of this file are subject to the terms of the 5355b4669Sjacobs * Common Development and Distribution License (the "License"). 6355b4669Sjacobs * You may not use this file except in compliance with the License. 7355b4669Sjacobs * 8355b4669Sjacobs * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9355b4669Sjacobs * or http://www.opensolaris.org/os/licensing. 10355b4669Sjacobs * See the License for the specific language governing permissions 11355b4669Sjacobs * and limitations under the License. 12355b4669Sjacobs * 13355b4669Sjacobs * When distributing Covered Code, include this CDDL HEADER in each 14355b4669Sjacobs * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15355b4669Sjacobs * If applicable, add the following below this CDDL HEADER, with the 16355b4669Sjacobs * fields enclosed by brackets "[]" replaced with your own identifying 17355b4669Sjacobs * information: Portions Copyright [yyyy] [name of copyright owner] 18355b4669Sjacobs * 19355b4669Sjacobs * CDDL HEADER END 20355b4669Sjacobs */ 21355b4669Sjacobs 22355b4669Sjacobs /* 23*c40965e4Sjacobs * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24355b4669Sjacobs * Use is subject to license terms. 25355b4669Sjacobs * 26355b4669Sjacobs */ 27355b4669Sjacobs 28355b4669Sjacobs /* $Id: read.c 146 2006-03-24 00:26:54Z njacobs $ */ 29355b4669Sjacobs 30355b4669Sjacobs #pragma ident "%Z%%M% %I% %E% SMI" 31355b4669Sjacobs 32355b4669Sjacobs #include <stdio.h> 33355b4669Sjacobs #include <stdlib.h> 34355b4669Sjacobs #include <alloca.h> 35355b4669Sjacobs #include <string.h> 36355b4669Sjacobs #include <stdarg.h> 37355b4669Sjacobs #include <sys/types.h> 38355b4669Sjacobs #include <netinet/in.h> 39355b4669Sjacobs #include <inttypes.h> 40355b4669Sjacobs 41355b4669Sjacobs #include <papi.h> 42355b4669Sjacobs #include <ipp.h> 43355b4669Sjacobs 44355b4669Sjacobs 45355b4669Sjacobs #define _ipp_tag_string(id) ipp_tag_string((id), buf, sizeof (buf)) 46355b4669Sjacobs 47355b4669Sjacobs static papi_status_t 48355b4669Sjacobs read_name_with_language(ipp_reader_t iread, void *fd, 49355b4669Sjacobs papi_attribute_t ***message) 50355b4669Sjacobs { 51355b4669Sjacobs char *string; 52355b4669Sjacobs uint16_t size; 53355b4669Sjacobs 54355b4669Sjacobs /* read the language */ 55355b4669Sjacobs if (iread(fd, &size, 2) != 2) { 56355b4669Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST, 57355b4669Sjacobs "read failed: lang len\n"); 58355b4669Sjacobs return (PAPI_BAD_REQUEST); 59355b4669Sjacobs } 60355b4669Sjacobs size = (uint16_t)ntohs(size); 61355b4669Sjacobs 62355b4669Sjacobs if ((string = alloca(size + 1)) == NULL) { 63355b4669Sjacobs ipp_set_status(message, PAPI_TEMPORARY_ERROR, 64355b4669Sjacobs "Memory allocation failed"); 65355b4669Sjacobs return (PAPI_TEMPORARY_ERROR); 66355b4669Sjacobs } 67355b4669Sjacobs if (iread(fd, string, size) != size) { 68355b4669Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST, 69355b4669Sjacobs "read failed: lang\n"); 70355b4669Sjacobs return (PAPI_BAD_REQUEST); 71355b4669Sjacobs } 72355b4669Sjacobs 73355b4669Sjacobs /* read the text */ 74355b4669Sjacobs if (iread(fd, &size, 2) != 2) { 75355b4669Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST, 76355b4669Sjacobs "read failed: text len\n"); 77355b4669Sjacobs return (PAPI_BAD_REQUEST); 78355b4669Sjacobs } 79355b4669Sjacobs size = (uint16_t)ntohs(size); 80355b4669Sjacobs 81355b4669Sjacobs if ((string = alloca(size + 1)) == NULL) { 82355b4669Sjacobs ipp_set_status(message, PAPI_TEMPORARY_ERROR, 83355b4669Sjacobs "Memory allocation failed"); 84355b4669Sjacobs return (PAPI_TEMPORARY_ERROR); 85355b4669Sjacobs } 86355b4669Sjacobs if (iread(fd, string, size) != size) { 87355b4669Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST, 88355b4669Sjacobs "read failed: text\n"); 89355b4669Sjacobs return (PAPI_BAD_REQUEST); 90355b4669Sjacobs } 91355b4669Sjacobs 92355b4669Sjacobs return (PAPI_OK); 93355b4669Sjacobs } 94355b4669Sjacobs 95355b4669Sjacobs 96355b4669Sjacobs static struct { 97355b4669Sjacobs int8_t ipp_type; 98355b4669Sjacobs int8_t size; 99355b4669Sjacobs } type_info[] = { 100355b4669Sjacobs { VTAG_INTEGER, 4 }, 101355b4669Sjacobs { VTAG_ENUM, 4 }, 102355b4669Sjacobs { VTAG_BOOLEAN, 1 }, 103355b4669Sjacobs { VTAG_RANGE_OF_INTEGER, 8 }, 104355b4669Sjacobs { VTAG_RESOLUTION, 9 }, 105355b4669Sjacobs { VTAG_DATE_TIME, 11 }, 106355b4669Sjacobs { DTAG_MIN, 0 } 107355b4669Sjacobs }; 108355b4669Sjacobs 109355b4669Sjacobs /* verify that the IPP type and size are compatible */ 110355b4669Sjacobs static int 111355b4669Sjacobs validate_length(int8_t type, int8_t size) 112355b4669Sjacobs { 113355b4669Sjacobs int i; 114355b4669Sjacobs 115355b4669Sjacobs for (i = 0; type_info[i].ipp_type != DTAG_MIN; i++) 116355b4669Sjacobs if (type_info[i].ipp_type == type) 117355b4669Sjacobs return ((type_info[i].size == size) ? 0 : -1); 118355b4669Sjacobs return (0); 119355b4669Sjacobs } 120355b4669Sjacobs 121355b4669Sjacobs /* convert tyep IPP type to a type that is marginally compatible */ 122355b4669Sjacobs static int8_t 123355b4669Sjacobs base_type(int8_t i) 124355b4669Sjacobs { 125355b4669Sjacobs switch (i) { 126355b4669Sjacobs case VTAG_ENUM: 127355b4669Sjacobs case VTAG_INTEGER: 128355b4669Sjacobs return (VTAG_INTEGER); 129355b4669Sjacobs case VTAG_URI: 130355b4669Sjacobs case VTAG_OCTET_STRING: 131355b4669Sjacobs case VTAG_TEXT_WITHOUT_LANGUAGE: 132355b4669Sjacobs case VTAG_URI_SCHEME: 133355b4669Sjacobs case VTAG_CHARSET: 134355b4669Sjacobs case VTAG_NATURAL_LANGUAGE: 135355b4669Sjacobs case VTAG_MIME_MEDIA_TYPE: 136355b4669Sjacobs case VTAG_NAME_WITHOUT_LANGUAGE: 137355b4669Sjacobs case VTAG_KEYWORD: 138355b4669Sjacobs return (VTAG_TEXT_WITHOUT_LANGUAGE); 139355b4669Sjacobs case VTAG_BOOLEAN: 140355b4669Sjacobs case VTAG_RANGE_OF_INTEGER: 141355b4669Sjacobs case VTAG_DATE_TIME: 142355b4669Sjacobs case VTAG_RESOLUTION: 143355b4669Sjacobs default: 144355b4669Sjacobs return (i); 145355b4669Sjacobs } 146355b4669Sjacobs } 147355b4669Sjacobs 148355b4669Sjacobs /* verify that the IPP type is correct for the named attribute */ 149355b4669Sjacobs static papi_status_t 150355b4669Sjacobs validate_type(char *name, int8_t type) 151355b4669Sjacobs { 152355b4669Sjacobs int8_t t = name_to_ipp_type(name); 153355b4669Sjacobs 154355b4669Sjacobs if (t == 0) /* The attribute is not defined in the RFC */ 155355b4669Sjacobs return (PAPI_NOT_FOUND); 156355b4669Sjacobs else if (t == type) /* The supplied type matched the RFC type */ 157355b4669Sjacobs return (PAPI_OK); 158355b4669Sjacobs else { /* The supplied type doesn't match the RFC */ 159355b4669Sjacobs if (base_type(t) == base_type(type)) 160355b4669Sjacobs return (PAPI_OK); 161355b4669Sjacobs 162355b4669Sjacobs return (PAPI_CONFLICT); 163355b4669Sjacobs } 164355b4669Sjacobs } 165355b4669Sjacobs 166355b4669Sjacobs /* verify that the IPP value is within specification for the named attribute */ 167355b4669Sjacobs static int 168355b4669Sjacobs validate_value(papi_attribute_t ***message, char *name, int8_t type, ...) 169355b4669Sjacobs { 170355b4669Sjacobs #define within(a, b, c) ((b >= a) && (b <= c)) 171355b4669Sjacobs va_list ap; 172355b4669Sjacobs int rc = -1; 173355b4669Sjacobs int min = min_val_len(type, name), 174355b4669Sjacobs max = max_val_len(type, name); 175355b4669Sjacobs char buf[64]; /* For _ipp_<...>_string() */ 176355b4669Sjacobs 177355b4669Sjacobs va_start(ap, type); 178355b4669Sjacobs switch (type) { 179355b4669Sjacobs case VTAG_ENUM: 180355b4669Sjacobs case VTAG_INTEGER: { 181355b4669Sjacobs int32_t i = (int32_t)va_arg(ap, int32_t); 182355b4669Sjacobs 183355b4669Sjacobs if (within(min, i, max)) 184355b4669Sjacobs rc = 0; 185355b4669Sjacobs else 186355b4669Sjacobs ipp_set_status(message, PAPI_BAD_ARGUMENT, 187355b4669Sjacobs "%s(%s): %d: out of range (%d - %d)", name, 188355b4669Sjacobs _ipp_tag_string(type), i, min, max); 189355b4669Sjacobs } 190355b4669Sjacobs break; 191355b4669Sjacobs case VTAG_BOOLEAN: { 192355b4669Sjacobs int8_t v = (int8_t)va_arg(ap, int); 193355b4669Sjacobs 194355b4669Sjacobs if (within(0, v, 1)) 195355b4669Sjacobs rc = 0; 196355b4669Sjacobs else 197355b4669Sjacobs ipp_set_status(message, PAPI_BAD_ARGUMENT, 198355b4669Sjacobs "%s(%s): %d: out of range (0 - 1)", name, 199355b4669Sjacobs _ipp_tag_string(type), v); 200355b4669Sjacobs } 201355b4669Sjacobs break; 202355b4669Sjacobs case VTAG_RANGE_OF_INTEGER: { 203355b4669Sjacobs int32_t lower = (int32_t)va_arg(ap, int32_t); 204355b4669Sjacobs int32_t upper = (int32_t)va_arg(ap, int32_t); 205355b4669Sjacobs 206355b4669Sjacobs if (within(min, lower, max) && 207355b4669Sjacobs within(min, upper, max)) 208355b4669Sjacobs rc = 0; 209355b4669Sjacobs else 210355b4669Sjacobs ipp_set_status(message, PAPI_BAD_ARGUMENT, 211355b4669Sjacobs "%s(%s): %d - %d: out of range (%d - %d)", name, 212355b4669Sjacobs _ipp_tag_string(type), lower, upper, min, max); 213355b4669Sjacobs } 214355b4669Sjacobs break; 215355b4669Sjacobs case VTAG_URI: 216355b4669Sjacobs case VTAG_OCTET_STRING: 217355b4669Sjacobs case VTAG_TEXT_WITHOUT_LANGUAGE: 218355b4669Sjacobs case VTAG_URI_SCHEME: 219355b4669Sjacobs case VTAG_CHARSET: 220355b4669Sjacobs case VTAG_NATURAL_LANGUAGE: 221355b4669Sjacobs case VTAG_MIME_MEDIA_TYPE: 222355b4669Sjacobs case VTAG_NAME_WITHOUT_LANGUAGE: { 223355b4669Sjacobs char *v = (char *)va_arg(ap, char *); 224355b4669Sjacobs 225355b4669Sjacobs if (strlen(v) < max) 226355b4669Sjacobs rc = 0; 227355b4669Sjacobs else 228355b4669Sjacobs ipp_set_status(message, PAPI_BAD_ARGUMENT, 229355b4669Sjacobs "%s(%s): %s: too long (max length: %d)", name, 230355b4669Sjacobs _ipp_tag_string(type), v, max); 231355b4669Sjacobs } 232355b4669Sjacobs break; 233355b4669Sjacobs case VTAG_KEYWORD: { 234355b4669Sjacobs char *v = (char *)va_arg(ap, char *); 235355b4669Sjacobs 236355b4669Sjacobs if (strlen(v) >= max) 237355b4669Sjacobs ipp_set_status(message, PAPI_BAD_ARGUMENT, 238355b4669Sjacobs "%s(%s): %s: too long (max length: %d)", name, 239355b4669Sjacobs _ipp_tag_string(type), v, max); 240355b4669Sjacobs else if (is_keyword(v) == 0) 241355b4669Sjacobs ipp_set_status(message, PAPI_BAD_ARGUMENT, 242355b4669Sjacobs "%s(%s): %s: invalid keyword", name, 243355b4669Sjacobs _ipp_tag_string(type), v); 244355b4669Sjacobs else 245355b4669Sjacobs rc = 0; 246355b4669Sjacobs } 247355b4669Sjacobs break; 248355b4669Sjacobs case VTAG_DATE_TIME: 249355b4669Sjacobs case VTAG_RESOLUTION: 250355b4669Sjacobs default: 251355b4669Sjacobs rc = 0; 252355b4669Sjacobs } 253355b4669Sjacobs va_end(ap); 254355b4669Sjacobs 255355b4669Sjacobs return (rc); 256355b4669Sjacobs #undef within 257355b4669Sjacobs } 258355b4669Sjacobs 259355b4669Sjacobs /* 260355b4669Sjacobs * read_attr_group() reads in enough of the message data to parse an entire 261355b4669Sjacobs * attribute group. Since to determine that the group is finished you have to 262355b4669Sjacobs * read the character that determines the type of the next group, this function 263355b4669Sjacobs * must return that character, in order that our caller knows how to call us for 264355b4669Sjacobs * the next group. Thus type is used both as an input parameter (the type of 265355b4669Sjacobs * attribute group to read in) and an output parameter (the type of the next 266355b4669Sjacobs * attribute group). 267355b4669Sjacobs */ 268355b4669Sjacobs 269355b4669Sjacobs static papi_status_t 270355b4669Sjacobs ipp_read_attribute_group(ipp_reader_t iread, void *fd, int8_t *type, 271355b4669Sjacobs papi_attribute_t ***message) 272355b4669Sjacobs { 273355b4669Sjacobs int8_t value_tag; 274355b4669Sjacobs uint16_t name_length, value_length; 275355b4669Sjacobs papi_attribute_t **attributes = NULL; 276355b4669Sjacobs char *name = NULL; 277355b4669Sjacobs int i; 278355b4669Sjacobs char buf[64]; /* For _ipp_<...>_string() */ 279355b4669Sjacobs 280355b4669Sjacobs /* 281355b4669Sjacobs * RFC2910 3.3 says we need to handle `An expected but missing 282355b4669Sjacobs * "begin-attribute-group-tag" field. How? 283355b4669Sjacobs */ 284355b4669Sjacobs if (*type > DTAG_MAX) { 285355b4669Sjacobs /* Scream bloody murder, or assign a new type? */ 286355b4669Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST, 287355b4669Sjacobs "Bad attribute group tag 0x%.2hx (%s)", 288355b4669Sjacobs *type, _ipp_tag_string(*type)); 289355b4669Sjacobs return (PAPI_BAD_REQUEST); 290355b4669Sjacobs } 291355b4669Sjacobs 292355b4669Sjacobs /* This loops through *values* not *attributes*! */ 293355b4669Sjacobs for (i = 0; ; i++) { 294355b4669Sjacobs papi_status_t valid = PAPI_OK; 295355b4669Sjacobs if (iread(fd, &value_tag, 1) != 1) { 296355b4669Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST, 297355b4669Sjacobs "bad read: value tag\n"); 298355b4669Sjacobs return (PAPI_BAD_REQUEST); 299355b4669Sjacobs } 300355b4669Sjacobs /* are we done with this group ? */ 301355b4669Sjacobs if (value_tag <= DTAG_MAX) 302355b4669Sjacobs break; 303355b4669Sjacobs 304355b4669Sjacobs if (iread(fd, &name_length, 2) != 2) { 305355b4669Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST, 306355b4669Sjacobs "bad read: name length\n"); 307355b4669Sjacobs return (PAPI_BAD_REQUEST); 308355b4669Sjacobs } 309355b4669Sjacobs name_length = (uint16_t)ntohs(name_length); 310355b4669Sjacobs 311355b4669Sjacobs /* Not just another value for the previous attribute */ 312355b4669Sjacobs if (name_length != 0) { 313355b4669Sjacobs if ((name = alloca(name_length + 1)) == NULL) { 314355b4669Sjacobs ipp_set_status(message, PAPI_TEMPORARY_ERROR, 315355b4669Sjacobs "alloca(): failed\n"); 316355b4669Sjacobs return (PAPI_TEMPORARY_ERROR); 317355b4669Sjacobs } 318355b4669Sjacobs (void) memset(name, 0, name_length + 1); 319355b4669Sjacobs 320355b4669Sjacobs if (iread(fd, name, name_length) != name_length) { 321355b4669Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST, 322355b4669Sjacobs "bad read: name\n"); 323355b4669Sjacobs return (PAPI_BAD_REQUEST); 324355b4669Sjacobs } 325355b4669Sjacobs } 326355b4669Sjacobs 327355b4669Sjacobs valid = validate_type(name, value_tag); 328355b4669Sjacobs if ((valid != PAPI_OK) && (valid != PAPI_NOT_FOUND)) 329355b4669Sjacobs ipp_set_status(message, valid, "%s(%s): %s", name, 330355b4669Sjacobs _ipp_tag_string(value_tag), 331355b4669Sjacobs papiStatusString(valid)); 332355b4669Sjacobs 333355b4669Sjacobs if (iread(fd, &value_length, 2) != 2) { 334355b4669Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST, 335355b4669Sjacobs "bad read: value length\n"); 336355b4669Sjacobs return (PAPI_BAD_REQUEST); 337355b4669Sjacobs } 338355b4669Sjacobs value_length = (uint16_t)ntohs(value_length); 339355b4669Sjacobs 340355b4669Sjacobs if (validate_length(value_tag, value_length) < 0) { 341355b4669Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST, 342355b4669Sjacobs "Bad value length (%d) for type %s", 343355b4669Sjacobs value_length, _ipp_tag_string(value_tag)); 344355b4669Sjacobs return (PAPI_BAD_REQUEST); 345355b4669Sjacobs } 346355b4669Sjacobs 347355b4669Sjacobs switch (value_tag) { 348355b4669Sjacobs case VTAG_INTEGER: 349355b4669Sjacobs case VTAG_ENUM: { 350355b4669Sjacobs int32_t v; 351355b4669Sjacobs 352355b4669Sjacobs if (iread(fd, &v, value_length) != value_length) { 353355b4669Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST, 354355b4669Sjacobs "bad read: int/enum\n"); 355355b4669Sjacobs return (PAPI_BAD_REQUEST); 356355b4669Sjacobs } 357355b4669Sjacobs v = (int32_t)ntohl(v); 358355b4669Sjacobs (void) validate_value(message, name, value_tag, v); 359355b4669Sjacobs papiAttributeListAddInteger(&attributes, 360355b4669Sjacobs PAPI_ATTR_APPEND, name, v); 361355b4669Sjacobs 362355b4669Sjacobs } 363355b4669Sjacobs break; 364355b4669Sjacobs case VTAG_BOOLEAN: { 365355b4669Sjacobs int8_t v; 366355b4669Sjacobs 367355b4669Sjacobs if (iread(fd, &v, value_length) != value_length) { 368355b4669Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST, 369355b4669Sjacobs "bad read: boolean\n"); 370355b4669Sjacobs return (PAPI_BAD_REQUEST); 371355b4669Sjacobs } 372355b4669Sjacobs (void) validate_value(message, name, value_tag, v); 373355b4669Sjacobs papiAttributeListAddBoolean(&attributes, 374355b4669Sjacobs PAPI_ATTR_APPEND, name, v); 375355b4669Sjacobs } 376355b4669Sjacobs break; 377355b4669Sjacobs case VTAG_RANGE_OF_INTEGER: { 378355b4669Sjacobs int32_t min, max; 379355b4669Sjacobs 380355b4669Sjacobs if (iread(fd, &min, 4) != 4) { 381355b4669Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST, 382355b4669Sjacobs "bad read: min\n"); 383355b4669Sjacobs return (PAPI_BAD_REQUEST); 384355b4669Sjacobs } 385355b4669Sjacobs if (iread(fd, &max, 4) != 4) { 386355b4669Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST, 387355b4669Sjacobs "bad read: max\n"); 388355b4669Sjacobs return (PAPI_BAD_REQUEST); 389355b4669Sjacobs } 390355b4669Sjacobs min = (int32_t)ntohl(min); 391355b4669Sjacobs max = (int32_t)ntohl(max); 392355b4669Sjacobs (void) validate_value(message, name, value_tag, 393355b4669Sjacobs min, max); 394355b4669Sjacobs papiAttributeListAddRange(&attributes, PAPI_ATTR_APPEND, 395355b4669Sjacobs name, min, max); 396355b4669Sjacobs } 397355b4669Sjacobs break; 398355b4669Sjacobs case VTAG_RESOLUTION: { 399355b4669Sjacobs int32_t x, y; 400355b4669Sjacobs int8_t units; 401355b4669Sjacobs 402355b4669Sjacobs if (iread(fd, &x, 4) != 4) { 403355b4669Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST, 404355b4669Sjacobs "bad read: x\n"); 405355b4669Sjacobs return (PAPI_BAD_REQUEST); 406355b4669Sjacobs } 407355b4669Sjacobs if (iread(fd, &y, 4) != 4) { 408355b4669Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST, 409355b4669Sjacobs "bad read: y\n"); 410355b4669Sjacobs return (PAPI_BAD_REQUEST); 411355b4669Sjacobs } 412355b4669Sjacobs if (iread(fd, &units, 1) != 1) { 413355b4669Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST, 414355b4669Sjacobs "bad read: units\n"); 415355b4669Sjacobs return (PAPI_BAD_REQUEST); 416355b4669Sjacobs } 417355b4669Sjacobs x = (int32_t)ntohl(x); 418355b4669Sjacobs y = (int32_t)ntohl(y); 419355b4669Sjacobs papiAttributeListAddResolution(&attributes, 420355b4669Sjacobs PAPI_ATTR_APPEND, name, x, y, 421355b4669Sjacobs (papi_resolution_unit_t)units); 422355b4669Sjacobs } 423355b4669Sjacobs break; 424355b4669Sjacobs case VTAG_DATE_TIME: { 425355b4669Sjacobs struct tm tm; 426355b4669Sjacobs time_t v; 427355b4669Sjacobs int8_t c; 428355b4669Sjacobs uint16_t s; 429355b4669Sjacobs 430355b4669Sjacobs (void) memset(&tm, 0, sizeof (tm)); 431355b4669Sjacobs if (iread(fd, &s, 2) != 2) { 432355b4669Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST, 433355b4669Sjacobs "bad read: year\n"); 434355b4669Sjacobs return (PAPI_BAD_REQUEST); 435355b4669Sjacobs } 436355b4669Sjacobs tm.tm_year = (uint16_t)ntohs(s) - 1900; 437355b4669Sjacobs if (iread(fd, &c, 1) != 1) { 438355b4669Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST, 439355b4669Sjacobs "bad read: month\n"); 440355b4669Sjacobs return (PAPI_BAD_REQUEST); 441355b4669Sjacobs } 442355b4669Sjacobs tm.tm_mon = c - 1; 443355b4669Sjacobs if (iread(fd, &c, 1) != 1) { 444355b4669Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST, 445355b4669Sjacobs "bad read: day\n"); 446355b4669Sjacobs return (PAPI_BAD_REQUEST); 447355b4669Sjacobs } 448355b4669Sjacobs tm.tm_mday = c; 449355b4669Sjacobs if (iread(fd, &c, 1) != 1) { 450355b4669Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST, 451355b4669Sjacobs "bad read: hour\n"); 452355b4669Sjacobs return (PAPI_BAD_REQUEST); 453355b4669Sjacobs } 454355b4669Sjacobs tm.tm_hour = c; 455355b4669Sjacobs if (iread(fd, &c, 1) != 1) { 456355b4669Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST, 457355b4669Sjacobs "bad read: minutes\n"); 458355b4669Sjacobs return (PAPI_BAD_REQUEST); 459355b4669Sjacobs } 460355b4669Sjacobs tm.tm_min = c; 461355b4669Sjacobs if (iread(fd, &c, 1) != 1) { 462355b4669Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST, 463355b4669Sjacobs "bad read: seconds\n"); 464355b4669Sjacobs return (PAPI_BAD_REQUEST); 465355b4669Sjacobs } 466355b4669Sjacobs tm.tm_sec = c; 467355b4669Sjacobs if (iread(fd, &c, 1) != 1) { 468355b4669Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST, 469355b4669Sjacobs "bad read: decisec\n"); 470355b4669Sjacobs return (PAPI_BAD_REQUEST); 471355b4669Sjacobs } 472355b4669Sjacobs /* tm.deciseconds = c; */ 473355b4669Sjacobs if (iread(fd, &c, 1) != 1) { 474355b4669Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST, 475355b4669Sjacobs "bad read: utc_dir\n"); 476355b4669Sjacobs return (PAPI_BAD_REQUEST); 477355b4669Sjacobs } 478355b4669Sjacobs /* tm.utc_dir = c; */ 479355b4669Sjacobs if (iread(fd, &c, 1) != 1) { 480355b4669Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST, 481355b4669Sjacobs "bad read: utc_hour\n"); 482355b4669Sjacobs return (PAPI_BAD_REQUEST); 483355b4669Sjacobs } 484355b4669Sjacobs /* tm.utc_hours = c; */ 485355b4669Sjacobs if (iread(fd, &c, 1) != 1) { 486355b4669Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST, 487355b4669Sjacobs "bad read: utc_min\n"); 488355b4669Sjacobs return (PAPI_BAD_REQUEST); 489355b4669Sjacobs } 490355b4669Sjacobs /* tm.utc_minutes = c; */ 491355b4669Sjacobs 492355b4669Sjacobs v = mktime(&tm); 493355b4669Sjacobs 494355b4669Sjacobs (void) validate_value(message, name, value_tag, v); 495355b4669Sjacobs papiAttributeListAddDatetime(&attributes, 496355b4669Sjacobs PAPI_ATTR_APPEND, name, v); 497355b4669Sjacobs } 498355b4669Sjacobs break; 499355b4669Sjacobs case VTAG_NAME_WITH_LANGUAGE: 500355b4669Sjacobs case VTAG_TEXT_WITH_LANGUAGE: 501355b4669Sjacobs /* 502355b4669Sjacobs * we are dropping this because we don't support 503355b4669Sjacobs * name with language at this time. 504355b4669Sjacobs */ 505355b4669Sjacobs (void) read_name_with_language(iread, fd, message); 506355b4669Sjacobs break; 507355b4669Sjacobs case VTAG_NAME_WITHOUT_LANGUAGE: 508355b4669Sjacobs case VTAG_TEXT_WITHOUT_LANGUAGE: 509355b4669Sjacobs case VTAG_URI: 510355b4669Sjacobs case VTAG_KEYWORD: 511355b4669Sjacobs case VTAG_CHARSET: { 512355b4669Sjacobs char *v; 513355b4669Sjacobs 514355b4669Sjacobs if ((v = calloc(1, value_length + 1)) == NULL) { 515355b4669Sjacobs ipp_set_status(message, PAPI_TEMPORARY_ERROR, 516355b4669Sjacobs "calloc(): failed\n"); 517355b4669Sjacobs return (PAPI_TEMPORARY_ERROR); 518355b4669Sjacobs } 519355b4669Sjacobs #ifdef NOTDEF 520355b4669Sjacobs if (iread(fd, v, value_length) != value_length) { 521355b4669Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST, 522355b4669Sjacobs "bad read: stringy\n"); 523355b4669Sjacobs return (PAPI_BAD_REQUEST); 524355b4669Sjacobs } 525355b4669Sjacobs #else 526355b4669Sjacobs { 527355b4669Sjacobs int rc, i = value_length; 528355b4669Sjacobs char *p = v; 529355b4669Sjacobs 530355b4669Sjacobs while ((rc = iread(fd, p, i)) != i) { 531355b4669Sjacobs if (rc <= 0) { 532355b4669Sjacobs ipp_set_status(message, 533355b4669Sjacobs PAPI_BAD_REQUEST, 534355b4669Sjacobs "bad read: stringy\n"); 535355b4669Sjacobs return (PAPI_BAD_REQUEST); 536355b4669Sjacobs } 537355b4669Sjacobs i -= rc; 538355b4669Sjacobs p += rc; 539355b4669Sjacobs } 540355b4669Sjacobs } 541355b4669Sjacobs #endif 542355b4669Sjacobs (void) validate_value(message, name, value_tag, v); 543355b4669Sjacobs papiAttributeListAddString(&attributes, 544355b4669Sjacobs PAPI_ATTR_APPEND, name, v); 545355b4669Sjacobs } 546355b4669Sjacobs break; 547355b4669Sjacobs case VTAG_UNKNOWN: 548355b4669Sjacobs case VTAG_NOVALUE: 549355b4669Sjacobs case VTAG_UNSUPPORTED: 550355b4669Sjacobs papiAttributeListAddValue(&attributes, PAPI_ATTR_EXCL, 551355b4669Sjacobs name, PAPI_COLLECTION, NULL); 552355b4669Sjacobs break; 553355b4669Sjacobs default: { 554355b4669Sjacobs char *v; 555355b4669Sjacobs 556355b4669Sjacobs if ((v = calloc(1, value_length + 1)) == NULL) { 557355b4669Sjacobs ipp_set_status(message, PAPI_TEMPORARY_ERROR, 558355b4669Sjacobs "calloc(): failed\n"); 559355b4669Sjacobs return (PAPI_TEMPORARY_ERROR); 560355b4669Sjacobs } 561355b4669Sjacobs if (iread(fd, v, value_length) != value_length) { 562355b4669Sjacobs ipp_set_status(message, PAPI_BAD_REQUEST, 563355b4669Sjacobs "bad read: other\n"); 564355b4669Sjacobs return (PAPI_BAD_REQUEST); 565355b4669Sjacobs } 566355b4669Sjacobs papiAttributeListAddString(&attributes, 567355b4669Sjacobs PAPI_ATTR_APPEND, name, v); 568355b4669Sjacobs } 569355b4669Sjacobs break; 570355b4669Sjacobs } 571355b4669Sjacobs } 572355b4669Sjacobs 573355b4669Sjacobs if (attributes != NULL) { 574355b4669Sjacobs char name[32]; 575355b4669Sjacobs 576355b4669Sjacobs (void) ipp_tag_string(*type, name, sizeof (name)); 577355b4669Sjacobs papiAttributeListAddCollection(message, PAPI_ATTR_APPEND, name, 578355b4669Sjacobs attributes); 579355b4669Sjacobs } 580355b4669Sjacobs 581355b4669Sjacobs *type = value_tag; 582355b4669Sjacobs 583355b4669Sjacobs return (PAPI_OK); 584355b4669Sjacobs } 585355b4669Sjacobs 586355b4669Sjacobs 587355b4669Sjacobs static papi_status_t 588355b4669Sjacobs ipp_read_header(ipp_reader_t iread, void *fd, papi_attribute_t ***message, 589355b4669Sjacobs char type) 590355b4669Sjacobs { 591355b4669Sjacobs char *attr_name = "status-code"; /* default to a response */ 592355b4669Sjacobs char buf[8]; 593355b4669Sjacobs int8_t c; 594355b4669Sjacobs uint16_t s; 595355b4669Sjacobs int32_t i; 596355b4669Sjacobs 597355b4669Sjacobs if ((iread == NULL) || (fd == NULL) || (message == NULL)) 598355b4669Sjacobs return (PAPI_BAD_ARGUMENT); 599355b4669Sjacobs 600355b4669Sjacobs /* 601355b4669Sjacobs * Apache 1.X uses the buffer supplied to it's read call to read in 602355b4669Sjacobs * the chunk size when chunking is used. This causes problems 603355b4669Sjacobs * reading the header a piece at a time, because we don't have 604355b4669Sjacobs * enough room to read in the chunk size prior to reading the 605355b4669Sjacobs * chunk. 606355b4669Sjacobs */ 607355b4669Sjacobs 608355b4669Sjacobs if (iread(fd, buf, 8) != 8) 609355b4669Sjacobs return (PAPI_BAD_REQUEST); 610355b4669Sjacobs 611355b4669Sjacobs c = buf[0]; 612355b4669Sjacobs (void) papiAttributeListAddInteger(message, PAPI_ATTR_REPLACE, 613355b4669Sjacobs "version-major", c); 614355b4669Sjacobs 615355b4669Sjacobs c = buf[1]; 616355b4669Sjacobs (void) papiAttributeListAddInteger(message, PAPI_ATTR_REPLACE, 617355b4669Sjacobs "version-minor", c); 618355b4669Sjacobs 619355b4669Sjacobs memcpy(&s, &buf[2], 2); 620355b4669Sjacobs s = (uint16_t)ntohs(s); 621355b4669Sjacobs if (type == IPP_TYPE_REQUEST) 622355b4669Sjacobs attr_name = "operation-id"; 623355b4669Sjacobs (void) papiAttributeListAddInteger(message, PAPI_ATTR_REPLACE, 624355b4669Sjacobs attr_name, s); 625355b4669Sjacobs 626*c40965e4Sjacobs memcpy(&i, &buf[4], 4); 627355b4669Sjacobs i = (uint32_t)ntohl(i); 628355b4669Sjacobs (void) papiAttributeListAddInteger(message, PAPI_ATTR_REPLACE, 629355b4669Sjacobs "request-id", i); 630355b4669Sjacobs 631355b4669Sjacobs return (PAPI_OK); 632355b4669Sjacobs } 633355b4669Sjacobs 634355b4669Sjacobs static papi_status_t 635355b4669Sjacobs ipp_read_attribute_groups(ipp_reader_t iread, void *fd, 636355b4669Sjacobs papi_attribute_t ***message) 637355b4669Sjacobs { 638355b4669Sjacobs papi_status_t result = PAPI_OK; 639355b4669Sjacobs int8_t tag; 640355b4669Sjacobs 641355b4669Sjacobs /* start reading the attribute groups */ 642355b4669Sjacobs if (iread(fd, &tag, 1) != 1) /* prime the pump */ 643355b4669Sjacobs return (PAPI_BAD_REQUEST); 644355b4669Sjacobs 645355b4669Sjacobs while ((tag != DTAG_END_OF_ATTRIBUTES) && (result == PAPI_OK)) { 646355b4669Sjacobs result = ipp_read_attribute_group(iread, fd, &tag, message); 647355b4669Sjacobs } 648355b4669Sjacobs 649355b4669Sjacobs return (result); 650355b4669Sjacobs } 651355b4669Sjacobs 652355b4669Sjacobs papi_status_t 653355b4669Sjacobs ipp_read_message(ipp_reader_t iread, void *fd, papi_attribute_t ***message, 654355b4669Sjacobs char type) 655355b4669Sjacobs { 656355b4669Sjacobs papi_status_t result = PAPI_OK; 657355b4669Sjacobs 658355b4669Sjacobs if ((iread == NULL) || (fd == NULL) || (message == NULL)) 659355b4669Sjacobs return (PAPI_BAD_ARGUMENT); 660355b4669Sjacobs 661355b4669Sjacobs result = ipp_read_header(iread, fd, message, type); 662355b4669Sjacobs if (result == PAPI_OK) 663355b4669Sjacobs result = ipp_read_attribute_groups(iread, fd, message); 664355b4669Sjacobs 665355b4669Sjacobs return (result); 666355b4669Sjacobs } 667