1
// rak - Rakshasa's toolbox
2
// Copyright (C) 2005-2007, Jari Sundell
4
// This program is free software; you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation; either version 2 of the License, or
7
// (at your option) any later version.
9
// This program is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
// GNU General Public License for more details.
14
// You should have received a copy of the GNU General Public License
15
// along with this program; if not, write to the Free Software
16
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
// In addition, as a special exception, the copyright holders give
19
// permission to link the code of portions of this program with the
20
// OpenSSL library under certain conditions as described in each
21
// individual source file, and distribute linked combinations
24
// You must obey the GNU General Public License in all respects for
25
// all of the code used other than OpenSSL. If you modify file(s)
26
// with this exception, you may extend this exception to your version
27
// of the file(s), but you are not obligated to do so. If you do not
28
// wish to do so, delete this exception statement from your version.
29
// If you delete this exception statement from all source files in the
30
// program, then also delete it here.
32
// Contact: Jari Sundell <jaris@ifi.uio.no>
35
// 3185 Skoppum, NORWAY
37
// Wrappers for the various sockaddr types with focus on zero-copy
38
// casting between the original type and the wrapper class.
40
// The default ctor does not initialize any data.
42
// _n suffixes indicate that the argument or return value is in
43
// network byte order, _h that they are in hardware byte order.
45
// Add define for inet6 scope id?
47
#ifndef RAK_SOCKET_ADDRESS_H
48
#define RAK_SOCKET_ADDRESS_H
53
#include <arpa/inet.h>
54
#include <netinet/in.h>
55
#include <sys/types.h>
56
#include <sys/socket.h>
60
class socket_address_inet;
61
class socket_address_inet6;
63
class socket_address {
65
static const sa_family_t af_inet = AF_INET;
66
static const int pf_inet = PF_INET;
67
static const sa_family_t af_inet6 = AF_INET6;
68
static const int pf_inet6 = PF_INET6;
69
static const sa_family_t af_unspec = AF_UNSPEC;
70
static const int pf_unspec = PF_UNSPEC;
73
static const sa_family_t af_local = AF_LOCAL;
74
static const int pf_local = PF_LOCAL;
76
static const sa_family_t af_local = AF_UNIX;
77
static const int pf_local = PF_UNIX;
80
bool is_valid() const;
81
bool is_bindable() const;
82
bool is_address_any() const;
84
// Should we need to set AF_UNSPEC?
85
void clear() { std::memset(this, 0, sizeof(socket_address)); set_family(); }
87
sa_family_t family() const { return m_sockaddr.sa_family; }
88
void set_family() { m_sockaddr.sa_family = af_unspec; }
90
uint16_t port() const;
91
void set_port(uint16_t p);
93
std::string address_str() const;
94
bool address_c_str(char* buf, socklen_t size) const;
96
// Attemts to set it as an inet, then an inet6 address. It will
97
// never set anything but net addresses, no local/unix.
98
bool set_address_str(const std::string& a) { return set_address_c_str(a.c_str()); }
99
bool set_address_c_str(const char* a);
101
uint32_t length() const;
103
socket_address_inet* sa_inet() { return reinterpret_cast<socket_address_inet*>(this); }
104
const socket_address_inet* sa_inet() const { return reinterpret_cast<const socket_address_inet*>(this); }
106
sockaddr* c_sockaddr() { return &m_sockaddr; }
107
sockaddr_in* c_sockaddr_inet() { return &m_sockaddrInet; }
109
const sockaddr* c_sockaddr() const { return &m_sockaddr; }
110
const sockaddr_in* c_sockaddr_inet() const { return &m_sockaddrInet; }
113
socket_address_inet6* sa_inet6() { return reinterpret_cast<socket_address_inet6*>(this); }
114
const socket_address_inet6* sa_inet6() const { return reinterpret_cast<const socket_address_inet6*>(this); }
116
sockaddr_in6* c_sockaddr_inet6() { return &m_sockaddrInet6; }
117
const sockaddr_in6* c_sockaddr_inet6() const { return &m_sockaddrInet6; }
120
// Copy a socket address which has the length 'length. Zero out any
121
// extranous bytes and ensure it does not go beyond the size of this
123
void copy(const socket_address& src, size_t length);
125
static socket_address* cast_from(sockaddr* sa) { return reinterpret_cast<socket_address*>(sa); }
126
static const socket_address* cast_from(const sockaddr* sa) { return reinterpret_cast<const socket_address*>(sa); }
128
// The different families will be sorted according to the
129
// sa_family_t's numeric value.
130
bool operator == (const socket_address& rhs) const;
131
bool operator < (const socket_address& rhs) const;
133
bool operator == (const sockaddr& rhs) const { return *this == *cast_from(&rhs); }
134
bool operator == (const sockaddr* rhs) const { return *this == *cast_from(rhs); }
135
bool operator < (const sockaddr& rhs) const { return *this == *cast_from(&rhs); }
136
bool operator < (const sockaddr* rhs) const { return *this == *cast_from(rhs); }
141
sockaddr_in m_sockaddrInet;
143
sockaddr_in6 m_sockaddrInet6;
148
// Remember to set the AF_INET.
150
class socket_address_inet {
152
bool is_any() const { return is_port_any() && is_address_any(); }
153
bool is_valid() const { return !is_port_any() && !is_address_any(); }
154
bool is_port_any() const { return port() == 0; }
155
bool is_address_any() const { return m_sockaddr.sin_addr.s_addr == htonl(INADDR_ANY); }
157
void clear() { std::memset(this, 0, sizeof(socket_address_inet)); set_family(); }
159
uint16_t port() const { return ntohs(m_sockaddr.sin_port); }
160
uint16_t port_n() const { return m_sockaddr.sin_port; }
161
void set_port(uint16_t p) { m_sockaddr.sin_port = htons(p); }
162
void set_port_n(uint16_t p) { m_sockaddr.sin_port = p; }
164
// Should address() return the uint32_t?
165
in_addr address() const { return m_sockaddr.sin_addr; }
166
uint32_t address_h() const { return ntohl(m_sockaddr.sin_addr.s_addr); }
167
uint32_t address_n() const { return m_sockaddr.sin_addr.s_addr; }
168
std::string address_str() const;
169
bool address_c_str(char* buf, socklen_t size) const;
171
void set_address(in_addr a) { m_sockaddr.sin_addr = a; }
172
void set_address_h(uint32_t a) { m_sockaddr.sin_addr.s_addr = htonl(a); }
173
void set_address_n(uint32_t a) { m_sockaddr.sin_addr.s_addr = a; }
174
bool set_address_str(const std::string& a) { return set_address_c_str(a.c_str()); }
175
bool set_address_c_str(const char* a);
177
void set_address_any() { set_port(0); set_address_h(INADDR_ANY); }
179
sa_family_t family() const { return m_sockaddr.sin_family; }
180
void set_family() { m_sockaddr.sin_family = AF_INET; }
182
sockaddr* c_sockaddr() { return reinterpret_cast<sockaddr*>(&m_sockaddr); }
183
sockaddr_in* c_sockaddr_inet() { return &m_sockaddr; }
185
const sockaddr* c_sockaddr() const { return reinterpret_cast<const sockaddr*>(&m_sockaddr); }
186
const sockaddr_in* c_sockaddr_inet() const { return &m_sockaddr; }
189
socket_address_inet6 to_mapped_address() const;
192
bool operator == (const socket_address_inet& rhs) const;
193
bool operator < (const socket_address_inet& rhs) const;
196
struct sockaddr_in m_sockaddr;
200
// Remember to set the AF_INET6.
202
class socket_address_inet6 {
204
bool is_any() const { return is_port_any() && is_address_any(); }
205
bool is_valid() const { return !is_port_any() && !is_address_any(); }
206
bool is_port_any() const { return port() == 0; }
207
bool is_address_any() const { return std::memcmp(&m_sockaddr.sin6_addr, &in6addr_any, sizeof(in6_addr)) == 0; }
209
void clear() { std::memset(this, 0, sizeof(socket_address_inet6)); set_family(); }
211
uint16_t port() const { return ntohs(m_sockaddr.sin6_port); }
212
uint16_t port_n() const { return m_sockaddr.sin6_port; }
213
void set_port(uint16_t p) { m_sockaddr.sin6_port = htons(p); }
214
void set_port_n(uint16_t p) { m_sockaddr.sin6_port = p; }
216
in6_addr address() const { return m_sockaddr.sin6_addr; }
217
std::string address_str() const;
218
bool address_c_str(char* buf, socklen_t size) const;
220
void set_address(in6_addr a) { m_sockaddr.sin6_addr = a; }
221
bool set_address_str(const std::string& a) { return set_address_c_str(a.c_str()); }
222
bool set_address_c_str(const char* a);
224
void set_address_any() { set_port(0); set_address(in6addr_any); }
226
sa_family_t family() const { return m_sockaddr.sin6_family; }
227
void set_family() { m_sockaddr.sin6_family = AF_INET6; }
229
sockaddr* c_sockaddr() { return reinterpret_cast<sockaddr*>(&m_sockaddr); }
230
sockaddr_in6* c_sockaddr_inet6() { return &m_sockaddr; }
232
const sockaddr* c_sockaddr() const { return reinterpret_cast<const sockaddr*>(&m_sockaddr); }
233
const sockaddr_in6* c_sockaddr_inet6() const { return &m_sockaddr; }
235
socket_address normalize_address() const;
237
bool operator == (const socket_address_inet6& rhs) const;
238
bool operator < (const socket_address_inet6& rhs) const;
241
struct sockaddr_in6 m_sockaddr;
245
// Unique key for the address, excluding port numbers etc.
246
class socket_address_key {
248
// socket_address_host_key() {}
250
socket_address_key(const socket_address& sa) {
254
socket_address_key& operator = (const socket_address& sa) {
255
if (sa.family() == 0) {
256
std::memset(this, 0, sizeof(socket_address_key));
258
} else if (sa.family() == socket_address::af_inet) {
259
// Using hardware order as we use operator < to compare when
261
m_addr.s_addr = sa.sa_inet()->address_h();
264
// When we implement INET6 handling, embed the ipv4 address in
266
throw std::logic_error("socket_address_key(...) received an unsupported protocol family.");
272
// socket_address_key& operator = (const socket_address_key& sa) {
275
bool operator < (const socket_address_key& sa) const {
276
// Compare the memory area instead.
277
return m_addr.s_addr < sa.m_addr.s_addr;
283
// #ifdef RAK_USE_INET6
290
socket_address::is_valid() const {
293
return sa_inet()->is_valid();
296
return sa_inet6()->is_valid();
304
socket_address::is_bindable() const {
307
return !sa_inet()->is_address_any();
310
return !sa_inet6()->is_address_any();
318
socket_address::is_address_any() const {
321
return sa_inet()->is_address_any();
324
return sa_inet6()->is_address_any();
332
socket_address::port() const {
335
return sa_inet()->port();
338
return sa_inet6()->port();
346
socket_address::set_port(uint16_t p) {
349
return sa_inet()->set_port(p);
352
return sa_inet6()->set_port(p);
360
socket_address::address_str() const {
363
return sa_inet()->address_str();
366
return sa_inet6()->address_str();
369
return std::string();
374
socket_address::address_c_str(char* buf, socklen_t size) const {
377
return sa_inet()->address_c_str(buf, size);
380
return sa_inet6()->address_c_str(buf, size);
388
socket_address::set_address_c_str(const char* a) {
389
if (sa_inet()->set_address_c_str(a)) {
390
sa_inet()->set_family();
394
} else if (sa_inet6()->set_address_c_str(a)) {
395
sa_inet6()->set_family();
404
// Is the zero length really needed, should we require some length?
406
socket_address::length() const {
409
return sizeof(sockaddr_in);
412
return sizeof(sockaddr_in6);
420
socket_address::copy(const socket_address& src, size_t length) {
421
length = std::min(length, sizeof(socket_address));
423
// Does this get properly optimized?
424
std::memset(this, 0, sizeof(socket_address));
425
std::memcpy(this, &src, length);
428
// Should we be able to compare af_unspec?
431
socket_address::operator == (const socket_address& rhs) const {
432
if (family() != rhs.family())
437
return *sa_inet() == *rhs.sa_inet();
440
return *sa_inet6() == *rhs.sa_inet6();
443
throw std::logic_error("socket_address::operator == (rhs) invalid type comparison.");
448
socket_address::operator < (const socket_address& rhs) const {
449
if (family() != rhs.family())
450
return family() < rhs.family();
454
return *sa_inet() < *rhs.sa_inet();
457
return *sa_inet6() < *rhs.sa_inet6();
460
throw std::logic_error("socket_address::operator < (rhs) invalid type comparison.");
465
socket_address_inet::address_str() const {
466
char buf[INET_ADDRSTRLEN];
468
if (!address_c_str(buf, INET_ADDRSTRLEN))
469
return std::string();
471
return std::string(buf);
475
socket_address_inet::address_c_str(char* buf, socklen_t size) const {
476
return inet_ntop(family(), &m_sockaddr.sin_addr, buf, size);
480
socket_address_inet::set_address_c_str(const char* a) {
481
return inet_pton(AF_INET, a, &m_sockaddr.sin_addr);
485
inline socket_address_inet6
486
socket_address_inet::to_mapped_address() const {
490
addr32[2] = htonl(0xffff);
491
addr32[3] = m_sockaddr.sin_addr.s_addr;
493
socket_address_inet6 sa;
495
sa.set_address(*reinterpret_cast<in6_addr *>(addr32));
496
sa.set_port_n(m_sockaddr.sin_port);
502
socket_address_inet::operator == (const socket_address_inet& rhs) const {
504
m_sockaddr.sin_addr.s_addr == rhs.m_sockaddr.sin_addr.s_addr &&
505
m_sockaddr.sin_port == rhs.m_sockaddr.sin_port;
509
socket_address_inet::operator < (const socket_address_inet& rhs) const {
511
m_sockaddr.sin_addr.s_addr < rhs.m_sockaddr.sin_addr.s_addr ||
512
(m_sockaddr.sin_addr.s_addr == rhs.m_sockaddr.sin_addr.s_addr &&
513
m_sockaddr.sin_port < rhs.m_sockaddr.sin_port);
519
socket_address_inet6::address_str() const {
520
char buf[INET6_ADDRSTRLEN];
522
if (!address_c_str(buf, INET6_ADDRSTRLEN))
523
return std::string();
525
return std::string(buf);
529
socket_address_inet6::address_c_str(char* buf, socklen_t size) const {
530
return inet_ntop(family(), &m_sockaddr.sin6_addr, buf, size);
534
socket_address_inet6::set_address_c_str(const char* a) {
535
return inet_pton(AF_INET6, a, &m_sockaddr.sin6_addr);
538
inline socket_address
539
socket_address_inet6::normalize_address() const {
540
const uint32_t *addr32 = reinterpret_cast<const uint32_t *>(m_sockaddr.sin6_addr.s6_addr);
541
if (addr32[0] == 0 && addr32[1] == 0 && addr32[2] == htonl(0xffff)) {
542
socket_address addr4;
543
addr4.sa_inet()->set_family();
544
addr4.sa_inet()->set_address_n(addr32[3]);
545
addr4.sa_inet()->set_port_n(m_sockaddr.sin6_port);
548
return *reinterpret_cast<const socket_address*>(this);
552
socket_address_inet6::operator == (const socket_address_inet6& rhs) const {
554
memcmp(&m_sockaddr.sin6_addr, &rhs.m_sockaddr.sin6_addr, sizeof(in6_addr)) == 0 &&
555
m_sockaddr.sin6_port == rhs.m_sockaddr.sin6_port;
559
socket_address_inet6::operator < (const socket_address_inet6& rhs) const {
560
int addr_comp = memcmp(&m_sockaddr.sin6_addr, &rhs.m_sockaddr.sin6_addr, sizeof(in6_addr));
564
m_sockaddr.sin6_port < rhs.m_sockaddr.sin6_port);