📄 testga.c
字号:
#include "unp.h"/* * Test program for getaddrinfo() and getnameinfo(). */ /* function prototypes for internal functions */static void do_errtest(void);static void do_funccall(const char *, const char *, int, int, int, int, int);static int do_onetest(char *, char *, struct addrinfo *, int);static const char *str_fam(int);static const char *str_sock(int);static void usage(const char *); /* globals */int vflag;intmain(int argc, char **argv){ int doerrtest = 0; int loopcount = 1; int c, i; char *host = NULL; char hostbuf[NI_MAXHOST]; char *serv = NULL; char servbuf[NI_MAXSERV]; struct protoent *proto; struct addrinfo hints; /* set by command-line options */ if (argc < 2) usage(""); memset(&hints, 0, sizeof(struct addrinfo)); opterr = 0; /* don't want getopt() writing to stderr */ while ( (c = getopt(argc, argv, "cef:h:l:pr:s:t:v")) != -1) { switch (c) { case 'c': hints.ai_flags |= AI_CANONNAME; break; case 'e': doerrtest = 1; break; case 'f': /* address family */#ifdef IPv4 if (strcmp(optarg, "inet") == 0) { hints.ai_family = AF_INET; break; }#endif#ifdef IPv6 if (strcmp(optarg, "inet6") == 0) { hints.ai_family = AF_INET6; break; }#endif#ifdef UNIXdomain if (strcmp(optarg, "unix") == 0) { hints.ai_family = AF_LOCAL; break; }#endif usage("invalid -f option"); case 'h': /* host */ strncpy(hostbuf, optarg, NI_MAXHOST-1); host = hostbuf; break; case 'l': /* loop count */ loopcount = atoi(optarg); break; case 'p': hints.ai_flags |= AI_PASSIVE; break; case 'r': /* protocol */ if ((proto = getprotobyname(optarg)) == NULL) { hints.ai_protocol = atoi(optarg); } else { hints.ai_protocol = proto->p_proto; } break; case 's': strncpy(servbuf, optarg, NI_MAXSERV-1); serv = servbuf; break; case 't': /* socket type */ if (strcmp(optarg, "stream") == 0) { hints.ai_socktype = SOCK_STREAM; break; } if (strcmp(optarg, "dgram") == 0) { hints.ai_socktype = SOCK_DGRAM; break; } if (strcmp(optarg, "raw") == 0) { hints.ai_socktype = SOCK_RAW; break; }#ifdef SOCK_RDM if (strcmp(optarg, "rdm") == 0) { hints.ai_socktype = SOCK_RDM; break; }#endif#ifdef SOCK_SEQPACKET if (strcmp(optarg, "seqpacket") == 0) { hints.ai_socktype = SOCK_SEQPACKET; break; }#endif usage("invalid -t option"); case 'v': vflag = 1; break; case '?': usage("unrecognized option"); } } if (optind < argc) { usage("extra args"); } if (doerrtest) { do_errtest(); exit(0); } for (i = 1; i <= loopcount; i++) { if (do_onetest(host, serv, &hints, i) > 0) exit(1); if (i % 1000 == 0) { printf(" %d", i); fflush(stdout); } } exit(0);}/* * Check that the right error codes are returned for invalid input. * Test all the errors that are easy to test for. */static voiddo_errtest(void){ /* passive open with no hostname and no address family */ do_funccall(NULL, "ftp", AI_PASSIVE, 0, 0, 0, 0); /* kind of hard to automatically test EAI_AGAIN ??? */ /* invalid flags */ do_funccall("localhost", NULL, 999999, 0, 0, 0, EAI_BADFLAGS); /* how to test EAI_FAIL ??? */ /* invalid address family */ do_funccall("localhost", NULL, 0, AF_SNA, 0, 0, EAI_FAMILY); /* hard to test for EAI_MEMORY: would have to malloc() until failure, then give some back, then call getaddrinfo and hope that its memory requests would not be satisfied. */ /* to test for EAI_NODATA: would have to know of a host with no A record in the DNS */#ifdef notdef /* following depends on resolver, sigh */ /* believe it or not, there is a registered domain "bar.com", so the following should generate NO_DATA from the DNS */ do_funccall("foo.bar.foo.bar.foo.bar.com", NULL, 0, 0, 0, 0, EAI_NODATA);#endif /* no hostname, no service name */ do_funccall(NULL, NULL, 0, 0, 0, 0, EAI_NONAME); /* invalid hostname (should be interpreted in local default domain) */ do_funccall("lkjjkhjhghgfgfd", NULL, 0, 0, 0, 0, EAI_NONAME); /* invalid service name */ do_funccall(NULL, "nosuchservice", 0, 0, 0, 0, EAI_NONAME); /* service valid but not supported for socket type */ do_funccall("localhost", "telnet", 0, 0, SOCK_DGRAM, 0, EAI_SERVICE); /* service valid but not supported for socket type */ do_funccall("localhost", "tftp", 0, 0, SOCK_STREAM, 0, EAI_SERVICE); /* invalid socket type */ do_funccall("localhost", NULL, 0, AF_INET, SOCK_SEQPACKET, 0, EAI_SOCKTYPE); /* EAI_SYSTEM not generated by my implementation */}static voiddo_funccall(const char *host, const char *serv, int flags, int family, int socktype, int protocol, int exprc){ int rc; struct addrinfo hints, *res; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_flags = flags; hints.ai_family = family; hints.ai_socktype = socktype; hints.ai_protocol = protocol; rc = getaddrinfo(host, serv, &hints, &res); if (rc != exprc) { printf("expected return = %d (%s),\nactual return = %d (%s)\n", exprc, gai_strerror(exprc), rc, gai_strerror(rc)); if (host != NULL) printf(" host = %s\n", host); if (serv != NULL) printf(" serv = %s\n", serv); printf(" flags = %d, family = %s, socktype = %s, protocol = %d\n", flags, str_fam(family), str_sock(socktype), protocol); exit(2); }}static intdo_onetest(char *host, char *serv, struct addrinfo *hints, int iteration){ int rc, fd, verbose; struct addrinfo *res, *rescopy; char rhost[NI_MAXHOST], rserv[NI_MAXSERV]; verbose = vflag && (iteration == 1); /* only first time */ if (host != NULL && verbose) printf("host = %s\n", host); if (serv != NULL && verbose) printf("serv = %s\n", serv); rc = getaddrinfo(host, serv, hints, &res); if (rc != 0) { printf("getaddrinfo return code = %d (%s)\n", rc, gai_strerror(rc)); return(1); } rescopy = res; do { if (iteration == 1) { /* always print results first time */ printf("\nsocket(%s, %s, %d)", str_fam(res->ai_family), str_sock(res->ai_socktype), res->ai_protocol); /* canonname should be set only in first addrinfo{} */ if (hints->ai_flags & AI_CANONNAME) { if (res->ai_canonname) printf(", ai_canonname = %s", res->ai_canonname); } printf("\n"); printf("\taddress: %s\n", Sock_ntop(res->ai_addr, res->ai_addrlen)); } /* Call socket() to make sure return values are valid */ fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (fd < 0) printf("call to socket() failed!\n"); else close(fd); /* * Call getnameinfo() to check the reverse mapping. */ rc = getnameinfo(res->ai_addr, res->ai_addrlen, rhost, NI_MAXHOST, rserv, NI_MAXSERV, (res->ai_socktype == SOCK_DGRAM) ? NI_DGRAM: 0); if (rc == 0) { if (verbose) printf("\tgetnameinfo: host = %s, serv = %s\n", rhost, rserv); } else printf("getnameinfo returned %d (%s)\n", rc, gai_strerror(rc)); } while ( (res = res->ai_next) != NULL); freeaddrinfo(rescopy); return(0);}static voidusage(const char *msg){ printf("usage: testaddrinfo [ options ]\n""options: -h <host> (can be hostname or address string)\n"" -s <service> (can be service name or decimal port number)\n"" -c AI_CANONICAL flag\n"" -p AI_PASSIVE flag\n"" -l N loop N times (check for memory leaks with ps)\n"" -f X address family, X = inet, inet6, unix\n"" -r X protocol, X = tcp, udp, ... or number e.g. 6, 17, ...\n"" -t X socket type, X = stream, dgram, raw, rdm, seqpacket\n"" -v verbose\n"" -e only do test of error returns (no options required)\n"" without -e, one or both of <host> and <service> must be specified.\n"); if (msg[0] != 0) printf("%s\n", msg); exit(1);}static const char *str_fam(int family){#ifdef IPv4 if (family == AF_INET) return("AF_INET");#endif#ifdef IPv6 if (family == AF_INET6) return("AF_INET6");#endif#ifdef UNIXdomain if (family == AF_LOCAL) return("AF_LOCAL");#endif return("<unknown family>");}static const char *str_sock(int socktype){ switch(socktype) { case SOCK_STREAM: return "SOCK_STREAM"; case SOCK_DGRAM: return "SOCK_DGRAM"; case SOCK_RAW: return "SOCK_RAW";#ifdef SOCK_RDM case SOCK_RDM: return "SOCK_RDM";#endif#ifdef SOCK_SEQPACKET case SOCK_SEQPACKET:return "SOCK_SEQPACKET";#endif default: return "<unknown socktype>"; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -