1829603e2SAlexander Motin /*- 24d846d26SWarner 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/types.h> 31829603e2SAlexander Motin #include <sys/time.h> 32829603e2SAlexander Motin #include <sys/socket.h> 33829603e2SAlexander Motin #include <sys/wait.h> 34829603e2SAlexander Motin #include <sys/endian.h> 35829603e2SAlexander Motin #include <netinet/in.h> 36829603e2SAlexander Motin #include <arpa/inet.h> 37829603e2SAlexander Motin #include <netdb.h> 38829603e2SAlexander Motin #include <stdbool.h> 39829603e2SAlexander Motin #include <stdlib.h> 40829603e2SAlexander Motin #include <string.h> 41829603e2SAlexander Motin #include <unistd.h> 42829603e2SAlexander Motin 43829603e2SAlexander Motin #include "ctld.h" 44829603e2SAlexander Motin #include "isns.h" 45829603e2SAlexander Motin 46829603e2SAlexander Motin struct isns_req * 47829603e2SAlexander Motin isns_req_alloc(void) 48829603e2SAlexander Motin { 49829603e2SAlexander Motin struct isns_req *req; 50829603e2SAlexander Motin 51*2ba12978SJohn Baldwin req = calloc(1, sizeof(struct isns_req)); 52829603e2SAlexander Motin if (req == NULL) { 53829603e2SAlexander Motin log_err(1, "calloc"); 54829603e2SAlexander Motin return (NULL); 55829603e2SAlexander Motin } 56829603e2SAlexander Motin req->ir_buflen = sizeof(struct isns_hdr); 57829603e2SAlexander Motin req->ir_usedlen = 0; 58*2ba12978SJohn Baldwin req->ir_buf = calloc(1, req->ir_buflen); 599f495878SEdward Tomasz Napierala if (req->ir_buf == NULL) { 60829603e2SAlexander Motin free(req); 61829603e2SAlexander Motin log_err(1, "calloc"); 62829603e2SAlexander Motin return (NULL); 63829603e2SAlexander Motin } 64829603e2SAlexander Motin return (req); 65829603e2SAlexander Motin } 66829603e2SAlexander Motin 67829603e2SAlexander Motin struct isns_req * 68829603e2SAlexander Motin isns_req_create(uint16_t func, uint16_t flags) 69829603e2SAlexander Motin { 70829603e2SAlexander Motin struct isns_req *req; 71829603e2SAlexander Motin struct isns_hdr *hdr; 72829603e2SAlexander Motin 73829603e2SAlexander Motin req = isns_req_alloc(); 74829603e2SAlexander Motin req->ir_usedlen = sizeof(struct isns_hdr); 75829603e2SAlexander Motin hdr = (struct isns_hdr *)req->ir_buf; 76829603e2SAlexander Motin be16enc(hdr->ih_version, ISNS_VERSION); 77829603e2SAlexander Motin be16enc(hdr->ih_function, func); 78829603e2SAlexander Motin be16enc(hdr->ih_flags, flags); 79829603e2SAlexander Motin return (req); 80829603e2SAlexander Motin } 81829603e2SAlexander Motin 82829603e2SAlexander Motin void 83829603e2SAlexander Motin isns_req_free(struct isns_req *req) 84829603e2SAlexander Motin { 85829603e2SAlexander Motin 86829603e2SAlexander Motin free(req->ir_buf); 87829603e2SAlexander Motin free(req); 88829603e2SAlexander Motin } 89829603e2SAlexander Motin 90829603e2SAlexander Motin static int 91829603e2SAlexander Motin isns_req_getspace(struct isns_req *req, uint32_t len) 92829603e2SAlexander Motin { 93829603e2SAlexander Motin void *newbuf; 94829603e2SAlexander Motin int newlen; 95829603e2SAlexander Motin 96829603e2SAlexander Motin if (req->ir_usedlen + len <= req->ir_buflen) 97829603e2SAlexander Motin return (0); 98829603e2SAlexander Motin newlen = 1 << flsl(req->ir_usedlen + len); 99829603e2SAlexander Motin newbuf = realloc(req->ir_buf, newlen); 100829603e2SAlexander Motin if (newbuf == NULL) { 101829603e2SAlexander Motin log_err(1, "realloc"); 102829603e2SAlexander Motin return (1); 103829603e2SAlexander Motin } 104829603e2SAlexander Motin req->ir_buf = newbuf; 105829603e2SAlexander Motin req->ir_buflen = newlen; 106829603e2SAlexander Motin return (0); 107829603e2SAlexander Motin } 108829603e2SAlexander Motin 109829603e2SAlexander Motin void 110829603e2SAlexander Motin isns_req_add(struct isns_req *req, uint32_t tag, uint32_t len, 111829603e2SAlexander Motin const void *value) 112829603e2SAlexander Motin { 113829603e2SAlexander Motin struct isns_tlv *tlv; 114829603e2SAlexander Motin uint32_t vlen; 115829603e2SAlexander Motin 116829603e2SAlexander Motin vlen = len + ((len & 3) ? (4 - (len & 3)) : 0); 117829603e2SAlexander Motin isns_req_getspace(req, sizeof(*tlv) + vlen); 118829603e2SAlexander Motin tlv = (struct isns_tlv *)&req->ir_buf[req->ir_usedlen]; 119829603e2SAlexander Motin be32enc(tlv->it_tag, tag); 120829603e2SAlexander Motin be32enc(tlv->it_length, vlen); 121829603e2SAlexander Motin memcpy(tlv->it_value, value, len); 122829603e2SAlexander Motin if (vlen != len) 123829603e2SAlexander Motin memset(&tlv->it_value[len], 0, vlen - len); 124829603e2SAlexander Motin req->ir_usedlen += sizeof(*tlv) + vlen; 125829603e2SAlexander Motin } 126829603e2SAlexander Motin 127829603e2SAlexander Motin void 128829603e2SAlexander Motin isns_req_add_delim(struct isns_req *req) 129829603e2SAlexander Motin { 130829603e2SAlexander Motin 131829603e2SAlexander Motin isns_req_add(req, 0, 0, NULL); 132829603e2SAlexander Motin } 133829603e2SAlexander Motin 134829603e2SAlexander Motin void 135829603e2SAlexander Motin isns_req_add_str(struct isns_req *req, uint32_t tag, const char *value) 136829603e2SAlexander Motin { 137829603e2SAlexander Motin 138829603e2SAlexander Motin isns_req_add(req, tag, strlen(value) + 1, value); 139829603e2SAlexander Motin } 140829603e2SAlexander Motin 141829603e2SAlexander Motin void 142829603e2SAlexander Motin isns_req_add_32(struct isns_req *req, uint32_t tag, uint32_t value) 143829603e2SAlexander Motin { 144829603e2SAlexander Motin uint32_t beval; 145829603e2SAlexander Motin 146829603e2SAlexander Motin be32enc(&beval, value); 147829603e2SAlexander Motin isns_req_add(req, tag, sizeof(value), &beval); 148829603e2SAlexander Motin } 149829603e2SAlexander Motin 150829603e2SAlexander Motin void 151829603e2SAlexander Motin isns_req_add_addr(struct isns_req *req, uint32_t tag, struct addrinfo *ai) 152829603e2SAlexander Motin { 153829603e2SAlexander Motin struct sockaddr_in *in4; 154829603e2SAlexander Motin struct sockaddr_in6 *in6; 155829603e2SAlexander Motin uint8_t buf[16]; 156829603e2SAlexander Motin 157829603e2SAlexander Motin switch (ai->ai_addr->sa_family) { 158829603e2SAlexander Motin case AF_INET: 159829603e2SAlexander Motin in4 = (struct sockaddr_in *)(void *)ai->ai_addr; 160829603e2SAlexander Motin memset(buf, 0, 10); 161829603e2SAlexander Motin buf[10] = 0xff; 162829603e2SAlexander Motin buf[11] = 0xff; 163829603e2SAlexander Motin memcpy(&buf[12], &in4->sin_addr, sizeof(in4->sin_addr)); 164829603e2SAlexander Motin isns_req_add(req, tag, sizeof(buf), buf); 165829603e2SAlexander Motin break; 166829603e2SAlexander Motin case AF_INET6: 167829603e2SAlexander Motin in6 = (struct sockaddr_in6 *)(void *)ai->ai_addr; 168829603e2SAlexander Motin isns_req_add(req, tag, sizeof(in6->sin6_addr), &in6->sin6_addr); 169829603e2SAlexander Motin break; 170829603e2SAlexander Motin default: 171829603e2SAlexander Motin log_errx(1, "Unsupported address family %d", 172829603e2SAlexander Motin ai->ai_addr->sa_family); 173829603e2SAlexander Motin } 174829603e2SAlexander Motin } 175829603e2SAlexander Motin 176829603e2SAlexander Motin void 177829603e2SAlexander Motin isns_req_add_port(struct isns_req *req, uint32_t tag, struct addrinfo *ai) 178829603e2SAlexander Motin { 179829603e2SAlexander Motin struct sockaddr_in *in4; 180829603e2SAlexander Motin struct sockaddr_in6 *in6; 181829603e2SAlexander Motin uint32_t buf; 182829603e2SAlexander Motin 183829603e2SAlexander Motin switch (ai->ai_addr->sa_family) { 184829603e2SAlexander Motin case AF_INET: 185829603e2SAlexander Motin in4 = (struct sockaddr_in *)(void *)ai->ai_addr; 186829603e2SAlexander Motin be32enc(&buf, ntohs(in4->sin_port)); 187829603e2SAlexander Motin isns_req_add(req, tag, sizeof(buf), &buf); 188829603e2SAlexander Motin break; 189829603e2SAlexander Motin case AF_INET6: 190829603e2SAlexander Motin in6 = (struct sockaddr_in6 *)(void *)ai->ai_addr; 191829603e2SAlexander Motin be32enc(&buf, ntohs(in6->sin6_port)); 192829603e2SAlexander Motin isns_req_add(req, tag, sizeof(buf), &buf); 193829603e2SAlexander Motin break; 194829603e2SAlexander Motin default: 195829603e2SAlexander Motin log_errx(1, "Unsupported address family %d", 196829603e2SAlexander Motin ai->ai_addr->sa_family); 197829603e2SAlexander Motin } 198829603e2SAlexander Motin } 199829603e2SAlexander Motin 200829603e2SAlexander Motin int 201829603e2SAlexander Motin isns_req_send(int s, struct isns_req *req) 202829603e2SAlexander Motin { 203829603e2SAlexander Motin struct isns_hdr *hdr; 204829603e2SAlexander Motin int res; 205829603e2SAlexander Motin 206829603e2SAlexander Motin hdr = (struct isns_hdr *)req->ir_buf; 207829603e2SAlexander Motin be16enc(hdr->ih_length, req->ir_usedlen - sizeof(*hdr)); 208829603e2SAlexander Motin be16enc(hdr->ih_flags, be16dec(hdr->ih_flags) | 209829603e2SAlexander Motin ISNS_FLAG_LAST | ISNS_FLAG_FIRST); 210829603e2SAlexander Motin be16enc(hdr->ih_transaction, 0); 211829603e2SAlexander Motin be16enc(hdr->ih_sequence, 0); 212829603e2SAlexander Motin 213829603e2SAlexander Motin res = write(s, req->ir_buf, req->ir_usedlen); 214829603e2SAlexander Motin return ((res < 0) ? -1 : 0); 215829603e2SAlexander Motin } 216829603e2SAlexander Motin 217829603e2SAlexander Motin int 218829603e2SAlexander Motin isns_req_receive(int s, struct isns_req *req) 219829603e2SAlexander Motin { 220829603e2SAlexander Motin struct isns_hdr *hdr; 221829603e2SAlexander Motin ssize_t res, len; 222829603e2SAlexander Motin 223829603e2SAlexander Motin req->ir_usedlen = 0; 224829603e2SAlexander Motin isns_req_getspace(req, sizeof(*hdr)); 225829603e2SAlexander Motin res = read(s, req->ir_buf, sizeof(*hdr)); 226829603e2SAlexander Motin if (res < (ssize_t)sizeof(*hdr)) 227829603e2SAlexander Motin return (-1); 228829603e2SAlexander Motin req->ir_usedlen = sizeof(*hdr); 229829603e2SAlexander Motin hdr = (struct isns_hdr *)req->ir_buf; 230829603e2SAlexander Motin if (be16dec(hdr->ih_version) != ISNS_VERSION) 231829603e2SAlexander Motin return (-1); 232829603e2SAlexander Motin if ((be16dec(hdr->ih_flags) & (ISNS_FLAG_LAST | ISNS_FLAG_FIRST)) != 233829603e2SAlexander Motin (ISNS_FLAG_LAST | ISNS_FLAG_FIRST)) 234829603e2SAlexander Motin return (-1); 235829603e2SAlexander Motin len = be16dec(hdr->ih_length); 236829603e2SAlexander Motin isns_req_getspace(req, len); 237829603e2SAlexander Motin res = read(s, &req->ir_buf[req->ir_usedlen], len); 238829603e2SAlexander Motin if (res < len) 239829603e2SAlexander Motin return (-1); 240829603e2SAlexander Motin req->ir_usedlen += len; 241829603e2SAlexander Motin return (0); 242829603e2SAlexander Motin } 243829603e2SAlexander Motin 244829603e2SAlexander Motin uint32_t 245829603e2SAlexander Motin isns_req_get_status(struct isns_req *req) 246829603e2SAlexander Motin { 247829603e2SAlexander Motin 248829603e2SAlexander Motin if (req->ir_usedlen < sizeof(struct isns_hdr) + 4) 249829603e2SAlexander Motin return (-1); 250829603e2SAlexander Motin return (be32dec(&req->ir_buf[sizeof(struct isns_hdr)])); 251829603e2SAlexander Motin } 252