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 #include <stdlib.h>
30*7c478bd9Sstevel@tonic-gate #include <syslog.h>
31*7c478bd9Sstevel@tonic-gate #include <slp-internal.h>
32*7c478bd9Sstevel@tonic-gate
33*7c478bd9Sstevel@tonic-gate struct attr_node {
34*7c478bd9Sstevel@tonic-gate char *tag, *val;
35*7c478bd9Sstevel@tonic-gate };
36*7c478bd9Sstevel@tonic-gate
37*7c478bd9Sstevel@tonic-gate static SLPError slp_packAttrRqst(slp_handle_impl_t *, const char *,
38*7c478bd9Sstevel@tonic-gate const char *);
39*7c478bd9Sstevel@tonic-gate static int compare_tags(const void *, const void *);
40*7c478bd9Sstevel@tonic-gate static void collate_attrs(char *, void **, int *, int);
41*7c478bd9Sstevel@tonic-gate static void parens_attr(char *, void **, int *);
42*7c478bd9Sstevel@tonic-gate static void merge_attrs(struct attr_node *, char *);
43*7c478bd9Sstevel@tonic-gate static char *build_attrs_list(void *collator);
44*7c478bd9Sstevel@tonic-gate static void collect_attrs(void *, VISIT, int, void *);
45*7c478bd9Sstevel@tonic-gate static SLPBoolean unpackDAAdvert_attr(slp_handle_impl_t *, char *,
46*7c478bd9Sstevel@tonic-gate SLPAttrCallback, void *,
47*7c478bd9Sstevel@tonic-gate void **, int *);
48*7c478bd9Sstevel@tonic-gate static SLPBoolean unpackSAAdvert_attr(slp_handle_impl_t *, char *,
49*7c478bd9Sstevel@tonic-gate SLPAttrCallback, void *,
50*7c478bd9Sstevel@tonic-gate void **, int *);
51*7c478bd9Sstevel@tonic-gate
SLPFindAttrs(SLPHandle hSLP,const char * pcURL,const char * pcScope,const char * pcAttrIds,SLPAttrCallback callback,void * pvUser)52*7c478bd9Sstevel@tonic-gate SLPError SLPFindAttrs(SLPHandle hSLP, const char *pcURL, const char *pcScope,
53*7c478bd9Sstevel@tonic-gate const char *pcAttrIds,
54*7c478bd9Sstevel@tonic-gate SLPAttrCallback callback, void *pvUser) {
55*7c478bd9Sstevel@tonic-gate SLPError err;
56*7c478bd9Sstevel@tonic-gate int wantSAAdvert =
57*7c478bd9Sstevel@tonic-gate strcasecmp(pcURL, "service:service-agent") == 0;
58*7c478bd9Sstevel@tonic-gate int wantDAAdvert =
59*7c478bd9Sstevel@tonic-gate strcasecmp(pcURL, "service:directory-agent") == 0;
60*7c478bd9Sstevel@tonic-gate int isSpecial = wantSAAdvert || wantDAAdvert;
61*7c478bd9Sstevel@tonic-gate SLPMsgReplyCB *unpack_cb;
62*7c478bd9Sstevel@tonic-gate
63*7c478bd9Sstevel@tonic-gate
64*7c478bd9Sstevel@tonic-gate if (!hSLP || !pcURL || !pcScope || (!*pcScope && !isSpecial) ||
65*7c478bd9Sstevel@tonic-gate !pcAttrIds || !callback) {
66*7c478bd9Sstevel@tonic-gate return (SLP_PARAMETER_BAD);
67*7c478bd9Sstevel@tonic-gate }
68*7c478bd9Sstevel@tonic-gate
69*7c478bd9Sstevel@tonic-gate if ((strlen(pcURL) > SLP_MAX_STRINGLEN) ||
70*7c478bd9Sstevel@tonic-gate (strlen(pcScope) > SLP_MAX_STRINGLEN) ||
71*7c478bd9Sstevel@tonic-gate (strlen(pcAttrIds) > SLP_MAX_STRINGLEN)) {
72*7c478bd9Sstevel@tonic-gate return (SLP_PARAMETER_BAD);
73*7c478bd9Sstevel@tonic-gate }
74*7c478bd9Sstevel@tonic-gate
75*7c478bd9Sstevel@tonic-gate if ((err = slp_start_call(hSLP)) != SLP_OK)
76*7c478bd9Sstevel@tonic-gate return (err);
77*7c478bd9Sstevel@tonic-gate
78*7c478bd9Sstevel@tonic-gate /* Special packer and unpacker for DA and SA solicitations */
79*7c478bd9Sstevel@tonic-gate if (wantDAAdvert) {
80*7c478bd9Sstevel@tonic-gate unpack_cb = (SLPMsgReplyCB *)unpackDAAdvert_attr;
81*7c478bd9Sstevel@tonic-gate err = slp_packSrvRqst(pcURL, "", hSLP);
82*7c478bd9Sstevel@tonic-gate ((slp_handle_impl_t *)hSLP)->force_multicast = SLP_TRUE;
83*7c478bd9Sstevel@tonic-gate } else if (wantSAAdvert) {
84*7c478bd9Sstevel@tonic-gate unpack_cb = (SLPMsgReplyCB *)unpackSAAdvert_attr;
85*7c478bd9Sstevel@tonic-gate err = slp_packSrvRqst(pcURL, "", hSLP);
86*7c478bd9Sstevel@tonic-gate ((slp_handle_impl_t *)hSLP)->force_multicast = SLP_TRUE;
87*7c478bd9Sstevel@tonic-gate } else {
88*7c478bd9Sstevel@tonic-gate /* normal service request */
89*7c478bd9Sstevel@tonic-gate unpack_cb = (SLPMsgReplyCB *)slp_UnpackAttrReply;
90*7c478bd9Sstevel@tonic-gate /* format params into msgBuf */
91*7c478bd9Sstevel@tonic-gate err = slp_packAttrRqst(hSLP, pcURL, pcAttrIds);
92*7c478bd9Sstevel@tonic-gate }
93*7c478bd9Sstevel@tonic-gate
94*7c478bd9Sstevel@tonic-gate if (err == SLP_OK)
95*7c478bd9Sstevel@tonic-gate err = slp_ua_common(hSLP, pcScope,
96*7c478bd9Sstevel@tonic-gate (SLPGenericAppCB *) callback, pvUser,
97*7c478bd9Sstevel@tonic-gate unpack_cb);
98*7c478bd9Sstevel@tonic-gate
99*7c478bd9Sstevel@tonic-gate if (err != SLP_OK)
100*7c478bd9Sstevel@tonic-gate slp_end_call(hSLP);
101*7c478bd9Sstevel@tonic-gate
102*7c478bd9Sstevel@tonic-gate return (err);
103*7c478bd9Sstevel@tonic-gate }
104*7c478bd9Sstevel@tonic-gate
slp_UnpackAttrReply(slp_handle_impl_t * hp,char * reply,SLPAttrCallback cb,void * cookie,void ** collator,int * numResults)105*7c478bd9Sstevel@tonic-gate SLPBoolean slp_UnpackAttrReply(slp_handle_impl_t *hp, char *reply,
106*7c478bd9Sstevel@tonic-gate SLPAttrCallback cb, void *cookie,
107*7c478bd9Sstevel@tonic-gate void **collator, int *numResults) {
108*7c478bd9Sstevel@tonic-gate char *pcAttrList;
109*7c478bd9Sstevel@tonic-gate SLPError errCode;
110*7c478bd9Sstevel@tonic-gate unsigned short protoErrCode;
111*7c478bd9Sstevel@tonic-gate size_t len, off;
112*7c478bd9Sstevel@tonic-gate int maxResults = slp_get_maxResults();
113*7c478bd9Sstevel@tonic-gate SLPBoolean cont = SLP_TRUE;
114*7c478bd9Sstevel@tonic-gate int auth_cnt;
115*7c478bd9Sstevel@tonic-gate size_t tbv_len;
116*7c478bd9Sstevel@tonic-gate char *attr_tbv;
117*7c478bd9Sstevel@tonic-gate
118*7c478bd9Sstevel@tonic-gate if (!reply) {
119*7c478bd9Sstevel@tonic-gate /* no more results */
120*7c478bd9Sstevel@tonic-gate if (!hp->async) {
121*7c478bd9Sstevel@tonic-gate pcAttrList = build_attrs_list(*collator);
122*7c478bd9Sstevel@tonic-gate }
123*7c478bd9Sstevel@tonic-gate
124*7c478bd9Sstevel@tonic-gate if (!hp->async && pcAttrList) {
125*7c478bd9Sstevel@tonic-gate cb(hp, pcAttrList, SLP_OK, cookie);
126*7c478bd9Sstevel@tonic-gate free(pcAttrList);
127*7c478bd9Sstevel@tonic-gate }
128*7c478bd9Sstevel@tonic-gate cb(hp, NULL, SLP_LAST_CALL, cookie);
129*7c478bd9Sstevel@tonic-gate return (SLP_FALSE);
130*7c478bd9Sstevel@tonic-gate }
131*7c478bd9Sstevel@tonic-gate
132*7c478bd9Sstevel@tonic-gate /* parse reply into params */
133*7c478bd9Sstevel@tonic-gate len = slp_get_length(reply);
134*7c478bd9Sstevel@tonic-gate off = SLP_HDRLEN + slp_get_langlen(reply);
135*7c478bd9Sstevel@tonic-gate /* err code */
136*7c478bd9Sstevel@tonic-gate if (slp_get_sht(reply, len, &off, &protoErrCode) != SLP_OK)
137*7c478bd9Sstevel@tonic-gate return (SLP_TRUE);
138*7c478bd9Sstevel@tonic-gate /* internal errors should have been filtered out by the net code */
139*7c478bd9Sstevel@tonic-gate if ((errCode = slp_map_err(protoErrCode)) != SLP_OK) {
140*7c478bd9Sstevel@tonic-gate return (cb(hp, NULL, errCode, cookie));
141*7c478bd9Sstevel@tonic-gate }
142*7c478bd9Sstevel@tonic-gate
143*7c478bd9Sstevel@tonic-gate /* attr list */
144*7c478bd9Sstevel@tonic-gate attr_tbv = reply + off;
145*7c478bd9Sstevel@tonic-gate tbv_len = off;
146*7c478bd9Sstevel@tonic-gate if (slp_get_string(reply, len, &off, &pcAttrList) != SLP_OK)
147*7c478bd9Sstevel@tonic-gate return (SLP_TRUE);
148*7c478bd9Sstevel@tonic-gate tbv_len = off - tbv_len;
149*7c478bd9Sstevel@tonic-gate
150*7c478bd9Sstevel@tonic-gate /* number of attr auths */
151*7c478bd9Sstevel@tonic-gate if (slp_get_byte(reply, len, &off, &auth_cnt) != SLP_OK) {
152*7c478bd9Sstevel@tonic-gate goto cleanup;
153*7c478bd9Sstevel@tonic-gate }
154*7c478bd9Sstevel@tonic-gate
155*7c478bd9Sstevel@tonic-gate /* get and verify auth blocks */
156*7c478bd9Sstevel@tonic-gate if ((!hp->internal_call && slp_get_security_on()) || auth_cnt > 0) {
157*7c478bd9Sstevel@tonic-gate size_t abLen = 0;
158*7c478bd9Sstevel@tonic-gate struct iovec iov[1];
159*7c478bd9Sstevel@tonic-gate
160*7c478bd9Sstevel@tonic-gate iov[0].iov_base = attr_tbv;
161*7c478bd9Sstevel@tonic-gate iov[0].iov_len = tbv_len;
162*7c478bd9Sstevel@tonic-gate
163*7c478bd9Sstevel@tonic-gate if (slp_verify(iov, 1,
164*7c478bd9Sstevel@tonic-gate reply + off,
165*7c478bd9Sstevel@tonic-gate len - off,
166*7c478bd9Sstevel@tonic-gate auth_cnt,
167*7c478bd9Sstevel@tonic-gate &abLen) != SLP_OK) {
168*7c478bd9Sstevel@tonic-gate goto cleanup;
169*7c478bd9Sstevel@tonic-gate }
170*7c478bd9Sstevel@tonic-gate }
171*7c478bd9Sstevel@tonic-gate
172*7c478bd9Sstevel@tonic-gate /* collate */
173*7c478bd9Sstevel@tonic-gate if (!hp->async) {
174*7c478bd9Sstevel@tonic-gate collate_attrs(pcAttrList, collator, numResults, maxResults);
175*7c478bd9Sstevel@tonic-gate } else {
176*7c478bd9Sstevel@tonic-gate /* async: invoke cb */
177*7c478bd9Sstevel@tonic-gate cont = cb((SLPHandle) hp, pcAttrList, errCode, cookie);
178*7c478bd9Sstevel@tonic-gate (*numResults)++;
179*7c478bd9Sstevel@tonic-gate }
180*7c478bd9Sstevel@tonic-gate
181*7c478bd9Sstevel@tonic-gate cleanup:
182*7c478bd9Sstevel@tonic-gate free(pcAttrList);
183*7c478bd9Sstevel@tonic-gate
184*7c478bd9Sstevel@tonic-gate /* check maxResults */
185*7c478bd9Sstevel@tonic-gate if (!hp->internal_call && *numResults == maxResults) {
186*7c478bd9Sstevel@tonic-gate return (SLP_FALSE);
187*7c478bd9Sstevel@tonic-gate }
188*7c478bd9Sstevel@tonic-gate
189*7c478bd9Sstevel@tonic-gate return (cont);
190*7c478bd9Sstevel@tonic-gate }
191*7c478bd9Sstevel@tonic-gate
192*7c478bd9Sstevel@tonic-gate /*
193*7c478bd9Sstevel@tonic-gate * unpackDAAdvert_attr follows the same logic stream as UnpackAttrReply,
194*7c478bd9Sstevel@tonic-gate * except that reply contains a DAAdvert.
195*7c478bd9Sstevel@tonic-gate */
unpackDAAdvert_attr(slp_handle_impl_t * hp,char * reply,SLPAttrCallback cb,void * cookie,void ** collator,int * numResults)196*7c478bd9Sstevel@tonic-gate static SLPBoolean unpackDAAdvert_attr(slp_handle_impl_t *hp, char *reply,
197*7c478bd9Sstevel@tonic-gate SLPAttrCallback cb, void *cookie,
198*7c478bd9Sstevel@tonic-gate void **collator, int *numResults) {
199*7c478bd9Sstevel@tonic-gate char *surl, *scopes, *attrs, *spis;
200*7c478bd9Sstevel@tonic-gate SLPBoolean cont = SLP_TRUE;
201*7c478bd9Sstevel@tonic-gate SLPError errCode;
202*7c478bd9Sstevel@tonic-gate int maxResults = slp_get_maxResults();
203*7c478bd9Sstevel@tonic-gate
204*7c478bd9Sstevel@tonic-gate if (!reply) {
205*7c478bd9Sstevel@tonic-gate /* no more results */
206*7c478bd9Sstevel@tonic-gate if (!hp->async) {
207*7c478bd9Sstevel@tonic-gate attrs = build_attrs_list(*collator);
208*7c478bd9Sstevel@tonic-gate }
209*7c478bd9Sstevel@tonic-gate
210*7c478bd9Sstevel@tonic-gate if (!hp->async && attrs) {
211*7c478bd9Sstevel@tonic-gate cb(hp, attrs, SLP_OK, cookie);
212*7c478bd9Sstevel@tonic-gate free(attrs);
213*7c478bd9Sstevel@tonic-gate }
214*7c478bd9Sstevel@tonic-gate cb(hp, NULL, SLP_LAST_CALL, cookie);
215*7c478bd9Sstevel@tonic-gate return (SLP_FALSE);
216*7c478bd9Sstevel@tonic-gate }
217*7c478bd9Sstevel@tonic-gate
218*7c478bd9Sstevel@tonic-gate if (slp_unpackDAAdvert(reply, &surl, &scopes, &attrs, &spis, &errCode)
219*7c478bd9Sstevel@tonic-gate != SLP_OK) {
220*7c478bd9Sstevel@tonic-gate return (SLP_TRUE);
221*7c478bd9Sstevel@tonic-gate }
222*7c478bd9Sstevel@tonic-gate if (errCode != SLP_OK) {
223*7c478bd9Sstevel@tonic-gate return (cb(hp, NULL, errCode, cookie));
224*7c478bd9Sstevel@tonic-gate }
225*7c478bd9Sstevel@tonic-gate
226*7c478bd9Sstevel@tonic-gate /* collate */
227*7c478bd9Sstevel@tonic-gate if (!hp->async) {
228*7c478bd9Sstevel@tonic-gate collate_attrs(attrs, collator, numResults, maxResults);
229*7c478bd9Sstevel@tonic-gate } else {
230*7c478bd9Sstevel@tonic-gate /* async: invoke cb */
231*7c478bd9Sstevel@tonic-gate cont = cb((SLPHandle) hp, attrs, errCode, cookie);
232*7c478bd9Sstevel@tonic-gate (*numResults)++;
233*7c478bd9Sstevel@tonic-gate }
234*7c478bd9Sstevel@tonic-gate
235*7c478bd9Sstevel@tonic-gate /* cleanup */
236*7c478bd9Sstevel@tonic-gate free(surl);
237*7c478bd9Sstevel@tonic-gate free(scopes);
238*7c478bd9Sstevel@tonic-gate free(attrs);
239*7c478bd9Sstevel@tonic-gate free(spis);
240*7c478bd9Sstevel@tonic-gate
241*7c478bd9Sstevel@tonic-gate /* check maxResults */
242*7c478bd9Sstevel@tonic-gate if (!hp->internal_call && *numResults == maxResults) {
243*7c478bd9Sstevel@tonic-gate return (SLP_FALSE);
244*7c478bd9Sstevel@tonic-gate }
245*7c478bd9Sstevel@tonic-gate
246*7c478bd9Sstevel@tonic-gate return (cont);
247*7c478bd9Sstevel@tonic-gate }
248*7c478bd9Sstevel@tonic-gate
249*7c478bd9Sstevel@tonic-gate /*
250*7c478bd9Sstevel@tonic-gate * unpackSAAdvert_attr follows the same logic stream as UnpackAttrReply,
251*7c478bd9Sstevel@tonic-gate * except that reply contains an SAAdvert.
252*7c478bd9Sstevel@tonic-gate */
unpackSAAdvert_attr(slp_handle_impl_t * hp,char * reply,SLPAttrCallback cb,void * cookie,void ** collator,int * numResults)253*7c478bd9Sstevel@tonic-gate static SLPBoolean unpackSAAdvert_attr(slp_handle_impl_t *hp, char *reply,
254*7c478bd9Sstevel@tonic-gate SLPAttrCallback cb, void *cookie,
255*7c478bd9Sstevel@tonic-gate void **collator, int *numResults) {
256*7c478bd9Sstevel@tonic-gate char *surl, *scopes, *attrs;
257*7c478bd9Sstevel@tonic-gate SLPBoolean cont = SLP_TRUE;
258*7c478bd9Sstevel@tonic-gate int maxResults = slp_get_maxResults();
259*7c478bd9Sstevel@tonic-gate
260*7c478bd9Sstevel@tonic-gate if (!reply) {
261*7c478bd9Sstevel@tonic-gate /* no more results */
262*7c478bd9Sstevel@tonic-gate if (!hp->async) {
263*7c478bd9Sstevel@tonic-gate attrs = build_attrs_list(*collator);
264*7c478bd9Sstevel@tonic-gate }
265*7c478bd9Sstevel@tonic-gate
266*7c478bd9Sstevel@tonic-gate if (!hp->async && attrs) {
267*7c478bd9Sstevel@tonic-gate cb(hp, attrs, SLP_OK, cookie);
268*7c478bd9Sstevel@tonic-gate free(attrs);
269*7c478bd9Sstevel@tonic-gate }
270*7c478bd9Sstevel@tonic-gate cb(hp, NULL, SLP_LAST_CALL, cookie);
271*7c478bd9Sstevel@tonic-gate return (SLP_FALSE);
272*7c478bd9Sstevel@tonic-gate }
273*7c478bd9Sstevel@tonic-gate
274*7c478bd9Sstevel@tonic-gate if (slp_unpackSAAdvert(reply, &surl, &scopes, &attrs) != SLP_OK) {
275*7c478bd9Sstevel@tonic-gate return (SLP_TRUE);
276*7c478bd9Sstevel@tonic-gate }
277*7c478bd9Sstevel@tonic-gate
278*7c478bd9Sstevel@tonic-gate /* collate */
279*7c478bd9Sstevel@tonic-gate if (!hp->async) {
280*7c478bd9Sstevel@tonic-gate collate_attrs(attrs, collator, numResults, maxResults);
281*7c478bd9Sstevel@tonic-gate } else {
282*7c478bd9Sstevel@tonic-gate /* async: invoke cb */
283*7c478bd9Sstevel@tonic-gate cont = cb((SLPHandle) hp, attrs, SLP_OK, cookie);
284*7c478bd9Sstevel@tonic-gate (*numResults)++;
285*7c478bd9Sstevel@tonic-gate }
286*7c478bd9Sstevel@tonic-gate
287*7c478bd9Sstevel@tonic-gate /* cleanup */
288*7c478bd9Sstevel@tonic-gate free(surl);
289*7c478bd9Sstevel@tonic-gate free(scopes);
290*7c478bd9Sstevel@tonic-gate free(attrs);
291*7c478bd9Sstevel@tonic-gate
292*7c478bd9Sstevel@tonic-gate /* check maxResults */
293*7c478bd9Sstevel@tonic-gate if (!hp->internal_call && *numResults == maxResults) {
294*7c478bd9Sstevel@tonic-gate return (SLP_FALSE);
295*7c478bd9Sstevel@tonic-gate }
296*7c478bd9Sstevel@tonic-gate
297*7c478bd9Sstevel@tonic-gate return (cont);
298*7c478bd9Sstevel@tonic-gate }
299*7c478bd9Sstevel@tonic-gate
slp_packAttrRqst(slp_handle_impl_t * hp,const char * url,const char * ids)300*7c478bd9Sstevel@tonic-gate static SLPError slp_packAttrRqst(slp_handle_impl_t *hp, const char *url,
301*7c478bd9Sstevel@tonic-gate const char *ids) {
302*7c478bd9Sstevel@tonic-gate SLPError err;
303*7c478bd9Sstevel@tonic-gate size_t len, tmplen, msgLen;
304*7c478bd9Sstevel@tonic-gate slp_msg_t *msg = &(hp->msg);
305*7c478bd9Sstevel@tonic-gate char *spi = NULL;
306*7c478bd9Sstevel@tonic-gate
307*7c478bd9Sstevel@tonic-gate if (slp_get_security_on()) {
308*7c478bd9Sstevel@tonic-gate spi = (char *)SLPGetProperty(SLP_CONFIG_SPI);
309*7c478bd9Sstevel@tonic-gate }
310*7c478bd9Sstevel@tonic-gate
311*7c478bd9Sstevel@tonic-gate if (!spi || !*spi) {
312*7c478bd9Sstevel@tonic-gate spi = "";
313*7c478bd9Sstevel@tonic-gate }
314*7c478bd9Sstevel@tonic-gate
315*7c478bd9Sstevel@tonic-gate /*
316*7c478bd9Sstevel@tonic-gate * Allocate iovec for the messge. An AttrRqst is layed out thus:
317*7c478bd9Sstevel@tonic-gate * 0: header
318*7c478bd9Sstevel@tonic-gate * 1: prlist length
319*7c478bd9Sstevel@tonic-gate * 2: prlist (filled in later by networking code)
320*7c478bd9Sstevel@tonic-gate * 3: URL string
321*7c478bd9Sstevel@tonic-gate * 4: scopes length
322*7c478bd9Sstevel@tonic-gate * 5: scopes (filled in later by networking code)
323*7c478bd9Sstevel@tonic-gate * 6: tag list string and SPI string
324*7c478bd9Sstevel@tonic-gate */
325*7c478bd9Sstevel@tonic-gate if (!(msg->iov = calloc(7, sizeof (*(msg->iov))))) {
326*7c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "slp_packAttrRqst", "out of memory");
327*7c478bd9Sstevel@tonic-gate return (SLP_MEMORY_ALLOC_FAILED);
328*7c478bd9Sstevel@tonic-gate }
329*7c478bd9Sstevel@tonic-gate msg->iovlen = 7;
330*7c478bd9Sstevel@tonic-gate
331*7c478bd9Sstevel@tonic-gate /* calculate msg length */
332*7c478bd9Sstevel@tonic-gate msgLen = 2 + /* prlist length */
333*7c478bd9Sstevel@tonic-gate 2 + strlen(url) + /* URL */
334*7c478bd9Sstevel@tonic-gate 2 + /* scope list length */
335*7c478bd9Sstevel@tonic-gate 2 + strlen(ids) + /* tag list */
336*7c478bd9Sstevel@tonic-gate 2 + strlen(spi); /* SPI string */
337*7c478bd9Sstevel@tonic-gate
338*7c478bd9Sstevel@tonic-gate if (!(msg->msg = calloc(1, msgLen))) {
339*7c478bd9Sstevel@tonic-gate free(msg->iov);
340*7c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "slp_packAttrRqst", "out of memory");
341*7c478bd9Sstevel@tonic-gate return (SLP_MEMORY_ALLOC_FAILED);
342*7c478bd9Sstevel@tonic-gate }
343*7c478bd9Sstevel@tonic-gate
344*7c478bd9Sstevel@tonic-gate /* set pointer to PR list and scope list length spaces */
345*7c478bd9Sstevel@tonic-gate msg->prlistlen.iov_base = msg->msg;
346*7c478bd9Sstevel@tonic-gate msg->prlistlen.iov_len = 2;
347*7c478bd9Sstevel@tonic-gate msg->iov[1].iov_base = msg->msg;
348*7c478bd9Sstevel@tonic-gate msg->iov[1].iov_len = 2;
349*7c478bd9Sstevel@tonic-gate
350*7c478bd9Sstevel@tonic-gate msg->scopeslen.iov_base = msg->msg + 2;
351*7c478bd9Sstevel@tonic-gate msg->scopeslen.iov_len = 2;
352*7c478bd9Sstevel@tonic-gate msg->iov[4].iov_base = msg->msg + 2;
353*7c478bd9Sstevel@tonic-gate msg->iov[4].iov_len = 2;
354*7c478bd9Sstevel@tonic-gate
355*7c478bd9Sstevel@tonic-gate /* set up the scopes and prlist pointers into iov */
356*7c478bd9Sstevel@tonic-gate msg->prlist = &(msg->iov[2]);
357*7c478bd9Sstevel@tonic-gate msg->scopes = &(msg->iov[5]);
358*7c478bd9Sstevel@tonic-gate
359*7c478bd9Sstevel@tonic-gate len = 4;
360*7c478bd9Sstevel@tonic-gate
361*7c478bd9Sstevel@tonic-gate /* Add URL string */
362*7c478bd9Sstevel@tonic-gate msg->iov[3].iov_base = msg->msg + len;
363*7c478bd9Sstevel@tonic-gate tmplen = len;
364*7c478bd9Sstevel@tonic-gate
365*7c478bd9Sstevel@tonic-gate err = slp_add_string(msg->msg, msgLen, url, &len);
366*7c478bd9Sstevel@tonic-gate msg->iov[3].iov_len = len - tmplen;
367*7c478bd9Sstevel@tonic-gate
368*7c478bd9Sstevel@tonic-gate if (err != SLP_OK)
369*7c478bd9Sstevel@tonic-gate goto error;
370*7c478bd9Sstevel@tonic-gate
371*7c478bd9Sstevel@tonic-gate /* Add tag list */
372*7c478bd9Sstevel@tonic-gate msg->iov[6].iov_base = msg->msg + len;
373*7c478bd9Sstevel@tonic-gate tmplen = len;
374*7c478bd9Sstevel@tonic-gate
375*7c478bd9Sstevel@tonic-gate err = slp_add_string(msg->msg, msgLen, ids, &len);
376*7c478bd9Sstevel@tonic-gate
377*7c478bd9Sstevel@tonic-gate if (err != SLP_OK)
378*7c478bd9Sstevel@tonic-gate goto error;
379*7c478bd9Sstevel@tonic-gate
380*7c478bd9Sstevel@tonic-gate /* SPI string */
381*7c478bd9Sstevel@tonic-gate err = slp_add_string(msg->msg, msgLen, spi, &len);
382*7c478bd9Sstevel@tonic-gate
383*7c478bd9Sstevel@tonic-gate msg->iov[6].iov_len = len - tmplen;
384*7c478bd9Sstevel@tonic-gate
385*7c478bd9Sstevel@tonic-gate hp->fid = ATTRRQST;
386*7c478bd9Sstevel@tonic-gate if (err == SLP_OK) {
387*7c478bd9Sstevel@tonic-gate return (SLP_OK);
388*7c478bd9Sstevel@tonic-gate }
389*7c478bd9Sstevel@tonic-gate
390*7c478bd9Sstevel@tonic-gate /* else error */
391*7c478bd9Sstevel@tonic-gate error:
392*7c478bd9Sstevel@tonic-gate free(msg->iov);
393*7c478bd9Sstevel@tonic-gate free(msg->msg);
394*7c478bd9Sstevel@tonic-gate
395*7c478bd9Sstevel@tonic-gate return (err);
396*7c478bd9Sstevel@tonic-gate }
397*7c478bd9Sstevel@tonic-gate
slp_packAttrRqst_single(const char * url,const char * scopes,const char * ids,char ** msg,const char * lang)398*7c478bd9Sstevel@tonic-gate SLPError slp_packAttrRqst_single(const char *url,
399*7c478bd9Sstevel@tonic-gate const char *scopes,
400*7c478bd9Sstevel@tonic-gate const char *ids,
401*7c478bd9Sstevel@tonic-gate char **msg,
402*7c478bd9Sstevel@tonic-gate const char *lang) {
403*7c478bd9Sstevel@tonic-gate SLPError err;
404*7c478bd9Sstevel@tonic-gate size_t len, msgLen;
405*7c478bd9Sstevel@tonic-gate
406*7c478bd9Sstevel@tonic-gate msgLen =
407*7c478bd9Sstevel@tonic-gate SLP_HDRLEN + strlen(lang) + 2 +
408*7c478bd9Sstevel@tonic-gate 2 + strlen(url) +
409*7c478bd9Sstevel@tonic-gate 2 + strlen(scopes) +
410*7c478bd9Sstevel@tonic-gate 2 + strlen(ids) +
411*7c478bd9Sstevel@tonic-gate 2; /* No SPI string for internal calls */
412*7c478bd9Sstevel@tonic-gate
413*7c478bd9Sstevel@tonic-gate if (!(*msg = calloc(msgLen, 1))) {
414*7c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "slp_packAttrRqst_single", "out of memory");
415*7c478bd9Sstevel@tonic-gate return (SLP_MEMORY_ALLOC_FAILED);
416*7c478bd9Sstevel@tonic-gate }
417*7c478bd9Sstevel@tonic-gate
418*7c478bd9Sstevel@tonic-gate len = 0;
419*7c478bd9Sstevel@tonic-gate err = slp_add_header(lang, *msg, msgLen, ATTRRQST, msgLen, &len);
420*7c478bd9Sstevel@tonic-gate
421*7c478bd9Sstevel@tonic-gate len += 2; /* empty PR list */
422*7c478bd9Sstevel@tonic-gate
423*7c478bd9Sstevel@tonic-gate if (err == SLP_OK) {
424*7c478bd9Sstevel@tonic-gate err = slp_add_string(*msg, msgLen, url, &len);
425*7c478bd9Sstevel@tonic-gate }
426*7c478bd9Sstevel@tonic-gate if (err == SLP_OK) {
427*7c478bd9Sstevel@tonic-gate err = slp_add_string(*msg, msgLen, scopes, &len);
428*7c478bd9Sstevel@tonic-gate }
429*7c478bd9Sstevel@tonic-gate if (err == SLP_OK) {
430*7c478bd9Sstevel@tonic-gate err = slp_add_string(*msg, msgLen, ids, &len);
431*7c478bd9Sstevel@tonic-gate }
432*7c478bd9Sstevel@tonic-gate /* empty SPI */
433*7c478bd9Sstevel@tonic-gate if (err == SLP_OK) {
434*7c478bd9Sstevel@tonic-gate err = slp_add_string(*msg, msgLen, "", &len);
435*7c478bd9Sstevel@tonic-gate }
436*7c478bd9Sstevel@tonic-gate
437*7c478bd9Sstevel@tonic-gate return (err);
438*7c478bd9Sstevel@tonic-gate }
439*7c478bd9Sstevel@tonic-gate
compare_tags(const void * n1,const void * n2)440*7c478bd9Sstevel@tonic-gate static int compare_tags(const void *n1, const void *n2) {
441*7c478bd9Sstevel@tonic-gate return slp_strcasecmp(
442*7c478bd9Sstevel@tonic-gate ((struct attr_node *)n1)->tag,
443*7c478bd9Sstevel@tonic-gate ((struct attr_node *)n2)->tag);
444*7c478bd9Sstevel@tonic-gate }
445*7c478bd9Sstevel@tonic-gate
merge_attrs(struct attr_node * n,char * vals)446*7c478bd9Sstevel@tonic-gate static void merge_attrs(struct attr_node *n, char *vals) {
447*7c478bd9Sstevel@tonic-gate char *p, *v;
448*7c478bd9Sstevel@tonic-gate
449*7c478bd9Sstevel@tonic-gate for (p = v = vals; p; v = p) {
450*7c478bd9Sstevel@tonic-gate p = slp_utf_strchr(v, ',');
451*7c478bd9Sstevel@tonic-gate if (p)
452*7c478bd9Sstevel@tonic-gate *p++ = 0;
453*7c478bd9Sstevel@tonic-gate slp_add2list(v, &(n->val), SLP_TRUE);
454*7c478bd9Sstevel@tonic-gate }
455*7c478bd9Sstevel@tonic-gate }
456*7c478bd9Sstevel@tonic-gate
parens_attr(char * attr,void ** collator,int * numResults)457*7c478bd9Sstevel@tonic-gate static void parens_attr(char *attr, void **collator, int *numResults) {
458*7c478bd9Sstevel@tonic-gate char *open_paren, *close_paren, *equals;
459*7c478bd9Sstevel@tonic-gate struct attr_node *n, **res;
460*7c478bd9Sstevel@tonic-gate
461*7c478bd9Sstevel@tonic-gate open_paren = attr + 1;
462*7c478bd9Sstevel@tonic-gate close_paren = slp_utf_strchr(open_paren, ')');
463*7c478bd9Sstevel@tonic-gate if (!close_paren)
464*7c478bd9Sstevel@tonic-gate return; /* skip bad attr list */
465*7c478bd9Sstevel@tonic-gate
466*7c478bd9Sstevel@tonic-gate *close_paren = 0;
467*7c478bd9Sstevel@tonic-gate if (!(equals = slp_utf_strchr(open_paren, '=')))
468*7c478bd9Sstevel@tonic-gate return;
469*7c478bd9Sstevel@tonic-gate
470*7c478bd9Sstevel@tonic-gate *equals++ = 0;
471*7c478bd9Sstevel@tonic-gate
472*7c478bd9Sstevel@tonic-gate if (!(n = malloc(sizeof (*n)))) {
473*7c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "collate_attrs", "out of memory");
474*7c478bd9Sstevel@tonic-gate return;
475*7c478bd9Sstevel@tonic-gate }
476*7c478bd9Sstevel@tonic-gate
477*7c478bd9Sstevel@tonic-gate if (!(n->tag = strdup(open_paren))) {
478*7c478bd9Sstevel@tonic-gate free(n);
479*7c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "collate_attrs", "out of memory");
480*7c478bd9Sstevel@tonic-gate return;
481*7c478bd9Sstevel@tonic-gate }
482*7c478bd9Sstevel@tonic-gate n->val = NULL;
483*7c478bd9Sstevel@tonic-gate
484*7c478bd9Sstevel@tonic-gate res = slp_tsearch(n, collator, compare_tags);
485*7c478bd9Sstevel@tonic-gate
486*7c478bd9Sstevel@tonic-gate if (*res != n) {
487*7c478bd9Sstevel@tonic-gate merge_attrs(*res, equals);
488*7c478bd9Sstevel@tonic-gate free(n->tag); free(n);
489*7c478bd9Sstevel@tonic-gate } else {
490*7c478bd9Sstevel@tonic-gate /* not found; populate new attr node */
491*7c478bd9Sstevel@tonic-gate (*numResults)++;
492*7c478bd9Sstevel@tonic-gate if (!(n->val = strdup(equals))) {
493*7c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "collate_attrs", "out of memory");
494*7c478bd9Sstevel@tonic-gate return;
495*7c478bd9Sstevel@tonic-gate }
496*7c478bd9Sstevel@tonic-gate }
497*7c478bd9Sstevel@tonic-gate }
498*7c478bd9Sstevel@tonic-gate
collate_attrs(char * attrs,void ** collator,int * numResults,int maxResults)499*7c478bd9Sstevel@tonic-gate static void collate_attrs(char *attrs, void **collator,
500*7c478bd9Sstevel@tonic-gate int *numResults, int maxResults) {
501*7c478bd9Sstevel@tonic-gate char *start, *end;
502*7c478bd9Sstevel@tonic-gate struct attr_node *n, **res;
503*7c478bd9Sstevel@tonic-gate
504*7c478bd9Sstevel@tonic-gate for (start = attrs;
505*7c478bd9Sstevel@tonic-gate start &&
506*7c478bd9Sstevel@tonic-gate *start &&
507*7c478bd9Sstevel@tonic-gate *numResults != maxResults;
508*7c478bd9Sstevel@tonic-gate start = end) {
509*7c478bd9Sstevel@tonic-gate if (*start == ',') start++;
510*7c478bd9Sstevel@tonic-gate if (*start == '(') {
511*7c478bd9Sstevel@tonic-gate /* form of (tag=val,val) */
512*7c478bd9Sstevel@tonic-gate if (!(end = slp_utf_strchr(start, ')')))
513*7c478bd9Sstevel@tonic-gate return; /* skip bad attr */
514*7c478bd9Sstevel@tonic-gate parens_attr(start, collator, numResults);
515*7c478bd9Sstevel@tonic-gate end++;
516*7c478bd9Sstevel@tonic-gate continue;
517*7c478bd9Sstevel@tonic-gate }
518*7c478bd9Sstevel@tonic-gate end = slp_utf_strchr(start, ',');
519*7c478bd9Sstevel@tonic-gate if (end)
520*7c478bd9Sstevel@tonic-gate *end++ = 0;
521*7c478bd9Sstevel@tonic-gate /* create a new node with the tag only */
522*7c478bd9Sstevel@tonic-gate if (!(n = malloc(sizeof (*n)))) {
523*7c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "collate_attrs", "out of memory");
524*7c478bd9Sstevel@tonic-gate return;
525*7c478bd9Sstevel@tonic-gate }
526*7c478bd9Sstevel@tonic-gate
527*7c478bd9Sstevel@tonic-gate if (!(n->tag = strdup(start))) {
528*7c478bd9Sstevel@tonic-gate free(n);
529*7c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "collate_attrs", "out of memory");
530*7c478bd9Sstevel@tonic-gate return;
531*7c478bd9Sstevel@tonic-gate }
532*7c478bd9Sstevel@tonic-gate n->val = NULL;
533*7c478bd9Sstevel@tonic-gate res = slp_tsearch(n, collator, compare_tags);
534*7c478bd9Sstevel@tonic-gate if (*res != n) {
535*7c478bd9Sstevel@tonic-gate /* already in the tree, so just free resources */
536*7c478bd9Sstevel@tonic-gate free(n->tag); free(n);
537*7c478bd9Sstevel@tonic-gate }
538*7c478bd9Sstevel@tonic-gate (*numResults)++;
539*7c478bd9Sstevel@tonic-gate }
540*7c478bd9Sstevel@tonic-gate }
541*7c478bd9Sstevel@tonic-gate
build_attrs_list(void * collator)542*7c478bd9Sstevel@tonic-gate static char *build_attrs_list(void *collator) {
543*7c478bd9Sstevel@tonic-gate char *answer = NULL;
544*7c478bd9Sstevel@tonic-gate
545*7c478bd9Sstevel@tonic-gate if (!collator)
546*7c478bd9Sstevel@tonic-gate return (NULL);
547*7c478bd9Sstevel@tonic-gate
548*7c478bd9Sstevel@tonic-gate slp_twalk(collator, collect_attrs, 0, &answer);
549*7c478bd9Sstevel@tonic-gate return (answer);
550*7c478bd9Sstevel@tonic-gate }
551*7c478bd9Sstevel@tonic-gate
552*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
collect_attrs(void * node,VISIT order,int level,void * cookie)553*7c478bd9Sstevel@tonic-gate static void collect_attrs(void *node, VISIT order, int level, void *cookie) {
554*7c478bd9Sstevel@tonic-gate struct attr_node *n;
555*7c478bd9Sstevel@tonic-gate char *attr, *p, **answer = (char **)cookie;
556*7c478bd9Sstevel@tonic-gate
557*7c478bd9Sstevel@tonic-gate if (order == endorder || order == leaf) {
558*7c478bd9Sstevel@tonic-gate n = *(struct attr_node **)node;
559*7c478bd9Sstevel@tonic-gate if (!n->val) {
560*7c478bd9Sstevel@tonic-gate /* no values, so no parens */
561*7c478bd9Sstevel@tonic-gate if (!(attr = malloc(strlen(n->tag) + 1))) {
562*7c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "collect_attrs",
563*7c478bd9Sstevel@tonic-gate "out of memory");
564*7c478bd9Sstevel@tonic-gate return;
565*7c478bd9Sstevel@tonic-gate }
566*7c478bd9Sstevel@tonic-gate (void) strcpy(attr, n->tag);
567*7c478bd9Sstevel@tonic-gate } else {
568*7c478bd9Sstevel@tonic-gate if (!(attr = malloc(1 + strlen(n->tag) + 1 +
569*7c478bd9Sstevel@tonic-gate strlen(n->val) + 2))) {
570*7c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "collect_attrs",
571*7c478bd9Sstevel@tonic-gate "out of memory");
572*7c478bd9Sstevel@tonic-gate return;
573*7c478bd9Sstevel@tonic-gate }
574*7c478bd9Sstevel@tonic-gate /* build attr string */
575*7c478bd9Sstevel@tonic-gate p = attr;
576*7c478bd9Sstevel@tonic-gate *p++ = '(';
577*7c478bd9Sstevel@tonic-gate (void) strcpy(p, n->tag); p += strlen(n->tag);
578*7c478bd9Sstevel@tonic-gate *p++ = '=';
579*7c478bd9Sstevel@tonic-gate (void) strcpy(p, n->val); p += strlen(n->val);
580*7c478bd9Sstevel@tonic-gate *p++ = ')'; *p = 0;
581*7c478bd9Sstevel@tonic-gate }
582*7c478bd9Sstevel@tonic-gate
583*7c478bd9Sstevel@tonic-gate slp_add2list(attr, answer, SLP_FALSE);
584*7c478bd9Sstevel@tonic-gate free(attr);
585*7c478bd9Sstevel@tonic-gate free(n->tag); if (n->val) free(n->val); free(n);
586*7c478bd9Sstevel@tonic-gate free(node);
587*7c478bd9Sstevel@tonic-gate }
588*7c478bd9Sstevel@tonic-gate }
589