Example #1
0
File: conf.c Project: idtek/knot
conf_remote_t conf_remote_txn(
	conf_t *conf,
	knot_db_txn_t *txn,
	conf_val_t *id,
	size_t index)
{
	assert(id != NULL && id->item != NULL);
	assert(id->item->type == YP_TSTR ||
	       (id->item->type == YP_TREF &&
	        id->item->var.r.ref->var.g.id->type == YP_TSTR));

	conf_remote_t out = { { AF_UNSPEC } };

	conf_val_t rundir_val = conf_get_txn(conf, txn, C_SRV, C_RUNDIR);
	char *rundir = conf_abs_path(&rundir_val, NULL);

	// Get indexed remote address.
	conf_val_t val = conf_id_get_txn(conf, txn, C_RMT, C_ADDR, id);
	for (size_t i = 0; val.code == KNOT_EOK && i < index; i++) {
		if (i == 0) {
			conf_val(&val);
		}
		conf_val_next(&val);
	}
	// Index overflow causes empty socket.
	out.addr = conf_addr(&val, rundir);

	// Get outgoing address if family matches (optional).
	val = conf_id_get_txn(conf, txn, C_RMT, C_VIA, id);
	while (val.code == KNOT_EOK) {
		struct sockaddr_storage via = conf_addr(&val, rundir);
		if (via.ss_family == out.addr.ss_family) {
			out.via = conf_addr(&val, rundir);
			break;
		}
		conf_val_next(&val);
	}

	// Get TSIG key (optional).
	conf_val_t key_id = conf_id_get_txn(conf, txn, C_RMT, C_KEY, id);
	if (key_id.code == KNOT_EOK) {
		out.key.name = (knot_dname_t *)conf_dname(&key_id);

		val = conf_id_get_txn(conf, txn, C_KEY, C_ALG, &key_id);
		out.key.algorithm = conf_opt(&val);

		val = conf_id_get_txn(conf, txn, C_KEY, C_SECRET, &key_id);
		out.key.secret.data = (uint8_t *)conf_bin(&val, &out.key.secret.size);
	}

	free(rundir);

	return out;
}
Example #2
0
/*! \brief Event loop listening for signals and remote commands. */
static void event_loop(server_t *server)
{
	uint8_t buf[KNOT_WIRE_MAX_PKTSIZE];
	size_t buflen = sizeof(buf);

	/* Read control socket configuration. */
	conf_val_t listen_val = conf_get(conf(), C_CTL, C_LISTEN);
	conf_val_t rundir_val = conf_get(conf(), C_SRV, C_RUNDIR);
	char *rundir = conf_abs_path(&rundir_val, NULL);
	struct sockaddr_storage addr = conf_addr(&listen_val, rundir);
	free(rundir);

	/* Bind to control interface (error logging is inside the function. */
	int remote = remote_bind(&addr);

	sigset_t empty;
	(void)sigemptyset(&empty);

	/* Run event loop. */
	for (;;) {
		int ret = remote_poll(remote, &empty);

		/* Events. */
		if (ret > 0) {
			ret = remote_process(server, &addr, remote, buf, buflen);
			if (ret == KNOT_CTL_STOP) {
				break;
			}
		}

		/* Interrupts. */
		if (sig_req_stop) {
			break;
		}
		if (sig_req_reload) {
			sig_req_reload = false;
			server_reload(server, conf()->filename);
		}
	}

	server_stop(server);

	/* Close remote control interface. */
	remote_unbind(&addr, remote);

	/* Wait for server to finish. */
	server_wait(server);
}
Example #3
0
File: conf.c Project: idtek/knot
static char* get_filename(
	conf_t *conf,
	knot_db_txn_t *txn,
	const knot_dname_t *zone,
	const char *name)
{
	assert(name);

	const char *end = name + strlen(name);
	char out[1024] = "";

	do {
		// Search for a formatter.
		const char *pos = strchr(name, '%');

		// If no formatter, copy the rest of the name.
		if (pos == NULL) {
			if (strlcat(out, name, sizeof(out)) >= sizeof(out)) {
				CONF_LOG_ZONE(LOG_WARNING, zone, "too long zonefile name");
				return NULL;
			}
			break;
		}

		// Copy constant block.
		char *block = strndup(name, pos - name);
		if (block == NULL ||
		    strlcat(out, block, sizeof(out)) >= sizeof(out)) {
			CONF_LOG_ZONE(LOG_WARNING, zone, "too long zonefile name");
			return NULL;
		}
		free(block);

		// Move name pointer behind the formatter.
		name = pos + 2;

		char buff[512] = "";
		uint8_t idx1, idx2;
		bool failed = false;

		const char type = *(pos + 1);
		switch (type) {
		case '%':
			strlcat(buff, "%", sizeof(buff));
			break;
		case 'c':
			if (get_index(&name, end, &idx1, &idx2) != KNOT_EOK ||
			    str_char(zone, buff, sizeof(buff), idx1, idx2) != KNOT_EOK) {
				failed = true;
			}
			break;
		case 'l':
			if (get_index(&name, end, &idx1, NULL) != KNOT_EOK ||
			    str_label(zone, buff, sizeof(buff), idx1) != KNOT_EOK) {
				failed = true;
			}
			break;
		case 's':
			if (str_zone(zone, buff, sizeof(buff)) != KNOT_EOK) {
				failed = true;
			}
			break;
		case '\0':
			CONF_LOG_ZONE(LOG_WARNING, zone, "ignoring missing "
			              "trailing zonefile formatter");
			continue;
		default:
			CONF_LOG_ZONE(LOG_WARNING, zone, "ignoring zonefile "
			              "formatter '%%%c'", type);
			continue;
		}

		if (failed) {
			CONF_LOG_ZONE(LOG_WARNING, zone, "failed to process "
			              "zonefile formatter '%%%c'", type);
			return NULL;
		}

		if (strlcat(out, buff, sizeof(out)) >= sizeof(out)) {
			CONF_LOG_ZONE(LOG_WARNING, zone, "too long zonefile name");
			return NULL;
		}
	} while (name < end);

	// Use storage prefix if not absolute path.
	if (out[0] == '/') {
		return strdup(out);
	} else {
		conf_val_t val = conf_zone_get_txn(conf, txn, C_STORAGE, zone);
		char *storage = conf_abs_path(&val, NULL);
		if (storage == NULL) {
			return NULL;
		}
		char *abs = sprintf_alloc("%s/%s", storage, out);
		free(storage);
		return abs;
	}
}