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