isns.c revision 273635
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: head/usr.sbin/ctld/isns.c 273635 2014-10-25 12:50:26Z mav $"); 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 <assert.h> 39273635Smav#include <ctype.h> 40273635Smav#include <errno.h> 41273635Smav#include <netdb.h> 42273635Smav#include <signal.h> 43273635Smav#include <stdbool.h> 44273635Smav#include <stdio.h> 45273635Smav#include <stdint.h> 46273635Smav#include <stdlib.h> 47273635Smav#include <string.h> 48273635Smav#include <unistd.h> 49273635Smav 50273635Smav#include "ctld.h" 51273635Smav#include "isns.h" 52273635Smav 53273635Smavstruct isns_req * 54273635Smavisns_req_alloc(void) 55273635Smav{ 56273635Smav struct isns_req *req; 57273635Smav 58273635Smav req = calloc(sizeof(struct isns_req), 1); 59273635Smav if (req == NULL) { 60273635Smav log_err(1, "calloc"); 61273635Smav return (NULL); 62273635Smav } 63273635Smav req->ir_buflen = sizeof(struct isns_hdr); 64273635Smav req->ir_usedlen = 0; 65273635Smav req->ir_buf = calloc(req->ir_buflen, 1); 66273635Smav if (req == NULL) { 67273635Smav free(req); 68273635Smav log_err(1, "calloc"); 69273635Smav return (NULL); 70273635Smav } 71273635Smav return (req); 72273635Smav} 73273635Smav 74273635Smavstruct isns_req * 75273635Smavisns_req_create(uint16_t func, uint16_t flags) 76273635Smav{ 77273635Smav struct isns_req *req; 78273635Smav struct isns_hdr *hdr; 79273635Smav 80273635Smav req = isns_req_alloc(); 81273635Smav req->ir_usedlen = sizeof(struct isns_hdr); 82273635Smav hdr = (struct isns_hdr *)req->ir_buf; 83273635Smav be16enc(hdr->ih_version, ISNS_VERSION); 84273635Smav be16enc(hdr->ih_function, func); 85273635Smav be16enc(hdr->ih_flags, flags); 86273635Smav return (req); 87273635Smav} 88273635Smav 89273635Smavvoid 90273635Smavisns_req_free(struct isns_req *req) 91273635Smav{ 92273635Smav 93273635Smav free(req->ir_buf); 94273635Smav free(req); 95273635Smav} 96273635Smav 97273635Smavstatic int 98273635Smavisns_req_getspace(struct isns_req *req, uint32_t len) 99273635Smav{ 100273635Smav void *newbuf; 101273635Smav int newlen; 102273635Smav 103273635Smav if (req->ir_usedlen + len <= req->ir_buflen) 104273635Smav return (0); 105273635Smav newlen = 1 << flsl(req->ir_usedlen + len); 106273635Smav newbuf = realloc(req->ir_buf, newlen); 107273635Smav if (newbuf == NULL) { 108273635Smav log_err(1, "realloc"); 109273635Smav return (1); 110273635Smav } 111273635Smav req->ir_buf = newbuf; 112273635Smav req->ir_buflen = newlen; 113273635Smav return (0); 114273635Smav} 115273635Smav 116273635Smavvoid 117273635Smavisns_req_add(struct isns_req *req, uint32_t tag, uint32_t len, 118273635Smav const void *value) 119273635Smav{ 120273635Smav struct isns_tlv *tlv; 121273635Smav uint32_t vlen; 122273635Smav 123273635Smav vlen = len + ((len & 3) ? (4 - (len & 3)) : 0); 124273635Smav isns_req_getspace(req, sizeof(*tlv) + vlen); 125273635Smav tlv = (struct isns_tlv *)&req->ir_buf[req->ir_usedlen]; 126273635Smav be32enc(tlv->it_tag, tag); 127273635Smav be32enc(tlv->it_length, vlen); 128273635Smav memcpy(tlv->it_value, value, len); 129273635Smav if (vlen != len) 130273635Smav memset(&tlv->it_value[len], 0, vlen - len); 131273635Smav req->ir_usedlen += sizeof(*tlv) + vlen; 132273635Smav} 133273635Smav 134273635Smavvoid 135273635Smavisns_req_add_delim(struct isns_req *req) 136273635Smav{ 137273635Smav 138273635Smav isns_req_add(req, 0, 0, NULL); 139273635Smav} 140273635Smav 141273635Smavvoid 142273635Smavisns_req_add_str(struct isns_req *req, uint32_t tag, const char *value) 143273635Smav{ 144273635Smav 145273635Smav isns_req_add(req, tag, strlen(value) + 1, value); 146273635Smav} 147273635Smav 148273635Smavvoid 149273635Smavisns_req_add_32(struct isns_req *req, uint32_t tag, uint32_t value) 150273635Smav{ 151273635Smav uint32_t beval; 152273635Smav 153273635Smav be32enc(&beval, value); 154273635Smav isns_req_add(req, tag, sizeof(value), &beval); 155273635Smav} 156273635Smav 157273635Smavvoid 158273635Smavisns_req_add_addr(struct isns_req *req, uint32_t tag, struct addrinfo *ai) 159273635Smav{ 160273635Smav struct sockaddr_in *in4; 161273635Smav struct sockaddr_in6 *in6; 162273635Smav uint8_t buf[16]; 163273635Smav 164273635Smav switch (ai->ai_addr->sa_family) { 165273635Smav case AF_INET: 166273635Smav in4 = (struct sockaddr_in *)(void *)ai->ai_addr; 167273635Smav memset(buf, 0, 10); 168273635Smav buf[10] = 0xff; 169273635Smav buf[11] = 0xff; 170273635Smav memcpy(&buf[12], &in4->sin_addr, sizeof(in4->sin_addr)); 171273635Smav isns_req_add(req, tag, sizeof(buf), buf); 172273635Smav break; 173273635Smav case AF_INET6: 174273635Smav in6 = (struct sockaddr_in6 *)(void *)ai->ai_addr; 175273635Smav isns_req_add(req, tag, sizeof(in6->sin6_addr), &in6->sin6_addr); 176273635Smav break; 177273635Smav default: 178273635Smav log_errx(1, "Unsupported address family %d", 179273635Smav ai->ai_addr->sa_family); 180273635Smav } 181273635Smav} 182273635Smav 183273635Smavvoid 184273635Smavisns_req_add_port(struct isns_req *req, uint32_t tag, struct addrinfo *ai) 185273635Smav{ 186273635Smav struct sockaddr_in *in4; 187273635Smav struct sockaddr_in6 *in6; 188273635Smav uint32_t buf; 189273635Smav 190273635Smav switch (ai->ai_addr->sa_family) { 191273635Smav case AF_INET: 192273635Smav in4 = (struct sockaddr_in *)(void *)ai->ai_addr; 193273635Smav be32enc(&buf, ntohs(in4->sin_port)); 194273635Smav isns_req_add(req, tag, sizeof(buf), &buf); 195273635Smav break; 196273635Smav case AF_INET6: 197273635Smav in6 = (struct sockaddr_in6 *)(void *)ai->ai_addr; 198273635Smav be32enc(&buf, ntohs(in6->sin6_port)); 199273635Smav isns_req_add(req, tag, sizeof(buf), &buf); 200273635Smav break; 201273635Smav default: 202273635Smav log_errx(1, "Unsupported address family %d", 203273635Smav ai->ai_addr->sa_family); 204273635Smav } 205273635Smav} 206273635Smav 207273635Smavint 208273635Smavisns_req_send(int s, struct isns_req *req) 209273635Smav{ 210273635Smav struct isns_hdr *hdr; 211273635Smav int res; 212273635Smav 213273635Smav hdr = (struct isns_hdr *)req->ir_buf; 214273635Smav be16enc(hdr->ih_length, req->ir_usedlen - sizeof(*hdr)); 215273635Smav be16enc(hdr->ih_flags, be16dec(hdr->ih_flags) | 216273635Smav ISNS_FLAG_LAST | ISNS_FLAG_FIRST); 217273635Smav be16enc(hdr->ih_transaction, 0); 218273635Smav be16enc(hdr->ih_sequence, 0); 219273635Smav 220273635Smav res = write(s, req->ir_buf, req->ir_usedlen); 221273635Smav return ((res < 0) ? -1 : 0); 222273635Smav} 223273635Smav 224273635Smavint 225273635Smavisns_req_receive(int s, struct isns_req *req) 226273635Smav{ 227273635Smav struct isns_hdr *hdr; 228273635Smav ssize_t res, len; 229273635Smav 230273635Smav req->ir_usedlen = 0; 231273635Smav isns_req_getspace(req, sizeof(*hdr)); 232273635Smav res = read(s, req->ir_buf, sizeof(*hdr)); 233273635Smav if (res < (ssize_t)sizeof(*hdr)) 234273635Smav return (-1); 235273635Smav req->ir_usedlen = sizeof(*hdr); 236273635Smav hdr = (struct isns_hdr *)req->ir_buf; 237273635Smav if (be16dec(hdr->ih_version) != ISNS_VERSION) 238273635Smav return (-1); 239273635Smav if ((be16dec(hdr->ih_flags) & (ISNS_FLAG_LAST | ISNS_FLAG_FIRST)) != 240273635Smav (ISNS_FLAG_LAST | ISNS_FLAG_FIRST)) 241273635Smav return (-1); 242273635Smav len = be16dec(hdr->ih_length); 243273635Smav isns_req_getspace(req, len); 244273635Smav res = read(s, &req->ir_buf[req->ir_usedlen], len); 245273635Smav if (res < len) 246273635Smav return (-1); 247273635Smav req->ir_usedlen += len; 248273635Smav return (0); 249273635Smav} 250273635Smav 251273635Smavuint32_t 252273635Smavisns_req_get_status(struct isns_req *req) 253273635Smav{ 254273635Smav 255273635Smav if (req->ir_usedlen < sizeof(struct isns_hdr) + 4) 256273635Smav return (-1); 257273635Smav return (be32dec(&req->ir_buf[sizeof(struct isns_hdr)])); 258273635Smav} 259