xref: /freebsd/usr.sbin/ctld/ctld.hh (revision ed076901ec80e23804ef432cfa7edeb10c4f9ede)
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