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