diff --git a/bin/named/statschannel.c b/bin/named/statschannel.c index 59fabdea89..ee9a0f38a8 100644 --- a/bin/named/statschannel.c +++ b/bin/named/statschannel.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -54,6 +53,14 @@ #include "xsl_p.h" +#define CHECK(m) \ + do { \ + result = (m); \ + if (result != ISC_R_SUCCESS) { \ + goto cleanup; \ + } \ + } while (0) + struct named_statschannel { /* Unlocked */ isc_httpdmgr_t *httpdmgr; @@ -170,11 +177,11 @@ static const char *gluecachestats_xmldesc[dns_gluecachestatscounter_max]; #define gluecachestats_xmldesc NULL #endif /* EXTENDED_STATS */ -#define TRY0(a) \ - do { \ - xmlrc = (a); \ - if (xmlrc < 0) \ - goto error; \ +#define TRY0(a) \ + do { \ + xmlrc = (a); \ + if (xmlrc < 0) \ + goto cleanup; \ } while (0) /*% @@ -1424,7 +1431,7 @@ dump_counters(isc_stats_t *stats, isc_statsformat_t type, void *arg, } return (ISC_R_SUCCESS); #ifdef HAVE_LIBXML2 -error: +cleanup: isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, "failed at dump_counters()"); @@ -1486,7 +1493,7 @@ rdtypestat_dump(dns_rdatastatstype_t type, uint64_t val, void *arg) { } return; #ifdef HAVE_LIBXML2 -error: +cleanup: isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, "failed at rdtypestat_dump()"); @@ -1574,7 +1581,7 @@ rdatasetstats_dump(dns_rdatastatstype_t type, uint64_t val, void *arg) { } return; #ifdef HAVE_LIBXML2 -error: +cleanup: isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, "failed at rdatasetstats_dump()"); @@ -1629,7 +1636,7 @@ opcodestat_dump(dns_opcode_t code, uint64_t val, void *arg) { return; #ifdef HAVE_LIBXML2 -error: +cleanup: isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, "failed at opcodestat_dump()"); @@ -1685,7 +1692,7 @@ rcodestat_dump(dns_rcode_t code, uint64_t val, void *arg) { return; #ifdef HAVE_LIBXML2 -error: +cleanup: isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, "failed at rcodestat_dump()"); @@ -1738,7 +1745,7 @@ dnssecsignstat_dump(dns_keytag_t tag, uint64_t val, void *arg) { } return; #ifdef HAVE_LIBXML2 -error: +cleanup: isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, "failed at dnssecsignstat_dump()"); @@ -1772,6 +1779,7 @@ zone_xmlrender(dns_zone_t *zone, void *arg) { int xmlrc; stats_dumparg_t dumparg; const char *ztype; + isc_time_t timestamp; statlevel = dns_zone_getstatlevel(zone); if (statlevel == dns_zonestat_none) { @@ -1814,12 +1822,8 @@ zone_xmlrender(dns_zone_t *zone, void *arg) { * master zones, only include the loaded time. For slave zones, also * include the expires and refresh times. */ - isc_time_t timestamp; - result = dns_zone_getloadtime(zone, ×tamp); - if (result != ISC_R_SUCCESS) { - goto error; - } + CHECK(dns_zone_getloadtime(zone, ×tamp)); isc_time_formatISO8601(×tamp, buf, 64); TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "loaded")); @@ -1827,19 +1831,13 @@ zone_xmlrender(dns_zone_t *zone, void *arg) { TRY0(xmlTextWriterEndElement(writer)); if (dns_zone_gettype(zone) == dns_zone_slave) { - result = dns_zone_getexpiretime(zone, ×tamp); - if (result != ISC_R_SUCCESS) { - goto error; - } + CHECK(dns_zone_getexpiretime(zone, ×tamp)); isc_time_formatISO8601(×tamp, buf, 64); TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "expires")); TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR buf)); TRY0(xmlTextWriterEndElement(writer)); - result = dns_zone_getrefreshtime(zone, ×tamp); - if (result != ISC_R_SUCCESS) { - goto error; - } + CHECK(dns_zone_getrefreshtime(zone, ×tamp)); isc_time_formatISO8601(×tamp, buf, 64); TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "refresh")); TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR buf)); @@ -1862,14 +1860,11 @@ zone_xmlrender(dns_zone_t *zone, void *arg) { ISC_XMLCHAR "type", ISC_XMLCHAR "rcode")); - result = dump_counters(zonestats, isc_statsformat_xml, - writer, NULL, nsstats_xmldesc, - ns_statscounter_max, - nsstats_index, nsstat_values, - ISC_STATSDUMP_VERBOSE); - if (result != ISC_R_SUCCESS) { - goto error; - } + CHECK(dump_counters(zonestats, isc_statsformat_xml, + writer, NULL, nsstats_xmldesc, + ns_statscounter_max, nsstats_index, + nsstat_values, + ISC_STATSDUMP_VERBOSE)); /* counters type="rcode"*/ TRY0(xmlTextWriterEndElement(writer)); } @@ -1882,15 +1877,12 @@ zone_xmlrender(dns_zone_t *zone, void *arg) { writer, ISC_XMLCHAR "type", ISC_XMLCHAR "gluecache")); - result = dump_counters( + CHECK(dump_counters( gluecachestats, isc_statsformat_xml, writer, NULL, gluecachestats_xmldesc, dns_gluecachestatscounter_max, gluecachestats_index, gluecachestats_values, - ISC_STATSDUMP_VERBOSE); - if (result != ISC_R_SUCCESS) { - goto error; - } + ISC_STATSDUMP_VERBOSE)); /* counters type="rcode"*/ TRY0(xmlTextWriterEndElement(writer)); } @@ -1906,9 +1898,7 @@ zone_xmlrender(dns_zone_t *zone, void *arg) { dumparg.result = ISC_R_SUCCESS; dns_rdatatypestats_dump(rcvquerystats, rdtypestat_dump, &dumparg, 0); - if (dumparg.result != ISC_R_SUCCESS) { - goto error; - } + CHECK(dumparg.result); /* counters type="qtype"*/ TRY0(xmlTextWriterEndElement(writer)); @@ -1927,9 +1917,7 @@ zone_xmlrender(dns_zone_t *zone, void *arg) { dns_dnssecsignstats_dump( dnssecsignstats, dns_dnssecsignstats_sign, dnssecsignstat_dump, &dumparg, 0); - if (dumparg.result != ISC_R_SUCCESS) { - goto error; - } + CHECK(dumparg.result); /* counters type="dnssec-sign"*/ TRY0(xmlTextWriterEndElement(writer)); @@ -1945,9 +1933,7 @@ zone_xmlrender(dns_zone_t *zone, void *arg) { dns_dnssecsignstats_dump( dnssecsignstats, dns_dnssecsignstats_refresh, dnssecsignstat_dump, &dumparg, 0); - if (dumparg.result != ISC_R_SUCCESS) { - goto error; - } + CHECK(dumparg.result); /* counters type="dnssec-refresh"*/ TRY0(xmlTextWriterEndElement(writer)); @@ -1957,7 +1943,7 @@ zone_xmlrender(dns_zone_t *zone, void *arg) { TRY0(xmlTextWriterEndElement(writer)); /* zone */ return (ISC_R_SUCCESS); -error: +cleanup: isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, "Failed at zone_xmlrender()"); @@ -1999,7 +1985,7 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen, writer = xmlNewTextWriterDoc(&doc, 0); if (writer == NULL) { - goto error; + goto cleanup; } TRY0(xmlTextWriterStartDocument(writer, NULL, "UTF-8", NULL)); TRY0(xmlTextWriterWritePI(writer, ISC_XMLCHAR "xml-stylesheet", @@ -2037,9 +2023,7 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen, dns_opcodestats_dump(server->sctx->opcodestats, opcodestat_dump, &dumparg, ISC_STATSDUMP_VERBOSE); - if (dumparg.result != ISC_R_SUCCESS) { - goto error; - } + CHECK(dumparg.result); TRY0(xmlTextWriterEndElement(writer)); @@ -2049,9 +2033,7 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen, dns_rcodestats_dump(server->sctx->rcodestats, rcodestat_dump, &dumparg, ISC_STATSDUMP_VERBOSE); - if (dumparg.result != ISC_R_SUCCESS) { - goto error; - } + CHECK(dumparg.result); TRY0(xmlTextWriterEndElement(writer)); @@ -2062,23 +2044,19 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen, dumparg.result = ISC_R_SUCCESS; dns_rdatatypestats_dump(server->sctx->rcvquerystats, rdtypestat_dump, &dumparg, 0); - if (dumparg.result != ISC_R_SUCCESS) { - goto error; - } + CHECK(dumparg.result); + TRY0(xmlTextWriterEndElement(writer)); /* counters */ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "nsstat")); - result = dump_counters(ns_stats_get(server->sctx->nsstats), - isc_statsformat_xml, writer, NULL, - nsstats_xmldesc, ns_statscounter_max, - nsstats_index, nsstat_values, - ISC_STATSDUMP_VERBOSE); - if (result != ISC_R_SUCCESS) { - goto error; - } + CHECK(dump_counters(ns_stats_get(server->sctx->nsstats), + isc_statsformat_xml, writer, NULL, + nsstats_xmldesc, ns_statscounter_max, + nsstats_index, nsstat_values, + ISC_STATSDUMP_VERBOSE)); TRY0(xmlTextWriterEndElement(writer)); /* /nsstat */ @@ -2086,14 +2064,10 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen, TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "zonestat")); - result = dump_counters(server->zonestats, isc_statsformat_xml, - writer, NULL, zonestats_xmldesc, - dns_zonestatscounter_max, - zonestats_index, zonestat_values, - ISC_STATSDUMP_VERBOSE); - if (result != ISC_R_SUCCESS) { - goto error; - } + CHECK(dump_counters(server->zonestats, isc_statsformat_xml, + writer, NULL, zonestats_xmldesc, + dns_zonestatscounter_max, zonestats_index, + zonestat_values, ISC_STATSDUMP_VERBOSE)); TRY0(xmlTextWriterEndElement(writer)); /* /zonestat */ @@ -2104,13 +2078,11 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen, TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "resstat")); - result = dump_counters( - server->resolverstats, isc_statsformat_xml, writer, - NULL, resstats_xmldesc, dns_resstatscounter_max, - resstats_index, resstat_values, 0); - if (result != ISC_R_SUCCESS) { - goto error; - } + CHECK(dump_counters(server->resolverstats, isc_statsformat_xml, + writer, NULL, resstats_xmldesc, + dns_resstatscounter_max, resstats_index, + resstat_values, 0)); + TRY0(xmlTextWriterEndElement(writer)); /* resstat */ #ifdef HAVE_DNSTAP @@ -2127,9 +2099,8 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen, dnstapstats_xmldesc, dns_dnstapcounter_max, dnstapstats_index, dnstapstat_values, 0); isc_stats_detach(&dnstapstats); - if (result != ISC_R_SUCCESS) { - goto error; - } + CHECK(result); + TRY0(xmlTextWriterEndElement(writer)); /* dnstap */ } #endif /* ifdef HAVE_DNSTAP */ @@ -2140,14 +2111,10 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen, TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "sockstat")); - result = dump_counters(server->sockstats, isc_statsformat_xml, - writer, NULL, sockstats_xmldesc, - isc_sockstatscounter_max, - sockstats_index, sockstat_values, - ISC_STATSDUMP_VERBOSE); - if (result != ISC_R_SUCCESS) { - goto error; - } + CHECK(dump_counters(server->sockstats, isc_statsformat_xml, + writer, NULL, sockstats_xmldesc, + isc_sockstatscounter_max, sockstats_index, + sockstat_values, ISC_STATSDUMP_VERBOSE)); TRY0(xmlTextWriterEndElement(writer)); /* /sockstat */ } @@ -2161,13 +2128,10 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen, TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "request-size")); - result = dump_counters( + CHECK(dump_counters( server->sctx->udpinstats4, isc_statsformat_xml, writer, NULL, udpinsizestats_xmldesc, dns_sizecounter_in_max, - udpinsizestats_index, udpinsizestat_values, 0); - if (result != ISC_R_SUCCESS) { - goto error; - } + udpinsizestats_index, udpinsizestat_values, 0)); TRY0(xmlTextWriterEndElement(writer)); /* */ @@ -2175,13 +2139,10 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen, TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "response-size")); - result = dump_counters( + CHECK(dump_counters( server->sctx->udpoutstats4, isc_statsformat_xml, writer, NULL, udpoutsizestats_xmldesc, dns_sizecounter_out_max, - udpoutsizestats_index, udpoutsizestat_values, 0); - if (result != ISC_R_SUCCESS) { - goto error; - } + udpoutsizestats_index, udpoutsizestat_values, 0)); TRY0(xmlTextWriterEndElement(writer)); /* */ TRY0(xmlTextWriterEndElement(writer)); /* */ @@ -2191,27 +2152,20 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen, TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "request-size")); - result = dump_counters( + CHECK(dump_counters( server->sctx->tcpinstats4, isc_statsformat_xml, writer, NULL, tcpinsizestats_xmldesc, dns_sizecounter_in_max, - tcpinsizestats_index, tcpinsizestat_values, 0); - if (result != ISC_R_SUCCESS) { - goto error; - } + tcpinsizestats_index, tcpinsizestat_values, 0)); TRY0(xmlTextWriterEndElement(writer)); /* */ - TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "response-size")); - result = dump_counters( + CHECK(dump_counters( server->sctx->tcpoutstats4, isc_statsformat_xml, writer, NULL, tcpoutsizestats_xmldesc, dns_sizecounter_out_max, - tcpoutsizestats_index, tcpoutsizestat_values, 0); - if (result != ISC_R_SUCCESS) { - goto error; - } + tcpoutsizestats_index, tcpoutsizestat_values, 0)); TRY0(xmlTextWriterEndElement(writer)); /* */ TRY0(xmlTextWriterEndElement(writer)); /* */ @@ -2223,13 +2177,10 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen, TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "request-size")); - result = dump_counters( + CHECK(dump_counters( server->sctx->udpinstats6, isc_statsformat_xml, writer, NULL, udpinsizestats_xmldesc, dns_sizecounter_in_max, - udpinsizestats_index, udpinsizestat_values, 0); - if (result != ISC_R_SUCCESS) { - goto error; - } + udpinsizestats_index, udpinsizestat_values, 0)); TRY0(xmlTextWriterEndElement(writer)); /* */ @@ -2237,13 +2188,10 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen, TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "response-size")); - result = dump_counters( + CHECK(dump_counters( server->sctx->udpoutstats6, isc_statsformat_xml, writer, NULL, udpoutsizestats_xmldesc, dns_sizecounter_out_max, - udpoutsizestats_index, udpoutsizestat_values, 0); - if (result != ISC_R_SUCCESS) { - goto error; - } + udpoutsizestats_index, udpoutsizestat_values, 0)); TRY0(xmlTextWriterEndElement(writer)); /* */ TRY0(xmlTextWriterEndElement(writer)); /* */ @@ -2253,13 +2201,10 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen, TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "request-size")); - result = dump_counters( + CHECK(dump_counters( server->sctx->tcpinstats6, isc_statsformat_xml, writer, NULL, tcpinsizestats_xmldesc, dns_sizecounter_in_max, - tcpinsizestats_index, tcpinsizestat_values, 0); - if (result != ISC_R_SUCCESS) { - goto error; - } + tcpinsizestats_index, tcpinsizestat_values, 0)); TRY0(xmlTextWriterEndElement(writer)); /* */ @@ -2267,13 +2212,10 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen, TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "response-size")); - result = dump_counters( + CHECK(dump_counters( server->sctx->tcpoutstats6, isc_statsformat_xml, writer, NULL, tcpoutsizestats_xmldesc, dns_sizecounter_out_max, - tcpoutsizestats_index, tcpoutsizestat_values, 0); - if (result != ISC_R_SUCCESS) { - goto error; - } + tcpoutsizestats_index, tcpoutsizestat_values, 0)); TRY0(xmlTextWriterEndElement(writer)); /* */ TRY0(xmlTextWriterEndElement(writer)); /* */ @@ -2296,11 +2238,8 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen, if ((flags & STATS_XML_ZONES) != 0) { TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "zones")); - result = dns_zt_apply(view->zonetable, true, NULL, - zone_xmlrender, writer); - if (result != ISC_R_SUCCESS) { - goto error; - } + CHECK(dns_zt_apply(view->zonetable, true, NULL, + zone_xmlrender, writer)); TRY0(xmlTextWriterEndElement(writer)); /* /zones */ } @@ -2318,9 +2257,7 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen, dumparg.result = ISC_R_SUCCESS; dns_rdatatypestats_dump(view->resquerystats, rdtypestat_dump, &dumparg, 0); - if (dumparg.result != ISC_R_SUCCESS) { - goto error; - } + CHECK(dumparg.result); } TRY0(xmlTextWriterEndElement(writer)); @@ -2329,14 +2266,11 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen, TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "resstats")); if (view->resstats != NULL) { - result = dump_counters( - view->resstats, isc_statsformat_xml, writer, - NULL, resstats_xmldesc, dns_resstatscounter_max, - resstats_index, resstat_values, - ISC_STATSDUMP_VERBOSE); - if (result != ISC_R_SUCCESS) { - goto error; - } + CHECK(dump_counters(view->resstats, isc_statsformat_xml, + writer, NULL, resstats_xmldesc, + dns_resstatscounter_max, + resstats_index, resstat_values, + ISC_STATSDUMP_VERBOSE)); } TRY0(xmlTextWriterEndElement(writer)); /* */ @@ -2350,9 +2284,7 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen, dumparg.result = ISC_R_SUCCESS; dns_rdatasetstats_dump(cacherrstats, rdatasetstats_dump, &dumparg, 0); - if (dumparg.result != ISC_R_SUCCESS) { - goto error; - } + CHECK(dumparg.result); TRY0(xmlTextWriterEndElement(writer)); /* cache */ } @@ -2361,14 +2293,11 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen, TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "adbstat")); if (view->adbstats != NULL) { - result = dump_counters( - view->adbstats, isc_statsformat_xml, writer, - NULL, adbstats_xmldesc, dns_adbstats_max, - adbstats_index, adbstat_values, - ISC_STATSDUMP_VERBOSE); - if (result != ISC_R_SUCCESS) { - goto error; - } + CHECK(dump_counters(view->adbstats, isc_statsformat_xml, + writer, NULL, adbstats_xmldesc, + dns_adbstats_max, adbstats_index, + adbstat_values, + ISC_STATSDUMP_VERBOSE)); } TRY0(xmlTextWriterEndElement(writer)); /* */ @@ -2411,12 +2340,12 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen, xmlDocDumpFormatMemoryEnc(doc, buf, buflen, "UTF-8", 0); if (*buf == NULL) { - goto error; + goto cleanup; } xmlFreeDoc(doc); return (ISC_R_SUCCESS); -error: +cleanup: isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, "failed generating XML response"); @@ -2573,18 +2502,11 @@ render_xml_traffic(const char *url, isc_httpdurl_t *urlinfo, #define STATS_JSON_TRAFFIC 0x20 #define STATS_JSON_ALL 0xff -#define CHECK(m) \ - do { \ - result = (m); \ - if (result != ISC_R_SUCCESS) \ - goto error; \ - } while (0) - #define CHECKMEM(m) \ do { \ if (m == NULL) { \ result = ISC_R_NOMEMORY; \ - goto error; \ + goto cleanup; \ } \ } while (0) @@ -2664,27 +2586,18 @@ zone_jsonrender(dns_zone_t *zone, void *arg) { isc_time_t timestamp; - result = dns_zone_getloadtime(zone, ×tamp); - if (result != ISC_R_SUCCESS) { - goto error; - } + CHECK(dns_zone_getloadtime(zone, ×tamp)); isc_time_formatISO8601(×tamp, buf, 64); json_object_object_add(zoneobj, "loaded", json_object_new_string(buf)); if (dns_zone_gettype(zone) == dns_zone_slave) { - result = dns_zone_getexpiretime(zone, ×tamp); - if (result != ISC_R_SUCCESS) { - goto error; - } + CHECK(dns_zone_getexpiretime(zone, ×tamp)); isc_time_formatISO8601(×tamp, buf, 64); json_object_object_add(zoneobj, "expires", json_object_new_string(buf)); - result = dns_zone_getrefreshtime(zone, ×tamp); - if (result != ISC_R_SUCCESS) { - goto error; - } + CHECK(dns_zone_getrefreshtime(zone, ×tamp)); isc_time_formatISO8601(×tamp, buf, 64); json_object_object_add(zoneobj, "refresh", json_object_new_string(buf)); @@ -2703,7 +2616,7 @@ zone_jsonrender(dns_zone_t *zone, void *arg) { json_object *counters = json_object_new_object(); if (counters == NULL) { result = ISC_R_NOMEMORY; - goto error; + goto cleanup; } result = dump_counters(zonestats, isc_statsformat_json, @@ -2712,7 +2625,7 @@ zone_jsonrender(dns_zone_t *zone, void *arg) { nsstats_index, nsstat_values, 0); if (result != ISC_R_SUCCESS) { json_object_put(counters); - goto error; + goto cleanup; } if (json_object_get_object(counters)->count != 0) { @@ -2728,7 +2641,7 @@ zone_jsonrender(dns_zone_t *zone, void *arg) { json_object *counters = json_object_new_object(); if (counters == NULL) { result = ISC_R_NOMEMORY; - goto error; + goto cleanup; } result = dump_counters( @@ -2738,7 +2651,7 @@ zone_jsonrender(dns_zone_t *zone, void *arg) { gluecachestats_index, gluecachestats_values, 0); if (result != ISC_R_SUCCESS) { json_object_put(counters); - goto error; + goto cleanup; } if (json_object_get_object(counters)->count != 0) { @@ -2762,7 +2675,7 @@ zone_jsonrender(dns_zone_t *zone, void *arg) { &dumparg, 0); if (dumparg.result != ISC_R_SUCCESS) { json_object_put(counters); - goto error; + goto cleanup; } if (json_object_get_object(counters)->count != 0) { @@ -2787,7 +2700,7 @@ zone_jsonrender(dns_zone_t *zone, void *arg) { dnssecsignstat_dump, &dumparg, 0); if (dumparg.result != ISC_R_SUCCESS) { json_object_put(sign_counters); - goto error; + goto cleanup; } if (json_object_get_object(sign_counters)->count != 0) { @@ -2809,7 +2722,7 @@ zone_jsonrender(dns_zone_t *zone, void *arg) { dnssecsignstat_dump, &dumparg, 0); if (dumparg.result != ISC_R_SUCCESS) { json_object_put(refresh_counters); - goto error; + goto cleanup; } if (json_object_get_object(refresh_counters)->count != @@ -2827,7 +2740,7 @@ zone_jsonrender(dns_zone_t *zone, void *arg) { zoneobj = NULL; result = ISC_R_SUCCESS; -error: +cleanup: if (zoneobj != NULL) { json_object_put(zoneobj); } @@ -2912,7 +2825,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg, &dumparg, ISC_STATSDUMP_VERBOSE); if (dumparg.result != ISC_R_SUCCESS) { json_object_put(counters); - goto error; + goto cleanup; } if (json_object_get_object(counters)->count != 0) { @@ -2931,7 +2844,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg, &dumparg, ISC_STATSDUMP_VERBOSE); if (dumparg.result != ISC_R_SUCCESS) { json_object_put(counters); - goto error; + goto cleanup; } if (json_object_get_object(counters)->count != 0) { @@ -2950,7 +2863,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg, rdtypestat_dump, &dumparg, 0); if (dumparg.result != ISC_R_SUCCESS) { json_object_put(counters); - goto error; + goto cleanup; } if (json_object_get_object(counters)->count != 0) { @@ -2971,7 +2884,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg, nsstats_index, nsstat_values, 0); if (result != ISC_R_SUCCESS) { json_object_put(counters); - goto error; + goto cleanup; } if (json_object_get_object(counters)->count != 0) { @@ -2992,7 +2905,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg, zonestats_index, zonestat_values, 0); if (result != ISC_R_SUCCESS) { json_object_put(counters); - goto error; + goto cleanup; } if (json_object_get_object(counters)->count != 0) { @@ -3014,7 +2927,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg, resstats_index, resstat_values, 0); if (result != ISC_R_SUCCESS) { json_object_put(counters); - goto error; + goto cleanup; } if (json_object_get_object(counters)->count != 0) { @@ -3039,7 +2952,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg, isc_stats_detach(&dnstapstats); if (result != ISC_R_SUCCESS) { json_object_put(counters); - goto error; + goto cleanup; } if (json_object_get_object(counters)->count != 0) { @@ -3069,12 +2982,8 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg, CHECKMEM(za); if ((flags & STATS_JSON_ZONES) != 0) { - result = dns_zt_apply(view->zonetable, true, - NULL, zone_jsonrender, - za); - if (result != ISC_R_SUCCESS) { - goto error; - } + CHECK(dns_zt_apply(view->zonetable, true, NULL, + zone_jsonrender, za)); } if (json_object_array_length(za) != 0) { @@ -3107,7 +3016,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg, if (result != ISC_R_SUCCESS) { json_object_put(counters); result = dumparg.result; - goto error; + goto cleanup; } json_object_object_add(res, "stats", @@ -3127,7 +3036,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg, if (dumparg.result != ISC_R_SUCCESS) { json_object_put(counters); result = dumparg.result; - goto error; + goto cleanup; } json_object_object_add(res, "qtypes", @@ -3147,7 +3056,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg, if (dumparg.result != ISC_R_SUCCESS) { json_object_put(counters); result = dumparg.result; - goto error; + goto cleanup; } json_object_object_add(res, "cache", @@ -3161,7 +3070,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg, counters); if (result != ISC_R_SUCCESS) { json_object_put(counters); - goto error; + goto cleanup; } json_object_object_add(res, "cachestats", @@ -3182,7 +3091,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg, if (result != ISC_R_SUCCESS) { json_object_put(counters); result = dumparg.result; - goto error; + goto cleanup; } json_object_object_add(res, "adb", @@ -3208,7 +3117,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg, sockstats_index, sockstat_values, 0); if (result != ISC_R_SUCCESS) { json_object_put(counters); - goto error; + goto cleanup; } if (json_object_get_object(counters)->count != 0) { @@ -3224,7 +3133,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg, result = isc_socketmgr_renderjson(named_g_socketmgr, sockets); if (result != ISC_R_SUCCESS) { json_object_put(sockets); - goto error; + goto cleanup; } json_object_object_add(bindstats, "socketmgr", sockets); @@ -3237,7 +3146,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg, result = isc_taskmgr_renderjson(named_g_taskmgr, tasks); if (result != ISC_R_SUCCESS) { json_object_put(tasks); - goto error; + goto cleanup; } json_object_object_add(bindstats, "taskmgr", tasks); @@ -3250,7 +3159,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg, result = isc_mem_renderjson(memory); if (result != ISC_R_SUCCESS) { json_object_put(memory); - goto error; + goto cleanup; } json_object_object_add(bindstats, "memory", memory); @@ -3375,7 +3284,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg, result = ISC_R_SUCCESS; -error: +cleanup: if (udpreq4 != NULL) { json_object_put(udpreq4); } @@ -3654,7 +3563,7 @@ client_ok(const isc_sockaddr_t *fromaddr, void *arg) { static void destroy_listener(void *arg) { - named_statschannel_t *listener = arg; + named_statschannel_t *listener = (named_statschannel_t *)arg; REQUIRE(listener != NULL); REQUIRE(!ISC_LINK_LINKED(listener, link)); @@ -3672,22 +3581,15 @@ add_listener(named_server_t *server, named_statschannel_t **listenerp, isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx, const char *socktext) { isc_result_t result; - named_statschannel_t *listener; - isc_task_t *task = NULL; - isc_socket_t *sock = NULL; - const cfg_obj_t *allow; + named_statschannel_t *listener = NULL; + const cfg_obj_t *allow = NULL; dns_acl_t *new_acl = NULL; + int pf; listener = isc_mem_get(server->mctx, sizeof(*listener)); - - listener->httpdmgr = NULL; - listener->address = *addr; - listener->acl = NULL; - listener->mctx = NULL; + *listener = (named_statschannel_t){ .address = *addr }; ISC_LINK_INIT(listener, link); - isc_mutex_init(&listener->lock); - isc_mem_attach(server->mctx, &listener->mctx); allow = cfg_tuple_get(listen_params, "allow"); @@ -3698,104 +3600,80 @@ add_listener(named_server_t *server, named_statschannel_t **listenerp, } else { result = dns_acl_any(listener->mctx, &new_acl); } - if (result != ISC_R_SUCCESS) { - goto cleanup; - } + CHECK(result); + dns_acl_attach(new_acl, &listener->acl); dns_acl_detach(&new_acl); - result = isc_task_create(named_g_taskmgr, 0, &task); - if (result != ISC_R_SUCCESS) { - goto cleanup; - } - isc_task_setname(task, "statchannel", NULL); - - result = isc_socket_create(named_g_socketmgr, isc_sockaddr_pf(addr), - isc_sockettype_tcp, &sock); - if (result != ISC_R_SUCCESS) { - goto cleanup; - } - isc_socket_setname(sock, "statchannel", NULL); - -#ifndef ISC_ALLOW_MAPPED - isc_socket_ipv6only(sock, true); -#endif /* ifndef ISC_ALLOW_MAPPED */ - - result = isc_socket_bind(sock, addr, ISC_SOCKET_REUSEADDRESS); - if (result != ISC_R_SUCCESS) { - goto cleanup; + pf = isc_sockaddr_pf(&listener->address); + if ((pf == AF_INET && isc_net_probeipv4() != ISC_R_SUCCESS) || + (pf == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS)) + { + CHECK(ISC_R_FAMILYNOSUPPORT); } - result = isc_httpdmgr_create(server->mctx, sock, task, client_ok, - destroy_listener, listener, - named_g_timermgr, &listener->httpdmgr); - if (result != ISC_R_SUCCESS) { - goto cleanup; - } + CHECK(isc_httpdmgr_create(named_g_nm, server->mctx, addr, client_ok, + destroy_listener, listener, + &listener->httpdmgr)); #ifdef HAVE_LIBXML2 - isc_httpdmgr_addurl(listener->httpdmgr, "/", render_xml_all, server); - isc_httpdmgr_addurl(listener->httpdmgr, "/xml", render_xml_all, server); - isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3", render_xml_all, + isc_httpdmgr_addurl(listener->httpdmgr, "/", false, render_xml_all, server); - isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/status", + isc_httpdmgr_addurl(listener->httpdmgr, "/xml", false, render_xml_all, + server); + isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3", false, + render_xml_all, server); + isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/status", false, render_xml_status, server); - isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/server", + isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/server", false, render_xml_server, server); - isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/zones", + isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/zones", false, render_xml_zones, server); - isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/net", render_xml_net, - server); - isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/tasks", + isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/net", false, + render_xml_net, server); + isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/tasks", false, render_xml_tasks, server); - isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/mem", render_xml_mem, - server); - isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/traffic", + isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/mem", false, + render_xml_mem, server); + isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/traffic", false, render_xml_traffic, server); #endif /* ifdef HAVE_LIBXML2 */ #ifdef HAVE_JSON_C - isc_httpdmgr_addurl(listener->httpdmgr, "/json", render_json_all, + isc_httpdmgr_addurl(listener->httpdmgr, "/json", false, render_json_all, server); - isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1", render_json_all, - server); - isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/status", + isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1", false, + render_json_all, server); + isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/status", false, render_json_status, server); - isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/server", + isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/server", false, render_json_server, server); - isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/zones", + isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/zones", false, render_json_zones, server); - isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/tasks", + isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/tasks", false, render_json_tasks, server); - isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/net", render_json_net, - server); - isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/mem", render_json_mem, - server); - isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/traffic", + isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/net", false, + render_json_net, server); + isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/mem", false, + render_json_mem, server); + isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/traffic", false, render_json_traffic, server); #endif /* ifdef HAVE_JSON_C */ - isc_httpdmgr_addurl2(listener->httpdmgr, "/bind9.xsl", true, render_xsl, - server); + isc_httpdmgr_addurl(listener->httpdmgr, "/bind9.xsl", true, render_xsl, + server); *listenerp = listener; isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE, "statistics channel listening on %s", socktext); + return (ISC_R_SUCCESS); + cleanup: - if (result != ISC_R_SUCCESS) { - if (listener->acl != NULL) { - dns_acl_detach(&listener->acl); - } - isc_mutex_destroy(&listener->lock); - isc_mem_putanddetach(&listener->mctx, listener, - sizeof(*listener)); - } - if (task != NULL) { - isc_task_detach(&task); - } - if (sock != NULL) { - isc_socket_detach(&sock); + if (listener->acl != NULL) { + dns_acl_detach(&listener->acl); } + isc_mutex_destroy(&listener->lock); + isc_mem_putanddetach(&listener->mctx, listener, sizeof(*listener)); return (result); } diff --git a/lib/isc/httpd.c b/lib/isc/httpd.c index d3117d4d6a..2bd82da721 100644 --- a/lib/isc/httpd.c +++ b/lib/isc/httpd.c @@ -18,11 +18,11 @@ #include #include #include +#include #include #include #include #include -#include #include #include @@ -30,16 +30,13 @@ #include #endif /* ifdef HAVE_ZLIB */ -/*% - * TODO: - * - * o Make the URL processing external functions which will fill-in a buffer - * structure we provide, or return an error and we will render a generic - * page and close the client. - */ - -#define MSHUTTINGDOWN(cm) ((cm->flags & ISC_HTTPDMGR_FLAGSHUTTINGDOWN) != 0) -#define MSETSHUTTINGDOWN(cm) (cm->flags |= ISC_HTTPDMGR_FLAGSHUTTINGDOWN) +#define CHECK(m) \ + do { \ + result = (m); \ + if (result != ISC_R_SUCCESS) { \ + goto cleanup; \ + } \ + } while (0) #define HTTP_RECVLEN 1024 #define HTTP_SENDGROW 1024 @@ -56,14 +53,31 @@ #define HTTPDMGR_MAGIC ISC_MAGIC('H', 'p', 'd', 'm') #define VALID_HTTPDMGR(m) ISC_MAGIC_VALID(m, HTTPDMGR_MAGIC) +/*% + * Client states. + * + * _RECV The client is waiting for data after starting a read. + * _SEND All data for a response has completed, and a reply was + * sent via a send call. + */ + +typedef enum { RECV, SEND } state_t; + +/*% + * HTTP methods. + */ +typedef enum { METHOD_UNKNOWN = 0, METHOD_GET = 1, METHOD_POST = 2 } method_t; + /*% http client */ struct isc_httpd { unsigned int magic; /* HTTPD_MAGIC */ - isc_refcount_t references; + isc_httpdmgr_t *mgr; /*%< our parent */ ISC_LINK(isc_httpd_t) link; - unsigned int state; - isc_socket_t *sock; + + isc_nmhandle_t *handle; + state_t state; + int flags; /*% * Received data state. @@ -71,16 +85,11 @@ struct isc_httpd { char recvbuf[HTTP_RECVLEN]; /*%< receive buffer */ uint32_t recvlen; /*%< length recv'd */ char *headers; /*%< set in process_request() */ - unsigned int method; + method_t method; char *url; char *querystring; char *protocol; - /* - * Flags on the httpd client. - */ - int flags; - /*% * Transmit data state. * @@ -119,14 +128,11 @@ struct isc_httpd { void *freecb_arg; }; -/*% lightweight socket manager for httpd output */ struct isc_httpdmgr { unsigned int magic; /* HTTPDMGR_MAGIC */ isc_refcount_t references; isc_mem_t *mctx; - isc_socket_t *sock; /*%< listening socket */ - isc_task_t *task; /*%< owning task */ - isc_timermgr_t *timermgr; + isc_nmsocket_t *sock; isc_httpdclientok_t *client_ok; /*%< client validator */ isc_httpdondestroy_t *ondestroy; /*%< cleanup callback */ @@ -142,73 +148,30 @@ struct isc_httpdmgr { isc_httpdaction_t *render_500; }; -/*% - * HTTP methods. - */ -#define ISC_HTTPD_METHODUNKNOWN 0 -#define ISC_HTTPD_METHODGET 1 -#define ISC_HTTPD_METHODPOST 2 - -/*% - * Client states. - * - * _IDLE The client is not doing anything at all. This state should - * only occur just after creation, and just before being - * destroyed. - * - * _RECV The client is waiting for data after issuing a socket recv(). - * - * _RECVDONE Data has been received, and is being processed. - * - * _SEND All data for a response has completed, and a reply was - * sent via a socket send() call. - * - * _SENDDONE Send is completed. - * - * Badly formatted state table: - * - * IDLE -> RECV when client has a recv() queued. - * - * RECV -> RECVDONE when recvdone event received. - * - * RECVDONE -> SEND if the data for a reply is at hand. - * - * SEND -> RECV when a senddone event was received. - * - * At any time -> RECV on error. If RECV fails, the client will - * self-destroy, closing the socket and freeing memory. - */ -#define ISC_HTTPD_STATEIDLE 0 -#define ISC_HTTPD_STATERECV 1 -#define ISC_HTTPD_STATERECVDONE 2 -#define ISC_HTTPD_STATESEND 3 -#define ISC_HTTPD_STATESENDDONE 4 - -#define ISC_HTTPD_ISRECV(c) ((c)->state == ISC_HTTPD_STATERECV) -#define ISC_HTTPD_ISRECVDONE(c) ((c)->state == ISC_HTTPD_STATERECVDONE) -#define ISC_HTTPD_ISSEND(c) ((c)->state == ISC_HTTPD_STATESEND) -#define ISC_HTTPD_ISSENDDONE(c) ((c)->state == ISC_HTTPD_STATESENDDONE) - -/*% - * Overall magic test that means we're not idle. - */ -#define ISC_HTTPD_SETRECV(c) ((c)->state = ISC_HTTPD_STATERECV) -#define ISC_HTTPD_SETRECVDONE(c) ((c)->state = ISC_HTTPD_STATERECVDONE) -#define ISC_HTTPD_SETSEND(c) ((c)->state = ISC_HTTPD_STATESEND) -#define ISC_HTTPD_SETSENDDONE(c) ((c)->state = ISC_HTTPD_STATESENDDONE) - -static void -isc_httpd_accept(isc_task_t *, isc_event_t *); -static void -isc_httpd_recvdone(isc_task_t *, isc_event_t *); -static void -isc_httpd_senddone(isc_task_t *, isc_event_t *); static isc_result_t -process_request(isc_httpd_t *, int); +httpd_newconn(isc_nmhandle_t *, isc_result_t, void *); +static void +httpd_request(isc_nmhandle_t *, isc_result_t, isc_region_t *, void *); +static void +httpd_senddone(isc_nmhandle_t *, isc_result_t, void *); +static void +httpd_reset(void *); +static void +httpd_put(void *); + +static isc_result_t +httpd_addheader(isc_httpd_t *, const char *, const char *); +static isc_result_t +httpd_addheaderuint(isc_httpd_t *, const char *, int); +static isc_result_t +httpd_endheaders(isc_httpd_t *); +static isc_result_t +httpd_response(isc_httpd_t *); + +static isc_result_t +process_request(isc_httpd_t *, isc_region_t *); static isc_result_t grow_headerspace(isc_httpd_t *); -static void -reset_client(isc_httpd_t *httpd); static isc_httpdaction_t render_404; static isc_httpdaction_t render_500; @@ -217,26 +180,13 @@ static isc_httpdaction_t render_500; static void (*finishhook)(void) = NULL; #endif /* ENABLE_AFL */ -static void -maybe_destroy_httpd(isc_httpd_t *); -static void -destroy_httpd(isc_httpd_t *); -static void -maybe_destroy_httpdmgr(isc_httpdmgr_t *); static void destroy_httpdmgr(isc_httpdmgr_t *); static void -isc_httpdmgr_attach(isc_httpdmgr_t *, isc_httpdmgr_t **); +httpdmgr_attach(isc_httpdmgr_t *, isc_httpdmgr_t **); static void -isc_httpdmgr_detach(isc_httpdmgr_t **); - -static void -maybe_destroy_httpd(isc_httpd_t *httpd) { - if (isc_refcount_decrement(&httpd->references) == 1) { - destroy_httpd(httpd); - } -} +httpdmgr_detach(isc_httpdmgr_t **); static inline void free_buffer(isc_mem_t *mctx, isc_buffer_t *buffer) { @@ -248,101 +198,20 @@ free_buffer(isc_mem_t *mctx, isc_buffer_t *buffer) { } } -static void -destroy_httpd(isc_httpd_t *httpd) { - isc_httpdmgr_t *httpdmgr; - - REQUIRE(VALID_HTTPD(httpd)); - - httpdmgr = httpd->mgr; - REQUIRE(VALID_HTTPDMGR(httpdmgr)); - - /* - * Unlink before calling isc_socket_detach so - * isc_httpdmgr_shutdown does not dereference a NULL pointer - * when calling isc_socket_cancel(). - */ - LOCK(&httpdmgr->lock); - ISC_LIST_UNLINK(httpdmgr->running, httpd, link); - UNLOCK(&httpdmgr->lock); - - httpd->magic = 0; - isc_refcount_destroy(&httpd->references); - isc_socket_detach(&httpd->sock); - - free_buffer(httpdmgr->mctx, &httpd->headerbuffer); - free_buffer(httpdmgr->mctx, &httpd->compbuffer); - - isc_mem_put(httpdmgr->mctx, httpd, sizeof(isc_httpd_t)); - -#if ENABLE_AFL - if (finishhook != NULL) { - finishhook(); - } -#endif /* ENABLE_AFL */ - - isc_httpdmgr_detach(&httpdmgr); -} - -static inline isc_result_t -httpdmgr_socket_accept(isc_task_t *task, isc_httpdmgr_t *httpdmgr) { - isc_result_t result = ISC_R_SUCCESS; - - /* decremented in isc_httpd_accept */ - isc_refcount_increment(&httpdmgr->references); - result = isc_socket_accept(httpdmgr->sock, task, isc_httpd_accept, - httpdmgr); - if (result != ISC_R_SUCCESS) { - INSIST(isc_refcount_decrement(&httpdmgr->references) > 1); - } - return (result); -} - -static inline void -httpd_socket_recv(isc_httpd_t *httpd, isc_region_t *region, isc_task_t *task) { - isc_result_t result = ISC_R_SUCCESS; - - /* decremented in isc_httpd_recvdone */ - (void)isc_refcount_increment(&httpd->references); - result = isc_socket_recv(httpd->sock, region, 1, task, - isc_httpd_recvdone, httpd); - if (result != ISC_R_SUCCESS) { - INSIST(isc_refcount_decrement(&httpd->references) > 1); - } -} - -static inline void -httpd_socket_send(isc_httpd_t *httpd, isc_region_t *region, isc_task_t *task) { - isc_result_t result = ISC_R_SUCCESS; - - /* decremented in isc_httpd_senddone */ - (void)isc_refcount_increment(&httpd->references); - result = isc_socket_send(httpd->sock, region, task, isc_httpd_senddone, - httpd); - if (result != ISC_R_SUCCESS) { - INSIST(isc_refcount_decrement(&httpd->references) > 1); - } -} - isc_result_t -isc_httpdmgr_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task, +isc_httpdmgr_create(isc_nm_t *nm, isc_mem_t *mctx, isc_sockaddr_t *addr, isc_httpdclientok_t *client_ok, isc_httpdondestroy_t *ondestroy, void *cb_arg, - isc_timermgr_t *tmgr, isc_httpdmgr_t **httpdmgrp) { + isc_httpdmgr_t **httpdmgrp) { isc_result_t result; - isc_httpdmgr_t *httpdmgr; + isc_httpdmgr_t *httpdmgr = NULL; + REQUIRE(nm != NULL); REQUIRE(mctx != NULL); - REQUIRE(sock != NULL); - REQUIRE(task != NULL); - REQUIRE(tmgr != NULL); REQUIRE(httpdmgrp != NULL && *httpdmgrp == NULL); httpdmgr = isc_mem_get(mctx, sizeof(isc_httpdmgr_t)); - - *httpdmgr = (isc_httpdmgr_t){ .timermgr = tmgr, /* XXXMLG no attach - * function? */ - .client_ok = client_ok, + *httpdmgr = (isc_httpdmgr_t){ .client_ok = client_ok, .ondestroy = ondestroy, .cb_arg = cb_arg, .render_404 = render_404, @@ -350,49 +219,34 @@ isc_httpdmgr_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task, isc_mutex_init(&httpdmgr->lock); isc_mem_attach(mctx, &httpdmgr->mctx); - isc_socket_attach(sock, &httpdmgr->sock); - isc_task_attach(task, &httpdmgr->task); ISC_LIST_INIT(httpdmgr->running); ISC_LIST_INIT(httpdmgr->urls); isc_refcount_init(&httpdmgr->references, 1); - /* XXXMLG ignore errors on isc_socket_listen() */ - result = isc_socket_listen(sock, SOMAXCONN); - if (result != ISC_R_SUCCESS) { - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_socket_listen() failed: %s", - isc_result_totext(result)); - goto cleanup; - } - - (void)isc_socket_filter(sock, "httpready"); + CHECK(isc_nm_listentcp(nm, (isc_nmiface_t *)addr, httpd_newconn, + httpdmgr, sizeof(isc_httpd_t), 5, NULL, + &httpdmgr->sock)); httpdmgr->magic = HTTPDMGR_MAGIC; - - result = httpdmgr_socket_accept(task, httpdmgr); - if (result != ISC_R_SUCCESS) { - goto cleanup; - } - *httpdmgrp = httpdmgr; + return (ISC_R_SUCCESS); cleanup: httpdmgr->magic = 0; isc_refcount_decrement(&httpdmgr->references); isc_refcount_destroy(&httpdmgr->references); - isc_task_detach(&httpdmgr->task); - isc_socket_detach(&httpdmgr->sock); isc_mem_detach(&httpdmgr->mctx); isc_mutex_destroy(&httpdmgr->lock); isc_mem_put(mctx, httpdmgr, sizeof(isc_httpdmgr_t)); + return (result); } static void -isc_httpdmgr_attach(isc_httpdmgr_t *source, isc_httpdmgr_t **targetp) { +httpdmgr_attach(isc_httpdmgr_t *source, isc_httpdmgr_t **targetp) { REQUIRE(VALID_HTTPDMGR(source)); REQUIRE(targetp != NULL && *targetp == NULL); @@ -402,16 +256,15 @@ isc_httpdmgr_attach(isc_httpdmgr_t *source, isc_httpdmgr_t **targetp) { } static void -isc_httpdmgr_detach(isc_httpdmgr_t **httpdmgrp) { - REQUIRE(httpdmgrp != NULL && VALID_HTTPDMGR(*httpdmgrp)); - isc_httpdmgr_t *httpdmgr = *httpdmgrp; +httpdmgr_detach(isc_httpdmgr_t **httpdmgrp) { + isc_httpdmgr_t *httpdmgr = NULL; + + REQUIRE(httpdmgrp != NULL); + REQUIRE(VALID_HTTPDMGR(*httpdmgrp)); + + httpdmgr = *httpdmgrp; *httpdmgrp = NULL; - maybe_destroy_httpdmgr(httpdmgr); -} - -static void -maybe_destroy_httpdmgr(isc_httpdmgr_t *httpdmgr) { if (isc_refcount_decrement(&httpdmgr->references) == 1) { destroy_httpdmgr(httpdmgr); } @@ -425,14 +278,14 @@ destroy_httpdmgr(isc_httpdmgr_t *httpdmgr) { LOCK(&httpdmgr->lock); + REQUIRE((httpdmgr->flags & ISC_HTTPDMGR_SHUTTINGDOWN) != 0); + REQUIRE(ISC_LIST_EMPTY(httpdmgr->running)); + httpdmgr->magic = 0; - INSIST(MSHUTTINGDOWN(httpdmgr)); - INSIST(ISC_LIST_EMPTY(httpdmgr->running)); - - isc_socket_detach(&httpdmgr->sock); - isc_task_detach(&httpdmgr->task); - httpdmgr->timermgr = NULL; + if (httpdmgr->sock != NULL) { + isc_nmsocket_close(&httpdmgr->sock); + } /* * Clear out the list of all actions we know about. Just free the @@ -532,18 +385,18 @@ have_header(isc_httpd_t *httpd, const char *header, const char *value, h++; } } + return (false); } } static isc_result_t -process_request(isc_httpd_t *httpd, int length) { - char *s; - char *p; +process_request(isc_httpd_t *httpd, isc_region_t *region) { + char *s = NULL, *p = NULL; int delim; - httpd->recvlen += length; - + memmove(httpd->recvbuf + httpd->recvlen, region->base, region->length); + httpd->recvlen += region->length; httpd->recvbuf[httpd->recvlen] = 0; httpd->headers = NULL; @@ -571,10 +424,10 @@ process_request(isc_httpd_t *httpd, int length) { * cause an error to be returned. */ if (strncmp(httpd->recvbuf, "GET ", 4) == 0) { - httpd->method = ISC_HTTPD_METHODGET; + httpd->method = METHOD_GET; p = httpd->recvbuf + 4; } else if (strncmp(httpd->recvbuf, "POST ", 5) == 0) { - httpd->method = ISC_HTTPD_METHODPOST; + httpd->method = METHOD_POST; p = httpd->recvbuf + 5; } else { return (ISC_R_RANGE); @@ -715,93 +568,134 @@ process_request(isc_httpd_t *httpd, int length) { } static void -isc_httpd_create(isc_httpdmgr_t *httpdmgr, isc_socket_t *sock, - isc_httpd_t **httpdp) { - isc_httpd_t *httpd; - char *headerdata; +httpd_reset(void *arg) { + isc_httpd_t *httpd = (isc_httpd_t *)arg; + isc_httpdmgr_t *httpdmgr = NULL; + + REQUIRE(VALID_HTTPD(httpd)); + + httpdmgr = httpd->mgr; REQUIRE(VALID_HTTPDMGR(httpdmgr)); - REQUIRE(httpdp != NULL && *httpdp == NULL); - httpd = isc_mem_get(httpdmgr->mctx, sizeof(isc_httpd_t)); + LOCK(&httpdmgr->lock); + ISC_LIST_UNLINK(httpdmgr->running, httpd, link); + UNLOCK(&httpdmgr->lock); - *httpd = (isc_httpd_t){ .sock = sock }; + httpd->recvbuf[0] = 0; + httpd->recvlen = 0; + httpd->headers = NULL; + httpd->method = METHOD_UNKNOWN; + httpd->url = NULL; + httpd->querystring = NULL; + httpd->protocol = NULL; + httpd->flags = 0; - isc_httpdmgr_attach(httpdmgr, &httpd->mgr); + isc_buffer_clear(&httpd->headerbuffer); + isc_buffer_clear(&httpd->compbuffer); + isc_buffer_invalidate(&httpd->bodybuffer); - isc_refcount_init(&httpd->references, 1); - ISC_HTTPD_SETRECV(httpd); - isc_socket_setname(httpd->sock, "httpd", NULL); + httpdmgr_detach(&httpdmgr); +} + +static void +httpd_put(void *arg) { + isc_httpd_t *httpd = (isc_httpd_t *)arg; + isc_httpdmgr_t *httpdmgr = NULL; + + REQUIRE(VALID_HTTPD(httpd)); + + httpdmgr = httpd->mgr; + REQUIRE(VALID_HTTPDMGR(httpdmgr)); + + httpd->magic = 0; + + free_buffer(httpdmgr->mctx, &httpd->headerbuffer); + free_buffer(httpdmgr->mctx, &httpd->compbuffer); + +#if ENABLE_AFL + if (finishhook != NULL) { + finishhook(); + } +#endif /* ENABLE_AFL */ +} + +static isc_result_t +new_httpd(isc_httpdmgr_t *httpdmgr, isc_nmhandle_t *handle) { + isc_result_t result; + isc_httpd_t *httpd = NULL; + char *headerdata = NULL; + + REQUIRE(VALID_HTTPDMGR(httpdmgr)); + + httpd = isc_nmhandle_getdata(handle); + if (httpd == NULL) { + httpd = isc_nmhandle_getextra(handle); + *httpd = (isc_httpd_t){ .handle = NULL }; + } + + if (httpd->handle == NULL) { + isc_nmhandle_setdata(handle, httpd, httpd_reset, httpd_put); + } else { + INSIST(httpd->handle == handle); + } + + httpdmgr_attach(httpdmgr, &httpd->mgr); /* * Initialize the buffer for our headers. */ headerdata = isc_mem_get(httpdmgr->mctx, HTTP_SENDGROW); isc_buffer_init(&httpd->headerbuffer, headerdata, HTTP_SENDGROW); + isc_buffer_clear(&httpd->headerbuffer); isc_buffer_initnull(&httpd->compbuffer); - isc_buffer_initnull(&httpd->bodybuffer); - reset_client(httpd); + isc_buffer_clear(&httpd->compbuffer); + + isc_buffer_invalidate(&httpd->bodybuffer); ISC_LINK_INIT(httpd, link); - ISC_LIST_APPEND(httpdmgr->running, httpd, link); httpd->magic = HTTPD_MAGIC; + httpd->state = RECV; - *httpdp = httpd; + LOCK(&httpdmgr->lock); + ISC_LIST_APPEND(httpdmgr->running, httpd, link); + UNLOCK(&httpdmgr->lock); + + isc_nmhandle_ref(handle); + result = isc_nm_read(handle, httpd_request, httpdmgr); + if (result != ISC_R_SUCCESS) { + isc_nmhandle_unref(handle); + } + + return (result); } -static void -isc_httpd_accept(isc_task_t *task, isc_event_t *ev) { - isc_httpdmgr_t *httpdmgr = ev->ev_arg; - isc_httpd_t *httpd = NULL; - isc_region_t r; - isc_socket_newconnev_t *nev = (isc_socket_newconnev_t *)ev; +static isc_result_t +httpd_newconn(isc_nmhandle_t *handle, isc_result_t result, void *arg) { + isc_httpdmgr_t *httpdmgr = (isc_httpdmgr_t *)arg; isc_sockaddr_t peeraddr; REQUIRE(VALID_HTTPDMGR(httpdmgr)); - LOCK(&httpdmgr->lock); - if (MSHUTTINGDOWN(httpdmgr)) { - goto out; + if ((httpdmgr->flags & ISC_HTTPDMGR_SHUTTINGDOWN) != 0) { + return (ISC_R_CANCELED); + } else if (result == ISC_R_CANCELED) { + isc_httpdmgr_shutdown(&httpdmgr); + return (result); + } else if (result != ISC_R_SUCCESS) { + return (result); } - if (nev->result == ISC_R_CANCELED) { - goto out; - } - - if (nev->result != ISC_R_SUCCESS) { - /* XXXMLG log failure */ - goto requeue; - } - - (void)isc_socket_getpeername(nev->newsocket, &peeraddr); + peeraddr = isc_nmhandle_peeraddr(handle); if (httpdmgr->client_ok != NULL && !(httpdmgr->client_ok)(&peeraddr, httpdmgr->cb_arg)) { - isc_socket_detach(&nev->newsocket); - goto requeue; + return (ISC_R_FAILURE); } - isc_httpd_create(httpdmgr, nev->newsocket, &httpd); - - r.base = (unsigned char *)httpd->recvbuf; - r.length = HTTP_RECVLEN - 1; - - httpd_socket_recv(httpd, &r, task); - -requeue: - (void)httpdmgr_socket_accept(task, httpdmgr); - -out: - UNLOCK(&httpdmgr->lock); - - if (httpd != NULL) { - maybe_destroy_httpd(httpd); - } - maybe_destroy_httpdmgr(httpdmgr); - - isc_event_free(&ev); + return (new_httpd(httpdmgr, handle)); } static isc_result_t @@ -898,7 +792,7 @@ alloc_compspace(isc_httpd_t *httpd, unsigned int size) { * data would be larger than input data */ static isc_result_t -isc_httpd_compress(isc_httpd_t *httpd) { +httpd_compress(isc_httpd_t *httpd) { z_stream zstr; isc_region_t r; isc_result_t result; @@ -938,60 +832,53 @@ isc_httpd_compress(isc_httpd_t *httpd) { #endif /* ifdef HAVE_ZLIB */ static void -isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev) { +httpd_request(isc_nmhandle_t *handle, isc_result_t eresult, + isc_region_t *region, void *arg) { isc_result_t result; - isc_httpd_t *httpd = ev->ev_arg; - isc_socketevent_t *sev = (isc_socketevent_t *)ev; - isc_buffer_t *databuffer; - isc_httpdurl_t *url; + isc_httpd_t *httpd = NULL; + isc_httpdmgr_t *mgr = (isc_httpdmgr_t *)arg; + isc_buffer_t *databuffer = NULL; + isc_httpdurl_t *url = NULL; isc_time_t now; isc_region_t r; bool is_compressed = false; char datebuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; - REQUIRE(VALID_HTTPD(httpd)); + httpd = isc_nmhandle_getdata(handle); - INSIST(ISC_HTTPD_ISRECV(httpd)); + REQUIRE(httpd->state == RECV); - if (sev->result != ISC_R_SUCCESS) { - goto out; + if (eresult != ISC_R_SUCCESS) { + goto done; } - result = process_request(httpd, sev->n); + result = process_request(httpd, region); if (result == ISC_R_NOTFOUND) { - if (httpd->recvlen >= HTTP_RECVLEN - 1) { - goto out; + if (httpd->recvlen < HTTP_RECVLEN - 1) { + /* don't unref, continue reading */ + return; } - r.base = (unsigned char *)httpd->recvbuf + httpd->recvlen; - r.length = HTTP_RECVLEN - httpd->recvlen - 1; - - httpd_socket_recv(httpd, &r, task); - goto out; + goto done; } else if (result != ISC_R_SUCCESS) { - goto out; + goto done; } - ISC_HTTPD_SETSEND(httpd); - - /* - * XXXMLG Call function here. Provide an add-header function - * which will append the common headers to a response we generate. - */ isc_buffer_initnull(&httpd->bodybuffer); isc_time_now(&now); isc_time_formathttptimestamp(&now, datebuf, sizeof(datebuf)); - LOCK(&httpd->mgr->lock); - url = ISC_LIST_HEAD(httpd->mgr->urls); + + LOCK(&mgr->lock); + url = ISC_LIST_HEAD(mgr->urls); while (url != NULL) { if (strcmp(httpd->url, url->url) == 0) { break; } url = ISC_LIST_NEXT(url, link); } - UNLOCK(&httpd->mgr->lock); + UNLOCK(&mgr->lock); if (url == NULL) { - result = httpd->mgr->render_404( + result = mgr->render_404( httpd->url, NULL, httpd->querystring, NULL, NULL, &httpd->retcode, &httpd->retmsg, &httpd->mimetype, &httpd->bodybuffer, &httpd->freecb, &httpd->freecb_arg); @@ -1003,7 +890,7 @@ isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev) { &httpd->freecb, &httpd->freecb_arg); } if (result != ISC_R_SUCCESS) { - result = httpd->mgr->render_500( + result = mgr->render_500( httpd->url, url, httpd->querystring, NULL, NULL, &httpd->retcode, &httpd->retmsg, &httpd->mimetype, &httpd->bodybuffer, &httpd->freecb, &httpd->freecb_arg); @@ -1012,69 +899,77 @@ isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev) { #ifdef HAVE_ZLIB if ((httpd->flags & HTTPD_ACCEPT_DEFLATE) != 0) { - result = isc_httpd_compress(httpd); + result = httpd_compress(httpd); if (result == ISC_R_SUCCESS) { is_compressed = true; } } #endif /* ifdef HAVE_ZLIB */ - isc_httpd_response(httpd); + httpd_response(httpd); if ((httpd->flags & HTTPD_KEEPALIVE) != 0) { - isc_httpd_addheader(httpd, "Connection", "Keep-Alive"); + httpd_addheader(httpd, "Connection", "Keep-Alive"); } - isc_httpd_addheader(httpd, "Content-Type", httpd->mimetype); - isc_httpd_addheader(httpd, "Date", datebuf); - isc_httpd_addheader(httpd, "Expires", datebuf); + httpd_addheader(httpd, "Content-Type", httpd->mimetype); + httpd_addheader(httpd, "Date", datebuf); + httpd_addheader(httpd, "Expires", datebuf); if (url != NULL && url->isstatic) { char loadbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; isc_time_formathttptimestamp(&url->loadtime, loadbuf, sizeof(loadbuf)); - isc_httpd_addheader(httpd, "Last-Modified", loadbuf); - isc_httpd_addheader(httpd, "Cache-Control: public", NULL); + httpd_addheader(httpd, "Last-Modified", loadbuf); + httpd_addheader(httpd, "Cache-Control: public", NULL); } else { - isc_httpd_addheader(httpd, "Last-Modified", datebuf); - isc_httpd_addheader(httpd, "Pragma: no-cache", NULL); - isc_httpd_addheader(httpd, "Cache-Control: no-cache", NULL); + httpd_addheader(httpd, "Last-Modified", datebuf); + httpd_addheader(httpd, "Pragma: no-cache", NULL); + httpd_addheader(httpd, "Cache-Control: no-cache", NULL); } - isc_httpd_addheader(httpd, "Server: libisc", NULL); + httpd_addheader(httpd, "Server: libisc", NULL); if (is_compressed) { - isc_httpd_addheader(httpd, "Content-Encoding", "deflate"); - isc_httpd_addheaderuint( - httpd, "Content-Length", - isc_buffer_usedlength(&httpd->compbuffer)); + httpd_addheader(httpd, "Content-Encoding", "deflate"); + httpd_addheaderuint(httpd, "Content-Length", + isc_buffer_usedlength(&httpd->compbuffer)); } else { - isc_httpd_addheaderuint( - httpd, "Content-Length", - isc_buffer_usedlength(&httpd->bodybuffer)); + httpd_addheaderuint(httpd, "Content-Length", + isc_buffer_usedlength(&httpd->bodybuffer)); } - isc_httpd_endheaders(httpd); /* done */ + httpd_endheaders(httpd); /* done */ /* * Append either the compressed or the non-compressed response body to * the response headers and store the result in httpd->sendbuffer. */ - isc_buffer_dup(httpd->mgr->mctx, &httpd->sendbuffer, - &httpd->headerbuffer); + isc_buffer_dup(mgr->mctx, &httpd->sendbuffer, &httpd->headerbuffer); isc_buffer_setautorealloc(httpd->sendbuffer, true); databuffer = (is_compressed ? &httpd->compbuffer : &httpd->bodybuffer); isc_buffer_usedregion(databuffer, &r); result = isc_buffer_copyregion(httpd->sendbuffer, &r); RUNTIME_CHECK(result == ISC_R_SUCCESS); + /* * Determine total response size. */ isc_buffer_usedregion(httpd->sendbuffer, &r); - httpd_socket_send(httpd, &r, task); + isc_nm_pauseread(handle); + httpd->state = SEND; -out: - maybe_destroy_httpd(httpd); - isc_event_free(&ev); + isc_nmhandle_ref(handle); + result = isc_nm_send(handle, &r, httpd_senddone, httpd); + if (result != ISC_R_SUCCESS) { + isc_nm_resumeread(handle); + isc_nmhandle_unref(handle); + + httpd->state = RECV; + } + + return; +done: + isc_nmhandle_unref(handle); } void @@ -1083,31 +978,29 @@ isc_httpdmgr_shutdown(isc_httpdmgr_t **httpdmgrp) { isc_httpd_t *httpd; REQUIRE(httpdmgrp != NULL); + REQUIRE(VALID_HTTPDMGR(*httpdmgrp)); + httpdmgr = *httpdmgrp; *httpdmgrp = NULL; - REQUIRE(VALID_HTTPDMGR(httpdmgr)); + + isc_nm_stoplistening(httpdmgr->sock); LOCK(&httpdmgr->lock); - - MSETSHUTTINGDOWN(httpdmgr); - - isc_socket_cancel(httpdmgr->sock, httpdmgr->task, ISC_SOCKCANCEL_ALL); + httpdmgr->flags |= ISC_HTTPDMGR_SHUTTINGDOWN; httpd = ISC_LIST_HEAD(httpdmgr->running); while (httpd != NULL) { - isc_socket_cancel(httpd->sock, httpdmgr->task, - ISC_SOCKCANCEL_ALL); + isc_nmhandle_unref(httpd->handle); httpd = ISC_LIST_NEXT(httpd, link); } - UNLOCK(&httpdmgr->lock); - maybe_destroy_httpdmgr(httpdmgr); + httpdmgr_detach(&httpdmgr); } static isc_result_t grow_headerspace(isc_httpd_t *httpd) { - char *newspace; + char *newspace = NULL; unsigned int newlen; isc_region_t r; @@ -1126,8 +1019,8 @@ grow_headerspace(isc_httpd_t *httpd) { return (ISC_R_SUCCESS); } -isc_result_t -isc_httpd_response(isc_httpd_t *httpd) { +static isc_result_t +httpd_response(isc_httpd_t *httpd) { isc_result_t result; unsigned int needlen; @@ -1149,8 +1042,8 @@ isc_httpd_response(isc_httpd_t *httpd) { httpd->retmsg)); } -isc_result_t -isc_httpd_addheader(isc_httpd_t *httpd, const char *name, const char *val) { +static isc_result_t +httpd_addheader(isc_httpd_t *httpd, const char *name, const char *val) { isc_result_t result; unsigned int needlen; @@ -1178,8 +1071,8 @@ isc_httpd_addheader(isc_httpd_t *httpd, const char *name, const char *val) { } } -isc_result_t -isc_httpd_endheaders(isc_httpd_t *httpd) { +static isc_result_t +httpd_endheaders(isc_httpd_t *httpd) { isc_result_t result; REQUIRE(VALID_HTTPD(httpd)); @@ -1194,8 +1087,8 @@ isc_httpd_endheaders(isc_httpd_t *httpd) { return (isc_buffer_printf(&httpd->headerbuffer, "\r\n")); } -isc_result_t -isc_httpd_addheaderuint(isc_httpd_t *httpd, const char *name, int val) { +static isc_result_t +httpd_addheaderuint(isc_httpd_t *httpd, const char *name, int val) { isc_result_t result; unsigned int needlen; char buf[sizeof "18446744073709551616"]; @@ -1220,23 +1113,17 @@ isc_httpd_addheaderuint(isc_httpd_t *httpd, const char *name, int val) { } static void -isc_httpd_senddone(isc_task_t *task, isc_event_t *ev) { - isc_httpd_t *httpd = ev->ev_arg; - isc_region_t r; - isc_socketevent_t *sev = (isc_socketevent_t *)ev; +httpd_senddone(isc_nmhandle_t *handle, isc_result_t result, void *arg) { + isc_httpd_t *httpd = (isc_httpd_t *)arg; REQUIRE(VALID_HTTPD(httpd)); - - INSIST(ISC_HTTPD_ISSEND(httpd)); + REQUIRE(httpd->state == SEND); isc_buffer_free(&httpd->sendbuffer); /* * We will always want to clean up our receive buffer, even if we * got an error on send or we are shutting down. - * - * We will pass in the buffer only if there is data in it. If - * there is no data, we will pass in a NULL. */ if (httpd->freecb != NULL) { isc_buffer_t *b = NULL; @@ -1246,63 +1133,18 @@ isc_httpd_senddone(isc_task_t *task, isc_event_t *ev) { } } - if (sev->result != ISC_R_SUCCESS) { - goto out; + if (result != ISC_R_SUCCESS) { + return; } - if ((httpd->flags & HTTPD_CLOSE) != 0) { - goto out; - } - - ISC_HTTPD_SETRECV(httpd); - - reset_client(httpd); - - r.base = (unsigned char *)httpd->recvbuf; - r.length = HTTP_RECVLEN - 1; - - httpd_socket_recv(httpd, &r, task); - -out: - maybe_destroy_httpd(httpd); - isc_event_free(&ev); -} - -static void -reset_client(isc_httpd_t *httpd) { - /* - * Catch errors here. We MUST be in RECV mode, and we MUST NOT have - * any outstanding buffers. If we have buffers, we have a leak. - */ - INSIST(ISC_HTTPD_ISRECV(httpd)); - INSIST(!ISC_LINK_LINKED(&httpd->headerbuffer, link)); - INSIST(!ISC_LINK_LINKED(&httpd->bodybuffer, link)); - - httpd->recvbuf[0] = 0; - httpd->recvlen = 0; - httpd->headers = NULL; - httpd->method = ISC_HTTPD_METHODUNKNOWN; - httpd->url = NULL; - httpd->querystring = NULL; - httpd->protocol = NULL; - httpd->flags = 0; - - isc_buffer_clear(&httpd->headerbuffer); - isc_buffer_clear(&httpd->compbuffer); - isc_buffer_invalidate(&httpd->bodybuffer); + httpd->state = RECV; + isc_nm_resumeread(handle); + isc_nmhandle_unref(handle); } isc_result_t -isc_httpdmgr_addurl(isc_httpdmgr_t *httpdmgr, const char *url, +isc_httpdmgr_addurl(isc_httpdmgr_t *httpdmgr, const char *url, bool isstatic, isc_httpdaction_t *func, void *arg) { - /* REQUIRE(VALID_HTTPDMGR(httpdmgr)); Dummy function */ - - return (isc_httpdmgr_addurl2(httpdmgr, url, false, func, arg)); -} - -isc_result_t -isc_httpdmgr_addurl2(isc_httpdmgr_t *httpdmgr, const char *url, bool isstatic, - isc_httpdaction_t *func, void *arg) { isc_httpdurl_t *item; REQUIRE(VALID_HTTPDMGR(httpdmgr)); diff --git a/lib/isc/include/isc/httpd.h b/lib/isc/include/isc/httpd.h index cfc3508054..bc52f4b14e 100644 --- a/lib/isc/include/isc/httpd.h +++ b/lib/isc/include/isc/httpd.h @@ -42,41 +42,21 @@ struct isc_httpdurl { #define HTTPD_EVENTCLASS ISC_EVENTCLASS(4300) #define HTTPD_SHUTDOWN (HTTPD_EVENTCLASS + 0x0001) -#define ISC_HTTPDMGR_FLAGSHUTTINGDOWN 0x00000001 +#define ISC_HTTPDMGR_SHUTTINGDOWN 0x00000001 -/* - * Create a new http daemon which will send, once every time period, - * a http-like header followed by HTTP data. - */ isc_result_t -isc_httpdmgr_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task, +isc_httpdmgr_create(isc_nm_t *nm, isc_mem_t *mctx, isc_sockaddr_t *addr, isc_httpdclientok_t * client_ok, - isc_httpdondestroy_t *ondestory, void *cb_arg, - isc_timermgr_t *tmgr, isc_httpdmgr_t **httpdp); + isc_httpdondestroy_t *ondestroy, void *cb_arg, + isc_httpdmgr_t **httpdmgrp); void isc_httpdmgr_shutdown(isc_httpdmgr_t **httpdp); isc_result_t -isc_httpdmgr_addurl(isc_httpdmgr_t *httpdmgr, const char *url, +isc_httpdmgr_addurl(isc_httpdmgr_t *httpdmgr, const char *url, bool isstatic, isc_httpdaction_t *func, void *arg); -isc_result_t -isc_httpdmgr_addurl2(isc_httpdmgr_t *httpdmgr, const char *url, bool isstatic, - isc_httpdaction_t *func, void *arg); - -isc_result_t -isc_httpd_response(isc_httpd_t *httpd); - -isc_result_t -isc_httpd_addheader(isc_httpd_t *httpd, const char *name, const char *val); - -isc_result_t -isc_httpd_addheaderuint(isc_httpd_t *httpd, const char *name, int val); - -isc_result_t -isc_httpd_endheaders(isc_httpd_t *httpd); - void isc_httpd_setfinishhook(void (*fn)(void)); diff --git a/lib/isc/win32/libisc.def.in b/lib/isc/win32/libisc.def.in index 102a2263ed..496464328e 100644 --- a/lib/isc/win32/libisc.def.in +++ b/lib/isc/win32/libisc.def.in @@ -291,13 +291,8 @@ isc_ht_iter_delcurrent_next isc_ht_iter_destroy isc_ht_iter_first isc_ht_iter_next -isc_httpd_addheader -isc_httpd_addheaderuint -isc_httpd_endheaders -isc_httpd_response isc_httpd_setfinishhook isc_httpdmgr_addurl -isc_httpdmgr_addurl2 isc_httpdmgr_create isc_httpdmgr_shutdown isc_interfaceiter_create