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