1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2014 Alexander Motin <mav@FreeBSD.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 */
29
30 #include <sys/param.h>
31 #include <sys/time.h>
32 #include <sys/socket.h>
33 #include <sys/wait.h>
34 #include <sys/endian.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
37 #include <netdb.h>
38 #include <stdbool.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <unistd.h>
42
43 #include "ctld.hh"
44 #include "isns.hh"
45
isns_req(uint16_t func,uint16_t flags,const char * descr)46 isns_req::isns_req(uint16_t func, uint16_t flags, const char *descr)
47 : ir_descr(descr)
48 {
49 struct isns_hdr hdr;
50
51 be16enc(&hdr.ih_version, ISNS_VERSION);
52 be16enc(&hdr.ih_function, func);
53 be16enc(&hdr.ih_flags, flags);
54 append(&hdr, sizeof(hdr));
55 }
56
57 void
getspace(uint32_t len)58 isns_req::getspace(uint32_t len)
59 {
60 ir_buf.reserve(ir_buf.size() + len);
61 }
62
63 void
append(const void * buf,size_t len)64 isns_req::append(const void *buf, size_t len)
65 {
66 const char *cp = reinterpret_cast<const char *>(buf);
67 ir_buf.insert(ir_buf.end(), cp, cp + len);
68 }
69
70 void
add(uint32_t tag,uint32_t len,const void * value)71 isns_req::add(uint32_t tag, uint32_t len, const void *value)
72 {
73 struct isns_tlv tlv;
74 uint32_t vlen;
75
76 vlen = roundup2(len, 4);
77 getspace(sizeof(tlv) + vlen);
78 be32enc(&tlv.it_tag, tag);
79 be32enc(&tlv.it_length, vlen);
80 append(&tlv, sizeof(tlv));
81 append(value, len);
82 if (vlen != len)
83 ir_buf.insert(ir_buf.end(), vlen - len, 0);
84 }
85
86 void
add_delim()87 isns_req::add_delim()
88 {
89 add(0, 0, nullptr);
90 }
91
92 void
add_str(uint32_t tag,const char * value)93 isns_req::add_str(uint32_t tag, const char *value)
94 {
95
96 add(tag, strlen(value) + 1, value);
97 }
98
99 void
add_32(uint32_t tag,uint32_t value)100 isns_req::add_32(uint32_t tag, uint32_t value)
101 {
102 uint32_t beval;
103
104 be32enc(&beval, value);
105 add(tag, sizeof(value), &beval);
106 }
107
108 void
add_addr(uint32_t tag,const struct addrinfo * ai)109 isns_req::add_addr(uint32_t tag, const struct addrinfo *ai)
110 {
111 const struct sockaddr_in *in4;
112 const struct sockaddr_in6 *in6;
113 uint8_t buf[16];
114
115 switch (ai->ai_addr->sa_family) {
116 case AF_INET:
117 in4 = (const struct sockaddr_in *)ai->ai_addr;
118 memset(buf, 0, 10);
119 buf[10] = 0xff;
120 buf[11] = 0xff;
121 memcpy(&buf[12], &in4->sin_addr, sizeof(in4->sin_addr));
122 add(tag, sizeof(buf), buf);
123 break;
124 case AF_INET6:
125 in6 = (const struct sockaddr_in6 *)ai->ai_addr;
126 add(tag, sizeof(in6->sin6_addr), &in6->sin6_addr);
127 break;
128 default:
129 log_errx(1, "Unsupported address family %d",
130 ai->ai_addr->sa_family);
131 }
132 }
133
134 void
add_port(uint32_t tag,const struct addrinfo * ai)135 isns_req::add_port(uint32_t tag, const struct addrinfo *ai)
136 {
137 const struct sockaddr_in *in4;
138 const struct sockaddr_in6 *in6;
139 uint32_t buf;
140
141 switch (ai->ai_addr->sa_family) {
142 case AF_INET:
143 in4 = (const struct sockaddr_in *)ai->ai_addr;
144 be32enc(&buf, ntohs(in4->sin_port));
145 add(tag, sizeof(buf), &buf);
146 break;
147 case AF_INET6:
148 in6 = (const struct sockaddr_in6 *)ai->ai_addr;
149 be32enc(&buf, ntohs(in6->sin6_port));
150 add(tag, sizeof(buf), &buf);
151 break;
152 default:
153 log_errx(1, "Unsupported address family %d",
154 ai->ai_addr->sa_family);
155 }
156 }
157
158 bool
send(int s)159 isns_req::send(int s)
160 {
161 struct isns_hdr *hdr;
162 int res;
163
164 hdr = (struct isns_hdr *)ir_buf.data();
165 be16enc(hdr->ih_length, ir_buf.size() - sizeof(*hdr));
166 be16enc(hdr->ih_flags, be16dec(hdr->ih_flags) |
167 ISNS_FLAG_LAST | ISNS_FLAG_FIRST);
168 be16enc(hdr->ih_transaction, 0);
169 be16enc(hdr->ih_sequence, 0);
170
171 res = write(s, ir_buf.data(), ir_buf.size());
172 return (res > 0 && (size_t)res == ir_buf.size());
173 }
174
175 bool
receive(int s)176 isns_req::receive(int s)
177 {
178 struct isns_hdr *hdr;
179 ssize_t res, len;
180
181 ir_buf.resize(sizeof(*hdr));
182 res = read(s, ir_buf.data(), sizeof(*hdr));
183 if (res < (ssize_t)sizeof(*hdr)) {
184 ir_buf.clear();
185 return (false);
186 }
187 hdr = (struct isns_hdr *)ir_buf.data();
188 if (be16dec(hdr->ih_version) != ISNS_VERSION)
189 return (false);
190 if ((be16dec(hdr->ih_flags) & (ISNS_FLAG_LAST | ISNS_FLAG_FIRST)) !=
191 (ISNS_FLAG_LAST | ISNS_FLAG_FIRST))
192 return (false);
193 len = be16dec(hdr->ih_length);
194 ir_buf.resize(sizeof(*hdr) + len);
195 res = read(s, ir_buf.data() + sizeof(*hdr), len);
196 if (res < len)
197 return (false);
198 return (res == len);
199 }
200
201 uint32_t
get_status()202 isns_req::get_status()
203 {
204
205 if (ir_buf.size() < sizeof(struct isns_hdr) + 4)
206 return (-1);
207 return (be32dec(&ir_buf[sizeof(struct isns_hdr)]));
208 }
209