<commit_before>/*
 * nsd-control.c - remote control utility for nsd.
 *
 * Copyright (c) 2011, NLnet Labs. All rights reserved.
 *
 * This software is open source.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * 
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 * 
 * Neither the name of the NLNET LABS nor the names of its contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * \file
 *
 * The remote control utility contacts the nsd server over ssl and
 * sends the command, receives the answer, and displays the result
 * from the commandline.
 */

#include "config.h"
#ifdef HAVE_SSL

#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#ifdef HAVE_OPENSSL_SSL_H
#include <openssl/ssl.h>
#endif
#ifdef HAVE_OPENSSL_ERR_H
#include <openssl/err.h>
#endif
#ifdef HAVE_OPENSSL_RAND_H
#include <openssl/rand.h>
#endif
#include "util.h"
#include "tsig.h"
#include "options.h"

/** Give nsd-control usage, and exit (1). */
static void
usage()
{
	printf("Usage:	nsd-control [options] command\n");
	printf("	Remote control utility for nsd server.\n");
	printf("Version %s. Report bugs to <%s>.\n",
		PACKAGE_VERSION, PACKAGE_BUGREPORT);
	printf("Options:\n");
	printf("  -c file	config file, default is %s\n", CONFIGFILE);
	printf("  -s ip[@port]	server address, if omitted config is used.\n");
	printf("  -h		show this usage help.\n");
	printf("Commands:\n");
	printf("  start				start server; runs nsd(8)\n");
	printf("  stop				stops the server\n");
	printf("  reload [<zone>]		reload modified zonefiles from disk\n");
	printf("  repattern			reload tsig keys, patterns from config file\n");
	printf("  log_reopen			reopen logfile (for log rotate)\n");
	printf("  status			display status of server\n");
	printf("  stats				print statistics\n");
	printf("  stats_noreset			peek at statistics\n");
	printf("  addzone <name> <pattern>	add a new zone\n");
	printf("  delzone <name>		remove a zone\n");
	printf("  write [<zone>]		write changed zonefiles to disk\n");
	printf("  notify [<zone>]		send NOTIFY messages to slave servers\n");
	printf("  transfer [<zone>]		try to update slave zones to newer serial\n");
	printf("  force_transfer [<zone>]	update slave zones with AXFR, no serial check\n");
	printf("  zonestatus [<zone>]		print state, serial, activity\n");
	printf("  verbosity <number>		change logging detail\n");
	exit(1);
}

/** exit with ssl error */
static void ssl_err(const char* s)
{
	fprintf(stderr, "error: %s\n", s);
	ERR_print_errors_fp(stderr);
	exit(1);
}

/** setup SSL context */
static SSL_CTX*
setup_ctx(nsd_options_t* cfg)
{
	char* s_cert, *c_key, *c_cert;
	SSL_CTX* ctx;

	s_cert = cfg->server_cert_file;
	c_key = cfg->control_key_file;
	c_cert = cfg->control_cert_file;

        ctx = SSL_CTX_new(SSLv23_client_method());
	if(!ctx)
		ssl_err("could not allocate SSL_CTX pointer");
        if(!(SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2))
		ssl_err("could not set SSL_OP_NO_SSLv2");
	if(!SSL_CTX_use_certificate_file(ctx,c_cert,SSL_FILETYPE_PEM) ||
		!SSL_CTX_use_PrivateKey_file(ctx,c_key,SSL_FILETYPE_PEM)
		|| !SSL_CTX_check_private_key(ctx))
		ssl_err("Error setting up SSL_CTX client key and cert");
	if (SSL_CTX_load_verify_locations(ctx, s_cert, NULL) != 1)
		ssl_err("Error setting up SSL_CTX verify, server cert");
	SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);

	return ctx;
}

/** contact the server with TCP connect */
static int
contact_server(const char* svr, nsd_options_t* cfg, int statuscmd)
{
#ifdef INET6
	struct sockaddr_storage addr;
#else
	struct sockaddr_in addr;
#endif
	socklen_t addrlen;
	int fd;
	int port = cfg->control_port;
	/* use svr or a config entry */
	if(!svr) {
		if(cfg->control_interface)
			svr = cfg->control_interface->address;
		else	svr = "127.0.0.1";
		/* config 0 addr (everything), means ask localhost */
		if(strcmp(svr, "0.0.0.0") == 0)
			svr = "127.0.0.1";
		else if(strcmp(svr, "::0") == 0 ||
			strcmp(svr, "0::0") == 0 ||
			strcmp(svr, "0::") == 0 ||
			strcmp(svr, "::") == 0)
			svr = "::1";
	}
	if(strchr(svr, '@')) {
		char* ps = strchr(svr, '@');
		*ps++ = 0;
		port = atoi(ps);
		if(!port) {
			fprintf(stderr, "could not parse port %s\n", ps);
			exit(1);
		}
	} 
        if(strchr(svr, ':')) {
		struct sockaddr_in6* sa = (struct sockaddr_in6*)&addr;
		addrlen = (socklen_t)sizeof(struct sockaddr_in6);
		memset(sa, 0, addrlen);
		sa->sin6_family = AF_INET6;
		sa->sin6_port = (in_port_t)htons((uint16_t)port);
		if(inet_pton((int)sa->sin6_family, svr, &sa->sin6_addr) <= 0) {
			fprintf(stderr, "could not parse IP: %s\n", svr);
			exit(1);
		}
	} else { /* ip4 */
		struct sockaddr_in* sa = (struct sockaddr_in*)&addr;
		addrlen = (socklen_t)sizeof(struct sockaddr_in);
		memset(sa, 0, addrlen);
		sa->sin_family = AF_INET;
		sa->sin_port = (in_port_t)htons((uint16_t)port);
		if(inet_pton((int)sa->sin_family, svr, &sa->sin_addr) <= 0) {
			fprintf(stderr, "could not parse IP: %s\n", svr);
			exit(1);
		}<commit_msg>Remove warning at compile time (Ubuntu LTS 10.04). svn:NO TEST<commit_after>/*
 * nsd-control.c - remote control utility for nsd.
 *
 * Copyright (c) 2011, NLnet Labs. All rights reserved.
 *
 * This software is open source.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * 
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 * 
 * Neither the name of the NLNET LABS nor the names of its contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * \file
 *
 * The remote control utility contacts the nsd server over ssl and
 * sends the command, receives the answer, and displays the result
 * from the commandline.
 */

#include "config.h"
#ifdef HAVE_SSL

#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#ifdef HAVE_OPENSSL_SSL_H
#include <openssl/ssl.h>
#endif
#ifdef HAVE_OPENSSL_ERR_H
#include <openssl/err.h>
#endif
#ifdef HAVE_OPENSSL_RAND_H
#include <openssl/rand.h>
#endif
#include "util.h"
#include "tsig.h"
#include "options.h"

/** Give nsd-control usage, and exit (1). */
static void
usage()
{
	printf("Usage:	nsd-control [options] command\n");
	printf("	Remote control utility for nsd server.\n");
	printf("Version %s. Report bugs to <%s>.\n",
		PACKAGE_VERSION, PACKAGE_BUGREPORT);
	printf("Options:\n");
	printf("  -c file	config file, default is %s\n", CONFIGFILE);
	printf("  -s ip[@port]	server address, if omitted config is used.\n");
	printf("  -h		show this usage help.\n");
	printf("Commands:\n");
	printf("  start				start server; runs nsd(8)\n");
	printf("  stop				stops the server\n");
	printf("  reload [<zone>]		reload modified zonefiles from disk\n");
	printf("  repattern			reload tsig keys, patterns from config file\n");
	printf("  log_reopen			reopen logfile (for log rotate)\n");
	printf("  status			display status of server\n");
	printf("  stats				print statistics\n");
	printf("  stats_noreset			peek at statistics\n");
	printf("  addzone <name> <pattern>	add a new zone\n");
	printf("  delzone <name>		remove a zone\n");
	printf("  write [<zone>]		write changed zonefiles to disk\n");
	printf("  notify [<zone>]		send NOTIFY messages to slave servers\n");
	printf("  transfer [<zone>]		try to update slave zones to newer serial\n");
	printf("  force_transfer [<zone>]	update slave zones with AXFR, no serial check\n");
	printf("  zonestatus [<zone>]		print state, serial, activity\n");
	printf("  verbosity <number>		change logging detail\n");
	exit(1);
}

/** exit with ssl error */
static void ssl_err(const char* s)
{
	fprintf(stderr, "error: %s\n", s);
	ERR_print_errors_fp(stderr);
	exit(1);
}

/** setup SSL context */
static SSL_CTX*
setup_ctx(nsd_options_t* cfg)
{
	char* s_cert, *c_key, *c_cert;
	SSL_CTX* ctx;

	s_cert = cfg->server_cert_file;
	c_key = cfg->control_key_file;
	c_cert = cfg->control_cert_file;

        ctx = SSL_CTX_new(SSLv23_client_method());
	if(!ctx)
		ssl_err("could not allocate SSL_CTX pointer");
        if(!(SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2))
		ssl_err("could not set SSL_OP_NO_SSLv2");
	if(!SSL_CTX_use_certificate_file(ctx,c_cert,SSL_FILETYPE_PEM) ||
		!SSL_CTX_use_PrivateKey_file(ctx,c_key,SSL_FILETYPE_PEM)
		|| !SSL_CTX_check_private_key(ctx))
		ssl_err("Error setting up SSL_CTX client key and cert");
	if (SSL_CTX_load_verify_locations(ctx, s_cert, NULL) != 1)
		ssl_err("Error setting up SSL_CTX verify, server cert");
	SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);

	return ctx;
}

/** contact the server with TCP connect */
static int
contact_server(const char* svr, nsd_options_t* cfg, int statuscmd)
{
#ifdef INET6
	struct sockaddr_storage addr;
#else
	struct sockaddr_in addr;
#endif
	socklen_t addrlen;
	int fd;
	int port = cfg->control_port;
	/* use svr or a config entry */
	if(!svr) {
		if(cfg->control_interface)
			svr = cfg->control_interface->address;
		else	svr = "127.0.0.1";
		/* config 0 addr (everything), means ask localhost */
		if(strcmp(svr, "0.0.0.0") == 0)
			svr = "127.0.0.1";
		else if(strcmp(svr, "::0") == 0 ||
			strcmp(svr, "0::0") == 0 ||
			strcmp(svr, "0::") == 0 ||
			strcmp(svr, "::") == 0)
			svr = "::1";
	}
	if(strchr(svr, '@')) {
		char* ps = strchr(svr, '@');
		*ps++ = 0;
		port = atoi(ps);
		if(!port) {
			fprintf(stderr, "could not parse port %s\n", ps);
			exit(1);
		}
	} 
        if(strchr(svr, ':')) {
		struct sockaddr_in6 sa;
		addrlen = (socklen_t)sizeof(struct sockaddr_in6);
		memset(&sa, 0, addrlen);
		sa.sin6_family = AF_INET6;
		sa.sin6_port = (in_port_t)htons((uint16_t)port);
		if(inet_pton((int)sa.sin6_family, svr, &sa.sin6_addr) <= 0) {
			fprintf(stderr, "could not parse IP: %s\n", svr);
			exit(1);
		}
		memcpy(&addr, &sa, addrlen);
	} else { /* ip4 */
		struct sockaddr_in sa;
		addrlen = (socklen_t)sizeof(struct sockaddr_in);
		memset(&sa, 0, addrlen);
		sa.sin_family = AF_INET;
		sa.sin_port = (in_port_t)htons((uint16_t)port);
		if(inet_pton((int)sa.sin_family, svr, &sa.sin_addr) <= 0) {
			fprintf(stderr, "could not parse IP: %s\n", svr);
			exit(1);
		}
		memcpy(&addr, &sa, addrlen);
{'fraction_non_alphanumeric': 0.1307864808585616, 'fraction_numerical': 0.010331571359923113, 'mean_word_length': 4.282148900169204, 'pattern_counts': {'":': 6, '<': 41, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 6, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4388338', 'n_tokens_mistral': 4643, 'n_tokens_neox': 4313, 'n_words': 1375}