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