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