summaryrefslogtreecommitdiff
path: root/TAO/tests/IOR_Endpoint_Hostnames/list_interfaces.cpp
blob: 10935773c5ca13e12978fe7aefe32af4ed916927 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
//
// Extract the address for each network interface using EXACTLY
// the same algorithm as TAO_IIOP_Acceptor, and then print
// it.  This is used by the run_test.pl to know how to set up
// "expected results" for hostnames in IORs.
//

#include "tao/corba.h"
#include "ace/ACE.h"
#include "ace/Auto_Ptr.h"
#include "ace/INET_Addr.h"
#include "ace/Log_Msg.h"
#include "ace/OS_NS_stdio.h"

ACE_RCSID (IOR_Endpoint_Hostnames,
           list_interfaces,
           "$Id$")

#if defined (ACE_HAS_IPV6) && !defined (ACE_USES_IPV4_IPV6_MIGRATION)
ACE_INET_Addr default_address (static_cast<unsigned short> (0), ACE_IPV6_ANY, AF_INET6);
#else
ACE_INET_Addr default_address (static_cast<unsigned short> (0), static_cast<ACE_UINT32> (INADDR_ANY));
#endif /* ACE_HAS_IPV6  && !ACE_USES_IPV4_IPV6_MIGRATION */

int
ACE_TMAIN(int argc, ACE_TCHAR *argv[])
{
  ACE_UNUSED_ARG (argc);
  ACE_UNUSED_ARG (argv);

  CORBA::ULong endpoint_count;
#if defined (ACE_HAS_IPV6)
  int def_type = AF_UNSPEC;
#endif /* ACE_HAS_IPV6 */

  // network interfaces.
  ACE_INET_Addr *if_addrs = 0;
  size_t if_cnt = 0;

  if (ACE::get_ip_interfaces (if_cnt,
                              if_addrs) != 0
      && errno != ENOTSUP)
    {
      // In the case where errno == ENOTSUP, if_cnt and if_addrs will
      // not be modified, and will each remain equal to zero.  This
      // causes the default interface to be used.
      return -1;
    }

  if (if_cnt == 0 || if_addrs == 0)
    {
      ACE_DEBUG ((LM_WARNING,
                  ACE_TEXT ("TAO (%P|%t) Unable to probe network ")
                  ACE_TEXT ("interfaces.  Using default.\n")));

      if_cnt = 1; // Force the network interface count to be one.
      delete [] if_addrs;
      ACE_NEW_RETURN (if_addrs,
                      ACE_INET_Addr[if_cnt],
                      -1);
    }

  // Scan for the loopback interface since it shouldn't be included in
  // the list of cached hostnames unless it is the only interface.
  size_t lo_cnt = 0;  // Loopback interface count
  for (size_t j = 0; j < if_cnt; ++j)
    if (if_addrs[j].is_loopback ())
      ++lo_cnt;

#if defined (ACE_HAS_IPV6)
  size_t ipv4_cnt = 0;
  size_t ipv4_lo_cnt = 0;
  size_t ipv6_ll = 0;
  bool ipv6_non_ll = false;
  // Scan for IPv4 interfaces since these should not be included
  // when IPv6-only is selected.
  for (size_t j = 0; j < if_cnt; ++j)
    if (if_addrs[j].get_type () != AF_INET6 ||
        if_addrs[j].is_ipv4_mapped_ipv6 ())
      {
        ++ipv4_cnt;
        if (if_addrs[j].is_loopback ())
          ++ipv4_lo_cnt;  // keep track of IPv4 loopback ifs
      }
    else if (!if_addrs[j].is_linklocal () &&
             !if_addrs[j].is_loopback())
      {
        ipv6_non_ll = true; // we have at least 1 non-local IPv6 if
      }
    else if (// !orb_core->orb_params ()->use_ipv6_link_local () &&
             if_addrs[j].is_linklocal ())
      {
        ++ipv6_ll;  // count link local addrs to exclude them afterwards
      }
#endif /* ACE_HAS_IPV6 */

  ACE_Auto_Basic_Array_Ptr<ACE_INET_Addr> safe_if_addrs (if_addrs);

#if defined (ACE_HAS_IPV6)
  bool ipv4_only = def_type == AF_INET;
  bool ipv6_only = (def_type == AF_INET6); // ||
  //    orb_core->orb_params ()->connect_ipv6_only ();
#if defined (ACE_WIN32)
  if (default_address.get_type () == AF_INET)
    ipv4_only = true;
  else
    ipv6_only = true;
#endif /* ACE_WIN32 */
  // If the loopback interface is the only interface then include it
  // in the list of interfaces to query for a hostname, otherwise
  // exclude it from the list.
  bool ignore_lo;
  if (ipv6_only)
    // only exclude loopback if non-local if exists
    ignore_lo = ipv6_non_ll;
  else if (ipv4_only)
    ignore_lo = ipv4_cnt != ipv4_lo_cnt;
  else
    ignore_lo = if_cnt != lo_cnt;

  // Adjust counts for IPv6 only if required
  size_t if_ok_cnt = if_cnt;
  if (ipv6_only)
    {
      if_ok_cnt -= ipv4_cnt;
      lo_cnt -= ipv4_lo_cnt;
      ipv4_lo_cnt = 0;
    }
  else if (ipv4_only)
    {
      if_ok_cnt = ipv4_cnt;
      lo_cnt = ipv4_lo_cnt;
      ipv6_ll = 0;
    }

  // In case there are no non-local IPv6 ifs in the list only exclude
  // IPv4 loopback.
  // IPv6 loopback will be needed to successfully connect IPv6 clients
  // in a localhost environment.
  if (!ipv4_only && !ipv6_non_ll)
    lo_cnt = ipv4_lo_cnt;

  if (!ignore_lo)
    endpoint_count = static_cast<CORBA::ULong> (if_ok_cnt - ipv6_ll);
  else
    endpoint_count = static_cast<CORBA::ULong> (if_ok_cnt - ipv6_ll - lo_cnt);
#else /* ACE_HAS_IPV6 */
  // If the loopback interface is the only interface then include it
  // in the list of interfaces to query for a hostname, otherwise
  // exclude it from the list.
  bool ignore_lo;
  ignore_lo = if_cnt != lo_cnt;
  if (!ignore_lo)
    endpoint_count = static_cast<CORBA::ULong> (if_cnt);
  else
    endpoint_count = static_cast<CORBA::ULong> (if_cnt - lo_cnt);
#endif /* !ACE_HAS_IPV6 */

  // The number of hosts/interfaces we want to cache may not be the
  // same as the number of detected interfaces so keep a separate
  // count.
  size_t host_cnt = 0;

  for (size_t i = 0; i < if_cnt; ++i)
    {
#if defined (ACE_HAS_IPV6)
      // Ignore any loopback interface if there are other
      // non-loopback interfaces.
      if (ignore_lo &&
          if_addrs[i].is_loopback () &&
          (ipv4_only ||
           ipv6_non_ll ||
           if_addrs[i].get_type () != AF_INET6))
        continue;

      // Ignore any non-IPv4 interfaces when so required.
      if (ipv4_only &&
          (if_addrs[i].get_type () != AF_INET))
        continue;

      // Ignore any non-IPv6 interfaces when so required.
      if (ipv6_only &&
          (if_addrs[i].get_type () != AF_INET6 ||
           if_addrs[i].is_ipv4_mapped_ipv6 ()))
        continue;

      // Ignore all IPv6 link local interfaces when so required.
      if (// !orb_core->orb_params ()->use_ipv6_link_local () &&
          if_addrs[i].is_linklocal ())
        continue;
#else /* ACE_HAS_IPV6 */
      // Ignore any loopback interface if there are other
      // non-loopback interfaces.
      if (ignore_lo &&
          if_addrs[i].is_loopback ())
        continue;
#endif /* !ACE_HAS_IPV6 */

      // Print the address as a string.
      ACE_OS::printf ("%s\n", if_addrs[i].get_host_addr());

      ++host_cnt;
    }

  return 0;
}