1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * Miscellaneous Utilities 31*7c478bd9Sstevel@tonic-gate * 32*7c478bd9Sstevel@tonic-gate * slp_err: Error and information message dispatch, i18n'd 33*7c478bd9Sstevel@tonic-gate * slp_start_call: Marks a SLP handle as in-use 34*7c478bd9Sstevel@tonic-gate * slp_end_call: Marks a SLP handle as available 35*7c478bd9Sstevel@tonic-gate * slp_map_err: protocol to API error mapping 36*7c478bd9Sstevel@tonic-gate * slp_onlist: determines if a token is on a list 37*7c478bd9Sstevel@tonic-gate * slp_add2list: adds a token to a list 38*7c478bd9Sstevel@tonic-gate * slp_list_subtract: removes a token from a list 39*7c478bd9Sstevel@tonic-gate * slp_add_header: creates a SLP message header 40*7c478bd9Sstevel@tonic-gate * slp_get_length: gets the length field from a SLP header 41*7c478bd9Sstevel@tonic-gate * slp_set_length: sets the length field in a SLP header 42*7c478bd9Sstevel@tonic-gate * slp_header_get_sht: gets a 16 bit integer from a SLP header 43*7c478bd9Sstevel@tonic-gate * slp_header_set_sht: sets a 16 bit interger in a SLP header 44*7c478bd9Sstevel@tonic-gate * slp_header_length: calculates the length of a header, including the 45*7c478bd9Sstevel@tonic-gate * language tag 46*7c478bd9Sstevel@tonic-gate * slp_get_errcode: returns the error code from a SLP message 47*7c478bd9Sstevel@tonic-gate * slp_add_byte: encodes a byte into the given buffer 48*7c478bd9Sstevel@tonic-gate * slp_add_sht: encodes a 16-bit integer into the given buffer 49*7c478bd9Sstevel@tonic-gate * slp_add_string: encodes the given string into the given buffer 50*7c478bd9Sstevel@tonic-gate * slp_get_byte: decodes a byte from the given buffer 51*7c478bd9Sstevel@tonic-gate * slp_get_sht: decodes a 16-bit integer from the given buffer 52*7c478bd9Sstevel@tonic-gate * slp_get_string: decodes a string from the given buffer 53*7c478bd9Sstevel@tonic-gate */ 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate #include <stdio.h> 56*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 57*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 58*7c478bd9Sstevel@tonic-gate #include <syslog.h> 59*7c478bd9Sstevel@tonic-gate #include <string.h> 60*7c478bd9Sstevel@tonic-gate #include <thread.h> 61*7c478bd9Sstevel@tonic-gate #include <synch.h> 62*7c478bd9Sstevel@tonic-gate #include <errno.h> 63*7c478bd9Sstevel@tonic-gate #include <unistd.h> 64*7c478bd9Sstevel@tonic-gate #include <limits.h> 65*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 66*7c478bd9Sstevel@tonic-gate #include <libintl.h> 67*7c478bd9Sstevel@tonic-gate #include <slp-internal.h> 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate #define SLP_ERR_BUF_LEN 1024UL 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate /* 72*7c478bd9Sstevel@tonic-gate * Outputs an error message. priority is a syslog(3) priority. 73*7c478bd9Sstevel@tonic-gate */ 74*7c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 75*7c478bd9Sstevel@tonic-gate /* PRINTFLIKE4 */ 76*7c478bd9Sstevel@tonic-gate void slp_err(int priority, int id, char *func, char *inmsg, ...) { 77*7c478bd9Sstevel@tonic-gate static char buf[SLP_ERR_BUF_LEN]; 78*7c478bd9Sstevel@tonic-gate char *p, *msg; 79*7c478bd9Sstevel@tonic-gate size_t len; 80*7c478bd9Sstevel@tonic-gate va_list ap; 81*7c478bd9Sstevel@tonic-gate static mutex_t loglock = DEFAULTMUTEX; 82*7c478bd9Sstevel@tonic-gate va_start(ap, inmsg); 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&loglock); 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate /* i18n mapping */ 87*7c478bd9Sstevel@tonic-gate msg = dgettext("libslp", inmsg); 88*7c478bd9Sstevel@tonic-gate 89*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "libslp: %s: ", func); 90*7c478bd9Sstevel@tonic-gate len = strlen(buf); 91*7c478bd9Sstevel@tonic-gate p = &(buf[len]); 92*7c478bd9Sstevel@tonic-gate (void) vsnprintf(p, SLP_ERR_BUF_LEN - len, msg, ap); 93*7c478bd9Sstevel@tonic-gate va_end(ap); 94*7c478bd9Sstevel@tonic-gate syslog(priority, buf); 95*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&loglock); 96*7c478bd9Sstevel@tonic-gate } 97*7c478bd9Sstevel@tonic-gate 98*7c478bd9Sstevel@tonic-gate /* 99*7c478bd9Sstevel@tonic-gate * Start and end slp calls 100*7c478bd9Sstevel@tonic-gate * slp_start_call returns SLP_HANDLE_IN_USE if the handle is already 101*7c478bd9Sstevel@tonic-gate * being used, otherwise SLP_OK. 102*7c478bd9Sstevel@tonic-gate */ 103*7c478bd9Sstevel@tonic-gate SLPError slp_start_call(slp_handle_impl_t *hp) { 104*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&(hp->outcall_lock)); 105*7c478bd9Sstevel@tonic-gate if (hp->pending_outcall) { 106*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&(hp->outcall_lock)); 107*7c478bd9Sstevel@tonic-gate return (SLP_HANDLE_IN_USE); 108*7c478bd9Sstevel@tonic-gate } 109*7c478bd9Sstevel@tonic-gate hp->pending_outcall = SLP_TRUE; 110*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&(hp->outcall_lock)); 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate hp->cancel = 0; 113*7c478bd9Sstevel@tonic-gate return (SLP_OK); 114*7c478bd9Sstevel@tonic-gate } 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate void slp_end_call(slp_handle_impl_t *hp) { 117*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&(hp->outcall_lock)); 118*7c478bd9Sstevel@tonic-gate if (hp->close_on_end) { 119*7c478bd9Sstevel@tonic-gate /* SLPClose() called from callback */ 120*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&(hp->outcall_lock)); 121*7c478bd9Sstevel@tonic-gate slp_cleanup_handle(hp); 122*7c478bd9Sstevel@tonic-gate return; 123*7c478bd9Sstevel@tonic-gate } 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate hp->pending_outcall = SLP_FALSE; 126*7c478bd9Sstevel@tonic-gate (void) cond_signal(&(hp->outcall_cv)); 127*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&(hp->outcall_lock)); 128*7c478bd9Sstevel@tonic-gate } 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate /* 131*7c478bd9Sstevel@tonic-gate * Map a protocol error code to an API error code. 132*7c478bd9Sstevel@tonic-gate */ 133*7c478bd9Sstevel@tonic-gate SLPError slp_map_err(unsigned short proto_err) { 134*7c478bd9Sstevel@tonic-gate switch (proto_err) { 135*7c478bd9Sstevel@tonic-gate case 0: return (SLP_OK); 136*7c478bd9Sstevel@tonic-gate case 1: return (SLP_LANGUAGE_NOT_SUPPORTED); 137*7c478bd9Sstevel@tonic-gate case 2: return (SLP_PARSE_ERROR); 138*7c478bd9Sstevel@tonic-gate case 3: return (SLP_INVALID_REGISTRATION); 139*7c478bd9Sstevel@tonic-gate case 4: return (SLP_SCOPE_NOT_SUPPORTED); 140*7c478bd9Sstevel@tonic-gate case 6: return (SLP_AUTHENTICATION_ABSENT); 141*7c478bd9Sstevel@tonic-gate case 7: return (SLP_AUTHENTICATION_FAILED); 142*7c478bd9Sstevel@tonic-gate case 13: return (SLP_INVALID_UPDATE); 143*7c478bd9Sstevel@tonic-gate /* 144*7c478bd9Sstevel@tonic-gate * 9 (VER_NOT_SUPPORTED), 10 (INTERNAL_ERROR), 145*7c478bd9Sstevel@tonic-gate * 11 (DA_BUSY_NOW), 12 (OPTION_NOT_UNDERSTOOD), 146*7c478bd9Sstevel@tonic-gate * and 14 (RQST_NOT_SUPPORTED) 147*7c478bd9Sstevel@tonic-gate * should be handled internally by the API. 148*7c478bd9Sstevel@tonic-gate */ 149*7c478bd9Sstevel@tonic-gate default: return (SLP_INTERNAL_SYSTEM_ERROR); 150*7c478bd9Sstevel@tonic-gate } 151*7c478bd9Sstevel@tonic-gate } 152*7c478bd9Sstevel@tonic-gate 153*7c478bd9Sstevel@tonic-gate /* 154*7c478bd9Sstevel@tonic-gate * SLP List Management: 155*7c478bd9Sstevel@tonic-gate * SLP lists are comma separated lists of tokens. The following routines 156*7c478bd9Sstevel@tonic-gate * manage SLP lists, ensuring proper UTF-8 parsing. 157*7c478bd9Sstevel@tonic-gate */ 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate /* 160*7c478bd9Sstevel@tonic-gate * If 'item' is on 'list', returns 1, otherwise 0. 161*7c478bd9Sstevel@tonic-gate */ 162*7c478bd9Sstevel@tonic-gate int slp_onlist(const char *item, const char *list) { 163*7c478bd9Sstevel@tonic-gate char *p; 164*7c478bd9Sstevel@tonic-gate for (p = (char *)list; p; p++) { 165*7c478bd9Sstevel@tonic-gate char *s; 166*7c478bd9Sstevel@tonic-gate size_t span; 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate s = p; 169*7c478bd9Sstevel@tonic-gate p = slp_utf_strchr(p, ','); 170*7c478bd9Sstevel@tonic-gate span = (p ? (size_t)(p - s): strlen(s)); 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate if (strlen(item) != span) { 173*7c478bd9Sstevel@tonic-gate if (!p) 174*7c478bd9Sstevel@tonic-gate break; 175*7c478bd9Sstevel@tonic-gate else 176*7c478bd9Sstevel@tonic-gate continue; 177*7c478bd9Sstevel@tonic-gate } 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate if (strncasecmp(item, s, span) == 0) 180*7c478bd9Sstevel@tonic-gate return (1); 181*7c478bd9Sstevel@tonic-gate if (!p) 182*7c478bd9Sstevel@tonic-gate break; 183*7c478bd9Sstevel@tonic-gate } 184*7c478bd9Sstevel@tonic-gate return (0); 185*7c478bd9Sstevel@tonic-gate } 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate /* 188*7c478bd9Sstevel@tonic-gate * Adds item to *list if it is not already on it. If *list == NULL, 189*7c478bd9Sstevel@tonic-gate * creates a new list. When it grows the list, it will free *list, 190*7c478bd9Sstevel@tonic-gate * so *list must not be on the caller's stack. 'check_onlist' specifies 191*7c478bd9Sstevel@tonic-gate * whether to look to item on the current list. This is a small 192*7c478bd9Sstevel@tonic-gate * optimization for callers which are that item is not on *list, or 193*7c478bd9Sstevel@tonic-gate * which don't care about duplicates. 194*7c478bd9Sstevel@tonic-gate */ 195*7c478bd9Sstevel@tonic-gate void slp_add2list(const char *item, char **list, SLPBoolean check_onlist) { 196*7c478bd9Sstevel@tonic-gate if (!(*list)) { 197*7c478bd9Sstevel@tonic-gate if (!(*list = strdup(item))) 198*7c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "slp_add2list", "out of memory"); 199*7c478bd9Sstevel@tonic-gate return; 200*7c478bd9Sstevel@tonic-gate } 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate if (check_onlist) 203*7c478bd9Sstevel@tonic-gate /* no duplicates */ 204*7c478bd9Sstevel@tonic-gate if (slp_onlist(item, *list)) 205*7c478bd9Sstevel@tonic-gate return; 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate if (!(*list = realloc(*list, strlen(*list) + strlen(item) + 2))) { 208*7c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "slp_add2list", "out of memory"); 209*7c478bd9Sstevel@tonic-gate return; 210*7c478bd9Sstevel@tonic-gate } 211*7c478bd9Sstevel@tonic-gate (void) strcat(*list, ","); 212*7c478bd9Sstevel@tonic-gate (void) strcat(*list, item); 213*7c478bd9Sstevel@tonic-gate } 214*7c478bd9Sstevel@tonic-gate 215*7c478bd9Sstevel@tonic-gate /* 216*7c478bd9Sstevel@tonic-gate * Removes the first instance of item from *list. 217*7c478bd9Sstevel@tonic-gate * When it shrinks the list, it may free *list, so *list must not be on 218*7c478bd9Sstevel@tonic-gate * the caller's stack. 219*7c478bd9Sstevel@tonic-gate */ 220*7c478bd9Sstevel@tonic-gate void slp_list_subtract(const char *item, char **list) { 221*7c478bd9Sstevel@tonic-gate char *p, *s; 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate if (!*list || !slp_onlist(item, *list)) 224*7c478bd9Sstevel@tonic-gate return; 225*7c478bd9Sstevel@tonic-gate /* find item's location on the list */ 226*7c478bd9Sstevel@tonic-gate for (p = *list; p; p++) { 227*7c478bd9Sstevel@tonic-gate size_t span; 228*7c478bd9Sstevel@tonic-gate 229*7c478bd9Sstevel@tonic-gate s = p; 230*7c478bd9Sstevel@tonic-gate p = slp_utf_strchr(p, ','); 231*7c478bd9Sstevel@tonic-gate span = (p ? (size_t)(p - s) : strlen(s)); 232*7c478bd9Sstevel@tonic-gate if (strlen(item) != span) 233*7c478bd9Sstevel@tonic-gate continue; 234*7c478bd9Sstevel@tonic-gate if (strncasecmp(item, s, span) == 0) 235*7c478bd9Sstevel@tonic-gate break; 236*7c478bd9Sstevel@tonic-gate if (!p) 237*7c478bd9Sstevel@tonic-gate break; 238*7c478bd9Sstevel@tonic-gate } 239*7c478bd9Sstevel@tonic-gate if (!p && s == *list) { 240*7c478bd9Sstevel@tonic-gate /* item is only one on list */ 241*7c478bd9Sstevel@tonic-gate free(*list); 242*7c478bd9Sstevel@tonic-gate *list = NULL; 243*7c478bd9Sstevel@tonic-gate return; 244*7c478bd9Sstevel@tonic-gate } 245*7c478bd9Sstevel@tonic-gate if (!p) { 246*7c478bd9Sstevel@tonic-gate /* last one on list; just chop it off */ 247*7c478bd9Sstevel@tonic-gate s--; 248*7c478bd9Sstevel@tonic-gate *s = 0; 249*7c478bd9Sstevel@tonic-gate return; 250*7c478bd9Sstevel@tonic-gate } 251*7c478bd9Sstevel@tonic-gate /* either first on list, or somewhere in the middle */ 252*7c478bd9Sstevel@tonic-gate (void) strcpy(s, p + 1); 253*7c478bd9Sstevel@tonic-gate } 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate /* SLPv2 header management */ 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate /* 258*7c478bd9Sstevel@tonic-gate * Lays a SLP header into pcSendBuf, performing byte-ordering and bounds 259*7c478bd9Sstevel@tonic-gate * checking where necessary. 260*7c478bd9Sstevel@tonic-gate * pcLangTag: Language tag 261*7c478bd9Sstevel@tonic-gate * pcSendBuf: a buffer into which to write the composed header 262*7c478bd9Sstevel@tonic-gate * iSendBufSz: the size of pcSendBuf in bytes 263*7c478bd9Sstevel@tonic-gate * iFun: SLP V2 function number 264*7c478bd9Sstevel@tonic-gate * iLen: The length of the whole SLP message, in bytes 265*7c478bd9Sstevel@tonic-gate * piLen: a pointer to an int into which will be written the size of the 266*7c478bd9Sstevel@tonic-gate * header + the language tag (i.e. the offset at which the rest of 267*7c478bd9Sstevel@tonic-gate * the message should be written into pcSendBuf). 268*7c478bd9Sstevel@tonic-gate */ 269*7c478bd9Sstevel@tonic-gate SLPError slp_add_header(const char *pcLangTag, char *pcSendBuf, 270*7c478bd9Sstevel@tonic-gate size_t iSendBufSz, int iFun, 271*7c478bd9Sstevel@tonic-gate size_t iLen, size_t *piLen) { 272*7c478bd9Sstevel@tonic-gate unsigned short us, xid; 273*7c478bd9Sstevel@tonic-gate static unsigned short xid_seeded = 0; 274*7c478bd9Sstevel@tonic-gate 275*7c478bd9Sstevel@tonic-gate if (!xid_seeded) { 276*7c478bd9Sstevel@tonic-gate static mutex_t lock = DEFAULTMUTEX; 277*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&lock); 278*7c478bd9Sstevel@tonic-gate if (!xid_seeded) { 279*7c478bd9Sstevel@tonic-gate /* generate a seed based on our PID */ 280*7c478bd9Sstevel@tonic-gate long long pid = getpid(); 281*7c478bd9Sstevel@tonic-gate pid *= UINT_MAX; 282*7c478bd9Sstevel@tonic-gate (void) seed48((unsigned short *) &pid); 283*7c478bd9Sstevel@tonic-gate xid_seeded = 1; 284*7c478bd9Sstevel@tonic-gate } 285*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&lock); 286*7c478bd9Sstevel@tonic-gate } 287*7c478bd9Sstevel@tonic-gate /* squish the random value into an unsigned short */ 288*7c478bd9Sstevel@tonic-gate xid = (unsigned short) (lrand48() % USHRT_MAX); 289*7c478bd9Sstevel@tonic-gate xid = xid ? xid : 1; /* 0 is for DAs only */ 290*7c478bd9Sstevel@tonic-gate 291*7c478bd9Sstevel@tonic-gate us = (unsigned short) strlen(pcLangTag); 292*7c478bd9Sstevel@tonic-gate if ((SLP_HDRLEN + us) > iSendBufSz) 293*7c478bd9Sstevel@tonic-gate return (SLP_PARAMETER_BAD); 294*7c478bd9Sstevel@tonic-gate 295*7c478bd9Sstevel@tonic-gate (void) memset(pcSendBuf, 0, SLP_HDRLEN); 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate slp_set_version(pcSendBuf, SLP_VERSION); 298*7c478bd9Sstevel@tonic-gate slp_set_function(pcSendBuf, (char)iFun); 299*7c478bd9Sstevel@tonic-gate slp_set_length(pcSendBuf, iLen); 300*7c478bd9Sstevel@tonic-gate slp_set_xid(pcSendBuf, xid); 301*7c478bd9Sstevel@tonic-gate slp_set_langlen(pcSendBuf, us); 302*7c478bd9Sstevel@tonic-gate (void) memcpy(&pcSendBuf[SLP_HDRLEN], pcLangTag, us); 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate *piLen = SLP_HDRLEN + us; 305*7c478bd9Sstevel@tonic-gate return (SLP_OK); 306*7c478bd9Sstevel@tonic-gate } 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate /* 309*7c478bd9Sstevel@tonic-gate * Retrieves the 24 bit int stored at 'off' offset into 'header'. 310*7c478bd9Sstevel@tonic-gate * Assumes 'header' is a valid SLP message header. 311*7c478bd9Sstevel@tonic-gate */ 312*7c478bd9Sstevel@tonic-gate unsigned int slp_header_get_int24(const char *header, size_t off) { 313*7c478bd9Sstevel@tonic-gate unsigned int len; 314*7c478bd9Sstevel@tonic-gate 315*7c478bd9Sstevel@tonic-gate len = ((unsigned int)(header[off] & 0xff)) << 16; 316*7c478bd9Sstevel@tonic-gate len += ((unsigned int)(header[off + 1] & 0xff)) << 8; 317*7c478bd9Sstevel@tonic-gate len += ((unsigned int)(header[off + 2] & 0xff)); 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate return (len); 320*7c478bd9Sstevel@tonic-gate } 321*7c478bd9Sstevel@tonic-gate 322*7c478bd9Sstevel@tonic-gate /* 323*7c478bd9Sstevel@tonic-gate * Sets a 24 bit int at the location in 'header' 'off' bytes 324*7c478bd9Sstevel@tonic-gate * offset into the header. 325*7c478bd9Sstevel@tonic-gate * Assumes 'header' is a valid SLP message header. 326*7c478bd9Sstevel@tonic-gate */ 327*7c478bd9Sstevel@tonic-gate void slp_header_set_int24(char *header, unsigned int len, size_t off) { 328*7c478bd9Sstevel@tonic-gate header[off] = (unsigned char) ((len & 0xff0000) >> 16); 329*7c478bd9Sstevel@tonic-gate header[off + 1] = (unsigned char) ((len & 0xff00) >> 8); 330*7c478bd9Sstevel@tonic-gate header[off + 2] = (unsigned char) (len & 0xff); 331*7c478bd9Sstevel@tonic-gate } 332*7c478bd9Sstevel@tonic-gate 333*7c478bd9Sstevel@tonic-gate /* 334*7c478bd9Sstevel@tonic-gate * Retrieves the 16 bit integer stored at 'off' offset into 'header'. 335*7c478bd9Sstevel@tonic-gate * Assumes 'header' is a valid SLP message header. 336*7c478bd9Sstevel@tonic-gate */ 337*7c478bd9Sstevel@tonic-gate unsigned short slp_header_get_sht(const char *header, size_t off) { 338*7c478bd9Sstevel@tonic-gate unsigned short answer = 0; 339*7c478bd9Sstevel@tonic-gate (void) slp_get_sht(header, SLP_HDRLEN, &off, &answer); 340*7c478bd9Sstevel@tonic-gate return (answer); 341*7c478bd9Sstevel@tonic-gate } 342*7c478bd9Sstevel@tonic-gate 343*7c478bd9Sstevel@tonic-gate /* 344*7c478bd9Sstevel@tonic-gate * Sets a 16 bit interger at the location in 'header' 'off' bytes 345*7c478bd9Sstevel@tonic-gate * offset into the header. 346*7c478bd9Sstevel@tonic-gate * Assumes 'header' is a valid SLP message header. 347*7c478bd9Sstevel@tonic-gate */ 348*7c478bd9Sstevel@tonic-gate void slp_header_set_sht(char *header, unsigned short len, size_t off) { 349*7c478bd9Sstevel@tonic-gate (void) slp_add_sht(header, SLP_HDRLEN, len, &off); 350*7c478bd9Sstevel@tonic-gate } 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate /* 353*7c478bd9Sstevel@tonic-gate * Returns the total length of a SLP header associated with the SLP 354*7c478bd9Sstevel@tonic-gate * handle 'hp', including the language tag. 355*7c478bd9Sstevel@tonic-gate */ 356*7c478bd9Sstevel@tonic-gate size_t slp_header_length(slp_handle_impl_t *hp) { 357*7c478bd9Sstevel@tonic-gate return (SLP_HDRLEN + strlen(hp->locale)); 358*7c478bd9Sstevel@tonic-gate } 359*7c478bd9Sstevel@tonic-gate 360*7c478bd9Sstevel@tonic-gate /* 361*7c478bd9Sstevel@tonic-gate * Retrieves the error code for UA replies -- the errcode is always 362*7c478bd9Sstevel@tonic-gate * the first short after the header for these functions. 'msg' points to 363*7c478bd9Sstevel@tonic-gate * the beginning of a SLP header. 364*7c478bd9Sstevel@tonic-gate */ 365*7c478bd9Sstevel@tonic-gate slp_proto_err slp_get_errcode(char *msg) { 366*7c478bd9Sstevel@tonic-gate unsigned short langlen, errcode; 367*7c478bd9Sstevel@tonic-gate size_t off, msglen; 368*7c478bd9Sstevel@tonic-gate 369*7c478bd9Sstevel@tonic-gate /* make sure the reply is long enough */ 370*7c478bd9Sstevel@tonic-gate msglen = slp_get_length(msg); 371*7c478bd9Sstevel@tonic-gate if (msglen < (SLP_LANGLEN + 2)) 372*7c478bd9Sstevel@tonic-gate return (SLP_MSG_PARSE_ERROR); 373*7c478bd9Sstevel@tonic-gate langlen = slp_get_langlen(msg); 374*7c478bd9Sstevel@tonic-gate off = SLP_HDRLEN + langlen; 375*7c478bd9Sstevel@tonic-gate 376*7c478bd9Sstevel@tonic-gate if (slp_get_sht(msg, msglen, &off, &errcode) != SLP_OK) 377*7c478bd9Sstevel@tonic-gate return (SLP_MSG_PARSE_ERROR); 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate return (errcode); 380*7c478bd9Sstevel@tonic-gate } 381*7c478bd9Sstevel@tonic-gate 382*7c478bd9Sstevel@tonic-gate /* 383*7c478bd9Sstevel@tonic-gate * Primitive Encoding and Decoding Routines. 384*7c478bd9Sstevel@tonic-gate * All perform byte-ordering coversions and bounds checking. 385*7c478bd9Sstevel@tonic-gate */ 386*7c478bd9Sstevel@tonic-gate 387*7c478bd9Sstevel@tonic-gate SLPError slp_add_byte(char *pcBuf, size_t iBufSz, int iVal, 388*7c478bd9Sstevel@tonic-gate size_t *piLen) { 389*7c478bd9Sstevel@tonic-gate if ((*piLen + 1) > iBufSz) 390*7c478bd9Sstevel@tonic-gate return (SLP_PARAMETER_BAD); 391*7c478bd9Sstevel@tonic-gate 392*7c478bd9Sstevel@tonic-gate pcBuf[(*piLen)++] = (unsigned char) iVal; 393*7c478bd9Sstevel@tonic-gate return (SLP_OK); 394*7c478bd9Sstevel@tonic-gate } 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate SLPError slp_add_sht(char *pcBuf, size_t iBufSz, unsigned short iVal, 397*7c478bd9Sstevel@tonic-gate size_t *piLen) { 398*7c478bd9Sstevel@tonic-gate if ((*piLen + 2) > iBufSz) 399*7c478bd9Sstevel@tonic-gate return (SLP_PARAMETER_BAD); 400*7c478bd9Sstevel@tonic-gate 401*7c478bd9Sstevel@tonic-gate pcBuf[(*piLen)++] = (unsigned char) ((iVal & 0xFF00) >> 8); 402*7c478bd9Sstevel@tonic-gate pcBuf[(*piLen)++] = (unsigned char) (iVal & 0xFF); 403*7c478bd9Sstevel@tonic-gate return (SLP_OK); 404*7c478bd9Sstevel@tonic-gate } 405*7c478bd9Sstevel@tonic-gate 406*7c478bd9Sstevel@tonic-gate SLPError slp_add_int32(char *pcBuf, size_t iBufSz, unsigned int iVal, 407*7c478bd9Sstevel@tonic-gate size_t *piLen) { 408*7c478bd9Sstevel@tonic-gate if ((*piLen + 4) > iBufSz) 409*7c478bd9Sstevel@tonic-gate return (SLP_PARAMETER_BAD); 410*7c478bd9Sstevel@tonic-gate 411*7c478bd9Sstevel@tonic-gate pcBuf[(*piLen)++] = (unsigned char) ((iVal & 0xFF000000) >> 24); 412*7c478bd9Sstevel@tonic-gate pcBuf[(*piLen)++] = (unsigned char) ((iVal & 0xFF0000) >> 16); 413*7c478bd9Sstevel@tonic-gate pcBuf[(*piLen)++] = (unsigned char) ((iVal & 0xFF00) >> 8); 414*7c478bd9Sstevel@tonic-gate pcBuf[(*piLen)++] = (unsigned char) (iVal & 0xFF); 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate return (SLP_OK); 417*7c478bd9Sstevel@tonic-gate } 418*7c478bd9Sstevel@tonic-gate 419*7c478bd9Sstevel@tonic-gate SLPError slp_add_string(char *pcBuf, size_t iBufSz, const char *pcStr, 420*7c478bd9Sstevel@tonic-gate size_t *piLen) { 421*7c478bd9Sstevel@tonic-gate size_t iStrLen = strlen(pcStr); 422*7c478bd9Sstevel@tonic-gate SLPError err = 0; 423*7c478bd9Sstevel@tonic-gate 424*7c478bd9Sstevel@tonic-gate if (iStrLen > USHRT_MAX) 425*7c478bd9Sstevel@tonic-gate /* SLP strings are limited to 16-bit len */ 426*7c478bd9Sstevel@tonic-gate return (SLP_PARAMETER_BAD); 427*7c478bd9Sstevel@tonic-gate if ((iStrLen + *piLen + 2) > iBufSz) 428*7c478bd9Sstevel@tonic-gate return (SLP_PARAMETER_BAD); 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate if ((err = slp_add_sht(pcBuf, iBufSz, (unsigned short)iStrLen, piLen)) 431*7c478bd9Sstevel@tonic-gate != SLP_OK) 432*7c478bd9Sstevel@tonic-gate return (err); 433*7c478bd9Sstevel@tonic-gate 434*7c478bd9Sstevel@tonic-gate (void) memcpy(&(pcBuf[*piLen]), pcStr, iStrLen); 435*7c478bd9Sstevel@tonic-gate *piLen += iStrLen; 436*7c478bd9Sstevel@tonic-gate return (SLP_OK); 437*7c478bd9Sstevel@tonic-gate } 438*7c478bd9Sstevel@tonic-gate 439*7c478bd9Sstevel@tonic-gate SLPError slp_get_byte(const char *pcBuf, size_t maxlen, 440*7c478bd9Sstevel@tonic-gate size_t *piOffset, int *piByte) { 441*7c478bd9Sstevel@tonic-gate size_t offset = 0; 442*7c478bd9Sstevel@tonic-gate 443*7c478bd9Sstevel@tonic-gate if (piOffset != NULL) { 444*7c478bd9Sstevel@tonic-gate if ((*piOffset+1) > maxlen) 445*7c478bd9Sstevel@tonic-gate return (SLP_PARSE_ERROR); 446*7c478bd9Sstevel@tonic-gate offset = *piOffset; 447*7c478bd9Sstevel@tonic-gate *piOffset += 1; 448*7c478bd9Sstevel@tonic-gate } 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate *piByte = (int)pcBuf[offset]; 451*7c478bd9Sstevel@tonic-gate return (SLP_OK); 452*7c478bd9Sstevel@tonic-gate } 453*7c478bd9Sstevel@tonic-gate 454*7c478bd9Sstevel@tonic-gate SLPError slp_get_sht(const char *pcBuf, size_t maxlen, 455*7c478bd9Sstevel@tonic-gate size_t *piOffset, unsigned short *piSht) { 456*7c478bd9Sstevel@tonic-gate size_t offset = 0; 457*7c478bd9Sstevel@tonic-gate 458*7c478bd9Sstevel@tonic-gate if (piOffset != NULL) { 459*7c478bd9Sstevel@tonic-gate if ((*piOffset+2) > maxlen) 460*7c478bd9Sstevel@tonic-gate return (SLP_PARSE_ERROR); 461*7c478bd9Sstevel@tonic-gate offset = *piOffset; 462*7c478bd9Sstevel@tonic-gate *piOffset += 2; 463*7c478bd9Sstevel@tonic-gate } 464*7c478bd9Sstevel@tonic-gate 465*7c478bd9Sstevel@tonic-gate *piSht = (unsigned short) 466*7c478bd9Sstevel@tonic-gate ((unsigned char)pcBuf[offset] & (unsigned char)0xFF); 467*7c478bd9Sstevel@tonic-gate *piSht <<= 8; 468*7c478bd9Sstevel@tonic-gate *piSht += (unsigned short) 469*7c478bd9Sstevel@tonic-gate ((unsigned char)pcBuf[offset+1] & (unsigned char)0xFF); 470*7c478bd9Sstevel@tonic-gate 471*7c478bd9Sstevel@tonic-gate return (SLP_OK); 472*7c478bd9Sstevel@tonic-gate } 473*7c478bd9Sstevel@tonic-gate 474*7c478bd9Sstevel@tonic-gate SLPError slp_get_int32(const char *pcBuf, size_t maxlen, 475*7c478bd9Sstevel@tonic-gate size_t *piOffset, unsigned int *piInt) { 476*7c478bd9Sstevel@tonic-gate size_t offset = 0; 477*7c478bd9Sstevel@tonic-gate 478*7c478bd9Sstevel@tonic-gate if (piOffset != NULL) { 479*7c478bd9Sstevel@tonic-gate if ((*piOffset+4) > maxlen) 480*7c478bd9Sstevel@tonic-gate return (SLP_PARSE_ERROR); 481*7c478bd9Sstevel@tonic-gate offset = *piOffset; 482*7c478bd9Sstevel@tonic-gate *piOffset += 4; 483*7c478bd9Sstevel@tonic-gate } 484*7c478bd9Sstevel@tonic-gate 485*7c478bd9Sstevel@tonic-gate *piInt = ((unsigned int)(pcBuf[offset] & 0xff)) << 24; 486*7c478bd9Sstevel@tonic-gate *piInt += ((unsigned int)(pcBuf[offset+1] & 0xff)) << 16; 487*7c478bd9Sstevel@tonic-gate *piInt += ((unsigned int)(pcBuf[offset+2] & 0xff)) << 8; 488*7c478bd9Sstevel@tonic-gate *piInt += ((unsigned int)(pcBuf[offset+3] & 0xff)); 489*7c478bd9Sstevel@tonic-gate 490*7c478bd9Sstevel@tonic-gate return (SLP_OK); 491*7c478bd9Sstevel@tonic-gate } 492*7c478bd9Sstevel@tonic-gate 493*7c478bd9Sstevel@tonic-gate SLPError slp_get_string(const char *pcBuf, size_t iMaxLen, 494*7c478bd9Sstevel@tonic-gate size_t *piOffset, char **ppcString) { 495*7c478bd9Sstevel@tonic-gate SLPError err; 496*7c478bd9Sstevel@tonic-gate unsigned short iLen; 497*7c478bd9Sstevel@tonic-gate 498*7c478bd9Sstevel@tonic-gate *ppcString = NULL; 499*7c478bd9Sstevel@tonic-gate err = slp_get_sht(pcBuf, iMaxLen, piOffset, &iLen); 500*7c478bd9Sstevel@tonic-gate if (err) 501*7c478bd9Sstevel@tonic-gate return (err); 502*7c478bd9Sstevel@tonic-gate if ((iLen+*piOffset) > iMaxLen) 503*7c478bd9Sstevel@tonic-gate return (SLP_PARSE_ERROR); 504*7c478bd9Sstevel@tonic-gate 505*7c478bd9Sstevel@tonic-gate if (!(*ppcString = malloc(iLen + 1))) { 506*7c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "slp_get_string", "out of memory"); 507*7c478bd9Sstevel@tonic-gate return (SLP_MEMORY_ALLOC_FAILED); 508*7c478bd9Sstevel@tonic-gate } 509*7c478bd9Sstevel@tonic-gate (void) memcpy(*ppcString, pcBuf + *piOffset, iLen); 510*7c478bd9Sstevel@tonic-gate (*ppcString)[iLen] = 0; 511*7c478bd9Sstevel@tonic-gate *piOffset += iLen; 512*7c478bd9Sstevel@tonic-gate return (SLP_OK); 513*7c478bd9Sstevel@tonic-gate } 514