00001
00002
00003 #include "ace/SOCK_Dgram_Bcast.h"
00004
00005 #include "ace/Log_Msg.h"
00006 #include "ace/ACE.h"
00007 #include "ace/OS_NS_string.h"
00008 #include "ace/os_include/net/os_if.h"
00009 #include "ace/OS_NS_netdb.h"
00010 #include "ace/OS_Memory.h"
00011
00012 #if !defined (__ACE_INLINE__)
00013 #include "ace/SOCK_Dgram_Bcast.inl"
00014 #endif
00015
00016 ACE_RCSID(ace, SOCK_Dgram_Bcast, "SOCK_Dgram_Bcast.cpp,v 4.45 2006/05/30 10:57:22 jwillemsen Exp")
00017
00018 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00019
00020 ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_Dgram_Bcast)
00021
00022 ACE_Bcast_Node::ACE_Bcast_Node (ACE_INET_Addr &addr,
00023 ACE_Bcast_Node *next)
00024 : bcast_addr_ (addr),
00025 next_ (next)
00026 {
00027 ACE_TRACE ("ACE_Bcast_Node::ACE_Bcast_Node");
00028 }
00029
00030 void
00031 ACE_SOCK_Dgram_Bcast::dump (void) const
00032 {
00033 #if defined (ACE_HAS_DUMP)
00034 ACE_TRACE ("ACE_SOCK_Dgram_Bcast::dump");
00035 #endif
00036 }
00037
00038
00039
00040 int
00041 ACE_SOCK_Dgram_Bcast::close (void)
00042 {
00043 ACE_TRACE ("ACE_SOCK_Dgram_Bcast::close");
00044
00045 ACE_Bcast_Node *temp = this->if_list_;
00046 this->if_list_ = 0;
00047
00048
00049
00050 while (temp != 0)
00051 {
00052 ACE_Bcast_Node *hold = temp->next_;
00053 delete temp;
00054 temp = hold;
00055 }
00056
00057
00058 return ACE_SOCK::close ();
00059 }
00060
00061
00062
00063 ACE_SOCK_Dgram_Bcast::ACE_SOCK_Dgram_Bcast (void)
00064 : if_list_ (0)
00065 {
00066 ACE_TRACE ("ACE_SOCK_Dgram_Bcast::ACE_SOCK_Dgram_Bcast");
00067 }
00068
00069
00070
00071
00072 ACE_SOCK_Dgram_Bcast::ACE_SOCK_Dgram_Bcast (const ACE_Addr &local,
00073 int protocol_family,
00074 int protocol,
00075 int reuse_addr,
00076 const ACE_TCHAR *host_name)
00077 : ACE_SOCK_Dgram (local, protocol_family, protocol, reuse_addr),
00078 if_list_ (0)
00079 {
00080 ACE_TRACE ("ACE_SOCK_Dgram_Bcast::ACE_SOCK_Dgram_Bcast");
00081
00082 if (this->mk_broadcast (host_name) == -1)
00083 ACE_ERROR ((LM_ERROR,
00084 ACE_LIB_TEXT ("%p\n"),
00085 ACE_LIB_TEXT ("ACE_SOCK_Dgram_Bcast")));
00086 }
00087
00088
00089
00090 int
00091 ACE_SOCK_Dgram_Bcast::open (const ACE_Addr &local,
00092 int protocol_family,
00093 int protocol,
00094 int reuse_addr,
00095 const ACE_TCHAR *host_name)
00096 {
00097 ACE_TRACE ("ACE_SOCK_Dgram_Bcast::open");
00098
00099 if (this->ACE_SOCK_Dgram::open (local, protocol_family,
00100 protocol, reuse_addr) == -1)
00101 return -1;
00102
00103 return this->mk_broadcast (host_name);
00104 }
00105
00106
00107
00108 int
00109 ACE_SOCK_Dgram_Bcast::mk_broadcast (const ACE_TCHAR *host_name)
00110 {
00111 ACE_TRACE ("ACE_SOCK_Dgram_Bcast::mk_broadcast");
00112
00113 int one = 1;
00114
00115 if (ACE_OS::setsockopt (this->get_handle (),
00116 SOL_SOCKET,
00117 SO_BROADCAST,
00118 (char *) &one,
00119 sizeof one) == -1)
00120 ACE_ERROR_RETURN ((LM_ERROR, "%p\n",
00121 "ACE_SOCK_Dgram_Bcast::mk_broadcast: setsockopt failed"),
00122 -1);
00123
00124 #if !defined (ACE_WIN32) && !defined(__INTERIX)
00125 ACE_HANDLE s = this->get_handle ();
00126
00127 char buf[BUFSIZ];
00128 struct ifconf ifc;
00129
00130 ifc.ifc_len = sizeof buf;
00131 ifc.ifc_buf = buf;
00132
00133
00134
00135 if (ACE_OS::ioctl (s,
00136 SIOCGIFCONF,
00137 (char *) &ifc) == -1)
00138 ACE_ERROR_RETURN ((LM_ERROR, "%p\n",
00139 "ACE_SOCK_Dgram_Bcast::mk_broadcast: ioctl (get interface configuration)"),
00140 ACE_INVALID_HANDLE);
00141
00142 struct ifreq *ifr = ifc.ifc_req;
00143
00144 struct sockaddr_in host_addr;
00145
00146
00147 if (host_name)
00148 {
00149 hostent *hp = ACE_OS::gethostbyname (ACE_TEXT_ALWAYS_CHAR (host_name));
00150
00151 if (hp == 0)
00152 return -1;
00153 else
00154 #if defined(_UNICOS)
00155 {
00156 ACE_UINT64 haddr;
00157 char * haddrp = (char *) &haddr;
00158 ACE_OS::memcpy(haddrp,(char *) hp->h_addr,hp->h_length);
00159 host_addr.sin_addr.s_addr = haddr;
00160 }
00161 #else
00162 ACE_OS::memcpy ((char *) &host_addr.sin_addr.s_addr,
00163 (char *) hp->h_addr,
00164 hp->h_length);
00165 #endif
00166 }
00167
00168
00169 #if !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (ACE_VXWORKS) && !defined(__APPLE__)
00170 for (int n = ifc.ifc_len / sizeof (struct ifreq) ; n > 0;
00171 n--, ifr++)
00172 #else
00173
00174
00175
00176
00177
00178
00179 for (int nbytes = ifc.ifc_len; nbytes >= (int) sizeof (struct ifreq) &&
00180 ((ifr->ifr_addr.sa_len > sizeof (struct sockaddr)) ?
00181 (nbytes >= (int) sizeof (ifr->ifr_name) + ifr->ifr_addr.sa_len) : 1);
00182 ((ifr->ifr_addr.sa_len > sizeof (struct sockaddr)) ?
00183 (nbytes -= sizeof (ifr->ifr_name) + ifr->ifr_addr.sa_len,
00184 ifr = (struct ifreq *)
00185 ((caddr_t) &ifr->ifr_addr + ifr->ifr_addr.sa_len)) :
00186 (nbytes -= sizeof (struct ifreq), ifr++)))
00187 #endif
00188 {
00189 #if defined (__QNX__) || defined (ACE_VXWORKS)
00190
00191 if (ifr->ifr_addr.sa_family == AF_LINK)
00192 continue;
00193 #endif
00194
00195 if (host_name)
00196 {
00197 struct sockaddr_in if_addr;
00198
00199 ACE_OS::memcpy (&if_addr,
00200 &ifr->ifr_addr,
00201 sizeof if_addr);
00202
00203 if (host_addr.sin_addr.s_addr != if_addr.sin_addr.s_addr)
00204 continue;
00205 }
00206
00207 if (ifr->ifr_addr.sa_family != AF_INET)
00208 {
00209
00210
00211
00212
00213 if (ifr->ifr_addr.sa_family != 0
00214 || ACE::debug () > 0)
00215 ACE_DEBUG ((LM_DEBUG,
00216 "warning %p: sa_family: %d\n",
00217 "ACE_SOCK_Dgram_Bcast::mk_broadcast: Not AF_INET",
00218 ifr->ifr_addr.sa_family));
00219 continue;
00220 }
00221
00222 struct ifreq flags = *ifr;
00223 struct ifreq if_req = *ifr;
00224
00225 if (ACE_OS::ioctl (s,
00226 SIOCGIFFLAGS,
00227 (char *) &flags) == -1)
00228 {
00229 ACE_ERROR ((LM_ERROR, "%p [%s]\n",
00230 "ACE_SOCK_Dgram_Bcast::mk_broadcast: ioctl (get interface flags)",
00231 flags.ifr_name));
00232 continue;
00233 }
00234
00235 if (ACE_BIT_ENABLED (flags.ifr_flags,
00236 IFF_UP) == 0)
00237 {
00238 ACE_ERROR ((LM_ERROR, "%p [%s]\n",
00239 "ACE_SOCK_Dgram_Bcast::mk_broadcast: Network interface is not up",
00240 flags.ifr_name));
00241 continue;
00242 }
00243
00244 if (ACE_BIT_ENABLED (flags.ifr_flags,
00245 IFF_LOOPBACK))
00246 continue;
00247
00248 if (ACE_BIT_ENABLED (flags.ifr_flags,
00249 IFF_BROADCAST))
00250 {
00251 if (ACE_OS::ioctl (s,
00252 SIOCGIFBRDADDR,
00253 (char *) &if_req) == -1)
00254 ACE_ERROR ((LM_ERROR, "%p [%s]\n",
00255 "ACE_SOCK_Dgram_Bcast::mk_broadcast: ioctl (get broadaddr)",
00256 flags.ifr_name));
00257 else
00258 {
00259 ACE_INET_Addr addr (reinterpret_cast <sockaddr_in *>
00260 (&if_req.ifr_broadaddr),
00261 sizeof if_req.ifr_broadaddr);
00262 ACE_NEW_RETURN (this->if_list_,
00263 ACE_Bcast_Node (addr,
00264 this->if_list_),
00265 -1);
00266 }
00267 }
00268 else
00269 {
00270 if (host_name != 0)
00271 ACE_ERROR ((LM_ERROR, "%p [%s]\n",
00272 "ACE_SOCK_Dgram_Bcast::mk_broadcast: Broadcast is not enable for this interface.",
00273 flags.ifr_name));
00274 }
00275 }
00276 #else
00277 ACE_UNUSED_ARG (host_name);
00278
00279 ACE_INET_Addr addr (u_short (0),
00280 ACE_UINT32 (INADDR_BROADCAST));
00281 ACE_NEW_RETURN (this->if_list_,
00282 ACE_Bcast_Node (addr,
00283 this->if_list_),
00284 -1);
00285 #endif
00286 if (this->if_list_ == 0)
00287 {
00288 errno = ENXIO;
00289 return -1;
00290 }
00291 else
00292 return 0;
00293 }
00294
00295
00296
00297
00298 ssize_t
00299 ACE_SOCK_Dgram_Bcast::send (const void *buf,
00300 size_t n,
00301 u_short port_number,
00302 int flags) const
00303 {
00304 ACE_TRACE ("ACE_SOCK_Dgram_Bcast::send");
00305 ssize_t iterations = 0;
00306 ssize_t total_bytes = 0;
00307
00308 if (this->if_list_ == 0)
00309 return -1;
00310
00311 for (ACE_Bcast_Node *temp = this->if_list_;
00312 temp != 0;
00313 temp = temp->next_)
00314 {
00315 temp->bcast_addr_.set_port_number (port_number);
00316
00317 ssize_t bytes_sent = ACE_SOCK_Dgram::send (buf,
00318 n,
00319 temp->bcast_addr_,
00320 flags);
00321
00322 if (bytes_sent == -1)
00323 return -1;
00324 else
00325 total_bytes += bytes_sent;
00326
00327 iterations++;
00328 }
00329
00330 return iterations == 0 ? 0 : total_bytes / iterations;
00331 }
00332
00333 #if defined (ACE_HAS_MSG)
00334
00335
00336 ssize_t
00337 ACE_SOCK_Dgram_Bcast::send (const iovec iov[],
00338 int n,
00339 u_short port_number,
00340 int flags) const
00341 {
00342 ACE_TRACE ("ACE_SOCK_Dgram_Bcast::send");
00343
00344 if (this->if_list_ == 0)
00345 return -1;
00346
00347
00348
00349 for (ACE_Bcast_Node *temp = this->if_list_;
00350 temp != 0;
00351 temp = temp->next_)
00352 {
00353 temp->bcast_addr_.set_port_number (port_number);
00354
00355 if (ACE_SOCK_Dgram::send (iov,
00356 n,
00357 temp->bcast_addr_,
00358 flags) == -1)
00359 return -1;
00360 }
00361
00362 return 0;
00363 }
00364
00365
00366
00367
00368 ssize_t
00369 ACE_SOCK_Dgram_Bcast::send (const iovec iov[],
00370 int n,
00371 const ACE_Addr &addr,
00372 int flags) const
00373 {
00374 ACE_TRACE ("ACE_SOCK_Dgram_Bcast::send");
00375
00376 return ACE_SOCK_Dgram::send (iov, n, addr, flags);
00377 }
00378 #endif
00379
00380 ACE_END_VERSIONED_NAMESPACE_DECL