source: rtems-libbsd/freebsd/lib/libc/net/getprotoent.c @ d48955b

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since d48955b was d48955b, checked in by Sebastian Huber <sebastian.huber@…>, on 11/06/13 at 08:02:16

Add and use <machine/rtems-bsd-user-space.h>

  • Property mode set to 100644
File size: 12.2 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3/*
4 * Copyright (c) 1983, 1993
5 *      The Regents of the University of California.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 4. Neither the name of the University nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#if defined(LIBC_SCCS) && !defined(lint)
33static char sccsid[] = "@(#)getprotoent.c       8.1 (Berkeley) 6/4/93";
34#endif /* LIBC_SCCS and not lint */
35#include <sys/cdefs.h>
36__FBSDID("$FreeBSD$");
37
38#include <rtems/bsd/sys/param.h>
39#include <rtems/bsd/sys/types.h>
40#include <sys/socket.h>
41#include <errno.h>
42#include <limits.h>
43#include <netdb.h>
44#include <nsswitch.h>
45#include <stdio.h>
46#include <stdlib.h>
47#include <string.h>
48#include "namespace.h"
49#include "reentrant.h"
50#include "un-namespace.h"
51#include "netdb_private.h"
52#ifdef NS_CACHING
53#include "nscache.h"
54#endif
55#include "nss_tls.h"
56
57static const ns_src defaultsrc[] = {
58        { NSSRC_FILES, NS_SUCCESS },
59        { NULL, 0 }
60};
61
62NETDB_THREAD_ALLOC(protoent_data)
63NETDB_THREAD_ALLOC(protodata)
64
65static void
66protoent_data_clear(struct protoent_data *ped)
67{
68        if (ped->fp) {
69                fclose(ped->fp);
70                ped->fp = NULL;
71        }
72}
73
74static void
75protoent_data_free(void *ptr)
76{
77        struct protoent_data *ped = ptr;
78
79        protoent_data_clear(ped);
80        free(ped);
81}
82
83static void
84protodata_free(void *ptr)
85{
86        free(ptr);
87}
88
89#ifdef NS_CACHING
90int
91__proto_id_func(char *buffer, size_t *buffer_size, va_list ap,
92    void *cache_mdata)
93{
94        char *name;
95        int proto;
96
97        size_t desired_size, size;
98        enum nss_lookup_type lookup_type;
99        int res = NS_UNAVAIL;
100
101        lookup_type = (enum nss_lookup_type)cache_mdata;
102        switch (lookup_type) {
103        case nss_lt_name:
104                name = va_arg(ap, char *);
105
106                size = strlen(name);
107                desired_size = sizeof(enum nss_lookup_type) + size + 1;
108                if (desired_size > *buffer_size) {
109                        res = NS_RETURN;
110                        goto fin;
111                }
112
113                memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
114                memcpy(buffer + sizeof(enum nss_lookup_type), name, size + 1);
115
116                res = NS_SUCCESS;
117                break;
118        case nss_lt_id:
119                proto = va_arg(ap, int);
120
121                desired_size = sizeof(enum nss_lookup_type) + sizeof(int);
122                if (desired_size > *buffer_size) {
123                        res = NS_RETURN;
124                        goto fin;
125                }
126
127                memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
128                memcpy(buffer + sizeof(enum nss_lookup_type), &proto,
129                        sizeof(int));
130
131                res = NS_SUCCESS;
132                break;
133        default:
134                /* should be unreachable */
135                return (NS_UNAVAIL);
136        }
137
138fin:
139        *buffer_size = desired_size;
140        return (res);
141}
142
143
144int
145__proto_marshal_func(char *buffer, size_t *buffer_size, void *retval,
146    va_list ap, void *cache_mdata)
147{
148        char *name;
149        int num;
150        struct protoent *proto;
151        char *orig_buf;
152        size_t orig_buf_size;
153
154        struct protoent new_proto;
155        size_t desired_size, size, aliases_size;
156        char *p;
157        char **alias;
158
159        switch ((enum nss_lookup_type)cache_mdata) {
160        case nss_lt_name:
161                name = va_arg(ap, char *);
162                break;
163        case nss_lt_id:
164                num = va_arg(ap, int);
165                break;
166        case nss_lt_all:
167                break;
168        default:
169                /* should be unreachable */
170                return (NS_UNAVAIL);
171        }
172
173        proto = va_arg(ap, struct protoent *);
174        orig_buf = va_arg(ap, char *);
175        orig_buf_size = va_arg(ap, size_t);
176
177        desired_size = _ALIGNBYTES + sizeof(struct protoent) + sizeof(char *);
178        if (proto->p_name != NULL)
179                desired_size += strlen(proto->p_name) + 1;
180
181        if (proto->p_aliases != NULL) {
182                aliases_size = 0;
183                for (alias = proto->p_aliases; *alias; ++alias) {
184                        desired_size += strlen(*alias) + 1;
185                        ++aliases_size;
186                }
187
188                desired_size += _ALIGNBYTES + (aliases_size + 1) *
189                    sizeof(char *);
190        }
191
192        if (*buffer_size < desired_size) {
193                /* this assignment is here for future use */
194                *buffer_size = desired_size;
195                return (NS_RETURN);
196        }
197
198        memcpy(&new_proto, proto, sizeof(struct protoent));
199
200        *buffer_size = desired_size;
201        memset(buffer, 0, desired_size);
202        p = buffer + sizeof(struct protoent) + sizeof(char *);
203        memcpy(buffer + sizeof(struct protoent), &p, sizeof(char *));
204        p = (char *)_ALIGN(p);
205
206        if (new_proto.p_name != NULL) {
207                size = strlen(new_proto.p_name);
208                memcpy(p, new_proto.p_name, size);
209                new_proto.p_name = p;
210                p += size + 1;
211        }
212
213        if (new_proto.p_aliases != NULL) {
214                p = (char *)_ALIGN(p);
215                memcpy(p, new_proto.p_aliases, sizeof(char *) * aliases_size);
216                new_proto.p_aliases = (char **)p;
217                p += sizeof(char *) * (aliases_size + 1);
218
219                for (alias = new_proto.p_aliases; *alias; ++alias) {
220                        size = strlen(*alias);
221                        memcpy(p, *alias, size);
222                        *alias = p;
223                        p += size + 1;
224                }
225        }
226
227        memcpy(buffer, &new_proto, sizeof(struct protoent));
228        return (NS_SUCCESS);
229}
230
231int
232__proto_unmarshal_func(char *buffer, size_t buffer_size, void *retval,
233    va_list ap, void *cache_mdata)
234{
235        char *name;
236        int num;
237        struct protoent *proto;
238        char *orig_buf;
239        size_t orig_buf_size;
240        int *ret_errno;
241
242        char *p;
243        char **alias;
244
245        switch ((enum nss_lookup_type)cache_mdata) {
246        case nss_lt_name:
247                name = va_arg(ap, char *);
248                break;
249        case nss_lt_id:
250                num = va_arg(ap, int);
251                break;
252        case nss_lt_all:
253                break;
254        default:
255                /* should be unreachable */
256                return (NS_UNAVAIL);
257        }
258
259        proto = va_arg(ap, struct protoent *);
260        orig_buf = va_arg(ap, char *);
261        orig_buf_size = va_arg(ap, size_t);
262        ret_errno = va_arg(ap, int *);
263
264        if (orig_buf_size <
265            buffer_size - sizeof(struct protoent) - sizeof(char *)) {
266                *ret_errno = ERANGE;
267                return (NS_RETURN);
268        }
269
270        memcpy(proto, buffer, sizeof(struct protoent));
271        memcpy(&p, buffer + sizeof(struct protoent), sizeof(char *));
272
273        orig_buf = (char *)_ALIGN(orig_buf);
274        memcpy(orig_buf, buffer + sizeof(struct protoent) + sizeof(char *) +
275            _ALIGN(p) - (size_t)p,
276            buffer_size - sizeof(struct protoent) - sizeof(char *) -
277            _ALIGN(p) + (size_t)p);
278        p = (char *)_ALIGN(p);
279
280        NS_APPLY_OFFSET(proto->p_name, orig_buf, p, char *);
281        if (proto->p_aliases != NULL) {
282                NS_APPLY_OFFSET(proto->p_aliases, orig_buf, p, char **);
283
284                for (alias = proto->p_aliases; *alias; ++alias)
285                        NS_APPLY_OFFSET(*alias, orig_buf, p, char *);
286        }
287
288        if (retval != NULL)
289                *((struct protoent **)retval) = proto;
290
291        return (NS_SUCCESS);
292}
293
294NSS_MP_CACHE_HANDLING(protocols);
295#endif /* NS_CACHING */
296
297int
298__copy_protoent(struct protoent *pe, struct protoent *pptr, char *buf,
299    size_t buflen)
300{
301        char *cp;
302        int i, n;
303        int numptr, len;
304
305        /* Find out the amount of space required to store the answer. */
306        numptr = 1; /* NULL ptr */
307        len = (char *)ALIGN(buf) - buf;
308        for (i = 0; pe->p_aliases[i]; i++, numptr++) {
309                len += strlen(pe->p_aliases[i]) + 1;
310        }
311        len += strlen(pe->p_name) + 1;
312        len += numptr * sizeof(char*);
313
314        if (len > (int)buflen) {
315                errno = ERANGE;
316                return (-1);
317        }
318
319        /* copy protocol value*/
320        pptr->p_proto = pe->p_proto;
321
322        cp = (char *)ALIGN(buf) + numptr * sizeof(char *);
323
324        /* copy official name */
325        n = strlen(pe->p_name) + 1;
326        strcpy(cp, pe->p_name);
327        pptr->p_name = cp;
328        cp += n;
329
330        /* copy aliases */
331        pptr->p_aliases = (char **)ALIGN(buf);
332        for (i = 0 ; pe->p_aliases[i]; i++) {
333                n = strlen(pe->p_aliases[i]) + 1;
334                strcpy(cp, pe->p_aliases[i]);
335                pptr->p_aliases[i] = cp;
336                cp += n;
337        }
338        pptr->p_aliases[i] = NULL;
339
340        return (0);
341}
342
343void
344__setprotoent_p(int f, struct protoent_data *ped)
345{
346        if (ped->fp == NULL)
347                ped->fp = fopen(_PATH_PROTOCOLS, "r");
348        else
349                rewind(ped->fp);
350        ped->stayopen |= f;
351}
352
353void
354__endprotoent_p(struct protoent_data *ped)
355{
356        if (ped->fp) {
357                fclose(ped->fp);
358                ped->fp = NULL;
359        }
360        ped->stayopen = 0;
361}
362
363int
364__getprotoent_p(struct protoent *pe, struct protoent_data *ped)
365{
366        char *p;
367        char *cp, **q, *endp;
368        long l;
369
370        if (ped->fp == NULL && (ped->fp = fopen(_PATH_PROTOCOLS, "r")) == NULL)
371                return (-1);
372again:
373        if ((p = fgets(ped->line, sizeof ped->line, ped->fp)) == NULL)
374                return (-1);
375        if (*p == '#')
376                goto again;
377        cp = strpbrk(p, "#\n");
378        if (cp != NULL)
379                *cp = '\0';
380        pe->p_name = p;
381        cp = strpbrk(p, " \t");
382        if (cp == NULL)
383                goto again;
384        *cp++ = '\0';
385        while (*cp == ' ' || *cp == '\t')
386                cp++;
387        p = strpbrk(cp, " \t");
388        if (p != NULL)
389                *p++ = '\0';
390        l = strtol(cp, &endp, 10);
391        if (endp == cp || *endp != '\0' || l < 0 || l > USHRT_MAX)
392                goto again;
393        pe->p_proto = l;
394        q = pe->p_aliases = ped->aliases;
395        if (p != NULL) {
396                cp = p;
397                while (cp && *cp) {
398                        if (*cp == ' ' || *cp == '\t') {
399                                cp++;
400                                continue;
401                        }
402                        if (q < &ped->aliases[_MAXALIASES - 1])
403                                *q++ = cp;
404                        cp = strpbrk(cp, " \t");
405                        if (cp != NULL)
406                                *cp++ = '\0';
407                }
408        }
409        *q = NULL;
410        return (0);
411}
412
413static int
414files_getprotoent_r(void *retval, void *mdata, va_list ap)
415{
416        struct protoent pe;
417        struct protoent_data *ped;
418
419        struct protoent *pptr;
420        char *buffer;
421        size_t buflen;
422        int *errnop;
423
424        pptr = va_arg(ap, struct protoent *);
425        buffer = va_arg(ap, char *);
426        buflen = va_arg(ap, size_t);
427        errnop = va_arg(ap, int *);
428
429        if ((ped = __protoent_data_init()) == NULL) {
430                *errnop = errno;
431                return (NS_NOTFOUND);
432        }
433
434        if (__getprotoent_p(&pe, ped) != 0) {
435                *errnop = errno;
436                return (NS_NOTFOUND);
437        }
438
439        if (__copy_protoent(&pe, pptr, buffer, buflen) != 0) {
440                *errnop = errno;
441                return (NS_RETURN);
442        }
443
444        *((struct protoent **)retval) = pptr;
445        return (NS_SUCCESS);
446}
447
448static int
449files_setprotoent(void *retval, void *mdata, va_list ap)
450{
451        struct protoent_data *ped;
452        int f;
453
454        f = va_arg(ap, int);
455        if ((ped = __protoent_data_init()) == NULL)
456                return (NS_UNAVAIL);
457
458        __setprotoent_p(f, ped);
459        return (NS_UNAVAIL);
460}
461
462static int
463files_endprotoent(void *retval, void *mdata, va_list ap)
464{
465        struct protoent_data *ped;
466
467        if ((ped = __protoent_data_init()) == NULL)
468                return (NS_UNAVAIL);
469
470        __endprotoent_p(ped);
471        return (NS_UNAVAIL);
472}
473
474int
475getprotoent_r(struct protoent *pptr, char *buffer, size_t buflen,
476    struct protoent **result)
477{
478#ifdef NS_CACHING
479        static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
480                protocols, (void *)nss_lt_all,
481                __proto_marshal_func, __proto_unmarshal_func);
482#endif
483        static const ns_dtab dtab[] = {
484                { NSSRC_FILES, files_getprotoent_r, (void *)nss_lt_all },
485#ifdef NS_CACHING
486                NS_CACHE_CB(&cache_info)
487#endif
488                { NULL, NULL, NULL }
489        };
490        int rv, ret_errno;
491
492        ret_errno = 0;
493        *result = NULL;
494        rv = nsdispatch(result, dtab, NSDB_PROTOCOLS, "getprotoent_r",
495            defaultsrc, pptr, buffer, buflen, &ret_errno);
496
497        if (rv != NS_SUCCESS) {
498                errno = ret_errno;
499                return (ret_errno);
500        }
501        return (0);
502}
503
504void
505setprotoent(int stayopen)
506{
507#ifdef NS_CACHING
508        static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
509                protocols, (void *)nss_lt_all,
510                NULL, NULL);
511#endif
512
513        static const ns_dtab dtab[] = {
514                { NSSRC_FILES, files_setprotoent, NULL },
515#ifdef NS_CACHING
516                NS_CACHE_CB(&cache_info)
517#endif
518                { NULL, NULL, NULL }
519        };
520
521        (void)nsdispatch(NULL, dtab, NSDB_PROTOCOLS, "setprotoent", defaultsrc,
522                stayopen);
523}
524
525void
526endprotoent(void)
527{
528#ifdef NS_CACHING
529        static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
530                protocols, (void *)nss_lt_all,
531                NULL, NULL);
532#endif
533
534        static const ns_dtab dtab[] = {
535                { NSSRC_FILES, files_endprotoent, NULL },
536#ifdef NS_CACHING
537                NS_CACHE_CB(&cache_info)
538#endif
539                { NULL, NULL, NULL }
540        };
541
542        (void)nsdispatch(NULL, dtab, NSDB_PROTOCOLS, "endprotoent", defaultsrc);
543}
544
545struct protoent *
546getprotoent(void)
547{
548        struct protodata *pd;
549        struct protoent *rval;
550
551        if ((pd = __protodata_init()) == NULL)
552                return (NULL);
553        if (getprotoent_r(&pd->proto, pd->data, sizeof(pd->data), &rval) != 0)
554                return (NULL);
555        return (rval);
556}
Note: See TracBrowser for help on using the repository browser.