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