1 /*---------------------------------------------------------------
2 * Copyright (c) 1999,2000,2001,2002,2003
3 * The Board of Trustees of the University of Illinois
5 *---------------------------------------------------------------
6 * Permission is hereby granted, free of charge, to any person
7 * obtaining a copy of this software (Iperf) and associated
8 * documentation files (the "Software"), to deal in the Software
9 * without restriction, including without limitation the
10 * rights to use, copy, modify, merge, publish, distribute,
11 * sublicense, and/or sell copies of the Software, and to permit
12 * persons to whom the Software is furnished to do
13 * so, subject to the following conditions:
16 * Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and
18 * the following disclaimers.
21 * Redistributions in binary form must reproduce the above
22 * copyright notice, this list of conditions and the following
23 * disclaimers in the documentation and/or other materials
24 * provided with the distribution.
27 * Neither the names of the University of Illinois, NCSA,
28 * nor the names of its contributors may be used to endorse
29 * or promote products derived from this Software without
30 * specific prior written permission.
32 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
33 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
34 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
35 * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT
36 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
37 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
38 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE
39 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
40 * ________________________________________________________________
41 * National Laboratory for Applied Network Research
42 * National Center for Supercomputing Applications
43 * University of Illinois at Urbana-Champaign
44 * http://www.ncsa.uiuc.edu
45 * ________________________________________________________________
48 * by Ajay Tirumala <tirumala@ncsa.uiuc.edu>
49 * and Mark Gates <mgates@nlanr.net>
50 * ------------------------------------------------------------------- */
56 #include "SocketAddr.h"
62 /* -------------------------------------------------------------------
63 * Create a socket address. If inHostname is not null, resolve that
64 * address and fill it in. Fill in the port number. Use IPv6 ADDR_ANY
65 * if that is what is desired.
66 * ------------------------------------------------------------------- */
68 void SockAddr_remoteAddr( thread_Settings *inSettings ) {
69 SockAddr_zeroAddress( &inSettings->peer );
70 if ( inSettings->mHost != NULL ) {
71 SockAddr_setHostname( inSettings->mHost, &inSettings->peer,
72 isIPV6( inSettings ) );
75 if ( isIPV6( inSettings ) ) {
76 ((struct sockaddr*)&inSettings->peer)->sa_family = AF_INET6;
78 ((struct sockaddr*)&inSettings->peer)->sa_family = AF_INET;
82 if ( SockAddr_isIPv6( &inSettings->peer ) ) {
83 inSettings->size_peer = sizeof( struct sockaddr_in6 );
85 inSettings->size_peer = sizeof( struct sockaddr_in );
88 ((struct sockaddr*)&inSettings->peer)->sa_family = AF_INET;
90 inSettings->size_peer = sizeof( struct sockaddr_in );
92 SockAddr_setPort( &inSettings->peer, inSettings->mPort );
96 void SockAddr_localAddr( thread_Settings *inSettings ) {
97 SockAddr_zeroAddress( &inSettings->local );
98 if ( inSettings->mLocalhost != NULL ) {
99 SockAddr_setHostname( inSettings->mLocalhost, &inSettings->local,
100 isIPV6( inSettings ) );
103 if ( isIPV6( inSettings ) ) {
104 ((struct sockaddr*)&inSettings->local)->sa_family = AF_INET6;
106 ((struct sockaddr*)&inSettings->local)->sa_family = AF_INET;
110 if ( SockAddr_isIPv6( &inSettings->local ) ) {
111 inSettings->size_local = sizeof( struct sockaddr_in6 );
113 inSettings->size_local = sizeof( struct sockaddr_in );
116 ((struct sockaddr*)&inSettings->local)->sa_family = AF_INET;
118 inSettings->size_local = sizeof( struct sockaddr_in );
120 SockAddr_setPort( &inSettings->local, inSettings->mPort );
124 /* -------------------------------------------------------------------
125 * Resolve the hostname address and fill it in.
126 * ------------------------------------------------------------------- */
128 void SockAddr_setHostname( const char* inHostname,
129 iperf_sockaddr *inSockAddr,
132 // ..I think this works for both ipv6 & ipv4... we'll see
133 #if defined(HAVE_IPV6)
135 struct addrinfo *res, *itr;
138 ret_ga = getaddrinfo(inHostname, NULL, NULL, &res);
140 fprintf(stderr, "error: %s\n", gai_strerror(ret_ga));
143 if ( !res->ai_addr ) {
144 fprintf(stderr, "getaddrinfo failed to get an address... target was '%s'\n", inHostname);
148 // Check address type before filling in the address
149 // ai_family = PF_xxx; ai_protocol = IPPROTO_xxx, see netdb.h
150 // ...but AF_INET6 == PF_INET6
153 // First check all results for a IPv6 Address
154 while ( itr != NULL ) {
155 if ( itr->ai_family == AF_INET6 ) {
156 memcpy(inSockAddr, (itr->ai_addr),
166 // Now find a IPv4 Address
167 while ( itr != NULL ) {
168 if ( itr->ai_family == AF_INET ) {
169 memcpy(inSockAddr, (itr->ai_addr),
179 // first try just converting dotted decimal
180 // on Windows gethostbyname doesn't understand dotted decimal
181 int rc = inet_pton( AF_INET, inHostname,
182 (unsigned char*)&(((struct sockaddr_in*)inSockAddr)->sin_addr) );
183 inSockAddr->sin_family = AF_INET;
185 struct hostent *hostP = gethostbyname( inHostname );
186 if ( hostP == NULL ) {
187 /* this is the same as herror() but works on more systems */
191 format = "%s: Unknown host\n";
194 format = "%s: No address associated with name\n";
197 format = "%s: Unknown server error\n";
200 format = "%s: Host name lookup failure\n";
204 format = "%s: Unknown resolver error\n";
207 fprintf( stderr, format, inHostname );
210 return; // TODO throw
213 memcpy(&(((struct sockaddr_in*)inSockAddr)->sin_addr), *(hostP->h_addr_list),
220 /* -------------------------------------------------------------------
221 * Copy the IP address into the string.
222 * ------------------------------------------------------------------- */
223 void SockAddr_getHostAddress( iperf_sockaddr *inSockAddr, char* outAddress,
225 if ( ((struct sockaddr*)inSockAddr)->sa_family == AF_INET ) {
226 inet_ntop( AF_INET, &(((struct sockaddr_in*) inSockAddr)->sin_addr),
231 inet_ntop( AF_INET6, &(((struct sockaddr_in6*) inSockAddr)->sin6_addr),
236 // end getHostAddress
238 /* -------------------------------------------------------------------
239 * Set the address to any (generally all zeros).
240 * ------------------------------------------------------------------- */
242 void SockAddr_setAddressAny( iperf_sockaddr *inSockAddr ) {
243 if ( ((struct sockaddr*)inSockAddr)->sa_family == AF_INET )
244 memset( &(((struct sockaddr_in*) inSockAddr)->sin_addr), 0,
245 sizeof( struct in_addr ));
246 #if defined(HAVE_IPV6)
248 memset( &(((struct sockaddr_in6*) inSockAddr)->sin6_addr), 0,
249 sizeof( struct in6_addr ));
254 /* -------------------------------------------------------------------
255 * Set the port to the given port. Handles the byte swapping.
256 * ------------------------------------------------------------------- */
258 void SockAddr_setPort( iperf_sockaddr *inSockAddr, unsigned short inPort ) {
259 if ( ((struct sockaddr*)inSockAddr)->sa_family == AF_INET )
260 ((struct sockaddr_in*) inSockAddr)->sin_port = htons( inPort );
261 #if defined(HAVE_IPV6)
263 ((struct sockaddr_in6*) inSockAddr)->sin6_port = htons( inPort );
269 /* -------------------------------------------------------------------
270 * Set the port to zero, which lets the OS pick the port.
271 * ------------------------------------------------------------------- */
273 void SockAddr_setPortAny( iperf_sockaddr *inSockAddr ) {
274 SockAddr_setPort( inSockAddr, 0 );
278 /* -------------------------------------------------------------------
279 * Return the port. Handles the byte swapping.
280 * ------------------------------------------------------------------- */
282 unsigned short SockAddr_getPort( iperf_sockaddr *inSockAddr ) {
283 if ( ((struct sockaddr*)inSockAddr)->sa_family == AF_INET )
284 return ntohs( ((struct sockaddr_in*) inSockAddr)->sin_port );
285 #if defined(HAVE_IPV6)
287 return ntohs( ((struct sockaddr_in6*) inSockAddr)->sin6_port);
294 /* -------------------------------------------------------------------
295 * Return the IPv4 Internet Address from the sockaddr_in structure
296 * ------------------------------------------------------------------- */
298 struct in_addr* SockAddr_get_in_addr( iperf_sockaddr *inSockAddr ) {
299 if ( ((struct sockaddr*)inSockAddr)->sa_family == AF_INET )
300 return &(((struct sockaddr_in*) inSockAddr)->sin_addr);
302 fprintf(stderr, "FATAL: get_in_addr called on IPv6 address\n");
306 /* -------------------------------------------------------------------
307 * Return the IPv6 Internet Address from the sockaddr_in6 structure
308 * ------------------------------------------------------------------- */
310 struct in6_addr* SockAddr_get_in6_addr( iperf_sockaddr *inSockAddr ) {
311 if ( ((struct sockaddr*)inSockAddr)->sa_family == AF_INET6 )
312 return &(((struct sockaddr_in6*) inSockAddr)->sin6_addr);
314 fprintf(stderr, "FATAL: get_in6_addr called on IPv4 address\n");
320 /* -------------------------------------------------------------------
321 * Return the size of the appropriate address structure.
322 * ------------------------------------------------------------------- */
324 Socklen_t SockAddr_get_sizeof_sockaddr( iperf_sockaddr *inSockAddr ) {
326 #if defined(HAVE_IPV6)
327 if ( ((struct sockaddr*)inSockAddr)->sa_family == AF_INET6 ) {
328 return(sizeof(struct sockaddr_in6));
331 return(sizeof(struct sockaddr_in));
333 // end get_sizeof_sockaddr
336 /* -------------------------------------------------------------------
337 * Return if IPv6 socket
338 * ------------------------------------------------------------------- */
340 int SockAddr_isIPv6( iperf_sockaddr *inSockAddr ) {
342 #if defined(HAVE_IPV6)
343 if ( ((struct sockaddr*)inSockAddr)->sa_family == AF_INET6 ) {
349 // end get_sizeof_sockaddr
351 /* -------------------------------------------------------------------
352 * Return true if the address is a IPv4 multicast address.
353 * ------------------------------------------------------------------- */
355 int SockAddr_isMulticast( iperf_sockaddr *inSockAddr ) {
357 #if defined(HAVE_IPV6)
358 if ( ((struct sockaddr*)inSockAddr)->sa_family == AF_INET6 ) {
359 return( IN6_IS_ADDR_MULTICAST(&(((struct sockaddr_in6*) inSockAddr)->sin6_addr) ));
363 // 224.0.0.0 to 239.255.255.255 (e0.00.00.00 to ef.ff.ff.ff)
364 const unsigned long kMulticast_Mask = 0xe0000000L;
366 return(kMulticast_Mask ==
367 (ntohl( ((struct sockaddr_in*) inSockAddr)->sin_addr.s_addr) & kMulticast_Mask));
372 /* -------------------------------------------------------------------
373 * Zero out the address structure.
374 * ------------------------------------------------------------------- */
376 void SockAddr_zeroAddress( iperf_sockaddr *inSockAddr ) {
377 memset( inSockAddr, 0, sizeof( iperf_sockaddr ));
381 /* -------------------------------------------------------------------
382 * Compare two sockaddrs and return true if they are equal
383 * ------------------------------------------------------------------- */
384 int SockAddr_are_Equal( struct sockaddr* first, struct sockaddr* second ) {
385 if ( first->sa_family == AF_INET && second->sa_family == AF_INET ) {
386 // compare IPv4 adresses
387 return( ((long) ((struct sockaddr_in*)first)->sin_addr.s_addr == (long) ((struct sockaddr_in*)second)->sin_addr.s_addr)
388 && ( ((struct sockaddr_in*)first)->sin_port == ((struct sockaddr_in*)second)->sin_port) );
390 #if defined(HAVE_IPV6)
391 if ( first->sa_family == AF_INET6 && second->sa_family == AF_INET6 ) {
392 // compare IPv6 addresses
393 return( !memcmp(((struct sockaddr_in6*)first)->sin6_addr.s6_addr, ((struct sockaddr_in6*)second)->sin6_addr.s6_addr, sizeof(struct in6_addr))
394 && (((struct sockaddr_in6*)first)->sin6_port == ((struct sockaddr_in6*)second)->sin6_port) );
401 /* -------------------------------------------------------------------
402 * Compare two sockaddrs and return true if the hosts are equal
403 * ------------------------------------------------------------------- */
404 int SockAddr_Hostare_Equal( struct sockaddr* first, struct sockaddr* second ) {
405 if ( first->sa_family == AF_INET && second->sa_family == AF_INET ) {
406 // compare IPv4 adresses
407 return( (long) ((struct sockaddr_in*)first)->sin_addr.s_addr ==
408 (long) ((struct sockaddr_in*)second)->sin_addr.s_addr);
410 #if defined(HAVE_IPV6)
411 if ( first->sa_family == AF_INET6 && second->sa_family == AF_INET6 ) {
412 // compare IPv6 addresses
413 return( !memcmp(((struct sockaddr_in6*)first)->sin6_addr.s6_addr,
414 ((struct sockaddr_in6*)second)->sin6_addr.s6_addr, sizeof(struct in6_addr)));
421 } /* end extern "C" */