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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright (c) 1986-1992 by Sun Microsystems Inc.
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 static 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 static 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 	NSS_XbyY_INIT(&arg, result, buffer, buflen, str2protoent);
61 	arg.key.name	= name;
62 	arg.stayopen	= proto_stayopen;
63 	res = nss_search(&db_root, _nss_initf_proto,
64 		NSS_DBOP_PROTOCOLS_BYNAME, &arg);
65 	arg.status = res;
66 	(void) NSS_XbyY_FINI(&arg);
67 	return ((struct protoent *)arg.returnval);
68 }
69 
70 struct protoent *
71 getprotobynumber_r(int proto, struct protoent *result, char *buffer, int buflen)
72 {
73 	nss_XbyY_args_t arg;
74 	nss_status_t	res;
75 
76 	NSS_XbyY_INIT(&arg, result, buffer, buflen, str2protoent);
77 	arg.key.number = proto;
78 	arg.stayopen	= proto_stayopen;
79 	res = nss_search(&db_root, _nss_initf_proto,
80 		NSS_DBOP_PROTOCOLS_BYNUMBER, &arg);
81 	arg.status = res;
82 	(void) NSS_XbyY_FINI(&arg);
83 	return ((struct protoent *)arg.returnval);
84 }
85 
86 int
87 setprotoent(int stay)
88 {
89 	proto_stayopen = stay;
90 	nss_setent(&db_root, _nss_initf_proto, &context);
91 	return (0);
92 }
93 
94 int
95 endprotoent()
96 {
97 	proto_stayopen = 0;
98 	nss_endent(&db_root, _nss_initf_proto, &context);
99 	nss_delete(&db_root);
100 	return (0);
101 }
102 
103 struct protoent *
104 getprotoent_r(struct protoent *result, char *buffer, int buflen)
105 {
106 	nss_XbyY_args_t arg;
107 	nss_status_t	res;
108 
109 	NSS_XbyY_INIT(&arg, result, buffer, buflen, str2protoent);
110 	/* No stayopen flag;  of course you stay open for iteration */
111 	res = nss_getent(&db_root, _nss_initf_proto, &context, &arg);
112 	arg.status = res;
113 	(void) NSS_XbyY_FINI(&arg);
114 	return ((struct protoent *)arg.returnval);
115 }
116 
117 /*
118  * Return values: 0 = success, 1 = parse error, 2 = erange ...
119  * The structure pointer passed in is a structure in the caller's space
120  * wherein the field pointers would be set to areas in the buffer if
121  * need be. instring and buffer should be separate areas. Let's not
122  * fight over crumbs.
123  */
124 static int
125 str2protoent(const char *instr, int lenstr,
126 	void *ent /* it is really (struct protoent *) */,
127 	char *buffer, int buflen)
128 {
129 	struct	protoent *proto = (struct protoent *)ent;
130 	const char	*p, *numstart, *namestart, *limit;
131 	int		numlen, namelen = 0;
132 	char		numbuf[16];
133 	char		*numend;
134 
135 	if ((instr >= buffer && (buffer + buflen) > instr) ||
136 	    (buffer >= instr && (instr + lenstr) > buffer)) {
137 		return (NSS_STR_PARSE_PARSE);
138 	}
139 
140 	p = instr;
141 	limit = p + lenstr;
142 
143 	while (p < limit && isspace(*p)) {
144 		p++;
145 	}
146 	namestart = p;
147 	while (p < limit && !isspace(*p)) {
148 		p++;		/* Skip over the canonical name */
149 	}
150 	namelen = (int)(p - namestart);
151 
152 	if (buflen <= namelen) { /* not enough buffer */
153 		return (NSS_STR_PARSE_ERANGE);
154 	}
155 	(void) memcpy(buffer, namestart, namelen);
156 	buffer[namelen] = '\0';
157 	proto->p_name = buffer;
158 
159 	while (p < limit && isspace(*p)) {
160 		p++;
161 	}
162 	if (p >= limit) {
163 		/* Syntax error -- no proto number */
164 		return (NSS_STR_PARSE_PARSE);
165 	}
166 	numstart = p;
167 	do {
168 		p++;		/* Find the end of the proto number */
169 	} while (p < limit && !isspace(*p));
170 	numlen = (int)(p - numstart);
171 	if (numlen >= (int)sizeof (numbuf)) {
172 		/* Syntax error -- supposed number is too long */
173 		return (NSS_STR_PARSE_PARSE);
174 	}
175 	(void) memcpy(numbuf, numstart, (size_t)numlen);
176 	numbuf[numlen] = '\0';
177 	proto->p_proto = (int)strtol(numbuf, &numend, 10);
178 	if (*numend != '\0') {
179 		/* Syntax error -- protocol number isn't a number */
180 		return (NSS_STR_PARSE_PARSE);
181 	}
182 
183 	while (p < limit && isspace(*p)) {
184 		p++;
185 	}
186 	/*
187 	 * Although nss_files_XY_all calls us with # stripped,
188 	 * we should be able to deal with it here in order to
189 	 * be more useful.
190 	 */
191 	if (p >= limit || *p == '#') { /* no aliases, no problem */
192 		char **ptr;
193 
194 		ptr = (char **)ROUND_UP(buffer + namelen + 1,
195 							sizeof (char *));
196 		if ((char *)ptr >= buffer + buflen) {
197 			/* hope they don't try to peek in */
198 			proto->p_aliases = 0;
199 			return (NSS_STR_PARSE_ERANGE);
200 		} else {
201 			*ptr = 0;
202 			proto->p_aliases = ptr;
203 			return (NSS_STR_PARSE_SUCCESS);
204 		}
205 	}
206 	proto->p_aliases = _nss_netdb_aliases(p, lenstr - (int)(p - instr),
207 				buffer + namelen + 1, buflen - namelen - 1);
208 	return (NSS_STR_PARSE_SUCCESS);
209 }
210