1/**********
2This library is free software; you can redistribute it and/or modify it under
3the terms of the GNU Lesser General Public License as published by the
4Free Software Foundation; either version 3 of the License, or (at your
5option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
6
7This library is distributed in the hope that it will be useful, but WITHOUT
8ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
10more details.
11
12You should have received a copy of the GNU Lesser General Public License
13along with this library; if not, write to the Free Software Foundation, Inc.,
1451 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
36NetAddress::NetAddress(u_int8_t const* data, unsigned length) {
37 assign(data, length);
38}
39
40NetAddress::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
51NetAddress::NetAddress(NetAddress const& orig) {
52 assign(orig.data(), orig.length());
53}
54
55NetAddress& NetAddress::operator=(NetAddress const& rightSide) {
56 if (&rightSide != this) {
57 clean();
58 assign(rightSide.data(), rightSide.length());
59 }
60 return *this;
61}
62
63NetAddress::~NetAddress() {
64 clean();
65}
66
67void 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
78void NetAddress::clean() {
79 delete[] fData; fData = NULL;
80 fLength = 0;
81}
82
83
84////////// NetAddressList //////////
85
86NetAddressList::NetAddressList(char const* hostname)
87 : fNumAddresses(0), fAddressArray(NULL) {
88 // First, check whether "hostname" is an IP address string:
89 netAddressBits addr = our_inet_addr((char*)hostname);
90 if (addr != INADDR_NONE) {
91 // Yes, it was an IP address string. Return a 1-element list with this address:
92 fNumAddresses = 1;
93 fAddressArray = new NetAddress*[fNumAddresses];
94 if (fAddressArray == NULL) return;
95
96 fAddressArray[0] = new NetAddress((u_int8_t*)&addr, sizeof (netAddressBits));
97 return;
98 }
99
100 // "hostname" is not an IP address string; try resolving it as a real host name instead:
101#if defined(USE_GETHOSTBYNAME) || defined(VXWORKS)
102 struct hostent* host;
103#if defined(VXWORKS)
104 char hostentBuf[512];
105
106 host = (struct hostent*)resolvGetHostByName((char*)hostname, (char*)&hostentBuf, sizeof hostentBuf);
107#else
108 host = gethostbyname((char*)hostname);
109#endif
110 if (host == NULL || host->h_length != 4 || host->h_addr_list == NULL) return; // no luck
111
112 u_int8_t const** const hAddrPtr = (u_int8_t const**)host->h_addr_list;
113 // First, count the number of addresses:
114 u_int8_t const** hAddrPtr1 = hAddrPtr;
115 while (*hAddrPtr1 != NULL) {
116 ++fNumAddresses;
117 ++hAddrPtr1;
118 }
119
120 // Next, set up the list:
121 fAddressArray = new NetAddress*[fNumAddresses];
122 if (fAddressArray == NULL) return;
123
124 for (unsigned i = 0; i < fNumAddresses; ++i) {
125 fAddressArray[i] = new NetAddress(hAddrPtr[i], host->h_length);
126 }
127#else
128 // Use "getaddrinfo()" (rather than the older, deprecated "gethostbyname()"):
129 struct addrinfo addrinfoHints;
130 memset(&addrinfoHints, 0, sizeof addrinfoHints);
131 addrinfoHints.ai_family = AF_INET; // For now, we're interested in IPv4 addresses only
132 struct addrinfo* addrinfoResultPtr = NULL;
133 int result = getaddrinfo(hostname, NULL, &addrinfoHints, &addrinfoResultPtr);
134 if (result != 0 || addrinfoResultPtr == NULL) return; // no luck
135
136 // First, count the number of addresses:
137 const struct addrinfo* p = addrinfoResultPtr;
138 while (p != NULL) {
139 if (p->ai_addrlen < 4) continue; // sanity check: skip over addresses that are too small
140 ++fNumAddresses;
141 p = p->ai_next;
142 }
143
144 // Next, set up the list:
145 fAddressArray = new NetAddress*[fNumAddresses];
146 if (fAddressArray == NULL) return;
147
148 unsigned i = 0;
149 p = addrinfoResultPtr;
150 while (p != NULL) {
151 if (p->ai_addrlen < 4) continue;
152 fAddressArray[i++] = new NetAddress((u_int8_t const*)&(((struct sockaddr_in*)p->ai_addr)->sin_addr.s_addr), 4);
153 p = p->ai_next;
154 }
155
156 // Finally, free the data that we had allocated by calling "getaddrinfo()":
157 freeaddrinfo(addrinfoResultPtr);
158#endif
159}
160
161NetAddressList::NetAddressList(NetAddressList const& orig) {
162 assign(orig.numAddresses(), orig.fAddressArray);
163}
164
165NetAddressList& NetAddressList::operator=(NetAddressList const& rightSide) {
166 if (&rightSide != this) {
167 clean();
168 assign(rightSide.numAddresses(), rightSide.fAddressArray);
169 }
170 return *this;
171}
172
173NetAddressList::~NetAddressList() {
174 clean();
175}
176
177void NetAddressList::assign(unsigned numAddresses, NetAddress** addressArray) {
178 fAddressArray = new NetAddress*[numAddresses];
179 if (fAddressArray == NULL) {
180 fNumAddresses = 0;
181 return;
182 }
183
184 for (unsigned i = 0; i < numAddresses; ++i) {
185 fAddressArray[i] = new NetAddress(*addressArray[i]);
186 }
187 fNumAddresses = numAddresses;
188}
189
190void NetAddressList::clean() {
191 while (fNumAddresses-- > 0) {
192 delete fAddressArray[fNumAddresses];
193 }
194 delete[] fAddressArray; fAddressArray = NULL;
195}
196
197NetAddress const* NetAddressList::firstAddress() const {
198 if (fNumAddresses == 0) return NULL;
199
200 return fAddressArray[0];
201}
202
203////////// NetAddressList::Iterator //////////
204NetAddressList::Iterator::Iterator(NetAddressList const& addressList)
205 : fAddressList(addressList), fNextIndex(0) {}
206
207NetAddress const* NetAddressList::Iterator::nextAddress() {
208 if (fNextIndex >= fAddressList.numAddresses()) return NULL; // no more
209 return fAddressList.fAddressArray[fNextIndex++];
210}
211
212
213////////// Port //////////
214
215Port::Port(portNumBits num /* in host byte order */) {
216 fPortNum = htons(num);
217}
218
219UsageEnvironment& operator<<(UsageEnvironment& s, const Port& p) {
220 return s << ntohs(p.num());
221}
222
223
224////////// AddressPortLookupTable //////////
225
226AddressPortLookupTable::AddressPortLookupTable()
227 : fTable(HashTable::create(3)) { // three-word keys are used
228}
229
230AddressPortLookupTable::~AddressPortLookupTable() {
231 delete fTable;
232}
233
234void* AddressPortLookupTable::Add(netAddressBits address1,
235 netAddressBits address2,
236 Port port, void* value) {
237 int key[3];
238 key[0] = (int)address1;
239 key[1] = (int)address2;
240 key[2] = (int)port.num();
241 return fTable->Add((char*)key, value);
242}
243
244void* AddressPortLookupTable::Lookup(netAddressBits address1,
245 netAddressBits address2,
246 Port port) {
247 int key[3];
248 key[0] = (int)address1;
249 key[1] = (int)address2;
250 key[2] = (int)port.num();
251 return fTable->Lookup((char*)key);
252}
253
254Boolean AddressPortLookupTable::Remove(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->Remove((char*)key);
262}
263
264AddressPortLookupTable::Iterator::Iterator(AddressPortLookupTable& table)
265 : fIter(HashTable::Iterator::create(*(table.fTable))) {
266}
267
268AddressPortLookupTable::Iterator::~Iterator() {
269 delete fIter;
270}
271
272void* AddressPortLookupTable::Iterator::next() {
273 char const* key; // dummy
274 return fIter->next(key);
275}
276
277
278////////// isMulticastAddress() implementation //////////
279
280Boolean IsMulticastAddress(netAddressBits address) {
281 // Note: We return False for addresses in the range 224.0.0.0
282 // through 224.0.0.255, because these are non-routable
283 // Note: IPv4-specific #####
284 netAddressBits addressInNetworkOrder = htonl(address);
285 return addressInNetworkOrder > 0xE00000FF &&
286 addressInNetworkOrder <= 0xEFFFFFFF;
287}
288
289
290////////// AddressString implementation //////////
291
292AddressString::AddressString(struct sockaddr_in const& addr) {
293 init(addr.sin_addr.s_addr);
294}
295
296AddressString::AddressString(struct in_addr const& addr) {
297 init(addr.s_addr);
298}
299
300AddressString::AddressString(netAddressBits addr) {
301 init(addr);
302}
303
304void AddressString::init(netAddressBits addr) {
305 fVal = new char[16]; // large enough for "abc.def.ghi.jkl"
306 netAddressBits addrNBO = htonl(addr); // make sure we have a value in a known byte order: big endian
307 sprintf(fVal, "%u.%u.%u.%u", (addrNBO>>24)&0xFF, (addrNBO>>16)&0xFF, (addrNBO>>8)&0xFF, addrNBO&0xFF);
308}
309
310AddressString::~AddressString() {
311 delete[] fVal;
312}
313