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