xref: /onnv-gate/usr/src/lib/libslp/clib/slp_utils.c (revision 0:68f95e015346)
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 */
slp_err(int priority,int id,char * func,char * inmsg,...)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  */
slp_start_call(slp_handle_impl_t * hp)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 
slp_end_call(slp_handle_impl_t * hp)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  */
slp_map_err(unsigned short proto_err)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  */
slp_onlist(const char * item,const char * list)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  */
slp_add2list(const char * item,char ** list,SLPBoolean check_onlist)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  */
slp_list_subtract(const char * item,char ** list)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  */
slp_add_header(const char * pcLangTag,char * pcSendBuf,size_t iSendBufSz,int iFun,size_t iLen,size_t * piLen)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  */
slp_header_get_int24(const char * header,size_t off)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  */
slp_header_set_int24(char * header,unsigned int len,size_t off)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  */
slp_header_get_sht(const char * header,size_t off)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  */
slp_header_set_sht(char * header,unsigned short len,size_t off)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  */
slp_header_length(slp_handle_impl_t * hp)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  */
slp_get_errcode(char * msg)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 
slp_add_byte(char * pcBuf,size_t iBufSz,int iVal,size_t * piLen)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 
slp_add_sht(char * pcBuf,size_t iBufSz,unsigned short iVal,size_t * piLen)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 
slp_add_int32(char * pcBuf,size_t iBufSz,unsigned int iVal,size_t * piLen)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 
slp_add_string(char * pcBuf,size_t iBufSz,const char * pcStr,size_t * piLen)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 
slp_get_byte(const char * pcBuf,size_t maxlen,size_t * piOffset,int * piByte)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 
slp_get_sht(const char * pcBuf,size_t maxlen,size_t * piOffset,unsigned short * piSht)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 
slp_get_int32(const char * pcBuf,size_t maxlen,size_t * piOffset,unsigned int * piInt)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 
slp_get_string(const char * pcBuf,size_t iMaxLen,size_t * piOffset,char ** ppcString)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