1 | /* Copyright (C) 1998-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 | /* |
19 | Testing of some network related lookup functions. |
20 | The system databases looked up are: |
21 | - /etc/services |
22 | - /etc/hosts |
23 | - /etc/networks |
24 | - /etc/protocols |
25 | The tests try to be fairly generic and simple so that they work on |
26 | every possible setup (and might therefore not detect some possible |
27 | errors). |
28 | */ |
29 | |
30 | #include <netdb.h> |
31 | #include <stdio.h> |
32 | #include <stdlib.h> |
33 | #include <string.h> |
34 | #include <arpa/inet.h> |
35 | #include <netinet/in.h> |
36 | #include <sys/param.h> |
37 | #include <sys/socket.h> |
38 | #include <unistd.h> |
39 | #include <errno.h> |
40 | #include "nss.h" |
41 | |
42 | #include <support/support.h> |
43 | |
44 | /* |
45 | The following define is necessary for glibc 2.0.6 |
46 | */ |
47 | #ifndef INET6_ADDRSTRLEN |
48 | # define INET6_ADDRSTRLEN 46 |
49 | #endif |
50 | |
51 | int error_count; |
52 | |
53 | static void |
54 | output_servent (const char *call, struct servent *sptr) |
55 | { |
56 | char **pptr; |
57 | |
58 | if (sptr == NULL) |
59 | printf (format: "Call: %s returned NULL\n" , call); |
60 | else |
61 | { |
62 | printf (format: "Call: %s, returned: s_name: %s, s_port: %d, s_proto: %s\n" , |
63 | call, sptr->s_name, ntohs(sptr->s_port), sptr->s_proto); |
64 | for (pptr = sptr->s_aliases; *pptr != NULL; pptr++) |
65 | printf (format: " alias: %s\n" , *pptr); |
66 | } |
67 | } |
68 | |
69 | |
70 | static void |
71 | test_services (void) |
72 | { |
73 | struct servent *sptr; |
74 | |
75 | sptr = getservbyname (name: "domain" , proto: "tcp" ); |
76 | output_servent (call: "getservbyname (\"domain\", \"tcp\")" , sptr); |
77 | |
78 | sptr = getservbyname (name: "domain" , proto: "udp" ); |
79 | output_servent (call: "getservbyname (\"domain\", \"udp\")" , sptr); |
80 | |
81 | sptr = getservbyname (name: "domain" , NULL); |
82 | output_servent (call: "getservbyname (\"domain\", NULL)" , sptr); |
83 | |
84 | sptr = getservbyname (name: "not-existant" , NULL); |
85 | output_servent (call: "getservbyname (\"not-existant\", NULL)" , sptr); |
86 | |
87 | /* This shouldn't return anything. */ |
88 | sptr = getservbyname (name: "" , proto: "" ); |
89 | output_servent (call: "getservbyname (\"\", \"\")" , sptr); |
90 | |
91 | sptr = getservbyname (name: "" , proto: "tcp" ); |
92 | output_servent (call: "getservbyname (\"\", \"tcp\")" , sptr); |
93 | |
94 | sptr = getservbyport (htons(53), proto: "tcp" ); |
95 | output_servent (call: "getservbyport (htons(53), \"tcp\")" , sptr); |
96 | |
97 | sptr = getservbyport (htons(53), NULL); |
98 | output_servent (call: "getservbyport (htons(53), NULL)" , sptr); |
99 | |
100 | sptr = getservbyport (htons(1), proto: "udp" ); /* shouldn't exist */ |
101 | output_servent (call: "getservbyport (htons(1), \"udp\")" , sptr); |
102 | |
103 | setservent (0); |
104 | do |
105 | { |
106 | sptr = getservent (); |
107 | output_servent (call: "getservent ()" , sptr); |
108 | } |
109 | while (sptr != NULL); |
110 | endservent (); |
111 | } |
112 | |
113 | |
114 | static void |
115 | output_hostent (const char *call, struct hostent *hptr) |
116 | { |
117 | char **pptr; |
118 | char buf[INET6_ADDRSTRLEN]; |
119 | |
120 | if (hptr == NULL) |
121 | printf (format: "Call: %s returned NULL\n" , call); |
122 | else |
123 | { |
124 | printf (format: "Call: %s returned: name: %s, addr_type: %d\n" , |
125 | call, hptr->h_name, hptr->h_addrtype); |
126 | if (hptr->h_aliases) |
127 | for (pptr = hptr->h_aliases; *pptr != NULL; pptr++) |
128 | printf (format: " alias: %s\n" , *pptr); |
129 | |
130 | for (pptr = hptr->h_addr_list; *pptr != NULL; pptr++) |
131 | printf (format: " ip: %s\n" , |
132 | inet_ntop (hptr->h_addrtype, *pptr, buf, sizeof (buf))); |
133 | } |
134 | } |
135 | |
136 | static void |
137 | test_hosts (void) |
138 | { |
139 | struct hostent *hptr1, *hptr2; |
140 | char *name = NULL; |
141 | size_t namelen = 0; |
142 | struct in_addr ip; |
143 | |
144 | hptr1 = gethostbyname (name: "localhost" ); |
145 | hptr2 = gethostbyname (name: "LocalHost" ); |
146 | if (hptr1 != NULL || hptr2 != NULL) |
147 | { |
148 | if (hptr1 == NULL) |
149 | { |
150 | printf (format: "localhost not found - but LocalHost found:-(\n" ); |
151 | ++error_count; |
152 | } |
153 | else if (hptr2 == NULL) |
154 | { |
155 | printf (format: "LocalHost not found - but localhost found:-(\n" ); |
156 | ++error_count; |
157 | } |
158 | else if (strcmp (hptr1->h_name, hptr2->h_name) != 0) |
159 | { |
160 | printf (format: "localhost and LocalHost have different canoncial name\n" ); |
161 | printf (format: "gethostbyname (\"localhost\")->%s\n" , hptr1->h_name); |
162 | printf (format: "gethostbyname (\"LocalHost\")->%s\n" , hptr2->h_name); |
163 | ++error_count; |
164 | } |
165 | else |
166 | output_hostent (call: "gethostbyname(\"localhost\")" , hptr: hptr1); |
167 | } |
168 | |
169 | hptr1 = gethostbyname (name: "127.0.0.1" ); |
170 | output_hostent (call: "gethostbyname (\"127.0.0.1\")" , hptr: hptr1); |
171 | |
172 | hptr1 = gethostbyname (name: "10.1234" ); |
173 | output_hostent (call: "gethostbyname (\"10.1234\")" , hptr: hptr1); |
174 | |
175 | hptr1 = gethostbyname2 (name: "localhost" , AF_INET); |
176 | output_hostent (call: "gethostbyname2 (\"localhost\", AF_INET)" , hptr: hptr1); |
177 | |
178 | while (gethostname (name: name, len: namelen) < 0 && errno == ENAMETOOLONG) |
179 | { |
180 | namelen += 2; /* tiny increments to test a lot */ |
181 | name = xrealloc (o: name, n: namelen); |
182 | } |
183 | if (gethostname (name: name, len: namelen) == 0) |
184 | { |
185 | printf (format: "Hostname: %s\n" , name); |
186 | if (name != NULL) |
187 | { |
188 | hptr1 = gethostbyname (name: name); |
189 | output_hostent (call: "gethostbyname (gethostname(...))" , hptr: hptr1); |
190 | } |
191 | } |
192 | |
193 | ip.s_addr = htonl (INADDR_LOOPBACK); |
194 | hptr1 = gethostbyaddr (addr: (char *) &ip, len: sizeof (ip), AF_INET); |
195 | if (hptr1 != NULL) |
196 | { |
197 | printf (format: "official name of 127.0.0.1: %s\n" , hptr1->h_name); |
198 | } |
199 | |
200 | sethostent (0); |
201 | do |
202 | { |
203 | hptr1 = gethostent (); |
204 | output_hostent (call: "gethostent ()" , hptr: hptr1); |
205 | } |
206 | while (hptr1 != NULL); |
207 | endhostent (); |
208 | |
209 | } |
210 | |
211 | |
212 | static void |
213 | output_netent (const char *call, struct netent *nptr) |
214 | { |
215 | char **pptr; |
216 | |
217 | if (nptr == NULL) |
218 | printf (format: "Call: %s returned NULL\n" , call); |
219 | else |
220 | { |
221 | struct in_addr ip; |
222 | |
223 | ip.s_addr = htonl(nptr->n_net); |
224 | printf (format: "Call: %s, returned: n_name: %s, network_number: %s\n" , |
225 | call, nptr->n_name, inet_ntoa (in: ip)); |
226 | |
227 | for (pptr = nptr->n_aliases; *pptr != NULL; pptr++) |
228 | printf (format: " alias: %s\n" , *pptr); |
229 | } |
230 | } |
231 | |
232 | static void |
233 | test_network (void) |
234 | { |
235 | struct netent *nptr; |
236 | uint32_t ip; |
237 | |
238 | /* |
239 | This test needs the following line in /etc/networks: |
240 | loopback 127.0.0.0 |
241 | */ |
242 | nptr = getnetbyname (name: "loopback" ); |
243 | output_netent (call: "getnetbyname (\"loopback\")" ,nptr); |
244 | |
245 | nptr = getnetbyname (name: "LoopBACK" ); |
246 | output_netent (call: "getnetbyname (\"LoopBACK\")" ,nptr); |
247 | |
248 | ip = inet_network (cp: "127.0.0.0" ); |
249 | nptr = getnetbyaddr (net: ip, AF_INET); |
250 | output_netent (call: "getnetbyaddr (inet_network (\"127.0.0.0\"), AF_INET)" ,nptr); |
251 | |
252 | setnetent (0); |
253 | do |
254 | { |
255 | nptr = getnetent (); |
256 | output_netent (call: "getnetent ()" , nptr); |
257 | } |
258 | while (nptr != NULL); |
259 | endnetent (); |
260 | } |
261 | |
262 | |
263 | static void |
264 | output_protoent (const char *call, struct protoent *prptr) |
265 | { |
266 | char **pptr; |
267 | |
268 | if (prptr == NULL) |
269 | printf (format: "Call: %s returned NULL\n" , call); |
270 | else |
271 | { |
272 | printf (format: "Call: %s, returned: p_name: %s, p_proto: %d\n" , |
273 | call, prptr->p_name, prptr->p_proto); |
274 | for (pptr = prptr->p_aliases; *pptr != NULL; pptr++) |
275 | printf (format: " alias: %s\n" , *pptr); |
276 | } |
277 | } |
278 | |
279 | |
280 | static void |
281 | test_protocols (void) |
282 | { |
283 | struct protoent *prptr; |
284 | |
285 | prptr = getprotobyname (name: "IP" ); |
286 | output_protoent (call: "getprotobyname (\"IP\")" , prptr); |
287 | |
288 | prptr = getprotobynumber (proto: 1); |
289 | output_protoent (call: "getprotobynumber (1)" , prptr); |
290 | |
291 | setprotoent (0); |
292 | do |
293 | { |
294 | prptr = getprotoent (); |
295 | output_protoent (call: "getprotoent ()" , prptr); |
296 | } |
297 | while (prptr != NULL); |
298 | endprotoent (); |
299 | } |
300 | |
301 | |
302 | /* Override /etc/nsswitch.conf for this program. This is mainly |
303 | useful for developers. */ |
304 | static void __attribute__ ((unused)) |
305 | setdb (const char *dbname) |
306 | { |
307 | if (strcmp ("db" , dbname)) |
308 | { |
309 | /* |
310 | db is not implemented for hosts, networks |
311 | */ |
312 | __nss_configure_lookup (dbname: "hosts" , string: dbname); |
313 | __nss_configure_lookup (dbname: "networks" , string: dbname); |
314 | } |
315 | __nss_configure_lookup (dbname: "protocols" , string: dbname); |
316 | __nss_configure_lookup (dbname: "services" , string: dbname); |
317 | } |
318 | |
319 | |
320 | static int |
321 | do_test (void) |
322 | { |
323 | /* |
324 | setdb ("db"); |
325 | */ |
326 | |
327 | test_hosts (); |
328 | test_network (); |
329 | test_protocols (); |
330 | test_services (); |
331 | |
332 | if (error_count) |
333 | printf (format: "\n %d errors occurred!\n" , error_count); |
334 | else |
335 | printf (format: "No visible errors occurred!\n" ); |
336 | |
337 | return (error_count != 0); |
338 | } |
339 | |
340 | #include <support/test-driver.c> |
341 | |