xref: /onnv-gate/usr/src/lib/nsswitch/ldap/common/getprotoent.c (revision 2830:5228d1267a01)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*2830Sdjl  * Common Development and Distribution License (the "License").
6*2830Sdjl  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*2830Sdjl  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include <ctype.h>
290Sstevel@tonic-gate #include <netdb.h>
300Sstevel@tonic-gate #include "ns_internal.h"
310Sstevel@tonic-gate #include "ldap_common.h"
320Sstevel@tonic-gate 
330Sstevel@tonic-gate /* protocols attributes filters */
340Sstevel@tonic-gate #define	_P_NAME			"cn"
350Sstevel@tonic-gate #define	_P_PROTO		"ipprotocolnumber"
360Sstevel@tonic-gate #define	_F_GETPROTOBYNAME	"(&(objectClass=ipProtocol)(cn=%s))"
370Sstevel@tonic-gate #define	_F_GETPROTOBYNAME_SSD	"(&(%%s)(cn=%s))"
380Sstevel@tonic-gate #define	_F_GETPROTOBYNUMBER	\
390Sstevel@tonic-gate 	"(&(objectClass=ipProtocol)(ipProtocolNumber=%d))"
400Sstevel@tonic-gate #define	_F_GETPROTOBYNUMBER_SSD	\
410Sstevel@tonic-gate 	"(&(%%s)(ipProtocolNumber=%d))"
420Sstevel@tonic-gate 
430Sstevel@tonic-gate static const char *protocols_attrs[] = {
440Sstevel@tonic-gate 	_P_NAME,
450Sstevel@tonic-gate 	_P_PROTO,
460Sstevel@tonic-gate 	(char *)NULL
470Sstevel@tonic-gate };
480Sstevel@tonic-gate 
49*2830Sdjl typedef struct protocol_alias {
50*2830Sdjl 	char	*protocol;
51*2830Sdjl 	char	*alias;
52*2830Sdjl } protocol_alias_t;
53*2830Sdjl 
54*2830Sdjl static const protocol_alias_t ip_aliases[10] = {
55*2830Sdjl 	{ "ip", "IP" },
56*2830Sdjl 	{ "ipip", "IP-IP" },
57*2830Sdjl 	{ "ipcomp", "IPComp" },
58*2830Sdjl 	{ "ipv6", "IPv6" },
59*2830Sdjl 	{ "ipv6-route", "IPv6-Route" },
60*2830Sdjl 	{ "ipv6-frag", "IPv6-Frag" },
61*2830Sdjl 	{ "ipv6-icmp", "IPv6-ICMP" },
62*2830Sdjl 	{ "ipv6-nonxt", "IPv6-NoNxt" },
63*2830Sdjl 	{ "ipv6-opts", "IPv6-Opts" },
64*2830Sdjl 	{ NULL, NULL }
65*2830Sdjl };
660Sstevel@tonic-gate 
670Sstevel@tonic-gate /*
68*2830Sdjl  * When the data is imported by ldapaddent, it does not save the aliase in the
69*2830Sdjl  * "cn" that is same as the canonical name but only different in case.
70*2830Sdjl  * e.g.
71*2830Sdjl  * icmp		1	ICMP
72*2830Sdjl  *
73*2830Sdjl  * is saved as
74*2830Sdjl  *
75*2830Sdjl  * dn: cn=icmp, ...
76*2830Sdjl  * ...
77*2830Sdjl  * cn: icmp
78*2830Sdjl  * ...
79*2830Sdjl  *
80*2830Sdjl  * So it needs to replicate the canonical name as an alias of upper case.
81*2830Sdjl  * But some protocol does have different aliases.
82*2830Sdjl  *
83*2830Sdjl  * e.g.
84*2830Sdjl  * dn: cn=ospf, ...
85*2830Sdjl  * ...
86*2830Sdjl  * cn: ospf
87*2830Sdjl  * cn: OSPFIGP
88*2830Sdjl  * ...
89*2830Sdjl  *
90*2830Sdjl  * For many ip* protocols, the aliases are mixed cased. Maybe it's case
91*2830Sdjl  * insensitive. But this fucntion tries to restore the aliases to the original
92*2830Sdjl  * form as much as possible. If the alias can't be found in the aliases table,
93*2830Sdjl  * it assumes the alias is all upper case.
94*2830Sdjl  *
95*2830Sdjl  */
96*2830Sdjl static char *
get_alias(char * protocol)97*2830Sdjl get_alias(char *protocol) {
98*2830Sdjl 	int	i;
99*2830Sdjl 	char	*cp;
100*2830Sdjl 
101*2830Sdjl 	if (strncmp(protocol, "ip", 2) == 0) {
102*2830Sdjl 		for (i = 0; ip_aliases[i].protocol != NULL; i++) {
103*2830Sdjl 			if (strcmp(protocol, ip_aliases[i].protocol) == 0)
104*2830Sdjl 				return (ip_aliases[i].alias);
105*2830Sdjl 		}
106*2830Sdjl 		/*
107*2830Sdjl 		 * No aliase in the table. Return an all upper case aliase
108*2830Sdjl 		 */
109*2830Sdjl 		for (cp = protocol; *cp; cp++)
110*2830Sdjl 			*cp = toupper(*cp);
111*2830Sdjl 
112*2830Sdjl 		return (protocol);
113*2830Sdjl 	} else {
114*2830Sdjl 		/* Return an all upper case aliase */
115*2830Sdjl 		for (cp = protocol; *cp; cp++)
116*2830Sdjl 			*cp = toupper(*cp);
117*2830Sdjl 
118*2830Sdjl 		return (protocol);
119*2830Sdjl 	}
120*2830Sdjl 
121*2830Sdjl }
122*2830Sdjl /*
123*2830Sdjl  * _nss_ldap_protocols2str is the data marshaling method for the protocols
1240Sstevel@tonic-gate  * getXbyY * (e.g., getbyname(), getbynumber(), getent()) backend processes.
1250Sstevel@tonic-gate  * This method is called after a successful ldap search has been performed.
126*2830Sdjl  * This method will parse the ldap search values into a file format.
127*2830Sdjl  * e.g.
128*2830Sdjl  * idrp 45 IDRP
129*2830Sdjl  * or
130*2830Sdjl  * ospf 89 OSPFIGP
1310Sstevel@tonic-gate  */
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate static int
_nss_ldap_protocols2str(ldap_backend_ptr be,nss_XbyY_args_t * argp)134*2830Sdjl _nss_ldap_protocols2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
1350Sstevel@tonic-gate {
136*2830Sdjl 	uint_t		i;
1370Sstevel@tonic-gate 	int		nss_result;
138*2830Sdjl 	int		buflen = 0, len;
139*2830Sdjl 	char		*cname = NULL;
140*2830Sdjl 	char		*buffer = NULL, **number, *alias;
1410Sstevel@tonic-gate 	ns_ldap_result_t	*result = be->result;
142*2830Sdjl 	ns_ldap_attr_t	*names;
143*2830Sdjl 
144*2830Sdjl 	if (result == NULL)
145*2830Sdjl 		return (NSS_STR_PARSE_PARSE);
1460Sstevel@tonic-gate 
147*2830Sdjl 	buflen = argp->buf.buflen;
148*2830Sdjl 	if (argp->buf.result != NULL) {
149*2830Sdjl 		if ((be->buffer = calloc(1, buflen)) == NULL) {
150*2830Sdjl 			nss_result = NSS_STR_PARSE_PARSE;
151*2830Sdjl 			goto result_pls2str;
152*2830Sdjl 		}
153*2830Sdjl 		buffer = be->buffer;
154*2830Sdjl 	} else
155*2830Sdjl 		buffer = argp->buf.buffer;
1560Sstevel@tonic-gate 
157*2830Sdjl 	nss_result = NSS_STR_PARSE_SUCCESS;
1580Sstevel@tonic-gate 	(void) memset(argp->buf.buffer, 0, buflen);
1590Sstevel@tonic-gate 
160*2830Sdjl 	names = __ns_ldap_getAttrStruct(result->entry, _P_NAME);
161*2830Sdjl 	if (names == NULL || names->attrvalue == NULL) {
162*2830Sdjl 		nss_result = NSS_STR_PARSE_PARSE;
163*2830Sdjl 		goto result_pls2str;
164*2830Sdjl 	}
165*2830Sdjl 	/* Get the canonical name */
166*2830Sdjl 	cname = __s_api_get_canonical_name(result->entry, names, 1);
167*2830Sdjl 	if (cname == NULL || (len = strlen(cname)) < 1) {
168*2830Sdjl 		nss_result = NSS_STR_PARSE_PARSE;
169*2830Sdjl 		goto result_pls2str;
170*2830Sdjl 	}
171*2830Sdjl 	number = __ns_ldap_getAttr(result->entry, _P_PROTO);
172*2830Sdjl 	if (number == NULL || number[0] == NULL ||
173*2830Sdjl 			(len = strlen(number[0])) < 1) {
174*2830Sdjl 		nss_result = NSS_STR_PARSE_PARSE;
175*2830Sdjl 		goto result_pls2str;
1760Sstevel@tonic-gate 	}
177*2830Sdjl 	len = snprintf(buffer, buflen,  "%s %s", cname, number[0]);
178*2830Sdjl 	TEST_AND_ADJUST(len, buffer, buflen, result_pls2str);
179*2830Sdjl 	/* Append aliases */
180*2830Sdjl 	if (names->value_count == 1) {
181*2830Sdjl 		/* create an aliase from protocol name */
182*2830Sdjl 		alias = get_alias(cname);
183*2830Sdjl 		len = snprintf(buffer, buflen,  " %s", alias);
184*2830Sdjl 		TEST_AND_ADJUST(len, buffer, buflen, result_pls2str);
185*2830Sdjl 
186*2830Sdjl 	} else {
187*2830Sdjl 		for (i = 0; i < names->value_count; i++) {
188*2830Sdjl 			if (names->attrvalue[i] == NULL) {
189*2830Sdjl 				nss_result = NSS_STR_PARSE_PARSE;
190*2830Sdjl 				goto result_pls2str;
1910Sstevel@tonic-gate 			}
192*2830Sdjl 			/* Skip the canonical name */
193*2830Sdjl 			if (strcasecmp(names->attrvalue[i], cname) != 0) {
194*2830Sdjl 				len = snprintf(buffer, buflen,  " %s",
195*2830Sdjl 						names->attrvalue[i]);
196*2830Sdjl 				TEST_AND_ADJUST(len, buffer, buflen,
197*2830Sdjl 						result_pls2str);
1980Sstevel@tonic-gate 			}
1990Sstevel@tonic-gate 		}
2000Sstevel@tonic-gate 	}
2010Sstevel@tonic-gate 
202*2830Sdjl 	/* The front end marshaller doesn't need to copy trailing nulls */
203*2830Sdjl 	if (argp->buf.result != NULL)
204*2830Sdjl 		be->buflen = strlen(be->buffer);
2050Sstevel@tonic-gate 
206*2830Sdjl result_pls2str:
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&be->result);
2090Sstevel@tonic-gate 	return ((int)nss_result);
2100Sstevel@tonic-gate }
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate /*
2140Sstevel@tonic-gate  * getbyname gets struct protoent values by protocol name. This
2150Sstevel@tonic-gate  * function constructs an ldap search filter using the protocol
2160Sstevel@tonic-gate  * name invocation parameter and the getprotobyname search filter
2170Sstevel@tonic-gate  * defined. Once the filter is constructed, we search for a matching
2180Sstevel@tonic-gate  * entry and marshal the data results into *proto = (struct *
2190Sstevel@tonic-gate  * protoent *)argp->buf.result. The function _nss_ldap_protocols2ent
2200Sstevel@tonic-gate  * performs the data marshaling.
2210Sstevel@tonic-gate  */
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate static nss_status_t
getbyname(ldap_backend_ptr be,void * a)2240Sstevel@tonic-gate getbyname(ldap_backend_ptr be, void *a)
2250Sstevel@tonic-gate {
2260Sstevel@tonic-gate 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
2270Sstevel@tonic-gate 	char		searchfilter[SEARCHFILTERLEN];
2280Sstevel@tonic-gate 	char		userdata[SEARCHFILTERLEN];
2290Sstevel@tonic-gate 	char		name[SEARCHFILTERLEN];
2300Sstevel@tonic-gate 	int		ret;
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate 	if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0)
2330Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate 	ret = snprintf(searchfilter, sizeof (searchfilter),
2360Sstevel@tonic-gate 	    _F_GETPROTOBYNAME, name);
2370Sstevel@tonic-gate 	if (ret >= sizeof (searchfilter) || ret < 0)
2380Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
2390Sstevel@tonic-gate 
2400Sstevel@tonic-gate 	ret = snprintf(userdata, sizeof (userdata),
2410Sstevel@tonic-gate 	    _F_GETPROTOBYNAME_SSD, name);
2420Sstevel@tonic-gate 	if (ret >= sizeof (userdata) || ret < 0)
2430Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate 	return ((nss_status_t)_nss_ldap_lookup(be, argp,
2460Sstevel@tonic-gate 		_PROTOCOLS, searchfilter, NULL,
2470Sstevel@tonic-gate 		_merge_SSD_filter, userdata));
2480Sstevel@tonic-gate }
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate /*
2520Sstevel@tonic-gate  * getbynumber gets struct protoent values by protocol number. This
2530Sstevel@tonic-gate  * function constructs an ldap search filter using the protocol
2540Sstevel@tonic-gate  * name invocation parameter and the getprotobynumber search filter
2550Sstevel@tonic-gate  * defined. Once the filter is constructed, we search for a matching
2560Sstevel@tonic-gate  * entry and marshal the data results into *proto = (struct *
2570Sstevel@tonic-gate  * protoent *)argp->buf.result. The function _nss_ldap_protocols2ent
2580Sstevel@tonic-gate  * performs the data marshaling.
2590Sstevel@tonic-gate  */
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate static nss_status_t
getbynumber(ldap_backend_ptr be,void * a)2620Sstevel@tonic-gate getbynumber(ldap_backend_ptr be, void *a)
2630Sstevel@tonic-gate {
2640Sstevel@tonic-gate 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
2650Sstevel@tonic-gate 	char		searchfilter[SEARCHFILTERLEN];
2660Sstevel@tonic-gate 	char		userdata[SEARCHFILTERLEN];
2670Sstevel@tonic-gate 	int		ret;
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate 	ret = snprintf(searchfilter, sizeof (searchfilter),
2700Sstevel@tonic-gate 	    _F_GETPROTOBYNUMBER, argp->key.number);
2710Sstevel@tonic-gate 	if (ret >= sizeof (searchfilter) || ret < 0)
2720Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 	ret = snprintf(userdata, sizeof (userdata),
2750Sstevel@tonic-gate 	    _F_GETPROTOBYNUMBER_SSD, argp->key.number);
2760Sstevel@tonic-gate 	if (ret >= sizeof (userdata) || ret < 0)
2770Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
2780Sstevel@tonic-gate 
2790Sstevel@tonic-gate 	return ((nss_status_t)_nss_ldap_lookup(be, argp,
2800Sstevel@tonic-gate 		_PROTOCOLS, searchfilter, NULL,
2810Sstevel@tonic-gate 		_merge_SSD_filter, userdata));
2820Sstevel@tonic-gate }
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate static ldap_backend_op_t proto_ops[] = {
2850Sstevel@tonic-gate 	_nss_ldap_destr,
2860Sstevel@tonic-gate 	_nss_ldap_endent,
2870Sstevel@tonic-gate 	_nss_ldap_setent,
2880Sstevel@tonic-gate 	_nss_ldap_getent,
2890Sstevel@tonic-gate 	getbyname,
2900Sstevel@tonic-gate 	getbynumber
2910Sstevel@tonic-gate };
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate /*
2950Sstevel@tonic-gate  * _nss_ldap_protocols_constr is where life begins. This function calls
2960Sstevel@tonic-gate  * the generic ldap constructor function to define and build the abstract
2970Sstevel@tonic-gate  * data types required to support ldap operations.
2980Sstevel@tonic-gate  */
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate /*ARGSUSED0*/
3010Sstevel@tonic-gate nss_backend_t *
_nss_ldap_protocols_constr(const char * dummy1,const char * dummy2,const char * dummy3)3020Sstevel@tonic-gate _nss_ldap_protocols_constr(const char *dummy1, const char *dummy2,
3030Sstevel@tonic-gate 			const char *dummy3)
3040Sstevel@tonic-gate {
3050Sstevel@tonic-gate 
3060Sstevel@tonic-gate 	return ((nss_backend_t *)_nss_ldap_constr(proto_ops,
3070Sstevel@tonic-gate 		sizeof (proto_ops)/sizeof (proto_ops[0]), _PROTOCOLS,
308*2830Sdjl 		protocols_attrs, _nss_ldap_protocols2str));
3090Sstevel@tonic-gate }
310