]> git.proxmox.com Git - ceph.git/blob - ceph/src/msg/msg_types.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / msg / msg_types.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include "msg_types.h"
5
6 #include <arpa/inet.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <netdb.h>
10
11 #include <fmt/format.h>
12
13 #include "common/Formatter.h"
14
15 bool entity_name_t::parse(std::string_view s)
16 {
17 const char* start = s.data();
18 if (s.find("mon.") == 0) {
19 _type = TYPE_MON;
20 start += 4;
21 } else if (s.find("osd.") == 0) {
22 _type = TYPE_OSD;
23 start += 4;
24 } else if (s.find("mds.") == 0) {
25 _type = TYPE_MDS;
26 start += 4;
27 } else if (s.find("client.") == 0) {
28 _type = TYPE_CLIENT;
29 start += 7;
30 } else if (s.find("mgr.") == 0) {
31 _type = TYPE_MGR;
32 start += 4;
33 } else {
34 return false;
35 }
36 if (isspace(*start))
37 return false;
38 char *end = nullptr;
39 _num = strtoll(start, &end, 10);
40 if (end == nullptr || end == start) {
41 return false;
42 } else {
43 return end == s.data() + s.size();
44 }
45 }
46
47 void entity_name_t::dump(ceph::Formatter *f) const
48 {
49 f->dump_string("type", type_str());
50 f->dump_unsigned("num", num());
51 }
52
53 void entity_addr_t::dump(ceph::Formatter *f) const
54 {
55 f->dump_string("type", get_type_name(type));
56 f->dump_stream("addr") << get_sockaddr();
57 f->dump_unsigned("nonce", nonce);
58 }
59
60 void entity_inst_t::dump(ceph::Formatter *f) const
61 {
62 f->dump_object("name", name);
63 f->dump_object("addr", addr);
64 }
65
66 void entity_name_t::generate_test_instances(std::list<entity_name_t*>& o)
67 {
68 o.push_back(new entity_name_t(entity_name_t::MON()));
69 o.push_back(new entity_name_t(entity_name_t::MON(1)));
70 o.push_back(new entity_name_t(entity_name_t::OSD(1)));
71 o.push_back(new entity_name_t(entity_name_t::CLIENT(1)));
72 }
73
74 void entity_addr_t::generate_test_instances(std::list<entity_addr_t*>& o)
75 {
76 o.push_back(new entity_addr_t());
77 entity_addr_t *a = new entity_addr_t();
78 a->set_nonce(1);
79 o.push_back(a);
80 entity_addr_t *b = new entity_addr_t();
81 b->set_type(entity_addr_t::TYPE_LEGACY);
82 b->set_nonce(5);
83 b->set_family(AF_INET);
84 b->set_in4_quad(0, 127);
85 b->set_in4_quad(1, 0);
86 b->set_in4_quad(2, 1);
87 b->set_in4_quad(3, 2);
88 b->set_port(2);
89 o.push_back(b);
90 }
91
92 void entity_inst_t::generate_test_instances(std::list<entity_inst_t*>& o)
93 {
94 o.push_back(new entity_inst_t());
95 entity_name_t name;
96 entity_addr_t addr;
97 entity_inst_t *a = new entity_inst_t(name, addr);
98 o.push_back(a);
99 }
100
101 bool entity_addr_t::parse(const std::string_view s, int default_type)
102 {
103 const char* start = s.data();
104 const char* end = nullptr;
105 bool got = parse(start, &end, default_type);
106 return got && end == start + s.size();
107 }
108
109 bool entity_addr_t::parse(const char *s, const char **end, int default_type)
110 {
111 *this = entity_addr_t();
112
113 const char *start = s;
114 if (end) {
115 *end = s;
116 }
117
118 int newtype = default_type;
119 if (strncmp("v1:", s, 3) == 0) {
120 start += 3;
121 newtype = TYPE_LEGACY;
122 } else if (strncmp("v2:", s, 3) == 0) {
123 start += 3;
124 newtype = TYPE_MSGR2;
125 } else if (strncmp("any:", s, 4) == 0) {
126 start += 4;
127 newtype = TYPE_ANY;
128 } else if (*s == '-') {
129 newtype = TYPE_NONE;
130 if (end) {
131 *end = s + 1;
132 }
133 return true;
134 }
135
136 bool brackets = false;
137 if (*start == '[') {
138 start++;
139 brackets = true;
140 }
141
142 // inet_pton() requires a null terminated input, so let's fill two
143 // buffers, one with ipv4 allowed characters, and one with ipv6, and
144 // then see which parses.
145 char buf4[39];
146 char *o = buf4;
147 const char *p = start;
148 while (o < buf4 + sizeof(buf4) &&
149 *p && ((*p == '.') ||
150 (*p >= '0' && *p <= '9'))) {
151 *o++ = *p++;
152 }
153 *o = 0;
154
155 char buf6[64]; // actually 39 + null is sufficient.
156 o = buf6;
157 p = start;
158 while (o < buf6 + sizeof(buf6) &&
159 *p && ((*p == ':') ||
160 (*p >= '0' && *p <= '9') ||
161 (*p >= 'a' && *p <= 'f') ||
162 (*p >= 'A' && *p <= 'F'))) {
163 *o++ = *p++;
164 }
165 *o = 0;
166 //cout << "buf4 is '" << buf4 << "', buf6 is '" << buf6 << "'" << std::endl;
167
168 // ipv4?
169 struct in_addr a4;
170 struct in6_addr a6;
171 if (inet_pton(AF_INET, buf4, &a4)) {
172 u.sin.sin_addr.s_addr = a4.s_addr;
173 u.sa.sa_family = AF_INET;
174 p = start + strlen(buf4);
175 } else if (inet_pton(AF_INET6, buf6, &a6)) {
176 u.sa.sa_family = AF_INET6;
177 memcpy(&u.sin6.sin6_addr, &a6, sizeof(a6));
178 p = start + strlen(buf6);
179 } else {
180 return false;
181 }
182
183 if (brackets) {
184 if (*p != ']')
185 return false;
186 p++;
187 }
188
189 //cout << "p is " << *p << std::endl;
190 if (*p == ':') {
191 // parse a port, too!
192 p++;
193 int port = atoi(p);
194 if (port > MAX_PORT_NUMBER) {
195 return false;
196 }
197 set_port(port);
198 while (*p && *p >= '0' && *p <= '9')
199 p++;
200 }
201
202 if (*p == '/') {
203 // parse nonce, too
204 p++;
205 int non = atoi(p);
206 set_nonce(non);
207 while (*p && *p >= '0' && *p <= '9')
208 p++;
209 }
210
211 if (end)
212 *end = p;
213
214 type = newtype;
215
216 //cout << *this << std::endl;
217 return true;
218 }
219
220 std::ostream& operator<<(std::ostream& out, const entity_addr_t &addr)
221 {
222 if (addr.type == entity_addr_t::TYPE_NONE) {
223 return out << "-";
224 }
225 if (addr.type != entity_addr_t::TYPE_ANY) {
226 out << entity_addr_t::get_type_name(addr.type) << ":";
227 }
228 out << addr.get_sockaddr() << '/' << addr.nonce;
229 return out;
230 }
231
232 std::ostream& operator<<(std::ostream& out, const sockaddr *psa)
233 {
234 char buf[NI_MAXHOST] = { 0 };
235
236 switch (psa->sa_family) {
237 case AF_INET:
238 {
239 const sockaddr_in *sa = (const sockaddr_in*)psa;
240 inet_ntop(AF_INET, &sa->sin_addr, buf, NI_MAXHOST);
241 return out << buf << ':'
242 << ntohs(sa->sin_port);
243 }
244 case AF_INET6:
245 {
246 const sockaddr_in6 *sa = (const sockaddr_in6*)psa;
247 inet_ntop(AF_INET6, &sa->sin6_addr, buf, NI_MAXHOST);
248 return out << '[' << buf << "]:"
249 << ntohs(sa->sin6_port);
250 }
251 default:
252 return out << "(unrecognized address family " << psa->sa_family << ")";
253 }
254 }
255
256 std::ostream& operator<<(std::ostream& out, const sockaddr_storage &ss)
257 {
258 return out << (const sockaddr*)&ss;
259 }
260
261
262 // entity_addrvec_t
263
264 bool entity_addrvec_t::parse(const char *s, const char **end)
265 {
266 const char *orig_s = s;
267 const char *static_end;
268 if (!end) {
269 end = &static_end;
270 } else {
271 *end = s;
272 }
273 v.clear();
274 bool brackets = false;
275 if (*s == '[') {
276 // weirdness: make sure this isn't an IPV6 addr!
277 entity_addr_t a;
278 const char *p;
279 if (!a.parse(s, &p) || !a.is_ipv6()) {
280 // it's not
281 brackets = true;
282 ++s;
283 }
284 }
285 while (*s) {
286 entity_addr_t a;
287 bool r = a.parse(s, end);
288 if (!r) {
289 if (brackets) {
290 v.clear();
291 *end = orig_s;
292 return false;
293 }
294 break;
295 }
296 v.push_back(a);
297 s = *end;
298 if (!brackets) {
299 break;
300 }
301 if (*s != ',') {
302 break;
303 }
304 ++s;
305 }
306 if (brackets) {
307 if (*s == ']') {
308 ++s;
309 *end = s;
310 } else {
311 *end = orig_s;
312 v.clear();
313 return false;
314 }
315 }
316 return !v.empty();
317 }
318
319 void entity_addrvec_t::encode(ceph::buffer::list& bl, uint64_t features) const
320 {
321 using ceph::encode;
322 if ((features & CEPH_FEATURE_MSG_ADDR2) == 0) {
323 // encode a single legacy entity_addr_t for unfeatured peers
324 encode(legacy_addr(), bl, 0);
325 return;
326 }
327 encode((__u8)2, bl);
328 encode(v, bl, features);
329 }
330
331 void entity_addrvec_t::decode(ceph::buffer::list::const_iterator& bl)
332 {
333 using ceph::decode;
334 __u8 marker;
335 decode(marker, bl);
336 if (marker == 0) {
337 // legacy!
338 entity_addr_t addr;
339 addr.decode_legacy_addr_after_marker(bl);
340 v.clear();
341 v.push_back(addr);
342 return;
343 }
344 if (marker == 1) {
345 entity_addr_t addr;
346 DECODE_START(1, bl);
347 decode(addr.type, bl);
348 decode(addr.nonce, bl);
349 __u32 elen;
350 decode(elen, bl);
351 if (elen) {
352 struct sockaddr *sa = (struct sockaddr *)addr.get_sockaddr();
353 #if defined(__FreeBSD__) || defined(__APPLE__)
354 sa->sa_len = 0;
355 #endif
356 uint16_t ss_family;
357 if (elen < sizeof(ss_family)) {
358 throw ceph::buffer::malformed_input("elen smaller than family len");
359 }
360 decode(ss_family, bl);
361 sa->sa_family = ss_family;
362 elen -= sizeof(ss_family);
363 if (elen > addr.get_sockaddr_len() - sizeof(sa->sa_family)) {
364 throw ceph::buffer::malformed_input("elen exceeds sockaddr len");
365 }
366 bl.copy(elen, sa->sa_data);
367 }
368 DECODE_FINISH(bl);
369 v.clear();
370 v.push_back(addr);
371 return;
372 }
373 if (marker > 2)
374 throw ceph::buffer::malformed_input("entity_addrvec_marker > 2");
375 decode(v, bl);
376 }
377
378 void entity_addrvec_t::dump(ceph::Formatter *f) const
379 {
380 f->open_array_section("addrvec");
381 for (auto p = v.begin(); p != v.end(); ++p) {
382 f->dump_object("addr", *p);
383 }
384 f->close_section();
385 }
386
387 void entity_addrvec_t::generate_test_instances(std::list<entity_addrvec_t*>& ls)
388 {
389 ls.push_back(new entity_addrvec_t());
390 ls.push_back(new entity_addrvec_t());
391 ls.back()->v.push_back(entity_addr_t());
392 ls.push_back(new entity_addrvec_t());
393 ls.back()->v.push_back(entity_addr_t());
394 ls.back()->v.push_back(entity_addr_t());
395 }
396
397 std::string entity_addr_t::ip_only_to_str() const
398 {
399 const char *host_ip = NULL;
400 char addr_buf[INET6_ADDRSTRLEN];
401 switch (get_family()) {
402 case AF_INET:
403 host_ip = inet_ntop(AF_INET, &in4_addr().sin_addr,
404 addr_buf, INET_ADDRSTRLEN);
405 break;
406 case AF_INET6:
407 host_ip = inet_ntop(AF_INET6, &in6_addr().sin6_addr,
408 addr_buf, INET6_ADDRSTRLEN);
409 break;
410 default:
411 break;
412 }
413 return host_ip ? host_ip : "";
414 }
415
416 std::string entity_addr_t::ip_n_port_to_str() const
417 {
418 if (is_ipv6()) {
419 return fmt::format("[{}]:{}", ip_only_to_str(), get_port());
420 } else {
421 return fmt::format("{}:{}", ip_only_to_str(), get_port());
422 }
423 }