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 #include <stdio.h>
30*0Sstevel@tonic-gate #include <stdlib.h>
31*0Sstevel@tonic-gate #include <syslog.h>
32*0Sstevel@tonic-gate #include <slp-internal.h>
33*0Sstevel@tonic-gate
34*0Sstevel@tonic-gate struct surl_node {
35*0Sstevel@tonic-gate char *surl;
36*0Sstevel@tonic-gate unsigned short lifetime;
37*0Sstevel@tonic-gate };
38*0Sstevel@tonic-gate
39*0Sstevel@tonic-gate struct caller_bundle {
40*0Sstevel@tonic-gate SLPSrvURLCallback *cb;
41*0Sstevel@tonic-gate void *cookie;
42*0Sstevel@tonic-gate SLPHandle handle;
43*0Sstevel@tonic-gate };
44*0Sstevel@tonic-gate
45*0Sstevel@tonic-gate static int compare_surls(struct surl_node *, struct surl_node *);
46*0Sstevel@tonic-gate static char *collate_surls(char *, unsigned short, void **);
47*0Sstevel@tonic-gate static void traverse_surls(SLPHandle, SLPSrvURLCallback, void *, void *);
48*0Sstevel@tonic-gate static void process_surl_node(void *, VISIT, int, void *);
49*0Sstevel@tonic-gate static SLPBoolean unpackDAAdvert_srv(slp_handle_impl_t *, char *,
50*0Sstevel@tonic-gate SLPSrvURLCallback, void *,
51*0Sstevel@tonic-gate void **, int *);
52*0Sstevel@tonic-gate static SLPBoolean unpackSAAdvert_srv(slp_handle_impl_t *, char *,
53*0Sstevel@tonic-gate SLPSrvURLCallback, void *,
54*0Sstevel@tonic-gate void **, int *);
55*0Sstevel@tonic-gate
SLPFindSrvs(SLPHandle hSLP,const char * pcServiceType,const char * pcScope,const char * pcSearchFilter,SLPSrvURLCallback callback,void * pvUser)56*0Sstevel@tonic-gate SLPError SLPFindSrvs(SLPHandle hSLP, const char *pcServiceType,
57*0Sstevel@tonic-gate const char *pcScope, const char *pcSearchFilter,
58*0Sstevel@tonic-gate SLPSrvURLCallback callback, void *pvUser) {
59*0Sstevel@tonic-gate SLPError err;
60*0Sstevel@tonic-gate slp_handle_impl_t *hp = (slp_handle_impl_t *)hSLP;
61*0Sstevel@tonic-gate int wantSAAdvert =
62*0Sstevel@tonic-gate strcasecmp(pcServiceType, "service:service-agent") == 0;
63*0Sstevel@tonic-gate int wantDAAdvert =
64*0Sstevel@tonic-gate strcasecmp(pcServiceType, "service:directory-agent") == 0;
65*0Sstevel@tonic-gate int isSpecial = wantSAAdvert || wantDAAdvert;
66*0Sstevel@tonic-gate SLPMsgReplyCB *unpack_cb;
67*0Sstevel@tonic-gate
68*0Sstevel@tonic-gate if (!hSLP || !pcServiceType || !pcScope || (!*pcScope && !isSpecial) ||
69*0Sstevel@tonic-gate !pcSearchFilter || !callback) {
70*0Sstevel@tonic-gate return (SLP_PARAMETER_BAD);
71*0Sstevel@tonic-gate }
72*0Sstevel@tonic-gate
73*0Sstevel@tonic-gate if ((strlen(pcServiceType) > SLP_MAX_STRINGLEN) ||
74*0Sstevel@tonic-gate (strlen(pcScope) > SLP_MAX_STRINGLEN) ||
75*0Sstevel@tonic-gate (strlen(pcSearchFilter) > SLP_MAX_STRINGLEN)) {
76*0Sstevel@tonic-gate return (SLP_PARAMETER_BAD);
77*0Sstevel@tonic-gate }
78*0Sstevel@tonic-gate
79*0Sstevel@tonic-gate if ((err = slp_start_call(hSLP)) != SLP_OK)
80*0Sstevel@tonic-gate return (err);
81*0Sstevel@tonic-gate
82*0Sstevel@tonic-gate /* Special unpacker for DA and SA solicitations */
83*0Sstevel@tonic-gate if (wantDAAdvert) {
84*0Sstevel@tonic-gate unpack_cb = (SLPMsgReplyCB *)unpackDAAdvert_srv;
85*0Sstevel@tonic-gate hp->force_multicast = SLP_TRUE;
86*0Sstevel@tonic-gate } else if (wantSAAdvert) {
87*0Sstevel@tonic-gate unpack_cb = (SLPMsgReplyCB *)unpackSAAdvert_srv;
88*0Sstevel@tonic-gate hp->force_multicast = SLP_TRUE;
89*0Sstevel@tonic-gate } else {
90*0Sstevel@tonic-gate /* normal service request */
91*0Sstevel@tonic-gate unpack_cb = (SLPMsgReplyCB *)slp_unpackSrvReply;
92*0Sstevel@tonic-gate }
93*0Sstevel@tonic-gate
94*0Sstevel@tonic-gate err = slp_packSrvRqst(pcServiceType, pcSearchFilter, hp);
95*0Sstevel@tonic-gate
96*0Sstevel@tonic-gate if (err == SLP_OK)
97*0Sstevel@tonic-gate err = slp_ua_common(hSLP, pcScope,
98*0Sstevel@tonic-gate (SLPGenericAppCB *) callback, pvUser,
99*0Sstevel@tonic-gate unpack_cb);
100*0Sstevel@tonic-gate if (err != SLP_OK)
101*0Sstevel@tonic-gate slp_end_call(hSLP);
102*0Sstevel@tonic-gate
103*0Sstevel@tonic-gate return (err);
104*0Sstevel@tonic-gate }
105*0Sstevel@tonic-gate
slp_unpackSrvReply(slp_handle_impl_t * hp,char * reply,SLPSrvURLCallback cb,void * cookie,void ** collator,int * numResults)106*0Sstevel@tonic-gate SLPBoolean slp_unpackSrvReply(slp_handle_impl_t *hp, char *reply,
107*0Sstevel@tonic-gate SLPSrvURLCallback cb, void *cookie,
108*0Sstevel@tonic-gate void **collator, int *numResults) {
109*0Sstevel@tonic-gate SLPError errCode;
110*0Sstevel@tonic-gate unsigned short urlCount, protoErrCode;
111*0Sstevel@tonic-gate size_t len, off;
112*0Sstevel@tonic-gate int i;
113*0Sstevel@tonic-gate int maxResults = slp_get_maxResults();
114*0Sstevel@tonic-gate SLPBoolean cont = SLP_TRUE;
115*0Sstevel@tonic-gate
116*0Sstevel@tonic-gate if (!reply) {
117*0Sstevel@tonic-gate /* no more results */
118*0Sstevel@tonic-gate /* traverse_surls:invoke cb for sync case,and free resources */
119*0Sstevel@tonic-gate if (!hp->async) {
120*0Sstevel@tonic-gate traverse_surls(hp, cb, cookie, *collator);
121*0Sstevel@tonic-gate }
122*0Sstevel@tonic-gate cb(hp, NULL, 0, SLP_LAST_CALL, cookie);
123*0Sstevel@tonic-gate return (SLP_FALSE);
124*0Sstevel@tonic-gate }
125*0Sstevel@tonic-gate
126*0Sstevel@tonic-gate len = slp_get_length(reply);
127*0Sstevel@tonic-gate off = SLP_HDRLEN + slp_get_langlen(reply);
128*0Sstevel@tonic-gate /* err code */
129*0Sstevel@tonic-gate if (slp_get_sht(reply, len, &off, &protoErrCode) != SLP_OK)
130*0Sstevel@tonic-gate return (SLP_TRUE);
131*0Sstevel@tonic-gate /* internal errors should have been filtered out by the net code */
132*0Sstevel@tonic-gate if ((errCode = slp_map_err(protoErrCode)) != SLP_OK) {
133*0Sstevel@tonic-gate return (cb(hp, NULL, 0, errCode, cookie));
134*0Sstevel@tonic-gate }
135*0Sstevel@tonic-gate
136*0Sstevel@tonic-gate /* url entry count */
137*0Sstevel@tonic-gate if (slp_get_sht(reply, len, &off, &urlCount) != SLP_OK)
138*0Sstevel@tonic-gate return (SLP_TRUE);
139*0Sstevel@tonic-gate
140*0Sstevel@tonic-gate /* for each srvRply, unpack and pass to CB */
141*0Sstevel@tonic-gate for (i = 0; i < urlCount && !hp->cancel; i++) {
142*0Sstevel@tonic-gate char *pcSrvURL;
143*0Sstevel@tonic-gate unsigned short sLifetime;
144*0Sstevel@tonic-gate int nURLAuthBlocks;
145*0Sstevel@tonic-gate size_t tbv_len;
146*0Sstevel@tonic-gate char *url_tbv;
147*0Sstevel@tonic-gate
148*0Sstevel@tonic-gate /* parse URL entry into params */
149*0Sstevel@tonic-gate off++; /* skip reserved byte */
150*0Sstevel@tonic-gate /* lifetime */
151*0Sstevel@tonic-gate if (slp_get_sht(reply, len, &off, &sLifetime) != SLP_OK)
152*0Sstevel@tonic-gate return (SLP_TRUE);
153*0Sstevel@tonic-gate /* URL itself; keep track of it in case we need to verify */
154*0Sstevel@tonic-gate url_tbv = reply + off;
155*0Sstevel@tonic-gate tbv_len = off;
156*0Sstevel@tonic-gate if (slp_get_string(reply, len, &off, &pcSrvURL) != SLP_OK)
157*0Sstevel@tonic-gate return (SLP_TRUE);
158*0Sstevel@tonic-gate tbv_len = off - tbv_len;
159*0Sstevel@tonic-gate
160*0Sstevel@tonic-gate /* number of url auths */
161*0Sstevel@tonic-gate if (slp_get_byte(reply, len, &off, &nURLAuthBlocks) != SLP_OK)
162*0Sstevel@tonic-gate goto cleanup;
163*0Sstevel@tonic-gate
164*0Sstevel@tonic-gate /* get and verify auth blocks */
165*0Sstevel@tonic-gate if ((!hp->internal_call && slp_get_security_on()) ||
166*0Sstevel@tonic-gate nURLAuthBlocks > 0) {
167*0Sstevel@tonic-gate struct iovec iov[1];
168*0Sstevel@tonic-gate size_t abLen = 0;
169*0Sstevel@tonic-gate
170*0Sstevel@tonic-gate iov[0].iov_base = url_tbv;
171*0Sstevel@tonic-gate iov[0].iov_len = tbv_len;
172*0Sstevel@tonic-gate
173*0Sstevel@tonic-gate if (slp_verify(iov, 1,
174*0Sstevel@tonic-gate reply + off,
175*0Sstevel@tonic-gate len - off,
176*0Sstevel@tonic-gate nURLAuthBlocks,
177*0Sstevel@tonic-gate &abLen) != SLP_OK) {
178*0Sstevel@tonic-gate goto cleanup;
179*0Sstevel@tonic-gate }
180*0Sstevel@tonic-gate off += abLen;
181*0Sstevel@tonic-gate }
182*0Sstevel@tonic-gate
183*0Sstevel@tonic-gate /* collate the srv urls for sync behavior */
184*0Sstevel@tonic-gate if (!hp->async) {
185*0Sstevel@tonic-gate pcSrvURL = collate_surls(pcSrvURL, sLifetime, collator);
186*0Sstevel@tonic-gate
187*0Sstevel@tonic-gate if (!pcSrvURL)
188*0Sstevel@tonic-gate continue;
189*0Sstevel@tonic-gate }
190*0Sstevel@tonic-gate
191*0Sstevel@tonic-gate (*numResults)++;
192*0Sstevel@tonic-gate /* invoke cb */
193*0Sstevel@tonic-gate if (hp->async)
194*0Sstevel@tonic-gate cont = cb(
195*0Sstevel@tonic-gate (SLPHandle) hp,
196*0Sstevel@tonic-gate pcSrvURL,
197*0Sstevel@tonic-gate sLifetime,
198*0Sstevel@tonic-gate errCode,
199*0Sstevel@tonic-gate cookie);
200*0Sstevel@tonic-gate
201*0Sstevel@tonic-gate /* cleanup */
202*0Sstevel@tonic-gate cleanup:
203*0Sstevel@tonic-gate free(pcSrvURL);
204*0Sstevel@tonic-gate
205*0Sstevel@tonic-gate /* check maxResults */
206*0Sstevel@tonic-gate if (!hp->internal_call && *numResults == maxResults) {
207*0Sstevel@tonic-gate cont = SLP_FALSE;
208*0Sstevel@tonic-gate }
209*0Sstevel@tonic-gate
210*0Sstevel@tonic-gate if (!cont) break;
211*0Sstevel@tonic-gate }
212*0Sstevel@tonic-gate
213*0Sstevel@tonic-gate return (cont);
214*0Sstevel@tonic-gate }
215*0Sstevel@tonic-gate
216*0Sstevel@tonic-gate /*
217*0Sstevel@tonic-gate * unpackDAAdvert_srv follows the same same logic flow as slp_unpackSrvReply
218*0Sstevel@tonic-gate * with two differences: the message in reply is a DAAdvert, and
219*0Sstevel@tonic-gate * this function is not used internally, so hp is never NULL. Although
220*0Sstevel@tonic-gate * all info from a DAAdvert is returned by slp_unpackDAAdvert, here
221*0Sstevel@tonic-gate * the recipient (the user-supplied SLPSrvURLCallback) is interested
222*0Sstevel@tonic-gate * only in the DA service URL.
223*0Sstevel@tonic-gate */
unpackDAAdvert_srv(slp_handle_impl_t * hp,char * reply,SLPSrvURLCallback cb,void * cookie,void ** collator,int * numResults)224*0Sstevel@tonic-gate static SLPBoolean unpackDAAdvert_srv(slp_handle_impl_t *hp, char *reply,
225*0Sstevel@tonic-gate SLPSrvURLCallback cb, void *cookie,
226*0Sstevel@tonic-gate void **collator, int *numResults) {
227*0Sstevel@tonic-gate char *surl, *scopes, *attrs, *spis;
228*0Sstevel@tonic-gate SLPBoolean cont = SLP_TRUE;
229*0Sstevel@tonic-gate SLPError errCode;
230*0Sstevel@tonic-gate int maxResults = slp_get_maxResults();
231*0Sstevel@tonic-gate
232*0Sstevel@tonic-gate if (!reply) {
233*0Sstevel@tonic-gate /* no more results */
234*0Sstevel@tonic-gate /* traverse_surls:invoke cb for sync case,and free resources */
235*0Sstevel@tonic-gate if (!hp->async) {
236*0Sstevel@tonic-gate traverse_surls(hp, cb, cookie, *collator);
237*0Sstevel@tonic-gate }
238*0Sstevel@tonic-gate cb(hp, NULL, 0, SLP_LAST_CALL, cookie);
239*0Sstevel@tonic-gate return (SLP_FALSE);
240*0Sstevel@tonic-gate }
241*0Sstevel@tonic-gate
242*0Sstevel@tonic-gate if (slp_unpackDAAdvert(reply, &surl, &scopes, &attrs, &spis, &errCode)
243*0Sstevel@tonic-gate != SLP_OK) {
244*0Sstevel@tonic-gate return (SLP_TRUE);
245*0Sstevel@tonic-gate }
246*0Sstevel@tonic-gate if (errCode != SLP_OK) {
247*0Sstevel@tonic-gate return (cb(hp, NULL, 0, errCode, cookie));
248*0Sstevel@tonic-gate }
249*0Sstevel@tonic-gate
250*0Sstevel@tonic-gate /* collate the urls */
251*0Sstevel@tonic-gate surl = collate_surls(surl, 0, collator);
252*0Sstevel@tonic-gate if (!surl) {
253*0Sstevel@tonic-gate return (SLP_TRUE);
254*0Sstevel@tonic-gate }
255*0Sstevel@tonic-gate
256*0Sstevel@tonic-gate (*numResults)++;
257*0Sstevel@tonic-gate if (hp->async) {
258*0Sstevel@tonic-gate cont = cb((SLPHandle)hp, surl, 0, errCode, cookie);
259*0Sstevel@tonic-gate }
260*0Sstevel@tonic-gate
261*0Sstevel@tonic-gate /* cleanup */
262*0Sstevel@tonic-gate free(surl);
263*0Sstevel@tonic-gate free(scopes);
264*0Sstevel@tonic-gate free(attrs);
265*0Sstevel@tonic-gate free(spis);
266*0Sstevel@tonic-gate
267*0Sstevel@tonic-gate /* check maxResults */
268*0Sstevel@tonic-gate if (!hp->internal_call && *numResults == maxResults) {
269*0Sstevel@tonic-gate return (SLP_FALSE);
270*0Sstevel@tonic-gate }
271*0Sstevel@tonic-gate
272*0Sstevel@tonic-gate return (cont);
273*0Sstevel@tonic-gate }
274*0Sstevel@tonic-gate /*
275*0Sstevel@tonic-gate * unpackSAAdvert_srv follows the same same logic flow as slp_unpackSrvReply
276*0Sstevel@tonic-gate * with two differences: the message in reply is a SAAdvert, and
277*0Sstevel@tonic-gate * this function is not used internally, so hp is never NULL. Although
278*0Sstevel@tonic-gate * all info from an SAAdvert is returned by slp_unpackSAAdvert, here
279*0Sstevel@tonic-gate * the recipient (the user-supplied SLPSrvURLCallback) is interested
280*0Sstevel@tonic-gate * only in the SA service URL.
281*0Sstevel@tonic-gate */
unpackSAAdvert_srv(slp_handle_impl_t * hp,char * reply,SLPSrvURLCallback cb,void * cookie,void ** collator,int * numResults)282*0Sstevel@tonic-gate static SLPBoolean unpackSAAdvert_srv(slp_handle_impl_t *hp, char *reply,
283*0Sstevel@tonic-gate SLPSrvURLCallback cb, void *cookie,
284*0Sstevel@tonic-gate void **collator, int *numResults) {
285*0Sstevel@tonic-gate char *surl, *scopes, *attrs;
286*0Sstevel@tonic-gate SLPBoolean cont = SLP_TRUE;
287*0Sstevel@tonic-gate int maxResults = slp_get_maxResults();
288*0Sstevel@tonic-gate
289*0Sstevel@tonic-gate if (!reply) {
290*0Sstevel@tonic-gate /* no more results */
291*0Sstevel@tonic-gate /* traverse_surls:invoke cb for sync case,and free resources */
292*0Sstevel@tonic-gate if (!hp->async) {
293*0Sstevel@tonic-gate /* sync case */
294*0Sstevel@tonic-gate traverse_surls(hp, cb, cookie, *collator);
295*0Sstevel@tonic-gate }
296*0Sstevel@tonic-gate cb(hp, NULL, 0, SLP_LAST_CALL, cookie);
297*0Sstevel@tonic-gate return (SLP_FALSE);
298*0Sstevel@tonic-gate }
299*0Sstevel@tonic-gate
300*0Sstevel@tonic-gate if (slp_unpackSAAdvert(reply, &surl, &scopes, &attrs) != SLP_OK) {
301*0Sstevel@tonic-gate return (SLP_TRUE);
302*0Sstevel@tonic-gate }
303*0Sstevel@tonic-gate
304*0Sstevel@tonic-gate /* collate the urls */
305*0Sstevel@tonic-gate surl = collate_surls(surl, 0, collator);
306*0Sstevel@tonic-gate if (!surl) {
307*0Sstevel@tonic-gate return (SLP_TRUE);
308*0Sstevel@tonic-gate }
309*0Sstevel@tonic-gate
310*0Sstevel@tonic-gate (*numResults)++;
311*0Sstevel@tonic-gate if (hp->async) {
312*0Sstevel@tonic-gate cont = cb((SLPHandle)hp, surl, 0, SLP_OK, cookie);
313*0Sstevel@tonic-gate }
314*0Sstevel@tonic-gate
315*0Sstevel@tonic-gate /* cleanup */
316*0Sstevel@tonic-gate free(surl);
317*0Sstevel@tonic-gate free(scopes);
318*0Sstevel@tonic-gate free(attrs);
319*0Sstevel@tonic-gate
320*0Sstevel@tonic-gate /* check maxResults */
321*0Sstevel@tonic-gate if (!hp->internal_call && *numResults == maxResults) {
322*0Sstevel@tonic-gate return (SLP_FALSE);
323*0Sstevel@tonic-gate }
324*0Sstevel@tonic-gate
325*0Sstevel@tonic-gate return (cont);
326*0Sstevel@tonic-gate }
327*0Sstevel@tonic-gate
slp_packSrvRqst(const char * type,const char * filter,slp_handle_impl_t * hp)328*0Sstevel@tonic-gate SLPError slp_packSrvRqst(const char *type,
329*0Sstevel@tonic-gate const char *filter,
330*0Sstevel@tonic-gate slp_handle_impl_t *hp) {
331*0Sstevel@tonic-gate SLPError err;
332*0Sstevel@tonic-gate size_t len, msgLen, tmplen;
333*0Sstevel@tonic-gate slp_msg_t *msg = &(hp->msg);
334*0Sstevel@tonic-gate char *spi = NULL;
335*0Sstevel@tonic-gate
336*0Sstevel@tonic-gate if (slp_get_security_on()) {
337*0Sstevel@tonic-gate spi = (char *)SLPGetProperty(SLP_CONFIG_SPI);
338*0Sstevel@tonic-gate }
339*0Sstevel@tonic-gate
340*0Sstevel@tonic-gate if (!spi || !*spi) {
341*0Sstevel@tonic-gate spi = "";
342*0Sstevel@tonic-gate }
343*0Sstevel@tonic-gate
344*0Sstevel@tonic-gate /*
345*0Sstevel@tonic-gate * Allocate iovec for the messge. A SrvRqst is layed out thus:
346*0Sstevel@tonic-gate * 0: header
347*0Sstevel@tonic-gate * 1: prlist length
348*0Sstevel@tonic-gate * 2: prlist (filled in later by networking code)
349*0Sstevel@tonic-gate * 3: service type string
350*0Sstevel@tonic-gate * 4: scopes length
351*0Sstevel@tonic-gate * 5: scopes (filled in later by networking code)
352*0Sstevel@tonic-gate * 6: predicate string and SPI string
353*0Sstevel@tonic-gate */
354*0Sstevel@tonic-gate if (!(msg->iov = calloc(7, sizeof (*(msg->iov))))) {
355*0Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "slp_packSrvRqst", "out of memory");
356*0Sstevel@tonic-gate return (SLP_MEMORY_ALLOC_FAILED);
357*0Sstevel@tonic-gate }
358*0Sstevel@tonic-gate msg->iovlen = 7;
359*0Sstevel@tonic-gate
360*0Sstevel@tonic-gate /* calculate msg length */
361*0Sstevel@tonic-gate msgLen = 2 + /* prlist length */
362*0Sstevel@tonic-gate 2 + strlen(type) + /* service type */
363*0Sstevel@tonic-gate 2 + /* scope list length */
364*0Sstevel@tonic-gate 2 + strlen(filter) + /* predicate string */
365*0Sstevel@tonic-gate 2 + strlen(spi); /* SPI string */
366*0Sstevel@tonic-gate
367*0Sstevel@tonic-gate if (!(msg->msg = calloc(1, msgLen))) {
368*0Sstevel@tonic-gate free(msg->iov);
369*0Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "slp_packSrvRqst", "out of memory");
370*0Sstevel@tonic-gate return (SLP_MEMORY_ALLOC_FAILED);
371*0Sstevel@tonic-gate }
372*0Sstevel@tonic-gate
373*0Sstevel@tonic-gate /* set pointer to PR list and scope list length spaces */
374*0Sstevel@tonic-gate msg->prlistlen.iov_base = msg->msg;
375*0Sstevel@tonic-gate msg->prlistlen.iov_len = 2;
376*0Sstevel@tonic-gate msg->iov[1].iov_base = msg->msg;
377*0Sstevel@tonic-gate msg->iov[1].iov_len = 2;
378*0Sstevel@tonic-gate
379*0Sstevel@tonic-gate msg->scopeslen.iov_base = msg->msg + 2;
380*0Sstevel@tonic-gate msg->scopeslen.iov_len = 2;
381*0Sstevel@tonic-gate msg->iov[4].iov_base = msg->msg + 2;
382*0Sstevel@tonic-gate msg->iov[4].iov_len = 2;
383*0Sstevel@tonic-gate
384*0Sstevel@tonic-gate /* set up the scopes and prlist pointers into iov */
385*0Sstevel@tonic-gate msg->prlist = &(msg->iov[2]);
386*0Sstevel@tonic-gate msg->scopes = &(msg->iov[5]);
387*0Sstevel@tonic-gate
388*0Sstevel@tonic-gate len = 4;
389*0Sstevel@tonic-gate
390*0Sstevel@tonic-gate /* Add type string */
391*0Sstevel@tonic-gate msg->iov[3].iov_base = msg->msg + len;
392*0Sstevel@tonic-gate tmplen = len;
393*0Sstevel@tonic-gate
394*0Sstevel@tonic-gate err = slp_add_string(msg->msg, msgLen, type, &len);
395*0Sstevel@tonic-gate msg->iov[3].iov_len = len - tmplen;
396*0Sstevel@tonic-gate
397*0Sstevel@tonic-gate if (err != SLP_OK)
398*0Sstevel@tonic-gate goto error;
399*0Sstevel@tonic-gate
400*0Sstevel@tonic-gate /* Add search filter */
401*0Sstevel@tonic-gate msg->iov[6].iov_base = msg->msg + len;
402*0Sstevel@tonic-gate tmplen = len;
403*0Sstevel@tonic-gate
404*0Sstevel@tonic-gate err = slp_add_string(msg->msg, msgLen, filter, &len);
405*0Sstevel@tonic-gate if (err != SLP_OK)
406*0Sstevel@tonic-gate goto error;
407*0Sstevel@tonic-gate
408*0Sstevel@tonic-gate err = slp_add_string(msg->msg, msgLen, spi, &len);
409*0Sstevel@tonic-gate
410*0Sstevel@tonic-gate msg->iov[6].iov_len = len - tmplen;
411*0Sstevel@tonic-gate
412*0Sstevel@tonic-gate hp->fid = SRVRQST;
413*0Sstevel@tonic-gate
414*0Sstevel@tonic-gate if (err == SLP_OK) {
415*0Sstevel@tonic-gate return (err);
416*0Sstevel@tonic-gate }
417*0Sstevel@tonic-gate
418*0Sstevel@tonic-gate /* else error */
419*0Sstevel@tonic-gate error:
420*0Sstevel@tonic-gate free(msg->iov);
421*0Sstevel@tonic-gate free(msg->msg);
422*0Sstevel@tonic-gate
423*0Sstevel@tonic-gate return (err);
424*0Sstevel@tonic-gate }
425*0Sstevel@tonic-gate
426*0Sstevel@tonic-gate /*
427*0Sstevel@tonic-gate * Caller must free msg
428*0Sstevel@tonic-gate */
slp_packSrvRqst_single(const char * type,const char * scopes,const char * filter,char ** msg,const char * lang)429*0Sstevel@tonic-gate SLPError slp_packSrvRqst_single(const char *type,
430*0Sstevel@tonic-gate const char *scopes,
431*0Sstevel@tonic-gate const char *filter,
432*0Sstevel@tonic-gate char **msg,
433*0Sstevel@tonic-gate const char *lang) {
434*0Sstevel@tonic-gate SLPError err;
435*0Sstevel@tonic-gate size_t len, msgLen;
436*0Sstevel@tonic-gate
437*0Sstevel@tonic-gate msgLen =
438*0Sstevel@tonic-gate SLP_HDRLEN + strlen(lang) + 2 +
439*0Sstevel@tonic-gate 2 + strlen(type) +
440*0Sstevel@tonic-gate 2 + strlen(scopes) +
441*0Sstevel@tonic-gate 2 + strlen(filter) +
442*0Sstevel@tonic-gate 2; /* No SPI string for internal calls */
443*0Sstevel@tonic-gate
444*0Sstevel@tonic-gate if (!(*msg = calloc(msgLen, 1))) {
445*0Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "slp_packSrvRqst_single",
446*0Sstevel@tonic-gate "out of memory");
447*0Sstevel@tonic-gate return (SLP_MEMORY_ALLOC_FAILED);
448*0Sstevel@tonic-gate }
449*0Sstevel@tonic-gate
450*0Sstevel@tonic-gate len = 0;
451*0Sstevel@tonic-gate err = slp_add_header(lang, *msg, msgLen, SRVRQST, msgLen, &len);
452*0Sstevel@tonic-gate
453*0Sstevel@tonic-gate len += 2; /* empty PR list */
454*0Sstevel@tonic-gate
455*0Sstevel@tonic-gate if (err == SLP_OK)
456*0Sstevel@tonic-gate err = slp_add_string(*msg, msgLen, type, &len);
457*0Sstevel@tonic-gate if (err == SLP_OK)
458*0Sstevel@tonic-gate err = slp_add_string(*msg, msgLen, scopes, &len);
459*0Sstevel@tonic-gate if (err == SLP_OK)
460*0Sstevel@tonic-gate err = slp_add_string(*msg, msgLen, filter, &len);
461*0Sstevel@tonic-gate if (err == SLP_OK)
462*0Sstevel@tonic-gate /* empty SPI string */
463*0Sstevel@tonic-gate err = slp_add_string(*msg, msgLen, "", &len);
464*0Sstevel@tonic-gate
465*0Sstevel@tonic-gate return (err);
466*0Sstevel@tonic-gate }
467*0Sstevel@tonic-gate
468*0Sstevel@tonic-gate
compare_surls(struct surl_node * s1,struct surl_node * s2)469*0Sstevel@tonic-gate static int compare_surls(struct surl_node *s1, struct surl_node *s2) {
470*0Sstevel@tonic-gate if (s1->lifetime != s2->lifetime)
471*0Sstevel@tonic-gate return (s1->lifetime - s2->lifetime);
472*0Sstevel@tonic-gate return (slp_strcasecmp(s1->surl, s2->surl));
473*0Sstevel@tonic-gate }
474*0Sstevel@tonic-gate
475*0Sstevel@tonic-gate /*
476*0Sstevel@tonic-gate * Using the collator, determine if this URL has already been processed.
477*0Sstevel@tonic-gate * If so, free surl and return NULL, else return the URL.
478*0Sstevel@tonic-gate */
collate_surls(char * surl,unsigned short life,void ** collator)479*0Sstevel@tonic-gate static char *collate_surls(char *surl, unsigned short life, void **collator) {
480*0Sstevel@tonic-gate struct surl_node *n, **res;
481*0Sstevel@tonic-gate
482*0Sstevel@tonic-gate if (!(n = malloc(sizeof (*n)))) {
483*0Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "collate_surls", "out of memory");
484*0Sstevel@tonic-gate return (NULL);
485*0Sstevel@tonic-gate }
486*0Sstevel@tonic-gate if (!(n->surl = strdup(surl))) {
487*0Sstevel@tonic-gate free(n);
488*0Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "collate_surls", "out of memory");
489*0Sstevel@tonic-gate return (NULL);
490*0Sstevel@tonic-gate }
491*0Sstevel@tonic-gate n->lifetime = life;
492*0Sstevel@tonic-gate res = slp_tsearch((void *) n, collator,
493*0Sstevel@tonic-gate (int (*)(const void *, const void *)) compare_surls);
494*0Sstevel@tonic-gate if (*res == n) {
495*0Sstevel@tonic-gate /* first time we've encountered this url */
496*0Sstevel@tonic-gate return (surl);
497*0Sstevel@tonic-gate }
498*0Sstevel@tonic-gate /* else already in tree */
499*0Sstevel@tonic-gate free(n->surl);
500*0Sstevel@tonic-gate free(n);
501*0Sstevel@tonic-gate free(surl);
502*0Sstevel@tonic-gate return (NULL);
503*0Sstevel@tonic-gate }
504*0Sstevel@tonic-gate
traverse_surls(SLPHandle h,SLPSrvURLCallback cb,void * cookie,void * collator)505*0Sstevel@tonic-gate static void traverse_surls(SLPHandle h, SLPSrvURLCallback cb,
506*0Sstevel@tonic-gate void *cookie, void *collator) {
507*0Sstevel@tonic-gate struct caller_bundle caller[1];
508*0Sstevel@tonic-gate
509*0Sstevel@tonic-gate if (!collator)
510*0Sstevel@tonic-gate return;
511*0Sstevel@tonic-gate caller->cb = cb;
512*0Sstevel@tonic-gate caller->cookie = cookie;
513*0Sstevel@tonic-gate caller->handle = h;
514*0Sstevel@tonic-gate slp_twalk(collator, process_surl_node, 0, caller);
515*0Sstevel@tonic-gate }
516*0Sstevel@tonic-gate
517*0Sstevel@tonic-gate /*ARGSUSED*/
process_surl_node(void * node,VISIT order,int level,void * c)518*0Sstevel@tonic-gate static void process_surl_node(void *node, VISIT order, int level, void *c) {
519*0Sstevel@tonic-gate struct surl_node *n;
520*0Sstevel@tonic-gate SLPSrvURLCallback *cb;
521*0Sstevel@tonic-gate slp_handle_impl_t *h;
522*0Sstevel@tonic-gate struct caller_bundle *caller = (struct caller_bundle *)c;
523*0Sstevel@tonic-gate
524*0Sstevel@tonic-gate if (order == endorder || order == leaf) {
525*0Sstevel@tonic-gate SLPBoolean cont = SLP_TRUE;
526*0Sstevel@tonic-gate
527*0Sstevel@tonic-gate cb = caller->cb;
528*0Sstevel@tonic-gate h = (slp_handle_impl_t *)caller->handle;
529*0Sstevel@tonic-gate n = *(struct surl_node **)node;
530*0Sstevel@tonic-gate /* invoke cb */
531*0Sstevel@tonic-gate if (cont && (!h || !h->async))
532*0Sstevel@tonic-gate cont = cb(
533*0Sstevel@tonic-gate h, n->surl,
534*0Sstevel@tonic-gate n->lifetime,
535*0Sstevel@tonic-gate SLP_OK,
536*0Sstevel@tonic-gate caller->cookie);
537*0Sstevel@tonic-gate
538*0Sstevel@tonic-gate free(n->surl);
539*0Sstevel@tonic-gate free(n);
540*0Sstevel@tonic-gate free(node);
541*0Sstevel@tonic-gate }
542*0Sstevel@tonic-gate }
543