1*829603e2SAlexander Motin /*- 2*829603e2SAlexander Motin * Copyright (c) 2014 Alexander Motin <mav@FreeBSD.org> 3*829603e2SAlexander Motin * All rights reserved. 4*829603e2SAlexander Motin * 5*829603e2SAlexander Motin * Redistribution and use in source and binary forms, with or without 6*829603e2SAlexander Motin * modification, are permitted provided that the following conditions 7*829603e2SAlexander Motin * are met: 8*829603e2SAlexander Motin * 1. Redistributions of source code must retain the above copyright 9*829603e2SAlexander Motin * notice, this list of conditions and the following disclaimer. 10*829603e2SAlexander Motin * 2. Redistributions in binary form must reproduce the above copyright 11*829603e2SAlexander Motin * notice, this list of conditions and the following disclaimer in the 12*829603e2SAlexander Motin * documentation and/or other materials provided with the distribution. 13*829603e2SAlexander Motin * 14*829603e2SAlexander Motin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15*829603e2SAlexander Motin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16*829603e2SAlexander Motin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17*829603e2SAlexander Motin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18*829603e2SAlexander Motin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19*829603e2SAlexander Motin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20*829603e2SAlexander Motin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21*829603e2SAlexander Motin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22*829603e2SAlexander Motin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23*829603e2SAlexander Motin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24*829603e2SAlexander Motin * SUCH DAMAGE. 25*829603e2SAlexander Motin * 26*829603e2SAlexander Motin */ 27*829603e2SAlexander Motin 28*829603e2SAlexander Motin #include <sys/cdefs.h> 29*829603e2SAlexander Motin __FBSDID("$FreeBSD$"); 30*829603e2SAlexander Motin 31*829603e2SAlexander Motin #include <sys/types.h> 32*829603e2SAlexander Motin #include <sys/time.h> 33*829603e2SAlexander Motin #include <sys/socket.h> 34*829603e2SAlexander Motin #include <sys/wait.h> 35*829603e2SAlexander Motin #include <sys/endian.h> 36*829603e2SAlexander Motin #include <netinet/in.h> 37*829603e2SAlexander Motin #include <arpa/inet.h> 38*829603e2SAlexander Motin #include <assert.h> 39*829603e2SAlexander Motin #include <ctype.h> 40*829603e2SAlexander Motin #include <errno.h> 41*829603e2SAlexander Motin #include <netdb.h> 42*829603e2SAlexander Motin #include <signal.h> 43*829603e2SAlexander Motin #include <stdbool.h> 44*829603e2SAlexander Motin #include <stdio.h> 45*829603e2SAlexander Motin #include <stdint.h> 46*829603e2SAlexander Motin #include <stdlib.h> 47*829603e2SAlexander Motin #include <string.h> 48*829603e2SAlexander Motin #include <unistd.h> 49*829603e2SAlexander Motin 50*829603e2SAlexander Motin #include "ctld.h" 51*829603e2SAlexander Motin #include "isns.h" 52*829603e2SAlexander Motin 53*829603e2SAlexander Motin struct isns_req * 54*829603e2SAlexander Motin isns_req_alloc(void) 55*829603e2SAlexander Motin { 56*829603e2SAlexander Motin struct isns_req *req; 57*829603e2SAlexander Motin 58*829603e2SAlexander Motin req = calloc(sizeof(struct isns_req), 1); 59*829603e2SAlexander Motin if (req == NULL) { 60*829603e2SAlexander Motin log_err(1, "calloc"); 61*829603e2SAlexander Motin return (NULL); 62*829603e2SAlexander Motin } 63*829603e2SAlexander Motin req->ir_buflen = sizeof(struct isns_hdr); 64*829603e2SAlexander Motin req->ir_usedlen = 0; 65*829603e2SAlexander Motin req->ir_buf = calloc(req->ir_buflen, 1); 66*829603e2SAlexander Motin if (req == NULL) { 67*829603e2SAlexander Motin free(req); 68*829603e2SAlexander Motin log_err(1, "calloc"); 69*829603e2SAlexander Motin return (NULL); 70*829603e2SAlexander Motin } 71*829603e2SAlexander Motin return (req); 72*829603e2SAlexander Motin } 73*829603e2SAlexander Motin 74*829603e2SAlexander Motin struct isns_req * 75*829603e2SAlexander Motin isns_req_create(uint16_t func, uint16_t flags) 76*829603e2SAlexander Motin { 77*829603e2SAlexander Motin struct isns_req *req; 78*829603e2SAlexander Motin struct isns_hdr *hdr; 79*829603e2SAlexander Motin 80*829603e2SAlexander Motin req = isns_req_alloc(); 81*829603e2SAlexander Motin req->ir_usedlen = sizeof(struct isns_hdr); 82*829603e2SAlexander Motin hdr = (struct isns_hdr *)req->ir_buf; 83*829603e2SAlexander Motin be16enc(hdr->ih_version, ISNS_VERSION); 84*829603e2SAlexander Motin be16enc(hdr->ih_function, func); 85*829603e2SAlexander Motin be16enc(hdr->ih_flags, flags); 86*829603e2SAlexander Motin return (req); 87*829603e2SAlexander Motin } 88*829603e2SAlexander Motin 89*829603e2SAlexander Motin void 90*829603e2SAlexander Motin isns_req_free(struct isns_req *req) 91*829603e2SAlexander Motin { 92*829603e2SAlexander Motin 93*829603e2SAlexander Motin free(req->ir_buf); 94*829603e2SAlexander Motin free(req); 95*829603e2SAlexander Motin } 96*829603e2SAlexander Motin 97*829603e2SAlexander Motin static int 98*829603e2SAlexander Motin isns_req_getspace(struct isns_req *req, uint32_t len) 99*829603e2SAlexander Motin { 100*829603e2SAlexander Motin void *newbuf; 101*829603e2SAlexander Motin int newlen; 102*829603e2SAlexander Motin 103*829603e2SAlexander Motin if (req->ir_usedlen + len <= req->ir_buflen) 104*829603e2SAlexander Motin return (0); 105*829603e2SAlexander Motin newlen = 1 << flsl(req->ir_usedlen + len); 106*829603e2SAlexander Motin newbuf = realloc(req->ir_buf, newlen); 107*829603e2SAlexander Motin if (newbuf == NULL) { 108*829603e2SAlexander Motin log_err(1, "realloc"); 109*829603e2SAlexander Motin return (1); 110*829603e2SAlexander Motin } 111*829603e2SAlexander Motin req->ir_buf = newbuf; 112*829603e2SAlexander Motin req->ir_buflen = newlen; 113*829603e2SAlexander Motin return (0); 114*829603e2SAlexander Motin } 115*829603e2SAlexander Motin 116*829603e2SAlexander Motin void 117*829603e2SAlexander Motin isns_req_add(struct isns_req *req, uint32_t tag, uint32_t len, 118*829603e2SAlexander Motin const void *value) 119*829603e2SAlexander Motin { 120*829603e2SAlexander Motin struct isns_tlv *tlv; 121*829603e2SAlexander Motin uint32_t vlen; 122*829603e2SAlexander Motin 123*829603e2SAlexander Motin vlen = len + ((len & 3) ? (4 - (len & 3)) : 0); 124*829603e2SAlexander Motin isns_req_getspace(req, sizeof(*tlv) + vlen); 125*829603e2SAlexander Motin tlv = (struct isns_tlv *)&req->ir_buf[req->ir_usedlen]; 126*829603e2SAlexander Motin be32enc(tlv->it_tag, tag); 127*829603e2SAlexander Motin be32enc(tlv->it_length, vlen); 128*829603e2SAlexander Motin memcpy(tlv->it_value, value, len); 129*829603e2SAlexander Motin if (vlen != len) 130*829603e2SAlexander Motin memset(&tlv->it_value[len], 0, vlen - len); 131*829603e2SAlexander Motin req->ir_usedlen += sizeof(*tlv) + vlen; 132*829603e2SAlexander Motin } 133*829603e2SAlexander Motin 134*829603e2SAlexander Motin void 135*829603e2SAlexander Motin isns_req_add_delim(struct isns_req *req) 136*829603e2SAlexander Motin { 137*829603e2SAlexander Motin 138*829603e2SAlexander Motin isns_req_add(req, 0, 0, NULL); 139*829603e2SAlexander Motin } 140*829603e2SAlexander Motin 141*829603e2SAlexander Motin void 142*829603e2SAlexander Motin isns_req_add_str(struct isns_req *req, uint32_t tag, const char *value) 143*829603e2SAlexander Motin { 144*829603e2SAlexander Motin 145*829603e2SAlexander Motin isns_req_add(req, tag, strlen(value) + 1, value); 146*829603e2SAlexander Motin } 147*829603e2SAlexander Motin 148*829603e2SAlexander Motin void 149*829603e2SAlexander Motin isns_req_add_32(struct isns_req *req, uint32_t tag, uint32_t value) 150*829603e2SAlexander Motin { 151*829603e2SAlexander Motin uint32_t beval; 152*829603e2SAlexander Motin 153*829603e2SAlexander Motin be32enc(&beval, value); 154*829603e2SAlexander Motin isns_req_add(req, tag, sizeof(value), &beval); 155*829603e2SAlexander Motin } 156*829603e2SAlexander Motin 157*829603e2SAlexander Motin void 158*829603e2SAlexander Motin isns_req_add_addr(struct isns_req *req, uint32_t tag, struct addrinfo *ai) 159*829603e2SAlexander Motin { 160*829603e2SAlexander Motin struct sockaddr_in *in4; 161*829603e2SAlexander Motin struct sockaddr_in6 *in6; 162*829603e2SAlexander Motin uint8_t buf[16]; 163*829603e2SAlexander Motin 164*829603e2SAlexander Motin switch (ai->ai_addr->sa_family) { 165*829603e2SAlexander Motin case AF_INET: 166*829603e2SAlexander Motin in4 = (struct sockaddr_in *)(void *)ai->ai_addr; 167*829603e2SAlexander Motin memset(buf, 0, 10); 168*829603e2SAlexander Motin buf[10] = 0xff; 169*829603e2SAlexander Motin buf[11] = 0xff; 170*829603e2SAlexander Motin memcpy(&buf[12], &in4->sin_addr, sizeof(in4->sin_addr)); 171*829603e2SAlexander Motin isns_req_add(req, tag, sizeof(buf), buf); 172*829603e2SAlexander Motin break; 173*829603e2SAlexander Motin case AF_INET6: 174*829603e2SAlexander Motin in6 = (struct sockaddr_in6 *)(void *)ai->ai_addr; 175*829603e2SAlexander Motin isns_req_add(req, tag, sizeof(in6->sin6_addr), &in6->sin6_addr); 176*829603e2SAlexander Motin break; 177*829603e2SAlexander Motin default: 178*829603e2SAlexander Motin log_errx(1, "Unsupported address family %d", 179*829603e2SAlexander Motin ai->ai_addr->sa_family); 180*829603e2SAlexander Motin } 181*829603e2SAlexander Motin } 182*829603e2SAlexander Motin 183*829603e2SAlexander Motin void 184*829603e2SAlexander Motin isns_req_add_port(struct isns_req *req, uint32_t tag, struct addrinfo *ai) 185*829603e2SAlexander Motin { 186*829603e2SAlexander Motin struct sockaddr_in *in4; 187*829603e2SAlexander Motin struct sockaddr_in6 *in6; 188*829603e2SAlexander Motin uint32_t buf; 189*829603e2SAlexander Motin 190*829603e2SAlexander Motin switch (ai->ai_addr->sa_family) { 191*829603e2SAlexander Motin case AF_INET: 192*829603e2SAlexander Motin in4 = (struct sockaddr_in *)(void *)ai->ai_addr; 193*829603e2SAlexander Motin be32enc(&buf, ntohs(in4->sin_port)); 194*829603e2SAlexander Motin isns_req_add(req, tag, sizeof(buf), &buf); 195*829603e2SAlexander Motin break; 196*829603e2SAlexander Motin case AF_INET6: 197*829603e2SAlexander Motin in6 = (struct sockaddr_in6 *)(void *)ai->ai_addr; 198*829603e2SAlexander Motin be32enc(&buf, ntohs(in6->sin6_port)); 199*829603e2SAlexander Motin isns_req_add(req, tag, sizeof(buf), &buf); 200*829603e2SAlexander Motin break; 201*829603e2SAlexander Motin default: 202*829603e2SAlexander Motin log_errx(1, "Unsupported address family %d", 203*829603e2SAlexander Motin ai->ai_addr->sa_family); 204*829603e2SAlexander Motin } 205*829603e2SAlexander Motin } 206*829603e2SAlexander Motin 207*829603e2SAlexander Motin int 208*829603e2SAlexander Motin isns_req_send(int s, struct isns_req *req) 209*829603e2SAlexander Motin { 210*829603e2SAlexander Motin struct isns_hdr *hdr; 211*829603e2SAlexander Motin int res; 212*829603e2SAlexander Motin 213*829603e2SAlexander Motin hdr = (struct isns_hdr *)req->ir_buf; 214*829603e2SAlexander Motin be16enc(hdr->ih_length, req->ir_usedlen - sizeof(*hdr)); 215*829603e2SAlexander Motin be16enc(hdr->ih_flags, be16dec(hdr->ih_flags) | 216*829603e2SAlexander Motin ISNS_FLAG_LAST | ISNS_FLAG_FIRST); 217*829603e2SAlexander Motin be16enc(hdr->ih_transaction, 0); 218*829603e2SAlexander Motin be16enc(hdr->ih_sequence, 0); 219*829603e2SAlexander Motin 220*829603e2SAlexander Motin res = write(s, req->ir_buf, req->ir_usedlen); 221*829603e2SAlexander Motin return ((res < 0) ? -1 : 0); 222*829603e2SAlexander Motin } 223*829603e2SAlexander Motin 224*829603e2SAlexander Motin int 225*829603e2SAlexander Motin isns_req_receive(int s, struct isns_req *req) 226*829603e2SAlexander Motin { 227*829603e2SAlexander Motin struct isns_hdr *hdr; 228*829603e2SAlexander Motin ssize_t res, len; 229*829603e2SAlexander Motin 230*829603e2SAlexander Motin req->ir_usedlen = 0; 231*829603e2SAlexander Motin isns_req_getspace(req, sizeof(*hdr)); 232*829603e2SAlexander Motin res = read(s, req->ir_buf, sizeof(*hdr)); 233*829603e2SAlexander Motin if (res < (ssize_t)sizeof(*hdr)) 234*829603e2SAlexander Motin return (-1); 235*829603e2SAlexander Motin req->ir_usedlen = sizeof(*hdr); 236*829603e2SAlexander Motin hdr = (struct isns_hdr *)req->ir_buf; 237*829603e2SAlexander Motin if (be16dec(hdr->ih_version) != ISNS_VERSION) 238*829603e2SAlexander Motin return (-1); 239*829603e2SAlexander Motin if ((be16dec(hdr->ih_flags) & (ISNS_FLAG_LAST | ISNS_FLAG_FIRST)) != 240*829603e2SAlexander Motin (ISNS_FLAG_LAST | ISNS_FLAG_FIRST)) 241*829603e2SAlexander Motin return (-1); 242*829603e2SAlexander Motin len = be16dec(hdr->ih_length); 243*829603e2SAlexander Motin isns_req_getspace(req, len); 244*829603e2SAlexander Motin res = read(s, &req->ir_buf[req->ir_usedlen], len); 245*829603e2SAlexander Motin if (res < len) 246*829603e2SAlexander Motin return (-1); 247*829603e2SAlexander Motin req->ir_usedlen += len; 248*829603e2SAlexander Motin return (0); 249*829603e2SAlexander Motin } 250*829603e2SAlexander Motin 251*829603e2SAlexander Motin uint32_t 252*829603e2SAlexander Motin isns_req_get_status(struct isns_req *req) 253*829603e2SAlexander Motin { 254*829603e2SAlexander Motin 255*829603e2SAlexander Motin if (req->ir_usedlen < sizeof(struct isns_hdr) + 4) 256*829603e2SAlexander Motin return (-1); 257*829603e2SAlexander Motin return (be32dec(&req->ir_buf[sizeof(struct isns_hdr)])); 258*829603e2SAlexander Motin } 259