xref: /openbsd-src/usr.sbin/iscsid/util.c (revision dda190fa52069057bd4ee3e5fdafe11ee1305b72)
1*dda190faSclaudio /*	$OpenBSD: util.c,v 1.10 2025/01/16 16:19:39 claudio Exp $ */
2bde1ae23Sclaudio 
3bde1ae23Sclaudio /*
4bde1ae23Sclaudio  * Copyright (c) 2009 Claudio Jeker <claudio@openbsd.org>
5bde1ae23Sclaudio  *
6bde1ae23Sclaudio  * Permission to use, copy, modify, and distribute this software for any
7bde1ae23Sclaudio  * purpose with or without fee is hereby granted, provided that the above
8bde1ae23Sclaudio  * copyright notice and this permission notice appear in all copies.
9bde1ae23Sclaudio  *
10bde1ae23Sclaudio  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11bde1ae23Sclaudio  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12bde1ae23Sclaudio  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13bde1ae23Sclaudio  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14bde1ae23Sclaudio  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15bde1ae23Sclaudio  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16bde1ae23Sclaudio  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17bde1ae23Sclaudio  */
18ea0867c0Sderaadt 
19bde1ae23Sclaudio #include <sys/queue.h>
20bde1ae23Sclaudio #include <sys/socket.h>
21bde1ae23Sclaudio #include <sys/uio.h>
22bde1ae23Sclaudio 
23bde1ae23Sclaudio #include <scsi/iscsi.h>
24bde1ae23Sclaudio 
25bde1ae23Sclaudio #include <errno.h>
26bde1ae23Sclaudio #include <event.h>
27bde1ae23Sclaudio #include <fcntl.h>
28bde1ae23Sclaudio #include <netdb.h>
29bde1ae23Sclaudio #include <stdio.h>
30bde1ae23Sclaudio #include <stdlib.h>
312f43ab01Smmcc #include <string.h>
32bde1ae23Sclaudio #include <unistd.h>
33bde1ae23Sclaudio 
34bde1ae23Sclaudio #include "iscsid.h"
35bde1ae23Sclaudio #include "log.h"
36bde1ae23Sclaudio 
37bde1ae23Sclaudio struct pdu *
38bde1ae23Sclaudio pdu_new(void)
39bde1ae23Sclaudio {
40bde1ae23Sclaudio 	struct pdu *p;
41bde1ae23Sclaudio 
42bde1ae23Sclaudio 	if (!(p = calloc(1, sizeof(*p))))
43bde1ae23Sclaudio 		return NULL;
44bde1ae23Sclaudio 	return p;
45bde1ae23Sclaudio }
46bde1ae23Sclaudio 
47bde1ae23Sclaudio void *
48bde1ae23Sclaudio pdu_alloc(size_t len)
49bde1ae23Sclaudio {
50bde1ae23Sclaudio 	return malloc(PDU_LEN(len));
51bde1ae23Sclaudio }
52bde1ae23Sclaudio 
53bde1ae23Sclaudio void *
54bde1ae23Sclaudio pdu_dup(void *data, size_t len)
55bde1ae23Sclaudio {
56bde1ae23Sclaudio 	void *p;
57bde1ae23Sclaudio 
58bde1ae23Sclaudio 	if ((p = malloc(PDU_LEN(len))))
59a86db512Sclaudio 		memcpy(p, data, len);
60bde1ae23Sclaudio 	return p;
61bde1ae23Sclaudio }
62bde1ae23Sclaudio 
63bde1ae23Sclaudio int
64bde1ae23Sclaudio pdu_addbuf(struct pdu *p, void *buf, size_t len, unsigned int elm)
65bde1ae23Sclaudio {
66bde1ae23Sclaudio 	if (len & 0x3) {
67bde1ae23Sclaudio 		bzero((char *)buf + len, 4 - (len & 0x3));
68bde1ae23Sclaudio 		len += 4 - (len & 0x3);
69bde1ae23Sclaudio 	}
70bde1ae23Sclaudio 
71bde1ae23Sclaudio 	if (elm < PDU_MAXIOV)
72bde1ae23Sclaudio 		if (!p->iov[elm].iov_base) {
73bde1ae23Sclaudio 			p->iov[elm].iov_base = buf;
74bde1ae23Sclaudio 			p->iov[elm].iov_len = len;
75bde1ae23Sclaudio 			return 0;
76bde1ae23Sclaudio 		}
77bde1ae23Sclaudio 
78bde1ae23Sclaudio 	/* no space left */
79bde1ae23Sclaudio 	return -1;
80bde1ae23Sclaudio }
81bde1ae23Sclaudio 
82bde1ae23Sclaudio void *
83bde1ae23Sclaudio pdu_getbuf(struct pdu *p, size_t *len, unsigned int elm)
84bde1ae23Sclaudio {
85bde1ae23Sclaudio 	if (len)
86bde1ae23Sclaudio 		*len = 0;
87bde1ae23Sclaudio 	if (elm < PDU_MAXIOV)
88bde1ae23Sclaudio 		if (p->iov[elm].iov_base) {
89bde1ae23Sclaudio 			if (len)
90bde1ae23Sclaudio 				*len = p->iov[elm].iov_len;
91bde1ae23Sclaudio 			return p->iov[elm].iov_base;
92bde1ae23Sclaudio 		}
93bde1ae23Sclaudio 
94bde1ae23Sclaudio 	return NULL;
95bde1ae23Sclaudio }
96bde1ae23Sclaudio 
97bde1ae23Sclaudio void
98bde1ae23Sclaudio pdu_free(struct pdu *p)
99bde1ae23Sclaudio {
100bde1ae23Sclaudio 	unsigned int j;
101bde1ae23Sclaudio 
102bde1ae23Sclaudio 	for (j = 0; j < PDU_MAXIOV; j++)
103bde1ae23Sclaudio 		free(p->iov[j].iov_base);
104bde1ae23Sclaudio 	free(p);
105bde1ae23Sclaudio }
106bde1ae23Sclaudio 
107bde1ae23Sclaudio int
108bde1ae23Sclaudio socket_setblockmode(int fd, int nonblocking)
109bde1ae23Sclaudio {
110bde1ae23Sclaudio 	int flags;
111bde1ae23Sclaudio 
11283094010Skrw 	if ((flags = fcntl(fd, F_GETFL)) == -1)
113bde1ae23Sclaudio 		return -1;
114bde1ae23Sclaudio 
115bde1ae23Sclaudio 	if (nonblocking)
116bde1ae23Sclaudio 		flags |= O_NONBLOCK;
117bde1ae23Sclaudio 	else
118bde1ae23Sclaudio 		flags &= ~O_NONBLOCK;
119bde1ae23Sclaudio 
120bde1ae23Sclaudio 	if ((flags = fcntl(fd, F_SETFL, flags)) == -1)
121bde1ae23Sclaudio 		return -1;
122bde1ae23Sclaudio 	return 0;
123bde1ae23Sclaudio }
124bde1ae23Sclaudio 
125bde1ae23Sclaudio const char *
126bde1ae23Sclaudio log_sockaddr(void *arg)
127bde1ae23Sclaudio {
128bde1ae23Sclaudio 	struct sockaddr *sa = arg;
129bde1ae23Sclaudio 	char port[6];
130bde1ae23Sclaudio 	char host[NI_MAXHOST];
131bde1ae23Sclaudio 	static char buf[NI_MAXHOST + 8];
132bde1ae23Sclaudio 
133bde1ae23Sclaudio 	if (getnameinfo(sa, sa->sa_len, host, sizeof(host), port, sizeof(port),
134bde1ae23Sclaudio 	    NI_NUMERICHOST))
135bde1ae23Sclaudio 		return "unknown";
136bde1ae23Sclaudio 	if (port[0] == '0')
137bde1ae23Sclaudio 		strlcpy(buf, host, sizeof(buf));
138bde1ae23Sclaudio 	else if (sa->sa_family == AF_INET)
139bde1ae23Sclaudio 		snprintf(buf, sizeof(buf), "%s:%s", host, port);
140bde1ae23Sclaudio 	else
141bde1ae23Sclaudio 		snprintf(buf, sizeof(buf), "[%s]:%s", host, port);
142bde1ae23Sclaudio 	return buf;
143bde1ae23Sclaudio }
144f73922b8Sclaudio 
145f73922b8Sclaudio int
146f73922b8Sclaudio control_compose(void *ch, u_int16_t type, void *buf, size_t len)
147f73922b8Sclaudio {
148f73922b8Sclaudio 	return control_build(ch, type, 1, CTRLARGV({ buf, len }));
149f73922b8Sclaudio }
150f73922b8Sclaudio 
151f73922b8Sclaudio int
152f73922b8Sclaudio control_build(void *ch, u_int16_t type, int argc, struct ctrldata *argv)
153f73922b8Sclaudio {
154f73922b8Sclaudio 	struct pdu *pdu;
155f73922b8Sclaudio 	struct ctrlmsghdr *cmh;
156f73922b8Sclaudio 	size_t size = 0;
157f73922b8Sclaudio 	int i;
158f73922b8Sclaudio 
159f73922b8Sclaudio 	if (argc > (int)nitems(cmh->len))
160f73922b8Sclaudio 		return -1;
161f73922b8Sclaudio 
162f73922b8Sclaudio 	for (i = 0; i < argc; i++)
163f73922b8Sclaudio 		size += argv[i].len;
164f73922b8Sclaudio 	if (PDU_LEN(size) > CONTROL_READ_SIZE - PDU_LEN(sizeof(*cmh)))
165f73922b8Sclaudio 		return -1;
166f73922b8Sclaudio 
167f73922b8Sclaudio 	if ((pdu = pdu_new()) == NULL)
168f73922b8Sclaudio 		return -1;
169f73922b8Sclaudio 	if ((cmh = pdu_alloc(sizeof(*cmh))) == NULL)
170f73922b8Sclaudio 		goto fail;
171f73922b8Sclaudio 	bzero(cmh, sizeof(*cmh));
172f73922b8Sclaudio 	cmh->type = type;
173f73922b8Sclaudio 	pdu_addbuf(pdu, cmh, sizeof(*cmh), 0);
174f73922b8Sclaudio 
175f73922b8Sclaudio 	for (i = 0; i < argc; i++)
176f73922b8Sclaudio 		if (argv[i].len > 0) {
177f73922b8Sclaudio 			void *ptr;
178f73922b8Sclaudio 
179f73922b8Sclaudio 			cmh->len[i] = argv[i].len;
180f73922b8Sclaudio 			if ((ptr = pdu_alloc(argv[i].len)) == NULL)
181f73922b8Sclaudio 				goto fail;
182f73922b8Sclaudio 			memcpy(ptr, argv[i].buf, argv[i].len);
183f73922b8Sclaudio 			pdu_addbuf(pdu, ptr, argv[i].len, i + 1);
184f73922b8Sclaudio 		}
185f73922b8Sclaudio 
186f73922b8Sclaudio 	control_queue(ch, pdu);
187f73922b8Sclaudio 	return 0;
188f73922b8Sclaudio fail:
189f73922b8Sclaudio 	pdu_free(pdu);
190f73922b8Sclaudio 	return -1;
191f73922b8Sclaudio }
192*dda190faSclaudio 
193*dda190faSclaudio void
194*dda190faSclaudio kvp_free(struct kvp *kvp)
195*dda190faSclaudio {
196*dda190faSclaudio 	struct kvp *k;
197*dda190faSclaudio 
198*dda190faSclaudio 	if (kvp == NULL)
199*dda190faSclaudio 		return;
200*dda190faSclaudio 	for (k = kvp; k->key; k++) {
201*dda190faSclaudio 		if (k->flags & KVP_KEY_ALLOCED)
202*dda190faSclaudio 			free(k->key);
203*dda190faSclaudio 		if (k->flags & KVP_VALUE_ALLOCED)
204*dda190faSclaudio 			free(k->value);
205*dda190faSclaudio 	}
206*dda190faSclaudio 	free(kvp);
207*dda190faSclaudio }
208