Wait until all of the configuration has been parsed before creating
associations for NVMe portals. This ensures that any options
specified in a transport group are honored when creating associations.
To enable this, add a new virtual method portal::prepare invoked when
applying a configuration prior to opening a socket (or reusing an
existing socket) for a portal.
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D52844
These fields all need to be explicitly initialized with zeroes. Prior
to the conversion to C++ these fields were zeroed by calloc().
This worked for me in earlier testing as my test boxes had
MALLOC_PRODUCTION enabled in make.conf.
PR: 289115
Reported by: Slawa Olhovchenkov <slw zxy.spb.ru>
Fixes: eb0dc901a5 ("ctld: Convert struct auth_group to a C++ class")
Fixes: 6acc7afa34 ("ctld: Convert struct port to a hierarchy of C++ classes")
Fixes: 2bb9180bb5 ("ctld: Convert struct target to a C++ class")
Fixes: ed076901ec ("ctld: Convert struct ctld_connection to a C++ class")
Sponsored by: Chelsio Communications
While the overall structure is similar for NVMeoF controllers and
iSCSI targets, there are sufficient differences that NVMe support uses
an alternate configuration syntax.
- In authentication groups, permitted NVMeoF hosts can be allowed by
names (NQNs) via "host-nqn" values (similar to "initiator-name" for
iSCSI). Similarly, "host-address" accepts permitted host addresses
similar to "initiator-portal" for iSCSI.
- A new "transport-group" context enumerates transports that can be
used by a group of NVMeoF controllers similar to the "portal-group"
context for iSCSI. In this section, the "listen" keyword accepts a
transport as well as an address to permit other types of transports
besides TCP in the future. The "foreign", "offload", and "redirect"
keywords are also not meaningful and thus not supported.
- A new "controller" context describes an NVMeoF I/O controller
similar to the "target" context for iSCSI. One key difference here
is that "lun" objects are replaced by "namespace" objects. However,
a "namespace" can reference a named global lun permitting LUNs to be
shared between iSCSI targets and NVMeoF controllers.
NB: Authentication via CHAP is not implemented for NVMeoF.
Reviewed by: imp
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D48773
Explicitly hand off ownership of accepted sockets to the
portal::handle_connection method.
Reviewed by: asomers
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D51729
This is a prerequisite for adding NVMe over Fabrics support.
Convert portal_group, portal_group_port, and target into abstract
classes with virtual methods to support protocol-specific methods.
Add new iscsi_portal_group, iscsi_port, iscsi_portal and iscsi_target
subclasses in a new iscsi.cc file and move some iSCSI-specific logic
there. Rename ctld_connection to iscsi_connection and move it to a
new iscsi.hh header. Move iscsi_connection methods out of ctld.cc and
kernel.cc into iscsi.cc.
Reviewed by: imp
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D48772
Split out a private method to parse a listen address and optional
mask. This will avoid having to duplicate that code for NVMe
host addresses.
Rename the ag_names and ag_portals members to include "initiator"
to indicate they are iSCSI-specific.
Reviewed by: imp
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D51728
Note that some of the functions for handling iSCSI login, discovery,
and kernel handoff are now functions of this class as they are logical
operations on an iSCSI connection and need access to various members
of this class.
This also fixes some memory leaks as ctld_connection wasn't properly
torn down once a connection finishes. These leaks were harmless in
practice since the ctld process exits after handling each connection.
Sponsored by: Chelsio Communications
Pull Request: https://github.com/freebsd/freebsd-src/pull/1794
Use C++ STL containers (std::string, std::list) for the data structure
holding the parsed output of the XML configuration obtained from the
kernel. This simplifies the code in various places and removes the
need for manual memory freeing (which was incomplete).
Use a std::list of pairs of std::string objects for the port and LUN
attribute lists instead of an nvlist.
Use a std::vector<char> for the resizable buffer receiving XML results
via ioctl(). Also, reuse the buffer from CTL_LUN_LIST for
CTL_PORT_LIST rather than doing a free() only to turn around and
malloc() again. While here, split out the code for fetching and
parsing the XML into a separate function.
Sponsored by: Chelsio Communications
Pull Request: https://github.com/freebsd/freebsd-src/pull/1794
- Various functions to add or lookup configuration objects are now
methods of the conf class.
- Use std::string and freebsd::pidfile for various members.
- Rename the global set_timeout() to start_timer() to avoid shadowing
conf::set_timeout() and also split out a separate stop_timer().
Sponsored by: Chelsio Communications
Pull Request: https://github.com/freebsd/freebsd-src/pull/1794
- Use std::string for string members.
- Use std::array for the array of LUN pointers indexed by LUN id.
- Move meat of the target_* functions from conf.cc into class methods.
Sponsored by: Chelsio Communications
Pull Request: https://github.com/freebsd/freebsd-src/pull/1794
- Use std::string and freebsd::nvlist_up for class members.
- Turn most lun_* and kernel_lun_* functions into class methods.
Sponsored by: Chelsio Communications
Pull Request: https://github.com/freebsd/freebsd-src/pull/1794
- Use std::string and freebsd::addrinfo_up for members.
- Add methods to open a connection and to send a request and parse
its response.
- Refactor existing isns_do_* functions to just construct requests
from a configuration.
Sponsored by: Chelsio Communications
Pull Request: https://github.com/freebsd/freebsd-src/pull/1794
- Use std::string, freebsd_nvlist_up to manage life cycle of class
members.
- Use an unordered_map<> keyed by std::string in struct conf to
replace the previous TAILQ.
- Replace PG_FILTER_* macros with a scoped enum.
- Provide a variety of accessors as portal groups are widely used
while keeping members private.
- The logic to "move" sockets from existing portals to new portals
when parsing new configuration is now split into several operations
across the conf and portal_group classes to preserve some semblance
of data hiding.
Sponsored by: Chelsio Communications
Pull Request: https://github.com/freebsd/freebsd-src/pull/1794
The existing C struct port was used to describe three types of ports:
iSCSI ports associated with a portal_group, ioctl ports, and
"physical" ports associated with a kernel device. This change chooses
to split these out into separate sub-classes of an abstract port base
class. Virtual methods are used in a few places such as sending the
class-specific CTL ioctls for creating and removing CTL kernel ports.
For ownership purposes, a struct conf instance "owns" each port via a
std::unique_ptr<> in a std::unordered_map<> indexed by name. Other
objects such as targets and portal_groups can also contain collections
of ports (targets hold a std::list of pointers, portal groups hold a
std::unordered_map<> indexed by target names). One
not-so-straightforward case is that if a new port fails to register,
it is removed from the configuration. In that case, these other
references also have to be removed explicitly.
Sponsored by: Chelsio Communications
Pull Request: https://github.com/freebsd/freebsd-src/pull/1794
- Use an unordered_map<> indexed by std::string to replace the TAILQ
of pport objects in struct kports since pport objects are looked up
name. Use a few wrapper methods around the unordered_map<> to
simplify consumers.
- Don't store a list of port pointers in pport. Only a single port is
ever associated (previously the code failed with an error if the
TAILQ wasn't empty when adding a port), so just store a pointer to a
single port and replace the empty TAILQ test with checking if the
pointer is null.
- Use std::string for the pport name.
- Add accessors (and a setter) for members of pport so that all the
fields can be private.
Sponsored by: Chelsio Communications
Pull Request: https://github.com/freebsd/freebsd-src/pull/1794
- Convert portal_init_socket and portal_reuse_socket into class methods.
Move the logic to handle proxy portal setup into the init_socket method
so that some fields can remain private.
- Add accessors for a few other members (most are const) so that all the
fields can be private.
- Use std::string, freebsd::addrinfo_up, and freebsd::fd_up classes to
manage fields owned exclusively.
- Add a vector of proxy portal pointers to struct conf and use the index
into the vector as the portal ID. This replaces an O(n^2) loop to
find the portal for a portal ID returned by kernel_accept with a direct
lookup.
Sponsored by: Chelsio Communications
Pull Request: https://github.com/freebsd/freebsd-src/pull/1794
Use a std::vector<> of chars to hold the iSNS packet. Convert the
various isns_req_* functions to be class methods instead.
Sponsored by: Chelsio Communications
Pull Request: https://github.com/freebsd/freebsd-src/pull/1794
Make data members private and convert functions for adding and
checking user and initiator authentication into class methods.
Use std::string to store the label for an auth_group and add a label()
method to retrieve a const C string version for logging.
Replace AG_TYPE_* macros with a scoped enum.
Replace the TAILQ of auth_group objects in struct conf with an
unordered_map<> of named auth_group objects. Anonymous auth_group
objects for targets are no longer stored in a global data structure.
Since a target can have a pointer to either named or anonymous
objects, use a shared_ptr<> to store references to auth_group objects.
Use the shared_ptr<>'s reference count to determine if a named
auth_group is unused in conf_verify() instead of walking all the
linked lists to check for references.
While here, avoid making a second copy of socket address for a client
and instead just store a pointer in ctld_connection.
Sponsored by: Chelsio Communications
Pull Request: https://github.com/freebsd/freebsd-src/pull/1794
Pull logic to parse a portal address string into a sockaddr and mask
into a parse() method. Reimplement the logic using operations on C++
std::string's instead of C string parsing.
Pull logic from inside the loop in auth_portal_find() to compare a
candidate socket address against a portal into a matches() method.
Use a std::list of auth_portal objects instead of a TAILQ in struct
auth_group.
Sponsored by: Chelsio Communications
Pull Request: https://github.com/freebsd/freebsd-src/pull/1794
Retire the struct auth_name type entirely and change the ag_names
member of struct auth_group to be an unordered_set<> of std::string
objects.
Sponsored by: Chelsio Communications
Pull Request: https://github.com/freebsd/freebsd-src/pull/1794
Use private std::string to hold secret and mutual authentication strings
along with accessors to retrieve constant C versions of those strings.
Add a helper function to determine if an auth object contains mutual
credentials.
Instead of storing the user name in the structure, use an
unordered_map<> with the username as the key for the ag_auths member
of auth_group. Add a parse error if multiple credentials specify the
same user. Previously the code always used the first credential when
verifying and ignored additional credentials silently.
Sponsored by: Chelsio Communications
Pull Request: https://github.com/freebsd/freebsd-src/pull/1794
In particular, this permits using ranged-for loops to iterate over
keys in an object which is more readable.
Sponsored by: Chelsio Communications
Pull Request: https://github.com/freebsd/freebsd-src/pull/1794
Split parse_conf in half keeping yyparse_conf as C-only function in
parse.y. parse_conf uses freebsd::FILE_up to ensure that the config
file is always closed.
Both parse_conf and uclparse_conf catch any exceptions thrown during
parsing. This is in preparation for using C++ objects allocated with
new for various data structures.
Note that this treats memory allocation failures from new as parsing
errors rather than ctld exiting entirely as it currently does if
malloc or calloc fail.
Sponsored by: Chelsio Communications
Pull Request: https://github.com/freebsd/freebsd-src/pull/1794
Subsequent commits will use C++ in these headers rather than only C.
conf.h remains as a C-only header since it is intended for use by the
C code generated from parse.y.
Sponsored by: Chelsio Communications
Pull Request: https://github.com/freebsd/freebsd-src/pull/1794
It is unclear whether this function was originally intended to support
negative numbers. The original implementation used signed integers,
but actually giving it a negative number as input would have invoked
undefined behavior, and the comments (since removed) only mentioned
positive numbers. Fifteen years ago, I “fixed” this by changing the
type from signed to unsigned. However, it would still have accepted
an input with a leading minus sign (though it would have returned its
absolute value). Fifteen years on, change the type back to signed and
fix the logic so it correctly handles both positive and negative
numbers without invoking undefined behavior. This makes it a better
match for humanize_number(3), which it is supposed to complement.
Fixes: bbb2703b4f
Reviewed by: jhb
Differential Revision: https://reviews.freebsd.org/D51542
This leaves the iscsi package for the iSCSI initiator, and the new
package provides the CAM target layer (including the iSCSI target).
Reviewed by: manu, des, jhb
Approved by: des (mentor)
Differential Revision: https://reviews.freebsd.org/D50287
While here, make use of cnvlist_* to simplify this code.
Fixes: d42a73fb6a ("ctld: Add a dedicated API between parse.y and the rest of the program")
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D49650
Portal discovery auth groups are always named auth groups
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D49649
If the / separator in a portal string is the last character in the
string, treat the portal as invalid.
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D49648
If an address starts with a [ character, require that it ends with a ]
character. Also, if an address starts with a [ character, assume it
is an IPv6 address.
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D49647
This code is incomplete (it does not handle some of the options that
can be set) and easily rots since it is not enabled by default or
hooked up to anything that calls it.
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D49646
libucl treats strings starting with "0x" as an integer if they do
not contain invalid characters. The code also looks broken as it
only calls strtol if the string exactly matches "0x" without any
trailing characters.
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D49644
This holds the abstract name of an auth-group for use in warning
messages. For anonymous groups associated with a target, the label
includes the target name.
Abstracting this out removes a lot of code duplication of
nearly-identical warning messages.
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D49643
Only check a single secret length in the function and call it twice
for the CHAP-MUTUAL case.
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D49642
When I switched new_pports_from_conf to return bool instead of an
inverted int, I missed updating the call after reloading the config
file due to SIGHUP.
Fixes: 450a84c292 ("ctld: Some bool-related cleanups")
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D49641
GCC raises shadow warnings in C++ when a global function shadows a
structure type name (since it shadows the constructors for that type).
System headers are full of such cases (and some such as struct sigaction
vs sigaction() are mandated by POSIX), so just disable the warning.
For example:
In file included from usr.sbin/ctld/ctld.cc:33:
sys/sys/event.h:366:20: error: 'int kqueue()' hides constructor for 'struct kqueue' [-Werror=shadow]
366 | int kqueue(void);
| ^
sys/sys/event.h:371:43: error: 'int kevent(int, const kevent*, int, kevent*, int, const timespec*)' hides constructor for 'struct kevent' [-Werror=shadow]
371 | const struct timespec *timeout);
| ^
In file included from usr.sbin/ctld/ctld.cc:37:
sys/sys/stat.h:396:63: error: 'int stat(const char*, stat*)' hides constructor for 'struct stat' [-Werror=shadow]
396 | int stat(const char * __restrict, struct stat * __restrict);
| ^
Reported by: bz
This is the minimal set of changes need to compile as C++ so git can
handle the rename correctly.
Reviewed by: asomers
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D49139
Allow the LUN number to be specified as the key for a LUN instead
of requiring it as a "number" field. If a key is used, permit
a simple string value to be used for non-anymous LUNs. This permits
replacing:
lun = [
{ number = 0, name = zvol_lun },
{
number = 1
backend = ramdisk
size = 1GB
}
]
with:
lun = {
0 = zvol_lun
1 {
backend = ramdisk
size = 1GB
}
}
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D48939
In the case that a separate auth-group is not required, this permits
replacing:
portal-group = { name = pg0 }
with:
portal-group = pg0
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D48938
If a target LUN entry doesn't have a name property, assume it is an
anonymous LUN and parse other properties from the entry to define the
LUN.
This removes the odd support for target LUNs only named by an integer.
My guess is this was meant to implement support for anonymous LUNs
based on how the syntax for this works in the non-UCL case, but the
prior implementation was useless (it just created unconfigured LUNs).
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D48937
- Support for "foreign", "offload", and "tag" properties in portal
group contexts.
- Support for "ctl-lun" and "device-type" properties in LUN contexts.
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D48936
The auth-group context required an array of entries for "chap",
"chap-mutual", "initiator-name", and "initiator-portal" whereas the
target context required exactly one entry (and only permitted a single
entry).
Allow either a single entry or an array of entries for these keywords
in both the auth-group and target contexts.
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D48935