getprotoent.c revision 2830:5228d1267a01
1235368Sgnn/* 2235368Sgnn * CDDL HEADER START 3235368Sgnn * 4235368Sgnn * The contents of this file are subject to the terms of the 5235368Sgnn * Common Development and Distribution License (the "License"). 6235368Sgnn * You may not use this file except in compliance with the License. 7235368Sgnn * 8235368Sgnn * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9235368Sgnn * or http://www.opensolaris.org/os/licensing. 10235368Sgnn * See the License for the specific language governing permissions 11235368Sgnn * and limitations under the License. 12235368Sgnn * 13235368Sgnn * When distributing Covered Code, include this CDDL HEADER in each 14235368Sgnn * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15235368Sgnn * If applicable, add the following below this CDDL HEADER, with the 16235368Sgnn * fields enclosed by brackets "[]" replaced with your own identifying 17235368Sgnn * information: Portions Copyright [yyyy] [name of copyright owner] 18235368Sgnn * 19235368Sgnn * CDDL HEADER END 20235368Sgnn */ 21235368Sgnn/* 22235368Sgnn * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23235368Sgnn * Use is subject to license terms. 24235368Sgnn */ 25235368Sgnn 26235368Sgnn#pragma ident "%Z%%M% %I% %E% SMI" 27235368Sgnn 28235368Sgnn#include <ctype.h> 29235368Sgnn#include <netdb.h> 30235368Sgnn#include "ns_internal.h" 31235368Sgnn#include "ldap_common.h" 32235368Sgnn 33235368Sgnn/* protocols attributes filters */ 34235368Sgnn#define _P_NAME "cn" 35235368Sgnn#define _P_PROTO "ipprotocolnumber" 36235368Sgnn#define _F_GETPROTOBYNAME "(&(objectClass=ipProtocol)(cn=%s))" 37235368Sgnn#define _F_GETPROTOBYNAME_SSD "(&(%%s)(cn=%s))" 38235368Sgnn#define _F_GETPROTOBYNUMBER \ 39235368Sgnn "(&(objectClass=ipProtocol)(ipProtocolNumber=%d))" 40235368Sgnn#define _F_GETPROTOBYNUMBER_SSD \ 41235368Sgnn "(&(%%s)(ipProtocolNumber=%d))" 42235368Sgnn 43235368Sgnnstatic const char *protocols_attrs[] = { 44235368Sgnn _P_NAME, 45235368Sgnn _P_PROTO, 46235368Sgnn (char *)NULL 47235368Sgnn}; 48235368Sgnn 49235368Sgnntypedef struct protocol_alias { 50235368Sgnn char *protocol; 51235368Sgnn char *alias; 52235368Sgnn} protocol_alias_t; 53235368Sgnn 54235368Sgnnstatic const protocol_alias_t ip_aliases[10] = { 55235368Sgnn { "ip", "IP" }, 56235368Sgnn { "ipip", "IP-IP" }, 57235368Sgnn { "ipcomp", "IPComp" }, 58235368Sgnn { "ipv6", "IPv6" }, 59235368Sgnn { "ipv6-route", "IPv6-Route" }, 60235368Sgnn { "ipv6-frag", "IPv6-Frag" }, 61235368Sgnn { "ipv6-icmp", "IPv6-ICMP" }, 62235368Sgnn { "ipv6-nonxt", "IPv6-NoNxt" }, 63235368Sgnn { "ipv6-opts", "IPv6-Opts" }, 64235368Sgnn { NULL, NULL } 65235368Sgnn}; 66235368Sgnn 67235368Sgnn/* 68235368Sgnn * When the data is imported by ldapaddent, it does not save the aliase in the 69235368Sgnn * "cn" that is same as the canonical name but only different in case. 70235368Sgnn * e.g. 71235368Sgnn * icmp 1 ICMP 72235368Sgnn * 73235368Sgnn * is saved as 74235368Sgnn * 75235368Sgnn * dn: cn=icmp, ... 76235368Sgnn * ... 77235368Sgnn * cn: icmp 78235368Sgnn * ... 79235368Sgnn * 80235368Sgnn * So it needs to replicate the canonical name as an alias of upper case. 81235368Sgnn * But some protocol does have different aliases. 82235368Sgnn * 83235368Sgnn * e.g. 84235368Sgnn * dn: cn=ospf, ... 85235368Sgnn * ... 86235368Sgnn * cn: ospf 87235368Sgnn * cn: OSPFIGP 88235368Sgnn * ... 89235368Sgnn * 90235368Sgnn * For many ip* protocols, the aliases are mixed cased. Maybe it's case 91235368Sgnn * insensitive. But this fucntion tries to restore the aliases to the original 92235368Sgnn * form as much as possible. If the alias can't be found in the aliases table, 93235368Sgnn * it assumes the alias is all upper case. 94235368Sgnn * 95235368Sgnn */ 96235368Sgnnstatic char * 97235368Sgnnget_alias(char *protocol) { 98235368Sgnn int i; 99235368Sgnn char *cp; 100235368Sgnn 101235368Sgnn if (strncmp(protocol, "ip", 2) == 0) { 102235368Sgnn for (i = 0; ip_aliases[i].protocol != NULL; i++) { 103235368Sgnn if (strcmp(protocol, ip_aliases[i].protocol) == 0) 104235368Sgnn return (ip_aliases[i].alias); 105235368Sgnn } 106235368Sgnn /* 107235368Sgnn * No aliase in the table. Return an all upper case aliase 108235368Sgnn */ 109235368Sgnn for (cp = protocol; *cp; cp++) 110235368Sgnn *cp = toupper(*cp); 111235368Sgnn 112235368Sgnn return (protocol); 113235368Sgnn } else { 114235368Sgnn /* Return an all upper case aliase */ 115235368Sgnn for (cp = protocol; *cp; cp++) 116235368Sgnn *cp = toupper(*cp); 117235368Sgnn 118235368Sgnn return (protocol); 119235368Sgnn } 120235368Sgnn 121235368Sgnn} 122235368Sgnn/* 123235368Sgnn * _nss_ldap_protocols2str is the data marshaling method for the protocols 124235368Sgnn * getXbyY * (e.g., getbyname(), getbynumber(), getent()) backend processes. 125235368Sgnn * This method is called after a successful ldap search has been performed. 126235368Sgnn * This method will parse the ldap search values into a file format. 127235368Sgnn * e.g. 128235368Sgnn * idrp 45 IDRP 129235368Sgnn * or 130235368Sgnn * ospf 89 OSPFIGP 131235368Sgnn */ 132235368Sgnn 133235368Sgnnstatic int 134235368Sgnn_nss_ldap_protocols2str(ldap_backend_ptr be, nss_XbyY_args_t *argp) 135235368Sgnn{ 136235368Sgnn uint_t i; 137235368Sgnn int nss_result; 138235368Sgnn int buflen = 0, len; 139235368Sgnn char *cname = NULL; 140235368Sgnn char *buffer = NULL, **number, *alias; 141235368Sgnn ns_ldap_result_t *result = be->result; 142235368Sgnn ns_ldap_attr_t *names; 143235368Sgnn 144235368Sgnn if (result == NULL) 145235368Sgnn return (NSS_STR_PARSE_PARSE); 146235368Sgnn 147235368Sgnn buflen = argp->buf.buflen; 148235368Sgnn if (argp->buf.result != NULL) { 149235368Sgnn if ((be->buffer = calloc(1, buflen)) == NULL) { 150235368Sgnn nss_result = NSS_STR_PARSE_PARSE; 151235368Sgnn goto result_pls2str; 152235368Sgnn } 153235368Sgnn buffer = be->buffer; 154235368Sgnn } else 155235368Sgnn buffer = argp->buf.buffer; 156235368Sgnn 157235368Sgnn nss_result = NSS_STR_PARSE_SUCCESS; 158235368Sgnn (void) memset(argp->buf.buffer, 0, buflen); 159235368Sgnn 160235368Sgnn names = __ns_ldap_getAttrStruct(result->entry, _P_NAME); 161235368Sgnn if (names == NULL || names->attrvalue == NULL) { 162235368Sgnn nss_result = NSS_STR_PARSE_PARSE; 163235368Sgnn goto result_pls2str; 164235368Sgnn } 165235368Sgnn /* Get the canonical name */ 166235368Sgnn cname = __s_api_get_canonical_name(result->entry, names, 1); 167235368Sgnn if (cname == NULL || (len = strlen(cname)) < 1) { 168235368Sgnn nss_result = NSS_STR_PARSE_PARSE; 169235368Sgnn goto result_pls2str; 170235368Sgnn } 171235368Sgnn number = __ns_ldap_getAttr(result->entry, _P_PROTO); 172235368Sgnn if (number == NULL || number[0] == NULL || 173235368Sgnn (len = strlen(number[0])) < 1) { 174235368Sgnn nss_result = NSS_STR_PARSE_PARSE; 175235368Sgnn goto result_pls2str; 176235368Sgnn } 177235368Sgnn len = snprintf(buffer, buflen, "%s %s", cname, number[0]); 178235368Sgnn TEST_AND_ADJUST(len, buffer, buflen, result_pls2str); 179235368Sgnn /* Append aliases */ 180235368Sgnn if (names->value_count == 1) { 181235368Sgnn /* create an aliase from protocol name */ 182235368Sgnn alias = get_alias(cname); 183235368Sgnn len = snprintf(buffer, buflen, " %s", alias); 184235368Sgnn TEST_AND_ADJUST(len, buffer, buflen, result_pls2str); 185235368Sgnn 186235368Sgnn } else { 187235368Sgnn for (i = 0; i < names->value_count; i++) { 188235368Sgnn if (names->attrvalue[i] == NULL) { 189235368Sgnn nss_result = NSS_STR_PARSE_PARSE; 190235368Sgnn goto result_pls2str; 191235368Sgnn } 192235368Sgnn /* Skip the canonical name */ 193235368Sgnn if (strcasecmp(names->attrvalue[i], cname) != 0) { 194235368Sgnn len = snprintf(buffer, buflen, " %s", 195235368Sgnn names->attrvalue[i]); 196235368Sgnn TEST_AND_ADJUST(len, buffer, buflen, 197235368Sgnn result_pls2str); 198235368Sgnn } 199235368Sgnn } 200235368Sgnn } 201235368Sgnn 202235368Sgnn /* The front end marshaller doesn't need to copy trailing nulls */ 203235368Sgnn if (argp->buf.result != NULL) 204235368Sgnn be->buflen = strlen(be->buffer); 205235368Sgnn 206235368Sgnnresult_pls2str: 207235368Sgnn 208235368Sgnn (void) __ns_ldap_freeResult(&be->result); 209235368Sgnn return ((int)nss_result); 210235368Sgnn} 211235368Sgnn 212235368Sgnn 213235368Sgnn/* 214235368Sgnn * getbyname gets struct protoent values by protocol name. This 215235368Sgnn * function constructs an ldap search filter using the protocol 216235368Sgnn * name invocation parameter and the getprotobyname search filter 217235368Sgnn * defined. Once the filter is constructed, we search for a matching 218235368Sgnn * entry and marshal the data results into *proto = (struct * 219235368Sgnn * protoent *)argp->buf.result. The function _nss_ldap_protocols2ent 220235368Sgnn * performs the data marshaling. 221235368Sgnn */ 222235368Sgnn 223235368Sgnnstatic nss_status_t 224235368Sgnngetbyname(ldap_backend_ptr be, void *a) 225235368Sgnn{ 226235368Sgnn nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 227235368Sgnn char searchfilter[SEARCHFILTERLEN]; 228235368Sgnn char userdata[SEARCHFILTERLEN]; 229235368Sgnn char name[SEARCHFILTERLEN]; 230235368Sgnn int ret; 231235368Sgnn 232235368Sgnn if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0) 233235368Sgnn return ((nss_status_t)NSS_NOTFOUND); 234235368Sgnn 235235368Sgnn ret = snprintf(searchfilter, sizeof (searchfilter), 236235368Sgnn _F_GETPROTOBYNAME, name); 237235368Sgnn if (ret >= sizeof (searchfilter) || ret < 0) 238235368Sgnn return ((nss_status_t)NSS_NOTFOUND); 239235368Sgnn 240235368Sgnn ret = snprintf(userdata, sizeof (userdata), 241235368Sgnn _F_GETPROTOBYNAME_SSD, name); 242235368Sgnn if (ret >= sizeof (userdata) || ret < 0) 243235368Sgnn return ((nss_status_t)NSS_NOTFOUND); 244235368Sgnn 245235368Sgnn return ((nss_status_t)_nss_ldap_lookup(be, argp, 246235368Sgnn _PROTOCOLS, searchfilter, NULL, 247235368Sgnn _merge_SSD_filter, userdata)); 248235368Sgnn} 249235368Sgnn 250235368Sgnn 251235368Sgnn/* 252235368Sgnn * getbynumber gets struct protoent values by protocol number. This 253235368Sgnn * function constructs an ldap search filter using the protocol 254235368Sgnn * name invocation parameter and the getprotobynumber search filter 255235368Sgnn * defined. Once the filter is constructed, we search for a matching 256235368Sgnn * entry and marshal the data results into *proto = (struct * 257235368Sgnn * protoent *)argp->buf.result. The function _nss_ldap_protocols2ent 258235368Sgnn * performs the data marshaling. 259235368Sgnn */ 260235368Sgnn 261235368Sgnnstatic nss_status_t 262235368Sgnngetbynumber(ldap_backend_ptr be, void *a) 263235368Sgnn{ 264235368Sgnn nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 265235368Sgnn char searchfilter[SEARCHFILTERLEN]; 266235368Sgnn char userdata[SEARCHFILTERLEN]; 267235368Sgnn int ret; 268235368Sgnn 269235368Sgnn ret = snprintf(searchfilter, sizeof (searchfilter), 270235368Sgnn _F_GETPROTOBYNUMBER, argp->key.number); 271235368Sgnn if (ret >= sizeof (searchfilter) || ret < 0) 272235368Sgnn return ((nss_status_t)NSS_NOTFOUND); 273235368Sgnn 274235368Sgnn ret = snprintf(userdata, sizeof (userdata), 275235368Sgnn _F_GETPROTOBYNUMBER_SSD, argp->key.number); 276235368Sgnn if (ret >= sizeof (userdata) || ret < 0) 277235368Sgnn return ((nss_status_t)NSS_NOTFOUND); 278235368Sgnn 279235368Sgnn return ((nss_status_t)_nss_ldap_lookup(be, argp, 280235368Sgnn _PROTOCOLS, searchfilter, NULL, 281235368Sgnn _merge_SSD_filter, userdata)); 282235368Sgnn} 283235368Sgnn 284235368Sgnnstatic ldap_backend_op_t proto_ops[] = { 285235368Sgnn _nss_ldap_destr, 286235368Sgnn _nss_ldap_endent, 287235368Sgnn _nss_ldap_setent, 288235368Sgnn _nss_ldap_getent, 289235368Sgnn getbyname, 290235368Sgnn getbynumber 291235368Sgnn}; 292235368Sgnn 293235368Sgnn 294235368Sgnn/* 295235368Sgnn * _nss_ldap_protocols_constr is where life begins. This function calls 296235368Sgnn * the generic ldap constructor function to define and build the abstract 297235368Sgnn * data types required to support ldap operations. 298235368Sgnn */ 299235368Sgnn 300235368Sgnn/*ARGSUSED0*/ 301235368Sgnnnss_backend_t * 302235368Sgnn_nss_ldap_protocols_constr(const char *dummy1, const char *dummy2, 303235368Sgnn const char *dummy3) 304235368Sgnn{ 305235368Sgnn 306235368Sgnn return ((nss_backend_t *)_nss_ldap_constr(proto_ops, 307235368Sgnn sizeof (proto_ops)/sizeof (proto_ops[0]), _PROTOCOLS, 308235368Sgnn protocols_attrs, _nss_ldap_protocols2str)); 309235368Sgnn} 310235368Sgnn