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 #define SOCKBUF_SIZE 1048576 60 61 struct isns_req; 62 struct port; 63 64 struct auth { authauth65 auth(std::string_view secret) : a_secret(secret) {} authauth66 auth(std::string_view secret, std::string_view mutual_user, 67 std::string_view mutual_secret) : 68 a_secret(secret), a_mutual_user(mutual_user), 69 a_mutual_secret(mutual_secret) {} 70 mutualauth71 bool mutual() const { return !a_mutual_user.empty(); } 72 secretauth73 const char *secret() const { return a_secret.c_str(); } mutual_userauth74 const char *mutual_user() const { return a_mutual_user.c_str(); } mutual_secretauth75 const char *mutual_secret() const { return a_mutual_secret.c_str(); } 76 77 private: 78 std::string a_secret; 79 std::string a_mutual_user; 80 std::string a_mutual_secret; 81 }; 82 83 struct auth_portal { 84 bool matches(const struct sockaddr *sa) const; 85 bool parse(const char *portal); 86 87 private: 88 struct sockaddr_storage ap_sa; 89 int ap_mask = 0; 90 }; 91 92 enum class auth_type { 93 UNKNOWN, 94 DENY, 95 NO_AUTHENTICATION, 96 CHAP, 97 CHAP_MUTUAL 98 }; 99 100 struct auth_group { auth_groupauth_group101 auth_group(std::string label) : ag_label(label) {} 102 typeauth_group103 auth_type type() const { return ag_type; } 104 bool set_type(const char *str); 105 void set_type(auth_type type); 106 labelauth_group107 const char *label() const { return ag_label.c_str(); } 108 109 bool add_chap(const char *user, const char *secret); 110 bool add_chap_mutual(const char *user, const char *secret, 111 const char *user2, const char *secret2); 112 const struct auth *find_auth(std::string_view user) const; 113 114 bool add_initiator_name(std::string_view initiator_name); 115 bool initiator_permitted(std::string_view initiator_name) const; 116 117 bool add_initiator_portal(const char *initiator_portal); 118 bool initiator_permitted(const struct sockaddr *sa) const; 119 120 private: 121 void check_secret_length(const char *user, const char *secret, 122 const char *secret_type); 123 124 std::string ag_label; 125 auth_type ag_type = auth_type::UNKNOWN; 126 std::unordered_map<std::string, auth> ag_auths; 127 std::unordered_set<std::string> ag_names; 128 std::list<auth_portal> ag_portals; 129 }; 130 131 using auth_group_sp = std::shared_ptr<auth_group>; 132 133 struct portal { portalportal134 portal(struct portal_group *pg, std::string_view listen, bool iser, 135 freebsd::addrinfo_up ai) : 136 p_portal_group(pg), p_listen(listen), p_ai(std::move(ai)), 137 p_iser(iser) {} 138 139 bool reuse_socket(portal &oldp); 140 bool init_socket(); 141 portal_groupportal142 portal_group *portal_group() { return p_portal_group; } listenportal143 const char *listen() const { return p_listen.c_str(); } aiportal144 const addrinfo *ai() const { return p_ai.get(); } socketportal145 int socket() const { return p_socket; } closeportal146 void close() { p_socket.reset(); } 147 148 private: 149 struct portal_group *p_portal_group; 150 std::string p_listen; 151 freebsd::addrinfo_up p_ai; 152 bool p_iser; 153 154 freebsd::fd_up p_socket; 155 }; 156 157 using portal_up = std::unique_ptr<portal>; 158 159 enum class discovery_filter { 160 UNKNOWN, 161 NONE, 162 PORTAL, 163 PORTAL_NAME, 164 PORTAL_NAME_AUTH 165 }; 166 167 struct portal_group { 168 portal_group(struct conf *conf, std::string_view name); 169 confportal_group170 struct conf *conf() const { return pg_conf; } nameportal_group171 const char *name() const { return pg_name.c_str(); } assignedportal_group172 bool assigned() const { return pg_assigned; } 173 bool is_dummy() const; is_redirectingportal_group174 bool is_redirecting() const { return !pg_redirection.empty(); } discovery_auth_groupportal_group175 struct auth_group *discovery_auth_group() const 176 { return pg_discovery_auth_group.get(); } discovery_filterportal_group177 discovery_filter discovery_filter() const 178 { return pg_discovery_filter; } dscpportal_group179 int dscp() const { return pg_dscp; } offloadportal_group180 const char *offload() const { return pg_offload.c_str(); } redirectionportal_group181 const char *redirection() const { return pg_redirection.c_str(); } pcpportal_group182 int pcp() const { return pg_pcp; } tagportal_group183 uint16_t tag() const { return pg_tag; } 184 185 freebsd::nvlist_up options() const; 186 portalsportal_group187 const std::list<portal_up> &portals() const { return pg_portals; } portsportal_group188 const std::unordered_map<std::string, port *> &ports() const 189 { return pg_ports; } 190 191 bool add_portal(const char *value, bool iser); 192 bool add_option(const char *name, const char *value); 193 bool set_discovery_auth_group(const char *name); 194 bool set_dscp(u_int dscp); 195 bool set_filter(const char *str); 196 void set_foreign(); 197 bool set_offload(const char *offload); 198 bool set_pcp(u_int pcp); 199 bool set_redirection(const char *addr); 200 void set_tag(uint16_t tag); 201 202 void add_port(struct portal_group_port *port); 203 const struct port *find_port(std::string_view target) const; 204 void remove_port(struct portal_group_port *port); 205 void verify(struct conf *conf); 206 207 bool reuse_socket(struct portal &newp); 208 int open_sockets(struct conf &oldconf); 209 void close_sockets(); 210 211 private: 212 struct conf *pg_conf; 213 freebsd::nvlist_up pg_options; 214 std::string pg_name; 215 auth_group_sp pg_discovery_auth_group; 216 enum discovery_filter pg_discovery_filter = 217 discovery_filter::UNKNOWN; 218 bool pg_foreign = false; 219 bool pg_assigned = false; 220 std::list<portal_up> pg_portals; 221 std::unordered_map<std::string, port *> pg_ports; 222 std::string pg_offload; 223 std::string pg_redirection; 224 int pg_dscp = -1; 225 int pg_pcp = -1; 226 227 uint16_t pg_tag = 0; 228 }; 229 230 using portal_group_up = std::unique_ptr<portal_group>; 231 232 struct port { 233 port(struct target *target); 234 virtual ~port() = default; 235 targetport236 struct target *target() const { return p_target; } auth_groupport237 virtual struct auth_group *auth_group() const { return nullptr; } portal_groupport238 virtual struct portal_group *portal_group() const { return nullptr; } 239 is_dummyport240 virtual bool is_dummy() const { return true; } 241 242 virtual void clear_references(); 243 244 bool kernel_add(); 245 bool kernel_update(const port *oport); 246 bool kernel_remove(); 247 248 virtual bool kernel_create_port() = 0; 249 virtual bool kernel_remove_port() = 0; 250 251 protected: 252 struct target *p_target; 253 254 uint32_t p_ctl_port = 0; 255 }; 256 257 struct portal_group_port final : public port { 258 portal_group_port(struct target *target, struct portal_group *pg, 259 auth_group_sp ag); 260 portal_group_port(struct target *target, struct portal_group *pg, 261 uint32_t ctl_port); 262 ~portal_group_port() override = default; 263 auth_groupportal_group_port264 struct auth_group *auth_group() const override 265 { return p_auth_group.get(); } portal_groupportal_group_port266 struct portal_group *portal_group() const override 267 { return p_portal_group; } 268 269 bool is_dummy() const override; 270 271 void clear_references() override; 272 273 bool kernel_create_port() override; 274 bool kernel_remove_port() override; 275 276 private: 277 auth_group_sp p_auth_group; 278 struct portal_group *p_portal_group; 279 }; 280 281 struct ioctl_port final : public port { ioctl_portioctl_port282 ioctl_port(struct target *target, int pp, int vp) : 283 port(target), p_ioctl_pp(pp), p_ioctl_vp(vp) {} 284 ~ioctl_port() override = default; 285 286 bool kernel_create_port() override; 287 bool kernel_remove_port() override; 288 289 private: 290 int p_ioctl_pp; 291 int p_ioctl_vp; 292 }; 293 294 struct kernel_port final : public port { kernel_portkernel_port295 kernel_port(struct target *target, struct pport *pp) : 296 port(target), p_pport(pp) {} 297 ~kernel_port() override = default; 298 299 bool kernel_create_port() override; 300 bool kernel_remove_port() override; 301 302 private: 303 struct pport *p_pport; 304 }; 305 306 struct lun { 307 lun(struct conf *conf, std::string_view name); 308 namelun309 const char *name() const { return l_name.c_str(); } pathlun310 const std::string &path() const { return l_path; } ctl_lunlun311 int ctl_lun() const { return l_ctl_lun; } 312 313 freebsd::nvlist_up options() const; 314 315 bool add_option(const char *name, const char *value); 316 bool set_backend(std::string_view value); 317 bool set_blocksize(size_t value); 318 bool set_ctl_lun(uint32_t value); 319 bool set_device_type(uint8_t device_type); 320 bool set_device_type(const char *value); 321 bool set_device_id(std::string_view value); 322 bool set_path(std::string_view value); 323 void set_scsiname(std::string_view value); 324 bool set_serial(std::string_view value); 325 bool set_size(uint64_t value); 326 327 bool changed(const struct lun &old) const; 328 bool verify(); 329 330 bool kernel_add(); 331 bool kernel_modify() const; 332 bool kernel_remove() const; 333 334 private: 335 struct conf *l_conf; 336 freebsd::nvlist_up l_options; 337 std::string l_name; 338 std::string l_backend; 339 uint8_t l_device_type = 0; 340 int l_blocksize = 0; 341 std::string l_device_id; 342 std::string l_path; 343 std::string l_scsiname; 344 std::string l_serial; 345 uint64_t l_size = 0; 346 347 int l_ctl_lun = -1; 348 }; 349 350 struct target { targettarget351 target(struct conf *conf, std::string_view name) : 352 t_conf(conf), t_name(name) {} 353 has_aliastarget354 bool has_alias() const { return !t_alias.empty(); } has_pporttarget355 bool has_pport() const { return !t_pport.empty(); } has_redirectiontarget356 bool has_redirection() const { return !t_redirection.empty(); } aliastarget357 const char *alias() const { return t_alias.c_str(); } nametarget358 const char *name() const { return t_name.c_str(); } pporttarget359 const char *pport() const { return t_pport.c_str(); } private_authtarget360 bool private_auth() const { return t_private_auth; } redirectiontarget361 const char *redirection() const { return t_redirection.c_str(); } 362 auth_grouptarget363 struct auth_group *auth_group() const { return t_auth_group.get(); } portstarget364 const std::list<port *> &ports() const { return t_ports; } luntarget365 const struct lun *lun(int idx) const { return t_luns[idx]; } 366 367 bool add_chap(const char *user, const char *secret); 368 bool add_chap_mutual(const char *user, const char *secret, 369 const char *user2, const char *secret2); 370 bool add_initiator_name(std::string_view name); 371 bool add_initiator_portal(const char *addr); 372 bool add_lun(u_int id, const char *lun_name); 373 bool add_portal_group(const char *pg_name, const char *ag_name); 374 bool set_alias(std::string_view alias); 375 bool set_auth_group(const char *ag_name); 376 bool set_auth_type(const char *type); 377 bool set_physical_port(std::string_view pport); 378 bool set_redirection(const char *addr); 379 struct lun *start_lun(u_int id); 380 381 void add_port(struct port *port); 382 void remove_lun(struct lun *lun); 383 void remove_port(struct port *port); 384 void verify(); 385 386 private: 387 bool use_private_auth(const char *keyword); 388 389 struct conf *t_conf; 390 std::array<struct lun *, MAX_LUNS> t_luns; 391 auth_group_sp t_auth_group; 392 std::list<port *> t_ports; 393 std::string t_name; 394 std::string t_alias; 395 std::string t_redirection; 396 /* Name of this target's physical port, if any, i.e. "isp0" */ 397 std::string t_pport; 398 bool t_private_auth; 399 }; 400 401 struct isns { isnsisns402 isns(std::string_view addr, freebsd::addrinfo_up ai) : 403 i_addr(addr), i_ai(std::move(ai)) {} 404 addrisns405 const char *addr() const { return i_addr.c_str(); } 406 407 freebsd::fd_up connect(); 408 bool send_request(int s, struct isns_req req); 409 410 private: 411 std::string i_addr; 412 freebsd::addrinfo_up i_ai; 413 }; 414 415 struct conf { maxprocconf416 int maxproc() const { return conf_maxproc; } timeoutconf417 int timeout() const { return conf_timeout; } 418 default_auth_group_definedconf419 bool default_auth_group_defined() const 420 { return conf_default_ag_defined; } default_portal_group_definedconf421 bool default_portal_group_defined() const 422 { return conf_default_pg_defined; } 423 424 struct auth_group *add_auth_group(const char *ag_name); 425 struct auth_group *define_default_auth_group(); 426 auth_group_sp find_auth_group(std::string_view ag_name); 427 428 struct portal_group *add_portal_group(const char *name); 429 struct portal_group *define_default_portal_group(); 430 struct portal_group *find_portal_group(std::string_view name); 431 432 bool add_port(struct target *target, struct portal_group *pg, 433 auth_group_sp ag); 434 bool add_port(struct target *target, struct portal_group *pg, 435 uint32_t ctl_port); 436 bool add_port(struct target *target, struct pport *pp); 437 bool add_port(struct kports &kports, struct target *target, int pp, 438 int vp); 439 bool add_pports(struct kports &kports); 440 441 struct target *add_target(const char *name); 442 struct target *find_target(std::string_view name); 443 444 struct lun *add_lun(const char *name); 445 struct lun *find_lun(std::string_view name); 446 447 void set_debug(int debug); 448 void set_isns_period(int period); 449 void set_isns_timeout(int timeout); 450 void set_maxproc(int maxproc); 451 bool set_pidfile_path(std::string_view path); 452 void set_timeout(int timeout); 453 454 void open_pidfile(); 455 void write_pidfile(); 456 void close_pidfile(); 457 458 bool add_isns(const char *addr); 459 void isns_register_targets(struct isns *isns, struct conf *oldconf); 460 void isns_deregister_targets(struct isns *isns); 461 void isns_schedule_update(); 462 void isns_update(); 463 464 int apply(struct conf *oldconf); 465 void delete_target_luns(struct lun *lun); 466 bool reuse_portal_group_socket(struct portal &newp); 467 bool verify(); 468 469 private: 470 struct isns_req isns_register_request(const char *hostname); 471 struct isns_req isns_check_request(const char *hostname); 472 struct isns_req isns_deregister_request(const char *hostname); 473 void isns_check(struct isns *isns); 474 475 std::string conf_pidfile_path; 476 std::unordered_map<std::string, std::unique_ptr<lun>> conf_luns; 477 std::unordered_map<std::string, std::unique_ptr<target>> conf_targets; 478 std::unordered_map<std::string, auth_group_sp> conf_auth_groups; 479 std::unordered_map<std::string, std::unique_ptr<port>> conf_ports; 480 std::unordered_map<std::string, portal_group_up> conf_portal_groups; 481 std::unordered_map<std::string, isns> conf_isns; 482 struct target *conf_first_target = nullptr; 483 int conf_isns_period = 900; 484 int conf_isns_timeout = 5; 485 int conf_debug = 0; 486 int conf_timeout = 60; 487 int conf_maxproc = 30; 488 489 freebsd::pidfile conf_pidfile; 490 491 bool conf_default_pg_defined = false; 492 bool conf_default_ag_defined = false; 493 494 #ifdef ICL_KERNEL_PROXY 495 public: 496 int add_proxy_portal(portal *); 497 portal *proxy_portal(int); 498 private: 499 std::vector<portal *> conf_proxy_portals; 500 #endif 501 }; 502 503 using conf_up = std::unique_ptr<conf>; 504 505 /* Physical ports exposed by the kernel */ 506 struct pport { pportpport507 pport(std::string_view name, uint32_t ctl_port) : pp_name(name), 508 pp_ctl_port(ctl_port) {} 509 namepport510 const char *name() const { return pp_name.c_str(); } ctl_portpport511 uint32_t ctl_port() const { return pp_ctl_port; } 512 linkedpport513 bool linked() const { return pp_linked; } linkpport514 void link() { pp_linked = true; } 515 516 private: 517 std::string pp_name; 518 uint32_t pp_ctl_port; 519 bool pp_linked; 520 }; 521 522 struct kports { 523 bool add_port(std::string &name, uint32_t ctl_port); 524 bool has_port(std::string_view name); 525 struct pport *find_port(std::string_view name); 526 527 private: 528 std::unordered_map<std::string, struct pport> pports; 529 }; 530 531 #define CONN_SESSION_TYPE_NONE 0 532 #define CONN_SESSION_TYPE_DISCOVERY 1 533 #define CONN_SESSION_TYPE_NORMAL 2 534 535 struct ctld_connection { 536 ctld_connection(struct portal *portal, int fd, const char *host, 537 const struct sockaddr *client_sa); 538 ~ctld_connection(); 539 session_typectld_connection540 int session_type() const { return conn_session_type; } 541 542 void login(); 543 void discovery(); 544 void kernel_handoff(); 545 private: 546 void login_chap(struct auth_group *ag); 547 void login_negotiate_key(struct pdu *request, const char *name, 548 const char *value, bool skipped_security, 549 struct keys *response_keys); 550 bool login_portal_redirect(struct pdu *request); 551 bool login_target_redirect(struct pdu *request); 552 void login_negotiate(struct pdu *request); 553 void login_wait_transition(); 554 555 bool discovery_target_filtered_out(const struct port *port) const; 556 557 struct connection conn; 558 struct portal *conn_portal = nullptr; 559 const struct port *conn_port = nullptr; 560 struct target *conn_target = nullptr; 561 int conn_session_type = CONN_SESSION_TYPE_NONE; 562 std::string conn_initiator_name; 563 std::string conn_initiator_addr; 564 std::string conn_initiator_alias; 565 uint8_t conn_initiator_isid[6]; 566 const struct sockaddr *conn_initiator_sa = nullptr; 567 int conn_max_recv_data_segment_limit = 0; 568 int conn_max_send_data_segment_limit = 0; 569 int conn_max_burst_limit = 0; 570 int conn_first_burst_limit = 0; 571 std::string conn_user; 572 struct chap *conn_chap = nullptr; 573 }; 574 575 extern int ctl_fd; 576 577 bool parse_conf(const char *path); 578 bool uclparse_conf(const char *path); 579 580 conf_up conf_new_from_kernel(struct kports &kports); 581 void conf_finish(void); 582 void conf_start(struct conf *new_conf); 583 584 bool option_new(nvlist_t *nvl, 585 const char *name, const char *value); 586 587 void kernel_init(void); 588 void kernel_capsicate(void); 589 590 #ifdef ICL_KERNEL_PROXY 591 void kernel_listen(struct addrinfo *ai, bool iser, 592 int portal_id); 593 void kernel_accept(int *connection_id, int *portal_id, 594 struct sockaddr *client_sa, 595 socklen_t *client_salen); 596 void kernel_send(struct pdu *pdu); 597 void kernel_receive(struct pdu *pdu); 598 #endif 599 600 void start_timer(int timeout, bool fatal = false); 601 void stop_timer(); 602 603 #endif /* !__CTLD_HH__ */ 604