Use LTTngUSTLogger logger plugin in logtest regression test
[deliverable/titan.core.git] / common / NetworkHandler.cc
CommitLineData
d44e3c4f 1/******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * Balasko, Jeno
10 * Beres, Szabolcs
11 * Delic, Adam
12 * Kovacs, Ferenc
13 * Raduly, Csaba
14 *
15 ******************************************************************************/
970ed795
EL
16#include "NetworkHandler.hh"
17
18#include <stdio.h>
19#include <string.h>
20#include <errno.h>
21
22#include <sys/types.h>
23#include <arpa/inet.h>
24#include <netinet/tcp.h>
25
26#include "memory.h"
27#include "../core/Textbuf.hh"
28
29IPAddress::~IPAddress() { }
30
31NetworkHandler::NetworkHandler() : m_family(ipv4) { }
32
33void NetworkHandler::set_family(const char *p_addr)
34{
35 if (!p_addr || IPv4Address::is_valid(p_addr)) m_family = ipv4;
36#if defined(LINUX) || defined(CYGWIN17)
37 else if (IPv6Address::is_valid(p_addr)) m_family = ipv6;
38#endif
39 else m_family = ipv0;
40}
41
42int NetworkHandler::socket()
43{
44 return socket(m_family);
45}
46
47int NetworkHandler::socket(const NetworkFamily& p_family)
48{
49#if defined(LINUX) || defined(CYGWIN17)
50 return ::socket(p_family == ipv4 ? AF_INET : AF_INET6, SOCK_STREAM, 0);
51#else
52 (void)p_family;
53 return ::socket(AF_INET, SOCK_STREAM, 0);
54#endif
55}
56
57HCNetworkHandler::HCNetworkHandler() : m_mc_addr(NULL), m_local_addr(NULL) { }
58
59HCNetworkHandler::~HCNetworkHandler()
60{
61 delete m_mc_addr;
62 delete m_local_addr;
63}
64
65bool HCNetworkHandler::set_local_addr(const char *p_addr, unsigned short p_port)
66{
67 if (!p_addr) return false;
68 switch (m_family) {
69 case ipv4: m_local_addr = new IPv4Address(p_addr, p_port); break;
70#if defined(LINUX) || defined(CYGWIN17)
71 case ipv6: m_local_addr = new IPv6Address(p_addr, p_port); break;
72#endif
73 default:
74 break;
75 }
76 return m_local_addr != NULL;
77}
78
79bool HCNetworkHandler::set_mc_addr(const char *p_addr, unsigned short p_port)
80{
81 if (!p_addr) return false;
82 switch (m_family) {
83 case ipv4: m_mc_addr = new IPv4Address(p_addr, p_port); break;
84#if defined(LINUX) || defined(CYGWIN17)
85 case ipv6: m_mc_addr = new IPv6Address(p_addr, p_port); break;
86#endif
87 default:
88 break;
89 }
90 return m_mc_addr != NULL;
91}
92
93int HCNetworkHandler::getsockname_local_addr(int p_sockfd)
94{
95 if (m_local_addr != NULL) delete m_local_addr;
96 switch (m_family) {
97 case ipv4: m_local_addr = new IPv4Address(); break;
98#if defined(LINUX) || defined(CYGWIN17)
99 case ipv6: m_local_addr = new IPv6Address(); break;
100#endif
101 default: return -1;
102 }
103 return m_local_addr->getsockname(p_sockfd);
104}
105
106int HCNetworkHandler::bind_local_addr(int p_sockfd) const
107{
108 m_local_addr->set_port(0);
109 return ::bind(p_sockfd, m_local_addr->get_addr(), m_local_addr->get_addr_len());
110}
111
112#ifdef SOLARIS
113#define CAST_AWAY_CONST_FOR_SOLARIS6 (sockaddr *)
114#else
115#define CAST_AWAY_CONST_FOR_SOLARIS6
116#endif
117
118int HCNetworkHandler::connect_to_mc(int p_sockfd) const
119{
120 return ::connect(p_sockfd, CAST_AWAY_CONST_FOR_SOLARIS6 m_mc_addr->get_addr(),
121 m_mc_addr->get_addr_len());
122}
123
124IPAddress *IPAddress::create_addr(const NetworkFamily& p_family)
125{
126 switch (p_family) {
127 case ipv4:
128 return new IPv4Address();
129#if defined(LINUX) || defined(CYGWIN17)
130 case ipv6:
131 return new IPv6Address();
132#endif
133 default:
134 return NULL;
135 }
136}
137
138IPAddress *IPAddress::create_addr(const char *p_addr)
139{
140 if (p_addr == NULL)
141 return NULL;
142 if (IPv4Address::is_valid(p_addr))
143 return new IPv4Address(p_addr);
144#if defined(LINUX) || defined(CYGWIN17)
145 else if (IPv6Address::is_valid(p_addr))
146 return new IPv6Address(p_addr);
147#endif
148 else
149 return NULL;
150}
151
152IPv4Address::IPv4Address()
153{
154 clean_up();
155 m_addr.sin_family = AF_INET;
156 m_addr.sin_addr.s_addr = htonl(INADDR_ANY);
157 m_addr.sin_port = htons(0);
158}
159
160IPv4Address::IPv4Address(const char *p_addr, unsigned short p_port)
161{
162 set_addr(p_addr, p_port);
163}
164
165IPv4Address::~IPv4Address()
166{
167 clean_up();
168}
169
170bool IPv4Address::is_valid(const char *p_addr)
171{
172 if (p_addr == NULL) {
173 return false;
174 } else {
175 IPv4Address addr;
176 return addr.set_addr(p_addr);
177 }
178}
179
180bool IPv4Address::is_local() const
181{
182 // Or: (ntohl(m_addr.sin_addr.s_addr) & 0xff000000u) == 0x7f000000u.
183 return m_addr.sin_addr.s_addr == inet_addr("127.0.0.1");
184}
185
186bool IPv4Address::set_addr(const char *p_addr, unsigned short p_port)
187{
188 clean_up();
189 if (p_addr != NULL) {
190 struct hostent *hptr = gethostbyname(p_addr);
191 if (hptr != NULL && (size_t)hptr->h_length == sizeof(struct in_addr)) {
192 m_addr.sin_family = AF_INET;
193 m_addr.sin_port = htons(p_port);
194 memset(m_addr.sin_zero, 0, sizeof(m_addr.sin_zero));
195 memcpy(&m_addr.sin_addr, hptr->h_addr_list[0], hptr->h_length);
196 strncpy(m_addr_str, inet_ntoa(m_addr.sin_addr), sizeof(m_addr_str));
197 strncpy(m_host_str, hptr->h_name, sizeof(m_host_str));
198 return true;
199 }
200 }
201 return false;
202}
203
204int IPv4Address::accept(int p_sockfd)
205{
206 clean_up();
207 socklen_type addrlen = sizeof(m_addr);
208 int fd = ::accept(p_sockfd, (struct sockaddr *)&m_addr, &addrlen);
209 if (fd >= 0) {
210 strncpy(m_addr_str, inet_ntoa(m_addr.sin_addr), sizeof(m_addr_str));
211 if (m_addr.sin_addr.s_addr != htonl(INADDR_ANY)) {
212 struct hostent *hptr =
213 gethostbyaddr((const char *)&m_addr.sin_addr,
214 sizeof(m_addr.sin_addr), m_addr.sin_family);
215 if (hptr != NULL && (size_t)hptr->h_length == sizeof(struct in_addr)) {
216 strncpy(m_host_str, hptr->h_name, sizeof(m_host_str));
217 }
218 }
219 }
220 return fd;
221}
222
223int IPv4Address::getsockname(int p_sockfd)
224{
225 clean_up();
226 socklen_type addrlen = sizeof(m_addr);
227 int s = ::getsockname(p_sockfd, (struct sockaddr *)&m_addr, &addrlen);
228 if (s >= 0) {
229 strncpy(m_addr_str, inet_ntoa(m_addr.sin_addr), sizeof(m_addr_str));
230 if (m_addr.sin_addr.s_addr != htonl(INADDR_ANY)) {
231 struct hostent *hptr =
232 gethostbyaddr((const char *)&m_addr.sin_addr,
233 sizeof(m_addr.sin_addr), m_addr.sin_family);
234 if (hptr != NULL && (size_t)hptr->h_length == sizeof(struct in_addr)) {
235 strncpy(m_host_str, hptr->h_name, sizeof(m_host_str));
236 }
237 }
238 }
239 return s;
240}
241
242bool IPv4Address::operator==(const IPAddress& p_addr) const
243{
244 return memcmp(&m_addr.sin_addr, &(((const IPv4Address&)p_addr).m_addr.sin_addr), sizeof(m_addr.sin_addr)) == 0;
245}
246
247bool IPv4Address::operator!=(const IPAddress& p_addr) const
248{
249 return !(*this == p_addr);
250}
251
252IPAddress& IPv4Address::operator=(const IPAddress& p_addr)
253{
254 clean_up();
255 memcpy(&m_addr, &((const IPv4Address&)p_addr).m_addr, sizeof(m_addr));
256 strncpy(m_host_str, ((const IPv4Address&)p_addr).m_host_str, sizeof(m_host_str));
257 strncpy(m_addr_str, ((const IPv4Address&)p_addr).m_addr_str, sizeof(m_addr_str));
258 return *this;
259}
260
261void IPv4Address::push_raw(Text_Buf& p_buf) const
262{
263 p_buf.push_raw(sizeof(m_addr.sin_family), &m_addr.sin_family);
264 p_buf.push_raw(sizeof(m_addr.sin_port), &m_addr.sin_port);
265 p_buf.push_raw(sizeof(m_addr.sin_addr), &m_addr.sin_addr);
266 p_buf.push_raw(sizeof(m_addr.sin_zero), &m_addr.sin_zero);
267}
268
269void IPv4Address::pull_raw(Text_Buf& p_buf)
270{
271 clean_up();
272 p_buf.pull_raw(sizeof(m_addr.sin_family), &m_addr.sin_family);
273 p_buf.pull_raw(sizeof(m_addr.sin_port), &m_addr.sin_port);
274 p_buf.pull_raw(sizeof(m_addr.sin_addr), &m_addr.sin_addr);
275 p_buf.pull_raw(sizeof(m_addr.sin_zero), &m_addr.sin_zero);
276}
277
278void IPv4Address::clean_up()
279{
280 memset(&m_addr, 0, sizeof(m_addr));
281 memset(m_host_str, 0, sizeof(m_host_str));
282 memset(m_addr_str, 0, sizeof(m_addr_str));
283}
284
285#if defined(LINUX) || defined(CYGWIN17)
286IPv6Address::IPv6Address()
287{
288 clean_up();
289 m_addr.sin6_family = AF_INET6;
290 m_addr.sin6_addr = in6addr_any;
291 m_addr.sin6_port = htons(0);
292}
293
294IPv6Address::IPv6Address(const char *p_addr, unsigned short p_port)
295{
296 set_addr(p_addr, p_port);
297}
298
299IPv6Address::~IPv6Address()
300{
301 clean_up();
302}
303
304const char *IPv6Address::get_addr_str() const
305{
306 if (strlen(m_addr_str) > 0) {
307 // The host name should always contain the interface's name for link-local addresses.
308 return (strlen(m_host_str) > 0 && strstr(m_host_str, "%") != NULL) ? m_host_str : m_addr_str;
309 } else {
310 return m_host_str;
311 }
312}
313
314bool IPv6Address::set_addr(const char *p_addr, unsigned short p_port)
315{
316 clean_up();
317 struct addrinfo hints, *res;
318 memset(&hints, 0, sizeof(struct addrinfo));
319 hints.ai_flags = AI_CANONNAME | AI_PASSIVE;
320 hints.ai_family = AF_INET6;
321 hints.ai_socktype = SOCK_STREAM;
322 hints.ai_protocol = 0; // Any.
323 char p_port_str[6];
324 memset(p_port_str, 0, sizeof(p_port_str));
325 snprintf(p_port_str, sizeof(p_port_str), "%u", p_port);
326 int s = getaddrinfo(p_addr, p_port_str, &hints, &res);
327 if (s == 0) {
328 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)(void*)res->ai_addr;
329 // The (void*) shuts up the "cast increases required alignment" warning.
330 // Hopefully, the res->ai_addr points to a properly aligned sockaddr_in6
331 // and we won't have problems like these if we decide to support Sparc:
332 // http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=340384
333 memcpy(&m_addr, addr, sizeof(m_addr));
334 m_addr.sin6_port = htons(p_port);
335 inet_ntop(res->ai_family, &(addr->sin6_addr), m_addr_str, sizeof(m_addr_str));
336 strncpy(m_host_str, res->ai_canonname, sizeof(m_host_str));
337 freeaddrinfo(res);
338 return true;
339 }
340 return false;
341}
342
343int IPv6Address::accept(int p_sockfd)
344{
345 clean_up();
346 socklen_type addrlen = sizeof(m_addr);
347 int fd = ::accept(p_sockfd, (struct sockaddr *)&m_addr, &addrlen);
348 if (fd >= 0) {
349 if (!inet_ntop(AF_INET6, &m_addr.sin6_addr, m_addr_str, sizeof(m_addr_str))) {
350 fprintf(stderr, "IPv6Address::accept(): Unable to convert IPv6 address "
351 "from binary to text form: %s\n", strerror(errno));
352 }
353 int s = getnameinfo((struct sockaddr *)&m_addr, sizeof(m_addr),
354 m_host_str, sizeof(m_host_str), NULL, 0, 0);
355 if (s != 0) {
356 fprintf(stderr, "IPv6Address::accept(): Address to name translation "
357 "failed: %s\n", gai_strerror(s));
358 }
359 }
360 return fd;
361}
362
363int IPv6Address::getsockname(int p_sockfd)
364{
365 clean_up();
366 socklen_type addrlen = sizeof(m_addr);
367 int s1 = ::getsockname(p_sockfd, (struct sockaddr *)&m_addr, &addrlen);
368 if (s1 >= 0) {
369 if (!inet_ntop(AF_INET6, &m_addr.sin6_addr, m_addr_str, sizeof(m_addr_str))) {
370 fprintf(stderr, "IPv6Address::getsockname(): Unable to convert IPv6 "
371 "address from binary to text form: %s\n", strerror(errno));
372 }
373 int s2 = getnameinfo((struct sockaddr *)&m_addr, sizeof(m_addr),
374 m_host_str, sizeof(m_host_str), NULL, 0, 0);
375 if (s2 != 0) {
376 fprintf(stderr, "IPv6Address::getsockname(): Address to name "
377 "translation failed: %s\n", gai_strerror(s2));
378 }
379 }
380 return s1;
381}
382
383bool IPv6Address::operator==(const IPAddress& p_addr) const
384{
385 return memcmp(&m_addr.sin6_addr, &(((const IPv6Address&)p_addr).m_addr.sin6_addr), sizeof(m_addr.sin6_addr)) == 0;
386}
387
388bool IPv6Address::operator!=(const IPAddress& p_addr) const
389{
390 return !(*this == p_addr);
391}
392
393IPAddress& IPv6Address::operator=(const IPAddress& p_addr)
394{
395 clean_up();
396 memcpy(&m_addr, &((const IPv6Address&)p_addr).m_addr, sizeof(m_addr));
397 strncpy(m_host_str, ((const IPv6Address&)p_addr).m_host_str, sizeof(m_host_str));
398 strncpy(m_addr_str, ((const IPv6Address&)p_addr).m_addr_str, sizeof(m_addr_str));
399 return *this;
400}
401
402void IPv6Address::push_raw(Text_Buf& p_buf) const
403{
404 p_buf.push_raw(sizeof(m_addr.sin6_family), &m_addr.sin6_family);
405 p_buf.push_raw(sizeof(m_addr.sin6_port), &m_addr.sin6_port);
406 p_buf.push_raw(sizeof(m_addr.sin6_flowinfo), &m_addr.sin6_flowinfo);
407 p_buf.push_raw(sizeof(m_addr.sin6_addr), &m_addr.sin6_addr);
408 p_buf.push_raw(sizeof(m_addr.sin6_scope_id), &m_addr.sin6_scope_id);
409}
410
411void IPv6Address::pull_raw(Text_Buf& p_buf)
412{
413 clean_up();
414 p_buf.pull_raw(sizeof(m_addr.sin6_family), &m_addr.sin6_family);
415 p_buf.pull_raw(sizeof(m_addr.sin6_port), &m_addr.sin6_port);
416 p_buf.pull_raw(sizeof(m_addr.sin6_flowinfo), &m_addr.sin6_flowinfo);
417 p_buf.pull_raw(sizeof(m_addr.sin6_addr), &m_addr.sin6_addr);
418 p_buf.pull_raw(sizeof(m_addr.sin6_scope_id), &m_addr.sin6_scope_id);
419}
420
421void IPv6Address::clean_up()
422{
423 memset(&m_addr, 0, sizeof(m_addr));
424 memset(m_host_str, 0, sizeof(m_host_str));
425 memset(m_addr_str, 0, sizeof(m_addr_str));
426}
427
428bool IPv6Address::is_local() const
429{
430 const unsigned char localhost_bytes[] =
431 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
432 const unsigned char mapped_ipv4_localhost[] =
433 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x7f, 0, 0, 1 };
434
435 return (memcmp(m_addr.sin6_addr.s6_addr, localhost_bytes, 16) == 0
436 || memcmp(m_addr.sin6_addr.s6_addr, mapped_ipv4_localhost, 16) == 0);
437}
438
439bool IPv6Address::is_valid(const char *p_addr)
440{
441 if (p_addr == NULL) {
442 return false;
443 } else {
444 IPv6Address addr;
445 return addr.set_addr(p_addr);
446 }
447}
448#endif // LINUX || CYGWIN17
This page took 0.039992 seconds and 5 git commands to generate.