17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*36e852a1SRaja Andra * Common Development and Distribution License (the "License"). 6*36e852a1SRaja Andra * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*36e852a1SRaja Andra * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #include <strings.h> 287c478bd9Sstevel@tonic-gate #include <string.h> 297c478bd9Sstevel@tonic-gate #include <lber.h> 307c478bd9Sstevel@tonic-gate #include <ldap.h> 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate #include "db_item_c.h" 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate #include "nisdb_mt.h" 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate #include "ldap_util.h" 377c478bd9Sstevel@tonic-gate #include "ldap_structs.h" 387c478bd9Sstevel@tonic-gate #include "ldap_val.h" 397c478bd9Sstevel@tonic-gate #include "ldap_ruleval.h" 407c478bd9Sstevel@tonic-gate #include "ldap_op.h" 417c478bd9Sstevel@tonic-gate #include "ldap_nisdbquery.h" 427c478bd9Sstevel@tonic-gate #include "ldap_attr.h" 437c478bd9Sstevel@tonic-gate #include "ldap_xdr.h" 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate item * 477c478bd9Sstevel@tonic-gate buildItem(int len, void *value) { 487c478bd9Sstevel@tonic-gate char *myself = "buildItem"; 497c478bd9Sstevel@tonic-gate item *i = am(myself, sizeof (*i)); 507c478bd9Sstevel@tonic-gate int mlen = len; 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate if (i == 0) 537c478bd9Sstevel@tonic-gate return (0); 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate /* 567c478bd9Sstevel@tonic-gate * To this function, a NULL value, or a length less than or equal 577c478bd9Sstevel@tonic-gate * zero means an item with no value. Hence, buildItem(0, 0) is 587c478bd9Sstevel@tonic-gate * _not_ the right way to create index_value == 0 to indicate 597c478bd9Sstevel@tonic-gate * deletion. 607c478bd9Sstevel@tonic-gate */ 617c478bd9Sstevel@tonic-gate if (value == 0 || len <= 0) { 627c478bd9Sstevel@tonic-gate i->itemvalue.itemvalue_len = 0; 637c478bd9Sstevel@tonic-gate i->itemvalue.itemvalue_val = 0; 647c478bd9Sstevel@tonic-gate return (i); 657c478bd9Sstevel@tonic-gate } 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate /* 687c478bd9Sstevel@tonic-gate * NIS+ usually stores the terminating NUL for strings, so we add 697c478bd9Sstevel@tonic-gate * it here just in case. This means we usually waste a byte for 707c478bd9Sstevel@tonic-gate * binary column values... 717c478bd9Sstevel@tonic-gate */ 727c478bd9Sstevel@tonic-gate if (len > 0 && ((char *)value)[len-1] != '\0') 737c478bd9Sstevel@tonic-gate mlen++; 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate i->itemvalue.itemvalue_len = len; 767c478bd9Sstevel@tonic-gate i->itemvalue.itemvalue_val = am(myself, mlen); 777c478bd9Sstevel@tonic-gate if (mlen > 0 && i->itemvalue.itemvalue_val == 0) { 787c478bd9Sstevel@tonic-gate free(i); 797c478bd9Sstevel@tonic-gate return (0); 807c478bd9Sstevel@tonic-gate } 817c478bd9Sstevel@tonic-gate memcpy(i->itemvalue.itemvalue_val, value, len); 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate return (i); 847c478bd9Sstevel@tonic-gate } 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate void 877c478bd9Sstevel@tonic-gate freeItem(item *i) { 887c478bd9Sstevel@tonic-gate if (i != 0) { 897c478bd9Sstevel@tonic-gate sfree(i->itemvalue.itemvalue_val); 907c478bd9Sstevel@tonic-gate free(i); 917c478bd9Sstevel@tonic-gate } 927c478bd9Sstevel@tonic-gate } 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate void 957c478bd9Sstevel@tonic-gate freeQcomp(db_qcomp *qc, int doFree) { 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate if (qc == 0) 987c478bd9Sstevel@tonic-gate return; 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate freeItem(qc->index_value); 1017c478bd9Sstevel@tonic-gate if (doFree) 1027c478bd9Sstevel@tonic-gate free(qc); 1037c478bd9Sstevel@tonic-gate } 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate db_query * 1067c478bd9Sstevel@tonic-gate buildQuery(int num_components, db_qcomp *components) { 1077c478bd9Sstevel@tonic-gate char *myself = "buildQuery"; 1087c478bd9Sstevel@tonic-gate db_query *q = am(myself, sizeof (*q)); 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate if (q == 0) 1117c478bd9Sstevel@tonic-gate return (0); 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate q->components.components_len = num_components; 1147c478bd9Sstevel@tonic-gate q->components.components_val = components; 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate return (q); 1177c478bd9Sstevel@tonic-gate } 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate /* 1207c478bd9Sstevel@tonic-gate * Clone a db_query. The 'numComps' parameter can be used to specify 1217c478bd9Sstevel@tonic-gate * the number of db_qcomp's to allocate (in the 'components.components_val' 1227c478bd9Sstevel@tonic-gate * array), if 'components.components_len' hasn't yet reached its expected 1237c478bd9Sstevel@tonic-gate * maximum value. 1247c478bd9Sstevel@tonic-gate */ 1257c478bd9Sstevel@tonic-gate db_query * 1267c478bd9Sstevel@tonic-gate cloneQuery(db_query *old, int numComps) { 1277c478bd9Sstevel@tonic-gate db_query *new; 1287c478bd9Sstevel@tonic-gate int i; 1297c478bd9Sstevel@tonic-gate char *myself = "cloneQuery"; 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate if (old == 0) 1327c478bd9Sstevel@tonic-gate return (0); 1337c478bd9Sstevel@tonic-gate 1347c478bd9Sstevel@tonic-gate new = am(myself, sizeof (*new)); 1357c478bd9Sstevel@tonic-gate if (new == 0) 1367c478bd9Sstevel@tonic-gate return (0); 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate if (old->components.components_len > numComps) 1397c478bd9Sstevel@tonic-gate numComps = old->components.components_len; 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate new->components.components_val = am(myself, 1427c478bd9Sstevel@tonic-gate sizeof (new->components.components_val[0]) * 1437c478bd9Sstevel@tonic-gate numComps); 1447c478bd9Sstevel@tonic-gate if (numComps > 0 && new->components.components_val == 0) { 1457c478bd9Sstevel@tonic-gate free(new); 1467c478bd9Sstevel@tonic-gate return (0); 1477c478bd9Sstevel@tonic-gate } 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate for (i = 0; i < old->components.components_len; i++) { 1507c478bd9Sstevel@tonic-gate item *it; 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate if (old->components.components_val[i].index_value == 0) { 1537c478bd9Sstevel@tonic-gate new->components.components_val[i].index_value = 0; 1547c478bd9Sstevel@tonic-gate new->components.components_val[i].which_index = 1557c478bd9Sstevel@tonic-gate old->components.components_val[i].which_index; 1567c478bd9Sstevel@tonic-gate continue; 1577c478bd9Sstevel@tonic-gate } 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate it = buildItem(old->components.components_val[i].index_value-> 1607c478bd9Sstevel@tonic-gate itemvalue.itemvalue_len, 1617c478bd9Sstevel@tonic-gate old->components.components_val[i].index_value-> 1627c478bd9Sstevel@tonic-gate itemvalue.itemvalue_val); 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate if (it == 0) { 1657c478bd9Sstevel@tonic-gate new->components.components_len = i + 1; 1667c478bd9Sstevel@tonic-gate freeQuery(new); 1677c478bd9Sstevel@tonic-gate return (0); 1687c478bd9Sstevel@tonic-gate } 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate new->components.components_val[i].index_value = it; 1717c478bd9Sstevel@tonic-gate new->components.components_val[i].which_index = 1727c478bd9Sstevel@tonic-gate old->components.components_val[i].which_index; 1737c478bd9Sstevel@tonic-gate } 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate new->components.components_len = old->components.components_len; 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate return (new); 1787c478bd9Sstevel@tonic-gate } 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate void 1817c478bd9Sstevel@tonic-gate freeQuery(db_query *q) { 1827c478bd9Sstevel@tonic-gate int i; 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate if (q == 0) 1857c478bd9Sstevel@tonic-gate return; 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate for (i = 0; i < q->components.components_len; i++) { 1887c478bd9Sstevel@tonic-gate freeItem(q->components.components_val[i].index_value); 1897c478bd9Sstevel@tonic-gate } 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate sfree(q->components.components_val); 1927c478bd9Sstevel@tonic-gate sfree(q); 1937c478bd9Sstevel@tonic-gate } 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate void 1967c478bd9Sstevel@tonic-gate freeQueries(db_query **q, int numQ) { 1977c478bd9Sstevel@tonic-gate int i; 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate if (q == 0) 2007c478bd9Sstevel@tonic-gate return; 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate for (i = 0; i < numQ; i++) 2037c478bd9Sstevel@tonic-gate freeQuery(q[i]); 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate sfree(q); 2067c478bd9Sstevel@tonic-gate } 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate /* 2097c478bd9Sstevel@tonic-gate * Given an array index[0..num-1] of pointers to strings of the form 2107c478bd9Sstevel@tonic-gate * "name=value", create the corresponding db_queries. "name=" indicates 2117c478bd9Sstevel@tonic-gate * deletion, which results in a db_query component where index_value == 0. 2127c478bd9Sstevel@tonic-gate * 2137c478bd9Sstevel@tonic-gate * The __nis_table_mapping_t structure is used to translate column 2147c478bd9Sstevel@tonic-gate * names to indices. 2157c478bd9Sstevel@tonic-gate * 2167c478bd9Sstevel@tonic-gate * If 'rvP' is non-NULL, the searchable columns from the 'index' 2177c478bd9Sstevel@tonic-gate * name/value pairs are used to retrieve copies of the corresponding NIS+ 2187c478bd9Sstevel@tonic-gate * entries, and '*rvP' is initialized with the current entry values 2197c478bd9Sstevel@tonic-gate * and object attributes. Names/values supplied in 'index' override 2207c478bd9Sstevel@tonic-gate * those from existing NIS+ entries. 2217c478bd9Sstevel@tonic-gate */ 2227c478bd9Sstevel@tonic-gate db_query ** 2237c478bd9Sstevel@tonic-gate createQuery(int num, char **index, __nis_table_mapping_t *t, 2247c478bd9Sstevel@tonic-gate __nis_rule_value_t **rvP, int *numVals) { 2257c478bd9Sstevel@tonic-gate db_query **q; 2267c478bd9Sstevel@tonic-gate db_qcomp *qc; 2277c478bd9Sstevel@tonic-gate int i, j, n, a, nv, niv, stat, sinum; 2287c478bd9Sstevel@tonic-gate __nis_rule_value_t *rvq; 2297c478bd9Sstevel@tonic-gate __nis_buffer_t b = {0, 0}; 2307c478bd9Sstevel@tonic-gate char *table = 0; 2317c478bd9Sstevel@tonic-gate char *myself = "createQuery"; 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate rvq = initRuleValue(1, 0); 2347c478bd9Sstevel@tonic-gate if (rvq == 0) 2357c478bd9Sstevel@tonic-gate return (0); 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate if (numVals == 0) 2387c478bd9Sstevel@tonic-gate numVals = &nv; 2397c478bd9Sstevel@tonic-gate *numVals = 0; 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate if (rvP != 0) { 2427c478bd9Sstevel@tonic-gate /* 2437c478bd9Sstevel@tonic-gate * Try to obtain a copy of the table object, in order to 2447c478bd9Sstevel@tonic-gate * determine the searchable columns. A failure isn't 2457c478bd9Sstevel@tonic-gate * necessarily fatal; we just try to compose the entire 2467c478bd9Sstevel@tonic-gate * LDAP data from the col=val pairs. 2477c478bd9Sstevel@tonic-gate */ 2487c478bd9Sstevel@tonic-gate table = fullObjName(F, t->objName); 2497c478bd9Sstevel@tonic-gate if (table == 0) { 2507c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 2517c478bd9Sstevel@tonic-gate "%s: Error converting \"%s\" to FQ object name", 2527c478bd9Sstevel@tonic-gate myself, NIL(t->objName)); 2537c478bd9Sstevel@tonic-gate freeRuleValue(rvq, 1); 2547c478bd9Sstevel@tonic-gate return (0); 2557c478bd9Sstevel@tonic-gate } 2567c478bd9Sstevel@tonic-gate } 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate /* Create a rule-value from the col=val pairs */ 2597c478bd9Sstevel@tonic-gate for (n = 0; n < num; n++) { 2607c478bd9Sstevel@tonic-gate char *name; 2617c478bd9Sstevel@tonic-gate char *value; 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate if ((value = strchr(index[n], '=')) == 0) { 2647c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 2657c478bd9Sstevel@tonic-gate "%s: no '=' in \"%s\"", 2667c478bd9Sstevel@tonic-gate myself, index[n]); 2677c478bd9Sstevel@tonic-gate continue; 2687c478bd9Sstevel@tonic-gate } 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate *value = '\0'; 2717c478bd9Sstevel@tonic-gate value++; 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate for (a = 0; a < t->numColumns; a++) { 2747c478bd9Sstevel@tonic-gate if (strcmp(index[n], t->column[a]) == 0) { 2757c478bd9Sstevel@tonic-gate int i, len = slen(value)+1; 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate /* Add col=val pair to 'rvq' */ 2787c478bd9Sstevel@tonic-gate if (addSCol2RuleValue(index[n], value, rvq)) { 2797c478bd9Sstevel@tonic-gate freeRuleValue(rvq, 1); 2807c478bd9Sstevel@tonic-gate sfree(table); 2817c478bd9Sstevel@tonic-gate return (0); 2827c478bd9Sstevel@tonic-gate } 2837c478bd9Sstevel@tonic-gate 2847c478bd9Sstevel@tonic-gate break; 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate if (a >= t->numColumns) { 2887c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 2897c478bd9Sstevel@tonic-gate "%s: Ignoring unknown column \"%s\"", 2907c478bd9Sstevel@tonic-gate myself, NIL(index[n])); 2917c478bd9Sstevel@tonic-gate } 2927c478bd9Sstevel@tonic-gate } 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate /* 2957c478bd9Sstevel@tonic-gate * Find out if any of the columns specified via the 'index' 2967c478bd9Sstevel@tonic-gate * array are multi-valued. 2977c478bd9Sstevel@tonic-gate */ 2987c478bd9Sstevel@tonic-gate for (n = 0, niv = 1; n < rvq->numColumns; n++) { 2997c478bd9Sstevel@tonic-gate if (rvq->colVal[n].numVals > 1) 3007c478bd9Sstevel@tonic-gate niv *= rvq->colVal[n].numVals; 3017c478bd9Sstevel@tonic-gate } 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate *numVals = 1; 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate sfree(b.buf); 3067c478bd9Sstevel@tonic-gate sfree(table); 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate if (rvq->numColumns <= 0) { 3097c478bd9Sstevel@tonic-gate freeRuleValue(rvq, *numVals); 3107c478bd9Sstevel@tonic-gate *numVals = 0; 3117c478bd9Sstevel@tonic-gate return (0); 3127c478bd9Sstevel@tonic-gate } 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate /* 3157c478bd9Sstevel@tonic-gate * If any column name was repeated in the col=val pairs (but with 3167c478bd9Sstevel@tonic-gate * different values), 'rvq' will have one or more multi-valued 3177c478bd9Sstevel@tonic-gate * column values. We now convert those into an array of rule-values 3187c478bd9Sstevel@tonic-gate * where every column is single-valued. 3197c478bd9Sstevel@tonic-gate * 3207c478bd9Sstevel@tonic-gate * Since we want all combinations of column values, the number 3217c478bd9Sstevel@tonic-gate * of array elements is the product of all column value counts. 3227c478bd9Sstevel@tonic-gate * 3237c478bd9Sstevel@tonic-gate * There are four possible combinations of 'index' and NIS+ data: 3247c478bd9Sstevel@tonic-gate * 3257c478bd9Sstevel@tonic-gate * (1) Only single-valued 'index' columns, and at most one NIS+ 3267c478bd9Sstevel@tonic-gate * entry, so 'rvq' is complete, and '*numVals' == 1. 3277c478bd9Sstevel@tonic-gate * 3287c478bd9Sstevel@tonic-gate * (2) Single-valued 'index' columns, but multiple NIS+ entries. 3297c478bd9Sstevel@tonic-gate * '*numVals' reflects the number of NIS+ entries, and no 3307c478bd9Sstevel@tonic-gate * expansion of 'index' column values to array elements is 3317c478bd9Sstevel@tonic-gate * needed. 3327c478bd9Sstevel@tonic-gate * 3337c478bd9Sstevel@tonic-gate * (3) At least one multi-valued 'index', and multiple NIS+ 3347c478bd9Sstevel@tonic-gate * entries. We already rejected the NIS+ data for this case 3357c478bd9Sstevel@tonic-gate * above, so it is in fact equivalent to case (4). 3367c478bd9Sstevel@tonic-gate * 3377c478bd9Sstevel@tonic-gate * (4) At least one multi-valued 'index', but at most one NIS+ 3387c478bd9Sstevel@tonic-gate * entry. This is the case where we must expand the multi-valued 3397c478bd9Sstevel@tonic-gate * columns to multiple array elements. 3407c478bd9Sstevel@tonic-gate */ 3417c478bd9Sstevel@tonic-gate if (niv > 1 && *numVals == 1) { 3427c478bd9Sstevel@tonic-gate __nis_rule_value_t *rv; 3437c478bd9Sstevel@tonic-gate int repeat; 3447c478bd9Sstevel@tonic-gate 3457c478bd9Sstevel@tonic-gate /* 3467c478bd9Sstevel@tonic-gate * By using initRuleValue() to create 'rv', and make each 3477c478bd9Sstevel@tonic-gate * element a clone of 'rvq', we save a lot of code. The 3487c478bd9Sstevel@tonic-gate * down side is that 'rv' only really needs one element 3497c478bd9Sstevel@tonic-gate * for each rv[].colVal[].val array, but we know that at 3507c478bd9Sstevel@tonic-gate * least one rvq->colVal[].val array has more than one 3517c478bd9Sstevel@tonic-gate * element. Hence, making 'rv' a clone of 'rvq' will waste 3527c478bd9Sstevel@tonic-gate * memory. 3537c478bd9Sstevel@tonic-gate * 3547c478bd9Sstevel@tonic-gate * However, we believe this waste is acceptable, because 3557c478bd9Sstevel@tonic-gate * we expect that 'niv' will be small. Also, we are executing 3567c478bd9Sstevel@tonic-gate * in the context of a utility command, not in a daemon. 3577c478bd9Sstevel@tonic-gate */ 3587c478bd9Sstevel@tonic-gate rv = initRuleValue(niv, rvq); 3597c478bd9Sstevel@tonic-gate if (rv == 0) { 3607c478bd9Sstevel@tonic-gate freeRuleValue(rvq, 1); 3617c478bd9Sstevel@tonic-gate *numVals = 0; 3627c478bd9Sstevel@tonic-gate return (0); 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate /* 3667c478bd9Sstevel@tonic-gate * For each column value in 'rvq', copy to the appropriate 3677c478bd9Sstevel@tonic-gate * place in 'rv', so that the end result is that all 3687c478bd9Sstevel@tonic-gate * combinations of values are enumerated, and each 3697c478bd9Sstevel@tonic-gate * 'rv[n].colVal[i]' is single-valued. 3707c478bd9Sstevel@tonic-gate * 3717c478bd9Sstevel@tonic-gate * We do this by traversing the rv[] array 'rvq->numColumns' 3727c478bd9Sstevel@tonic-gate * times, where each traversal 'i' works on the values 3737c478bd9Sstevel@tonic-gate * for rvq->colVal[i]. A repeat factor 'repeat' starts out 3747c478bd9Sstevel@tonic-gate * at '1', and is multiplied by 'rvq->colVal[i].numVals' 3757c478bd9Sstevel@tonic-gate * at the end of each traversal. Every value 3767c478bd9Sstevel@tonic-gate * rvq->colVal[i].val[j] is repeated 'repeat' times. 3777c478bd9Sstevel@tonic-gate * 3787c478bd9Sstevel@tonic-gate * This algorithm works by regarding the rv[] array as 3797c478bd9Sstevel@tonic-gate * an I-dimensional array (I = rvq->numColumns), where 3807c478bd9Sstevel@tonic-gate * each dimension 'i' corresponds to the values for 3817c478bd9Sstevel@tonic-gate * rvq->colVal[i]. The I-dimensional array is stored 3827c478bd9Sstevel@tonic-gate * in column-major order. 3837c478bd9Sstevel@tonic-gate * 3847c478bd9Sstevel@tonic-gate * Since the 'rv' elements start out as copies of 'rvq', 3857c478bd9Sstevel@tonic-gate * we achieve the "copy" of the 'rvq' column values by 3867c478bd9Sstevel@tonic-gate * deleting those we don't want from the 'rv' elements. 3877c478bd9Sstevel@tonic-gate */ 3887c478bd9Sstevel@tonic-gate for (i = 0, repeat = 1; i < rvq->numColumns; i++) { 3897c478bd9Sstevel@tonic-gate int r, k; 3907c478bd9Sstevel@tonic-gate for (n = 0, j = 0, r = 0; n < niv; n++) { 3917c478bd9Sstevel@tonic-gate /* 3927c478bd9Sstevel@tonic-gate * Free all but element 'j' of the 3937c478bd9Sstevel@tonic-gate * rv[n].colVal[i].val array. 3947c478bd9Sstevel@tonic-gate */ 3957c478bd9Sstevel@tonic-gate for (k = 0; k < rv[n].colVal[i].numVals; k++) { 3967c478bd9Sstevel@tonic-gate /* Leave element 'j' in place */ 3977c478bd9Sstevel@tonic-gate if (k == j) 3987c478bd9Sstevel@tonic-gate continue; 3997c478bd9Sstevel@tonic-gate sfree(rv[n].colVal[i].val[k]. 4007c478bd9Sstevel@tonic-gate value); 4017c478bd9Sstevel@tonic-gate } 4027c478bd9Sstevel@tonic-gate rv[n].colVal[i].numVals = 1; 4037c478bd9Sstevel@tonic-gate /* Move element 'j' to zero */ 4047c478bd9Sstevel@tonic-gate if (j != 0) 4057c478bd9Sstevel@tonic-gate rv[n].colVal[i].val[0] = 4067c478bd9Sstevel@tonic-gate rv[n].colVal[i].val[j]; 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate /* 4097c478bd9Sstevel@tonic-gate * Increment the repeat index 'r'. If >= 4107c478bd9Sstevel@tonic-gate * 'repeat', reset 'r' and increment the 4117c478bd9Sstevel@tonic-gate * value index 'j'. If 'j' >= 4127c478bd9Sstevel@tonic-gate * rvq->colVal[i].numVals, start over on 4137c478bd9Sstevel@tonic-gate * the column values for column 'i' (i.e., 4147c478bd9Sstevel@tonic-gate * reset 'j' to zero). 4157c478bd9Sstevel@tonic-gate */ 4167c478bd9Sstevel@tonic-gate r += 1; 4177c478bd9Sstevel@tonic-gate if (r >= repeat) { 4187c478bd9Sstevel@tonic-gate r = 0; 4197c478bd9Sstevel@tonic-gate j += 1; 4207c478bd9Sstevel@tonic-gate if (j >= rvq->colVal[i].numVals) 4217c478bd9Sstevel@tonic-gate j = 0; 4227c478bd9Sstevel@tonic-gate } 4237c478bd9Sstevel@tonic-gate } 4247c478bd9Sstevel@tonic-gate repeat *= rvq->colVal[i].numVals; 4257c478bd9Sstevel@tonic-gate } 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate *numVals = niv; 4287c478bd9Sstevel@tonic-gate freeRuleValue(rvq, 1); 4297c478bd9Sstevel@tonic-gate rvq = rv; 4307c478bd9Sstevel@tonic-gate rv = 0; 4317c478bd9Sstevel@tonic-gate } 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate q = am(myself, *numVals * sizeof (q[0])); 4347c478bd9Sstevel@tonic-gate if (q == 0) { 4357c478bd9Sstevel@tonic-gate freeRuleValue(rvq, *numVals); 4367c478bd9Sstevel@tonic-gate return (0); 4377c478bd9Sstevel@tonic-gate } 4387c478bd9Sstevel@tonic-gate 4397c478bd9Sstevel@tonic-gate /* 4407c478bd9Sstevel@tonic-gate * Create queries from the rvq[] array. 4417c478bd9Sstevel@tonic-gate */ 4427c478bd9Sstevel@tonic-gate for (a = 0; a < *numVals; a++) { 4437c478bd9Sstevel@tonic-gate int nn, err = 0; 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate qc = am(myself, rvq[a].numColumns * sizeof (*qc)); 4467c478bd9Sstevel@tonic-gate if (qc != 0) { 4477c478bd9Sstevel@tonic-gate for (nn = 0, i = 0; i < rvq[a].numColumns; i++) { 4487c478bd9Sstevel@tonic-gate for (j = 0; j < t->numColumns; j++) { 4497c478bd9Sstevel@tonic-gate if (strcmp(rvq[a].colName[i], 4507c478bd9Sstevel@tonic-gate t->column[j]) == 0) { 4517c478bd9Sstevel@tonic-gate break; 4527c478bd9Sstevel@tonic-gate } 4537c478bd9Sstevel@tonic-gate } 4547c478bd9Sstevel@tonic-gate if (j >= t->numColumns) 4557c478bd9Sstevel@tonic-gate continue; 4567c478bd9Sstevel@tonic-gate qc[nn].which_index = j; 4577c478bd9Sstevel@tonic-gate if (rvq[a].colVal[i].numVals > 0) { 4587c478bd9Sstevel@tonic-gate qc[nn].index_value = buildItem( 4597c478bd9Sstevel@tonic-gate rvq[a].colVal[i].val[0].length, 4607c478bd9Sstevel@tonic-gate rvq[a].colVal[i].val[0].value); 4617c478bd9Sstevel@tonic-gate if (qc[nn].index_value == 0) 4627c478bd9Sstevel@tonic-gate err++; 4637c478bd9Sstevel@tonic-gate } else { 4647c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 4657c478bd9Sstevel@tonic-gate "%s: No values for [%d]%s", 4667c478bd9Sstevel@tonic-gate myself, a, rvq[a].colName[i]); 4677c478bd9Sstevel@tonic-gate err++; 4687c478bd9Sstevel@tonic-gate } 4697c478bd9Sstevel@tonic-gate nn++; 4707c478bd9Sstevel@tonic-gate } 4717c478bd9Sstevel@tonic-gate if (err == 0) 4727c478bd9Sstevel@tonic-gate q[a] = buildQuery(nn, qc); 4737c478bd9Sstevel@tonic-gate } 4747c478bd9Sstevel@tonic-gate if (err > 0 || q[a] == 0) { 4757c478bd9Sstevel@tonic-gate freeQueries(q, a); 4767c478bd9Sstevel@tonic-gate for (a = 0; a < nn; a++) 4777c478bd9Sstevel@tonic-gate freeQcomp(&qc[a], F); 4787c478bd9Sstevel@tonic-gate sfree(qc); 4797c478bd9Sstevel@tonic-gate freeRuleValue(rvq, *numVals); 4807c478bd9Sstevel@tonic-gate return (0); 4817c478bd9Sstevel@tonic-gate } 4827c478bd9Sstevel@tonic-gate } 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate if (rvP != 0) { 4857c478bd9Sstevel@tonic-gate *rvP = rvq; 4867c478bd9Sstevel@tonic-gate } else { 4877c478bd9Sstevel@tonic-gate freeRuleValue(rvq, 1); 4887c478bd9Sstevel@tonic-gate *numVals = 0; 4897c478bd9Sstevel@tonic-gate } 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate return (q); 4927c478bd9Sstevel@tonic-gate } 4937c478bd9Sstevel@tonic-gate 4947c478bd9Sstevel@tonic-gate void 4957c478bd9Sstevel@tonic-gate printQuery(db_query *q, __nis_table_mapping_t *t) { 4967c478bd9Sstevel@tonic-gate int i, mc = -1; 4977c478bd9Sstevel@tonic-gate char *myself = "printQuery"; 4987c478bd9Sstevel@tonic-gate char *val[NIS_MAXCOLUMNS]; 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate if (q == 0) 5017c478bd9Sstevel@tonic-gate return; 5027c478bd9Sstevel@tonic-gate 5037c478bd9Sstevel@tonic-gate (void) memset(val, 0, sizeof (val)); 5047c478bd9Sstevel@tonic-gate 5057c478bd9Sstevel@tonic-gate /* 5067c478bd9Sstevel@tonic-gate * Collect the values, which may be out of order in 'q'. 5077c478bd9Sstevel@tonic-gate * Remember the largest index. 5087c478bd9Sstevel@tonic-gate */ 5097c478bd9Sstevel@tonic-gate for (i = 0; i < q->components.components_len; i++) { 5107c478bd9Sstevel@tonic-gate int ix = q->components.components_val[i].which_index; 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate if (ix >= NIS_MAXCOLUMNS || 5137c478bd9Sstevel@tonic-gate (t != 0 && ix >= t->numColumns)) 5147c478bd9Sstevel@tonic-gate continue; 5157c478bd9Sstevel@tonic-gate if (ix > mc) 5167c478bd9Sstevel@tonic-gate mc = ix; 5177c478bd9Sstevel@tonic-gate val[ix] = q->components.components_val[i].index_value-> 5187c478bd9Sstevel@tonic-gate itemvalue.itemvalue_val; 5197c478bd9Sstevel@tonic-gate } 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate /* Print the values we collected */ 5227c478bd9Sstevel@tonic-gate for (i = 0; i <= mc; i++) { 5237c478bd9Sstevel@tonic-gate p2buf(myself, "%s%s", (i != 0 ? " " : ""), 5247c478bd9Sstevel@tonic-gate (val[i] != 0 ? val[i] : "")); 5257c478bd9Sstevel@tonic-gate } 5267c478bd9Sstevel@tonic-gate /* If we printed anything, add a newline */ 5277c478bd9Sstevel@tonic-gate if (mc >= 0) 5287c478bd9Sstevel@tonic-gate p2buf(myself, "\n"); 5297c478bd9Sstevel@tonic-gate } 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate /* 5327c478bd9Sstevel@tonic-gate * Verify that the db_query's 'q' and 'fq' match, in the sense that if 5337c478bd9Sstevel@tonic-gate * they both have a value for a certain index, the values are the same. 5347c478bd9Sstevel@tonic-gate */ 5357c478bd9Sstevel@tonic-gate int 5367c478bd9Sstevel@tonic-gate verifyQueryMatch(db_query *q, db_query *fq) { 5377c478bd9Sstevel@tonic-gate int i, j, match; 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate if (fq == 0) 5407c478bd9Sstevel@tonic-gate return (1); 5417c478bd9Sstevel@tonic-gate 5427c478bd9Sstevel@tonic-gate if (q == 0) 5437c478bd9Sstevel@tonic-gate return ((fq == 0) ? 1 : 0); 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate for (i = 0, match = 1; match && i < q->components.components_len; 5467c478bd9Sstevel@tonic-gate i++) { 5477c478bd9Sstevel@tonic-gate for (j = 0; j < fq->components.components_len; j++) { 5487c478bd9Sstevel@tonic-gate int len, flen; 5497c478bd9Sstevel@tonic-gate 5507c478bd9Sstevel@tonic-gate /* Same index ? */ 5517c478bd9Sstevel@tonic-gate if (q->components.components_val[i].which_index != 5527c478bd9Sstevel@tonic-gate fq->components.components_val[j]. 5537c478bd9Sstevel@tonic-gate which_index) 5547c478bd9Sstevel@tonic-gate continue; 5557c478bd9Sstevel@tonic-gate /* 5567c478bd9Sstevel@tonic-gate * If one 'index_value' is NULL, the other one must 5577c478bd9Sstevel@tonic-gate * be NULL as well. 5587c478bd9Sstevel@tonic-gate */ 5597c478bd9Sstevel@tonic-gate if (q->components.components_val[i].index_value == 0) { 5607c478bd9Sstevel@tonic-gate if (fq->components.components_val[j]. 5617c478bd9Sstevel@tonic-gate index_value == 0) 5627c478bd9Sstevel@tonic-gate continue; 5637c478bd9Sstevel@tonic-gate else { 5647c478bd9Sstevel@tonic-gate match = 0; 5657c478bd9Sstevel@tonic-gate break; 5667c478bd9Sstevel@tonic-gate } 5677c478bd9Sstevel@tonic-gate } 5687c478bd9Sstevel@tonic-gate if (fq->components.components_val[j].index_value == 5697c478bd9Sstevel@tonic-gate 0) { 5707c478bd9Sstevel@tonic-gate match = 0; 5717c478bd9Sstevel@tonic-gate break; 5727c478bd9Sstevel@tonic-gate } 5737c478bd9Sstevel@tonic-gate /* Same value lengths ? */ 5747c478bd9Sstevel@tonic-gate len = q->components.components_val[i].index_value-> 5757c478bd9Sstevel@tonic-gate itemvalue.itemvalue_len; 5767c478bd9Sstevel@tonic-gate flen = fq->components.components_val[j].index_value-> 5777c478bd9Sstevel@tonic-gate itemvalue.itemvalue_len; 5787c478bd9Sstevel@tonic-gate if (len != flen) { 5797c478bd9Sstevel@tonic-gate /* 5807c478bd9Sstevel@tonic-gate * There's a twist here: the input query 5817c478bd9Sstevel@tonic-gate * may well _not_ count a concluding NUL 5827c478bd9Sstevel@tonic-gate * in a string value, while the output 5837c478bd9Sstevel@tonic-gate * usually will. So, if the difference in 5847c478bd9Sstevel@tonic-gate * length is one, and the "extra" byte is 5857c478bd9Sstevel@tonic-gate * a zero-valued one, we accept equality. 5867c478bd9Sstevel@tonic-gate * 'q' is assumed to be the output, and 5877c478bd9Sstevel@tonic-gate * 'fq' the input. 5887c478bd9Sstevel@tonic-gate */ 5897c478bd9Sstevel@tonic-gate if (!(len > 0 && len == (flen+1) && 5907c478bd9Sstevel@tonic-gate q->components.components_val[i]. 5917c478bd9Sstevel@tonic-gate index_value-> 5927c478bd9Sstevel@tonic-gate itemvalue.itemvalue_val[len-1] == 0)) { 5937c478bd9Sstevel@tonic-gate match = 0; 5947c478bd9Sstevel@tonic-gate break; 5957c478bd9Sstevel@tonic-gate } 5967c478bd9Sstevel@tonic-gate } 5977c478bd9Sstevel@tonic-gate /* Same value ? */ 5987c478bd9Sstevel@tonic-gate if (memcmp(q->components.components_val[i].index_value-> 5997c478bd9Sstevel@tonic-gate itemvalue.itemvalue_val, 6007c478bd9Sstevel@tonic-gate fq->components.components_val[j].index_value-> 6017c478bd9Sstevel@tonic-gate itemvalue.itemvalue_val, 6027c478bd9Sstevel@tonic-gate flen) != 0) { 6037c478bd9Sstevel@tonic-gate match = 0; 6047c478bd9Sstevel@tonic-gate break; 6057c478bd9Sstevel@tonic-gate } 6067c478bd9Sstevel@tonic-gate } 6077c478bd9Sstevel@tonic-gate } 6087c478bd9Sstevel@tonic-gate 6097c478bd9Sstevel@tonic-gate return (match); 6107c478bd9Sstevel@tonic-gate } 6117c478bd9Sstevel@tonic-gate 6127c478bd9Sstevel@tonic-gate /* 6137c478bd9Sstevel@tonic-gate * Remove those queries in 'q' that don't match t->index. 6147c478bd9Sstevel@tonic-gate * Returns a pointer to the filtered array, which could be 6157c478bd9Sstevel@tonic-gate * a compacted version of the original, or a new copy; in 6167c478bd9Sstevel@tonic-gate * the latter case, the original will have been freed. 6177c478bd9Sstevel@tonic-gate * 6187c478bd9Sstevel@tonic-gate * Filtered/removed db_query's are freed. 6197c478bd9Sstevel@tonic-gate */ 6207c478bd9Sstevel@tonic-gate db_query ** 6217c478bd9Sstevel@tonic-gate filterQuery(__nis_table_mapping_t *t, db_query **q, db_query *qin, 6227c478bd9Sstevel@tonic-gate __nis_obj_attr_t ***objAttr, int *numQueries) { 6237c478bd9Sstevel@tonic-gate db_query **new; 6247c478bd9Sstevel@tonic-gate __nis_obj_attr_t **attr; 6257c478bd9Sstevel@tonic-gate int i, nq, nn; 6267c478bd9Sstevel@tonic-gate char *myself = "filterQuery"; 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate if ((t == 0 && qin == 0) || q == 0 || 6297c478bd9Sstevel@tonic-gate numQueries == 0 || *numQueries <= 0) 6307c478bd9Sstevel@tonic-gate return (q); 6317c478bd9Sstevel@tonic-gate 6327c478bd9Sstevel@tonic-gate nq = *numQueries; 6337c478bd9Sstevel@tonic-gate new = am(myself, nq * sizeof (new[0])); 6347c478bd9Sstevel@tonic-gate if (objAttr != 0) 6357c478bd9Sstevel@tonic-gate attr = am(myself, nq * sizeof (attr[0])); 6367c478bd9Sstevel@tonic-gate else 6377c478bd9Sstevel@tonic-gate attr = 0; 6387c478bd9Sstevel@tonic-gate if (new == 0 || (objAttr != 0 && attr == 0)) { 6397c478bd9Sstevel@tonic-gate sfree(new); 6407c478bd9Sstevel@tonic-gate freeQueries(q, nq); 6417c478bd9Sstevel@tonic-gate sfree(attr); 6427c478bd9Sstevel@tonic-gate if (objAttr != 0) { 6437c478bd9Sstevel@tonic-gate freeObjAttr(*objAttr, nq); 6447c478bd9Sstevel@tonic-gate *objAttr = 0; 6457c478bd9Sstevel@tonic-gate } 6467c478bd9Sstevel@tonic-gate *numQueries = -1; 6477c478bd9Sstevel@tonic-gate return (0); 6487c478bd9Sstevel@tonic-gate } 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate for (i = 0, nn = 0; i < nq; i++) { 6517c478bd9Sstevel@tonic-gate int retain = 1; 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate if (t != 0) 6547c478bd9Sstevel@tonic-gate retain = verifyIndexMatch(t, q[i], 0, 0, 0); 6557c478bd9Sstevel@tonic-gate 6567c478bd9Sstevel@tonic-gate if (retain && qin != 0) 6577c478bd9Sstevel@tonic-gate retain = verifyQueryMatch(q[i], qin); 6587c478bd9Sstevel@tonic-gate 6597c478bd9Sstevel@tonic-gate if (retain) { 6607c478bd9Sstevel@tonic-gate new[nn] = q[i]; 6617c478bd9Sstevel@tonic-gate if (objAttr != 0) 6627c478bd9Sstevel@tonic-gate attr[nn] = (*objAttr)[i]; 6637c478bd9Sstevel@tonic-gate nn++; 6647c478bd9Sstevel@tonic-gate } else { 6657c478bd9Sstevel@tonic-gate freeQuery(q[i]); 6667c478bd9Sstevel@tonic-gate q[i] = 0; 6677c478bd9Sstevel@tonic-gate if (objAttr != 0) { 6687c478bd9Sstevel@tonic-gate freeSingleObjAttr((*objAttr)[i]); 6697c478bd9Sstevel@tonic-gate (*objAttr)[i] = 0; 6707c478bd9Sstevel@tonic-gate } 6717c478bd9Sstevel@tonic-gate } 6727c478bd9Sstevel@tonic-gate } 6737c478bd9Sstevel@tonic-gate 6747c478bd9Sstevel@tonic-gate /* All q[i]'s are either in 'new', or have been deleted */ 6757c478bd9Sstevel@tonic-gate free(q); 6767c478bd9Sstevel@tonic-gate if (objAttr != 0) { 6777c478bd9Sstevel@tonic-gate sfree(*objAttr); 6787c478bd9Sstevel@tonic-gate *objAttr = attr; 6797c478bd9Sstevel@tonic-gate } 6807c478bd9Sstevel@tonic-gate 6817c478bd9Sstevel@tonic-gate *numQueries = nn; 6827c478bd9Sstevel@tonic-gate 6837c478bd9Sstevel@tonic-gate return (new); 6847c478bd9Sstevel@tonic-gate } 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate db_query ** 6877c478bd9Sstevel@tonic-gate createNisPlusEntry(__nis_table_mapping_t *t, __nis_rule_value_t *rv, 6887c478bd9Sstevel@tonic-gate db_query *qin, __nis_obj_attr_t ***objAttr, 6897c478bd9Sstevel@tonic-gate int *numQueries) { 6907c478bd9Sstevel@tonic-gate db_query **query = 0; 6917c478bd9Sstevel@tonic-gate int r, i, j, ir; 6927c478bd9Sstevel@tonic-gate __nis_value_t *rval, *lval; 6937c478bd9Sstevel@tonic-gate __nis_mapping_item_t *litem; 6947c478bd9Sstevel@tonic-gate int numItems; 6957c478bd9Sstevel@tonic-gate int nq, iqc; 6967c478bd9Sstevel@tonic-gate __nis_obj_attr_t **attr = 0; 6977c478bd9Sstevel@tonic-gate char **dn = 0; 6987c478bd9Sstevel@tonic-gate int numDN = 0; 6997c478bd9Sstevel@tonic-gate char *myself = "createNisPlusEntry"; 7007c478bd9Sstevel@tonic-gate 7017c478bd9Sstevel@tonic-gate if (t == 0 || t->objectDN == 0 || rv == 0) 7027c478bd9Sstevel@tonic-gate return (0); 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate /* Establish default, per-thread, search base */ 7057c478bd9Sstevel@tonic-gate __nisdb_get_tsd()->searchBase = t->objectDN->read.base; 7067c478bd9Sstevel@tonic-gate 7077c478bd9Sstevel@tonic-gate for (r = 0, nq = 0; r < t->numRulesFromLDAP; r++) { 7087c478bd9Sstevel@tonic-gate int nrq, ntq, err; 7097c478bd9Sstevel@tonic-gate db_query **newq; 7107c478bd9Sstevel@tonic-gate __nis_obj_attr_t **newattr; 7117c478bd9Sstevel@tonic-gate 7127c478bd9Sstevel@tonic-gate rval = buildRvalue(&t->ruleFromLDAP[r]->rhs, 7137c478bd9Sstevel@tonic-gate mit_ldap, rv, NULL); 7147c478bd9Sstevel@tonic-gate if (rval == 0) 7157c478bd9Sstevel@tonic-gate continue; 7167c478bd9Sstevel@tonic-gate 7177c478bd9Sstevel@tonic-gate litem = buildLvalue(&t->ruleFromLDAP[r]->lhs, &rval, 7187c478bd9Sstevel@tonic-gate &numItems); 7197c478bd9Sstevel@tonic-gate if (litem == 0) { 7207c478bd9Sstevel@tonic-gate freeValue(rval, 1); 7217c478bd9Sstevel@tonic-gate /* XXX Should this be a fatal error ? */ 7227c478bd9Sstevel@tonic-gate continue; 7237c478bd9Sstevel@tonic-gate } 7247c478bd9Sstevel@tonic-gate 7257c478bd9Sstevel@tonic-gate lval = 0; 7267c478bd9Sstevel@tonic-gate for (i = 0; i < numItems; i++) { 7277c478bd9Sstevel@tonic-gate __nis_value_t *tmpval, *old; 7287c478bd9Sstevel@tonic-gate 7297c478bd9Sstevel@tonic-gate tmpval = getMappingItem(&litem[i], 7307c478bd9Sstevel@tonic-gate mit_nisplus, 0, 0, NULL); 7317c478bd9Sstevel@tonic-gate 7327c478bd9Sstevel@tonic-gate /* 7337c478bd9Sstevel@tonic-gate * If the LHS specifies an out-of-context LDAP or 7347c478bd9Sstevel@tonic-gate * NIS+ item, we do the update right here. We 7357c478bd9Sstevel@tonic-gate * don't add any values to 'lval'; instead, we 7367c478bd9Sstevel@tonic-gate * skip to the next item. (However, we still 7377c478bd9Sstevel@tonic-gate * get a string representation of the LHS in case 7387c478bd9Sstevel@tonic-gate * we need to report an error.) 7397c478bd9Sstevel@tonic-gate */ 740*36e852a1SRaja Andra if (litem[i].type == mit_ldap) { 7417c478bd9Sstevel@tonic-gate int stat; 7427c478bd9Sstevel@tonic-gate 7437c478bd9Sstevel@tonic-gate if (dn == 0) 7447c478bd9Sstevel@tonic-gate dn = findDNs(myself, rv, 1, 7457c478bd9Sstevel@tonic-gate t->objectDN->write.base, 7467c478bd9Sstevel@tonic-gate &numDN); 7477c478bd9Sstevel@tonic-gate 7487c478bd9Sstevel@tonic-gate stat = storeLDAP(&litem[i], i, numItems, rval, 7497c478bd9Sstevel@tonic-gate t->objectDN, dn, numDN); 7507c478bd9Sstevel@tonic-gate if (stat != LDAP_SUCCESS) { 7517c478bd9Sstevel@tonic-gate char *iname = "<unknown>"; 7527c478bd9Sstevel@tonic-gate 7537c478bd9Sstevel@tonic-gate if (tmpval != 0 && 7547c478bd9Sstevel@tonic-gate tmpval->numVals == 1) 7557c478bd9Sstevel@tonic-gate iname = tmpval->val[0].value; 7567c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 7577c478bd9Sstevel@tonic-gate "%s: LDAP store \"%s\": %s", 7587c478bd9Sstevel@tonic-gate myself, iname, 7597c478bd9Sstevel@tonic-gate ldap_err2string(stat)); 7607c478bd9Sstevel@tonic-gate } 7617c478bd9Sstevel@tonic-gate 7627c478bd9Sstevel@tonic-gate freeValue(tmpval, 1); 7637c478bd9Sstevel@tonic-gate continue; 7647c478bd9Sstevel@tonic-gate } 7657c478bd9Sstevel@tonic-gate 7667c478bd9Sstevel@tonic-gate old = lval; 7677c478bd9Sstevel@tonic-gate lval = concatenateValues(old, tmpval); 7687c478bd9Sstevel@tonic-gate freeValue(tmpval, 1); 7697c478bd9Sstevel@tonic-gate freeValue(old, 1); 7707c478bd9Sstevel@tonic-gate } 7717c478bd9Sstevel@tonic-gate 7727c478bd9Sstevel@tonic-gate freeMappingItem(litem, numItems); 7737c478bd9Sstevel@tonic-gate if (lval == 0 || lval->numVals <= 0 || rval->numVals <= 0) { 7747c478bd9Sstevel@tonic-gate freeValue(lval, 1); 7757c478bd9Sstevel@tonic-gate freeValue(rval, 1); 7767c478bd9Sstevel@tonic-gate continue; 7777c478bd9Sstevel@tonic-gate } 7787c478bd9Sstevel@tonic-gate 7797c478bd9Sstevel@tonic-gate /* 7807c478bd9Sstevel@tonic-gate * We now have a number of possible cases. The notation 7817c478bd9Sstevel@tonic-gate * used in the table is: 7827c478bd9Sstevel@tonic-gate * 7837c478bd9Sstevel@tonic-gate * single A single value (numVals == 1) 7847c478bd9Sstevel@tonic-gate * single/rep A single value with repeat == 1 7857c478bd9Sstevel@tonic-gate * multi[N] N values 7867c478bd9Sstevel@tonic-gate * multi[N]/rep M values with repeat == 1 7877c478bd9Sstevel@tonic-gate * (M) M resulting db_query's 7887c478bd9Sstevel@tonic-gate * 7897c478bd9Sstevel@tonic-gate * lval \ rval single single/rep multi[N] multi[N]/rep 7907c478bd9Sstevel@tonic-gate * single (1) (1) (1) (1) 7917c478bd9Sstevel@tonic-gate * single/rep (1) (1) (N) (N) 7927c478bd9Sstevel@tonic-gate * multi[M] (1) (1) (1) 1+(N-1)/M 7937c478bd9Sstevel@tonic-gate * multi[M]/rep (1) (1) (1) 1+(N-1)/M 7947c478bd9Sstevel@tonic-gate * 7957c478bd9Sstevel@tonic-gate * Of course, we already have 'nq' db_query's from previous 7967c478bd9Sstevel@tonic-gate * rules, so the resulting number of queries is max(1,nq) 7977c478bd9Sstevel@tonic-gate * times the numbers in the table above. 7987c478bd9Sstevel@tonic-gate */ 7997c478bd9Sstevel@tonic-gate 8007c478bd9Sstevel@tonic-gate /* The number of queries resulting from the current rule */ 8017c478bd9Sstevel@tonic-gate if (rval->numVals > 1) { 8027c478bd9Sstevel@tonic-gate if (lval->numVals == 1 && lval->repeat) 8037c478bd9Sstevel@tonic-gate nrq = rval->numVals; 8047c478bd9Sstevel@tonic-gate else if (lval->numVals > 1 && rval->repeat) 8057c478bd9Sstevel@tonic-gate nrq = 1 + ((rval->numVals-1)/lval->numVals); 8067c478bd9Sstevel@tonic-gate else 8077c478bd9Sstevel@tonic-gate nrq = 1; 8087c478bd9Sstevel@tonic-gate } else { 8097c478bd9Sstevel@tonic-gate nrq = 1; 8107c478bd9Sstevel@tonic-gate } 8117c478bd9Sstevel@tonic-gate 8127c478bd9Sstevel@tonic-gate /* Total number of queries after adding the current rule */ 8137c478bd9Sstevel@tonic-gate if (nq <= 0) 8147c478bd9Sstevel@tonic-gate ntq = nrq; 8157c478bd9Sstevel@tonic-gate else 8167c478bd9Sstevel@tonic-gate ntq = nq * nrq; 8177c478bd9Sstevel@tonic-gate 8187c478bd9Sstevel@tonic-gate if (ntq > nq) { 8197c478bd9Sstevel@tonic-gate newq = realloc(query, ntq * sizeof (query[0])); 8207c478bd9Sstevel@tonic-gate newattr = realloc(attr, ntq * sizeof (attr[0])); 8217c478bd9Sstevel@tonic-gate if (newq == 0 || newattr == 0) { 8227c478bd9Sstevel@tonic-gate logmsg(MSG_NOMEM, LOG_ERR, 8237c478bd9Sstevel@tonic-gate "%s: realloc(%d) => NULL", 8247c478bd9Sstevel@tonic-gate myself, ntq * sizeof (query[0])); 8257c478bd9Sstevel@tonic-gate freeValue(lval, 1); 8267c478bd9Sstevel@tonic-gate freeValue(rval, 1); 8277c478bd9Sstevel@tonic-gate freeQueries(query, nq); 8287c478bd9Sstevel@tonic-gate freeObjAttr(attr, nq); 8297c478bd9Sstevel@tonic-gate sfree(newq); 8307c478bd9Sstevel@tonic-gate freeDNs(dn, numDN); 8317c478bd9Sstevel@tonic-gate return (0); 8327c478bd9Sstevel@tonic-gate } 8337c478bd9Sstevel@tonic-gate query = newq; 8347c478bd9Sstevel@tonic-gate attr = newattr; 8357c478bd9Sstevel@tonic-gate } 8367c478bd9Sstevel@tonic-gate 8377c478bd9Sstevel@tonic-gate /* 8387c478bd9Sstevel@tonic-gate * Copy/clone the existing queries to the new array, 8397c478bd9Sstevel@tonic-gate * remembering that realloc() has done the first 'nq' 8407c478bd9Sstevel@tonic-gate * ones. 8417c478bd9Sstevel@tonic-gate * 8427c478bd9Sstevel@tonic-gate * If there's an error (probably memory allocation), we 8437c478bd9Sstevel@tonic-gate * still go through the rest of the array, so that it's 8447c478bd9Sstevel@tonic-gate * simple to free the elements when we clean up. 8457c478bd9Sstevel@tonic-gate */ 8467c478bd9Sstevel@tonic-gate for (i = 1, err = 0; i < nrq; i++) { 8477c478bd9Sstevel@tonic-gate for (j = 0; j < nq; j++) { 8487c478bd9Sstevel@tonic-gate query[(nq*i)+j] = cloneQuery(query[j], 8497c478bd9Sstevel@tonic-gate t->numColumns); 8507c478bd9Sstevel@tonic-gate if (query[(nq*i)+j] == 0 && 8517c478bd9Sstevel@tonic-gate query[j] != 0) 8527c478bd9Sstevel@tonic-gate err++; 8537c478bd9Sstevel@tonic-gate attr[(nq*i)+j] = cloneObjAttr(attr[j]); 8547c478bd9Sstevel@tonic-gate if (attr[(nq*i)+j] == 0 && 8557c478bd9Sstevel@tonic-gate attr[j] != 0) 8567c478bd9Sstevel@tonic-gate err++; 8577c478bd9Sstevel@tonic-gate } 8587c478bd9Sstevel@tonic-gate } 8597c478bd9Sstevel@tonic-gate 8607c478bd9Sstevel@tonic-gate if (err > 0) { 8617c478bd9Sstevel@tonic-gate freeValue(lval, 1); 8627c478bd9Sstevel@tonic-gate freeValue(rval, 1); 8637c478bd9Sstevel@tonic-gate freeQueries(query, ntq); 8647c478bd9Sstevel@tonic-gate freeObjAttr(attr, ntq); 8657c478bd9Sstevel@tonic-gate freeDNs(dn, numDN); 8667c478bd9Sstevel@tonic-gate return (0); 8677c478bd9Sstevel@tonic-gate } 8687c478bd9Sstevel@tonic-gate 8697c478bd9Sstevel@tonic-gate /* 8707c478bd9Sstevel@tonic-gate * Special case if nq == 0 (i.e., the first time we 8717c478bd9Sstevel@tonic-gate * allocated db_query's). If so, we now allocate empty 8727c478bd9Sstevel@tonic-gate * db_qcomp arrays, which simplifies subsequent 8737c478bd9Sstevel@tonic-gate * copying of values. 8747c478bd9Sstevel@tonic-gate */ 8757c478bd9Sstevel@tonic-gate if (nq <= 0) { 8767c478bd9Sstevel@tonic-gate (void) memset(query, 0, ntq * sizeof (query[0])); 8777c478bd9Sstevel@tonic-gate (void) memset(attr, 0, ntq * sizeof (attr[0])); 8787c478bd9Sstevel@tonic-gate for (i = 0, err = 0; i < ntq; i++) { 8797c478bd9Sstevel@tonic-gate query[i] = am(myself, sizeof (*query[i])); 8807c478bd9Sstevel@tonic-gate if (query[i] == 0) { 8817c478bd9Sstevel@tonic-gate err++; 8827c478bd9Sstevel@tonic-gate break; 8837c478bd9Sstevel@tonic-gate } 8847c478bd9Sstevel@tonic-gate query[i]->components.components_val = 8857c478bd9Sstevel@tonic-gate am(myself, t->numColumns * 8867c478bd9Sstevel@tonic-gate sizeof (query[i]->components.components_val[0])); 8877c478bd9Sstevel@tonic-gate if (query[i]->components.components_val == 0) { 8887c478bd9Sstevel@tonic-gate err++; 8897c478bd9Sstevel@tonic-gate break; 8907c478bd9Sstevel@tonic-gate } 8917c478bd9Sstevel@tonic-gate query[i]->components.components_len = 0; 8927c478bd9Sstevel@tonic-gate } 8937c478bd9Sstevel@tonic-gate if (err > 0) { 8947c478bd9Sstevel@tonic-gate freeValue(lval, 1); 8957c478bd9Sstevel@tonic-gate freeValue(rval, 1); 8967c478bd9Sstevel@tonic-gate freeQueries(query, ntq); 8977c478bd9Sstevel@tonic-gate freeObjAttr(attr, ntq); 8987c478bd9Sstevel@tonic-gate freeDNs(dn, numDN); 8997c478bd9Sstevel@tonic-gate return (0); 9007c478bd9Sstevel@tonic-gate } 9017c478bd9Sstevel@tonic-gate } 9027c478bd9Sstevel@tonic-gate 9037c478bd9Sstevel@tonic-gate /* Now we're ready to add the new values */ 9047c478bd9Sstevel@tonic-gate for (i = 0, ir = 0; i < lval->numVals; i++) { 9057c478bd9Sstevel@tonic-gate char *oaName = 0; 9067c478bd9Sstevel@tonic-gate int index; 9077c478bd9Sstevel@tonic-gate 9087c478bd9Sstevel@tonic-gate /* Find column index */ 9097c478bd9Sstevel@tonic-gate for (index = 0; index < t->numColumns; 9107c478bd9Sstevel@tonic-gate index++) { 9117c478bd9Sstevel@tonic-gate if (strncmp(t->column[index], 9127c478bd9Sstevel@tonic-gate lval->val[i].value, 9137c478bd9Sstevel@tonic-gate lval->val[i].length) == 0) 9147c478bd9Sstevel@tonic-gate break; 9157c478bd9Sstevel@tonic-gate } 9167c478bd9Sstevel@tonic-gate if (index >= t->numColumns) { 9177c478bd9Sstevel@tonic-gate /* 9187c478bd9Sstevel@tonic-gate * Could be one of the special object 9197c478bd9Sstevel@tonic-gate * attributes. 9207c478bd9Sstevel@tonic-gate */ 9217c478bd9Sstevel@tonic-gate oaName = isObjAttr(&lval->val[i]); 9227c478bd9Sstevel@tonic-gate if (oaName == 0) 9237c478bd9Sstevel@tonic-gate continue; 9247c478bd9Sstevel@tonic-gate } 9257c478bd9Sstevel@tonic-gate 9267c478bd9Sstevel@tonic-gate for (j = i*nrq; j < (i+1)*nrq; j++) { 9277c478bd9Sstevel@tonic-gate int k; 9287c478bd9Sstevel@tonic-gate 9297c478bd9Sstevel@tonic-gate /* If we're out of values, repeat last one */ 9307c478bd9Sstevel@tonic-gate ir = (j < rval->numVals) ? 9317c478bd9Sstevel@tonic-gate j : rval->numVals - 1; 9327c478bd9Sstevel@tonic-gate 9337c478bd9Sstevel@tonic-gate /* 9347c478bd9Sstevel@tonic-gate * Step through the query array, adding 9357c478bd9Sstevel@tonic-gate * the new value every 'nrq' queries, and 9367c478bd9Sstevel@tonic-gate * starting at 'query[j % nrq]'. 9377c478bd9Sstevel@tonic-gate */ 9387c478bd9Sstevel@tonic-gate for (k = j % nrq, err = 0; k < ntq; k += nrq) { 9397c478bd9Sstevel@tonic-gate int ic, c; 9407c478bd9Sstevel@tonic-gate 9417c478bd9Sstevel@tonic-gate if (oaName != 0) { 9427c478bd9Sstevel@tonic-gate int fail = setObjAttrField( 9437c478bd9Sstevel@tonic-gate oaName, 9447c478bd9Sstevel@tonic-gate &rval->val[ir], 9457c478bd9Sstevel@tonic-gate &attr[k]); 9467c478bd9Sstevel@tonic-gate if (fail) { 9477c478bd9Sstevel@tonic-gate err++; 9487c478bd9Sstevel@tonic-gate break; 9497c478bd9Sstevel@tonic-gate } 9507c478bd9Sstevel@tonic-gate continue; 9517c478bd9Sstevel@tonic-gate } 9527c478bd9Sstevel@tonic-gate 9537c478bd9Sstevel@tonic-gate ic = query[k]->components. 9547c478bd9Sstevel@tonic-gate components_len; 9557c478bd9Sstevel@tonic-gate /* 9567c478bd9Sstevel@tonic-gate * If we've already filled this 9577c478bd9Sstevel@tonic-gate * query, the new value is a dup 9587c478bd9Sstevel@tonic-gate * which we'll ignore. 9597c478bd9Sstevel@tonic-gate */ 9607c478bd9Sstevel@tonic-gate if (ic >= t->numColumns) 9617c478bd9Sstevel@tonic-gate continue; 9627c478bd9Sstevel@tonic-gate 9637c478bd9Sstevel@tonic-gate /* 9647c478bd9Sstevel@tonic-gate * Do we already have a value for 9657c478bd9Sstevel@tonic-gate * this 'index' ? 9667c478bd9Sstevel@tonic-gate */ 9677c478bd9Sstevel@tonic-gate for (c = 0; c < ic; c++) { 9687c478bd9Sstevel@tonic-gate if (query[k]->components. 9697c478bd9Sstevel@tonic-gate components_val[c]. 9707c478bd9Sstevel@tonic-gate which_index == index) 9717c478bd9Sstevel@tonic-gate break; 9727c478bd9Sstevel@tonic-gate } 9737c478bd9Sstevel@tonic-gate 9747c478bd9Sstevel@tonic-gate /* If no previous value, add it */ 9757c478bd9Sstevel@tonic-gate if (c >= ic) { 9767c478bd9Sstevel@tonic-gate int l; 9777c478bd9Sstevel@tonic-gate char *v; 9787c478bd9Sstevel@tonic-gate 9797c478bd9Sstevel@tonic-gate query[k]->components. 9807c478bd9Sstevel@tonic-gate components_val[ic]. 9817c478bd9Sstevel@tonic-gate which_index = index; 9827c478bd9Sstevel@tonic-gate l = rval->val[ir].length; 9837c478bd9Sstevel@tonic-gate v = rval->val[ir].value; 9847c478bd9Sstevel@tonic-gate if (rval->type == vt_string && 9857c478bd9Sstevel@tonic-gate l > 0 && 9867c478bd9Sstevel@tonic-gate v[l-1] != '\0' && 9877c478bd9Sstevel@tonic-gate v[l] == '\0') 9887c478bd9Sstevel@tonic-gate l++; 9897c478bd9Sstevel@tonic-gate query[k]->components. 9907c478bd9Sstevel@tonic-gate components_val[ic]. 9917c478bd9Sstevel@tonic-gate index_value = 9927c478bd9Sstevel@tonic-gate buildItem(l, v); 9937c478bd9Sstevel@tonic-gate if (query[k]-> 9947c478bd9Sstevel@tonic-gate components. 9957c478bd9Sstevel@tonic-gate components_val[ic]. 9967c478bd9Sstevel@tonic-gate index_value == 0) { 9977c478bd9Sstevel@tonic-gate err++; 9987c478bd9Sstevel@tonic-gate break; 9997c478bd9Sstevel@tonic-gate } 10007c478bd9Sstevel@tonic-gate query[k]->components. 10017c478bd9Sstevel@tonic-gate components_len++; 10027c478bd9Sstevel@tonic-gate } 10037c478bd9Sstevel@tonic-gate } 10047c478bd9Sstevel@tonic-gate if (err > 0) { 10057c478bd9Sstevel@tonic-gate freeValue(lval, 1); 10067c478bd9Sstevel@tonic-gate freeValue(rval, 1); 10077c478bd9Sstevel@tonic-gate freeQueries(query, ntq); 10087c478bd9Sstevel@tonic-gate freeObjAttr(attr, ntq); 10097c478bd9Sstevel@tonic-gate freeDNs(dn, numDN); 10107c478bd9Sstevel@tonic-gate return (0); 10117c478bd9Sstevel@tonic-gate } 10127c478bd9Sstevel@tonic-gate } 10137c478bd9Sstevel@tonic-gate } 10147c478bd9Sstevel@tonic-gate freeValue(lval, 1); 10157c478bd9Sstevel@tonic-gate freeValue(rval, 1); 10167c478bd9Sstevel@tonic-gate 10177c478bd9Sstevel@tonic-gate nq = ntq; 10187c478bd9Sstevel@tonic-gate } 10197c478bd9Sstevel@tonic-gate 10207c478bd9Sstevel@tonic-gate freeDNs(dn, numDN); 10217c478bd9Sstevel@tonic-gate 10227c478bd9Sstevel@tonic-gate if (nq <= 0) { 10237c478bd9Sstevel@tonic-gate sfree(query); 10247c478bd9Sstevel@tonic-gate query = 0; 10257c478bd9Sstevel@tonic-gate } 10267c478bd9Sstevel@tonic-gate 10277c478bd9Sstevel@tonic-gate /* Should we filter on index or input query ? */ 10287c478bd9Sstevel@tonic-gate if (query != 0) { 10297c478bd9Sstevel@tonic-gate if (t->index.numIndexes > 0) 10307c478bd9Sstevel@tonic-gate query = filterQuery(t, query, qin, &attr, &nq); 10317c478bd9Sstevel@tonic-gate else if (qin != 0) 10327c478bd9Sstevel@tonic-gate query = filterQuery(0, query, qin, &attr, &nq); 10337c478bd9Sstevel@tonic-gate } 10347c478bd9Sstevel@tonic-gate 10357c478bd9Sstevel@tonic-gate if (query != 0 && numQueries != 0) 10367c478bd9Sstevel@tonic-gate *numQueries = nq; 10377c478bd9Sstevel@tonic-gate 10387c478bd9Sstevel@tonic-gate if (objAttr != 0) 10397c478bd9Sstevel@tonic-gate *objAttr = attr; 10407c478bd9Sstevel@tonic-gate else 10417c478bd9Sstevel@tonic-gate freeObjAttr(attr, nq); 10427c478bd9Sstevel@tonic-gate 10437c478bd9Sstevel@tonic-gate return (query); 10447c478bd9Sstevel@tonic-gate } 10457c478bd9Sstevel@tonic-gate /* 10467c478bd9Sstevel@tonic-gate * Given a table mapping and a rule-value, convert to an array of 10477c478bd9Sstevel@tonic-gate * (db_query *), using the fromLDAP ruleset. 10487c478bd9Sstevel@tonic-gate * 10497c478bd9Sstevel@tonic-gate * On entry, '*numQueries' holds the number of elements in the 'rv' 10507c478bd9Sstevel@tonic-gate * array. On exit, it holds the number of (db_query *)'s in the return 10517c478bd9Sstevel@tonic-gate * value array. 10527c478bd9Sstevel@tonic-gate */ 10537c478bd9Sstevel@tonic-gate db_query ** 10547c478bd9Sstevel@tonic-gate ruleValue2Query(__nis_table_mapping_t *t, __nis_rule_value_t *rv, 10557c478bd9Sstevel@tonic-gate db_query *qin, __nis_obj_attr_t ***objAttr, int *numQueries) { 10567c478bd9Sstevel@tonic-gate db_query **q = 0, ***qp = 0; 10577c478bd9Sstevel@tonic-gate int i, nqp, nq, *nnp = 0, nv; 10587c478bd9Sstevel@tonic-gate __nis_obj_attr_t **attr = 0, ***atp = 0; 10597c478bd9Sstevel@tonic-gate char *myself = "ruleValue2Query"; 10607c478bd9Sstevel@tonic-gate 10617c478bd9Sstevel@tonic-gate 10627c478bd9Sstevel@tonic-gate if (t == 0 || rv == 0 || numQueries == 0) 10637c478bd9Sstevel@tonic-gate return (0); 10647c478bd9Sstevel@tonic-gate 10657c478bd9Sstevel@tonic-gate nv = *numQueries; 10667c478bd9Sstevel@tonic-gate if (nv <= 0) 10677c478bd9Sstevel@tonic-gate return (0); 10687c478bd9Sstevel@tonic-gate 10697c478bd9Sstevel@tonic-gate /* 10707c478bd9Sstevel@tonic-gate * 'qp' is an array of (db_query **), and we get one element for 10717c478bd9Sstevel@tonic-gate * each call to createNisPlusEntry(); i.e., one for each rule-value. 10727c478bd9Sstevel@tonic-gate * 10737c478bd9Sstevel@tonic-gate * 'nnp[i]' is the count of (db_query *) in each 'qp[i]'. 10747c478bd9Sstevel@tonic-gate */ 10757c478bd9Sstevel@tonic-gate qp = am(myself, nv * sizeof (*qp)); 10767c478bd9Sstevel@tonic-gate nnp = am(myself, nv * sizeof (*nnp)); 10777c478bd9Sstevel@tonic-gate atp = am(myself, nv * sizeof (*atp)); 10787c478bd9Sstevel@tonic-gate if (qp == 0 || nnp == 0 || atp == 0) { 10797c478bd9Sstevel@tonic-gate sfree(qp); 10807c478bd9Sstevel@tonic-gate sfree(nnp); 10817c478bd9Sstevel@tonic-gate sfree(atp); 10827c478bd9Sstevel@tonic-gate return (0); 10837c478bd9Sstevel@tonic-gate } 10847c478bd9Sstevel@tonic-gate 10857c478bd9Sstevel@tonic-gate for (i = 0, nq = 0, nqp = 0; i < nv; i++) { 10867c478bd9Sstevel@tonic-gate qp[nqp] = createNisPlusEntry(t, &rv[i], qin, &atp[nqp], 10877c478bd9Sstevel@tonic-gate &nnp[nqp]); 10887c478bd9Sstevel@tonic-gate /* If we fail, abort (XXX??? or continue ???) */ 10897c478bd9Sstevel@tonic-gate if (qp[nqp] == 0) 10907c478bd9Sstevel@tonic-gate goto cleanup; 10917c478bd9Sstevel@tonic-gate nq += nnp[nqp]; 10927c478bd9Sstevel@tonic-gate nqp++; 10937c478bd9Sstevel@tonic-gate } 10947c478bd9Sstevel@tonic-gate 10957c478bd9Sstevel@tonic-gate /* If we didn't get any (db_query **)'s, return failure */ 10967c478bd9Sstevel@tonic-gate if (nqp == 0 || nq <= 0) 10977c478bd9Sstevel@tonic-gate goto cleanup; 10987c478bd9Sstevel@tonic-gate 10997c478bd9Sstevel@tonic-gate q = am(myself, nq * sizeof (q[0])); 11007c478bd9Sstevel@tonic-gate attr = am(myself, nq * sizeof (attr[0])); 11017c478bd9Sstevel@tonic-gate if (q == 0 || attr == 0) { 11027c478bd9Sstevel@tonic-gate nq = 0; 11037c478bd9Sstevel@tonic-gate goto cleanup; 11047c478bd9Sstevel@tonic-gate } 11057c478bd9Sstevel@tonic-gate 11067c478bd9Sstevel@tonic-gate /* Convert 'qp' to an array of (db_query *)'s */ 11077c478bd9Sstevel@tonic-gate for (i = 0, nq = 0; i < nqp; i++) { 11087c478bd9Sstevel@tonic-gate (void) memcpy(&q[nq], qp[i], nnp[i] * sizeof (qp[i][0])); 11097c478bd9Sstevel@tonic-gate (void) memcpy(&attr[nq], atp[i], nnp[i] * sizeof (atp[i][0])); 11107c478bd9Sstevel@tonic-gate nq += nnp[i]; 11117c478bd9Sstevel@tonic-gate free(qp[i]); 11127c478bd9Sstevel@tonic-gate free(atp[i]); 11137c478bd9Sstevel@tonic-gate } 11147c478bd9Sstevel@tonic-gate 11157c478bd9Sstevel@tonic-gate *numQueries = nq; 11167c478bd9Sstevel@tonic-gate if (objAttr != 0) 11177c478bd9Sstevel@tonic-gate *objAttr = attr; 11187c478bd9Sstevel@tonic-gate else 11197c478bd9Sstevel@tonic-gate freeObjAttr(attr, nq); 11207c478bd9Sstevel@tonic-gate 11217c478bd9Sstevel@tonic-gate /* Make sure 'cleanup' doesn't free the db_query pointers */ 11227c478bd9Sstevel@tonic-gate nqp = 0; 11237c478bd9Sstevel@tonic-gate 11247c478bd9Sstevel@tonic-gate cleanup: 11257c478bd9Sstevel@tonic-gate for (i = 0; i < nqp; i++) { 11267c478bd9Sstevel@tonic-gate freeQueries(qp[i], nnp[i]); 11277c478bd9Sstevel@tonic-gate sfree(atp[i]); 11287c478bd9Sstevel@tonic-gate } 11297c478bd9Sstevel@tonic-gate sfree(qp); 11307c478bd9Sstevel@tonic-gate sfree(nnp); 11317c478bd9Sstevel@tonic-gate sfree(atp); 11327c478bd9Sstevel@tonic-gate 11337c478bd9Sstevel@tonic-gate return (q); 11347c478bd9Sstevel@tonic-gate } 11357c478bd9Sstevel@tonic-gate 11367c478bd9Sstevel@tonic-gate db_query * 11377c478bd9Sstevel@tonic-gate pseudoEntryObj2Query(entry_obj *e, nis_object *tobj, __nis_rule_value_t *rv) { 11387c478bd9Sstevel@tonic-gate db_query *qbuf; 11397c478bd9Sstevel@tonic-gate db_qcomp *qcbuf; 11407c478bd9Sstevel@tonic-gate int nc, i; 11417c478bd9Sstevel@tonic-gate __nis_rule_value_t *rvt = 0; 11427c478bd9Sstevel@tonic-gate char *myself = "pseudoEntryObj2Query"; 11437c478bd9Sstevel@tonic-gate 11447c478bd9Sstevel@tonic-gate nc = e->en_cols.en_cols_len - 1; 11457c478bd9Sstevel@tonic-gate 11467c478bd9Sstevel@tonic-gate if (e == 0 || nc < 0 || nc > NIS_MAXCOLUMNS) 11477c478bd9Sstevel@tonic-gate return (0); 11487c478bd9Sstevel@tonic-gate 11497c478bd9Sstevel@tonic-gate /* 11507c478bd9Sstevel@tonic-gate * If 'rvP' is non-NULL, build a rule value from the pseudo- 11517c478bd9Sstevel@tonic-gate * nis_object in e->en_cols.en_cols_val[0]. 11527c478bd9Sstevel@tonic-gate */ 11537c478bd9Sstevel@tonic-gate if (rv != 0) { 11547c478bd9Sstevel@tonic-gate nis_object *o; 11557c478bd9Sstevel@tonic-gate 11567c478bd9Sstevel@tonic-gate o = unmakePseudoEntryObj(e, tobj); 11577c478bd9Sstevel@tonic-gate if (o == 0) 11587c478bd9Sstevel@tonic-gate return (0); 11597c478bd9Sstevel@tonic-gate rvt = addObjAttr2RuleValue(o, 0); 11607c478bd9Sstevel@tonic-gate nis_destroy_object(o); 11617c478bd9Sstevel@tonic-gate if (rvt == 0) 11627c478bd9Sstevel@tonic-gate return (0); 11637c478bd9Sstevel@tonic-gate } 11647c478bd9Sstevel@tonic-gate 11657c478bd9Sstevel@tonic-gate qbuf = am(myself, sizeof (*qbuf)); 11667c478bd9Sstevel@tonic-gate /* 11677c478bd9Sstevel@tonic-gate * If there are no columns (other than the pseudo-entry object), 11687c478bd9Sstevel@tonic-gate * we're done. 11697c478bd9Sstevel@tonic-gate */ 11707c478bd9Sstevel@tonic-gate if (nc == 0) 11717c478bd9Sstevel@tonic-gate return (qbuf); 11727c478bd9Sstevel@tonic-gate 11737c478bd9Sstevel@tonic-gate qcbuf = am(myself, nc * sizeof (*qcbuf)); 11747c478bd9Sstevel@tonic-gate if (qcbuf == 0) { 11757c478bd9Sstevel@tonic-gate sfree(qcbuf); 11767c478bd9Sstevel@tonic-gate if (rvt != 0) 11777c478bd9Sstevel@tonic-gate freeRuleValue(rvt, 1); 11787c478bd9Sstevel@tonic-gate return (0); 11797c478bd9Sstevel@tonic-gate } 11807c478bd9Sstevel@tonic-gate 11817c478bd9Sstevel@tonic-gate /* 11827c478bd9Sstevel@tonic-gate * Build the db_query, remembering that e->en_cols.en_cols_val[0] 11837c478bd9Sstevel@tonic-gate * is the pseudo-nis_object. 11847c478bd9Sstevel@tonic-gate */ 11857c478bd9Sstevel@tonic-gate qbuf->components.components_val = qcbuf; 11867c478bd9Sstevel@tonic-gate qbuf->components.components_len = nc; 11877c478bd9Sstevel@tonic-gate for (i = 0; i < nc; i++) { 11887c478bd9Sstevel@tonic-gate qcbuf[i].which_index = i; 11897c478bd9Sstevel@tonic-gate qcbuf[i].index_value = buildItem( 11907c478bd9Sstevel@tonic-gate e->en_cols.en_cols_val[i+1].ec_value.ec_value_len, 11917c478bd9Sstevel@tonic-gate e->en_cols.en_cols_val[i+1].ec_value.ec_value_val); 11927c478bd9Sstevel@tonic-gate if (qcbuf[i].index_value == 0) { 11937c478bd9Sstevel@tonic-gate freeQuery(qbuf); 11947c478bd9Sstevel@tonic-gate if (rvt != 0) 11957c478bd9Sstevel@tonic-gate freeRuleValue(rvt, 1); 11967c478bd9Sstevel@tonic-gate return (0); 11977c478bd9Sstevel@tonic-gate } 11987c478bd9Sstevel@tonic-gate } 11997c478bd9Sstevel@tonic-gate 12007c478bd9Sstevel@tonic-gate if (rvt != 0) { 12017c478bd9Sstevel@tonic-gate *rv = *rvt; 12027c478bd9Sstevel@tonic-gate sfree(rvt); 12037c478bd9Sstevel@tonic-gate } 12047c478bd9Sstevel@tonic-gate 12057c478bd9Sstevel@tonic-gate return (qbuf); 12067c478bd9Sstevel@tonic-gate } 12077c478bd9Sstevel@tonic-gate 12087c478bd9Sstevel@tonic-gate /* 12097c478bd9Sstevel@tonic-gate * Given an input query 'q', and a db_query work buffer 'qbuf', return 12107c478bd9Sstevel@tonic-gate * a pointer to a query with one component corresponding to component 12117c478bd9Sstevel@tonic-gate * 'index' in 'q'. 12127c478bd9Sstevel@tonic-gate * 12137c478bd9Sstevel@tonic-gate * Note that no memory is allocated, and that the returned query has 12147c478bd9Sstevel@tonic-gate * pointers into 'q'. 12157c478bd9Sstevel@tonic-gate */ 12167c478bd9Sstevel@tonic-gate db_query * 12177c478bd9Sstevel@tonic-gate queryFromComponent(db_query *q, int index, db_query *qbuf) { 12187c478bd9Sstevel@tonic-gate 12197c478bd9Sstevel@tonic-gate if (q == 0 || index < 0 || index >= q->components.components_len || 12207c478bd9Sstevel@tonic-gate qbuf == 0) 12217c478bd9Sstevel@tonic-gate return (0); 12227c478bd9Sstevel@tonic-gate 12237c478bd9Sstevel@tonic-gate qbuf->components.components_len = 1; 12247c478bd9Sstevel@tonic-gate qbuf->components.components_val = &q->components.components_val[index]; 12257c478bd9Sstevel@tonic-gate 12267c478bd9Sstevel@tonic-gate return (qbuf); 12277c478bd9Sstevel@tonic-gate } 1228