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