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 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 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 <stdlib.h> 30*7c478bd9Sstevel@tonic-gate #include <syslog.h> 31*7c478bd9Sstevel@tonic-gate #include <slp-internal.h> 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate struct attr_node { 34*7c478bd9Sstevel@tonic-gate char *tag, *val; 35*7c478bd9Sstevel@tonic-gate }; 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate static SLPError slp_packAttrRqst(slp_handle_impl_t *, const char *, 38*7c478bd9Sstevel@tonic-gate const char *); 39*7c478bd9Sstevel@tonic-gate static int compare_tags(const void *, const void *); 40*7c478bd9Sstevel@tonic-gate static void collate_attrs(char *, void **, int *, int); 41*7c478bd9Sstevel@tonic-gate static void parens_attr(char *, void **, int *); 42*7c478bd9Sstevel@tonic-gate static void merge_attrs(struct attr_node *, char *); 43*7c478bd9Sstevel@tonic-gate static char *build_attrs_list(void *collator); 44*7c478bd9Sstevel@tonic-gate static void collect_attrs(void *, VISIT, int, void *); 45*7c478bd9Sstevel@tonic-gate static SLPBoolean unpackDAAdvert_attr(slp_handle_impl_t *, char *, 46*7c478bd9Sstevel@tonic-gate SLPAttrCallback, void *, 47*7c478bd9Sstevel@tonic-gate void **, int *); 48*7c478bd9Sstevel@tonic-gate static SLPBoolean unpackSAAdvert_attr(slp_handle_impl_t *, char *, 49*7c478bd9Sstevel@tonic-gate SLPAttrCallback, void *, 50*7c478bd9Sstevel@tonic-gate void **, int *); 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate SLPError SLPFindAttrs(SLPHandle hSLP, const char *pcURL, const char *pcScope, 53*7c478bd9Sstevel@tonic-gate const char *pcAttrIds, 54*7c478bd9Sstevel@tonic-gate SLPAttrCallback callback, void *pvUser) { 55*7c478bd9Sstevel@tonic-gate SLPError err; 56*7c478bd9Sstevel@tonic-gate int wantSAAdvert = 57*7c478bd9Sstevel@tonic-gate strcasecmp(pcURL, "service:service-agent") == 0; 58*7c478bd9Sstevel@tonic-gate int wantDAAdvert = 59*7c478bd9Sstevel@tonic-gate strcasecmp(pcURL, "service:directory-agent") == 0; 60*7c478bd9Sstevel@tonic-gate int isSpecial = wantSAAdvert || wantDAAdvert; 61*7c478bd9Sstevel@tonic-gate SLPMsgReplyCB *unpack_cb; 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate if (!hSLP || !pcURL || !pcScope || (!*pcScope && !isSpecial) || 65*7c478bd9Sstevel@tonic-gate !pcAttrIds || !callback) { 66*7c478bd9Sstevel@tonic-gate return (SLP_PARAMETER_BAD); 67*7c478bd9Sstevel@tonic-gate } 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate if ((strlen(pcURL) > SLP_MAX_STRINGLEN) || 70*7c478bd9Sstevel@tonic-gate (strlen(pcScope) > SLP_MAX_STRINGLEN) || 71*7c478bd9Sstevel@tonic-gate (strlen(pcAttrIds) > SLP_MAX_STRINGLEN)) { 72*7c478bd9Sstevel@tonic-gate return (SLP_PARAMETER_BAD); 73*7c478bd9Sstevel@tonic-gate } 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate if ((err = slp_start_call(hSLP)) != SLP_OK) 76*7c478bd9Sstevel@tonic-gate return (err); 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate /* Special packer and unpacker for DA and SA solicitations */ 79*7c478bd9Sstevel@tonic-gate if (wantDAAdvert) { 80*7c478bd9Sstevel@tonic-gate unpack_cb = (SLPMsgReplyCB *)unpackDAAdvert_attr; 81*7c478bd9Sstevel@tonic-gate err = slp_packSrvRqst(pcURL, "", hSLP); 82*7c478bd9Sstevel@tonic-gate ((slp_handle_impl_t *)hSLP)->force_multicast = SLP_TRUE; 83*7c478bd9Sstevel@tonic-gate } else if (wantSAAdvert) { 84*7c478bd9Sstevel@tonic-gate unpack_cb = (SLPMsgReplyCB *)unpackSAAdvert_attr; 85*7c478bd9Sstevel@tonic-gate err = slp_packSrvRqst(pcURL, "", hSLP); 86*7c478bd9Sstevel@tonic-gate ((slp_handle_impl_t *)hSLP)->force_multicast = SLP_TRUE; 87*7c478bd9Sstevel@tonic-gate } else { 88*7c478bd9Sstevel@tonic-gate /* normal service request */ 89*7c478bd9Sstevel@tonic-gate unpack_cb = (SLPMsgReplyCB *)slp_UnpackAttrReply; 90*7c478bd9Sstevel@tonic-gate /* format params into msgBuf */ 91*7c478bd9Sstevel@tonic-gate err = slp_packAttrRqst(hSLP, pcURL, pcAttrIds); 92*7c478bd9Sstevel@tonic-gate } 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate if (err == SLP_OK) 95*7c478bd9Sstevel@tonic-gate err = slp_ua_common(hSLP, pcScope, 96*7c478bd9Sstevel@tonic-gate (SLPGenericAppCB *) callback, pvUser, 97*7c478bd9Sstevel@tonic-gate unpack_cb); 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate if (err != SLP_OK) 100*7c478bd9Sstevel@tonic-gate slp_end_call(hSLP); 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate return (err); 103*7c478bd9Sstevel@tonic-gate } 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate SLPBoolean slp_UnpackAttrReply(slp_handle_impl_t *hp, char *reply, 106*7c478bd9Sstevel@tonic-gate SLPAttrCallback cb, void *cookie, 107*7c478bd9Sstevel@tonic-gate void **collator, int *numResults) { 108*7c478bd9Sstevel@tonic-gate char *pcAttrList; 109*7c478bd9Sstevel@tonic-gate SLPError errCode; 110*7c478bd9Sstevel@tonic-gate unsigned short protoErrCode; 111*7c478bd9Sstevel@tonic-gate size_t len, off; 112*7c478bd9Sstevel@tonic-gate int maxResults = slp_get_maxResults(); 113*7c478bd9Sstevel@tonic-gate SLPBoolean cont = SLP_TRUE; 114*7c478bd9Sstevel@tonic-gate int auth_cnt; 115*7c478bd9Sstevel@tonic-gate size_t tbv_len; 116*7c478bd9Sstevel@tonic-gate char *attr_tbv; 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate if (!reply) { 119*7c478bd9Sstevel@tonic-gate /* no more results */ 120*7c478bd9Sstevel@tonic-gate if (!hp->async) { 121*7c478bd9Sstevel@tonic-gate pcAttrList = build_attrs_list(*collator); 122*7c478bd9Sstevel@tonic-gate } 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate if (!hp->async && pcAttrList) { 125*7c478bd9Sstevel@tonic-gate cb(hp, pcAttrList, SLP_OK, cookie); 126*7c478bd9Sstevel@tonic-gate free(pcAttrList); 127*7c478bd9Sstevel@tonic-gate } 128*7c478bd9Sstevel@tonic-gate cb(hp, NULL, SLP_LAST_CALL, cookie); 129*7c478bd9Sstevel@tonic-gate return (SLP_FALSE); 130*7c478bd9Sstevel@tonic-gate } 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate /* parse reply into params */ 133*7c478bd9Sstevel@tonic-gate len = slp_get_length(reply); 134*7c478bd9Sstevel@tonic-gate off = SLP_HDRLEN + slp_get_langlen(reply); 135*7c478bd9Sstevel@tonic-gate /* err code */ 136*7c478bd9Sstevel@tonic-gate if (slp_get_sht(reply, len, &off, &protoErrCode) != SLP_OK) 137*7c478bd9Sstevel@tonic-gate return (SLP_TRUE); 138*7c478bd9Sstevel@tonic-gate /* internal errors should have been filtered out by the net code */ 139*7c478bd9Sstevel@tonic-gate if ((errCode = slp_map_err(protoErrCode)) != SLP_OK) { 140*7c478bd9Sstevel@tonic-gate return (cb(hp, NULL, errCode, cookie)); 141*7c478bd9Sstevel@tonic-gate } 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate /* attr list */ 144*7c478bd9Sstevel@tonic-gate attr_tbv = reply + off; 145*7c478bd9Sstevel@tonic-gate tbv_len = off; 146*7c478bd9Sstevel@tonic-gate if (slp_get_string(reply, len, &off, &pcAttrList) != SLP_OK) 147*7c478bd9Sstevel@tonic-gate return (SLP_TRUE); 148*7c478bd9Sstevel@tonic-gate tbv_len = off - tbv_len; 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate /* number of attr auths */ 151*7c478bd9Sstevel@tonic-gate if (slp_get_byte(reply, len, &off, &auth_cnt) != SLP_OK) { 152*7c478bd9Sstevel@tonic-gate goto cleanup; 153*7c478bd9Sstevel@tonic-gate } 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate /* get and verify auth blocks */ 156*7c478bd9Sstevel@tonic-gate if ((!hp->internal_call && slp_get_security_on()) || auth_cnt > 0) { 157*7c478bd9Sstevel@tonic-gate size_t abLen = 0; 158*7c478bd9Sstevel@tonic-gate struct iovec iov[1]; 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate iov[0].iov_base = attr_tbv; 161*7c478bd9Sstevel@tonic-gate iov[0].iov_len = tbv_len; 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate if (slp_verify(iov, 1, 164*7c478bd9Sstevel@tonic-gate reply + off, 165*7c478bd9Sstevel@tonic-gate len - off, 166*7c478bd9Sstevel@tonic-gate auth_cnt, 167*7c478bd9Sstevel@tonic-gate &abLen) != SLP_OK) { 168*7c478bd9Sstevel@tonic-gate goto cleanup; 169*7c478bd9Sstevel@tonic-gate } 170*7c478bd9Sstevel@tonic-gate } 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate /* collate */ 173*7c478bd9Sstevel@tonic-gate if (!hp->async) { 174*7c478bd9Sstevel@tonic-gate collate_attrs(pcAttrList, collator, numResults, maxResults); 175*7c478bd9Sstevel@tonic-gate } else { 176*7c478bd9Sstevel@tonic-gate /* async: invoke cb */ 177*7c478bd9Sstevel@tonic-gate cont = cb((SLPHandle) hp, pcAttrList, errCode, cookie); 178*7c478bd9Sstevel@tonic-gate (*numResults)++; 179*7c478bd9Sstevel@tonic-gate } 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate cleanup: 182*7c478bd9Sstevel@tonic-gate free(pcAttrList); 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate /* check maxResults */ 185*7c478bd9Sstevel@tonic-gate if (!hp->internal_call && *numResults == maxResults) { 186*7c478bd9Sstevel@tonic-gate return (SLP_FALSE); 187*7c478bd9Sstevel@tonic-gate } 188*7c478bd9Sstevel@tonic-gate 189*7c478bd9Sstevel@tonic-gate return (cont); 190*7c478bd9Sstevel@tonic-gate } 191*7c478bd9Sstevel@tonic-gate 192*7c478bd9Sstevel@tonic-gate /* 193*7c478bd9Sstevel@tonic-gate * unpackDAAdvert_attr follows the same logic stream as UnpackAttrReply, 194*7c478bd9Sstevel@tonic-gate * except that reply contains a DAAdvert. 195*7c478bd9Sstevel@tonic-gate */ 196*7c478bd9Sstevel@tonic-gate static SLPBoolean unpackDAAdvert_attr(slp_handle_impl_t *hp, char *reply, 197*7c478bd9Sstevel@tonic-gate SLPAttrCallback cb, void *cookie, 198*7c478bd9Sstevel@tonic-gate void **collator, int *numResults) { 199*7c478bd9Sstevel@tonic-gate char *surl, *scopes, *attrs, *spis; 200*7c478bd9Sstevel@tonic-gate SLPBoolean cont = SLP_TRUE; 201*7c478bd9Sstevel@tonic-gate SLPError errCode; 202*7c478bd9Sstevel@tonic-gate int maxResults = slp_get_maxResults(); 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate if (!reply) { 205*7c478bd9Sstevel@tonic-gate /* no more results */ 206*7c478bd9Sstevel@tonic-gate if (!hp->async) { 207*7c478bd9Sstevel@tonic-gate attrs = build_attrs_list(*collator); 208*7c478bd9Sstevel@tonic-gate } 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate if (!hp->async && attrs) { 211*7c478bd9Sstevel@tonic-gate cb(hp, attrs, SLP_OK, cookie); 212*7c478bd9Sstevel@tonic-gate free(attrs); 213*7c478bd9Sstevel@tonic-gate } 214*7c478bd9Sstevel@tonic-gate cb(hp, NULL, SLP_LAST_CALL, cookie); 215*7c478bd9Sstevel@tonic-gate return (SLP_FALSE); 216*7c478bd9Sstevel@tonic-gate } 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate if (slp_unpackDAAdvert(reply, &surl, &scopes, &attrs, &spis, &errCode) 219*7c478bd9Sstevel@tonic-gate != SLP_OK) { 220*7c478bd9Sstevel@tonic-gate return (SLP_TRUE); 221*7c478bd9Sstevel@tonic-gate } 222*7c478bd9Sstevel@tonic-gate if (errCode != SLP_OK) { 223*7c478bd9Sstevel@tonic-gate return (cb(hp, NULL, errCode, cookie)); 224*7c478bd9Sstevel@tonic-gate } 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate /* collate */ 227*7c478bd9Sstevel@tonic-gate if (!hp->async) { 228*7c478bd9Sstevel@tonic-gate collate_attrs(attrs, collator, numResults, maxResults); 229*7c478bd9Sstevel@tonic-gate } else { 230*7c478bd9Sstevel@tonic-gate /* async: invoke cb */ 231*7c478bd9Sstevel@tonic-gate cont = cb((SLPHandle) hp, attrs, errCode, cookie); 232*7c478bd9Sstevel@tonic-gate (*numResults)++; 233*7c478bd9Sstevel@tonic-gate } 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate /* cleanup */ 236*7c478bd9Sstevel@tonic-gate free(surl); 237*7c478bd9Sstevel@tonic-gate free(scopes); 238*7c478bd9Sstevel@tonic-gate free(attrs); 239*7c478bd9Sstevel@tonic-gate free(spis); 240*7c478bd9Sstevel@tonic-gate 241*7c478bd9Sstevel@tonic-gate /* check maxResults */ 242*7c478bd9Sstevel@tonic-gate if (!hp->internal_call && *numResults == maxResults) { 243*7c478bd9Sstevel@tonic-gate return (SLP_FALSE); 244*7c478bd9Sstevel@tonic-gate } 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate return (cont); 247*7c478bd9Sstevel@tonic-gate } 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate /* 250*7c478bd9Sstevel@tonic-gate * unpackSAAdvert_attr follows the same logic stream as UnpackAttrReply, 251*7c478bd9Sstevel@tonic-gate * except that reply contains an SAAdvert. 252*7c478bd9Sstevel@tonic-gate */ 253*7c478bd9Sstevel@tonic-gate static SLPBoolean unpackSAAdvert_attr(slp_handle_impl_t *hp, char *reply, 254*7c478bd9Sstevel@tonic-gate SLPAttrCallback cb, void *cookie, 255*7c478bd9Sstevel@tonic-gate void **collator, int *numResults) { 256*7c478bd9Sstevel@tonic-gate char *surl, *scopes, *attrs; 257*7c478bd9Sstevel@tonic-gate SLPBoolean cont = SLP_TRUE; 258*7c478bd9Sstevel@tonic-gate int maxResults = slp_get_maxResults(); 259*7c478bd9Sstevel@tonic-gate 260*7c478bd9Sstevel@tonic-gate if (!reply) { 261*7c478bd9Sstevel@tonic-gate /* no more results */ 262*7c478bd9Sstevel@tonic-gate if (!hp->async) { 263*7c478bd9Sstevel@tonic-gate attrs = build_attrs_list(*collator); 264*7c478bd9Sstevel@tonic-gate } 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate if (!hp->async && attrs) { 267*7c478bd9Sstevel@tonic-gate cb(hp, attrs, SLP_OK, cookie); 268*7c478bd9Sstevel@tonic-gate free(attrs); 269*7c478bd9Sstevel@tonic-gate } 270*7c478bd9Sstevel@tonic-gate cb(hp, NULL, SLP_LAST_CALL, cookie); 271*7c478bd9Sstevel@tonic-gate return (SLP_FALSE); 272*7c478bd9Sstevel@tonic-gate } 273*7c478bd9Sstevel@tonic-gate 274*7c478bd9Sstevel@tonic-gate if (slp_unpackSAAdvert(reply, &surl, &scopes, &attrs) != SLP_OK) { 275*7c478bd9Sstevel@tonic-gate return (SLP_TRUE); 276*7c478bd9Sstevel@tonic-gate } 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate /* collate */ 279*7c478bd9Sstevel@tonic-gate if (!hp->async) { 280*7c478bd9Sstevel@tonic-gate collate_attrs(attrs, collator, numResults, maxResults); 281*7c478bd9Sstevel@tonic-gate } else { 282*7c478bd9Sstevel@tonic-gate /* async: invoke cb */ 283*7c478bd9Sstevel@tonic-gate cont = cb((SLPHandle) hp, attrs, SLP_OK, cookie); 284*7c478bd9Sstevel@tonic-gate (*numResults)++; 285*7c478bd9Sstevel@tonic-gate } 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate /* cleanup */ 288*7c478bd9Sstevel@tonic-gate free(surl); 289*7c478bd9Sstevel@tonic-gate free(scopes); 290*7c478bd9Sstevel@tonic-gate free(attrs); 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate /* check maxResults */ 293*7c478bd9Sstevel@tonic-gate if (!hp->internal_call && *numResults == maxResults) { 294*7c478bd9Sstevel@tonic-gate return (SLP_FALSE); 295*7c478bd9Sstevel@tonic-gate } 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate return (cont); 298*7c478bd9Sstevel@tonic-gate } 299*7c478bd9Sstevel@tonic-gate 300*7c478bd9Sstevel@tonic-gate static SLPError slp_packAttrRqst(slp_handle_impl_t *hp, const char *url, 301*7c478bd9Sstevel@tonic-gate const char *ids) { 302*7c478bd9Sstevel@tonic-gate SLPError err; 303*7c478bd9Sstevel@tonic-gate size_t len, tmplen, msgLen; 304*7c478bd9Sstevel@tonic-gate slp_msg_t *msg = &(hp->msg); 305*7c478bd9Sstevel@tonic-gate char *spi = NULL; 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate if (slp_get_security_on()) { 308*7c478bd9Sstevel@tonic-gate spi = (char *)SLPGetProperty(SLP_CONFIG_SPI); 309*7c478bd9Sstevel@tonic-gate } 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gate if (!spi || !*spi) { 312*7c478bd9Sstevel@tonic-gate spi = ""; 313*7c478bd9Sstevel@tonic-gate } 314*7c478bd9Sstevel@tonic-gate 315*7c478bd9Sstevel@tonic-gate /* 316*7c478bd9Sstevel@tonic-gate * Allocate iovec for the messge. An AttrRqst is layed out thus: 317*7c478bd9Sstevel@tonic-gate * 0: header 318*7c478bd9Sstevel@tonic-gate * 1: prlist length 319*7c478bd9Sstevel@tonic-gate * 2: prlist (filled in later by networking code) 320*7c478bd9Sstevel@tonic-gate * 3: URL string 321*7c478bd9Sstevel@tonic-gate * 4: scopes length 322*7c478bd9Sstevel@tonic-gate * 5: scopes (filled in later by networking code) 323*7c478bd9Sstevel@tonic-gate * 6: tag list string and SPI string 324*7c478bd9Sstevel@tonic-gate */ 325*7c478bd9Sstevel@tonic-gate if (!(msg->iov = calloc(7, sizeof (*(msg->iov))))) { 326*7c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "slp_packAttrRqst", "out of memory"); 327*7c478bd9Sstevel@tonic-gate return (SLP_MEMORY_ALLOC_FAILED); 328*7c478bd9Sstevel@tonic-gate } 329*7c478bd9Sstevel@tonic-gate msg->iovlen = 7; 330*7c478bd9Sstevel@tonic-gate 331*7c478bd9Sstevel@tonic-gate /* calculate msg length */ 332*7c478bd9Sstevel@tonic-gate msgLen = 2 + /* prlist length */ 333*7c478bd9Sstevel@tonic-gate 2 + strlen(url) + /* URL */ 334*7c478bd9Sstevel@tonic-gate 2 + /* scope list length */ 335*7c478bd9Sstevel@tonic-gate 2 + strlen(ids) + /* tag list */ 336*7c478bd9Sstevel@tonic-gate 2 + strlen(spi); /* SPI string */ 337*7c478bd9Sstevel@tonic-gate 338*7c478bd9Sstevel@tonic-gate if (!(msg->msg = calloc(1, msgLen))) { 339*7c478bd9Sstevel@tonic-gate free(msg->iov); 340*7c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "slp_packAttrRqst", "out of memory"); 341*7c478bd9Sstevel@tonic-gate return (SLP_MEMORY_ALLOC_FAILED); 342*7c478bd9Sstevel@tonic-gate } 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate /* set pointer to PR list and scope list length spaces */ 345*7c478bd9Sstevel@tonic-gate msg->prlistlen.iov_base = msg->msg; 346*7c478bd9Sstevel@tonic-gate msg->prlistlen.iov_len = 2; 347*7c478bd9Sstevel@tonic-gate msg->iov[1].iov_base = msg->msg; 348*7c478bd9Sstevel@tonic-gate msg->iov[1].iov_len = 2; 349*7c478bd9Sstevel@tonic-gate 350*7c478bd9Sstevel@tonic-gate msg->scopeslen.iov_base = msg->msg + 2; 351*7c478bd9Sstevel@tonic-gate msg->scopeslen.iov_len = 2; 352*7c478bd9Sstevel@tonic-gate msg->iov[4].iov_base = msg->msg + 2; 353*7c478bd9Sstevel@tonic-gate msg->iov[4].iov_len = 2; 354*7c478bd9Sstevel@tonic-gate 355*7c478bd9Sstevel@tonic-gate /* set up the scopes and prlist pointers into iov */ 356*7c478bd9Sstevel@tonic-gate msg->prlist = &(msg->iov[2]); 357*7c478bd9Sstevel@tonic-gate msg->scopes = &(msg->iov[5]); 358*7c478bd9Sstevel@tonic-gate 359*7c478bd9Sstevel@tonic-gate len = 4; 360*7c478bd9Sstevel@tonic-gate 361*7c478bd9Sstevel@tonic-gate /* Add URL string */ 362*7c478bd9Sstevel@tonic-gate msg->iov[3].iov_base = msg->msg + len; 363*7c478bd9Sstevel@tonic-gate tmplen = len; 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate err = slp_add_string(msg->msg, msgLen, url, &len); 366*7c478bd9Sstevel@tonic-gate msg->iov[3].iov_len = len - tmplen; 367*7c478bd9Sstevel@tonic-gate 368*7c478bd9Sstevel@tonic-gate if (err != SLP_OK) 369*7c478bd9Sstevel@tonic-gate goto error; 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate /* Add tag list */ 372*7c478bd9Sstevel@tonic-gate msg->iov[6].iov_base = msg->msg + len; 373*7c478bd9Sstevel@tonic-gate tmplen = len; 374*7c478bd9Sstevel@tonic-gate 375*7c478bd9Sstevel@tonic-gate err = slp_add_string(msg->msg, msgLen, ids, &len); 376*7c478bd9Sstevel@tonic-gate 377*7c478bd9Sstevel@tonic-gate if (err != SLP_OK) 378*7c478bd9Sstevel@tonic-gate goto error; 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate /* SPI string */ 381*7c478bd9Sstevel@tonic-gate err = slp_add_string(msg->msg, msgLen, spi, &len); 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate msg->iov[6].iov_len = len - tmplen; 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate hp->fid = ATTRRQST; 386*7c478bd9Sstevel@tonic-gate if (err == SLP_OK) { 387*7c478bd9Sstevel@tonic-gate return (SLP_OK); 388*7c478bd9Sstevel@tonic-gate } 389*7c478bd9Sstevel@tonic-gate 390*7c478bd9Sstevel@tonic-gate /* else error */ 391*7c478bd9Sstevel@tonic-gate error: 392*7c478bd9Sstevel@tonic-gate free(msg->iov); 393*7c478bd9Sstevel@tonic-gate free(msg->msg); 394*7c478bd9Sstevel@tonic-gate 395*7c478bd9Sstevel@tonic-gate return (err); 396*7c478bd9Sstevel@tonic-gate } 397*7c478bd9Sstevel@tonic-gate 398*7c478bd9Sstevel@tonic-gate SLPError slp_packAttrRqst_single(const char *url, 399*7c478bd9Sstevel@tonic-gate const char *scopes, 400*7c478bd9Sstevel@tonic-gate const char *ids, 401*7c478bd9Sstevel@tonic-gate char **msg, 402*7c478bd9Sstevel@tonic-gate const char *lang) { 403*7c478bd9Sstevel@tonic-gate SLPError err; 404*7c478bd9Sstevel@tonic-gate size_t len, msgLen; 405*7c478bd9Sstevel@tonic-gate 406*7c478bd9Sstevel@tonic-gate msgLen = 407*7c478bd9Sstevel@tonic-gate SLP_HDRLEN + strlen(lang) + 2 + 408*7c478bd9Sstevel@tonic-gate 2 + strlen(url) + 409*7c478bd9Sstevel@tonic-gate 2 + strlen(scopes) + 410*7c478bd9Sstevel@tonic-gate 2 + strlen(ids) + 411*7c478bd9Sstevel@tonic-gate 2; /* No SPI string for internal calls */ 412*7c478bd9Sstevel@tonic-gate 413*7c478bd9Sstevel@tonic-gate if (!(*msg = calloc(msgLen, 1))) { 414*7c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "slp_packAttrRqst_single", "out of memory"); 415*7c478bd9Sstevel@tonic-gate return (SLP_MEMORY_ALLOC_FAILED); 416*7c478bd9Sstevel@tonic-gate } 417*7c478bd9Sstevel@tonic-gate 418*7c478bd9Sstevel@tonic-gate len = 0; 419*7c478bd9Sstevel@tonic-gate err = slp_add_header(lang, *msg, msgLen, ATTRRQST, msgLen, &len); 420*7c478bd9Sstevel@tonic-gate 421*7c478bd9Sstevel@tonic-gate len += 2; /* empty PR list */ 422*7c478bd9Sstevel@tonic-gate 423*7c478bd9Sstevel@tonic-gate if (err == SLP_OK) { 424*7c478bd9Sstevel@tonic-gate err = slp_add_string(*msg, msgLen, url, &len); 425*7c478bd9Sstevel@tonic-gate } 426*7c478bd9Sstevel@tonic-gate if (err == SLP_OK) { 427*7c478bd9Sstevel@tonic-gate err = slp_add_string(*msg, msgLen, scopes, &len); 428*7c478bd9Sstevel@tonic-gate } 429*7c478bd9Sstevel@tonic-gate if (err == SLP_OK) { 430*7c478bd9Sstevel@tonic-gate err = slp_add_string(*msg, msgLen, ids, &len); 431*7c478bd9Sstevel@tonic-gate } 432*7c478bd9Sstevel@tonic-gate /* empty SPI */ 433*7c478bd9Sstevel@tonic-gate if (err == SLP_OK) { 434*7c478bd9Sstevel@tonic-gate err = slp_add_string(*msg, msgLen, "", &len); 435*7c478bd9Sstevel@tonic-gate } 436*7c478bd9Sstevel@tonic-gate 437*7c478bd9Sstevel@tonic-gate return (err); 438*7c478bd9Sstevel@tonic-gate } 439*7c478bd9Sstevel@tonic-gate 440*7c478bd9Sstevel@tonic-gate static int compare_tags(const void *n1, const void *n2) { 441*7c478bd9Sstevel@tonic-gate return slp_strcasecmp( 442*7c478bd9Sstevel@tonic-gate ((struct attr_node *)n1)->tag, 443*7c478bd9Sstevel@tonic-gate ((struct attr_node *)n2)->tag); 444*7c478bd9Sstevel@tonic-gate } 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate static void merge_attrs(struct attr_node *n, char *vals) { 447*7c478bd9Sstevel@tonic-gate char *p, *v; 448*7c478bd9Sstevel@tonic-gate 449*7c478bd9Sstevel@tonic-gate for (p = v = vals; p; v = p) { 450*7c478bd9Sstevel@tonic-gate p = slp_utf_strchr(v, ','); 451*7c478bd9Sstevel@tonic-gate if (p) 452*7c478bd9Sstevel@tonic-gate *p++ = 0; 453*7c478bd9Sstevel@tonic-gate slp_add2list(v, &(n->val), SLP_TRUE); 454*7c478bd9Sstevel@tonic-gate } 455*7c478bd9Sstevel@tonic-gate } 456*7c478bd9Sstevel@tonic-gate 457*7c478bd9Sstevel@tonic-gate static void parens_attr(char *attr, void **collator, int *numResults) { 458*7c478bd9Sstevel@tonic-gate char *open_paren, *close_paren, *equals; 459*7c478bd9Sstevel@tonic-gate struct attr_node *n, **res; 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate open_paren = attr + 1; 462*7c478bd9Sstevel@tonic-gate close_paren = slp_utf_strchr(open_paren, ')'); 463*7c478bd9Sstevel@tonic-gate if (!close_paren) 464*7c478bd9Sstevel@tonic-gate return; /* skip bad attr list */ 465*7c478bd9Sstevel@tonic-gate 466*7c478bd9Sstevel@tonic-gate *close_paren = 0; 467*7c478bd9Sstevel@tonic-gate if (!(equals = slp_utf_strchr(open_paren, '='))) 468*7c478bd9Sstevel@tonic-gate return; 469*7c478bd9Sstevel@tonic-gate 470*7c478bd9Sstevel@tonic-gate *equals++ = 0; 471*7c478bd9Sstevel@tonic-gate 472*7c478bd9Sstevel@tonic-gate if (!(n = malloc(sizeof (*n)))) { 473*7c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "collate_attrs", "out of memory"); 474*7c478bd9Sstevel@tonic-gate return; 475*7c478bd9Sstevel@tonic-gate } 476*7c478bd9Sstevel@tonic-gate 477*7c478bd9Sstevel@tonic-gate if (!(n->tag = strdup(open_paren))) { 478*7c478bd9Sstevel@tonic-gate free(n); 479*7c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "collate_attrs", "out of memory"); 480*7c478bd9Sstevel@tonic-gate return; 481*7c478bd9Sstevel@tonic-gate } 482*7c478bd9Sstevel@tonic-gate n->val = NULL; 483*7c478bd9Sstevel@tonic-gate 484*7c478bd9Sstevel@tonic-gate res = slp_tsearch(n, collator, compare_tags); 485*7c478bd9Sstevel@tonic-gate 486*7c478bd9Sstevel@tonic-gate if (*res != n) { 487*7c478bd9Sstevel@tonic-gate merge_attrs(*res, equals); 488*7c478bd9Sstevel@tonic-gate free(n->tag); free(n); 489*7c478bd9Sstevel@tonic-gate } else { 490*7c478bd9Sstevel@tonic-gate /* not found; populate new attr node */ 491*7c478bd9Sstevel@tonic-gate (*numResults)++; 492*7c478bd9Sstevel@tonic-gate if (!(n->val = strdup(equals))) { 493*7c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "collate_attrs", "out of memory"); 494*7c478bd9Sstevel@tonic-gate return; 495*7c478bd9Sstevel@tonic-gate } 496*7c478bd9Sstevel@tonic-gate } 497*7c478bd9Sstevel@tonic-gate } 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate static void collate_attrs(char *attrs, void **collator, 500*7c478bd9Sstevel@tonic-gate int *numResults, int maxResults) { 501*7c478bd9Sstevel@tonic-gate char *start, *end; 502*7c478bd9Sstevel@tonic-gate struct attr_node *n, **res; 503*7c478bd9Sstevel@tonic-gate 504*7c478bd9Sstevel@tonic-gate for (start = attrs; 505*7c478bd9Sstevel@tonic-gate start && 506*7c478bd9Sstevel@tonic-gate *start && 507*7c478bd9Sstevel@tonic-gate *numResults != maxResults; 508*7c478bd9Sstevel@tonic-gate start = end) { 509*7c478bd9Sstevel@tonic-gate if (*start == ',') start++; 510*7c478bd9Sstevel@tonic-gate if (*start == '(') { 511*7c478bd9Sstevel@tonic-gate /* form of (tag=val,val) */ 512*7c478bd9Sstevel@tonic-gate if (!(end = slp_utf_strchr(start, ')'))) 513*7c478bd9Sstevel@tonic-gate return; /* skip bad attr */ 514*7c478bd9Sstevel@tonic-gate parens_attr(start, collator, numResults); 515*7c478bd9Sstevel@tonic-gate end++; 516*7c478bd9Sstevel@tonic-gate continue; 517*7c478bd9Sstevel@tonic-gate } 518*7c478bd9Sstevel@tonic-gate end = slp_utf_strchr(start, ','); 519*7c478bd9Sstevel@tonic-gate if (end) 520*7c478bd9Sstevel@tonic-gate *end++ = 0; 521*7c478bd9Sstevel@tonic-gate /* create a new node with the tag only */ 522*7c478bd9Sstevel@tonic-gate if (!(n = malloc(sizeof (*n)))) { 523*7c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "collate_attrs", "out of memory"); 524*7c478bd9Sstevel@tonic-gate return; 525*7c478bd9Sstevel@tonic-gate } 526*7c478bd9Sstevel@tonic-gate 527*7c478bd9Sstevel@tonic-gate if (!(n->tag = strdup(start))) { 528*7c478bd9Sstevel@tonic-gate free(n); 529*7c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "collate_attrs", "out of memory"); 530*7c478bd9Sstevel@tonic-gate return; 531*7c478bd9Sstevel@tonic-gate } 532*7c478bd9Sstevel@tonic-gate n->val = NULL; 533*7c478bd9Sstevel@tonic-gate res = slp_tsearch(n, collator, compare_tags); 534*7c478bd9Sstevel@tonic-gate if (*res != n) { 535*7c478bd9Sstevel@tonic-gate /* already in the tree, so just free resources */ 536*7c478bd9Sstevel@tonic-gate free(n->tag); free(n); 537*7c478bd9Sstevel@tonic-gate } 538*7c478bd9Sstevel@tonic-gate (*numResults)++; 539*7c478bd9Sstevel@tonic-gate } 540*7c478bd9Sstevel@tonic-gate } 541*7c478bd9Sstevel@tonic-gate 542*7c478bd9Sstevel@tonic-gate static char *build_attrs_list(void *collator) { 543*7c478bd9Sstevel@tonic-gate char *answer = NULL; 544*7c478bd9Sstevel@tonic-gate 545*7c478bd9Sstevel@tonic-gate if (!collator) 546*7c478bd9Sstevel@tonic-gate return (NULL); 547*7c478bd9Sstevel@tonic-gate 548*7c478bd9Sstevel@tonic-gate slp_twalk(collator, collect_attrs, 0, &answer); 549*7c478bd9Sstevel@tonic-gate return (answer); 550*7c478bd9Sstevel@tonic-gate } 551*7c478bd9Sstevel@tonic-gate 552*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 553*7c478bd9Sstevel@tonic-gate static void collect_attrs(void *node, VISIT order, int level, void *cookie) { 554*7c478bd9Sstevel@tonic-gate struct attr_node *n; 555*7c478bd9Sstevel@tonic-gate char *attr, *p, **answer = (char **)cookie; 556*7c478bd9Sstevel@tonic-gate 557*7c478bd9Sstevel@tonic-gate if (order == endorder || order == leaf) { 558*7c478bd9Sstevel@tonic-gate n = *(struct attr_node **)node; 559*7c478bd9Sstevel@tonic-gate if (!n->val) { 560*7c478bd9Sstevel@tonic-gate /* no values, so no parens */ 561*7c478bd9Sstevel@tonic-gate if (!(attr = malloc(strlen(n->tag) + 1))) { 562*7c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "collect_attrs", 563*7c478bd9Sstevel@tonic-gate "out of memory"); 564*7c478bd9Sstevel@tonic-gate return; 565*7c478bd9Sstevel@tonic-gate } 566*7c478bd9Sstevel@tonic-gate (void) strcpy(attr, n->tag); 567*7c478bd9Sstevel@tonic-gate } else { 568*7c478bd9Sstevel@tonic-gate if (!(attr = malloc(1 + strlen(n->tag) + 1 + 569*7c478bd9Sstevel@tonic-gate strlen(n->val) + 2))) { 570*7c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "collect_attrs", 571*7c478bd9Sstevel@tonic-gate "out of memory"); 572*7c478bd9Sstevel@tonic-gate return; 573*7c478bd9Sstevel@tonic-gate } 574*7c478bd9Sstevel@tonic-gate /* build attr string */ 575*7c478bd9Sstevel@tonic-gate p = attr; 576*7c478bd9Sstevel@tonic-gate *p++ = '('; 577*7c478bd9Sstevel@tonic-gate (void) strcpy(p, n->tag); p += strlen(n->tag); 578*7c478bd9Sstevel@tonic-gate *p++ = '='; 579*7c478bd9Sstevel@tonic-gate (void) strcpy(p, n->val); p += strlen(n->val); 580*7c478bd9Sstevel@tonic-gate *p++ = ')'; *p = 0; 581*7c478bd9Sstevel@tonic-gate } 582*7c478bd9Sstevel@tonic-gate 583*7c478bd9Sstevel@tonic-gate slp_add2list(attr, answer, SLP_FALSE); 584*7c478bd9Sstevel@tonic-gate free(attr); 585*7c478bd9Sstevel@tonic-gate free(n->tag); if (n->val) free(n->val); free(n); 586*7c478bd9Sstevel@tonic-gate free(node); 587*7c478bd9Sstevel@tonic-gate } 588*7c478bd9Sstevel@tonic-gate } 589