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