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