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 * files/getservent.c -- "files" backend for nsswitch "services" database
26 */
27
28 #pragma ident "%Z%%M% %I% %E% SMI"
29
30 #include <netdb.h>
31 #include "files_common.h"
32 #include <sys/types.h>
33 #include <netinet/in.h>
34 #include <inttypes.h>
35 #include <strings.h>
36 #include <ctype.h>
37 #include <stdlib.h>
38
39 static int
check_name(nss_XbyY_args_t * argp,const char * line,int linelen)40 check_name(nss_XbyY_args_t *argp, const char *line, int linelen)
41 {
42 const char *limit, *linep, *keyp;
43 int name_match = 0;
44
45 linep = line;
46 limit = line + linelen;
47 keyp = argp->key.serv.serv.name;
48
49 /* compare name */
50 while (*keyp && linep < limit && !isspace(*linep) && *keyp == *linep) {
51 keyp++;
52 linep++;
53 }
54 if (*keyp == '\0' && linep < limit && isspace(*linep)) {
55 if (argp->key.serv.proto == NULL)
56 return (1);
57 else
58 name_match = 1;
59 }
60
61 /* skip remainder of the name, if any */
62 while (linep < limit && !isspace(*linep))
63 linep++;
64 /* skip the delimiting spaces */
65 while (linep < limit && isspace(*linep))
66 linep++;
67 /* skip port number */
68 while (linep < limit && !isspace(*linep) && *linep != '/')
69 linep++;
70 if (linep == limit || *linep != '/')
71 return (0);
72
73 linep++;
74 if ((keyp = argp->key.serv.proto) == NULL) {
75 /* skip protocol */
76 while (linep < limit && !isspace(*linep))
77 linep++;
78 } else {
79 /* compare protocol */
80 while (*keyp && linep < limit && !isspace(*linep) &&
81 *keyp == *linep) {
82 keyp++;
83 linep++;
84 }
85 /* no protocol match */
86 if (*keyp || (linep < limit && !isspace(*linep)))
87 return (0);
88 /* protocol and name match, return */
89 if (name_match)
90 return (1);
91 /* protocol match but name yet to be matched, so continue */
92 }
93
94 /* compare with the aliases */
95 while (linep < limit) {
96 /* skip the delimiting spaces */
97 while (linep < limit && isspace(*linep))
98 linep++;
99
100 /* compare with the alias name */
101 keyp = argp->key.serv.serv.name;
102 while (*keyp && linep < limit && !isspace(*linep) &&
103 *keyp == *linep) {
104 keyp++;
105 linep++;
106 }
107 if (*keyp == '\0' && (linep == limit || isspace(*linep)))
108 return (1);
109
110 /* skip remainder of the alias name, if any */
111 while (linep < limit && !isspace(*linep))
112 linep++;
113 }
114 return (0);
115 }
116
117 static nss_status_t
getbyname(be,a)118 getbyname(be, a)
119 files_backend_ptr_t be;
120 void *a;
121 {
122 nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
123
124 return (_nss_files_XY_all(be, argp, 1,
125 argp->key.serv.serv.name, check_name));
126 }
127
128 static int
check_port(nss_XbyY_args_t * argp,const char * line,int linelen)129 check_port(nss_XbyY_args_t *argp, const char *line, int linelen)
130 {
131 const char *limit, *linep, *keyp, *numstart;
132 int numlen, s_port;
133 char numbuf[12], *numend;
134
135 linep = line;
136 limit = line + linelen;
137
138 /* skip name */
139 while (linep < limit && !isspace(*linep))
140 linep++;
141 /* skip the delimiting spaces */
142 while (linep < limit && isspace(*linep))
143 linep++;
144
145 /* compare port num */
146 numstart = linep;
147 while (linep < limit && !isspace(*linep) && *linep != '/')
148 linep++;
149 if (linep == limit || *linep != '/')
150 return (0);
151 numlen = linep - numstart;
152 if (numlen == 0 || numlen >= sizeof (numbuf))
153 return (0);
154 (void) memcpy(numbuf, numstart, numlen);
155 numbuf[numlen] = '\0';
156 s_port = htons((int)strtol(numbuf, &numend, 10));
157 if (*numend != '\0')
158 return (0);
159 if (s_port == argp->key.serv.serv.port) {
160 if ((keyp = argp->key.serv.proto) == NULL)
161 return (1);
162 } else
163 return (0);
164
165 /* compare protocol */
166 linep++;
167 while (*keyp && linep < limit && !isspace(*linep) && *keyp == *linep) {
168 keyp++;
169 linep++;
170 }
171 return (*keyp == '\0' && (linep == limit || isspace(*linep)));
172 }
173
174 static nss_status_t
getbyport(be,a)175 getbyport(be, a)
176 files_backend_ptr_t be;
177 void *a;
178 {
179 nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
180 char portstr[12];
181
182 (void) snprintf(portstr, 12, "%d", ntohs(argp->key.serv.serv.port));
183 return (_nss_files_XY_all(be, argp, 1, portstr, check_port));
184 }
185
186 static files_backend_op_t serv_ops[] = {
187 _nss_files_destr,
188 _nss_files_endent,
189 _nss_files_setent,
190 _nss_files_getent_netdb,
191 getbyname,
192 getbyport
193 };
194
195 /*ARGSUSED*/
196 nss_backend_t *
_nss_files_services_constr(dummy1,dummy2,dummy3)197 _nss_files_services_constr(dummy1, dummy2, dummy3)
198 const char *dummy1, *dummy2, *dummy3;
199 {
200 return (_nss_files_constr(serv_ops,
201 sizeof (serv_ops) / sizeof (serv_ops[0]),
202 _PATH_SERVICES,
203 NSS_LINELEN_SERVICES,
204 NULL));
205 }
206