| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- /*
- * lws-api-test-async-dns
- *
- * Written in 2019 by Andy Green <[email protected]>
- *
- * This file is made available under the Creative Commons CC0 1.0
- * Universal Public Domain Dedication.
- *
- * This api test confirms various kinds of async dns apis
- */
- #include <libwebsockets.h>
- #include <signal.h>
- static int interrupted, dtest, ok, fail, _exp = 26;
- struct lws_context *context;
- /*
- * These are used to test the apis to parse and print ipv4 / ipv6 literal
- * address strings for various cases.
- *
- * Expected error cases are not used to test the ip data -> string api.
- */
- static const struct ipparser_tests {
- const char *test;
- int rlen;
- const char *emit_test;
- int emit_len;
- uint8_t b[16];
- } ipt[] = {
- { "2001:db8:85a3:0:0:8a2e:370:7334", 16,
- "2001:db8:85a3::8a2e:370:7334", 28,
- { 0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3, 0x00, 0x00,
- 0x00, 0x00, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x34 } },
- { "2001:db8:85a3::8a2e:370:7334", 16,
- "2001:db8:85a3::8a2e:370:7334", 28,
- { 0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3, 0x00, 0x00,
- 0x00, 0x00, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x34 } },
- { "::1", 16, "::1", 3,
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 } },
- { "::", 16, "::", 2,
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
- { "::ffff:192.0.2.128", 16, "::ffff:192.0.2.128", 18,
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xff, 0xff, 0xc0, 0x00, 0x02, 0x80 } },
- { "cats", -1, "", 0,
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 } },
- { "onevalid.bogus.warmcat.com", -1, "", 0,
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 } },
- { "1.cat.dog.com", -1, "", 0,
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 } },
- { ":::1", -8, "", 0,
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 } },
- { "0:0::0:1", 16, "::1", 3,
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 } },
- { "1.2.3.4", 4, "1.2.3.4", 7, { 1, 2, 3, 4 } },
- };
- static const struct async_dns_tests {
- const char *dns_name;
- int recordtype;
- int addrlen;
- uint8_t ads[16];
- } adt[] = {
- { "warmcat.com", LWS_ADNS_RECORD_A, 4,
- { 46, 105, 127, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } },
- { "libwebsockets.org", LWS_ADNS_RECORD_A, 4,
- { 46, 105, 127, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } },
- { "doesntexist", LWS_ADNS_RECORD_A, 0,
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } },
- { "localhost", LWS_ADNS_RECORD_A, 4,
- { 127, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } },
- { "ipv4only.warmcat.com", LWS_ADNS_RECORD_A, 4,
- { 46, 105, 127, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } },
- { "onevalid.bogus.warmcat.com", LWS_ADNS_RECORD_A, 4,
- { 46, 105, 127, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } },
- #if defined(LWS_WITH_IPV6)
- { "warmcat.com", LWS_ADNS_RECORD_AAAA, 16, /* check ipv6 */
- { 0x20, 0x01, 0x41, 0xd0, 0x00, 0x02, 0xee, 0x93,
- 0, 0, 0, 0, 0, 0, 0, 0, } },
- { "ipv6only.warmcat.com", LWS_ADNS_RECORD_AAAA, 16, /* check ipv6 */
- { 0x20, 0x01, 0x41, 0xd0, 0x00, 0x02, 0xee, 0x93,
- 0, 0, 0, 0, 0, 0, 0, 0, } },
- #endif
- };
- static lws_sorted_usec_list_t sul;
- struct lws *
- cb1(struct lws *wsi_unused, const char *ads, const struct addrinfo *a, int n,
- void *opaque);
- static void
- next_test_cb(lws_sorted_usec_list_t *sul)
- {
- int m;
- lwsl_notice("%s: querying %s\n", __func__, adt[dtest].dns_name);
- m = lws_async_dns_query(context, 0,
- adt[dtest].dns_name,
- adt[dtest].recordtype, cb1, NULL,
- context);
- if (m != LADNS_RET_CONTINUING && m != LADNS_RET_FOUND) {
- lwsl_err("%s: adns 1 failed: %d\n", __func__, m);
- interrupted = 1;
- }
- }
- struct lws *
- cb1(struct lws *wsi_unused, const char *ads, const struct addrinfo *a, int n,
- void *opaque)
- {
- const struct addrinfo *ac = a;
- int ctr = 0, alen;
- uint8_t *addr;
- char buf[64];
- dtest++;
- if (!ac)
- lwsl_warn("%s: no results\n", __func__);
- /* dump the results */
- while (ac) {
- if (ac->ai_family == AF_INET) {
- addr = (uint8_t *)&(((struct sockaddr_in *)
- ac->ai_addr)->sin_addr.s_addr);
- alen = 4;
- } else {
- addr = (uint8_t *)&(((struct sockaddr_in6 *)
- ac->ai_addr)->sin6_addr.s6_addr);
- alen = 16;
- }
- strcpy(buf, "unknown");
- lws_write_numeric_address(addr, alen, buf, sizeof(buf));
- lwsl_warn("%s: %d: %s %d %s\n", __func__, ctr++, ads, alen, buf);
- ac = ac->ai_next;
- }
- ac = a;
- while (ac) {
- if (ac->ai_family == AF_INET) {
- addr = (uint8_t *)&(((struct sockaddr_in *)
- ac->ai_addr)->sin_addr.s_addr);
- alen = 4;
- } else {
- #if defined(LWS_WITH_IPV6)
- addr = (uint8_t *)&(((struct sockaddr_in6 *)
- ac->ai_addr)->sin6_addr.s6_addr);
- alen = 16;
- #else
- goto again;
- #endif
- }
- if (alen == adt[dtest - 1].addrlen &&
- !memcmp(adt[dtest - 1].ads, addr, alen)) {
- ok++;
- goto next;
- }
- #if !defined(LWS_WITH_IPV6)
- again:
- #endif
- ac = ac->ai_next;
- }
- /* testing for NXDOMAIN? */
- if (!a && !adt[dtest - 1].addrlen) {
- ok++;
- goto next;
- }
- lwsl_err("%s: dns test %d: no match\n", __func__, dtest);
- fail++;
- next:
- lws_async_dns_freeaddrinfo(&a);
- if (dtest == (int)LWS_ARRAY_SIZE(adt))
- interrupted = 1;
- else
- lws_sul_schedule(context, 0, &sul, next_test_cb, 1);
- return NULL;
- }
- void sigint_handler(int sig)
- {
- interrupted = 1;
- }
- int
- main(int argc, const char **argv)
- {
- int n = 1, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE;
- struct lws_context_creation_info info;
- const char *p;
- /* the normal lws init */
- signal(SIGINT, sigint_handler);
- if ((p = lws_cmdline_option(argc, argv, "-d")))
- logs = atoi(p);
- lws_set_log_level(logs, NULL);
- lwsl_user("LWS API selftest: Async DNS\n");
- memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
- info.port = CONTEXT_PORT_NO_LISTEN;
- info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
- context = lws_create_context(&info);
- if (!context) {
- lwsl_err("lws init failed\n");
- return 1;
- }
- /* ip address parser tests */
- for (n = 0; n < (int)LWS_ARRAY_SIZE(ipt); n++) {
- uint8_t u[16];
- int m = lws_parse_numeric_address(ipt[n].test, u, sizeof(u));
- if (m != ipt[n].rlen) {
- lwsl_err("%s: fail %s ret %d\n",
- __func__, ipt[n].test, m);
- fail++;
- continue;
- }
- if (m > 0) {
- if (memcmp(ipt[n].b, u, m)) {
- lwsl_err("%s: fail %s compare\n", __func__,
- ipt[n].test);
- lwsl_hexdump_notice(u, m);
- fail++;
- continue;
- }
- }
- ok++;
- }
- /* ip address formatter tests */
- for (n = 0; n < (int)LWS_ARRAY_SIZE(ipt); n++) {
- char buf[64];
- int m;
- /* don't attempt to reverse the ones that are meant to fail */
- if (ipt[n].rlen < 0)
- continue;
- m = lws_write_numeric_address(ipt[n].b, ipt[n].rlen, buf,
- sizeof(buf));
- if (m != ipt[n].emit_len) {
- lwsl_err("%s: fail %s ret %d\n",
- __func__, ipt[n].emit_test, m);
- fail++;
- continue;
- }
- if (m > 0) {
- if (strcmp(ipt[n].emit_test, buf)) {
- lwsl_err("%s: fail %s compare\n", __func__,
- ipt[n].test);
- lwsl_hexdump_notice(buf, m);
- fail++;
- continue;
- }
- }
- ok++;
- }
- #if !defined(LWS_WITH_IPV6)
- _exp -= 2;
- #endif
- /* kick off the async dns tests */
- lws_sul_schedule(context, 0, &sul, next_test_cb, 1);
- /* the usual lws event loop */
- n = 1;
- while (n >= 0 && !interrupted)
- n = lws_service(context, 0);
- lws_context_destroy(context);
- if (fail || ok != _exp)
- lwsl_user("Completed: PASS: %d / %d, FAIL: %d\n", ok, _exp,
- fail);
- else
- lwsl_user("Completed: ALL PASS: %d / %d\n", ok, _exp);
- return !(ok == _exp && !fail);
- }
|