Home | History | Annotate | Download | only in inet
      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 (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      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.
     12  *
     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]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     27 
     28 #include <ctype.h>
     29 #include <netdb.h>
     30 #include <stdlib.h>
     31 #include <string.h>
     32 #include <nss_dbdefs.h>
     33 
     34 int str2protoent(const char *, int, void *,
     35 		char *, int);
     36 
     37 static int proto_stayopen;
     38 /*
     39  * Unsynchronized, but it affects only
     40  * efficiency, not correctness
     41  */
     42 
     43 static DEFINE_NSS_DB_ROOT(db_root);
     44 static DEFINE_NSS_GETENT(context);
     45 
     46 void
     47 _nss_initf_proto(nss_db_params_t *p)
     48 {
     49 	p->name	= NSS_DBNAM_PROTOCOLS;
     50 	p->default_config = NSS_DEFCONF_PROTOCOLS;
     51 }
     52 
     53 struct protoent *
     54 getprotobyname_r(const char *name, struct protoent *result,
     55 	char *buffer, int buflen)
     56 {
     57 	nss_XbyY_args_t arg;
     58 	nss_status_t	res;
     59 
     60 	if (name == (const char *)NULL) {
     61 		errno = ERANGE;
     62 		return (NULL);
     63 	}
     64 	NSS_XbyY_INIT(&arg, result, buffer, buflen, str2protoent);
     65 	arg.key.name	= name;
     66 	arg.stayopen	= proto_stayopen;
     67 	res = nss_search(&db_root, _nss_initf_proto,
     68 		NSS_DBOP_PROTOCOLS_BYNAME, &arg);
     69 	arg.status = res;
     70 	(void) NSS_XbyY_FINI(&arg);
     71 	return ((struct protoent *)arg.returnval);
     72 }
     73 
     74 struct protoent *
     75 getprotobynumber_r(int proto, struct protoent *result, char *buffer, int buflen)
     76 {
     77 	nss_XbyY_args_t arg;
     78 	nss_status_t	res;
     79 
     80 	NSS_XbyY_INIT(&arg, result, buffer, buflen, str2protoent);
     81 	arg.key.number = proto;
     82 	arg.stayopen	= proto_stayopen;
     83 	res = nss_search(&db_root, _nss_initf_proto,
     84 		NSS_DBOP_PROTOCOLS_BYNUMBER, &arg);
     85 	arg.status = res;
     86 	(void) NSS_XbyY_FINI(&arg);
     87 	return ((struct protoent *)arg.returnval);
     88 }
     89 
     90 int
     91 setprotoent(int stay)
     92 {
     93 	proto_stayopen = stay;
     94 	nss_setent(&db_root, _nss_initf_proto, &context);
     95 	return (0);
     96 }
     97 
     98 int
     99 endprotoent()
    100 {
    101 	proto_stayopen = 0;
    102 	nss_endent(&db_root, _nss_initf_proto, &context);
    103 	nss_delete(&db_root);
    104 	return (0);
    105 }
    106 
    107 struct protoent *
    108 getprotoent_r(struct protoent *result, char *buffer, int buflen)
    109 {
    110 	nss_XbyY_args_t arg;
    111 	nss_status_t	res;
    112 
    113 	NSS_XbyY_INIT(&arg, result, buffer, buflen, str2protoent);
    114 	/* No stayopen flag;  of course you stay open for iteration */
    115 	res = nss_getent(&db_root, _nss_initf_proto, &context, &arg);
    116 	arg.status = res;
    117 	(void) NSS_XbyY_FINI(&arg);
    118 	return ((struct protoent *)arg.returnval);
    119 }
    120 
    121 /*
    122  * Return values: 0 = success, 1 = parse error, 2 = erange ...
    123  * The structure pointer passed in is a structure in the caller's space
    124  * wherein the field pointers would be set to areas in the buffer if
    125  * need be. instring and buffer should be separate areas. Let's not
    126  * fight over crumbs.
    127  */
    128 int
    129 str2protoent(const char *instr, int lenstr,
    130 	void *ent /* it is really (struct protoent *) */,
    131 	char *buffer, int buflen)
    132 {
    133 	struct	protoent *proto = (struct protoent *)ent;
    134 	const char	*p, *numstart, *namestart, *limit;
    135 	int		numlen, namelen = 0;
    136 	char		numbuf[16];
    137 	char		*numend;
    138 
    139 	if ((instr >= buffer && (buffer + buflen) > instr) ||
    140 	    (buffer >= instr && (instr + lenstr) > buffer)) {
    141 		return (NSS_STR_PARSE_PARSE);
    142 	}
    143 
    144 	p = instr;
    145 	limit = p + lenstr;
    146 
    147 	while (p < limit && isspace(*p)) {
    148 		p++;
    149 	}
    150 	namestart = p;
    151 	while (p < limit && !isspace(*p)) {
    152 		p++;		/* Skip over the canonical name */
    153 	}
    154 	namelen = (int)(p - namestart);
    155 
    156 	if (buflen <= namelen) { /* not enough buffer */
    157 		return (NSS_STR_PARSE_ERANGE);
    158 	}
    159 	(void) memcpy(buffer, namestart, namelen);
    160 	buffer[namelen] = '\0';
    161 	proto->p_name = buffer;
    162 
    163 	while (p < limit && isspace(*p)) {
    164 		p++;
    165 	}
    166 	if (p >= limit) {
    167 		/* Syntax error -- no proto number */
    168 		return (NSS_STR_PARSE_PARSE);
    169 	}
    170 	numstart = p;
    171 	do {
    172 		p++;		/* Find the end of the proto number */
    173 	} while (p < limit && !isspace(*p));
    174 	numlen = (int)(p - numstart);
    175 	if (numlen >= (int)sizeof (numbuf)) {
    176 		/* Syntax error -- supposed number is too long */
    177 		return (NSS_STR_PARSE_PARSE);
    178 	}
    179 	(void) memcpy(numbuf, numstart, (size_t)numlen);
    180 	numbuf[numlen] = '\0';
    181 	proto->p_proto = (int)strtol(numbuf, &numend, 10);
    182 	if (*numend != '\0') {
    183 		/* Syntax error -- protocol number isn't a number */
    184 		return (NSS_STR_PARSE_PARSE);
    185 	}
    186 
    187 	while (p < limit && isspace(*p)) {
    188 		p++;
    189 	}
    190 	/*
    191 	 * Although nss_files_XY_all calls us with # stripped,
    192 	 * we should be able to deal with it here in order to
    193 	 * be more useful.
    194 	 */
    195 	if (p >= limit || *p == '#') { /* no aliases, no problem */
    196 		char **ptr;
    197 
    198 		ptr = (char **)ROUND_UP(buffer + namelen + 1,
    199 							sizeof (char *));
    200 		if ((char *)ptr >= buffer + buflen) {
    201 			/* hope they don't try to peek in */
    202 			proto->p_aliases = 0;
    203 			return (NSS_STR_PARSE_ERANGE);
    204 		} else {
    205 			*ptr = 0;
    206 			proto->p_aliases = ptr;
    207 			return (NSS_STR_PARSE_SUCCESS);
    208 		}
    209 	}
    210 	proto->p_aliases = _nss_netdb_aliases(p, lenstr - (int)(p - instr),
    211 				buffer + namelen + 1, buflen - namelen - 1);
    212 	return (NSS_STR_PARSE_SUCCESS);
    213 }
    214