/* Copyright (C) 1998,99,2000,01 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Andreas Jaeger
, 1998.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
/*
Testing of some network related lookup functions.
The system databases looked up are:
- /etc/services
- /etc/hosts
::1 localhost
127.0.0.1 localhost linuxhost
192.168.1.86 linuxhost
192.100.100.101 linuxhost
192.168.1.96 sunhost
- /etc/networks
default 0.0.0.0
loopback 127.0.0.0
link-local 169.254.0.0
DANETA 192.168.1.0 daneta
DANETB 192.100.100.0 danetb
- /etc/protocols
- /etc/rpc
The tests try to be fairly generic and simple so that they work on
every possible setup (and might therefore not detect some possible
errors).
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/* #include */
#include
#if defined(__sun) /* solaris */
#include
#include
#endif
/*
The following define is necessary for glibc 2.0.6
*/
#ifndef INET6_ADDRSTRLEN
# define INET6_ADDRSTRLEN 46
#endif
int error_count;
static void
output_servent (const char *call, struct servent *sptr)
{
char **pptr;
if (sptr == NULL)
printf ("Call: %s returned NULL\n", call);
else
{
printf ("Call: %s, returned: s_name: %s, s_port: %d, s_proto: %s\n",
call, sptr->s_name, ntohs(sptr->s_port), sptr->s_proto);
for (pptr = sptr->s_aliases; *pptr != NULL; pptr++)
printf (" alias: %s\n", *pptr);
}
return;
}
static void
test_services (void)
{
struct servent *sptr;
sptr = getservbyname ("domain", "tcp");
output_servent ("getservbyname (\"domain\", \"tcp\")", sptr);
sptr = getservbyname ("domain", "udp");
output_servent ("getservbyname (\"domain\", \"udp\")", sptr);
sptr = getservbyname ("domain", NULL);
output_servent ("getservbyname (\"domain\", NULL)", sptr);
sptr = getservbyname ("not-existant", NULL);
output_servent ("getservbyname (\"not-existant\", NULL)", sptr);
/* This shouldn't return anything. */
sptr = getservbyname ("", "");
output_servent ("getservbyname (\"\", \"\")", sptr);
sptr = getservbyname ("", "tcp");
output_servent ("getservbyname (\"\", \"tcp\")", sptr);
sptr = getservbyport (htons(53), "tcp");
output_servent ("getservbyport (htons(53), \"tcp\")", sptr);
sptr = getservbyport (htons(53), NULL);
output_servent ("getservbyport (htons(53), NULL)", sptr);
sptr = getservbyport (htons(1), "udp"); /* shouldn't exist */
output_servent ("getservbyport (htons(1), \"udp\")", sptr);
setservent (0);
do
{
sptr = getservent ();
output_servent ("getservent ()", sptr);
}while (sptr != NULL);
endservent ();
return;
}
static void
output_hostent (const char *call, struct hostent *hptr)
{
char **pptr;
char buf[INET6_ADDRSTRLEN];
if (hptr == NULL)
printf ("Call: %s returned NULL\n", call);
else
{
printf ("Call: %s returned: name: %s, addr_type: %d\n",
call, hptr->h_name, hptr->h_addrtype);
if (hptr->h_aliases)
for (pptr = hptr->h_aliases; *pptr != NULL; pptr++)
printf (" alias: %s\n", *pptr);
for (pptr = hptr->h_addr_list; *pptr != NULL; pptr++)
printf (" ip: %s\n",
inet_ntop (hptr->h_addrtype, *pptr, buf, sizeof (buf)));
}
return;
}
static void
test_hosts (void)
{
struct hostent *hptr1, *hptr2;
char *name = NULL;
size_t namelen = 0;
struct in_addr ip;
hptr1 = gethostbyname ("localhost");
hptr2 = gethostbyname ("LocalHost");
if (hptr1 != NULL || hptr2 != NULL)
{
if (hptr1 == NULL)
{
printf ("localhost not found - but LocalHost found:-(\n");
++error_count;
}
else if (hptr2 == NULL)
{
printf ("LocalHost not found - but localhost found:-(\n");
++error_count;
}
else if (strcmp (hptr1->h_name, hptr2->h_name) != 0)
{
printf ("localhost and LocalHost have different canoncial name\n");
printf ("gethostbyname (\"localhost\")->%s\n", hptr1->h_name);
printf ("gethostbyname (\"LocalHost\")->%s\n", hptr2->h_name);
++error_count;
}
else
output_hostent ("gethostbyname(\"localhost\")", hptr1);
}
hptr1 = gethostbyname ("127.0.0.1");
output_hostent ("gethostbyname (\"127.0.0.1\")", hptr1);
#if defined(__linux)
hptr1 = gethostbyname ("10.1234");
output_hostent ("gethostbyname (\"10.1234\")", hptr1);
hptr1 = gethostbyname2 ("localhost", AF_INET);
output_hostent ("gethostbyname2 (\"localhost\", AF_INET)", hptr1);
#endif
namelen = 64;
name = (char *)malloc(namelen);
if (gethostname (name, namelen) == 0)
{
printf ("Hostname: %s\n", name);
if (name != NULL)
{
hptr1 = gethostbyname (name);
output_hostent ("gethostbyname (gethostname(...))", hptr1);
}
}
ip.s_addr = htonl (INADDR_LOOPBACK);
hptr1 = gethostbyaddr ((char *) &ip, sizeof(ip), AF_INET);
if (hptr1 != NULL)
{
printf ("official name of 127.0.0.1: %s\n", hptr1->h_name);
}
sethostent (0);
do
{
hptr1 = gethostent ();
output_hostent ("gethostent ()", hptr1);
}while (hptr1 != NULL);
endhostent ();
if (name != NULL) free(name);
return;
}
static void
output_netent (const char *call, struct netent *nptr)
{
char **pptr;
if (nptr == NULL)
printf ("Call: %s returned NULL\n", call);
else
{
struct in_addr ip;
ip.s_addr = htonl(nptr->n_net);
printf ("Call: %s, returned: n_name: %s, network_number: %s\n",
call, nptr->n_name, inet_ntoa (ip));
for (pptr = nptr->n_aliases; *pptr != NULL; pptr++)
printf (" alias: %s\n", *pptr);
}
return;
}
static void
test_network (void)
{
struct netent *nptr;
uint32_t ip;
/*
This test needs the following line in /etc/networks:
loopback 127.0.0.0
*/
nptr = getnetbyname ("loopback");
output_netent ("getnetbyname (\"loopback\")",nptr);
nptr = getnetbyname ("LoopBACK");
output_netent ("getnetbyname (\"LoopBACK\")",nptr);
ip = inet_network ("127.0.0.0");
nptr = getnetbyaddr (ip, AF_INET);
output_netent ("getnetbyaddr (inet_network (\"127.0.0.0\"), AF_INET)",nptr);
setnetent (0);
do
{
nptr = getnetent ();
output_netent ("getnetent ()", nptr);
}while (nptr != NULL);
endnetent ();
return;
}
static void
output_protoent (const char *call, struct protoent *prptr)
{
char **pptr;
if (prptr == NULL)
printf ("Call: %s returned NULL\n", call);
else
{
printf ("Call: %s, returned: p_name: %s, p_proto: %d\n",
call, prptr->p_name, prptr->p_proto);
for (pptr = prptr->p_aliases; *pptr != NULL; pptr++)
printf (" alias: %s\n", *pptr);
}
return;
}
static void
test_protocols (void)
{
struct protoent *prptr;
prptr = getprotobyname ("IP");
output_protoent ("getprotobyname (\"IP\")", prptr);
prptr = getprotobynumber (1);
output_protoent ("getprotobynumber (1)", prptr);
setprotoent (0);
do
{
prptr = getprotoent ();
output_protoent ("getprotoent ()", prptr);
}while (prptr != NULL);
endprotoent ();
return;
}
static void
output_rpcent (const char *call, struct rpcent *rptr)
{
char **pptr;
if (rptr == NULL)
printf ("Call: %s returned NULL\n", call);
else
{
printf ("Call: %s, returned: r_name: %s, r_number: %d\n",
call, rptr->r_name, rptr->r_number);
for (pptr = rptr->r_aliases; *pptr != NULL; pptr++)
printf (" alias: %s\n", *pptr);
}
return;
}
static void
test_rpc (void)
{
struct rpcent *rptr;
rptr = getrpcbyname ("portmap");
output_rpcent ("getrpcyname (\"portmap\")", rptr);
rptr = getrpcbynumber (100000);
output_rpcent ("getrpcbynumber (100000)", rptr);
setrpcent (0);
do
{
rptr = getrpcent ();
output_rpcent ("getrpcent ()", rptr);
}while (rptr != NULL);
endrpcent ();
return;
}
#if defined(__linux)
/* Override /etc/nsswitch.conf for this program. This is mainly
useful for developers. */
static void __attribute__ ((unused))
setdb (const char *dbname)
{
if (strcmp ("db", dbname))
{
/*
db is not implemented for hosts, networks
*/
__nss_configure_lookup ("hosts", dbname);
__nss_configure_lookup ("networks", dbname);
}
__nss_configure_lookup ("protocols", dbname);
__nss_configure_lookup ("rpc", dbname);
__nss_configure_lookup ("services", dbname);
return;
}
#endif
int main (int argc, char **argv)
{
int ret;
int csock, tsock, dsock;
int i, size;
int namelen, salen;
char *ptr = NULL, **pptr = NULL;
char *hostname = NULL, *str = NULL;
struct ifconf ifc;
struct ifreq ifr, *pifr;
struct hostent *pHostEntry = NULL;
struct sockaddr saddr, tsaddr;
struct sockaddr_in si_addr, *psa;
struct in_addr addr, inaddr;
struct netent *nptr = NULL;
/* struct sockaddr { */
/* unsigned short sa_family; */ /* Protocal Family, PF_xxx */
/* char sa_data[14]; */ /* 14 bytes of protocol address */
/* } */
/* struct sockaddr_in { */
/* short int sin_family; */ /* Address Family, AF_XXX */
/* unsigned short int sin_port; */ /* Port number */
/* struct in_addr sin_addr; */ /* Internet address */
/* unsigned char sin_zero[8]; */ /* Same size as struct sockaddr */
/* }; */
/* typedef uint32_t in_addr_t; */
/* struct in_addr { */
/* in_addr_t s_addr; */
/* }; */
#define TCP_PORT 4321
#define UDP_PORT 4321
/* Protocal Family: PF_INET Type: stream Protocal: IPPROTO_TCP*/
/* csock = socket(PF_INET, SOCK_STREAM, 0); */
csock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
psa = (struct sockaddr_in *)&saddr;
psa->sin_family = AF_INET; /* Address Family */
psa->sin_port = htons(TCP_PORT);
psa->sin_addr.s_addr = htonl(INADDR_ANY);
ret = bind(csock, &saddr, sizeof (struct sockaddr));
/* ret = listen(csock, 5); */
/* tsock = accept(csock, &tsaddr, &salen); */
/* if (tsock >= 0) */
/* { */
/* salen = sizeof(struct sockaddr); */
/* ret = getpeername(csock, &saddr, &salen); */
/* inaddr.s_addr = psa->sin_addr.s_addr; */
/* printf("TCPSocket is connected on %s : %d\n", \ */
/* inet_ntoa(psa->sin_addr), ntohs(psa->sin_port)); */
/* } */
/* Protocal Family: PF_INET Type: datagram Protocal: IPPROTO_UDP*/
/* dsock = socket(PF_INET, SOCK_DGRAM, 0); */
dsock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
psa = (struct sockaddr_in *)&saddr;
psa->sin_family = AF_INET; /* Address Family */
psa->sin_port = htons(0); /* any one */
psa->sin_addr.s_addr = htonl(INADDR_ANY);
ret = bind(dsock, &saddr, sizeof (struct sockaddr));
if (ret == 0)
{
salen = sizeof(struct sockaddr);
ret = getsockname(csock, &saddr, &salen);
inaddr.s_addr = psa->sin_addr.s_addr;
printf("UDPSocket is created and bound on %s : %d\n", \
inet_ntoa(psa->sin_addr), ntohs(psa->sin_port));
/* ret = ioctl(dsock, SIOCGSIZIFCONF, &size); */
ifc.ifc_len = sizeof(struct ifreq) * 16; /* size */
ifc.ifc_buf = (char *)malloc(ifc.ifc_len);
ret = ioctl(dsock, SIOCGIFCONF, &ifc);
#if defined(GETIFS_LOOP)
size = sizeof(struct ifreq);
ifc.ifc_len = size;
ifc.ifc_buf = (char *)malloc(ifc.ifc_len);
while(0 == ioctl(dsock, SIOCGIFCONF, &ifc))
{
if (size == ifc.ifc_len)
{
size += size;
ifc.ifc_len = size;
ifc.ifc_buf = (char *)realloc(ifc.ifc_buf, ifc.ifc_len);
continue;
}
break;
}
#endif
printf("ifcount = %d\n", (ifc.ifc_len)/sizeof(struct ifreq));
ptr = ifc.ifc_buf;
while (ptr < (ifc.ifc_buf + ifc.ifc_len))
{
/* Debug stuff: struct sockaddr_in *psa; */
pifr = (struct ifreq *)ptr;
psa = (struct sockaddr_in *) &pifr->ifr_addr;
printf("interface: %s, address: %s\n", \
pifr->ifr_name, inet_ntoa(psa->sin_addr));
/* End debug stuff */
/* memcpy(&ifr, ptr, sizeof(struct ifreq)) */
strcpy(ifr.ifr_name, pifr->ifr_name);
ret = ioctl(dsock, SIOCGIFFLAGS, &ifr);
printf("\tflags = 0x%x\n", ifr.ifr_flags);
if ((0 == (ifr.ifr_flags & IFF_LOOPBACK)) \
&& (ifr.ifr_flags & IFF_UP) \
&& (ifr.ifr_flags & IFF_BROADCAST) \
&& (0 == (ifr.ifr_flags & IFF_SLAVE)))
{
ret = ioctl(dsock, SIOCGIFADDR, &ifr);
psa = (struct sockaddr_in *) &ifr.ifr_addr;
printf("\taddr: %s\n", inet_ntoa(psa->sin_addr));
ret = ioctl(dsock, SIOCGIFHWADDR, &ifr);
saddr = ifr.ifr_hwaddr;
printf("\thwad: %02x:%02x:%02x:%02x:%02x:%02x\n", \
(unsigned char)saddr.sa_data[0], (unsigned char)saddr.sa_data[1], \
(unsigned char)saddr.sa_data[2], (unsigned char)saddr.sa_data[3], \
(unsigned char)saddr.sa_data[4], (unsigned char)saddr.sa_data[5]);
ret = ioctl(dsock, SIOCGIFBRDADDR, &ifr);
psa = (struct sockaddr_in *) &ifr.ifr_broadaddr;
printf("\tbroad: %s\n", inet_ntoa(psa->sin_addr));
ret = ioctl(dsock, SIOCGIFNETMASK, &ifr);
psa = (struct sockaddr_in *) &ifr.ifr_addr;
printf("\tmask: %s\n", inet_ntoa(psa->sin_addr));
ret = ioctl(dsock, SIOCGIFMTU, &ifr);
printf("\tmtu: %d\n", ifr.ifr_mtu);
ret = ioctl(dsock, SIOCGIFMETRIC, &ifr);
printf("\tmetric: %d\n", ifr.ifr_metric);
}
ptr += sizeof(struct ifreq);
}
}
namelen = 16;
hostname = (char *)malloc(namelen);
while ((ret = gethostname(hostname, namelen)) < 0 && errno == ENAMETOOLONG)
{
namelen += namelen;
hostname = (char *)realloc(hostname, namelen);
}
if (ret == 0)
{
str = strchr(hostname, '.');
if (str != NULL)
{
*str = '\0';
printf("Short");
}
printf("Hostname: %s\n", hostname);
}
else
{
printf("Unknown host!\n");
return 0;
}
pHostEntry = gethostbyname(hostname);
if (pHostEntry->h_addrtype == AF_INET)
{
for (i = 0; (pHostEntry->h_addr_list[i]) != NULL; i++)
{
/* inet_ntop (pHostEntry->h_addrtype, pHostEntry->h_addr_list[i], buf, sizeof (buf))); */
inaddr.s_addr = *(long *)(pHostEntry->h_addr_list[i]);
printf(" ip4: %s\n", inet_ntoa(inaddr));
}
for (i = 0; (pHostEntry->h_aliases[i]) != NULL; i++)
{
printf(" alias: %s\n", pHostEntry->h_aliases[i]);
}
}
/* addr.s_addr = ntohl(inet_addr("192.168.1.0")); */
addr.s_addr = inet_network("192.168.1.0");
nptr = getnetbyaddr(addr.s_addr, AF_INET);
if (nptr == NULL)
{
inaddr.s_addr = htonl(addr.s_addr);
printf("Get nothing of net %s!\n", \
inet_ntoa (inaddr));
}
else
{
inaddr.s_addr = htonl(nptr->n_net);
printf ("n_name: %s, network_number: %s\n",
nptr->n_name, inet_ntoa (inaddr));
for (pptr = nptr->n_aliases; *pptr != NULL; pptr++)
printf (" alias: %s\n", *pptr);
}
/*
setdb ("db");
*/
test_hosts ();
test_network ();
test_protocols ();
test_rpc ();
test_services ();
if (error_count)
printf ("\n %d errors occurred!\n", error_count);
else
printf ("No visible errors occurred!\n");
if (hostname != NULL) free(hostname);
return error_count;
}
阅读(752) | 评论(0) | 转发(0) |