Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/usr.sbin/ctld/isns.cc
104133 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2014 Alexander Motin <[email protected]>
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
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
58
isns_req::getspace(uint32_t len)
59
{
60
ir_buf.reserve(ir_buf.size() + len);
61
}
62
63
void
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
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
87
isns_req::add_delim()
88
{
89
add(0, 0, nullptr);
90
}
91
92
void
93
isns_req::add_str(uint32_t tag, const char *value)
94
{
95
96
add(tag, strlen(value) + 1, value);
97
}
98
99
void
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
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
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
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
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
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
210