00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "config.hh"
00020
00021 #ifndef QOLYESTER_ENABLE_VIRTUAL
00022
00023 # ifndef QOLYESTER_DAEMON_SYS_SOCKET_HXX
00024 # define QOLYESTER_DAEMON_SYS_SOCKET_HXX 1
00025
00026 # include <sys/socket.h>
00027 # include <fcntl.h>
00028 # include <sys/ioctl.h>
00029 # include <net/if.h>
00030 # include <sstream>
00031
00032 # include "cst/constants.hh"
00033 # include "utl/exception.hh"
00034
00035 # include "sys/realinterfaceinfo.hh"
00036
00037 # include "socket.hh"
00038
00039 namespace olsr {
00040
00041 # if QOLYESTER_FAMILY_INET == 6
00042 extern bool dirty_promisc_hack;
00043 # endif
00044
00045 namespace sys {
00046
00047 Socket::Socket(_dummy_values)
00048 : _fd(-1),
00049 _mtu(0),
00050 _baddr(),
00051 _index(0)
00052 {}
00053
00054 Socket::Socket()
00055 : _mtu(0),
00056 _baddr(),
00057 _index(0) {
00058 init();
00059 }
00060
00061 Socket::Socket(unsigned mtu)
00062 : _mtu(mtu),
00063 _baddr(),
00064 _index(0) {
00065 init();
00066 }
00067
00068 Socket::Socket(unsigned mtu, const addr_t& addr, port_t port)
00069 : _mtu(mtu),
00070 _baddr(),
00071 _index(0) {
00072 init();
00073 bind(addr, port);
00074 }
00075
00076 Socket::Socket(unsigned mtu, const std::string& host, port_t port)
00077 : _mtu(mtu),
00078 _baddr(),
00079 _index(0) {
00080 init();
00081 bind(addr_t(host), port);
00082 }
00083
00084 Socket::Socket(unsigned mtu, const char* host, port_t port)
00085 : _mtu(mtu),
00086 _baddr(),
00087 _index(0) {
00088 init();
00089 bind(addr_t(std::string(host)), port);
00090 }
00091
00092 void
00093 Socket::close() {
00094 if (_fd >= 0)
00095 ::close(_fd);
00096 _fd = -1;
00097 }
00098
00099 void
00100 Socket::bind_to_device(const std::string& name) {
00101 if (::setsockopt(_fd, SOL_SOCKET, SO_BINDTODEVICE,
00102 name.c_str(), name.length() + 1) < 0)
00103 throw errnoexcept_t(std::string("setsockopt(SO_BINDTODEVICE): ") +
00104 strerror(errno), errno);
00105 }
00106
00107 void
00108 # if QOLYESTER_FAMILY_INET != 6
00109 Socket::set_multicast(const RealInterfaceInfo&) {
00110 int val = 1;
00111 if (setsockopt(_fd, SOL_SOCKET, SO_BROADCAST, &val, sizeof val) < 0)
00112 throw errnoexcept_t(std::string("setsockopt(SO_BROADCAST): ") +
00113 strerror(errno), errno);
00114 # else
00115 Socket::set_multicast(const RealInterfaceInfo& info) {
00116 unsigned index = info.index();
00117
00118 if (setsockopt(_fd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
00119 &index, sizeof index) < 0)
00120 throw errnoexcept_t(std::string("setsockopt(IPV6_MULTICAST_IF): ") +
00121 strerror(errno), errno);
00122 int val = 0;
00123
00124 if (setsockopt(_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
00125 &val, sizeof val) < 0)
00126 throw errnoexcept_t(std::string("setsockopt(IPV6_MULTICAST_LOOP): ") +
00127 strerror(errno), errno);
00128
00129 if (dirty_promisc_hack) {
00130 ifreq ifr;
00131 strncpy(ifr.ifr_name, info.name().c_str(), IFNAMSIZ);
00132 ifr.ifr_name[IFNAMSIZ - 1] = 0;
00133 if (ioctl(_fd, SIOCGIFFLAGS, &ifr) < 0)
00134 throw errnoexcept_t(std::string("ioctl(SIOCGIFFLAGS): ") +
00135 strerror(errno), errno);
00136 if ((ifr.ifr_flags & IFF_PROMISC) == 0) {
00137 ifr.ifr_flags |= IFF_PROMISC;
00138 if (ioctl(_fd, SIOCSIFFLAGS, &ifr) < 0)
00139 throw errnoexcept_t(std::string("ioctl(SIOCSIFFLAGS): ") +
00140 strerror(errno), errno);
00141 ifr.ifr_flags &= ~IFF_PROMISC;
00142 if (ioctl(_fd, SIOCSIFFLAGS, &ifr) < 0)
00143 throw errnoexcept_t(std::string("ioctl(SIOCSIFFLAGS): ") +
00144 strerror(errno), errno);
00145 }
00146 }
00147 # endif
00148 }
00149
00150 void
00151 Socket::bind(const sockaddr_t& sin) {
00152 if (::bind(_fd, (::sockaddr*) &sin, sizeof sin) < 0) {
00153 std::stringstream msg;
00154 msg << "bind("
00155 << address_t(sin) << ":" <<
00156 # if QOLYESTER_FAMILY_INET == 6
00157 ntohs(sin.sin6_port)
00158 # else
00159 ntohs(sin.sin_port)
00160 # endif
00161 << "): "
00162 << strerror(errno);
00163 throw errnoexcept_t(msg.str(), errno);
00164 }
00165 }
00166
00167 void
00168 Socket::bind_multicast(const RealInterfaceInfo& info,
00169 const address_t& a, port_t port) {
00170 # if QOLYESTER_FAMILY_INET == 6
00171 bind_to_device(info.name());
00172 _index = info.index();
00173
00174 bind(a, port);
00175
00176 set_multicast(info);
00177
00178 int hops = 1;
00179
00180 if (setsockopt(_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
00181 &hops, sizeof hops) < 0)
00182 throw errnoexcept_t(std::string("setsockopt(IPV6_MULTICAST_HOPS): ") +
00183 strerror(errno), errno);
00184
00185 ipv6_mreq mreq;
00186 a.dump(reinterpret_cast<u_int8_t*>(&mreq.ipv6mr_multiaddr));
00187 mreq.ipv6mr_interface = info.index();
00188
00189 if (setsockopt(_fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
00190 &mreq, sizeof mreq) < 0) {
00191 std::stringstream msg;
00192 msg << "setsockopt(IPV6_ADD_MEMBERSHIP, "
00193 << a << ", " << info.index() << "): " << strerror(errno);
00194 throw errnoexcept_t(msg.str(), errno);
00195 }
00196
00197 int val = 0;
00198
00199 if (setsockopt(_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
00200 &val, sizeof val) < 0)
00201 throw errnoexcept_t(std::string("setsockopt(IPV6_MULTICAST_LOOP): ") +
00202 strerror(errno), errno);
00203
00204 # else // QOLYESTER_FAMILY_INET != 6
00205
00206 bind(a, port);
00207 bind_to_device(info.name());
00208 set_multicast(info);
00209
00210 # endif
00211 }
00212
00213 # if QOLYESTER_FAMILY_INET == 6
00214 void
00215 Socket::bind(const addr_t& addr, port_t port, unsigned index) {
00216 sockaddr_t sin = addr.make_sockaddr(port);
00217 sin.sin6_scope_id = index;
00218 bind(sin);
00219 # else // QOLYESTER_FAMILY_INET != 6
00220 void
00221 Socket::bind(const addr_t& addr, port_t port) {
00222 bind(addr.make_sockaddr(port));
00223 # endif
00224 }
00225
00226 void
00227 Socket::connect(const sockaddr_t& sin) {
00228 if (::connect(_fd, (::sockaddr*) &sin, sizeof sin) < 0) {
00229 std::stringstream msg;
00230 msg << "connect("
00231 << address_t(sin) << ":" <<
00232 # if QOLYESTER_FAMILY_INET == 6
00233 ntohs(sin.sin6_port)
00234 # else
00235 ntohs(sin.sin_port)
00236 # endif
00237 << "): "
00238 << strerror(errno);
00239 throw errnoexcept_t(msg.str(), errno);
00240 }
00241 }
00242
00243 void
00244 Socket::connect(const addr_t& addr, port_t port) {
00245 connect(addr.make_sockaddr(port));
00246 }
00247
00248 utl::Data
00249 Socket::receive(address_t& sender) const {
00250 sockaddr_t sin_from;
00251 socklen_t sin_len = sizeof sin_from;
00252 utl::Data data(_mtu);
00253 int len;
00254 while ((len = ::recvfrom(_fd, data.raw(), data.size(), 0,
00255 (sockaddr*) &sin_from, &sin_len)) < 0 &&
00256 errno == EINTR);
00257 if (len < 0)
00258 throw errnoexcept_t(std::string("recvfrom(): ") + strerror(errno),
00259 errno);
00260
00261 sender = address_t(sin_from);
00262
00263 return data.shrink_to(len);
00264 }
00265
00266 void
00267 Socket::send(const utl::ConstData& d) const {
00268 int len;
00269 while ((len = ::send(_fd, d.raw(), d.size(), 0)) < 0 &&
00270 errno == EINTR);
00271 if (len < 0)
00272 throw errnoexcept_t(std::string("send(): ") + strerror(errno), errno);
00273 }
00274
00275 void
00276 Socket::sendto(const utl::ConstData& d,
00277 const address_t::sockaddr_t& s) const {
00278 int len;
00279 while ((len = ::sendto(_fd, d.raw(), d.size(), 0,
00280 reinterpret_cast<const sockaddr*>(&s),
00281 sizeof s)) < 0 && errno == EINTR);
00282 if (len < 0) {
00283 std::stringstream msg;
00284 msg << "sendto("
00285 << address_t(s) << ":" <<
00286 # if QOLYESTER_FAMILY_INET == 6
00287 ntohs(s.sin6_port)
00288 # else
00289 ntohs(s.sin_port)
00290 # endif
00291 << "): "
00292 << strerror(errno);
00293 throw errnoexcept_t(msg.str(), errno);
00294 }
00295 }
00296
00297 void
00298 Socket::sendto_bcast(const utl::ConstData& d) const {
00299 address_t::sockaddr_t sin = _baddr.make_sockaddr(OLSR_PORT_NUMBER);
00300 # if QOLYESTER_FAMILY_INET == 6
00301 sin.sin6_scope_id = _index;
00302 # endif // QOLYESTER_FAMILY_INET != 6
00303 int len;
00304 while ((len = ::sendto(_fd, d.raw(), d.size(), 0,
00305 reinterpret_cast<sockaddr*>(&sin),
00306 sizeof (address_t::sockaddr_t))) < 0 &&
00307 errno == EINTR);
00308 if (len < 0) {
00309 std::stringstream msg;
00310 msg << "sendto("
00311 << address_t(sin) << ":" <<
00312 # if QOLYESTER_FAMILY_INET == 6
00313 ntohs(sin.sin6_port)
00314 # else
00315 ntohs(sin.sin_port)
00316 # endif
00317 << "): "
00318 << strerror(errno);
00319 throw errnoexcept_t(msg.str(), errno);
00320 }
00321 }
00322
00323 bool
00324 Socket::operator<(const This& rhs) const { return _fd < rhs._fd; }
00325
00326 sch::IOEvent::p_t
00327 Socket::read_p() const {
00328 return sch::IOEvent::p_t(_fd, POLLIN);
00329 }
00330
00331 sch::IOEvent::p_t
00332 Socket::write_p() const {
00333 return sch::IOEvent::p_t(_fd, POLLOUT);
00334 }
00335
00336 void
00337 Socket::init() {
00338 if ((_fd = ::socket(addr_t::proto, SOCK_DGRAM, IPPROTO_UDP)) < 0)
00339 throw errnoexcept_t(std::string("socket(SOCK_DGRAM, IPPROTO_UDP): ") +
00340 strerror(errno), errno);
00341 if (::fcntl(_fd, F_SETFL, O_RDWR | O_NONBLOCK) < 0)
00342 throw errnoexcept_t(std::string("fcntl(F_SETFL, O_NONBLOCK): ") +
00343 strerror(errno), errno);
00344 }
00345
00346 }
00347
00348 }
00349
00350 # endif // ! QOLYESTER_DAEMON_SYS_SOCKET_HXX
00351
00352 #endif // ! QOLYESTER_ENABLE_VIRTUAL