/* * getaddrinfo test suite. * * Written by Russ Allbery * Copyright 2009 Board of Trustees, Leland Stanford Jr. University * Copyright (c) 2004, 2005, 2006, 2007 * by Internet Systems Consortium, Inc. ("ISC") * Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, * 2002, 2003 by The Internet Software Consortium and Rich Salz * * See LICENSE for licensing terms. */ #include #include #include #include /* * If the native platform doesn't support AI_NUMERICSERV or AI_NUMERICHOST, * pick some other values for them that match the values set in our * implementation. */ #if AI_NUMERICSERV == 0 # undef AI_NUMERICSERV # define AI_NUMERICSERV 0x0080 #endif #if AI_NUMERICHOST == 0 # undef AI_NUMERICHOST # define AI_NUMERICHOST 0x0100 #endif const char *test_gai_strerror(int); void test_freeaddrinfo(struct addrinfo *); int test_getaddrinfo(const char *, const char *, const struct addrinfo *, struct addrinfo **); int main(void) { struct addrinfo *ai, *first; struct addrinfo hints; struct sockaddr_in *saddr; struct hostent *host; struct in_addr addr; struct servent *service; int i; int found; plan(75); is_string("Host name lookup failure", test_gai_strerror(1), "gai_strerror(1)"); is_string("System error", test_gai_strerror(9), "gai_strerror(9)"); is_string("Unknown error", test_gai_strerror(40), "gai_strerror(40)"); is_string("Unknown error", test_gai_strerror(-37), "gai_strerror(-37)"); ok(test_getaddrinfo(NULL, "25", NULL, &ai) == 0, "service of 25"); is_int(AF_INET, ai->ai_family, "...right family"); is_int(0, ai->ai_socktype, "...right socktype"); is_int(IPPROTO_TCP, ai->ai_protocol, "...right protocol"); is_string(NULL, ai->ai_canonname, "...no canonname"); is_int(sizeof(struct sockaddr_in), ai->ai_addrlen, "...right addrlen"); saddr = (struct sockaddr_in *) ai->ai_addr; is_int(htons(25), saddr->sin_port, "...right port"); ok(saddr->sin_addr.s_addr == INADDR_LOOPBACK, "...right address"); test_freeaddrinfo(ai); memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_PASSIVE; hints.ai_socktype = SOCK_STREAM; ok(test_getaddrinfo(NULL, "25", &hints, &ai) == 0, "passive lookup"); is_int(SOCK_STREAM, ai->ai_socktype, "...right socktype"); saddr = (struct sockaddr_in *) ai->ai_addr; is_int(htons(25), saddr->sin_port, "...right port"); ok(saddr->sin_addr.s_addr == INADDR_ANY, "...right address"); test_freeaddrinfo(ai); service = getservbyname("smtp", "tcp"); if (service == NULL) skip_block(4, "smtp service not found"); else { hints.ai_socktype = 0; ok(test_getaddrinfo(NULL, "smtp", &hints, &ai) == 0, "service of smtp"); is_int(SOCK_STREAM, ai->ai_socktype, "...right socktype"); saddr = (struct sockaddr_in *) ai->ai_addr; is_int(htons(25), saddr->sin_port, "...right port"); ok(saddr->sin_addr.s_addr == INADDR_ANY, "...right address"); test_freeaddrinfo(ai); } hints.ai_flags = AI_NUMERICSERV; ok(test_getaddrinfo(NULL, "smtp", &hints, &ai) == EAI_NONAME, "AI_NUMERICSERV with smtp"); ok(test_getaddrinfo(NULL, "25 smtp", &hints, &ai) == EAI_NONAME, "AI_NUMERICSERV with 25 smtp"); ok(test_getaddrinfo(NULL, "25 ", &hints, &ai) == EAI_NONAME, "AI_NUMERICSERV with 25 space"); ok(test_getaddrinfo(NULL, "25", &hints, &ai) == 0, "valid AI_NUMERICSERV"); saddr = (struct sockaddr_in *) ai->ai_addr; is_int(htons(25), saddr->sin_port, "...right port"); ok(saddr->sin_addr.s_addr == INADDR_LOOPBACK, "...right address"); test_freeaddrinfo(ai); ok(test_getaddrinfo(NULL, NULL, NULL, &ai) == EAI_NONAME, "EAI_NONAME"); hints.ai_flags = 2000; ok(test_getaddrinfo(NULL, "25", &hints, &ai) == EAI_BADFLAGS, "EAI_BADFLAGS"); hints.ai_flags = 0; hints.ai_socktype = SOCK_RAW; ok(test_getaddrinfo(NULL, "25", &hints, &ai) == EAI_SOCKTYPE, "EAI_SOCKTYPE"); hints.ai_socktype = 0; hints.ai_family = AF_UNIX; ok(test_getaddrinfo(NULL, "25", &hints, &ai) == EAI_FAMILY, "EAI_FAMILY"); hints.ai_family = AF_UNSPEC; inet_aton("10.20.30.40", &addr); ok(test_getaddrinfo("10.20.30.40", NULL, NULL, &ai) == 0, "IP address lookup"); is_int(AF_INET, ai->ai_family, "...right family"); is_int(0, ai->ai_socktype, "...right socktype"); is_int(IPPROTO_TCP, ai->ai_protocol, "...right protocol"); is_string(NULL, ai->ai_canonname, "...no canonname"); is_int(sizeof(struct sockaddr_in), ai->ai_addrlen, "...right addrlen"); saddr = (struct sockaddr_in *) ai->ai_addr; is_int(0, saddr->sin_port, "...right port"); ok(saddr->sin_addr.s_addr == addr.s_addr, "...right address"); test_freeaddrinfo(ai); if (service == NULL) skip_block(7, "smtp service not found"); else { ok(test_getaddrinfo("10.20.30.40", "smtp", &hints, &ai) == 0, "IP address lookup with smtp service"); is_int(AF_INET, ai->ai_family, "...right family"); is_int(SOCK_STREAM, ai->ai_socktype, "...right socktype"); is_int(IPPROTO_TCP, ai->ai_protocol, "...right protocol"); is_string(NULL, ai->ai_canonname, "...no canonname"); saddr = (struct sockaddr_in *) ai->ai_addr; is_int(htons(25), saddr->sin_port, "...right port"); ok(saddr->sin_addr.s_addr == addr.s_addr, "...right address"); test_freeaddrinfo(ai); } hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; ok(test_getaddrinfo("10.2.3.4", "smtp", &hints, &ai) == EAI_NONAME, "AI_NUMERICHOST and AI_NUMERICSERV with symbolic service"); ok(test_getaddrinfo("example.com", "25", &hints, &ai) == EAI_NONAME, "AI_NUMERICHOST and AI_NUMERICSERV with symbolic name"); ok(test_getaddrinfo("10.20.30.40", "25", &hints, &ai) == 0, "valid AI_NUMERICHOST and AI_NUMERICSERV"); saddr = (struct sockaddr_in *) ai->ai_addr; is_int(htons(25), saddr->sin_port, "...right port"); ok(saddr->sin_addr.s_addr == addr.s_addr, "...right address"); test_freeaddrinfo(ai); if (service == NULL) skip_block(4, "smtp service not found"); else { hints.ai_flags = AI_NUMERICHOST | AI_CANONNAME; ok(test_getaddrinfo("10.20.30.40", "smtp", &hints, &ai) == 0, "AI_NUMERICHOST and AI_CANONNAME"); is_string("10.20.30.40", ai->ai_canonname, "...right canonname"); saddr = (struct sockaddr_in *) ai->ai_addr; is_int(htons(25), saddr->sin_port, "...right port"); ok(saddr->sin_addr.s_addr == addr.s_addr, "...right address"); test_freeaddrinfo(ai); } service = getservbyname("domain", "udp"); if (service == NULL) skip_block(5, "domain service not found"); else { hints.ai_flags = 0; hints.ai_socktype = SOCK_DGRAM; ok(test_getaddrinfo("10.20.30.40", "domain", &hints, &ai) == 0, "domain service with UDP hint"); is_int(SOCK_DGRAM, ai->ai_socktype, "...right socktype"); is_string(NULL, ai->ai_canonname, "...no canonname"); saddr = (struct sockaddr_in *) ai->ai_addr; is_int(htons(53), saddr->sin_port, "...right port"); ok(saddr->sin_addr.s_addr == addr.s_addr, "...right address"); test_freeaddrinfo(ai); } /* Hopefully this will always resolve. */ host = gethostbyname("www.isc.org"); if (host == NULL) skip_block(9, "cannot look up www.isc.org"); else { hints.ai_flags = 0; hints.ai_socktype = SOCK_STREAM; ok(test_getaddrinfo("www.isc.org", "80", &hints, &ai) == 0, "lookup of www.isc.org"); is_int(SOCK_STREAM, ai->ai_socktype, "...right socktype"); is_string(NULL, ai->ai_canonname, "...no canonname"); saddr = (struct sockaddr_in *) ai->ai_addr; is_int(htons(80), saddr->sin_port, "...right port"); ok(saddr->sin_addr.s_addr != INADDR_ANY, "...address is something"); addr = saddr->sin_addr; test_freeaddrinfo(ai); hints.ai_flags = AI_CANONNAME; ok(test_getaddrinfo("www.isc.org", "80", &hints, &ai) == 0, "lookup of www.isc.org with A_CANONNAME"); ok(ai->ai_canonname != NULL, "...canonname isn't null"); saddr = (struct sockaddr_in *) ai->ai_addr; is_int(htons(80), saddr->sin_port, "...right port"); ok(saddr->sin_addr.s_addr == addr.s_addr, "...and same address"); test_freeaddrinfo(ai); } /* Included because it had multiple A records. */ host = gethostbyname("cnn.com"); if (host == NULL) skip_block(3, "cannot look up cnn.com"); else { ok(test_getaddrinfo("cnn.com", "80", NULL, &ai) == 0, "lookup of cnn.com with multiple A records"); saddr = (struct sockaddr_in *) ai->ai_addr; is_int(htons(80), saddr->sin_port, "...right port"); ok(saddr->sin_addr.s_addr != INADDR_ANY, "...address is something"); test_freeaddrinfo(ai); } hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_CANONNAME; ok(test_getaddrinfo("foo.invalid", NULL, NULL, &ai) == EAI_NONAME, "lookup of invalid address"); host = gethostbyname("cnn.com"); if (host == NULL) { skip_block(3, "cannot look up cnn.com"); exit(0); } ok(test_getaddrinfo("cnn.com", NULL, &hints, &ai) == 0, "lookup of cnn.com"); saddr = (struct sockaddr_in *) ai->ai_addr; is_int(0, saddr->sin_port, "...port is 0"); first = ai; for (found = 0; ai != NULL; ai = ai->ai_next) { if (!strcmp(ai->ai_canonname, first->ai_canonname) == 0) { ok(0, "...canonname matches"); break; } if (ai != first && ai->ai_canonname == first->ai_canonname) { ok(0, "...each canonname is a separate pointer"); break; } found = 0; saddr = (struct sockaddr_in *) ai->ai_addr; addr = saddr->sin_addr; for (i = 0; host->h_addr_list[i] != NULL; i++) if (memcmp(&addr, host->h_addr_list[i], host->h_length) == 0) found = 1; if (!found) { ok(0, "...result found in gethostbyname address list"); break; } } if (found) ok(1, "...result found in gethostbyname address list"); test_freeaddrinfo(ai); return 0; }