1 /*
2 * CDDL HEADER START
3 *
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
7 * with the License.
8 *
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.
13 *
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]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright (c) 1999 by Sun Microsystems, Inc.
24 * All rights reserved.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #include <syslog.h>
30 #include <slp-internal.h>
31
32 static SLPBoolean UnpackSrvTypesReply(slp_handle_impl_t *, char *,
33 SLPSrvTypeCallback, void *,
34 void **, int *);
35 static SLPError slp_packSrvTypeRqst(slp_handle_impl_t *, const char *);
36 static char *collate_types(char *, void **, int *, int);
37 static char *build_types_list(void *);
38 static void collect_types(void *, VISIT, int, void *);
39
SLPFindSrvTypes(SLPHandle hSLP,const char * pcNamingAuthority,const char * pcScopeList,SLPSrvTypeCallback callback,void * pvUser)40 SLPError SLPFindSrvTypes(SLPHandle hSLP, const char *pcNamingAuthority,
41 const char *pcScopeList,
42 SLPSrvTypeCallback callback, void *pvUser) {
43 SLPError err;
44
45 if (!hSLP || !pcNamingAuthority || !pcScopeList ||
46 !*pcScopeList || !callback) {
47 return (SLP_PARAMETER_BAD);
48 }
49
50 if ((strlen(pcNamingAuthority) > SLP_MAX_STRINGLEN) ||
51 (strlen(pcScopeList) > SLP_MAX_STRINGLEN)) {
52 return (SLP_PARAMETER_BAD);
53 }
54
55 if ((err = slp_start_call(hSLP)) != SLP_OK)
56 return (err);
57
58 /* format params into msgBuf */
59 err = slp_packSrvTypeRqst(hSLP, pcNamingAuthority);
60
61 if (err == SLP_OK)
62 err = slp_ua_common(hSLP, pcScopeList,
63 (SLPGenericAppCB *) callback, pvUser,
64 (SLPMsgReplyCB *) UnpackSrvTypesReply);
65
66 if (err != SLP_OK)
67 slp_end_call(hSLP);
68
69 return (err);
70 }
71
UnpackSrvTypesReply(slp_handle_impl_t * hp,char * reply,SLPSrvTypeCallback cb,void * cookie,void ** collator,int * numResults)72 static SLPBoolean UnpackSrvTypesReply(slp_handle_impl_t *hp, char *reply,
73 SLPSrvTypeCallback cb, void *cookie,
74 void **collator, int *numResults) {
75 char *pcSrvTypes;
76 SLPError errCode;
77 unsigned short protoErrCode;
78 size_t off, len;
79 int maxResults = slp_get_maxResults();
80 SLPBoolean cont = SLP_TRUE;
81
82 if (!reply) {
83 /* no more results */
84 if (!hp->async) {
85 pcSrvTypes = build_types_list(*collator);
86 }
87
88 if (!hp->async && pcSrvTypes) {
89 /* synchronous case */
90 cb(hp, pcSrvTypes, SLP_OK, cookie);
91 free(pcSrvTypes);
92 }
93 cb(hp, NULL, SLP_LAST_CALL, cookie);
94 return (SLP_FALSE);
95 }
96
97 /* parse reply into params */
98 len = slp_get_length(reply);
99 off = SLP_HDRLEN + slp_get_langlen(reply);
100 /* error code */
101 if (slp_get_sht(reply, len, &off, &protoErrCode) != SLP_OK)
102 return (SLP_TRUE);
103 /* internal errors should have been filtered out by the net code */
104 if ((errCode = slp_map_err(protoErrCode)) != SLP_OK) {
105 return (cb(hp, NULL, errCode, cookie));
106 }
107
108 /* types string */
109 if (slp_get_string(reply, len, &off, &pcSrvTypes) != SLP_OK)
110 return (SLP_TRUE);
111
112 /* collate the types for sync behavior */
113 if (!hp->async) {
114 pcSrvTypes = collate_types(pcSrvTypes, collator,
115 numResults, maxResults);
116 if (!pcSrvTypes)
117 return (SLP_TRUE);
118 } else {
119 /* async; invoke cb */
120 cont = cb((SLPHandle) hp, pcSrvTypes, errCode, cookie);
121 }
122
123 /* cleanup */
124 free(pcSrvTypes);
125
126 /* check maxResults */
127 if (!hp->internal_call && *numResults == maxResults) {
128 return (SLP_FALSE);
129 }
130
131 return (cont);
132 }
133
slp_packSrvTypeRqst(slp_handle_impl_t * hp,const char * na)134 static SLPError slp_packSrvTypeRqst(slp_handle_impl_t *hp, const char *na) {
135 SLPError err;
136 size_t len, nalen, msgLen, tmplen;
137 int all_nas;
138 slp_msg_t *msg = &(hp->msg);
139
140 /*
141 * Allocate iovec for the message. A SrvTypeRqst is layed out thus:
142 * 0: header
143 * 1: prlist length
144 * 2: prlist (filled in later by networking code)
145 * 3: na
146 * 4: scopes length
147 * 5: scopes (filled in later by networking code)
148 */
149 if (!(msg->iov = calloc(6, sizeof (*(msg->iov))))) {
150 slp_err(LOG_CRIT, 0, "slp_packSrvTypeRqst", "out of memory");
151 return (SLP_MEMORY_ALLOC_FAILED);
152 }
153 msg->iovlen = 6;
154
155 /* calculate msg length */
156 all_nas = strcmp(na, "*") == 0 ? 1 : 0;
157 if (all_nas) {
158 nalen = 0;
159 } else {
160 nalen = strlen(na);
161 }
162 nalen += 2;
163
164 msgLen = 2 + /* prlist length */
165 nalen + /* NA string */
166 2; /* Scope string length */
167
168 if (!(msg->msg = calloc(1, msgLen))) {
169 free(msg->iov);
170 slp_err(LOG_CRIT, 0, "slp_packSrvTypeRqst", "out of memory");
171 return (SLP_MEMORY_ALLOC_FAILED);
172 }
173
174 /* set pointer to PR list and scope list length spaces */
175 msg->prlistlen.iov_base = msg->msg;
176 msg->prlistlen.iov_len = 2;
177 msg->iov[1].iov_base = msg->msg;
178 msg->iov[1].iov_len = 2;
179
180 msg->scopeslen.iov_base = msg->msg + 2;
181 msg->scopeslen.iov_len = 2;
182 msg->iov[4].iov_base = msg->msg + 2;
183 msg->iov[4].iov_len = 2;
184
185 /* set up the scopes and prlist pointers into iov */
186 msg->prlist = &(msg->iov[2]);
187 msg->scopes = &(msg->iov[5]);
188
189 len = 4;
190
191 /* set up NA string in iovec */
192 msg->iov[3].iov_base = msg->msg + len;
193 tmplen = len;
194
195 if (all_nas) {
196 err = slp_add_sht(msg->msg, msgLen, 0xffff, &len);
197 } else {
198 err = slp_add_string(msg->msg, msgLen, na, &len);
199 }
200 msg->iov[3].iov_len = len - tmplen;
201
202 hp->fid = SRVTYPERQST;
203 if (err == SLP_OK) {
204 return (SLP_OK);
205 }
206
207 /* else error */
208 free(msg->iov);
209 free(msg->msg);
210
211 return (err);
212 }
213
214 /*
215 * Using the collator, determines which types in the types list
216 * have already been recieved, and composes a new list of the remaining
217 * (unique) types. If there are no unique types, returns NULL;
218 * types is destructively modified.
219 */
collate_types(char * types,void ** collator,int * numResults,int maxResults)220 static char *collate_types(char *types, void **collator,
221 int *numResults, int maxResults) {
222 char *p, *s, **res, *utypes = NULL;
223
224 /* walk through the types list */
225 p = types;
226 for (s = types; p && *numResults != maxResults; s = p) {
227 p = slp_utf_strchr(s, ',');
228 if (p)
229 *p++ = 0;
230 if (!(s = strdup(s))) {
231 free(types);
232 if (utypes) free(utypes);
233 slp_err(LOG_CRIT, 0, "collate_types", "out of memory");
234 return (NULL);
235 }
236 /* search the tree for this type */
237 res = slp_tsearch((void *) s, collator,
238 (int (*)(const void *, const void *)) slp_strcasecmp);
239 if (*res == s) {
240 /* first time we've encountered this type */
241 slp_add2list(s, &utypes, SLP_FALSE);
242 (*numResults)++;
243 } else {
244 /* else already in tree */
245 free(s);
246 }
247 }
248 free(types);
249 return (utypes);
250 }
251
252 /*
253 * This is used after all types have been collated into the tree.
254 * It walks through the tree, composing a list from all the types in
255 * the tree, and freeing each node of the tree as it goes.
256 * Returns the list, or NULL if the tree is empty.
257 */
258 /* the walk action function: */
259 /*ARGSUSED*/
collect_types(void * node,VISIT order,int level,void * cookie)260 static void collect_types(void *node, VISIT order, int level, void *cookie) {
261 char **types = (char **)cookie;
262
263 if (order == endorder || order == leaf) {
264 char *t = *(char **)node;
265 slp_add2list(t, types, SLP_FALSE);
266 free(t);
267 free(node);
268 }
269 }
270
271 /* the walk driver: */
build_types_list(void * collator)272 static char *build_types_list(void *collator) {
273 char *types = NULL;
274
275 if (!collator)
276 return (NULL);
277 slp_twalk(collator, collect_types, 0, (void *) &types);
278 return (types);
279 }
280