1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <stdio.h>
30 #include <sys/types.h>
31 #include <stdlib.h>
32 #include <libintl.h>
33 
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <unistd.h>
37 #include <string.h>
38 #include <strings.h>
39 #include <lber.h>
40 #include <ldap.h>
41 #include <syslog.h>
42 
43 #include "ns_sldap.h"
44 #include "ns_internal.h"
45 
46 /* Additional headers for addTypedEntry Conversion routines */
47 #include <pwd.h>
48 #include <shadow.h>
49 #include <grp.h>
50 #include <netinet/in.h>
51 #include <arpa/inet.h>
52 #include <netdb.h>
53 #include <rpc/rpcent.h>
54 #include <auth_attr.h>
55 #include <exec_attr.h>
56 #include <prof_attr.h>
57 #include <user_attr.h>
58 #include <bsm/libbsm.h>
59 
60 
61 /*
62  * If the rdn is a mapped attr:
63  * 	return NS_LDAP_SUCCESS and a new_dn.
64  * If no mapped attr is found in the rdn:
65  * 	return NS_LDAP_SUCCESS and *new_dn == NULL
66  * For example:
67  *  service = abc
68  *  dn =  cn=foo,dc=bar,dc=com
69  *  attributeMapping: abc:cn=sn
70  * Then:
71  *  new_dn = sn=foo,dc=bar,dc=com
72  *
73  */
74 static int
75 replace_mapped_attr_in_dn(
76 	const char *service, const char *dn, char **new_dn)
77 {
78 	char	**mappedattr;
79 	char	**dnArray = NULL;
80 	char	*rservice;
81 	char	*cur = NULL;
82 	int	len = 0, orig_len = 0, mapped_len = 0;
83 	int	dn_len = 0;
84 
85 	*new_dn = NULL;
86 
87 	/*
88 	 * seperate dn into individual componets
89 	 * e.g.
90 	 * "automountKey=user_01" , "automountMapName_test=auto_home", ...
91 	 */
92 	dnArray = ldap_explode_dn(dn, 0);
93 	if (!dnArray || !*dnArray)
94 		return (NS_LDAP_INVALID_PARAM);
95 
96 	cur = strchr(dnArray[0], '=');
97 	if (!cur) {
98 		__s_api_free2dArray(dnArray);
99 		return (NS_LDAP_INVALID_PARAM);
100 	}
101 	*cur = '\0';
102 
103 	/* we only check schema mapping for automount, not for auto_* */
104 	if (strncasecmp(service, NS_LDAP_TYPE_AUTOMOUNT,
105 	    sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0)
106 		rservice = "automount";
107 	else
108 		rservice = (char *)service;
109 
110 	mappedattr = __ns_ldap_getMappedAttributes(rservice, dnArray[0]);
111 	if (!mappedattr || !mappedattr[0]) {
112 		__s_api_free2dArray(dnArray);
113 		if (mappedattr)
114 			__s_api_free2dArray(mappedattr);
115 		return (NS_LDAP_SUCCESS);
116 	}
117 	orig_len = strlen(dnArray[0]);
118 
119 	/*
120 	 * The new length is *dn length + (difference between
121 	 * orig attr and mapped attr) + 1 ;
122 	 * e.g.
123 	 * automountKey=aa,automountMapName=auto_home,dc=foo,dc=com
124 	 * ==>
125 	 * cn=aa,automountMapName=auto_home,dc=foo,dc=com
126 	 */
127 	mapped_len = strlen(mappedattr[0]);
128 	dn_len = strlen(dn);
129 	len = dn_len - orig_len + mapped_len + 1;
130 	*new_dn = (char *)calloc(1, len);
131 	if (*new_dn == NULL) {
132 		__s_api_free2dArray(dnArray);
133 		__s_api_free2dArray(mappedattr);
134 		return (NS_LDAP_MEMORY);
135 	}
136 
137 	(void) snprintf(*new_dn, len, "%s=%s", mappedattr[0], dn + orig_len +1);
138 	__s_api_free2dArray(dnArray);
139 	__s_api_free2dArray(mappedattr);
140 
141 	return (NS_LDAP_SUCCESS);
142 }
143 
144 
145 /*
146  * The following function is only used by the
147  * "gecos" 1 to N attribute mapping code. It expects
148  * and handle only one data/length pair.
149  */
150 static int
151 init_bval_mod(
152 	LDAPMod *mod,
153 	int	mop,
154 	char	*mtype,
155 	char	*mvptr,
156 	int 	mvlen)
157 {
158 
159 	struct berval	**bmodval;
160 
161 	/* dup attribute name */
162 	mod->mod_type = strdup(mtype);
163 	if (mod->mod_type == NULL)
164 		return (-1);
165 
166 	/*
167 	 * assume single value,
168 	 * since only one value/length pair passed in
169 	 */
170 	bmodval = (struct berval **)calloc(2,
171 			sizeof (struct berval *));
172 	if (bmodval == NULL) {
173 		free(mod->mod_type);
174 		mod->mod_type = NULL;
175 		return	(-1);
176 	}
177 	bmodval[0] = (struct berval *)calloc(1,
178 			sizeof (struct berval));
179 	if (bmodval[0] == NULL) {
180 		free(mod->mod_type);
181 		mod->mod_type = NULL;
182 		free(bmodval);
183 		return	(-1);
184 	}
185 
186 	/* set pointer to data */
187 	bmodval[0]->bv_val = mvptr;
188 
189 	/* set length */
190 	bmodval[0]->bv_len = mvlen;
191 
192 	/*
193 	 * turn on the BVALUE bit to indicate
194 	 * that the length of data is supplied
195 	 */
196 	mod->mod_op = mop | LDAP_MOD_BVALUES;
197 
198 	mod->mod_bvalues = bmodval;
199 
200 	return	(0);
201 }
202 
203 static void
204 freeModList(LDAPMod **mods)
205 {
206 	int i, j;
207 	int name_is_oc;
208 
209 	if (mods == NULL)
210 		return;
211 
212 	for (i = 0; mods[i]; i++) {
213 
214 		/* free attribute name */
215 		name_is_oc = FALSE;
216 		if (mods[i]->mod_type) {
217 			if (strcasecmp(mods[i]->mod_type,
218 				"objectclass") == 0)
219 				name_is_oc = TRUE;
220 			free(mods[i]->mod_type);
221 		}
222 
223 		if (mods[i]->mod_bvalues == NULL)
224 			continue;
225 		/*
226 		 * LDAP_MOD_BVALUES is only set by
227 		 * the "gecos" 1 to N attribute mapping
228 		 * code, and the attribute is single valued.
229 		 */
230 		if (mods[i]->mod_op & LDAP_MOD_BVALUES) {
231 			if (mods[i]->mod_bvalues[0])
232 				free(mods[i]->mod_bvalues[0]);
233 		} else {
234 			if (name_is_oc) {
235 				/*
236 				 * only values for the "objectclass"
237 				 * were dupped using strdup.
238 				 * other attribute values were
239 				 * not dupped, but via pointer
240 				 * assignment. So here the
241 				 * values for "objectclass"
242 				 * is freed one by one,
243 				 * but the values for other
244 				 * attributes need not be freed.
245 				 */
246 				for (j = 0; mods[i]->mod_values[j]; j++)
247 					free(mods[i]->mod_values[j]);
248 			}
249 
250 		}
251 		free(mods[i]->mod_bvalues);
252 	}
253 
254 	/* modlist */
255 	free((char *)(mods[0]));
256 	free(mods);
257 }
258 
259 static LDAPMod **
260 __s_api_makeModListCount(
261 	const char *service,
262 	const ns_ldap_attr_t * const *attr,
263 	const int mod_op,
264 	const int count,
265 	const int flags)
266 {
267 	LDAPMod		**mods, *modlist;
268 	char		**modval;
269 	char		**mapping;
270 	int		i;
271 	int		j;
272 	int		k, rc, vlen;
273 	char		*c, *comma1 = NULL, *comma2 = NULL;
274 	int		schema_mapping_existed = FALSE;
275 	int		auto_service = FALSE;
276 
277 
278 	/*
279 	 * add 2 for "gecos" 1 to up to 3 attribute mapping
280 	 */
281 	mods = (LDAPMod **)calloc((count + 3), sizeof (LDAPMod *));
282 	if (mods == NULL) {
283 		return (NULL);
284 	}
285 	/*
286 	 * add 2 for "gecos" 1 to up to 3 attribute mapping
287 	 */
288 	modlist = (LDAPMod *)calloc(count + 2, sizeof (LDAPMod));
289 	if (modlist == NULL) {
290 		free(mods);
291 		return (NULL);
292 	}
293 
294 	if (service != NULL && strncasecmp(service, NS_LDAP_TYPE_AUTOMOUNT,
295 	    sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0)
296 		auto_service = TRUE;
297 
298 	/*
299 	 * see if schema mapping existed for the given service
300 	 */
301 	mapping = __ns_ldap_getOrigAttribute(service,
302 	    NS_HASH_SCHEMA_MAPPING_EXISTED);
303 	if (mapping) {
304 		schema_mapping_existed = TRUE;
305 		__s_api_free2dArray(mapping);
306 		mapping = NULL;
307 	}
308 
309 	for (i = 0, k = 0; k < count && attr[k] != NULL; i++, k++) {
310 		mods[i] = &modlist[i];
311 		mods[i]->mod_op = mod_op;
312 		/*
313 		 * Perform attribute mapping if necessary.
314 		 */
315 		if (schema_mapping_existed &&
316 			(flags & NS_LDAP_NOMAP) == 0) {
317 			mapping = __ns_ldap_getMappedAttributes(service,
318 			    attr[k]->attrname);
319 		} else
320 			mapping = NULL;
321 
322 		if (mapping == NULL && auto_service &&
323 		    (flags & NS_LDAP_NOMAP) == 0) {
324 			/*
325 			 * if service == auto_xxx and
326 			 * no mapped attribute is found
327 			 * and NS_LDAP_NOMAP is not set
328 			 * then try automount's mapped attribute
329 			 */
330 			mapping = __ns_ldap_getMappedAttributes("automount",
331 			    attr[k]->attrname);
332 		}
333 
334 		if (mapping == NULL) {
335 		    mods[i]->mod_type = strdup(attr[k]->attrname);
336 		    if (mods[i]->mod_type == NULL) {
337 			goto free_memory;
338 		    }
339 		} else {
340 			/*
341 			 * 1 to N attribute mapping is only done for "gecos",
342 			 * and only 1 to 3 mapping.
343 			 * nine cases here:
344 			 *
345 			 * A. attrMap=passwd:gecos=a
346 			 *    1. gecos="xx,yy,zz" -> a="xx,yy,zz"
347 			 *    2. gecos="xx,yy" -> a="xx,yy"
348 			 *    3. gecos="xx" -> a="xx"
349 			 *
350 			 * B. attrMap=passwd:gecos=a b
351 			 *    4. gecos="xx,yy,zz" -> a="xx" b="yy,zz"
352 			 *    5. gecos="xx,yy" -> a="xx" b="yy"
353 			 *    6. gecos="xx" -> a="xx"
354 			 *
355 			 * C. attrMap=passwd:gecos=a b c
356 			 *    7. gecos="xx,yy,zz" -> a="xx" b="yy" c="zz"
357 			 *    8. gecos="xx,yy" -> a="xx" b="yy"
358 			 *    9. gecos="xx" -> a="xx"
359 			 *
360 			 * This can be grouped as:
361 			 *
362 			 * c1 cases: 1,2,3,6,9
363 			 *    if ((attrMap=passwd:gecos=a) ||
364 			 *		(no "," in gecos value))
365 			 *	same as other no-mapping attributes,
366 			 *	no special processing needed
367 			 *    else
368 			 *
369 			 * c2 cases: 4,5,8
370 			 *    if ((attrMap=passwd:gecos=a b) ||
371 			 *	(only one "," in gecos value))
372 			 *	a=xx b=yy[,...]
373 			 *    else
374 			 *
375 			 * c3 case: 7
376 			 *    a=xx b=yy c=...
377 			 *
378 			 * notes: in case c2 and c3, ... could still contain ","
379 			 */
380 		    if (strcasecmp(service, "passwd") == 0 &&
381 			strcasecmp(attr[k]->attrname, "gecos") == 0 &&
382 			mapping[1] && attr[k]->attrvalue[0] &&
383 			(comma1 = strchr(attr[k]->attrvalue[0],
384 			COMMATOK)) != NULL) {
385 
386 			/* is there a second comma? */
387 			if (*(comma1 + 1) != '\0')
388 				comma2 = strchr(comma1 + 1, COMMATOK);
389 
390 			/*
391 			 * Process case c2 or c3.
392 			 * case c2: mapped to two attributes or just
393 			 * one comma
394 			 */
395 			if (mapping[2] == NULL ||
396 				comma2 == NULL) {
397 				/* case c2 */
398 
399 				/*
400 				 * int mod structure for the first attribute
401 				 */
402 				vlen = comma1 - attr[k]->attrvalue[0];
403 				c = attr[k]->attrvalue[0];
404 
405 				if (vlen > 0 && c) {
406 					rc = init_bval_mod(mods[i], mod_op,
407 						mapping[0], c, vlen);
408 					if (rc != 0)
409 						goto free_memory;
410 				} else {
411 					/* don't leave a hole in mods array */
412 					mods[i] = NULL;
413 					i--;
414 				}
415 
416 
417 				/*
418 				 * init mod structure for the 2nd attribute
419 				 */
420 				if (*(comma1 + 1) == '\0') {
421 					__s_api_free2dArray(mapping);
422 					mapping = NULL;
423 					continue;
424 				}
425 
426 				i++;
427 				mods[i] = &modlist[i];
428 
429 				/*
430 				 * get pointer to data.
431 				 * Skip leading spaces.
432 				 */
433 				for (c = comma1 + 1; *c == SPACETOK; c++);
434 
435 				/* get data length */
436 				vlen = strlen(attr[k]->attrvalue[0]) -
437 					(c - attr[k]->attrvalue[0]);
438 
439 				if (vlen > 0 && c) {
440 					rc = init_bval_mod(mods[i], mod_op,
441 						mapping[1], c, vlen);
442 					if (rc != 0)
443 						goto free_memory;
444 				} else {
445 					/* don't leave a hole in mods array */
446 					mods[i] = NULL;
447 					i--;
448 				}
449 
450 				/* done with the mapping array */
451 				__s_api_free2dArray(mapping);
452 				mapping = NULL;
453 
454 				continue;
455 			} else {
456 				/* case c3 */
457 
458 				/*
459 				 * int mod structure for the first attribute
460 				 */
461 				vlen = comma1 - attr[k]->attrvalue[0];
462 				c = attr[k]->attrvalue[0];
463 
464 				if (vlen > 0 && c) {
465 					rc = init_bval_mod(mods[i], mod_op,
466 						mapping[0], c, vlen);
467 					if (rc != 0)
468 						goto free_memory;
469 				} else {
470 					/* don't leave a hole in mods array */
471 					mods[i] = NULL;
472 					i--;
473 				}
474 
475 				/*
476 				 * init mod structure for the 2nd attribute
477 				 */
478 				i++;
479 				mods[i] = &modlist[i];
480 
481 				/*
482 				 * get pointer to data.
483 				 * Skip leading spaces.
484 				 */
485 				for (c = comma1 + 1; *c == SPACETOK; c++);
486 
487 				/* get data length */
488 				vlen = comma2 - c;
489 
490 				if (vlen > 0 && c) {
491 					rc = init_bval_mod(mods[i], mod_op,
492 						mapping[1], c, vlen);
493 					if (rc != 0)
494 						goto free_memory;
495 				} else {
496 					/* don't leave a hole in mods array */
497 					mods[i] = NULL;
498 					i--;
499 				}
500 
501 				/*
502 				 * init mod structure for the 3rd attribute
503 				 */
504 				if (*(comma2 + 1) == '\0') {
505 					__s_api_free2dArray(mapping);
506 					mapping = NULL;
507 					continue;
508 				}
509 
510 				i++;
511 				mods[i] = &modlist[i];
512 				/*
513 				 * get pointer to data.
514 				 * Skip leading spaces.
515 				 */
516 				for (c = comma2 + 1; *c == SPACETOK; c++);
517 
518 				/* get data length */
519 				vlen = strlen(attr[k]->attrvalue[0]) -
520 					(c - attr[k]->attrvalue[0]);
521 
522 				if (vlen > 0 && c) {
523 					rc = init_bval_mod(mods[i], mod_op,
524 						mapping[2], c, vlen);
525 					if (rc != 0)
526 						goto free_memory;
527 				} else {
528 					/* don't leave a hole in mods array */
529 					mods[i] = NULL;
530 					i--;
531 				}
532 
533 				/* done with the mapping array */
534 				__s_api_free2dArray(mapping);
535 				mapping = NULL;
536 
537 				continue;
538 			}
539 		    }
540 
541 		    /* case c1 */
542 		    mods[i]->mod_type = strdup(mapping[0]);
543 		    if (mods[i]->mod_type == NULL) {
544 				goto free_memory;
545 		    }
546 		    __s_api_free2dArray(mapping);
547 		    mapping = NULL;
548 		}
549 
550 		modval = (char **)calloc(attr[k]->value_count+1,
551 				sizeof (char *));
552 		if (modval == NULL)
553 			goto free_memory;
554 		/*
555 		 * Perform objectclass mapping.
556 		 * Note that the values for the "objectclass" attribute
557 		 * will be dupped using strdup. Values for other
558 		 * attributes will be referenced via pointer
559 		 * assignments.
560 		 */
561 		if (strcasecmp(mods[i]->mod_type, "objectclass") == 0) {
562 			for (j = 0; j < attr[k]->value_count; j++) {
563 				if (schema_mapping_existed &&
564 					(flags & NS_LDAP_NOMAP) == 0)
565 					mapping =
566 					__ns_ldap_getMappedObjectClass(
567 					service, attr[k]->attrvalue[j]);
568 				else
569 					mapping = NULL;
570 
571 				if (mapping == NULL && auto_service &&
572 					(flags & NS_LDAP_NOMAP) == 0)
573 					/*
574 					 * if service == auto_xxx and
575 					 * no mapped objectclass is found
576 					 * then try automount
577 					 */
578 					mapping =
579 					__ns_ldap_getMappedObjectClass(
580 					"automount", attr[k]->attrvalue[j]);
581 
582 				if (mapping && mapping[0]) {
583 					/* assume single mapping */
584 					modval[j] = strdup(mapping[0]);
585 				} else {
586 					modval[j] = strdup(attr[k]->
587 							attrvalue[j]);
588 				}
589 				if (modval[j] == NULL)
590 					goto free_memory;
591 			}
592 		} else {
593 			for (j = 0; j < attr[k]->value_count; j++) {
594 				/* ASSIGN NOT COPY */
595 				modval[j] = attr[k]->attrvalue[j];
596 			}
597 		}
598 		mods[i]->mod_values = modval;
599 	}
600 
601 	return (mods);
602 
603 free_memory:
604 	freeModList(mods);
605 	if (mapping)
606 	__s_api_free2dArray(mapping);
607 
608 	return (NULL);
609 
610 }
611 
612 static LDAPMod **
613 __s_api_makeModList(
614 	const char *service,
615 	const ns_ldap_attr_t * const *attr,
616 	const int mod_op,
617 	const int flags)
618 {
619 	ns_ldap_attr_t	**aptr = (ns_ldap_attr_t **)attr;
620 	int		count = 0;
621 
622 	if (aptr == NULL)
623 		return (NULL);
624 
625 	/* count number of attributes */
626 	while (*aptr++)
627 		count++;
628 
629 	return (__s_api_makeModListCount(service, attr, mod_op, count, flags));
630 }
631 
632 static void
633 __s_cvt_freeEntryRdn(ns_ldap_entry_t **entry, char **rdn)
634 {
635 	if (*entry != NULL) {
636 		__ns_ldap_freeEntry(*entry);
637 		*entry = NULL;
638 	}
639 	if (*rdn != NULL) {
640 		free(*rdn);
641 		*rdn = NULL;
642 	}
643 }
644 
645 /*
646  * This state machine performs one or more LDAP add/delete/modify
647  * operations to configured LDAP servers.
648  */
649 static int
650 write_state_machine(
651 	int 		ldap_op,
652 	char 		*dn,
653 	LDAPMod		**mods,
654 	const ns_cred_t *cred,
655 	const int 	flags,
656 	ns_ldap_error_t ** errorp)
657 {
658 	ConnectionID    connectionId = -1;
659 	Connection	*conp = NULL;
660 	LDAPMessage 	*res;
661 	char		*target_dn = NULL;
662 	char		errstr[MAXERROR];
663 	int		rc = NS_LDAP_SUCCESS;
664 	int		return_rc = NS_LDAP_SUCCESS;
665 	int		followRef = FALSE;
666 	int		target_dn_allocated = FALSE;
667 	int		len;
668 	int		msgid;
669 	int		Errno;
670 	int		always = 1;
671 	char		*err, *errmsg = NULL;
672 	char		**referrals = NULL;
673 	ns_referral_info_t *ref = NULL;
674 	ns_write_state_t state = W_INIT, new_state, err_state = W_INIT;
675 	int		do_not_fail_if_new_pwd_reqd = 0;
676 	ns_ldap_passwd_status_t	pwd_status = NS_PASSWD_GOOD;
677 	int		passwd_mgmt = 0;
678 
679 	while (always) {
680 		switch (state) {
681 		case W_EXIT:
682 			if (connectionId > -1)
683 				DropConnection(connectionId, 0);
684 			if (ref)
685 				__s_api_deleteRefInfo(ref);
686 			if (target_dn && target_dn_allocated)
687 				free(target_dn);
688 			return (return_rc);
689 		case W_INIT:
690 			/* see if need to follow referrals */
691 			rc = __s_api_toFollowReferrals(flags,
692 				&followRef, errorp);
693 			if (rc != NS_LDAP_SUCCESS) {
694 				return_rc = rc;
695 				new_state = W_ERROR;
696 				break;
697 			}
698 			len = strlen(dn);
699 			if (dn[len-1] == COMMATOK)
700 				rc = __s_api_append_default_basedn(
701 					dn, &target_dn,
702 					&target_dn_allocated,
703 					errorp);
704 			else
705 				target_dn = dn;
706 			if (rc != NS_LDAP_SUCCESS) {
707 				return_rc = rc;
708 				new_state = W_ERROR;
709 			}
710 			else
711 				new_state = GET_CONNECTION;
712 			break;
713 		case GET_CONNECTION:
714 			rc = __s_api_getConnection(NULL,
715 				flags,
716 				cred,
717 				&connectionId,
718 				&conp,
719 				errorp,
720 				do_not_fail_if_new_pwd_reqd);
721 
722 			/*
723 			 * If password control attached
724 			 * in *errorp,
725 			 * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO,
726 			 * free the error structure (we do not need
727 			 * the password management info).
728 			 * Reset rc to NS_LDAP_SUCCESS.
729 			 */
730 			if (rc == NS_LDAP_SUCCESS_WITH_INFO) {
731 				(void) __ns_ldap_freeError(
732 					errorp);
733 				*errorp = NULL;
734 				rc = NS_LDAP_SUCCESS;
735 			}
736 
737 			if (rc != NS_LDAP_SUCCESS) {
738 				return_rc = rc;
739 				new_state = W_ERROR;
740 				break;
741 			}
742 			if (followRef)
743 				new_state = SELECT_OPERATION_ASYNC;
744 			else
745 				new_state = SELECT_OPERATION_SYNC;
746 			break;
747 		case SELECT_OPERATION_SYNC:
748 			if (ldap_op == LDAP_REQ_ADD)
749 				new_state = DO_ADD_SYNC;
750 			else if (ldap_op == LDAP_REQ_DELETE)
751 				new_state = DO_DELETE_SYNC;
752 			else if (ldap_op == LDAP_REQ_MODIFY)
753 				new_state = DO_MODIFY_SYNC;
754 			break;
755 		case SELECT_OPERATION_ASYNC:
756 			if (ldap_op == LDAP_REQ_ADD)
757 				new_state = DO_ADD_ASYNC;
758 			else if (ldap_op == LDAP_REQ_DELETE)
759 				new_state = DO_DELETE_ASYNC;
760 			else if (ldap_op == LDAP_REQ_MODIFY)
761 				new_state = DO_MODIFY_ASYNC;
762 			break;
763 		case DO_ADD_SYNC:
764 			rc = ldap_add_ext_s(conp->ld, target_dn,
765 				mods, NULL, NULL);
766 			new_state = GET_RESULT_SYNC;
767 			break;
768 		case DO_DELETE_SYNC:
769 			rc = ldap_delete_ext_s(conp->ld, target_dn,
770 				NULL, NULL);
771 			new_state = GET_RESULT_SYNC;
772 			break;
773 		case DO_MODIFY_SYNC:
774 			rc = ldap_modify_ext_s(conp->ld, target_dn,
775 				mods, NULL, NULL);
776 			new_state = GET_RESULT_SYNC;
777 			break;
778 		case DO_ADD_ASYNC:
779 			rc = ldap_add_ext(conp->ld, target_dn,
780 				mods, NULL, NULL, &msgid);
781 			new_state = GET_RESULT_ASYNC;
782 			break;
783 		case DO_DELETE_ASYNC:
784 			rc = ldap_delete_ext(conp->ld, target_dn,
785 				NULL, NULL, &msgid);
786 			new_state = GET_RESULT_ASYNC;
787 			break;
788 		case DO_MODIFY_ASYNC:
789 			rc = ldap_modify_ext(conp->ld, target_dn,
790 				mods, NULL, NULL, &msgid);
791 			new_state = GET_RESULT_ASYNC;
792 			break;
793 		case GET_RESULT_SYNC:
794 			if (rc != LDAP_SUCCESS) {
795 				Errno = rc;
796 				(void) ldap_get_lderrno(conp->ld,
797 					NULL, &errmsg);
798 				/*
799 				 * free errmsg if it is an empty string
800 				 */
801 				if (errmsg && *errmsg == '\0') {
802 					ldap_memfree(errmsg);
803 					errmsg = NULL;
804 				}
805 				new_state = W_LDAP_ERROR;
806 			} else {
807 				return_rc = NS_LDAP_SUCCESS;
808 				new_state = W_EXIT;
809 			}
810 			break;
811 		case GET_RESULT_ASYNC:
812 			rc = ldap_result(conp->ld, msgid, 1,
813 				(struct timeval *)NULL, &res);
814 			/* if no server response, set Errno */
815 			if (rc == -1) {
816 				(void) ldap_get_option(conp->ld,
817 				    LDAP_OPT_ERROR_NUMBER, &Errno);
818 				new_state = W_LDAP_ERROR;
819 				break;
820 			}
821 			if (rc == LDAP_RES_ADD ||
822 				rc == LDAP_RES_MODIFY ||
823 				rc == LDAP_RES_DELETE) {
824 				new_state = PARSE_RESULT;
825 				break;
826 			} else {
827 				return_rc = rc;
828 				new_state = W_ERROR;
829 			}
830 			break;
831 		case PARSE_RESULT:
832 			/*
833 			 * need Errno, referrals, error msg,
834 			 * and the last "1" is to free
835 			 * the result (res)
836 			 */
837 			rc = ldap_parse_result(conp->ld,
838 				res, &Errno,
839 				NULL, &errmsg,
840 				&referrals, NULL, 1);
841 			/*
842 			 * free errmsg if it is an empty string
843 			 */
844 			if (errmsg && *errmsg == '\0') {
845 				ldap_memfree(errmsg);
846 				errmsg = NULL;
847 			}
848 			if (Errno == LDAP_REFERRAL) {
849 				/* only follow one referral */
850 				if (referrals[0]) {
851 					rc = __s_api_addRefInfo(&ref,
852 						referrals[0],
853 						NULL, NULL, NULL,
854 						conp->ld);
855 				}
856 				ldap_value_free(referrals);
857 				if (ref == NULL) {
858 					if (rc != NS_LDAP_MEMORY)
859 						rc = NS_LDAP_INTERNAL;
860 					new_state = W_ERROR;
861 				} else
862 					new_state = GET_REFERRAL_CONNECTION;
863 				if (errmsg) {
864 					ldap_memfree(errmsg);
865 					errmsg = NULL;
866 				}
867 				break;
868 			}
869 			if (Errno != LDAP_SUCCESS) {
870 				new_state = W_LDAP_ERROR;
871 			} else {
872 				return_rc = NS_LDAP_SUCCESS;
873 				new_state = W_EXIT;
874 			}
875 			break;
876 		case GET_REFERRAL_CONNECTION:
877 			if (connectionId > -1)
878 				DropConnection(connectionId, 0);
879 			rc = __s_api_getConnection(ref->refHost,
880 				0,
881 				cred,
882 				&connectionId,
883 				&conp,
884 				errorp,
885 				do_not_fail_if_new_pwd_reqd);
886 
887 			/*
888 			 * If password control attached
889 			 * in errorp,
890 			 * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO,
891 			 * free the error structure (we do not need
892 			 * the password management info).
893 			 * Reset rc to NS_LDAP_SUCCESS.
894 			 */
895 			if (rc == NS_LDAP_SUCCESS_WITH_INFO) {
896 				(void) __ns_ldap_freeError(
897 					errorp);
898 				*errorp = NULL;
899 				rc = NS_LDAP_SUCCESS;
900 			}
901 
902 			if (rc != NS_LDAP_SUCCESS) {
903 				__s_api_deleteRefInfo(ref);
904 				ref = NULL;
905 				return_rc = rc;
906 				new_state = W_ERROR;
907 				break;
908 			}
909 			/* target DN may changed due to referrals */
910 			if (ref->refDN) {
911 				if (target_dn && target_dn_allocated) {
912 					free(target_dn);
913 					target_dn = NULL;
914 					target_dn_allocated = FALSE;
915 				}
916 				target_dn = ref->refDN;
917 			}
918 			new_state = SELECT_OPERATION_SYNC;
919 			break;
920 		case W_LDAP_ERROR:
921 			/*
922 			 * map error code and error message
923 			 * to password status if necessary.
924 			 * This is to see if password updates
925 			 * failed due to password policy or
926 			 * password syntax checking.
927 			 */
928 			if (errmsg) {
929 				/*
930 				 * check if server supports
931 				 * password management
932 				 */
933 				passwd_mgmt =
934 					__s_api_contain_passwd_control_oid(
935 						conp->controls);
936 					if (passwd_mgmt)
937 						pwd_status =
938 						__s_api_set_passwd_status(
939 						Errno, errmsg);
940 				ldap_memfree(errmsg);
941 				errmsg = NULL;
942 			}
943 
944 			(void) sprintf(errstr,
945 				gettext(ldap_err2string(Errno)));
946 			err = strdup(errstr);
947 			if (pwd_status != NS_PASSWD_GOOD) {
948 				MKERROR_PWD_MGMT(*errorp, Errno, err,
949 					pwd_status, 0, NULL);
950 			} else {
951 				MKERROR(LOG_INFO, *errorp, Errno, err, NULL);
952 			}
953 			return_rc = NS_LDAP_INTERNAL;
954 			new_state = W_EXIT;
955 			break;
956 		case W_ERROR:
957 		default:
958 			(void) sprintf(errstr,
959 				gettext("Internal write State machine exit"
960 					" (state = %d, rc = %d)."),
961 					err_state, return_rc);
962 			err = strdup(errstr);
963 			MKERROR(LOG_WARNING, *errorp, return_rc, err, NULL);
964 			new_state = W_EXIT;
965 			break;
966 		}
967 
968 		if (new_state == W_ERROR)
969 			err_state = state;
970 		state = new_state;
971 	}
972 
973 	/*
974 	 * should never be here, the next line is to eliminating
975 	 * lint message
976 	 */
977 	return (NS_LDAP_INTERNAL);
978 }
979 
980 
981 /*ARGSUSED*/
982 int
983 __ns_ldap_addAttr(
984 	const char *service,
985 	const char *dn,
986 	const ns_ldap_attr_t * const *attr,
987 	const ns_cred_t *cred,
988 	const int flags,
989 	ns_ldap_error_t ** errorp)
990 {
991 	LDAPMod		**mods;
992 	int		rc = 0;
993 
994 #ifdef DEBUG
995 	(void) fprintf(stderr, "__ns_ldap_addAttr START\n");
996 #endif
997 	*errorp = NULL;
998 
999 	/* Sanity check */
1000 	if ((attr == NULL) || (*attr == NULL) ||
1001 	    (dn == NULL) || (cred == NULL))
1002 		return (NS_LDAP_INVALID_PARAM);
1003 
1004 	mods = __s_api_makeModList(service, attr, LDAP_MOD_ADD, flags);
1005 	if (mods == NULL) {
1006 		return (NS_LDAP_MEMORY);
1007 	}
1008 
1009 	rc = write_state_machine(LDAP_REQ_MODIFY,
1010 	    (char *)dn, mods, cred, flags, errorp);
1011 	freeModList(mods);
1012 
1013 	return (rc);
1014 }
1015 
1016 
1017 /*ARGSUSED*/
1018 int
1019 __ns_ldap_delAttr(
1020 	const char *service,
1021 	const char *dn,
1022 	const ns_ldap_attr_t * const *attr,
1023 	const ns_cred_t *cred,
1024 	const int flags,
1025 	ns_ldap_error_t ** errorp)
1026 {
1027 	LDAPMod		**mods;
1028 	int		rc = 0;
1029 
1030 #ifdef DEBUG
1031 	(void) fprintf(stderr, "__ns_ldap_delAttr START\n");
1032 #endif
1033 	*errorp = NULL;
1034 
1035 	/* Sanity check */
1036 	if ((attr == NULL) || (*attr == NULL) ||
1037 	    (dn == NULL) || (cred == NULL))
1038 		return (NS_LDAP_INVALID_PARAM);
1039 
1040 	mods = __s_api_makeModList(service, attr, LDAP_MOD_DELETE, flags);
1041 	if (mods == NULL) {
1042 		return (NS_LDAP_MEMORY);
1043 	}
1044 
1045 	rc = write_state_machine(LDAP_REQ_MODIFY,
1046 	    (char *)dn, mods, cred, flags, errorp);
1047 
1048 	freeModList(mods);
1049 	return (rc);
1050 }
1051 
1052 /*ARGSUSED*/
1053 int
1054 __ns_ldap_repAttr(
1055 	const char *service,
1056 	const char *dn,
1057 	const ns_ldap_attr_t * const *attr,
1058 	const ns_cred_t *cred,
1059 	const int flags,
1060 	ns_ldap_error_t ** errorp)
1061 {
1062 	LDAPMod		**mods;
1063 	int		rc = 0;
1064 
1065 #ifdef DEBUG
1066 	(void) fprintf(stderr, "__ns_ldap_repAttr START\n");
1067 #endif
1068 	*errorp = NULL;
1069 
1070 	/* Sanity check */
1071 	if ((attr == NULL) || (*attr == NULL) ||
1072 	    (dn == NULL) || (cred == NULL))
1073 		return (NS_LDAP_INVALID_PARAM);
1074 	mods = __s_api_makeModList(service, attr, LDAP_MOD_REPLACE, flags);
1075 	if (mods == NULL) {
1076 		return (NS_LDAP_MEMORY);
1077 	}
1078 
1079 	rc = write_state_machine(LDAP_REQ_MODIFY,
1080 	    (char *)dn, mods, cred, flags, errorp);
1081 
1082 	freeModList(mods);
1083 	return (rc);
1084 }
1085 
1086 
1087 /*ARGSUSED*/
1088 int
1089 __ns_ldap_addEntry(
1090 	const char *service,
1091 	const char *dn,
1092 	const ns_ldap_entry_t *entry,
1093 	const ns_cred_t *cred,
1094 	const int flags,
1095 	ns_ldap_error_t ** errorp)
1096 {
1097 	char		*new_dn = NULL;
1098 	LDAPMod		**mods = NULL;
1099 	const ns_ldap_attr_t	* const *attr;
1100 	int		nAttr = 0;
1101 	int		rc = 0;
1102 
1103 #ifdef DEBUG
1104 	(void) fprintf(stderr, "__ns_ldap_addEntry START\n");
1105 #endif
1106 
1107 	if ((entry == NULL) || (dn == NULL) || (cred == NULL))
1108 		return (NS_LDAP_INVALID_PARAM);
1109 	*errorp = NULL;
1110 
1111 	/* Construct array of LDAPMod representing attributes of new entry. */
1112 
1113 	nAttr = entry->attr_count;
1114 	attr = (const ns_ldap_attr_t * const *)(entry->attr_pair);
1115 	mods = __s_api_makeModListCount(service, attr, LDAP_MOD_ADD,
1116 	    nAttr, flags);
1117 	if (mods == NULL) {
1118 		return (NS_LDAP_MEMORY);
1119 	}
1120 
1121 	rc = replace_mapped_attr_in_dn(service, dn, &new_dn);
1122 	if (rc != NS_LDAP_SUCCESS) {
1123 		freeModList(mods);
1124 		return (rc);
1125 	}
1126 
1127 	rc = write_state_machine(LDAP_REQ_ADD,
1128 	    new_dn ? new_dn : (char *)dn, mods, cred, flags, errorp);
1129 
1130 	if (new_dn)
1131 		free(new_dn);
1132 	freeModList(mods);
1133 	return (rc);
1134 }
1135 
1136 
1137 /*ARGSUSED*/
1138 int
1139 __ns_ldap_delEntry(
1140 	const char *service,
1141 	const char *dn,
1142 	const ns_cred_t *cred,
1143 	const int flags,
1144 	ns_ldap_error_t ** errorp)
1145 {
1146 	int		rc;
1147 
1148 #ifdef DEBUG
1149 	(void) fprintf(stderr, "__ns_ldap_delEntry START\n");
1150 #endif
1151 	if ((dn == NULL) || (cred == NULL))
1152 		return (NS_LDAP_INVALID_PARAM);
1153 
1154 	*errorp = NULL;
1155 
1156 	rc = write_state_machine(LDAP_REQ_DELETE,
1157 	    (char *)dn, NULL, cred, flags, errorp);
1158 
1159 	return (rc);
1160 }
1161 
1162 /*
1163  * Add Typed Entry Helper routines
1164  */
1165 
1166 /*
1167  * Add Typed Entry Conversion routines
1168  */
1169 
1170 static int
1171 __s_add_attr(ns_ldap_entry_t *e, char *attrname, char *value)
1172 {
1173 	ns_ldap_attr_t	*a;
1174 	char		*v;
1175 
1176 	a = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t));
1177 	if (a == NULL)
1178 		return (NS_LDAP_MEMORY);
1179 	a->attrname = strdup(attrname);
1180 	if (a->attrname == NULL)
1181 		return (NS_LDAP_MEMORY);
1182 	a->attrvalue = (char **)calloc(1, sizeof (char **));
1183 	if (a->attrvalue == NULL)
1184 		return (NS_LDAP_MEMORY);
1185 	a->value_count = 1;
1186 	a->attrvalue[0] = NULL;
1187 	v = strdup(value);
1188 	if (v == NULL)
1189 		return (NS_LDAP_MEMORY);
1190 	a->attrvalue[0] = v;
1191 	e->attr_pair[e->attr_count] = a;
1192 	e->attr_count++;
1193 	return (NS_LDAP_SUCCESS);
1194 }
1195 
1196 static int
1197 __s_add_attrlist(ns_ldap_entry_t *e, char *attrname, char **argv)
1198 {
1199 	ns_ldap_attr_t	*a;
1200 	char		*v;
1201 	char		**av;
1202 	int		i, j;
1203 
1204 	a = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t));
1205 	if (a == NULL)
1206 		return (NS_LDAP_MEMORY);
1207 	a->attrname = strdup(attrname);
1208 	if (a->attrname == NULL)
1209 		return (NS_LDAP_MEMORY);
1210 
1211 	for (i = 0, av = argv; *av != NULL; av++, i++)
1212 		;
1213 
1214 	a->attrvalue = (char **)calloc(i, sizeof (char *));
1215 
1216 	if (a->attrvalue == NULL)
1217 		return (NS_LDAP_MEMORY);
1218 
1219 	a->value_count = i;
1220 	for (j = 0; j < i; j++) {
1221 		v = strdup(argv[j]);
1222 		if (v == NULL)
1223 			return (NS_LDAP_MEMORY);
1224 		a->attrvalue[j] = v;
1225 	}
1226 	e->attr_pair[e->attr_count] = a;
1227 	e->attr_count++;
1228 	return (NS_LDAP_SUCCESS);
1229 }
1230 
1231 static ns_ldap_entry_t *
1232 __s_mk_entry(char **objclass, int max_attr)
1233 {
1234 	ns_ldap_entry_t *e;
1235 	e = (ns_ldap_entry_t *)calloc(1, sizeof (ns_ldap_entry_t));
1236 	if (e == NULL)
1237 		return (NULL);
1238 	/* allocate attributes, +1 for objectclass, +1 for NULL terminator */
1239 	e->attr_pair = (ns_ldap_attr_t **)
1240 	    calloc(max_attr + 2, sizeof (ns_ldap_attr_t *));
1241 	if (e->attr_pair == NULL) {
1242 		free(e);
1243 		return (NULL);
1244 	}
1245 	e->attr_count = 0;
1246 	if (__s_add_attrlist(e, "objectClass", objclass) != NS_LDAP_SUCCESS) {
1247 		free(e->attr_pair);
1248 		free(e);
1249 		return (NULL);
1250 	}
1251 	return (e);
1252 }
1253 
1254 
1255 /*
1256  * Conversion:			passwd
1257  * Input format:		struct passwd
1258  * Exported objectclass:	posixAccount
1259  */
1260 static int
1261 __s_cvt_passwd(const void *data, char **rdn,
1262 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
1263 {
1264 	ns_ldap_entry_t	*e;
1265 	int		rc;
1266 	char		trdn[RDNSIZE];
1267 	/* routine specific */
1268 	struct passwd	*ptr;
1269 	int		max_attr = 9;
1270 	char		ibuf[10];
1271 	static		char *oclist[] = {
1272 			"posixAccount",
1273 			"shadowAccount",
1274 			"account",
1275 			"top",
1276 			NULL
1277 			};
1278 
1279 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
1280 		return (NS_LDAP_OP_FAILED);
1281 	*entry = e = __s_mk_entry(oclist, max_attr);
1282 	if (e == NULL)
1283 		return (NS_LDAP_MEMORY);
1284 
1285 	/* Convert the structure */
1286 	ptr = (struct passwd *)data;
1287 
1288 	if (ptr->pw_name == NULL || ptr->pw_uid < 0 ||
1289 	    ptr->pw_gid < 0 || ptr->pw_dir == NULL) {
1290 		__ns_ldap_freeEntry(e);
1291 		*entry = NULL;
1292 		return (NS_LDAP_INVALID_PARAM);
1293 	}
1294 
1295 	/* Create an appropriate rdn */
1296 	(void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->pw_name);
1297 	*rdn = strdup(trdn);
1298 	if (*rdn == NULL) {
1299 		__ns_ldap_freeEntry(e);
1300 		*entry = NULL;
1301 		return (NS_LDAP_MEMORY);
1302 	}
1303 
1304 	/* Error check the data and add the attributes */
1305 	rc = __s_add_attr(e, "uid", ptr->pw_name);
1306 	if (rc != NS_LDAP_SUCCESS) {
1307 		__s_cvt_freeEntryRdn(entry, rdn);
1308 		return (rc);
1309 	}
1310 	rc = __s_add_attr(e, "cn", ptr->pw_name);
1311 	if (rc != NS_LDAP_SUCCESS) {
1312 		__s_cvt_freeEntryRdn(entry, rdn);
1313 		return (rc);
1314 	}
1315 
1316 	if (ptr->pw_passwd != NULL &&
1317 		ptr->pw_passwd[0] != '\0') {
1318 		rc = __s_add_attr(e, "userPassword", ptr->pw_passwd);
1319 		if (rc != NS_LDAP_SUCCESS) {
1320 			__s_cvt_freeEntryRdn(entry, rdn);
1321 			return (rc);
1322 		}
1323 	}
1324 
1325 #ifdef _LP64
1326 	(void) sprintf(ibuf, "%d", ptr->pw_uid);
1327 #else
1328 	(void) sprintf(ibuf, "%ld", ptr->pw_uid);
1329 #endif
1330 	rc = __s_add_attr(e, "uidNumber", ibuf);
1331 	if (rc != NS_LDAP_SUCCESS) {
1332 		__s_cvt_freeEntryRdn(entry, rdn);
1333 		return (rc);
1334 	}
1335 
1336 #ifdef _LP64
1337 	(void) sprintf(ibuf, "%d", ptr->pw_gid);
1338 #else
1339 	(void) sprintf(ibuf, "%ld", ptr->pw_gid);
1340 #endif
1341 	rc = __s_add_attr(e, "gidNumber", ibuf);
1342 	if (rc != NS_LDAP_SUCCESS) {
1343 		__s_cvt_freeEntryRdn(entry, rdn);
1344 		return (rc);
1345 	}
1346 	if (ptr->pw_gecos != NULL &&
1347 		ptr->pw_gecos[0] != '\0') {
1348 		rc = __s_add_attr(e, "gecos", ptr->pw_gecos);
1349 		if (rc != NS_LDAP_SUCCESS) {
1350 			__s_cvt_freeEntryRdn(entry, rdn);
1351 			return (rc);
1352 		}
1353 	}
1354 
1355 	rc = __s_add_attr(e, "homeDirectory", ptr->pw_dir);
1356 	if (rc != NS_LDAP_SUCCESS) {
1357 		__s_cvt_freeEntryRdn(entry, rdn);
1358 		return (rc);
1359 	}
1360 	if (ptr->pw_shell != NULL &&
1361 		ptr->pw_shell[0] != '\0') {
1362 		rc = __s_add_attr(e, "loginShell", ptr->pw_shell);
1363 		if (rc != NS_LDAP_SUCCESS) {
1364 			__s_cvt_freeEntryRdn(entry, rdn);
1365 			return (rc);
1366 		}
1367 	}
1368 
1369 	return (NS_LDAP_SUCCESS);
1370 }
1371 
1372 /*
1373  * Conversion:			shadow
1374  * Input format:		struct shadow
1375  * Exported objectclass:	shadowAccount
1376  */
1377 static int
1378 __s_cvt_shadow(const void *data, char **rdn,
1379 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
1380 {
1381 	ns_ldap_entry_t	*e;
1382 	int		rc;
1383 	char		trdn[RDNSIZE];
1384 	/* routine specific */
1385 	struct spwd	*ptr;
1386 	int		max_attr = 10;
1387 	char		ibuf[10];
1388 	static		char *oclist[] = {
1389 			"posixAccount",
1390 			"shadowAccount",
1391 			"account",
1392 			"top",
1393 			NULL
1394 			};
1395 
1396 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
1397 		return (NS_LDAP_OP_FAILED);
1398 	*entry = e = __s_mk_entry(oclist, max_attr);
1399 	if (e == NULL)
1400 		return (NS_LDAP_MEMORY);
1401 
1402 	/* Convert the structure */
1403 	ptr = (struct spwd *)data;
1404 
1405 	if (ptr->sp_namp == NULL) {
1406 		__ns_ldap_freeEntry(e);
1407 		*entry = NULL;
1408 		return (NS_LDAP_INVALID_PARAM);
1409 	}
1410 
1411 	/* Create an appropriate rdn */
1412 	(void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->sp_namp);
1413 	*rdn = strdup(trdn);
1414 	if (*rdn == NULL) {
1415 		__ns_ldap_freeEntry(e);
1416 		*entry = NULL;
1417 		return (NS_LDAP_MEMORY);
1418 	}
1419 
1420 	/* Error check the data and add the attributes */
1421 	rc = __s_add_attr(e, "uid", ptr->sp_namp);
1422 	if (rc != NS_LDAP_SUCCESS) {
1423 		__s_cvt_freeEntryRdn(entry, rdn);
1424 		return (rc);
1425 	}
1426 
1427 	if (ptr->sp_pwdp == NULL) {
1428 		__s_cvt_freeEntryRdn(entry, rdn);
1429 		return (NS_LDAP_INVALID_PARAM);
1430 	} else {
1431 		rc = __s_add_attr(e, "userPassword", ptr->sp_pwdp);
1432 		if (rc != NS_LDAP_SUCCESS) {
1433 			__s_cvt_freeEntryRdn(entry, rdn);
1434 			return (rc);
1435 		}
1436 	}
1437 	if (ptr->sp_lstchg >= 0) {
1438 		(void) sprintf(ibuf, "%d", ptr->sp_lstchg);
1439 		rc = __s_add_attr(e, "shadowLastChange", ibuf);
1440 		if (rc != NS_LDAP_SUCCESS) {
1441 			__s_cvt_freeEntryRdn(entry, rdn);
1442 			return (rc);
1443 		}
1444 	}
1445 	if (ptr->sp_min >= 0) {
1446 		(void) sprintf(ibuf, "%d", ptr->sp_min);
1447 		rc = __s_add_attr(e, "shadowMin", ibuf);
1448 		if (rc != NS_LDAP_SUCCESS) {
1449 			__s_cvt_freeEntryRdn(entry, rdn);
1450 			return (rc);
1451 		}
1452 	}
1453 	if (ptr->sp_max >= 0) {
1454 		(void) sprintf(ibuf, "%d", ptr->sp_max);
1455 		rc = __s_add_attr(e, "shadowMax", ibuf);
1456 		if (rc != NS_LDAP_SUCCESS) {
1457 			__s_cvt_freeEntryRdn(entry, rdn);
1458 			return (rc);
1459 		}
1460 	}
1461 	if (ptr->sp_warn >= 0) {
1462 		(void) sprintf(ibuf, "%d", ptr->sp_warn);
1463 		rc = __s_add_attr(e, "shadowWarning", ibuf);
1464 		if (rc != NS_LDAP_SUCCESS) {
1465 			__s_cvt_freeEntryRdn(entry, rdn);
1466 			return (rc);
1467 		}
1468 	}
1469 	if (ptr->sp_inact >= 0) {
1470 		(void) sprintf(ibuf, "%d", ptr->sp_inact);
1471 		rc = __s_add_attr(e, "shadowInactive", ibuf);
1472 		if (rc != NS_LDAP_SUCCESS) {
1473 			__s_cvt_freeEntryRdn(entry, rdn);
1474 			return (rc);
1475 		}
1476 	}
1477 	if (ptr->sp_expire >= 0) {
1478 		(void) sprintf(ibuf, "%d", ptr->sp_expire);
1479 		rc = __s_add_attr(e, "shadowExpire", ibuf);
1480 		if (rc != NS_LDAP_SUCCESS) {
1481 			__s_cvt_freeEntryRdn(entry, rdn);
1482 			return (rc);
1483 		}
1484 	}
1485 	(void) sprintf(ibuf, "%d", ptr->sp_flag);
1486 	rc = __s_add_attr(e, "shadowFlag", ibuf);
1487 	if (rc != NS_LDAP_SUCCESS) {
1488 		__s_cvt_freeEntryRdn(entry, rdn);
1489 		return (rc);
1490 	}
1491 
1492 	return (NS_LDAP_SUCCESS);
1493 }
1494 
1495 
1496 /*
1497  * Conversion:			group
1498  * Input format:		struct group
1499  * Exported objectclass:	posixGroup
1500  */
1501 static int
1502 __s_cvt_group(const void *data, char **rdn,
1503 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
1504 {
1505 	ns_ldap_entry_t	*e;
1506 	int		rc;
1507 	char		trdn[RDNSIZE];
1508 	/* routine specific */
1509 	struct group	*ptr;
1510 	int		i, j, k;
1511 	char		**nm, **lm;
1512 	int		max_attr = 4;
1513 	char		ibuf[10];
1514 	static		char *oclist[] = {
1515 			"posixGroup",
1516 			"top",
1517 			NULL
1518 			};
1519 
1520 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
1521 		return (NS_LDAP_OP_FAILED);
1522 	*entry = e = __s_mk_entry(oclist, max_attr);
1523 	if (e == NULL)
1524 		return (NS_LDAP_MEMORY);
1525 
1526 	/* Convert the structure */
1527 	ptr = (struct group *)data;
1528 
1529 	if (ptr->gr_name == NULL || ptr->gr_gid < 0) {
1530 		__ns_ldap_freeEntry(e);
1531 		*entry = NULL;
1532 		return (NS_LDAP_INVALID_PARAM);
1533 	}
1534 
1535 	/* Create an appropriate rdn */
1536 	(void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->gr_name);
1537 	*rdn = strdup(trdn);
1538 	if (*rdn == NULL) {
1539 		__ns_ldap_freeEntry(e);
1540 		*entry = NULL;
1541 		return (NS_LDAP_MEMORY);
1542 	}
1543 
1544 	/* Error check the data and add the attributes */
1545 	rc = __s_add_attr(e, "cn", ptr->gr_name);
1546 	if (rc != NS_LDAP_SUCCESS) {
1547 		__s_cvt_freeEntryRdn(entry, rdn);
1548 		return (rc);
1549 	}
1550 
1551 #ifdef _LP64
1552 	(void) sprintf(ibuf, "%d", ptr->gr_gid);
1553 #else
1554 	(void) sprintf(ibuf, "%ld", ptr->gr_gid);
1555 #endif
1556 	rc = __s_add_attr(e, "gidNumber", ibuf);
1557 	if (rc != NS_LDAP_SUCCESS) {
1558 		__s_cvt_freeEntryRdn(entry, rdn);
1559 		return (rc);
1560 	}
1561 	if (ptr->gr_passwd && ptr->gr_passwd[0] != '\0') {
1562 		rc = __s_add_attr(e, "userPassword", ptr->gr_passwd);
1563 		if (rc != NS_LDAP_SUCCESS) {
1564 			__s_cvt_freeEntryRdn(entry, rdn);
1565 			return (rc);
1566 		}
1567 	}
1568 
1569 	if (ptr->gr_mem && ptr->gr_mem[0]) {
1570 		lm = ptr->gr_mem;
1571 		for (i = 0; *lm; i++, lm++)
1572 			;
1573 		lm = ptr->gr_mem;
1574 		nm = (char **)calloc(i+2, sizeof (char *));
1575 		if (nm == NULL) {
1576 			__s_cvt_freeEntryRdn(entry, rdn);
1577 			return (NS_LDAP_MEMORY);
1578 		}
1579 		for (j = 0; j < i; j++) {
1580 			nm[j] = strdup(lm[j]);
1581 			if (nm[j] == NULL) {
1582 				for (k = 0; k < j; k++)
1583 					free(nm[k]);
1584 				free(nm);
1585 				__s_cvt_freeEntryRdn(entry, rdn);
1586 				return (NS_LDAP_MEMORY);
1587 			}
1588 		}
1589 		rc = __s_add_attrlist(e, "memberUid", nm);
1590 		for (j = 0; j < i; j++) {
1591 			free(nm[j]);
1592 		}
1593 		free(nm);
1594 		nm = NULL;
1595 		if (rc != NS_LDAP_SUCCESS) {
1596 			__s_cvt_freeEntryRdn(entry, rdn);
1597 			return (rc);
1598 		}
1599 	}
1600 
1601 	return (NS_LDAP_SUCCESS);
1602 }
1603 
1604 /*
1605  * Conversion:			hosts
1606  * Input format:		struct hostent
1607  * Exported objectclass:	ipHost
1608  */
1609 static int
1610 __s_cvt_hosts(const void *data, char **rdn,
1611 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
1612 {
1613 	ns_ldap_entry_t	*e;
1614 	int		rc;
1615 	char		trdn[RDNSIZE];
1616 	/* routine specific */
1617 	struct hostent	*ptr;
1618 	int		max_attr = 6;
1619 	int		i, j, k;
1620 	char		**nm, **lm;
1621 	static		char *oclist[] = {
1622 			"ipHost",
1623 			"device",
1624 			"top",
1625 			NULL
1626 			};
1627 
1628 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
1629 		return (NS_LDAP_OP_FAILED);
1630 	*entry = e = __s_mk_entry(oclist, max_attr);
1631 	if (e == NULL)
1632 		return (NS_LDAP_MEMORY);
1633 
1634 	/* Convert the structure */
1635 	ptr = (struct hostent *)data;
1636 
1637 	if (ptr->h_name == NULL ||
1638 	    ptr->h_addr_list == NULL || ptr->h_addr_list[0] == '\0') {
1639 		__ns_ldap_freeEntry(e);
1640 		*entry = NULL;
1641 		return (NS_LDAP_INVALID_PARAM);
1642 	}
1643 
1644 	/* Create an appropriate rdn */
1645 	(void) snprintf(trdn, RDNSIZE, "cn=%s+ipHostNumber=%s",
1646 	    ptr->h_name, ptr->h_addr_list[0]);
1647 	*rdn = strdup(trdn);
1648 	if (*rdn == NULL) {
1649 		__ns_ldap_freeEntry(e);
1650 		*entry = NULL;
1651 		return (NS_LDAP_MEMORY);
1652 	}
1653 
1654 	/* Error check the data and add the attributes */
1655 	if (ptr->h_aliases && ptr->h_aliases[0]) {
1656 		lm = ptr->h_aliases;
1657 		for (i = 0; *lm; i++, lm++)
1658 			;
1659 		lm = ptr->h_aliases;
1660 		nm = (char **)calloc(i+2, sizeof (char *));
1661 		if (nm == NULL) {
1662 			__s_cvt_freeEntryRdn(entry, rdn);
1663 			return (NS_LDAP_MEMORY);
1664 		}
1665 		nm[0] = ptr->h_name;
1666 		for (j = 0; j < i; j++)
1667 			nm[j+1] = ptr->h_aliases[j];
1668 
1669 		rc = __s_add_attrlist(e, "cn", nm);
1670 		free(nm);
1671 		nm = NULL;
1672 		if (rc != NS_LDAP_SUCCESS) {
1673 			__s_cvt_freeEntryRdn(entry, rdn);
1674 			return (rc);
1675 		}
1676 	} else {
1677 		rc = __s_add_attr(e, "cn", ptr->h_name);
1678 		if (rc != NS_LDAP_SUCCESS) {
1679 			__s_cvt_freeEntryRdn(entry, rdn);
1680 			return (rc);
1681 		}
1682 	}
1683 
1684 	if (ptr->h_addr_list && ptr->h_addr_list[0]) {
1685 		lm = ptr->h_addr_list;
1686 		for (i = 0; *lm; i++, lm++)
1687 			;
1688 		lm = ptr->h_addr_list;
1689 		nm = (char **)calloc(i+2, sizeof (char *));
1690 		if (nm == NULL) {
1691 			__s_cvt_freeEntryRdn(entry, rdn);
1692 			return (NS_LDAP_MEMORY);
1693 		}
1694 		for (j = 0; j < i; j++) {
1695 			nm[j] = strdup(lm[j]);
1696 			if (nm[j] == NULL) {
1697 				for (k = 0; k < j; k++)
1698 					free(nm[k]);
1699 				free(nm);
1700 				__s_cvt_freeEntryRdn(entry, rdn);
1701 				return (NS_LDAP_MEMORY);
1702 			}
1703 		}
1704 		rc = __s_add_attrlist(e, "ipHostNumber", nm);
1705 		for (j = 0; j < i; j++) {
1706 			free(nm[j]);
1707 		}
1708 		free(nm);
1709 		nm = NULL;
1710 		if (rc != NS_LDAP_SUCCESS) {
1711 			__s_cvt_freeEntryRdn(entry, rdn);
1712 			return (rc);
1713 		}
1714 	} else {
1715 		__s_cvt_freeEntryRdn(entry, rdn);
1716 		return (NS_LDAP_INVALID_PARAM);
1717 	}
1718 
1719 	return (NS_LDAP_SUCCESS);
1720 }
1721 
1722 /*
1723  * Conversion:			rpc
1724  * Input format:		struct rpcent
1725  * Exported objectclass:	oncRpc
1726  */
1727 static int
1728 __s_cvt_rpc(const void *data, char **rdn,
1729 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
1730 {
1731 	ns_ldap_entry_t	*e;
1732 	int		rc;
1733 	char		trdn[RDNSIZE];
1734 	/* routine specific */
1735 	struct rpcent	*ptr;
1736 	int		max_attr = 3;
1737 	int		i, j;
1738 	char		**nm;
1739 	char		ibuf[10];
1740 	static		char *oclist[] = {
1741 			"oncRpc",
1742 			"top",
1743 			NULL
1744 			};
1745 
1746 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
1747 		return (NS_LDAP_OP_FAILED);
1748 	*entry = e = __s_mk_entry(oclist, max_attr);
1749 	if (e == NULL)
1750 		return (NS_LDAP_MEMORY);
1751 
1752 	/* Convert the structure */
1753 	ptr = (struct rpcent *)data;
1754 
1755 	if (ptr->r_name == NULL || ptr->r_number < 0) {
1756 		__ns_ldap_freeEntry(e);
1757 		*entry = NULL;
1758 		return (NS_LDAP_INVALID_PARAM);
1759 	}
1760 
1761 	/* Create an appropriate rdn */
1762 	(void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->r_name);
1763 	*rdn = strdup(trdn);
1764 	if (*rdn == NULL) {
1765 		__ns_ldap_freeEntry(e);
1766 		*entry = NULL;
1767 		return (NS_LDAP_MEMORY);
1768 	}
1769 
1770 	/* Error check the data and add the attributes */
1771 	if (ptr->r_aliases && ptr->r_aliases[0]) {
1772 		nm = ptr->r_aliases;
1773 		for (i = 0; *nm; i++, nm++)
1774 			;
1775 		nm = (char **)calloc(i+2, sizeof (char *));
1776 		if (nm == NULL) {
1777 			__s_cvt_freeEntryRdn(entry, rdn);
1778 			return (NS_LDAP_MEMORY);
1779 		}
1780 		nm[0] = ptr->r_name;
1781 		for (j = 0; j < i; j++)
1782 			nm[j+1] = ptr->r_aliases[j];
1783 
1784 		rc = __s_add_attrlist(e, "cn", nm);
1785 		free(nm);
1786 		nm = NULL;
1787 		if (rc != NS_LDAP_SUCCESS) {
1788 			__s_cvt_freeEntryRdn(entry, rdn);
1789 			return (rc);
1790 		}
1791 	} else {
1792 		rc = __s_add_attr(e, "cn", ptr->r_name);
1793 		if (rc != NS_LDAP_SUCCESS) {
1794 			__s_cvt_freeEntryRdn(entry, rdn);
1795 			return (rc);
1796 		}
1797 	}
1798 
1799 	if (ptr->r_number >= 0) {
1800 		(void) sprintf(ibuf, "%d", ptr->r_number);
1801 		rc = __s_add_attr(e, "oncRpcNumber", ibuf);
1802 		if (rc != NS_LDAP_SUCCESS) {
1803 			__s_cvt_freeEntryRdn(entry, rdn);
1804 			return (rc);
1805 		}
1806 	}
1807 
1808 	return (NS_LDAP_SUCCESS);
1809 
1810 }
1811 
1812 /*
1813  * Conversion:			protocols
1814  * Input format:		struct protoent
1815  * Exported objectclass:	ipProtocol
1816  */
1817 static int
1818 __s_cvt_protocols(const void *data, char **rdn,
1819 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
1820 {
1821 	ns_ldap_entry_t	*e;
1822 	int		rc;
1823 	char		trdn[RDNSIZE];
1824 	/* routine specific */
1825 	struct protoent	*ptr;
1826 	int		max_attr = 3;
1827 	int		i, j;
1828 	char		ibuf[10];
1829 	char		**nm;
1830 	static		char *oclist[] = {
1831 			"ipProtocol",
1832 			"top",
1833 			NULL
1834 			};
1835 
1836 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
1837 		return (NS_LDAP_OP_FAILED);
1838 	*entry = e = __s_mk_entry(oclist, max_attr);
1839 	if (e == NULL)
1840 		return (NS_LDAP_MEMORY);
1841 
1842 	/* Convert the structure */
1843 	ptr = (struct protoent *)data;
1844 
1845 	if (ptr->p_name == NULL || ptr->p_proto < 0) {
1846 		__ns_ldap_freeEntry(e);
1847 		*entry = NULL;
1848 		return (NS_LDAP_INVALID_PARAM);
1849 	}
1850 
1851 	/* Create an appropriate rdn */
1852 	(void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->p_name);
1853 	*rdn = strdup(trdn);
1854 	if (*rdn == NULL) {
1855 		__ns_ldap_freeEntry(e);
1856 		*entry = NULL;
1857 		return (NS_LDAP_MEMORY);
1858 	}
1859 
1860 	/* Error check the data and add the attributes */
1861 	if (ptr->p_aliases && ptr->p_aliases[0]) {
1862 		nm = ptr->p_aliases;
1863 		for (i = 0; *nm; i++, nm++)
1864 			;
1865 		nm = (char **)calloc(i+2, sizeof (char *));
1866 		if (nm == NULL) {
1867 			__s_cvt_freeEntryRdn(entry, rdn);
1868 			return (NS_LDAP_MEMORY);
1869 		}
1870 		nm[0] = ptr->p_name;
1871 		for (j = 0; j < i; j++)
1872 			nm[j+1] = ptr->p_aliases[j];
1873 
1874 		rc = __s_add_attrlist(e, "cn", nm);
1875 		free(nm);
1876 		nm = NULL;
1877 		if (rc != NS_LDAP_SUCCESS) {
1878 			__s_cvt_freeEntryRdn(entry, rdn);
1879 			return (rc);
1880 		}
1881 	} else {
1882 		rc = __s_add_attr(e, "cn", ptr->p_name);
1883 		if (rc != NS_LDAP_SUCCESS) {
1884 			__s_cvt_freeEntryRdn(entry, rdn);
1885 			return (rc);
1886 		}
1887 	}
1888 
1889 	(void) sprintf(ibuf, "%d", ptr->p_proto);
1890 	rc = __s_add_attr(e, "ipProtocolNumber", ibuf);
1891 	if (rc != NS_LDAP_SUCCESS) {
1892 		__s_cvt_freeEntryRdn(entry, rdn);
1893 		return (rc);
1894 	}
1895 
1896 	return (NS_LDAP_SUCCESS);
1897 
1898 }
1899 
1900 /*
1901  * Conversion:			services
1902  * Input format:		struct servent
1903  * Exported objectclass:	ipService
1904  */
1905 static int
1906 __s_cvt_services(const void *data, char **rdn,
1907 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
1908 {
1909 	ns_ldap_entry_t	*e;
1910 	int		rc;
1911 	char		trdn[RDNSIZE];
1912 	/* routine specific */
1913 	struct servent	*ptr;
1914 	int		max_attr = 4;
1915 	int		i, j;
1916 	char		ibuf[10];
1917 	char		**nm;
1918 	static		char *oclist[] = {
1919 			"ipService",
1920 			"top",
1921 			NULL
1922 			};
1923 
1924 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
1925 		return (NS_LDAP_OP_FAILED);
1926 	*entry = e = __s_mk_entry(oclist, max_attr);
1927 	if (e == NULL)
1928 		return (NS_LDAP_MEMORY);
1929 
1930 	/* Convert the structure */
1931 	ptr = (struct servent *)data;
1932 
1933 	if (ptr->s_name == NULL || ptr->s_port < 0 || ptr->s_proto == '\0') {
1934 		__ns_ldap_freeEntry(e);
1935 		*entry = NULL;
1936 		return (NS_LDAP_INVALID_PARAM);
1937 	}
1938 
1939 	/* Create an appropriate rdn */
1940 	(void) snprintf(trdn, RDNSIZE, "cn=%s+ipServiceProtocol=%s",
1941 				ptr->s_name, ptr->s_proto);
1942 	*rdn = strdup(trdn);
1943 	if (*rdn == NULL) {
1944 		__ns_ldap_freeEntry(e);
1945 		*entry = NULL;
1946 		return (NS_LDAP_MEMORY);
1947 	}
1948 
1949 	/* Error check the data and add the attributes */
1950 	if (ptr->s_aliases && ptr->s_aliases[0]) {
1951 		nm = ptr->s_aliases;
1952 		for (i = 0; *nm; i++, nm++)
1953 			;
1954 		nm = (char **)calloc(i+2, sizeof (char *));
1955 		if (nm == NULL) {
1956 			__s_cvt_freeEntryRdn(entry, rdn);
1957 			return (NS_LDAP_MEMORY);
1958 		}
1959 		nm[0] = ptr->s_name;
1960 		for (j = 0; j < i; j++)
1961 			nm[j+1] = ptr->s_aliases[j];
1962 
1963 		rc = __s_add_attrlist(e, "cn", nm);
1964 		free(nm);
1965 		nm = NULL;
1966 		if (rc != NS_LDAP_SUCCESS) {
1967 			__s_cvt_freeEntryRdn(entry, rdn);
1968 			return (rc);
1969 		}
1970 	} else {
1971 		rc = __s_add_attr(e, "cn", ptr->s_name);
1972 		if (rc != NS_LDAP_SUCCESS) {
1973 			__s_cvt_freeEntryRdn(entry, rdn);
1974 			return (rc);
1975 		}
1976 	}
1977 
1978 	(void) sprintf(ibuf, "%d", ptr->s_port);
1979 	rc = __s_add_attr(e, "ipServicePort", ibuf);
1980 	if (rc != NS_LDAP_SUCCESS) {
1981 		__s_cvt_freeEntryRdn(entry, rdn);
1982 		return (rc);
1983 	}
1984 	rc = __s_add_attr(e, "ipServiceProtocol", ptr->s_proto);
1985 	if (rc != NS_LDAP_SUCCESS) {
1986 		__s_cvt_freeEntryRdn(entry, rdn);
1987 		return (rc);
1988 	}
1989 
1990 	return (NS_LDAP_SUCCESS);
1991 }
1992 
1993 /*
1994  * Conversion:			networks
1995  * Input format:		struct netent
1996  * Exported objectclass:	ipNetwork
1997  */
1998 static int
1999 __s_cvt_networks(const void *data, char **rdn,
2000 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2001 {
2002 	ns_ldap_entry_t	*e;
2003 	int		rc;
2004 	char		trdn[RDNSIZE];
2005 	/* routine specific */
2006 	struct netent	*ptr;
2007 	int		max_attr = 4;
2008 	int		i, j;
2009 	char		cp[64];
2010 	char		**nm;
2011 	static		char *oclist[] = {
2012 			"ipNetwork",
2013 			"top",
2014 			NULL
2015 			};
2016 
2017 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2018 		return (NS_LDAP_OP_FAILED);
2019 	*entry = e = __s_mk_entry(oclist, max_attr);
2020 	if (e == NULL)
2021 		return (NS_LDAP_MEMORY);
2022 
2023 	/* Convert the structure */
2024 	ptr = (struct netent *)data;
2025 
2026 	if (ptr->n_name == NULL || ptr->n_net == 0) {
2027 		__ns_ldap_freeEntry(e);
2028 		*entry = NULL;
2029 		return (NS_LDAP_INVALID_PARAM);
2030 	}
2031 
2032 	(void) snprintf(cp, sizeof (cp), "%d.%d.%d.%d",
2033 			(ptr->n_net & 0xFF000000) >> 24,
2034 			(ptr->n_net & 0x00FF0000) >> 16,
2035 			(ptr->n_net & 0x0000FF00) >> 8,
2036 			(ptr->n_net & 0x000000FF));
2037 
2038 	/* Create an appropriate rdn */
2039 	(void) snprintf(trdn, RDNSIZE, "ipNetworkNumber=%s", cp);
2040 	*rdn = strdup(trdn);
2041 	if (*rdn == NULL) {
2042 		__ns_ldap_freeEntry(e);
2043 		*entry = NULL;
2044 		return (NS_LDAP_MEMORY);
2045 	}
2046 
2047 	/* Error check the data and add the attributes */
2048 	if (ptr->n_aliases && ptr->n_aliases[0]) {
2049 		nm = ptr->n_aliases;
2050 		for (i = 0; *nm; i++, nm++)
2051 			;
2052 		nm = (char **)calloc(i+2, sizeof (char *));
2053 		if (nm == NULL) {
2054 			__s_cvt_freeEntryRdn(entry, rdn);
2055 			return (NS_LDAP_MEMORY);
2056 		}
2057 		nm[0] = ptr->n_name;
2058 		for (j = 0; j < i; j++)
2059 			nm[j+1] = ptr->n_aliases[j];
2060 
2061 		rc = __s_add_attrlist(e, "cn", nm);
2062 		free(nm);
2063 		nm = NULL;
2064 		if (rc != NS_LDAP_SUCCESS) {
2065 			__s_cvt_freeEntryRdn(entry, rdn);
2066 			return (rc);
2067 		}
2068 	} else {
2069 		rc = __s_add_attr(e, "cn", ptr->n_name);
2070 		if (rc != NS_LDAP_SUCCESS) {
2071 			__s_cvt_freeEntryRdn(entry, rdn);
2072 			return (rc);
2073 		}
2074 	}
2075 
2076 	rc = __s_add_attr(e, "ipNetworkNumber", cp);
2077 	if (rc != NS_LDAP_SUCCESS) {
2078 		__s_cvt_freeEntryRdn(entry, rdn);
2079 		return (rc);
2080 	}
2081 
2082 	return (NS_LDAP_SUCCESS);
2083 
2084 }
2085 /*
2086  * Conversion:			netmasks
2087  * Input format:		struct _ns_netmasks
2088  * Exported objectclass:	ipNetwork
2089  */
2090 static int
2091 __s_cvt_netmasks(const void *data, char **rdn,
2092 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2093 {
2094 	ns_ldap_entry_t	*e;
2095 	int		rc;
2096 	char		trdn[RDNSIZE];
2097 	/* routine specific */
2098 	struct _ns_netmasks *ptr;
2099 	int		max_attr = 4;
2100 	static		char *oclist[] = {
2101 			"ipNetwork",
2102 			"top",
2103 			NULL
2104 			};
2105 
2106 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2107 		return (NS_LDAP_OP_FAILED);
2108 	*entry = e = __s_mk_entry(oclist, max_attr);
2109 	if (e == NULL)
2110 		return (NS_LDAP_MEMORY);
2111 
2112 	/* Convert the structure */
2113 	ptr = (struct _ns_netmasks *)data;
2114 
2115 	if (ptr->netnumber == NULL) {
2116 		__ns_ldap_freeEntry(e);
2117 		*entry = NULL;
2118 		return (NS_LDAP_INVALID_PARAM);
2119 	}
2120 
2121 	/* Create an appropriate rdn */
2122 	(void) snprintf(trdn, RDNSIZE, "ipNetworkNumber=%s", ptr->netnumber);
2123 	*rdn = strdup(trdn);
2124 	if (*rdn == NULL) {
2125 		__ns_ldap_freeEntry(e);
2126 		*entry = NULL;
2127 		return (NS_LDAP_MEMORY);
2128 	}
2129 
2130 	/* Error check the data and add the attributes */
2131 		rc = __s_add_attr(e, "ipNetworkNumber", ptr->netnumber);
2132 		if (rc != NS_LDAP_SUCCESS) {
2133 			__s_cvt_freeEntryRdn(entry, rdn);
2134 			return (rc);
2135 		}
2136 
2137 	if (ptr->netmask != '\0') {
2138 		rc = __s_add_attr(e, "ipNetmaskNumber", ptr->netmask);
2139 		if (rc != NS_LDAP_SUCCESS) {
2140 			__s_cvt_freeEntryRdn(entry, rdn);
2141 			return (rc);
2142 		}
2143 	}
2144 
2145 	return (NS_LDAP_SUCCESS);
2146 
2147 }
2148 /*
2149  * Conversion:			netgroups
2150  * Input format:		struct _ns_netgroups
2151  * Exported objectclass:	nisNetgroup
2152  */
2153 static int
2154 __s_cvt_netgroups(const void *data, char **rdn,
2155 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2156 {
2157 	ns_ldap_entry_t	*e;
2158 	int		rc;
2159 	char		trdn[RDNSIZE];
2160 	/* routine specific */
2161 	struct _ns_netgroups *ptr;
2162 	int		max_attr = 6;
2163 	int		i, j;
2164 	char		**nm;
2165 	static		char *oclist[] = {
2166 			"nisNetgroup",
2167 			"top",
2168 			NULL
2169 			};
2170 
2171 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2172 		return (NS_LDAP_OP_FAILED);
2173 	*entry = e = __s_mk_entry(oclist, max_attr);
2174 	if (e == NULL)
2175 		return (NS_LDAP_MEMORY);
2176 
2177 	/* Convert the structure */
2178 	ptr = (struct _ns_netgroups *)data;
2179 
2180 	if (ptr->name == NULL) {
2181 		__ns_ldap_freeEntry(e);
2182 		*entry = NULL;
2183 		return (NS_LDAP_INVALID_PARAM);
2184 	}
2185 
2186 	/* Create an appropriate rdn */
2187 	(void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
2188 	*rdn = strdup(trdn);
2189 	if (*rdn == NULL) {
2190 		__ns_ldap_freeEntry(e);
2191 		*entry = NULL;
2192 		return (NS_LDAP_MEMORY);
2193 	}
2194 
2195 	if (ptr->name != '\0') {
2196 		rc = __s_add_attr(e, "cn", ptr->name);
2197 		if (rc != NS_LDAP_SUCCESS) {
2198 			__s_cvt_freeEntryRdn(entry, rdn);
2199 			return (rc);
2200 		}
2201 	}
2202 
2203 	/* Error check the data and add the attributes */
2204 	if (ptr->triplet && ptr->triplet[0]) {
2205 		nm = ptr->triplet;
2206 		for (i = 0; *nm; i++, nm++)
2207 			;
2208 		nm = (char **)calloc(i+2, sizeof (char *));
2209 		if (nm == NULL) {
2210 			__s_cvt_freeEntryRdn(entry, rdn);
2211 			return (NS_LDAP_MEMORY);
2212 		}
2213 		for (j = 0; j < i; j++)
2214 			nm[j] = ptr->triplet[j];
2215 
2216 		rc = __s_add_attrlist(e, "nisNetgroupTriple", nm);
2217 		free(nm);
2218 		nm = NULL;
2219 		if (rc != NS_LDAP_SUCCESS) {
2220 			__s_cvt_freeEntryRdn(entry, rdn);
2221 			return (rc);
2222 		}
2223 	}
2224 	if (ptr->netgroup && ptr->netgroup[0]) {
2225 		nm = ptr->netgroup;
2226 		for (i = 0; *nm; i++, nm++)
2227 			;
2228 		nm = (char **)calloc(i+2, sizeof (char *));
2229 		if (nm == NULL) {
2230 			__s_cvt_freeEntryRdn(entry, rdn);
2231 			return (NS_LDAP_MEMORY);
2232 		}
2233 		for (j = 0; j < i; j++)
2234 			nm[j] = ptr->netgroup[j];
2235 
2236 		rc = __s_add_attrlist(e, "memberNisNetgroup", nm);
2237 		free(nm);
2238 		nm = NULL;
2239 		if (rc != NS_LDAP_SUCCESS) {
2240 			__s_cvt_freeEntryRdn(entry, rdn);
2241 			return (rc);
2242 		}
2243 	}
2244 	return (NS_LDAP_SUCCESS);
2245 }
2246 /*
2247  * Conversion:			bootparams
2248  * Input format:		struct _ns_bootp
2249  * Exported objectclass:	bootableDevice, device
2250  */
2251 static int
2252 __s_cvt_bootparams(const void *data, char **rdn,
2253 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2254 {
2255 	ns_ldap_entry_t	*e;
2256 	int		rc;
2257 	char		trdn[RDNSIZE];
2258 	/* routine specific */
2259 	struct _ns_bootp *ptr;
2260 	int		max_attr = 4;
2261 	int		i, j;
2262 	char		**nm;
2263 	static		char *oclist[] = {
2264 			"bootableDevice",
2265 			"device",
2266 			"top",
2267 			NULL
2268 			};
2269 
2270 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2271 		return (NS_LDAP_OP_FAILED);
2272 	*entry = e = __s_mk_entry(oclist, max_attr);
2273 	if (e == NULL)
2274 		return (NS_LDAP_MEMORY);
2275 
2276 	/* Convert the structure */
2277 	ptr = (struct _ns_bootp *)data;
2278 
2279 	if (ptr->name == NULL) {
2280 		__ns_ldap_freeEntry(e);
2281 		*entry = NULL;
2282 		return (NS_LDAP_INVALID_PARAM);
2283 	}
2284 
2285 	/* Create an appropriate rdn */
2286 	(void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
2287 	*rdn = strdup(trdn);
2288 	if (*rdn == NULL) {
2289 		__ns_ldap_freeEntry(e);
2290 		*entry = NULL;
2291 		return (NS_LDAP_MEMORY);
2292 	}
2293 
2294 	if (ptr->name != '\0') {
2295 		rc = __s_add_attr(e, "cn", ptr->name);
2296 		if (rc != NS_LDAP_SUCCESS) {
2297 			__s_cvt_freeEntryRdn(entry, rdn);
2298 			return (rc);
2299 		}
2300 	}
2301 
2302 	/* Error check the data and add the attributes */
2303 	if (ptr->param && ptr->param[0]) {
2304 		nm = ptr->param;
2305 		for (i = 0; *nm; i++, nm++)
2306 			;
2307 		nm = (char **)calloc(i+2, sizeof (char *));
2308 		if (nm == NULL) {
2309 			__s_cvt_freeEntryRdn(entry, rdn);
2310 			return (NS_LDAP_MEMORY);
2311 		}
2312 		for (j = 0; j < i; j++)
2313 			nm[j] = ptr->param[j];
2314 
2315 		rc = __s_add_attrlist(e, "bootParameter", nm);
2316 		free(nm);
2317 		nm = NULL;
2318 		if (rc != NS_LDAP_SUCCESS) {
2319 			__s_cvt_freeEntryRdn(entry, rdn);
2320 			return (rc);
2321 		}
2322 	}
2323 
2324 	return (NS_LDAP_SUCCESS);
2325 
2326 }
2327 /*
2328  * Conversion:			ethers
2329  * Input format:		struct _ns_ethers
2330  * Exported objectclass:	ieee802Device, device
2331  */
2332 static int
2333 __s_cvt_ethers(const void *data, char **rdn,
2334 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2335 {
2336 	ns_ldap_entry_t	*e;
2337 	int		rc;
2338 	char		trdn[RDNSIZE];
2339 	/* routine specific */
2340 	struct _ns_ethers	*ptr;
2341 	int		max_attr = 4;
2342 	static		char *oclist[] = {
2343 			"ieee802Device",
2344 			"device",
2345 			"top",
2346 			NULL
2347 			};
2348 
2349 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2350 		return (NS_LDAP_OP_FAILED);
2351 	*entry = e = __s_mk_entry(oclist, max_attr);
2352 	if (e == NULL)
2353 		return (NS_LDAP_MEMORY);
2354 
2355 	/* Convert the structure */
2356 	ptr = (struct _ns_ethers *)data;
2357 
2358 	if (ptr->name == NULL || ptr->ether == '\0') {
2359 		__ns_ldap_freeEntry(e);
2360 		*entry = NULL;
2361 		return (NS_LDAP_INVALID_PARAM);
2362 	}
2363 
2364 	/* Create an appropriate rdn */
2365 	(void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
2366 	*rdn = strdup(trdn);
2367 	if (*rdn == NULL) {
2368 		__ns_ldap_freeEntry(e);
2369 		*entry = NULL;
2370 		return (NS_LDAP_MEMORY);
2371 	}
2372 
2373 	/* Error check the data and add the attributes */
2374 	rc = __s_add_attr(e, "cn", ptr->name);
2375 	if (rc != NS_LDAP_SUCCESS) {
2376 		__s_cvt_freeEntryRdn(entry, rdn);
2377 		return (rc);
2378 	}
2379 
2380 	rc = __s_add_attr(e, "macAddress", ptr->ether);
2381 	if (rc != NS_LDAP_SUCCESS) {
2382 		__s_cvt_freeEntryRdn(entry, rdn);
2383 		return (rc);
2384 	}
2385 
2386 	return (NS_LDAP_SUCCESS);
2387 }
2388 /*
2389  * This function is used when processing an ethers (objectclass: ieee802Device)
2390  * or a bootparams (objectclass: bootableDevice) entry, and the entry is
2391  * already found in LDAP. Since both ethers and bootparams share the same
2392  * LDAP container, we want to check that the entry found in LDAP is:
2393  * - either the same entry (same cn, same objectclass): we don't do anything
2394  *   in this case
2395  * - or an entry which does not have the objectclass we are interesting in:
2396  *   in this case, we modify the existing entry by adding the relevant
2397  *   objectclass (ieee802Device or bootableDevice) and the relevant attribute(s)
2398  *   from the attribute list previously computing by the relevant conversion
2399  *   function.
2400  *   Note: from conversion functions __s_cvt_ethers() and  __s_cvt_bootparams()
2401  *   we know that there is only 1 more attribute today to add (macAddress
2402  *   or bootParameter)
2403  */
2404 #define	_MAX_ATTR_ETHBOOTP	2
2405 static int
2406 modify_ethers_bootp(
2407 	const char *service,
2408 	const char *rdn,
2409 	const char *fulldn,
2410 	const ns_ldap_attr_t * const *attrlist,
2411 	const ns_cred_t *cred,
2412 	const int flags,
2413 	ns_ldap_error_t	 **errorp)
2414 {
2415 	char	filter[BUFSIZ];
2416 	ns_ldap_result_t *resultp;
2417 	int rc = 0;
2418 	int i;
2419 	ns_ldap_attr_t *new_attrlist[_MAX_ATTR_ETHBOOTP+1];
2420 	ns_ldap_attr_t new_attrlist0;
2421 	char *new_attrvalue0[1];
2422 	const ns_ldap_attr_t	* const *aptr = attrlist;
2423 	ns_ldap_attr_t *aptr2;
2424 	ns_ldap_error_t	 *new_errorp = NULL;
2425 
2426 	if (rdn == NULL || fulldn == NULL || attrlist == NULL ||
2427 		errorp == NULL || service == NULL)
2428 		return (NS_LDAP_OP_FAILED);
2429 
2430 	bzero(&new_attrlist, sizeof (new_attrlist));
2431 	bzero(&new_attrlist0, sizeof (new_attrlist0));
2432 	new_attrlist[0] = &new_attrlist0;
2433 	new_attrlist[0]->attrvalue = new_attrvalue0;
2434 
2435 	new_attrlist[0]->attrname = "objectclass";
2436 	new_attrlist[0]->value_count = 1;
2437 	if (strcasecmp(service, "ethers") == NULL) {
2438 		(void) snprintf(&filter[0], sizeof (filter),
2439 			"(&(objectClass=ieee802Device)(%s))",
2440 			rdn);
2441 		new_attrlist[0]->attrvalue[0] = "ieee802Device";
2442 	} else {
2443 		(void) snprintf(&filter[0], sizeof (filter),
2444 			"(&(objectClass=bootableDevice)(%s))",
2445 			rdn);
2446 		new_attrlist[0]->attrvalue[0] = "bootableDevice";
2447 	}
2448 
2449 	rc =  __ns_ldap_list(service, filter, NULL, (const char **)NULL,
2450 		NULL, NS_LDAP_SCOPE_SUBTREE, &resultp, &new_errorp,
2451 		NULL, NULL);
2452 
2453 	switch (rc) {
2454 	case NS_LDAP_SUCCESS:
2455 		/*
2456 		 * entry already exists for this service
2457 		 * return NS_LDAP_INTERNAL and do not modify the incoming errorp
2458 		 */
2459 		rc = NS_LDAP_INTERNAL;
2460 		break;
2461 	case NS_LDAP_NOTFOUND:
2462 		/*
2463 		 * entry not found with the given objectclasss but entry exists
2464 		 * hence add the relevant attribute (macAddress or bootparams).
2465 		 */
2466 		i = 1;
2467 		while (*aptr && (i < _MAX_ATTR_ETHBOOTP)) {
2468 			/* aptr2 needed here to avoid lint warning */
2469 			aptr2 = (ns_ldap_attr_t *)*aptr++;
2470 			if ((strcasecmp(aptr2->attrname, "cn") != 0) &&
2471 				(strcasecmp(aptr2->attrname,
2472 					"objectclass") != 0)) {
2473 				    new_attrlist[i++] =	(ns_ldap_attr_t *)aptr2;
2474 			}
2475 		}
2476 
2477 		if (i != _MAX_ATTR_ETHBOOTP) {
2478 			/* we haven't found all expected attributes */
2479 			rc = NS_LDAP_OP_FAILED;
2480 			break;
2481 		}
2482 
2483 		aptr = (const ns_ldap_attr_t	* const *) new_attrlist;
2484 		/* clean errorp first */
2485 		(void) __ns_ldap_freeError(errorp);
2486 		rc =  __ns_ldap_addAttr(service, fulldn, aptr, cred, flags,
2487 			errorp);
2488 		break;
2489 	default:
2490 		/*
2491 		 * unexpected error happenned
2492 		 * returning relevant error
2493 		 */
2494 		(void) __ns_ldap_freeError(errorp);
2495 		*errorp = new_errorp;
2496 		break;
2497 	}
2498 
2499 	return (rc);
2500 }
2501 
2502 /*
2503  * Conversion:			publickey
2504  * Input format:		struct _ns_pubkey
2505  * Exported objectclass:	NisKeyObject
2506  */
2507 static int
2508 __s_cvt_publickey(const void *data, char **rdn,
2509 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2510 {
2511 	ns_ldap_entry_t	*e;
2512 	int		rc;
2513 	char		trdn[RDNSIZE];
2514 	/* routine specific */
2515 	struct _ns_pubkey	*ptr;
2516 	int		max_attr = 3;
2517 	static		char *oclist[] = {
2518 			"NisKeyObject",
2519 			NULL
2520 			};
2521 
2522 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2523 		return (NS_LDAP_OP_FAILED);
2524 	*entry = e = __s_mk_entry(oclist, max_attr);
2525 	if (e == NULL)
2526 		return (NS_LDAP_MEMORY);
2527 
2528 	/* Convert the structure */
2529 	ptr = (struct _ns_pubkey *)data;
2530 
2531 	if (ptr->name == NULL || ptr->pubkey == '\0' || ptr->privkey == '\0') {
2532 		__ns_ldap_freeEntry(e);
2533 		*entry = NULL;
2534 		return (NS_LDAP_INVALID_PARAM);
2535 	}
2536 
2537 	/* Create an appropriate rdn */
2538 	if (ptr->hostcred == NS_HOSTCRED_FALSE)
2539 		(void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->name);
2540 	else
2541 		(void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
2542 	*rdn = strdup(trdn);
2543 	if (*rdn == NULL) {
2544 		__ns_ldap_freeEntry(e);
2545 		*entry = NULL;
2546 		return (NS_LDAP_MEMORY);
2547 	}
2548 
2549 	/* Error check the data and add the attributes */
2550 
2551 	rc = __s_add_attr(e, "nisPublickey", ptr->pubkey);
2552 	if (rc != NS_LDAP_SUCCESS) {
2553 		__s_cvt_freeEntryRdn(entry, rdn);
2554 		return (rc);
2555 	}
2556 
2557 	rc = __s_add_attr(e, "nisSecretkey", ptr->privkey);
2558 	if (rc != NS_LDAP_SUCCESS) {
2559 		__s_cvt_freeEntryRdn(entry, rdn);
2560 		return (rc);
2561 	}
2562 
2563 	return (NS_LDAP_SUCCESS);
2564 }
2565 /*
2566  * Conversion:			aliases
2567  * Input format:		struct _ns_alias
2568  * Exported objectclass:	mailGroup
2569  */
2570 static int
2571 __s_cvt_aliases(const void *data, char **rdn,
2572 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2573 {
2574 	ns_ldap_entry_t	*e;
2575 	int		rc;
2576 	char		trdn[RDNSIZE];
2577 	/* routine specific */
2578 	struct _ns_alias *ptr;
2579 	int		max_attr = 4;
2580 	int		i, j;
2581 	char		**nm;
2582 	static		char *oclist[] = {
2583 			"mailGroup",
2584 			"top",
2585 			NULL
2586 			};
2587 
2588 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2589 		return (NS_LDAP_OP_FAILED);
2590 	*entry = e = __s_mk_entry(oclist, max_attr);
2591 	if (e == NULL)
2592 		return (NS_LDAP_MEMORY);
2593 
2594 	/* Convert the structure */
2595 	ptr = (struct _ns_alias *)data;
2596 
2597 	if (ptr->alias == NULL) {
2598 		__ns_ldap_freeEntry(e);
2599 		*entry = NULL;
2600 		return (NS_LDAP_INVALID_PARAM);
2601 	}
2602 
2603 	/* Create an appropriate rdn */
2604 	(void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->alias);
2605 	*rdn = strdup(trdn);
2606 	if (*rdn == NULL) {
2607 		__ns_ldap_freeEntry(e);
2608 		*entry = NULL;
2609 		return (NS_LDAP_MEMORY);
2610 	}
2611 
2612 	if (ptr->alias != '\0') {
2613 		rc = __s_add_attr(e, "mail", (char *)ptr->alias);
2614 		if (rc != NS_LDAP_SUCCESS) {
2615 			__s_cvt_freeEntryRdn(entry, rdn);
2616 			return (rc);
2617 		}
2618 	}
2619 
2620 	/* Error check the data and add the attributes */
2621 	if (ptr->member && ptr->member[0]) {
2622 		nm = ptr->member;
2623 		for (i = 0; *nm; i++, nm++)
2624 			;
2625 		nm = (char **)calloc(i+2, sizeof (char *));
2626 		if (nm == NULL) {
2627 			__s_cvt_freeEntryRdn(entry, rdn);
2628 			return (NS_LDAP_MEMORY);
2629 		}
2630 		for (j = 0; j < i; j++)
2631 			nm[j] = ptr->member[j];
2632 
2633 		rc = __s_add_attrlist(e, "mgrpRFC822MailMember", nm);
2634 		free(nm);
2635 		nm = NULL;
2636 		if (rc != NS_LDAP_SUCCESS) {
2637 			__s_cvt_freeEntryRdn(entry, rdn);
2638 			return (rc);
2639 		}
2640 	}
2641 
2642 	return (NS_LDAP_SUCCESS);
2643 
2644 }
2645 /*
2646  * Conversion:			automount
2647  * Input format:		struct _ns_automount
2648  * Exported objectclass:	automount
2649  */
2650 static int
2651 __s_cvt_auto_mount(const void *data, char **rdn,
2652 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2653 {
2654 	ns_ldap_entry_t	*e;
2655 	int		rc;
2656 	char		trdn[RDNSIZE];
2657 	/* routine specific */
2658 	struct _ns_automount *ptr;
2659 	int		max_attr = 6;
2660 	void		**paramVal = NULL;
2661 	char		**mappedschema = NULL;
2662 	int		version1 = 0;
2663 	static		char *oclist[] = {
2664 			NULL,
2665 			"top",
2666 			NULL
2667 			};
2668 
2669 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2670 		return (NS_LDAP_OP_FAILED);
2671 
2672 	/* determine profile version number */
2673 	rc = __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P, &paramVal, errorp);
2674 	if (paramVal && *paramVal &&
2675 		strcasecmp(*paramVal, NS_LDAP_VERSION_1) == 0)
2676 		version1 = 1;
2677 	if (paramVal)
2678 		(void) __ns_ldap_freeParam(&paramVal);
2679 	if (rc && errorp)
2680 		(void) __ns_ldap_freeError(errorp);
2681 
2682 	/* use old schema for version 1 profiles */
2683 	if (version1)
2684 		oclist[0] = "nisObject";
2685 	else
2686 		oclist[0] = "automount";
2687 
2688 	*entry = e = __s_mk_entry(oclist, max_attr);
2689 	if (e == NULL)
2690 		return (NS_LDAP_MEMORY);
2691 
2692 	/* Convert the structure */
2693 	ptr = (struct _ns_automount *)data;
2694 
2695 	if (ptr->key == NULL || ptr->value == '\0' || ptr->mapname == '\0') {
2696 		__ns_ldap_freeEntry(e);
2697 		*entry = NULL;
2698 		return (NS_LDAP_INVALID_PARAM);
2699 	}
2700 
2701 	/* Create an appropriate rdn */
2702 	(void) snprintf(trdn, RDNSIZE, version1 ? "cn=%s" : "automountKey=%s",
2703 		ptr->key);
2704 	*rdn = strdup(trdn);
2705 	if (*rdn == NULL) {
2706 		__ns_ldap_freeEntry(e);
2707 		*entry = NULL;
2708 		return (NS_LDAP_MEMORY);
2709 	}
2710 
2711 	if (ptr->key != '\0') {
2712 		rc = __s_add_attr(e, version1 ? "cn" : "automountKey",
2713 		(char *)ptr->key);
2714 		if (rc != NS_LDAP_SUCCESS) {
2715 			__s_cvt_freeEntryRdn(entry, rdn);
2716 			return (rc);
2717 		}
2718 	}
2719 
2720 	rc = __s_add_attr(e, version1 ? "nisMapEntry" : "automountInformation",
2721 		(char *)ptr->value);
2722 	if (rc != NS_LDAP_SUCCESS) {
2723 		__s_cvt_freeEntryRdn(entry, rdn);
2724 		return (rc);
2725 	}
2726 
2727 	/*
2728 	 * even for version 2, if automount is mapped to nisObject we
2729 	 * still need 'nisMapName' attribute
2730 	 */
2731 	mappedschema = __ns_ldap_getMappedObjectClass("automount", "automount");
2732 	if (mappedschema && mappedschema[0] &&
2733 		strcasecmp(mappedschema[0], "nisObject") == 0)
2734 		version1 = 1;
2735 	if (mappedschema)
2736 		__s_api_free2dArray(mappedschema);
2737 
2738 	if (version1) {
2739 		rc = __s_add_attr(e, "nisMapName", (char *)ptr->mapname);
2740 		if (rc != NS_LDAP_SUCCESS) {
2741 			__s_cvt_freeEntryRdn(entry, rdn);
2742 			return (rc);
2743 		}
2744 	}
2745 
2746 	return (NS_LDAP_SUCCESS);
2747 }
2748 /*
2749  * Conversion:			auth_attr
2750  * Input format:		authstr_t
2751  * Exported objectclass:	SolarisAuthAttr
2752  */
2753 static int
2754 __s_cvt_authattr(const void *data, char **rdn,
2755 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2756 {
2757 	ns_ldap_entry_t	*e;
2758 	int		rc;
2759 	char		trdn[RDNSIZE];
2760 	/* routine specific */
2761 	authstr_t	*ptr;
2762 	int		max_attr = 6;
2763 	static		char *oclist[] = {
2764 			"SolarisAuthAttr",
2765 			"top",
2766 			NULL
2767 			};
2768 
2769 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2770 		return (NS_LDAP_OP_FAILED);
2771 
2772 	*entry = e = __s_mk_entry(oclist, max_attr);
2773 	if (e == NULL)
2774 		return (NS_LDAP_MEMORY);
2775 
2776 	/* Convert the structure */
2777 	ptr = (authstr_t *)data;
2778 
2779 	if (ptr->name == NULL || ptr->name[0] == '\0' || ptr->attr == NULL) {
2780 		__ns_ldap_freeEntry(e);
2781 		*entry = NULL;
2782 		return (NS_LDAP_INVALID_PARAM);
2783 	}
2784 
2785 	/* Create an appropriate rdn */
2786 	(void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
2787 	*rdn = strdup(trdn);
2788 	if (*rdn == NULL) {
2789 		__ns_ldap_freeEntry(e);
2790 		*entry = NULL;
2791 		return (NS_LDAP_MEMORY);
2792 	}
2793 
2794 	rc = __s_add_attr(e, "cn", ptr->name);
2795 	if (rc != NS_LDAP_SUCCESS) {
2796 		__s_cvt_freeEntryRdn(entry, rdn);
2797 		return (rc);
2798 	}
2799 
2800 	rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr);
2801 	if (rc != NS_LDAP_SUCCESS) {
2802 		__s_cvt_freeEntryRdn(entry, rdn);
2803 		return (rc);
2804 	}
2805 
2806 	if (ptr->res1 != NULL) {
2807 		rc = __s_add_attr(e, "SolarisAttrReserved1", ptr->res1);
2808 		if (rc != NS_LDAP_SUCCESS) {
2809 			__s_cvt_freeEntryRdn(entry, rdn);
2810 			return (rc);
2811 		}
2812 	}
2813 
2814 	if (ptr->res2 != NULL) {
2815 		rc = __s_add_attr(e, "SolarisAttrReserved2", ptr->res2);
2816 		if (rc != NS_LDAP_SUCCESS) {
2817 			__s_cvt_freeEntryRdn(entry, rdn);
2818 			return (rc);
2819 		}
2820 	}
2821 
2822 	if (ptr->short_desc != NULL) {
2823 		rc = __s_add_attr(e, "SolarisAttrShortDesc", ptr->short_desc);
2824 		if (rc != NS_LDAP_SUCCESS) {
2825 			__s_cvt_freeEntryRdn(entry, rdn);
2826 			return (rc);
2827 		}
2828 	}
2829 
2830 	if (ptr->long_desc != NULL) {
2831 		rc = __s_add_attr(e, "SolarisAttrLongDesc", ptr->long_desc);
2832 		if (rc != NS_LDAP_SUCCESS) {
2833 			__s_cvt_freeEntryRdn(entry, rdn);
2834 			return (rc);
2835 		}
2836 	}
2837 
2838 	return (NS_LDAP_SUCCESS);
2839 }
2840 /*
2841  * Conversion:			exec_attr
2842  * Input format:		execstr_t
2843  * Exported objectclass:	SolarisExecAttr
2844  */
2845 static int
2846 __s_cvt_execattr(const void *data, char **rdn,
2847 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2848 {
2849 	ns_ldap_entry_t	*e;
2850 	int		rc;
2851 	char		trdn[RDNSIZE];
2852 	/* routine specific */
2853 	execstr_t	*ptr;
2854 	int		max_attr = 7;
2855 	static		char *oclist[] = {
2856 			"SolarisExecAttr",
2857 			"SolarisProfAttr",
2858 			"top",
2859 			NULL
2860 			};
2861 
2862 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2863 		return (NS_LDAP_OP_FAILED);
2864 
2865 	*entry = e = __s_mk_entry(oclist, max_attr);
2866 	if (e == NULL)
2867 		return (NS_LDAP_MEMORY);
2868 
2869 	/* Convert the structure */
2870 	ptr = (execstr_t *)data;
2871 
2872 	if (ptr->name == NULL || ptr->name[0] == '\0' ||
2873 	    ptr->policy == NULL || ptr->policy[0] == '\0' ||
2874 	    ptr->type == NULL || ptr->type[0] == '\0' ||
2875 	    ptr->id == NULL || ptr->id[0] == '\0') {
2876 		__ns_ldap_freeEntry(e);
2877 		*entry = NULL;
2878 		return (NS_LDAP_INVALID_PARAM);
2879 	}
2880 
2881 	/* Create an appropriate rdn */
2882 	(void) snprintf(trdn, RDNSIZE, "cn=%s+SolarisKernelSecurityPolicy=%s"
2883 	    "+SolarisProfileType=%s+SolarisProfileId=%s",
2884 	    ptr->name, ptr->policy, ptr->type, ptr->id);
2885 	*rdn = strdup(trdn);
2886 	if (*rdn == NULL) {
2887 		__ns_ldap_freeEntry(e);
2888 		*entry = NULL;
2889 		return (NS_LDAP_MEMORY);
2890 	}
2891 
2892 	rc = __s_add_attr(e, "cn", ptr->name);
2893 	if (rc != NS_LDAP_SUCCESS) {
2894 		__s_cvt_freeEntryRdn(entry, rdn);
2895 		return (rc);
2896 	}
2897 
2898 	rc = __s_add_attr(e, "SolarisKernelSecurityPolicy", ptr->policy);
2899 	if (rc != NS_LDAP_SUCCESS) {
2900 		__s_cvt_freeEntryRdn(entry, rdn);
2901 		return (rc);
2902 	}
2903 
2904 	rc = __s_add_attr(e, "SolarisProfileType", ptr->type);
2905 	if (rc != NS_LDAP_SUCCESS) {
2906 		__s_cvt_freeEntryRdn(entry, rdn);
2907 		return (rc);
2908 	}
2909 
2910 	rc = __s_add_attr(e, "SolarisProfileId", ptr->id);
2911 	if (rc != NS_LDAP_SUCCESS) {
2912 		__s_cvt_freeEntryRdn(entry, rdn);
2913 		return (rc);
2914 	}
2915 
2916 	rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr);
2917 	if (rc != NS_LDAP_SUCCESS) {
2918 		__s_cvt_freeEntryRdn(entry, rdn);
2919 		return (rc);
2920 	}
2921 
2922 	if (ptr->res1 != NULL) {
2923 		rc = __s_add_attr(e, "SolarisAttrRes1", ptr->res1);
2924 		if (rc != NS_LDAP_SUCCESS) {
2925 			__s_cvt_freeEntryRdn(entry, rdn);
2926 			return (rc);
2927 		}
2928 	}
2929 
2930 	if (ptr->res2 != NULL) {
2931 		rc = __s_add_attr(e, "SolarisAttrRes2", ptr->res2);
2932 		if (rc != NS_LDAP_SUCCESS) {
2933 			__s_cvt_freeEntryRdn(entry, rdn);
2934 			return (rc);
2935 		}
2936 	}
2937 
2938 	return (NS_LDAP_SUCCESS);
2939 }
2940 /*
2941  * Conversion:			prof_attr
2942  * Input format:		profstr_t
2943  * Exported objectclass:	SolarisProfAttr
2944  */
2945 static int
2946 __s_cvt_profattr(const void *data, char **rdn,
2947 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2948 {
2949 	ns_ldap_entry_t	*e;
2950 	int		rc;
2951 	char		trdn[RDNSIZE];
2952 	/* routine specific */
2953 	profstr_t	*ptr;
2954 	int		max_attr = 5;
2955 	static		char *oclist[] = {
2956 			"SolarisProfAttr",
2957 			"top",
2958 			NULL
2959 			};
2960 
2961 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2962 		return (NS_LDAP_OP_FAILED);
2963 
2964 	*entry = e = __s_mk_entry(oclist, max_attr);
2965 	if (e == NULL)
2966 		return (NS_LDAP_MEMORY);
2967 
2968 	/* Convert the structure */
2969 	ptr = (profstr_t *)data;
2970 
2971 	if (ptr->name == NULL || ptr->name[0] == '\0' || ptr->attr == NULL) {
2972 		__ns_ldap_freeEntry(e);
2973 		*entry = NULL;
2974 		return (NS_LDAP_INVALID_PARAM);
2975 	}
2976 
2977 	/* Create an appropriate rdn */
2978 	(void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
2979 	*rdn = strdup(trdn);
2980 	if (*rdn == NULL) {
2981 		__ns_ldap_freeEntry(e);
2982 		*entry = NULL;
2983 		return (NS_LDAP_MEMORY);
2984 	}
2985 
2986 	rc = __s_add_attr(e, "cn", ptr->name);
2987 	if (rc != NS_LDAP_SUCCESS) {
2988 		__s_cvt_freeEntryRdn(entry, rdn);
2989 		return (rc);
2990 	}
2991 
2992 	rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr);
2993 	if (rc != NS_LDAP_SUCCESS) {
2994 		__s_cvt_freeEntryRdn(entry, rdn);
2995 		return (rc);
2996 	}
2997 
2998 	if (ptr->res1 != NULL) {
2999 		rc = __s_add_attr(e, "SolarisAttrReserved1", ptr->res1);
3000 		if (rc != NS_LDAP_SUCCESS) {
3001 			__s_cvt_freeEntryRdn(entry, rdn);
3002 			return (rc);
3003 		}
3004 	}
3005 
3006 	if (ptr->res2 != NULL) {
3007 		rc = __s_add_attr(e, "SolarisAttrReserved2", ptr->res2);
3008 		if (rc != NS_LDAP_SUCCESS) {
3009 			__s_cvt_freeEntryRdn(entry, rdn);
3010 			return (rc);
3011 		}
3012 	}
3013 
3014 	if (ptr->desc != NULL) {
3015 		rc = __s_add_attr(e, "SolarisAttrLongDesc", ptr->desc);
3016 		if (rc != NS_LDAP_SUCCESS) {
3017 			__s_cvt_freeEntryRdn(entry, rdn);
3018 			return (rc);
3019 		}
3020 	}
3021 
3022 	return (NS_LDAP_SUCCESS);
3023 }
3024 /*
3025  * Conversion:			user_attr
3026  * Input format:		userstr_t
3027  * Exported objectclass:	SolarisUserAttr
3028  */
3029 static int
3030 __s_cvt_userattr(const void *data, char **rdn,
3031 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3032 {
3033 	ns_ldap_entry_t	*e;
3034 	int		rc;
3035 	char		trdn[RDNSIZE];
3036 	/* routine specific */
3037 	userstr_t	*ptr;
3038 	int		max_attr = 5;
3039 	static		char *oclist[] = {
3040 			"SolarisUserAttr",
3041 			NULL
3042 			};
3043 
3044 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3045 		return (NS_LDAP_OP_FAILED);
3046 
3047 	*entry = e = __s_mk_entry(oclist, max_attr);
3048 	if (e == NULL)
3049 		return (NS_LDAP_MEMORY);
3050 
3051 	/* Convert the structure */
3052 	ptr = (userstr_t *)data;
3053 
3054 	if (ptr->name == NULL || ptr->name[0] == '\0' ||
3055 	    ptr->attr == NULL) {
3056 		__ns_ldap_freeEntry(e);
3057 		*entry = NULL;
3058 		return (NS_LDAP_INVALID_PARAM);
3059 	}
3060 
3061 	/* Create an appropriate rdn */
3062 	(void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->name);
3063 	*rdn = strdup(trdn);
3064 	if (*rdn == NULL) {
3065 		__ns_ldap_freeEntry(e);
3066 		*entry = NULL;
3067 		return (NS_LDAP_MEMORY);
3068 	}
3069 
3070 	/*
3071 	 * SolarisUserAttr has no uid attribute
3072 	 */
3073 
3074 	rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr);
3075 	if (rc != NS_LDAP_SUCCESS) {
3076 		__s_cvt_freeEntryRdn(entry, rdn);
3077 		return (rc);
3078 	}
3079 
3080 	if (ptr->qualifier != NULL) {
3081 		rc = __s_add_attr(e, "SolarisUserQualifier", ptr->qualifier);
3082 		if (rc != NS_LDAP_SUCCESS) {
3083 			__s_cvt_freeEntryRdn(entry, rdn);
3084 			return (rc);
3085 		}
3086 	}
3087 
3088 	if (ptr->res1 != NULL) {
3089 		rc = __s_add_attr(e, "SolarisAttrReserved1", ptr->res1);
3090 		if (rc != NS_LDAP_SUCCESS) {
3091 			__s_cvt_freeEntryRdn(entry, rdn);
3092 			return (rc);
3093 		}
3094 	}
3095 
3096 	if (ptr->res2 != NULL) {
3097 		rc = __s_add_attr(e, "SolarisAttrReserved2", ptr->res2);
3098 		if (rc != NS_LDAP_SUCCESS) {
3099 			__s_cvt_freeEntryRdn(entry, rdn);
3100 			return (rc);
3101 		}
3102 	}
3103 
3104 	return (NS_LDAP_SUCCESS);
3105 }
3106 /*
3107  * Conversion:			audit_user
3108  * Input format:		au_user_str_t
3109  * Exported objectclass:	SolarisAuditUser
3110  */
3111 static int
3112 __s_cvt_audituser(const void *data, char **rdn,
3113 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3114 {
3115 	ns_ldap_entry_t	*e;
3116 	int		rc;
3117 	char		trdn[RDNSIZE];
3118 	/* routine specific */
3119 	au_user_str_t	*ptr;
3120 	int		max_attr = 3;
3121 	static		char *oclist[] = {
3122 			"SolarisAuditUser",
3123 			NULL
3124 			};
3125 
3126 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3127 		return (NS_LDAP_OP_FAILED);
3128 
3129 	*entry = e = __s_mk_entry(oclist, max_attr);
3130 	if (e == NULL)
3131 		return (NS_LDAP_MEMORY);
3132 
3133 	/* Convert the structure */
3134 	ptr = (au_user_str_t *)data;
3135 
3136 	if (ptr->au_name == NULL || ptr->au_name[0] == '\0') {
3137 		__ns_ldap_freeEntry(e);
3138 		*entry = NULL;
3139 		return (NS_LDAP_INVALID_PARAM);
3140 	}
3141 
3142 	/* Create an appropriate rdn */
3143 	(void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->au_name);
3144 	*rdn = strdup(trdn);
3145 	if (*rdn == NULL) {
3146 		__ns_ldap_freeEntry(e);
3147 		*entry = NULL;
3148 		return (NS_LDAP_MEMORY);
3149 	}
3150 
3151 	/*
3152 	 * Solaris AuditUser has no uid attribute
3153 	 */
3154 
3155 	if (ptr->au_always != NULL) {
3156 		rc = __s_add_attr(e, "SolarisAuditAlways", ptr->au_always);
3157 		if (rc != NS_LDAP_SUCCESS) {
3158 			__s_cvt_freeEntryRdn(entry, rdn);
3159 			return (rc);
3160 		}
3161 	}
3162 
3163 	if (ptr->au_never != NULL) {
3164 		rc = __s_add_attr(e, "SolarisAuditNever", ptr->au_never);
3165 		if (rc != NS_LDAP_SUCCESS) {
3166 			__s_cvt_freeEntryRdn(entry, rdn);
3167 			return (rc);
3168 		}
3169 	}
3170 
3171 	return (NS_LDAP_SUCCESS);
3172 }
3173 
3174 /*
3175  * Add Typed Entry Conversion data structures
3176  */
3177 
3178 typedef struct	__ns_cvt_type {
3179 	const char	*service;
3180 	int		flags;
3181 #define	AE		1	/* alway add entries */
3182 	int		(*cvt_rtn)(const void *data,
3183 				char		**rdn,
3184 				ns_ldap_entry_t	**entry,
3185 				ns_ldap_error_t	**errorp);
3186 } __ns_cvt_type_t;
3187 
3188 static __ns_cvt_type_t __s_cvtlist[] = {
3189 	{ NS_LDAP_TYPE_PASSWD,		0, __s_cvt_passwd },
3190 	{ NS_LDAP_TYPE_GROUP,		0, __s_cvt_group },
3191 	{ NS_LDAP_TYPE_HOSTS,		0, __s_cvt_hosts },
3192 	{ NS_LDAP_TYPE_IPNODES,		0, __s_cvt_hosts },
3193 	{ NS_LDAP_TYPE_RPC,		0, __s_cvt_rpc },
3194 	{ NS_LDAP_TYPE_PROTOCOLS,	0, __s_cvt_protocols },
3195 	{ NS_LDAP_TYPE_NETWORKS,	0, __s_cvt_networks },
3196 	{ NS_LDAP_TYPE_NETGROUP,	0, __s_cvt_netgroups },
3197 	{ NS_LDAP_TYPE_ALIASES,		0, __s_cvt_aliases },
3198 	{ NS_LDAP_TYPE_SERVICES,	0, __s_cvt_services },
3199 	{ NS_LDAP_TYPE_ETHERS,		0, __s_cvt_ethers },
3200 	{ NS_LDAP_TYPE_SHADOW,		0, __s_cvt_shadow },
3201 	{ NS_LDAP_TYPE_NETMASKS,	0, __s_cvt_netmasks },
3202 	{ NS_LDAP_TYPE_BOOTPARAMS,	0, __s_cvt_bootparams },
3203 	{ NS_LDAP_TYPE_AUTHATTR,	0, __s_cvt_authattr },
3204 	{ NS_LDAP_TYPE_EXECATTR,	0, __s_cvt_execattr },
3205 	{ NS_LDAP_TYPE_PROFILE,		0, __s_cvt_profattr },
3206 	{ NS_LDAP_TYPE_USERATTR,	AE, __s_cvt_userattr },
3207 	{ NS_LDAP_TYPE_AUTOMOUNT,	0, __s_cvt_auto_mount },
3208 	{ NS_LDAP_TYPE_PUBLICKEY,	AE, __s_cvt_publickey },
3209 	{ NS_LDAP_TYPE_AUUSER,		AE, __s_cvt_audituser },
3210 	{ NULL,				0, NULL },
3211 };
3212 
3213 /*
3214  * Add Typed Entry Routine
3215  */
3216 
3217 /*ARGSUSED*/
3218 int  __ns_ldap_addTypedEntry(
3219 	const char *servicetype,
3220 	const char *basedn,
3221 	const void *data,
3222 	const int  create,
3223 	const ns_cred_t *cred,
3224 	const int flags,
3225 	ns_ldap_error_t **errorp)
3226 {
3227 	char			*rdn = NULL, *fulldn = NULL;
3228 	void			**paramVal = NULL;
3229 	ns_ldap_entry_t 	*entry = NULL;
3230 	const ns_ldap_attr_t	*const *modattrlist;
3231 	ns_ldap_search_desc_t	**sdlist;
3232 	char			**dns = NULL;
3233 	char			trdn[RDNSIZE];
3234 	char			service[BUFSIZE];
3235 	int			rc = 0;
3236 	int			automount = 0;
3237 	int			i, s;
3238 
3239 	rc = NS_LDAP_OP_FAILED;
3240 	for (s = 0; __s_cvtlist[s].service != NULL; s++) {
3241 		if (__s_cvtlist[s].cvt_rtn == NULL)
3242 			continue;
3243 		if (strcasecmp(__s_cvtlist[s].service, servicetype) == 0)
3244 			break;
3245 		/* Or, check if the servicetype is  auto_ */
3246 		if (strcmp(__s_cvtlist[s].service,
3247 		    NS_LDAP_TYPE_AUTOMOUNT) == 0 &&
3248 		    strncasecmp(servicetype, NS_LDAP_TYPE_AUTOMOUNT,
3249 		    sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0) {
3250 			automount++;
3251 			break;
3252 		}
3253 	}
3254 	if (__s_cvtlist[s].service == NULL)
3255 		return (rc);
3256 
3257 	/* Convert the data */
3258 	rc = (*__s_cvtlist[s].cvt_rtn)(data, &rdn, &entry, errorp);
3259 	if (rc != NS_LDAP_SUCCESS) {
3260 		__s_cvt_freeEntryRdn(&entry, &rdn);
3261 		return (rc);
3262 	}
3263 	if (rdn == NULL) {
3264 		__ns_ldap_freeEntry(entry);
3265 		return (NS_LDAP_OP_FAILED);
3266 	}
3267 
3268 	if (strcmp(servicetype, "publickey") == 0) {
3269 		struct _ns_pubkey *ptr;
3270 		ptr = (struct _ns_pubkey *)data;
3271 		if (ptr->hostcred == NS_HOSTCRED_TRUE)
3272 			(void) strcpy(service, "hosts");
3273 		else
3274 			(void) strcpy(service, "passwd");
3275 	} else
3276 		(void) strcpy(service, servicetype);
3277 
3278 	/* Create the Full DN */
3279 	if (basedn == NULL) {
3280 		rc = __s_api_get_SSD_from_SSDtoUse_service(service,
3281 		    &sdlist, errorp);
3282 		if (rc != NS_LDAP_SUCCESS) {
3283 			__s_cvt_freeEntryRdn(&entry, &rdn);
3284 			return (rc);
3285 		}
3286 
3287 		if (sdlist == NULL) {
3288 			rc = __s_api_getDNs(&dns, service, errorp);
3289 			if (rc != NS_LDAP_SUCCESS) {
3290 				if (dns) {
3291 					__s_api_free2dArray(dns);
3292 					dns = NULL;
3293 				}
3294 				__s_cvt_freeEntryRdn(&entry, &rdn);
3295 				return (rc);
3296 			}
3297 			(void) snprintf(trdn, RDNSIZE, "%s,%s", rdn, dns[0]);
3298 			__s_api_free2dArray(dns);
3299 		} else {
3300 			if (sdlist[0]->basedn) {
3301 				(void) snprintf(trdn, RDNSIZE, "%s,%s",
3302 				    rdn, sdlist[0]->basedn);
3303 			} else {
3304 				__s_cvt_freeEntryRdn(&entry, &rdn);
3305 				return (NS_LDAP_OP_FAILED);
3306 			}
3307 		}
3308 		i = strlen(trdn) - 1;
3309 		if (trdn[i] == COMMATOK) {
3310 			rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P,
3311 			    &paramVal, errorp);
3312 			if (rc != NS_LDAP_SUCCESS) {
3313 				__s_cvt_freeEntryRdn(&entry, &rdn);
3314 				return (rc);
3315 			}
3316 			i = strlen(trdn) + strlen((char *)(paramVal[0])) + 1;
3317 			fulldn = (char *)calloc(i, 1);
3318 			if (fulldn == NULL) {
3319 				(void) __ns_ldap_freeParam(&paramVal);
3320 				__s_cvt_freeEntryRdn(&entry, &rdn);
3321 				return (NS_LDAP_MEMORY);
3322 			}
3323 			(void) snprintf(fulldn, i, "%s%s", trdn,
3324 			    (char *)(paramVal[0]));
3325 			(void) __ns_ldap_freeParam(&paramVal);
3326 		} else {
3327 			fulldn = strdup(trdn);
3328 			if (fulldn == NULL) {
3329 				__s_cvt_freeEntryRdn(&entry, &rdn);
3330 				return (NS_LDAP_MEMORY);
3331 			}
3332 		}
3333 	} else {
3334 		i = strlen(rdn) + strlen(basedn) + 2;
3335 		fulldn = (char *)calloc(i, 1);
3336 		if (fulldn == NULL) {
3337 			__s_cvt_freeEntryRdn(&entry, &rdn);
3338 			return (NS_LDAP_MEMORY);
3339 		}
3340 		(void) snprintf(fulldn, i, "%s,%s", rdn, basedn);
3341 	}
3342 
3343 	modattrlist = (const ns_ldap_attr_t * const *)entry->attr_pair;
3344 	/* Check to see if the entry exists already */
3345 	/* May need to delete or update first */
3346 
3347 	if (create != 1) {
3348 		/* Modify the entry */
3349 		if ((__s_cvtlist[s].flags & AE) != 0)
3350 			rc = __ns_ldap_addAttr(service, fulldn, modattrlist,
3351 			    cred, flags, errorp);
3352 		else {
3353 			rc = __ns_ldap_repAttr(service, fulldn, modattrlist,
3354 					cred, flags, errorp);
3355 			if (rc == NS_LDAP_INTERNAL && *errorp &&
3356 			    (*errorp)->status == LDAP_NO_SUCH_OBJECT) {
3357 				(void) __ns_ldap_freeError(errorp);
3358 				rc = __ns_ldap_addEntry(service, fulldn,
3359 				    entry, cred, flags, errorp);
3360 			}
3361 		}
3362 	} else {
3363 		/* Add the entry */
3364 		rc = __ns_ldap_addEntry(service, fulldn, entry,
3365 		    cred, flags, errorp);
3366 		if (rc == NS_LDAP_INTERNAL && *errorp &&
3367 		    (*errorp)->status == LDAP_ALREADY_EXISTS &&
3368 		    ((strcmp(service, "ethers") == 0) ||
3369 		    (strcmp(service, "bootparams") == 0))) {
3370 			rc = modify_ethers_bootp(service, rdn, fulldn,
3371 			    modattrlist, cred, flags, errorp);
3372 		}
3373 	}
3374 
3375 	/* Free up entry created by conversion routine */
3376 	if (fulldn != NULL)
3377 		free(fulldn);
3378 	__s_cvt_freeEntryRdn(&entry, &rdn);
3379 	return (rc);
3380 }
3381 
3382 
3383 /*
3384  * Append the default base dn to the dn
3385  * when it ends with ','.
3386  * e.g.
3387  * SSD = service:ou=foo,
3388  */
3389 int
3390 __s_api_append_default_basedn(
3391 	const char *dn,
3392 	char **new_dn,
3393 	int *allocated,
3394 	ns_ldap_error_t **errp) {
3395 
3396 	int		rc = NS_LDAP_SUCCESS, len = 0;
3397 	void		**param = NULL;
3398 	char		*str = NULL;
3399 
3400 	*allocated = FALSE;
3401 	*new_dn = NULL;
3402 
3403 	if (dn == NULL)
3404 		return (NS_LDAP_INVALID_PARAM);
3405 
3406 	rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P,
3407 		(void ***)&param, errp);
3408 
3409 	if (rc != NS_LDAP_SUCCESS) {
3410 		if (param)
3411 			(void) __ns_ldap_freeParam(&param);
3412 		return (rc);
3413 	}
3414 
3415 	len = strlen(dn);
3416 	str = ((char **)param)[0];
3417 	len = len + strlen(str) +1;
3418 	*new_dn = (char *)malloc(len);
3419 	if (*new_dn == NULL) {
3420 		(void) __ns_ldap_freeParam(&param);
3421 		return (NS_LDAP_MEMORY);
3422 	}
3423 	*allocated = TRUE;
3424 
3425 	(void) strcpy(*new_dn, dn);
3426 	(void) strcat(*new_dn, str);
3427 
3428 	(void) __ns_ldap_freeParam(&param);
3429 	return (NS_LDAP_SUCCESS);
3430 }
3431