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