1829603e2SAlexander Motin /*- 2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 38eebe1bfSEdward Tomasz Napierala * 4829603e2SAlexander Motin * Copyright (c) 2014 Alexander Motin <mav@FreeBSD.org> 5829603e2SAlexander Motin * All rights reserved. 6829603e2SAlexander Motin * 7829603e2SAlexander Motin * Redistribution and use in source and binary forms, with or without 8829603e2SAlexander Motin * modification, are permitted provided that the following conditions 9829603e2SAlexander Motin * are met: 10829603e2SAlexander Motin * 1. Redistributions of source code must retain the above copyright 11829603e2SAlexander Motin * notice, this list of conditions and the following disclaimer. 12829603e2SAlexander Motin * 2. Redistributions in binary form must reproduce the above copyright 13829603e2SAlexander Motin * notice, this list of conditions and the following disclaimer in the 14829603e2SAlexander Motin * documentation and/or other materials provided with the distribution. 15829603e2SAlexander Motin * 16829603e2SAlexander Motin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17829603e2SAlexander Motin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18829603e2SAlexander Motin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19829603e2SAlexander Motin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20829603e2SAlexander Motin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21829603e2SAlexander Motin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22829603e2SAlexander Motin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23829603e2SAlexander Motin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24829603e2SAlexander Motin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25829603e2SAlexander Motin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26829603e2SAlexander Motin * SUCH DAMAGE. 27829603e2SAlexander Motin * 28829603e2SAlexander Motin */ 29829603e2SAlexander Motin 30829603e2SAlexander Motin #include <sys/cdefs.h> 31829603e2SAlexander Motin __FBSDID("$FreeBSD$"); 32829603e2SAlexander Motin 33829603e2SAlexander Motin #include <sys/types.h> 34829603e2SAlexander Motin #include <sys/time.h> 35829603e2SAlexander Motin #include <sys/socket.h> 36829603e2SAlexander Motin #include <sys/wait.h> 37829603e2SAlexander Motin #include <sys/endian.h> 38829603e2SAlexander Motin #include <netinet/in.h> 39829603e2SAlexander Motin #include <arpa/inet.h> 40829603e2SAlexander Motin #include <netdb.h> 41829603e2SAlexander Motin #include <stdbool.h> 42829603e2SAlexander Motin #include <stdlib.h> 43829603e2SAlexander Motin #include <string.h> 44829603e2SAlexander Motin #include <unistd.h> 45829603e2SAlexander Motin 46829603e2SAlexander Motin #include "ctld.h" 47829603e2SAlexander Motin #include "isns.h" 48829603e2SAlexander Motin 49829603e2SAlexander Motin struct isns_req * 50829603e2SAlexander Motin isns_req_alloc(void) 51829603e2SAlexander Motin { 52829603e2SAlexander Motin struct isns_req *req; 53829603e2SAlexander Motin 54829603e2SAlexander Motin req = calloc(sizeof(struct isns_req), 1); 55829603e2SAlexander Motin if (req == NULL) { 56829603e2SAlexander Motin log_err(1, "calloc"); 57829603e2SAlexander Motin return (NULL); 58829603e2SAlexander Motin } 59829603e2SAlexander Motin req->ir_buflen = sizeof(struct isns_hdr); 60829603e2SAlexander Motin req->ir_usedlen = 0; 61829603e2SAlexander Motin req->ir_buf = calloc(req->ir_buflen, 1); 629f495878SEdward Tomasz Napierala if (req->ir_buf == NULL) { 63829603e2SAlexander Motin free(req); 64829603e2SAlexander Motin log_err(1, "calloc"); 65829603e2SAlexander Motin return (NULL); 66829603e2SAlexander Motin } 67829603e2SAlexander Motin return (req); 68829603e2SAlexander Motin } 69829603e2SAlexander Motin 70829603e2SAlexander Motin struct isns_req * 71829603e2SAlexander Motin isns_req_create(uint16_t func, uint16_t flags) 72829603e2SAlexander Motin { 73829603e2SAlexander Motin struct isns_req *req; 74829603e2SAlexander Motin struct isns_hdr *hdr; 75829603e2SAlexander Motin 76829603e2SAlexander Motin req = isns_req_alloc(); 77829603e2SAlexander Motin req->ir_usedlen = sizeof(struct isns_hdr); 78829603e2SAlexander Motin hdr = (struct isns_hdr *)req->ir_buf; 79829603e2SAlexander Motin be16enc(hdr->ih_version, ISNS_VERSION); 80829603e2SAlexander Motin be16enc(hdr->ih_function, func); 81829603e2SAlexander Motin be16enc(hdr->ih_flags, flags); 82829603e2SAlexander Motin return (req); 83829603e2SAlexander Motin } 84829603e2SAlexander Motin 85829603e2SAlexander Motin void 86829603e2SAlexander Motin isns_req_free(struct isns_req *req) 87829603e2SAlexander Motin { 88829603e2SAlexander Motin 89829603e2SAlexander Motin free(req->ir_buf); 90829603e2SAlexander Motin free(req); 91829603e2SAlexander Motin } 92829603e2SAlexander Motin 93829603e2SAlexander Motin static int 94829603e2SAlexander Motin isns_req_getspace(struct isns_req *req, uint32_t len) 95829603e2SAlexander Motin { 96829603e2SAlexander Motin void *newbuf; 97829603e2SAlexander Motin int newlen; 98829603e2SAlexander Motin 99829603e2SAlexander Motin if (req->ir_usedlen + len <= req->ir_buflen) 100829603e2SAlexander Motin return (0); 101829603e2SAlexander Motin newlen = 1 << flsl(req->ir_usedlen + len); 102829603e2SAlexander Motin newbuf = realloc(req->ir_buf, newlen); 103829603e2SAlexander Motin if (newbuf == NULL) { 104829603e2SAlexander Motin log_err(1, "realloc"); 105829603e2SAlexander Motin return (1); 106829603e2SAlexander Motin } 107829603e2SAlexander Motin req->ir_buf = newbuf; 108829603e2SAlexander Motin req->ir_buflen = newlen; 109829603e2SAlexander Motin return (0); 110829603e2SAlexander Motin } 111829603e2SAlexander Motin 112829603e2SAlexander Motin void 113829603e2SAlexander Motin isns_req_add(struct isns_req *req, uint32_t tag, uint32_t len, 114829603e2SAlexander Motin const void *value) 115829603e2SAlexander Motin { 116829603e2SAlexander Motin struct isns_tlv *tlv; 117829603e2SAlexander Motin uint32_t vlen; 118829603e2SAlexander Motin 119829603e2SAlexander Motin vlen = len + ((len & 3) ? (4 - (len & 3)) : 0); 120829603e2SAlexander Motin isns_req_getspace(req, sizeof(*tlv) + vlen); 121829603e2SAlexander Motin tlv = (struct isns_tlv *)&req->ir_buf[req->ir_usedlen]; 122829603e2SAlexander Motin be32enc(tlv->it_tag, tag); 123829603e2SAlexander Motin be32enc(tlv->it_length, vlen); 124829603e2SAlexander Motin memcpy(tlv->it_value, value, len); 125829603e2SAlexander Motin if (vlen != len) 126829603e2SAlexander Motin memset(&tlv->it_value[len], 0, vlen - len); 127829603e2SAlexander Motin req->ir_usedlen += sizeof(*tlv) + vlen; 128829603e2SAlexander Motin } 129829603e2SAlexander Motin 130829603e2SAlexander Motin void 131829603e2SAlexander Motin isns_req_add_delim(struct isns_req *req) 132829603e2SAlexander Motin { 133829603e2SAlexander Motin 134829603e2SAlexander Motin isns_req_add(req, 0, 0, NULL); 135829603e2SAlexander Motin } 136829603e2SAlexander Motin 137829603e2SAlexander Motin void 138829603e2SAlexander Motin isns_req_add_str(struct isns_req *req, uint32_t tag, const char *value) 139829603e2SAlexander Motin { 140829603e2SAlexander Motin 141829603e2SAlexander Motin isns_req_add(req, tag, strlen(value) + 1, value); 142829603e2SAlexander Motin } 143829603e2SAlexander Motin 144829603e2SAlexander Motin void 145829603e2SAlexander Motin isns_req_add_32(struct isns_req *req, uint32_t tag, uint32_t value) 146829603e2SAlexander Motin { 147829603e2SAlexander Motin uint32_t beval; 148829603e2SAlexander Motin 149829603e2SAlexander Motin be32enc(&beval, value); 150829603e2SAlexander Motin isns_req_add(req, tag, sizeof(value), &beval); 151829603e2SAlexander Motin } 152829603e2SAlexander Motin 153829603e2SAlexander Motin void 154829603e2SAlexander Motin isns_req_add_addr(struct isns_req *req, uint32_t tag, struct addrinfo *ai) 155829603e2SAlexander Motin { 156829603e2SAlexander Motin struct sockaddr_in *in4; 157829603e2SAlexander Motin struct sockaddr_in6 *in6; 158829603e2SAlexander Motin uint8_t buf[16]; 159829603e2SAlexander Motin 160829603e2SAlexander Motin switch (ai->ai_addr->sa_family) { 161829603e2SAlexander Motin case AF_INET: 162829603e2SAlexander Motin in4 = (struct sockaddr_in *)(void *)ai->ai_addr; 163829603e2SAlexander Motin memset(buf, 0, 10); 164829603e2SAlexander Motin buf[10] = 0xff; 165829603e2SAlexander Motin buf[11] = 0xff; 166829603e2SAlexander Motin memcpy(&buf[12], &in4->sin_addr, sizeof(in4->sin_addr)); 167829603e2SAlexander Motin isns_req_add(req, tag, sizeof(buf), buf); 168829603e2SAlexander Motin break; 169829603e2SAlexander Motin case AF_INET6: 170829603e2SAlexander Motin in6 = (struct sockaddr_in6 *)(void *)ai->ai_addr; 171829603e2SAlexander Motin isns_req_add(req, tag, sizeof(in6->sin6_addr), &in6->sin6_addr); 172829603e2SAlexander Motin break; 173829603e2SAlexander Motin default: 174829603e2SAlexander Motin log_errx(1, "Unsupported address family %d", 175829603e2SAlexander Motin ai->ai_addr->sa_family); 176829603e2SAlexander Motin } 177829603e2SAlexander Motin } 178829603e2SAlexander Motin 179829603e2SAlexander Motin void 180829603e2SAlexander Motin isns_req_add_port(struct isns_req *req, uint32_t tag, struct addrinfo *ai) 181829603e2SAlexander Motin { 182829603e2SAlexander Motin struct sockaddr_in *in4; 183829603e2SAlexander Motin struct sockaddr_in6 *in6; 184829603e2SAlexander Motin uint32_t buf; 185829603e2SAlexander Motin 186829603e2SAlexander Motin switch (ai->ai_addr->sa_family) { 187829603e2SAlexander Motin case AF_INET: 188829603e2SAlexander Motin in4 = (struct sockaddr_in *)(void *)ai->ai_addr; 189829603e2SAlexander Motin be32enc(&buf, ntohs(in4->sin_port)); 190829603e2SAlexander Motin isns_req_add(req, tag, sizeof(buf), &buf); 191829603e2SAlexander Motin break; 192829603e2SAlexander Motin case AF_INET6: 193829603e2SAlexander Motin in6 = (struct sockaddr_in6 *)(void *)ai->ai_addr; 194829603e2SAlexander Motin be32enc(&buf, ntohs(in6->sin6_port)); 195829603e2SAlexander Motin isns_req_add(req, tag, sizeof(buf), &buf); 196829603e2SAlexander Motin break; 197829603e2SAlexander Motin default: 198829603e2SAlexander Motin log_errx(1, "Unsupported address family %d", 199829603e2SAlexander Motin ai->ai_addr->sa_family); 200829603e2SAlexander Motin } 201829603e2SAlexander Motin } 202829603e2SAlexander Motin 203829603e2SAlexander Motin int 204829603e2SAlexander Motin isns_req_send(int s, struct isns_req *req) 205829603e2SAlexander Motin { 206829603e2SAlexander Motin struct isns_hdr *hdr; 207829603e2SAlexander Motin int res; 208829603e2SAlexander Motin 209829603e2SAlexander Motin hdr = (struct isns_hdr *)req->ir_buf; 210829603e2SAlexander Motin be16enc(hdr->ih_length, req->ir_usedlen - sizeof(*hdr)); 211829603e2SAlexander Motin be16enc(hdr->ih_flags, be16dec(hdr->ih_flags) | 212829603e2SAlexander Motin ISNS_FLAG_LAST | ISNS_FLAG_FIRST); 213829603e2SAlexander Motin be16enc(hdr->ih_transaction, 0); 214829603e2SAlexander Motin be16enc(hdr->ih_sequence, 0); 215829603e2SAlexander Motin 216829603e2SAlexander Motin res = write(s, req->ir_buf, req->ir_usedlen); 217829603e2SAlexander Motin return ((res < 0) ? -1 : 0); 218829603e2SAlexander Motin } 219829603e2SAlexander Motin 220829603e2SAlexander Motin int 221829603e2SAlexander Motin isns_req_receive(int s, struct isns_req *req) 222829603e2SAlexander Motin { 223829603e2SAlexander Motin struct isns_hdr *hdr; 224829603e2SAlexander Motin ssize_t res, len; 225829603e2SAlexander Motin 226829603e2SAlexander Motin req->ir_usedlen = 0; 227829603e2SAlexander Motin isns_req_getspace(req, sizeof(*hdr)); 228829603e2SAlexander Motin res = read(s, req->ir_buf, sizeof(*hdr)); 229829603e2SAlexander Motin if (res < (ssize_t)sizeof(*hdr)) 230829603e2SAlexander Motin return (-1); 231829603e2SAlexander Motin req->ir_usedlen = sizeof(*hdr); 232829603e2SAlexander Motin hdr = (struct isns_hdr *)req->ir_buf; 233829603e2SAlexander Motin if (be16dec(hdr->ih_version) != ISNS_VERSION) 234829603e2SAlexander Motin return (-1); 235829603e2SAlexander Motin if ((be16dec(hdr->ih_flags) & (ISNS_FLAG_LAST | ISNS_FLAG_FIRST)) != 236829603e2SAlexander Motin (ISNS_FLAG_LAST | ISNS_FLAG_FIRST)) 237829603e2SAlexander Motin return (-1); 238829603e2SAlexander Motin len = be16dec(hdr->ih_length); 239829603e2SAlexander Motin isns_req_getspace(req, len); 240829603e2SAlexander Motin res = read(s, &req->ir_buf[req->ir_usedlen], len); 241829603e2SAlexander Motin if (res < len) 242829603e2SAlexander Motin return (-1); 243829603e2SAlexander Motin req->ir_usedlen += len; 244829603e2SAlexander Motin return (0); 245829603e2SAlexander Motin } 246829603e2SAlexander Motin 247829603e2SAlexander Motin uint32_t 248829603e2SAlexander Motin isns_req_get_status(struct isns_req *req) 249829603e2SAlexander Motin { 250829603e2SAlexander Motin 251829603e2SAlexander Motin if (req->ir_usedlen < sizeof(struct isns_hdr) + 4) 252829603e2SAlexander Motin return (-1); 253829603e2SAlexander Motin return (be32dec(&req->ir_buf[sizeof(struct isns_hdr)])); 254829603e2SAlexander Motin } 255