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 <sys/types.h>
     30 #include <sys/socket.h>
     31 #include <netinet/in.h>
     32 #include <arpa/inet.h>
     33 #include <netdb.h>
     34 #include <stdlib.h>
     35 #include <string.h>
     36 #include <nss_dbdefs.h>
     37 
     38 
     39 int str2netent(const char *, int, void *, char *, int);
     40 
     41 static int net_stayopen;
     42 /*
     43  * Unsynchronized, but it affects only
     44  * efficiency, not correctness
     45  */
     46 
     47 static DEFINE_NSS_DB_ROOT(db_root);
     48 static DEFINE_NSS_GETENT(context);
     49 
     50 void
     51 _nss_initf_net(nss_db_params_t *p)
     52 {
     53 	p->name	= NSS_DBNAM_NETWORKS;
     54 	p->default_config = NSS_DEFCONF_NETWORKS;
     55 }
     56 
     57 struct netent *
     58 getnetbyname_r(const char *name, struct netent *result,
     59 	char *buffer, int buflen)
     60 {
     61 	nss_XbyY_args_t arg;
     62 	nss_status_t	res;
     63 
     64 	if (name == (const char *)NULL) {
     65 		errno = ERANGE;
     66 		return (NULL);
     67 	}
     68 	NSS_XbyY_INIT(&arg, result, buffer, buflen, str2netent);
     69 	arg.key.name	= name;
     70 	arg.stayopen	= net_stayopen;
     71 	res = nss_search(&db_root, _nss_initf_net,
     72 		NSS_DBOP_NETWORKS_BYNAME, &arg);
     73 	arg.status = res;
     74 	(void) NSS_XbyY_FINI(&arg);
     75 	return ((struct netent *)arg.returnval);
     76 }
     77 
     78 struct netent *
     79 getnetbyaddr_r(long net, int type, struct netent *result,
     80 	char *buffer, int buflen)
     81 {
     82 	nss_XbyY_args_t arg;
     83 	nss_status_t	res;
     84 
     85 	NSS_XbyY_INIT(&arg, result, buffer, buflen, str2netent);
     86 	arg.key.netaddr.net = (uint32_t)net;
     87 	arg.key.netaddr.type = type;
     88 	arg.stayopen	= net_stayopen;
     89 	res = nss_search(&db_root, _nss_initf_net,
     90 		NSS_DBOP_NETWORKS_BYADDR, &arg);
     91 	arg.status = res;
     92 	(void) NSS_XbyY_FINI(&arg);
     93 	return ((struct netent *)arg.returnval);
     94 }
     95 
     96 int
     97 setnetent(int stay)
     98 {
     99 	net_stayopen |= stay;	/* === Or maybe just "=" ? */
    100 	nss_setent(&db_root, _nss_initf_net, &context);
    101 	return (0);
    102 }
    103 
    104 int
    105 endnetent()
    106 {
    107 	net_stayopen = 0;
    108 	nss_endent(&db_root, _nss_initf_net, &context);
    109 	nss_delete(&db_root);
    110 	return (0);
    111 }
    112 
    113 struct netent *
    114 getnetent_r(struct netent *result, char *buffer, int buflen)
    115 {
    116 	nss_XbyY_args_t arg;
    117 	nss_status_t	res;
    118 
    119 	NSS_XbyY_INIT(&arg, result, buffer, buflen, str2netent);
    120 	/* No stayopen flag;  of course you stay open for iteration */
    121 	res = nss_getent(&db_root, _nss_initf_net, &context, &arg);
    122 	arg.status = res;
    123 	(void) NSS_XbyY_FINI(&arg);
    124 	return ((struct netent *)arg.returnval);
    125 }
    126 
    127 /*
    128  * Return values: 0 = success, 1 = parse error, 2 = erange ...
    129  * The structure pointer passed in is a structure in the caller's space
    130  * wherein the field pointers would be set to areas in the buffer if
    131  * need be. instring and buffer should be separate areas.
    132  */
    133 int
    134 str2netent(const char *instr, int lenstr,
    135 	void *ent /* really (struct netnet *) */, char *buffer, int buflen)
    136 {
    137 	struct netent	*net	= (struct netent *)ent;
    138 	const char	*p, *numstart, *limit, *namestart;
    139 	int		namelen = 0;
    140 	ptrdiff_t	numlen;
    141 	char		numbuf[16];
    142 
    143 	if ((instr >= buffer && (buffer + buflen) > instr) ||
    144 	    (buffer >= instr && (instr + lenstr) > buffer)) {
    145 		return (NSS_STR_PARSE_PARSE);
    146 	}
    147 
    148 	p = instr;
    149 	limit = p + lenstr;
    150 
    151 	while (p < limit && isspace(*p)) {
    152 		p++;
    153 	}
    154 	namestart = p;
    155 	while (p < limit && !isspace(*p)) {
    156 		p++;		/* Skip over the canonical name */
    157 	}
    158 	namelen = (int)(p - namestart);
    159 
    160 	if (buflen <= namelen) { /* not enough buffer */
    161 		return (NSS_STR_PARSE_ERANGE);
    162 	}
    163 	(void) memcpy(buffer, namestart, namelen);
    164 	buffer[namelen] = '\0';
    165 	net->n_name = buffer;
    166 
    167 	while (p < limit && isspace(*p)) {
    168 		p++;
    169 	}
    170 	if (p >= limit) {
    171 		/* Syntax error -- no net number */
    172 		return (NSS_STR_PARSE_PARSE);
    173 	}
    174 	numstart = p;
    175 	do {
    176 		p++;		/* Find the end of the net number */
    177 	} while (p < limit && !isspace(*p));
    178 	numlen = p - numstart;
    179 	if (numlen >= (ptrdiff_t)sizeof (numbuf)) {
    180 		/* Syntax error -- supposed number is too long */
    181 		return (NSS_STR_PARSE_PARSE);
    182 	}
    183 	(void) memcpy(numbuf, numstart, numlen);
    184 	numbuf[numlen] = '\0';
    185 	net->n_net = inet_network(numbuf);
    186 	if (net->n_net == (in_addr_t)-1) {
    187 		/* inet_network failed to parse the string */
    188 		return (NSS_STR_PARSE_PARSE);
    189 	}
    190 
    191 	net->n_addrtype = AF_INET;
    192 
    193 	while (p < limit && isspace(*p)) {
    194 		p++;
    195 	}
    196 	/*
    197 	 * Although nss_files_XY_all calls us with # stripped,
    198 	 * we should be able to deal with it here in order to
    199 	 * be more useful.
    200 	 */
    201 	if (p >= limit || *p == '#') { /* no aliases, no problem */
    202 		char **ptr;
    203 
    204 		ptr = (char **)ROUND_UP(buffer + namelen + 1,
    205 							sizeof (char *));
    206 		if ((char *)ptr >= buffer + buflen) {
    207 			net->n_aliases = 0; /* hope they don't try to peek in */
    208 			return (NSS_STR_PARSE_ERANGE);
    209 		} else {
    210 			*ptr = 0;
    211 			net->n_aliases = ptr;
    212 			return (NSS_STR_PARSE_SUCCESS);
    213 		}
    214 	}
    215 	net->n_aliases = _nss_netdb_aliases(p, lenstr - (int)(p - instr),
    216 				buffer + namelen + 1, buflen - namelen - 1);
    217 	return (NSS_STR_PARSE_SUCCESS);
    218 }
    219