1273635Smav/*- 2273635Smav * Copyright (c) 2014 Alexander Motin <mav@FreeBSD.org> 3273635Smav * All rights reserved. 4273635Smav * 5273635Smav * Redistribution and use in source and binary forms, with or without 6273635Smav * modification, are permitted provided that the following conditions 7273635Smav * are met: 8273635Smav * 1. Redistributions of source code must retain the above copyright 9273635Smav * notice, this list of conditions and the following disclaimer. 10273635Smav * 2. Redistributions in binary form must reproduce the above copyright 11273635Smav * notice, this list of conditions and the following disclaimer in the 12273635Smav * documentation and/or other materials provided with the distribution. 13273635Smav * 14273635Smav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15273635Smav * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16273635Smav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17273635Smav * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18273635Smav * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19273635Smav * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20273635Smav * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21273635Smav * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22273635Smav * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23273635Smav * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24273635Smav * SUCH DAMAGE. 25273635Smav * 26273635Smav */ 27273635Smav 28273635Smav#include <sys/cdefs.h> 29273635Smav__FBSDID("$FreeBSD: releng/11.0/usr.sbin/ctld/isns.c 281532 2015-04-14 18:13:55Z delphij $"); 30273635Smav 31273635Smav#include <sys/types.h> 32273635Smav#include <sys/time.h> 33273635Smav#include <sys/socket.h> 34273635Smav#include <sys/wait.h> 35273635Smav#include <sys/endian.h> 36273635Smav#include <netinet/in.h> 37273635Smav#include <arpa/inet.h> 38273635Smav#include <netdb.h> 39273635Smav#include <stdbool.h> 40273635Smav#include <stdlib.h> 41273635Smav#include <string.h> 42273635Smav#include <unistd.h> 43273635Smav 44273635Smav#include "ctld.h" 45273635Smav#include "isns.h" 46273635Smav 47273635Smavstruct isns_req * 48273635Smavisns_req_alloc(void) 49273635Smav{ 50273635Smav struct isns_req *req; 51273635Smav 52273635Smav req = calloc(sizeof(struct isns_req), 1); 53273635Smav if (req == NULL) { 54273635Smav log_err(1, "calloc"); 55273635Smav return (NULL); 56273635Smav } 57273635Smav req->ir_buflen = sizeof(struct isns_hdr); 58273635Smav req->ir_usedlen = 0; 59273635Smav req->ir_buf = calloc(req->ir_buflen, 1); 60274797Strasz if (req->ir_buf == NULL) { 61273635Smav free(req); 62273635Smav log_err(1, "calloc"); 63273635Smav return (NULL); 64273635Smav } 65273635Smav return (req); 66273635Smav} 67273635Smav 68273635Smavstruct isns_req * 69273635Smavisns_req_create(uint16_t func, uint16_t flags) 70273635Smav{ 71273635Smav struct isns_req *req; 72273635Smav struct isns_hdr *hdr; 73273635Smav 74273635Smav req = isns_req_alloc(); 75273635Smav req->ir_usedlen = sizeof(struct isns_hdr); 76273635Smav hdr = (struct isns_hdr *)req->ir_buf; 77273635Smav be16enc(hdr->ih_version, ISNS_VERSION); 78273635Smav be16enc(hdr->ih_function, func); 79273635Smav be16enc(hdr->ih_flags, flags); 80273635Smav return (req); 81273635Smav} 82273635Smav 83273635Smavvoid 84273635Smavisns_req_free(struct isns_req *req) 85273635Smav{ 86273635Smav 87273635Smav free(req->ir_buf); 88273635Smav free(req); 89273635Smav} 90273635Smav 91273635Smavstatic int 92273635Smavisns_req_getspace(struct isns_req *req, uint32_t len) 93273635Smav{ 94273635Smav void *newbuf; 95273635Smav int newlen; 96273635Smav 97273635Smav if (req->ir_usedlen + len <= req->ir_buflen) 98273635Smav return (0); 99273635Smav newlen = 1 << flsl(req->ir_usedlen + len); 100273635Smav newbuf = realloc(req->ir_buf, newlen); 101273635Smav if (newbuf == NULL) { 102273635Smav log_err(1, "realloc"); 103273635Smav return (1); 104273635Smav } 105273635Smav req->ir_buf = newbuf; 106273635Smav req->ir_buflen = newlen; 107273635Smav return (0); 108273635Smav} 109273635Smav 110273635Smavvoid 111273635Smavisns_req_add(struct isns_req *req, uint32_t tag, uint32_t len, 112273635Smav const void *value) 113273635Smav{ 114273635Smav struct isns_tlv *tlv; 115273635Smav uint32_t vlen; 116273635Smav 117273635Smav vlen = len + ((len & 3) ? (4 - (len & 3)) : 0); 118273635Smav isns_req_getspace(req, sizeof(*tlv) + vlen); 119273635Smav tlv = (struct isns_tlv *)&req->ir_buf[req->ir_usedlen]; 120273635Smav be32enc(tlv->it_tag, tag); 121273635Smav be32enc(tlv->it_length, vlen); 122273635Smav memcpy(tlv->it_value, value, len); 123273635Smav if (vlen != len) 124273635Smav memset(&tlv->it_value[len], 0, vlen - len); 125273635Smav req->ir_usedlen += sizeof(*tlv) + vlen; 126273635Smav} 127273635Smav 128273635Smavvoid 129273635Smavisns_req_add_delim(struct isns_req *req) 130273635Smav{ 131273635Smav 132273635Smav isns_req_add(req, 0, 0, NULL); 133273635Smav} 134273635Smav 135273635Smavvoid 136273635Smavisns_req_add_str(struct isns_req *req, uint32_t tag, const char *value) 137273635Smav{ 138273635Smav 139273635Smav isns_req_add(req, tag, strlen(value) + 1, value); 140273635Smav} 141273635Smav 142273635Smavvoid 143273635Smavisns_req_add_32(struct isns_req *req, uint32_t tag, uint32_t value) 144273635Smav{ 145273635Smav uint32_t beval; 146273635Smav 147273635Smav be32enc(&beval, value); 148273635Smav isns_req_add(req, tag, sizeof(value), &beval); 149273635Smav} 150273635Smav 151273635Smavvoid 152273635Smavisns_req_add_addr(struct isns_req *req, uint32_t tag, struct addrinfo *ai) 153273635Smav{ 154273635Smav struct sockaddr_in *in4; 155273635Smav struct sockaddr_in6 *in6; 156273635Smav uint8_t buf[16]; 157273635Smav 158273635Smav switch (ai->ai_addr->sa_family) { 159273635Smav case AF_INET: 160273635Smav in4 = (struct sockaddr_in *)(void *)ai->ai_addr; 161273635Smav memset(buf, 0, 10); 162273635Smav buf[10] = 0xff; 163273635Smav buf[11] = 0xff; 164273635Smav memcpy(&buf[12], &in4->sin_addr, sizeof(in4->sin_addr)); 165273635Smav isns_req_add(req, tag, sizeof(buf), buf); 166273635Smav break; 167273635Smav case AF_INET6: 168273635Smav in6 = (struct sockaddr_in6 *)(void *)ai->ai_addr; 169273635Smav isns_req_add(req, tag, sizeof(in6->sin6_addr), &in6->sin6_addr); 170273635Smav break; 171273635Smav default: 172273635Smav log_errx(1, "Unsupported address family %d", 173273635Smav ai->ai_addr->sa_family); 174273635Smav } 175273635Smav} 176273635Smav 177273635Smavvoid 178273635Smavisns_req_add_port(struct isns_req *req, uint32_t tag, struct addrinfo *ai) 179273635Smav{ 180273635Smav struct sockaddr_in *in4; 181273635Smav struct sockaddr_in6 *in6; 182273635Smav uint32_t buf; 183273635Smav 184273635Smav switch (ai->ai_addr->sa_family) { 185273635Smav case AF_INET: 186273635Smav in4 = (struct sockaddr_in *)(void *)ai->ai_addr; 187273635Smav be32enc(&buf, ntohs(in4->sin_port)); 188273635Smav isns_req_add(req, tag, sizeof(buf), &buf); 189273635Smav break; 190273635Smav case AF_INET6: 191273635Smav in6 = (struct sockaddr_in6 *)(void *)ai->ai_addr; 192273635Smav be32enc(&buf, ntohs(in6->sin6_port)); 193273635Smav isns_req_add(req, tag, sizeof(buf), &buf); 194273635Smav break; 195273635Smav default: 196273635Smav log_errx(1, "Unsupported address family %d", 197273635Smav ai->ai_addr->sa_family); 198273635Smav } 199273635Smav} 200273635Smav 201273635Smavint 202273635Smavisns_req_send(int s, struct isns_req *req) 203273635Smav{ 204273635Smav struct isns_hdr *hdr; 205273635Smav int res; 206273635Smav 207273635Smav hdr = (struct isns_hdr *)req->ir_buf; 208273635Smav be16enc(hdr->ih_length, req->ir_usedlen - sizeof(*hdr)); 209273635Smav be16enc(hdr->ih_flags, be16dec(hdr->ih_flags) | 210273635Smav ISNS_FLAG_LAST | ISNS_FLAG_FIRST); 211273635Smav be16enc(hdr->ih_transaction, 0); 212273635Smav be16enc(hdr->ih_sequence, 0); 213273635Smav 214273635Smav res = write(s, req->ir_buf, req->ir_usedlen); 215273635Smav return ((res < 0) ? -1 : 0); 216273635Smav} 217273635Smav 218273635Smavint 219273635Smavisns_req_receive(int s, struct isns_req *req) 220273635Smav{ 221273635Smav struct isns_hdr *hdr; 222273635Smav ssize_t res, len; 223273635Smav 224273635Smav req->ir_usedlen = 0; 225273635Smav isns_req_getspace(req, sizeof(*hdr)); 226273635Smav res = read(s, req->ir_buf, sizeof(*hdr)); 227273635Smav if (res < (ssize_t)sizeof(*hdr)) 228273635Smav return (-1); 229273635Smav req->ir_usedlen = sizeof(*hdr); 230273635Smav hdr = (struct isns_hdr *)req->ir_buf; 231273635Smav if (be16dec(hdr->ih_version) != ISNS_VERSION) 232273635Smav return (-1); 233273635Smav if ((be16dec(hdr->ih_flags) & (ISNS_FLAG_LAST | ISNS_FLAG_FIRST)) != 234273635Smav (ISNS_FLAG_LAST | ISNS_FLAG_FIRST)) 235273635Smav return (-1); 236273635Smav len = be16dec(hdr->ih_length); 237273635Smav isns_req_getspace(req, len); 238273635Smav res = read(s, &req->ir_buf[req->ir_usedlen], len); 239273635Smav if (res < len) 240273635Smav return (-1); 241273635Smav req->ir_usedlen += len; 242273635Smav return (0); 243273635Smav} 244273635Smav 245273635Smavuint32_t 246273635Smavisns_req_get_status(struct isns_req *req) 247273635Smav{ 248273635Smav 249273635Smav if (req->ir_usedlen < sizeof(struct isns_hdr) + 4) 250273635Smav return (-1); 251273635Smav return (be32dec(&req->ir_buf[sizeof(struct isns_hdr)])); 252273635Smav} 253