INetAddressing.cc
Go to the documentation of this file.
1 //
2 // Copyright (c) 2020 Fraunhofer Institute for Applied Information Technology (FIT)
3 // Network Research Group (NET)
4 // Schloss Birlinghoven, 53754 Sankt Augustin, GERMANY
5 // Contact: support@wiback.org
6 //
7 // This file is part of the SENF code tree.
8 // It is licensed under the 3-clause BSD License (aka New BSD License).
9 // See LICENSE.txt in the top level directory for details or visit
10 // https://opensource.org/licenses/BSD-3-Clause
11 //
12 
13 
18 #include "INetAddressing.hh"
19 //#include "INetAddressing.ih"
20 
21 // Custom includes
22 #include <sstream>
23 #include <string.h>
24 #include <sys/socket.h>
25 #include <net/if.h>
26 #include <boost/lexical_cast.hpp>
27 #include <boost/regex.hpp>
28 #include <senf/Utils/senfassert.hh>
30 
31 //#include "INetAddressing.mpp"
32 #define prefix_
33 //-/////////////////////////////////////////////////////////////////////////////////////////////////
34 
35 //-/////////////////////////////////////////////////////////////////////////////////////////////////
36 // senf::INet4SocketAddress
37 
39  : BSDSocketAddress (sizeof(sockaddr_in), AF_INET)
40 {
41  std::string::size_type portIx = addr.find(':');
42  try {
43  port( boost::lexical_cast< ::uint16_t>(portIx == std::string::npos ? addr : std::string(addr,portIx+1)) );
44  }
45  catch (boost::bad_lexical_cast const &) {
46  throw AddressSyntaxException(addr) << ": invalid port number";
47  }
48  if (portIx != std::string::npos)
49  address( INet4Address::from_string(std::string(addr,0,portIx)) );
50 }
51 
53  : BSDSocketAddress (sizeof(sockaddr_in), AF_INET)
54 {
55  address(addr);
56  port(p);
57 }
58 
60  : BSDSocketAddress (sizeof(sockaddr_in), AF_INET)
61 {
62  port(p);
63 }
64 
65 prefix_ std::ostream & senf::operator<<(std::ostream & os, INet4SocketAddress const & addr)
66 {
67  os << addr.address() << ":" << addr.port();
68  return os;
69 }
70 
71 prefix_ std::istream & senf::operator>>(std::istream & is, INet4SocketAddress & addr)
72 {
73  std::string s;
74  if (!(is >> s))
75  return is;
76  try {
77  addr = INet4SocketAddress(s);
78  }
79  catch (AddressException &) {
80  is.setstate(std::ios::failbit);
81  }
82  return is;
83 }
84 
85 //-/////////////////////////////////////////////////////////////////////////////////////////////////
86 // senf::INet6SocketAddress
87 
90  : BSDSocketAddress (sizeof(sockaddr_in6), AF_INET6)
91 {
92  // Format of addr: "[" address [ "%" interface ] "]" ":" port
93  // or: host ":" port
94  // or: port
95 
96  static boost::regex const addressRx ("(?:(?:\\[([^%]+)(?:%(.+))?\\]|(.+)):)?([0-9]+)");
97  // Subexpression numbers:
98  enum { Address = 1,
99  ZoneId = 2,
100  Hostname = 3,
101  Port = 4 };
102 
103  boost::smatch match;
104  if (! regex_match(addr, match, addressRx))
105  throw AddressSyntaxException(addr);
106 
107  if (match[ZoneId].matched)
108  assignIface(match[ZoneId]);
109 
110  sockaddr_.sin6_port = htons(boost::lexical_cast<boost::uint16_t>(match[Port]));
111 
112  if (match[Address].matched || match[Hostname].matched) {
114  match[Address].matched ? match[Address] : match[Hostname],
115  resolve));
116  std::copy(a.begin(), a.end(), &sockaddr_.sin6_addr.s6_addr[0]);
117  }
118 }
119 
121  const
122 {
123  if (sockaddr_.sin6_scope_id == 0)
124  return "";
125  char buffer[IFNAMSIZ];
126  SENF_ASSERT_EXPRESSION(if_indextoname(sockaddr_.sin6_scope_id,buffer),
127  "Internal failure: Invalid interface index (how does it get here?)");
128  return std::string(buffer);
129 }
130 
131 prefix_ void senf::INet6SocketAddress::assignIface(std::string const & iface)
132 {
133  if (iface.empty())
134  sockaddr_.sin6_scope_id = 0;
135  else {
136  sockaddr_.sin6_scope_id = if_nametoindex(iface.c_str());
137  if (sockaddr_.sin6_scope_id == 0)
138  throw AddressSyntaxException(iface);
139  }
140 }
141 
142 prefix_ std::ostream & senf::operator<<(std::ostream & os, INet6SocketAddress const & addr)
143 {
144  os << '[' << addr.address();
145  std::string iface (addr.iface());
146  if (! iface.empty())
147  os << '%' << iface;
148  os << "]:" << addr.port();
149  return os;
150 }
151 
152 prefix_ std::istream & senf::operator>>(std::istream & is, INet6SocketAddress & addr)
153 {
154  std::string s;
155  if (!(is >> s))
156  return is;
157  try {
158  addr = INet6SocketAddress(s);
159  }
160  catch (AddressException &) {
161  is.setstate(std::ios::failbit);
162  }
163  return is;
164 }
165 
166 //-/////////////////////////////////////////////////////////////////////////////////////////////////
167 #undef prefix_
168 //#include "INetAddressing.mpp"
169 
170 
171 // Local Variables:
172 // mode: c++
173 // fill-column: 100
174 // c-file-style: "senf"
175 // indent-tabs-mode: nil
176 // ispell-local-dictionary: "american"
177 // compile-command: "scons -u test"
178 // comment-column: 40
179 // End:
#define prefix_
static INet6Address from_string(std::string const &s, Resolve_t resolve=ResolveINet6)
Convert string to address.
Definition: INet6Address.cc:38
#define SENF_ASSERT_EXPRESSION(expression, comment)
IPv6 socket address.
std::ostream & operator<<(std::ostream &os, Packet const &packet)
IPv4 socket address.
std::istream & operator>>(std::istream &is, INet4SocketAddress &addr)
std::string iface() const
Get interface name.
AddressExceptions public header.
unsigned port() const
Get port number.
static INet4Address from_string(std::string const &s)
Convert string to address.
Definition: INet4Address.cc:41
INet6 network address.
Socket addressing, BSD style.
INet[46]Address and INet[46]AddressingPolicy public header.
IPv4 Internet address.
Definition: INet4Address.hh:78
Base-class for Address exceptions.
INet6Address address() const
Get printable address representation.
Invalid address syntax.
unsigned port() const
Return port number.
INet4Address address() const
Return address.
INet6SocketAddress()
Create empty instance.