4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <netinet/in.h>
30 #include <arpa/inet.h>
31 #include <sys/socket.h>
32 #include "ns_internal.h"
33 #include "ldap_common.h"
35 /* networks attributes filters */
37 #define _N_NETWORK "ipnetworknumber"
38 #define _F_GETNETBYNAME "(&(objectClass=ipNetwork)(cn=%s))"
39 #define _F_GETNETBYNAME_SSD "(&(%%s)(cn=%s))"
40 #define _F_GETNETBYADDR "(&(objectClass=ipNetwork)(|(ipNetworkNumber=%s)" \
41 "(ipNetworkNumber=%s)))"
42 #define _F_GETNETBYADDR_SSD "(&(%%s)(|(ipNetworkNumber=%s)" \
43 "(ipNetworkNumber=%s)))"
45 static const char *networks_attrs
[] = {
52 * _nss_ldap_networks2str is the data marshaling method for the networks
53 * getXbyY * (e.g., getbyname(), getbyaddr(), getnetent() backend processes.
54 * This method is called after a successful ldap search has been performed.
55 * This method will parse the ldap search values into the file format.
58 * SunRay-ce2 10.34.96.0 SunRay
62 _nss_ldap_networks2str(ldap_backend_ptr be
, nss_XbyY_args_t
*argp
)
67 char **network
, *cname
= NULL
;
69 ns_ldap_result_t
*result
= be
->result
;
70 ns_ldap_attr_t
*names
;
73 return (NSS_STR_PARSE_PARSE
);
74 buflen
= argp
->buf
.buflen
;
76 if (argp
->buf
.result
!= NULL
) {
77 if ((be
->buffer
= calloc(1, buflen
)) == NULL
) {
78 nss_result
= NSS_STR_PARSE_PARSE
;
83 buffer
= argp
->buf
.buffer
;
85 nss_result
= NSS_STR_PARSE_SUCCESS
;
86 (void) memset(argp
->buf
.buffer
, 0, buflen
);
88 names
= __ns_ldap_getAttrStruct(result
->entry
, _N_NAME
);
89 if (names
== NULL
|| names
->attrvalue
== NULL
) {
90 nss_result
= NSS_STR_PARSE_PARSE
;
93 /* Get the canonical name */
94 cname
= __s_api_get_canonical_name(result
->entry
, names
, 1);
96 * The definition of the object class "ipNetwork" has a
97 * discrepency between RFC 2307 and 2307bis.
98 * In 2307, "cn" is a MUST attribute. In 2307bis, "cn" is a
100 * If "cn" is a MAY attribute, it does not appear in RDN and can't
101 * be derived from RDN as a canonical "cn" name. In that case, use 1st
102 * "cn" value as the official name.
106 cname
= names
->attrvalue
[0];
107 if (cname
== NULL
|| (len
= strlen(cname
)) < 1) {
108 nss_result
= NSS_STR_PARSE_PARSE
;
111 network
= __ns_ldap_getAttr(result
->entry
, _N_NETWORK
);
112 if (network
== NULL
|| network
[0] == NULL
||
113 (len
= strlen(network
[0])) < 1) {
114 nss_result
= NSS_STR_PARSE_PARSE
;
117 len
= snprintf(buffer
, buflen
, "%s %s", cname
, network
[0]);
118 TEST_AND_ADJUST(len
, buffer
, buflen
, result_net2str
);
120 for (i
= 0; i
< names
->value_count
; i
++) {
121 if (names
->attrvalue
[i
] == NULL
) {
122 nss_result
= NSS_STR_PARSE_PARSE
;
125 /* Skip the canonical name */
126 if (strcasecmp(names
->attrvalue
[i
], cname
) != 0) {
127 len
= snprintf(buffer
, buflen
, " %s",
128 names
->attrvalue
[i
]);
129 TEST_AND_ADJUST(len
, buffer
, buflen
, result_net2str
);
133 /* The front end marshaller doesn't need to copy trailing nulls */
134 if (argp
->buf
.result
!= NULL
)
135 be
->buflen
= strlen(be
->buffer
);
139 (void) __ns_ldap_freeResult(&be
->result
);
144 * Takes an unsigned integer in host order, and returns a printable
145 * string for it as a network number. To allow for the possibility of
146 * naming subnets, only trailing dot-zeros are truncated.
147 * buf2 is untruncated version.
150 static int nettoa(int anet
, char *buf
, char *buf2
, int buflen
)
156 if (buf
== NULL
|| buf2
== NULL
)
159 in
= inet_makeaddr(anet
, INADDR_ANY
);
161 if (inet_ntop(AF_INET
, (const void *)&in
, buf2
, INET_ADDRSTRLEN
)
164 if (strlcpy(buf
, buf2
, buflen
) >= buflen
)
166 if ((IN_CLASSA_HOST
& htonl(addr
)) == 0) {
167 p
= strchr(buf
, '.');
171 } else if ((IN_CLASSB_HOST
& htonl(addr
)) == 0) {
172 p
= strchr(buf
, '.');
175 p
= strchr(p
+ 1, '.');
179 } else if ((IN_CLASSC_HOST
& htonl(addr
)) == 0) {
180 p
= strrchr(buf
, '.');
191 * getbyname gets a network entry by name. This function constructs an
192 * ldap search filter using the network name invocation parameter and the
193 * getnetbyname search filter defined. Once the filter is constructed, we
194 * search for a matching entry and marshal the data results into struct
195 * netent for the frontend process. The function _nss_ldap_networks2ent
196 * performs the data marshaling.
200 getbyname(ldap_backend_ptr be
, void *a
)
202 nss_XbyY_args_t
*argp
= (nss_XbyY_args_t
*)a
;
203 char searchfilter
[SEARCHFILTERLEN
];
204 char userdata
[SEARCHFILTERLEN
];
205 char netname
[SEARCHFILTERLEN
];
208 if (_ldap_filter_name(netname
, argp
->key
.name
, sizeof (netname
)) != 0)
209 return ((nss_status_t
)NSS_NOTFOUND
);
211 ret
= snprintf(searchfilter
, sizeof (searchfilter
),
212 _F_GETNETBYNAME
, netname
);
213 if (ret
>= sizeof (searchfilter
) || ret
< 0)
214 return ((nss_status_t
)NSS_NOTFOUND
);
216 ret
= snprintf(userdata
, sizeof (userdata
),
217 _F_GETNETBYNAME_SSD
, netname
);
218 if (ret
>= sizeof (userdata
) || ret
< 0)
219 return ((nss_status_t
)NSS_NOTFOUND
);
221 return ((nss_status_t
)_nss_ldap_lookup(be
, argp
,
222 _NETWORKS
, searchfilter
, NULL
,
223 _merge_SSD_filter
, userdata
));
228 * getbyaddr gets a network entry by ip address. This function constructs an
229 * ldap search filter using the name invocation parameter and the getnetbyaddr
230 * search filter defined. Once the filter is constructed, we search for a
231 * matching entry and marshal the data results into struct netent for the
232 * frontend process. The function _nss_ldap_networks2ent performs the data
237 getbyaddr(ldap_backend_ptr be
, void *a
)
239 nss_XbyY_args_t
*argp
= (nss_XbyY_args_t
*)a
;
240 char addrstr
[INET_ADDRSTRLEN
], addrstr2
[INET_ADDRSTRLEN
];
241 char searchfilter
[SEARCHFILTERLEN
];
242 char userdata
[SEARCHFILTERLEN
];
245 if (nettoa((int)argp
->key
.netaddr
.net
, addrstr
, addrstr2
,
246 INET_ADDRSTRLEN
) != 0)
247 return ((nss_status_t
)NSS_UNAVAIL
);
249 ret
= snprintf(searchfilter
, sizeof (searchfilter
),
250 _F_GETNETBYADDR
, addrstr
, addrstr2
);
251 if (ret
>= sizeof (searchfilter
) || ret
< 0)
252 return ((nss_status_t
)NSS_NOTFOUND
);
254 ret
= snprintf(userdata
, sizeof (userdata
),
255 _F_GETNETBYADDR_SSD
, addrstr
, addrstr2
);
256 if (ret
>= sizeof (userdata
) || ret
< 0)
257 return ((nss_status_t
)NSS_NOTFOUND
);
259 return ((nss_status_t
)_nss_ldap_lookup(be
, argp
,
260 _NETWORKS
, searchfilter
, NULL
,
261 _merge_SSD_filter
, userdata
));
264 static ldap_backend_op_t net_ops
[] = {
275 * _nss_ldap_networks_constr is where life begins. This function calls the
276 * generic ldap constructor function to define and build the abstract data
277 * types required to support ldap operations.
282 _nss_ldap_networks_constr(const char *dummy1
, const char *dummy2
,
286 return ((nss_backend_t
*)_nss_ldap_constr(net_ops
,
287 sizeof (net_ops
)/sizeof (net_ops
[0]), _NETWORKS
,
288 networks_attrs
, _nss_ldap_networks2str
));