4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
31 #include <slp-internal.h>
37 static SLPError
slp_packAttrRqst(slp_handle_impl_t
*, const char *,
39 static int compare_tags(const void *, const void *);
40 static void collate_attrs(char *, void **, int *, int);
41 static void parens_attr(char *, void **, int *);
42 static void merge_attrs(struct attr_node
*, char *);
43 static char *build_attrs_list(void *collator
);
44 static void collect_attrs(void *, VISIT
, int, void *);
45 static SLPBoolean
unpackDAAdvert_attr(slp_handle_impl_t
*, char *,
46 SLPAttrCallback
, void *,
48 static SLPBoolean
unpackSAAdvert_attr(slp_handle_impl_t
*, char *,
49 SLPAttrCallback
, void *,
52 SLPError
SLPFindAttrs(SLPHandle hSLP
, const char *pcURL
, const char *pcScope
,
53 const char *pcAttrIds
,
54 SLPAttrCallback callback
, void *pvUser
) {
57 strcasecmp(pcURL
, "service:service-agent") == 0;
59 strcasecmp(pcURL
, "service:directory-agent") == 0;
60 int isSpecial
= wantSAAdvert
|| wantDAAdvert
;
61 SLPMsgReplyCB
*unpack_cb
;
64 if (!hSLP
|| !pcURL
|| !pcScope
|| (!*pcScope
&& !isSpecial
) ||
65 !pcAttrIds
|| !callback
) {
66 return (SLP_PARAMETER_BAD
);
69 if ((strlen(pcURL
) > SLP_MAX_STRINGLEN
) ||
70 (strlen(pcScope
) > SLP_MAX_STRINGLEN
) ||
71 (strlen(pcAttrIds
) > SLP_MAX_STRINGLEN
)) {
72 return (SLP_PARAMETER_BAD
);
75 if ((err
= slp_start_call(hSLP
)) != SLP_OK
)
78 /* Special packer and unpacker for DA and SA solicitations */
80 unpack_cb
= (SLPMsgReplyCB
*)unpackDAAdvert_attr
;
81 err
= slp_packSrvRqst(pcURL
, "", hSLP
);
82 ((slp_handle_impl_t
*)hSLP
)->force_multicast
= SLP_TRUE
;
83 } else if (wantSAAdvert
) {
84 unpack_cb
= (SLPMsgReplyCB
*)unpackSAAdvert_attr
;
85 err
= slp_packSrvRqst(pcURL
, "", hSLP
);
86 ((slp_handle_impl_t
*)hSLP
)->force_multicast
= SLP_TRUE
;
88 /* normal service request */
89 unpack_cb
= (SLPMsgReplyCB
*)slp_UnpackAttrReply
;
90 /* format params into msgBuf */
91 err
= slp_packAttrRqst(hSLP
, pcURL
, pcAttrIds
);
95 err
= slp_ua_common(hSLP
, pcScope
,
96 (SLPGenericAppCB
*) callback
, pvUser
,
105 SLPBoolean
slp_UnpackAttrReply(slp_handle_impl_t
*hp
, char *reply
,
106 SLPAttrCallback cb
, void *cookie
,
107 void **collator
, int *numResults
) {
110 unsigned short protoErrCode
;
112 int maxResults
= slp_get_maxResults();
113 SLPBoolean cont
= SLP_TRUE
;
119 /* no more results */
121 pcAttrList
= build_attrs_list(*collator
);
124 if (!hp
->async
&& pcAttrList
) {
125 cb(hp
, pcAttrList
, SLP_OK
, cookie
);
128 cb(hp
, NULL
, SLP_LAST_CALL
, cookie
);
132 /* parse reply into params */
133 len
= slp_get_length(reply
);
134 off
= SLP_HDRLEN
+ slp_get_langlen(reply
);
136 if (slp_get_sht(reply
, len
, &off
, &protoErrCode
) != SLP_OK
)
138 /* internal errors should have been filtered out by the net code */
139 if ((errCode
= slp_map_err(protoErrCode
)) != SLP_OK
) {
140 return (cb(hp
, NULL
, errCode
, cookie
));
144 attr_tbv
= reply
+ off
;
146 if (slp_get_string(reply
, len
, &off
, &pcAttrList
) != SLP_OK
)
148 tbv_len
= off
- tbv_len
;
150 /* number of attr auths */
151 if (slp_get_byte(reply
, len
, &off
, &auth_cnt
) != SLP_OK
) {
155 /* get and verify auth blocks */
156 if ((!hp
->internal_call
&& slp_get_security_on()) || auth_cnt
> 0) {
160 iov
[0].iov_base
= attr_tbv
;
161 iov
[0].iov_len
= tbv_len
;
163 if (slp_verify(iov
, 1,
174 collate_attrs(pcAttrList
, collator
, numResults
, maxResults
);
176 /* async: invoke cb */
177 cont
= cb((SLPHandle
) hp
, pcAttrList
, errCode
, cookie
);
184 /* check maxResults */
185 if (!hp
->internal_call
&& *numResults
== maxResults
) {
193 * unpackDAAdvert_attr follows the same logic stream as UnpackAttrReply,
194 * except that reply contains a DAAdvert.
196 static SLPBoolean
unpackDAAdvert_attr(slp_handle_impl_t
*hp
, char *reply
,
197 SLPAttrCallback cb
, void *cookie
,
198 void **collator
, int *numResults
) {
199 char *surl
, *scopes
, *attrs
, *spis
;
200 SLPBoolean cont
= SLP_TRUE
;
202 int maxResults
= slp_get_maxResults();
205 /* no more results */
207 attrs
= build_attrs_list(*collator
);
210 if (!hp
->async
&& attrs
) {
211 cb(hp
, attrs
, SLP_OK
, cookie
);
214 cb(hp
, NULL
, SLP_LAST_CALL
, cookie
);
218 if (slp_unpackDAAdvert(reply
, &surl
, &scopes
, &attrs
, &spis
, &errCode
)
222 if (errCode
!= SLP_OK
) {
223 return (cb(hp
, NULL
, errCode
, cookie
));
228 collate_attrs(attrs
, collator
, numResults
, maxResults
);
230 /* async: invoke cb */
231 cont
= cb((SLPHandle
) hp
, attrs
, errCode
, cookie
);
241 /* check maxResults */
242 if (!hp
->internal_call
&& *numResults
== maxResults
) {
250 * unpackSAAdvert_attr follows the same logic stream as UnpackAttrReply,
251 * except that reply contains an SAAdvert.
253 static SLPBoolean
unpackSAAdvert_attr(slp_handle_impl_t
*hp
, char *reply
,
254 SLPAttrCallback cb
, void *cookie
,
255 void **collator
, int *numResults
) {
256 char *surl
, *scopes
, *attrs
;
257 SLPBoolean cont
= SLP_TRUE
;
258 int maxResults
= slp_get_maxResults();
261 /* no more results */
263 attrs
= build_attrs_list(*collator
);
266 if (!hp
->async
&& attrs
) {
267 cb(hp
, attrs
, SLP_OK
, cookie
);
270 cb(hp
, NULL
, SLP_LAST_CALL
, cookie
);
274 if (slp_unpackSAAdvert(reply
, &surl
, &scopes
, &attrs
) != SLP_OK
) {
280 collate_attrs(attrs
, collator
, numResults
, maxResults
);
282 /* async: invoke cb */
283 cont
= cb((SLPHandle
) hp
, attrs
, SLP_OK
, cookie
);
292 /* check maxResults */
293 if (!hp
->internal_call
&& *numResults
== maxResults
) {
300 static SLPError
slp_packAttrRqst(slp_handle_impl_t
*hp
, const char *url
,
303 size_t len
, tmplen
, msgLen
;
304 slp_msg_t
*msg
= &(hp
->msg
);
307 if (slp_get_security_on()) {
308 spi
= (char *)SLPGetProperty(SLP_CONFIG_SPI
);
316 * Allocate iovec for the messge. An AttrRqst is layed out thus:
319 * 2: prlist (filled in later by networking code)
322 * 5: scopes (filled in later by networking code)
323 * 6: tag list string and SPI string
325 if (!(msg
->iov
= calloc(7, sizeof (*(msg
->iov
))))) {
326 slp_err(LOG_CRIT
, 0, "slp_packAttrRqst", "out of memory");
327 return (SLP_MEMORY_ALLOC_FAILED
);
331 /* calculate msg length */
332 msgLen
= 2 + /* prlist length */
333 2 + strlen(url
) + /* URL */
334 2 + /* scope list length */
335 2 + strlen(ids
) + /* tag list */
336 2 + strlen(spi
); /* SPI string */
338 if (!(msg
->msg
= calloc(1, msgLen
))) {
340 slp_err(LOG_CRIT
, 0, "slp_packAttrRqst", "out of memory");
341 return (SLP_MEMORY_ALLOC_FAILED
);
344 /* set pointer to PR list and scope list length spaces */
345 msg
->prlistlen
.iov_base
= msg
->msg
;
346 msg
->prlistlen
.iov_len
= 2;
347 msg
->iov
[1].iov_base
= msg
->msg
;
348 msg
->iov
[1].iov_len
= 2;
350 msg
->scopeslen
.iov_base
= msg
->msg
+ 2;
351 msg
->scopeslen
.iov_len
= 2;
352 msg
->iov
[4].iov_base
= msg
->msg
+ 2;
353 msg
->iov
[4].iov_len
= 2;
355 /* set up the scopes and prlist pointers into iov */
356 msg
->prlist
= &(msg
->iov
[2]);
357 msg
->scopes
= &(msg
->iov
[5]);
362 msg
->iov
[3].iov_base
= msg
->msg
+ len
;
365 err
= slp_add_string(msg
->msg
, msgLen
, url
, &len
);
366 msg
->iov
[3].iov_len
= len
- tmplen
;
372 msg
->iov
[6].iov_base
= msg
->msg
+ len
;
375 err
= slp_add_string(msg
->msg
, msgLen
, ids
, &len
);
381 err
= slp_add_string(msg
->msg
, msgLen
, spi
, &len
);
383 msg
->iov
[6].iov_len
= len
- tmplen
;
398 SLPError
slp_packAttrRqst_single(const char *url
,
407 SLP_HDRLEN
+ strlen(lang
) + 2 +
411 2; /* No SPI string for internal calls */
413 if (!(*msg
= calloc(msgLen
, 1))) {
414 slp_err(LOG_CRIT
, 0, "slp_packAttrRqst_single", "out of memory");
415 return (SLP_MEMORY_ALLOC_FAILED
);
419 err
= slp_add_header(lang
, *msg
, msgLen
, ATTRRQST
, msgLen
, &len
);
421 len
+= 2; /* empty PR list */
424 err
= slp_add_string(*msg
, msgLen
, url
, &len
);
427 err
= slp_add_string(*msg
, msgLen
, scopes
, &len
);
430 err
= slp_add_string(*msg
, msgLen
, ids
, &len
);
434 err
= slp_add_string(*msg
, msgLen
, "", &len
);
440 static int compare_tags(const void *n1
, const void *n2
) {
441 return slp_strcasecmp(
442 ((struct attr_node
*)n1
)->tag
,
443 ((struct attr_node
*)n2
)->tag
);
446 static void merge_attrs(struct attr_node
*n
, char *vals
) {
449 for (p
= v
= vals
; p
; v
= p
) {
450 p
= slp_utf_strchr(v
, ',');
453 slp_add2list(v
, &(n
->val
), SLP_TRUE
);
457 static void parens_attr(char *attr
, void **collator
, int *numResults
) {
458 char *open_paren
, *close_paren
, *equals
;
459 struct attr_node
*n
, **res
;
461 open_paren
= attr
+ 1;
462 close_paren
= slp_utf_strchr(open_paren
, ')');
464 return; /* skip bad attr list */
467 if (!(equals
= slp_utf_strchr(open_paren
, '=')))
472 if (!(n
= malloc(sizeof (*n
)))) {
473 slp_err(LOG_CRIT
, 0, "collate_attrs", "out of memory");
477 if (!(n
->tag
= strdup(open_paren
))) {
479 slp_err(LOG_CRIT
, 0, "collate_attrs", "out of memory");
484 res
= slp_tsearch(n
, collator
, compare_tags
);
487 merge_attrs(*res
, equals
);
488 free(n
->tag
); free(n
);
490 /* not found; populate new attr node */
492 if (!(n
->val
= strdup(equals
))) {
493 slp_err(LOG_CRIT
, 0, "collate_attrs", "out of memory");
499 static void collate_attrs(char *attrs
, void **collator
,
500 int *numResults
, int maxResults
) {
502 struct attr_node
*n
, **res
;
507 *numResults
!= maxResults
;
509 if (*start
== ',') start
++;
511 /* form of (tag=val,val) */
512 if (!(end
= slp_utf_strchr(start
, ')')))
513 return; /* skip bad attr */
514 parens_attr(start
, collator
, numResults
);
518 end
= slp_utf_strchr(start
, ',');
521 /* create a new node with the tag only */
522 if (!(n
= malloc(sizeof (*n
)))) {
523 slp_err(LOG_CRIT
, 0, "collate_attrs", "out of memory");
527 if (!(n
->tag
= strdup(start
))) {
529 slp_err(LOG_CRIT
, 0, "collate_attrs", "out of memory");
533 res
= slp_tsearch(n
, collator
, compare_tags
);
535 /* already in the tree, so just free resources */
536 free(n
->tag
); free(n
);
542 static char *build_attrs_list(void *collator
) {
548 slp_twalk(collator
, collect_attrs
, 0, &answer
);
553 static void collect_attrs(void *node
, VISIT order
, int level
, void *cookie
) {
555 char *attr
, *p
, **answer
= (char **)cookie
;
557 if (order
== endorder
|| order
== leaf
) {
558 n
= *(struct attr_node
**)node
;
560 /* no values, so no parens */
561 if (!(attr
= malloc(strlen(n
->tag
) + 1))) {
562 slp_err(LOG_CRIT
, 0, "collect_attrs",
566 (void) strcpy(attr
, n
->tag
);
568 if (!(attr
= malloc(1 + strlen(n
->tag
) + 1 +
569 strlen(n
->val
) + 2))) {
570 slp_err(LOG_CRIT
, 0, "collect_attrs",
574 /* build attr string */
577 (void) strcpy(p
, n
->tag
); p
+= strlen(n
->tag
);
579 (void) strcpy(p
, n
->val
); p
+= strlen(n
->val
);
583 slp_add2list(attr
, answer
, SLP_FALSE
);
585 free(n
->tag
); if (n
->val
) free(n
->val
); free(n
);