1 #include "ace/SOCK_Dgram_Bcast.h"
3 #include "ace/Log_Category.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
,
26 ACE_TRACE ("ACE_Bcast_Node::ACE_Bcast_Node");
29 ACE_ALLOC_HOOK_DEFINE(ACE_Bcast_Node
)
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.
42 ACE_SOCK_Dgram_Bcast::close ()
44 ACE_TRACE ("ACE_SOCK_Dgram_Bcast::close");
46 ACE_Bcast_Node
*temp
= this->if_list_
;
49 // Release the dynamically allocated memory.
53 ACE_Bcast_Node
*hold
= temp
->next_
;
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 ()
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
,
77 const ACE_TCHAR
*host_name
)
78 : ACE_SOCK_Dgram (local
, protocol_family
, protocol
, reuse_addr
),
81 ACE_TRACE ("ACE_SOCK_Dgram_Bcast::ACE_SOCK_Dgram_Bcast");
83 if (this->mk_broadcast (host_name
) == -1)
84 ACELIB_ERROR ((LM_ERROR
,
86 ACE_TEXT ("ACE_SOCK_Dgram_Bcast")));
89 // Here's the general-purpose open routine.
92 ACE_SOCK_Dgram_Bcast::open (const ACE_Addr
&local
,
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)
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");
116 if (ACE_OS::setsockopt (this->get_handle (),
121 ACELIB_ERROR_RETURN ((LM_ERROR
, ACE_TEXT("%p\n"),
122 ACE_TEXT("ACE_SOCK_Dgram_Bcast::mk_broadcast: setsockopt failed")),
125 #if !defined (ACE_WIN32)
126 ACE_HANDLE s
= this->get_handle ();
131 ifc
.ifc_len
= sizeof buf
;
134 // Get interface structure and initialize the addresses using UNIX
136 if (ACE_OS::ioctl (s
,
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)")),
143 struct ifreq
*ifr
= ifc
.ifc_req
;
145 struct sockaddr_in host_addr
;
147 // Get host ip address
150 hostent
*hp
= ACE_OS::gethostbyname (ACE_TEXT_ALWAYS_CHAR (host_name
));
155 ACE_OS::memcpy ((char *) &host_addr
.sin_addr
.s_addr
,
156 # ifdef ACE_HOSTENT_H_ADDR
157 (char *) hp
->ACE_HOSTENT_H_ADDR
,
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;
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
)
189 #endif /* __QNX__ || ACE_VXWORKS */
190 // Compare host ip address with interface ip address.
193 struct sockaddr_in if_addr
;
195 ACE_OS::memcpy (&if_addr
,
199 if (host_addr
.sin_addr
.s_addr
!= if_addr
.sin_addr
.s_addr
)
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
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
));
218 struct ifreq flags
= *ifr
;
219 struct ifreq if_req
= *ifr
;
221 if (ACE_OS::ioctl (s
,
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)"),
231 if (ACE_BIT_ENABLED (flags
.ifr_flags
,
234 ACELIB_ERROR ((LM_ERROR
, ACE_TEXT("%p [%C]\n"),
235 ACE_TEXT("ACE_SOCK_Dgram_Bcast::mk_broadcast: Network interface is not up"),
240 if (ACE_BIT_ENABLED (flags
.ifr_flags
,
244 if (ACE_BIT_ENABLED (flags
.ifr_flags
,
247 if (ACE_OS::ioctl (s
,
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)"),
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
,
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."),
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
,
281 #endif /* !ACE_WIN32 */
282 if (this->if_list_
== 0)
291 // Broadcast the datagram to every interface. Returns the average
292 // number of bytes sent.
295 ACE_SOCK_Dgram_Bcast::send (const void *buf
,
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)
307 for (ACE_Bcast_Node
*temp
= this->if_list_
;
311 temp
->bcast_addr_
.set_port_number (port_number
);
313 ssize_t bytes_sent
= ACE_SOCK_Dgram::send (buf
,
318 if (bytes_sent
== -1)
321 total_bytes
+= bytes_sent
;
326 return iterations
== 0 ? 0 : total_bytes
/ iterations
;
329 #if defined (ACE_HAS_MSG)
330 // Broadcast datagram to every interfaces.
333 ACE_SOCK_Dgram_Bcast::send (const iovec iov
[],
338 ACE_TRACE ("ACE_SOCK_Dgram_Bcast::send");
340 if (this->if_list_
== 0)
343 // Send the message to every interface.
345 for (ACE_Bcast_Node
*temp
= this->if_list_
;
349 temp
->bcast_addr_
.set_port_number (port_number
);
351 if (ACE_SOCK_Dgram::send (iov
,
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...).
365 ACE_SOCK_Dgram_Bcast::send (const iovec iov
[],
367 const ACE_Addr
&addr
,
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