Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/usr.sbin/ctld/parse.y
103829 views
%{
/*-
 * SPDX-License-Identifier: BSD-2-Clause
 *
 * Copyright (c) 2012 The FreeBSD Foundation
 *
 * This software was developed by Edward Tomasz Napierala under sponsorship
 * from the FreeBSD Foundation.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
 */

#include <sys/types.h>
#include <sys/nv.h>
#include <sys/queue.h>
#include <sys/stat.h>
#include <assert.h>
#include <libiscsiutil.h>
#include <libutil.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <netinet/ip.h>

#include "conf.h"

extern FILE *yyin;
extern char *yytext;
extern int lineno;

extern void	yyerror(const char *);
extern void	yyrestart(FILE *);

%}

%token ALIAS AUTH_GROUP AUTH_TYPE BACKEND BLOCKSIZE CHAP CHAP_MUTUAL
%token CLOSING_BRACKET CONTROLLER CTL_LUN DEBUG DEVICE_ID DEVICE_TYPE
%token DISCOVERY_AUTH_GROUP DISCOVERY_FILTER DISCOVERY_TCP DSCP FOREIGN
%token HOST_ADDRESS HOST_NQN
%token INITIATOR_NAME INITIATOR_PORTAL ISNS_SERVER ISNS_PERIOD ISNS_TIMEOUT
%token LISTEN LISTEN_ISER LUN MAXPROC NAMESPACE
%token OFFLOAD OPENING_BRACKET OPTION
%token PATH PCP PIDFILE PORT PORTAL_GROUP REDIRECT SEMICOLON SERIAL
%token SIZE STR TAG TARGET TCP TIMEOUT TRANSPORT_GROUP
%token AF11 AF12 AF13 AF21 AF22 AF23 AF31 AF32 AF33 AF41 AF42 AF43
%token BE EF CS0 CS1 CS2 CS3 CS4 CS5 CS6 CS7

%union
{
	char *str;
}

%token <str> STR

%%

statements:
	|
	statements statement
	|
	statements statement SEMICOLON
	;

statement:
	debug
	|
	timeout
	|
	maxproc
	|
	pidfile
	|
	isns_server
	|
	isns_period
	|
	isns_timeout
	|
	auth_group
	|
	portal_group
	|
	transport_group
	|
	lun
	|
	target
	|
	controller
	;

debug:		DEBUG STR
	{
		int64_t tmp;

		if (expand_number($2, &tmp) != 0) {
			yyerror("invalid numeric value");
			free($2);
			return (1);
		}
		free($2);

		conf_set_debug(tmp);
	}
	;

timeout:	TIMEOUT STR
	{
		int64_t tmp;

		if (expand_number($2, &tmp) != 0) {
			yyerror("invalid numeric value");
			free($2);
			return (1);
		}
		free($2);

		conf_set_timeout(tmp);
	}
	;

maxproc:	MAXPROC STR
	{
		int64_t tmp;

		if (expand_number($2, &tmp) != 0) {
			yyerror("invalid numeric value");
			free($2);
			return (1);
		}
		free($2);

		conf_set_maxproc(tmp);
	}
	;

pidfile:	PIDFILE STR
	{
		bool ok;

		ok = conf_set_pidfile_path($2);
		free($2);
		if (!ok)
			return (1);
	}
	;

isns_server:	ISNS_SERVER STR
	{
		bool ok;

		ok = isns_add_server($2);
		free($2);
		if (!ok)
			return (1);
	}
	;

isns_period:	ISNS_PERIOD STR
	{
		int64_t tmp;

		if (expand_number($2, &tmp) != 0) {
			yyerror("invalid numeric value");
			free($2);
			return (1);
		}
		free($2);

		conf_set_isns_period(tmp);
	}
	;

isns_timeout:	ISNS_TIMEOUT STR
	{
		int64_t tmp;

		if (expand_number($2, &tmp) != 0) {
			yyerror("invalid numeric value");
			free($2);
			return (1);
		}
		free($2);

		conf_set_isns_timeout(tmp);
	}
	;

auth_group:	AUTH_GROUP auth_group_name
    OPENING_BRACKET auth_group_entries CLOSING_BRACKET
	{
		auth_group_finish();
	}
	;

auth_group_name:	STR
	{
		bool ok;

		ok = auth_group_start($1);
		free($1);
		if (!ok)
			return (1);
	}
	;

auth_group_entries:
	|
	auth_group_entries auth_group_entry
	|
	auth_group_entries auth_group_entry SEMICOLON
	;

auth_group_entry:
	auth_group_auth_type
	|
	auth_group_chap
	|
	auth_group_chap_mutual
	|
	auth_group_host_address
	|
	auth_group_host_nqn
	|
	auth_group_initiator_name
	|
	auth_group_initiator_portal
	;

auth_group_auth_type:	AUTH_TYPE STR
	{
		bool ok;

		ok = auth_group_set_type($2);
		free($2);
		if (!ok)
			return (1);
	}
	;

auth_group_chap:	CHAP STR STR
	{
		bool ok;

		ok = auth_group_add_chap($2, $3);
		free($2);
		free($3);
		if (!ok)
			return (1);
	}
	;

auth_group_chap_mutual:	CHAP_MUTUAL STR STR STR STR
	{
		bool ok;

		ok = auth_group_add_chap_mutual($2, $3, $4, $5);
		free($2);
		free($3);
		free($4);
		free($5);
		if (!ok)
			return (1);
	}
	;

auth_group_host_address:	HOST_ADDRESS STR
	{
		bool ok;

		ok = auth_group_add_host_address($2);
		free($2);
		if (!ok)
			return (1);
	}
	;

auth_group_host_nqn:	HOST_NQN STR
	{
		bool ok;

		ok = auth_group_add_host_nqn($2);
		free($2);
		if (!ok)
			return (1);
	}
	;

auth_group_initiator_name:	INITIATOR_NAME STR
	{
		bool ok;

		ok = auth_group_add_initiator_name($2);
		free($2);
		if (!ok)
			return (1);
	}
	;

auth_group_initiator_portal:	INITIATOR_PORTAL STR
	{
		bool ok;

		ok = auth_group_add_initiator_portal($2);
		free($2);
		if (!ok)
			return (1);
	}
	;

portal_group:	PORTAL_GROUP portal_group_name
    OPENING_BRACKET portal_group_entries CLOSING_BRACKET
	{
		portal_group_finish();
	}
	;

portal_group_name:	STR
	{
		bool ok;

		ok = portal_group_start($1);
		free($1);
		if (!ok)
			return (1);
	}
	;

portal_group_entries:
	|
	portal_group_entries portal_group_entry
	|
	portal_group_entries portal_group_entry SEMICOLON
	;

portal_group_entry:
	portal_group_discovery_auth_group
	|
	portal_group_discovery_filter
	|
	portal_group_foreign
	|
	portal_group_listen
	|
	portal_group_listen_iser
	|
	portal_group_offload
	|
	portal_group_option
	|
	portal_group_redirect
	|
	portal_group_tag
	|
	portal_group_dscp
	|
	portal_group_pcp
	;

portal_group_discovery_auth_group:	DISCOVERY_AUTH_GROUP STR
	{
		bool ok;

		ok = portal_group_set_discovery_auth_group($2);
		free($2);
		if (!ok)
			return (1);
	}
	;

portal_group_discovery_filter:	DISCOVERY_FILTER STR
	{
		bool ok;

		ok = portal_group_set_filter($2);
		free($2);
		if (!ok)
			return (1);
	}
	;

portal_group_foreign:	FOREIGN
	{

		portal_group_set_foreign();
	}
	;

portal_group_listen:	LISTEN STR
	{
		bool ok;

		ok = portal_group_add_listen($2, false);
		free($2);
		if (!ok)
			return (1);
	}
	;

portal_group_listen_iser:	LISTEN_ISER STR
	{
		bool ok;

		ok = portal_group_add_listen($2, true);
		free($2);
		if (!ok)
			return (1);
	}
	;

portal_group_offload:	OFFLOAD STR
	{
		bool ok;

		ok = portal_group_set_offload($2);
		free($2);
		if (!ok)
			return (1);
	}
	;

portal_group_option:	OPTION STR STR
	{
		bool ok;

		ok = portal_group_add_option($2, $3);
		free($2);
		free($3);
		if (!ok)
			return (1);
	}
	;

portal_group_redirect:	REDIRECT STR
	{
		bool ok;

		ok = portal_group_set_redirection($2);
		free($2);
		if (!ok)
			return (1);
	}
	;

portal_group_tag:	TAG STR
	{
		int64_t tmp;

		if (expand_number($2, &tmp) != 0) {
			yyerror("invalid numeric value");
			free($2);
			return (1);
		}
		free($2);

		portal_group_set_tag(tmp);
	}
	;

portal_group_dscp
: DSCP STR
	{
		int64_t tmp;

		if (strcmp($2, "0x") == 0) {
			tmp = strtol($2 + 2, NULL, 16);
		} else if (expand_number($2, &tmp) != 0) {
			yyerror("invalid numeric value");
			free($2);
			return (1);
		}
		free($2);

		if (!portal_group_set_dscp(tmp))
			return (1);
	}
| DSCP BE	{ portal_group_set_dscp(IPTOS_DSCP_CS0  >> 2); }
| DSCP EF	{ portal_group_set_dscp(IPTOS_DSCP_EF   >> 2); }
| DSCP CS0	{ portal_group_set_dscp(IPTOS_DSCP_CS0  >> 2); }
| DSCP CS1	{ portal_group_set_dscp(IPTOS_DSCP_CS1  >> 2); }
| DSCP CS2	{ portal_group_set_dscp(IPTOS_DSCP_CS2  >> 2); }
| DSCP CS3	{ portal_group_set_dscp(IPTOS_DSCP_CS3  >> 2); }
| DSCP CS4	{ portal_group_set_dscp(IPTOS_DSCP_CS4  >> 2); }
| DSCP CS5	{ portal_group_set_dscp(IPTOS_DSCP_CS5  >> 2); }
| DSCP CS6	{ portal_group_set_dscp(IPTOS_DSCP_CS6  >> 2); }
| DSCP CS7	{ portal_group_set_dscp(IPTOS_DSCP_CS7  >> 2); }
| DSCP AF11	{ portal_group_set_dscp(IPTOS_DSCP_AF11 >> 2); }
| DSCP AF12	{ portal_group_set_dscp(IPTOS_DSCP_AF12 >> 2); }
| DSCP AF13	{ portal_group_set_dscp(IPTOS_DSCP_AF13 >> 2); }
| DSCP AF21	{ portal_group_set_dscp(IPTOS_DSCP_AF21 >> 2); }
| DSCP AF22	{ portal_group_set_dscp(IPTOS_DSCP_AF22 >> 2); }
| DSCP AF23	{ portal_group_set_dscp(IPTOS_DSCP_AF23 >> 2); }
| DSCP AF31	{ portal_group_set_dscp(IPTOS_DSCP_AF31 >> 2); }
| DSCP AF32	{ portal_group_set_dscp(IPTOS_DSCP_AF32 >> 2); }
| DSCP AF33	{ portal_group_set_dscp(IPTOS_DSCP_AF33 >> 2); }
| DSCP AF41	{ portal_group_set_dscp(IPTOS_DSCP_AF41 >> 2); }
| DSCP AF42	{ portal_group_set_dscp(IPTOS_DSCP_AF42 >> 2); }
| DSCP AF43	{ portal_group_set_dscp(IPTOS_DSCP_AF43 >> 2); }
	;

portal_group_pcp:	PCP STR
	{
		int64_t tmp;

		if (expand_number($2, &tmp) != 0) {
			yyerror("invalid numeric value");
			free($2);
			return (1);
		}
		free($2);

		if (!portal_group_set_pcp(tmp))
			return (1);
	}
	;

transport_group:	TRANSPORT_GROUP transport_group_name
    OPENING_BRACKET transport_group_entries CLOSING_BRACKET
	{
		portal_group_finish();
	}
	;

transport_group_name:	STR
	{
		bool ok;

		ok = transport_group_start($1);
		free($1);
		if (!ok)
			return (1);
	}
	;

transport_group_entries:
	|
	transport_group_entries transport_group_entry
	|
	transport_group_entries transport_group_entry SEMICOLON
	;

transport_group_entry:
	portal_group_discovery_auth_group
	|
	portal_group_discovery_filter
	|
	transport_group_listen_discovery_tcp
	|
	transport_group_listen_tcp
	|
	portal_group_option
	|
	portal_group_tag
	|
	portal_group_dscp
	|
	portal_group_pcp
	;

transport_group_listen_discovery_tcp:	LISTEN DISCOVERY_TCP STR
	{
		bool ok;

		ok = transport_group_add_listen_discovery_tcp($3);
		free($3);
		if (!ok)
			return (1);
	}
	;

transport_group_listen_tcp:	LISTEN TCP STR
	{
		bool ok;

		ok = transport_group_add_listen_tcp($3);
		free($3);
		if (!ok)
			return (1);
	}
	;

lun:	LUN lun_name
    OPENING_BRACKET lun_entries CLOSING_BRACKET
	{
		lun_finish();
	}
	;

lun_name:	STR
	{
		bool ok;

		ok = lun_start($1);
		free($1);
		if (!ok)
			return (1);
	}
	;

target:	TARGET target_name
    OPENING_BRACKET target_entries CLOSING_BRACKET
	{
		target_finish();
	}
	;

target_name:	STR
	{
		bool ok;

		ok = target_start($1);
		free($1);
		if (!ok)
			return (1);
	}
	;

target_entries:
	|
	target_entries target_entry
	|
	target_entries target_entry SEMICOLON
	;

target_entry:
	target_alias
	|
	target_auth_group
	|
	target_auth_type
	|
	target_chap
	|
	target_chap_mutual
	|
	target_initiator_name
	|
	target_initiator_portal
	|
	target_portal_group
	|
	target_port
	|
	target_redirect
	|
	target_lun
	|
	target_lun_ref
	;

target_alias:	ALIAS STR
	{
		bool ok;

		ok = target_set_alias($2);
		free($2);
		if (!ok)
			return (1);
	}
	;

target_auth_group:	AUTH_GROUP STR
	{
		bool ok;

		ok = target_set_auth_group($2);
		free($2);
		if (!ok)
			return (1);
	}
	;

target_auth_type:	AUTH_TYPE STR
	{
		bool ok;

		ok = target_set_auth_type($2);
		free($2);
		if (!ok)
			return (1);
	}
	;

target_chap:	CHAP STR STR
	{
		bool ok;

		ok = target_add_chap($2, $3);
		free($2);
		free($3);
		if (!ok)
			return (1);
	}
	;

target_chap_mutual:	CHAP_MUTUAL STR STR STR STR
	{
		bool ok;

		ok = target_add_chap_mutual($2, $3, $4, $5);
		free($2);
		free($3);
		free($4);
		free($5);
		if (!ok)
			return (1);
	}
	;

target_initiator_name:	INITIATOR_NAME STR
	{
		bool ok;

		ok = target_add_initiator_name($2);
		free($2);
		if (!ok)
			return (1);
	}
	;

target_initiator_portal:	INITIATOR_PORTAL STR
	{
		bool ok;

		ok = target_add_initiator_portal($2);
		free($2);
		if (!ok)
			return (1);
	}
	;

target_portal_group:	PORTAL_GROUP STR STR
	{
		bool ok;

		ok = target_add_portal_group($2, $3);
		free($2);
		free($3);
		if (!ok)
			return (1);
	}
	|		PORTAL_GROUP STR
	{
		bool ok;

		ok = target_add_portal_group($2, NULL);
		free($2);
		if (!ok)
			return (1);
	}
	;

target_port:	PORT STR
	{
		bool ok;

		ok = target_set_physical_port($2);
		free($2);
		if (!ok)
			return (1);
	}
	;

target_redirect:	REDIRECT STR
	{
		bool ok;

		ok = target_set_redirection($2);
		free($2);
		if (!ok)
			return (1);
	}
	;

target_lun:	LUN lun_number
    OPENING_BRACKET lun_entries CLOSING_BRACKET
	{
		lun_finish();
	}
	;

lun_number:	STR
	{
		int64_t tmp;

		if (expand_number($1, &tmp) != 0) {
			yyerror("invalid numeric value");
			free($1);
			return (1);
		}
		free($1);

		if (!target_start_lun(tmp))
			return (1);
	}
	;

target_lun_ref:	LUN STR STR
	{
		int64_t tmp;
		bool ok;

		if (expand_number($2, &tmp) != 0) {
			yyerror("invalid numeric value");
			free($2);
			free($3);
			return (1);
		}
		free($2);

		ok = target_add_lun(tmp, $3);
		free($3);
		if (!ok)
			return (1);
	}
	;

controller:	CONTROLLER controller_name
    OPENING_BRACKET controller_entries CLOSING_BRACKET
	{
		target_finish();
	}
	;

controller_name:	STR
	{
		bool ok;

		ok = controller_start($1);
		free($1);
		if (!ok)
			return (1);
	}
	;

controller_entries:
	|
	controller_entries controller_entry
	|
	controller_entries controller_entry SEMICOLON
	;

controller_entry:
	target_auth_group
	|
	target_auth_type
	|
	controller_host_address
	|
	controller_host_nqn
	|
	controller_transport_group
	|
	controller_namespace
	|
	controller_namespace_ref
	;

controller_host_address:	HOST_ADDRESS STR
	{
		bool ok;

		ok = controller_add_host_address($2);
		free($2);
		if (!ok)
			return (1);
	}
	;

controller_host_nqn:	HOST_NQN STR
	{
		bool ok;

		ok = controller_add_host_nqn($2);
		free($2);
		if (!ok)
			return (1);
	}
	;

controller_transport_group:	TRANSPORT_GROUP STR STR
	{
		bool ok;

		ok = target_add_portal_group($2, $3);
		free($2);
		free($3);
		if (!ok)
			return (1);
	}
	|		TRANSPORT_GROUP STR
	{
		bool ok;

		ok = target_add_portal_group($2, NULL);
		free($2);
		if (!ok)
			return (1);
	}
	;

controller_namespace:	NAMESPACE ns_number
    OPENING_BRACKET lun_entries CLOSING_BRACKET
	{
		lun_finish();
	}
	;

ns_number:	STR
	{
		uint64_t tmp;

		if (expand_number($1, &tmp) != 0) {
			yyerror("invalid numeric value");
			free($1);
			return (1);
		}
		free($1);

		if (!controller_start_namespace(tmp))
			return (1);
	}
	;

controller_namespace_ref:	NAMESPACE STR STR
	{
		uint64_t tmp;
		bool ok;

		if (expand_number($2, &tmp) != 0) {
			yyerror("invalid numeric value");
			free($2);
			free($3);
			return (1);
		}
		free($2);

		ok = controller_add_namespace(tmp, $3);
		free($3);
		if (!ok)
			return (1);
	}
	;

lun_entries:
	|
	lun_entries lun_entry
	|
	lun_entries lun_entry SEMICOLON
	;

lun_entry:
	lun_backend
	|
	lun_blocksize
	|
	lun_device_id
	|
	lun_device_type
	|
	lun_ctl_lun
	|
	lun_option
	|
	lun_path
	|
	lun_serial
	|
	lun_size
	;

lun_backend:	BACKEND STR
	{
		bool ok;

		ok = lun_set_backend($2);
		free($2);
		if (!ok)
			return (1);
	}
	;

lun_blocksize:	BLOCKSIZE STR
	{
		int64_t tmp;

		if (expand_number($2, &tmp) != 0) {
			yyerror("invalid numeric value");
			free($2);
			return (1);
		}
		free($2);

		if (!lun_set_blocksize(tmp))
			return (1);
	}
	;

lun_device_id:	DEVICE_ID STR
	{
		bool ok;

		ok = lun_set_device_id($2);
		free($2);
		if (!ok)
			return (1);
	}
	;

lun_device_type:	DEVICE_TYPE STR
	{
		bool ok;

		ok = lun_set_device_type($2);
		free($2);
		if (!ok)
			return (1);
	}
	;

lun_ctl_lun:	CTL_LUN STR
	{
		int64_t tmp;

		if (expand_number($2, &tmp) != 0) {
			yyerror("invalid numeric value");
			free($2);
			return (1);
		}
		free($2);

		if (!lun_set_ctl_lun(tmp))
			return (1);
	}
	;

lun_option:	OPTION STR STR
	{
		bool ok;

		ok = lun_add_option($2, $3);
		free($2);
		free($3);
		if (!ok)
			return (1);
	}
	;

lun_path:	PATH STR
	{
		bool ok;

		ok = lun_set_path($2);
		free($2);
		if (!ok)
			return (1);
	}
	;

lun_serial:	SERIAL STR
	{
		bool ok;

		ok = lun_set_serial($2);
		free($2);
		if (!ok)
			return (1);
	}
	;

lun_size:	SIZE STR
	{
		int64_t tmp;

		if (expand_number($2, &tmp) != 0) {
			yyerror("invalid numeric value");
			free($2);
			return (1);
		}
		free($2);

		if (!lun_set_size(tmp))
			return (1);
	}
	;
%%

void
yyerror(const char *str)
{

	log_warnx("error in configuration file at line %d near '%s': %s",
	    lineno, yytext, str);
}

bool
yyparse_conf(FILE *fp)
{
	int error;

	yyin = fp;
	lineno = 1;
	yyrestart(yyin);
	error = yyparse();

	return (error == 0);
}