diff --git a/lib/libutil/expand_number.3 b/lib/libutil/expand_number.3 index 3609b1ad3939..1b932400de69 100644 --- a/lib/libutil/expand_number.3 +++ b/lib/libutil/expand_number.3 @@ -1,93 +1,105 @@ .\" Copyright (c) 2007 Eric Anderson .\" Copyright (c) 2007 Pawel Jakub Dawidek +.\" Copyright (c) 2025 Dag-Erling Smørgrav .\" All rights reserved. .\" .\" 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 AUTHORS 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 AUTHORS 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. .\" -.Dd June 13, 2023 +.Dd July 25, 2025 .Dt EXPAND_NUMBER 3 .Os .Sh NAME .Nm expand_number -.Nd format a number from human readable form +.Nd parse a number from human readable form .Sh LIBRARY .Lb libutil .Sh SYNOPSIS .In libutil.h .Ft int .Fo expand_number -.Fa "const char *buf" "uint64_t *num" +.Fa "const char *buf" "int64_t *num" .Fc .Sh DESCRIPTION The .Fn expand_number -function parses the +function parses the number in the string pointed to by its .Fa buf -string and stores a unsigned 64-bit quantity at -.Fa *num . +argument and stores the number it represents as a signed 64-bit +quantity in the location pointed to by its +.Fa *num +argument. .Pp -The -.Fn expand_number -function -is case-insensitive and -follows the SI power of two convention. +The input string must consist of a decimal number, optionally preceded +by a +.Sq + +or +.Sq - +sign, and optionally followed, without intervening whitespace, by a +suffix indicating a power-of-two multiplier to apply. +Any amount of whitespace at the beginning of the string will be +ignored. .Pp -The suffixes are: +Recognized suffixes are: .Bl -column "Suffix" "Description" "1000000000000000000" -offset indent .It Sy "Suffix" Ta Sy "Description" Ta Sy "Multiplier" -.It Li K Ta No kilo Ta 1024 -.It Li M Ta No mega Ta 1048576 -.It Li G Ta No giga Ta 1073741824 -.It Li T Ta No tera Ta 1099511627776 -.It Li P Ta No peta Ta 1125899906842624 -.It Li E Ta No exa Ta 1152921504606846976 +.It Li K Ta No kilo Ta 1,024 +.It Li M Ta No mega Ta 1,048,576 +.It Li G Ta No giga Ta 1,073,741,824 +.It Li T Ta No tera Ta 1,099,511,627,776 +.It Li P Ta No peta Ta 1,125,899,906,842,624 +.It Li E Ta No exa Ta 1,152,921,504,606,846,976 .El .Pp For historical reasons, the .Fn expand_number function accepts and ignores a single .Dq B suffix at the end of the .Fa buf -string. +string (i.e. +.Dq 5b +is interpreted as 5, and +.Dq 5kb +is interpreted as 5,120). However, the usage of this suffix is discouraged. .Sh RETURN VALUES .Rv -std .Sh ERRORS The .Fn expand_number function will fail if: .Bl -tag -width Er .It Bq Er EINVAL -The given string contains no digits. +The given string does not contain a valid number. .It Bq Er EINVAL -An unrecognized suffix was given. +An unrecognized suffix was encountered. .It Bq Er ERANGE -Result doesn't fit into 64 bits. +The given string represents a number which does not fit into a +.Vt int64_t . .El .Sh SEE ALSO .Xr humanize_number 3 .Sh HISTORY The .Fn expand_number function first appeared in .Fx 6.3 . diff --git a/lib/libutil/expand_number.c b/lib/libutil/expand_number.c index fc2ea8e8b17c..f4c19d7867a3 100644 --- a/lib/libutil/expand_number.c +++ b/lib/libutil/expand_number.c @@ -1,106 +1,148 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2007 Eric Anderson * Copyright (c) 2007 Pawel Jakub Dawidek + * Copyright (c) 2025 Dag-Erling Smørgrav * All rights reserved. * * 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 AUTHORS 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 AUTHORS 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 + #include #include #include #include +#include #include int -expand_number(const char *buf, uint64_t *num) +expand_number(const char *buf, int64_t *num) { char *endptr; - uintmax_t umaxval; - uint64_t number; - unsigned shift; + uintmax_t number; + unsigned int shift; + bool neg; int serrno; + /* + * Skip whitespace and optional sign. + */ + while (isspace((unsigned char)*buf)) + buf++; + if (*buf == '-') { + neg = true; + buf++; + } else { + neg = false; + if (*buf == '+') + buf++; + } + + /* + * The next character should be the first digit of the number. If + * we don't enforce this ourselves, strtoumax() will allow further + * whitespace and a (second?) sign. + */ + if (!isdigit((unsigned char)*buf)) { + errno = EINVAL; + return (-1); + } + serrno = errno; errno = 0; - umaxval = strtoumax(buf, &endptr, 0); - if (umaxval > UINT64_MAX) - errno = ERANGE; + number = strtoumax(buf, &endptr, 0); if (errno != 0) return (-1); errno = serrno; - number = umaxval; switch (tolower((unsigned char)*endptr)) { case 'e': shift = 60; + endptr++; break; case 'p': shift = 50; + endptr++; break; case 't': shift = 40; + endptr++; break; case 'g': shift = 30; + endptr++; break; case 'm': shift = 20; + endptr++; break; case 'k': shift = 10; + endptr++; break; - case 'b': - shift = 0; - break; - case '\0': /* No unit. */ - *num = number; - return (0); default: - /* Unrecognized unit. */ - errno = EINVAL; - return (-1); + shift = 0; } /* * Treat 'b' as an ignored suffix for all unit except 'b', * otherwise there should be no remaining character(s). */ - endptr++; - if (shift != 0 && tolower((unsigned char)*endptr) == 'b') + if (tolower((unsigned char)*endptr) == 'b') endptr++; if (*endptr != '\0') { errno = EINVAL; return (-1); } + /* + * Apply the shift and check for overflow. + */ if ((number << shift) >> shift != number) { /* Overflow */ errno = ERANGE; return (-1); } - *num = number << shift; + number <<= shift; + + /* + * Apply the sign and check for overflow. + */ + if (neg) { + if (number > 0x8000000000000000LLU /* -INT64_MIN */) { + errno = ERANGE; + return (-1); + } + *num = -number; + } else { + if (number > INT64_MAX) { + errno = ERANGE; + return (-1); + } + *num = number; + } + return (0); } diff --git a/lib/libutil/libutil.h b/lib/libutil/libutil.h index 7d8bfdf67fac..6d36a0c291c6 100644 --- a/lib/libutil/libutil.h +++ b/lib/libutil/libutil.h @@ -1,273 +1,273 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1996 Peter Wemm . * All rights reserved. * Copyright (c) 2002 Networks Associates Technology, Inc. * All rights reserved. * * Portions of this software were developed for the FreeBSD Project by * ThinkSec AS and NAI Labs, the Security Research Division of Network * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 * ("CBOSS"), as part of the DARPA CHATS research program. * * Redistribution and use in source and binary forms, with or without * modification, is 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. * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * 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. */ #ifndef _LIBUTIL_H_ #define _LIBUTIL_H_ #include #include #include #ifndef _GID_T_DECLARED typedef __gid_t gid_t; #define _GID_T_DECLARED #endif #ifndef _MODE_T_DECLARED typedef __mode_t mode_t; #define _MODE_T_DECLARED #endif #ifndef _PID_T_DECLARED typedef __pid_t pid_t; #define _PID_T_DECLARED #endif #ifndef _SIZE_T_DECLARED typedef __size_t size_t; #define _SIZE_T_DECLARED #endif #ifndef _UID_T_DECLARED typedef __uid_t uid_t; #define _UID_T_DECLARED #endif #define PROPERTY_MAX_NAME 64 #define PROPERTY_MAX_VALUE 512 /* For properties.c. */ typedef struct _property { struct _property *next; char *name; char *value; } *properties; /* Avoid pulling in all the include files for no need. */ struct in_addr; struct pidfh; struct sockaddr; struct termios; struct winsize; __BEGIN_DECLS char *auth_getval(const char *_name); void clean_environment(const char * const *_white, const char * const *_more_white); -int expand_number(const char *_buf, uint64_t *_num); +int expand_number(const char *_buf, int64_t *_num); int extattr_namespace_to_string(int _attrnamespace, char **_string); int extattr_string_to_namespace(const char *_string, int *_attrnamespace); int flopen(const char *_path, int _flags, ...); int flopenat(int _dirfd, const char *_path, int _flags, ...); int forkpty(int *_amaster, char *_name, struct termios *_termp, struct winsize *_winp); const char * getlocalbase(void); void hexdump(const void *_ptr, int _length, const char *_hdr, int _flags); int humanize_number(char *_buf, size_t _len, int64_t _number, const char *_suffix, int _scale, int _flags); struct kinfo_file * kinfo_getfile(pid_t _pid, int *_cntp); struct kinfo_vmentry * kinfo_getvmmap(pid_t _pid, int *_cntp); struct kinfo_vmobject * kinfo_getvmobject(int *_cntp); struct kinfo_vmobject * kinfo_getswapvmobject(int *_cntp); struct kinfo_proc * kinfo_getallproc(int *_cntp); struct kinfo_proc * kinfo_getproc(pid_t _pid); int kld_isloaded(const char *_name); int kld_load(const char *_name); int login_tty(int _fd); int openpty(int *_amaster, int *_aslave, char *_name, struct termios *_termp, struct winsize *_winp); int pidfile_close(struct pidfh *_pfh); int pidfile_fileno(const struct pidfh *_pfh); int pidfile_signal(const char *pathp, int sig, pid_t *pidptr); struct pidfh * pidfile_open(const char *_path, mode_t _mode, pid_t *_pidptr); int pidfile_remove(struct pidfh *_pfh); int pidfile_write(struct pidfh *_pfh); void properties_free(properties _list); char *property_find(properties _list, const char *_name); properties properties_read(int _fd); int realhostname(char *_host, size_t _hsize, const struct in_addr *_ip); int realhostname_sa(char *_host, size_t _hsize, struct sockaddr *_addr, int _addrlen); int _secure_path(const char *_path, uid_t _uid, gid_t _gid); void trimdomain(char *_fullhost, int _hostsize); const char * uu_lockerr(int _uu_lockresult); int uu_lock(const char *_ttyname); int uu_unlock(const char *_ttyname); int uu_lock_txfr(const char *_ttyname, pid_t _pid); /* * Conditionally prototype the following functions if the include * files upon which they depend have been included. */ #ifdef _STDIO_H_ char *fparseln(FILE *_fp, size_t *_len, size_t *_lineno, const char _delim[3], int _flags); #endif #ifdef _PWD_H_ int pw_copy(int _ffd, int _tfd, const struct passwd *_pw, struct passwd *_old_pw); struct passwd *pw_dup(const struct passwd *_pw); int pw_edit(int _notsetuid); int pw_equal(const struct passwd *_pw1, const struct passwd *_pw2); void pw_fini(void); int pw_init(const char *_dir, const char *_master); void pw_initpwd(struct passwd *_pw); char *pw_make(const struct passwd *_pw); char *pw_make_v7(const struct passwd *_pw); int pw_mkdb(const char *_user); int pw_lock(void); struct passwd * pw_scan(const char *_line, int _flags); const char * pw_tempname(void); int pw_tmp(int _mfd); #endif #ifdef _GRP_H_ int gr_copy(int __ffd, int _tfd, const struct group *_gr, struct group *_old_gr); struct group * gr_dup(const struct group *_gr); struct group * gr_add(const struct group *_gr, const char *_newmember); int gr_equal(const struct group *_gr1, const struct group *_gr2); void gr_fini(void); int gr_init(const char *_dir, const char *_master); int gr_lock(void); char *gr_make(const struct group *_gr); int gr_mkdb(void); struct group * gr_scan(const char *_line); int gr_tmp(int _mdf); #endif #ifdef _UFS_UFS_QUOTA_H_ struct fstab; struct quotafile; int quota_check_path(const struct quotafile *_qf, const char *_path); void quota_close(struct quotafile *_qf); int quota_convert(struct quotafile *_qf, int _wordsize); const char * quota_fsname(const struct quotafile *_qf); int quota_maxid(struct quotafile *_qf); int quota_off(struct quotafile *_qf); int quota_on(struct quotafile *_qf); struct quotafile * quota_open(struct fstab *_fs, int _quotatype, int _openflags); const char * quota_qfname(const struct quotafile *_qf); int quota_read(struct quotafile *_qf, struct dqblk *_dqb, int _id); int quota_write_limits(struct quotafile *_qf, struct dqblk *_dqb, int _id); int quota_write_usage(struct quotafile *_qf, struct dqblk *_dqb, int _id); #endif #ifdef _SYS_CPUSET_H_ int cpuset_parselist(const char *list, cpuset_t *mask); #define CPUSET_PARSE_OK 0 #define CPUSET_PARSE_GETAFFINITY -1 #define CPUSET_PARSE_ERROR -2 #define CPUSET_PARSE_OUT_OF_RANGE -3 #define CPUSET_PARSE_GETDOMAIN -4 #define CPUSET_PARSE_INVALID_CPU CPUSET_PARSE_OUT_OF_RANGE /* backwards compat */ #endif #ifdef _SYS_DOMAINSET_H_ int domainset_parselist(const char *list, domainset_t *mask, int *policyp); #endif __END_DECLS /* fparseln(3) */ #define FPARSELN_UNESCESC 0x01 #define FPARSELN_UNESCCONT 0x02 #define FPARSELN_UNESCCOMM 0x04 #define FPARSELN_UNESCREST 0x08 #define FPARSELN_UNESCALL 0x0f /* Flags for hexdump(3). */ #define HD_COLUMN_MASK 0xff #define HD_DELIM_MASK 0xff00 #define HD_OMIT_COUNT (1 << 16) #define HD_OMIT_HEX (1 << 17) #define HD_OMIT_CHARS (1 << 18) /* Values for humanize_number(3)'s flags parameter. */ #define HN_DECIMAL 0x01 #define HN_NOSPACE 0x02 #define HN_B 0x04 #define HN_DIVISOR_1000 0x08 #define HN_IEC_PREFIXES 0x10 /* Values for humanize_number(3)'s scale parameter. */ #define HN_GETSCALE 0x10 #define HN_AUTOSCALE 0x20 /* Return values from realhostname(). */ #define HOSTNAME_FOUND 0 #define HOSTNAME_INCORRECTNAME 1 #define HOSTNAME_INVALIDADDR 2 #define HOSTNAME_INVALIDNAME 3 /* Flags for pw_scan(). */ #define PWSCAN_MASTER 0x01 #define PWSCAN_WARN 0x02 /* Return values from uu_lock(). */ #define UU_LOCK_INUSE 1 #define UU_LOCK_OK 0 #define UU_LOCK_OPEN_ERR (-1) #define UU_LOCK_READ_ERR (-2) #define UU_LOCK_CREAT_ERR (-3) #define UU_LOCK_WRITE_ERR (-4) #define UU_LOCK_LINK_ERR (-5) #define UU_LOCK_TRY_ERR (-6) #define UU_LOCK_OWNER_ERR (-7) #endif /* !_LIBUTIL_H_ */ diff --git a/usr.sbin/ctld/conf.cc b/usr.sbin/ctld/conf.cc index e86b44ee5004..f3285ebf9d56 100644 --- a/usr.sbin/ctld/conf.cc +++ b/usr.sbin/ctld/conf.cc @@ -1,755 +1,759 @@ /*- * 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 #include #include #include #include #include #include #include #include #include "conf.h" #include "ctld.h" static struct conf *conf = NULL; static struct auth_group *auth_group = NULL; static struct portal_group *portal_group = NULL; static struct target *target = NULL; static struct lun *lun = NULL; void conf_start(struct conf *new_conf) { assert(conf == NULL); conf = new_conf; } void conf_finish(void) { auth_group = NULL; portal_group = NULL; target = NULL; lun = NULL; conf = NULL; } bool isns_add_server(const char *addr) { return (isns_new(conf, addr)); } void conf_set_debug(int debug) { conf->conf_debug = debug; } void conf_set_isns_period(int period) { conf->conf_isns_period = period; } void conf_set_isns_timeout(int timeout) { conf->conf_isns_timeout = timeout; } void conf_set_maxproc(int maxproc) { conf->conf_maxproc = maxproc; } bool conf_set_pidfile_path(const char *path) { if (conf->conf_pidfile_path != NULL) { log_warnx("pidfile specified more than once"); return (false); } conf->conf_pidfile_path = checked_strdup(path); return (true); } void conf_set_timeout(int timeout) { conf->conf_timeout = timeout; } static bool _auth_group_set_type(struct auth_group *ag, const char *str) { int type; if (strcmp(str, "none") == 0) { type = AG_TYPE_NO_AUTHENTICATION; } else if (strcmp(str, "deny") == 0) { type = AG_TYPE_DENY; } else if (strcmp(str, "chap") == 0) { type = AG_TYPE_CHAP; } else if (strcmp(str, "chap-mutual") == 0) { type = AG_TYPE_CHAP_MUTUAL; } else { log_warnx("invalid auth-type \"%s\" for %s", str, ag->ag_label); return (false); } if (ag->ag_type != AG_TYPE_UNKNOWN && ag->ag_type != type) { log_warnx("cannot set auth-type to \"%s\" for %s; " "already has a different type", str, ag->ag_label); return (false); } ag->ag_type = type; return (true); } bool auth_group_add_chap(const char *user, const char *secret) { return (auth_new_chap(auth_group, user, secret)); } bool auth_group_add_chap_mutual(const char *user, const char *secret, const char *user2, const char *secret2) { return (auth_new_chap_mutual(auth_group, user, secret, user2, secret2)); } bool auth_group_add_initiator_name(const char *name) { return (auth_name_new(auth_group, name)); } bool auth_group_add_initiator_portal(const char *portal) { return (auth_portal_new(auth_group, portal)); } bool auth_group_set_type(const char *type) { return (_auth_group_set_type(auth_group, type)); } bool auth_group_start(const char *name) { /* * Make it possible to redefine the default auth-group. but * only once. */ if (strcmp(name, "default") == 0) { if (conf->conf_default_ag_defined) { log_warnx("duplicated auth-group \"default\""); return (false); } conf->conf_default_ag_defined = true; auth_group = auth_group_find(conf, "default"); return (true); } auth_group = auth_group_new(conf, name); return (auth_group != NULL); } void auth_group_finish(void) { auth_group = NULL; } bool portal_group_start(const char *name) { /* * Make it possible to redefine the default portal-group. but * only once. */ if (strcmp(name, "default") == 0) { if (conf->conf_default_pg_defined) { log_warnx("duplicated portal-group \"default\""); return (false); } conf->conf_default_pg_defined = true; portal_group = portal_group_find(conf, "default"); return (true); } portal_group = portal_group_new(conf, name); return (portal_group != NULL); } void portal_group_finish(void) { portal_group = NULL; } bool portal_group_add_listen(const char *listen, bool iser) { return (portal_group_add_portal(portal_group, listen, iser)); } bool portal_group_add_option(const char *name, const char *value) { return (option_new(portal_group->pg_options, name, value)); } bool portal_group_set_discovery_auth_group(const char *name) { if (portal_group->pg_discovery_auth_group != NULL) { log_warnx("discovery-auth-group for portal-group " "\"%s\" specified more than once", portal_group->pg_name); return (false); } portal_group->pg_discovery_auth_group = auth_group_find(conf, name); if (portal_group->pg_discovery_auth_group == NULL) { log_warnx("unknown discovery-auth-group \"%s\" " "for portal-group \"%s\"", name, portal_group->pg_name); return (false); } return (true); } bool portal_group_set_dscp(u_int dscp) { if (dscp >= 0x40) { log_warnx("invalid DSCP value %u for portal-group \"%s\"", dscp, portal_group->pg_name); return (false); } portal_group->pg_dscp = dscp; return (true); } bool portal_group_set_filter(const char *str) { int filter; if (strcmp(str, "none") == 0) { filter = PG_FILTER_NONE; } else if (strcmp(str, "portal") == 0) { filter = PG_FILTER_PORTAL; } else if (strcmp(str, "portal-name") == 0) { filter = PG_FILTER_PORTAL_NAME; } else if (strcmp(str, "portal-name-auth") == 0) { filter = PG_FILTER_PORTAL_NAME_AUTH; } else { log_warnx("invalid discovery-filter \"%s\" for portal-group " "\"%s\"; valid values are \"none\", \"portal\", " "\"portal-name\", and \"portal-name-auth\"", str, portal_group->pg_name); return (false); } if (portal_group->pg_discovery_filter != PG_FILTER_UNKNOWN && portal_group->pg_discovery_filter != filter) { log_warnx("cannot set discovery-filter to \"%s\" for " "portal-group \"%s\"; already has a different " "value", str, portal_group->pg_name); return (false); } portal_group->pg_discovery_filter = filter; return (true); } void portal_group_set_foreign(void) { portal_group->pg_foreign = true; } bool portal_group_set_offload(const char *offload) { if (portal_group->pg_offload != NULL) { log_warnx("cannot set offload to \"%s\" for " "portal-group \"%s\"; already defined", offload, portal_group->pg_name); return (false); } portal_group->pg_offload = checked_strdup(offload); return (true); } bool portal_group_set_pcp(u_int pcp) { if (pcp > 7) { log_warnx("invalid PCP value %u for portal-group \"%s\"", pcp, portal_group->pg_name); return (false); } portal_group->pg_pcp = pcp; return (true); } bool portal_group_set_redirection(const char *addr) { if (portal_group->pg_redirection != NULL) { log_warnx("cannot set redirection to \"%s\" for " "portal-group \"%s\"; already defined", addr, portal_group->pg_name); return (false); } portal_group->pg_redirection = checked_strdup(addr); return (true); } void portal_group_set_tag(uint16_t tag) { portal_group->pg_tag = tag; } bool lun_start(const char *name) { lun = lun_new(conf, name); return (lun != NULL); } void lun_finish(void) { lun = NULL; } bool lun_add_option(const char *name, const char *value) { return (option_new(lun->l_options, name, value)); } bool lun_set_backend(const char *value) { if (lun->l_backend != NULL) { log_warnx("backend for lun \"%s\" specified more than once", lun->l_name); return (false); } lun->l_backend = checked_strdup(value); return (true); } bool lun_set_blocksize(size_t value) { if (lun->l_blocksize != 0) { log_warnx("blocksize for lun \"%s\" specified more than once", lun->l_name); return (false); } lun->l_blocksize = value; return (true); } bool lun_set_device_type(const char *value) { - uint64_t device_type; + const char *errstr; + int device_type; if (strcasecmp(value, "disk") == 0 || strcasecmp(value, "direct") == 0) device_type = T_DIRECT; else if (strcasecmp(value, "processor") == 0) device_type = T_PROCESSOR; else if (strcasecmp(value, "cd") == 0 || strcasecmp(value, "cdrom") == 0 || strcasecmp(value, "dvd") == 0 || strcasecmp(value, "dvdrom") == 0) device_type = T_CDROM; - else if (expand_number(value, &device_type) != 0 || device_type > 15) { - log_warnx("invalid device-type \"%s\" for lun \"%s\"", value, - lun->l_name); + else { + device_type = strtonum(value, 0, 15, &errstr); + if (errstr != NULL) { + log_warnx("invalid device-type \"%s\" for lun \"%s\"", value, + lun->l_name); + } return (false); } lun->l_device_type = device_type; return (true); } bool lun_set_device_id(const char *value) { if (lun->l_device_id != NULL) { log_warnx("device_id for lun \"%s\" specified more than once", lun->l_name); return (false); } lun->l_device_id = checked_strdup(value); return (true); } bool lun_set_path(const char *value) { if (lun->l_path != NULL) { log_warnx("path for lun \"%s\" specified more than once", lun->l_name); return (false); } lun->l_path = checked_strdup(value); return (true); } bool lun_set_serial(const char *value) { if (lun->l_serial != NULL) { log_warnx("serial for lun \"%s\" specified more than once", lun->l_name); return (false); } lun->l_serial = checked_strdup(value); return (true); } bool lun_set_size(uint64_t value) { if (lun->l_size != 0) { log_warnx("size for lun \"%s\" specified more than once", lun->l_name); return (false); } lun->l_size = value; return (true); } bool lun_set_ctl_lun(uint32_t value) { if (lun->l_ctl_lun >= 0) { log_warnx("ctl_lun for lun \"%s\" specified more than once", lun->l_name); return (false); } lun->l_ctl_lun = value; return (true); } bool target_start(const char *name) { target = target_new(conf, name); return (target != NULL); } void target_finish(void) { target = NULL; } bool target_add_chap(const char *user, const char *secret) { if (target->t_auth_group != NULL) { if (target->t_auth_group->ag_name != NULL) { log_warnx("cannot use both auth-group and " "chap for target \"%s\"", target->t_name); return (false); } } else { target->t_auth_group = auth_group_new(conf, target); if (target->t_auth_group == NULL) return (false); } return (auth_new_chap(target->t_auth_group, user, secret)); } bool target_add_chap_mutual(const char *user, const char *secret, const char *user2, const char *secret2) { if (target->t_auth_group != NULL) { if (target->t_auth_group->ag_name != NULL) { log_warnx("cannot use both auth-group and " "chap-mutual for target \"%s\"", target->t_name); return (false); } } else { target->t_auth_group = auth_group_new(conf, target); if (target->t_auth_group == NULL) return (false); } return (auth_new_chap_mutual(target->t_auth_group, user, secret, user2, secret2)); } bool target_add_initiator_name(const char *name) { if (target->t_auth_group != NULL) { if (target->t_auth_group->ag_name != NULL) { log_warnx("cannot use both auth-group and " "initiator-name for target \"%s\"", target->t_name); return (false); } } else { target->t_auth_group = auth_group_new(conf, target); if (target->t_auth_group == NULL) return (false); } return (auth_name_new(target->t_auth_group, name)); } bool target_add_initiator_portal(const char *addr) { if (target->t_auth_group != NULL) { if (target->t_auth_group->ag_name != NULL) { log_warnx("cannot use both auth-group and " "initiator-portal for target \"%s\"", target->t_name); return (false); } } else { target->t_auth_group = auth_group_new(conf, target); if (target->t_auth_group == NULL) return (false); } return (auth_portal_new(target->t_auth_group, addr)); } bool target_add_lun(u_int id, const char *name) { struct lun *t_lun; if (id >= MAX_LUNS) { log_warnx("LUN %u too big for target \"%s\"", id, target->t_name); return (false); } if (target->t_luns[id] != NULL) { log_warnx("duplicate LUN %u for target \"%s\"", id, target->t_name); return (false); } t_lun = lun_find(conf, name); if (t_lun == NULL) { log_warnx("unknown LUN named %s used for target \"%s\"", name, target->t_name); return (false); } target->t_luns[id] = t_lun; return (true); } bool target_add_portal_group(const char *pg_name, const char *ag_name) { struct portal_group *pg; struct auth_group *ag; struct port *p; pg = portal_group_find(conf, pg_name); if (pg == NULL) { log_warnx("unknown portal-group \"%s\" for target \"%s\"", pg_name, target->t_name); return (false); } if (ag_name != NULL) { ag = auth_group_find(conf, ag_name); if (ag == NULL) { log_warnx("unknown auth-group \"%s\" for target \"%s\"", ag_name, target->t_name); return (false); } } else ag = NULL; p = port_new(conf, target, pg); if (p == NULL) { log_warnx("can't link portal-group \"%s\" to target \"%s\"", pg_name, target->t_name); return (false); } p->p_auth_group = ag; return (true); } bool target_set_alias(const char *alias) { if (target->t_alias != NULL) { log_warnx("alias for target \"%s\" specified more than once", target->t_name); return (false); } target->t_alias = checked_strdup(alias); return (true); } bool target_set_auth_group(const char *name) { if (target->t_auth_group != NULL) { if (target->t_auth_group->ag_name != NULL) log_warnx("auth-group for target \"%s\" " "specified more than once", target->t_name); else log_warnx("cannot use both auth-group and explicit " "authorisations for target \"%s\"", target->t_name); return (false); } target->t_auth_group = auth_group_find(conf, name); if (target->t_auth_group == NULL) { log_warnx("unknown auth-group \"%s\" for target \"%s\"", name, target->t_name); return (false); } return (true); } bool target_set_auth_type(const char *type) { if (target->t_auth_group != NULL) { if (target->t_auth_group->ag_name != NULL) { log_warnx("cannot use both auth-group and " "auth-type for target \"%s\"", target->t_name); return (false); } } else { target->t_auth_group = auth_group_new(conf, target); if (target->t_auth_group == NULL) return (false); } return (_auth_group_set_type(target->t_auth_group, type)); } bool target_set_physical_port(const char *pport) { if (target->t_pport != NULL) { log_warnx("cannot set multiple physical ports for target " "\"%s\"", target->t_name); return (false); } target->t_pport = checked_strdup(pport); return (true); } bool target_set_redirection(const char *addr) { if (target->t_redirection != NULL) { log_warnx("cannot set redirection to \"%s\" for " "target \"%s\"; already defined", addr, target->t_name); return (false); } target->t_redirection = checked_strdup(addr); return (true); } bool target_start_lun(u_int id) { struct lun *new_lun; char *name; if (id >= MAX_LUNS) { log_warnx("LUN %u too big for target \"%s\"", id, target->t_name); return (false); } if (target->t_luns[id] != NULL) { log_warnx("duplicate LUN %u for target \"%s\"", id, target->t_name); return (false); } if (asprintf(&name, "%s,lun,%u", target->t_name, id) <= 0) log_err(1, "asprintf"); new_lun = lun_new(conf, name); if (new_lun == NULL) return (false); lun_set_scsiname(new_lun, name); free(name); target->t_luns[id] = new_lun; lun = new_lun; return (true); } diff --git a/usr.sbin/ctld/parse.y b/usr.sbin/ctld/parse.y index 56455d33bd27..c0146262e895 100644 --- a/usr.sbin/ctld/parse.y +++ b/usr.sbin/ctld/parse.y @@ -1,909 +1,909 @@ %{ /*- * 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 #include #include #include #include #include #include #include #include #include #include #include #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 CTL_LUN DEBUG DEVICE_ID DEVICE_TYPE %token DISCOVERY_AUTH_GROUP DISCOVERY_FILTER DSCP FOREIGN %token INITIATOR_NAME INITIATOR_PORTAL ISNS_SERVER ISNS_PERIOD ISNS_TIMEOUT %token LISTEN LISTEN_ISER LUN MAXPROC OFFLOAD OPENING_BRACKET OPTION %token PATH PCP PIDFILE PORT PORTAL_GROUP REDIRECT SEMICOLON SERIAL %token SIZE STR TAG TARGET TIMEOUT %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 %% statements: | statements statement | statements statement SEMICOLON ; statement: debug | timeout | maxproc | pidfile | isns_server | isns_period | isns_timeout | auth_group | portal_group | lun | target ; debug: DEBUG STR { - uint64_t tmp; + 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 { - uint64_t tmp; + 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 { - uint64_t tmp; + 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 { - uint64_t tmp; + 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 { - uint64_t tmp; + 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_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_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 { - uint64_t tmp; + 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 { - uint64_t tmp; + 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 { - uint64_t tmp; + 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); } ; 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 { - uint64_t tmp; + 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 { - uint64_t tmp; + 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); } ; 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 { - uint64_t tmp; + 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 { - uint64_t tmp; + 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 { - uint64_t tmp; + 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 parse_conf(const char *path) { int error; yyin = fopen(path, "r"); if (yyin == NULL) { log_warn("unable to open configuration file %s", path); return (false); } lineno = 1; yyrestart(yyin); error = yyparse(); fclose(yyin); return (error == 0); }