1 /* $OpenBSD: util.c,v 1.8 2016/08/16 18:41:57 tedu 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/queue.h> 20 #include <sys/socket.h> 21 #include <sys/uio.h> 22 23 #include <scsi/iscsi.h> 24 25 #include <errno.h> 26 #include <event.h> 27 #include <fcntl.h> 28 #include <netdb.h> 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <unistd.h> 33 34 #include "iscsid.h" 35 #include "log.h" 36 37 struct pdu * 38 pdu_new(void) 39 { 40 struct pdu *p; 41 42 if (!(p = calloc(1, sizeof(*p)))) 43 return NULL; 44 return p; 45 } 46 47 void * 48 pdu_alloc(size_t len) 49 { 50 return malloc(PDU_LEN(len)); 51 } 52 53 void * 54 pdu_dup(void *data, size_t len) 55 { 56 void *p; 57 58 if ((p = malloc(PDU_LEN(len)))) 59 memcpy(p, data, len); 60 return p; 61 } 62 63 int 64 pdu_addbuf(struct pdu *p, void *buf, size_t len, unsigned int elm) 65 { 66 if (len & 0x3) { 67 bzero((char *)buf + len, 4 - (len & 0x3)); 68 len += 4 - (len & 0x3); 69 } 70 71 if (elm < PDU_MAXIOV) 72 if (!p->iov[elm].iov_base) { 73 p->iov[elm].iov_base = buf; 74 p->iov[elm].iov_len = len; 75 return 0; 76 } 77 78 /* no space left */ 79 return -1; 80 } 81 82 void * 83 pdu_getbuf(struct pdu *p, size_t *len, unsigned int elm) 84 { 85 if (len) 86 *len = 0; 87 if (elm < PDU_MAXIOV) 88 if (p->iov[elm].iov_base) { 89 if (len) 90 *len = p->iov[elm].iov_len; 91 return p->iov[elm].iov_base; 92 } 93 94 return NULL; 95 } 96 97 void 98 pdu_free(struct pdu *p) 99 { 100 unsigned int j; 101 102 for (j = 0; j < PDU_MAXIOV; j++) 103 free(p->iov[j].iov_base); 104 free(p); 105 } 106 107 int 108 socket_setblockmode(int fd, int nonblocking) 109 { 110 int flags; 111 112 if ((flags = fcntl(fd, F_GETFL)) == -1) 113 return -1; 114 115 if (nonblocking) 116 flags |= O_NONBLOCK; 117 else 118 flags &= ~O_NONBLOCK; 119 120 if ((flags = fcntl(fd, F_SETFL, flags)) == -1) 121 return -1; 122 return 0; 123 } 124 125 const char * 126 log_sockaddr(void *arg) 127 { 128 struct sockaddr *sa = arg; 129 char port[6]; 130 char host[NI_MAXHOST]; 131 static char buf[NI_MAXHOST + 8]; 132 133 if (getnameinfo(sa, sa->sa_len, host, sizeof(host), port, sizeof(port), 134 NI_NUMERICHOST)) 135 return "unknown"; 136 if (port[0] == '0') 137 strlcpy(buf, host, sizeof(buf)); 138 else if (sa->sa_family == AF_INET) 139 snprintf(buf, sizeof(buf), "%s:%s", host, port); 140 else 141 snprintf(buf, sizeof(buf), "[%s]:%s", host, port); 142 return buf; 143 } 144 145 int 146 control_compose(void *ch, u_int16_t type, void *buf, size_t len) 147 { 148 return control_build(ch, type, 1, CTRLARGV({ buf, len })); 149 } 150 151 int 152 control_build(void *ch, u_int16_t type, int argc, struct ctrldata *argv) 153 { 154 struct pdu *pdu; 155 struct ctrlmsghdr *cmh; 156 size_t size = 0; 157 int i; 158 159 if (argc > (int)nitems(cmh->len)) 160 return -1; 161 162 for (i = 0; i < argc; i++) 163 size += argv[i].len; 164 if (PDU_LEN(size) > CONTROL_READ_SIZE - PDU_LEN(sizeof(*cmh))) 165 return -1; 166 167 if ((pdu = pdu_new()) == NULL) 168 return -1; 169 if ((cmh = pdu_alloc(sizeof(*cmh))) == NULL) 170 goto fail; 171 bzero(cmh, sizeof(*cmh)); 172 cmh->type = type; 173 pdu_addbuf(pdu, cmh, sizeof(*cmh), 0); 174 175 for (i = 0; i < argc; i++) 176 if (argv[i].len > 0) { 177 void *ptr; 178 179 cmh->len[i] = argv[i].len; 180 if ((ptr = pdu_alloc(argv[i].len)) == NULL) 181 goto fail; 182 memcpy(ptr, argv[i].buf, argv[i].len); 183 pdu_addbuf(pdu, ptr, argv[i].len, i + 1); 184 } 185 186 control_queue(ch, pdu); 187 return 0; 188 fail: 189 pdu_free(pdu); 190 return -1; 191 } 192