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