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" |