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