1*86d7f5d3SJohn Marino /*-
2*86d7f5d3SJohn Marino * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru>
3*86d7f5d3SJohn Marino * All rights reserved.
4*86d7f5d3SJohn Marino *
5*86d7f5d3SJohn Marino * Redistribution and use in source and binary forms, with or without
6*86d7f5d3SJohn Marino * modification, are permitted provided that the following conditions
7*86d7f5d3SJohn Marino * are met:
8*86d7f5d3SJohn Marino * 1. Redistributions of source code must retain the above copyright
9*86d7f5d3SJohn Marino * notice, this list of conditions and the following disclaimer.
10*86d7f5d3SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright
11*86d7f5d3SJohn Marino * notice, this list of conditions and the following disclaimer in the
12*86d7f5d3SJohn Marino * documentation and/or other materials provided with the distribution.
13*86d7f5d3SJohn Marino *
14*86d7f5d3SJohn Marino * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*86d7f5d3SJohn Marino * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*86d7f5d3SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*86d7f5d3SJohn Marino * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*86d7f5d3SJohn Marino * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*86d7f5d3SJohn Marino * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*86d7f5d3SJohn Marino * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*86d7f5d3SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*86d7f5d3SJohn Marino * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*86d7f5d3SJohn Marino * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*86d7f5d3SJohn Marino * SUCH DAMAGE.
25*86d7f5d3SJohn Marino *
26*86d7f5d3SJohn Marino * $FreeBSD: src/usr.sbin/nscd/agents/services.c,v 1.4 2008/10/23 00:15:00 delphij Exp $
27*86d7f5d3SJohn Marino */
28*86d7f5d3SJohn Marino
29*86d7f5d3SJohn Marino #include <sys/param.h>
30*86d7f5d3SJohn Marino #include <sys/types.h>
31*86d7f5d3SJohn Marino #include <assert.h>
32*86d7f5d3SJohn Marino #include <nsswitch.h>
33*86d7f5d3SJohn Marino #include <netdb.h>
34*86d7f5d3SJohn Marino #include <string.h>
35*86d7f5d3SJohn Marino #include <stdlib.h>
36*86d7f5d3SJohn Marino #include "../debug.h"
37*86d7f5d3SJohn Marino #include "services.h"
38*86d7f5d3SJohn Marino
39*86d7f5d3SJohn Marino static int services_marshal_func(struct servent *, char *, size_t *);
40*86d7f5d3SJohn Marino static int services_lookup_func(const char *, size_t, char **, size_t *);
41*86d7f5d3SJohn Marino static void *services_mp_init_func(void);
42*86d7f5d3SJohn Marino static int services_mp_lookup_func(char **, size_t *, void *);
43*86d7f5d3SJohn Marino static void services_mp_destroy_func(void *);
44*86d7f5d3SJohn Marino
45*86d7f5d3SJohn Marino static int
services_marshal_func(struct servent * serv,char * buffer,size_t * buffer_size)46*86d7f5d3SJohn Marino services_marshal_func(struct servent *serv, char *buffer, size_t *buffer_size)
47*86d7f5d3SJohn Marino {
48*86d7f5d3SJohn Marino struct servent new_serv;
49*86d7f5d3SJohn Marino size_t desired_size;
50*86d7f5d3SJohn Marino char **alias;
51*86d7f5d3SJohn Marino char *p;
52*86d7f5d3SJohn Marino size_t size;
53*86d7f5d3SJohn Marino size_t aliases_size;
54*86d7f5d3SJohn Marino
55*86d7f5d3SJohn Marino TRACE_IN(services_marshal_func);
56*86d7f5d3SJohn Marino desired_size = ALIGNBYTES + sizeof(struct servent) + sizeof(char *);
57*86d7f5d3SJohn Marino if (serv->s_name != NULL)
58*86d7f5d3SJohn Marino desired_size += strlen(serv->s_name) + 1;
59*86d7f5d3SJohn Marino if (serv->s_proto != NULL)
60*86d7f5d3SJohn Marino desired_size += strlen(serv->s_proto) + 1;
61*86d7f5d3SJohn Marino
62*86d7f5d3SJohn Marino aliases_size = 0;
63*86d7f5d3SJohn Marino if (serv->s_aliases != NULL) {
64*86d7f5d3SJohn Marino for (alias = serv->s_aliases; *alias; ++alias) {
65*86d7f5d3SJohn Marino desired_size += strlen(*alias) + 1;
66*86d7f5d3SJohn Marino ++aliases_size;
67*86d7f5d3SJohn Marino }
68*86d7f5d3SJohn Marino
69*86d7f5d3SJohn Marino desired_size += ALIGNBYTES + sizeof(char *) *
70*86d7f5d3SJohn Marino (aliases_size + 1);
71*86d7f5d3SJohn Marino }
72*86d7f5d3SJohn Marino
73*86d7f5d3SJohn Marino if ((*buffer_size < desired_size) || (buffer == NULL)) {
74*86d7f5d3SJohn Marino *buffer_size = desired_size;
75*86d7f5d3SJohn Marino TRACE_OUT(services_marshal_func);
76*86d7f5d3SJohn Marino return (NS_RETURN);
77*86d7f5d3SJohn Marino }
78*86d7f5d3SJohn Marino
79*86d7f5d3SJohn Marino memcpy(&new_serv, serv, sizeof(struct servent));
80*86d7f5d3SJohn Marino memset(buffer, 0, desired_size);
81*86d7f5d3SJohn Marino
82*86d7f5d3SJohn Marino *buffer_size = desired_size;
83*86d7f5d3SJohn Marino p = buffer + sizeof(struct servent) + sizeof(char *);
84*86d7f5d3SJohn Marino memcpy(buffer + sizeof(struct servent), &p, sizeof(char *));
85*86d7f5d3SJohn Marino p = (char *)ALIGN(p);
86*86d7f5d3SJohn Marino
87*86d7f5d3SJohn Marino if (new_serv.s_name != NULL) {
88*86d7f5d3SJohn Marino size = strlen(new_serv.s_name);
89*86d7f5d3SJohn Marino memcpy(p, new_serv.s_name, size);
90*86d7f5d3SJohn Marino new_serv.s_name = p;
91*86d7f5d3SJohn Marino p += size + 1;
92*86d7f5d3SJohn Marino }
93*86d7f5d3SJohn Marino
94*86d7f5d3SJohn Marino if (new_serv.s_proto != NULL) {
95*86d7f5d3SJohn Marino size = strlen(new_serv.s_proto);
96*86d7f5d3SJohn Marino memcpy(p, new_serv.s_proto, size);
97*86d7f5d3SJohn Marino new_serv.s_proto = p;
98*86d7f5d3SJohn Marino p += size + 1;
99*86d7f5d3SJohn Marino }
100*86d7f5d3SJohn Marino
101*86d7f5d3SJohn Marino if (new_serv.s_aliases != NULL) {
102*86d7f5d3SJohn Marino p = (char *)ALIGN(p);
103*86d7f5d3SJohn Marino memcpy(p, new_serv.s_aliases, sizeof(char *) * aliases_size);
104*86d7f5d3SJohn Marino new_serv.s_aliases = (char **)p;
105*86d7f5d3SJohn Marino p += sizeof(char *) * (aliases_size + 1);
106*86d7f5d3SJohn Marino
107*86d7f5d3SJohn Marino for (alias = new_serv.s_aliases; *alias; ++alias) {
108*86d7f5d3SJohn Marino size = strlen(*alias);
109*86d7f5d3SJohn Marino memcpy(p, *alias, size);
110*86d7f5d3SJohn Marino *alias = p;
111*86d7f5d3SJohn Marino p += size + 1;
112*86d7f5d3SJohn Marino }
113*86d7f5d3SJohn Marino }
114*86d7f5d3SJohn Marino
115*86d7f5d3SJohn Marino memcpy(buffer, &new_serv, sizeof(struct servent));
116*86d7f5d3SJohn Marino TRACE_OUT(services_marshal_func);
117*86d7f5d3SJohn Marino return (NS_SUCCESS);
118*86d7f5d3SJohn Marino }
119*86d7f5d3SJohn Marino
120*86d7f5d3SJohn Marino static int
services_lookup_func(const char * key,size_t key_size,char ** buffer,size_t * buffer_size)121*86d7f5d3SJohn Marino services_lookup_func(const char *key, size_t key_size, char **buffer,
122*86d7f5d3SJohn Marino size_t *buffer_size)
123*86d7f5d3SJohn Marino {
124*86d7f5d3SJohn Marino enum nss_lookup_type lookup_type;
125*86d7f5d3SJohn Marino char *name = NULL;
126*86d7f5d3SJohn Marino char *proto = NULL;
127*86d7f5d3SJohn Marino size_t size, size2;
128*86d7f5d3SJohn Marino int port;
129*86d7f5d3SJohn Marino
130*86d7f5d3SJohn Marino struct servent *result;
131*86d7f5d3SJohn Marino
132*86d7f5d3SJohn Marino TRACE_IN(services_lookup_func);
133*86d7f5d3SJohn Marino
134*86d7f5d3SJohn Marino assert(buffer != NULL);
135*86d7f5d3SJohn Marino assert(buffer_size != NULL);
136*86d7f5d3SJohn Marino
137*86d7f5d3SJohn Marino if (key_size < sizeof(enum nss_lookup_type)) {
138*86d7f5d3SJohn Marino TRACE_OUT(passwd_lookup_func);
139*86d7f5d3SJohn Marino return (NS_UNAVAIL);
140*86d7f5d3SJohn Marino }
141*86d7f5d3SJohn Marino memcpy(&lookup_type, key, sizeof(enum nss_lookup_type));
142*86d7f5d3SJohn Marino
143*86d7f5d3SJohn Marino switch (lookup_type) {
144*86d7f5d3SJohn Marino case nss_lt_name:
145*86d7f5d3SJohn Marino size = key_size - sizeof(enum nss_lookup_type);
146*86d7f5d3SJohn Marino name = (char *)calloc(1, size + 1);
147*86d7f5d3SJohn Marino assert(name != NULL);
148*86d7f5d3SJohn Marino memcpy(name, key + sizeof(enum nss_lookup_type), size);
149*86d7f5d3SJohn Marino
150*86d7f5d3SJohn Marino size2 = strlen(name) + 1;
151*86d7f5d3SJohn Marino
152*86d7f5d3SJohn Marino if (size2 < size)
153*86d7f5d3SJohn Marino proto = name + size2;
154*86d7f5d3SJohn Marino else
155*86d7f5d3SJohn Marino proto = NULL;
156*86d7f5d3SJohn Marino break;
157*86d7f5d3SJohn Marino case nss_lt_id:
158*86d7f5d3SJohn Marino if (key_size < sizeof(enum nss_lookup_type) +
159*86d7f5d3SJohn Marino sizeof(int)) {
160*86d7f5d3SJohn Marino TRACE_OUT(passwd_lookup_func);
161*86d7f5d3SJohn Marino return (NS_UNAVAIL);
162*86d7f5d3SJohn Marino }
163*86d7f5d3SJohn Marino
164*86d7f5d3SJohn Marino memcpy(&port, key + sizeof(enum nss_lookup_type),
165*86d7f5d3SJohn Marino sizeof(int));
166*86d7f5d3SJohn Marino
167*86d7f5d3SJohn Marino size = key_size - sizeof(enum nss_lookup_type) - sizeof(int);
168*86d7f5d3SJohn Marino if (size > 0) {
169*86d7f5d3SJohn Marino proto = (char *)calloc(1, size + 1);
170*86d7f5d3SJohn Marino assert(proto != NULL);
171*86d7f5d3SJohn Marino memcpy(proto, key + sizeof(enum nss_lookup_type) +
172*86d7f5d3SJohn Marino sizeof(int), size);
173*86d7f5d3SJohn Marino }
174*86d7f5d3SJohn Marino break;
175*86d7f5d3SJohn Marino default:
176*86d7f5d3SJohn Marino TRACE_OUT(passwd_lookup_func);
177*86d7f5d3SJohn Marino return (NS_UNAVAIL);
178*86d7f5d3SJohn Marino }
179*86d7f5d3SJohn Marino
180*86d7f5d3SJohn Marino switch (lookup_type) {
181*86d7f5d3SJohn Marino case nss_lt_name:
182*86d7f5d3SJohn Marino result = getservbyname(name, proto);
183*86d7f5d3SJohn Marino free(name);
184*86d7f5d3SJohn Marino break;
185*86d7f5d3SJohn Marino case nss_lt_id:
186*86d7f5d3SJohn Marino result = getservbyport(port, proto);
187*86d7f5d3SJohn Marino free(proto);
188*86d7f5d3SJohn Marino break;
189*86d7f5d3SJohn Marino default:
190*86d7f5d3SJohn Marino /* SHOULD NOT BE REACHED */
191*86d7f5d3SJohn Marino break;
192*86d7f5d3SJohn Marino }
193*86d7f5d3SJohn Marino
194*86d7f5d3SJohn Marino if (result != NULL) {
195*86d7f5d3SJohn Marino services_marshal_func(result, NULL, buffer_size);
196*86d7f5d3SJohn Marino *buffer = (char *)malloc(*buffer_size);
197*86d7f5d3SJohn Marino assert(*buffer != NULL);
198*86d7f5d3SJohn Marino services_marshal_func(result, *buffer, buffer_size);
199*86d7f5d3SJohn Marino }
200*86d7f5d3SJohn Marino
201*86d7f5d3SJohn Marino TRACE_OUT(services_lookup_func);
202*86d7f5d3SJohn Marino return (result == NULL ? NS_NOTFOUND : NS_SUCCESS);
203*86d7f5d3SJohn Marino }
204*86d7f5d3SJohn Marino
205*86d7f5d3SJohn Marino static void *
services_mp_init_func(void)206*86d7f5d3SJohn Marino services_mp_init_func(void)
207*86d7f5d3SJohn Marino {
208*86d7f5d3SJohn Marino TRACE_IN(services_mp_init_func);
209*86d7f5d3SJohn Marino setservent(0);
210*86d7f5d3SJohn Marino TRACE_OUT(services_mp_init_func);
211*86d7f5d3SJohn Marino
212*86d7f5d3SJohn Marino return (NULL);
213*86d7f5d3SJohn Marino }
214*86d7f5d3SJohn Marino
215*86d7f5d3SJohn Marino static int
services_mp_lookup_func(char ** buffer,size_t * buffer_size,void * mdata)216*86d7f5d3SJohn Marino services_mp_lookup_func(char **buffer, size_t *buffer_size, void *mdata)
217*86d7f5d3SJohn Marino {
218*86d7f5d3SJohn Marino struct servent *result;
219*86d7f5d3SJohn Marino
220*86d7f5d3SJohn Marino TRACE_IN(services_mp_lookup_func);
221*86d7f5d3SJohn Marino result = getservent();
222*86d7f5d3SJohn Marino if (result != NULL) {
223*86d7f5d3SJohn Marino services_marshal_func(result, NULL, buffer_size);
224*86d7f5d3SJohn Marino *buffer = (char *)malloc(*buffer_size);
225*86d7f5d3SJohn Marino assert(*buffer != NULL);
226*86d7f5d3SJohn Marino services_marshal_func(result, *buffer, buffer_size);
227*86d7f5d3SJohn Marino }
228*86d7f5d3SJohn Marino
229*86d7f5d3SJohn Marino TRACE_OUT(services_mp_lookup_func);
230*86d7f5d3SJohn Marino return (result == NULL ? NS_NOTFOUND : NS_SUCCESS);
231*86d7f5d3SJohn Marino }
232*86d7f5d3SJohn Marino
233*86d7f5d3SJohn Marino static void
services_mp_destroy_func(void * mdata)234*86d7f5d3SJohn Marino services_mp_destroy_func(void *mdata)
235*86d7f5d3SJohn Marino {
236*86d7f5d3SJohn Marino TRACE_IN(services_mp_destroy_func);
237*86d7f5d3SJohn Marino TRACE_OUT(services_mp_destroy_func);
238*86d7f5d3SJohn Marino }
239*86d7f5d3SJohn Marino
240*86d7f5d3SJohn Marino struct agent *
init_services_agent(void)241*86d7f5d3SJohn Marino init_services_agent(void)
242*86d7f5d3SJohn Marino {
243*86d7f5d3SJohn Marino struct common_agent *retval;
244*86d7f5d3SJohn Marino TRACE_IN(init_services_agent);
245*86d7f5d3SJohn Marino
246*86d7f5d3SJohn Marino retval = (struct common_agent *)calloc(1, sizeof(struct common_agent));
247*86d7f5d3SJohn Marino assert(retval != NULL);
248*86d7f5d3SJohn Marino
249*86d7f5d3SJohn Marino retval->parent.name = strdup("services");
250*86d7f5d3SJohn Marino assert(retval->parent.name != NULL);
251*86d7f5d3SJohn Marino
252*86d7f5d3SJohn Marino retval->parent.type = COMMON_AGENT;
253*86d7f5d3SJohn Marino retval->lookup_func = services_lookup_func;
254*86d7f5d3SJohn Marino
255*86d7f5d3SJohn Marino TRACE_OUT(init_services_agent);
256*86d7f5d3SJohn Marino return ((struct agent *)retval);
257*86d7f5d3SJohn Marino }
258*86d7f5d3SJohn Marino
259*86d7f5d3SJohn Marino struct agent *
init_services_mp_agent(void)260*86d7f5d3SJohn Marino init_services_mp_agent(void)
261*86d7f5d3SJohn Marino {
262*86d7f5d3SJohn Marino struct multipart_agent *retval;
263*86d7f5d3SJohn Marino
264*86d7f5d3SJohn Marino TRACE_IN(init_services_mp_agent);
265*86d7f5d3SJohn Marino retval = (struct multipart_agent *)calloc(1,
266*86d7f5d3SJohn Marino sizeof(struct multipart_agent));
267*86d7f5d3SJohn Marino assert(retval != NULL);
268*86d7f5d3SJohn Marino
269*86d7f5d3SJohn Marino retval->parent.name = strdup("services");
270*86d7f5d3SJohn Marino retval->parent.type = MULTIPART_AGENT;
271*86d7f5d3SJohn Marino retval->mp_init_func = services_mp_init_func;
272*86d7f5d3SJohn Marino retval->mp_lookup_func = services_mp_lookup_func;
273*86d7f5d3SJohn Marino retval->mp_destroy_func = services_mp_destroy_func;
274*86d7f5d3SJohn Marino assert(retval->parent.name != NULL);
275*86d7f5d3SJohn Marino
276*86d7f5d3SJohn Marino TRACE_OUT(init_services_mp_agent);
277*86d7f5d3SJohn Marino return ((struct agent *)retval);
278*86d7f5d3SJohn Marino }
279