static char *	
lxl_dns_core_listen(lxl_conf_t *cf, lxl_command_t *cmd, void *conf)
{
	size_t off;
	lxl_uint_t i, nelts;
	lxl_url_t u;
	lxl_str_t *value;
	in_port_t port;
	struct sockaddr *sa;
	struct sockaddr_in *sin;
	lxl_dns_listen_t *ls;
	lxl_dns_core_main_conf_t *cmcf;

	value = lxl_array_elts(cf->args);
	u.url = value[1];
	u.listen = 1;

	if (lxl_parse_url(cf->pool, &u) != 0) {
		if (u.err) {
			lxl_conf_log_error(LXL_LOG_EMERG, cf, 0, "%s in \"%s\" of the \"listen\" directive", u.err, u.url.data);
		}

		return LXL_CONF_ERROR;
	}

	cmcf = lxl_dns_conf_get_module_main_conf(cf, lxl_dns_core_module);
	ls = lxl_array_elts(&cmcf->listens);
	nelts = lxl_array_nelts(&cmcf->listens);
	for (i = 0; i < nelts; ++i) {
		sa = (struct sockaddr *) ls[i].sockaddr;
		off = offsetof(struct sockaddr_in, sin_addr);
		sin = (struct sockaddr_in *) sa;
		port = sin->sin_port;
		
		if (memcmp(ls[i].sockaddr + off, u.sockaddr + off, 4) != 0) {
			continue;
		}

		if (port != u.port) {
			continue;
		}

		lxl_conf_log_error(LXL_LOG_EMERG, cf, 0, "duplicate \"%s\" address and port again", &u.url);
		
		return LXL_CONF_ERROR;
	}
	
	ls = lxl_array_push(&cmcf->listens);
	if (ls == NULL) {
		return LXL_CONF_ERROR;
	}

	memset(ls, 0x00, sizeof(lxl_dns_listen_t));
	memcpy(ls->sockaddr, u.sockaddr, u.socklen);
	ls->socklen = u.socklen;
	ls->wildcard = u.wildcard;
	ls->ctx = cf->ctx;
	
	return LXL_CONF_OK;
}
static char *
lxl_dns_core_server(lxl_conf_t *cf, lxl_command_t *cmd, void *conf)
{
	char 					   *rv;
	void 					   *mconf;
	lxl_uint_t 					i;
	lxl_conf_t 					pcf;
	lxl_dns_module_t		   *module;
	lxl_dns_conf_ctx_t 		   *ctx, *main_ctx;
	lxl_dns_core_srv_conf_t    *cscf, **cscfp;
	lxl_dns_core_main_conf_t   *cmcf;

	ctx = lxl_pcalloc(cf->pool, sizeof(lxl_dns_conf_ctx_t));
	if (ctx == NULL) {
		return LXL_CONF_ERROR;
	}

	main_ctx = cf->ctx;
	ctx->main_conf = main_ctx->main_conf;

	ctx->srv_conf = lxl_pcalloc(cf->pool, lxl_dns_max_module * sizeof(void *));
	if (ctx->srv_conf == NULL) {
		return LXL_CONF_ERROR;
	}

	for (i = 0; lxl_modules[i]; ++i) {
		if (lxl_modules[i]->type != LXL_DNS_MODULE) {
			continue;
		}

		module = lxl_modules[i]->ctx;
		if (module->create_srv_conf) {
			mconf = module->create_srv_conf(cf);
			if (mconf == NULL) {
				return LXL_CONF_ERROR;
			}

			ctx->srv_conf[lxl_modules[i]->ctx_index] = mconf;
		}
	}
	
	cscf = ctx->srv_conf[lxl_dns_core_module.ctx_index];
	cscf->ctx = ctx;
	cmcf = ctx->main_conf[lxl_dns_core_module.ctx_index];
	cscfp = lxl_array_push(&cmcf->servers);
	if (cscfp == NULL) {
		return LXL_CONF_ERROR;
	}

	*cscfp = cscf;

	pcf = *cf;
	cf->ctx = ctx;
	cf->cmd_type = LXL_DNS_SRV_CONF;
	rv = lxl_conf_parse(cf, NULL);
	*cf = pcf;

	return rv;
}
예제 #3
0
static int 
lxl_conf_read_token(lxl_conf_t *cf)
{
	char ch, *dst, *src, *start;
	off_t file_size;
	size_t len;
	ssize_t n, size;
	lxl_str_t *word;
	lxl_buf_t *b;
	lxl_uint_t found, start_line, last_space, sharp_comment;

	found = 0;
	last_space = 1;
	sharp_comment = 0;

	lxl_array_clear(cf->args);
	b = cf->conf_file->buffer;
	start = b->pos;
	start_line = cf->conf_file->line;

	file_size = lxl_file_size(&cf->conf_file->file.info);

	for (; ;) {
		if (b->pos >= b->last) {
			if (cf->conf_file->file.offset >= file_size) {
				if (cf->args->nelts > 0 || !last_space) {
					lxl_conf_log_error(LXL_LOG_EMERG, cf, 0, "unexpected end file, \";\" or \"}\"");
					return LXL_ERROR;
				}

				return LXL_CONF_FILE_DONE;
			}		

			len = b->pos - start;
			if (len == LXL_CONF_BUFFER) {
				cf->conf_file->line = start_line;
				lxl_conf_log_error(LXL_LOG_EMERG, cf, 0, "too long paraments \"%*s...\" started", start);
				return LXL_ERROR;
			}

			if (len) {
				memmove(b->start, start, len);
			}

			size = (ssize_t) (file_size - cf->conf_file->file.offset);
			if (size > b->end - (b->start + len)) {
				size = b->end - (b->start + len);
			}

			n = lxl_read_file(&cf->conf_file->file, b->start + len, size, cf->conf_file->file.offset);
			if (n == -1) {
				return -1;
			}

			if (n != size) {
				lxl_conf_log_error(LXL_LOG_EMERG, cf, 0, lxl_read_file_n " returned only %ld bytes instead of %ld", n, size);
				return -1;
			}

			b->pos = b->start + len;
			b->last = b->pos + n;
			start = b->start;
		}
	
		ch = *b->pos++;
		if (ch == '\n') {
			cf->conf_file->line++;
			if (sharp_comment) {
				sharp_comment = 0;
			}
		}

		if (sharp_comment) {
			continue;
		}

		if (last_space) {
			if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) {
				continue;
			}

			start = b->pos - 1;
			start_line = cf->conf_file->line;

			switch (ch) {
				case ';':
					if (lxl_array_nelts(cf->args) == 0) {
						lxl_conf_log_error(LXL_LOG_EMERG, cf, 0,  "unexpected \";\"");
						return LXL_ERROR;
					}

					return LXL_OK;
				
				case '{':
					if (lxl_array_nelts(cf->args) == 0) {
						lxl_conf_log_error(LXL_LOG_EMERG, cf, 0,  "unexpected \"{\"");
						return LXL_ERROR;
					}

					return LXL_CONF_BLOCK_START;

				case '}':
					if (lxl_array_nelts(cf->args) != 0) {
						lxl_conf_log_error(LXL_LOG_EMERG, cf, 0,  "unexpected \"}\"");
						return LXL_ERROR;
					}

					return LXL_CONF_BLOCK_DONE;
					
				case '#':
					sharp_comment = 1;
					continue;

				default:
					last_space = 0;
			}
		} else {
			if (ch == ' ' || ch == '\t' || ch == CR || ch == LF || ch == ';' || ch == '{') {
				last_space = 1;
				found = 1;
			}

			if (found) {
				word = lxl_array_push(cf->args);
				if (word == NULL) {
					return LXL_ERROR;
				}

				word->data = lxl_pnalloc(cf->pool, b->pos - start + 1);
				if (word == NULL) {
					return LXL_ERROR;
				}

				for (dst = word->data, src = start, len = 0; src < b->pos - 1; ++len) {
					*dst++ = *src++;
				}
				*dst = '\0';
				word->len = len;

				if (ch == ';') {
					return LXL_OK;
				}

				if (ch == '{') {
					return LXL_CONF_BLOCK_START;
				}

				found = 0;
			}
		}
	}
}