133965Sjdp/*- 233965Sjdp * Copyright (c) 2014 Alexander Motin <mav@FreeBSD.org> 377298Sobrien * All rights reserved. 477298Sobrien * 533965Sjdp * Redistribution and use in source and binary forms, with or without 633965Sjdp * modification, are permitted provided that the following conditions 733965Sjdp * are met: 833965Sjdp * 1. Redistributions of source code must retain the above copyright 933965Sjdp * notice, this list of conditions and the following disclaimer. 1033965Sjdp * 2. Redistributions in binary form must reproduce the above copyright 1133965Sjdp * notice, this list of conditions and the following disclaimer in the 1233965Sjdp * documentation and/or other materials provided with the distribution. 1333965Sjdp * 1433965Sjdp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1533965Sjdp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1633965Sjdp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1733965Sjdp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18218822Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19218822Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2033965Sjdp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2133965Sjdp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2233965Sjdp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2333965Sjdp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2433965Sjdp * SUCH DAMAGE. 2533965Sjdp * 2633965Sjdp */ 2733965Sjdp 2833965Sjdp#include <sys/cdefs.h> 2933965Sjdp__FBSDID("$FreeBSD$"); 3033965Sjdp 3133965Sjdp#include <sys/types.h> 3233965Sjdp#include <sys/time.h> 3333965Sjdp#include <sys/socket.h> 3433965Sjdp#include <sys/wait.h> 3533965Sjdp#include <sys/endian.h> 3633965Sjdp#include <netinet/in.h> 3733965Sjdp#include <arpa/inet.h> 3833965Sjdp#include <netdb.h> 3933965Sjdp#include <stdbool.h> 4033965Sjdp#include <stdlib.h> 4133965Sjdp#include <string.h> 4233965Sjdp#include <unistd.h> 4333965Sjdp 4433965Sjdp#include "ctld.h" 4533965Sjdp#include "isns.h" 4633965Sjdp 4733965Sjdpstruct isns_req * 4877298Sobrienisns_req_alloc(void) 4933965Sjdp{ 5033965Sjdp struct isns_req *req; 5133965Sjdp 5233965Sjdp req = calloc(sizeof(struct isns_req), 1); 5333965Sjdp if (req == NULL) { 5433965Sjdp log_err(1, "calloc"); 5533965Sjdp return (NULL); 5633965Sjdp } 5733965Sjdp req->ir_buflen = sizeof(struct isns_hdr); 5833965Sjdp req->ir_usedlen = 0; 5933965Sjdp req->ir_buf = calloc(req->ir_buflen, 1); 6033965Sjdp if (req->ir_buf == NULL) { 6133965Sjdp free(req); 6233965Sjdp log_err(1, "calloc"); 6333965Sjdp return (NULL); 6433965Sjdp } 6533965Sjdp return (req); 6633965Sjdp} 6733965Sjdp 68218822Sdimstruct isns_req * 6933965Sjdpisns_req_create(uint16_t func, uint16_t flags) 7033965Sjdp{ 7160484Sobrien struct isns_req *req; 7233965Sjdp struct isns_hdr *hdr; 7377298Sobrien 7433965Sjdp req = isns_req_alloc(); 7533965Sjdp req->ir_usedlen = sizeof(struct isns_hdr); 7633965Sjdp hdr = (struct isns_hdr *)req->ir_buf; 7733965Sjdp be16enc(hdr->ih_version, ISNS_VERSION); 7833965Sjdp be16enc(hdr->ih_function, func); 7933965Sjdp be16enc(hdr->ih_flags, flags); 8033965Sjdp return (req); 8133965Sjdp} 8233965Sjdp 8333965Sjdpvoid 8433965Sjdpisns_req_free(struct isns_req *req) 8533965Sjdp{ 8633965Sjdp 8733965Sjdp free(req->ir_buf); 8833965Sjdp free(req); 8933965Sjdp} 9033965Sjdp 9133965Sjdpstatic int 9233965Sjdpisns_req_getspace(struct isns_req *req, uint32_t len) 9333965Sjdp{ 9433965Sjdp void *newbuf; 9533965Sjdp int newlen; 9633965Sjdp 9760484Sobrien if (req->ir_usedlen + len <= req->ir_buflen) 9833965Sjdp return (0); 9933965Sjdp newlen = 1 << flsl(req->ir_usedlen + len); 10033965Sjdp newbuf = realloc(req->ir_buf, newlen); 10133965Sjdp if (newbuf == NULL) { 10233965Sjdp log_err(1, "realloc"); 10333965Sjdp return (1); 10433965Sjdp } 10533965Sjdp req->ir_buf = newbuf; 10633965Sjdp req->ir_buflen = newlen; 10733965Sjdp return (0); 10833965Sjdp} 10933965Sjdp 11033965Sjdpvoid 11133965Sjdpisns_req_add(struct isns_req *req, uint32_t tag, uint32_t len, 11233965Sjdp const void *value) 11333965Sjdp{ 11433965Sjdp struct isns_tlv *tlv; 11560484Sobrien uint32_t vlen; 11633965Sjdp 11733965Sjdp vlen = len + ((len & 3) ? (4 - (len & 3)) : 0); 11860484Sobrien isns_req_getspace(req, sizeof(*tlv) + vlen); 11933965Sjdp tlv = (struct isns_tlv *)&req->ir_buf[req->ir_usedlen]; 12033965Sjdp be32enc(tlv->it_tag, tag); 12133965Sjdp be32enc(tlv->it_length, vlen); 12233965Sjdp memcpy(tlv->it_value, value, len); 12333965Sjdp if (vlen != len) 12433965Sjdp memset(&tlv->it_value[len], 0, vlen - len); 12533965Sjdp req->ir_usedlen += sizeof(*tlv) + vlen; 12633965Sjdp} 127218822Sdim 12833965Sjdpvoid 12933965Sjdpisns_req_add_delim(struct isns_req *req) 13033965Sjdp{ 13133965Sjdp 13233965Sjdp isns_req_add(req, 0, 0, NULL); 13333965Sjdp} 13433965Sjdp 13533965Sjdpvoid 136218822Sdimisns_req_add_str(struct isns_req *req, uint32_t tag, const char *value) 137218822Sdim{ 13833965Sjdp 13933965Sjdp isns_req_add(req, tag, strlen(value) + 1, value); 14033965Sjdp} 14133965Sjdp 14233965Sjdpvoid 14360484Sobrienisns_req_add_32(struct isns_req *req, uint32_t tag, uint32_t value) 14433965Sjdp{ 14533965Sjdp uint32_t beval; 14633965Sjdp 14733965Sjdp be32enc(&beval, value); 14833965Sjdp isns_req_add(req, tag, sizeof(value), &beval); 14933965Sjdp} 15033965Sjdp 15133965Sjdpvoid 15233965Sjdpisns_req_add_addr(struct isns_req *req, uint32_t tag, struct addrinfo *ai) 15333965Sjdp{ 15433965Sjdp struct sockaddr_in *in4; 15533965Sjdp struct sockaddr_in6 *in6; 15633965Sjdp uint8_t buf[16]; 15733965Sjdp 15833965Sjdp switch (ai->ai_addr->sa_family) { 15933965Sjdp case AF_INET: 16033965Sjdp in4 = (struct sockaddr_in *)(void *)ai->ai_addr; 16133965Sjdp memset(buf, 0, 10); 16233965Sjdp buf[10] = 0xff; 16333965Sjdp buf[11] = 0xff; 16433965Sjdp memcpy(&buf[12], &in4->sin_addr, sizeof(in4->sin_addr)); 16533965Sjdp isns_req_add(req, tag, sizeof(buf), buf); 16633965Sjdp break; 16733965Sjdp case AF_INET6: 16833965Sjdp in6 = (struct sockaddr_in6 *)(void *)ai->ai_addr; 16933965Sjdp isns_req_add(req, tag, sizeof(in6->sin6_addr), &in6->sin6_addr); 17033965Sjdp break; 17133965Sjdp default: 17233965Sjdp log_errx(1, "Unsupported address family %d", 17360484Sobrien ai->ai_addr->sa_family); 17460484Sobrien } 17533965Sjdp} 17633965Sjdp 17733965Sjdpvoid 17833965Sjdpisns_req_add_port(struct isns_req *req, uint32_t tag, struct addrinfo *ai) 17933965Sjdp{ 180218822Sdim struct sockaddr_in *in4; 18133965Sjdp struct sockaddr_in6 *in6; 18233965Sjdp uint32_t buf; 18333965Sjdp 18433965Sjdp switch (ai->ai_addr->sa_family) { 18533965Sjdp case AF_INET: 18633965Sjdp in4 = (struct sockaddr_in *)(void *)ai->ai_addr; 18733965Sjdp be32enc(&buf, ntohs(in4->sin_port)); 18833965Sjdp isns_req_add(req, tag, sizeof(buf), &buf); 18933965Sjdp break; 19033965Sjdp case AF_INET6: 19133965Sjdp in6 = (struct sockaddr_in6 *)(void *)ai->ai_addr; 19233965Sjdp be32enc(&buf, ntohs(in6->sin6_port)); 19333965Sjdp isns_req_add(req, tag, sizeof(buf), &buf); 19433965Sjdp break; 19533965Sjdp default: 19633965Sjdp log_errx(1, "Unsupported address family %d", 197218822Sdim ai->ai_addr->sa_family); 19833965Sjdp } 19933965Sjdp} 20033965Sjdp 20133965Sjdpint 20233965Sjdpisns_req_send(int s, struct isns_req *req) 20360484Sobrien{ 20433965Sjdp struct isns_hdr *hdr; 20533965Sjdp int res; 20633965Sjdp 20733965Sjdp hdr = (struct isns_hdr *)req->ir_buf; 20833965Sjdp be16enc(hdr->ih_length, req->ir_usedlen - sizeof(*hdr)); 20933965Sjdp be16enc(hdr->ih_flags, be16dec(hdr->ih_flags) | 21033965Sjdp ISNS_FLAG_LAST | ISNS_FLAG_FIRST); 21133965Sjdp be16enc(hdr->ih_transaction, 0); 21233965Sjdp be16enc(hdr->ih_sequence, 0); 21333965Sjdp 21433965Sjdp res = write(s, req->ir_buf, req->ir_usedlen); 21533965Sjdp return ((res < 0) ? -1 : 0); 21633965Sjdp} 21733965Sjdp 21833965Sjdpint 21933965Sjdpisns_req_receive(int s, struct isns_req *req) 22033965Sjdp{ 221 struct isns_hdr *hdr; 222 ssize_t res, len; 223 224 req->ir_usedlen = 0; 225 isns_req_getspace(req, sizeof(*hdr)); 226 res = read(s, req->ir_buf, sizeof(*hdr)); 227 if (res < (ssize_t)sizeof(*hdr)) 228 return (-1); 229 req->ir_usedlen = sizeof(*hdr); 230 hdr = (struct isns_hdr *)req->ir_buf; 231 if (be16dec(hdr->ih_version) != ISNS_VERSION) 232 return (-1); 233 if ((be16dec(hdr->ih_flags) & (ISNS_FLAG_LAST | ISNS_FLAG_FIRST)) != 234 (ISNS_FLAG_LAST | ISNS_FLAG_FIRST)) 235 return (-1); 236 len = be16dec(hdr->ih_length); 237 isns_req_getspace(req, len); 238 res = read(s, &req->ir_buf[req->ir_usedlen], len); 239 if (res < len) 240 return (-1); 241 req->ir_usedlen += len; 242 return (0); 243} 244 245uint32_t 246isns_req_get_status(struct isns_req *req) 247{ 248 249 if (req->ir_usedlen < sizeof(struct isns_hdr) + 4) 250 return (-1); 251 return (be32dec(&req->ir_buf[sizeof(struct isns_hdr)])); 252} 253