1/* Copyright (C) 1997-2016 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
18
19#include <errno.h>
20#include <hesiod.h>
21#include <netdb.h>
22#include <netinet/in.h>
23#include <nss.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27
28/* Declare a parser for Hesiod protocol entries. Although the format
29 of the entries is identical to those in /etc/protocols, here is no
30 predefined parser for us to use. */
31
32#define ENTNAME protoent
33
34struct protoent_data {};
35
36#define TRAILING_LIST_MEMBER p_aliases
37#define TRAILING_LIST_SEPARATOR_P isspace
38#include <nss/nss_files/files-parse.c>
39LINE_PARSER
40("#",
41 STRING_FIELD (result->p_name, isspace, 1);
42 INT_FIELD (result->p_proto, isspace, 1, 10,);
43 )
44
45enum nss_status
46_nss_hesiod_setprotoent (int stayopen)
47{
48 return NSS_STATUS_SUCCESS;
49}
50
51enum nss_status
52_nss_hesiod_endprotoent (void)
53{
54 return NSS_STATUS_SUCCESS;
55}
56
57static enum nss_status
58lookup (const char *name, const char *type, struct protoent *proto,
59 char *buffer, size_t buflen, int *errnop)
60{
61 struct parser_data *data = (void *) buffer;
62 size_t linebuflen;
63 void *context;
64 char **list, **item;
65 int parse_res;
66 int found;
67 int olderr = errno;
68
69 if (hesiod_init (&context) < 0)
70 return NSS_STATUS_UNAVAIL;
71
72 list = hesiod_resolve (context, name, type);
73 if (list == NULL)
74 {
75 int err = errno;
76 hesiod_end (context);
77 __set_errno (olderr);
78 return err == ENOENT ? NSS_STATUS_NOTFOUND : NSS_STATUS_UNAVAIL;
79 }
80
81 linebuflen = buffer + buflen - data->linebuffer;
82
83 item = list;
84 found = 0;
85 do
86 {
87 size_t len = strlen (*item) + 1;
88
89 if (linebuflen < len)
90 {
91 hesiod_free_list (context, list);
92 hesiod_end (context);
93 *errnop = ERANGE;
94 return NSS_STATUS_TRYAGAIN;
95 }
96
97 memcpy (data->linebuffer, *item, len);
98
99 parse_res = parse_line (buffer, proto, data, buflen, errnop);
100 if (parse_res == -1)
101 {
102 hesiod_free_list (context, list);
103 hesiod_end (context);
104 return NSS_STATUS_TRYAGAIN;
105 }
106
107 if (parse_res > 0)
108 found = 1;
109
110 ++item;
111 }
112 while (*item != NULL && !found);
113
114 hesiod_free_list (context, list);
115 hesiod_end (context);
116
117 if (found == 0)
118 {
119 __set_errno (olderr);
120 return NSS_STATUS_NOTFOUND;
121 }
122
123 return NSS_STATUS_SUCCESS;
124}
125
126enum nss_status
127_nss_hesiod_getprotobyname_r (const char *name, struct protoent *proto,
128 char *buffer, size_t buflen, int *errnop)
129{
130 return lookup (name, "protocol", proto, buffer, buflen, errnop);
131}
132
133enum nss_status
134_nss_hesiod_getprotobynumber_r (const int protocol, struct protoent *proto,
135 char *buffer, size_t buflen, int *errnop)
136{
137 char protostr[21];
138
139 snprintf (protostr, sizeof protostr, "%d", protocol);
140
141 return lookup (protostr, "protonum", proto, buffer, buflen, errnop);
142}
143