1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2012 The FreeBSD Foundation 5 * 6 * This software was developed by Edward Tomasz Napierala under sponsorship 7 * from the FreeBSD Foundation. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #ifndef __CTLD_HH__ 32 #define __CTLD_HH__ 33 34 #include <sys/_nv.h> 35 #include <sys/queue.h> 36 #ifdef ICL_KERNEL_PROXY 37 #include <sys/types.h> 38 #endif 39 #include <sys/socket.h> 40 #include <stdbool.h> 41 #include <libiscsiutil.h> 42 #include <libutil.h> 43 44 #include <array> 45 #include <list> 46 #include <memory> 47 #include <string> 48 #include <string_view> 49 #include <unordered_map> 50 #include <unordered_set> 51 #include <libutil++.hh> 52 53 #define DEFAULT_CONFIG_PATH "/etc/ctl.conf" 54 #define DEFAULT_PIDFILE "/var/run/ctld.pid" 55 #define DEFAULT_BLOCKSIZE 512 56 #define DEFAULT_CD_BLOCKSIZE 2048 57 58 #define MAX_LUNS 1024 59 60 struct isns_req; 61 struct port; 62 63 struct auth { authauth64 auth(std::string_view secret) : a_secret(secret) {} authauth65 auth(std::string_view secret, std::string_view mutual_user, 66 std::string_view mutual_secret) : 67 a_secret(secret), a_mutual_user(mutual_user), 68 a_mutual_secret(mutual_secret) {} 69 mutualauth70 bool mutual() const { return !a_mutual_user.empty(); } 71 secretauth72 const char *secret() const { return a_secret.c_str(); } mutual_userauth73 const char *mutual_user() const { return a_mutual_user.c_str(); } mutual_secretauth74 const char *mutual_secret() const { return a_mutual_secret.c_str(); } 75 76 private: 77 std::string a_secret; 78 std::string a_mutual_user; 79 std::string a_mutual_secret; 80 }; 81 82 struct auth_portal { 83 bool matches(const struct sockaddr *sa) const; 84 bool parse(const char *portal); 85 86 private: 87 struct sockaddr_storage ap_sa; 88 int ap_mask = 0; 89 }; 90 91 enum class auth_type { 92 UNKNOWN, 93 DENY, 94 NO_AUTHENTICATION, 95 CHAP, 96 CHAP_MUTUAL 97 }; 98 99 struct auth_group { auth_groupauth_group100 auth_group(std::string label) : ag_label(label) {} 101 typeauth_group102 auth_type type() const { return ag_type; } 103 bool set_type(const char *str); 104 void set_type(auth_type type); 105 labelauth_group106 const char *label() const { return ag_label.c_str(); } 107 108 bool add_chap(const char *user, const char *secret); 109 bool add_chap_mutual(const char *user, const char *secret, 110 const char *user2, const char *secret2); 111 const struct auth *find_auth(std::string_view user) const; 112 113 bool add_host_nqn(std::string_view nqn); 114 bool host_permitted(std::string_view nqn) const; 115 116 bool add_host_address(const char *address); 117 bool host_permitted(const struct sockaddr *sa) const; 118 119 bool add_initiator_name(std::string_view initiator_name); 120 bool initiator_permitted(std::string_view initiator_name) const; 121 122 bool add_initiator_portal(const char *initiator_portal); 123 bool initiator_permitted(const struct sockaddr *sa) const; 124 125 private: 126 void check_secret_length(const char *user, const char *secret, 127 const char *secret_type); 128 129 std::string ag_label; 130 auth_type ag_type = auth_type::UNKNOWN; 131 std::unordered_map<std::string, auth> ag_auths; 132 std::unordered_set<std::string> ag_host_names; 133 std::list<auth_portal> ag_host_addresses; 134 std::unordered_set<std::string> ag_initiator_names; 135 std::list<auth_portal> ag_initiator_portals; 136 }; 137 138 using auth_group_sp = std::shared_ptr<auth_group>; 139 140 enum class portal_protocol { 141 ISCSI, 142 ISER, 143 NVME_TCP, 144 NVME_DISCOVERY_TCP, 145 }; 146 147 struct portal { portalportal148 portal(struct portal_group *pg, std::string_view listen, 149 portal_protocol protocol, freebsd::addrinfo_up ai) : 150 p_portal_group(pg), p_listen(listen), p_ai(std::move(ai)), 151 p_protocol(protocol) {} 152 virtual ~portal() = default; 153 prepareportal154 virtual bool prepare() { return true; } 155 bool reuse_socket(portal &oldp); 156 bool init_socket(); init_socket_optionsportal157 virtual bool init_socket_options(int s __unused) { return true; } 158 virtual void handle_connection(freebsd::fd_up fd, const char *host, 159 const struct sockaddr *client_sa) = 0; 160 portal_groupportal161 struct portal_group *portal_group() const { return p_portal_group; } listenportal162 const char *listen() const { return p_listen.c_str(); } aiportal163 const addrinfo *ai() const { return p_ai.get(); } protocolportal164 portal_protocol protocol() const { return p_protocol; } socketportal165 int socket() const { return p_socket; } closeportal166 void close() { p_socket.reset(); } 167 168 private: 169 struct portal_group *p_portal_group; 170 std::string p_listen; 171 freebsd::addrinfo_up p_ai; 172 portal_protocol p_protocol; 173 174 freebsd::fd_up p_socket; 175 }; 176 177 using portal_up = std::unique_ptr<portal>; 178 using port_up = std::unique_ptr<port>; 179 180 enum class discovery_filter { 181 UNKNOWN, 182 NONE, 183 PORTAL, 184 PORTAL_NAME, 185 PORTAL_NAME_AUTH 186 }; 187 188 struct portal_group { 189 portal_group(struct conf *conf, std::string_view name); 190 virtual ~portal_group() = default; 191 confportal_group192 struct conf *conf() const { return pg_conf; } 193 virtual const char *keyword() const = 0; nameportal_group194 const char *name() const { return pg_name.c_str(); } assignedportal_group195 bool assigned() const { return pg_assigned; } 196 bool is_dummy() const; is_redirectingportal_group197 bool is_redirecting() const { return !pg_redirection.empty(); } discovery_auth_groupportal_group198 struct auth_group *discovery_auth_group() const 199 { return pg_discovery_auth_group.get(); } discovery_filterportal_group200 enum discovery_filter discovery_filter() const 201 { return pg_discovery_filter; } dscpportal_group202 int dscp() const { return pg_dscp; } offloadportal_group203 const char *offload() const { return pg_offload.c_str(); } redirectionportal_group204 const char *redirection() const { return pg_redirection.c_str(); } pcpportal_group205 int pcp() const { return pg_pcp; } tagportal_group206 uint16_t tag() const { return pg_tag; } 207 208 freebsd::nvlist_up options() const; 209 portalsportal_group210 const std::list<portal_up> &portals() const { return pg_portals; } portsportal_group211 const std::unordered_map<std::string, port *> &ports() const 212 { return pg_ports; } 213 214 virtual void allocate_tag() = 0; 215 virtual bool add_portal(const char *value, 216 portal_protocol protocol) = 0; 217 virtual void add_default_portals() = 0; 218 bool add_option(const char *name, const char *value); 219 bool set_discovery_auth_group(const char *name); 220 bool set_dscp(u_int dscp); 221 virtual bool set_filter(const char *str) = 0; 222 void set_foreign(); 223 bool set_offload(const char *offload); 224 bool set_pcp(u_int pcp); 225 bool set_redirection(const char *addr); 226 void set_tag(uint16_t tag); 227 228 virtual port_up create_port(struct target *target, auth_group_sp ag) = 229 0; 230 virtual port_up create_port(struct target *target, uint32_t ctl_port) = 231 0; 232 233 void add_port(struct portal_group_port *port); 234 const struct port *find_port(std::string_view target) const; 235 void remove_port(struct portal_group_port *port); 236 void verify(struct conf *conf); 237 238 bool reuse_socket(struct portal &newp); 239 int open_sockets(struct conf &oldconf); 240 void close_sockets(); 241 242 protected: 243 struct conf *pg_conf; 244 freebsd::nvlist_up pg_options; 245 const char *pg_keyword; 246 std::string pg_name; 247 auth_group_sp pg_discovery_auth_group; 248 enum discovery_filter pg_discovery_filter = 249 discovery_filter::UNKNOWN; 250 bool pg_foreign = false; 251 bool pg_assigned = false; 252 std::list<portal_up> pg_portals; 253 std::unordered_map<std::string, port *> pg_ports; 254 std::string pg_offload; 255 std::string pg_redirection; 256 int pg_dscp = -1; 257 int pg_pcp = -1; 258 259 uint16_t pg_tag = 0; 260 }; 261 262 using portal_group_up = std::unique_ptr<portal_group>; 263 264 struct port { 265 port(struct target *target); 266 virtual ~port() = default; 267 targetport268 struct target *target() const { return p_target; } auth_groupport269 virtual struct auth_group *auth_group() const { return nullptr; } portal_groupport270 virtual struct portal_group *portal_group() const { return nullptr; } 271 is_dummyport272 virtual bool is_dummy() const { return true; } 273 274 virtual void clear_references(); 275 276 bool kernel_add(); 277 bool kernel_update(const port *oport); 278 bool kernel_remove(); 279 280 virtual bool kernel_create_port() = 0; 281 virtual bool kernel_remove_port() = 0; 282 283 protected: 284 struct target *p_target; 285 286 uint32_t p_ctl_port = 0; 287 }; 288 289 struct portal_group_port : public port { 290 portal_group_port(struct target *target, struct portal_group *pg, 291 auth_group_sp ag); 292 portal_group_port(struct target *target, struct portal_group *pg, 293 uint32_t ctl_port); 294 ~portal_group_port() override = default; 295 auth_groupportal_group_port296 struct auth_group *auth_group() const override 297 { return p_auth_group.get(); } portal_groupportal_group_port298 struct portal_group *portal_group() const override 299 { return p_portal_group; } 300 301 bool is_dummy() const override; 302 303 void clear_references() override; 304 305 protected: 306 auth_group_sp p_auth_group; 307 struct portal_group *p_portal_group; 308 }; 309 310 struct ioctl_port final : public port { ioctl_portioctl_port311 ioctl_port(struct target *target, int pp, int vp) : 312 port(target), p_ioctl_pp(pp), p_ioctl_vp(vp) {} 313 ~ioctl_port() override = default; 314 315 bool kernel_create_port() override; 316 bool kernel_remove_port() override; 317 318 private: 319 int p_ioctl_pp; 320 int p_ioctl_vp; 321 }; 322 323 struct kernel_port final : public port { kernel_portkernel_port324 kernel_port(struct target *target, struct pport *pp) : 325 port(target), p_pport(pp) {} 326 ~kernel_port() override = default; 327 328 bool kernel_create_port() override; 329 bool kernel_remove_port() override; 330 331 private: 332 struct pport *p_pport; 333 }; 334 335 struct lun { 336 lun(struct conf *conf, std::string_view name); 337 namelun338 const char *name() const { return l_name.c_str(); } pathlun339 const std::string &path() const { return l_path; } ctl_lunlun340 int ctl_lun() const { return l_ctl_lun; } 341 342 freebsd::nvlist_up options() const; 343 344 bool add_option(const char *name, const char *value); 345 bool set_backend(std::string_view value); 346 bool set_blocksize(size_t value); 347 bool set_ctl_lun(uint32_t value); 348 bool set_device_type(uint8_t device_type); 349 bool set_device_type(const char *value); 350 bool set_device_id(std::string_view value); 351 bool set_path(std::string_view value); 352 void set_scsiname(std::string_view value); 353 bool set_serial(std::string_view value); 354 bool set_size(uint64_t value); 355 356 bool changed(const struct lun &old) const; 357 bool verify(); 358 359 bool kernel_add(); 360 bool kernel_modify() const; 361 bool kernel_remove() const; 362 363 private: 364 struct conf *l_conf; 365 freebsd::nvlist_up l_options; 366 std::string l_name; 367 std::string l_backend; 368 uint8_t l_device_type = 0; 369 int l_blocksize = 0; 370 std::string l_device_id; 371 std::string l_path; 372 std::string l_scsiname; 373 std::string l_serial; 374 uint64_t l_size = 0; 375 376 int l_ctl_lun = -1; 377 }; 378 379 struct target { 380 target(struct conf *conf, const char *keyword, std::string_view name); 381 virtual ~target() = default; 382 has_aliastarget383 bool has_alias() const { return !t_alias.empty(); } has_pporttarget384 bool has_pport() const { return !t_pport.empty(); } has_redirectiontarget385 bool has_redirection() const { return !t_redirection.empty(); } aliastarget386 const char *alias() const { return t_alias.c_str(); } nametarget387 const char *name() const { return t_name.c_str(); } labeltarget388 const char *label() const { return t_label.c_str(); } pporttarget389 const char *pport() const { return t_pport.c_str(); } private_authtarget390 bool private_auth() const { return t_private_auth; } redirectiontarget391 const char *redirection() const { return t_redirection.c_str(); } 392 auth_grouptarget393 struct auth_group *auth_group() const { return t_auth_group.get(); } portstarget394 const std::list<port *> &ports() const { return t_ports; } luntarget395 const struct lun *lun(int idx) const { return t_luns[idx]; } 396 397 bool add_chap(const char *user, const char *secret); 398 bool add_chap_mutual(const char *user, const char *secret, 399 const char *user2, const char *secret2); add_host_addresstarget400 virtual bool add_host_address(const char *) { return false; } add_host_nqntarget401 virtual bool add_host_nqn(std::string_view) { return false; } add_initiator_nametarget402 virtual bool add_initiator_name(std::string_view) { return false; } add_initiator_portaltarget403 virtual bool add_initiator_portal(const char *) { return false; } add_luntarget404 virtual bool add_lun(u_int, const char *) { return false; } add_namespacetarget405 virtual bool add_namespace(u_int, const char *) { return false; } 406 virtual bool add_portal_group(const char *pg_name, 407 const char *ag_name) = 0; 408 bool set_alias(std::string_view alias); 409 bool set_auth_group(const char *ag_name); 410 bool set_auth_type(const char *type); 411 bool set_physical_port(std::string_view pport); 412 bool set_redirection(const char *addr); start_luntarget413 virtual struct lun *start_lun(u_int) { return nullptr; } start_namespacetarget414 virtual struct lun *start_namespace(u_int) { return nullptr; } 415 416 void add_port(struct port *port); 417 void remove_lun(struct lun *lun); 418 void remove_port(struct port *port); 419 void verify(); 420 421 protected: 422 bool use_private_auth(const char *keyword); 423 bool add_lun(u_int id, const char *lun_label, const char *lun_name); 424 struct lun *start_lun(u_int id, const char *lun_label, 425 const char *lun_name); 426 virtual struct portal_group *default_portal_group() = 0; 427 428 struct conf *t_conf; 429 std::array<struct lun *, MAX_LUNS> t_luns = {}; 430 auth_group_sp t_auth_group; 431 std::list<port *> t_ports; 432 std::string t_name; 433 std::string t_label; 434 std::string t_alias; 435 std::string t_redirection; 436 /* Name of this target's physical port, if any, i.e. "isp0" */ 437 std::string t_pport; 438 bool t_private_auth = false; 439 }; 440 441 using target_up = std::unique_ptr<target>; 442 443 struct isns { isnsisns444 isns(std::string_view addr, freebsd::addrinfo_up ai) : 445 i_addr(addr), i_ai(std::move(ai)) {} 446 addrisns447 const char *addr() const { return i_addr.c_str(); } 448 449 freebsd::fd_up connect(); 450 bool send_request(int s, struct isns_req req); 451 452 private: 453 std::string i_addr; 454 freebsd::addrinfo_up i_ai; 455 }; 456 457 struct conf { 458 conf(); 459 maxprocconf460 int maxproc() const { return conf_maxproc; } timeoutconf461 int timeout() const { return conf_timeout; } genctrconf462 uint32_t genctr() const { return conf_genctr; } 463 default_auth_group_definedconf464 bool default_auth_group_defined() const 465 { return conf_default_ag_defined; } default_portal_group_definedconf466 bool default_portal_group_defined() const 467 { return conf_default_pg_defined; } default_transport_group_definedconf468 bool default_transport_group_defined() const 469 { return conf_default_tg_defined; } 470 471 struct auth_group *add_auth_group(const char *ag_name); 472 struct auth_group *define_default_auth_group(); 473 auth_group_sp find_auth_group(std::string_view ag_name); 474 475 struct portal_group *add_portal_group(const char *name); 476 struct portal_group *define_default_portal_group(); 477 struct portal_group *find_portal_group(std::string_view name); 478 479 struct portal_group *add_transport_group(const char *name); 480 struct portal_group *define_default_transport_group(); 481 struct portal_group *find_transport_group(std::string_view name); 482 483 bool add_port(struct target *target, struct portal_group *pg, 484 auth_group_sp ag); 485 bool add_port(struct target *target, struct portal_group *pg, 486 uint32_t ctl_port); 487 bool add_port(struct target *target, struct pport *pp); 488 bool add_port(struct kports &kports, struct target *target, int pp, 489 int vp); 490 bool add_pports(struct kports &kports); 491 492 struct target *add_controller(const char *name); 493 struct target *find_controller(std::string_view name); 494 495 struct target *add_target(const char *name); 496 struct target *find_target(std::string_view name); 497 498 struct lun *add_lun(const char *name); 499 struct lun *find_lun(std::string_view name); 500 501 void set_debug(int debug); 502 void set_isns_period(int period); 503 void set_isns_timeout(int timeout); 504 void set_maxproc(int maxproc); 505 bool set_pidfile_path(std::string_view path); 506 void set_timeout(int timeout); 507 508 void open_pidfile(); 509 void write_pidfile(); 510 void close_pidfile(); 511 512 bool add_isns(const char *addr); 513 void isns_register_targets(struct isns *isns, struct conf *oldconf); 514 void isns_deregister_targets(struct isns *isns); 515 void isns_schedule_update(); 516 void isns_update(); 517 518 int apply(struct conf *oldconf); 519 void delete_target_luns(struct lun *lun); 520 bool reuse_portal_group_socket(struct portal &newp); 521 bool verify(); 522 523 private: 524 struct isns_req isns_register_request(const char *hostname); 525 struct isns_req isns_check_request(const char *hostname); 526 struct isns_req isns_deregister_request(const char *hostname); 527 void isns_check(struct isns *isns); 528 529 std::string conf_pidfile_path; 530 std::unordered_map<std::string, std::unique_ptr<lun>> conf_luns; 531 std::unordered_map<std::string, target_up> conf_targets; 532 std::unordered_map<std::string, target_up> conf_controllers; 533 std::unordered_map<std::string, auth_group_sp> conf_auth_groups; 534 std::unordered_map<std::string, std::unique_ptr<port>> conf_ports; 535 std::unordered_map<std::string, portal_group_up> conf_portal_groups; 536 std::unordered_map<std::string, portal_group_up> conf_transport_groups; 537 std::unordered_map<std::string, isns> conf_isns; 538 struct target *conf_first_target = nullptr; 539 int conf_isns_period = 900; 540 int conf_isns_timeout = 5; 541 int conf_debug = 0; 542 int conf_timeout = 60; 543 int conf_maxproc = 30; 544 uint32_t conf_genctr = 0; 545 546 freebsd::pidfile conf_pidfile; 547 548 bool conf_default_pg_defined = false; 549 bool conf_default_tg_defined = false; 550 bool conf_default_ag_defined = false; 551 552 static uint32_t global_genctr; 553 554 #ifdef ICL_KERNEL_PROXY 555 public: 556 int add_proxy_portal(portal *); 557 portal *proxy_portal(int); 558 private: 559 std::vector<portal *> conf_proxy_portals; 560 #endif 561 }; 562 563 using conf_up = std::unique_ptr<conf>; 564 565 /* Physical ports exposed by the kernel */ 566 struct pport { pportpport567 pport(std::string_view name, uint32_t ctl_port) : pp_name(name), 568 pp_ctl_port(ctl_port) {} 569 namepport570 const char *name() const { return pp_name.c_str(); } ctl_portpport571 uint32_t ctl_port() const { return pp_ctl_port; } 572 linkedpport573 bool linked() const { return pp_linked; } linkpport574 void link() { pp_linked = true; } 575 576 private: 577 std::string pp_name; 578 uint32_t pp_ctl_port; 579 bool pp_linked = false; 580 }; 581 582 struct kports { 583 bool add_port(std::string &name, uint32_t ctl_port); 584 bool has_port(std::string_view name); 585 struct pport *find_port(std::string_view name); 586 587 private: 588 std::unordered_map<std::string, struct pport> pports; 589 }; 590 591 extern bool proxy_mode; 592 extern int ctl_fd; 593 594 bool parse_conf(const char *path); 595 bool uclparse_conf(const char *path); 596 597 conf_up conf_new_from_kernel(struct kports &kports); 598 void conf_finish(void); 599 void conf_start(struct conf *new_conf); 600 601 bool option_new(nvlist_t *nvl, 602 const char *name, const char *value); 603 604 freebsd::addrinfo_up parse_addr_port(const char *address, 605 const char *def_port); 606 607 void kernel_init(void); 608 void kernel_capsicate(void); 609 610 #ifdef ICL_KERNEL_PROXY 611 void kernel_listen(struct addrinfo *ai, bool iser, 612 int portal_id); 613 void kernel_accept(int *connection_id, int *portal_id, 614 struct sockaddr *client_sa, 615 socklen_t *client_salen); 616 void kernel_send(struct pdu *pdu); 617 void kernel_receive(struct pdu *pdu); 618 #endif 619 620 bool ctl_create_port(const char *driver, 621 const nvlist_t *nvl, uint32_t *ctl_port); 622 bool ctl_remove_port(const char *driver, nvlist_t *nvl); 623 624 portal_group_up iscsi_make_portal_group(struct conf *conf, 625 std::string_view name); 626 target_up iscsi_make_target(struct conf *conf, 627 std::string_view name); 628 629 portal_group_up nvmf_make_transport_group(struct conf *conf, 630 std::string_view name); 631 target_up nvmf_make_controller(struct conf *conf, 632 std::string_view name); 633 634 void start_timer(int timeout, bool fatal = false); 635 void stop_timer(); 636 bool timed_out(); 637 638 #endif /* !__CTLD_HH__ */ 639