1 /**********
2 This library is free software; you can redistribute it and/or modify it under
3 the terms of the GNU Lesser General Public License as published by the
4 Free Software Foundation; either version 3 of the License, or (at your
5 option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
6
7 This library is distributed in the hope that it will be useful, but WITHOUT
8 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
10 more details.
11
12 You should have received a copy of the GNU Lesser General Public License
13 along with this library; if not, write to the Free Software Foundation, Inc.,
14 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15 **********/
16 // "mTunnel" multicast access service
17 // Copyright (c) 1996-2020 Live Networks, Inc. All rights reserved.
18 // Network Addresses
19 // Implementation
20
21 #include "NetAddress.hh"
22 #include "GroupsockHelper.hh"
23
24 #include <stddef.h>
25 #include <stdio.h>
26 #if defined(__WIN32__) || defined(_WIN32)
27 #define USE_GETHOSTBYNAME 1 /*because at least some Windows don't have getaddrinfo()*/
28 #else
29 #ifndef INADDR_NONE
30 #define INADDR_NONE 0xFFFFFFFF
31 #endif
32 #endif
33
34 ////////// NetAddress //////////
35
NetAddress(u_int8_t const * data,unsigned length)36 NetAddress::NetAddress(u_int8_t const* data, unsigned length) {
37 assign(data, length);
38 }
39
NetAddress(unsigned length)40 NetAddress::NetAddress(unsigned length) {
41 fData = new u_int8_t[length];
42 if (fData == NULL) {
43 fLength = 0;
44 return;
45 }
46
47 for (unsigned i = 0; i < length; ++i) fData[i] = 0;
48 fLength = length;
49 }
50
NetAddress(NetAddress const & orig)51 NetAddress::NetAddress(NetAddress const& orig) {
52 assign(orig.data(), orig.length());
53 }
54
operator =(NetAddress const & rightSide)55 NetAddress& NetAddress::operator=(NetAddress const& rightSide) {
56 if (&rightSide != this) {
57 clean();
58 assign(rightSide.data(), rightSide.length());
59 }
60 return *this;
61 }
62
~NetAddress()63 NetAddress::~NetAddress() {
64 clean();
65 }
66
assign(u_int8_t const * data,unsigned length)67 void NetAddress::assign(u_int8_t const* data, unsigned length) {
68 fData = new u_int8_t[length];
69 if (fData == NULL) {
70 fLength = 0;
71 return;
72 }
73
74 for (unsigned i = 0; i < length; ++i) fData[i] = data[i];
75 fLength = length;
76 }
77
clean()78 void NetAddress::clean() {
79 delete[] fData; fData = NULL;
80 fLength = 0;
81 }
82
83
84 ////////// NetAddressList //////////
85
NetAddressList(char const * hostname)86 NetAddressList::NetAddressList(char const* hostname)
87 : fNumAddresses(0), fAddressArray(NULL) {
88 // First, check whether "hostname" is an IP address string (check IPv4, then IPv6).
89 // If so, return a 1-element list with this address:
90 ipv4AddressBits addr4;
91 if (inet_pton(AF_INET, hostname, (u_int8_t*)&addr4) == 1) {
92 fNumAddresses = 1;
93 fAddressArray = new NetAddress*[fNumAddresses];
94 if (fAddressArray == NULL) return;
95
96 fAddressArray[0] = new NetAddress((u_int8_t*)&addr4, sizeof addr4);
97 return;
98 }
99
100 ipv6AddressBits addr6;
101 if (inet_pton(AF_INET6, hostname, (u_int8_t*)&addr6) == 1) {
102 fNumAddresses = 1;
103 fAddressArray = new NetAddress*[fNumAddresses];
104 if (fAddressArray == NULL) return;
105
106 fAddressArray[0] = new NetAddress((u_int8_t*)&addr6, sizeof addr6);
107 return;
108 }
109
110 // "hostname" is not an IP address string; try resolving it as a real host name instead:
111 #if defined(USE_GETHOSTBYNAME) || defined(VXWORKS)
112 struct hostent* host;
113 #if defined(VXWORKS)
114 char hostentBuf[512];
115
116 host = (struct hostent*)resolvGetHostByName((char*)hostname, (char*)&hostentBuf, sizeof hostentBuf);
117 #else
118 host = gethostbyname((char*)hostname);
119 #endif
120 if (host == NULL || host->h_length != 4 || host->h_addr_list == NULL) return; // no luck
121
122 u_int8_t const** const hAddrPtr = (u_int8_t const**)host->h_addr_list;
123 // First, count the number of addresses:
124 u_int8_t const** hAddrPtr1 = hAddrPtr;
125 while (*hAddrPtr1 != NULL) {
126 ++fNumAddresses;
127 ++hAddrPtr1;
128 }
129
130 // Next, set up the list:
131 fAddressArray = new NetAddress*[fNumAddresses];
132 if (fAddressArray == NULL) return;
133
134 for (unsigned i = 0; i < fNumAddresses; ++i) {
135 fAddressArray[i] = new NetAddress(hAddrPtr[i], host->h_length);
136 }
137 #else
138 // Use "getaddrinfo()" (rather than the older, deprecated "gethostbyname()"):
139 struct addrinfo addrinfoHints;
140 memset(&addrinfoHints, 0, sizeof addrinfoHints);
141 addrinfoHints.ai_family = AF_INET; // For now, we're interested in IPv4 addresses only
142 struct addrinfo* addrinfoResultPtr = NULL;
143 int result = getaddrinfo(hostname, NULL, &addrinfoHints, &addrinfoResultPtr);
144 if (result != 0 || addrinfoResultPtr == NULL) return; // no luck
145
146 // First, count the number of addresses:
147 const struct addrinfo* p = addrinfoResultPtr;
148 while (p != NULL) {
149 if (p->ai_addrlen < 4) continue; // sanity check: skip over addresses that are too small
150 ++fNumAddresses;
151 p = p->ai_next;
152 }
153
154 // Next, set up the list:
155 fAddressArray = new NetAddress*[fNumAddresses];
156 if (fAddressArray == NULL) return;
157
158 unsigned i = 0;
159 p = addrinfoResultPtr;
160 while (p != NULL) {
161 if (p->ai_addrlen < 4) continue;
162 fAddressArray[i++] = new NetAddress((u_int8_t const*)&(((struct sockaddr_in*)p->ai_addr)->sin_addr.s_addr), 4);
163 p = p->ai_next;
164 }
165
166 // Finally, free the data that we had allocated by calling "getaddrinfo()":
167 freeaddrinfo(addrinfoResultPtr);
168 #endif
169 }
170
NetAddressList(NetAddressList const & orig)171 NetAddressList::NetAddressList(NetAddressList const& orig) {
172 assign(orig.numAddresses(), orig.fAddressArray);
173 }
174
operator =(NetAddressList const & rightSide)175 NetAddressList& NetAddressList::operator=(NetAddressList const& rightSide) {
176 if (&rightSide != this) {
177 clean();
178 assign(rightSide.numAddresses(), rightSide.fAddressArray);
179 }
180 return *this;
181 }
182
~NetAddressList()183 NetAddressList::~NetAddressList() {
184 clean();
185 }
186
assign(unsigned numAddresses,NetAddress ** addressArray)187 void NetAddressList::assign(unsigned numAddresses, NetAddress** addressArray) {
188 fAddressArray = new NetAddress*[numAddresses];
189 if (fAddressArray == NULL) {
190 fNumAddresses = 0;
191 return;
192 }
193
194 for (unsigned i = 0; i < numAddresses; ++i) {
195 fAddressArray[i] = new NetAddress(*addressArray[i]);
196 }
197 fNumAddresses = numAddresses;
198 }
199
clean()200 void NetAddressList::clean() {
201 while (fNumAddresses-- > 0) {
202 delete fAddressArray[fNumAddresses];
203 }
204 delete[] fAddressArray; fAddressArray = NULL;
205 }
206
firstAddress() const207 NetAddress const* NetAddressList::firstAddress() const {
208 if (fNumAddresses == 0) return NULL;
209
210 return fAddressArray[0];
211 }
212
213 ////////// NetAddressList::Iterator //////////
Iterator(NetAddressList const & addressList)214 NetAddressList::Iterator::Iterator(NetAddressList const& addressList)
215 : fAddressList(addressList), fNextIndex(0) {}
216
nextAddress()217 NetAddress const* NetAddressList::Iterator::nextAddress() {
218 if (fNextIndex >= fAddressList.numAddresses()) return NULL; // no more
219 return fAddressList.fAddressArray[fNextIndex++];
220 }
221
222
223 ////////// Port //////////
224
Port(portNumBits num)225 Port::Port(portNumBits num /* in host byte order */) {
226 fPortNum = htons(num);
227 }
228
operator <<(UsageEnvironment & s,const Port & p)229 UsageEnvironment& operator<<(UsageEnvironment& s, const Port& p) {
230 return s << ntohs(p.num());
231 }
232
233
234 ////////// AddressPortLookupTable //////////
235
AddressPortLookupTable()236 AddressPortLookupTable::AddressPortLookupTable()
237 : fTable(HashTable::create(3)) { // three-word keys are used
238 }
239
~AddressPortLookupTable()240 AddressPortLookupTable::~AddressPortLookupTable() {
241 delete fTable;
242 }
243
Add(netAddressBits address1,netAddressBits address2,Port port,void * value)244 void* AddressPortLookupTable::Add(netAddressBits address1,
245 netAddressBits address2,
246 Port port, void* value) {
247 int key[3];
248 key[0] = (int)address1;
249 key[1] = (int)address2;
250 key[2] = (int)port.num();
251 return fTable->Add((char*)key, value);
252 }
253
Lookup(netAddressBits address1,netAddressBits address2,Port port)254 void* AddressPortLookupTable::Lookup(netAddressBits address1,
255 netAddressBits address2,
256 Port port) {
257 int key[3];
258 key[0] = (int)address1;
259 key[1] = (int)address2;
260 key[2] = (int)port.num();
261 return fTable->Lookup((char*)key);
262 }
263
Remove(netAddressBits address1,netAddressBits address2,Port port)264 Boolean AddressPortLookupTable::Remove(netAddressBits address1,
265 netAddressBits address2,
266 Port port) {
267 int key[3];
268 key[0] = (int)address1;
269 key[1] = (int)address2;
270 key[2] = (int)port.num();
271 return fTable->Remove((char*)key);
272 }
273
Iterator(AddressPortLookupTable & table)274 AddressPortLookupTable::Iterator::Iterator(AddressPortLookupTable& table)
275 : fIter(HashTable::Iterator::create(*(table.fTable))) {
276 }
277
~Iterator()278 AddressPortLookupTable::Iterator::~Iterator() {
279 delete fIter;
280 }
281
next()282 void* AddressPortLookupTable::Iterator::next() {
283 char const* key; // dummy
284 return fIter->next(key);
285 }
286
287
288 ////////// isMulticastAddress() implementation //////////
289
IsMulticastAddress(netAddressBits address)290 Boolean IsMulticastAddress(netAddressBits address) {
291 // Note: We return False for addresses in the range 224.0.0.0
292 // through 224.0.0.255, because these are non-routable
293 // Note: IPv4-specific #####
294 netAddressBits addressInNetworkOrder = htonl(address);
295 return addressInNetworkOrder > 0xE00000FF &&
296 addressInNetworkOrder <= 0xEFFFFFFF;
297 }
298
299
300 ////////// AddressString implementation //////////
301
AddressString(struct sockaddr_in const & addr)302 AddressString::AddressString(struct sockaddr_in const& addr) {
303 init(addr.sin_addr.s_addr);
304 }
AddressString(struct in_addr const & addr)305 AddressString::AddressString(struct in_addr const& addr) {
306 init(addr.s_addr);
307 }
AddressString(ipv4AddressBits const & addr)308 AddressString::AddressString(ipv4AddressBits const& addr) {
309 init(addr);
310 }
311
AddressString(struct sockaddr_in6 const & addr)312 AddressString::AddressString(struct sockaddr_in6 const& addr) {
313 init(addr.sin6_addr.s6_addr);
314 }
AddressString(struct in6_addr const & addr)315 AddressString::AddressString(struct in6_addr const& addr) {
316 init(addr.s6_addr);
317 }
AddressString(ipv6AddressBits const & addr)318 AddressString::AddressString(ipv6AddressBits const& addr) {
319 init(addr);
320 }
321
AddressString(struct sockaddr_storage const & addr)322 AddressString::AddressString(struct sockaddr_storage const& addr) {
323 switch (addr.ss_family) {
324 case AF_INET: {
325 init(((sockaddr_in*)&addr)->sin_addr.s_addr);
326 break;
327 }
328 case AF_INET6: {
329 init(((sockaddr_in6*)&addr)->sin6_addr.s6_addr);
330 break;
331 }
332 }
333 }
334
init(ipv4AddressBits const & addr)335 void AddressString::init(ipv4AddressBits const& addr) {
336 fVal = new char[INET_ADDRSTRLEN];
337 inet_ntop(AF_INET, &addr, fVal, INET_ADDRSTRLEN);
338 }
339
init(ipv6AddressBits const & addr)340 void AddressString::init(ipv6AddressBits const& addr) {
341 fVal = new char[INET6_ADDRSTRLEN];
342 inet_ntop(AF_INET6, &addr, fVal, INET6_ADDRSTRLEN);
343 }
344
~AddressString()345 AddressString::~AddressString() {
346 delete[] fVal;
347 }
348
portNum(struct sockaddr_storage const & addr)349 portNumBits portNum(struct sockaddr_storage const& addr) {
350 switch (addr.ss_family) {
351 case AF_INET: {
352 return ((sockaddr_in*)&addr)->sin_port;
353 }
354 case AF_INET6: {
355 return ((sockaddr_in6*)&addr)->sin6_port;
356 }
357 default: {
358 return 0;
359 }
360 }
361 }
362