Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / ace / SOCK_Dgram_Bcast.cpp
blob129fcdce25b0011a8f1faa168678428919d9c11d
1 #include "ace/SOCK_Dgram_Bcast.h"
3 #include "ace/Log_Category.h"
4 #include "ace/ACE.h"
5 #include "ace/OS_NS_string.h"
6 #include "ace/os_include/net/os_if.h"
7 #include "ace/OS_NS_netdb.h"
8 #include "ace/OS_Memory.h"
9 #if defined (ACE_HAS_ALLOC_HOOKS)
10 # include "ace/Malloc_Base.h"
11 #endif /* ACE_HAS_ALLOC_HOOKS */
13 #if !defined (__ACE_INLINE__)
14 #include "ace/SOCK_Dgram_Bcast.inl"
15 #endif /* __ACE_INLINE__ */
17 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
19 ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_Dgram_Bcast)
21 ACE_Bcast_Node::ACE_Bcast_Node (ACE_INET_Addr &addr,
22 ACE_Bcast_Node *next)
23 : bcast_addr_ (addr),
24 next_ (next)
26 ACE_TRACE ("ACE_Bcast_Node::ACE_Bcast_Node");
29 ACE_ALLOC_HOOK_DEFINE(ACE_Bcast_Node)
31 void
32 ACE_SOCK_Dgram_Bcast::dump () const
34 #if defined (ACE_HAS_DUMP)
35 ACE_TRACE ("ACE_SOCK_Dgram_Bcast::dump");
36 #endif /* ACE_HAS_DUMP */
39 // Close up and release resources.
41 int
42 ACE_SOCK_Dgram_Bcast::close ()
44 ACE_TRACE ("ACE_SOCK_Dgram_Bcast::close");
46 ACE_Bcast_Node *temp = this->if_list_;
47 this->if_list_ = 0;
49 // Release the dynamically allocated memory.
51 while (temp != 0)
53 ACE_Bcast_Node *hold = temp->next_;
54 delete temp;
55 temp = hold;
58 // Shut down the descriptor.
59 return ACE_SOCK::close ();
62 // Here's the simple-minded constructor.
64 ACE_SOCK_Dgram_Bcast::ACE_SOCK_Dgram_Bcast ()
65 : if_list_ (0)
67 ACE_TRACE ("ACE_SOCK_Dgram_Bcast::ACE_SOCK_Dgram_Bcast");
70 // Here's the general-purpose constructor used by a connectionless
71 // datagram ``server''...
73 ACE_SOCK_Dgram_Bcast::ACE_SOCK_Dgram_Bcast (const ACE_Addr &local,
74 int protocol_family,
75 int protocol,
76 int reuse_addr,
77 const ACE_TCHAR *host_name)
78 : ACE_SOCK_Dgram (local, protocol_family, protocol, reuse_addr),
79 if_list_ (0)
81 ACE_TRACE ("ACE_SOCK_Dgram_Bcast::ACE_SOCK_Dgram_Bcast");
83 if (this->mk_broadcast (host_name) == -1)
84 ACELIB_ERROR ((LM_ERROR,
85 ACE_TEXT ("%p\n"),
86 ACE_TEXT ("ACE_SOCK_Dgram_Bcast")));
89 // Here's the general-purpose open routine.
91 int
92 ACE_SOCK_Dgram_Bcast::open (const ACE_Addr &local,
93 int protocol_family,
94 int protocol,
95 int reuse_addr,
96 const ACE_TCHAR *host_name)
98 ACE_TRACE ("ACE_SOCK_Dgram_Bcast::open");
100 if (this->ACE_SOCK_Dgram::open (local, protocol_family,
101 protocol, reuse_addr) == -1)
102 return -1;
104 return this->mk_broadcast (host_name);
107 // Make broadcast available for Datagram socket.
110 ACE_SOCK_Dgram_Bcast::mk_broadcast (const ACE_TCHAR *host_name)
112 ACE_TRACE ("ACE_SOCK_Dgram_Bcast::mk_broadcast");
114 int one = 1;
116 if (ACE_OS::setsockopt (this->get_handle (),
117 SOL_SOCKET,
118 SO_BROADCAST,
119 (char *) &one,
120 sizeof one) == -1)
121 ACELIB_ERROR_RETURN ((LM_ERROR, ACE_TEXT("%p\n"),
122 ACE_TEXT("ACE_SOCK_Dgram_Bcast::mk_broadcast: setsockopt failed")),
123 -1);
125 #if !defined (ACE_WIN32)
126 ACE_HANDLE s = this->get_handle ();
128 char buf[BUFSIZ];
129 struct ifconf ifc;
131 ifc.ifc_len = sizeof buf;
132 ifc.ifc_buf = buf;
134 // Get interface structure and initialize the addresses using UNIX
135 // techniques.
136 if (ACE_OS::ioctl (s,
137 SIOCGIFCONF,
138 (char *) &ifc) == -1)
139 ACELIB_ERROR_RETURN ((LM_ERROR, ACE_TEXT("%p\n"),
140 ACE_TEXT("ACE_SOCK_Dgram_Bcast::mk_broadcast: ioctl (get interface configuration)")),
141 ACE_INVALID_HANDLE);
143 struct ifreq *ifr = ifc.ifc_req;
145 struct sockaddr_in host_addr;
147 // Get host ip address
148 if (host_name)
150 hostent *hp = ACE_OS::gethostbyname (ACE_TEXT_ALWAYS_CHAR (host_name));
152 if (hp == 0)
153 return -1;
154 else
155 ACE_OS::memcpy ((char *) &host_addr.sin_addr.s_addr,
156 # ifdef ACE_HOSTENT_H_ADDR
157 (char *) hp->ACE_HOSTENT_H_ADDR,
158 # else
159 (char *) hp->h_addr,
160 # endif
161 hp->h_length);
165 #if !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (ACE_VXWORKS) && !defined(__APPLE__)
166 for (int n = ifc.ifc_len / sizeof (struct ifreq) ; n > 0;
167 n--, ifr++)
168 #else
170 There are addresses longer than sizeof (struct sockaddr) eg. IPv6
171 or QNX::links. In this case address does not fit into struct ifreq.
172 The code below could be applied everywhere, but not every system
173 provides sockaddr.sa_len field.
175 for (int nbytes = ifc.ifc_len; nbytes >= (int) sizeof (struct ifreq) &&
176 ((ifr->ifr_addr.sa_len > sizeof (struct sockaddr)) ?
177 (nbytes >= (int) sizeof (ifr->ifr_name) + ifr->ifr_addr.sa_len) : 1);
178 ((ifr->ifr_addr.sa_len > sizeof (struct sockaddr)) ?
179 (nbytes -= sizeof (ifr->ifr_name) + ifr->ifr_addr.sa_len,
180 ifr = (struct ifreq *)
181 ((caddr_t) &ifr->ifr_addr + ifr->ifr_addr.sa_len)) :
182 (nbytes -= sizeof (struct ifreq), ifr++)))
183 #endif /* !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (ACE_VXWORKS) && !defined(__APPLE__) */
185 #if defined (__QNX__) || defined (ACE_VXWORKS)
186 // Silently skip link interfaces
187 if (ifr->ifr_addr.sa_family == AF_LINK)
188 continue;
189 #endif /* __QNX__ || ACE_VXWORKS */
190 // Compare host ip address with interface ip address.
191 if (host_name)
193 struct sockaddr_in if_addr;
195 ACE_OS::memcpy (&if_addr,
196 &ifr->ifr_addr,
197 sizeof if_addr);
199 if (host_addr.sin_addr.s_addr != if_addr.sin_addr.s_addr)
200 continue;
203 if (ifr->ifr_addr.sa_family != AF_INET)
205 // Note that some systems seem to generate 0 (AF_UNDEF) for
206 // the sa_family, even when there are no errors! Thus, we
207 // only print an error if this is not the case, or if we're
208 // in "debugging" mode.
209 if (ifr->ifr_addr.sa_family != 0
210 || ACE::debug ())
211 ACELIB_DEBUG ((LM_DEBUG,
212 ACE_TEXT("warning %p: sa_family: %d\n"),
213 ACE_TEXT("ACE_SOCK_Dgram_Bcast::mk_broadcast: Not AF_INET"),
214 ifr->ifr_addr.sa_family));
215 continue;
218 struct ifreq flags = *ifr;
219 struct ifreq if_req = *ifr;
221 if (ACE_OS::ioctl (s,
222 SIOCGIFFLAGS,
223 (char *) &flags) == -1)
225 ACELIB_ERROR ((LM_ERROR, ACE_TEXT("%p [%C]\n"),
226 ACE_TEXT("ACE_SOCK_Dgram_Bcast::mk_broadcast: ioctl (get interface flags)"),
227 flags.ifr_name));
228 continue;
231 if (ACE_BIT_ENABLED (flags.ifr_flags,
232 IFF_UP) == 0)
234 ACELIB_ERROR ((LM_ERROR, ACE_TEXT("%p [%C]\n"),
235 ACE_TEXT("ACE_SOCK_Dgram_Bcast::mk_broadcast: Network interface is not up"),
236 flags.ifr_name));
237 continue;
240 if (ACE_BIT_ENABLED (flags.ifr_flags,
241 IFF_LOOPBACK))
242 continue;
244 if (ACE_BIT_ENABLED (flags.ifr_flags,
245 IFF_BROADCAST))
247 if (ACE_OS::ioctl (s,
248 SIOCGIFBRDADDR,
249 (char *) &if_req) == -1)
250 ACELIB_ERROR ((LM_ERROR, ACE_TEXT("%p [%C]\n"),
251 ACE_TEXT("ACE_SOCK_Dgram_Bcast::mk_broadcast: ioctl (get broadaddr)"),
252 flags.ifr_name));
253 else
255 ACE_INET_Addr addr (reinterpret_cast <sockaddr_in *>
256 (&if_req.ifr_broadaddr),
257 sizeof if_req.ifr_broadaddr);
258 ACE_NEW_RETURN (this->if_list_,
259 ACE_Bcast_Node (addr,
260 this->if_list_),
261 -1);
264 else
266 if (host_name != 0)
267 ACELIB_ERROR ((LM_ERROR, ACE_TEXT("%p [%C]\n"),
268 ACE_TEXT("ACE_SOCK_Dgram_Bcast::mk_broadcast: Broadcast is not enabled for this interface."),
269 flags.ifr_name));
272 #else
273 ACE_UNUSED_ARG (host_name);
275 ACE_INET_Addr addr (u_short (0),
276 ACE_UINT32 (INADDR_BROADCAST));
277 ACE_NEW_RETURN (this->if_list_,
278 ACE_Bcast_Node (addr,
279 this->if_list_),
280 -1);
281 #endif /* !ACE_WIN32 */
282 if (this->if_list_ == 0)
284 errno = ENXIO;
285 return -1;
287 else
288 return 0;
291 // Broadcast the datagram to every interface. Returns the average
292 // number of bytes sent.
294 ssize_t
295 ACE_SOCK_Dgram_Bcast::send (const void *buf,
296 size_t n,
297 u_short port_number,
298 int flags) const
300 ACE_TRACE ("ACE_SOCK_Dgram_Bcast::send");
301 ssize_t iterations = 0;
302 ssize_t total_bytes = 0;
304 if (this->if_list_ == 0)
305 return -1;
307 for (ACE_Bcast_Node *temp = this->if_list_;
308 temp != 0;
309 temp = temp->next_)
311 temp->bcast_addr_.set_port_number (port_number);
313 ssize_t bytes_sent = ACE_SOCK_Dgram::send (buf,
315 temp->bcast_addr_,
316 flags);
318 if (bytes_sent == -1)
319 return -1;
320 else
321 total_bytes += bytes_sent;
323 iterations++;
326 return iterations == 0 ? 0 : total_bytes / iterations;
329 #if defined (ACE_HAS_MSG)
330 // Broadcast datagram to every interfaces.
332 ssize_t
333 ACE_SOCK_Dgram_Bcast::send (const iovec iov[],
334 int n,
335 u_short port_number,
336 int flags) const
338 ACE_TRACE ("ACE_SOCK_Dgram_Bcast::send");
340 if (this->if_list_ == 0)
341 return -1;
343 // Send the message to every interface.
345 for (ACE_Bcast_Node *temp = this->if_list_;
346 temp != 0;
347 temp = temp->next_)
349 temp->bcast_addr_.set_port_number (port_number);
351 if (ACE_SOCK_Dgram::send (iov,
353 temp->bcast_addr_,
354 flags) == -1)
355 return -1;
358 return 0;
361 // Broadcast an iovec of size N to ADDR as a datagram (note that addr
362 // must be preassigned to the broadcast address of the subnet...).
364 ssize_t
365 ACE_SOCK_Dgram_Bcast::send (const iovec iov[],
366 int n,
367 const ACE_Addr &addr,
368 int flags) const
370 ACE_TRACE ("ACE_SOCK_Dgram_Bcast::send");
372 return ACE_SOCK_Dgram::send (iov, n, addr, flags);
374 #endif /* ACE_HAS_MSG */
376 ACE_END_VERSIONED_NAMESPACE_DECL